Skip to content

Add C4 release evidence dashboard - #87

Open
KevinBigham wants to merge 2 commits into
mainfrom
feat/evidence-dashboard
Open

Add C4 release evidence dashboard#87
KevinBigham wants to merge 2 commits into
mainfrom
feat/evidence-dashboard

Conversation

@KevinBigham

Copy link
Copy Markdown
Owner

Understanding

C4 (Fable board #14): "is the ledger current?" was ambiguous — gate results, bundle size, route sweep, and anomaly counts lived in different places with no single freshness view.

What changed

  • New scripts/evidence-dashboard.mjs (also pnpm evidence:dashboard) refreshes a marker-delimited ## Evidence Dashboard section at the top of STATUS.md. Idempotent: reruns replace only the marked section.
  • Rows: remote CI gate on main (test / determinism-gate / release-gate conclusions via gh), G6 route-sweep presence in the 37-step release contract, Ecology Lab nightly scoreboard, local release-gate contract integrity, engine-chunk bundle size vs the 312 KB ceiling (when a local build exists), Math.random determinism scan, opt-in fast-tier playtest anomalies (--with-playtest), and run-ledger freshness.
  • Every row carries the exact refresh command; --check exits non-zero on any red row (future CI hook).
  • STATUS.md gains the dashboard section plus a run-ledger entry (which also flips the freshness row green).
  • package.json gains evidence:dashboard.

What did not change

  • No engine source, no web source, no save schema/migrations/SAVE_VERSION, no sim math, no dependencies, no CI/deploy wiring.
  • Heavy gates are never run implicitly — rows point at the exact command instead.

Verification

Check Result
node scripts/evidence-dashboard.mjs all rows render; remote gate green @ main 10d9da3; idempotent across reruns ✅
node scripts/evidence-dashboard.mjs --check exit 0 with no red rows ✅
Ledger freshness row flips ✅ after the run-ledger entry lands ✅

Remote 37-step gate runs on this PR as a required check.

Rollback

Revert this commit; removes the script and STATUS.md section only.

kevin added 2 commits August 2, 2026 20:01
Replace narrativeState.hooks z.array(z.any()) with a strict
NarrativeHookSchema verified against the NarrativeHook interface and
both writers (franchise-week-helpers weekly refresh, convention-save
seed). type stays a free-form string: hooks-engine categories are an
open set. Adds 5 schema tests.
New scripts/evidence-dashboard.mjs (pnpm evidence:dashboard) refreshes
a marked Evidence Dashboard section at the top of STATUS.md: remote CI
gate per-check conclusions, G6 route-sweep contract presence, Ecology
Lab nightly scoreboard, local gate contract, bundle size vs ceiling,
Math.random scan, opt-in playtest anomalies, and ledger freshness.
--check exits non-zero on red rows for future CI use.
@KevinBigham
KevinBigham enabled auto-merge (squash) August 3, 2026 01:07

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 60ddf16d1c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const job = jobs.find((j) => j.name === name);
return `${name}:${job ? job.conclusion : '?'}`;
});
const status = ci.conclusion === 'success' ? OK : ci.status !== 'completed' ? WARN : FAIL;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Require named CI jobs before marking the gate green

When the CI workflow succeeds after one of the expected jobs is renamed or removed, this still marks the remote gate ✅ even though the evidence text reports that job as ?. Because this row is meant to attest specifically to test, determinism-gate, and release-gate, derive the status from all three named job conclusions as well as the workflow conclusion; otherwise a weakened CI contract is displayed as healthy.

Useful? React with 👍 / 👎.

Comment on lines +114 to +115
const gateList = tryExec(process.execPath, ['scripts/release-gate.mjs', '--list']);
const hasSweep = /g6|route sweep/i.test(gateList.out);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Match the visual sweep rather than any G6 step

If the visual route-sweep steps are removed while any other G6 step remains, this broad regex still turns the route-sweep row green. The inspected release plan contains unrelated g6-chip, g6-ux, and g6-mobile steps, so the check should look for the specific g6-visual-sweep-* IDs or g6-visual group before claiming that the visual/playability sweep remains in the contract.

Useful? React with 👍 / 👎.

evidence: gateList.ok && hasSweep
? 'G6 sweep step present in the 37-step release contract (runs inside every release-gate, local + remote)'
: 'G6 sweep step NOT found in release-gate contract',
pointer: 'node scripts/release-gate.mjs --only browser (local sweep)',

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Point the route-sweep refresh at its actual gate group

The advertised refresh command does not run the G6 route sweep: inspecting scripts/release-gate.mjs --only browser --list selects only built-page-smoke, g1-full-setup-desktop, and g5-cba-commissioner-browser. The visual sweep is in the g6-visual group, with its mobile counterpart under g6-mobile, so following this dashboard instruction cannot refresh the evidence named by the row.

Useful? React with 👍 / 👎.

pointer: 'pnpm --filter @mfd/web build && bash scripts/check-bundle-size.sh',
});
} else {
const chunk = readdirSync(distDir).find((f) => /^engine-.*\.js$/.test(f) && !f.startsWith('engine-content-'));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject multiple engine chunks before reporting bundle health

When a build contains multiple non-content engine-*.js chunks, find silently measures whichever filename readdirSync returns first and may report ✅. The authoritative scripts/check-bundle-size.sh explicitly fails unless exactly one matching engine chunk exists, so this dashboard can disagree with the real release gate after an accidental chunk split; count the candidates and fail the row unless there is exactly one.

Useful? React with 👍 / 👎.

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.

2 participants