From 08bc2aa02773b95d41d0eed5d53715d8e1b9188c Mon Sep 17 00:00:00 2001 From: Brummel Date: Thu, 2 Jul 2026 11:35:06 +0200 Subject: [PATCH] refactor(pipeline): specs/plans are gitignored working files, never committed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per-cycle specs and plans stop being git-tracked commit-then-git-rm artefacts and become git-ignored working files: created on disk for the active cycle, read across sessions from the working tree, and shell-rm'd at cycle close by audit. Nothing is committed, so there is no git-history copy — the durable record of a cycle's intent is the design ledger only, and no durable artefact (code, test, doc, ledger) may cite a spec/plan by number or path. - conventions/pipeline/design/README: invert the git-tracked -> git-rm -> git-history-recovery model to gitignored -> shell-rm -> ledger-only. - naming: drop the NNNN file counter; files are slug.md (fieldtest specs keep a fieldtest- prefix as the cycle-close discriminator). - cycle number: separated from the (now-gone) file number, sourced from the feat(NNNN)/audit(NNNN) commit subjects, which cycle commits carry. - specify/planner/fieldtest/fieldtester: no commit step; fieldtest splits fixtures (committed as code) from its spec (gitignored), with the cross-cycle rule that a fieldtest- spec belongs to the next cycle. - boss: auto-sign auditability moves from the (boss-signed) commit subject to the run's reference issue; rollback reverts only code. - audit: new Step 5 shell-rm's the cycle spec+plan after the architect reads them, sparing fieldtest- specs. Companion machine config (outside this repo): the global git excludes (~/.config/git/ignore) gains docs/specs/ and docs/plans/ so the ignore applies to every project at once. --- README.md | 11 +++-- audit/SKILL.md | 27 +++++++++++- boss/SKILL.md | 32 +++++++++------ docs/conventions.md | 73 ++++++++++++++++++++++----------- docs/design.md | 12 +++--- docs/pipeline.md | 28 ++++++++----- fieldtest/SKILL.md | 15 +++++-- fieldtest/agents/fieldtester.md | 17 ++++---- planner/SKILL.md | 17 ++++---- specify/SKILL.md | 58 ++++++++++++++------------ 10 files changed, 185 insertions(+), 105 deletions(-) diff --git a/README.md b/README.md index ab09e67..f48e77f 100644 --- a/README.md +++ b/README.md @@ -111,11 +111,13 @@ This repo (the **plugin**) carries everything that is universal: The constants that used to be configurable but were the same in every project are now **fixed conventions** — named directly in the skills and documented once in `docs/conventions.md`: spec dir -`docs/specs`, plan dir `docs/plans`, 4-digit per-directory naming, +`docs/specs`, plan dir `docs/plans`, slug-only `slug.md` naming, the vocabulary above, standing reading (`CLAUDE.md` + `git log -10`), git discipline, Gitea + `closes #N`, and the whole pipeline graph. -Specs and plans are ephemeral — git-tracked, held only for the active -cycle, then `git rm`'d at cycle close; git history keeps the record +Specs and plans are ephemeral — git-ignored, held only for the active +cycle, then shell-`rm`'d at cycle close (never committed, so there is +nothing to `git rm` and no git-history copy); the design ledger is the +durable record and no durable artefact cites a spec/plan (`docs/conventions.md` § Lifecycle). The handful of facts that genuinely vary per project live in the @@ -141,7 +143,8 @@ spec boundaries unattended. (Outside `/boss` the user signs every spec directly.) The autonomous signature is the **`grounding-check` `PASS`**: an independent fresh-context agent's verdict against currently-green tests, not the orchestrator's confidence. On `PASS` the orchestrator -commits the spec (`(boss-signed)` in the subject), sends a mandatory +keeps the signed spec as a git-ignored working file (never committed) and +records the sign on the run's reference issue, sends a mandatory informational notify that names the signed capability and invites a veto, and continues to `planner` without stopping. A no-override grounding `BLOCK` / `INFRA_ERROR` routes to the human sign-off pause. diff --git a/audit/SKILL.md b/audit/SKILL.md index 0bfb77b..bc720e4 100644 --- a/audit/SKILL.md +++ b/audit/SKILL.md @@ -51,7 +51,9 @@ For cycle : read the project's design ledger, if it has one (its CLAUDE.md project facts), walk its contracts; `git log ..HEAD --format=full` for the cycle's iter and audit commit bodies; `git diff ..HEAD` -for the diff; report drift. +for the diff; read the cycle's spec at `docs/specs/.md` +if one exists (a git-ignored working file — read it from disk, +not git); report drift. ``` Architect produces a prioritised drift list (see @@ -120,6 +122,29 @@ The orchestrator picks per item: Red Flags, "about to return clean without having read the diff in full"; the gate verifies it rather than trusting the status.) +### Step 5 — Discard the cycle's spec and plan + +Once the cycle is drift-clean (or the drift is ratified) and the +architect has read the spec, the cycle's spec and plan have served their +purpose. Discard them from the working tree with a plain shell `rm`: + +``` +rm -f docs/specs/.md docs/plans/.md +``` + +This is a shell delete, NOT `git rm` — the files are git-ignored and were +never committed, so nothing is staged and the audit-close commit carries +only code and ledger changes. **Ordering is load-bearing:** the +architect's read (Step 1) must precede this delete, because a git-ignored +spec has no `git show` recovery once it is gone. + +**Spare any `fieldtest-`-prefixed spec.** A `fieldtest-.md` under +`docs/specs` belongs to the *next* cycle (it is the input to its +`planner`), so it is not this cycle's to discard — leave it for the next +cycle's close. If this cycle is itself a milestone close with no +following `planner`, discard the fieldtest spec too (see +`../fieldtest/SKILL.md`). + ## Handoff Contract `audit` hands to the orchestrator: diff --git a/boss/SKILL.md b/boss/SKILL.md index a24da21..3ca19bd 100644 --- a/boss/SKILL.md +++ b/boss/SKILL.md @@ -538,10 +538,13 @@ pause. The boss-side contract is just this: verifies. Editorial roughness the old panel would have caught is let through deliberately — cheap to patch inline downstream, never worth an obligatory five-juror panel on every spec. -- **On a clean sign, do not stop.** Commit the spec (the auto-sign - commit subject carries `(boss-signed)` so the act is auditable in - history), fire the auto-sign notify, and continue to `planner` in - the same run. The notify is informational-with-veto, not a pause. +- **On a clean sign, do not stop.** The spec is never committed — it is + a git-ignored working file, signed by the `grounding-check` PASS. + Make the sign auditable on the run's **reference issue** (a + decision-log comment recording that the spec was auto-signed on a + PASS with no human), fire the auto-sign notify, and continue to + `planner` in the same run. The notify is informational-with-veto, not + a pause. - **The notify must be vetoable.** It follows the same editorial rules as a done-state notify (English, user-as-reader, no iteration codes or crate names) with one addition forced by its purpose: it must @@ -552,15 +555,18 @@ pause. The boss-side contract is just this: capability> myself and started the implementation plan — reply to veto." No internals, but enough identity to act on. - **A veto is a forward correction — or, within the run, a rollback.** - If the user vetoes a spec already committed below the session anchor - (ratified history), undo it forward - — revert the spec commit, discard the downstream working-tree work with - `git checkout`, file the redirection. *Within* the autonomous run, the - rollback sandbox (§ Direction freedom) is the additional remedy: the - orchestrator may hard-reset its own unpushed `(boss-signed)` commit and - the work built on it back toward the session anchor when it judges the - fork was wrong — its own work only, never below the anchor, never a - pushed commit. + The spec is never a commit (it is a git-ignored working file), so a + veto is undone forward by shell-`rm`ing (or editing) the spec and + reverting only the downstream **code** it produced: `git revert` the + code commits below the session anchor (ratified history), or + `git checkout` the unstaged work, and file the redirection. *Within* + the autonomous run, the rollback sandbox (§ Direction freedom) is the + additional remedy: the orchestrator may hard-reset its own unpushed + autonomous **code** commits and the work built on them back toward the + session anchor when it judges the fork was wrong — its own work only, + never below the anchor, never a pushed commit — and shell-`rm`s the + git-ignored spec/plan of the abandoned line. The reference-issue thread + is the only surviving trace of the abandoned attempt. ## Skill-system feedback diff --git a/docs/conventions.md b/docs/conventions.md index 4ccbb69..9d7b2a6 100644 --- a/docs/conventions.md +++ b/docs/conventions.md @@ -27,6 +27,15 @@ These directories are fixed. A project that keeps specs and plans elsewhere is the rare exception and states the override in its `CLAUDE.md` project facts. +Both directories are **git-ignored** — their contents are transient +working files, never committed (see § Lifecycle). The plugin ignores +them **globally**: `docs/specs/` and `docs/plans/` live in the user's +global git excludes (`~/.config/git/ignore`, the XDG default that +applies to every repo), next to the other plugin-wide ignores. One +entry set covers every project — no per-project `.gitignore` line is +needed, though a project MAY add its own if it wants the ignore to +travel with the repo. + ## Lifecycle `docs/specs/` and `docs/plans/` hold **only the active cycle's @@ -35,35 +44,51 @@ valid for the cycle that produces it; its code shapes drift the moment the code moves, so a stale one left lying around reads as a live API reference and misleads the next agent that opens it. -The two directories stay **git-tracked** — never git-ignored. A -spec/plan is committed while its cycle is live, and at **cycle close** — -after `audit` is drift-clean — the orchestrator **retires** it: `git rm` -the spec and plan in the cycle-close commit. The deletion rides in that -commit, so at `HEAD` the directories hold only what is still in flight, -while the full text stays recoverable from git history -(`git show :`). +The two directories are **git-ignored** — their contents are never +committed. A spec/plan is a working file: present on disk while its +cycle is live (readable across sessions, since the working tree +persists), and at **cycle close** — after `audit` is drift-clean — the +orchestrator **discards** it with a plain shell `rm`. There is nothing +to `git rm` (it was never tracked) and no deletion commit is produced; +the working tree is simply left without a stale artefact. This is the +same shell-delete-an-uncommitted-file mechanic `specify` already uses on +its grounding-`BLOCK` failure path. -A spec/plan is therefore **transient in the repo**: present for its own -cycle, gone from `HEAD` afterwards. The durable record of a past cycle -is the design ledger (where the rationale is lifted during audit) + the -git history of the spec, plan, and code — never a live file under -`docs/specs` / `docs/plans`. +A spec/plan is therefore **transient on disk**: present for its own +cycle, `rm`'d afterwards, and — never having been committed — leaving no +trace in git. It is **not recoverable, by design**. The durable record +of a past cycle's design intent is the **design ledger only** (where the +rationale is lifted during audit); the implementation is committed as +normal code. + +**No durable artefact may cite a spec or plan** — not by number, not by +path. Code, tests, docs, and ledger entries outlive the spec/plan that +prompted them, so any reference to `docs/specs/…` or "spec NNNN" would +dangle the moment the cycle closes. Cite the **design-ledger contract** +instead (e.g. a `C`-id); it is the durable record the spec's rationale +was lifted into. ## Naming -Counter-prefixed, per directory: `NNNN-slug.md`, 4-digit -zero-padded. The counter is per directory, assigned in creation -order, and stable for the life of the file. New files take the -next-higher number; `brainstorm` / `specify` / `planner` scan the -target directory for the next free number before writing. +Files are named `slug.md` — a short kebab-case identifier of the +cycle's topic (slug separator `-`). There is **no numeric prefix**: +because the directories are git-ignored, shell-`rm`'d at cycle close, +and cited by nothing (see § Lifecycle), they hold at most the active +cycle's handful of files, so a slug is already unique enough — the old +scan-for-the-next-free-number ritual bought nothing and is gone. A +`fieldtest`-produced spec takes a `fieldtest-` prefix +(`fieldtest-slug.md`): that prefix is the discriminator the cycle-close +sweep uses to spare it, because it belongs to the next cycle (see +`../fieldtest/SKILL.md`). -The number is a within-cycle handle, not a stable archival ID. -Because the directories hold only active artefacts (see § Lifecycle), -an emptied directory restarts at `0001` and a number freed by a -retired file may be reused — that recycling is fine, since the durable -record is git history, not the filename. - -The slug separator is `-`. +**The file name is not the cycle number.** The **cycle number** that +appears in commit subjects (`feat(NNNN)`, `audit(NNNN)`) and in `git +log` cycle ranges is a distinct, monotonic identifier that must survive +spec/plan discard. Source it from the highest `NNNN` in the +`feat(NNNN)` / `audit(NNNN)` git-log subjects, plus one — never from a +file name (there is none) and never from a per-directory scan. Cycle +commits therefore MUST carry the zero-padded `(NNNN)` cycle number in +their subject. ## Vocabulary diff --git a/docs/design.md b/docs/design.md index a6e3167..d107f88 100644 --- a/docs/design.md +++ b/docs/design.md @@ -85,16 +85,18 @@ The plugin owns: The constants that used to be configurable but were the same in every project are now plugin conventions, named directly in skill and agent bodies and documented once in `conventions.md`: -spec dir `docs/specs`, plan dir `docs/plans`, 4-digit per-directory +spec dir `docs/specs`, plan dir `docs/plans`, slug-only `slug.md` naming, the vocabulary cycle / iteration / milestone / contract, standing reading (`CLAUDE.md` + `git log -10`), git discipline (only-orchestrator commits, main sacrosanct), Gitea + `closes #N`, and the whole pipeline graph (see `pipeline.md`). -Specs and plans are ephemeral active-cycle artefacts — the two -directories stay git-tracked and hold only what is in flight; at cycle -close each is `git rm`'d from the repo, kept only in git history, never -as a durable file (see `conventions.md` § Lifecycle). +Specs and plans are ephemeral active-cycle working files — the two +directories are git-ignored and hold only what is in flight; at cycle +close each is shell-`rm`'d (never committed, so nothing to `git rm` and +no git-history copy). The durable record of a past cycle is the design +ledger only, and no durable artefact cites a spec/plan (see +`conventions.md` § Lifecycle). ## Project facts (project-specific) diff --git a/docs/pipeline.md b/docs/pipeline.md index a813e65..4fca014 100644 --- a/docs/pipeline.md +++ b/docs/pipeline.md @@ -140,8 +140,9 @@ Hard-gate before plan — the spec-production core and the carrier of the "no plan without an approved spec" invariant. Takes a settled design (directly from sources, or a ratified design handed over by `brainstorm`), applies the feature-acceptance criterion, writes the -spec to `docs/specs` (an ephemeral active-cycle artefact, git-tracked -and `git rm`'d at cycle close — see `conventions.md` § Lifecycle), runs +spec to `docs/specs` (an ephemeral active-cycle working file — +git-ignored, never committed, shell-`rm`'d at cycle close — see +`conventions.md` § Lifecycle), runs the `grounding-check` gate, and takes sign-off — with review but no interview. Under the bold stance it decides every load-bearing fork it can *derive* an answer for and records the decision in the run's @@ -152,9 +153,11 @@ gate before `planner` on every design path. Outside `/boss` the sign-off is the user's. Under `/boss` the autonomous signature is the **`grounding-check` `PASS`** itself: an independent fresh-context agent's verdict against currently-green tests, not the -orchestrator's confidence. On `PASS` the orchestrator commits the spec -(subject `(boss-signed)`), fires the vetoable auto-sign notify, and -continues to `planner`; a no-override grounding `BLOCK` / `INFRA_ERROR` +orchestrator's confidence. On `PASS` the orchestrator keeps the signed +spec as a git-ignored working file (never committed), records the +autonomous sign on the run's reference issue, fires the vetoable +auto-sign notify, and continues to `planner`; a no-override grounding +`BLOCK` / `INFRA_ERROR` routes to the human sign-off pause. The former obligatory five-lens `spec-skeptic` panel is **retired** (baseline tag `pre-autosign-rework`): the judgement it applied now lives upstream in Step 1.5's bold-decide @@ -167,9 +170,10 @@ See `../specify/SKILL.md` Step 6 and `../boss/SKILL.md` §"Spec auto-sign". ### planner Hard-gate before implement. Produces a placeholder-free, -bite-sized implementation plan in `docs/plans` (ephemeral, retired -alongside the spec at cycle close — see `conventions.md` § Lifecycle) -that the implement skill can execute task-by-task. Dispatches +bite-sized implementation plan in `docs/plans` (an ephemeral, +git-ignored working file, shell-`rm`'d alongside the spec at cycle +close — see `conventions.md` § Lifecycle) that the implement skill can +execute task-by-task. Dispatches the plan-recon agent for read-only file-structure mapping. ### implement @@ -209,9 +213,11 @@ review-and-commit discipline; the orchestrator inspects and commits. Runs at cycle close. Dispatches the architect agent (read-only drift review against the design ledger) and the bencher agent (regression diagnostics). Reports drift and regress. Once it is -drift-clean, the orchestrator retires the cycle's spec and plan — -`git rm`'ing them in the cycle-close commit (see `conventions.md` -§ Lifecycle). +drift-clean, the orchestrator discards the cycle's spec and plan with a +plain shell `rm` (nothing to `git rm` — they were never committed), +sparing any `fieldtest-`-prefixed spec (it belongs to the next cycle); +the cycle-close commit contains only code and ledger changes (see +`conventions.md` § Lifecycle). ### debug diff --git a/fieldtest/SKILL.md b/fieldtest/SKILL.md index bc05529..f8301b3 100644 --- a/fieldtest/SKILL.md +++ b/fieldtest/SKILL.md @@ -120,10 +120,17 @@ Contract below. The agent picks 2-4 examples (one per axis the cycle touched; fewer loses the signal on variation, more overflows one readable report), implements them as downstream consumers, runs them, classifies findings, and writes the -spec. All artefacts (fixtures + spec) stay in the working tree -as unstaged changes; the orchestrator commits them after -reviewing the report (suggested commit subject: -`fieldtest: examples, findings`). +spec. The two artefact kinds part ways at commit: the **fixtures are +committed as normal code** (they are consumer test assets — suggested +subject `fieldtest: examples, findings`), while the +**fieldtest spec is a git-ignored working file that is never committed**. + +The fieldtest spec is written at cycle N's close but is an **input to +the next cycle's `planner`**, so it belongs to cycle N+1, not N: the +cycle-close sweep spares it (its `fieldtest-` filename prefix is the +discriminator) and it is shell-`rm`'d at N+1's close alongside N+1's own +spec and plan. If the consuming cycle closes without a `planner` (e.g. a +milestone close), the orchestrator discards it explicitly. ## Handoff Contract diff --git a/fieldtest/agents/fieldtester.md b/fieldtest/agents/fieldtester.md index c0af05c..50c5dcb 100644 --- a/fieldtest/agents/fieldtester.md +++ b/fieldtest/agents/fieldtester.md @@ -211,14 +211,15 @@ not merged. ### Phase 5 — Write the spec, hand back -Write the fieldtest spec under `docs/specs` with a name -following the `NNNN-slug.md` convention (4-digit prefix, -per-directory; see `docs/conventions.md`). Use the spec -template below. Leave all artefacts (the fixtures and the -spec file) in the working tree as unstaged changes. You do -NOT commit — the orchestrator commits after reading the -end-report (suggested commit subject: -`fieldtest: examples, findings`). +Write the fieldtest spec under `docs/specs` named +`fieldtest-slug.md` (the `fieldtest-` prefix is mandatory — it is the +discriminator that spares the spec from the cycle-close sweep; no numeric +prefix, see `docs/conventions.md` § Naming). Use the spec +template below. Leave all artefacts in the working tree as unstaged +changes. You do NOT commit — the orchestrator commits the **fixtures** +as code after reading the end-report (suggested subject +`fieldtest: examples, findings`); the fieldtest +**spec** is git-ignored and is never committed. Report `DONE` with the carrier (see Output format). diff --git a/planner/SKILL.md b/planner/SKILL.md index ce177a6..c5e35d8 100644 --- a/planner/SKILL.md +++ b/planner/SKILL.md @@ -16,8 +16,9 @@ into bites small enough that a subagent can execute one in 2-5 minutes without making judgement calls outside its remit. Plans live under `docs/plans` with the fixed name shape -`NNNN-slug.md` — a 4-digit counter per directory (see -`docs/conventions.md`). The header references the parent spec. The plan +`slug.md` — a short kebab-case topic slug, no numeric prefix (see +`docs/conventions.md` § Naming). `docs/plans` is git-ignored; the plan +is a working file, never committed. The header references the parent spec. The plan decomposes work into tasks; each task is the unit of review (spec-compliance and quality gates inside `implement`), not the unit of commit. Commits are an orchestrator-only decision @@ -226,16 +227,14 @@ Fix issues inline. ### Step 6 — Hand off -The plan sits in the working tree as an unstaged file under +The plan sits in the working tree as a git-ignored working file under `docs/plans`. Hand off to `implement` with: path to the plan file + optional task focus ("only Tasks 1-3 this run"). -The orchestrator commits the plan when handing it forward -(suggested commit subject: `plan: `). -The planner skill does not perform the commit itself. Like the spec, -the plan is an ephemeral active-cycle artefact: committed for its own -cycle and `git rm`'d at cycle close (see `docs/conventions.md` -§ Lifecycle). +The plan is **never committed**. Like the spec, it is a git-ignored +active-cycle working file: present on disk for its own cycle and +shell-`rm`'d alongside the spec at cycle close by `audit` (see +`docs/conventions.md` § Lifecycle). ## Handoff Contract diff --git a/specify/SKILL.md b/specify/SKILL.md index 35fe885..4551efe 100644 --- a/specify/SKILL.md +++ b/specify/SKILL.md @@ -268,10 +268,10 @@ it as a target, not verified fact. ### Step 3 — Write the spec -Path: under `docs/specs`, named per the fixed naming convention — -`NNNN-slug.md`, 4-digit per-directory counter (see -`docs/conventions.md`). Determine the next free number by scanning the -directory. +Path: under `docs/specs`, named `slug.md` per the fixed naming +convention (see `docs/conventions.md` § Naming) — a short kebab-case +topic slug, no numeric prefix. The directory is git-ignored; the spec is +created there and never `git add`'d. Structure: @@ -377,22 +377,23 @@ spec file; nothing slips between it and the commit. Outside `/boss` the signature is the user's; under `/boss` it is the Step-5 `grounding-check` `PASS` (the `/boss` subsection below). -The spec sits in the working tree as an unstaged file. Tell the user: +The spec sits in the working tree as a git-ignored working file. Tell +the user: -> Spec written to `` (uncommitted). Please review it and let me -> know if you want changes before we start the implementation plan. -> The orchestrator will commit it once you approve. +> Spec written to `` (git-ignored, never committed). Please review +> it and let me know if you want changes before we start the +> implementation plan. Wait for the user's response. If they request changes, edit the file -in place (still uncommitted), **re-run Step 4 AND re-dispatch Step 5** +in place, **re-run Step 4 AND re-dispatch Step 5** (the previous PASS report no longer covers the edited bytes), then return here. Only proceed after approval AND a fresh Step 5 PASS. -The orchestrator commits the approved spec after sign-off (suggested -commit subject: `spec: `). The skill does not perform -the commit itself. The spec is an ephemeral active-cycle artefact: it -lives in the repo only for its own cycle and is `git rm`'d at cycle -close (see `docs/conventions.md` § Lifecycle). +The spec is **never committed**: it is a git-ignored active-cycle working +file that lives on disk only for its own cycle and is shell-`rm`'d at +cycle close by `audit` (see `docs/conventions.md` § Lifecycle). The +durable record of its design intent is the design ledger, lifted during +audit — not the spec file. **In `/boss` (autonomous):** `specify` is dispatched autonomously — it is bounded (no interview), so there is no user at this gate to take the @@ -404,11 +405,13 @@ adversarial panel**, no objective-gates-then-panel staging, no self-correction loop; those were retired in favour of decide-upstream + recover-downstream (baseline tag `pre-autosign-rework`). -- On a Step-5 **`PASS`**: commit the spec yourself (subject `spec: - (boss-signed)`), fire the auto-sign notify (see `boss` - § Notifications — it names the capability in user terms and states the - plan is proceeding and a reply vetoes), then proceed to Step 7. No - pause. +- On a Step-5 **`PASS`**: the spec is signed by the PASS — leave it as a + git-ignored working file (never committed). Record the autonomous sign + on the run's reference issue (a decision-log comment: which capability, + that the `grounding-check` PASS was the signature, that no human + signed), fire the auto-sign notify (see `boss` § Notifications — it + names the capability in user terms and states the plan is proceeding + and a reply vetoes), then proceed to Step 7. No pause. - On a Step-5 no-override **`BLOCK`** or **`INFRA_ERROR`**: there is no human to override it, so it routes to the human sign-off pause — a problem-state notify ("spec X needs your sign-off") — exactly as the @@ -435,13 +438,16 @@ leaning. This is a *tool it reaches for*, not a gate it must clear: the lens returns a finding, the orchestrator decides. Carrier and lenses are defined in `agents/spec-skeptic.md`. -**Auto-sign commits on `main` are forward-only — with one `/boss` -exception.** A later user veto is normally a forward correction (revert / -revised spec / `git checkout` of downstream work). The `/boss` rollback -sandbox is the exception: within an autonomous run the orchestrator may -hard-reset its own *unpushed* autonomous commits back toward (never -below) the session anchor when it has run into a dead end — its own work -only. See `boss` § Direction freedom for the exact boundary. +**Auto-signed CODE commits on `main` are forward-only — with one `/boss` +exception.** The spec itself is never a commit (it is a git-ignored +working file), so a later user veto is a forward correction: shell-`rm` +(or edit) the git-ignored spec, and `git revert` / `git checkout` only +the downstream **code** it produced. The `/boss` rollback sandbox is the +exception: within an autonomous run the orchestrator may hard-reset its +own *unpushed* autonomous code commits back toward (never below) the +session anchor when it has run into a dead end — its own work only, and +it shell-`rm`s the git-ignored spec/plan of the abandoned line. See +`boss` § Direction freedom for the exact boundary. ### Step 7 — Hand off to `planner`