Skip to content

Hub truth fixes: events-fallback timeline, honest integrity count, Proof Rail names its run (#496, #497, #498) - #511

Merged
richard-devbot merged 5 commits into
mainfrom
claude/hub-truth-fixes-496-498
Jul 31, 2026
Merged

Hub truth fixes: events-fallback timeline, honest integrity count, Proof Rail names its run (#496, #497, #498)#511
richard-devbot merged 5 commits into
mainfrom
claude/hub-truth-fixes-496-498

Conversation

@richard-devbot

@richard-devbot richard-devbot commented Jul 31, 2026

Copy link
Copy Markdown
Owner

The last three bugs from the 2026-07-30 tour's batch — all dashboard-truthfulness fixes, one bisected commit per issue, TDD throughout (every test verified failing on unfixed code first).

Closes #496
Closes #497
Closes #498

Commit 1 — #496: the timeline falls back to events.jsonl

The Run Workspace timeline read only the derived collections (run.timeline/run.activityTimeline, populated for index entries since #296) — legacy and fixture-shaped runs declared "no recorded timeline events" while events.jsonl sat populated in the same snapshot. The projection now derives a minimal timeline from events when the derived collections are empty (time-ordered, capped at the index's own 120), and the page labels it — "Derived from events.jsonl — this run has no persisted timeline" — the same honesty convention as the 3D Studio's lifecycle timeline. Derived timelines keep precedence (no double-merge); the honest empty state remains when both sources are empty.

Commit 2 — #497: the integrity signal is never a false zero

buildDiagnostics aggregated integrity over fully-parsed runs only; index-served runs carry has_integrity_errors (INDEX_VERSION 5, the #316 parity fix) but not the detail array — a damaged run served from the rollup index contributed nothing, and Diagnostics read "0" with the damaged run in plain view. Index-served damage now counts and names its run ("rollup index entry — run reports damaged files — open the run for per-file detail"); fully-parsed detail unchanged, no double-counting. Pinned by unit cases plus a real two-build round-trip (first build persists the index, second serves the damaged run from it — the exact false-zero path). Persisting compact detail into index entries rides the next INDEX_VERSION bump (noted on the issue).

Commit 3 — #498: the Proof Rail names and follows its run

At all-runs scope the hero cited one run's verdict while the rail silently rendered a different run's stages — 15 unqualified "Not Started" beside "coverage 85%" read as the dashboard disagreeing with itself. Server-owned fix in the overview projection: focusRun prefers the run the verdict's first blocker cites (in-scope only, safe fallbacks), and stagesSource {runId, goal} labels the rail ("Stage proof from Blocked fixture — exhausted retries · run-fx-blocked"). Pages render the label; they never re-derive it.

Verification

  • Core suite 1721/1721 (exit 0) · browser regression 5/5 · lint 0 errors · typecheck 0 · validate 196 agents · schemas 34 PASS · security gate green · whitespace clean.
  • Live-verified on the fixture-seeded hub: Timeline tab shows all 5 events with the source note; Diagnostics reads "Data integrity errors: 1" naming run-fx-damaged through its index entry; the Command Center hero's verdict, goal chip, and rail all speak about the same run with the source label visible. Zero console errors.

Merge-order note

state/overview.js is also touched by #508 (#493's rationale fix) — the hunks are adjacent (both in buildOverviewProjection), so whichever merges second may hit a trivial conflict (keep both: #508's rationale field + this PR's stagesSource field and readiness-first ordering). Everything else is disjoint from #504/#508/#509.

Held for Richardson's batch review — please verify before merge.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Overview proof rails now identify the run and goal supporting displayed stages.
    • Run timelines can fall back to recent event data and indicate when sourced from events.jsonl.
    • Diagnostics now include integrity issues from indexed runs.
  • Bug Fixes

    • Overview selection now prioritizes runs associated with readiness blockers.
    • Improved visibility and counting of damaged runs without duplicate reporting.

richardsongunde and others added 3 commits July 31, 2026 19:11
The timeline section read only the derived collections (run.timeline /
run.activityTimeline, populated for index entries since #296), so legacy
runs, fixture-shaped runs, and index entries predating the field declared
"no recorded timeline events" while events.jsonl sat populated in the
same snapshot — the Live Feed rendered those exact events one page over.

readableTimeline now derives a minimal timeline from events when the
derived collections are empty (ts/type/task_id/stage_id, time-ordered,
capped to the most recent 120 — the index's own timeline cap), and the
section carries its source. The page labels the fallback ("Derived from
events.jsonl — this run has no persisted timeline"), matching the 3D
Studio's "events.jsonl projection" honesty convention. Derived timelines
keep precedence (no event double-merge) and the honest empty state
remains when both sources are empty — all pinned, verified failing first.

Closes #496.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
buildDiagnostics aggregated integrity detail over fully-parsed runs only;
index-served runs carry the has_integrity_errors boolean (persisted at
INDEX_VERSION 5 by the #316 lite-full parity fix) but not the integrity[]
detail array — so a damaged run served from the rollup index contributed
nothing, and Diagnostics read "Data integrity errors: 0" with the damaged
run in plain view (observed live in the 2026-07-30 tour). The #316 class
one level deeper: the badge boolean made it into the index, the detail
array feeding Diagnostics did not.

Index-served damaged runs now count and appear in the problem list naming
their run, with an honest entry that per-file detail requires a full
parse ("rollup index entry — run reports damaged files"). Fully-parsed
detail is unchanged and never double-counts via its own boolean. Pinned
by unit cases plus a real two-build round-trip (first build parses fully
and persists the index, the second serves the damaged run from it — the
exact path that reported zero), verified failing first.

Persisting the compact detail into index entries rides the next
INDEX_VERSION bump, noted on the issue.

Closes #497.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
At all-runs scope the hero cited one run's readiness verdict ("blocked,
coverage 85%") while the Proof Rail silently rendered a DIFFERENT run's
stages — 15 unqualified "Not Started" beside a non-zero coverage verdict
read as the dashboard disagreeing with itself (observed live in the
2026-07-30 tour: the verdict cited run-fx-blocked, the rail showed
run-fx-stale).

Two server-owned changes in the overview projection: focusRun now prefers
the run the verdict's first blocker cites (when that run is in scope), so
the rail reflects the run the hero is talking about; and the projection
exposes stagesSource {runId, goal} so the rail labels which run it shows
("Stage proof from <goal> · <runId>") — pages render the label, they
never re-derive it. No-blocker verdicts keep the existing focus
selection, citations outside the scope fall back safely, and no-runs
scopes invent nothing — all pinned, verified failing first.

Live-verified at all-runs scope: verdict, goal chip, and rail now speak
about the same run, with the source label under the rail title.

Closes #498.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@strix-security

strix-security Bot commented Jul 31, 2026

Copy link
Copy Markdown

Strix Security Review

No security issues found.

Updated for 5047f89.


Reviewed by Strix
Re-run review · Configure security review settings

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@richard-devbot, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 47 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 59224861-b5ee-4590-89fb-42e29c83210b

📥 Commits

Reviewing files that changed from the base of the PR and between 5047f89 and d524b5c.

📒 Files selected for processing (4)
  • src/observability/dashboard/state/overview.js
  • src/observability/dashboard/state/run-workspace.js
  • src/observability/dashboard/ui/pages/command-center.js
  • src/observability/dashboard/ui/pages/run-workspace.js
📝 Walkthrough

Walkthrough

This PR changes diagnostics integrity counting to include index-served runs with synthetic entries, updates overview run selection to prioritize readiness-blocker-referenced runs and expose stagesSource, and adds an events-based timeline fallback with source labeling in run-workspace. Regression tests cover each area.

Changes

Dashboard integrity, selection, and timeline updates

Layer / File(s) Summary
Diagnostics integrity counting for index-served runs
src/observability/dashboard/state/layers.js, tests/diagnostics-integrity-497.test.js
buildDiagnostics reports integrity errors from index-served runs using synthetic entries, counted alongside detailed issues from fully parsed runs. Tests verify counting, naming, and no double-counting.
Readiness-based run selection and stage source
src/observability/dashboard/state/overview.js, src/observability/dashboard/ui/pages/command-center.js, src/observability/dashboard/ui/pages/index.js, tests/overview-proof-rail-498.test.js
focusRun selects the run cited by the first readiness blocker before existing fallback logic. buildOverviewProjection passes readiness through and returns stagesSource. Command Center renders the source label, with a supporting placeholder span added to the page markup. Tests cover selection, fallback, and label exposure.
Run-workspace timeline events fallback and source label
src/observability/dashboard/state/run-workspace.js, src/observability/dashboard/ui/pages/run-workspace.js, tests/run-workspace-timeline-496.test.js
readableTimeline returns items and source, falling back to normalized run.events data (capped at 120, sorted) when no persisted timeline exists. buildRunWorkspace and the UI consume timeline.items/timeline.source, showing a notice when data comes from events.jsonl. Tests cover fallback, precedence, and label rendering.

Estimated code review effort: 2 (Simple) | ~15 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Readiness
  participant OverviewProjection as buildOverviewProjection
  participant FocusRun as focusRun
  participant CommandCenter as command-center.js

  OverviewProjection->>FocusRun: pass readiness, runs
  FocusRun->>FocusRun: check first blocker sourceRef.runId
  FocusRun-->>OverviewProjection: selected run
  OverviewProjection-->>CommandCenter: stagesSource (runId, goal or null)
  CommandCenter->>CommandCenter: render or hide overview-proof-source
Loading

Possibly related issues

Possibly related PRs

Suggested reviewers: richardsongunde

Poem

A rabbit checked the runs today,
found blockers pointing clear the way.
Events.jsonl gave timelines new life,
no more counting errors twice with strife.
Hop, hop — the dashboard tells the truth! 🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes all three dashboard truthfulness fixes and identifies the main user-visible changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/hub-truth-fixes-496-498

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.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Dashboard truth fixes: timeline fallback, integrity counting, Proof Rail source

🐞 Bug fix 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Derive Run Workspace timeline from events when persisted timeline is missing, and label it.
• Count index-served integrity damage (no more false zero) while preserving parsed per-file detail.
• Make Proof Rail follow the verdict’s cited run and render a server-owned source label.
Diagram

graph TD
  IDX[("Rollup index") ] --> RUNS[("Runs in scope") ] --> WS["Run workspace projection"] --> WSUI{{"Run Workspace UI"}}
  RUNS --> DIAG["Diagnostics builder"]
  RUNS --> OVR["Overview projection"] --> CCUI{{"Command Center UI"}}
  READY[("Readiness verdict") ] --> OVR
  subgraph Legend
    direction LR
    _db[(Database / index)] ~~~ _mod["Projection / builder"] ~~~ _ui{{UI page}}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Persist integrity detail in the rollup index (now)
  • ➕ Eliminates placeholder integrity entries and enables per-file detail without a full parse
  • ➕ Makes diagnostics consistent across index-served and fully-parsed runs
  • ➖ Requires INDEX_VERSION bump + migration/compat logic
  • ➖ Increases index size and write costs; needs careful backward compatibility
2. Merge derived timeline and events timeline
  • ➕ Potentially shows the richest, most complete history in one view
  • ➕ Could recover missing derived events without changing pipeline persistence
  • ➖ Risk of duplicates and conflicting semantics between derived vs raw events
  • ➖ Harder to explain provenance; current precedence rule is clearer
3. Have readiness verdict explicitly publish focusRunId
  • ➕ Single authority for which run the hero/rail should represent
  • ➕ Avoids heuristic coupling in overview projection (blocker[0] citation interpretation)
  • ➖ Requires upstream readiness computation changes and additional contract surface
  • ➖ Less robust when verdict has no natural single run to cite

Recommendation: The PR’s approach is a good incremental fix: it preserves existing precedence rules (persisted timeline wins; fully-parsed integrity detail wins) while making partial/index-served data truthful via explicit provenance and labeling. Deferring index schema changes is reasonable given the required INDEX_VERSION bump; the placeholder integrity entry is honest and test-backed.

Files changed (9) +297 / -7

Bug fix (6) +69 / -7
layers.jsCount and name integrity errors for index-served runs +18/-2

Count and name integrity errors for index-served runs

• Extends buildDiagnostics integrity aggregation to include index-served runs that only provide hasIntegrityErrors. Adds a placeholder issue entry per damaged index run and increments the integrityErrorCount accordingly, while keeping parsed per-file detail unchanged and avoiding double-counting.

src/observability/dashboard/state/layers.js

overview.jsAlign Proof Rail focus run with readiness blocker citation +13/-2

Align Proof Rail focus run with readiness blocker citation

• Updates focusRun to prefer the runId cited by the readiness verdict’s first blocker when that run is in scope. Exposes stagesSource {runId, goal} in the overview projection so the UI can label which run’s stages are being displayed.

src/observability/dashboard/state/overview.js

run-workspace.jsFallback timeline derived from events when persisted timeline absent +19/-2

Fallback timeline derived from events when persisted timeline absent

• Refactors readableTimeline to return {items, source} and to fall back to a minimal, time-ordered timeline derived from run.events when the persisted derived timelines are empty. Caps the events-derived timeline to the most recent 120 entries and propagates the source into the workspace section model.

src/observability/dashboard/state/run-workspace.js

command-center.jsRender Proof Rail source label from overview.stagesSource +12/-0

Render Proof Rail source label from overview.stagesSource

• Adds DOM rendering for a Proof Rail source label driven by overview.stagesSource. The label is hidden when absent and shows a concise goal/runId string when present, preventing silent mismatches between verdict and displayed stages.

src/observability/dashboard/ui/pages/command-center.js

index.jsAdd placeholder element for Proof Rail source label +1/-0

Add placeholder element for Proof Rail source label

• Introduces a muted span (overview-proof-source) in the Proof Rail header to host the server-owned stages source label rendered by the Command Center script.

src/observability/dashboard/ui/pages/index.js

run-workspace.jsLabel events-derived timeline in Run Workspace UI +6/-1

Label events-derived timeline in Run Workspace UI

• Prepends a source note when the timeline section is derived from events.jsonl (run.events fallback) and keeps existing empty-state behavior when no timeline items exist. Ensures the UI communicates provenance rather than implying missing data.

src/observability/dashboard/ui/pages/run-workspace.js

Tests (3) +228 / -0
diagnostics-integrity-497.test.jsAdd unit + round-trip coverage for index-served integrity counting +70/-0

Add unit + round-trip coverage for index-served integrity counting

• Adds tests asserting that index-served damaged runs contribute to integrityErrorCount and are named with an honest message about missing per-file detail. Includes a two-build round-trip test that persists the rollup index then verifies the index-served damaged run no longer produces a false zero.

tests/diagnostics-integrity-497.test.js

overview-proof-rail-498.test.jsTest Proof Rail focus selection and stagesSource labeling +87/-0

Test Proof Rail focus selection and stagesSource labeling

• Adds projection tests ensuring the focus run follows a readiness blocker’s cited runId when in scope, preserves existing selection when uncited, and never follows out-of-scope citations. Also asserts the Command Center script consumes stagesSource for rendering.

tests/overview-proof-rail-498.test.js

run-workspace-timeline-496.test.jsTest timeline fallback to events and source labeling +71/-0

Test timeline fallback to events and source labeling

• Adds tests verifying that runs with events but no derived timeline get an events-sourced timeline, that persisted derived timelines retain precedence without merging, and that the empty state remains when both sources are empty. Includes a UI bundle assertion that the events.jsonl source label is rendered.

tests/run-workspace-timeline-496.test.js

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
tests/overview-proof-rail-498.test.js (1)

84-87: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Verify the rail source label through rendered DOM state.

assert.match(commandCenterScript, /stagesSource/) only checks that the script contains the property name. Add or extend the browser regression to call the renderer with an overview projection including stagesSource, then assert #overview-proof-source text and hidden state instead of relying on a string presence check.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/overview-proof-rail-498.test.js` around lines 84 - 87, Replace the
source-string assertion in the rail-label test with a browser regression that
invokes the renderer using an overview projection containing stagesSource, then
verify the rendered `#overview-proof-source` element has the expected text and
hidden state. Keep the test focused on the rendered DOM behavior rather than
merely checking commandCenterScript for the property name.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/diagnostics-integrity-497.test.js`:
- Around line 62-66: Update the test around buildFullState and the
run-fx-damaged lookup to make the fixture deterministically use the rollup-index
path, then assert that served.fromIndex is present instead of conditionally
calling t.skip. Keep the subsequent integrityErrorCount assertion so the test
always validates Diagnostics through the indexed serving path.

In `@tests/run-workspace-timeline-496.test.js`:
- Around line 41-71: The current renderer test only matches the string
"events.jsonl" in the bundle but does not verify it appears in the rendered
output when source is 'events' and omits it when source is 'persisted'. Add a
test that renders the workspace through the DOM regression path to verify the
source note actually displays for source 'events' but not for source
'persisted'. Additionally, add a test case with 121 ordered events to verify
that only the newest 120 entries are retained after capping, ensuring the
boundary enforcement is tested through the real rendering path rather than unit
assertions alone.

---

Nitpick comments:
In `@tests/overview-proof-rail-498.test.js`:
- Around line 84-87: Replace the source-string assertion in the rail-label test
with a browser regression that invokes the renderer using an overview projection
containing stagesSource, then verify the rendered `#overview-proof-source` element
has the expected text and hidden state. Keep the test focused on the rendered
DOM behavior rather than merely checking commandCenterScript for the property
name.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e69a5387-ec07-4f65-8074-31f8d373d792

📥 Commits

Reviewing files that changed from the base of the PR and between 544cfd8 and 5047f89.

📒 Files selected for processing (9)
  • src/observability/dashboard/state/layers.js
  • src/observability/dashboard/state/overview.js
  • src/observability/dashboard/state/run-workspace.js
  • src/observability/dashboard/ui/pages/command-center.js
  • src/observability/dashboard/ui/pages/index.js
  • src/observability/dashboard/ui/pages/run-workspace.js
  • tests/diagnostics-integrity-497.test.js
  • tests/overview-proof-rail-498.test.js
  • tests/run-workspace-timeline-496.test.js

Comment on lines +62 to +66
const second = await buildFullState(root, { includeRegistry: false });
const served = second.runs.find((run) => run.runId === 'run-fx-damaged');
assert.ok(served, 'the damaged run is in scope');
if (!served.fromIndex) t.skip('run was fully parsed again — index path not exercised in this environment');
assert.ok(second.diagnostics.integrityErrorCount >= 1,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not skip the index-served assertion.

This test can pass without exercising the rollup-index path. Make the fixture deterministic, then require served.fromIndex before asserting the Diagnostics result.

Proposed test change
-  if (!served.fromIndex) t.skip('run was fully parsed again — index path not exercised in this environment');
+  assert.equal(served.fromIndex, true,
+    'the second build must serve the damaged run from the rollup index');

As per coding guidelines, “Run regression tests against the real enforcement path where possible.”

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const second = await buildFullState(root, { includeRegistry: false });
const served = second.runs.find((run) => run.runId === 'run-fx-damaged');
assert.ok(served, 'the damaged run is in scope');
if (!served.fromIndex) t.skip('run was fully parsed again — index path not exercised in this environment');
assert.ok(second.diagnostics.integrityErrorCount >= 1,
const second = await buildFullState(root, { includeRegistry: false });
const served = second.runs.find((run) => run.runId === 'run-fx-damaged');
assert.ok(served, 'the damaged run is in scope');
assert.equal(served.fromIndex, true,
'the second build must serve the damaged run from the rollup index');
assert.ok(second.diagnostics.integrityErrorCount >= 1,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/diagnostics-integrity-497.test.js` around lines 62 - 66, Update the
test around buildFullState and the run-fx-damaged lookup to make the fixture
deterministically use the rollup-index path, then assert that served.fromIndex
is present instead of conditionally calling t.skip. Keep the subsequent
integrityErrorCount assertion so the test always validates Diagnostics through
the indexed serving path.

Source: Coding guidelines

Comment on lines +41 to +71
test('a run with events but no derived timeline gets an events-sourced timeline (#496)', () => {
const workspace = buildRunWorkspace(baseRun());
const timeline = workspace.sections.timeline;
assert.equal(timeline.available, true, 'the timeline is available');
assert.equal(timeline.items.length, 5, 'every event becomes an entry');
assert.equal(timeline.source, 'events', 'and the section names its fallback source');
assert.equal(timeline.items[0].ts, '2026-07-01T01:00:00.000Z', 'entries stay time-ordered');
assert.equal(timeline.items[0].type, 'task_started');
assert.equal(timeline.items[0].task_id, '07-code');
});

test('a derived timeline keeps precedence — no event double-merge (#496)', () => {
const workspace = buildRunWorkspace(baseRun({
timeline: [{ ts: '2026-07-01T05:00:00.000Z', type: 'stage_completed', stage_id: '07-code' }],
}));
const timeline = workspace.sections.timeline;
assert.equal(timeline.available, true);
assert.equal(timeline.items.length, 1, 'derived entries only — events never merge in beside them');
assert.equal(timeline.source, 'persisted');
});

test('a run with neither derived timeline nor events keeps the honest empty state (#496)', () => {
const workspace = buildRunWorkspace(baseRun({ events: [] }));
const timeline = workspace.sections.timeline;
assert.equal(timeline.available, false, 'no invented timeline');
});

test('the workspace page renders the events-fallback source label (#496)', () => {
const bundle = commandCenterScript + runWorkspaceScript;
assert.match(bundle, /events\.jsonl/, 'the renderer names the fallback source in the timeline section');
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Test the rendered source note and the cap boundary.

Line 70 matches events.jsonl in the explanatory comment in runWorkspaceScript. The test still passes if the section.source === 'events' branch is removed.

Run the renderer through the dashboard browser or DOM regression path. Assert that the note appears for source: 'events' and does not appear for source: 'persisted'. Add a case with 121 ordered events and assert that only the newest 120 entries remain.

As per coding guidelines, “Run regression tests against the real enforcement path where possible, including cross-process or browser behavior when those are the affected boundaries.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/run-workspace-timeline-496.test.js` around lines 41 - 71, The current
renderer test only matches the string "events.jsonl" in the bundle but does not
verify it appears in the rendered output when source is 'events' and omits it
when source is 'persisted'. Add a test that renders the workspace through the
DOM regression path to verify the source note actually displays for source
'events' but not for source 'persisted'. Additionally, add a test case with 121
ordered events to verify that only the newest 120 entries are retained after
capping, ensuring the boundary enforcement is tested through the real rendering
path rather than unit assertions alone.

Source: Coding guidelines

@qodo-code-review

qodo-code-review Bot commented Jul 31, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (3)

Context used
✅ Compliance rules (platform): 300 rules
✅ Skills: 17 invoked
  code-review-pr
  claude-api
  documentation-writing
  pptx
  docx
  performance-monitoring
  security-compliance
  cso
  plan-eng-review
  design-review
  prompt-engineering
  mcp-builder
  qa-testing
  code-patterns
  xlsx
  security-owasp
  testing-qa

Grey Divider


Remediation recommended

1. 120/54 magic numbers ✓ Resolved 📜 Skill insight ⚙ Maintainability
Description
New UI/state logic introduces hardcoded truncation caps (.slice(-120) and .slice(0, 54)) instead
of named constants. This reduces clarity and makes future adjustments error-prone/inconsistent
across the dashboard.
Code

src/observability/dashboard/state/run-workspace.js[R23-25]

+    .sort((a, b) => String(a.ts).localeCompare(String(b.ts)))
+    .slice(-120);
+  return { items: events, source: events.length ? 'events' : 'none' };
Relevance

●●● Strong

Team previously accepted replacing hardcoded numeric caps with named constants (magic-number
refactor) in PR #490.

PR-#490

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 1400588 requires replacing literal numeric caps with named constants. The PR adds
new truncation logic using .slice(-120) for timeline entries and .slice(0, 54) for the
proof-rail label, both of which are literal caps added/modified in this change.

src/observability/dashboard/state/run-workspace.js[23-25]
src/observability/dashboard/ui/pages/command-center.js[142-144]
Skill: code-patterns

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New code introduces magic numbers (`120`, `54`) for truncation/labeling logic instead of named constants.

## Issue Context
Compliance requires replacing literal numeric caps with descriptive constants so intent is clear and caps can be updated consistently.

## Fix Focus Areas
- src/observability/dashboard/state/run-workspace.js[23-25]
- src/observability/dashboard/ui/pages/command-center.js[142-144]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

2. Missing regression attribution metadata 📜 Skill insight ⚙ Maintainability
Description
The new regression-style test files include issue context but do not include the required found-date
and QA report path attribution fields. This makes it harder to audit and trace regressions back to
discovery context.
Code

tests/run-workspace-timeline-496.test.js[R1-14]

+/**
+ * #496 — the Run Workspace timeline falls back to events.jsonl.
+ *
+ * The timeline section read only the derived timeline collections
+ * (run.timeline / run.activityTimeline, populated for index-served runs
+ * since #296). Runs without them — legacy runs, fixture-shaped runs, index
+ * entries predating the field — declared "no recorded timeline events" while
+ * events.jsonl sat populated in the same snapshot. The projection now
+ * derives a minimal timeline from events when the derived collections are
+ * empty, labeled with its source; the honest empty state remains only when
+ * both sources are empty.
+ *
+ * owner: RStack developed by Richardson Gunde
+ */
Relevance

● Weak

Regression-test header metadata (found-date/QA report path) requests were rejected previously (PR
#475).

PR-#475

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 1400067 requires regression tests to include attribution comments with issue ID,
what broke, date found, and QA report path. The new test headers describe the issue but omit the
date found and QA report reference.

tests/run-workspace-timeline-496.test.js[1-14]
tests/diagnostics-integrity-497.test.js[1-14]
tests/overview-proof-rail-498.test.js[1-13]
Skill: qa-testing

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New regression test files added for #496/#497/#498 are missing required attribution metadata fields (found date and QA report path reference).

## Issue Context
The compliance rule requires regression tests to include: issue ID, description of what broke, the date found, and a reference to the QA report path.

## Fix Focus Areas
- tests/run-workspace-timeline-496.test.js[1-14]
- tests/diagnostics-integrity-497.test.js[1-14]
- tests/overview-proof-rail-498.test.js[1-13]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. run() helper name too vague 📜 Skill insight ⚙ Maintainability
Description
The new test helper function is named run, which is a noun-only, non-descriptive name and does not
follow the required verb-noun naming pattern. This reduces readability and makes it harder to
understand intent when scanning tests.
Code

tests/overview-proof-rail-498.test.js[R21-29]

+function run(runId, goal, extras = {}) {
+  return {
+    runId,
+    projectRoot: '/tmp/p',
+    manifest: { goal },
+    tasks: [],
+    ...extras,
+  };
+}
Relevance

● Weak

Verb-noun/rename-vague-helper naming suggestions were explicitly rejected (e.g., function rename
requests) in PR #488.

PR-#488

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 1399694 requires JavaScript/TypeScript function names to follow a verb-noun
pattern. The added helper function run(...) is noun-only/vague and does not indicate the action
being performed (it constructs a run fixture object).

tests/overview-proof-rail-498.test.js[21-29]
Skill: code-patterns

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A newly added helper function is named `run`, which is noun-only/vague and violates the verb-noun function naming requirement.

## Issue Context
This helper constructs run objects for overview projection tests; the name should communicate construction intent (e.g., `makeRun`, `buildRunFixture`).

## Fix Focus Areas
- tests/overview-proof-rail-498.test.js[21-29]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Filesystem I/O in test 📜 Skill insight ▣ Testability
Description
The new test performs real filesystem operations (creating/removing temp directories and writing
fixture data) instead of mocking/stubbing external dependencies. This violates the requirement that
tests must mock external dependencies to avoid brittleness and environment-dependent failures.
Code

tests/diagnostics-integrity-497.test.js[R51-63]

+test('a damaged run stays visible in Diagnostics when served from the rollup index (#497)', async (t) => {
+  const root = realpathSync(mkdtempSync(join(tmpdir(), 'rstack-integrity-497-')));
+  t.after(() => rmSync(root, { recursive: true, force: true }));
+  await fixtureMalformedRun(root);
+
+  // First build parses fully and persists the rollup index; the second build
+  // serves the (stale, inactive) damaged run from that index — the exact
+  // path that reported zero.
+  const first = await buildFullState(root, { includeRegistry: false });
+  assert.ok(first.diagnostics.integrityErrorCount >= 1, 'full parse sees the damage');
+
+  const second = await buildFullState(root, { includeRegistry: false });
+  const served = second.runs.find((run) => run.runId === 'run-fx-damaged');
Relevance

● Weak

Repo routinely uses real temp dirs/files in tests (mkdtempSync/rmSync) without mocking; accepted in
PR #167.

PR-#167

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 1400146 requires tests to mock external dependencies (including filesystem
operations). The added test creates and deletes real temporary directories and writes/reads run
artifacts via fixtureMalformedRun + buildFullState, which is direct filesystem usage in a test.

tests/diagnostics-integrity-497.test.js[51-63]
Skill: qa-testing

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`tests/diagnostics-integrity-497.test.js` performs real filesystem I/O (temp dir creation, teardown, fixture writes, and a full state build that reads/writes disk). The compliance rule requires tests to mock external dependencies (including filesystem operations) rather than touching the real FS.

## Issue Context
This test currently uses `mkdtempSync`, `rmSync`, and `fixtureMalformedRun(root)` and then runs `buildFullState(root, ...)` twice, which depends on reading/writing the project snapshot/index on disk.

## Fix Focus Areas
- tests/diagnostics-integrity-497.test.js[51-63]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread src/observability/dashboard/state/run-workspace.js
Qodo (convention, PR #490 precedent): the events-timeline depth cap and
the rail-label goal length are named constants (EVENTS_TIMELINE_CAP —
matching the rollup index's own timeline depth — and
PROOF_SOURCE_GOAL_CHARS).

Refs #496 #498 (PR #511 review follow-up).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@richard-devbot

Copy link
Copy Markdown
Owner Author

Qodo's single insight addressed in the follow-up commit (it reported Bugs (0); Strix: 0 findings; CodeRabbit reviewed clean — no rate limit this time): the 120/54 truncation caps are now named constants (EVENTS_TIMELINE_CAP, matching the rollup index's own timeline depth, and PROOF_SOURCE_GOAL_CHARS) per the #490 convention. Batch tests 9/9, lint clean. — Claude Main

@richard-devbot
richard-devbot merged commit 844cb8c into main Jul 31, 2026
9 checks passed
richard-devbot pushed a commit that referenced this pull request Jul 31, 2026
Qodo (convention, #490/#509/#511 precedent): the settle guard's 120ms
slack is now COUNT_UP_SETTLE_BUFFER_MS with its rationale.

Refs #516 (PR #520 review follow-up).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants