feat(specify): bound the auto-sign panel with an editorial self-correction loop
The spec-skeptic auto-sign panel was one-shot: under /boss with spec_auto_sign on, any panel BLOCK fell straight back to the human sign-off pause. Because the panel is adversarial-by-design and rarely returns a unanimous SOUND, /boss escalated to the user even for defects the orchestrator could mechanically repair. Partition the five lenses by what a BLOCK means and run Step 6 as a bounded loop: - Editorial (criterion, ambiguity, plan-readiness) — the spec is under-articulated; the orchestrator self-corrects in place, re-runs Step 4 + Step 5, and re-dispatches all five lenses. - Design (scope-fork, grounding) — the ground is not settled; escalate, never self-correct. Re-loop limit: <= 2 rounds, the 3rd unresolved editorial BLOCK escalates (hard-coded N, matching implement-orchestrator's idiom). INFRA_ERROR and exhausted budget escalate too. Auto-sign still requires a fresh unanimous SOUND on a green objective gate. Re-dispatching all five lenses every round is the backstop: an editorial repair that launders an unsourced design decision is caught by the re-run scope-fork / grounding jurors and escalates. A criterion repair is bounded to supplying the worked evidence the criterion already demands — not re-judging acceptance (architect drift item). specify/SKILL.md owns the loop; spec-skeptic.md keeps the juror lens-agnostic; boss/SKILL.md, README.md, docs/profile-schema.md and docs/pipeline.md are synced to the new semantics. closes #6
This commit is contained in:
+51
-12
@@ -328,17 +328,50 @@ gate then depends on the profile slot `pipeline.boss.spec_auto_sign`:
|
||||
`plan-readiness`. Carrier per dispatch: `spec_path` (absolute),
|
||||
`iteration_scope`, and the single `lens`. Each juror tries to
|
||||
*refute* the spec along its lens and returns `SOUND` / `BLOCK` /
|
||||
`INFRA_ERROR`.
|
||||
`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.
|
||||
|
||||
| Panel outcome | Orchestrator action |
|
||||
|---------------|---------------------|
|
||||
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 `BLOCK` or `INFRA_ERROR` | **No auto-sign.** Fall back to the human sign-off pause; the notify carries which lens(es) blocked and their findings, so the user sees why it routed to them. |
|
||||
| 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. |
|
||||
|
||||
The fall-back is not a failure — it is the panel correctly routing a
|
||||
spec to the human who was going to review it anyway. A unanimous
|
||||
`SOUND` is the *only* thing that lets the orchestrator sign;
|
||||
"the spec looks good to me" never is.
|
||||
**Re-loop limit: ≤ 2 self-correction rounds. The 3rd unresolved
|
||||
editorial `BLOCK` escalates** — same shape as the per-task re-loop
|
||||
limit in `implement-orchestrator`.
|
||||
|
||||
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
|
||||
@@ -399,7 +432,7 @@ discipline `tdd` applies when behaviour is not test-specifiable.
|
||||
| "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. Code lifted from a `status: aspirational` source must clear the Step-4 parse gate like any other block. |
|
||||
| "In `/boss` with auto-sign on, 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. One `BLOCK` routes the spec to the human who was going to review it regardless. You do not get to overrule a juror; that is the whole point of replacing your eye with five independent ones. |
|
||||
| "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. |
|
||||
|
||||
## Red Flags — STOP
|
||||
|
||||
@@ -414,7 +447,10 @@ discipline `tdd` applies when behaviour is not test-specifiable.
|
||||
- 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; or overruling a single juror's `BLOCK`
|
||||
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 at all when `spec_auto_sign` is not enabled
|
||||
- Jumping straight from spec to `implement` (must go via `planner`)
|
||||
@@ -438,8 +474,11 @@ discipline `tdd` applies when behaviour is not test-specifiable.
|
||||
dispatched in Step 6 five times in parallel (one per lens) ONLY under
|
||||
a `/boss` session with `pipeline.boss.spec_auto_sign` enabled. Each
|
||||
juror tries to refute the spec along its lens; a unanimous `SOUND` is
|
||||
what lets the orchestrator sign in the user's place. Any `BLOCK`
|
||||
falls back to the human sign-off pause.
|
||||
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.
|
||||
- **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; opt-in, not part of the standard
|
||||
|
||||
@@ -23,16 +23,17 @@ eye. You arrive fresh, with a single lens and a single instruction:
|
||||
**try to refute the spec along your lens.** You are not asked "is
|
||||
this spec roughly fine?" — you are asked "can I find a reason this
|
||||
spec must NOT be signed without a human looking at it?" If you can,
|
||||
you `BLOCK`, and the auto-sign collapses back to a human sign-off
|
||||
pause. Your loyalty is to the refutation, not to the orchestrator's
|
||||
momentum.
|
||||
you `BLOCK`, and auto-sign is denied this round — at worst routing the
|
||||
spec to the human sign-off pause it would have hit anyway. Your loyalty
|
||||
is to the refutation, not to the orchestrator's momentum.
|
||||
|
||||
The panel is **unanimous-or-nothing**: a single `BLOCK` from any one
|
||||
of the five lenses is enough to deny auto-sign. So you do not need to
|
||||
catch everything — only your own lens. Lean toward `BLOCK` when in
|
||||
doubt; the cost of a false `BLOCK` is one human sign-off the user was
|
||||
going to do anyway, while the cost of a false `SOUND` is an unreviewed
|
||||
spec ratified into the pipeline.
|
||||
doubt; the cost of a false `BLOCK` is, at worst, one human sign-off the
|
||||
user was going to do anyway (and often just a cheap repair-and-re-panel),
|
||||
while the cost of a false `SOUND` is an unreviewed spec ratified into
|
||||
the pipeline.
|
||||
|
||||
## The lens you are assigned
|
||||
|
||||
@@ -133,13 +134,16 @@ it is the rubber-stamp the human sign-off was protecting against.
|
||||
| Status | Meaning |
|
||||
|--------|---------|
|
||||
| `SOUND` | After an honest refutation attempt along this lens, no defect found. This juror permits auto-sign. |
|
||||
| `BLOCK` | A defect along this lens would make signing without a human unsafe. Auto-sign is denied; specify falls back to a human sign-off pause and shows this report. |
|
||||
| `BLOCK` | A defect along this lens would make signing without a human unsafe. Auto-sign is denied this round. What `specify` does next depends on your lens class — an editorial defect it may repair and re-panel, a design defect it routes to the human — but that is the orchestrator's call (defined in `../SKILL.md` Step 6), not yours. |
|
||||
| `INFRA_ERROR` | The dispatch cannot complete (spec missing, no/invalid `lens`, workspace does not build for a `grounding` test-list, etc.). Auto-sign is denied; orchestrator falls back to human sign-off. |
|
||||
|
||||
There is no override path here and no "needs context": you are one of
|
||||
five jurors and the panel is unanimous-or-nothing, so an
|
||||
honest `BLOCK` simply routes the spec to the human who was going to
|
||||
review it anyway.
|
||||
five jurors and the panel is unanimous-or-nothing. Report the defect
|
||||
you found along your lens, full stop — do not soften a `BLOCK` because
|
||||
you guess the orchestrator will only repair it, and do not escalate
|
||||
your own verdict to "this needs a human." How a `BLOCK` is handled is
|
||||
decided in `../SKILL.md` Step 6 by lens class; your job is the honest
|
||||
verdict, not its routing.
|
||||
|
||||
## Output format
|
||||
|
||||
|
||||
Reference in New Issue
Block a user