| name | Accept |
| description | The boundary ritual — review what just landed, record an approval, journal it, and advance the phase. The ONLY step that writes approvals, and it does NO git. |
| argument-hint | [phase] [--force] [--exclude <item>] |
Accept — The Boundary Ritual
Accept fires after every pipeline step. It is the only step that writes approval records — every other step reads them. It reviews what just happened, records a disposition, writes a journal entry, and advances the phase in project-state.md.
Accept does NO git. No commit, no push, no PR, no branch operations. Git lives entirely in /genesis-closure. This separation is load-bearing: Accept records what landed; Closure moves what landed. If Accept committed, uncommitted work could masquerade as approved.
Inference
Accept infers what it is approving from context — the most recent un-approved artifact — so it usually needs no argument. Always print an inference trace so the decision is explainable:
Approving: {phase} — most recent un-approved action in {file}
If a phase is given as an argument, approve that phase explicitly.
Routing — which file gets written
Two approval layers live under .genesis/features/{feature}/approvals/:
master.json — spec-level and feature-level phases (brainstorm, design, specify, clarify, northstar, group-accept, final audits, review).
group-N.json — per-group work (the micro specs for group N, each spec's implementation, and the per-group audits A1–A5).
| Phase being approved | Target file | Recorded phase |
|---|
| brainstorm / design / specify / clarify / northstar | master.json | brainstorm / design / … |
| micro specs for group N | group-N.json | micro |
| implement spec | group-N.json | implement-{spec-id} |
| audit AX for group N | group-N.json | audit-aX |
| group accept for group N | master.json | group-accept (with group: N) |
| final audit FX | master.json | audit-fX |
| feature review | master.json | review |
Rule of thumb: spec-level phases → master.json; per-spec implementation and per-group audits → group-N.json; group-accept closes the group but is itself a spec-level gate, so it writes to master.json.
What Accept checks before approving
1. Clean working tree
Before recording anything, verify the tree is clean:
git diff --quiet # no unstaged changes
git diff --cached --quiet # no staged-but-uncommitted changes
If either reports changes, refuse:
Cannot accept — working tree is dirty.
{N} files with unstaged changes, {M} files staged but uncommitted.
Accept records what landed. A dirty tree means uncommitted work is not
captured by the commit you are about to approve. Commit or stash first,
then re-run accept.
Override: --force (records the variance in the approval note).
This is the central guardrail and it is enforced by this skill itself — there is no external daemon. The rationale is the Accept/Closure split: if the tree is dirty, the thing you are approving is not what is actually committed.
2. Quality gates
If the constitution defines quality gates, run them — typically lint and tests (and a type-check or build where applicable) — and record each result. A failing gate does not auto-block: record it as fail in the gates field and let the user decide. With --force, note the failure and proceed. If the constitution defines no gates, gates is null.
3. Group-accept completeness
For a group-level accept, all in-scope audit types (A1–A5) must show clean passes in group-N.json before the group can close.
4. The Standard (rejection-default posture)
Accept does not ask "is this good enough to pass?" It asks "is there any reason NOT to accept?" The default is rejection; approval is earned by actively disproving each reason:
| # | Rejection reason | How to disprove it |
|---|
| 1 | Incomplete implementation | every file operation in the spec is satisfied |
| 2 | Failing quality gates | all constitution gates pass |
| 3 | Unresolved audit findings | zero open findings from A1–A5 (or the final audits at feature scope) |
| 4 | Missing acceptance criteria | every AC in the spec is checked |
| 5 | Drift from the North Star | implementation aligns with the stated direction |
| 6 | Undocumented decisions | key decisions are recorded in the journal / decision log |
If any reason cannot be disproven, return revise naming the specific unmet criterion. The default holds.
The approval record
Append a record to the flat JSON array in the target file:
{
"phase": "implement-spec-3",
"version": "1.0",
"status": "approved",
"disposition": "pass",
"timestamp": "2026-06-18T14:32:00Z",
"approvedBy": "user",
"gates": { "lint": "pass", "tests": "pass" },
"group": null,
"scope": null,
"note": "",
"conviction": null,
"exclusions": []
}
| Field | Meaning |
|---|
phase | what was approved (from the routing table) |
version | record schema version ("1.0") |
status | derived from disposition (mapping below) |
disposition | the verdict: pass | revise | conditional | reject |
timestamp | ISO 8601 |
approvedBy | who approved (e.g. "user") |
gates | { "lint": "pass"|"fail", "tests": "pass"|"fail" }, or null if no gates defined |
group | group number for group-scoped records; null otherwise |
scope | optional finer scope (a spec id/title) or null |
note | free text — findings reference, conditions, or a recorded variance |
conviction | integer 0–100 for audit phases; null for non-audit phases |
exclusions | items excluded under a conditional accept |
Disposition → status:
| Disposition | status | Behavior |
|---|
pass | approved | advance to next phase |
revise | revise | return to the previous stage; note must reference findings |
conditional | conditional | advance with documented exceptions; exclusions populated |
reject | rejected | return to an earlier phase; note must give the reason |
Skipped stage — when a stage is deliberately skipped, carry the justification rather than silently omitting it:
"variance": { "skippedStage": "clarify", "reason": "spec is trivial, no open questions" }
The clean-tree override (--force)
--force proceeds past a dirty tree or a failing gate. There is no enforcement daemon — the override is simply a recorded variance in the note field:
clean-tree override — 2 dirty files at accept time: src/foo.ts, README.md
The legitimate use case is parallel work: a second editing session can make the tree look dirty to the one running Accept. The override closes the loop while the note keeps the trail honest. Without --force, Accept exits before writing anything.
Conviction
Conviction is an integer (0–100) attached to audit-phase approvals only — how confident the review is that the work is genuinely ready, not merely that no findings are open.
- Applies only to audit phases (A1–A5, final audits, feature review). Other phases leave
conviction: null.
- Computed as the mean conviction across all findings in scope (each audit finding carries its own score). Zero findings ⇒ conviction 100.
- An optional
.genesis/features/{feature}/conviction/policy.yaml defines thresholds. If absent, skip this step entirely (graceful degradation):
| Mean conviction | Behavior |
|---|
| ≥ auto-pass (default 80) | recommend pass; proceed, record the score |
| prompt ≤ … < auto-pass (default 60–79) | show breakdown, recommend reviewing low-conviction findings, ask before proceeding |
| < stop (default 60) | stop; list the lowest-conviction findings; require explicit --force |
When prompting or stopping, show a per-audit breakdown:
Conviction Breakdown:
A1 (design+master): 3 findings, mean 88 [OK]
A2 (spec review): 2 findings, mean 72 [REVIEW]
A3 (polish): 0 findings [CLEAN]
A4 (north star): 1 finding, mean 65 [LOW]
A5 (web): 0 findings [CLEAN]
Aggregate: 76 (below auto-pass threshold of 80)
Journal
After recording, write a plain markdown entry to .genesis/features/{feature}/journal/{date}_{time}.md:
---
feature: "{feature}"
phase: "{phase}"
scope: "{group/spec if applicable}"
date: "{ISO date}"
---
## {Phase}: {Feature}
{2–3 sentence summary of what was done}
### Decisions
- {key decision made during this phase}
### Next
{what comes next in the pipeline}
The journal is the durable record of why. It is written here, never by an automatic hook.
Advance the phase
After journaling, update project-state.md and present the next pipeline action:
- brainstorm → feature doc / specify · specify → clarify · clarify → northstar · northstar → first group's micro specs
- micro group N → next group's micro specs (if more) or implement (when all groups are written)
- implement spec → next spec, or A1 when the group's specs are done
- audit AX clean → next audit type, or group-accept after A5 is clean
- group-accept → if all groups are now accepted, the mandatory next step is F1 (never skip straight to closure); otherwise run group closure (push + PR) and move to the next group
- final audits run F1 → F2 → … in sequence; after the last, feature review, then the final closure PR
Disposition routing: revise re-runs the stage sent back; reject re-runs from an earlier phase; conditional advances like pass but exclusions stay visible.
Finally, scan the accepted artifact for actionable ideas and ingest them into the furnace (see /genesis-brainstorm and docs/concepts.md): update a matching F-NNN entry, or append a new one with status: seed.
Natural language triggers
- "accept"
- "approve this"
- "looks good, advance"
- "lock it in"