@tacuchi/agent-workflow-cli 20.17.0 → 20.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -58,7 +58,7 @@ Read **[`../CHASSIS.md`](../CHASSIS.md)** — the loop's **full engine** — **a
58
58
  - **`Recortar alcance`** → the AI proposes the **sub-task that DOES fit** a quick; the loop continues with it (`SESSION.Objective` = the sub-task; the original prompt goes into the session's `## Origin`) and the rest is deferred to `BACKLOG` ("trimmed at the gate — may warrant its own spec, `/w:spec-new`").
59
59
  - **Anti-duplicate** (the `create_or_resume` spirit): if a spec whose `## Origin` references this same objective already exists (or an equivalent `*-spec-refine` session), the recommended option becomes **resuming that spec** (`/w:spec-refine` semantics) — never a second draft.
60
60
  - **Live transition to SPEC** (shared by the gate and mid-loop escalation). On acceptance, the work line **moves to the SPEC flow**: the explicit consent in the structured-choice **equals invoking the destination command** (*consented exception* — rule 3 of the *Continuity rule*, [`../../SKILL.md`](../../SKILL.md) § *Operating context*). On the SPEC side:
61
- 1. **Materialize the draft** via the [`../../commands/spec-new.md`](../../commands/spec-new.md) procedure: `aw next-number docs/specs`, slug, schema, single-pass **NO RESEARCH**. `## Origin` = "escalated from `/w:quick`" + the original prompt (+ the origin quick session if it exists).
61
+ 1. **Materialize the draft** via the [`../../commands/spec-new.md`](../../commands/spec-new.md) procedure: `aw next-number docs/specs`, slug, schema, single-pass **NO RESEARCH** — its bounded reconnaissance does **not** re-fire (this run's context arrives adopted). `## Origin` = "escalated from `/w:quick`" + the original prompt (+ the origin quick session if it exists). The draft is born `status: draft`: only the SPEC gate promotes it to `ready-for-plan`.
62
62
  2. **Load and execute** [`../spec-refine-loop/LOOP.md`](../spec-refine-loop/LOOP.md) — over that spec (trampoline pattern).
63
63
  3. The run's session is that loop's **normal** `NNN-<slug>-spec-refine` (the CLI numbers it; its `## Origin` records the escalation). **Invariant 2 intact**: quick, while it is quick, never writes `docs/` — the draft is written by the SPEC flow, post-consent.
64
64
  - **Mid-loop escalation + handoff**: if the task grows (same gate signals) → propose moving up to **SPEC/PLAN** (structured-choice, recommendation first). If the user accepts:
@@ -2,13 +2,13 @@
2
2
  name: spec-refine-loop
3
3
  description: >-
4
4
  Refines a draft spec (docs/specs/NNN-spec-<slug>.md) by editing it IN PLACE
5
- until it is unambiguous. Heir of the chassis (loops/CHASSIS.md). Deltas:
6
- spec gap taxonomy, analyze gate, ideation gate (consented brainstorming,
7
- optional web-research), ## UI spec section via the ui-design
8
- capability, and adds Refinement decisions the refined mark plan-new
9
- detects. Started by /w:spec-refine (or the live escalation
10
- from quick-loop); resumable via CHECKPOINT and re-runnable on demand.
11
- Invoke to refine/disambiguate a specification before planning.
5
+ until PLAN can design without inventing behavior, scope or product
6
+ decisions. Heir of the chassis (loops/CHASSIS.md). Deltas: current-behavior
7
+ baseline, change-shape gate, gap taxonomy classified by destination,
8
+ conditional ideation gate, ## UI spec via the ui-design capability, and the
9
+ ready-for-plan gate that stamps the status frontmatter plan-new reads.
10
+ Started by /w:spec-refine (or the live escalation from quick-loop);
11
+ resumable via CHECKPOINT and re-runnable on demand.
12
12
  ---
13
13
 
14
14
  # spec-refine-loop
@@ -30,11 +30,25 @@ SPEC
30
30
 
31
31
  It is also started by the **live escalation from `quick-loop`** (entry gate or mid-loop — see [`../quick-loop/LOOP.md`](../quick-loop/LOOP.md) § *QUICK delta*): quick materializes the draft (`spec-new` procedure) and **loads this loop** over that spec — same semantics as if the user had run `/w:spec-refine`.
32
32
 
33
+ ## Convergence target
34
+
35
+ > **READY FOR PLAN, NOT PERFECTLY CLOSED**
36
+ >
37
+ > Converge when the spec defines behavior and scope well enough that PLAN can design the solution without inventing functional decisions. Do NOT close in SPEC the architecture or implementation questions that can be answered later without changing the contract.
38
+
39
+ Closing *every* gap turns the spec into a premature plan. Close what changes **what** gets built; what only changes **how** travels to `PLAN` with its destination declared (§ *Gap taxonomy*).
40
+
33
41
  ## Reads
34
42
  - `docs/specs/NNN-spec*.md` (glob — locates the spec by number; also catches the legacy `NNN-spec.md`), **or** the exact path passed as the command argument. **Always the spec itself**: this loop edits it in place; there is no separate "refined" file.
35
43
 
44
+ > **Boundary with `spec-new`:** the draft arrives from a **bounded reconnaissance** of the surface ([`../../commands/spec-new.md`](../../commands/spec-new.md) § *Bounded reconnaissance*) — hypotheses, not verified facts. **Deep investigation is this loop's**: walk the dependencies, check those hypotheses, and close the doubts parked in `## Open questions`.
45
+
46
+ **Adopt, do not repeat.** `spec-new`'s **facts** are reused; its **assumptions** are re-validated **only when one blocks a gap**; its `Open questions` are re-classified by destination; its one-vs-many hypothesis is re-judged at the *Change-shape gate*. The shallow sweep is never re-run wholesale. Keep the labels distinct — a spec that blurs them cannot be gated: **fact** (backed by repo, data or docs) · **inference** (unproven) · **user decision** · **deferred decision** (owner declared) · **open question** (can still move the contract).
47
+
36
48
  ## Writes
37
- Updates `docs/specs/NNN-spec-<slug>.md` **in place** (when the user picks `Guardar especificación refinada`): completes sections and **adds** `## Refinement decisions`, closing `Open questions` as they get resolved. Since it overwrites an existing doc, it asks the user's **confirmation**.
49
+ Updates `docs/specs/NNN-spec-<slug>.md` **in place** (when the user picks `Guardar especificación refinada`): completes sections, **adds** `## Decisions`, closes `Open questions` as they get resolved, and stamps the frontmatter `status: ready-for-plan`. Since it overwrites an existing doc, it asks the user's **confirmation**.
50
+
51
+ > **Not every shape decision creates a file** (§ *Change-shape gate*). An accepted **split** writes the reduced original **and** the extracted sibling specs; a replacement by **`Crear una nueva spec`** writes one new file and leaves this one untouched; **`Reformular esta spec`** creates nothing — it edits this same file, same number, same path. Every write, new or overwriting, is confirmed first.
38
52
 
39
53
  > **Boundary invariant:** this loop writes **only** into `docs/specs`. It never graduates/exports other artifacts to `docs/` — that is separate `export-*` work (chassis § *docs/ boundary*).
40
54
 
@@ -60,18 +74,56 @@ Other transversal capabilities the engine always uses: `research` (**inline**
60
74
 
61
75
  > **Ambient conventions (not roles):** code/testing/writing standards and `creating-tools` are standalone skills the host auto-discovers by `description` — Workline neither binds nor depends on them. Full doctrine: [../../roles/README.md](../../roles/README.md).
62
76
 
77
+ ## Current-behavior baseline (brownfield first)
78
+
79
+ When the project already exists, establish the current behavior the change rests on **before** describing the change: what happens today, which actor starts or receives it, which capabilities take part, which existing rules and observable limits shape the request — each with its source.
80
+
81
+ **Stop when the baseline is enough to state and accept the functional change** — not when the system is documented. Digging on to pick an architecture, anticipate tasks or map every dependency is `PLAN` work, and gold-plating here. Greenfield has no baseline: skip it — that is what makes `## Behavioral changes` earn its place or not.
82
+
83
+ ## Change-shape gate
84
+
85
+ Runs once the baseline exists and **before** closing details: the investigation can reveal the draft's shape was wrong. Does the spec still carry **one** functional outcome, did its purpose survive, can the delivery be accepted as a unit? The verdict is **one of three shapes** — `same` | `split` | `replace` — each with its own branch; only the last two ask anything.
86
+
87
+ > **Resolved before the gap loop starts, never carried into it (hard rule).** A `split` or a `replace` is asked, answered and applied **immediately** — its own structured-choice, in its own step, between the baseline and the first gap batch. It never travels in `pending_human`: that collection is rebuilt on every iteration and is reserved for questions about functional, technical or scope **gaps**, so a shape decision parked there is erased by the next batch — or never asked at all, because a spec with no blocking gap breaks out of the loop before the batch is built. The resolution lands in `CHECKPOINT` **before** anything else runs, so a resume re-enters with the shape already decided and never re-asks it.
88
+
89
+ - same outcome — more clarity, or more technical components → **`same`**: no shape question, keep refining this spec;
90
+ - independent functional outcomes discovered → **`split`** (below);
91
+ - purpose fundamentally changed → **`replace`** (below);
92
+ - refactor indispensable to the outcome → a consideration for `PLAN`, never its own spec; refactor with no functional change → out of the contract;
93
+ - evidence insufficient → **`same`** + the uncertainty recorded. Thin evidence never justifies a cut.
94
+
95
+ **Split criterion** — the one `spec-new` already uses ([`../../commands/spec-new.md`](../../commands/spec-new.md) § *Split gate (multi-spec)*), never a different one: divide **only** when each part can be refined, accepted and planned on its own. Repos, technologies, layers or teams are **secondary evidence**, never the reason.
96
+
97
+ **Split semantics (in place).** The offer enters the batch as a content question — `Dividir en varias specs` | `Una sola spec`; declining marks it **exhausted** for the run. On acceptance: the original **keeps its number/path**, rewritten reduced to its remaining outcome; each extracted outcome is minted with `aw next-number docs/specs` right before its write and is born **`status: draft`**. Siblings are **not** elaborated here — unlike the multi-plan gate, where `plan-exec` would break on a plan with no `## Tasks`; a draft spec is legitimate input to this very loop — so the run keeps refining the **reduced original** and reports `/w:spec-refine` as each sibling's next step. Every `## Origin` records "split from `docs/specs/NNN-spec-<slug>.md`" + the siblings **by path**. Closing action on this branch: `Guardar specs`.
98
+
99
+ **Replace semantics.** Its offer is its own — `Crear una nueva spec` | `Reformular esta spec`, **never** the split labels: what gets decided is which identity carries the new purpose. Recommend **a new spec** when the main functional outcome or the actor/consumer changed; **reformulating** when the user confirms this file is still the same unit of work and wants to keep its identity.
100
+
101
+ - **New spec:** this one is **preserved**, its purpose never silently rewritten; the new one is minted with `aw next-number docs/specs`, born **`status: draft`**, its `## Origin` recording the origin spec, the replaced purpose and the user's decision. Its path goes to the `CHECKPOINT`; the run closes reporting `/w:spec-refine <new path>` as the next step.
102
+ - **Reformulate:** same number/path, the work treated as `refining` while rewritten; baseline, gap classification and the *ready-for-plan gate* run again over the new purpose; `status` is stamped only on the save that follows the passing gate, and the material decision lands in `## Decisions`.
103
+
104
+ **Every branch has a way out that changes nothing.** The `flow` control present on every structured-choice (chassis) is that exit here: `Cerrar` closes the run **without applying the shape change** — no sibling minted, no spec reformulated, the document untouched and the decision recorded in `CHECKPOINT` as declined. And no branch writes a file without the user's confirmation: minting siblings and minting a replacement both go through the same confirm-before-write rule as an in-place save.
105
+
106
+ Neither branch adds a `superseded` status or archives the replaced spec: a historical close needs its own runtime contract, out of scope here.
107
+
63
108
  ## Deliverable schema (the spec, edited in place)
64
109
 
65
- The spec is completed **in place**: the draft's sections get **completed** + one new one is **added** (`Refinement decisions`). NO separate file is created.
110
+ The spec is completed **in place**: the draft's sections get **completed**, a few are **added**, and the frontmatter `status` is stamped. NO separate file is created.
66
111
 
67
112
  ```markdown
68
- # Spec NNN — <slug>
113
+ ---
114
+ status: ready-for-plan ← stamped on Guardar (vocabulary: draft | refining | ready-for-plan)
115
+ ---
69
116
 
70
- > Refined in place by spec-refine-loop
117
+ # Spec NNN <slug>
71
118
 
72
119
  ## Origin (opt. — preserved from the draft)
73
120
  ## Requirement (sharpened, unambiguous)
74
121
  ## Context (complete)
122
+ ## Affected capabilities (opt. — functional boundaries, NOT a repo list; only when the
123
+ change touches capabilities that already exist. The repos that
124
+ implement them belong in Context, as evidence or location)
125
+ ## Behavioral changes (opt. — behavior added / modified / removed / preserved; only
126
+ when existing behavior is touched — greenfield omits it)
75
127
  ## Scope (clear In / Out)
76
128
  ## Acceptance criteria (testable, - [ ]; EARS style; behavioral ones expand in ## Scenarios)
77
129
  ## Scenarios (opt. — GIVEN/WHEN/THEN/AND blocks; each traces to ≥1 criterion.
@@ -82,88 +134,118 @@ The spec is completed **in place**: the draft's sections get **completed** + one
82
134
  ## UI spec (opt. — if UI is involved; via the ui-design capability / ui-spec skill)
83
135
  Structured Markdown description (screens → regions/components). See [`ui-spec`](../../roles/ui-spec/ROLE.md).
84
136
 
85
- ## Refinement decisions NEW (ADDED) — the run's single trace
86
- What was defined while refining and why. Includes what inline research
87
- resolved (ref. the session's CONCLUSIONS), the ideation verdicts (§ Ideation
88
- gate) and every doubt asked to the human, as entries
89
- `Q: <question> → <chosen answer> — <rationale>`.
137
+ ## Decisions ← ADDED — the material decisions, NOT the run's history
138
+ The choices a reader needs in order to interpret the contract, each with its why.
90
139
 
91
- ## Open questions (whatever remains is deferred; OMIT the section when empty)
140
+ ## Open questions (each entry declares its destination; OMIT the section when empty)
92
141
  ```
93
142
 
94
- > **Refined mark (contract with PLAN):** the presence of `## Refinement decisions` distinguishes a refined spec from a draft plan-new detects it this way, NOT by filename; without that section plan-new soft-suggests spec-refine. *(Legacy specs also carry `## Q&A traceability` — they still count as refined; new runs never write it.)*
143
+ > **Ready mark (contract with PLAN):** the frontmatter **`status`** is the mark `ready-for-plan` means this gate passed and plan-new can proceed; `draft` and `refining` make it soft-suggest a refine first. It is machine state, never prose. *(Legacy specs carry no frontmatter: `## Refinement decisions` — and the older `## Q&A traceability` — still count as ready. A legacy mark does NOT skip the gate on a re-refine.)*
144
+
145
+ > **`## Decisions` is contract, not expedient.** Only the material decisions, each with its why — not the transcript of every question asked, file read, discarded alternative or progress step: that detail lives in the session (`CONCLUSIONS`, `CHECKPOINT`), which is where a reader of the contract should not have to go. *(It replaces `## Refinement decisions`, which stays the name of plan-refine's audit trace — that one has no `status` to take over as its prior-work mark.)*
146
+
147
+ > **`## Open questions` carries destinations.** Each entry states why it is still open, whether it blocks `ready-for-plan`, and where it goes: `PLAN`, the user, later research, another spec. A question may survive convergence **only** if it does not force `PLAN` to invent behavior.
95
148
 
96
149
  > **Acceptance criteria = static testable criteria** (the "what"): plan-exec validates them, but progress is tracked in the PLAN (its Tasks), never by ticking these `- [ ]` in the spec; the spec never mutates by execution, only by a re-refine.
97
150
 
98
- ## Gap taxonomy (= weak sections of the schema)
151
+ ## Gap taxonomy signal, resolver, destination
99
152
 
100
- `detect_gaps(work)` looks for these signals; each has a resolver:
153
+ `detect_gaps(work)` looks for these signals. Each is **classified by destination before its resolver is chosen**: closing a `PLAN`-owned question here is the failure mode this taxonomy exists to prevent.
101
154
 
102
- | Gap | Signal | Resolved by |
103
- |---|---|---|
104
- | Vague requirement | the what/why is ambiguous | **human** |
105
- | Incomplete context | systems/components unidentified | **research** |
106
- | Blurry scope | `Out` missing, or In/Out overlap | **human** |
107
- | Untestable criteria | acceptance not verifiable | **human** (derive + confirm — often as a `### Scenario`) |
108
- | Scenario missing | behavioral criterion whose behavior is NOT captured by its WHEN/THEN (needs GIVEN setup or edge semantics; a criterion a scenario would only restate 1:1 is not a gap) | the AI drafts GIVEN/WHEN/THEN + **human** confirms |
109
- | Open questions pending | explicit doubts | by nature |
110
- | Hidden assumptions | the spec assumes unstated things | **research** validates / **human** confirms |
111
- | Internal contradiction | sections contradict each other | **human** |
112
- | Over-specified requirement | scope/criteria gold-plated — beyond the actual need (chassis § *Minimality*) | **human** (AI proposes the cut, human ratifies) |
113
- | Unexplored solution space | the spec settles on the first conceivable approach no alternatives weighed nor adopted from the conversation | **human consents** **ideation** (see *Ideation gate*) |
114
- | UI unspecified *(if it applies)* | the requirement involves UI but `## UI spec` is missing | **`ui-design` capability** |
155
+ | Gap | Signal | Resolved by | Destination |
156
+ |---|---|---|---|
157
+ | Vague requirement | the what/why is ambiguous | **human** | SPEC — blocking |
158
+ | Blurry scope | `Out` missing, or In/Out overlap | **human** | SPEC — blocking |
159
+ | Business rule undefined | which condition decides an outcome | **research** or **human** | SPEC — blocking |
160
+ | Untestable criteria | acceptance not verifiable | **human** (derive + confirm — often as a `### Scenario`) | SPEC — blocking |
161
+ | Internal contradiction | sections contradict each other | **human** | SPEC blocking |
162
+ | Current behavior unknown | the baseline the change rests on is missing | **research** (inline) | SPEC → `Context` / `Behavioral changes` |
163
+ | Incomplete context | systems/components unidentified | **research** | SPEC |
164
+ | Scenario missing | behavioral criterion whose behavior is NOT captured by its WHEN/THEN (needs GIVEN setup or edge semantics; a criterion a scenario would only restate 1:1 is not a gap) | the AI drafts GIVEN/WHEN/THEN + **human** confirms | SPEC |
165
+ | Hidden assumptions | the spec assumes unstated things | **research** validates / **human** confirms | SPEC |
166
+ | Over-specified requirement | scope/criteria gold-plated beyond the actual need (chassis § *Minimality*) | **human** (AI proposes the cut, human ratifies) | SPEC |
167
+ | Unexplored solution space *(conditional)* | the spec settles on the first conceivable approach **and** a trigger fires (see *Ideation gate*) | **human consents** → **ideation** | SPEC — only on a trigger |
168
+ | UI unspecified *(if it applies)* | the requirement involves UI but `## UI spec` is missing | **`ui-design` capability** | SPEC |
169
+ | Architecture | how to distribute technical responsibilities | — | **`PLAN`** — declare, never close here |
170
+ | Implementation | library, class, method, pattern, folder layout | — | **`PLAN`** / `EXEC` — outside the spec |
171
+ | Executable technical risk | whether an integration really works | — | **`PLAN`** (probe), unless the answer changes the contract |
172
+ | Non-blocking detail | does not change what will be built | — | deferred, with destination |
173
+
174
+ **Blocking or not.** A gap **blocks SPEC** when its answer can change the outcome, the scope, a business rule, an actor, an acceptance criterion, or the one-vs-many decision. Anything else is recorded with its destination and the loop moves on.
175
+
176
+ **Resolution order** — the chassis *ask-vs-research rule* with the destination step in front: settled in the conversation → **adopt** · provable by reading repos or data → **research inline** · depends on what the user wants → **ask** · defines the technical solution without changing behavior → **hand to `PLAN`** · answerable later without touching the contract → **defer explicitly**.
115
177
 
116
178
  ## Ideation gate (creativity)
117
179
 
118
- The loop's one **divergent** gate: every other resolver closes a gap; this one widens the option space before the spec hardens around its first idea. It resolves **Unexplored solution space** in two consented steps:
180
+ The loop's one **divergent** gate: every other resolver closes a gap; this one widens the option space before the spec hardens around its first idea. **Unexplored solution space is not a universal gap** it stays shut unless a trigger fires, because exploring what is already decided burns context and invites gold-plating.
181
+
182
+ **Triggers (≥1).** The user knows the problem but not the desired outcome · several functional directions carry materially different consequences · the spec adopted the first alternative prematurely · a choice can materially change scope · the alternatives change experience, rules or acceptance · the user asks to explore.
183
+
184
+ **Not triggers.** More than one technical solution exists · no library is chosen yet · the system uses several technologies · every implementation admits alternatives · the request is already functionally clear. Purely technical alternatives belong to `PLAN`.
119
185
 
120
186
  1. **Offer & consent.** The gap enters the batch as a content question — `Explorar ideas` vs `Seguir sin ideación` — carrying the AI's recommendation like any other. Declining marks the gap **exhausted** (never re-offered this run); an explicit user request for ideas at any point counts as an accepted offer (on-demand entry). Alternatives already weighed in the conversation are *adopted context* — the gap does not fire.
121
187
  2. **Ideation round** (one per consent). Propose fresh ideas and **combinations** (the user's + found ones). If the host exposes **web-research** ([`../../harness/HARNESS.md`](../../harness/HARNESS.md)), the accepted offer also authorizes that round's web searches — no per-search consent; findings + sources land in the session's `CONCLUSIONS`, like inline research. Without the capability, ideate offline (own knowledge + workspace + repos) and **declare it** — never silently.
122
188
 
123
- **Verdicts (back to convergence).** Present the top ≤3 ideas via the same structured-choice, each with a recommended verdict: `Adoptar` → integrate into `Requirement`/`Scope`/criteria + trace in `## Refinement decisions` (idea, rationale, source/URL when web-found) · `Descartar` → one line + reason there · `Aparcar` → `## Open questions`. Ideas beyond the top 3 stay summarized in `CONCLUSIONS`. Divergence is bounded by *Minimality* (chassis): nothing enters the spec without an explicit `Adoptar`; the analyze gate keeps pruning gold-plating. This gate exists **only** in this loop — `spec-new` stays single-pass (no research, no web) and the plan/quick loops inherit none of it.
189
+ **Verdicts (back to convergence).** Present the top ≤3 ideas via the same structured-choice, each with a recommended verdict: `Adoptar` → integrate into `Requirement`/`Scope`/criteria + record it in `## Decisions` (the choice and its why, with the source/URL when web-found) · `Descartar` → the reason goes to `CONCLUSIONS`, not to the spec · `Aparcar` → `## Open questions` with its destination. Ideas beyond the top 3 stay summarized in `CONCLUSIONS`. Divergence is bounded by *Minimality* (chassis): nothing enters the spec without an explicit `Adoptar`. This gate exists **only** in this loop — `spec-new` stays single-pass (bounded reconnaissance at most, no web) and the plan/quick loops inherit none of it.
124
190
 
125
191
  ## Sequence
126
192
 
127
193
  ```
128
194
  spec-refine-loop(spec):
129
195
  input = glob(NNN-spec*.md) | argument (path) # always the spec itself (in place)
130
- refine_session = create_or_resume("<slug>-spec-refine") # <slug> from the input spec; CLI prepends global NNN; resume locates by descriptor/origin
131
- seed SESSION.Success criteria = acceptance criteria + analyze-gate checklist # verification-first: BEFORE iterating
196
+ refine_session = create_or_resume("<slug>-spec-refine") # <slug> from the spec; CLI prepends global NNN
197
+ seed SESSION.Success criteria = acceptance criteria + ready-for-plan checklist # verification-first, BEFORE
132
198
  work = read(input) (+ apply checkpoint progress if resuming)
199
+ adopt(spec-new facts + assumptions + open questions + conversation) # never re-derive (§ Reads)
200
+ baseline = resolve_current_behavior(work) # inline research, ONLY what the change rests on
201
+ shape = change_shape_gate(work, baseline) # BEFORE closing details → same | split | replace
202
+ if shape != same: # RESOLVED HERE — never queued into pending_human
203
+ ans = structured_choice(content: [the offer of THIS branch], # split and replace never share labels
204
+ flow: [Compactar, Cerrar])
205
+ write CHECKPOINT (the decision + its consequence) # BEFORE acting: a resume re-enters already decided
206
+ flow Cerrar → goto finalize # closed without applying the change; the spec stays untouched
207
+ `Una sola spec` → shape resolved as same; keep refining this spec
208
+ `Dividir en varias specs` → the accepted cut is fixed now; its writes wait for `Guardar specs`
209
+ `Crear una nueva spec` → mint draft with confirmation (## Origin) ; THIS spec untouched ;
210
+ CHECKPOINT.Next = refine it ; goto finalize
211
+ `Reformular esta spec` → same number/path ; re-run baseline + this gate before any stamp
133
212
  attempts = {} # anti re-fire per gap
134
213
  repeat:
135
- gaps = detect_gaps(work) minus the "exhausted" gaps
136
- if gaps == ∅: break
137
- batch = top ≤3 gaps ; pending_human = []
214
+ gaps = classify_by_destination(detect_gaps(work)) minus the "exhausted" gaps
215
+ record(gaps.plan_owned + gaps.deferrable) ## Open questions with destination # never closed here
216
+ blocking = gaps.spec_blocking
217
+ if blocking == ∅: break
218
+ batch = top ≤3 blocking ; pending_human = [] # gap questions ONLY — the shape was resolved above
138
219
  seed CHECKPOINT.Pending/Next = batch (refine_session) # BEFORE: seed the intent (artifact-first)
139
220
  for each gap in batch:
140
221
  if gap = UI (requirement involves UI, ## UI spec missing):
141
222
  compose ui-design → author ## UI spec # design-system/theme via structured-choice (counts in the batch)
142
223
  work = integrate(work, ui) # → ## UI spec
143
- else if gap = Unexplored solution space (creativity):
144
- pending_human.push("ideation offer") # offer with AI recommendation: `Explorar ideas` | `Seguir sin ideación`
224
+ else if gap = Unexplored solution space and a trigger fires:
225
+ pending_human.push("ideation offer") # `Explorar ideas` | `Seguir sin ideación`
145
226
  else if factual(gap) and attempts[gap] < MAX:
146
227
  if it needs DB and >1 MCP without default → queue "MCP choice" in pending_human
147
- res = research_inline(gap) # in the current session: ANALYSIS-FILE → CONCLUSIONS (+read-only SCRIPTS.sql)
148
- if res.conclusive: work = integrate(work, res) # → Refinement decisions
228
+ res = research_inline(gap) # current session: ANALYSIS-FILE → CONCLUSIONS (+read-only SCRIPTS.sql)
229
+ if res.conclusive: work = integrate(work, res) # → Context / Behavioral changes / Decisions
149
230
  else: attempts[gap]++ ; if attempts[gap] >= MAX → pending_human.push(gap)
150
231
  else:
151
232
  pending_human.push(gap)
152
- update CHECKPOINT (refine_session) # AFTER: Pending→Completed, at every gap boundary (chassis § artifact-first cycle)
233
+ update CHECKPOINT (refine_session) # AFTER: Pending→Completed, at every gap boundary (chassis)
153
234
  if pending_human not empty:
154
235
  ans = structured_choice(content: pending_human (≤3), flow: [Compactar, Cerrar])
155
236
  switch(flow):
156
237
  Compactar → write CHECKPOINT (refine_session) ; compact(harness) ; continue
157
238
  Cerrar → goto finalize
158
- work = integrate(work, ans) # → Refinement decisions (Q: entries) / Open questions
159
- ideation offer accepted → run the round NOW, then its verdicts as a NEW ≤3+flow batch (§ Ideation gate) → integrate
239
+ work = integrate(work, ans) # → Decisions / Open questions
240
+ ideation offer accepted → run the round NOW, then its verdicts as a NEW ≤3+flow batch (§ Ideation gate)
160
241
  ideation offer declined → mark that gap exhausted # anti re-fire; on-demand entry stays open
161
- # no material gaps → analyze gate = Success criteria green (read-only) before offering Guardar:
162
- issues = analyze(work) # criteria trace to the Requirement · no contradictions · coherent Scope · Open questions closed/deferred · scenarios↔criteria · no gold-plating (minimality)
163
- if issues: gaps += issues ; continue # findings come back into the loop as gaps
164
- ans = structured_choice(content: [Guardar refinada, Preguntar algo más],
242
+ # no BLOCKING gaps → ready-for-plan gate = Success criteria green (read-only) before offering Guardar:
243
+ issues = ready_for_plan(work) # § Convergence / exit PLAN-owned questions never fail it
244
+ if issues: blocking += issues ; continue # findings come back into the loop as gaps
245
+ ans = structured_choice(content: [Guardar refinada | Guardar specs, Preguntar algo más],
165
246
  flow: [Compactar, Cerrar])
166
- Guardar → edit_in_place_with_confirm(spec) # completes sections + inserts UI spec/Refinement decisions ; goto finalize
247
+ Guardar → edit_in_place_with_confirm(spec) + stamp status: ready-for-plan ; goto finalize
248
+ # split branch → also mint + write the extracted siblings as status: draft
167
249
  Preguntar algo más → continue
168
250
  flow Compactar/Cerrar → handle the same way
169
251
  finalize:
@@ -176,19 +258,30 @@ finalize:
176
258
 
177
259
  Full mechanism (3 cases, `Compactar`, re-run on demand with `--reopen`) in the chassis (§ *Compact / resume*). SPEC keys:
178
260
 
179
- - The **prior-work mark** is the presence of `## Refinement decisions` in the spec (the *refined mark*, see *Deliverable schema*; legacy specs may also carry `## Q&A traceability`).
261
+ - The **prior-work mark** is the frontmatter `status: ready-for-plan` (legacy specs: `## Refinement decisions`, older ones also `## Q&A traceability`).
262
+ - The **shape decision survives a resume.** It is written to `CHECKPOINT` the moment it is taken, before anything acts on it, so a compact, a `Cerrar` or a crash between the gate and the save re-enters with the shape settled — the gate is not re-run and the question is not re-asked. Only a *new* run over a spec whose baseline changed re-opens it.
180
263
  - Re-refining on demand is a **first-class operation** while the flow stays in SPEC (new requirements, scope changes, after re-reading the spec): it always reads the **spec itself**, incremental re-refinement; on `Guardar`, edits in place with confirmation.
264
+ - **Legacy migration happens only here.** A re-refined legacy spec runs the gate like any other; on `Guardar`, its `## Refinement decisions` is renamed `## Decisions` and pruned to the material decisions — **in the same write that stamps `status`**, so the spec is never left with no mark. Specs nobody re-refines are not migrated.
265
+ - **`Cerrar` before converging leaves the spec untouched**: the progress lives in the `CHECKPOINT`, and `status` is neither invented nor downgraded. `refining` is understood **on read** (a hand-written spec may declare it) — this loop never writes a partial spec.
181
266
 
182
267
  ## Convergence / exit
183
268
 
184
- - **No material gaps** → **analyze gate** (read-only) = **`Success criteria` green** (*verification-first*; the SPEC instance of the chassis convergence gate): every acceptance criterion traces to the `Requirement`, no internal contradictions, coherent `Scope` In/Out, `Open questions` closed or explicitly deferred. **Minimality** — no gold-plating: every criterion and scope item earns its place (chassis § *Minimality*); speculative scope is cut or deferred. Scenarios must trace to ≥1 criterion — and add GIVEN setup or edge semantics beyond it (a 1:1 restatement of a criterion is gold-plating: cut it) — without contradicting `Scope`. Whatever fails **comes back as a gap**; if it passes → offer `Guardar especificación refinada`.
185
- - `Guardar` `edit_in_place_with_confirm(spec)` and `finalize`.
269
+ - **No blocking gaps** → **ready-for-plan gate** (read-only) = **`Success criteria` green** (*verification-first*; the SPEC instance of the chassis convergence gate). The checklist:
270
+ - the requested outcome is understandable, the relevant current behavior is established, and the behavior change is described whenever existing behavior is touched;
271
+ - `Scope` separates In from Out; every acceptance criterion traces to the `Requirement`; scenarios trace to ≥1 criterion and add GIVEN setup or edge semantics beyond it, without contradicting `Scope` (a 1:1 restatement is gold-plating: cut it);
272
+ - no material contradictions; the one-vs-many shape was validated at the *Change-shape gate*;
273
+ - every **blocking** functional decision is resolved, and every remaining question carries its destination;
274
+ - **Minimality** — no gold-plating: every criterion and scope item earns its place (chassis § *Minimality*); speculative scope is cut or deferred, and no technical solution was imposed that the requirement did not ask for;
275
+ - `PLAN` can continue without inventing behavior, scope or product decisions.
276
+ - Whatever fails **comes back as a gap**. A question owned by `PLAN` **never** fails the gate: it is recorded with its destination, not closed.
277
+ - Passes → offer `Guardar especificación refinada` (split branch: `Guardar specs`) → `edit_in_place_with_confirm(spec)` + `status: ready-for-plan` → `finalize`.
186
278
  - `Cerrar` → the chassis `finalize` (always persists `CHECKPOINT`; `BACKLOG` **only if** something is deferred — here: close reason + deferred `Open questions`).
187
279
 
188
280
  ## Integration (where each resolution lands)
189
281
 
190
- - Resolved via **inline research** → the spec's `## Refinement decisions` (+ ref to the session's `CONCLUSIONS`).
191
- - Resolved via **ideation** → per verdict (§ *Ideation gate*): `Adoptar` → the spec's sections + `## Refinement decisions` · `Descartar` → there · `Aparcar` → `## Open questions`.
192
- - Resolved via **human** → the same `## Refinement decisions`, as a `Q: <question> <chosen answer> <rationale>` entry.
193
- - Resolved via the **`ui-design` capability** (UI gap) → the spec's `## UI spec` section.
194
- - **Inconclusive or unresolved research** → the spec's `## Open questions` (deferred) + the refine session's `BACKLOG.md` (only if something is deferred).
282
+ - **Inline research** → the fact lands in `## Context` / `## Behavioral changes`; if it settles a choice, the choice goes to `## Decisions` (+ ref to the session's `CONCLUSIONS`).
283
+ - **Ideation** → per verdict (§ *Ideation gate*): `Adoptar` → the spec's sections + `## Decisions` · `Descartar` → `CONCLUSIONS` · `Aparcar` → `## Open questions`.
284
+ - **Human** → `## Decisions`, as the decision plus its why. **Not** a `Q:` transcript: the question-by-question trace stays in the session.
285
+ - **`ui-design` capability** (UI gap) → the spec's `## UI spec` section.
286
+ - **Owned by `PLAN` or deferred** → `## Open questions` with its destination, and nothing else in the spec.
287
+ - **Inconclusive or unresolved research** → `## Open questions` (deferred) + the refine session's `BACKLOG.md` (only if something is deferred).