From 52c87d19cee8fdd468d64d0f62204eb904b56e8d Mon Sep 17 00:00:00 2001 From: Brummel Date: Thu, 2 Jul 2026 12:34:04 +0200 Subject: [PATCH] fix(boss): done-state is queue-empty-of-autonomously-doable, not primary-task-complete MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A /boss run whose closing gate (audit / milestone fieldtest) surfaces new follow-up work no longer stops at a manufactured done-state: the follow-ups — routed inline or filed onto the tracker — re-enter the queue and take the direction-freedom test, and the loop continues onto the autonomously-doable subset. Being discovered after the primary task, or falling outside the originally discussed scope, is not a stopping reason. The done-state check gains its two edges everywhere it is stated (Overview, exit list, Iron Law, Step 1, Step 4, notify state 1): - closing-gate follow-ups re-enter the queue; primary-task-complete is a sub-goal, never a done-state; - a queue of only user-reserved leftovers (idea items, user-reserved acts) IS a legitimate done-state, named in the notify — while a remaining design fork stays a bounce-back (triggers 1/4, problem-state notify), never a done-state wrap-up; when both remain, the bounce governs. Plus a rationalisation-table row and a red flag pinning the observed failure shape (file the fieldtest findings, then declare done). closes #21 --- boss/SKILL.md | 92 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 71 insertions(+), 21 deletions(-) diff --git a/boss/SKILL.md b/boss/SKILL.md index 3ca19bd..beb16c5 100644 --- a/boss/SKILL.md +++ b/boss/SKILL.md @@ -13,8 +13,9 @@ Autonomous orchestrator mode is how the orchestrator moves a project forward when the user is away. Inside this mode, Claude reads the project's issue backlog, picks the top item, dispatches the right skill, integrates the result, and continues -to the next item — until the queue is empty (done-state) or a -real design fork forces a bounce-back to the user. +to the next item — until the queue holds nothing more it can do +autonomously (done-state) or a real design fork forces a +bounce-back to the user. Outside this mode, the default is interactive collaboration: the user asks; Claude answers or executes the specific request; @@ -44,8 +45,8 @@ May be exited mid-session by: - The user signalling "stop", "pause", or "back to chat". - A bounce-back trigger firing (see "Direction freedom" below). -- Done-state (the queue is empty and the done-state procedure has - fired). +- Done-state (the queue holds nothing autonomously-doable and the + done-state procedure has fired). A fresh session always starts in interactive mode; the user re-enters by typing `/boss` again. @@ -54,7 +55,7 @@ re-enters by typing `/boss` again. ``` NO AUTONOMOUS DISPATCH OUTSIDE A `/boss` SESSION. -DONE-STATE = QUEUE EMPTY, NOT SUB-GOAL COMPLETE. +DONE-STATE = QUEUE EMPTY OF AUTONOMOUSLY-DOABLE ITEMS, NOT SUB-GOAL COMPLETE. BOUNCE-BACK ONLY ON THE FOUR NAMED TRIGGERS. A NEW CYCLE'S DESIGN RUNS AUTONOMOUSLY VIA THE `brainstorm` SWARM — IT DECIDES THE CONVERGENT (CITED-GROUND) FORKS AND BOUNCES ONLY A DIVERGENT DIRECTION @@ -83,8 +84,10 @@ facts. If the project names no issue tracker there, it does not have an autonomously addressable queue — bounce back to the user with that diagnosis. -If the entire open backlog is empty: skip to Step 5 -(done-state). Do not invent work; an empty queue is a real +If the entire open backlog is empty — or holds only user-reserved +leftovers (`idea`-labelled items, user-reserved acts; an open +design fork bounces via Step 2 instead) — skip to Step 5 +(done-state). Do not invent work; an exhausted queue is a real signal that the cycle closed and there is nothing left. ### Step 2 — Pick the top item per direction-freedom rules @@ -245,9 +248,35 @@ For each dispatched skill's result, decide: the queue is non-empty. Most common case. - **Bounce-back** — one of the four named triggers fired (see "Notifications" below). Send a notify, stop the loop. -- **Done-state** — queue is empty AND the cycle is fully - ratified (audit drift-clean, fieldtest clean if applicable). - Go to Step 5. A `/boss` done-state means this run has nothing +- **Done-state** — the queue is empty of **autonomously-doable** + items AND the cycle is fully ratified (audit drift-clean, + fieldtest clean if applicable). Go to Step 5. The check has two + edges: + - **Closing-gate follow-ups re-enter the queue.** Follow-up + work this run's own closing gate surfaced — an audit drift + item, a fieldtest `bug` or `friction` finding — is queue work + like any other, whether it was routed inline (the skills' + documented dispositions) or filed onto the tracker (the + milestone shape). Walk each through the direction-freedom + test (§ Direction freedom): a clear, fork-free follow-up — a + bug with an established fix pattern, a mechanical edit, a + test-specifiable feature — sends the loop back to Step 2, no + matter that it was discovered *after* the primary task rather + than before. Primary-task-complete is a sub-goal, never a + done-state. + - **A queue of only user-reserved leftovers IS done-state.** + When everything still open genuinely needs the user without + blocking on a decision — an `idea`-labelled item (droppable + by definition; its triage is the user's prioritisation call) + or a user-reserved act (push, formal milestone close, + external-service consent) — the run is done; name those + leftovers in the notify. A remaining **design fork** is the + one user-reserved residue that is *not* done-state: it + matches bounce-back triggers 1/4 and takes the problem-state + notify's actionable ask, not the done-state wrap-up. When + both kinds remain, the bounce governs. + + A `/boss` done-state means this run has nothing left to dispatch; it is **not** an automatic milestone close — closing a tracker milestone needs its end-to-end milestone fieldtest green and stays a deliberate manual act (see @@ -284,6 +313,19 @@ the user, latency on my side — exceeds the expected cost of discarding or rolling back a bad state. So when the queue is non-empty and the path is clear, just pick and proceed. +The same test is the **done-state discriminator**. An open item is +**autonomously-doable** when it has a clear path with no genuine design +fork (a bug with an established fix pattern, a mechanical/type edit, a +test-specifiable feature) and requires no user-reserved act (no push, no +formal milestone close, no external-service consent). Follow-ups the +run's own closing gate discovered — audit drift items, fieldtest +findings, routed inline or filed onto the tracker — re-enter the queue +and take the same test; being discovered *after* the primary task does +not make an item a stopping point, and a narrow reading of the original +task's scope does not either. The run stops only when what remains is +empty or entirely user-reserved — a done-state for `idea` items and +user-reserved acts, a bounce-back for a fork (Step 4). + ### The reference issue (mandatory) Every `/boss` run is anchored to a tracker issue — the one that seeded @@ -416,16 +458,22 @@ question. Two states call for a notify; nothing else does — plus a third, narrow one for spec auto-sign: -1. **Done-state.** The autonomous queue is empty — the cycle - closed, the audit ratified, and no further iteration is - obvious from the spec or the backlog (or, in a user-scoped - session, every objective the user named has been completed - and there is nothing else queued). A finished sub-goal - inside a still-open cycle is *not* done-state. If the next - iteration is obvious and substantive, keep dispatching — - "test suite landed", "audit clean before close-fixes", - "iter N done with N+1 in scope" are internal progress, not - notify events. +1. **Done-state.** The queue is empty of autonomously-doable + items — the cycle closed, the audit ratified, and nothing + the direction-freedom test clears is left open (or, in a + user-scoped session, every objective the user named has been + completed and no autonomously-doable follow-up is queued — + including ones this run's own closing gate just surfaced; a + narrow scope reading does not halt the run on a clear, + fork-free follow-up). A queue holding only user-reserved + leftovers — `idea`-labelled entries, user-reserved acts — is + a legitimate done-state; name them in the notify. A remaining + design fork is not: it bounces as problem-state (state 2). A + finished sub-goal inside a still-open cycle is *not* + done-state. If the next iteration is obvious and + substantive, keep dispatching — "test suite landed", + "audit clean before close-fixes", "iter N done with N+1 in + scope" are internal progress, not notify events. 2. **Problem-state.** A bounce-back trigger per §"Direction freedom" — design fork the orchestrator cannot resolve, an @@ -685,7 +733,8 @@ the user wants it — there is no autonomous filing to govern. | Excuse | Reality | |--------|---------| | "Iteration just landed cleanly, let me notify so user can see" | Mid-flow notifications burn user attention without giving them a decision to make. Iteration-clean is internal progress, not a notify event. | -| "Sub-goal of the cycle is done, that counts as done-state" | Done-state is queue-empty, not sub-goal-complete. If the next iteration is obvious and substantive, keep dispatching. | +| "Sub-goal of the cycle is done, that counts as done-state" | Done-state is queue-empty-of-autonomously-doable, not sub-goal-complete. If the next iteration is obvious and substantive, keep dispatching. | +| "Primary task done, the audit/fieldtest findings are filed as issues — that's a wrap, notify done-state" | Filing the findings *repopulated the queue* — and findings routed inline instead (a `bug` → `debug`, a drift item → tidy iteration) are queue work all the same. Each follow-up takes the direction-freedom test like any other item: a clear, fork-free bug or mechanical edit continues the loop — being discovered after the primary task is not a stopping reason. Only a residue of `idea` items and user-reserved acts is a legitimate done-state; a remaining fork bounces instead. | | "Top of the backlog has two equally good options, I'll just pick one" | If both are substantive and the choice is non-obvious, that's a real fork — bounce back. The cost of a wrong pick (working-tree discard) is higher than the cost of one short ping to the user. | | "User said 'until X then notify', X just completed, notify now" | Check whether X was actually the last actionable thing. If hitting X leaves an open cycle with obvious follow-up, the user's intent was "wake me when there's nothing else to do" — continue. | | "Notify can name the iteration code — user will figure out what it means" | No. The notify text is for the user-as-reader who did not watch the orchestrator work. Iteration codes, crate names, function identifiers, type names — all internal, all banned. | @@ -710,6 +759,7 @@ the user wants it — there is no autonomous filing to govern. ## Red Flags — STOP - About to send a notify on an internal-progress event (test suite landed, audit clean before close-fixes, iter N done with N+1 in scope). +- About to declare done-state while the queue holds a follow-up that passes the direction-freedom test — including one this run's own closing gate just surfaced. Primary-task-complete is a sub-goal; "discovered after the primary task" and "outside the originally discussed tickets" are not stopping reasons. (The inverse holds too: a queue of only `idea` items and user-reserved acts IS done-state — do not grind through user-reserved work to avoid the notify; a remaining design fork bounces as problem-state instead.) - About to dispatch the next skill without checking that the previous output was actually good. - About to autonomously dispatch in a session where the user did NOT type `/boss`. - About to send a notify that names a crate, an iteration code, or an agent.