Repository navigation
EPIC: the guards this arc built do not guard what they claim — fifteen verified defects, and the reason they survived three reviews #241
Description
Rewritten 2026-08-12 after an expert review of the standing decisions. The first draft was nine stories of widening guards. This one is mostly deletion, and it is scoped so that PR #240 can merge after three issues, not nine.
The problem, in one paragraph
This repository has 9,200 lines of tests against 2,998 lines of package, and 3,182 of those test lines guard the repository's claims about itself rather than the product. A post-merge review of #239 found fifteen defects, all reproduced. They are not fifteen unrelated slips. Every one sits on a check that tries to verify a fact this repository does not own — another repo's source layout, another repo's edition semantics, every markdown dialect a person might write. Those checks cannot be proven against reality, so they get proven against the author's imagination, and then they fail inspection. That is the loop this epic exists to break.
The root decision
A check here may rest on a fact we own, on a fact another repository has declared in the public registry, or on an outcome we can observe. It may never rest on another repository's implementation.
Where a needed fact is none of those three, the check is not built here. It is requested as a declaration, requested as a consumer obligation, or registered as an accepted gap with a named owner and trigger.
ADR-003 already says this. It was applied rigorously to the product and not at all across the repository boundary. Landing it as an ADR-017 clause is what makes this a roadmap instead of a queue.
The evidence it is right: the consumer source-read broke twice in 24 hours — views-faoapi on 2026-08-11, views-crafdapi on 2026-08-12 — both times because the other repository refactored a literal into a named constant. Their code got better and our test went red. The regex was measuring their code quality and reporting it as our failure.
What ships, and when
This is an MVP with one maintainer. The test for every item below is: does this make the thing smaller, or does it add a second product to maintain?
Gate 1 — blocks PR #240. Three issues, almost entirely deletion.
| net | ||
|---|---|---|
| #242 | The no-copy guard prints the coordinate value it exists to hide, into public CI logs, on the one event it fires for | ~5 lines changed |
| #245 | Delete arrived. It is computed over every row of every table we depend on — 8 of 25 belong to other repositories — so any coordinate issued for any repo blocks a release here. This is the thing that literally stops shipping. |
net deletion |
| #248 | Delete both consumer source-reads. Broken twice in 24 hours; one is red on development right now. Not replaced — the category is wrong. Register the gap with an owner and a trigger. |
net deletion |
After these three, #240 merges. Nothing below blocks the release.
Gate 2 — cheap, same week, each makes the code smaller or truer
| #243 | Replace the assignment parser with a pair matcher, and adopt a corpus-derived stopping rule. This deletes regex complexity; it does not add any. (#244 merged in.) |
| #246 | Two proofs that cannot fail: a tautology, and the untested function an entire module was extracted to create. |
| #247 | The cheap legibility fixes only — rows() refusing a scalar row, commit.gpgsign and a timeout on the scratch repo. No platform-module extraction. |
| #249 | Eight stale claims this arc left behind, plus a þing mis-citation that concealed a whole mechanism for weeks. |
Gate 3 — the two paragraphs that stop the next round
| #250 | The ADR-017 clause above, plus a short ADR-014 §2 amendment: a guard provable only against imagined inputs is on the wrong side of a boundary. Two paragraphs, not an essay. |
Deliberately NOT built — deferred with named triggers
Each of these was recommended by the expert review. Each is defensible. Each is also a second thing to maintain, and none of them is needed to ship.
| Deferred | Why not now | Trigger to revisit |
|---|---|---|
| Read-only findability preflight — query the store after upload, assert the document is findable by the declared name | It is the right long-term answer to invisible delivery and it needs a read credential wired into the launcher — an operator action, not a code change. Delivery works today. | A delivery is reported empty, or APPWRITE_READ_API_KEY is provisioned for the launcher. Registered as C-94. |
Adopt [edition].obliges_consumers |
Deleting arrived already fixes the shipping problem. Adopting the flag is an addition, and it would move a safety property onto upstream's labelling discipline. |
The drift check fires again on something we do not care about. |
Extract a platform/ declarations module (C-88) |
One script hardcodes one string that conftest declares. One duplicated string is cheaper than a new package for a solo maintainer. WET before DRY, and the abstraction is not yet known. |
A third consumer needs one of these declarations. C-88 stays open with its existing trigger. |
| GitHub push protection / secret scanning | These coordinates need a custom pattern, which historically requires paid Advanced Security. Money is the operator's decision, not mine. | The cost is known, or GHAS becomes available on this org. |
Splitting test_env_declaration.py (1,145 lines) |
Real debt, correctly diagnosed, and moving 1,145 lines while fixing bugs in them is how a fourth review finds a sixteenth defect. | The file grows again after this epic, or a second contributor arrives. |
| A write-path integration test | Forbidden by the seam contract until a non-production Appwrite project exists — an operator assignment from þing-01 D2 that is still open. | The test project is created. |
Desired end state
- PR Sync development → main: the sibling-CI arc, three ADRs, and a drift check that matches on the right thing #240 merged; FAO has the eight days of work.
- No guard in this repository reads another repository's source. Ever again.
- The drift check fires on exactly one condition: a row we name moved between the pin and their
main. - The no-copy scan's stopping rule is written down, mechanical, and derived from this repo's own documents rather than from imagination.
- Every proof in the arc fails under mutation of the thing it names.
- The guard surface is smaller than when this epic started.
Out of scope, permanently for this epic
- Any change to delivered bytes.
CONTRACT_VERSIONstays1.5;tests/fixtures/stays byte-identical. Any story that would touch either is wrong and must stop. - De-inheritance (C-40 / Cluster G).
mainbranch protection and required status checks (C-81, C-86) — operator-owned, and deliberately sequenced after this epic. The epic is what makes requiring the check cheap, by shrinking what CI needs from siblings.- Editing views-faoapi or views-crafdapi. This epic may file issues there; it does not touch them.
Acceptance criteria
- Gate 1 complete; PR Sync development → main: the sibling-CI arc, three ADRs, and a drift check that matches on the right thing #240 green and merged.
-
ruff check .clean; suite green; no test skipped that was not skipped before. -
CONTRACT_VERSION == "1.5";git diff origin/main..HEAD -- tests/fixtures/empty. -
wc -l tests/*.pyis lower than at the start of this epic. If it is higher, the epic did the opposite of its purpose and needs re-reading. - Every deferral above is in the register with an owner and a trigger (ADR-014 §4).
- C-89 … C-96 each resolved or amended with a measured residual.
- A review pass by something other than the author finds nothing above suggestion severity.
Provenance
Every claim here was reproduced locally against views-appwrite@origin/main (registry v1.6.0) and views-faoapi@origin/development. Where the review that raised an item overstated it, the issue says so.
Activity
Polichinel commentedon Aug 12, 2026
Stories and tracking issue are filed.
Implementation order and completion criteria: #251.
PR #240 (
development→main) is blocked on this epic.Polichinel commentedon Aug 12, 2026
Complete. All nine stories closed, PR #240 released, post-mortem in
reports/post_mortems/2026-08-12_the_guards_that_did_not_guard.md.Closing summary in #251.
Merge pull request #262 from views-platform/development