shapeup-sdlc 3.18.2 → 4.0.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.
Files changed (141) hide show
  1. package/.claude/settings.local.example.json +2 -3
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/AGENTS.md +115 -56
  4. package/README.md +101 -143
  5. package/SECURITY.md +16 -25
  6. package/agents/orient.md +14 -0
  7. package/agents/qa-edge-hunter.md +13 -0
  8. package/agents/spec-evaluator.md +14 -0
  9. package/agents/task-executor.md +14 -0
  10. package/bin/init.mjs +13 -16
  11. package/bin/lib/grant.mjs +8 -19
  12. package/commands/build.md +9 -14
  13. package/commands/eval.md +3 -3
  14. package/commands/hammer.md +9 -5
  15. package/commands/retro.md +12 -11
  16. package/commands/scopes.md +1 -12
  17. package/commands/ship.md +45 -88
  18. package/commands/wire.md +1 -8
  19. package/hooks/dispatch-receipt.mjs +94 -8
  20. package/hooks/hooks.json +0 -41
  21. package/hooks/lib/decision.mjs +6 -9
  22. package/hooks/lib/tier.mjs +50 -0
  23. package/hooks/sandbox-guard.mjs +140 -64
  24. package/kernel/gate.mjs +203 -22
  25. package/kernel/harness.mjs +20 -67
  26. package/kernel/init/run.mjs +175 -523
  27. package/kernel/lib/contract.mjs +9 -93
  28. package/kernel/lib/floor.mjs +64 -0
  29. package/kernel/lib/paths.mjs +39 -112
  30. package/kernel/order.mjs +157 -0
  31. package/kernel/probe/digest.mjs +2 -38
  32. package/kernel/schemas/domain.schema.json +146 -1125
  33. package/kernel/schemas/work-order.schema.json +8 -4
  34. package/kernel/schemas/work-result.schema.json +1 -1
  35. package/kernel/verify/envelope.mjs +2 -2
  36. package/kernel/verify/skills.mjs +27 -8
  37. package/kernel/verify/t0.mjs +2 -2
  38. package/package.json +4 -2
  39. package/skills/building/SKILL.md +144 -0
  40. package/skills/building/resources/gates.md +76 -0
  41. package/skills/building/resources/guidance.md +23 -0
  42. package/skills/{translator/references/preservation-rules.md → building/resources/intake-preservation.md} +1 -1
  43. package/skills/building/resources/intake.md +157 -0
  44. package/skills/building/resources/orders.md +69 -0
  45. package/skills/{ba-pitch-analyzer/references → building/resources/plan-references}/doc-schemas.md +1 -1
  46. package/skills/{ba-pitch-analyzer/references → building/resources/plan-references}/task-generation.md +13 -13
  47. package/skills/{ba-pitch-analyzer/references → building/resources/plan-references}/test-surface.md +6 -7
  48. package/skills/building/resources/plan-scopes.md +95 -0
  49. package/skills/building/resources/plan-spec.md +102 -0
  50. package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/_index.tmpl.md +1 -1
  51. package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/assess-report.tmpl.md +10 -11
  52. package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/run-state.tmpl.md +4 -4
  53. package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/scope-summary.tmpl.md +2 -2
  54. package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/synthesis.tmpl.md +4 -4
  55. package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/usecase.tmpl.md +2 -2
  56. package/skills/building/resources/plan-wire.md +82 -0
  57. package/skills/building/resources/plan.md +98 -0
  58. package/skills/building/resources/retro-research.md +60 -0
  59. package/skills/building/resources/retro-scan.md +49 -0
  60. package/skills/building/resources/retro.md +225 -0
  61. package/skills/building/resources/rounds.md +78 -0
  62. package/skills/building/resources/stop.md +127 -0
  63. package/skills/orient/SKILL.md +37 -37
  64. package/skills/qa-edge-hunter/SKILL.md +29 -14
  65. package/skills/shapeup/SKILL.md +5 -5
  66. package/skills/shapeup/resources/breadboarding.md +1 -1
  67. package/skills/shapeup/resources/context-compaction.md +5 -5
  68. package/skills/shapeup/resources/shaping.md +1 -1
  69. package/skills/spec-evaluator/SKILL.md +17 -21
  70. package/skills/spec-evaluator/references/dimension-contract.md +1 -1
  71. package/skills/spec-evaluator/references/dimensions/completeness.md +3 -3
  72. package/skills/spec-evaluator/references/dimensions/spec-conformance.md +1 -1
  73. package/skills/spec-evaluator/references/dimensions/test-surface-conformance.md +5 -5
  74. package/skills/task-executor/SKILL.md +11 -15
  75. package/commands/hill.md +0 -10
  76. package/hooks/gate-intake.mjs +0 -109
  77. package/hooks/gate-zerowork.mjs +0 -349
  78. package/hooks/tier-guard.mjs +0 -162
  79. package/kernel/compile.mjs +0 -1419
  80. package/kernel/init/fit.mjs +0 -199
  81. package/kernel/init/run-args.mjs +0 -206
  82. package/kernel/lib/breadboard.mjs +0 -165
  83. package/kernel/probe/attempts.mjs +0 -161
  84. package/kernel/probe/concurrency.mjs +0 -535
  85. package/kernel/probe/eval.mjs +0 -405
  86. package/kernel/probe/hunt.mjs +0 -104
  87. package/kernel/probe/leg.mjs +0 -229
  88. package/kernel/probe/owner.mjs +0 -142
  89. package/kernel/probe/requirements.mjs +0 -328
  90. package/kernel/probe/resume.mjs +0 -1110
  91. package/kernel/probe/rounds.mjs +0 -115
  92. package/kernel/probe/staged.mjs +0 -83
  93. package/kernel/probe/stats.mjs +0 -477
  94. package/kernel/probe/t0.mjs +0 -115
  95. package/kernel/reduce/board.mjs +0 -350
  96. package/kernel/reduce/graph.mjs +0 -482
  97. package/kernel/reduce/hill.mjs +0 -322
  98. package/kernel/reduce/ingest.mjs +0 -767
  99. package/kernel/reduce/leftovers.mjs +0 -159
  100. package/kernel/reduce/ship.mjs +0 -529
  101. package/kernel/reduce/snapshot.mjs +0 -291
  102. package/kernel/reduce/verdict.mjs +0 -172
  103. package/kernel/report/export.mjs +0 -384
  104. package/kernel/report/facts.mjs +0 -234
  105. package/kernel/verify/budget.mjs +0 -153
  106. package/kernel/verify/build.mjs +0 -428
  107. package/kernel/verify/dispatch.mjs +0 -114
  108. package/kernel/verify/spec.mjs +0 -975
  109. package/kernel/verify/trace.mjs +0 -604
  110. package/skills/ba-pitch-analyzer/SKILL.md +0 -204
  111. package/skills/coach/SKILL.md +0 -397
  112. package/skills/hill-chart/SKILL.md +0 -154
  113. package/skills/hill-chart/assets/dashboard.template.html +0 -1432
  114. package/skills/scope-architect/SKILL.md +0 -174
  115. package/skills/scope-hammer/SKILL.md +0 -231
  116. package/skills/solution-architect/SKILL.md +0 -158
  117. package/skills/tech-lead/SKILL.md +0 -151
  118. package/skills/tech-lead/references/gates.md +0 -605
  119. package/skills/tech-lead/references/protocol.md +0 -889
  120. package/skills/tech-lead/references/tiny-lane.md +0 -53
  121. package/skills/tech-lead/workflows/shapeup-run.js +0 -2187
  122. package/skills/translator/SKILL.md +0 -258
  123. /package/skills/{ba-pitch-analyzer/references → building/resources/plan-references}/contract-patterns.md +0 -0
  124. /package/skills/{ba-pitch-analyzer/references → building/resources/plan-references}/ddd-patterns.md +0 -0
  125. /package/skills/{ba-pitch-analyzer/references → building/resources/plan-references}/integration-analysis.md +0 -0
  126. /package/skills/{ba-pitch-analyzer/references → building/resources/plan-references}/ux-behavior-patterns.md +0 -0
  127. /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/api-feasibility.tmpl.md +0 -0
  128. /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/contracts/be-service.contract.tmpl.md +0 -0
  129. /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/contracts/offline-storage.contract.tmpl.md +0 -0
  130. /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/contracts/third-party-api.contract.tmpl.md +0 -0
  131. /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/cross-context/context-map.tmpl.md +0 -0
  132. /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/cross-context/event-choreography.tmpl.md +0 -0
  133. /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/cross-context/migration-plan.tmpl.md +0 -0
  134. /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/cross-context/team-handoff.tmpl.md +0 -0
  135. /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/domain-model.tmpl.md +0 -0
  136. /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/feedback.tmpl.md +0 -0
  137. /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/integration.tmpl.md +0 -0
  138. /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/task-board.tmpl.md +0 -0
  139. /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/task-spike.tmpl.md +0 -0
  140. /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/task.tmpl.md +0 -0
  141. /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/ux-behavior.tmpl.md +0 -0
@@ -1,605 +0,0 @@
1
- # Tech-Lead Gate Playbooks
2
-
3
- The full collect-lists, gate-output blocks, and delegation scripts for every gate and delegation
4
- step, extracted from `SKILL.md` (progressive disclosure). **Read the relevant section when you
5
- reach that gate** — `SKILL.md` carries the workflow spine and the hard rules; this file carries the
6
- step-by-step playbooks. The L2/L4 gates stay hook-enforced regardless of where the prose lives.
7
-
8
- **Which lane these playbooks serve.** The gate blocks below are lane-independent: every
9
- lane emits them verbatim, and on the scoped lane `shapeup-run.js` returns the `block` field for
10
- `SKILL.md` to print unchanged. What differs is who runs the loop *between* the gates:
11
-
12
- | lane | BUILD → GATE L2 → EVAL is | read |
13
- |---|---|---|
14
- | a spec with committed `scopes/*.md` (the common case) | **code** — `skills/tech-lead/workflows/shapeup-run.js`'s round loop | that script's comments |
15
- | `--tiny`, or a spec with no scope contracts yet | **prose**, unchanged and non-regression | `references/protocol.md` (`:11-22` states the same split) |
16
-
17
- Order matches the run: GATE L0 → ORIENT → GATE L1a → ANALYZE → WIRE/L1a.5 → MAP SCOPES →
18
- GATE L1b → (BUILD → GATE L2 → EVAL — see the table above) → GATE L3 → SHIP → GATE L4.
19
-
20
- ⟐ **ANALYZE runs before WIRE.** MAP SCOPES' two dispatches split around
21
- L1a.5: `analyze` writes the spec tree, then `wire` reads its `usecases/` — one wiring-map entry per
22
- use case — then `map-scopes` slices. Dispatching WIRE first hands `solution-architect` an empty
23
- spec folder, which its own input contract excludes (`skills/solution-architect/SKILL.md:43-44`); it
24
- escalates, writes nothing, and every relaunch re-dispatches it.
25
-
26
- ---
27
-
28
- ## GATE L0 — Intake & Run Config
29
-
30
- **Purpose:** Pin everything the run needs once, up front, so the loop never has to guess.
31
-
32
- ```
33
- Collect (explicit — never inferred):
34
- L0.1 Kicked-off pitch source: `shaping.md` — and its `breadboard.md`, which the run finds
35
- beside it (or in `shaping/`) or takes from `--breadboard`; a `pitch.md` may carry the
36
- breadboard inline. Already shaped + bet by PO.
37
- Not a raw idea — shaping (1-4) / betting (5) / kick-off (6) are PO-personal, upstream.
38
- L0.1a Language gate, BEFORE init run: Agent (model: exec) → Skill(shapeup-sdlc-plugin:translator)
39
- --check over the pitch AND its breadboard.
40
- English → use both as-is.
41
- non-English → Agent (model: exec) → Skill(shapeup-sdlc-plugin:translator) <pitch> <breadboard>
42
- (--auto under auto/unattended), then open the run on the produced
43
- <name>.en.md — init run prefers a breadboard.en.md beside it, and warns
44
- when it can find only the untranslated breadboard. The run's intake is
45
- what every planning worker reads, so a translation made after the run
46
- opened reaches nobody: re-open with --force naming the .en.md. Log in ledger.
47
- L0.1b Appetite: read the `appetite` field from the pitch's YAML frontmatter (set by /shapeup).
48
- Surface it in the gate output. Use it to:
49
- - Contextualise the scope at L1b (right-size cuts to the budget).
50
- - Anchor max_rounds suggestion: 1-week → 2 rounds, 2-week → 3, 6-week → 4.
51
- If appetite is missing or "TBD (uncapped)": flag as a risk and note it in the ledger;
52
- proceed, but the PO should set scope expectations manually at GATE L1b.
53
- L0.2 Workspace roots (both keyed off <slug>, set here and threaded to every worker as args):
54
- - SHARED shapeup/<slug>/ — durable source + deliverable (committed):
55
- shaping/ (from /shapeup), spec/ (where ba-pitch-analyzer writes the spec tree:
56
- _index, domain-model, usecases/, contracts/, scopes/, scope-summary.md — NOT tasks/)
57
- - LOCAL .shapeup/<slug>/ — run-trace (hidden, gitignorable):
58
- harness-run.md (this ledger), digest, orient/, evaluation/, qa/,
59
- discovery/ledger.md, orders/ + results/ (the envelope port), tasks/ (the task
60
- spec_folder = shapeup/<slug>/spec/ (the deliverable arg passed to ba/eval/exec)
61
- L0.3 lens: lite | standard | cross-context (passed to planner at step 8)
62
- L0.4 stack hint (e.g. "pnpm, Next 16 web :3000") — aims orient's code-surface sweeps + run commands
63
- L0.5 eval dimensions: default `auto` — each EVAL order resolves the set from the spec
64
- (spec-conformance + tdd-surface always; integration for .be/.e2e tasks; completeness
65
- when a UC has Invariants; test-surface-conformance when one has a Test Surface).
66
- Name a set only if the user asks. It must reach `harness init run --dimensions <a,b>`
67
- — it is recorded in the ledger's `eval_dimensions:` line and replaces the resolved
68
- set, so a set agreed in conversation and not passed to the flag grades nothing. Shipped ids:
69
- spec-conformance, tdd-surface, integration, completeness, test-surface-conformance
70
- (security + performance ship disabled). Whatever is left out is reported at L4 as
71
- `dims_not_evaluated` — "shipped" never silently means "verified for all".
72
- L0.6 max_rounds: default 3, appetite-informed (see L0.1b)
73
- L0.7 auto level:
74
- interactive (default) — pause at every L-gate; sub-skills keep their own gates
75
- --auto — sub-skills run unattended (--auto); tech lead still pauses
76
- at L1a/L1b (orient+plan), L3 (verdict), L4 (ship)
77
- --unattended — auto-confirm all L-gates too; stop only on PASS,
78
- max_rounds, or hard error (for headless / Agent SDK / CI)
79
- L0.8 Model & budget resolution (four layers, highest precedence
80
- first) — resolve ONCE here, record the resulting matrix in the ledger header:
81
- /ship flags → .claude/settings.local.json (per-member, Tier C) →
82
- .claude/settings.json (team defaults, committed) → skill-shipped defaults
83
- Env knobs read at this layer: SHAPEUP_ORCH_MODEL, SHAPEUP_EXEC_MODEL,
84
- SHAPEUP_EVAL_MODEL, SHAPEUP_QA_MODEL, SHAPEUP_ATTEMPT_BUDGET (default 5),
85
- SHAPEUP_DIGESTER_MODEL (default "script" — harness probe digest's regex pass; falls
86
- back to a Sonnet dispatch only when the digester reports unrecognized log formats).
87
- A requested model unavailable on the member's plan → degrade to the next tier down,
88
- record the degrade in the ledger (R2 — invariants are code paths, so adherence
89
- survives even when the model tier doesn't).
90
- L0.9 attempt_budget: the INNER circuit breaker, nested inside
91
- max_rounds (the OUTER breaker, unchanged, L0.6). Default 5 — the number of T0 verify
92
- attempts a single scope gets inside one round before its attempt loop trips and
93
- queues a hammer PROPOSAL for GATE H rather than blocking the round. Only meaningful
94
- when the spec folder has scope contracts; a spec with none skips the attempt loop
95
- entirely and BUILD behaves exactly as in v0.2.6 (task-executor --next, no T0).
96
- no_progress_k (v1.5): the STAGNATION term of the same inner breaker. Default 2 — the
97
- number of consecutive non-`kept` trials after which a scope ends early and queues the
98
- same GATE H proposal. attempt_budget counts ATTEMPTS and cannot see that the last two
99
- produced nothing; this term can, and on a flailing scope it saves three of five
100
- attempts. Set per scope (`no_progress_k` on the contract) or per run in the payload.
101
- L0.10 knowledge base (read, never obeyed): if `shapeup/knowledge-base/tech-lead.md` exists,
102
- read it now. Its **Workflow guidance** may add a question, a check or a warning line to
103
- any gate block below and may name the spike to insist on at L1a; its **Suggested run
104
- config** lines are PROPOSALS for L0.2–L0.9 and the profile — confirm each with the PO
105
- before pinning it, and record `(source: knowledge-base)` beside a value taken from there.
106
- Nothing in that file answers a gate: the answer set resolves exactly as it would without
107
- it, and a line that could only be honoured by skipping, reordering or relaxing a gate is
108
- reported as a suspected harness defect, not applied. If `shapeup/knowledge-base/` has no
109
- file at all, offer the optional seed once — `/retro --scan` (the coach's scan operation)
110
- drafts guidelines from the project on disk, or `/retro --research <stack>` (its
111
- research operation) from the platform's official documentation when the project has no
112
- build file to scan; both put every rule through GATE COACH-1 — and continue whether or
113
- not the PO takes it. A Suggested run config line with `web-research` provenance has
114
- never run in this project: confirm it like any other, and expect the first round build
115
- gate to be its first execution.
116
- ```
117
-
118
- **L0.9b — the launch record.** Every switch the operator typed to *this launch* becomes a `RunArgs`
119
- field, or it does nothing at all: the workflow cannot read a config file and cannot ask a follow-up,
120
- so a flag that stops at the skill boundary was accepted and ignored. That is not hypothetical —
121
- `--no-qa` was documented in seven places across the shipped set and inert in all of them, because no
122
- line of this protocol ever put `noQa` into the record. `--wall-clock-budget` is the one flag below
123
- that is not a `RunArgs` field at all — it is consumed earlier, at `init run` itself, and never
124
- needed to reach this launch; see its row for where it actually lands.
125
-
126
- | Flag | `RunArgs` field |
127
- |---|---|
128
- | `--no-eval` | `noEval: true` |
129
- | `--no-qa` | `noQa: true` |
130
- | `--parallel-scopes N` | `maxParallelScopes: N` — how many scopes build at once (default 4; `1` = sequential) |
131
- | `--adversarial-verify` | `adversarialVerify: true` |
132
- | `--rounds N` / `--attempts N` | `budgets.{maxRounds,attemptBudget}` |
133
- | `--gate-answers <set>` | `answers` |
134
- | `--wall-clock-budget S` | *(not a `RunArgs` field)* — typed once, on the `harness init run` command line itself, not on this launch; it lands straight in the run receipt as `wall_clock_budget_s`, and the deadline breaker reads that receipt field directly — consumed by `kernel/verify/budget.mjs` as `wall_clock_budget_s`. `budgets` declares only `maxRounds`/`attemptBudget` — the schema, `SKILL.md`'s own RunArgs contract line and this script's own header comment all agree there is no third member |
135
- | `--orch-model/--exec-model/--eval-model/--qa-model` | `models.{…}` (L0.8) |
136
-
137
- `harness init run-args` (invoked at Step 2 of `SKILL.md`) is the sole writer of the assembled
138
- object: it takes the resolved values above, writes `.shapeup/<slug>/run-args.json` fresh on every
139
- launch and relaunch, and prints the same object back so the launch never re-assembles it by hand. It
140
- is the only artifact that records what a run was configured with; the ship report, a resumed session
141
- and any later measurement all read it, and none of them can recover a value that only ever existed
142
- as an argument. Step 2 is not merely advisory: `shapeup-run.js`'s own Preflight refuses to dispatch
143
- ORIENT (or anything past it) when this file is missing at the run's local root — a launch that
144
- skipped this step aborts there rather than proceeding on a silent default.
145
-
146
- **L0.0 — intake precondition (before any other L0 collection):**
147
- ```
148
- resolve intake from, in order:
149
- 1. --pitch <path> (a shaping/pitch file on disk)
150
- 2. --spec <folder> (an existing spec tree)
151
- 3. <intake> requirement text passed to the skill
152
- none resolvable -> ABORT. Print the ✋ NO INTAKE block from SKILL.md and stop.
153
- Do NOT emit the GATE L0 block. Do NOT list downstream gates.
154
- Do NOT describe the pipeline that "will" run.
155
- ```
156
- An orchestrator with no spec has nothing to orchestrate. Narrating the gate list in that state
157
- produces output that reads exactly like a successful run and contains no work. Fail loudly instead.
158
-
159
- **GATE L0 Output:**
160
- ```
161
- ⏸ GATE L0 — Intake & Run Config
162
- Feature : [slug] (kicked-off pitch: [path])
163
- Intake lang : [English | translated via /translator → <name>.en.md]
164
- Appetite : [~1 week | ~2 weeks | ~6 weeks | ⚠️ missing — scope uncapped]
165
- Spec folder : [path] (lens: [lite|standard])
166
- Eval dims : [auto | the named set] max_rounds: [N, appetite-informed] auto: [interactive|auto|unattended]
167
- Run commands : [web: ... | api: ... | mobile: ...] (run_cmd → the round build gate, every round before EVAL)
168
- Build gate : build_probe [set | —] launch_probe [set | — ⚠ mobile: the install/launch risk has no owner]
169
- Model matrix : orch=[model] exec=[model] eval=[model] qa=[model] digester=[script|sonnet] (source: [flags|settings.local|settings.json|default])
170
- Budgets : round_budget=[N] (outer) attempt_budget=[N] (inner, per scope)
171
- Knowledge : [tech-lead.md — N workflow rules, M suggested values (confirmed above) | none — `/retro --scan` or `/retro --research <stack>` seeds it (optional)]
172
- ```
173
- **Resolve it** — this gate is this skill's own (the workflow never sees it), so it is this skill
174
- that runs the same tool every other gate resolves through, not a paragraph read as a stand-in for
175
- one: `node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" gate --resolve L0 --slug <slug>
176
- [--file <path>|--preset <name>]`. Exit 4 (`ask`) is the confirmation this block already asks for —
177
- put it to the PO and wait, same as the paragraph above always meant. Exit 0 (`decision=proceed`) —
178
- continue straight to ORIENT, which is what `--unattended`'s pre-answered set resolves to. Exit 5
179
- (`abort`) — stop; do not launch. Either way, the gate's own ledger row is what lets a later reader
180
- see the decision that opened the run, not only the decisions that closed it.
181
-
182
- ---
183
-
184
- ## ORIENT (step 7) — delegate to orient (the Scout)
185
-
186
- The Shape Up Building phase opens with **Orient, not planning**: the team reads the real code
187
- and spikes the scary parts *before* any board exists, so the board comes out reality-born.
188
-
189
- ```
190
- Invoke via Agent (model: exec — see references/protocol.md "Invocation mechanism"):
191
- Skill(shapeup-sdlc-plugin:orient) --pitch <intake> --spec <path> --stack "<hint>" [--auto]
192
- Owns: its own GATE O-A/O-B; runs straight through under --auto.
193
- Writes: .shapeup/<slug>/orient/ → code-surface.md, spike-<area>.md, discovered-seed.md, hill-signal.md.
194
- Record in ledger: orient duration + the spiked area + spike result (resolved | SPIKE-UNRESOLVED).
195
- ```
196
- The four artifacts are the **orient → ba contract**: `ba` (step 8) consumes them instead of
197
- re-scanning the codebase. Pass `--auto` only when the run level is `--auto`/`--unattended`.
198
-
199
- ---
200
-
201
- ## GATE L1a — Orient Review
202
-
203
- **Purpose:** PO sees where the pitch lands in real code and what's still unknown — *before*
204
- committing to a scope map. This is the first Hill read (area-level — slices don't exist yet).
205
-
206
- ```
207
- Read .shapeup/<slug>/orient/. Render the 🗻 Hill from hill-signal.md (see protocol.md "Hill report"):
208
- - each suspected area → uphill (open unknowns) | crest (approach proven by the spike) | downhill
209
- Print: `Breadboard: <source> | none` (how init run found the pitch's breadboard — flag, sibling,
210
- shaping-dir, shared-root, embedded — or none), the code-surface headline (where it lands),
211
- the spiked area + result, the riskiest open unknowns going into mapping.
212
- Ask (max 2): is the riskiest area the right one to have spiked? any unknown that must be
213
- resolved (another spike) before we map scopes?
214
- ```
215
- Do NOT enter MAP SCOPES until Orient is accepted.
216
-
217
- ---
218
-
219
- ## WIRE (step 7.5) + traceability spine ✚ — delegate to solution-architect
220
-
221
- **Active only when the spine is in use** — on a legacy spec skip it; `trace-lint` self-skips every arm whose artifact is absent (non-regression).
222
-
223
- ```
224
- 1. PROFILE (you write it at L0 — compile-order stays pipeline-blind): SHARED project-profile.md
225
- = {schema_version:1, archetype, entry_point, source_extensions?, build_probe?, launch_probe?}.
226
- archetype ∈ {client-only-game|web-service|mobile|library|data-pipeline}; entry_point is the
227
- reachability seam (a game's main.js is NOT a service's src/server.ts). Validate the enum — a
228
- typo must fail, not silently disable the check. entry_point is also the root reachability walks
229
- the import graph from, so where some module does compose the app, name that one rather than the
230
- file the platform happens to start. Where the screens are registered in a MANIFEST instead (a
231
- route map, a plugin table, a string-loaded page), no entry point roots an import walk at all —
232
- measured on a real ArkTS app, where the navigation host imports nothing and every screen arrives
233
- through route_map.json. The arm then reports that it could not check, and that is the correct
234
- end state for such a project rather than a profile to keep re-declaring.
235
- source_extensions is optional and only needed when the project's modules end in something the
236
- entry point does not (e.g. [".ets"] when the entry is a .ts file); leaving it out costs a
237
- skipped arm, never a false red. The two probes feed the round build gate (`harness verify
238
- build`, every round before EVAL): build_probe asserts the BUILT ARTIFACT covers what the run
239
- wrote (a green exit code is not proof the feature compiled when the toolchain compiles only what
240
- an entry point reaches); launch_probe installs, starts and asserts the first screen. A `mobile`
241
- profile without a launch_probe is warned about every round — nothing else in the loop launches
242
- the app.
243
- 2. WIRE — compile-order --operation wire --slug <slug> (worker→solution-architect), payload
244
- {project_profile, breadboard?}. Sole writer of committed wiring-map.md (per-UC engine → seam → entry-point
245
- call site → affordance). ⏸ GATE L1a.5: confirm each UC has a declared seam before slicing.
246
- ⟐ PRECONDITION: MAP SCOPES step 1 (ANALYZE) has already run and usecases/ is
247
- populated. WIRE writes one entry per use case, so dispatching it against an empty spec folder
248
- is an escalation, not a wiring map — and a phase that writes no artifact is re-dispatched on
249
- every relaunch. Verify: node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" probe resume
250
- --slug <slug> --require analyze (exit 0 = the spec tree is there; exit 6 = do not dispatch WIRE).
251
- Post-check the same way after the dispatch: --require wire.
252
- requirements.md registry (atomic REQ clauses, frozen ids).
253
- 4. trace-lint — node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" verify trace --slug <slug>. ADVISORY at L1b:
254
- covers-closure (every covered REQ named by ≥1 AC's covers:) + reachability (every UC engine
255
- reaches entry_point). Promote to --gate only once covers: is populated. Reachability reports
256
- checked:false with a reason rather than a verdict in two cases, both warns: an import it could
257
- not follow (the graph is incomplete) and no engine reachable at all (nothing controls the walk,
258
- so an orphan and a wrong root look identical). Read either as "re-declare the profile", never
259
- as a clean arm. When it does run it also reports, per scope, how many of that scope's own source
260
- files the app reaches, and warns (SCOPE-UNREACHABLE) on a scope it reaches none of — a scope's
261
- build fixture can be green while its code never compiles, on any toolchain that compiles only
262
- what the entry point reaches. Warn only: the wiring may be a later scope's job by design.
263
- ```
264
-
265
- ---
266
-
267
- ## MAP SCOPES (step 8) — delegate to ba-pitch-analyzer (orient-informed)
268
-
269
- ⟐ **Step 1 runs BEFORE the WIRE section above; step 2 runs after it.** The two
270
- dispatches sit either side of L1a.5: ANALYZE writes the use cases WIRE reads, and MAP SCOPES slices
271
- against the seams WIRE declared. Sequence: ORIENT → L1a → **ANALYZE** → **WIRE** → L1a.5 →
272
- **MAP SCOPES** → L1b.
273
-
274
- ```
275
- Two orders, two workers, one step (both model: exec — see references/protocol.md):
276
- 1. ANALYZE + BOARD — compile-order --operation analyze --slug <slug> --worker ba-pitch-analyzer
277
- --payload '{"pitch": "<path>", "breadboard": "<the path init run printed, when it printed one>", "lens": "<lens>", "orient_dir": ".shapeup/<slug>/orient/"}'
278
- dispatch: Skill(shapeup-sdlc-plugin:ba-pitch-analyzer) --order <path>. The order hands it
279
- code-surface.md (Phase-1 ingest consumes the map, does not re-scan), discovered-seed.md
280
- (task gen starts from reality), spike-<area>.md (feasibility/contracts).
281
- Output expected: spec_folder populated with _index, domain-model, usecases/, contracts/,
282
- scope-summary.md (all SHARED/committed) + tasks/TASK-NNN*.md, tasks/_index.md (board)
283
- written to the LOCAL root .shapeup/<slug>/tasks/ (v3.2) + a WorkResult → ingest.
284
- 2. MAP SCOPES — compile-order --operation map-scopes --slug <slug> --worker scope-architect
285
- dispatch: Skill(shapeup-sdlc-plugin:scope-architect) --order <path>. Sole writer of the
286
- committed scopes/<scope-id>.md contracts (import-graph slicing, substrate whitelists,
287
- affordance manifest, fixtures, PA1/PA2 — mechanically linted by harness verify spec).
288
- Record in ledger: planner duration + task count + scope count.
289
- ```
290
- Faithful note: keep the planner ambitious on scope but high-level on tech — do not push it
291
- to over-specify implementation. Errors baked into the spec cascade into every build round.
292
- Honest deviation: `ba` is heavier than Shape Up's light "map scopes" bucketing — that extra
293
- upfront spec-traceability is a deliberate trade for an LLM builder, not
294
- "pure Shape Up". State it; don't pretend otherwise.
295
-
296
- ---
297
-
298
- ## GATE L1b — Board Review (Plan Acceptance)
299
-
300
- **Purpose:** PO sees the shape of the work before a single line of code. This is where scope
301
- is cut or confirmed — cheap here, expensive later.
302
-
303
- **v3.2 (local-tasks-architecture):** on a spec with
304
- scope contracts, the PO reviews the SHARED, committed plan — `usecases/_index.md` +
305
- `scopes/*.md` + `scope-summary.md`'s Done-when headlines — never the LOCAL task board
306
- (`tasks/_index.md`, gitignored, per-machine run-trace). Implementation-level task detail stays
307
- hidden at this gate by design; the PO signs off on the UCs covered and how they're cut into
308
- scopes, not a line-by-line task list. A pre-v0.3.0 spec (no scope contracts) has no scope
309
- board to substitute for — this gate still reads `tasks/_index.md` directly, unchanged from
310
- v0.2.6 (non-regression).
311
-
312
- **Bootstrap check (local tasks board) — run BEFORE the read below, always:**
313
- ```
314
- `.shapeup/<slug>/tasks/_index.md` missing AND `shapeup/<slug>/spec/usecases/`
315
- exists → a teammate (or a `--from build` resumed run) has the SHARED spec via git but no LOCAL
316
- task board on this machine — `.shapeup/` is gitignored and never travels with a branch.
317
- Agent (model: exec): Skill(shapeup-sdlc-plugin:ba-pitch-analyzer) --order <path> + ingest —
318
- regenerates the board from the committed usecases/domain-model/scopes. Record the bootstrap in
319
- the ledger. No-op on a fresh r=1 run (MAP SCOPES just wrote the board on this same machine) or
320
- any machine that already has one — this only fires for the second-developer / resumed-run case.
321
- ```
322
-
323
- ```
324
- Scope contracts present:
325
- Read usecases/_index.md + scopes/*.md (scope-board.md) + scope-summary.md. Print:
326
- - UC count + actors (usecases/_index.md)
327
- - scope board: scope_id, topology_type, substrate file count (scopes/*.md / scope-board.md)
328
- - any SPIKE blockers (scope-summary.md)
329
- - scope-summary "Done when" headline statements
330
- - the Deferred Places from ux-behavior.md (breadboard Places this shape will not build) —
331
- each one needs the PO's yes; a rejected deferral goes back to the planner as a screen
332
- - the REQ → AC table from requirements.md, one row per registered requirement: REQ-id, the
333
- source clause it came from (`REQ-12 ← shaping.md R12`), and the acceptance criterion that
334
- grades it — or the scope that claims it, or CUT (PO-approved). Omitted entirely when the run
335
- has no registry. A requirement with none of the three is already a red below; this table is
336
- what the PO reads to answer it — cover it, or cut it on the record. Printed, never asked:
337
- the table decides nothing at this gate
338
- No scope contracts (pre-v0.3.0, unchanged from v0.2.6):
339
- Read tasks/_index.md (LOCAL root). Print:
340
- - task count by package/variant (.shared / .be / .web / .mobile / .e2e)
341
- - layer distribution (Layer 1→6) and the critical dependency path
342
- - any SPIKE tasks (third-party feasibility) that block others
343
- - scope-summary "Done when" headline statements
344
-
345
- Substrate-disjointness assertion (only when
346
- shapeup/<slug>/scopes/*.md exist — scope-architect's lint pass already ran;
347
- this is the orchestrator's own re-confirmation before committing to a build sequence):
348
- - Run `node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" verify spec --slug <slug>`: DISJOINT (a file in two
349
- scopes' `allowed_file_substrate` without BOTH declaring it `shared_substrate` — PA3
350
- waiting to happen), PA1 (directory-aligned scope), PA2 (size cap), SCOPE-ANCHOR (a scope
351
- naming no committed use case, or one that does not resolve), TIER-DIRECTION (a committed
352
- contract naming LOCAL task ids), SCOPE-DEPS (a build-order id naming a scope that is not
353
- in this run), REQ-UNCOVERED (a requirement in requirements.md that no acceptance criterion
354
- grades and no scope claims — the PO's two ways out are an AC carrying `(covers: REQ-…)` or
355
- `CUT (PO-approved)` in the registry; silent on a run with no registry),
356
- CONTRACT-SCHEMA (a scope contract that parses but not into the shape a WorkOrder carries —
357
- most often a list written bare in a table cell where the dialect wants `[a, b]`; without
358
- this the compiler refuses the order later and the scope is never dispatched at all, with
359
- the board green and the leg reporting done), CONTRACT-UNREADABLE (a table the parser could
360
- not see, or a table field also declared in frontmatter where nothing reads it),
361
- BREADBOARD-PLACE (a breadboard Place with UI affordances has no
362
- `## Screen: … (P#)` in ux-behavior.md and is not deferred), BREADBOARD-UI (a U# not
363
- specified on a screen of its own Place). Any red → HARD STOP, past a 🔴 at the
364
- architect's own checkpoint. The breadboard reds are the planner's to fix — add the screen
365
- or defer the Place; never fold it into another screen.
366
- - Lock the build SEQUENCE riskiest-first: order scopes by open-unknowns count (from
367
- hill/<scope-id>.yml if present, else the orient hill signal), not by file count or
368
- alphabetical — Shape Up's "solve in the right sequence" (step 10).
369
- DEPENDENCIES CONSTRAIN THAT ORDER, and each contract declares its own: scope A follows scope
370
- B when A names B in `depends_on`. The order lives in the same committed tier as the contracts
371
- it orders, so it survives a clone. Risk orders the scopes; the dependencies decide when each one is
372
- RELEASED — a scope starts as soon as the scopes it consumes have settled, not when its whole
373
- level has, so a scope may well start while a sibling is still building. A scope that consumes
374
- the others' output (an entry point wiring up command modules) therefore cannot be scheduled
375
- alongside them however low its unknowns count. It fails open: a contract declaring no
376
- `depends_on`, or naming a scope that is not in this run, falls back to releasing a level at a
377
- time, and then to no constraint at all (spec-lint SCOPE-DEPS reports the dangling id).
378
-
379
- Ask (max 2): scope cuts? lens correct? any SPIKE to resolve before build?
380
- Scope-hammer framing: reference the appetite from the pitch
381
- (e.g. "Given a ~1-week appetite, which of these scopes feels right-sized?").
382
- Also surface any rabbit holes identified in the pitch — they flag where scope
383
- may expand unexpectedly if not cut now. A scope cut here is cheap; after
384
- BUILD round 1 it's expensive.
385
- ```
386
- Do NOT enter BUILD until the board is accepted.
387
-
388
- ---
389
-
390
- ## GATE L2 — Board 100% Done (Pre-Eval)
391
-
392
- **Purpose:** The single exit point from the BUILD loop into EVAL. It ensures every scope is green before invoking the evaluator.
393
-
394
- **Output:**
395
- ```
396
- ⏸ GATE L2 — Board 100% ✅ + T0-green
397
- Feature : [slug]
398
- Round : [r]
399
- Scopes : [N] green, [M] queued for hammer
400
- Build gate: [green | red — <failing step> | undeclared]
401
- ```
402
-
403
- The build gate is `harness verify build --slug <slug> --round <r>` — the ledger's `run_cmd`, then
404
- the profile's `build_probe` and `launch_probe`, stopping at the first failure. It runs before this
405
- gate so the block shows it; `red` means EVAL is NOT dispatched this round (the judge grades a running
406
- feature) and the failing step is compiled into round r+1's orders as `payload.bugs`. `undeclared`
407
- means L0 pinned no run command and the profile names no probe — the round proceeds over an
408
- unproven build, and the block says so.
409
-
410
- Under `--interactive` / `--auto`, the gate block carries the board facts — `green_scopes`, `hammer_proposals` — and requires explicit PO approval to proceed. Under `--unattended` the answer set resolves it. **There is no hook behind this gate**: the `PreToolUse` warning it used to carry was retired into the block in v2.0, so what an unfinished board costs you here is a human reading the numbers, not a machine refusing the call.
411
-
412
- ---
413
-
414
- ## GATE L3 — Verdict & Loop
415
-
416
- ```
417
- Render the 🗻 Hill report (slice-level) — NOT a task count. Scope contracts present → read
418
- committed hill/<scope-id>.yml shards (mechanical phases from GATE L2, never authored). No contracts →
419
- fall back to the board + open-unknowns heuristic (uphill/crest/downhill/done). See
420
- references/protocol.md "Hill report". Roadmap rule unchanged either way: progress is
421
- reported by hill position, never by "N/M tasks done".
422
-
423
- Read EVAL-FEATURE-<slug>.md verdict.
424
-
425
- PASS:
426
- → first PASS of the run AND not --no-qa:
427
- delegate ▶ QA EDGE HUNT → Agent (model: qa — see references/protocol.md
428
- "Invocation mechanism"): Skill(shapeup-sdlc-plugin:qa-edge-hunter) (pure worker; see
429
- round-protocol "QA edge hunt"). Args: spec folder, EVAL report path, ledger path, app URL.
430
- Its GATE Q0/Q1 pauses surface here. Output: `~` findings → .shapeup/<slug>/discovery/ledger.md
431
- + .shapeup/<slug>/qa/hunt-report.md. No verdict — the run's verdict stays this EVAL's PASS.
432
- → then proceed to SHIP (triage of QA findings happens at SHIP S.0/GATE L4).
433
- → subsequent PASS (a promoted-findings fix round): Agent (model: qa):
434
- → --no-qa or skill absent: proceed straight to SHIP; ledger records `qa: skipped`.
435
-
436
- FAIL:
437
- → a round whose build gate was red never reached the judge: the block carries `build_gate: red`,
438
- the "bug list" is the gate's failing step (its command, exit and output tail), and round r+1
439
- is a fix round over exactly that. Nothing the evaluator would have said is missing — it was
440
- never asked.
441
- → print the bug list grouped by task/severity. For each bug: task ID + failed Done-when criterion + repro.
442
- DO NOT prescribe fix options or root cause hypotheses — that is the implementer's job.
443
- The tech lead names scope; the implementer diagnoses and fixes.
444
- → ask (max 1): approve fixing these in BUILD round r+1? (or cut scope / waive a bug)
445
- → if r+1 > max_rounds: STOP. Escalate to PO with the residual bug list — do not loop
446
- forever. The harness reports honestly that it hit its round budget.
447
- → else: go to BUILD round r+1 (bug-only).
448
- ```
449
-
450
- **GATE L3 Output:**
451
- ```
452
- ⏸ GATE L3 — Verdict (round [r])
453
- 🗻 Hill : S1-spine 🔽 downhill · S2-filters ⛰️ crest · S3-export 🔼 uphill
454
- Verdict : [PASS | FAIL] bugs: [N] (rounds used: [r]/[max])
455
- Decision : [SHIP | re-build bugs in round r+1 | escalate: max rounds hit]
456
- ```
457
- The Hill is the progress narrative; the board's `N/N ✅` is execution substrate (it gates
458
- EVAL at L2), never the headline. Slices come from `ba`'s board; if slice IDs aren't present
459
- yet, report at task-group level and note the fallback in the ledger.
460
-
461
- ---
462
-
463
- ## SHIP (step 11) — close out
464
-
465
- ```
466
- S.0 GATE H — delegate to scope-hammer (this IS Shape Up's "Decide When to Stop", step 11):
467
- Invoke via Agent (model: exec — see references/protocol.md "Invocation mechanism"):
468
- Skill(shapeup-sdlc-plugin:scope-hammer) --slug <slug> --baseline <shaping/baseline.md if present>
469
- [--breaker outer] when round_budget hit 0 with scopes still open
470
- [--breaker inner --scope <id>] once per queued hammer proposal (attempt_budget
471
- exhausted scopes accumulated during BUILD)
472
- (no --breaker flag) normal stop — all scopes FINISHED, post-QA-hunt
473
- Feeds it: qa/hunt-report.md findings (when present), discovery/ledger.md open items,
474
- the hammer-proposal queue from BUILD (attempt-budget exhaustions).
475
- Ownership facts in its census — "no scope owns X", "X belongs to scope Y" — come from
476
- node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" probe owner --slug <slug> [--path <p>]...
477
- which elects the owner from the committed contracts' substrates, never from prose.
478
- Reads back: its GATE H0/H1/H2 output — census, baseline comparison, cut list + verdict.
479
- Authority: scope-hammer proposes; the tech lead records the PO's decision in
480
- round-ledger.md and performs the actual close (S.1 onward). It never ships on its own.
481
- - Cut list confirmed → all cuts carried to discovery/ledger.md as raw ideas (debt-free).
482
- - Verdict = CANNOT SHIP (a must-have item failed H1.2) → do NOT proceed to S.1; escalate
483
- to PO honestly with scope-hammer's ship-blocking list, same spirit as a max-rounds
484
- escalation.
485
- Pre-v0.3.0 spec (no scope contracts) → scope-hammer still runs; H0's only census sources
486
- are QA + discovery ledger (no scope/attempt-budget inputs), equivalent to the old inline
487
- triage this step used to do.
488
- S.1 Confirm board green + latest eval verdict = PASS.
489
- S.1b Checklist-hygiene assert: `grep -c "^- \[ \]" .shapeup/<slug>/tasks/TASK-*.md` →
490
- every count must be 0 on a shipping board. An unchecked AC box on a done task means
491
- either an unverified criterion (real gap — back to BUILD/EVAL) or an ingest miss (the
492
- WorkResult's ac_results never covered it — re-run ingest-result on that result, or route
493
- back to the owning worker for a corrected result; the tech lead does not tick boxes
494
- itself). Do not SHIP past a non-zero count without logging the reason in the ledger.
495
- S.2 Print a feature summary: tasks shipped, rounds used, final verdict, dims evaluated
496
- (and explicitly: dims NOT evaluated, so "shipped" is never read as "verified for all").
497
- S.3 Point to the traceability: tasks/_index.md (all ✅) + EVAL-FEATURE-<slug>.md (PASS) +
498
- harness-run.md (the round ledger).
499
- S.4 task-executor's own verification checklist remains the formal per-task close; the tech
500
- lead confirms the feature-level close.
501
- S.5 Deploy truth — "done means deployed", honestly. Building stops at "built & verified";
502
- deployment is an outward-facing action gated to the PO. Either:
503
- - PO says yes → run the project's own deploy procedure and record "deployed".
504
- - otherwise → record "built & verified — deploy pending (PO)".
505
- NEVER auto-deploy; "shipped" must never silently mean "deployed".
506
- (Baseline-anchored scope-hammering at ship time is deliberately deferred; for now,
507
- `ba`'s Appetite Guard covers overflow and cuts go to synthesis "Hammered Out".)
508
- S.6 Harvest one signal row → append to `.shapeup/metrics/<machine-id>.jsonl`
509
- (LOCAL root, gitignored since ADR-0001 — a committed shard keyed on a hostname only
510
- grows and publishes a machine name; sharded per machine so shards can be pooled
511
- deliberately without colliding on one filename. The read plane is
512
- `harness probe stats`, or `cat .shapeup/metrics/*.jsonl`).
513
- Copy fields that ALREADY exist as structured output (run-state, final EVAL report,
514
- discovery ledger, qa/hunt-report, and the receipt's `breadboard.ids.V` for `slice_count` —
515
- the slices init run counted in the staged breadboard, never a hand copy). Two hard rules:
516
- 1. Harvest only fields that already exist at ship time — never evaluate something new.
517
- 2. Record facts, never compute a new verdict (no `run_quality_score` — that would be
518
- a second judge behind spec-evaluator). The eval suite interprets; harvest records.
519
- `final_audit_score` is COPIED from the EVAL report, never re-graded.
520
- ALSO copy two run-quality measurements, both produced by scripts at zero model tokens:
521
- node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" probe stats --ratchet --slug <slug>
522
- → `ratchet`: {trials, scopes_multi_trial, improvement_rate, monotone_rate,
523
- sawtooth_count, mean_trials_to_green}
524
- node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" probe stats --hooks
525
- → `hooks`: {evaluations, denials, errors, per_hook}
526
- Harvest them HERE or lose them: both read per-run working ledgers (t0/trials.jsonl,
527
- decisions.jsonl) that the next run's bookkeeping supersedes, so a number left there
528
- answers its question exactly once. The metrics shard is the one record that
529
- accumulates across runs — and neither measurement is meaningful from a single run.
530
- ALSO copy `run_id` from `receipt.json`. It is the row's only link to the run trace
531
- that produced it: every other field here is a count, and `feature_slug` groups runs
532
- TOGETHER rather than apart. It is what joins this row to the S.7 export.
533
- → full field list + row template: references/protocol.md "Harvest row".
534
- S.7 Export the run's records → one keyed dataset, before the trace is superseded.
535
- node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" report export --slug <slug>
536
- Same argument as S.6, applied to the records the harvest row does NOT carry: orders,
537
- results, T0 verdicts, trial rows, criterion verdicts and this run's hook decisions all
538
- live in the LOCAL tier, which is regenerable and gets wiped.
539
- The export freezes them as fact tables under `.shapeup/exports/<run_id>/` (JSONL, one
540
- object per line), keyed by run id so a second run of the same feature is a second
541
- dataset rather than an overwrite. `--out <dir>` sends it somewhere durable instead.
542
- It is READ-ONLY: it writes nothing into the trace, so it may be re-run at any time.
543
- NOT COST/WALL-CLOCK. This harness carries no run-economics record — the design once
544
- called for one derived from a per-agent-call journal, but nothing in the pipeline ever
545
- wrote that journal, so the derivation and its reporting command were removed rather than
546
- left presenting nulls as measurements. Even a real cost record would not belong in the
547
- harvest row's schema either way — that row's contract rejects clock fields on purpose
548
- (see protocol.md "Rejected fields"), because a signal feed that carried a duration would
549
- become a velocity feed on the next person who read it.
550
- ```
551
-
552
- ---
553
-
554
- ## GATE L4 — Ship Sign-Off
555
-
556
- ```
557
- ⏸ GATE L4 — Ship Sign-Off
558
- Feature : [slug] — [SHIPPED (deployed) | BUILT & VERIFIED — deploy pending (PO)]
559
- Rounds : [r] (build+eval cycles)
560
- Verdict : PASS (dims: [dims_evaluated]; not evaluated: [dims_not_evaluated])
561
- QA : [hunt done — N findings, M promoted+fixed, rest ~ | skipped (--no-qa) | n/a (pre-QA spec)]
562
- Requirements: [15/17 PASS · 1 CUT (PO) · 1 no evidence (REQ-12 ← R12) | n/a (no registry)]
563
- Ledger : harness-run.md
564
- ```
565
- The Requirements line is TRANSCRIBED, never composed — run
566
- `node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" probe requirements --slug <slug> --format table`
567
- and copy its `Requirements:` summary. It joins each registered clause to the acceptance criterion
568
- that covers it and to the criterion the judge graded, over the run named in its own output. It
569
- decides nothing here: a requirement with no PASS evidence is a fact GATE H's census and the
570
- baseline comparison weigh, not a ship blocker.
571
- Question (max 1): "Anything to record before I close the run? (y/n) or provide feedback for the next sprint."
572
- On confirm:
573
- - If the PO provides substantive feedback (not just 'y' or empty) → automatically delegate via Agent (model: exec — see references/protocol.md "Invocation mechanism"): Skill(shapeup-sdlc-plugin:coach) with the provided feedback for RLHF. The coach runs its own GATE COACH-1 to have the PO categorize each rule, then files it under the responsible skill in `shapeup/knowledge-base/<skill>.md` (committed → team-shared). Coachable: `task-executor`, `ba-pitch-analyzer`, `qa-edge-hunter`, `orient`, `scope-architect`, `solution-architect` (each reads its own file at the top of its next run) and `tech-lead` (workflow guidance, read at the next GATE L0). Guidance never decides a gate: a filed rule may add a question or a check to a gate block, never an answer. The tech lead does not categorize the feedback itself — that is the coach's gate, by design (no assumptions).
574
- - Then output → `✅ [slug] [shipped & deployed | built & verified, deploy pending] — [r] rounds, verdict PASS.`
575
-
576
- **A launched run already crossed L4 — never resolve it again after a `shipped` or `escalated`
577
- return; a second row after the close is a second sign-off.** In the prose lane, **resolve the gate
578
- itself before any of the above** — this is the decision that shipped the run,
579
- and without it the trace holds no record of that decision at all: `node
580
- "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" gate --resolve L4 --slug <slug>
581
- [--file <path>|--preset <name>]`. Exit 0 (`decision=ship|hold`) — render the block above and close
582
- the run: `node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" probe resume --slug <slug> --close shipped
583
- --cause "verdict=<verdict> rounds=<r> decision=<ship|hold>"`. **This applies to the prose lane
584
- only.** A launched run (`shapeup-run.js`) resolves L4 itself, on both the PASS path and a breaker
585
- path: it dispatches the census, crosses GATE H, writes the ship report with the verdict as it is,
586
- crosses L4, and only then closes — `shipped` when the census and L4 clear it, `escalated` naming
587
- the census when they do not. A run that returned `{status: "shipped"}` or `{status: "gate_h"}` is
588
- already closed; do not close it again, and do not run the census by hand after it.
589
- The close itself is a once-only fact IN THE KERNEL (`closeRun`'s own guard reads a `closed_status:`
590
- line that only `closeRun` ever writes — never the mutable `status:` line every phase rewrites, this
591
- call included), not a conditional this instruction has to get right: if this run_id was NOT already
592
- closed, this call performs the close, fresh. If it was already closed `shipped` (or `aborted`) and
593
- the cause text is byte-identical to what is already on the ledger, this call is a true idempotent
594
- no-op. If it was already closed with the SAME status but a genuinely different cause — a run closed
595
- more than once across relaunches, the ordinary shape a `gate_h` hand-off after an earlier abort takes
596
- — this call SUPERSEDES it: the new cause is written, the prior one is folded into the same
597
- `close_cause` line rather than lost, and the kernel call itself still exits 0 (only the RunReturn a
598
- launch's own `withWarnings` wraps carries the resulting `state_warning` — a prose-driven close like
599
- this one has no RunReturn to attach it to, so read `close_cause` by hand if this branch matters to
600
- you). If it was already closed with a DIFFERENT status altogether, this call is refused outright —
601
- cause intact, never silently flipped. Exit 4 (`ask`) — the block above IS that stop; put it to the
602
- PO and wait, same as always. L4's answer set carries no `abort`.
603
-
604
- ---
605
-