canon-kit
Spec discipline for agent-authored components: one canonical spec per component, deltas as short-lived amendment files, and a star topology across the prose surfaces — every fact has exactly one owning surface, and every other surface cites it rather than restating it. Gates hold the copy-shaped failure modes; the irreducibly semantic judgment stays a review tripwire, not a gate.
Why: when a coding agent authors the specs, design rationale gets re-derived under build pressure unless it is captured up front, and a parallel copy of any gated fact is an un-gateable second source that drifts silently. The remedy is a lifecycle (amendments authored up front, merged and deleted at build) plus gates over the mechanically-decidable copy failures — a doubled Definition-of-Done, a banned-heading code dump, a fenced block that verbatim-copies a source file, a glossary definition restated on another surface, a feature task with no amendment. See SPEC.md for the full contracts.
This file ships in the installer payload; what that payload withholds, and where this page’s SPEC.md links then resolve, is gate-sdk/SPEC.md §Consumer payload.
Install
Vendor the kit beside gate-sdk (required); the queue-facing gate reads the tag syntax queue-kit defines.
-
Register the gates — add to your
gates.list, each where its surface exists:check-amendment-queue # needs a task queue check-amendment-update-target # every update target cites a delta the amendment defines check-amendment-retired-spelling # declared retired spellings survive only where the roster names check-spec-dod-singleton # needs canonical specs check-spec-derivable-section # needs canonical specs check-spec-embedded-source # needs canonical specs + tracked source check-surface-duplication # needs a glossary (exits 2 without one) check-comment-tier # classifies comments on shell/config sources check-spec-pointer # resolves spec:/contract: pointer targets check-todo-task-liveness # resolves TODO(task:) slugs against the queue check-docs-cmd # invoked paths + kit knobs in docs resolve check-docs-restatement-parity # needs restating pages (their code tokens held to the README beside each) check-docs-page-repeat # needs declared pages (no link target or long sentence stated twice on one) check-docs-page-length # needs declared pages and a bound (no page past the word bound) check-citation-link # needs declared pages (every section citation links its section) check-fence-command-head # every shell-fence command starts with a word that can run check-fence-run # every shell fence marked runnable runs and exits as declared check-fence-paste-unit # needs declared pages (every code block is one paste) check-knob-citation # knob values stated only in the owning SPEC check-knob-default-coupling # source knob defaults agree with the owning SPEC check-manifest-count # no bare cardinal over a governed collection check-measured-claim # needs a measured-claim oracle (marked claims re-measured) check-unmarked-claim # needs a claim-class roster (a declared class carries a marker) check-manifest-temporal # no temporal narration in manifest prose check-pendency-contradiction # no file calls one code span both pending and landed check-provenance-seam # no publisher provenance in a kit SPEC or a declared seam surface check-tracking-claim # a path's tracking status in prose agrees with git check-task-path-claim # needs task lists (a ticked task names only paths that exist) check-task-label-resolution # needs task lists and label families (a cited label resolves beside it) check-prose-enum # partial enumeration of a governed set check-md-refs # internal markdown links resolve check-md-unwrapped # needs an unwrapped markdown set (no paragraph broken across lines) check-install-claim # one declared primary install transport, led with everywhere check-payload-claim # one declared payload-disclosure class, asserted nowhere else check-spec-fence-balance # even fence counts, parsers never desync check-docs-link-convention # needs a docs site (cite-downward links) check-prose-tells # needs prose surfaces (mechanical AI-prose tells) check-prose-bounds # needs governed prose (sentence, unit and repeated-phrase bounds) check-deprecation-task # needs a deprecation-marker vocabularyThey resolve through gate-sdk’s registry path (your gates dir first, then each kit’s
checks/), and the pre-commit hook runs the precommit-tier ones their# graph:manifests trigger, read at commit.--install-hookson the gate binaryGATE_SDK_NATIVE_BINnames places both hooks in a clone once, and a gate registered later is reached with no re-install. -
Adopt the amendment lifecycle — copy
templates/SPEC-amendment.mdwhen a designed-but-unimplemented change needs a home. Name it after the feature (SPEC-<feature>.md), place it in the owning component’s directory (a governance ruling with no component lives at the repo root), and pair it with a queue entry tagged[spec: SPEC-<feature>.md]. Merge it into the canonical spec and delete it when the work completes. -
Optional — reshape the config: copy
templates/canon-config.knobsinto your gates dir and override the manifest set, the spec/amendment names, section set, the Definition-of-Done mode (exactly-one/at-most-one), the banned-heading set and density budget, the embedded-source language map, or the glossary surface list. Defaults are this repo’s layout.
Use
The lifecycle is prose discipline the gates enforce; there is no runtime tool. Author a spec so it (1) owns semantics, (2) names every contract and couples it to code by a gate, and (3) never copies a structural definition — reference the code instead. Author amendments up front; merge and delete them at build.
Test
Run this arm with the gate binary GATE_SDK_NATIVE_BIN names, where init places it. In PowerShell, spell the line ./scripts/checkwright-gates <arm> at the repository root, with .exe on native Windows:
gates="${GATE_SDK_NATIVE_BIN:-./scripts/checkwright-gates}"
"$gates" --run-gate-tests canon-kit/gate-tests canon-kit/checks
License
Licensed under Apache-2.0, with the text in LICENSE beside this file in an installed copy and at the repository root in the source tree.