@gtrabanco/pi-agentic-workflow 0.24.2 → 0.26.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gtrabanco/pi-agentic-workflow",
3
- "version": "0.24.2",
3
+ "version": "0.26.0",
4
4
  "description": "Pi package: canonical agentic-workflow skills, friendly slash commands, and per-command model routing.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: execute-phase
3
3
  user-invocable: true
4
- version: 6.0.0
4
+ version: 6.1.0
5
5
  argument-hint: <NN-slug> [P<k>|step] [--max-attempts N] [--force]
6
6
  allowed-tools: [Bash, Read, Edit, Write, MultiEdit]
7
7
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
@@ -15,7 +15,12 @@ when every step below ran — fixing the code and stopping is the classic way
15
15
  findings end up "solved" locally but absent from the merged PR:
16
16
 
17
17
  ```
18
- ✓ Fixes implemented (scope: only the routed findings — nothing extra)
18
+ ✓ Fixes implemented — the batch is the routed findings **plus everything that
19
+ depends on them**: callers of what changes, consumers of what it delivers, and
20
+ every mention that stops being true (a comment, a prose claim, a declared
21
+ validator, a manifest narration). Nothing beyond that
22
+ ✓ `bun scripts/promise-coherence.mjs` RUN → `verdict PASS` (the repaired claims
23
+ reproduce at the head; a skipped line is read, never assumed)
19
24
  ✓ Gate RUN and green (exit codes pasted)
20
25
  ✓ Never edit an existing test's expectation to match behaviour — a setup
21
26
  repair keeps assertions at least as strong and never touches expectations
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: init-workspace
3
3
  user-invocable: true
4
- version: 4.0.2
4
+ version: 4.0.3
5
5
  argument-hint: <target-dir>
6
6
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
7
7
  license: MIT
@@ -152,9 +152,9 @@ loads exactly upgrade and skips bootstrap plus portability.
152
152
 
153
153
  The adaptive lane (feature 61) replaces the fixed pipeline with a single-unit-
154
154
  document model. Every NEW unit produces one `SPEC.md` under
155
- `docs/features/<NN>-<slug>/` with 14 sections: Objective, Why, User outcome, Impact,
156
- Acceptance criteria, Non-goals, Future cost, Applicable tests, Known pre-existing
157
- issues, Tasks, Evidence, Progress log, Next, References.
155
+ `docs/features/<NN>-<slug>/` with 14 sections: Objective, Why, User outcome, Acceptance criteria, Impact,
156
+ Non-goals, Future cost, Applicable tests, Known pre-existing issues, Tasks,
157
+ Evidence, Progress log, Next, References.
158
158
 
159
159
  Conventions written into the project's AGENTS.md:
160
160
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: orchestration-envelope
3
3
  user-invocable: false
4
- version: 2.3.0
4
+ version: 2.4.0
5
5
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
6
6
  license: MIT
7
7
  description: >
@@ -16,6 +16,14 @@
16
16
  ✓ 11. No reconstruction from memory — missing reference → STOP.
17
17
  ```
18
18
 
19
+ **A box that runs a command discloses what the command needs.** When a box
20
+ invokes a script with a placeholder (`node scripts/x.mjs <unit-dir>`), the same
21
+ skill's text must name the artifact that placeholder requires — the script
22
+ declares it (`PREREQUISITES` in `scripts/needs-input.mjs`) and
23
+ `scripts/promise-coherence.mjs` checks the disclosure. A box that instructs a
24
+ run the skill never equips reproduces the failure it was written to prevent
25
+ (fix #258 F45/F53: `missing-unit-doc`).
26
+
19
27
  **Single owner:** orchestration-envelope/references/TURN_CONTRACT.md. All skills load this + skill-specific additions only. Duplication forbidden. Missing reference = STOP.
20
28
 
21
29
  **Push policy supplement:** Box 4 covers the end-of-unit push. Some consumers (e.g. `execute-phase/references/PREFLIGHT.md`) define additional push rules for mid-phase commits when a PR is already open — those per-consumer supplements extend this contract and must be loaded alongside it by the consumer skill.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: pre-execution-review
3
3
  user-invocable: false
4
- version: 2.7.1
4
+ version: 2.8.0
5
5
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
6
6
  license: MIT
7
7
  description: >
@@ -55,7 +55,7 @@ task | implementation-owner | validator | required-evidence | status
55
55
  | `authority-source` | the SPEC/acceptance/criterion or ledger row that *requires* it — never the implementation |
56
56
  | `phase` / `task` | exactly one phase and one task; a row needing two phases means the phase cut is wrong |
57
57
  | `implementation-owner` | the skill/role that performs it (usually `execute-phase`) |
58
- | `validator` | the command or check that proves it, copied from the acceptance artifact (`ACCEPTANCE.md` for legacy (pre-feature 61) units; `sed -n '/^## Acceptance criteria/,/^## /p' <unit>/SPEC.md \| git hash-object --stdin` for post-feature 61) or the phase's done-when |
58
+ | `validator` | the command or check that proves it, copied from the acceptance artifact (`ACCEPTANCE.md` for legacy (pre-feature 61) units; `sed -n '/^## Acceptance criteria/,/^## /p' <unit>/SPEC.md \| git hash-object --stdin` for post-feature 61) or the phase's done-when. When it is a backticked reader command, state the outcome it must produce — `` … matches <N> `` or `` … exits <N> `` — because `scripts/promise-coherence.mjs` re-runs it at the head and `verified` is only truthful while it reproduces. A validator with no stated outcome is a claim nobody can check |
59
59
  | `required-evidence` | what must be recorded where (test name, receipt line, ledger row) |
60
60
  | `status` | `planned \| in-progress \| verified \| n/a \| deferred` |
61
61
 
@@ -66,7 +66,9 @@ Status lifecycle and its hard edges:
66
66
  follow-up issue.
67
67
  - `verified` requires the named validator to have run and its evidence to be
68
68
  recorded where `required-evidence` says. An assertion of intent is not a
69
- status change.
69
+ status change. A count or exit code in the validator cell is re-run by
70
+ `scripts/promise-coherence.mjs`; when the command stops producing it, the row
71
+ is stale even while it still reads `verified`.
70
72
  - `n/a` needs evidence in the row (a `path:line`, ledger row, or cited contract)
71
73
  and may never contradict the SPEC's scope section. `n/a` without evidence is
72
74
  an open obligation.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: unit-lane
3
3
  user-invocable: true
4
- version: 2.0.0
4
+ version: 2.3.0
5
5
  argument-hint: <NN-slug | "<idea>"> [--retriage] | --fix <issue-number> | --from-issue <issue-number>
6
6
  description: >
7
7
  One-shot lane conductor for a delivery unit: triage, implement, evidence, and
@@ -25,6 +25,12 @@ done:
25
25
  is inferred: a gap re-enters provenance → research, and a gap surviving both
26
26
  runs `node scripts/needs-input.mjs <unit-dir>` and stops with the
27
27
  `open-questions@1` block routed back to the owning stage.
28
+ ✓ Every claim the SPEC or the plan asserts (objective, why, ACs, tasks) cites
29
+ its source — `path:line`, a doc, or an owner answer in the unit folder's
30
+ `sources.md`. A claim with none is a question, never a default.
31
+ ✓ Every question asked is recorded with its resolution (owner answer, "Decide
32
+ for me" + reason, or the explicit `none — no questions` line) in
33
+ `decisions.md`; no question the user already answered is asked twice.
28
34
  ✓ Triage ran (bun scripts/unit-route.mjs --triage <slug>) and its block pasted
29
35
  verbatim into the unit doc's Evidence section as the authoritative step list
30
36
  ✓ Unit doc exists at docs/features/<NN>-<slug>/SPEC.md (created from template
@@ -13,9 +13,10 @@ Cheap-to-change defaults are recorded as assumptions, never silent.
13
13
 
14
14
  ## Purpose
15
15
 
16
- Run the gap interview, induce acceptance criteria from user scenarios, and
17
- close entity, role, and expectation boundaries — distilled from the full design
18
- skill's closure.
16
+ Run **investigate → orient → ask → decide**: every claim the SPEC makes is
17
+ entered in a ledger that cites its source, and entity, role, and expectation
18
+ boundaries close. The unit of progress is a **claim with a source** — a claim no
19
+ source or owner answer supports is a defect, not a judgment call.
19
20
 
20
21
  ## Inputs
21
22
 
@@ -24,20 +25,63 @@ skill's closure.
24
25
  installed tooling — whatever they already answer is never asked again
25
26
  - Research findings from the research step
26
27
 
27
- ## The gap interview (runs before acceptance criteria lock)
28
+ ## Stage 1 — investigate
28
29
 
29
- Collect every open decision the unit depends on and filter each one:
30
+ Open with a provenance search, then journal every claim. **The first action of
31
+ this stage is a search, not a sentence**: no design claim is written before the
32
+ repository has been asked.
30
33
 
31
- | The gap… | The lane does |
34
+ 1. **Provenance search.** Run the greps and reads whose result would settle the
35
+ claim (`grep -rn "<term>" docs/ src/`, the documentation map, the architecture
36
+ doc, the roadmap, prior units' `decisions.md`), and record **where you
37
+ looked**: `path:line` hits and the greps run. A "not found" without that
38
+ receipt is the defect this stage exists to catch.
39
+ 2. **Journal** — append one row per claim to the unit folder's `sources.md`:
40
+
41
+ | id | claim | source | certainty |
42
+ |---|---|---|---|
43
+ | INV-001 | <the claim, one line> | `<path:line>`, `<doc#anchor>`, `owner answer <Q-id>`, or `user request` | confirmed / inferred / unknown |
44
+
45
+ `confirmed` = verifiable by a command or documented; `inferred` = deduced,
46
+ not yet verified; `unknown` = no evidence found (→ the orient stage must ask).
47
+ 3. **Induce acceptance criteria** from user scenarios — each AC is a claim too,
48
+ and cites the scenario or owner answer it came from.
49
+ 4. **Close boundaries**: entities and their roles, actors, accepted and rejected
50
+ inputs (the expectation sweep), deferrals (→ `## Future`).
51
+
52
+ Pass only if: ✓ the provenance search ran and its receipt is recorded ✓ every
53
+ claim is a `sources.md` row ✓ every AC is induced from a user scenario.
54
+
55
+ ## Stage 2 — orient
56
+
57
+ Filter each `INV-*` claim with three fixed tiers, in order — the lowest tier that
58
+ settles the claim wins, and the repository always speaks first:
59
+
60
+ | Tier | When it settles the claim | What this stage does |
61
+ |---|---|---|
62
+ | **0 · provenance** | A recorded `path:line`, doc, or prior decision answers it | Nothing to ask — point the row at the source |
63
+ | **1 · research** | External and unresearched, in tier 0 or outside it | Research it into 2–3 options with trade-offs |
64
+ | **2 · ask** | No evidence exists anywhere | Backlog it for the ask stage — never decided here |
65
+
66
+ The tier-2 backlog is then filtered by cost of being wrong — expensive to undo
67
+ = **scope** (personal / team / global), **stack**, **architecture pattern**,
68
+ **data model**, **deployment target**, **security configuration**:
69
+
70
+ | The claim… | The lane does |
32
71
  |---|---|
33
- | The request, the repo, or the installed tooling already answers it | Never asks |
34
72
  | Blocks now and is expensive to undo once code sits on top | Asks |
35
73
  | Blocks a later task that is already foreseeable | Asks now as a possibility; re-asks only if conditions change |
36
- | Cheap to change later | Takes a reasonable default and records it as an assumption — never silent |
74
+ | Cheap to change later | Takes a reasonable default, records it as a dated assumption — never silent |
75
+
76
+ Pass only if: ✓ every `INV-*` row carries a tier and a cost verdict ✓ every
77
+ tier-0 row names the source that settled it ✓ no claim was researched or asked
78
+ before the provenance tier ran.
37
79
 
38
- Expensive to undo = the choices that cost a lot to change once code exists on
39
- top: **scope** (personal / team / global), **stack**, **architecture pattern**,
40
- **data model**, **deployment target**, and **security configuration**.
80
+ ## Stage 3 — ask
81
+
82
+ Batch the tier-2 claims from the orient stage. This stage reads the **orient
83
+ output and the ask backlog** — never re-derives a claim the provenance tier
84
+ settled, never re-asks an answer the user already gave.
41
85
 
42
86
  Mechanics — one batched form-turn, never one-question-per-turn:
43
87
 
@@ -49,52 +93,104 @@ Mechanics — one batched form-turn, never one-question-per-turn:
49
93
  - Every slot carries: the **recommended option with its why**, one
50
94
  alternative, **"Decide for me"**, and **"Explain the options"** — the user
51
95
  may always answer freely.
52
- - **"Decide for me"**: the lane chooses, then records the choice and its
53
- reason as a dated row in the unit folder's `decisions.md` — explicit, never
54
- guessed silently.
55
- - **"Explain the options"**: explain each alternative didactically, then
56
- re-ask only that slot.
57
96
  - A tool the project lacks may be offered as one more option (with its
58
97
  recommendation and why); installing it always needs the user's explicit
59
98
  consent.
60
- - **Ready when:** no expensive-to-undo blocking gap remains unanswered — not
61
- when no gaps remain. An answer the user already gave is never re-asked.
99
+ - **Ready when:** no expensive-to-undo blocking claim remains unanswered — not
100
+ when no questions remain.
101
+
102
+ The questions are the `open-questions@1` block of the unit folder's
103
+ `decisions.md` — the grammar `scripts/needs-input.mjs` reads, published in the
104
+ template agent guide's question protocol. Append the block (never a table of
105
+ your own invention) and carry a search receipt on every question:
62
106
 
63
- Deferred ideas ("down the road I'd like…") are never implemented, never turned
64
- into spec or tasks by this unit: they go verbatim to the unit doc's
65
- `## Future` section, dated, so the architecture may accommodate them without
66
- building them.
107
+ ```text
108
+ open-questions@1
109
+ id | date | type | question | blocks | search-receipt | options | route
110
+ Q1 | <YYYY-MM-DD> | open-question | <the decision being asked> | <why nothing proceeds without it> | <where the repository was searched: path:line, greps, prior units> | <option A — trade-off> \| <option B — trade-off> \| Decide for me \| Explain the options | design
111
+ ```
112
+
113
+ ## Stage 4 — decide
114
+
115
+ Record every answer — the user's, and every "Decide for me" choice with its
116
+ reason — as a `decision` row of the same block, newest last. Only the owner
117
+ closes a question; the row carries where the answer is recorded (a chat paste, an
118
+ issue comment) and what was discarded:
119
+
120
+ ```text
121
+ D1 | <YYYY-MM-DD> | decision | Q1 | human-owner | <where the answer is recorded> | <what was chosen> | <what was discarded and why>
122
+ ```
123
+
124
+ A cheap default taken in stage 2 goes to the file's `## Assumptions` as a dated
125
+ row, correctable by the user. Then fill the unit doc's **Acceptance criteria**
126
+ (induced from a concrete scenario, command-verified where possible, numbered).
67
127
 
68
128
  ## Fixed output contract
69
129
 
70
- Fill the unit doc's **Acceptance criteria** section. Each AC must be:
71
- - Induced from a concrete user scenario ("I do X and observe Y")
72
- - Command-verified where possible (not "feel correct")
73
- - Numbered (AC1, AC2, …)
130
+ The step owns four panes of the unit folder and nothing else:
131
+
132
+ <!-- sources:start -->
133
+ `sources.md` — one row per claim, each with a source or an owner answer. A
134
+ claim row with an empty, `—`, or `n/a` source is a **defect**: either find the
135
+ source in the provenance tier or convert the claim into a question.
136
+ <!-- sources:end -->
137
+
138
+ <!-- questions:start -->
139
+ The unit folder's `decisions.md` — the `open-questions@1` block the ask stage
140
+ appended, plus the `decision` rows the decide stage appended (one per question
141
+ closed). The step also refreshes `BRIEF.md`, the reviewer brief that restates
142
+ them, so a reviewer never has to re-derive the step's questions.
143
+
144
+ | Asked | Resolution |
145
+ |---|---|
146
+ | <question id + the decision being asked> | <what was chosen, by whom (owner answer / Decide for me), and why> |
147
+
148
+ When the orient stage left an empty ask backlog, write exactly
149
+ ``none — no questions: every claim was settled by provenance or research``.
150
+ An empty table is never that line — the form is a decision, the blank is a
151
+ missing one.
152
+ <!-- questions:end -->
153
+
154
+ <!-- deferred:start -->
155
+ `## Future` in the unit doc — deferred ideas ("down the road I'd like…"),
156
+ verbatim and dated. They are never implemented, never turned into spec or tasks
157
+ by this unit, and are reviewed at close, on resume, and when work returns to the
158
+ area.
159
+ <!-- deferred:end -->
160
+
161
+ <!-- acceptance:start -->
162
+ The unit doc's **Acceptance criteria** section, numbered and command-verified.
163
+ <!-- acceptance:end -->
74
164
 
75
165
  ## Checklist (pass only if)
76
166
 
77
- - [ ] The gap interview ran before the ACs locked: one batched form-turn,
78
- each gap filtered through the table above
79
- - [ ] No expensive-to-undo blocking gap remains unanswered
167
+ - [ ] The provenance search ran first and its receipt is recorded (`path:line`, the greps, prior units)
168
+ - [ ] Every claim (objective, why, every AC, non-goals) cites its source or an owner answer in `sources.md`, and none lacks one
169
+ - [ ] Every claim carries a certainty (`confirmed` / `inferred` / `unknown`); an `unknown` claim became a question
170
+ - [ ] Every acceptance criterion (AC1, AC2, …) is induced from a user scenario and cites what induced it
171
+ - [ ] The orient tiers ran in order: provenance before research before ask
172
+ - [ ] Every question asked was recorded with its resolution — or the questions pane says `none` explicitly
173
+ - [ ] No expensive-to-undo blocking claim remains unanswered
80
174
  - [ ] Every "Decide for me" choice is recorded with its reason in `decisions.md`
81
- - [ ] Cheap defaults are recorded as assumptions, correctable by the user
82
- - [ ] Deferred user ideas landed in `## Future`, not in scope
83
- - [ ] Every AC is induced from a user scenario, not inferred from vague intent
84
- - [ ] Acceptance criteria are command-verified where possible
175
+ - [ ] Cheap defaults are recorded as dated assumptions, correctable by the user
85
176
  - [ ] Entity closure: every entity mentioned has its role in the unit stated
86
177
  - [ ] Role closure: every actor/role that interacts with the unit is listed
87
178
  - [ ] Expectation sweep: user's accepted and rejected inputs are bounded
88
- - [ ] Vague items → ask the user with concrete options, never invent
179
+ - [ ] Deferrals landed in `## Future`, not in scope
89
180
 
90
181
  ## Forbidden
91
182
 
183
+ - Never infer a claim: one that is not in the repository and not derivable from
184
+ it is a question for the owner, never a default. A claim with no source and no
185
+ owner answer is the defect, not a judgment call
186
+ - Do not write a design claim before the provenance search ran
92
187
  - Do not ask what the request, the repo, or the installed tooling already answers
93
188
  - Do not ask one question per turn when slots are independent
189
+ - Do not invent a question table of your own: the ask stage writes the
190
+ `open-questions@1` block the dispatcher reads
191
+ - Do not decide at the ask stage — asking and answering are different stages
94
192
  - Do not implement, spec, or task anything from `## Future`
95
193
  - Do not install a missing tool without explicit user consent
96
194
  - Do not build a separate DESIGN.md — one SPEC, all in the unit doc
97
- - Do not invent product scope the user did not confirm
98
195
  - Do not pre-fill engineering content (phases, tests, architecture)
99
196
  - Do not stamp "designed" with an incomplete closure row
100
- - An incomplete row silently un-does the skill's purpose
@@ -43,6 +43,12 @@ its work landed in the unit doc before continuing:
43
43
  - [ ] Each executor turn recorded its Evidence row and dated Progress entry
44
44
  - [ ] Diff guard run at the lane's resume (see step 4 in SKILL.md)
45
45
  - [ ] `git status --porcelain` is empty when the lane resumes
46
+ - [ ] Each phase swept the change **plus everything that depends on it** —
47
+ callers of what changed, consumers of what it delivers, and every mention
48
+ that stops being true; a surviving mention is part of the same phase, not
49
+ a finding for the next review
50
+ - [ ] `bun scripts/promise-coherence.mjs` RUN at the lane's resume → `verdict
51
+ PASS` (the unit doc's declared validators reproduce at the head)
46
52
 
47
53
  ## Allowed
48
54
 
@@ -2,16 +2,96 @@
2
2
 
3
3
  ## Purpose
4
4
 
5
- Cut tasks from acceptance criteria. Each task names its validator. Smallest
6
- first. No future-phase work.
5
+ Run **investigate → orient → ask → decide** over the plan itself: cite every
6
+ task, sweep every claim against what the repository already decided, ask only
7
+ what no source answers, and record the answers. Each task names its validator;
8
+ smallest first; no future-phase work.
7
9
 
8
10
  ## Inputs
9
11
 
10
- - The unit's Acceptance criteria (filled by the design step)
11
- - The unit's non-goals
12
+ - The unit doc: acceptance criteria, non-goals, and the design step's four panes
13
+ (`sources.md`, `decisions.md`)
14
+ - The unit's Impact section — the surface the executor must sweep
15
+
16
+ ## Stage 1 — investigate
17
+
18
+ Open with the same provenance search the design step ran, aimed at the plan's own
19
+ claims ("does a validator for this exist?", "is this module already covered?",
20
+ "did a prior unit decide this?"). Journal each claim as a row of the unit
21
+ folder's `sources.md`, with the id prefix `CLAIM-`:
22
+
23
+ | id | claim | source | certainty |
24
+ |---|---|---|---|
25
+ | CLAIM-001 | <the plan claim, one line> | `<path:line>`, prior `decisions.md:line`, or `owner answer <Q-id>` | confirmed / inferred / unknown |
26
+
27
+ Two claims never need a search: the unit's own acceptance criteria (the design
28
+ step cited them) and its non-goals. Everything else does — a plan claim with no
29
+ source and no owner answer is the defect this stage exists to catch.
30
+
31
+ ## Stage 2 — orient
32
+
33
+ Re-run the provenance tier over the plan's claims, then sweep every one of them
34
+ against what the repository has **already decided in writing** — a plan must not
35
+ contradict a prior decision in architecture, engineering, product, or any other
36
+ domain. A claim the provenance search explains is settled at tier 0: point the
37
+ row at `path:line` and move on. **Record where you looked** for every row the
38
+ search did not settle — the greps meant for it and the prior units of the same
39
+ area. In the same pass, check that the acceptance criteria are the plan's
40
+ *input*, not a claim it re-decides: a task that would change an AC belongs to the
41
+ design step, not here.
42
+
43
+ **Candidate sources** — deterministic keyword/FTS matching, no new index and no
44
+ new tooling: `docs/features/<NN>-<slug>/decisions.md`,
45
+ `docs/fix/<issue>-<topic>/decisions.md`, the project's architectural invariants,
46
+ the Normalized Repository State (`discover-repository-state` /
47
+ `resolve-repository-state`), `AGENTS.md`, and a unit SPEC's `## Design status`
48
+ (legacy marker, units ≤ 60).
49
+
50
+ **Advisory only — no new authority.** `contradicts` routes to
51
+ `resolve-repository-state` only when the hit is against a frozen NRS fact (its
52
+ only candidate source that carries a `<contradiction-id>` row after a
53
+ `discover-repository-state` step); hits against `decisions.md` / `AGENTS.md` /
54
+ architectural invariants / `## Design status` surface a `NEEDS-DECISION` for the
55
+ user, per the existing rules. A plan with **no candidate match is clean and
56
+ proceeds** — a miss never blocks it, a missed candidate can never void a plan,
57
+ and the sweep issues no stage verdict and grants no gate of its own.
58
+
59
+ Pass only if: ✓ the provenance search ran and where you looked is recorded ✓ every `CLAIM-*` row was swept ✓ every `contradicts` hit is either
60
+ resolved from a frozen NRS fact or backlogged for the ask stage ✓ no task
61
+ re-decides an acceptance criterion.
62
+
63
+ ## Stage 3 — ask
64
+
65
+ Only `contradicts` hits and `unknown` claims that no source settles reach this
66
+ stage — a plan asks after the repository has spoken, never before. Batch them
67
+ into **one** form-turn (≤6 slots) using the design step's mechanics: recommended
68
+ option with its why, one alternative, "Decide for me", "Explain the options".
69
+
70
+ The questions are the same `open-questions@1` block the dispatcher reads — append
71
+ the block to the unit folder's `decisions.md` (route `unit-lane`: these are
72
+ plan-owned facts), never a table of your own:
73
+
74
+ ```text
75
+ open-questions@1
76
+ id | date | type | question | blocks | search-receipt | options | route
77
+ Q2 | <YYYY-MM-DD> | open-question | <the decision being asked> | <why nothing proceeds without it> | <where the repository was searched: path:line, greps, prior units> | <option A — trade-off> \| <option B — trade-off> \| Decide for me \| Explain the options | unit-lane
78
+ ```
79
+
80
+ A plan with an empty backlog writes the explicit `none` line instead — never a
81
+ blank.
82
+
83
+ ## Stage 4 — decide
84
+
85
+ Record every answer as a `decision` row of the same block (newest last), and a
86
+ `Decide for me` choice with its reason — then cut the tasks:
87
+
88
+ ```text
89
+ D2 | <YYYY-MM-DD> | decision | Q2 | human-owner | <where the answer is recorded> | <what was chosen> | <what was discarded and why>
90
+ ```
12
91
 
13
92
  ## Fixed output contract
14
93
 
94
+ <!-- tasks:start -->
15
95
  Fill the unit doc's **Tasks** section:
16
96
 
17
97
  ```
@@ -30,39 +110,27 @@ backticked command **and** an expected outcome, e.g. `exits 0`), and the nested
30
110
  `Relevant files:` line is **metadata, never a task** — it is that phase's read
31
111
  set, written from the planner's own discovery, and a file that is missing from
32
112
  it is never out of scope for the executor.
113
+ <!-- tasks:end -->
33
114
 
34
- ## Prior-decisions contradiction sweep
35
-
36
- Before the plan is accepted, sweep its claims against what the repository has
37
- **already decided in writing** — a plan must not contradict a prior decision in
38
- architecture, engineering, product, or any other domain.
39
-
40
- **Candidate sources** — deterministic keyword/FTS matching, no new index and no
41
- new tooling: `docs/features/<NN>-<slug>/decisions.md`,
42
- `docs/fix/<issue>-<topic>/decisions.md`, the project's architectural invariants,
43
- the Normalized Repository State (`discover-repository-state` /
44
- `resolve-repository-state`), `AGENTS.md`, and a unit SPEC's `## Design status`
45
- (legacy marker, units ≤ 60).
46
-
47
- **Fixed evidence shape** — one row per candidate hit, the decision quoted from
48
- its source:
115
+ <!-- sources:start -->
116
+ `sources.md` — every `CLAIM-*` row with a source or an owner answer. A claim row
117
+ whose source is empty, `—`, or `n/a` is a **defect**: find the source in the
118
+ provenance tier or convert the claim into a question.
119
+ <!-- sources:end -->
49
120
 
50
- | claim | prior decision | source path | relation |
51
- |---|---|---|---|
52
- | <the plan claim> | <the recorded decision> | <path:line> | `contradicts` \| `compatible` |
121
+ <!-- questions:start -->
122
+ The unit folder's `decisions.md` — the `open-questions@1` block the ask stage
123
+ appended, plus the `decision` rows the decide stage appended, one per question
124
+ closed. The step also refreshes `BRIEF.md`, the reviewer brief that restates
125
+ them, so a reviewer never has to re-derive the step's questions:
53
126
 
54
- The cell value is exactly one of two values: `contradicts` or `compatible` —
55
- a row relation, not a stage verdict.
127
+ | Asked | Resolution |
128
+ |---|---|
129
+ | <question id + the decision being asked> | <what was chosen, by whom (owner answer / Decide for me), and why> |
56
130
 
57
- **Advisory only — no new authority.** `contradicts` routes to
58
- `resolve-repository-state` only when the hit is against a frozen NRS fact
59
- (its only candidate source that carries a `<contradiction-id>` row after a
60
- `discover-repository-state` step); hits against
61
- `decisions.md` / `AGENTS.md` / architectural invariants / `## Design status`
62
- surface a `NEEDS-DECISION` for the user, per the existing rules. A plan with **no
63
- candidate match is clean and proceeds** — a miss never blocks it, a missed
64
- candidate can never void a plan, and the sweep issues no stage verdict and grants no
65
- gate of its own.
131
+ When the sweep and the provenance tier left an empty backlog, write exactly
132
+ ``none — no questions: every claim was settled by provenance or research``.
133
+ <!-- questions:end -->
66
134
 
67
135
  ## Planning ledgers (same step)
68
136
 
@@ -89,25 +157,31 @@ name those files instead.
89
157
 
90
158
  ## Checklist (pass only if)
91
159
 
92
- - [ ] Every AC maps to at least one task
160
+ - [ ] The provenance search ran first and its receipt is recorded for every plan claim
161
+ - [ ] Every claim (CLAIM-001, …) cites its source or an owner answer in `sources.md`, including every acceptance criterion it rests on — none is blank, `—`, or `n/a`
162
+ - [ ] Every claim was swept against the candidate sources; each `contradicts` hit is resolved or asked
163
+ - [ ] Every question asked was recorded in `decisions.md` with its resolution (or the questions pane says `none`)
164
+ - [ ] Every AC maps to at least one task, and no task re-decides an AC
93
165
  - [ ] Tasks are ordered smallest first
94
166
  - [ ] Each task names its validator (a backticked command plus its expected outcome)
95
167
  - [ ] Final task is verification (proves the whole unit works)
96
168
  - [ ] No task reaches into a future-phase concern (docs, release, migrations)
97
169
  - [ ] Phases labeled P1, P2, … (never S1, Step 1)
98
- - [ ] Every plan claim touching architecture, engineering or product intent was
99
- swept against the candidate sources above
100
- - [ ] Each candidate hit is one fixed-shape row, with the prior decision cited
101
- at `path:line` and one of the two relations
102
170
  - [ ] Both planning ledgers are cut (planning evidence + obligations), in the
103
171
  sizing rule's home, with stable ids
104
172
 
105
173
  ## Forbidden
106
174
 
175
+ - Never infer a plan claim: one the repository does not answer and no owner
176
+ settled is a question, never a default
177
+ - Do not cut a task before the claim it rests on cites a source or an owner answer
178
+ - Do not invent a question table of your own: the ask stage writes the
179
+ `open-questions@1` block the dispatcher reads
180
+ - Do not decide at the ask stage, and do not re-ask an answered question
107
181
  - Do not bundle across phase boundaries — one phase = one commit
108
182
  - Do not plan work beyond the unit's acceptance criteria
109
183
  - Do not include docs/release tasks here — those are separate catalog steps
110
184
  - Do not invent tasks that the ACs do not demand
111
185
  - Do not turn the sweep into a gate, stage verdict or blocking check — it routes,
112
186
  it never blocks a miss, and it adds no authority
113
- - Do not record a `prior decision` that no source `path:line` cites
187
+ - Do not record a `prior decision` that no source `path:line` cites
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: verification-contract
3
3
  user-invocable: false
4
- version: 1.4.2
4
+ version: 1.4.3
5
5
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
6
6
  license: MIT
7
7
  description: >
@@ -17,6 +17,16 @@ description: >
17
17
  Single owner of the delivery finish line. Planning freezes it; executors may
18
18
  strengthen coverage but cannot move it; review checks the same bytes.
19
19
 
20
+ ## Executable claims
21
+
22
+ An acceptance criterion or Evidence row that states a count, an exit code or a
23
+ length is a promise, not a description: `scripts/promise-coherence.mjs` re-runs
24
+ it. Write the outcome a command must produce (`` `cmd` matches <N> ``,
25
+ `` `cmd` exits <N> ``) or, for a shape promise, name the file and the
26
+ `## Section` the count is about (`` … a 3–5 line `## Inputs` in
27
+ `skills/<name>/SKILL.md` ``) — a length with no named surface cannot be recounted
28
+ and fails closed.
29
+
20
30
  ## Artifact
21
31
 
22
32
  Legacy (pre-feature 61) units (ACCEPTANCE.md present — binding if present):