Skip to content

docs: CLAUDE.md becomes a constitution; current truth gets one owner each - #215

Open
adrianwedd wants to merge 2 commits into
masterfrom
docs/constitution-and-canonical-map
Open

docs: CLAUDE.md becomes a constitution; current truth gets one owner each#215
adrianwedd wants to merge 2 commits into
masterfrom
docs/constitution-and-canonical-map

Conversation

@adrianwedd

Copy link
Copy Markdown
Owner

Documentation architecture only. No behaviour change — no file under src/ or bin/ is touched.

The problem

CLAUDE.md was 495 lines mixing four genres in one voice: binding rules, subsystem detail, tuning constants, and incident narrative. Nothing in it could be trimmed safely, and because none of it was checkable, several claims had quietly outlived the code they described.

What changed

CLAUDE.md → 212 lines, holding only what a fresh agent must never break and where current truth lives: ten cross-cutting invariants, a "where current truth lives" table, a "read this before touching that" table, and the tool-addition checklist.

16 canonical docs, each separating ## Invariant (current, testable, citing the code and the test that pins it) from ## Why it looks like this (history, explicitly labelled as rationale rather than rule).

docs/architecture/  overview, resident-brain, policy-and-authority,
                    provenance, privacy, memory-and-learning
docs/hardware/      gpio-and-alive, wander-safety, audio-and-mic, power
docs/operations/    state-and-runtime, health, llm-routing, deployment
docs/               testing, git-workflow

Stale claims corrected against code

Each was verified by reading the source, not by trusting the old text:

Claim in old CLAUDE.md Reality on master
"~1235 tests" 1460 collected
provenance has "six kinds" sevenmodel_perception (ceiling 0.75, added by #177) was undocumented
DESCRIBE_SCENE_TIMEOUT 150s 165s, raised with CLAUDE_TIMEOUT 45→60 by #202
evolve blacklist omitted policy.py + test_policy_invariants.py, both in BLACKLIST_FILES
state/ is where state lives runtime_paths.py's /run/spark tmpfs class was absent entirely, though it is what ended the px-alive watchdog storm
README "1070 dry-run" tests corrected, plus a pointer to the canonical docs

Also verified and left alone because they are still true: SIGUSR1/yield_alive, the GPIO lease and PX_GPIO_LEASE_ID borrowing, and the three-enforcement-point policy description. Every numeric claim carried forward — the Claude budget table, PIN lockout, consolidation window, STALE_AFTER_S, relay address — was re-read from source.

Fossils

docs/superpowers/README.md and docs/historical/README.md carry a banner making clear those documents are decision fossils, not current truth. HANDOFF.md and docs/ALL_DOCS_REVIEW.md move under docs/historical/ (pure renames). AGENTS.md described a Codex-only voice loop that no longer exists and becomes a pointer to CLAUDE.md.

Preserved rather than duplicated

docs/SCRIPTS.md already owned px-race's PD sign convention and safety-layer ordering more accurately than CLAUDE.md did — it correctly explains the negative gains. wander-safety.md links to it. Same for systemd/README.md, whose back-reference into a CLAUDE.md section that no longer exists is repointed to docs/operations/deployment.md.

Tests

tests/test_docs.py — 25 tests, deliberately small. Relative links resolve; the blanket-staging prohibition is present in CLAUDE.md; the fossil banner exists; every canonical doc separates invariant from history.

Each check was confirmed to fail when broken (broke a link, removed the staging rule, removed the banner, removed an ## Invariant heading — one red each, then restored). A doc test that cannot fail is worse than none.

Verification

Full suite run on this branch: 1459 passed, 21 failed, 1 skipped in 23m52s. All 21 accounted for and none caused by this branch:

Failures Cause
11 test_tools_live.py — needs sudo and free hardware
6 test_mind_utils — live session sampling, #210 (fixed by #212, not on master)
2 TestBudgetSummarynew finding, filed as #213
2 TestRaceEndpoint — fixed thread waits under load, #211

The TestBudgetSummary pair was reproduced on a pristine origin/master worktree before being attributed elsewhere.

Defects found and filed, not absorbed

Noted, not fixed

docs/SCRIPTS.md claims to document every script but has no entry for px-post, px-blog, mcp-server, or tool-announce. Out of scope here.

Base is origin/master (825c253c), not the #212 branch — #212 is still open, so documenting its fixture as current would have been wrong. docs/testing.md marks session isolation as pending.

🤖 Generated with Claude Code

https://claude.ai/code/session_01TTC3fktSvjQNSShHyj7ATt

adrianwedd and others added 2 commits August 19, 2026 00:46
CLAUDE.md had grown to 495 lines holding rules, subsystem detail, tuning
constants and incident history in the same voice, so nothing in it could be
trimmed safely and several claims had outlived the code. It now holds only the
cross-cutting invariants and a map (212 lines); every subsystem gets one
canonical doc that separates `## Invariant` from `## Why it looks like this`.

Stale claims corrected against code rather than carried forward:

- test count ~1235 -> 1460 collected
- provenance "six kinds" -> seven; `model_perception` (ceiling 0.75, added by
  #177) was undocumented. The same off-by-one is still in
  `src/pxh/provenance.py`'s docstring and is filed separately.
- `DESCRIBE_SCENE_TIMEOUT` 150s -> 165s, raised with `CLAUDE_TIMEOUT` by #202
- the self-evolution blacklist omitted `policy.py` and
  `test_policy_invariants.py`, which are in `BLACKLIST_FILES`
- `runtime_paths.py`'s `/run/spark` tmpfs class was absent entirely, though it
  is what ended the px-alive watchdog storm

Verified as still true and left alone: SIGUSR1/`yield_alive`, the GPIO lease,
and the three policy enforcement points all match master.

`docs/SCRIPTS.md` already owned px-race's PD sign convention more accurately
than CLAUDE.md did, so wander-safety links to it rather than duplicating it.

Specs, plans and superseded notes get a banner saying they are decision
fossils; HANDOFF.md and ALL_DOCS_REVIEW.md move under docs/historical/.
AGENTS.md described a Codex-only voice loop that no longer exists and becomes
a pointer.

`tests/test_docs.py` pins the three things that can rot silently: relative
links resolve, the blanket-staging prohibition is present, and the fossil
banner exists. Each check was confirmed to fail when broken.

Docs only. No behaviour change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TTC3fktSvjQNSShHyj7ATt
The 21 failures on a full run are not one thing. Eleven need hardware, six
sample the live session (#210), two are decided by the wall clock (#213, filed
from this audit) and one or two are fixed waits under load (#211). Reading
that list as "the suite is flaky" is how a real regression gets waved through.

Also cites #214 for the provenance docstring's stale count, so the note in
provenance.md has somewhere to go when it lands.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TTC3fktSvjQNSShHyj7ATt
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