Skip to content

Kit v2.5 — contracts stay local, CI checks only what it owns - #21

Merged
David405 merged 1 commit into
masterfrom
feat/kit-adopt-001-local-contracts
Aug 29, 2026
Merged

Kit v2.5 — contracts stay local, CI checks only what it owns#21
David405 merged 1 commit into
masterfrom
feat/kit-adopt-001-local-contracts

Conversation

@David405

Copy link
Copy Markdown
Owner

Kit v2.5 — contracts stay local, CI checks only what it owns

Reverses the v2.3 trade. v2.3 tracked contracts so CI could grade a PR against one, and had CI
re-run the contract's VERIFY block. Both are removed here. skills/.harness/ is working state,
and the review gate is a person reading this PR body, not a machine reading the repo.

Also fixes the two adoption defects found when v2.4 was added to a fresh repo for real.

What changed

Area Change
.gitignore Blanket skills/.harness/ ignore restored; the /.harness/ root-anchoring fix from v2.3 kept. Eight contracts out of the index, still on disk
.github/workflows/harness.yml No pull_request.body read, no contract execution. Ends with a What this run did not cover step (if: always())
scripts/verify-harness.sh Check 5 finds rules in rules/.cursor/rules/.agents/rules/ and reports which. Checks 6–8 skip with a stated reason
scripts/setup-harness-kit.sh Warns when AGENTS.md is absent — names the consequence and the fix
skills/sprint-contract/ PR body carries the contract + local gate output. No tool attribution anywhere in a PR or commit
rules/no-stage-harness-files.mdc Commit authorship — author and committer are the human. Rules budget stays at six
skills/harness-review/templates/REVIEW.md Step 0: read the contract from the PR body
Version 2.5.0, changelog, BOOTSTRAP.md regenerated, KIT-ADOPT-001 in the ledger

What this costs, stated plainly

A careless or determined agent can paste gate output that does not match what it ran. That is now
caught by a person reading this PR, not by a machine. In exchange, an entire class of CI attack
surface — executing text authored in a pull request — is gone.

Local gate output (verbatim)

harness verify
  PASS  FEATURES.json: parses, statuses legal, verify fields runnable
  PASS  every PENDING_REVIEW feature has a contract file
  PASS  STATE.md current contract exists (skills/.harness/contracts/KIT-ADOPT-001.md)
  PASS  skills: frontmatter valid (retrievable)
  PASS  rules: frontmatter valid, will load (from rules)
  PASS  contract impact map: 20 [GROUNDED] path(s) verified
  PASS  diff is contained by the contract impact map
  PASS  RED: recorded and failed on an assertion
  PASS  STATE inbox: inbox references only open work
  PASS  on a feature branch (feat/kit-adopt-001-local-contracts)

harness verify: green (0 skipped)

Fresh-repo adoption, re-run against this branch (verbatim)

No AGENTS.md present — defect 2:

harness-kit: linked 6 rules into .cursor/rules
warn: no AGENTS.md yet, so rules were NOT assembled into it.
      Agents without a rules feature will receive no rules.
      Fix: run the harness-onboard skill to create AGENTS.md, then re-run this script.
harness-kit: linked 8 skills into .agents/skills

With AGENTS.md present, re-run → harness-kit: assembled rules into AGENTS.md (block at lines
5–153); a third run leaves exactly one marker pair.

Gate run from the consumer root — defect 3:

  PASS  rules: frontmatter valid, will load (from .cursor/rules)
  SKIP  contract impact map (contract is local — run this before pushing; a human reviews the output)
  SKIP  scope containment (contract is local — run before pushing)
  SKIP  RED artifact (contract is local — run before pushing)

v2.4 printed SKIP no rules directory here.

Reviewer, please confirm

  1. The contract below matches the diff — scope WILL / will NOT, and the impact map against git diff --stat.
  2. The gate output above is what this branch actually produces (re-run it; it is one command).
  3. Nothing in the diff, the commit message, or this body carries tool attribution.
  4. git log --format='%an|%cn' on this branch shows a person in both fields.

CI does not check 1–4. That is the point of this change.


SPRINT CONTRACT — KIT-ADOPT-001: contracts stay local, CI checks only what it owns, adoption defects

Status: PENDING_REVIEW — approved by David 2026-08-29; EXECUTE + VERIFY complete.
Feature ID: KIT-ADOPT-001
Repo: harness-kit only
Branch: proposed feat/kit-adopt-001-local-contracts from master @ 204d65c (v2.4).
Version → 2.5.0.
Trigger: David (2026-08-29) — contracts stay gitignored; and "this process ideally should be manually
reviewed by the human rather than relying on the machine."


Work-type profile (required)

  • ops-docs

Languages / toolchain: POSIX sh, GitHub Actions YAML, Markdown. No application code.


The correction this sprint applies

v2.3 pushed enforcement as far as it would go: CI re-running the contract's VERIFY block, contracts
tracked so CI could read them, the machine as the unforgeable layer. David has pulled that back.
The human review is the control. The machine handles what is cheap and mechanical, and says plainly
what it did not check.

Three consequences, and the third is the important one:

  1. Contracts return to local working state. Eight files come out of the index.
  2. CI stops trying to read a contract at all — no PR-body extraction, no execution of anything
    authored in a PR body.
    The threat model that came with that idea disappears with it.
  3. Checks 6–8 (grounded paths, scope containment, RED recorded) remain valuable and local. The agent
    runs them before pushing; their output goes in the PR body; a human reads it. They are not weaker
    because CI does not repeat them — they are differently placed.

What this costs, stated honestly: a determined or careless agent can paste gate output that does
not match what it ran. That is now caught by a person reading the PR, not by a machine. For a team this
size that is a reasonable trade, and it removes an entire class of CI attack surface.


Decisions

Topic Decision Status
Contracts in git No. Local working state; revert the v2.3 tracking Locked (David)
CI reading the PR body No. Not parsed, not executed. Nothing authored in a PR body reaches the runner Locked (David)
CI scope Only what lives in the repo: ledger validity, skills and rules frontmatter, branch discipline, STATE.md inbox Locked
Checks 6–8 Local, before push. Skip in CI with a stated reason, never a silent one Locked
PR body Carries the contract for the human reviewer, not for a machine Locked
Honesty of a reduced run CI prints which checks it ran and which it cannot, so a partial run never reads as a full one Locked
Defects 2 and 3 Fixed here Locked

Context — the three adoption defects

Adding v2.4 as a submodule to a fresh repo and running setup, for real:

# Defect Evidence
1 Setup writes a blanket skills/.harness/ ignore into the consumer git check-ignore reported a consumer contract ignored. Now correct — the defect was the kit disagreeing with itself, and the decision above resolves it
2 Rules assembly silently no-ops on a fresh repo scripts/setup-harness-kit.sh:119 guards on [ -f AGENTS.md ]. A new repo has none, so nothing assembles and nothing warns. harness-onboard creates it afterwards, so the block never appears unless setup is re-run
3 Check 5 never fires in a consumer scripts/verify-harness.sh:112 tests [ -d rules ]. Rules live in harness-kit/rules/, symlinked to .cursor/rules/. Printed SKIP no rules directory

Shared cause: both were written against harness-kit's own layout, where everything sits at the root.


Scope — WILL do

A — Contracts return to local working state

  1. .gitignore — remove the !skills/.harness/contracts negations; restore the blanket ignore. Keep
    the /.harness/ anchoring fix from v2.3 — that was a separate, correct bug fix.
  2. git rm --cached the eight tracked contracts. Files stay on disk.
  3. verify-harness.sh — checks 6–8 skip with
    (contract is local — run this before pushing; a human reviews the output), not a bare skip.

B — CI does less, and says so

  1. .github/workflows/harness.ymlremove the contract VERIFY step. CI runs
    verify-harness.sh and nothing else.
  2. CI prints a closing line naming what it did not cover: contract-dependent checks are local, and
    the reviewer confirms them from the PR body.
  3. Delete the threat model this file previously needed. No untrusted input reaches the runner.

C — The PR body carries the contract, for a person

  1. sprint-contract skill and form — the PR body includes the contract and the local gate output.
    Reason stated: a reviewer cannot see a gitignored file, and harness-review §0 grades against it.
    7b. No tool attribution in a PR title, body or commit message — no "generated with", "made with/by",
    no assistant or editor name, no Co-Authored-By trailer. The PR describes the change; who or what
    typed it is not part of the record. Stated in the skill and the form.

    Placement, per rules/README.md: this applies only while writing a PR body, so by the kit's own
    ordering it belongs in the skill that owns that task, not in a rule. The rules budget is six and a
    seventh would have to displace one — this does not earn that.

7c. Commit authorship — extend the existing no-stage-harness-files rule, which already governs
staging and committing, with: when a commit is made, its author and committer are the human.
Never a tool, assistant, editor or bot identity, and no attribution trailer in the body. Unlike 7b
this is not task-scoped — it holds on every commit in any context — so it belongs in a rule, and
extending an existing one keeps the budget at six.

Verified before writing: across all branches, author and committer are already a person on every
commit. This records the convention rather than changing behaviour.
8. harness-review §0 — the reviewer reads the contract from the PR body and confirms the pasted
gate output. Machine confirmation is explicitly not expected.

D — Adoption defects

  1. setup-harness-kit.sh — when AGENTS.md is absent, warn loudly: name the consequence (agents
    without a rules feature receive no rules) and the fix (harness-onboard, then re-run setup).
  2. verify-harness.sh check 5 — look for rules in rules/, else .cursor/rules/, else the merge dir;
    report which was found. Skip only when none exists.

E — Version + ledger

  1. 2.5.0, changelog, FEATURES.json entry, bootstrap regenerated.

Scope — will NOT do

  • Re-open whether contracts are tracked, or whether CI reads PR bodies. Both decided.
  • Any new check. This sprint removes machine scope.
  • Adopt into a real repo — that is next, after this.
  • Changes to rules, skills, ERD or audit work.

Branch

  • Base: master @ 204d65c (v2.4)
  • Proposed: feat/kit-adopt-001-local-contracts
  • Human confirmed: pending.

RED (recorded before EXECUTE)

  • Command: test "$(git ls-tree -r --name-only origin/master | grep -c '\.harness/contracts')" -eq 0; grep -q 'Contract VERIFY block' .github/workflows/harness.yml
  • Exit code: 1
  • Failure reason: assertion — expected 0 tracked contracts, found 8; the workflow still
    contains the Contract VERIFY block step this sprint removes. Setup still guards assembly on
    [ -f AGENTS.md ] (setup-harness-kit.sh:119); check 5 still tests [ -d rules ]
    (verify-harness.sh:112).
  • Captured: 2026-08-29, before any edit on this branch

Behavioural RED, demonstrated: v2.4 added as a submodule to a fresh repo and setup run. 8 skills and
6 rules linked; no AGENTS.md rules block, silently; consumer contract reported ignored; gate
printed SKIP no rules directory and 8 skips.

BASELINE./scripts/verify-harness.sh on master @ 204d65c: exit 0, 10 checks.

GREEN (recorded 2026-08-29, after EXECUTE)

  • Command: git ls-files | grep -c '\.harness/contracts'0. ls skills/.harness/contracts/*.md | wc -l9 (the eight plus this contract). git check-ignore -v attributes the ignore to .gitignore:23 skills/.harness/.

  • Workflow: no pull_request.body, no contract execution. The only occurrence of "VERIFY block" is inside the did-not-cover notice naming what CI deliberately skips.

  • CI honesty: .github/workflows/harness.yml:25What this run did not cover, if: always().

  • Fresh-repo adoption (re-run against this branch, throwaway repo, no AGENTS.md):

    harness-kit: linked 6 rules into .cursor/rules
    warn: no AGENTS.md yet, so rules were NOT assembled into it.
          Agents without a rules feature will receive no rules.
          Fix: run the harness-onboard skill to create AGENTS.md, then re-run this script.
    harness-kit: linked 8 skills into .agents/skills
    

    Then with AGENTS.md present, re-run → harness-kit: assembled rules into AGENTS.md; block at
    lines 5–153; a third run leaves exactly one marker pair (idempotent). Defect 2 fixed.

  • Gate from the consumer root: PASS rules: frontmatter valid, will load (from .cursor/rules)
    v2.4 printed SKIP no rules directory. Defect 3 fixed. Checks 6–8 there read
    SKIP contract impact map (contract is local — run this before pushing; a human reviews the output).

  • Gate here: ./scripts/verify-harness.shexit 0, 10 PASS, 0 skipped.

  • Ledger verify field for KIT-ADOPT-001: exit 0.

  • Found by the gate during this sprint: the eight git rm --cached deletions were absent from the
    impact map. The contract was amended to declare them — the check was not relaxed. Related weakness,
    logged as a candidate rather than fixed here: check 7 diffs base...HEAD, so before the work is
    committed it compares HEAD to itself and prints a vacuous PASS. By the kit's own v2.4 reasoning
    a check that cannot see anything should say so, not pass.

  • Rules count: ls rules/*.mdc | wc -l6. Budget intact.

  • Version: 2.5.0 in scripts/build-bootstrap.sh, README.md (Kit v2.5), and regenerated
    BOOTSTRAP.md (4 occurrences). FEATURES.json parses.


Impact map

Path Change Marker
.gitignore Restore blanket ignore; keep the /.harness/ anchor [GROUNDED]
scripts/verify-harness.sh Check 5 consumer-aware; 6–8 skip with a stated reason [GROUNDED]
scripts/setup-harness-kit.sh Warn when AGENTS.md is absent [GROUNDED]
.github/workflows/harness.yml Drop the contract VERIFY step; print uncovered scope [GROUNDED]
skills/sprint-contract/templates/SPRINT_CONTRACT.md PR body carries contract + local gate output [GROUNDED]
skills/harness-review/templates/REVIEW.md Reviewer reads the contract from the PR body; flags tool attribution [GROUNDED]
skills/sprint-contract/SKILL.md PR body instructions incl. no tool attribution [GROUNDED]
rules/no-stage-harness-files.mdc Commit authorship: author and committer are the human [GROUNDED]
scripts/build-bootstrap.sh 2.5.0 + changelog [GROUNDED]
BOOTSTRAP.md Regenerated [GROUNDED]
FEATURES.json Add KIT-ADOPT-001 [GROUNDED]
README.md Version; what CI does and does not cover [GROUNDED]
skills/.harness/contracts/KIT-V13-001.md Deleted from the index (stays on disk) [GROUNDED]
skills/.harness/contracts/KIT-QUALITY-001.md Deleted from the index (stays on disk) [GROUNDED]
skills/.harness/contracts/KIT-AUDIT-001.md Deleted from the index (stays on disk) [GROUNDED]
skills/.harness/contracts/KIT-SKILLS-001.md Deleted from the index (stays on disk) [GROUNDED]
skills/.harness/contracts/KIT-ERD-001.md Deleted from the index (stays on disk) [GROUNDED]
skills/.harness/contracts/KIT-RULES-001.md Deleted from the index (stays on disk) [GROUNDED]
skills/.harness/contracts/KIT-GATES-001.md Deleted from the index (stays on disk) [GROUNDED]
skills/.harness/contracts/KIT-GATES-002.md Deleted from the index (stays on disk) [GROUNDED]

Success criteria

  1. git ls-files | grep -c '.harness/contracts'0; all eight files still on disk.
  2. Checks 6–8 skip with a message naming why and where they belong.
  3. The workflow contains no reference to pull_request.body and no contract execution.
  4. CI output states which checks it could not cover.
  5. Fresh-repo adoption warns when AGENTS.md is absent; re-running after harness-onboard assembles the block. Demonstrated.
  6. Check 5 finds rules via .cursor/rules in a consumer layout. Demonstrated.
  7. harness-review §0 instructs reading the contract from the PR body.
    7b. The sprint-contract skill and form forbid tool attribution in PR titles, bodies and commit messages; harness-review treats it as a finding.
    7c. no-stage-harness-files states that a commit's author and committer are the human, never a tool identity. Rules count stays at six.
  8. 2.5.0 everywhere; bootstrap regenerates; FEATURES.json parses; diff confined to the impact map.

Quality gates (tick or N/A)

  • Falsifiable success criteria — 1, 3, 5, 6 are executable
  • Trust-boundary — N/A by design: this sprint removes the only path by which untrusted input reached CI
  • Partial/optional deps — CI states its own coverage
  • Code-quality / solidity — N/A (ops-docs)

Edge cases / failure modes

Risk Mitigation
Pasted gate output does not match what was run Accepted. A person reads the PR. This is the trade the decision makes
A reduced CI run reads as a full one Criterion 4: CI names what it did not cover
Contract block bloats PR bodies Accepted cost of keeping contracts local
Consumer has no .cursor/ Check 5 skips with a named reason rather than failing
Someone later re-adds machine enforcement by reflex The decision and its reasoning are recorded here

Threat model

SKIP — and that is the point. Removing the PR-body read removes the only untrusted input the kit's
CI ever handled.

Blocking questions

None. Both open questions from the previous draft are closed by the decision: CI does not read PR
bodies, so there is nothing to execute and nothing to guard. The eight contracts are untracked going
forward rather than removed from history — they are process documents, already public in this repo.


VERIFY (run after EXECUTE)

cd "$HOME/mnt/harness-kit"

# contracts local again, not lost
test "$(git ls-files | grep -c '.harness/contracts')" -eq 0
test "$(ls skills/.harness/contracts/*.md | wc -l)" -ge 8

# CI reads nothing authored in a PR
! grep -q 'pull_request.body' .github/workflows/harness.yml
! grep -q 'Contract VERIFY block' .github/workflows/harness.yml
grep -qi 'not cover' .github/workflows/harness.yml

# local checks say where they belong
grep -qi 'contract is local' scripts/verify-harness.sh

# review reads the contract from the PR
grep -qi 'PR body' skills/harness-review/templates/REVIEW.md
grep -qi 'PR body' skills/sprint-contract/templates/SPRINT_CONTRACT.md

# no tool attribution, anywhere it could leak
grep -qi 'attribution' skills/sprint-contract/templates/SPRINT_CONTRACT.md
grep -qi 'author and committer are the human' rules/no-stage-harness-files.mdc
test "$(ls rules/*.mdc | wc -l)" -eq 6
! grep -rIlq 'Generated with\|made with\|Co-Authored-By' skills/.harness/PR-*.md 2>/dev/null

# adoption defects
grep -qi 'harness-onboard' scripts/setup-harness-kit.sh
grep -q 'cursor/rules' scripts/verify-harness.sh

./scripts/verify-harness.sh
sh -n scripts/verify-harness.sh && sh -n scripts/setup-harness-kit.sh
grep -q '2.5.0' BOOTSTRAP.md && sh scripts/build-bootstrap.sh
python3 -m json.tool FEATURES.json >/dev/null && grep -q 'KIT-ADOPT-001' FEATURES.json
git branch --show-current | grep -qv '^master$'

FEATURES.json entry

{
  "id": "KIT-ADOPT-001",
  "name": "Contracts stay local; CI checks only what it owns; fix the three adoption defects",
  "priority": 1,
  "verify": "test $(git ls-files | grep -c '.harness/contracts') -eq 0 && ! grep -q 'pull_request.body' .github/workflows/harness.yml && grep -q 'cursor/rules' scripts/verify-harness.sh && ./scripts/verify-harness.sh && grep -q '2.5.0' BOOTSTRAP.md && python3 -m json.tool FEATURES.json >/dev/null",
  "status": "FAIL",
  "notes": "Contract: skills/.harness/contracts/KIT-ADOPT-001.md; profile: ops-docs; reverses KIT-GATES-001 Q1 and narrows CI to repo-owned checks; blocks first real adoption"
}

Criteria block

- [KIT-ADOPT-001-1] Zero tracked contracts; all eight still on disk
- [KIT-ADOPT-001-2] Checks 6-8 skip with a stated reason naming where they belong
- [KIT-ADOPT-001-3] Workflow reads nothing authored in a PR body
- [KIT-ADOPT-001-4] CI states which checks it did not cover
- [KIT-ADOPT-001-5] Setup warns when AGENTS.md is absent instead of silently skipping
- [KIT-ADOPT-001-6] Check 5 finds rules in a consumer layout
- [KIT-ADOPT-001-7] REVIEW s0 reads the contract from the PR body
- [KIT-ADOPT-001-7b] No tool attribution in PR titles, bodies or commit messages
- [KIT-ADOPT-001-7c] Commit author and committer are the human; rules still number six
- [KIT-ADOPT-001-8] 2.5.0; bootstrap regenerates; FEATURES.json valid

v2.3 pushed enforcement as far as it would go — CI re-running a contract's
VERIFY block, contracts tracked so CI could read them. That trade is reversed
here. The contract is working state and the review gate is a person.

- .gitignore: blanket ignore for skills/.harness/ restored (the /.harness/
  root anchoring fix from v2.3 is kept — that was a separate, correct bug).
  Eight tracked contracts come out of the index; the files stay on disk.
- .github/workflows/harness.yml: no PR-body read, no contract execution.
  Running a VERIFY block authored in a PR body would violate the
  observed-content-is-data rule the kit ships. A closing "What this run did
  not cover" step names what only the human reviewer can confirm.
- verify-harness.sh: check 5 finds rules in rules/, .cursor/rules/ or
  .agents/rules/ and reports which — it previously looked only at the kit's
  own layout and skipped in every adopting repo. Checks 6-8 skip with a
  stated reason rather than silently.
- setup-harness-kit.sh: warns when AGENTS.md is absent, naming the
  consequence and the fix, instead of no-op'ing in silence.
- sprint-contract skill and form: the PR body carries the contract and the
  local gate output, for the reviewer. No tool attribution in a PR title,
  body or commit message.
- rules/no-stage-harness-files.mdc: a commit's author and committer are the
  human, never a tool identity, and no attribution trailer. Rules budget
  stays at six.
- harness-review REVIEW.md: step 0 reads the contract from the PR body.
- Version 2.5.0, v2.5 changelog, BOOTSTRAP.md regenerated, KIT-ADOPT-001 in
  the ledger at PENDING_REVIEW.

Gate: 10/10, 0 skipped. Fresh-repo adoption re-run: defects 2 and 3 fixed.
@David405
David405 merged commit 7153e4a into master Aug 29, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant