You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Investigate: is the import topology declared, enforced, and is the declaration itself checked? #285
Whether this repository's internal import topology is declared and enforced, and — the sharper question — whether anything that is declared is itself checked, rather than only being the thing the code is checked against.
Measured across all views_platform repos on 2026-08-18: 4 of 18 carry import cycles, 7 have some form of import-enforcement test, and only 1 has a declared topology contract.
In order, and the platform's best-behaved repo — which makes locking it in worth more, not less.
Zero cycles across crafd|unfao → contract → delivery. No enforcement test.
Worth stating plainly: this is the only register on the platform that fully converges — 78 concerns arrived, 78 resolved, open count flat at 22 over four months. Whatever is happening here is working.
The namespace-package concern raised in issue #284 was tested and disproved — grimp builds the graph fine, 37 modules, all four packages found. No __init__.py is needed.
Note this repo uses poetry, not uv — the dev group is [tool.poetry.group.dev.dependencies] and CI is run_pytest.yml.
For examples / inspiration
views-datafactory#457/#458 — test_the_declared_graph_is_acyclic and test_every_package_on_disk_is_declared. Two assertions in an existing file. No new dependency, no graph library, no new module. The insight is worth stealing verbatim: an assertion about conformance standing in for an assertion about the property.
views-framespyproject.toml[tool.importlinter] — two layers contracts, | between siblings meaning independent (that is what prevents a cycle; : permits one), each recording the direction the code already has. Note the comment explaining why the contract and tests/test_import_enforcement.py deliberately overlap.
Investigative issue filed by Claude Opus 5 at Simon's request, after a census of import structure across all views_platform repos. Nothing was changed in this repository.
I wrote that this register is "flat at 22 open over four months" and "the only register on the platform that fully converges". That was measured on 2026-08-15. It now reads 28 open, and has since at least 2026-08-17.
Six concerns arrived and were not closed. That does not overturn the point — 78 arrived and 78 were resolved over the measured window, which is still the best ratio on the platform — but "fully converges" is no longer accurate as a present-tense statement, and I should not have repeated it without re-checking.
The recommendation is unaffected: the repo is cycle-free, and a contract passes on arrival. But if the register is now accumulating, that is worth a look on its own terms rather than being cited as the example everyone else should follow.
This repo has partial enforcement already: tests/test_clone_readiness.py.
It asserts that contract/ does not depend on unfao/, and it does so by importing modules in a fresh interpreter and watching what actually arrives in sys.modules — its header explains why, since "views_postprocessing.unfao" in sys.modules is meaningless in a process that already imported it. ADR-002's amendment names it explicitly: the seam is "enforced mechanically by tests/test_clone_readiness.py, not by convention (#153/#155)."
I missed it in the 2026-08-18 census because I scanned for [tool.importlinter] blocks and for import-enforcement-shaped filenames. This one is named after clone readiness, so the scan did not reach it.
Two consequences, both sharpening this issue rather than closing it.
1. The declaration-checking question lands squarely. That test hardcodes a sixteen-name list of contract.* modules to check. A seventeenth is not unchecked-and-failing, it is unchecked-and-passing. The file's own header records that this already happened once: crafd/ joined unfao/ and every assertion hardcoded the string "views_postprocessing.unfao", so contract/ could import crafd freely. That is exactly the C-350/C-351 shape this issue asks about, with a documented prior occurrence.
2. import-linter is not a superset of it. Static analysis cannot see runtime import arrival. If a contract lands here (see #284), the two overlap deliberately and both should stay — views-frames states that overlap in a comment for precisely this reason, so nobody deletes the test believing the contract replaced it.
The actionable proposal remains #284, which now also carries the exhaustive option that closes the hardcoded-list hole, plus a separate finding: ADR-002's "Current internal layering (replaces the stale illustration)" never mentions crafd/.
Correction by Claude Opus 5 at Simon's request, after re-auditing the census that produced this issue. Nothing changed in this repository.
Answered, and one fact in the census needs correcting: this repo is recorded as "enforcement test: none". It has seven.
tests/test_clone_readiness.py proves both vertical arrows of ADR-002 by importing packages in a subprocess with the others blocked — and its own docstring records that a regex was written first and rejected, because it missed from ..contract import gaul_schema and from views_postprocessing import contract. There is also a mutation proof of the detector (test_the_guard_would_actually_catch_a_violation, parametrised over both partners).
That is stronger than a static contract: it proves the modules import in isolation, rather than that no import statement mentions them.
The real gap, and it was worth finding
Nothing proved the horizontal arrow. Nothing stopped crafd and unfao importing each other — and that is the arrow that keeps a partner liftable. The two are deliberate clones (C-33), so the realistic violation is a copy-paste leaving a sibling's import behind, and test_the_machinery_imports_without_any_partner cannot see it, because that test imports the machinery.
Closed in #291 with test_a_partner_does_not_import_its_sibling, in two halves matching the split this file already documents: subprocess (load-bearing, sees transitive arrivals) and AST-of-imports (the supplement, covering managers/, which the subprocess skips because importing a manager needs views-pipeline-core).
On suggestion 2 — "mutation-test it before trusting it"
Taken, and it earned its keep twice. The first version scanned the manager's text, which would have failed on a comment naming the sibling — this repo's comments cite module paths constantly, so that guard would have been deleted for crying wolf (ADR-014 §3). The second version used the AST but skipped node.level, reintroducing exactly the relative-import miss this file's docstring says killed the earlier regex. Both caught by review, both mutation-proven after fixing.
Final coverage: absolute, dotted, 3-dot relative, the from views_postprocessing import unfao package form, and managers/__init__.py — each fails; a comment naming the sibling and an innocent contract import do not.
Activity
Polichinel commentedon Aug 18, 2026
Correction: the convergence claim above is stale.
I wrote that this register is "flat at 22 open over four months" and "the only register on the platform that fully converges". That was measured on 2026-08-15. It now reads 28 open, and has since at least 2026-08-17.
Six concerns arrived and were not closed. That does not overturn the point — 78 arrived and 78 were resolved over the measured window, which is still the best ratio on the platform — but "fully converges" is no longer accurate as a present-tense statement, and I should not have repeated it without re-checking.
The recommendation is unaffected: the repo is cycle-free, and a contract passes on arrival. But if the register is now accumulating, that is worth a look on its own terms rather than being cited as the example everyone else should follow.
Polichinel commentedon Aug 20, 2026
Correction — "enforcement test: none" is wrong
This repo has partial enforcement already:
tests/test_clone_readiness.py.It asserts that
contract/does not depend onunfao/, and it does so by importing modules in a fresh interpreter and watching what actually arrives insys.modules— its header explains why, since"views_postprocessing.unfao" in sys.modulesis meaningless in a process that already imported it. ADR-002's amendment names it explicitly: the seam is "enforced mechanically bytests/test_clone_readiness.py, not by convention (#153/#155)."I missed it in the 2026-08-18 census because I scanned for
[tool.importlinter]blocks and for import-enforcement-shaped filenames. This one is named after clone readiness, so the scan did not reach it.Two consequences, both sharpening this issue rather than closing it.
1. The declaration-checking question lands squarely. That test hardcodes a sixteen-name list of
contract.*modules to check. A seventeenth is not unchecked-and-failing, it is unchecked-and-passing. The file's own header records that this already happened once:crafd/joinedunfao/and every assertion hardcoded the string"views_postprocessing.unfao", socontract/could importcrafdfreely. That is exactly the C-350/C-351 shape this issue asks about, with a documented prior occurrence.2. import-linter is not a superset of it. Static analysis cannot see runtime import arrival. If a contract lands here (see #284), the two overlap deliberately and both should stay — views-frames states that overlap in a comment for precisely this reason, so nobody deletes the test believing the contract replaced it.
The actionable proposal remains #284, which now also carries the
exhaustiveoption that closes the hardcoded-list hole, plus a separate finding: ADR-002's "Current internal layering (replaces the stale illustration)" never mentionscrafd/.Correction by Claude Opus 5 at Simon's request, after re-auditing the census that produced this issue. Nothing changed in this repository.
Merge pull request #291 from views-platform/chore/286-adopt-views-fra…
Polichinel commentedon Aug 21, 2026
Answered, and one fact in the census needs correcting: this repo is recorded as "enforcement test: none". It has seven.
tests/test_clone_readiness.pyproves both vertical arrows of ADR-002 by importing packages in a subprocess with the others blocked — and its own docstring records that a regex was written first and rejected, because it missedfrom ..contract import gaul_schemaandfrom views_postprocessing import contract. There is also a mutation proof of the detector (test_the_guard_would_actually_catch_a_violation, parametrised over both partners).That is stronger than a static contract: it proves the modules import in isolation, rather than that no import statement mentions them.
The real gap, and it was worth finding
Nothing proved the horizontal arrow. Nothing stopped
crafdandunfaoimporting each other — and that is the arrow that keeps a partner liftable. The two are deliberate clones (C-33), so the realistic violation is a copy-paste leaving a sibling's import behind, andtest_the_machinery_imports_without_any_partnercannot see it, because that test imports the machinery.Closed in #291 with
test_a_partner_does_not_import_its_sibling, in two halves matching the split this file already documents: subprocess (load-bearing, sees transitive arrivals) and AST-of-imports (the supplement, coveringmanagers/, which the subprocess skips because importing a manager needs views-pipeline-core).On suggestion 2 — "mutation-test it before trusting it"
Taken, and it earned its keep twice. The first version scanned the manager's text, which would have failed on a comment naming the sibling — this repo's comments cite module paths constantly, so that guard would have been deleted for crying wolf (ADR-014 §3). The second version used the AST but skipped
node.level, reintroducing exactly the relative-import miss this file's docstring says killed the earlier regex. Both caught by review, both mutation-proven after fixing.Final coverage: absolute, dotted, 3-dot relative, the
from views_postprocessing import unfaopackage form, andmanagers/__init__.py— each fails; a comment naming the sibling and an innocentcontractimport do not.Full reasoning on import-linter in #284.