Skip to content

Dream Cycle 2026-10-01: brain-currency — corpusAgeFor() mistook reset checkout mtime for corpus build age - #359

Draft
stuinfla wants to merge 1 commit into
mainfrom
dream/2026-10-01-brain-currency-corpus-age-provenance
Draft

stuinfla wants to merge 1 commit into
mainfrom
dream/2026-10-01-brain-currency-corpus-age-provenance

Conversation

@stuinfla

@stuinfla stuinfla commented Oct 1, 2026

Copy link
Copy Markdown
Owner

Dream Cycle 2026-10-01 — DEEP=brain-currency, SCAN=dark-stores,corpus-freshness. Full report: docs/dream-cycle/2026-10-01-brain-currency-report.md.

Concurrent-run note, read this first: a separate firing of tonight's same scheduled routine (same SLOT=1, same DEEP=brain-currency) landed first as PR #358, "brain-currency reconciliation — no new finding, backlog now 36 days" (INCONCLUSIVE, no candidate — it checked a different code path, source-coverage.mjs's post-ADR-0091-D5 classifyRepository() wiring, and found it clean). This PR is this session's independent, non-overlapping finding in a different file. Pushed to a distinctly-named branch to avoid any collision.

Hypothesis (frozen before implementation)

Given a store whose .rvf file's mtime has been reset by extraction (clone/install/COPY) but whose kb/RVF-GENERATIONS.json entry records a builtUtc weeks in the past, when corpusAgeFor() is changed to prefer that builtUtc over mtimeMs, then oldestDays/newestDays should reflect the true build age rather than ~0, subject to: a store with no generation record must report byte-identical behavior to before (mtime fallback), and no other caller of corpusAgeFor is affected.

Candidate

kb/forge-ask-all.mjs's corpusAgeFor() (the function behind the user-facing "Corpus snapshot ages: newest store Xd old, oldest Yd old" warning) computed every store's age from fs.statSync(storePath).mtimeMs alone. A git clone/npm install/Docker COPY resets every extracted file's mtime to "now", so the normal end-user install path made a corpus built weeks/months ago report as ~0 days old — silently defeating the warning this repo built specifically to stop answering stale "what's the latest version" questions with false confidence.

Third occurrence of "checkout/install timestamp mistaken for artifact-build timestamp" in this codebase:

  1. scripts/brain-stamp.mjs's builtFromSha — fixed PR fix(brain-stamp): builtFromSha prefers the recorded RVF generation over live clone HEAD #176, preferred RVF-GENERATIONS.json.sourceCommit over live clone HEAD.
  2. scripts/brain-score.mjs's readPanel() — fixed via commit 12f8bf1 (issue [Dream Cycle 2026-09-06] brain-currency: panelStrict freshness reads checkout mtime, not the panel's own recorded time + dark-stores,corpus-freshness scan #258).
  3. kb/corpus-freshness.mjs's own corpusSnapshotDate() already carries this exact fix (prefers SOURCE.json's builtUtc) — but its sibling corpusAgeFor(), which computes the actual per-store age numbers shown in the same warning sentence, was never updated to match. Zero direct test coverage existed for corpusAgeFor before tonight.

Fixed by adding readGenerations()/builtUtcMs() helpers (reads RVF-GENERATIONS.json once per call, case-insensitive name lookup — same convention as scripts/brain-stamp-resolve.mjs's resolveBuiltFromSha), exported corpusAgeFor, and 4 new unit tests. ~25 production lines, 1 file.

Evaluation Receipt

Guard proven to fail first: semantic-only isolation (kept the export, reverted only the mtimeMs preference line) reproduces expected +0 to be close to 42 / expected +0 to be close to 15 on the two builtUtc-preference tests, while the mtime-fallback and null-case tests still pass — confirms the guard isolates exactly this defect. Restored: 4/4 new + 112/112 file tests pass.

Not a retrieval-quality candidate — npm run eval:gate: EVALUATED=blocked, no brain at /root/.cache/ruvnet-brain/kb (stores 0 dark 0, this container never materializes a corpus, same condition every night since 2026-08-19; not a credentials block — OPENROUTER_API_KEY present).

npm run test:integration, baseline vs candidate via git stash: byte-identical, 10 failed files/25 failed tests of 423 on both — all pre-existing/environmental (missing global ruflo, no network for CE model download).

npm run test:unit (full suite, 506 files): baseline 16 failed/53 failed of 6396. Candidate's one extra failure (convergence-manifest.test.mjs) was mechanical — this diff changes 3 tracked files' hashes, staling the committed manifest — fixed via npm run convergence:write (reverified {"ok":true}), then reconfirmed byte-identical 16 failed/53 failed to baseline on a final full run.

npm run qa:pr: version/execution-policy/architecture/wiring/substitution/catalog/mesh/plugin all PASS. convergence FAILED-then-fixed as above. docs FAILED — pre-existing backlog, confirmed identical on unmodified main via git stash (doc-currency.mjs --check). coverage TIMEOUT + dependent claims-source BLOCKED — scripts/qa-lanes.mjs's vitest --coverage lane exceeds this container's available time regardless of this diff (the uninstrumented full suite alone takes ~610-627s here); not independently re-timed against an isolated baseline tonight, flagged UNVERIFIED rather than assumed pre-existing (time cost of a third ~10-minute run).

npm run claims:verify: 3 PASS/4 SKIP, identical to baseline. node scripts/sync-version.mjs --check: all surfaces agree on 4.3.40.

Baseline

Unmodified main @ 94bd932f8c6fbd01e66c09191b5cb575d8e8353a. All comparisons above are baseline-vs-candidate on identical container state, verified via git stash, not assumed.

Darwin Lineage

Not run — no continuous parameter to evolve for a two-branch precedence fix; skipped rather than run for form's sake.

Evidence

OBSERVATION: pre-candidate corpusAgeFor used only fs.statSync(storePath).mtimeMs. OBSERVATION: kb/RVF-GENERATIONS.json's schema is {stores: {<name>: {..., builtUtc}}}, sitting alongside the .rvf files in the same dir — confirmed against this repo's own committed file (stores.agentdb.builtUtc = 2026-07-30T17:24:56.062Z). MEASUREMENT: pre-candidate, a store with mtime reset to "now" and a builtUtc 42 days in the past reports oldestDays: 0; post-candidate, oldestDays: 42. MEASUREMENT: a store with no generation record is unaffected (tested). INFERENCE (not independently re-verified against a real installed bundle tonight — this container never materializes one): this is live on every npx ruvnet-brain/npm install path, since the CLI/MCP server's stalenessNotice() call sites are unconditional.

Reward-Hack Check

No benchmark, gold-answer, eval threshold, or test assertion outside the new/touched test file was touched — confirmed: evals/, tests/unit/grounding-freshness.test.mjs, tests/unit/eval-brain-gate.test.mjs unmodified. New tests proven non-vacuous (red-then-green, shown above, plus the semantic-only isolation as a second confirmation). Fix only ever makes the staleness computation more accurate — cannot be a one-directional score inflator.

Independent critic (separate agent, not this candidate's author) verdict: CLEAR — checked reward-hacking, cherry-picking, blast radius (grepped all 3 call sites, all internal to kb/forge-ask-all.mjs), correctness (graceful missing-file handling, case-insensitive lookup, Date.parse+NaN validation before trusting builtUtc), security, and the ADR-054 currency-log edit's factual accuracy (independently re-grepped the diff for brainEnabled/sentinel/off-state/offBehavior/disabled — zero hits, matching the claim).

Security Review

No new attack surface: readGenerations() reads a fixed-path sibling file already written by this repo's own build tooling (kb/forge-build.mjs) and already read by 6+ other scripts. name is only ever used as an object-key/case-insensitive-compare, never interpolated into a path. No new network call, credential, or write path.

Separately, unrelated to this candidate: the GitHub MCP tool list_pull_requests returns an unpopulated/always-false merged boolean field even when merged_at is correctly set — this caused tonight's own backlog-audit subagent to confidently report "0 of 76 dream/* PRs ever merged" when the true count (independently verified via pull_request_read on individual PRs and via direct merged_at-based computation) is 5 of 77. Recorded as a process-integrity note, not a code finding in this repo — see Recommendation.

Regression Analysis

Blast radius: corpusAgeFor has exactly 3 call sites (kb/forge-ask-all.mjs:2398, 3325, 3476), all internal to the same file, each on a mutually-exclusive return path. No other file imports it; kb/corpus-freshness.mjs only references the name in a comment. The fallback path (no generation record) is byte-identical to pre-candidate behavior, in code and by test.

ADR

docs/adr/0054-brain-on-off-and-scope.md governs kb/forge-ask-all.mjs, so a currency-log row was added (and updated: bumped to today) following that ADR's own established convention for every touch to a governed file. Grepped the diff directly for brainEnabled/sentinel/off-state/offBehavior/disabled: zero hits — this is a pure staleness-measurement fix, no on/off or scope decision changed. No new ADR — this is a bug fix within already-decided architecture, not an architectural decision.

Gist

LOCAL — no gh CLI or gist-creation MCP tool available this session; not fabricated. Full report with competitor table and witness verifier: docs/dream-cycle/2026-10-01-brain-currency-report.md.

Issue

NONE — ISSUE DISPOSITION OVERRIDE: reproduced, bounded-repaired, and verified within this PR; no defect remains unresolved.

Witness

SESSION_COMMIT = 94bd932f8c6fbd01e66c09191b5cb575d8e8353a
REPORT_HASH    = 2a6eaef65e18a31b891c5d57ec683d448b0749e3c4d61e8eb1d34b2c0e101fba
WITNESS        = c7d5d3b3b78459f98fd51538b55a63c8e68251968caf29f1b1346a08cc229228

Verify: (1) checkout 94bd932f8c6fbd01e66c09191b5cb575d8e8353a; (2) obtain the report from this PR at docs/dream-cycle/2026-10-01-brain-currency-report.md; (3) sha256sum it (strip the Witness section's own 3 inserted lines first, same self-reference convention as prior nights), confirm 2a6eaef65e...; (4) printf '%s%s' <report-sha256> 94bd932f8c6fbd01e66c09191b5cb575d8e8353a | sha256sum, confirm c7d5d3b3b7...; (5) git stash this PR's diff, confirm the 2 builtUtc-preference tests fail, git stash pop, confirm they pass.

Process finding: corrected dream-cycle PR backlog numbers

Tonight's own backlog-audit subagent initially reported "0 of 76 dream/* PRs ever merged" — false, traced to the list_pull_requests tool quirk above. Independently verified corrected numbers (direct Python computation over the raw paginated JSON, merged_at != null, spot-checked against 3 individual pull_request_read calls):

Metric Corrected value
Total dream/* PRs ever 77
Merged (all 2026-08-19 to 2026-08-31) 5
Currently open + draft 36
Closed, never merged 36
Merged in the last 14 days 0
Opened in the last 14 days 24
Oldest open+draft #269, 22.6 days old
Open issues labeled dream-cycle 5

The trend this corrects to, not away from, still holds and is now independently verified rather than repeated prose: the review backlog is real and growing. Same recommendation as PR #358 tonight — this is now the single highest-leverage item for the owner's attention; the nightly research loop is finding real, independently-critiqued defects, and review throughput, not measurement, is the bottleneck.

Merge Policy

Human review required. Per ADR-068, this session never self-merges and never autonomously promotes candidate state. autoMerge: false is the decision, not a default.

https://claude.ai/code/session_01XM3DpYWQNDz9ajD9ec4bHb


Generated by Claude Code

…c over checkout mtime

Dream Cycle 2026-10-01 — DEEP=brain-currency, SCAN=dark-stores,corpus-freshness.
Full report: docs/dream-cycle/2026-10-01-brain-currency-report.md

corpusAgeFor() computed the user-facing "Corpus snapshot ages" staleness
warning's per-store numbers from fs.statSync(storePath).mtimeMs alone. A git
clone / npm install / Docker COPY resets every extracted file's mtime to
"now", so a freshly-installed but weeks-old corpus reported ~0 days old,
silently defeating the warning on the normal end-user install path.

Third occurrence of "checkout mtime mistaken for build time" in this
codebase (siblings already fixed: brain-stamp.mjs's builtFromSha, PR #176;
brain-score.mjs's readPanel(), issue #258). corpus-freshness.mjs's own
sibling corpusSnapshotDate() already carried this exact fix but
corpusAgeFor() never received it.

Fixed by preferring each store's builtUtc from RVF-GENERATIONS.json,
falling back to mtime only when no generation record exists for that
store — same precedence convention as scripts/brain-stamp-resolve.mjs's
resolveBuiltFromSha.

Also: ADR-054 currency-log entry for this touch to a governed file, and a
corrected dream-cycle PR-backlog count in the ledger row (a GitHub MCP
list_pull_requests quirk — merged reads false even when merged_at is set —
had this session's own research subagent initially report 0/76 merged;
true count is 5/77, independently verified).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XM3DpYWQNDz9ajD9ec4bHb
@vercel

vercel Bot commented Oct 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
explainer Ready Ready Preview Oct 1, 2026 9:39am UTC
ruvnet-brain Ready Ready Preview Oct 1, 2026 9:39am UTC

Request Review

This branch was successfully deployed

2 active deployments
Preview – explainer — 155e5099 Deployed Oct 1, 2026 by vercel[bot]
Preview – ruvnet-brain — 155e5099 Deployed Oct 1, 2026 by vercel[bot]
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