Repository navigation
Sort docs/governance from 63 documents into three, and check doc links - #833
Merged
Merged
Conversation
An audit prompt is an instrument, not policy. The nine in docs/governance were
reusable and language-agnostic -- AUDIT_ARCHITECTURE.md opens "Applies to: any
language runtime with a compiler, VM, and embedding API" and describes no Nodus
rule at all. You run one, fix what it finds, and re-run it. That is a
development and benchmarking tool, and it now lives in docs/audits/.
The same reading applies to the records. Four docset-sweep documents carry an
explicit "a dated record ... do not update it to match the tree" banner; five
version plans are superseded; two release notes predate CHANGELOG.md; the
reconciliation plan is CLOSED and CLAUDE.md already warns it is not a to-do
list; three ecosystem analyses are pinned to released versions; and
INVARIANT_TEST_MAPPING.md says in its own header that tools/invariant_coverage.json
supersedes it. None of those governs anything. They are docs/history/ now, with
the sweep, the plans and the release notes grouped so their sibling links keep
working.
The three eval prompts joined the results they produce in docs/evals/, so the
prompt and its output sit together.
Governance keeps the 34 documents that actually govern. The size was itself the
problem: a folder nobody can navigate does not govern anything.
The paths inside the dated records were deliberately not rewritten. A record is
a statement about the tree on a given day, and editing "docs/governance/V2_1_PLAN.md"
to the current path would make the sweep claim it saw a file somewhere it never
was. Markdown links were repointed so they resolve -- a link is navigation, not
a claim -- while prose naming an old location was left alone. Same reasoning for
CHANGELOG.md, whose entries describe releases that happened.
docs/history/README.md records the distinction so the next reader does not
"fix" it.
Mechanical care, since 57 files mention a moved document:
- a link checker found 11 genuinely broken links across 6 files; all fixed
- 36 full-path references updated, in live documents only
- version_claims.json's discovery sweep globbed docs/governance/*.md, so it
stopped covering the moved files -- widened to the three new directories
- .gitignore pointed at docs/governance/V3_0_PLAN.md, which no longer exists
- docs/README.md's directory map gained audits/ and history/ and lost the
audit row from governance
tests/test_doc_links_resolve.py is the check that was missing. The gate verifies
documented symbols, runnable blocks, opcodes, version claims, invariants and
staged flips -- and nothing verified that a link went anywhere. Every one of
those eleven breaks was found by writing this test, not by reading the diff.
Bounded deliberately: tracked files, relative links, .md targets, anchors
stripped. A link checker that needs the network gets disabled the first week it
goes red on someone's train.
All ten gate phases green, 0 broken links, ruff clean, 81 tests over the
affected suites.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TnzKwmx6XecNEqP2482MuA
CI failed this test on its first run, and the finding is better than the fix.
docs/history/plans/V3_1_PLAN.md linked to V3_0_PLAN.md, a sibling gitignored in
an early commit ("gitignore V3_0_PLAN", da88df9's successor). So the link has
been broken for every reader who cloned the repo since it was written -- and my
local run passed, because the file is on this disk.
That is the wrong way round for a check whose whole purpose is catching a link
nobody clicked. A filesystem check is not a smaller version of this check; it is
one that passes for the person least able to notice and fails for everyone else.
So `broken_links` resolves targets against `git ls-files` now. Local and CI
agree, and reverting the de-link below reproduces CI's failure here.
The link itself is gone rather than repointed: the target is deliberately not in
the repo, so no path would make it resolve for a reader. The line says so, and
notes that its sibling plans ARE tracked -- which makes V3_0_PLAN an
inconsistency rather than a rule. Left as found; it is not this change's
decision to make.
The hermetic cases pass `exists=` explicitly, since they build files in a temp
directory that git tracks nothing of, and one new case pins the property
directly: a target present on disk but untracked is reported.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TnzKwmx6XecNEqP2482MuA
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.
An audit prompt is an instrument, not policy
AUDIT_ARCHITECTURE.mdopens with "Applies to: any language runtime with acompiler, VM, and embedding API" and describes no Nodus rule at all. You run
one, fix what it finds, and re-run it. Nine of those sat in
docs/governance/.They are
docs/audits/now.The same reading applies to the records — and each says so in its own header:
V6_0_PLAN.mdCHANGELOG.mdHIGH_CONFLICT_DOC_RECONCILIATION_PLAN.mdINVARIANT_TEST_MAPPING.mdtools/invariant_coverage.json", in its own headerNone of those governs anything. They are
docs/history/, grouped so siblinglinks keep working. The three eval prompts joined the results they produce in
docs/evals/.Governance keeps the 34 documents that actually govern. The size was itself
the problem: a folder nobody can navigate does not govern anything.
The paths inside the dated records were deliberately not rewritten
A record is a statement about the tree on a given day. Editing
docs/governance/V2_1_PLAN.mdto the current path would make the sweep claim itsaw a file somewhere it never was.
So markdown links were repointed so they resolve — a link is navigation, not
a claim — while prose naming an old location was left alone. Same reasoning
for
CHANGELOG.md, whose entries describe releases that happened.docs/history/README.mdrecords the distinction so the next reader does not"fix" it.
Mechanical care — 57 files mention a moved document
version_claims.json's discovery sweep globbeddocs/governance/*.md, so itsilently stopped covering the moved files — widened to the three new directories
.gitignorepointed atdocs/governance/V3_0_PLAN.md, which no longer existsdocs/README.md's directory map gainedaudits/andhistory/Every move is recorded by git as a rename, so history follows the files.
The check that was missing
nodus_gateverifies documented symbols, runnable blocks, opcodes, versionclaims, invariants and staged flips — and nothing verified that a link went
anywhere. That is why this move broke eleven links silently, and why every one
of them was found by writing
tests/test_doc_links_resolve.pyrather than byreading the diff.
Bounded deliberately: tracked files, relative links,
.mdtargets, anchorsstripped. A link checker that needs the network gets disabled the first week it
goes red on someone's train.
Falsified: breaking one link in
docs/README.mdturns it red naming the file andthe target; the hermetic cases cover missing, present, anchored, external and
parent-relative targets, with a control so none of them can pass for a broken
matcher.
Checks
nodus_gate --all— all ten phases, 306/306 doc blocksruff check .clean🤖 Generated with Claude Code
https://claude.ai/code/session_01TnzKwmx6XecNEqP2482MuA