refactor: keep learning-ledger IDs on the machine - #412
Merged
dean0x merged 55 commits intoOct 3, 2026
Merged
Conversation
The learning ledger under .devflow/learning/ is gitignored and numbered per machine, so an ADR/PF number resolves on no other clone, and numbers have been reused: some citations already name an unrelated entry. Agents may now name an ID only in what stays in the session (reasoning, decision tables, prompts to downstream agents, the report to the caller); anything committed, pushed or posted states the rule in words. - apply-decisions: Step 4 confines citations to in-session handoffs and drops inline comments; the index and worked example use placeholders. - knowledge, feature-knowledge: a knowledge base states decisions in words and its Related section links only to other knowledge bases and files, since KNOWLEDGE.md is tracked and shared. - review, diagnose, design, research, triage, resolve, dynamic-plan, dynamic-tickets: findings, triage reasoning, resolution summaries, plans and ticket bodies state decisions in words. - git.mds and the PR-host BY_DESIGN verdict: posted evidence no longer lists ADR IDs. - code: drop the usage-tracking citation line. - Every literal ID left in the prompt corpus is restated in words or removed where its reason was already given; the dynamic commands name the LLM-vs-plumbing Iron Rule their own preamble states. The PR-host reply rule in _pr.mds still lists ADR IDs among internal evidence: that line is sampled into the frozen github-status-lines fixture and changes only under its own authorisation. Refs #411
Regenerated with `npm run test:golden:update -- git-agent` after the Git agent's two internal-evidence lists stopped naming ADR IDs (18 characters shorter, same line count). Equality baselines moved with it: GIT_MD_CHARS 43,832 -> 43,814, TOTAL_CHARS 53,403 -> 53,385 and GIT_AGENT_BYTES 44,149 -> 44,131. GIT_MD_LINES and TOTAL_LINES are unchanged, and the frozen github-status-lines fixture is untouched. Refs #411
Learning-ledger IDs point into a per-machine, gitignored ledger that no other reader can resolve. Remove them from the resolve-pipeline and tracker-references knowledge bases, stating the rule in words where the ID carried the reason, and drop them from both keyword lists in the KB frontmatter and the matching index.md lines so the cache stays byte-consistent with the frontmatter. Refs #411
Remove learning-ledger citations from the dynamic-workflow-engine knowledge base. Where a citation carried the reason, the rule is now stated in words; the Iron Rule sites name the preamble's rule itself, and the review-cycle pointer names the single review pass and evidence-gated disposition this KB already describes. Refs #411
Remove learning-ledger citations from the feature-knowledge-system knowledge base. Citations that followed a stated reason are deleted; where the ID carried the reason (the MDS compile-cost cliff, the delete-then-write ENOENT window, per-item failure isolation, the config-only gate) the reason is now stated in words, and the Related bullets keep their titles without the IDs. Refs #411
Learning-ledger IDs point into a per-machine, gitignored ledger that no other reader can resolve, and some point at the wrong entry. Comments in src/core and src/targets now carry the reason itself: citations that followed a stated reason are dropped, the few that were the only reason become a short reason in words, D-series decision names stay verbatim, and anchor-ID format examples use the ADR-NNN placeholder. Comment-only.
Learning-ledger IDs resolve only on the machine that wrote them, so a citation in a guard, helper, seam or setup file points a reader at nothing. Each one is either dropped where its sentence already states the reason, or replaced by the reason in plain words. Only comments, describe/it titles and numeric-floor descriptions change; fixture data, expected values and floor patterns are untouched. The two retired-wording rows that banned two specific ledger IDs are removed: the no-ledger-citations guard covers every ID. Refs #411
Comments and test titles in the tracker, PR-host, docs and goldens suites cited entries of the per-machine learning ledger, which nobody else can resolve. Each citation is now dropped where the sentence already gives the reason, or replaced by the reason in words where it was the only explanation. Test data and assertion messages are unchanged. Refs #411
Remove learning-ledger citations from the learning-capture-system knowledge base without otherwise refreshing it. Citations that followed a stated reason are deleted; where the ID carried the meaning (the log-to-ledger content-update path, delimiter-regex truncation, the validating sink, the pipe-free exit status) it is stated in words, and the Related bullets keep their descriptions without the IDs. Refs #411
Comments and test titles in the decisions suites cited entries of the per-machine learning ledger, which nobody else can resolve, and several now resolve to unrelated entries because numbers were reused. Each citation is dropped where its sentence already gives the reason, or replaced by the reason in words where it was the only explanation. Titles that named the ledger entry a specimen imitated now describe the specimen instead. Fixture rows, expected outputs and the frozen corpus strings are unchanged, and IDs that describe a fixture's own data stay. Refs #411
Comments and test titles in the hook, memory, learning-agent and learning-config suites cited entries of the per-machine learning ledger, which nobody else can resolve. Each citation is dropped where its sentence already gives the reason, or replaced by the reason in words where it was the only explanation; D-series and plan-item labels are kept. Test data, asserted strings and the shell text of the fake claude shims are unchanged. Refs #411
Remove learning-ledger citations from the tracker-feature knowledge base. Citations that followed a stated reason are deleted, the D-CONFIG-PRESERVE-UNMANAGED name is kept without its bracketed ID, and where the ID carried the rule (no shell reads of the conventions file, an additive PATH shim, no stop rule for a corruption-only failure, a self-contained unattended agent) it is stated in words. The Related bullets keep their rules without the IDs. Refs #411
Comments and describe/it titles in the core, cache, manifest, model discovery, orphan-sweep, MDS-variant, plugin, agent-model, proxy and compliance-compose suites cited the per-machine learning ledger by ID. They now keep only the reason in words; test data, fixtures and assertion strings are unchanged.
Comments in the CLI commands, the agents and flags TUIs, the shared TUI shell and the HUD cited entries of the per-machine learning ledger, which nobody else can resolve and some of which now name an unrelated entry. Each citation is dropped where its sentence already gives the reason, or replaced by the reason in words where it was the only explanation; D-series names and review-finding labels are kept. Comment-only change: no code, string literal or behavior differs. Refs #411
Comments in the MDS build script and both vitest configs cited entries of the per-machine learning ledger. The build-script citations followed a reason already given and are dropped; D-TEST-HOME-ISOLATION keeps its name and now says why the temp HOME exists. Comment-only change. Refs #411
Comments and describe/it titles in the flags CLI, flags view, flags core, TUI shell and cell, proxy and agents-command suites cited entries of the per-machine learning ledger. Each citation is dropped where its sentence already gives the reason, or replaced by the reason in words where it was the only explanation. Test data, fixtures and asserted strings are unchanged. Refs #411
The learning ledger lives per machine and is gitignored, so an ID cited in a shipped script resolves for nobody else, and some resolved to the wrong entry after numbers were reused. Each citation is now dropped where the comment already gave its reason, stated in words where it was the only reason, or replaced by a placeholder where it was a format example. Comment-only: no behaviour changes. Refs #411
The evidence-policy seam cited machine-local ledger IDs in its JSDoc. The D-POLICY-* names stay; the citations go, and the one that carried the only reason (why a loader failure gets no handling beyond its line: only a damaged package fails the load) is now stated in words. Comment-only. Refs #411
Comments and describe/it titles in the evidence, evidence-policy and redact-secrets suites no longer cite machine-local ledger IDs; a reason is kept in words where the citation was the only one. Assertion data and assertion messages are unchanged. Three design-decision marker lists still expect the removed citation in the swept sources (cli-seam, resolver and settings-mode AC-12 checks) and fail until that entry is dropped from each list. Refs #411
The Git-agent, Tracker-agent, provider-literal and tracker hook suites cited entries of the per-machine learning ledger in comments and test titles. Each citation is dropped where the surrounding sentence already gives the reason, or replaced by that reason in words where it was the only explanation; the conventions-commit pins now say what they protect instead of pointing at an entry that resolves to an unrelated pitfall. Test data and assertion messages are unchanged. Refs #411
Comments and describe/it titles in the root install, init, uninstall, build-mds, compliance and packaging suites, and in tests/installer, tests/commands, tests/dynamic, tests/integration and tests/resolve, cited learning-ledger entries that resolve only on one machine. Each citation is dropped where the surrounding text already gives the reason, or replaced by that reason in words where it was the only one. D-series names stay. Assertion messages, fixtures and other string literals are unchanged, as are the numeric-floor patterns. Refs #411
The resolve-review-threads rule listed learning-ledger IDs among the internal evidence a reply body may cite. Replies are posted to the pull request, and ledger IDs resolve only on the machine that wrote them, so the rule now names commit SHAs and file:line from this codebase only. The frozen status-line fixture samples this line; it is re-captured in its own fixture-only commit. Refs #411
The frozen status-line fixture samples the resolve-review-threads reply rule at line 207, which no longer lists ledger IDs as evidence a posted reply may cite. Re-captured under the user's eighth authorisation (2026-10-03, line 207 only): that one line changes, 18,392 to 18,383 bytes, and the newline count stays 249. FIXTURE_BYTES follows the fixture. The authorisation log records the eighth grant as spent, and the update script's refusal text now counts eight; the --unfreeze refusal itself is unchanged. Refs #411
The compliance KB repeated the old resolve-review-threads allowance that a reply body may cite ledger IDs. Replies are posted, so the KB now lists commit SHAs and file:line from the codebase, as the rule does. Refs #411
Three AC-12 checks expected a learning-ledger ID in the evidence seam, the shared project-config parser and the settings resolver. Those sources now state the reason in words, so each list keeps its D-name markers, which still pin the decision at its code site, and drops the ledger entries. Refs #411
The refresh-anchor divergence refusal ended with a learning-ledger citation, which reaches the user's terminal on every clone where the ID names some other entry or none. The message already says why the re-projection is refused. The ledger-ops test pins only the message's "Reconcile the log row first" substring, which is unchanged. Refs #411
The comment above the orphan guard pointed at a decision in the per-machine learning ledger and described an exemption for format-spec skills. That exemption was removed when it had no members left, and the guard now requires every skill and agent under src/assets/ to be declared by a plugin, the compliance skill excepted. The comment says that, and why: installs select assets by plugin. Refs #411
The formatComplianceSummary re-export cited tests/init-logic.test.ts by a line number that now lands in an unrelated deny-list case. It now names the suite that imports the function through init.js, with no line number to drift. Comment-only. Refs #411
The convergence JSDoc said the temp-sibling write avoids ENOENT windows, and the swap's comment called it atomic. The code removes the old skill directory and then renames the sibling into place, so a reader can still see no directory between those two calls. Both comments now say the window is narrowed to that gap. Comment-only. Refs #411
The resolve-pipeline KB still said agent instructions must avoid a bare rm. The Recommended deny-list actually blocks rm's flag spellings (rm -f, rm -rf, and compounds containing them), while a flagless `rm <path>` and `unlink <path>` both pass. The bullet now says that, keeps cleanup failure-tolerant, and asks for one narrower retry after a denial before a leftover is reported. Refs #411
Two Related bullets in the test-harness KB discussed only how ledger citations should be read: one called a citation a claim rather than a tag, the other disclaimed a miscited ownership contract. Committed text no longer cites the ledger, and the rules the second bullet pointed to (the non-vacuity requirement and the absence-based-guard rule) remain listed as bullets of their own. Refs #411
Assertion messages in the evidence-policy, core, mds-variants and redact-secrets suites, and the comments inside the fake claude shims of the capture-hooks and eager-memory-refresh suites, cited learning-ledger entries that resolve on no other clone. Each message already stated its reason, so only the citation is removed. Ledger IDs that are test data (fixture rows, scanner inputs, expected output) are unchanged. Refs #411
Assertion messages and thrown errors in the tracker, Git-agent and PR-host suites cited learning-ledger entries, which resolve on no other clone and in places named an unrelated entry. Where a message already gave its reason the citation is dropped; the two that relied on the citation alone now give the reason in words. Messages only: no compared value, probe input or fixture changes. Refs #411
Assertion messages, a thrown error and exemption justifications in the guards cited learning-ledger IDs, which resolve on no other clone. Where a message already said why, the citation is gone. Where the ID carried the reason, the reason is written out: a provider check is only real at the one sink every caller passes through, and never capping how many tickets a round runs keeps the refresh's page bound an API bound. Each region justification stays above the length its check requires. Refs #411
Seven assertion messages in the seam suites ended in a learning-ledger ID, which resolves on no other clone. Each message already said why the assertion matters, so the citation is gone and the words stay. Refs #411
The errors the unit suite's HOME isolation throws ended in a learning-ledger ID that resolves on no other clone. Each already says what failed and why it refuses to run, so the citation is gone. The red probes match the words, not the ID. Refs #411
Thirteen assertion messages in the build suites cited learning-ledger IDs, which resolve on no other clone. Where a message already said why, the citation is gone. Two DUPLICATE-verdict messages now say the reason the ID stood for, as the resolve-pipeline knowledge base words it: the verdict enum must match on both sides of the spawn-to-op seam, and the Duplicates section is additive, so the convergence parser is unaffected. Refs #411
Six assertion messages in the Depends-on grammar suite cited learning-ledger IDs, which resolve on no other clone. Each message already says why the assertion matters, so the citations are gone; the API-bound message keeps its rule and loses only its ID label. Refs #411
Thirteen assertion messages across the init, installer, packaging and uninstall suites cited learning-ledger IDs, which resolve on no other clone. Where a message already said why, the citation is gone; the settings-merge message keeps its in-repo design marker. One message named a group of tests by an ID and now names them as the file's own comment does: the bare-dir safety tests. Refs #411
The init-residue suite labelled its HOME echo with a learning-ledger ID, which resolves on no other clone; the label now says what the echo is, the sandboxed init's HOME. The pack-install escaped-brace message already said what leaked, so its citation is gone. Refs #411
The test-harness knowledge base still gave the frozen status-lines fixture as 18,420 bytes with five re-captures granted. The fixture is 18,383 bytes, and eight have been granted, all spent, as the golden test's own log records; the three later ones are now listed. The compliance knowledge base said the skill directory is swapped atomically. installSkillDir removes the target and then renames the temp sibling into place, two calls, which narrows the window with no directory to the gap between them; both passages now say so. Refs #411
The test-harness knowledge base still gave the git-agent golden as 824 lines, 44,163 chars and 44,486 bytes, and the preloaded set as 53,686 chars and 1,129 lines. The golden tests pin 822 lines, 43,814 chars and 44,131 bytes, and 53,385 chars and 1,127 lines, and the fixture measures the same; both passages that quote them now agree. The heading over those figures said the frozen fixture did not move. That held for #376's byte-budget slices, but the fixture has been re-captured three times since, so the claim is now scoped to them. Refs #411
The two bare-skill-dir safety suites took their mkdtemp prefixes from a learning-ledger number, which resolves on no other clone. They are now devflow-baredir-test- and devflow-baredir-selective-, named after the behaviour the suites guard; no other file referenced either prefix. Refs #411
The test-harness knowledge base gave the budget-git-md ceiling as 44_243 against a measured 44_163, and the tracker-references one said git.md measures 44,163 ch / 824 lines against that ceiling. #393 lowered the ceiling to 43_912 (its measured 43_832 + 80) and the git-agent golden now pins 43_814 ch / 822 lines; both passages give those figures and name #393 as the ceiling's source. The test-harness file list also called the git-agent golden (tests/fixtures/golden/git-agent.md) frozen. It is byte-equal and regenerates with npm run test:golden:update -- git-agent; the frozen fixture is github-status-lines.txt. Refs #411
Spell the NBSP, BOM and U+FFFF characters in the identifier and whitespace tests as escapes instead of raw invisible characters. Derive Area from SCANNED_AREAS, compute a regular-expression literal's end once, move the call-chain walk into titleOfCall so collectTitles loses its isTestCall flag, drop an identity map in extractCommentary, and point the header at CHAIN_MODIFIERS and CALLING_MODIFIERS instead of a partial list of them. No behaviour change: the old and new extractors agree on every file in the worktree and on several hundred thousand generated inputs.
The DECISIONS_CONTEXT input description and step 4 both stated the rule, and step 4 repeated the rationale that the feature-knowledge and apply-decisions skills already carry. Keep the instruction, the refresh case and the Related-section line; drop the repeats.
The triage prompt now states a decision in words in the Reasoning column instead of citing it inline, so the title that said citing inline described the old behaviour. The assertion is unchanged.
The test arm flagged only citation-shaped IDs in comments and titles, and it never read assertion messages. Run over main's pre-sweep tree it passed this repo's commonest citation idioms: a leading label (`// <id>: reason`), an ID mid-sentence, a title that opens with an ID, and the 95 IDs that sat in expect() messages before the sweep. Nothing stopped those from coming back. Commentary now includes the message argument of expect(value, message), and an ID in commentary is reported unless the same file holds it as data outside its commentary, so the ledger-plumbing tests can still name the fixture rows they describe. Citation shapes stay reported, data or not. On main's tree the arm reports 1,177 sites instead of 854; the rest are fixture-row descriptions plus a residual the header now states. .release/RELEASE-FLOW.md joins the root prose: /release writes it with the decisions index loaded, and it is committed. The root-prose probes now cover every listed file, and the header no longer says the full ban matches any spelling — it matches the upper-case, ASCII-hyphenated form.
The sweep stated reasons in words but left two decisions it had cited throughout without a resolvable anchor. D-LOG-CONTENT-AUTHORITY, at toLedgerRow, records that the observation log is the one home of entry content and that a ledger row is a projection re-derived from it. D-MEMORY-STAGED-CAS, above verify_and_swap, records that the memory worker writes WORKING-MEMORY.md only through a staged file and a compare-and-swap. Each states its reason; the comments that restated either rule in loose words now name it. Comment-only: no behaviour change. Refs #411
Owner
Author
Test Plan Evidence — d33f370Verified 7/7: VERIFIED-CI 5, ATTESTED-LOCAL 2, UNVERIFIED 0, STALE 0, FAILED 0, INDETERMINATE 0
|
dean0x
deleted the
refactor/411-keep-learning-ledger-ids-on-the-machine
branch
October 3, 2026 15:55
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Learning-ledger IDs, the numbered decision and pitfall entries under
.devflow/learning/, were cited in committed code, tests, docs and knowledge bases, and in text that agents post to PRs. The ledger is gitignored and numbered per machine, so no other clone can resolve those IDs. Numbers have also been reused, which left some citations pointing at the wrong entry. This PR keeps the IDs on the machine: an ID may appear only in what stays inside a session, and anything committed, pushed or posted states the rule in words.It does four things:
tests/guards/no-ledger-citations.test.tsso a ledger ID cannot creep back into committed text.D-LOG-CONTENT-AUTHORITYandD-MEMORY-STAGED-CAS.Changes
Prompts (26 files under
src/assets/agents,commands,mdsandskills)apply-decisionsskill:applies/avoidscitations go only where they stay in the session (reasoning, decision tables, prompts to downstream agents, the report to the caller). Code, comments, tests, docs,KNOWLEDGE.mdfiles, commit messages, PR and issue text, review and PR comments and resolution summaries state the rule in words, and so does any report a later step copies into one of those. The worked example uses placeholders instead of real numbers./resolve: the Reasoning column and the resolution summary state decisions in words, andBY_DESIGNevidence is a recorded decision stated in words or a code comment/doc citation.feature-knowledgeskill: aKNOWLEDGE.mdstates each decision in the section it governs, and its Related section links only to other knowledge bases and files. The Knowledge agent states the rule once./dynamic-build,/dynamic-profile) are stated in words.Sweep
src/cli,src/core,src/targetsandsrc/hud, 19 undersrc/assets/scripts,scripts/build-mds.ts,scripts/update-golden.tsand bothvitestconfigs.docs/reference/, and 12 files under.devflow/features/(11KNOWLEDGE.mdfiles and the index).tests/modified, plus the new guard. Most edits are comments and test titles; the human-facing strings are listed under Deviations.tests/fixtures/numeric-floors.json: description strings only. No floor or ceiling value moved.Guard:
tests/guards/no-ledger-citations.test.ts(77 checks)src/**,scripts/**, the rootvitest*.config.tsfiles,docs/**, the root prose (CLAUDE.md,README.md,CONTRIBUTING.md,.devflow/conventions.md,.release/RELEASE-FLOW.md), the feature knowledge index, everyKNOWLEDGE.mdandtests/fixtures/numeric-floors.json.tests/**/*.tsit reads comments,describe/it/testtitles and the message argument ofexpect(value, message). A citation shape is always reported:applies,avoids,perorseebefore an ID, an ID that opens or closes a parenthesis or bracket, or an ID in the possessive. Any other ID in commentary is reported unless the same file holds it as data, because the ledger plumbing is tested on rows that carry IDs.CHANGELOG.md(released history), the frozen golden fixtures and install-snapshot goldens, and the ledger itself.retired-wordingrows the guard now covers are removed.D-series anchors
D-LOG-CONTENT-AUTHORITY(src/assets/scripts/hooks/lib/decisions-format.cjs, referenced fromjson-helper.cjs): the observation log is the one home of an entry's content. Its ledger row is a projection re-derived through one function.D-MEMORY-STAGED-CAS(src/assets/scripts/hooks/background-memory-update): the memory worker never writesWORKING-MEMORY.mddirectly. It writes a staged file and moves it into place only when the real file is byte-identical to its pre-run read, so an edit made during the run is kept.Deviations from the plan
tests/fixtures/golden/github-status-lines.txt, for line 207 only: the reply-evidence rule in the PR partial drops, ADR IDs. The diff is exactly that one line, 18,392 → 18,383 bytes, and the authorisation is logged intests/goldens/github-status-lines.test.ts. TP-6 in the test plan below predates that grant: it calls the fixture unchanged and names ittests/fixtures/github-status-lines.txt. The fixture lives undertests/fixtures/golden/, and apart from line 207 it is unchanged..release/RELEASE-FLOW.mdjoined the full-ban prose roots:/releasewrites it with the decisions index loaded, and it is committed.tests/evidence-policy/that pinned a ledger ID as a source marker now pin only the D-names./research,/dynamic-planand/dynamic-ticketscommands.test-harnessandtracker-referencesKBs;compliance-install.tscomments and thecompliance-featureKB now say it narrows the window to the gap between the two calls;src/cli/commands/init.ts;resolve-pipelineKB's file-deletion rule, which now matches the Recommended deny-list: it blocksrm's flag spellings, not a flaglessrmorunlink.Breaking Changes
None. A follow-up PR (learning v2: store, ops, render, agent, CLI) builds on this one.
Testing
tests/guards/no-ledger-citations.test.ts: 77 checks.dist/agents/git.mdis 43,814 characters against its 43,912 ceiling.npm run test:golden:update -- git-agentin a fixture-only commit: it moves only the golden and the equality baselines pinned to it.retired-wording,byte-budgetand both golden suites (5 files, 164 tests), all green.Related Issues
Closes #411
Test Plan