feat(boss): bolder autonomous /boss — grounding-PASS auto-sign, rollback sandbox, reference issue
Retire the obligatory five-lens spec-skeptic auto-sign panel (worst case 18 agent runs per spec under /boss). The autonomous signature is now the Step-5 grounding-check PASS alone — an independent fresh-context agent's verdict against currently-green tests; a no-override BLOCK/INFRA_ERROR routes to the human sign-off pause. The judgement the panel applied moves upstream into specify Step 1.5, whose stance inverts: a load-bearing fork the orchestrator can DERIVE an answer for (sources, code, consistency, risk) is decided boldly and recorded on the run's reference issue; only a pure-preference fork bounces. spec-skeptic survives as an optional ad-hoc bias-breaker the orchestrator pulls when unsure whether its leaning is judgement or bias — not a gate, not a veto. Every /boss run carries a mandatory reference issue (created if the cycle had none): the fork-decision log, the orchestrator's cross-run memory, and the only surviving trace of a hard-dropped attempt. Relax main-sacrosanct below the session anchor: within an autonomous run the orchestrator may git reset --hard its OWN UNPUSHED commits above the anchor on a dead end — never below the anchor, never a pushed commit (forward-only/revert). Discarded attempts are hard-dropped, no parking. Verified across the 9 edited files by a 4-lens adversarial review (retired-panel residue, cross-file contracts, rollback-boundary safety, stance coherence): unanimous SOUND. Baseline tagged pre-autosign-rework. closes #8
This commit is contained in:
+190
-194
@@ -17,7 +17,7 @@ planner consumes: with review, but **without an interview**.
|
||||
|
||||
It is the **sole home of the spec-production gates**: the
|
||||
feature-acceptance criterion, the write-spec step, the
|
||||
`grounding-check` hard-gate, and the user-review gate. Whichever way design work enters — fresh
|
||||
`grounding-check` hard-gate, and the sign-off gate. Whichever way design work enters — fresh
|
||||
through `brainstorm`'s discovery, or directly from sources that
|
||||
already resolve the design — it passes through `specify` to become a
|
||||
spec. `specify` carries the universal invariant **no plan without an
|
||||
@@ -61,28 +61,34 @@ Triggers:
|
||||
|
||||
**Skipping a gate is never permitted.** The interview is `brainstorm`'s,
|
||||
and its absence here is the whole point — but the *production gates*
|
||||
(criterion, grounding-check, user-review) are
|
||||
(criterion, grounding-check, sign-off) are
|
||||
non-negotiable regardless of how the work entered. "The issue looks
|
||||
exhaustive, skip the grounding-check" is the reactive-deference failure
|
||||
this skill must not reintroduce.
|
||||
this skill must not reintroduce. (Under `/boss` the sign-off gate is the
|
||||
`grounding-check` `PASS` itself — see Step 6.)
|
||||
|
||||
## The Iron Law
|
||||
|
||||
```
|
||||
THE SOURCES MUST RESOLVE EVERY LOAD-BEARING DESIGN DECISION BEFORE THE SPEC IS WRITTEN.
|
||||
IF WRITING THE SPEC FORCES A CHOICE BETWEEN PLAUSIBLE DESIGNS THE SOURCES DO NOT RESOLVE,
|
||||
STOP AND BOUNCE TO brainstorm. DO NOT SILENTLY PICK ONE.
|
||||
THE PRODUCTION GATES — ACCEPTANCE CRITERION, GROUNDING-CHECK, USER-REVIEW —
|
||||
EVERY LOAD-BEARING DESIGN DECISION MUST BE RESOLVED BEFORE THE SPEC IS WRITTEN — BUT
|
||||
"RESOLVED" INCLUDES A FORK THE ORCHESTRATOR CAN DERIVE AN ANSWER FOR (FROM THE SOURCES,
|
||||
THE CODE, EXISTING-DESIGN CONSISTENCY, OR RISK). A DERIVABLE FORK -> DECIDE IT BOLDLY AND
|
||||
RECORD THE DECISION IN THE REFERENCE ISSUE. ONLY A FORK THAT HANGS ON PURE USER PREFERENCE
|
||||
WITH NO DERIVABLE BETTER -> STOP AND BOUNCE / PAUSE. DO NOT BOUNCE A FORK YOU CAN DECIDE.
|
||||
THE PRODUCTION GATES — ACCEPTANCE CRITERION, GROUNDING-CHECK, SIGN-OFF —
|
||||
ARE NON-NEGOTIABLE REGARDLESS OF ENTRY PATH.
|
||||
NO PLAN, SCAFFOLDING, OR DOWNSTREAM SKILL UNTIL THE SPEC IS APPROVED — BY THE USER, OR
|
||||
(UNDER /boss) BY THE AUTO-SIGN GATE: ALL OBJECTIVE GATES GREEN
|
||||
AND A UNANIMOUS ADVERSARIAL spec-skeptic PANEL. MODEL SELF-CONFIDENCE ALONE IS NEVER APPROVAL.
|
||||
(UNDER /boss) BY A grounding-check PASS. MODEL SELF-CONFIDENCE ALONE IS NEVER APPROVAL;
|
||||
THE grounding-check IS AN INDEPENDENT FRESH-CONTEXT AGENT, NOT THE PRODUCER'S CONFIDENCE.
|
||||
```
|
||||
|
||||
Every clause is non-negotiable. The precondition gate is what makes
|
||||
the no-interview path legitimate rather than merely convenient: it is
|
||||
the honest fork-check that `tdd`'s "is this test-specifiable?" is for
|
||||
test work.
|
||||
test work. Its bar is *decidability*, not *pre-settlement*: a fork the
|
||||
orchestrator can ground an answer for is resolved by deciding it; only a
|
||||
fork that turns on the user's own preference, with no derivable better,
|
||||
is the one that bounces.
|
||||
|
||||
## The Process
|
||||
|
||||
@@ -107,56 +113,86 @@ Enumerate the **load-bearing design decisions** the spec must encode
|
||||
— the choices that, decided differently, would change what ships.
|
||||
For each, ask the honest question:
|
||||
|
||||
> Do the sources **resolve** this, or am I about to **pick** it
|
||||
> myself?
|
||||
> Can I **derive** an answer for this fork — from the sources, the
|
||||
> code, consistency with the existing design, or relative risk — or
|
||||
> does it turn on a **preference only the user holds**?
|
||||
|
||||
If every load-bearing decision is resolved by the sources, proceed to
|
||||
Step 2. If even one is unresolved — the sources leave a genuine fork
|
||||
between plausible designs with real trade-offs — **STOP and bounce to
|
||||
`brainstorm`** (see Error handling / The Bounce-Back). Do not silently
|
||||
pick one and bake it into the spec; a guessed design ratified into a
|
||||
spec is harder to dislodge than an open question, and it is exactly
|
||||
the reactive-deference failure the gate exists to prevent.
|
||||
This is a *decidability* test, not a *pre-settlement* test, and the
|
||||
default is **decide, not bounce**:
|
||||
|
||||
Genuine doubt about whether the sources resolve a decision *is itself*
|
||||
the fork signal — it resolves to a bounce, not to a guess.
|
||||
- **Derivable fork → decide it boldly.** If there is a groundable
|
||||
reason to prefer one option — it fits the existing design better, it
|
||||
is simpler, it carries less risk, the sources lean that way — the
|
||||
orchestrator decides it and proceeds. It does **not** bounce a fork it
|
||||
can actually answer. When unsure whether its own leaning is bias
|
||||
rather than judgement, it pulls **one** independent opinion — an
|
||||
ad-hoc `spec-skeptic` lens (see Step 6) — and weighs it; the lens
|
||||
informs the decision, it does not veto. Every derived decision is
|
||||
**recorded in the reference issue** (below) with its rationale.
|
||||
- **Pure-preference fork → bounce / pause.** Only when the fork turns on
|
||||
something the orchestrator cannot derive — roadmap order, product
|
||||
taste, two genuinely equivalent paths whose trade-off only the user
|
||||
can weigh — is it a real bounce. Then **STOP and bounce to
|
||||
`brainstorm`** (see The Bounce-Back), or under `/boss` route to the
|
||||
human sign-off pause. A guessed *preference* baked into a spec is the
|
||||
reactive-overreach this gate still prevents.
|
||||
|
||||
**Reconciliation comment (lagging-issue case).** A load-bearing fork can
|
||||
be resolved by the in-context design discussion yet still be listed
|
||||
*open* by the tracker issue that seeded the cycle — the issue lags the
|
||||
conversation. When that holds (entry is in-context **and** a tracker
|
||||
issue still carries a now-resolved fork as open), record the resolution
|
||||
as an auditable issue comment **before** writing the spec, via the
|
||||
project's issue-tracker comment command (`tea comment <idx>` for Gitea;
|
||||
a heredoc body per the `issue` skill's conventions). One comment, this
|
||||
exact shape:
|
||||
The old "genuine doubt *is* the fork signal → bounce" reflex is
|
||||
**retired**: doubt about whether you can derive an answer resolves to an
|
||||
honest attempt to derive it (with a bias-breaker if needed), not to a
|
||||
reflexive bounce. Being wrong on a derived call is allowed — the net is
|
||||
the user's veto and, under `/boss`, the rollback sandbox
|
||||
(`../boss/SKILL.md` § Direction freedom). What is *not* allowed is
|
||||
dressing a pure-preference guess as a derived decision.
|
||||
|
||||
**Every `/boss` run carries a reference issue.** The run is always
|
||||
anchored to a tracker issue — an existing one that seeded the cycle, or
|
||||
one the orchestrator creates when the work was settled in pure chat with
|
||||
no prior issue (the mechanic below). That issue is the run's **decision
|
||||
log**: as the orchestrator derives fork answers, it comments each one
|
||||
there, so the user can audit and veto after the fact and the orchestrator
|
||||
has a cross-run "issue memory". Because a `/boss` dead-end is recovered
|
||||
by hard-dropping the autonomous commits (no attempt branch survives), the
|
||||
issue's comment thread is also the **only surviving trace** of an
|
||||
abandoned attempt — which is the second reason it is mandatory, not
|
||||
optional.
|
||||
|
||||
A comment records one of two distinct things, and the distinction is
|
||||
load-bearing:
|
||||
|
||||
- A **user decision** the conversation settled — minuted with
|
||||
**provenance** (a verbatim user statement, or explicit attribution +
|
||||
date). Legitimate: you are recording what the user chose.
|
||||
- A **derived orchestrator decision** — recorded with its **rationale**
|
||||
(why one option is groundably better). Legitimate under the new stance,
|
||||
but it must be labelled as what it is: a derived call, never disguised
|
||||
as a user decision. If you cannot state a rationale, the fork was not
|
||||
derivable — that is a pure-preference bounce, not a comment.
|
||||
|
||||
**Reconciliation comment (lagging-issue case).** A fork can be resolved
|
||||
— by a user decision in the discussion, or derived by the orchestrator —
|
||||
yet still be listed *open* by the tracker issue that seeded the cycle.
|
||||
When that holds, record the resolution as an auditable issue comment
|
||||
**before** writing the spec, via the project's issue-tracker comment
|
||||
command (`tea comment <idx>` for Gitea; a heredoc body per the `issue`
|
||||
skill's conventions). One comment, this shape:
|
||||
|
||||
```
|
||||
## Design reconciliation (specify, in-context entry)
|
||||
## Design reconciliation (specify)
|
||||
Spec: <spec-name>. The fork(s) below are still listed open on this
|
||||
issue; they were resolved in the in-context design discussion.
|
||||
issue; this records their resolution.
|
||||
- **Fork: <name>** → <decision>.
|
||||
Provenance: <verbatim user statement, or explicit attribution + date>.
|
||||
Basis: <verbatim user statement + attribution, OR "derived:" + the
|
||||
groundable rationale>.
|
||||
```
|
||||
|
||||
The comment must carry **provenance**, and the distinction is
|
||||
load-bearing: it is the *record of a user decision* (legitimate — the
|
||||
user settled the fork in discussion, you are minuting it), never a *new
|
||||
orchestrator decision* dressed as settled (illegitimate). A bare
|
||||
`decision: B` with no provenance is the latter. If you cannot point to a
|
||||
real user statement, that is the signal that *you* picked the fork, not
|
||||
the user — which is a Step-1.5 bounce, not a comment. The comment is
|
||||
*persistent and auditable* (author + timestamp, in the forward queue) —
|
||||
which is exactly why it, and not your ephemeral confidence, is what a
|
||||
downstream `scope-fork` juror reads to confirm the fork is settled (see
|
||||
Step 6). Recording it keeps the forward queue honest in either run mode;
|
||||
under `/boss` it is *load-bearing* — without it the `scope-fork` juror
|
||||
sees only the stale issue body and (correctly) blocks.
|
||||
|
||||
Provenance enforcement is not yours to self-certify: you *write* the
|
||||
comment, the adversarial `scope-fork` juror *checks* it carries
|
||||
provenance (Step 6). Writing a provenance-less comment does not buy a
|
||||
pass — the re-dispatched juror blocks on it.
|
||||
`Basis:` carries either provenance (user decision) or rationale (derived
|
||||
decision) — both are auditable, neither is a bare `decision: X` with no
|
||||
support. The comment is *persistent and auditable* (author + timestamp,
|
||||
in the forward queue) — which is exactly why it, and not your ephemeral
|
||||
confidence, is what the user reads to understand and veto a call made
|
||||
without them. Recording it keeps the forward queue honest in either run
|
||||
mode.
|
||||
|
||||
Gitea writes are pre-authorized (per `~/.claude/CLAUDE.md`); post the
|
||||
comment without a confirmation prompt.
|
||||
@@ -164,8 +200,8 @@ comment without a confirmation prompt.
|
||||
**Issue-less in-context entry.** If the cycle has *no* tracker issue —
|
||||
the design was settled in pure chat — there is no existing artefact to
|
||||
comment on, so *create one*: open a new tracker issue that records the
|
||||
resolved fork(s) with provenance, under the same discipline as the
|
||||
reconciliation comment above. The body takes this shape:
|
||||
resolved fork(s) under the same discipline as the reconciliation comment
|
||||
above. The body takes this shape:
|
||||
|
||||
```
|
||||
## Design record (specify, issue-less in-context entry)
|
||||
@@ -173,38 +209,26 @@ This issue seeds <one-line identity of the work>. The design was settled
|
||||
in an in-context discussion with no prior tracker issue; this records it.
|
||||
Load-bearing fork(s) resolved:
|
||||
- **Fork: <name>** → <decision>.
|
||||
Provenance: <verbatim user statement, or explicit attribution + date>.
|
||||
Basis: <verbatim user statement + attribution, OR "derived:" + rationale>.
|
||||
```
|
||||
|
||||
The body names the *work*, not the spec file — the spec does not exist
|
||||
yet at Step 1.5 (its number is assigned only in Step 3). This new issue
|
||||
is the cycle's seeding issue from here on: the `scope-fork` juror reads
|
||||
it via the project's issue show command — its index handed to the juror
|
||||
in the Step-6 carrier (the `seeding_issue` field, below) — exactly as it
|
||||
reads any seeding issue. A *new issue* is the right artefact where a spec-note
|
||||
is the wrong one — a provenance note *inside the spec* is
|
||||
self-referential (the spec asserting its own sources settle it) and
|
||||
stays banned, but a separate issue is independent (author + timestamp,
|
||||
in the forward queue, juror-readable without opening the spec), as
|
||||
auditable as a reconciliation comment. Creating it is what lets the
|
||||
`scope-fork` juror ratify the resolution here, instead of blocking for
|
||||
lack of an auditable source.
|
||||
|
||||
The provenance gate is unchanged and load-bearing: the new issue records
|
||||
*user* decisions, never fresh orchestrator ones. No real user statement
|
||||
for a fork means *you* picked it — a Step-1.5 bounce, not an issue to
|
||||
manufacture. You *write* the issue; the adversarial `scope-fork` juror
|
||||
*checks* the provenance, and a provenance-less body buys no pass.
|
||||
is the run's reference issue from here on: the orchestrator comments
|
||||
later derived decisions on it as the run proceeds, and a downstream
|
||||
ad-hoc `spec-skeptic` can read it via the project's issue show command if
|
||||
the orchestrator pulls one. A *new issue* is the right artefact where a
|
||||
provenance note *inside the spec* would be the wrong one — a note inside
|
||||
the spec is self-referential (the spec asserting its own sources settle
|
||||
it) and stays banned, but a separate issue is independent (author +
|
||||
timestamp, in the forward queue, readable without opening the spec).
|
||||
|
||||
Create it via the project's issue-create command (the `issue` skill's
|
||||
mechanics — `tea issues create` for Gitea), title and label per the
|
||||
project's vocabulary as in the Step-5 failure-mode procedure. Gitea
|
||||
writes are pre-authorized, so create it without a confirmation prompt.
|
||||
**Capture the new issue's index** the moment it is created and carry it
|
||||
into the Step-6 panel as the `seeding_issue` field — it is the only way
|
||||
the `scope-fork` juror knows which issue to read. An issue created but
|
||||
never handed to the panel is invisible to the juror, which leaves the
|
||||
fork looking picked and the creation pointless.
|
||||
project's vocabulary. Gitea writes are pre-authorized, so create it
|
||||
without a confirmation prompt. **Capture the new issue's index** the
|
||||
moment it is created — it is the run's reference issue, the target for
|
||||
every later decision comment.
|
||||
|
||||
### Step 2 — Apply the project's feature-acceptance criterion
|
||||
|
||||
@@ -347,7 +371,10 @@ report and requires a fresh dispatch of `grounding-check` before the
|
||||
Step-6 sign-off and commit. Step 5 is the *last* step that touches the
|
||||
spec file; nothing slips between it and the commit.
|
||||
|
||||
### Step 6 — User-review gate
|
||||
### Step 6 — Sign-off gate
|
||||
|
||||
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:
|
||||
|
||||
@@ -366,94 +393,54 @@ 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).
|
||||
|
||||
**In `/boss` (autonomous):** `specify` is dispatched autonomously —
|
||||
it is bounded (no interview). It runs the criterion, parse, and
|
||||
grounding-check gates without a checkpoint. At *this* gate the
|
||||
orchestrator signs in the user's place, but only through the
|
||||
**auto-sign gate** below — never on its own confidence. The gate
|
||||
exists because the orchestrator that wrote the spec is the worst-placed
|
||||
party to judge it, so it is built to *not* rely on that confidence. The
|
||||
human sign-off pause is not the default here; it is where the gate
|
||||
**escalates** — a spec that cannot clear the gate routes to a
|
||||
problem-state notify ("spec X ready, please sign off") and waits for the
|
||||
user, exactly as a plain pause would. Run the gate in two stages:
|
||||
**In `/boss` (autonomous):** `specify` is dispatched autonomously — it
|
||||
is bounded (no interview), so there is no user at this gate to take the
|
||||
signature. The signature comes from the **Step-5 `grounding-check`
|
||||
`PASS`**: an independent fresh-context agent's verdict against
|
||||
currently-green tests, not the producing orchestrator's confidence — and
|
||||
that is what the bold stance trusts in the user's place. There is **no
|
||||
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`).
|
||||
|
||||
1. **Objective gates (all must already hold — these are facts, not
|
||||
judgements):**
|
||||
- Step 1.5 precondition gate passed cleanly — no load-bearing
|
||||
fork was silently picked (if one had been, `specify` would have
|
||||
bounced, so reaching here is the evidence; do not re-decide it).
|
||||
- Step 4 self-review clean, **including the placeholder scan** (no
|
||||
`TBD` / `TODO` / incomplete section).
|
||||
- Step 5 `grounding-check` returned **`PASS`** — *not* an
|
||||
overridden `BLOCK`. An override needs a human; with no human in
|
||||
the loop a `BLOCK` can never be overridden, so any non-`PASS`
|
||||
grounding result denies auto-sign outright.
|
||||
- On a Step-5 **`PASS`**: commit the spec yourself (subject `spec:
|
||||
<cycle> <topic> (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 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
|
||||
Step-5 failure mode describes. A no-override grounding `BLOCK` is the
|
||||
one objective denial of an autonomous sign and is never signed over.
|
||||
|
||||
If any objective gate is not green, **do not run the panel** —
|
||||
fall straight to the human sign-off pause (the default-slot
|
||||
behaviour above), carrying the failing gate in the notify.
|
||||
The judgement that used to live in the panel now lives **upstream**, in
|
||||
Step 1.5's bold-decide stance: a load-bearing fork is *decided* there
|
||||
(with an ad-hoc `spec-skeptic` bias-breaker if the orchestrator wants
|
||||
one) and recorded in the reference issue, or — if it is a pure-preference
|
||||
fork — bounced before the spec is ever written. By the time a spec
|
||||
reaches this gate the only thing left to verify is the objective one the
|
||||
`grounding-check` already verifies. Editorial defects the old panel would
|
||||
have caught (a clumsy worked example, a two-way-readable sentence) are
|
||||
allowed through **deliberately**: they are cheap to patch inline
|
||||
downstream, and catching them was never worth an obligatory five-juror
|
||||
panel on every spec.
|
||||
|
||||
2. **Adversarial panel (unanimous-or-nothing):** dispatch the
|
||||
read-only `spec-skeptic` agent **five times in parallel**, once
|
||||
per lens — `criterion`, `grounding`, `scope-fork`, `ambiguity`,
|
||||
`plan-readiness`. Carrier per dispatch: `spec_path` (absolute),
|
||||
`iteration_scope`, the single `lens`, and `seeding_issue` — the
|
||||
index of the cycle's seeding issue (the lagging issue reconciled in
|
||||
Step 1.5, the issue Step 1.5 created for an otherwise issue-less
|
||||
cycle, or `none` if the cycle has neither) for the `scope-fork`
|
||||
juror to read; the other four lenses ignore it. Each juror tries to
|
||||
*refute* the spec along its lens and returns `SOUND` / `BLOCK` /
|
||||
`INFRA_ERROR`. Auto-sign requires a **unanimous `SOUND`** — that
|
||||
never changes. What the partition below adds is a bounded path to
|
||||
*reach* that unanimity for defects the orchestrator can repair
|
||||
without judging the spec.
|
||||
**Bias-breaker (optional, the orchestrator's call).** When deciding a
|
||||
fork in Step 1.5 the orchestrator MAY dispatch the read-only
|
||||
`spec-skeptic` agent ad hoc — one lens, or a few, whichever fork it is
|
||||
unsure about — for an independent refutation to weigh against its own
|
||||
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`.
|
||||
|
||||
The five lenses split by what a `BLOCK` actually means:
|
||||
|
||||
| Lens class | Lenses | A `BLOCK` means |
|
||||
|------------|--------|-----------------|
|
||||
| **Editorial** | `criterion`, `ambiguity`, `plan-readiness` | The spec is under-*articulated*: missing worked evidence, a requirement readable two ways, scope too broad for one plan. Repairable by editing the prose without settling any new design or fact. A `criterion` repair may only *supply or sharpen the worked evidence the criterion already demands* (paste the concrete before → after / user-facing code the spec implied) — it may **not** soften what the criterion requires or re-judge acceptance, and if the missing evidence cannot be shown without picking an un-settled design, that is a `scope-fork` in disguise: leave it, and the re-dispatched `scope-fork` juror escalates it. |
|
||||
| **Design** | `scope-fork`, `grounding` | The *ground is not settled*: the sources do not resolve a load-bearing fork, or a load-bearing assumption is not ratified by a green test. The orchestrator may **never** settle these in the user's place. |
|
||||
|
||||
Resolve the panel against that split, in a bounded loop
|
||||
(`round` starts at `0`):
|
||||
|
||||
| Panel outcome this round | Orchestrator action |
|
||||
|--------------------------|---------------------|
|
||||
| All five `SOUND` | **Auto-sign.** Commit the spec yourself (subject `spec: <cycle> <topic> (boss-signed)`), send the informational auto-sign notify (see `boss` § Notifications — names the capability in user terms and states the plan is proceeding and a reply vetoes), then proceed to Step 7. No pause. |
|
||||
| Any `INFRA_ERROR` | **Escalate.** Fall back to the human sign-off pause; the notify carries the failing dispatch. |
|
||||
| Any **design**-lens (`scope-fork` / `grounding`) `BLOCK` | **Escalate.** No self-correction — this is exactly the judgement the gate refuses to make for the user. Fall back to the human sign-off pause, carrying *all* lens findings this round. |
|
||||
| Only **editorial**-lens `BLOCK`(s), and `round == 2` | **Escalate.** The self-correction budget is spent. Fall back to the human sign-off pause, carrying the findings *and* the per-round correction history. |
|
||||
| Only **editorial**-lens `BLOCK`(s), and `round < 2` | **Self-correct.** Edit the spec in place to address each editorial finding (each names its `§section` / offending text / defect). Then **re-run Step 4 self-review and re-dispatch Step 5 `grounding-check`** — the edit invalidated the prior `PASS` (see "Re-dispatch on any post-PASS edit"); if `grounding-check` does not return `PASS`, escalate. Increment `round` and re-dispatch all five lenses from the top of this table. |
|
||||
|
||||
**Re-loop limit: ≤ 2 self-correction rounds. The 3rd unresolved
|
||||
editorial `BLOCK` escalates** — same shape as the per-task re-loop
|
||||
limit in the implement loop (`../implement/workflows/implement-loop.js`).
|
||||
|
||||
Three properties keep this loop honest, not a way to grind the panel
|
||||
into submission:
|
||||
|
||||
- **The panel stays the sole arbiter.** The orchestrator never judges
|
||||
the spec; it only edits in response to a juror's finding, and a
|
||||
fresh panel re-adjudicates. "The spec looks good to me" still never
|
||||
signs.
|
||||
- **Re-dispatch is all five lenses, every round.** This is the
|
||||
backstop. If an editorial repair silently *launders* an unsourced
|
||||
design decision into the spec (resolving an ambiguity by picking an
|
||||
un-settled fork), the re-run `scope-fork` / `grounding` jurors now
|
||||
`BLOCK` on it — and a design `BLOCK` escalates. The only thing the
|
||||
loop can converge to autonomously is a spec whose every lens is
|
||||
`SOUND` *and* whose only repairs were editorial.
|
||||
- **Escalation is the panel doing its job**, not a failure — it routes
|
||||
the spec to the human who was going to review it anyway, the moment
|
||||
a real design question surfaces or the budget runs out.
|
||||
|
||||
**Auto-sign commits on `main` are forward-only like every other
|
||||
commit.** A later user veto is a forward correction (revert / revised
|
||||
spec / `git checkout` of downstream working-tree work), never a
|
||||
history rewind — same discipline as any other orchestrator call (see
|
||||
`boss` § Direction freedom).
|
||||
**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.
|
||||
|
||||
### Step 7 — Hand off to `planner`
|
||||
|
||||
@@ -468,11 +455,13 @@ Hand off carries:
|
||||
|
||||
## The Bounce-Back
|
||||
|
||||
`specify` returns to `brainstorm` whenever the precondition fails — the
|
||||
sources do not resolve a load-bearing design decision (Step 1.5), or a
|
||||
`grounding-check` `BLOCK` reveals an unratified mechanism the user does
|
||||
not override (Step 5 failure-mode routes to a re-design). On a
|
||||
precondition bounce:
|
||||
`specify` returns to `brainstorm` whenever the precondition fails — a
|
||||
load-bearing fork turns on **pure user preference** the orchestrator
|
||||
cannot derive (Step 1.5), or a `grounding-check` `BLOCK` reveals an
|
||||
unratified mechanism the user does not override (Step 5 failure-mode
|
||||
routes to a re-design). A fork the orchestrator *can* derive an answer
|
||||
for is **not** a bounce — it is decided and recorded in the reference
|
||||
issue. On a precondition bounce:
|
||||
|
||||
1. Nothing was written yet (the gate fires *before* Step 3), so there
|
||||
is no working-tree artefact to discard.
|
||||
@@ -481,8 +470,9 @@ precondition bounce:
|
||||
planner` path runs.
|
||||
|
||||
The bounce-back is not a failure of this skill; it is the skill
|
||||
correctly refusing to ratify an un-chosen design into a spec — the same
|
||||
discipline `tdd` applies when behaviour is not test-specifiable.
|
||||
correctly refusing to ratify a *pure-preference guess* into a spec — the
|
||||
same discipline `tdd` applies when behaviour is not test-specifiable. It
|
||||
is narrow by design: only the user's-call forks bounce, not every fork.
|
||||
|
||||
## Handoff Contract
|
||||
|
||||
@@ -491,9 +481,10 @@ discipline `tdd` applies when behaviour is not test-specifiable.
|
||||
| user / issue (design settled) → `specify` | the sources: issue body, in-context design discussion, design docs |
|
||||
| `brainstorm` → `specify` | ratified design narrative (approaches chosen, constraints, sections approved) — in-context; brainstorm writes no spec file |
|
||||
| `specify` → `grounding-check` (Step 5) | `spec_path` (absolute) + `iteration_scope` |
|
||||
| `specify` → `spec-skeptic` panel (Step 6, `/boss` only) | `spec_path` (absolute) + `iteration_scope` + one `lens` per dispatch (five in parallel) + `seeding_issue` (index for the `scope-fork` juror to read, or `none`) |
|
||||
| `specify` → `spec-skeptic` bias-breaker (Step 1.5, optional, orchestrator's call) | `spec_path` (absolute) + `iteration_scope` + one `lens` + `seeding_issue` (or `none`); dispatched ad hoc for a fork the orchestrator is deciding, never as a gate |
|
||||
| `specify` → reference issue (Step 1.5) | a derived-decision comment (rationale) or user-decision comment (provenance); a freshly created seeding issue if the cycle had none |
|
||||
| `specify` → `planner` (Step 7, on PASS or overridden BLOCK) | path to spec + iteration scope |
|
||||
| `specify` → `brainstorm` (precondition bounce) | the unresolved design question as a cycle request; no spec written |
|
||||
| `specify` → `brainstorm` (precondition bounce, pure-preference fork) | the unresolved design question as a cycle request; no spec written |
|
||||
| `specify` → issue backlog (Step 5, no-override BLOCK) | new issue naming the unratified dependency; spec file deleted from the working tree |
|
||||
|
||||
## Common Rationalisations
|
||||
@@ -501,17 +492,22 @@ discipline `tdd` applies when behaviour is not test-specifiable.
|
||||
| Excuse | Reality |
|
||||
|--------|---------|
|
||||
| "The issue looks exhaustive — skip the grounding-check / criterion too" | The interview is what `specify` skips, by design. The production gates are not the interview; they are what keeps the spec honest no matter how it entered. Skipping a gate because the sources look thorough is the exact reactive-deference failure this skill must not reintroduce. |
|
||||
| "There's a small open fork but the sources mostly decide it — I'll pick the rest" | "Mostly decided" with one real fork left is an unresolved design, and a guessed design baked into a spec is harder to dislodge than an open question. That is the bounce-back trigger — stop and go to `brainstorm`. |
|
||||
| "Genuine doubt whether the sources resolve this — but bouncing feels like overkill" | Doubt about whether the sources resolve a decision *is* the fork signal. It resolves to a bounce, not a guess. The bounce is cheap (nothing is written yet); a wrong guess in a ratified spec is not. |
|
||||
| "There's an open fork left — I should bounce to `brainstorm` to be safe" | Only if it is a *pure-preference* fork. If you can derive an answer — sources, code, consistency, risk — decide it boldly, record the rationale in the reference issue, and proceed. Bouncing a fork you can actually decide is the reactive-deference reflex the new stance retired. |
|
||||
| "I can derive an answer but I'm not 100% sure it's right — safer to bounce" | Being wrong on a *derived* call is allowed: the net is the user's veto and the `/boss` rollback sandbox. If you're unsure your leaning is judgement not bias, pull one ad-hoc `spec-skeptic` lens and weigh it — then decide. Reserve the bounce for forks only the user's preference can settle. |
|
||||
| "This is pure product taste but one option seems fine — I'll just pick it" | A fork with no derivable better is the user's call; picking it is the pure-preference guess the gate still forbids. Bounce it, or under `/boss` route to the human sign-off pause. The line is *derivable vs. preference*, not *small vs. large*. |
|
||||
| "The shape is clear from the prose, I don't need to paste the code" | If it's clear, pasting it is free; if pasting it is hard, it wasn't clear. The acceptance criterion is unjudgeable without the worked code. |
|
||||
| "Just polishing a wording after PASS, no need to re-dispatch" | The grounding-check report attests to specific bytes. A polish edit changes the bytes; the attestation no longer covers them. Re-dispatch is cheap. |
|
||||
| "It's in a model doc / the design ledger, so it's canonical" | A `models` / RFC / proposal doc holds aspirational code — a target, not verified fact. Flag code lifted from a `status: aspirational` source as such; it is not ratified contract. |
|
||||
| "In `/boss` this spec looks solid — I'll sign and move on" | Your sense that it looks solid is the exact signal the auto-sign gate refuses to trust. Signing requires all objective gates green AND a unanimous `spec-skeptic` panel. If you find yourself wanting to sign on confidence, that is the cue to run the gate, not to skip it. |
|
||||
| "One lens blocked on something minor — I'll sign anyway since the rest passed" | The panel is unanimous-or-nothing by design. You never *sign over* a `BLOCK`. An editorial `BLOCK` you may *repair* (within the ≤ 2-round budget, with a full re-panel after); a design `BLOCK` routes to the human. Neither is overruling a juror — that is the whole point of replacing your eye with five independent ones. |
|
||||
| "In `/boss` this spec looks solid — I'll sign and move on" | Your sense that it looks solid is not the signature. Under `/boss` the signature is the Step-5 `grounding-check` `PASS` — an independent agent's verdict, not your confidence. Run the grounding-check; a no-override `BLOCK` routes to the human, never auto-signed over. |
|
||||
| "A grounding `BLOCK` looks like a false alarm — I'll sign over it" | With no human in the loop there is no override. A no-override grounding `BLOCK` is the one objective denial of an autonomous sign; it routes to the human sign-off pause. The whole point of trusting grounding-PASS as the signature is that you also honour its `BLOCK`. |
|
||||
|
||||
## Red Flags — STOP
|
||||
|
||||
- An unresolved design fork silently picked instead of bounced (any flavour)
|
||||
- A *pure-preference* fork silently picked instead of bounced — or its
|
||||
inverse: a *derivable* fork bounced to `brainstorm` instead of decided
|
||||
(the reactive-deference reflex the new stance retired)
|
||||
- A derived fork decision made but **not recorded** in the reference
|
||||
issue (no rationale comment, or no reference issue at all on a `/boss` run)
|
||||
- "The sources are thorough, skip a gate" thoughts (any flavour)
|
||||
- A load-bearing change described in prose with no before → after code
|
||||
block; a surface cycle with no worked user-facing example
|
||||
@@ -519,14 +515,14 @@ discipline `tdd` applies when behaviour is not test-specifiable.
|
||||
flagging it as a target, not verified fact
|
||||
- Editing the spec file after a Step 5 PASS without re-dispatching
|
||||
- (auto-sign) About to sign a spec in the user's place on confidence —
|
||||
without all objective gates green AND a unanimous `spec-skeptic`
|
||||
panel; signing over any `BLOCK`; self-correcting a *design*-lens
|
||||
(`scope-fork` / `grounding`) `BLOCK` instead of escalating; or
|
||||
re-dispatching only the blocked lens rather than all five, or past
|
||||
the 2-round self-correction budget
|
||||
- (auto-sign) Running the panel before the objective gates are green,
|
||||
or running it outside a `/boss` session (interactive runs take the
|
||||
user's signature directly)
|
||||
rather than on the Step-5 `grounding-check` `PASS` that is the
|
||||
autonomous signature; or signing over a no-override grounding `BLOCK`
|
||||
/ `INFRA_ERROR` instead of routing it to the human sign-off pause
|
||||
- (auto-sign) Treating the retired `spec-skeptic` panel as still a gate
|
||||
— re-introducing a unanimous five-juror pass as a sign precondition,
|
||||
rather than using `spec-skeptic` only as the optional Step-1.5
|
||||
bias-breaker; or running any auto-sign path outside a `/boss` session
|
||||
(interactive runs take the user's signature directly)
|
||||
- Jumping straight from spec to `implement` (must go via `planner`)
|
||||
- Running an interview here (that is `brainstorm`'s job — if the work
|
||||
needs one, bounce)
|
||||
@@ -544,15 +540,15 @@ discipline `tdd` applies when behaviour is not test-specifiable.
|
||||
- **Agent dispatched:** `agents/grounding-check.md` — dispatched in
|
||||
Step 5 as a hard-gate. Reads the spec with fresh context and reports
|
||||
PASS / BLOCK / INFRA_ERROR.
|
||||
- **Agent dispatched (auto-sign):** `agents/spec-skeptic.md` —
|
||||
dispatched in Step 6 five times in parallel (one per lens) under
|
||||
a `/boss` session. Each
|
||||
juror tries to refute the spec along its lens; a unanimous `SOUND` is
|
||||
what lets the orchestrator sign in the user's place. An editorial-lens
|
||||
`BLOCK` (`criterion` / `ambiguity` / `plan-readiness`) is self-
|
||||
corrected in a bounded loop (≤ 2 rounds, full re-panel each round); a
|
||||
design-lens `BLOCK` (`scope-fork` / `grounding`), an `INFRA_ERROR`, or
|
||||
an exhausted budget falls back to the human sign-off pause.
|
||||
- **Agent dispatched (optional bias-breaker):** `agents/spec-skeptic.md`
|
||||
— an ad-hoc tool, **not** a gate. Under `/boss`, when the orchestrator
|
||||
is deciding a load-bearing fork in Step 1.5 and is unsure whether its
|
||||
leaning is judgement or bias, it MAY dispatch one (or a few)
|
||||
`spec-skeptic` lens(es) for an independent refutation to weigh. The
|
||||
lens returns a finding; the orchestrator decides. The former obligatory
|
||||
unanimous five-lens auto-sign panel is retired (baseline tag
|
||||
`pre-autosign-rework`); the autonomous signature is now the Step-5
|
||||
`grounding-check` `PASS`.
|
||||
- **Ad-hoc dispatch.** The orchestrator MAY also ad-hoc dispatch
|
||||
`../planner/agents/plan-recon.md` during Step 1 when the work enters
|
||||
code territory not recently read; discretionary, not part of the
|
||||
|
||||
Reference in New Issue
Block a user