git:20261021.f069886 to git:20261026.dfda8ad

1 added, 1 removed. Audit A to A.

# Design step
## Needs-input guard
A blank or vague scope or acceptance-criteria input is a gap, not a licence to
infer. The order is fixed: search the repository's own docs first and append an
`open-question` row to the unit folder's `decisions.md` recording where; research
an external gap into 2–3 concrete options. A gap surviving both runs
- `node scripts/needs-input.mjs <unit-dir>`, pastes the `open-questions@1` block
+ `bun scripts/needs-input.mjs <unit-dir>` (node fallback if bun is not installed), pastes the `open-questions@1` block
and stops — route `design` for scope/architecture questions. "Decide for me" is
a legitimate answer: the lane chooses and records the choice with its reason.
Cheap-to-change defaults are recorded as assumptions, never silent.
## Purpose
Run **investigate → orient → ask → decide**: every claim the SPEC makes is
entered in a ledger that cites its source, and entity, role, and expectation
boundaries close. The unit of progress is a **claim with a source** — a claim no
source or owner answer supports is a defect, not a judgment call.
## Inputs
- The unit's objective, why, and user outcome from the SPEC
- The user's original request, the repository's current state, and the
installed tooling — whatever they already answer is never asked again
- Research findings from the research step
## Stage 1 — investigate
Open with a provenance search, then journal every claim. **The first action of
this stage is a search, not a sentence**: no design claim is written before the
repository has been asked.
1. **Provenance search.** Run the greps and reads whose result would settle the
claim (`grep -rn "<term>" docs/ src/`, the documentation map, the architecture
doc, the roadmap, prior units' `decisions.md`), and record **where you
looked**: `path:line` hits and the greps run. A "not found" without that
receipt is the defect this stage exists to catch.
2. **Journal** — append one row per claim to the unit folder's `sources.md`:
| id | claim | source | certainty |
|---|---|---|---|
| INV-001 | <the claim, one line> | `<path:line>`, `<doc#anchor>`, `owner answer <Q-id>`, or `user request` | confirmed / inferred / unknown |
`confirmed` = verifiable by a command or documented; `inferred` = deduced,
not yet verified; `unknown` = no evidence found (→ the orient stage must ask).
3. **Induce acceptance criteria** from user scenarios — each AC is a claim too,
and cites the scenario or owner answer it came from.
4. **Close boundaries**: entities and their roles, actors, accepted and rejected
inputs (the expectation sweep), deferrals (→ `## Future`).
Pass only if: ✓ the provenance search ran and its receipt is recorded ✓ every
claim is a `sources.md` row ✓ every AC is induced from a user scenario.
## Stage 2 — orient
Filter each `INV-*` claim with three fixed tiers, in order — the lowest tier that
settles the claim wins, and the repository always speaks first:
| Tier | When it settles the claim | What this stage does |
|---|---|---|
| **0 · provenance** | A recorded `path:line`, doc, or prior decision answers it | Nothing to ask — point the row at the source |
| **1 · research** | External and unresearched, in tier 0 or outside it | Research it into 2–3 options with trade-offs |
| **2 · ask** | No evidence exists anywhere | Backlog it for the ask stage — never decided here |
The tier-2 backlog is then filtered by cost of being wrong — expensive to undo
= **scope** (personal / team / global), **stack**, **architecture pattern**,
**data model**, **deployment target**, **security configuration**:
| The claim… | The lane does |
|---|---|
| Blocks now and is expensive to undo once code sits on top | Asks |
| Blocks a later task that is already foreseeable | Asks now as a possibility; re-asks only if conditions change |
| Cheap to change later | Takes a reasonable default, records it as a dated assumption — never silent |
Pass only if: ✓ every `INV-*` row carries a tier and a cost verdict ✓ every
tier-0 row names the source that settled it ✓ no claim was researched or asked
before the provenance tier ran.
## Stage 3 — ask
Batch the tier-2 claims from the orient stage. This stage reads the **orient
output and the ask backlog** — never re-derives a claim the provenance tier
settled, never re-asks an answer the user already gave.
Mechanics — one batched form-turn, never one-question-per-turn:
- Group all independent questions into a single turn; ≤6 slots, one-word
defaults accepted, ≤2 ambiguity follow-ups per slot.
- Ask a single question first only when its answer changes the others. When
more than five gaps remain, the root decision (objective or scope) goes
first — its answer usually removes most of the rest.
- Every slot carries: the **recommended option with its why**, one
alternative, **"Decide for me"**, and **"Explain the options"** — the user
may always answer freely.
- A tool the project lacks may be offered as one more option (with its
recommendation and why); installing it always needs the user's explicit
consent.
- **Ready when:** no expensive-to-undo blocking claim remains unanswered — not
when no questions remain.
The questions are the `open-questions@1` block of the unit folder's
`decisions.md` — the grammar `scripts/needs-input.mjs` reads, published in the
template agent guide's question protocol. Append the block (never a table of
your own invention) and carry a search receipt on every question:
```text
open-questions@1
id | date | type | question | blocks | search-receipt | options | route
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
```
## Stage 4 — decide
Record every answer — the user's, and every "Decide for me" choice with its
reason — as a `decision` row of the same block, newest last. Only the owner
closes a question; the row carries where the answer is recorded (a chat paste, an
issue comment) and what was discarded:
```text
D1 | <YYYY-MM-DD> | decision | Q1 | human-owner | <where the answer is recorded> | <what was chosen> | <what was discarded and why>
```
A cheap default taken in stage 2 goes to the file's `## Assumptions` as a dated
row, correctable by the user. Then fill the unit doc's **Acceptance criteria**
(induced from a concrete scenario, command-verified where possible, numbered).
## Fixed output contract
The step owns four panes of the unit folder and nothing else:
<!-- sources:start -->
`sources.md` — one row per claim, each with a source or an owner answer. A
claim row with an empty, `—`, or `n/a` source is a **defect**: either find the
source in the provenance tier or convert the claim into a question.
<!-- sources:end -->
<!-- questions:start -->
The unit folder's `decisions.md` — the `open-questions@1` block the ask stage
appended, plus the `decision` rows the decide stage appended (one per question
closed). The step also refreshes `BRIEF.md`, the reviewer brief that restates
them, so a reviewer never has to re-derive the step's questions.
| Asked | Resolution |
|---|---|
| <question id + the decision being asked> | <what was chosen, by whom (owner answer / Decide for me), and why> |
When the orient stage left an empty ask backlog, write exactly
``none — no questions: every claim was settled by provenance or research``.
An empty table is never that line — the form is a decision, the blank is a
missing one.
<!-- questions:end -->
<!-- deferred:start -->
`## Future` in the unit doc — deferred ideas ("down the road I'd like…"),
verbatim and dated. They are never implemented, never turned into spec or tasks
by this unit, and are reviewed at close, on resume, and when work returns to the
area.
<!-- deferred:end -->
<!-- acceptance:start -->
The unit doc's **Acceptance criteria** section, numbered and command-verified.
<!-- acceptance:end -->
## Checklist (pass only if)
- [ ] The provenance search ran first and its receipt is recorded (`path:line`, the greps, prior units)
- [ ] Every claim (objective, why, every AC, non-goals) cites its source or an owner answer in `sources.md`, and none lacks one
- [ ] Every claim carries a certainty (`confirmed` / `inferred` / `unknown`); an `unknown` claim became a question
- [ ] Every acceptance criterion (AC1, AC2, …) is induced from a user scenario and cites what induced it
- [ ] The orient tiers ran in order: provenance before research before ask
- [ ] Every question asked was recorded with its resolution — or the questions pane says `none` explicitly
- [ ] No expensive-to-undo blocking claim remains unanswered
- [ ] Every "Decide for me" choice is recorded with its reason in `decisions.md`
- [ ] Cheap defaults are recorded as dated assumptions, correctable by the user
- [ ] Entity closure: every entity mentioned has its role in the unit stated
- [ ] Role closure: every actor/role that interacts with the unit is listed
- [ ] Expectation sweep: user's accepted and rejected inputs are bounded
- [ ] Deferrals landed in `## Future`, not in scope
## Forbidden
- Never infer a claim: one that is not in the repository and not derivable from
it is a question for the owner, never a default. A claim with no source and no
owner answer is the defect, not a judgment call
- Do not write a design claim before the provenance search ran
- Do not ask what the request, the repo, or the installed tooling already answers
- Do not ask one question per turn when slots are independent
- Do not invent a question table of your own: the ask stage writes the
`open-questions@1` block the dispatcher reads
- Do not decide at the ask stage — asking and answering are different stages
- Do not implement, spec, or task anything from `## Future`
- Do not install a missing tool without explicit user consent
- Do not build a separate DESIGN.md — one SPEC, all in the unit doc
- Do not pre-fill engineering content (phases, tests, architecture)
- Do not stamp "designed" with an incomplete closure row