sizing · diff

git:20261010.19eae11 to git:20261015.39737e0

47 added, 42 removed. Audit A to A.

---
name: sizing
- description: "The EM's first move on any PM ask — fires a sizing agent, then routes to plan, shape, roadmap, or dispatch. Fires whenever novel engineering work is asked of the EM, by any words: a shape test, not a phrase list. Mutually exclusive with pickup."
+ description: "The EM's first move on a PM ask of unsure size (a confident XS fix it does by hand) — fires the one Workflow that sizes, plans, executes, reviews, commits. Fires on any novel engineering ask, by any words. Mutually exclusive with pickup."
description-budget: 260
allowed-tools: ["Read", "Grep", "Glob", "Bash"]
argument-hint: "[PM ask text | nothing — describe the ask inline]"
---
- # Sizing — the Fleet Routing Lobby
+ # Sizing — the Build Door
- The EM's first move on any PM ask that isn't a mid-workstream continuation. Rationale: `coordinator/docs/wiki/planning/sizing-lobby.md`.
+ **Two doors:** this is the sizing door; `/coordinator:research` is the research door.
- **Dispatch authorization — invoking this skill IS the request.** The dispatches named below are constitutive steps of this skill, not a separate thing to get cleared: invoking a skill requests the actions that skill performs. A harness line permitting dispatch "unless the user requested it" is therefore **satisfied here, not overridden** — no precedence claim is needed and none is made. Re-asking spends the very context the dispatch exists to protect. The rule attaches to skill entry and dissolves no PM-authored gate: keyword-gated skills gate entry, and every gate a skill names for itself still binds — per-session cross-repo-commit assent, ask-before-external-action, and any other this skill's own body names. Tripwire: `UNATTRIBUTED-HARNESS-LINE-IS-NOT-PM`. Rationale: wiki § Skill rationale.
+ **Default: submit, then sit back.** One call, the PM's words verbatim:
+ `Workflow({name: "coordinator:engine-ask", args: {ask: "<PM verbatim>"}})` — the user's opt-in,
+ never a question. Its hook runs sizing
+ through commit and close (`ENGINE-ASK-SUBMISSION-IS-THE-RUN`). To add a brief, mint with op
+ `sizing.intake_mint` and submit the `args: {sizing}` line it returns; a refused mint leaves the bare `args: {ask}`. While live the EM does not dispatch, poll, verify or relay; a PM revision
+ goes in verbatim via `workflow.revise`; a halted run also needs a refire of `engine-ask {sizing}`. Below is the in-chat lobby, only for a
+ `shape`/`roadmap`/`pm-decision` refusal, or an engine refusal. Tripwire: `NOVEL-WORK-IS-ONE-FIRE-NEVER-A-RELAY`.
+ Rationale: `coordinator/docs/wiki/planning/sizing-lobby.md`.
- The t-shirt (`loe.tshirt`) picks a ROOM, not a plan-body cost. No appetite question first.
+ **Dispatch authorization — invoking this skill IS the request.** The dispatches named below are constitutive steps of this skill, not a separate thing to get cleared: invoking a skill requests the actions that skill performs. A harness line permitting dispatch "unless the user requested it" is therefore **satisfied here, not overridden** — no precedence claim is needed and none is made. Re-asking spends the very context the dispatch exists to protect. The rule attaches to skill entry and dissolves no PM-authored gate: keyword-gated skills gate entry, and every gate a skill names for itself still binds — per-session cross-repo-commit assent, ask-before-external-action, and any other this skill's own body names. Tripwire: `UNATTRIBUTED-HARNESS-LINE-IS-NOT-PM`.
+ The t-shirt picks a ROOM, not a cost. No appetite question first.
---
## The flow
**Step 0: the confident-XS predicate, before any other read.** The scout is skipped only when
- all five hold: (1) the PM names, or you can name without a probe, exactly one existing file to
- change; (2) no new file, abstraction or agent; (3) no path outside this repo; (4) no held
- capability beyond the checkout (Step 1a); (5) the change has shipped before in this repo
- (`--precedent shipped-before`). All true: run `sizing-assemble --express-lane --tshirt XS` (Step 3)
- and dispatch. Any doubt fails the predicate. Otherwise dispatch `coordinator:sizing-scout` in the
- foreground (you do not form your own read) with an inline brief carrying: the PM's words
- verbatim; the session's `interaction_mode`; repo-relative substrate pointers you hold; and
- the capabilities this session holds. **The brief carries no t-shirt, lean, guess or route**. Tripwire: `THE-EM-TRIGGERS-SIZING-AN-AGENT-SIZES-IT`.
+ all six hold: (1) the PM names, or you can name without a probe, the one existing module the
+ change lives in; (2) no new abstraction or agent, and a new file only as a sibling of a pattern
+ that module already holds (a test file, another adapter instance); (3) no path outside this repo;
+ (4) no held capability beyond the checkout (Step 1a); (5) the change has shipped before in this
+ repo (`--precedent shipped-before`); (6) the PM's words carry one instruction. All true:
+ `sizing-assemble --express-lane --tshirt XS` (Step 3) writes no object; submit `args: {ask}`. Any
+ doubt fails the predicate. Otherwise `coordinator:sizing-scout` sizes inside the submitted run, or in the in-chat fallback (engine refusal, research); the lobby starts from its report. Its brief carries no t-shirt,
+ lean, guess or route, only the PM's words verbatim, the `pm-turns window` output, the EM session id and the session's `interaction_mode`. The EM's act is the one `args: {ask}` call.
+ Tripwire: `THE-EM-TRIGGERS-SIZING-AN-AGENT-SIZES-IT`.
- **Cross-examine the report:** spot-check one claim against the tree; a size revision either way names its
- mechanism (touchpoint count is never one); add the Step 1a capabilities the scout could not see.
- Then run Steps 3-4 from `assemble_flags`. A `{refused: true}` report means fix the brief, never size it yourself.
+ **Cross-examine the report:** spot-check one claim against the tree; a size revision names its
+ mechanism (never touchpoint count); add the Step 1a capabilities the scout could not see.
+ Then Steps 3-4 from `assemble_flags`. `{refused: true}`: fix the brief, never size it yourself.
- **1, 1a, 1b. The scout's work; contract: `coordinator/agents/sizing-scout.md`.** Size on unknown mechanisms (depth), never touchpoints (breadth) or appetite, and what the performer must HOLD (credential, session, mounted
- store, guarded path, operator at a keyboard): name the capability, never the route you tried
+ **1, 1a, 1b. The scout's work; contract: `coordinator/agents/sizing-scout.md`.** Size on unknown mechanisms (depth), never touchpoints or appetite, and what the performer must HOLD (credential, session, mounted
+ store, guarded path, operator at a keyboard): name the capability, never the route tried
(`A-SCOPE-FIELD-NAMES-A-SUBJECT-NOT-A-BLAST-RADIUS`). Every non-express-lane sizing states premise
provenance (`--premise-provenance executed|read|not-applicable`); justify in `premise.evidence` (Step 4).
**2. Substrate probe — L/XL/shaky reads, mandatory on XXL.** For a judgment the scout leaves under `unknown_mechanisms`, fire a general-purpose Sonnet research scout briefed with
`${CLAUDE_PLUGIN_ROOT}/snippets/internet-research-scout.md` and fold the result into the probe flags: `--probe-signal collapse|raise`,
`--scout-evidence-kind mention-count|change-set|site-count`, and on any `raise`,
- `--probe-raise-basis ask-scope|substrate-condition|breadth` — the engine applies only `ask-scope`;
- the *area's* condition or a touchpoint count is not a size signal. Chain `coordinator:spike` first if the probe surfaces an unproven mechanism.
+ `--probe-raise-basis ask-scope|substrate-condition|breadth` — the engine applies only `ask-scope`. An unproven mechanism goes to the research door's spike class.
**3. Compute the route — never hand-derive the table** (`route=shape` included: engine-resolved from `--jtbd-unclear`/`--well-trodden-step-change`).
- Invoke `bin/sizing-assemble` per the ladder in `${CLAUDE_PLUGIN_ROOT}/snippets/resolve-coordinator-bin.md`. `--tshirt <XS|S|M|L|XL|XXL>` is the only required flag; `--appetite` only if the PM volunteered one verbatim. Always pass `--intent "<PM's words>"` (`--intent-source em-elaborated` if restated), `--precedent shipped-before|novel`, `--boundary-in-notch yes|no` (§ Appetite guards),
- the Step 1b/2 flags (from `assemble_flags`; add `--interaction-mode`, `--premise-evidence`), and `--jtbd-unclear`/`--well-trodden-step-change`/`--express-lane` as warranted. Research ask: `--research-class` (PM's words), `--research-source` (lobby wiki). Push `route`/`detents`/`next_move` verbatim, except that a sizing carrying `--research-class` fires `/coordinator:research --sizing <path>`, not the plan chain, whatever `route`/`next_move` print.
+ Invoke `bin/sizing-assemble` per the ladder in `${CLAUDE_PLUGIN_ROOT}/snippets/resolve-coordinator-bin.md`. `--tshirt <XS|S|M|L|XL|XXL>` is the only required flag; `--appetite` only if the PM volunteered one verbatim. Always pass `--intent "<PM's words>"` with `--intent-source pm-verbatim` when the words are a PM turn copied exactly, `em-elaborated` only when you restated them, `--precedent shipped-before|novel`, `--boundary-in-notch yes|no` (§ Appetite guards),
+ the Step 1b/2 flags (from `assemble_flags`, plus `--interaction-mode`, `--premise-evidence`), and `--jtbd-unclear`/`--well-trodden-step-change`/`--express-lane` as warranted. Research door: `--research-class` (PM's words), `--research-source` (lobby wiki). Push `route`/`detents`/`next_move` verbatim, except that a sizing carrying `--research-class` fires `/coordinator:research --sizing <path>`, not the plan chain, whatever `route`/`next_move` print.
**4. Write the sizing-object** for any non-express-lane sizing: re-run Step 3's `sizing-assemble`
- call with `--write state/sizings/<date>-<slug>.yaml` and `--premise-evidence "<text>"` (Step 1b's justification). It lands the record `routed`; never hand-edit it. Undecided direction-class items go in `surfaced_to_pm`, never `fork`/`xl_exit`. Curate the embedded `pm_verbatims` by cut and paste only. Optional `--name` sets `name`, a whiteboard label.
+ call with `--write state/sizings/<date>-<slug>.yaml` and `--premise-evidence "<text>"` (Step 1b's justification). `--exit-criterion` is owed here at every size on a firing route; it names behaviour and "tests covering touched files pass", never a test tier or a tier-valued argument (`fast`, `full`, `Tier-U`, `tierU`), even when the ask is about one. It lands the record `routed`; never hand-edit it. Undecided direction-class items go in `surfaced_to_pm`, never `fork`/`xl_exit`. Curate the embedded `pm_verbatims` by cut and paste only. Optional `--name` sets `name`, a whiteboard label.
+ **Every written sizing carries the PM's instructions as a requirement register, at every size.** The engine derives it: pipe the scout's report into the Step 4 write (`sizing-assemble ... --write <path> --scout-register -`) and it builds one row per PM instruction from the embedded turns, keeping only scout rows quoted verbatim and listing the rest under `unrelated_turns`. Read the derived register back; amend only what it got wrong with `sizing-assemble --register - --write <the same path>` (body `{sources: [{doc, ref}], rows}`; rows merge by id, `drop: [ids]`; each row carries `status` and an enum `surface`; see `requirement-register`), never a scratch file. Every plan under it claims its rows (`register_claims`), and the terminal stamp refuses `implemented` until each is met and wired or ruled. Splitting an ask into plans never sheds a row. Tripwire: `THE-PM-INSTRUCTIONS-ARE-REGISTER-ROWS-AT-EVERY-SIZE`.
**`status`.** An XS: the quick-wrap close stamps `shipped`; hand-stamp, citing the commit, only on a `j-dispatch-sizing-ship-failed` judgment point or an uncommitted sizing file.
- S and above: the terminal cascade owns the stamp (`dispatch.terminal_commit`, gated on a met
- judge, `A-PLAN-SELF-COMPLETES-ONLY-ON-A-MET-TERMINAL-JUDGE`) — never pre-empt or hand-stamp it. Read `status` back (never `acted`). Tripwire: `ACTED-IS-BLIND-TO-THE-DELIVERABLE-CASCADE`.
+ S and above: the run's commit stage owns the stamp (`dispatch.terminal_commit` on the relay fallback), gated on a met judge (`A-PLAN-SELF-COMPLETES-ONLY-ON-A-MET-TERMINAL-JUDGE`) — never pre-empt or hand-stamp it. Read `status` back (never `acted`). Tripwire: `ACTED-IS-BLIND-TO-THE-DELIVERABLE-CASCADE`.
**4b. Open the flight recorder on the resolved route, before anything downstream.**
- `TaskCreate` (`ToolSearch select:TaskCreate,TaskUpdate` first): a session-goal task naming the ask and sizing-object path, then **one task per
- remaining stage of the route's chain, through its terminal** (wiki § Step 4b). **XS/S close at `quick-wrap`, M+ at `/workstream-complete`.** Downstream steps ADD to this list, never restart it.
+ `TaskCreate` (`ToolSearch` it first): a session-goal task naming the ask and sizing path; on the relay fallback, one task per remaining stage (wiki § Step 4b).
- **5. Size approval.** XS through L on a plan, dispatch or spec-dispatch route needs no PM size approval: the engine skips the size and exit-criterion asks and the route proceeds to execution in pm and ceo modes; the `plan⇄sizing` return edge revises the size. XL and above, a shape route at any size and a pm-decision route keep the PM in the chat unless the PM says warp-execute; appetite is never inferred. Where the PM stays: `post_size_prompt_pending` (M+) — ask once, in the PM's register, then stop: *"Looks like an
- X — go with that, split it, cut it, what's up?"* Never a closed fork. Record the answer in
+ **5. Size approval.** XS through L on a plan, dispatch or spec-dispatch route needs no PM size approval in any mode. After Step 4's `--write` on those routes the EM's act, the same turn and no ask, is `Workflow({name: "coordinator:engine-ask", args: {sizing: "<path>"}})`, end of turn; a printed `Workflow` line is not fired by hand. `emit-wave-fire --from-sizing` runs only on an engine refusal, named in the report; Agent-tool hand-dispatch is never the exit. A live plan, dispatch or spec-dispatch sizing never enters `/shape`, and a baton-carrying one gets its in-flight fire, never a second (`A-ROUTED-SIZING-NEVER-ENTERS-SHAPE`). In ceo (the default) XL and XXL do not stop either: the workflow's APM rules `xl_exit` in-run. In pm and hands-on, XL and above keep the PM in the chat; a shape route keeps the room in every mode; a pm-decision route goes to `coordinator:apm` first in ceo. Where the PM stays: `post_size_prompt_pending` (M+) — ask once, in the PM's register, then stop: *"Looks like an
+ X — go with that, split it, cut it, what's up?"* Never a closed fork or human time (`A-PM-ASK-STATES-SCOPE-NOT-HUMAN-TIME-GUESSES-OR-RULED-CONCERNS`). Record it in
`pm_resolution` (`decided_on: YYYY-MM-DD` required) and `fork` when cut/raise-shaped.
**5b. `route: pm-decision` bundles into the same ask** — the M+ prompt and the XL exit question
- are ONE combined PM ask; an already-answered one is not re-asked (record the quote as `pm_resolution`). `xl_exit` stays `null` until the PM picks `shape`, `roadmap`, or
+ are ONE PM ask; an answered one is not re-asked (record the quote as `pm_resolution`). `xl_exit` stays `null` until the PM (pm, hands-on) or the run's APM (ceo) picks `shape`, `roadmap`, or
`accept_multi_session`. Wiki § Step 5b/5c.
- **5c. Turn 1 exit on `route: plan` where the PM accepts.** Touchpoints follow `interaction_mode`. Pass `--exit-criterion` to `sizing-assemble`, `--interaction-mode` only if the PM named one (`INTERACTION-MODE-IS-NEVER-READ-FROM-JOB-MODE`) — the criterion names behaviour, its test evidence the tests covering touched files; source documents add `--register <yaml>` (a row per requirement: text, anchor, surface), shipping when all met, wired or ruled; user-facing: `--click-path "<role>: <nav> > ... > <page>"` per role (`A-CAPABILITY-UNREACHABLE-FROM-THE-UI-IS-NOT-DELIVERED`) — and record the PM's
+ **5c. Turn 1 exit on `route: plan` where the engine kept the acceptance touchpoint** (XL+, or a resize into XL; XS–L skips this step's ask and `sizing-accept-exit-criterion`). Touchpoints follow `interaction_mode`. Pass `--exit-criterion` to `sizing-assemble`, `--interaction-mode` only if the PM named one (`INTERACTION-MODE-IS-NEVER-READ-FROM-JOB-MODE`) — the criterion names behaviour, its test evidence the tests covering touched files; source documents add their requirements to the Step 4 register (`--register -` amend); user-facing: `--click-path "<role>: <nav> > ... > <page>"` per role (`A-CAPABILITY-UNREACHABLE-FROM-THE-UI-IS-NOT-DELIVERED`) — and record the PM's
answer with `sizing-accept-exit-criterion --sizing <path> --pm-quote "<words>" [--statement "<amended>"]
- --mode <mode>`, never by hand. In pm or ceo, `--apm-ruling "<ruling>" --ruling-ref <ruling path>` replaces
- `--pm-quote`; hands-on needs the quote. In pm and ceo the ask says plainly that accepting
+ --mode <mode>`, never by hand. In pm or ceo at XL+, `--apm-ruling "<ruling>" --ruling-ref <ruling path>` replaces
+ `--pm-quote`; only hands-on at XL+ needs the quote. At XS–L the EM writes the exit criterion itself (`sizing-accept-exit-criterion --sizing <path> --statement "<criterion>"`, no quote, any mode) and never asks the PM to set or accept one; an engine refusal demanding acceptance there is an engine defect, never a PM ask. In pm and ceo the ask says plainly that accepting
it authorizes execution without a further ask. A picker label is EM text, not PM words.
- After acceptance, `emit-wave-fire --from-sizing <repo-relative sizing path> --repo-root <abs repo>
- --trail-dir <abs trail dir>` mints the baton (never via /spinoff or /handoff) and prints one `Workflow` line. That line is the in-session fire, every mode: fire it and end
- the turn; on each stage's return the EM runs its `next_action` (`dispatch.terminal_commit` after execute) and fires the next stage. A headless
- `plan_chain.run` chain fire is opt-in only, pm/ceo, via `--chain`, which warns; the next EM touch is then the final wake digest (wiki
- `sizing-to-commit-chain-contract`). Never chain where an in-session Workflow would do.
+ After acceptance, submit `Workflow({name: "coordinator:engine-ask", args: {sizing: "<path>"}})`: the
+ run commits and ships the sizing, so no `dispatch.terminal_commit` follows it. Relay fallback, only when the engine refuses
+ that submission: `emit-wave-fire --from-sizing <repo-relative sizing path> --repo-root <abs repo>
+ --trail-dir <abs trail dir>` (never /spinoff or /handoff); name the refusal in the report.
- **6. Hard gate.** The t-shirt→route map binds absolutely; no override, no ratifier. A route that
+ **6. Hard gate.** The t-shirt→route map binds absolutely, with no override. A route that
feels wrong means the size was wrong: fix it with evidence (symmetric resize, or the `plan⇄sizing` return edge).
---
## Appetite guards
- `appetite` is the PM's stated budget, set only after the size lands and never moves the estimate. A cross-team dependency is a gate
- (`blocked_by`/`awaiting_gate`), never the t-shirt: answer `--boundary-in-notch no`. A roadmap
- `blocked` resting only on stakeholder alignment is stale against a fresh PM ask to execute.
+ `appetite` is the PM's stated budget, set after the size lands; it never moves the estimate. A cross-team dependency is a gate
+ (`blocked_by`/`awaiting_gate`), never the t-shirt: answer `--boundary-in-notch no`.