Contracts
diagram-drift-guard.md
Contract: Schema-diagram drift guard (FR-004, NFR-001, C-003) — hardened per post-plan squad
Both sides of the comparison (architecture HIGH — diagram side was missing)
- Model side: introspect via an explicit
file:classbinding table (1:N). Pydanticmodel_fieldswithFieldInfo.alias or name+ transitive nested recursion; frozen-dataclassfields(); StrEnum vialist(). Never a hand-copied count. - Diagram side: the
@startyamlfield-declaration shape is PINNED — top-level YAML keys (recursing into nested-model sub-maps) = the declared field set; scalar example values are excluded. The guard extracts this set and diffs it against the model side.
Non-fakeable tests (reviewer HIGH/MEDIUM)
1. Completeness over ALL kinds: add a synthetic ArtifactKind member → the guard FAILS until it carries an explicit disposition (diagrammed | consciously-omitted) in the binding table. (Not just the 4 priority kinds.) 2. Omit-a-field: a diagram MISSING a model field FAILS (not only "add a field to the model"). 3. Nested depth-2: add a field to a genuinely nested value-object — AgentProfileSchema → AgentSpecialization, or MissionStepContract → MissionStepContractStep → inputs (DRG is FLAT — do not use it for the depth test) — and assert FAIL. 4. Binds styleguides/models.py:AntiPattern vs the DRG anti_pattern NodeKind (no class) correctly.
no-egress-proof.md
Contract: No-egress proof (NFR-002, C-001) — hardened per post-plan squad
Execution locus (architecture HIGH)
- Python orchestration (fence recovery,
html.unescape, SVG injection) runs host-native, stdlib-only (docs-pages.yml has no setup-python / no pip install — no third-party imports). - Only the untrusted
java -jar plantuml.jarinvocation is wrapped:docker run --network=none -v <tmp>:<tmp> <digest-pinned-JRE-image> java -jar plantuml.jar …. The JRE image is prefetched before the isolated run. Drop hostsetup-java(redundant).
Proof (both required, BLOCKING CI gates)
- (a) Behavioral SANDBOX (reviewer MEDIUM): a diagram with
!includeurlpointed at a local listener renders under SANDBOX and the listener sees zero inbound connection (or the SANDBOX-specific refusal signal). NOT the weak "build fails" disjunct. - (b) Network isolation (reviewer HIGH): the isolation test renders the actual authored schema-diagram corpus (not a sample) under
docker run --network=none, and passes. This IS the hard gate (not the ≤60s budget).
Spike (blocking WP01 — planner/architecture HIGH)
Runnability is currently UNPROVEN. WP01 renders a real @startyaml diagram under --network=none on both ubuntu-latest and blacksmith-4vcpu-ubuntu-2404, confirming no font/DNS-driven failure. Its green exit-criterion gates every render/diagram WP. URL-grep is a secondary lint.
plantuml-render.md
Contract: PlantUML render step (FR-001, NFR-003/004/005) — hardened per post-plan squad
Placement
- Inserted immediately after
glossary_linker, before redirect-stub generation +seo_verify --strict, in BOTHdocs-build-pr.yml+docs-pages.yml(+ the deploypaths:enumerated allowlist — it is not a glob). A round-trip test runs the full downstream chain over an SVG-injected page. - Recovers
`plantumlfences from_site:html.unescapethe payload; confirm the emitted fence class against real_siteHTML (language-plantumlvslang-…) — the round-trip test is the backstop.
Alt-text (NFR-005, reviewer MEDIUM — concrete predicate)
- Alt/aria derived from the diagram's title/caption; test renders two differently-titled diagrams and asserts distinct alt equal to the derived caption and NOT in a generic-fallback set (
{"yaml","diagram",""}). Confirm the derivation source (PlantUMLtitlevs surrounding markdown heading).
Other testable guarantees
- Mermaid untouched; malformed fence fails-closed; jar sha256 mismatch fails before render; ≤60s is a monitored budget (not a gate).