- the timeline's Δ glyph became a **Details** button, and it now appears on
Update rows too (not just card-side changes); EN "Changed (card)" ->
"Changed on card", RU "Изменено (картой)" -> "Изменено картой"
- the details modal shows the affected unit — the whole file, or the single
record that changed — **before and after** the change as hex views (16 bytes
per row, ASCII column, never-observed bytes as `--`), with the bytes that
changed and the bytes the operation *first observed* highlighted in two
different colours, plus the changed/new byte counts and the APDU reference;
the old before/after byte table is gone
- `GET /api/sessions/<id>/files/image?key=…&change=…` returns those two views
(segments with offsets) plus the change's metadata; the images are
reconstructed from the current image by undoing the later changes
(`FileTracker.change_images`), so nothing is duplicated per event — every
value change is an event, hence the values are exact (a byte only first
observed later can appear as known in both views)
- tracker: change events carry `observed_ranges` (bytes that were unknown
before the operation) next to `ranges`; an update that only observes new
bytes now records an event (so it can be inspected); record-file ranges are
in-record byte offsets (the record number stays in its own field), which the
previous "record number as position" could not express for a hex highlight
- tests: change-images reconstruction (before/after per event, later changes
undone, records isolated, observation-only events, unknown gaps), the image
endpoint (200/404/400), and Node tests for the hex-image helper (highlight
classes, unknown gaps, ASCII, row limit) and the modal rendering
- v2.4.0; SW cache simtrace-analyser-v65
- `API._fetch` never checked the HTTP status: an error body (e.g. the 404
`{"error": "Session not found"}`) was returned as data, so the Files view
rendered it as "No file operations recorded" — and, worse, that bad payload
was cached per session id, which is why only re-opening the session (which
resets the cache) appeared to fix it. It now throws with the server's
message for any non-OK response (all 13 `await API.*` call sites are inside
try/catch) and marks the server unavailable only for a real network error
- `renderFileView` accepts a payload only when it carries a `timeline` array:
a genuine `timeline_total === 0` keeps the empty state, anything else shows
"Failed to load files: <reason>"; failures are not cached, so the next visit
retries; a response that arrives after the user switched sessions is ignored
- tests: HTTP-error vs network-error behaviour of `_fetch` (network error is
the only disconnected state), the valid/empty/error render paths and the
retry-after-error, the stale-response guard
- v2.3.1; SW cache simtrace-analyser-v64
- new `simtrace_analyser/filetrack.py`: a single-pass tracker over a
session's decoded messages, keyed by (DF, FID) and trace-wide (resets only
wipe the per-channel selection): counters (`select`/`read`/`update`,
successful operations only), a sparse image of the observed bytes
(transparent files by offset, record files per record number) and the
change log
- changes: **device** = an UPDATE seen in the trace (applied to the image,
`no_change` flags a provable no-op); **card** = a READ whose bytes differ
from the image on bytes already known (logged at the surfacing read with
the changed ranges and the before/after hex; never-seen bytes just fill
the image, they are an observation, not a change)
- SFI-addressed accesses join the same entry as path/FID ones: the SFI ↔ FID
relations come from the normative tables and from every surfaced FCP `88`
DO (including the spec's "SFI = 5 LSBs of the FID" rule when the DO is
absent); an SFI used before its relation is learned stays provisional and
merges into the resolved entry
- the DF identity follows TS 102 221 §8.4/Table 8.2: `selected_df_fid()` now
resolves an EF path selection to its parent DF and returns `aid:<hex>` for
applications selected by an unknown AID (named from EF.DIR when the trace
surfaced it); `Database._decode_rows` gained an `on_message` hook and
`track_files()`
- `GET /api/sessions/<id>/files`: the operation timeline, the per-file
counters/coverage/change log, the SFI relations and the AID labels
- PWA: the side panel's Map/Stats tabs became a view selector (Map / Stats /
Files); the Files view is a timeline of Read / Update / Changed (card) rows
(colour-coded, the same file names as the Map view), a row click jumps to
the APDU (loading the pages it needs) and a card-change row's Δ opens the
changed ranges with the previous and the new bytes; EN/RU
- bounds: the image freezes past 64 KB of observed bytes per file, the change
log keeps the last 1000 events per file (counters keep counting)
- tests: tests/test_filetrack.py (counters, resets, channels, image/diff
semantics, record files, SFI resolution and the provisional merge, EF.DIR
labels, caps, the endpoint) and Node tests for the Files-view helpers and
wiring
- v2.3.0; MIN_SERVER_VERSION 2.3.0; SW cache simtrace-analyser-v63
- new `simtrace_analyser/comprion.py`: parses the tab-separated ISO Protocol
Layer export (metadata block, ATR/PPS exchanges, APDUs with continuation
rows, delays in etu) and re-encodes every exchange into the wire-shaped
TPDUs the analyser stores — a case-4 exchange becomes the command, a
fabricated `61 <len>` status word and a GET RESPONSE (command's logical
channel preserved), so command/response pairing, FCP/file decoding and the
GET RESPONSE filters work unchanged; Cold reset / Power off become RST/VCC
line events, deliberately without the sigrok CLK extension (the export
carries no clock measurement)
- optional matching **ISO Application Layer** export as the exact time base:
its one `Time:` row per exchange (ms precision) replaces the delay estimate
(0-based elapsed, `started = Session Name + first Time`), guarded by a
session-identity check (`Session Name`, falling back to `Working
directory`; the two layers' export timestamps differ and are not compared)
and an exchange-count check — mismatched files are refused, never mixed
- protocol-only imports keep the Delay-based timeline: card/line activity
time (host pauses absent), the unit assuming 3.8 MHz (`CLK_HZ`); the
estimate is not fed into the CLK/RST line-event annotation
- `POST /api/sessions/import?format=comprion` (raw text body, or a JSON
`{text, times_text}` bundle) with stable error codes (app_layer /
not_comprion / unsupported_layout / no_data / times_unparsable /
session_mismatch / time_base_unverified / time_base_mismatch); a COMPRION
file dropped on the PCAP path answers with a pointer (comprion_export);
session mode `comprion`, window from the Session Name
- PWA: import dialog with two separate pickers (Protocol Layer required,
Application Layer optional) whose hint switches between "activity time"
and "exact timestamps"; errors stay in the dialog with both selections
until fixed or cancelled (Cancel/Esc, also disabled while importing);
EN/RU
- tests: tests/test_comprion.py (parser, wire encoding, time base + guards,
import endpoint) and frontend/tests/comprion.test.js (file checks, slot
validation, dialog state machine with a DOM stub, RU coverage)
- v2.2.0; MIN_SERVER_VERSION 2.2.0; SW cache simtrace-analyser-v61