feat(console): Activity view + local outcome log (Stage 7 — closes Phase 2)#15
Merged
Conversation
Phase-1 backlog item: first 6 + last 4 hex, EIP-55 casing verbatim, non-ASCII/short/unprefixed input returned as-is. For the Activity list rows exclusively — signing surfaces keep full addresses (ТЗ §4.1).
…ctivity OutcomeState is deliberately not TerminalState: §3.9 promises never 'pending', so a reply carrying one fails the parse (default-deny). OutcomeEntry mirrors §3.9 verbatim (tx_hash/reason absent => None); parse_activity mirrors parse_positions but has NO degradable answer — wallet_locked is not in the §3.9 vocabulary, any error fails closed.
…se 2 read layer) - transport/app: Request::Activity + Reply::Activity; the activity op rides the existing list-first slot when the Activity view is on top (same STALE_TICKS cadence; the Dashboard's two-valued alternation is untouched and resumes where it left off). - History pipeline: the model owns a pure Vec<HistoryEntry> (unix desc, id asc — ties inside one second are id-ordered by documented design); the run loop owns the clock, the JSONL file on RUSTOK_CONSOLE_LOG -> $RUSTOK_DATA_DIR/console-activity.jsonl, and the id-dedup set. A decision born here is recorded rich (to/amount from the still-open card in apply_resolve); server outcomes stamp arrival-age (§3.9) and fill missing fields of known rows (never overwrite, file keeps its first record). Corrupt lines skip with a visible note; a failed write switches to session-only with a visible note; oversized files compact atomically. - ui: fourth tab (h), filter cycle (f), shortened addresses — the one display list ТЗ §4.1 allows; exact-fit/'+N more' budget (Stage-5 lesson). - Decision/decision_line (ADR #7) untouched — the history drain is a separate channel, proven by test.
…lockers) BLOCKER-1: load_history deduped by whole-record replace on the bigger unix — but a rich decision record (unix = now) and a poor server-window record (unix = arrival − age) come from DIFFERENT formulas, so an ordinary two-console session could trade rich details for a poor duplicate on the next reload. Load now merges field-by-field in file order through the one shared seam HistoryEntry::fill_missing_from (present fields are never overwritten); Model::fill_history_detail takes &HistoryEntry (five positional Options were a silent-swap hazard). BLOCKER-2: read_to_string flattened EVERY read error into 'no history yet' — a torn non-UTF8 tail after a SIGKILL mid-append silently hid the whole file. The log is now read as bytes (a torn write poisons one line, counted and noted), and NotFound (normal empty) is distinguished from unreadable (surfaced as a note, never a healthy empty view). Minors folded in: writers serialize on a sidecar lockfile (compaction re-reads fresh under the lock — the TOCTOU race; the sidecar because rename would strand a waiter on the old inode) · compaction triggers on RAW line count and re-fires every HISTORY_CAP appends in a resident session · per-pid tmp name · 0600 on log/lock/tmp.
temrjan
added a commit
that referenced
this pull request
Jul 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The last stage of Console v2 Phase 2: the fourth view Activity/History (
h, filter onf), the client side of the §3.9activityop (server side shipped in core#93, canon in #14), and a local outcome journal — history deeper than the core's 60-min retention window.Spec:
.claude/specs/2026-07-14-console-v2-phase2-s7-activity.md(Gate-1: both signatures; /check 7 findings applied). Report incl. Gate-2 delta:.claude/reports/2026-07-14-console-v2-phase2-s7-activity.md.What
Request::Activity+parse_activity(mirror of positions;OutcomeStateis deliberately NOTTerminalState— §3.9 promises never"pending", so one fails the parse; no degradable errors:wallet_lockedis not in the vocabulary).Vec<HistoryEntry>(unix desc, id asc; ties inside one second are id-ordered by documented design — Gate-1 finding); the run loop owns the clock, the JSONL file (RUSTOK_CONSOLE_LOG→$RUSTOK_DATA_DIR/console-activity.jsonl→ session-only with a visible note) and the id-dedup set. A decision made here is recorded RICH inapply_resolvewhile the card is still open (to/amount/chain — the only moment they are known); server outcomes stamparrival − age(§3.9) and fill missing fields of known rows.Decision/decision_line(ADR Console v2 UX + visual redesign: human-readable card, brand palette, animated tx flow, persistent dashboard #7) untouched — a separate drain, proven by test and smoke.Gate-2 round (2 blockers found by review, fixed in
718c594with true-red proofs)HistoryEntry::fill_missing_from. True-red both directions.read_to_stringflattened every read error into "no history yet". Now: byte-wise read (a torn non-UTF8 tail poisons one line, counted + noted),NotFounddistinguished from unreadable (surfaced as a note). True-red.Minors folded in: sidecar-lockfile serializing writers (compaction re-reads fresh under the OS advisory lock — TOCTOU closed by construction), raw-line compaction trigger + periodic re-compaction in a resident session, per-pid tmp, 0600 on log/lock/tmp,
fill_history_detail(&HistoryEntry).Evidence
fmt / clippy
-D warnings/cargo deny check advisories licenses bans sourcesclean ·cargo test211+30+1 (was 184+19+1; zero existing tests edited) · 37 new tests, 15 red proofs (5 true-red incl. both blockers, 10 targeted mutations) · DoD smoke 11/11 (real binary in a pty, two runs over one log file: instant rich row at decision, exactly one ADR-#7 decision line on piped stdout, full address absent from the frame, restart reloads history with an empty server window).Open, deliberately deferred question (Captain's word, not blocking): same-uid tamper-integrity of the journal — 0600 done, the rest tracked separately.