diff --git a/docs/dream-cycle/2026-09-23-grounding-quality-report.md b/docs/dream-cycle/2026-09-23-grounding-quality-report.md new file mode 100644 index 00000000..b11f17d1 --- /dev/null +++ b/docs/dream-cycle/2026-09-23-grounding-quality-report.md @@ -0,0 +1,137 @@ +# Dream Cycle 2026-09-23 — grounding-quality reconciliation + +DEEP=`grounding-quality`, SCAN=`retrieval-precision`,`citation-binding` (slot 3 of 5, +`20260923 % 5 == 3`). No bonus deep dive tonight (`% 25` = 23, `% 75` = 48, both non-zero). + +## Rotation / Ledger Check + +`docs/dream-cycle/LEDGER.md` on `main` still ends at 2026-08-31 — expected, not a gap: the ledger +row ships in the candidate PR by convention and nothing on this surface has merged since #178 +(2026-08-26). Re-checked recent fates directly rather than assuming: + +- **#142/#143, #147/#148, #149/#150** (2026-08-19/20): MERGED. +- **#178** (2026-08-26): MERGED — the last dream-cycle merge of any kind, 28 days ago. +- **#154/#155**: PR closed unmerged, change landed on `main` directly via `420854b`. +- Every `dream/*` PR opened 2026-09-01 through tonight — 25 PRs (#269 through #317) — remains open + and draft. Confirmed via GitHub MCP `search_pull_requests` against `head:dream/*`, not assumed. + +### This surface specifically (grounding-quality), last 4 prior nights + +| Date | PR | Finding | Status on `main` today | +|---|---|---|---| +| 2026-09-03 | #237 (closed unmerged) | Citation-header rank hijack (relative +1 offset); filed issue #236, ADR-0076/0087 Proposed | **Still live** — `kb/verify-citation.mjs:38-39`'s own comment still says "not airtight against a document engineered to predict and spoof the exact next rank"; ADR-0087 not on `main`; issue #236 still open | +| 2026-09-08 | #270 | `gradeQuestion()`'s `routed` metric blind to right-repo-wrong-file citations; adds `expectPath` | Integrated — `scripts/eval-brain.mjs:85-87` uses `routedRepo` for `routed` today | +| 2026-09-13 | #287 | Recovers ADR-0076 as ADR-0087 (byte-for-byte, after a renumbering collision) | **Not integrated** — `docs/adr/0087-*.md` absent from `main`; #287 still open | +| 2026-09-18 | #297 | Recovers PR #239: `provenance`/`pass` case still read `top?.repo` instead of `routedRepo` | **Not integrated** — verified live tonight, see below | + +## Verification performed tonight (not re-derived from memory) + +``` +$ grep -n "routedRepo\|top?.repo !== 'ruv-gists'" scripts/eval-brain.mjs +85: const routedRepo = receipt?.repo ?? top?.repo ?? null; +86: const routed = !!(grounded && q.expectRepo?.length && routedRepo +87: && repoMatchesExpected(routedRepo, q.expectRepo, repoAliases)); +95: return { grounded, routed: null, abstained, pass: !!grounded && !abstained && (top?.repo !== 'ruv-gists' || bannerPresent) }; +``` + +Line 95's `provenance` stratum `pass` computation still reads the raw top-ranked citation +(`top?.repo`) instead of the same `routedRepo` the function already computes at line 85 — exactly +the defect PR #297 (2026-09-18) already fixes, TEETH-verified, adversarially critiqued CLEAR, and +confirmed rebased onto current `main` (`git merge-base --is-ancestor origin/main origin/dream/2026-09-18-grounding-quality-provenance-receipt` +→ true, zero commits behind). **This is not a new finding** — it is issue #239's original gap, +never a tracking issue under this repo's ISSUE DISPOSITION OVERRIDE (a verified fix is a work +record), sitting unmerged for 5 days with a ready, current, non-conflicting fix. + +`docs/adr/0076-memory-full-integration.md` and `docs/adr/0086-corpus-seed-pipeline-consolidation.md` +exist on `main` under those numbers (unrelated content, confirmed by reading both); ADR-0087's slot +is free on `main`, consistent with #287's own account of the two renumbering collisions. + +Targeted regression check (both grounding-quality-surface test files, current `main`, +zero diff applied): `npx vitest run tests/unit/eval-brain-gate.test.mjs +tests/unit/verify-citation.test.mjs` → **45/45 pass**. `npm run claims:verify`: 3 PASS / 4 SKIP +(brain-dependent claims skip loudly — standard composition, unchanged from every prior night). +`npm run eval:gate`: `EVALUATED=blocked` — `no brain at /root/.cache/ruvnet-brain/kb` (container +never materializes a corpus; not a credentials block, `OPENROUTER_API_KEY` is present). + +No new grounding-quality defect was found tonight distinct from the three already tracked above. + +## Hypothesis + +None reached the freeze-then-evaluate stage — this is a reconciliation night (same precedent as +PR #269, 2026-09-08). Per STEP 5-9: `EVALUATED=no / VERDICT=INCONCLUSIVE / reason=no new testable +hypothesis; the surface's known findings are already tracked in open, currently-mergeable PRs +(#270 integrated, #287 and #297 still open) awaiting human review, and re-deriving them again +tonight would be pure duplicate work`. + +## Darwin Lineage + +Not run — no candidate diff, no continuous parameter to evolve. + +## Evidence + +OBSERVATION (re-read `scripts/eval-brain.mjs`, `kb/verify-citation.mjs`, ADR namespace on current +`main`) → MEASUREMENT (grep + targeted test run, both reproduced live tonight, not assumed from +prior nights' reports) → INFERENCE (#297's fix still applies cleanly; #287's ADR slot is still +free) → DECISION (no new work; reconcile and record). + +## Reward-Hack Check + +N/A — no benchmark, threshold, or gold answer touched; no candidate code shipped tonight. + +## Security Review + +No new attack surface. Reconfirms, rather than newly discloses, the citation-rank-hijack gap +tracked in issue #236 / ADR-0087: `kb/verify-citation.mjs`'s own docstring still names it unresolved +line-for-line as it did on 2026-09-13. Nothing in tonight's read-only verification touched the +evaluator, the held-out set, or any gold answer. + +## Recommendation (read this first — unchanged from the last several nights, now more urgent) + +This engine never merges and this session has no authority to change that. Recorded, not acted on: + +1. **25 open `dream/*` PRs (#269–#317), 100% draft, zero merged since #178 (2026-08-26) — 28 days.** + Ordinary `fix/`/`release/` PRs from the same window (#302, #306, #307, #309, #310, #315) merged + normally, so this is specific to the dream-cycle track, not general review capacity. +2. **Issue #236** (2026-09-03, citation-header rank hijack) needs a human Option A/B decision on + ADR-0087 — itself sitting unmerged in PR #287 for 10 days, so the decision document a reviewer + would need to read isn't even visible on `main`. +3. **PR #297** is a ready, TEETH-verified, zero-conflict fix for a real scoring-attribution bug + still live on `main` tonight (confirmed above) — the single lowest-effort, highest-confidence + merge available on this surface right now. + +## ADR + +None created — no architectural decision reached tonight. + +## Gist + +LOCAL — no `gh` CLI or gist-creation MCP tool available this session (same limitation every prior +Dream Cycle night on this repo has recorded). + +## Issue + +`NONE` — per this repo's ISSUE DISPOSITION OVERRIDE: nothing new, reproduced, and unresolved +surfaced tonight; every finding above already has an open issue (#236) or an open, verified, +non-duplicate fix PR (#287, #297). A run without a new issue is a valid completed run. + +## Witness + +``` +SESSION_COMMIT = e89ea1ba167d9252ec99910304f534c8da5ca0ab +REPORT_HASH = f909c798b8f6099d4fd6a8bd7650fcf43b1cef6bd3337a736b216fa5521ae7fc +WITNESS = 7c152e1df8480839c4b5d2e7627a7912fe9cc8f1dd196747d761dd9cd41dd263 +``` + +Verifier procedure: (1) check out commit `e89ea1b`; (2) `sha256sum` this report file at the state +before this section was filled in and confirm it matches `REPORT_HASH` (the hash covers the +pre-stamp bytes, per this pipeline's STEP 16 ordering); (3) `printf '%s%s' "$REPORT_HASH" +"$SESSION_COMMIT" | sha256sum` and confirm it matches `WITNESS`; (4) re-run +`grep -n "routedRepo\|top?.repo !== 'ruv-gists'" scripts/eval-brain.mjs` against that commit and +confirm line 95 still reads `top?.repo`; (5) re-run `npx vitest run tests/unit/eval-brain-gate.test.mjs +tests/unit/verify-citation.test.mjs` and confirm 45/45 pass. + +## Merge Policy + +**Human review required.** `autoMerge: false` per `dream.config.json` (ADR-068) — the decision, not +a default. This session never self-merges and never autonomously promotes candidate state. Draft, +by design. diff --git a/docs/dream-cycle/LEDGER.md b/docs/dream-cycle/LEDGER.md index 8b215a12..f596ba9d 100644 --- a/docs/dream-cycle/LEDGER.md +++ b/docs/dream-cycle/LEDGER.md @@ -39,3 +39,4 @@ running behavior changed. See [deployment verification](OPERATING-POLICY.md). | 2026-08-28 | grounding-quality | `kb/verify-citation.mjs`'s `parseCitations()` trusted any text shaped like the reader's own citation-block format (`#N repo=... / path : ... / title: ...`) wherever it appeared in `forge-ask-all.mjs`'s stdout — including inside a retrieved document's own raw, unescaped "full document" dump. A retrieved document that itself quotes or discusses this exact format (this very file's pre-fix header comment was one concrete instance) gets parsed as an EXTRA, fabricated citation; if that citation's path happens to resolve, `verifyGrounding()` reports `grounded: true` off a citation the retriever never returned. Fixed by bounding each citation's `path`/`title` extraction to its own span (stop at the next real header) and requiring strictly sequential ranks (`#1, #2, …`, the reader's own real invariant, since `forge-ask-all.mjs` always numbers hits `#${i+1}` with no gaps) | #185 | #186 | yes | ACCEPT | New TEETH tests fail on pre-candidate code exactly as predicted (fabricated-citation injection, cross-block path bleed, out-of-sequence rank, end-to-end false-`grounded:true`), 20/20 pass post-fix. `test:unit` byte-identical failure set baseline vs candidate (3 files/4 tests of 3596, all pre-existing `chmod`/EACCES-under-root fixtures, confirmed unrelated by re-running against baseline directly). `test:integration` 5/38 files fail, all pre-existing `sqlite3`/`@xenova/transformers` infra blockers, none referencing the changed file (grep-confirmed); both-hosts conformance gate green, 5/5. `eval:gate` itself EVALUATED=blocked: `no brain at /root/.cache/ruvnet-brain/kb` (this container never materializes a corpus — confirmed independently via `restore-local-ingests.mjs`/`brain-score.mjs`/`store-root.mjs`, all `stores 0 dark 0`); LLM_EVAL=blocked too (no model-provider key). Self-critique CLEAR: fix only ever makes grounding checks stricter, never more lenient; disclosed one residual risk (a maximally adversarial document predicting the exact next expected rank would still be accepted — needs a structural wire-format fix, out of scope tonight) | 552aad71b3858c769ebceed2e665ad2ef85f4fb6c1d5bc014e47692c508c981f | #142/#143 (08-19), #147/#148, #149/#150 (08-20): all MERGED. #154/#155 (08-21): PR closed unmerged, change landed on `main` via `420854b`. #175/#176, #177/#178 (08-26, both this repeated brain-currency surface): still open/draft as of tonight. Separately: of the 14 most-recent `dream/*` PRs checked tonight via GitHub MCP, **zero have merged since 2026-08-20/21** (#157, #159, #160, #162, #164, #167, #168, #169, #172, #174, #175, #176, #182, #184 all open) — the review backlog #175/#176 first flagged on 2026-08-26 is still growing; tonight's candidate was deliberately kept tiny (2 files, ~100 lines) in response | | 2026-08-28 | grounding-quality | CONCURRENT NIGHT — a separate firing of this same routine (same SLOT=3/DEEP) landed first as #185/#186 (`kb/verify-citation.mjs`'s `parseCitations()` citation-block spoofing fix); this row is this session's independent, non-overlapping finding: `scripts/eval-brain.mjs`'s `gradeQuestion()`, the scoring function behind the frozen 120-question `npm run eval:gate` held-out set, computed the `routed` credit ("does a by-description query reach the store that actually holds the answer," `brain-score.mjs`'s own wording) from the raw top-ranked `citations[0]`, discarding `verifyGrounding()`'s own `receipt.repo` — the citation it actually verified as resolving on disk, which `citationResolves()` can accept at a lower rank than #1 when the top citation is unverified. This let a genuinely correctly-routed answer score as a routing failure (top fabricated, real hit lower-ranked) or a wrongly-credited pass (top coincidentally names the expected repo but never resolved, a different repo actually grounded it). Fix threads `receipt` through the one call site; `routedRepo = receipt?.repo ?? top?.repo ?? null` preserves identical behavior for the two other, receipt-less callers. Pushed to a suffixed branch, `dream/2026-08-28-grounding-quality-routed-receipt`, rebased onto #186's tip, to avoid colliding with the concurrent firing's branch and its identically-named report file | #187 | (opening now) | yes | ACCEPT | New TEETH test fails on pre-candidate code (`expected false to be true`), 16/16 pass post-fix — independently reproduced by the orchestrating session via `git stash`/`pop`, not merely the candidate's own claim. `test:unit` byte-identical failure set baseline vs candidate (4 files/4 tests of 3592→3593, all pre-existing chmod/EACCES-under-root fixtures: `advocacy-ignored`, `advocacy-outcomes`, `hook-shim-fallback-once`, `user-settings`); `test:integration` 5 failed files/9 failed tests/240 passed/11 skipped/53 todo of 313, matching the 2026-08-26 ledger row's own documented baseline exactly; `claims:verify` 3 PASS/4 SKIP, independently re-run by the orchestrating session. Blast radius independently re-grepped: `gradeQuestion` has exactly 3 call sites repo-wide; the 2 other callers never construct `receipt`, so both fall back to identical prior behavior. `eval:gate` EVALUATED=blocked (`no brain at /root/.cache/ruvnet-brain/kb`, same pre-existing condition). Self-critique CLEAR: fix corrects the metric in both directions (raises an undercounted true positive, lowers an overcounted false positive), so it cannot be a one-directional score inflator | f9910b34d073f887d0354af981ae04d697f5f4b9710e7440cd21b633424dd1c8 | #142/#143 (08-19), #147/#148, #149/#150 (08-20): all MERGED. #154/#155 (08-21): landed on `main` via `420854b`. #178 (08-26): MERGED (confirmed via GitHub MCP `list_pull_requests`, `merged_at` set, commit `7a19fd2` in `git log main`). #180 (`fix/integration-timeout`, non-dream but related): also MERGED (`git log main` commit `2af5bfd`). All other dream-cycle PRs opened 2026-08-22 through 2026-08-27 (#157, #159, #162, #164, #167, #168, #172, #174, #176, #182, #184 — 11 total) remain open/draft as of tonight — only 1 of 12 dream-cycle PRs in that window has merged; the backlog first flagged 2026-08-26 is now larger, not smaller | | 2026-08-31 | brain-currency | CONCURRENT NIGHT — a separate firing of this same routine (same SLOT=1/DEEP) landed first as #212/#213 (`kb/forge-currency.mjs`'s `brainKnownSet()` sourcing the wrong root directory); this row is this session's independent, non-overlapping finding: `scripts/source-coverage.mjs`'s `artifactEvidence()` computed `cardPresent` via a direct name match against capability-card headings (`cardStores.has(store)`), missing stores reachable only through a `kb/repo-aliases.json` alias (the standing example: `metaharness`, card-listed only under `## agent-harness-generator`). The exact same conflation was already fixed twice in this codebase (ADR-058) — `kb/store-root.mjs`'s `darkStores()` and `scripts/brain-score.mjs`'s `readCoverage()` — but never migrated to this third, sibling computation, which feeds the committed `data/source-coverage.json`/`docs/RUVNET-COVERAGE.md` (ADR-069). Fixed by importing the router's own alias resolver (`repositoryNames` from `kb/card-lane.mjs`) instead of a raw Set lookup, mirroring the two prior fixes | #214 | #215 | yes | ACCEPT | New TEETH test fails on pre-candidate code (`expected false to be true`, reproduced via `git stash` with the function temporarily exported unchanged), 20/20 pass post-candidate, covering the alias case, the canonical-name case, and a false-positive guard (unrelated store, no alias/card, stays `false`). `test:unit` 3718/3909 pass, 4 failures = the exact chmod/EACCES-under-root container artifact already documented pre-existing in the 2026-08-26/2026-08-28 rows. `test:integration` baseline vs candidate byte-identical, 5 failed files/9 failed tests (pre-existing `sqlite3`/`@xenova/transformers` infra); one extra failure in a single candidate run reproduced under 3-way concurrent resource contention, confirmed passing 3/3 in isolation on baseline (load-flake, unrelated advocacy-dial subsystem). `qa:pr` convergence lane fixed via regenerated `data/convergence-manifest.json` (committed in this PR); docs lane's 52 violations reproduced identically on baseline (pre-existing). `eval:gate` EVALUATED=blocked (`no brain at /root/.cache/ruvnet-brain/kb`, container never materializes a corpus — not a credentials block, `OPENROUTER_API_KEY` present). `claims:verify` 3 PASS/4 SKIP as usual. Independent critic (separate agent, not the candidate's author) verdict CLEAR after checking benchmark/threshold non-involvement, cherry-picking, perf, blast radius (gist call site unaffected), security, and double-normalization correctness | b85b4caa263f6f2d568026acc09c6dcf6073b95e0824e16802705ac97001e90e | #142/#143, #147/#148, #149/#150 (all 2026-08-19/20): MERGED. #178 (2026-08-26): MERGED. #154/#155 (2026-08-21): closed unmerged, change landed on `main` directly via `420854b`. #157, #159, #162, #164, #167, #168, #172, #174, #176, #182, #184, #186, #192, #194 (2026-08-22 through 2026-08-30): all still open/draft as of tonight — zero merged since #178 (2026-08-26), a growing review backlog worth the owner's attention (also flagged in prior rows since 2026-08-26). #212/#213 (2026-08-31, concurrent): open draft as of this row, on branch `dream/2026-08-31-brain-currency`; this session's branch was renamed to `dream/2026-08-31-brain-currency-source-coverage-alias` to avoid the collision. GIST: LOCAL — no `gh` CLI or gist-creation tool available this session; not fabricated | +| 2026-09-23 | grounding-quality | RECONCILIATION, no new finding. Re-verified live on current `main` (`e89ea1b`) rather than assumed: (1) issue #236's citation-header rank-hijack is still live — `kb/verify-citation.mjs:38-39`'s own comment still names it unresolved; its decision doc, ADR-0087 (PR #287), is still unmerged so the ADR isn't even on `main` for a reviewer to read; (2) PR #297's fix (2026-09-18) for `gradeQuestion()`'s `provenance` case reading `top?.repo` instead of the already-computed `routedRepo` is still unmerged, still applies cleanly to current `main` (confirmed via `git merge-base --is-ancestor`), and the defect it fixes is still live at `scripts/eval-brain.mjs:95` today; (3) PR #270's `routed`/`expectPath` fix (2026-09-08) IS integrated — `routedRepo` is used at lines 85-87. Deliberately did not re-implement #297's already-verified fix a second time — that would be pure duplicate work, the pattern driving this exact backlog. Full detail: `docs/dream-cycle/2026-09-23-grounding-quality-report.md` | NONE | (opening now) | no | INCONCLUSIVE | No hypothesis reached the freeze-then-evaluate stage (STEP 5-9: not testable as a new candidate tonight — reason: no new defect, existing fixes already open and current). Targeted regression check only: `npx vitest run tests/unit/eval-brain-gate.test.mjs tests/unit/verify-citation.test.mjs` 45/45 pass on unmodified `main`. `npm run claims:verify` 3 PASS/4 SKIP (standard composition). `npm run eval:gate` EVALUATED=blocked (`no brain at /root/.cache/ruvnet-brain/kb`, container never materializes a corpus; not a credentials block, `OPENROUTER_API_KEY` present) | 7c152e1df8480839c4b5d2e7627a7912fe9cc8f1dd196747d761dd9cd41dd263 | #142/#143, #147/#148, #149/#150 (08-19/20), #178 (08-26): MERGED — confirmed via GitHub MCP. #154/#155: closed unmerged, landed on `main` via `420854b`. Every `dream/*` PR opened 2026-09-01 through tonight — 25 PRs, #269 through #317 — is open/draft: **zero merged since #178, now 28 days**. Ordinary `fix/`/`release/` PRs in the same window (#302, #306, #307, #309, #310, #315) merged normally — the gap is specific to the dream-cycle track. Issue #236 (2026-09-03, security-relevant rank-hijack) has waited 20 days for a human ADR-0087 Option A/B decision. PR #297 (5 days old) is a ready, zero-conflict, TEETH-verified fix for a real bug still live on `main` tonight — flagged as the lowest-effort merge available on this surface |