feat(kit): v2.4 the gate reads structure, not prose - #20
Merged
Conversation
Adds the third layer. Rules and skills are instructions to a model that can misread them under load; a gate is a fact that exits non-zero. scripts/verify-harness.sh checks discipline rather than code: ledger integrity, every PENDING_REVIEW has a contract, skills and rules will actually load, every [GROUNDED] path in the contract exists, the diff is contained by the impact map, and RED was recorded and failed on an assertion. Contract-dependent checks skip visibly when no contract is reachable; --strict turns skips into failures. The contract form asked for "Expected RED output" — a prediction, written before anything ran, never compared to reality. That becomes recorded RED, BASELINE and GREEN blocks. A test that never failed proves nothing: it may be vacuous or already passing, and one that failed on an import error proves the test file is wrong rather than the behaviour absent. Slices without an ERD are covered by the same gate, and it tightens rather than relaxes: if you cannot write a test that fails today you do not have a falsifiable criterion, and the contract is not approvable. CI re-runs both the gate and the contract's own VERIFY block, so an agent's claim that verification passed stops mattering. One script, invoked from CI and optionally from an editor hook, never reimplemented per surface. Contracts become tracked. The review process grades a PR against its contract and CI cannot check a file it cannot see; the same invisibility hid contracts from Finder and the editor sidebar. Session state, drafts and PR bodies stay local. This also anchors the legacy .harness/ ignore rule, which was unanchored and matched skills/.harness at any depth. Adds Appendices R and S and bumps the kit to 2.3.0. Contract: skills/.harness/contracts/KIT-GATES-001.md
Two findings from the gate's own first run against this repo. Check 6 was guessing. The v2.3 patch accepted a backticked token as a path only if it contained a slash or a known extension, which silently skipped real paths like Makefile and checked things that were not paths at all. A check that silently skips is worse than one that fails loudly. It now locates the Impact map section, reads to the next heading, and takes the first cell of each marked table row. Unparseable marked rows fail; bullet-list impact maps skip visibly. That only works because the artifact is unambiguous, so the contract form now states that [GROUNDED] belongs to the impact map alone, and the Branch section example no longer carries a marker. Structure the parser can read position from, instead of prose it has to interpret. Check 10 closes the drift the ledger check already covers. FEATURES.json rot was caught; the same rot in STATE.md was invisible, since the gate only asked whether the named contract existed. An inbox entry naming a feature already PASS now fails. The first implementation of check 10 also flagged four ids that were not rot at all: an audit belonging to another repo, two pieces of planned work deliberately named, and a filename the regex matched inside. That half was noise, so it is gone; the check now fires only on ids present in the ledger and already PASS. Bumps the kit to 2.4.0. Contract: skills/.harness/contracts/KIT-GATES-002.md
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.
Summary
Adds the kit's third layer. Rules and skills are instructions to a model that can misread them under load. A gate is a fact that exits non-zero. Kit → 2.3.0.
Before this, every "gate" in the kit was self-reported:
AGENT_PROCESSasked the agent to run commands and nothing confirmed it, so an executor could setPENDING_REVIEWwithout running anything. Status drift went unnoticed four times this month across two repos.Prediction becomes recording
The contract form asked for "Expected RED output". Expected. A prediction written before anything ran, never compared to reality. It becomes three recorded blocks: RED (real command, real exit code, the assertion message, timestamp — captured before EXECUTE), BASELINE (suite before), GREEN (same commands after, counts compared).
Slices with no ERD are covered by the same gate, and it tightens rather than relaxes: without a design document each success criterion must be expressible as a failing test before work starts, or the contract is not approvable. That was already the kit's law — the RED artifact makes it executable.
scripts/verify-harness.shNine checks on discipline rather than code. The three that matter most: every
[GROUNDED]path must exist (catches invented files, the commonest contract hallucination), the diff must be contained by the impact map (undeclared files are how regressions arrive), and RED must have failed on an assertion.Contract-dependent checks skip visibly when no contract is reachable, so the script is useful mid-adoption;
--strictturns skips into failures.Criterion 2 — demonstrated, not asserted
The contract required proving the gate fails, not claiming it. Four defects injected and restored:
status: "BOGUS"status 'BOGUS' not in legendverify: "tested"verify does not look like a commandPENDING_REVIEW, no contractPENDING_REVIEW without a contract: GHOST-001rules with bad frontmatterAnd it exits 0 against harness-kit itself.
CI is the unforgeable layer
.github/workflows/harness.ymlruns the gate and re-runs the contract's own VERIFY block, so a claim that verification passed locally stops mattering. One script, invoked from CI and optionally from an editor hook — never reimplemented per surface, or the layers drift and you get a gate that passes locally and fails in CI for reasons nobody can reproduce.Contracts are now tracked
harness-review§0 tells a reviewer to grade a PR against its contract, and the contract was gitignored — invisible to the reviewer, invisible to CI, and (observed this week) invisible to the author in Finder and the editor sidebar. Checks 6–8 need to read it, so this stopped being cosmetic.Seven existing contracts land in git with this commit.
STATE.md, drafts and PR bodies stay local.This needed more than a
.gitignoreedit: the legacy rule.harness/is unanchored, so it matchedskills/.harnessat any depth and kept contracts ignored regardless of the new negation. Found withgit check-ignore -v, anchored to/.harness/— its intended root-only meaning.Deviations
The gate found a false positive in itself. On first run, check 6 reported
masterandef393c3as missing paths — branch names and commit SHAs are also backticked on[GROUNDED]lines in the Branch section. Narrowed to tokens containing/or carrying a known extension. Caught by dogfooding before shipping, which is the argument for making criterion 1 "exits 0 against this repo".And it caught the sprint that introduced it. Tracking contracts pulled six pre-existing contract files into the diff which the impact map had not declared. Scope containment reported them as undeclared and exited 1. The remedy was to amend the contract, which is the intended behaviour — not to relax the check. First live catch, on its own PR.
Q1–Q4 as executed
Contracts tracked · scope containment blocks (the remedy is amending the contract; warning-only gates get ignored) · BASELINE for behaviour changes only · CI shipped as a kit file adopted through the skill tree rather than written into a consumer's
.github/.Known limit
A vacuous test (
expect(true).toBe(true)) survives every check here. Mitigations in ascending cost: the assertion-shaped RED requirement; reviewing the test at contract approval, before EXECUTE, when changing it is cheap; and mutation testing, which is documented as an option and deliberately not a default.VERIFY
20/20 green — gate executable, POSIX-clean, exits 0 on this repo; CI present and invoking the script; "Expected RED output" gone and the recorded blocks present; never-failed and no-ERD rules stated;
AGENT_PROCESSandREVIEWwired to the same script; contracts tracked whileSTATE.mdstays ignored; 2.3.0 across README, build script and BOOTSTRAP; Appendices R and S; bootstrap regenerates;FEATURES.jsonparses.🤖 Generated with Claude Code