Redesign native setup and Work with a central activity timeline - #190
Merged
Merged
Conversation
added 9 commits
September 11, 2026 19:50
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.
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.
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
FZ2000
marked this pull request as ready for review
September 13, 2026 22:24
This was referenced Sep 14, 2026
Merged
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.
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.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 countedOverflowDisclosurefor 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;barSegmentsderives 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:a24fc08also passed all four in run 34784862066.) Local merged Python suite: 2,881 passed.canShowDistributionhonesty guard are untouched, andReceiptActionSummaryTestsalready lock theshareDenominatorinvariant the stacked bar depends on._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 ineef8bd5.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.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 incentral-installed-identity.json. Rollback bundles preserved.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.Ready for review; no merge to main without explicit authorization.
🤖 Generated with Claude Code
https://claude.ai/code/session_013w9bhGCPP2g37g4xiehwDV