@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.
- package/README.md +35 -3
- package/dist/application/markdown.js +61 -16
- package/dist/application/markdown.js.map +1 -1
- package/dist/application/parsers/phases.js +128 -0
- package/dist/application/parsers/phases.js.map +1 -0
- package/dist/application/parsers/plan-status.js +75 -0
- package/dist/application/parsers/plan-status.js.map +1 -0
- package/dist/application/status-service.js +102 -2
- package/dist/application/status-service.js.map +1 -1
- package/package.json +1 -1
- package/skills/w/SKILL.md +11 -7
- package/skills/w/artifacts/artifacts-core/CHECKPOINT.md +3 -1
- package/skills/w/artifacts/artifacts-exec/DECISION.md +2 -0
- package/skills/w/commands/README.md +1 -1
- package/skills/w/commands/plan-exec.md +6 -3
- package/skills/w/commands/plan-new.md +7 -3
- package/skills/w/commands/plan-refine.md +5 -2
- package/skills/w/commands/resume.md +13 -6
- package/skills/w/commands/spec-new.md +53 -15
- package/skills/w/commands/spec-refine.md +19 -6
- package/skills/w/commands/status.md +20 -7
- package/skills/w/loops/CHASSIS.md +3 -3
- package/skills/w/loops/CODE-POLICIES.md +2 -0
- package/skills/w/loops/README.md +5 -3
- package/skills/w/loops/plan-exec-loop/LOOP.md +102 -36
- package/skills/w/loops/plan-new-loop/LOOP.md +72 -11
- package/skills/w/loops/plan-refine-loop/LOOP.md +91 -21
- package/skills/w/loops/quick-loop/LOOP.md +1 -1
- package/skills/w/loops/spec-refine-loop/LOOP.md +153 -60
|
@@ -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
|
|
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
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
113
|
+
---
|
|
114
|
+
status: ready-for-plan ← stamped on Guardar (vocabulary: draft | refining | ready-for-plan)
|
|
115
|
+
---
|
|
69
116
|
|
|
70
|
-
|
|
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
|
-
##
|
|
86
|
-
|
|
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 (
|
|
140
|
+
## Open questions (each entry declares its destination; OMIT the section when empty)
|
|
92
141
|
```
|
|
93
142
|
|
|
94
|
-
> **
|
|
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
|
|
151
|
+
## Gap taxonomy — signal, resolver, destination
|
|
99
152
|
|
|
100
|
-
`detect_gaps(work)` looks for these signals
|
|
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
|
-
|
|
|
106
|
-
|
|
|
107
|
-
| Untestable criteria | acceptance not verifiable | **human** (derive + confirm — often as a `### Scenario`) |
|
|
108
|
-
|
|
|
109
|
-
|
|
|
110
|
-
|
|
|
111
|
-
|
|
|
112
|
-
|
|
|
113
|
-
|
|
|
114
|
-
|
|
|
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.
|
|
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 +
|
|
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")
|
|
131
|
-
seed SESSION.Success criteria = acceptance criteria +
|
|
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)
|
|
136
|
-
|
|
137
|
-
|
|
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
|
|
144
|
-
pending_human.push("ideation offer") #
|
|
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) #
|
|
148
|
-
if res.conclusive: work = integrate(work, res)
|
|
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
|
|
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) # →
|
|
159
|
-
ideation offer accepted → run the round NOW, then its verdicts as a NEW ≤3+flow batch (§ Ideation gate)
|
|
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
|
|
162
|
-
issues =
|
|
163
|
-
if issues:
|
|
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)
|
|
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
|
|
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
|
|
185
|
-
-
|
|
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
|
-
-
|
|
191
|
-
-
|
|
192
|
-
-
|
|
193
|
-
-
|
|
194
|
-
- **
|
|
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).
|