Skip to content

Redesign native setup and Work with a central activity timeline - #190

Merged
FZ2000 merged 33 commits into
mainfrom
design/native-recording-experience
Sep 13, 2026
Merged

FZ2000 merged 33 commits into
mainfrom
design/native-recording-experience

Conversation

@FZ2000

@FZ2000 FZ2000 commented Sep 12, 2026

Copy link
Copy Markdown
Collaborator

Recording setup and recovery stay in the main macOS window. Work places activity above and below one horizontal timeline with held history, and event details on selection. Comparison and unused detail placeholders are removed.

Timeline navigation is now spatial. Axis ticks, labels and cards are anchored to absolute time and translate together: dragging the canvas or the overview window visibly moves through time, and scrolling resizes the visible time span around the pointer (pinch zooms as before). Card packing covers all loaded dated records, so grouping depends only on the records and the current scale — panning can never rearrange or regroup cards. Dense regions cluster while retaining every member; a span crossing an edge keeps its line running through the viewport instead of pinning a fake card. The visible window spans at least five seconds and at most the recorded history; panning may show up to half a card beyond the recorded range (bounded) so a card centered on the first or last record is fully reachable at the current text size, and the overview maps that same scrollable range.

Selection details open below the timeline. Selecting an event opens its details in a region under the canvas instead of a floating popover; dense-group member lists and undated records share that region, with a way back to the group. The region reveals itself by scrolling the page only when it would open out of view, and the canvas keeps its position and scale throughout. Keyboard focus stays on the triggering card (Escape closes, Space reopens); VoiceOver focus moves to the region heading.

The native canvas consumes the existing backend task timeline. Python supplies stable identities, session/section links, time bounds, provenance, artifacts, supersession and dispositions. Swift's duplicate session/check reconstruction and per-session polling are removed. History pages belong to one immutable snapshot; the app publishes and saves complete history and retains the previous snapshot on errors.

The receipt reads like one. The totals panel (Checks, Tool calls, Cost, Sessions, Coverage) sits between the task status and the Activity timeline, and the receipt's second half is a visible document below the timeline — USAGE, SESSIONS and RECORDING under caps section rules, always shown. The rejected outer "Task details" fold and its per-topic folds are gone; the only fold left is a single counted control for a genuinely long list (more sessions, more gaps, all tool types). Usage renders tool calls as one 100% stacked bar — drawn only for a reconciled positive partition, so a missing or conflicting total still shows exact counts and never a proportion — with a wrapping legend and per-segment tooltips. Recording keeps caps-label rows with hover definitions (the Sources chips carry the daemon's own legend) and a copyable Task ID that announces its copy. Lists the timeline already shows (check events, session steps) are not re-told; every fact has one home.

The performance fixes remain in place: rendering no longer rehashes recorder payloads or reloads saved-work JSON; views use stored presentation and snapshot state while protected operations still validate current installation contents and ownership; timeline calculations are reused and viewing-position writes wait for a 250 ms pause with an immediate flush on leaving.

Commits since bc2190f:

  • ad095df: anchor timeline navigation to time — drag pans, scroll resizes the visible span.
  • 112e08c: keep offscreen cards out of the accessibility tree.
  • b7fb1bf: show selection details below the timeline; bound the minimum window span.
  • dc326f0: give the group chooser its own close identifier.
  • 8fa2734: keep keyboard focus on the card when the selection region opens.
  • merge of origin/main (fix: apply _fmt_time out-of-range guard before local-tz conversion #191, feat: worked-example receipts, coverage matrix, and receipt --markdown #192) with the worked-example doc regenerated against the branch's receipt engine.
  • 95c3c94: the receipt totals (Checks, Tool calls, Cost, Sessions, Coverage) move out of the fold into a panel above the Activity timeline; detail rows adopt the strip's caps-label language; sessions become a structured index; per-row provenance and gaps stop repeating the Sources and Gaps rows; the tool-call digest goes compact and its definitions move into help; "1 subagents" reads "1 subagent".
  • 429fca4: the coverage qualifier reads "of checkable claims" so it never truncates.
  • a24fc08: Task details becomes a visible receipt document — the outer fold and its three per-topic folds are removed; USAGE, SESSIONS and RECORDING show in full under caps section rules with one counted OverflowDisclosure for long lists; the compact tool-call digest becomes a 100% stacked bar with a wrapping legend, per-segment tooltips and a "Show all N tool types" overflow, dropping the lines that Sources and the section help already own; the Task ID copies from its row with a VoiceOver announcement; four stale design images (the removed record-detail popover captures and the orphaned before/after row-timeline captures) leave the doc.
  • eef8bd5: review hardening — the Gaps overflow counts every remaining gap (detailed and counted-without-detail) and names the undetailed remainder; "details not included" is amber everywhere; gap rows use index-stable identities; the copy glyph is also visible while keyboard-focused; the bar legend is hidden from assistive tech so segments are not read twice; barSegments derives the visible five and tint ranks from one sort; comments name where each omitted fact lives.
  • a2e16e3: every Task details topic row carries a chevron, hover target and count hint (tool types, sessions, recorded gaps); Check history leaves the page because the timeline already shows every check interactively; Sessions becomes a quiet index; coverage, sources and gaps merge into one Recording details block; the timeline's internal Recording details fold retires; dead coverage cards are deleted.
  • 13415d9: "undefined for this client" becomes "not applicable for this client" in the receipt headline, plan basis, Python test and native mirror.
  • 4725b7c: Task details reads like a receipt — visible line items (Checks, Tool calls, Cost, Sessions, Coverage) with qualifiers or named absences inside the trailing disclosure, one home per fact, the duplicated decision explanation removed, and the ledger split into Usage and Recording details.
  • 9548243: the edge reveal is half a card at the current text size again (bounded) so wide large-text cards fit at the extremes; zoom keeps its span bound at the recorded range while preserving an overscrolled position; the overview maps the same pannable domain as the canvas.
  • ac233b9: two-pass line-by-line audit hardening — one edge-reveal clamp for canvas/overview/view, cumulative gesture-scoped dragging with a gesture-began reset, tick steps that depend only on span and width (pre-epoch lattice floored, integer conversions capped, formatters cached), crossing-cluster span dedupe, histogram and slider totality guards, a shared card-tint definition, and static-render accessibility fixes.

Earlier commits:

  • a5d557a: separate display advice from live setup authorization; remove quadratic filtering and redundant projection rebuilds.
  • a15cade: load saved work once per window off the main actor; cache immutable time bounds and pending-arrival differences.
  • bc2190f: coalesce preference writes during gestures, avoiding unrelated AppStorage invalidations.
  • 5bfaca4: shared timeline contract and paged API; reuse PR feat: worked-example receipts, coverage matrix, and receipt --markdown #192's Markdown renderer and tests.
  • e34354c: native adapter/loader, removal of duplicate reconstruction, offline snapshots, and PR Make Sources health fail closed #158's independent Sources refresh.
  • 3674c86: preserve chronological order for older important receipt checks.

The design and code review guide maps the setup/canvas changes and upstream overlap.

Validation at eef8bd5:

  • All four CI jobs passed: macOS app/tests/packaging/review renders, and Python 3.11, 3.12, 3.13. (The prior head a24fc08 also passed all four in run 34784862066.) Local merged Python suite: 2,881 passed.
  • Local native suite: 496 tests, six guarded visual-reference skips, zero failures. This change is view-layer over unchanged data logic: the tool-call synopsis and its canShowDistribution honesty guard are untouched, and ReceiptActionSummaryTests already lock the shareDenominator invariant the stacked bar depends on.
  • Independent code review (read-only, verified against the daemon's _roll_up_gaps) confirmed the honesty invariants — the bar is a reconciled 100% partition, and every digest line omitted on the Work page reappears in the Sources or rolled-up Gaps row — and its seven findings were applied in eef8bd5.
  • The 19 installed interaction checks were not re-run on this build. They exercise timeline navigation, which this change does not modify, and they passed on 429fca4. On this host the Accessibility subsystem was wedged (the AX probe returned empty for every process, Finder included — a known environmental state, not a product regression), so a live replay was not possible without a tccd restart or reboot.
  • Installed and verified: both bundles and the managed recorder at eef8bd5, all 543 payload entries/modes, runtime running/healthy; 80 pre-merge branch files and 23 later files match the editable checkout and the 19 main-arriving files are listed in central-installed-identity.json. Rollback bundles preserved.
  • NSWorkspace confirms one production GUI, including checks for unbundled development processes.
  • Performance numbers at bc2190f (page-switch median 835→79 ms, p95 1,392→134 ms) remain valid — this change adds no per-frame disk reads, hashing, preference writes or history reconstruction.
  • The earlier 100-agent studies evaluated older candidates; their scores are not attributed to this revision. Canonical pixel comparison remains guarded because local/hosted OS builds differ from the pinned renderer. Full VoiceOver and physical pinch hardware have not been exhaustively tested.

Ready for review; no merge to main without explicit authorization.

🤖 Generated with Claude Code

https://claude.ai/code/session_013w9bhGCPP2g37g4xiehwDV

@FZ2000 FZ2000 changed the title Bring recording setup and live work review into the macOS app Redesign native setup and Work with a central activity timeline Sep 12, 2026
FZ2000 added 17 commits September 12, 2026 02:15
Axis ticks, labels and activity are anchored to absolute time and translate
together while dragging, instead of labels renumbering at fixed positions.
Card packing covers all loaded dated records, so grouping depends on records
and scale only; offscreen items cull at render time without affecting
placement. Wheel input over the canvas and overview now resizes the visible
span around the pointer with bounded per-event factors, matching the pinch
zoom; drag and arrow keys remain the panning path.
Cards render as buttons only when their frame approaches the viewport; a
record whose span crosses the window now draws its line without pinning a
clipped card, so physical and accessibility activation always target a
visible element.
…w span

Selecting an event opens its details in a region under the canvas instead of
a floating popover; dense groups list members in the same region with a way
back, and the page scrolls just enough to reveal the region when it would
open out of view. The canvas keeps its position and scale throughout. The
visible window never shrinks below five seconds so the axis and overview stay
meaningful at maximum zoom-in.
Assigning button focus on open fell back to the timeline heading when Full
Keyboard Access is off, breaking Escape-to-dismiss. The inline region is
non-modal: keyboard focus stays on the triggering card (Escape closes, Space
reopens), while VoiceOver focus moves to the region heading.
- Allow a bounded edge reveal (15% of the span) beyond the recorded range,
  using one clamp formula for the canvas, the overview and the view, so a
  card centered on the first or last record is fully reachable at the
  extreme positions without any snap between surfaces.
- Resolve mouse drags against a gesture-start base window with cumulative
  translation and a gesture-began reset, so a slow frame can drop a request
  but never motion or leak a stale base across gestures.
- Keep the tick step a function of span and width only (labels still carry
  the date at day boundaries), floor the pre-epoch day lattice, cap integer
  conversions, and cache date formatters per template, calendar and locale.
- Draw every member of a crossing cluster exactly once, guard the histogram
  and tick math against non-finite inputs, and bound the whole-window slider
  range so it can never be zero-length.
- Share one card-tint definition between the canvas and the detail region,
  give the chooser its own record identifiers, clear cluster state on canvas
  and undated selection, and keep accessibility focus assignments off
  represented containers so static renders stay clean.
The edge reveal is half a card at the current text size again (bounded),
so large-text cards fit fully at the extreme positions. Zoom keeps its span
bound at the recorded range while preserving an overscrolled position, and
the overview maps the same pannable domain as the canvas so the pill shows
the true scrollable range instead of pinning at the data edge.
FZ2000 added 2 commits September 13, 2026 00:26
Inside the trailing Task details disclosure, the decision-relevant facts now
appear as receipt line items (Checks, Tool calls, Cost, Sessions, Coverage),
each value carrying its own qualifier or a named absence. The four topics
below stay one level deep and each fact gets one home: the duplicated
decision explanation is gone, the ledger splits into Usage (tool calls and
cost) and Recording details (task identity, agents, coverage, sources, gaps),
and the full task ID moves into Recording details with copyable text. The
line-item derivation lives in a testable presentation type.
Every topic row now carries a rotating chevron, a hover target and a count
hint (tool types, sessions, recorded gaps) so the folded content announces
itself. Check history leaves the page: the timeline already shows every
check interactively, and the Checks line item carries the tallies. Sessions
becomes a quiet index instead of a second step list, and the coverage,
sources and gaps cards collapse into one Recording details block with task
identity and per-fact rows. The timeline's internal Recording details fold is
retired; degradation notices stay visible under the canvas and the static
explanations move into Activity help.
FZ2000 and others added 5 commits September 13, 2026 01:09
Clients without a calibratable weekly meter read 'undefined for this
client' on their receipts — an implementation word leaking into a user
value. The receipt headline and the plan basis now say 'not applicable',
and the native row mirrors the same wording.
The line items (Checks, Tool calls, Cost, Sessions, Coverage) move out of
the fold into their own panel between the task status and the timeline —
verdict, then totals, then history. Inside Task details, the fact rows get
caps labels matching the strip, per-dimension provenance and gap chips step
aside for the Sources and Gaps rows that already own them, sessions become a
structured index with meta lines and group headers, the Task ID moves to a
quiet footer, and the tool-call digest drops its per-category descriptions
and teaching lines into the Usage help (also fixing '1 subagents').
The trailing "Task details" disclosure and its three per-topic folds are
removed. Below the timeline the receipt's second half now reads as a visible
document: USAGE, SESSIONS and RECORDING sit under caps section rules and are
always shown — verdict, then totals, then history, then the record. The only
fold left is a single counted OverflowDisclosure used for a genuinely long
list (more sessions, more gaps, all tool types), one level deep with the count
in its trigger.

USAGE presents tool calls as one 100% stacked bar (accent tints only, the
largest share darkest) with a wrapping swatch legend and per-segment hover
tooltips; the full itemized list with exact shares is one click away only when
types collapse into "Other". The bar renders only for a reconciled positive
partition — the existing honesty guard is unchanged, so a missing or
conflicting total still shows exact counts and never a proportional bar. The
compact digest drops the per-category descriptions, the capture-boundary line
(now in the section's help) and the action-sources line (Sources owns
provenance), so no fact is repeated.

RECORDING keeps caps-label rows for Task, Agents, Coverage, Sources, Gaps and
Task ID. Coverage and the Sources chips carry hover definitions (the chips'
own daemon legend); the Task ID becomes a CopyableValue whose copy glyph fades
in on hover, is a keyboard focus stop, and announces the copy to VoiceOver.
Static rows stay non-focusable — nothing looks clickable unless it acts.

Also drop four stale design images from the doc: the two record-detail popover
captures (the popover was removed) and the orphaned before/after row-timeline
captures (referenced nowhere), and update the one prose line that still
described Task details as separate expanding categories.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013w9bhGCPP2g37g4xiehwDV
Independent review of the Task-details redesign: the honesty invariants hold
(the stacked bar is a reconciled 100% partition; the digest lines dropped on
the Work page reappear in Sources and the rolled-up Gaps row), and these
refinements close what it found.

- The Gaps overflow counts every remaining gap — detailed items beyond the
  third and any counted without detail — and names the undetailed remainder
  inside; "details not included" is amber everywhere, since a counted gap is
  still a gap. Gap rows use index-stable identities so two gaps sharing a
  dimension and reason never collapse into one.
- The copy glyph on the Task ID also appears while its button has keyboard
  focus, so a sighted keyboard user sees the stop and its checkmark, not only
  the VoiceOver announcement.
- The bar's legend is a visual key only: hidden from assistive tech so the
  segments' own labels are not read twice.
- barSegments derives the visible five and each slice's tint rank from one
  descending-count sort, walking taxonomy order once; the 2 pt minimum slice
  width is documented as the bounded proportionality trade it is.
- Comments name where each omitted fact actually lives, and a stale timeline
  comment no longer refers to the removed Task details fold.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013w9bhGCPP2g37g4xiehwDV
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant