Skip to content

ledger-signals: derive zeroMergeStreak from Prior-night fates tokens - #15

Draft
ruvnet wants to merge 2 commits into
mainfrom
dream/2026-08-16-ledger-signals
Draft

ledger-signals: derive zeroMergeStreak from Prior-night fates tokens#15
ruvnet wants to merge 2 commits into
mainfrom
dream/2026-08-16-ledger-signals

Conversation

@ruvnet

@ruvnet ruvnet commented Aug 16, 2026

Copy link
Copy Markdown
Owner

Nightly Dream Cycle, 2026-08-16. DEEP=ledger-signals, SCAN=witness,verify. Full report: docs/dream-cycle/2026-08-16-ledger-signals-report.md. Issue: #14.

Hypothesis

Given the ledger's Prior-night fates column carries per-PR fate text recorded by each night's STEP-1 fate check, when learningSignals() additionally parses that column for an explicit #<PR>:MERGED token (never inventing a fate from free prose), then zeroMergeStreak should correctly clear once a row records a PR as MERGED — whereas today it is asserted true for any window containing a PR regardless of real merge status. Frozen before implementation.

Candidate

+150/-4 across 3 files (1 new report, 2 edits: packages/ledger/src/index.ts + its test file). One conceptual change: an additive parsePriorFates() token parser wired into learningSignals()'s existing mergedPrNumbers union — no removal, no behavior change when fate tokens are absent.

Evaluation Receipt

Real evaluator: npm test (vitest, this repo's own bench entrypoint).

Baseline (parent, commit 8ce3857) Candidate
Tests 96 100 (+4, 0 removed, 0 modified)
Result 96 passed 100 passed

Live receipt against the real repo ledger tonight vs. a synthetic follow-up ledger:

-- real repo ledger (no fate tokens yet) --
{ "zeroMergeStreak": true, "nightsConsidered": 1 }
-- synthetic ledger where a later night recorded #7:MERGED --
{ "zeroMergeStreak": false, "nightsConsidered": 2 }

Baseline

Parent commit 8ce385786faa5e63cc0e7105cc6e96f663a51f07, 96/96 tests passing, clean build (npm ci && npm run build, no wasm/NAPI packages in this workspace).

Darwin Lineage

Not run — DARWIN=not-applicable. Single, minimal, pure-parsing conceptual change; no evolvable population.

Evidence

Confirmed live via GitHub MCP tonight: PR #7 (last night's candidate) is merged: true, merged_at: 2026-08-13T22:05:44Z, issue #6 closed/completed. The pre-fix ledger signals CLI output nonetheless claimed zeroMergeStreak: true on the real ledger — a real, demonstrated contradiction, not a hypothetical one. Root cause: packages/cli/src/index.ts's ledger signals sub-command has always called learningSignals(rows) with no mergedPrNumbers option, and the pre-fix logic (!merged || ...) forces the streak true whenever merged is undefined — which it always was on the CLI path. Existing unit tests never caught this because every pre-fix test exercising zeroMergeStreak explicitly supplied mergedPrNumbers — the CLI's actual (unsupplied) path was untested.

Reward-Hack Check

Self-critique (no second agent available in this environment tonight): CLEAR. Only the ledger package's source + test file changed, all additive. The new #N:FATE token format is a hard, explicit syntax (#(\d+)\s*:\s*(MERGED|CLOSED|OPEN|STALE)) — verified by a dedicated test that free prose like "PR 105 was merged into main yesterday" is correctly ignored, so the fix cannot manufacture a false positive from loose language. Today's real 1-row ledger (no fate tokens present) is verified unchanged: still reports zeroMergeStreak: true, its existing conservative default — the fix adds recall, it never removes a real signal.

Security Review

Pure string/regex parsing over docs/dream-cycle/LEDGER.md, a file this repo already owns and writes to itself. No new I/O, no new credentials, no LLM calls, no change to evaluatorEntrypoints or io.exec.

Regression Analysis

0 pre-existing tests modified or removed. All 96 baseline tests still pass unchanged; 4 new tests added covering: token-present clears streak, non-MERGED tokens don't clear it, free-prose is ignored, and latest-token-wins when a PR is mentioned more than once.

ADR

None — this is a signal-computation bug fix using an existing, already-designed-for-but-unused ledger column, not a new architectural decision. (Extends, doesn't supersede, ADR-0001.)

Gist

No gh gist create tool / gh CLI available in this environment (same as the #6/#7 night). Report committed at docs/dream-cycle/2026-08-16-ledger-signals-report.md instead. GIST=LOCAL.

Issue

#14

Witness

report_sha256 : 5613cb408316404d4becd712a51c479a4cd4d286f778172442355e34dc55b91c
session_commit: 8ce385786faa5e63cc0e7105cc6e96f663a51f07
witness       : 4fac9b71af3f447ee35949058a1cab3d0c20bc5d2def8847ceff15418bfaeb8c

Verify: sha256sum docs/dream-cycle/2026-08-16-ledger-signals-report.md, then printf '%s%s' "<hash>" "8ce385786faa5e63cc0e7105cc6e96f663a51f07" | sha256sum must equal the witness above. Confirmed tonight via dream-machine witness verify (✓ VALID).

Merge Policy

Draft — human review required. This PR does not carry the automerge-safe label: while the diff is small and additive, it changes the semantics of a decision-support signal (zeroMergeStreak) that future nights read to decide candidate scope, which per this repo's own guarded-auto-merge policy warrants a human look before it starts influencing subsequent nights' behavior. The session never applies that label itself and never merges.


Generated by Claude Code

claude added 2 commits August 16, 2026 09:14
The CLI's `ledger signals` command has always called learningSignals(rows)
with no mergedPrNumbers option, so zeroMergeStreak was unconditionally true
whenever any PR existed in the window, regardless of real merge status —
demonstrated live tonight: PR #7 merged three days ago but the signal still
reported a zero-merge streak. Prior-night fates already exists to record
per-PR MERGED/CLOSED/OPEN/STALE fates from each night's STEP-1 check; wire
it in via a small #N:FATE token parser (parsePriorFates), additive to the
existing option so nothing regresses when fate data is absent.

Dream Cycle 2026-08-16, DEEP=ledger-signals, SCAN=witness,verify.
Records tonight's zeroMergeStreak fix (#15) plus the live STEP-1 fate
check on the prior night's issue/PR (#7:MERGED, #6:CLOSED), giving the
new Prior-night-fates parser real data to consume starting immediately.

ruvnet commented Aug 16, 2026

Copy link
Copy Markdown
Owner Author

Independent critic pass

Spawned a separate agent (not the candidate's author) to adversarially review this diff. Verdict: CLEAR of reward-hacking, with two disclosed limitations worth tracking as follow-ups rather than blockers:

  1. No existing test weakened/deleted; 4 new tests added, all real assertions; npx vitest run independently re-run by the critic — 20/20 (ledger), 100/100 (full suite), confirmed live rather than taken on faith.
  2. Root-cause claim verified: git diff for packages/cli/src/index.ts between the parent commit and this branch is empty — the CLI's ledger signals call site is genuinely untouched, confirming it never populated mergedPrNumbers.
  3. Regex exploit attempted, confirmed narrow: free prose ("PR 105 was merged...") does not match; #105:MERGEDGE-style suffix collisions correctly fail via \b. But the token parser has no negation/context awareness — a string literally containing #105:MERGED inside a sentence denying the merge (e.g. "someone wrote #105:MERGED but it's still open") would still parse as MERGED. This is inherent to a token-only design and is disclosed in the function's doc comment; not fixed tonight since the ledger is self-authored by this same trusted pipeline (not third-party input) and the risk is low, but flagged for anyone extending this to untrusted input.
  4. Minor scope nit: parsePriorFates(rows) scans all rows rather than just the signal's window-limited slice. Harmless today (only PR numbers already in prsInWindow are checked against it), but under PR-number reuse it could theoretically let a stale fate token leak into a later window. Not a realistic risk on GitHub (PR numbers are monotonic, never reused) — noted for completeness, not fixed tonight.

Neither limitation changes the verdict: the fix is additive, conservative-by-default, and demonstrated live against real GitHub state (PR #7's actual merge) in the issue/PR description above.


Generated by Claude Code

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