feat: v8 ctx-split swimlane — dashboard integration (#91)#124
Merged
Conversation
Replace v7 turn bars in public/workflow-timeline.js with the v8 design (9.03/10, autoresearch 3 rounds): - bar height = ctx window % with cache read/write/input 3-color split - 40%/80% threshold dashed lines (gray/red) replace zone-hue bars - cost moves to a dedicated 8px mini-bar track (orange when >3x lane median) - 4 event tracks (Faults/Context/Mutations/Safety), exclusive color family; collapsed lanes show Faults+Safety only - tri-state interaction: Idle -> Hover (bars 1..N cumulative spotlight, unique per-lane cursor guide, rich tooltip) -> Locked (click, cross-lane dim 0.35, Esc/re-click unlock) - event detection aligned to real SSE entry fields (status/isRetry/ isCompacted/toolCalls/hasCredential/usage); undetectable design events (perm-denied, git-commit, danger-bash, perm-prompt, unsafe-blocked) deferred until server signals exist Smoke-tested against real restored logs on an isolated CCXRAY_HOME (light + dark theme, hover/lock/unlock/lane-expand verified in Chrome). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Net result of the post-integration design review: - legend drawn inside the main SVG axis row label zone (x 0-240 was empty) instead of squeezing the overview minimap - no per-lane cursor guide / lock ghost: the pre-existing #wf-cursor band carries lock position and the bar-highlight boundary marks the hover edge (prototype's guide compensated for having no band) - hovered lane fully undims (class toggle, not CSS :hover 0.7); cross- lane dim restored on leave - leaving the locked lane mid-hover snaps its highlight back to the locked turn - tooltip shows a lock reminder when hovering a non-locked turn on the locked lane Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- workflow-view-design.md: new §v8 encoding section (lane anatomy, event detection table wired to real SSE fields, tri-state interaction); mark v1.10 zone-coloring superseded for turn bars; P12 amendment — swimlane expresses zone thresholds by position, other elements by color - design-principles.md: Implicit Bridging example updated (bridge moved from zone hue to shared threshold position in v8); lane heights 64/88 - DESIGN-DECISIONS.md: integration decisions 15-17 (legend placement, guide/ghost removal rationale, band stays single-turn) + lessons 17-18 (audit production affordances before porting prototype compensations; detect events from real fields only, defer the rest) - CLAUDE.md: add missing public/workflow-timeline.js row to client table Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
User feedback: 7-8px SVG text unreadable; cache read #58a6ff identical to --accent so data fill was indistinguishable from viewport border / cursor band / selection chrome. - Type scale: lane label 9→11px, axis ticks/legend/zoom badge/overview canvas 8→10px, 40/80 threshold + event track labels 7→9px (9px floor) - WF_V8_CACHE_READ #58a6ff → #39c5cf (teal); accent blue now reserved for position/selection chrome only - Docs: design spec §v8 + DESIGN-DECISIONS integration decisions 18-19 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
KNOWN_AGENTS detection already ran server-side to feed versionIndex,
but the result never reached entries or the client. Now:
- SSE/HTTP path (server/index.js): agentKey/agentLabel from
registerPromptVersion, with extractPromptAgentType fallback for
short-form prompts (subagents, title-gen); carried on forward ctx
and returned by both wire parsers' buildEntryFields
- WebSocket path (ws-proxy): computes sysHash/toolsHash, registers
prompt identity, and writes shared instructions/tools/prompt-meta
files exactly like the HTTP path — codex's normal transport gets
the same fields. Header agent_type (x-codex-turn-metadata) merges
fill-if-absent, matching withCodexMetadata precedence (body wins);
captured requests without instructions classify via
extractPromptAgentType (codex default)
- index.ndjson: agentKey/agentLabel added to INDEX_FIELDS; restore
backfills old lines from the shared sys_ file scan
(sysHashToAgentKey now carries {key, label})
- rebuild-index: rebuilt lines preserve sysHash/toolsHash from the
stripped req and recompute coreHash/agentKey/agentLabel from the
rehydrated system prompt (offline twin of registerPromptVersion)
- summarizeEntry exposes both fields to SSE/API clients
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ation Lane label gutter (240px) becomes a 3-row agent info block: - Row 1 (11px): agent name — detected agentLabel; child lanes append the 8-char session id; fallback subagent-<model> when the request has no system prompt to detect from - Row 2 (10px): model · context window size - Row 3 (10px): sysprompt version chips, one per distinct coreHash in first-seen order, width-budgeted (~196px) with +n overflow. Chip click locks the turn where that version first appeared; ↗ opens the System Prompt page pre-selected via spPendingDeepLink state handoff (URL params don't survive syncUrlFromState's rebuild — the prompt badge has the same latent race). Hashes/keys are validated (hex / safe charset) before innerHTML interpolation since escapeHtml doesn't cover quotes. Lane classification is agent-identity-first: main keys (orchestrator / sdk-agent / codex default) always go to the main lane regardless of model switches or the isSubagent flag — a mid-session opus→fable switch no longer splits the orchestrator into a phantom sub-lane (157c0faa: 32/287 turns split, sub-lane literally named "Orchestrator"). Other keys get an agent-<key> lane named by agentLabel. Model/ctx heuristics remain as fallback for entries without agent identity. Main lane is longest and on top; sub lanes sort by first-turn time. Lane selection with no locked turn renders the last turn's Timeline detail directly (its request carries the whole conversation = full range) with no lock visuals — _wfShowTurnDetail suppresses the selectTurn → wfHighlightTurn echo. No flat-list intermediate state. Closes #121 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Jul 4, 2026
This was referenced Jul 4, 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.
繁體中文摘要
把 v8 ctx-split swimlane 設計(prototype 9.03/10)整合進正式 dashboard 的 workflow view,並依實際使用回饋完成六輪迭代:
#58a6ff改 teal#39c5cf——原色與 accent 藍完全同值,資料填色會與選取框線/色帶混淆agentKey/agentLabel)現在跟著每個 entry 走(SSE/HTTP/WebSocket/index.ndjson/rebuild),舊資料由 restore 從 shared sys_ 檔反查 backfill/fast切換、opus→fable)不再把主 agent 切成假 subagent lane(fix: lane inference misclassifies /fast model switch as subagent #113 的 1050-turn 誤判、157c0faa 的 287-turn 誤判都由此修復)Codex CLI 二審四輪收斂(R1 3 findings → R4 PASS),詳見下方 Review trail。
Lane gutter (240px)
Lane classification (agent-identity-first)
Classification:
agentKey ∈ {orchestrator, sdk-agent, default}→ main lane, regardless of model orisSubagent; other keys →agent-<key>lane named byagentLabel; entries without identity (old data, no system prompt) fall back to the previous model/ctx heuristics.Agent identity data flow (new)
English details
Commit 1 — legibility pass
WF_V8_CACHE_READ#58a6ff→#39c5cf; rule recorded in spec: accent blue is reserved for position/selection chrome, data fill must not use itCommit 2 — agent identity on every entry (server)
registerPromptVersion,extractPromptAgentTypefallback for short-form prompts (subagents, title-gen)sysHash/toolsHash, registers prompt identity, writes shared instructions/tools/prompt-meta files — full parity with the HTTP path incl.x-codex-turn-metadataagent_type merged fill-if-absent (body wins) and no-instructions fallback (→ codexdefault)index.ndjsonschema:agentKey/agentLabeladded; restore backfills old lines from the sharedsys_scanrebuild-index: preservessysHash/toolsHashfrom stripped reqs, recomputes identity from the rehydrated system prompt (offline twin ofregisterPromptVersion)Commit 3 — client UI
+noverflow), hex/charset-validated before innerHTML interpolation (escapeHtmldoesn't cover quotes)↗deep-link viaspPendingDeepLinkstate handoff — URL params don't survivesyncUrlFromState's rebuild (note: the prompt badge's "View in System Prompt" has the same latent race, untouched here)_wfShowTurnDetailsuppresses theselectTurn → wfHighlightTurnecho); no flat-list intermediate stateReview trail (codex CLI, 4 rounds)
Testing
CCXRAY_HOME: only pre-existing failure is flaky test: codex-adapter rate_limits fixture fails intermittently (expected 1, got 0) #119 (codex-adapter fixture time bomb, root cause posted there)CCXRAY_HOME+ port with real session data: 6-lane misclassified session reclassifies to main=287t; chips click-to-turn and↗deep-link assertions; lane click → full-range detail withselectedTurnId === nullCloses #91, closes #113, closes #118, closes #121
Partially addresses #114 (fonts + lane height done; resize-handle grip and taller minimap remain) and #117 (part A identity recording done; part B spawn/return arcs remain)
🤖 Generated with Claude Code