lifecycle-kit
The iteration stage state machine for coding-agent-assisted delivery: stage skills, an evidence file of stamps whose last stamp is the current stage, and gates that fail the commit when a stage is skipped or claimed without running its skill. The stamp grammar, the queue’s iteration header and the configurable stage roster are SPEC.md §The state machine’s.
Why: a stateless agent session doesn’t reliably re-read process prose. So the process state lives in two files a gate can read, and every stage skill stamps its invocation as its first step (mechanized by the --enter-stage <stage> arm on the gate binary GATE_SDK_NATIVE_BIN names, so the misformat-prone hand ritual is one command). That stamp is the stage transition — there is no second copy of the cursor to keep in sync, and stage motion writes no queue at all. check-stage-evidence verifies the stamp file’s grammar and that every stamp belongs to the header’s iteration; check-stage-entry verifies the predecessor stamp, the drained queue at validate entry, and, at build entry, the cross-component audit trigger and no unrun inferred-claim marker. 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.
The linear stage walk is the default; the gate-legal ways to leave it — abandon, split, reopen — compose existing mechanism with no new tooling (SPEC.md §Deviation transitions).
Install
Vendor the kit beside gate-sdk (required), then:
-
Register the gates — add to your
gates.list:check-stage-evidence check-stage-entry check-lesson-disposition check-lifecycle-registration check-stage-skill-coverage # skill-shim trio: needs the skills dir (step 3) check-skill-binding check-shim-restatement check-merge-attrs # multi-operator: needs the .gitattributes step (step 4) check-close-surfaces check-survey-record # inert until a survey is filed (--emit file-survey) check-audit-roster # inert until LIFECYCLE_KIT_AUDIT_ROSTER_FILE names a roster check-scratch-citation # no permanent surface points a reader into per-iteration scratch check-gap-inbox-neutrality # inert until a gap is filed (--emit file-gap) check-disposed-findings # inert until a drain discards a finding check-stamp-subject # commit-msg tier: a stamp commit's subject scope is its stage check-dispatch-entry # commit-msg tier: inert until a lead declares a dispatch (--enter-stage --dispatch)They resolve through gate-sdk’s registry path (your gates dir first, then each kit’s
checks/), and the hooks run those their# graph:manifests trigger, read at commit (check-stamp-subjectandcheck-dispatch-entryin the commit-msg hook).--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. -
Give the queue file its header and each evidence file its skeleton — the stage-stamp file and the lesson-disposition file (
LIFECYCLE_KIT_LESSON_EVIDENCE_FILE, both boundary-reset to their header). The queue header line:## Iteration: —The stage-stamp skeleton:
# contract: lifecycle-kit/SPEC.md §check-stage-evidence ---The lesson-disposition skeleton:
# contract: lifecycle-kit/SPEC.md §check-lesson-disposition -
Adopt
templates/stages/*.mdin your agent-skill directory (e.g..claude/commands/): by default make each skill a binding shim that references the template (SPEC.md §templates/stages/) — it tracks the kit, so a re-vendor reaches it and the shim gates hold it thin. Or, as the sanctioned fork, copy each in and fill its named slots (*<slot-name: …>*) with your project’s ritual — you then own the ritual prose, upgrades don’t reach it, and the shim gates don’t cover it (kept for legitimate structural divergence). -
Point your always-loaded agent file at the machine — run
--install-lifecycleon the gate binaryGATE_SDK_NATIVE_BINnames. It writes a marker-bounded registration block (the state machine, the stage roster as skill invocations, the SPEC link) into the fileLIFECYCLE_KIT_AGENT_FILEnames, the roster derived from your config so a reshape (step 5) flows in on a re-run.check-lifecycle-registration(step 1) holds the block in lockstep. The same run also writes the merge-attribute block into.gitattributes— amerge=iteration-scopedline per per-iteration state surface (these resolve to the arriving branch at a merge — SPEC.md §Multi-operator semantics) and amerge=unionline for each committed inbox (their append-only bullets must survive a concurrent merge — SPEC.md §The committed gap inbox, §The consult inbox) — and registers the keep-ours driver in your clone’s git config (per-clone, the--install-hooksopt-in class; the git-native union driver needs no such step).check-merge-attrs(step 1) holds the block in parity with the derived supersede and union sets. -
Optional — narrow the hand-edit window: register the gate binary
GATE_SDK_NATIVE_BINnames, under<project-dir>, as thecommandof aPreToolUse(Write|Edit)hook, with--hook workflow-state-guardas itsargs(guard-kit’stemplates/settings-hooks.jsoncarries the block, with<project-dir>, your harness’s project-directory variable, spelled for Claude Code, and the binary as a placeholder its note says how to replace). It refuses an agent write to the stage-stamp file, whose only sanctioned writer is the--enter-stagearm — the gates that would catch a hand-stamp all fire at commit, and an uncommitted one moves the cursor for a whole session (SPEC.md §check-stage-evidence). WithLIFECYCLE_KIT_STAGE_SESSION_TYPESset, it also refuses a dispatched stage session’s write before that session’s stamp, and its write outside the scratch dir once the cursor has left its stage. Requires guard-kit vendored. -
Optional — reshape the machine: copy
templates/lifecycle-config.knobsinto your gates dir and set stages, predecessors, drain/audit stages, section names, or file paths, oneNAME = valueorNAME[] = elementline each. Defaults are this repo’s own lifecycle;--emit knob-rosteron the gate binaryGATE_SDK_NATIVE_BINnames prints them.
After install the battery is red at check-stage-evidence until your first /scope session runs (it names the iteration and stamps the evidence file as its first step) — the bootstrap header is a stage like any other, fail-closed by design.
Use
Run these arms with the gate binary GATE_SDK_NATIVE_BIN names, where init places it. In PowerShell, spell each line ./scripts/checkwright-gates <arm> at the repository root, with .exe on native Windows:
gates="${GATE_SDK_NATIVE_BIN:-./scripts/checkwright-gates}"
"$gates" --enter-stage <stage> # stamp a stage entry (the transition itself)
"$gates" --install-lifecycle # (re)write the registration and merge-attribute blocks
"$gates" --emit file-gap "<gap>" # route a work-shaped finding to the gap inbox
"$gates" --emit file-consult "<item>" # route a ruling to reconsider or a request for advice to the consult inbox
"$gates" --emit consult-count # one line counting the consult inbox, nothing when it is empty
"$gates" --emit file-survey "<question>" "<corpus>" "<oracle>" "<inferred>" "<finding>"
"$gates" --emit journal "<finding>" # append to the resume journal of the stage you entered
"$gates" --emit journal --lead "<finding>" # a lead session: append to the lead journal its opener opened
"$gates" --emit cite-survey "<heading-substring>" # one carried survey, inline-ready
"$gates" --emit stage-contract <stage> # a stage's contract for a reader with no skill and no write path
"$gates" --emit session-id # the canonical stamp id, by the derivation order
"$gates" --emit ruling-staleness ["<ruling name>"…] # fired conditions, undeclared ones, citing sites
--emit session-id is SPEC.md §bin/session-id.sh’s derivation order, which --enter-stage reads for you: reach for it directly only where a session writes an id itself, as templates/lead.md’s session-role marker step does. It takes no argument and resolves no knob. The front-end route reads the cwd bin/run-gates.sh cds to — the git toplevel — so a caller standing elsewhere whose sessions dir is the cwd-slugged default invokes the binary’s --emit-session-id arm directly instead, which is what --enter-stage does.
The two survey arms are the capture and citation affordances of SPEC.md §The survey record. -- ends option processing for either, and a positional beginning with - without it, --help included, is a refusal that prints the arm’s usage at exit 2 (gate-sdk/SPEC.md §The bin/-tool contract).
Test
Run this arm the same way:
gates="${GATE_SDK_NATIVE_BIN:-./scripts/checkwright-gates}"
"$gates" --run-gate-tests lifecycle-kit/gate-tests lifecycle-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.