Skip to content

Timeline: group the toolbar toggles, band the eighteen lanes - #24

Merged
guan4tou2 merged 3 commits into
mainfrom
feat/timeline-toggles-lanes
Aug 24, 2026
Merged

guan4tou2 merged 3 commits into
mainfrom
feat/timeline-toggles-lanes

Conversation

@guan4tou2

Copy link
Copy Markdown
Owner

The last open item in DESIGN-core-and-capture.md §6: the timeline's eight flat
toolbar toggles and its eighteen lanes. Both were "problems" with no decision —
and the timeline is the product's most complex, most fragile screen, so the
approach was picked before building (a prior three-view-modes attempt was
reverted for inventing personas).

Toolbar toggles — grouped, rare ones behind "More"

The eight toggles sat in one undifferentiated row mixing three kinds of control
(time/axis, filter, view). Not the reverted approach — no modes or personas.
The low-frequency view/audit controls (session dividers, timezone, auditor
view) move behind a single More popover; the high-frequency ones stay in the
row where they cluster. The auditor view in particular was worth demoting — it
hides the logged tier to show the chained chain, a tamper-evidence concern the
core revision moved off centre.

18 lanes — banded by capture group

Lanes now group into the same commands / traffic / artifacts bands the
readiness card uses, plus a signals band for the derived/alert lanes. A band
opens collapsed to one row whose dots keep their per-lane colour, and expands to
its member lanes on click. Default all-collapsed: the timeline opens as three or
four bands, not eighteen. Band-collapse is project-scoped, like lane visibility.

Under the hood this is a row-key abstraction over the existing geometry — a row
is a band id (collapsed) or a lane id (expanded) — so every site that keyed on a
lane now keys on the row, while dot colour still comes from each event's own
lane.

The crash the e2e caught

The project-scoped band-load effect referenced projectIdForKeys in its
dependency array while sitting above that const's declaration — a
temporal-dead-zone throw during render, in the esbuild-bundled app only, that
vitest's source transform never saw. Same class as the TargetView crash from
PR #23, caught the same way: app-in-the-loop. Moved below the declaration.

Verification

  • npm test — 847 passed
  • npm run e2e — 63 passed, including two new specs that verify, in a
    running app, that the overflow hides/reveals the rare controls and that the
    timeline opens banded, still draws its events collapsed, and expands on click.
  • Screenshot of the banded timeline attached to the branch.

🤖 Generated with Claude Code

guan4tou2 and others added 3 commits August 24, 2026 01:32
docs/DESIGN-core-and-capture.md §6's first half: the eight flat toolbar
toggles. They sat in one undifferentiated row — compress, follow, timezone,
anomaly, auditor, dividers — mixing three different kinds of control (time/axis,
filter, view) that the operator has to scan past every time.

Not the reverted approach: this does NOT invent modes or personas onto flag
combinations (that shipped and was reverted in 59ff5fc because the categories
were reverse-engineered and the defaults landed on "debug"). It groups by what
each control *does*, honestly, and moves the low-frequency view/audit ones —
session dividers, timezone, and the auditor view — behind a single "More"
control. Those are set once and rarely touched; each was taking a slot in the
row the operator reads on every glance.

The high-frequency controls stay in the row where they cluster naturally:
zoom and compress (axis), the filter box and anomaly chip (filter), collapse
and minimap (view). The auditor view in particular was worth demoting rather
than featuring — it hides the logged tier to show the chained chain, a
tamper-evidence concern the core revision moved off centre.

e2e/timeline-toolbar-overflow.spec.ts verifies the rare controls are gone from
the flat row, reachable in the overflow, still functional, and that the menu
closes on outside click. No existing e2e referenced the moved controls.

npm test 847 passed · overflow e2e 3 passed

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
docs/DESIGN-core-and-capture.md §6's second half. Eighteen lanes is past
reliable scanning; most engagements touch three or four. The lanes now group
into the same capture-group bands the readiness card uses — commands, traffic,
artifacts — plus a signals band for the derived/alert lanes, so the timeline
and the readiness model describe capture the same way.

A band opens collapsed to a single row whose dots keep their per-lane colour
(what happened is still legible at a glance) and expands to its member lanes on
click; empty bands contribute no row, exactly as empty lanes did. The default
is all-collapsed, so the timeline opens as three or four bands instead of a
wall of eighteen. Band-collapse is a project-scoped preference, like lane
visibility — the lanes that matter differ by engagement.

The change is a row-key abstraction over the existing geometry: a row is a
band id when collapsed or a lane id when expanded, and every place that keyed
on a lane (visible rows, event buckets, virtualisation, labels, keyboard
navigation) now keys on the row. Dot colour still comes from each event's own
lane, so a collapsed band's row is multi-coloured by source.

The e2e caught a temporal-dead-zone crash that the unit suite could not: the
project-scoped band-load effect referenced `projectIdForKeys` in its dependency
array while sitting ABOVE that const's declaration — a throw during render in
the esbuild-bundled app, invisible to vitest's source transform. Same class as
the TargetView crash, caught the same way: app-in-the-loop. Moved below the
declaration.

Verified in a running app (e2e/timeline-lane-bands.spec.ts): opens as bands not
eighteen lanes, the collapsed bands still draw their events, and clicking one
expands it to its lanes. The P0-2 vertical-scroll geometry test now expands all
bands first to recreate the many-rows overflow it exists for.

npm test 847 passed · npm run e2e 63 passed

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 23, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bd81b9e6-ee80-4c6a-b804-b8fa8334c31c


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@guan4tou2
guan4tou2 merged commit d20efed into main Aug 24, 2026
5 checks passed
@guan4tou2
guan4tou2 deleted the feat/timeline-toggles-lanes branch August 24, 2026 02:11
guan4tou2 added a commit that referenced this pull request Oct 8, 2026
…ocus

  • #25 FindingsView CDP poll now backs off from 3s → 10s while the browser
    isn't running. Was hitting IPC every 3s regardless.
  • #26 Mark URLs (both the primary and the auto-captured browserUrl) now
    open in the operator's real browser via app.openExternal — was inert
    plain text before. New http/https-only openExternal IPC (rejects file:
    and other schemes so untrusted content can't dispatch side effects).
  • #27 SearchPanel results are clickable — click jumps to the event on
    the Timeline via the existing focusEvent flow. Also dropped the q<2
    gate to q<1 so single-char IPs/octets work.
  • #37 Cluster popover now flips ABOVE the cluster when the natural
    position would drop it off the bottom of the timeline (last-lane
    clusters).
  • #39 Recent-project delete ✕ now shows on focus, not only hover —
    keyboard users can reach it. Also gained a focus ring.
  • #47 Timeline zoom-reset button gained a ↺ glyph so the click-to-reset
    behaviour is discoverable (was just the percentage number), plus is
    disabled at 100% and has aria-label + focus ring.

New i18n keys: marks.openUrl, search.openInTimeline (en + zh-TW).

Deferred (still queued): #24 already fixed by v0.6.29's shortcut order
change; #33 uptime → engagement start; #38 timeline layout with detail
panel; #48 MCP UI stdio vs http. Bigger P1s (#9-14, #49-50 shared IPC
store) and P2 shared-component extractions still need dedicated design.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
guan4tou2 added a commit that referenced this pull request Oct 8, 2026
Delete + export gaps from the second-pass audit (#24, #27, #30, #80):

  • Screenshot delete (#27) — deletes only the underlying JPEG; the source
    event STAYS in the DB so the SHA-256 hash chain doesn't break. Appends
    a chained system.screenshot_deleted event naming the source event, its
    basename, and the pre-delete sha256 for later verification. Renderer
    shows a "(file deleted)" placeholder + hides the expand click.
  • Screenshot cap 50 → 500 (#30). Was hardcoded; a long engagement's
    older screenshots were unreachable from the UI.
  • Marks / Loot / Scope-violation exports (#24, #80) — three new IPC
    routes (data.exportMarks / exportLoot / exportViolations) that dump a
    slice of the project DB to the same `exports/` dir as the full
    exportJson, timestamped filename. Small Export buttons appear on
    each panel's header when there's data to export. Path shows in a
    toast; matches the existing profileExport / scopeExport pattern.

New IPC surface:
  main : screenshot:deleteFile / data:exportMarks / data:exportLoot /
         data:exportViolations
  preload : screenshot.deleteFile, data.exportMarks/Loot/Violations

i18n: 12 new keys (screenshots.deleted*/deleteConfirm, marks/loot/scope.
export, toast.exportedTo, toast.exportFailed) in en + zh-TW.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
guan4tou2 added a commit that referenced this pull request Oct 8, 2026
Timeline: group the toolbar toggles, band the eighteen lanes
guan4tou2 added a commit that referenced this pull request Oct 8, 2026
…ocus

  • #25 FindingsView CDP poll now backs off from 3s → 10s while the browser
    isn't running. Was hitting IPC every 3s regardless.
  • #26 Mark URLs (both the primary and the auto-captured browserUrl) now
    open in the operator's real browser via app.openExternal — was inert
    plain text before. New http/https-only openExternal IPC (rejects file:
    and other schemes so untrusted content can't dispatch side effects).
  • #27 SearchPanel results are clickable — click jumps to the event on
    the Timeline via the existing focusEvent flow. Also dropped the q<2
    gate to q<1 so single-char IPs/octets work.
  • #37 Cluster popover now flips ABOVE the cluster when the natural
    position would drop it off the bottom of the timeline (last-lane
    clusters).
  • #39 Recent-project delete ✕ now shows on focus, not only hover —
    keyboard users can reach it. Also gained a focus ring.
  • #47 Timeline zoom-reset button gained a ↺ glyph so the click-to-reset
    behaviour is discoverable (was just the percentage number), plus is
    disabled at 100% and has aria-label + focus ring.

New i18n keys: marks.openUrl, search.openInTimeline (en + zh-TW).

Deferred (still queued): #24 already fixed by v0.6.29's shortcut order
change; #33 uptime → engagement start; #38 timeline layout with detail
panel; #48 MCP UI stdio vs http. Bigger P1s (#9-14, #49-50 shared IPC
store) and P2 shared-component extractions still need dedicated design.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
guan4tou2 added a commit that referenced this pull request Oct 8, 2026
Delete + export gaps from the second-pass audit (#24, #27, #30, #80):

  • Screenshot delete (#27) — deletes only the underlying JPEG; the source
    event STAYS in the DB so the SHA-256 hash chain doesn't break. Appends
    a chained system.screenshot_deleted event naming the source event, its
    basename, and the pre-delete sha256 for later verification. Renderer
    shows a "(file deleted)" placeholder + hides the expand click.
  • Screenshot cap 50 → 500 (#30). Was hardcoded; a long engagement's
    older screenshots were unreachable from the UI.
  • Marks / Loot / Scope-violation exports (#24, #80) — three new IPC
    routes (data.exportMarks / exportLoot / exportViolations) that dump a
    slice of the project DB to the same `exports/` dir as the full
    exportJson, timestamped filename. Small Export buttons appear on
    each panel's header when there's data to export. Path shows in a
    toast; matches the existing profileExport / scopeExport pattern.

New IPC surface:
  main : screenshot:deleteFile / data:exportMarks / data:exportLoot /
         data:exportViolations
  preload : screenshot.deleteFile, data.exportMarks/Loot/Violations

i18n: 12 new keys (screenshots.deleted*/deleteConfirm, marks/loot/scope.
export, toast.exportedTo, toast.exportFailed) in en + zh-TW.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
guan4tou2 added a commit that referenced this pull request Oct 8, 2026
Timeline: group the toolbar toggles, band the eighteen lanes
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