S2 — Rewrite the physical-architecture standard's directory tree (closes C-84) - #253
Merged
Merged
Conversation
…oses C-84) S2 of epic #240, closing register C-84. Documentation only. The §2 directory tree was a pre-implementation sketch that was never revised after the package was built. It showed one of three packages, omitted `metadata.py`, `_typing.py` and the whole `conformance/` subpackage, listed two files that never shipped (`weight_frame.py`, `mask_frame.py`), and still marked `target_frame.py` as "(anticipated)" — it shipped in v1.0.0 with its own CIC. The document was also undated, so its staleness could not be seen by looking. The tree now covers all three shipped packages and all 36 modules, ordered by the ADR-002 layering S1 corrected, with the ADR-001 category on each file that has one. `_typing.py` and `conformance/` are marked as having no category and why — one is a typing helper, the other verifies the ontology rather than belonging to it. The document carries a `Last reviewed` date and a note saying the tree is authoritative and therefore perishable. Verified with a check written to match the shape of the claim rather than a fixed phrase, and mutation-tested in both directions before being trusted — per the refinement S1 added to C-77. It parses the fenced tree and diffs it against `src/**/*.py`: clean at exit 0; reinstating a phantom module gives exit 1 naming `weight_frame.py`; hiding a real one gives exit 1 naming `views_frames/metadata.py`. Extending the tree to three packages surfaced two contradictions in the sections below it, fixed here rather than left: - §3 forbids `utils`/`helpers`/`common` dumping grounds, while the newly-visible `_common.py` and `_typing.py` carry exactly such names. §3 now says why each is a focused module — two functions with one responsibility, two type aliases — and that a third unrelated concern is the signal to split rather than to widen the exception. - §5 said compliance would be audited "once the leaf is stood up". It now names the two rules that are machine-enforced and states plainly that the tree itself is not — it is kept current by the review note at the top. Not done here: folding the tree check into `validate_docs.sh`. That script is bash-and-grep by design and parsing a fenced tree is the one candidate check that plausibly cannot be. Recorded on #246 for S6 to decide. Closes #242. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…oken parenthetical Four findings from /review-diff on this branch. The perishability note said the tree "showed one of three packages and eight of thirteen modules". Placed next to "one of three packages", a reader takes thirteen as the repository total — and it is not: this PR's own verification reports 36 source modules. Thirteen was a count of views_frames modules-as-named- concepts, and even that is arguable (14 files, 11 excluding `__init__.py`). This is S1's "Ten modules" defect recurring one story later, in a note whose subject is documents that fall out of step with reality. Same fix as S1: delete the number rather than correct it, and say the specific thing instead — one of the three shipped packages, the three omitted modules by name, two files never written. Nothing left to drift. Also: - The `_typing.py` entry closed its parenthetical on an em-dash and padding — "(private; no category — )" — with the completing clause on the next line, outside the parentheses. It read as unfinished text in the one document whose stated purpose is that a reader infers every responsibility from the tree without reading bodies. - Realigned the comment column across all three package blocks. Category annotations had landed at four different columns where the original tree was aligned; in a screaming-architecture document the tree's legibility is the deliverable. Re-verified after the rewrite: 36 modules, no ghosts, all three packages. - The C-84 resolution now says the tree-check script is deliberately not committed and why — it would be the only Python under a `docs/` tree whose CI job installs none, and whether the logic belongs in `validate_docs.sh` is S6's call (#246). A reader was otherwise left hunting for a file that is not in the repository. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… close the cluster Five findings, and one of them says I was too conservative in the last commit. **The check is now committed** as `scripts/check_arch_tree.py`. The previous commit argued it should stay out of the repository because `docs/` has no Python. That was the wrong boundary: `scripts/` already holds exactly this kind of standalone tool (`verify_reconcile_parity.py`, the fixture generators), all unwired from CI. Pasting a transcript of a script nobody can re-run is the pattern C-77 exists to flag, and the register entry was doing it. The script parses the fenced §2 tree and diffs it against `src/**/*.py` in both directions; mutation-tested again after committing. Whether it belongs in `validate_docs.sh` is still S6's call (#246) and the module docstring says so. **§1 contradicted the tree §2 now makes visible.** It required every non-trivial class to live in a file named after it, and named "bundling unrelated frames in a frames.py" as the incorrect example. The reconcile block exposes `module.py` (ReconciliationModule), `result.py` (ReconciliationResult) and `frames.py` — which under a literal reading violates both. It does not: module names are read package-qualified, so `views_frames_reconcile/module.py` reads as `reconcile.module` and `reconciliation_module.py` would stutter; and `frames.py` holds the package's array→frame adapter *functions*, not a bundle of frame classes. §1 now says this, and separates the mechanically-checked half (`test_one_concept_per_file`) from the review-judgement half. **Three register/CHANGELOG inconsistencies**, all created or exposed by this epic: - The Status-section prose read "At 17 open concerns — 13 of them Tier 3" three lines under a header this branch changed to 16. Both numbers described 2026-07-31, when the Status class was introduced. It now says so, and points at the header as the current count. - The `doc↔code topology drift` cluster still read as pending work, in present tense, though both members are now resolved — and Register Conventions declare that list the single authority on clustering. Marked CLOSED by S1+S2, matching the form the other closed clusters use. - The `[Unreleased]` CHANGELOG recorded C-84 as registered but never as resolved, while giving S1's C-82 correction a full entry. S2 now has one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two stories, two refinements, both learned by getting it wrong. S1 taught that a check has to be capable of failing: C-82's grep matched four fixed phrases and missed two occurrences inside its own search path. S2 taught the next part. The C-84 resolution pasted output from a script that had been mutation-tested in both directions — which satisfies S1's lesson — but the script lived in a scratchpad and was never committed. The only artifact proving the tree was correct was a transcript nobody else could execute. A claim backed by an unreproducible transcript is the same shape as a claim backed by nothing. So the rule has three parts, and S10 (#250) should write all three somewhere durable: demonstrate rather than describe; use a check that could actually have failed; leave the check where the next person can run it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
S2 of epic #240. Closes #242 and register C-84. Documentation only —
src/untouched, no public API change,CONFORMANCE_FLOORstays1.0.0.Depended on #252 (S1), which corrected the layering paragraph in this same file. That is why these were separate stories: S1 owned
:48-49and:67, S2 owns the tree those lines sit under.The problem
docs/standards/physical_architecture_standard.md§2 held the repository's authoritative directory tree — the document a contributor is pointed at to answer "where does this file go?", and one ADR-007 expects agents to read. It was a pre-implementation design sketch that was never revised after the package was built:weight_frame.py"(anticipated)"mask_frame.py"(anticipated)"target_frame.py"(anticipated)"metadata.py_typing.pyconformance/views_frames_summarize/views_frames_reconcile/Eight of thirteen leaf modules, one of three packages, two phantom files. The document was also undated, so its staleness was invisible — every CIC carries a
Last reviewedline and all eight are current; this standard had nothing.What changed
_typing.pyandconformance/marked as having no category, and why — one is a typing helper (C-19), the other verifies the ontology rather than belonging to it (ADR-016). Inventing category numbers for them would have been worse than saying so.Last revieweddate and a perishability note at the top: the tree is authoritative and therefore perishable; update it in the same change that moves a module.Verification
Per the refinement S1 added to C-77, the check matches the shape of the claim rather than a fixed phrase, and was mutation-tested in both directions before being trusted. It parses the fenced tree and diffs it against
src/**/*.py:Both failure directions are caught, which is what makes the green run mean anything. This is the lesson from S1, where C-82's first verification pasted real output from a real command and still missed two surviving occurrences because the command could not have found them.
Two contradictions the rewrite surfaced, fixed here
Extending the tree to three packages made two existing sections wrong. Both were created by this change, so both are fixed in it rather than deferred:
utils/helpers/commondumping grounds — while the newly-visibleviews_frames_summarize/_common.pyandviews_frames/_typing.pycarry exactly such names. §3 now states why each is a focused module (two functions with one responsibility; two array aliases) and that a third unrelated concern is the signal to split, not to widen the exception.test_one_concept_per_filefor §1; theimport-lintercontracts andtest_package_dependency_dagfor §4) and states plainly that the tree is not machine-checked — it is kept current by the review note at the top.Deliberately not done
The tree check is not folded into
docs/validate_docs.sh. It is a natural fourth assertion alongside S6's three (#246), but that script is bash-and-grep by design — thedocsCI job installs no Python on purpose — and parsing a fenced tree is the one candidate of the four that plausibly cannot be done in bash. Recorded on #246 for S6 to decide rather than pre-empted here.Section 1's rules, the naming convention, and the Category taxonomy are untouched. They are accurate and test-enforced. This story fixed the tree, the date, and the two contradictions the tree created.
Register
C-84 closed and moved to Resolved: open 17 → 16, resolved 65 → 66.
🤖 Generated with Claude Code