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,7 +1,7 @@
1
1
  {
2
2
  "$id": "work-order.schema.json",
3
3
  "title": "WorkOrder",
4
- "description": "The orchestrator \u2192 worker envelope (pure-skill architecture v1.0). Compiled by kernel/compile.mjs, validated by harness verify envelope before any worker dispatch. A worker depends only on this envelope \u2014 never on filesystem topology, run-state format, board schema, or another worker. Path: .shapeup/<slug>/orders/r<N>-a<M>.json (or <slug>/orders/<operation>.json for non-attempt work). Every record type and payload field is DEFINED CENTRALLY in domain.schema.json ($defs + x-payload-by-worker) \u2014 this file only shapes the envelope; it never re-defines a domain entity.",
4
+ "description": "The orchestrator \u2192 worker envelope (pure-skill architecture v1.0). Written by the loop, validated by harness verify envelope before any worker dispatch. A worker depends only on this envelope \u2014 never on filesystem topology, run-state format, board schema, or another worker. Path: .shapeup/<slug>/orders/r<N>-a<M>.json (or <slug>/orders/<operation>.json for non-attempt work). Every record type and payload field is DEFINED CENTRALLY in domain.schema.json ($defs + x-payload-by-worker) \u2014 this file only shapes the envelope; it never re-defines a domain entity.",
5
5
  "type": "object",
6
6
  "required": [
7
7
  "schema_version",
@@ -24,11 +24,11 @@
24
24
  },
25
25
  "kernel": {
26
26
  "type": "string",
27
- "description": "OPTIONAL \u2014 the absolute path of the kernel entry point (harness.mjs) of the plugin copy that compiled this order. A worker runs every kernel command as node \"<kernel>\" \u2026: a command naming a variable instead (${CLAUDE_PLUGIN_ROOT}) is refused in a headless session before any permission rule is consulted."
27
+ "description": "OPTIONAL \u2014 the absolute path of the kernel entry point (harness.mjs) of the plugin copy that wrote this order. A worker runs every kernel command as node \"<kernel>\" \u2026: a command naming a variable instead (${CLAUDE_PLUGIN_ROOT}) is refused in a headless session before any permission rule is consulted."
28
28
  },
29
29
  "run_id": {
30
30
  "type": "string",
31
- "description": "OPTIONAL (v1.8) \u2014 the run this dispatch belongs to, stamped by harness compile from the receipt (kernel/lib/paths.mjs). The join key the analysis plane groups on: order_id alone collides across runs of the same slug, so without this no record the pipeline writes can be attributed to a run. Absent when no readable receipt exists (a standalone dispatch in a workspace with no open run) \u2014 never invented, and never required, because an analytic field must not be able to block a build.",
31
+ "description": "OPTIONAL (v1.8) \u2014 the run this dispatch belongs to, stamped by the loop from the receipt (kernel/lib/paths.mjs). The join key the analysis plane groups on: order_id alone collides across runs of the same slug, so without this no record the pipeline writes can be attributed to a run. Absent when no readable receipt exists (a standalone dispatch in a workspace with no open run) \u2014 never invented, and never required, because an analytic field must not be able to block a build.",
32
32
  "pattern": "^[a-z0-9][a-z0-9-]*-[0-9]{8}T[0-9]{6}Z-[0-9a-f]{8}$"
33
33
  },
34
34
  "compiled_at": {
@@ -36,7 +36,11 @@
36
36
  "description": "OPTIONAL (v1.8) \u2014 ISO timestamp of compilation. The dispatch record's own time dimension: WorkResult carries none, and the journal's timings exist only on the workflow lane, so without this a dispatch on the prose lane is timeless."
37
37
  },
38
38
  "worker": {
39
- "$ref": "domain.schema.json#/$defs/WorkerName"
39
+ "description": "The skill the order is addressed to — a member of the worker roster — or `building`, the loop itself, for a `plan` order: a fence-only order no sub-agent answers. `building` is deliberately not in the roster: the roster is what a dispatch can be addressed to, and nothing is ever dispatched to the loop.",
40
+ "anyOf": [
41
+ { "$ref": "domain.schema.json#/$defs/WorkerName" },
42
+ { "type": "string", "enum": ["building"] }
43
+ ]
40
44
  },
41
45
  "mode": {
42
46
  "type": "string",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$id": "work-result.schema.json",
3
3
  "title": "WorkResult",
4
- "description": "The worker → orchestrator envelope (pure-skill architecture v1.0). Everything a worker used to write into shared files it now RETURNS as data; kernel/reduce/ingest.mjs performs the writes (tick AC boxes, flip board status, append execution log, propagate unblocks, append discoveries) deterministically, in one place. Path: .shapeup/<slug>/results/r<N>-a<M>.json. Every record type is DEFINED CENTRALLY in domain.schema.json — this file only shapes the envelope.",
4
+ "description": "The worker → orchestrator envelope (pure-skill architecture v1.0). Everything a worker used to write into shared files it now RETURNS as data; the loop performs the writes (tick AC boxes, flip board status, append execution log, propagate unblocks, append discoveries) deterministically, in one place. Path: .shapeup/<slug>/results/r<N>-a<M>.json. Every record type is DEFINED CENTRALLY in domain.schema.json — this file only shapes the envelope.",
5
5
  "type": "object",
6
6
  "required": [
7
7
  "schema_version",
@@ -4,7 +4,7 @@
4
4
  // The lesson already in the repo: structured artifacts + deterministic tooling beat prose
5
5
  // conventions (harness verify t0 is the most reliable component in the harness). This script makes
6
6
  // the WorkOrder/WorkResult ports mechanically checkable: a malformed order never reaches a
7
- // worker, a malformed result never reaches ingest.
7
+ // worker, a malformed result is sent back before the loop applies it.
8
8
  //
9
9
  // Zero dependencies, zero network — same discipline as the oracles and the GATE L2 block. Implements
10
10
  // the JSON-Schema subset the shipped schemas use (type, required, properties, items, enum,
@@ -271,7 +271,7 @@ export async function cli(rawArgv) {
271
271
  },
272
272
  });
273
273
  if (!existsSync(orderPath)) {
274
- deny(`WorkOrder gate — order file not found: ${orderPath}. Compile it first (harness compile) — a worker must never be dispatched against a dangling order.`, "order-missing");
274
+ deny(`WorkOrder gate — order file not found: ${orderPath}. Write the order first (resources/orders.md in the building skill) — a worker must never be dispatched against a dangling order.`, "order-missing");
275
275
  }
276
276
  try {
277
277
  const { valid, errors } = validateFile(orderPath, join(SCHEMAS_DIR, "work-order.schema.json"));
@@ -4,7 +4,7 @@
4
4
  // WHAT IT CATCHES. A dispatch against a plugin that is absent, disabled or a different version
5
5
  // returns `<tool_use_error>Unknown skill</tool_use_error>`, and the sub-agent then does the craft
6
6
  // itself from the prose already in its own prompt. `hooks/dispatch-receipt.mjs` makes that visible
7
- // at ingest; this makes it visible at `init run`, before a single sub-agent has been paid for.
7
+ // in the receipts; this makes it visible at `init run`, before a single sub-agent has been paid for.
8
8
  //
9
9
  // WHAT IT HONESTLY CANNOT DO, stated here because a check that overclaims is worse than no check.
10
10
  // It proves *these files exist at this root at this version*. It cannot prove the SESSION will
@@ -15,9 +15,9 @@
15
15
  //
16
16
  // THE ROSTER IS DERIVED, NEVER SPELLED. It comes from `domain.schema.json#/$defs/WorkerName` — the
17
17
  // same enum that decides which workers a WorkOrder may be addressed to. A hand-written list beside
18
- // a schema enum is the drift this project exists to prevent: eight names beside a ten-member enum
19
- // reads perfectly and is wrong, and the two it would omit (`translator`, `coach`) are exactly the
20
- // ones a short run never reaches, so the omission would surface months later on the one run that did.
18
+ // a schema enum is the drift this project exists to prevent: a list that drops one member of the enum
19
+ // reads perfectly and is wrong, and the member it omits is exactly the one a short run never reaches,
20
+ // so the omission would surface months later on the one run that did.
21
21
  //
22
22
  // THE ROOT IS DERIVED FROM THIS MODULE'S OWN LOCATION, not from `CLAUDE_PLUGIN_ROOT`: the env var is
23
23
  // not reliably exported into a sub-agent's shell, and the kernel that is executing is already inside
@@ -54,11 +54,26 @@ export function roster(root = PLUGIN_ROOT) {
54
54
  return names;
55
55
  }
56
56
 
57
+ /**
58
+ * The skills an agent definition preloads, read from its `skills:` frontmatter list.
59
+ *
60
+ * @param {string} path - The `agents/<worker>.md` file.
61
+ * @returns {string[]} The listed skill names; [] when the file or the list is absent.
62
+ */
63
+ export function preloadedSkills(path) {
64
+ let text;
65
+ try { text = readFileSync(path, "utf8"); } catch { return []; }
66
+ const fm = /^---\r?\n([\s\S]*?)\r?\n---/.exec(text)?.[1] ?? "";
67
+ const block = /^skills:[ \t]*\r?\n((?:[ \t]+-[ \t]*\S+[ \t]*\r?\n?)+)/m.exec(fm + "\n")?.[1] ?? "";
68
+ return [...block.matchAll(/-[ \t]*(\S+)/g)].map((m) => m[1]);
69
+ }
70
+
57
71
  /**
58
72
  * Resolve every worker in the roster against a plugin root.
59
73
  *
60
- * A worker is present when its `SKILL.md` is readable. That is the file the host loads to answer a
61
- * `Skill(...)` call, so its absence is the closest on-disk fact to "this dispatch will fail".
74
+ * A worker is present when its `SKILL.md` is readable AND its agent definition (`agents/<worker>.md`)
75
+ * is readable and preloads that skill. The agent is what a dispatch names, the skill is its craft, and
76
+ * either one missing is the closest on-disk fact to "this dispatch will fail".
62
77
  *
63
78
  * @param {string} [root=PLUGIN_ROOT] - Plugin root to check.
64
79
  * @returns {{root:string, version:(string|null), name:(string|null), workers:Array<{worker:string,
@@ -74,7 +89,9 @@ export function resolveWorkers(root = PLUGIN_ROOT) {
74
89
  } catch { /* an unreadable manifest is reported as null, never as a failure of its own */ }
75
90
  const workers = roster(root).map((worker) => {
76
91
  const path = join(root, "skills", worker, "SKILL.md");
77
- return { worker, path, present: existsSync(path) };
92
+ const agent = join(root, "agents", `${worker}.md`);
93
+ const preloads = preloadedSkills(agent).includes(worker);
94
+ return { worker, path, agent, present: existsSync(path) && preloads, skill: existsSync(path), agent_preloads_skill: preloads };
78
95
  });
79
96
  return { root, version, name, workers, missing: workers.filter((w) => !w.present).map((w) => w.worker) };
80
97
  }
@@ -116,7 +133,9 @@ export function cli(rawArgv) {
116
133
  }
117
134
  if (report.missing.length) {
118
135
  console.error(` ✗ verify skills: ${report.missing.length} worker skill(s) missing under ${report.root}:`);
119
- for (const w of report.workers.filter((x) => !x.present)) console.error(` ${w.worker} — no SKILL.md at ${w.path}`);
136
+ for (const w of report.workers.filter((x) => !x.present)) {
137
+ console.error(` ${w.worker} — ${w.skill ? `${w.agent} does not preload the \`${w.worker}\` skill` : `no SKILL.md at ${w.path}`}`);
138
+ }
120
139
  console.error(` This plugin copy cannot run the pipeline. Load the working copy with`);
121
140
  console.error(` \`claude --plugin-dir <repo>\`, or install/enable the plugin, then retry.`);
122
141
  process.exit(1);
@@ -574,7 +574,7 @@ export const ARGV_SPEC = {
574
574
  export async function cli(rawArgv) {
575
575
  const args = runArgs(ARGV_SPEC, rawArgv);
576
576
  const contractPath = args._[0];
577
- // Markdown first, legacy JSON second (ADR-0001, lib/contract.mjs).
577
+ // Markdown first, legacy JSON second (lib/contract.mjs).
578
578
  const found = readContract(contractPath, SCOPE_CONTRACT);
579
579
  if (!found) { console.error(`t0-verify: no scope contract at ${contractPath} (.md or .json)`); process.exit(2); }
580
580
  const contract = found.contract;
@@ -583,7 +583,7 @@ export async function cli(rawArgv) {
583
583
  // contract's own location.
584
584
  //
585
585
  // This used to be `dirname(dirname(contractPath))` — "the parent of scopes/" — which was correct
586
- // while scope contracts and the run trace shared a root. ADR-0001 split the tiers and moved scope
586
+ // while scope contracts and the run trace shared a root. The tier split moved scope
587
587
  // contracts to COMMITTED `shapeup/<slug>/scopes/`, so the default silently followed them: every
588
588
  // T0 verdict and trial row was written to `shapeup/<slug>/t0/` while `probe t0` — the ONLY reader,
589
589
  // and the one the build round's confirm stage asks — resolves `verdictsDir()` to
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shapeup-sdlc",
3
- "version": "3.18.2",
3
+ "version": "4.0.0",
4
4
  "description": "Shape Up for coding agents \u2014 with gates the agent can't talk its way past. Harness for Claude Code.",
5
5
  "bin": {
6
6
  "shapeup-sdlc": "bin/init.mjs"
@@ -11,6 +11,7 @@
11
11
  ".env.shapeup.example",
12
12
  "AGENTS.md",
13
13
  "SECURITY.md",
14
+ "agents/",
14
15
  "bin/",
15
16
  "commands/",
16
17
  "hooks/",
@@ -35,7 +36,8 @@
35
36
  "scripts": {
36
37
  "test": "node tests/structural.mjs",
37
38
  "demo": "node tools/demo/record-demo.mjs",
38
- "test:grant": "node tests/grant/executing-grant.mjs"
39
+ "test:grant": "node tests/grant/executing-grant.mjs",
40
+ "verify:cross-dir": "node tools/verify-cross-dir.mjs"
39
41
  },
40
42
  "keywords": [
41
43
  "shapeup",
@@ -0,0 +1,144 @@
1
+ ---
2
+ name: building
3
+ description: "Use this skill whenever the user wants to ship a kicked-off Shape Up pitch end to end — orient, plan, build, evaluate, hunt, cut, ship — as the tech lead who drives the run in this session and sits at every gate with the PO. Trigger on: \"ship this feature\", \"run the harness\", \"build from this pitch\", \"from pitch to ship\", \"run the full harness\", \"orchestrate the build\", \"resume the run\". Also covers its sub-commands: translate a non-English pitch to English (intake), decide when to stop with the census and cut list (the Cut-List Review gate, \"hammer this down to must-haves\"), and file ship feedback or seed the knowledge base from the project or the platform docs (the retro, \"coach this feedback\", \"scan the project for guidelines\"). DEFAULT: /ship <pitch>. Use it even when the user describes a multi-step build flow without naming the skills."
4
+ ---
5
+
6
+ # Building — the loop that drives a run
7
+
8
+ ## ▶ RUN THIS FIRST — do not summarise this file
9
+
10
+ **Your first output is a tool call, not a plan.** Narrating the pipeline reads like a clean run and
11
+ leaves defects behind it. A run that left no receipt did not happen; loading these instructions is not
12
+ running them.
13
+
14
+ You drive the run, in this session. What stands between you and a claim of "done" is five mechanisms and
15
+ nothing else: the **receipt** `init run` writes, the **gate resolver**, the **T0 witness** that runs a
16
+ scope's fixtures and re-hashes what it cites, the **write fence** that refuses a worker's write outside
17
+ its order's substrate, and the **dispatch receipts** that name which agent ran. Everything else in this
18
+ file is your own discipline, and no script checks it for you — so after every action, read the files
19
+ again instead of remembering them.
20
+
21
+ Every kernel command below is run exactly as written, on ONE line (a grant matches a single-line
22
+ command; a `\`-continued one comes back "requires approval"). If a kernel command comes back "requires
23
+ approval", stop and say so — the scripts need a one-time grant (`npx shapeup-sdlc init`); never route
24
+ around it or hand-build the feature.
25
+
26
+ ## Rules
27
+
28
+ 1. **ASK, DON'T ASSUME.** Collect the intake explicitly (`resources/intake.md`); put every gate to the PO with a recommendation first.
29
+ 2. **SIMPLEST FIRST.** The smallest change that satisfies the pitch.
30
+ 3. **NON-REGRESSION.** Never touch what already works.
31
+ 4. **A CLAIM NAMES ITS FILE.** Every "done", "green" or "shipped" you write cites the file or kernel output it came from.
32
+
33
+ ## Step 0 — open the run
34
+
35
+ Resolve the intake and open it as `resources/intake.md` says: language check (a non-English pitch is made
36
+ English by you, right there: `<name>.en.md` and the glossary, and the run opens on the copy), the L0 collect-list,
37
+ `init run` — with every switch the operator typed, because it writes the launch record in the same act
38
+ as the receipt and refuses a model below the floor (exit 3 = a run is already open, or the worker roster is
39
+ missing: the record is kept and the loop continues from the files), the shared `project-profile.md`, and the
40
+ L0 gate.
41
+
42
+ ## Where the facts are
43
+
44
+ `K` is `node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs"`. `<run>` is `.shapeup/<slug>/`, `<spec>` is `shapeup/<slug>/`.
45
+
46
+ | Fact | File |
47
+ |---|---|
48
+ | the launch record: models, `budgets.maxRounds`, `budgets.attemptBudget`, the answer set (`answers`), `noEval`, `noQa`, `maxParallelScopes` | `<run>/run-args.json` |
49
+ | the intake, and which plugin copy opened the run | `<run>/intake.md`, `<run>/receipt.json` |
50
+ | a gate is crossed when a row with that `gate` and `"status":"ok"` exists (matching `round` where it has one) | `<run>/gates.jsonl` |
51
+ | orders and results — a dispatch is answered when `results/<stem>.json` exists | `<run>/orders/<stem>.json`, `<run>/results/<stem>.json` |
52
+ | the scorer's verdict per attempt; the latest row per scope is its state | `<run>/t0/trials.jsonl`, `<run>/t0/verdicts/r<R>-a<A>-t<T>.json` |
53
+ | committed plan: requirements, spec tree, wiring map, scope contracts | `<spec>requirements.md`, `<spec>spec/`, `<spec>wiring-map.md`, `<spec>scopes/<id>.md` |
54
+ | the board: one `TASK-NNN.md` per task, `status:` in its frontmatter | `<run>/tasks/` |
55
+ | the census GATE L4 reads | `<run>/reports/hammer-census.json` |
56
+
57
+ ## The phases — do the first one whose condition holds, then read the files again
58
+
59
+ A gate is crossed with `K gate --resolve <GATE> --slug <slug> [--round R] [--verdict V] --preset <set>` (exit 0 = crossed; 4 = ask the PO and
60
+ re-run with `--answer <decision>`; 5 = the set aborts: close the run as aborted and stop). `<set>` is the launch record's `answers`.
61
+
62
+ | # | Condition | Do |
63
+ |---|---|---|
64
+ | 0 | `<run>/close.json` exists | the run has ended: report its `status` and `cause`, and stop. Reopening it is the PO's decision (`init run --force`) |
65
+ | 1 | no `results/orient.json` | **dispatch** `orient` (below) |
66
+ | 2 | GATE L1a not crossed | `K gate --resolve L1a --slug <slug> --preset <set>` |
67
+ | 3 | no `<spec>requirements.md` | plan substep `requirements` |
68
+ | 4 | no spec tree or no board | plan substep `spec`; then read the board back against `resources/plan-spec.md`'s checklist |
69
+ | 5 | no `<spec>wiring-map.md` | plan substep `wire`; then GATE L1a.5 |
70
+ | 6 | no `<spec>scopes/*.md` | plan substep `scopes`; then GATE L1b |
71
+ | 7 | a scope has no green latest trial for round R (R starts at 1) | **build** it (below) |
72
+ | 8 | every scope green or out of attempts, GATE L2 not crossed for R | `K gate --resolve L2 --slug <slug> --round R --preset <set>` |
73
+ | 9 | no `results/evaluate-rR.json` (skipped under `noEval`) | **dispatch** `spec-evaluator` |
74
+ | 10 | GATE L3 not crossed for R | `K gate --resolve L3 --slug <slug> --round R --verdict <pass\|fail\|not-evaluated>`. On fail and `R < maxRounds`, round R+1 repeats 7 to 10 for the scopes the verdict's bugs name; otherwise go to 13 |
75
+ | 11 | GATE QA not crossed | `K gate --resolve QA --slug <slug> --round R --verdict pass --preset <set>` |
76
+ | 12 | QA answered `run` and no `results/hunt.json` (skipped under `noQa`) | **dispatch** `qa-edge-hunter`. Do not move on without it: GATE L4 refuses `ship` over a hunt the run owed and never ran, and the only recorded way out is `K gate --resolve QA … --answer skip` |
77
+ | 13 | no census file | do the census (`resources/stop.md`) and write `<run>/reports/hammer-census.json`; then GATE H |
78
+ | 14 | GATE H crossed, no `<spec>REPORT.md` | write the ship report (`resources/stop.md`); then GATE L4 |
79
+ | 15 | GATE L4 crossed | `K order close --slug <slug> --status <shipped\|escalated\|aborted> --cause "<verdict, rounds>"`; `shipped` is refused (exit 1) unless this run's L4 row says `ship`, so a refusal here means the gate was not crossed — go back to phase 14; then GATE COACH-1 |
80
+
81
+ **A plan substep** is done here, in this session, with no sub-agent: write the substep's order (`resources/orders.md`, operation `plan`,
82
+ `worker: "building"`), open it with `K order open`, write only what the substep produces (`resources/plan.md` and its `plan-*.md`
83
+ siblings say what and how), then write `results/plan-<step>.json` yourself (the order's `own` path, so it is writable though results are frozen) and read the artifact back, before you write the next order. The order's substrate is the
84
+ fence: while it is open, the staged pitch, the receipt and the other orders are frozen.
85
+
86
+ ## A dispatch
87
+
88
+ The same five moves for every worker. `resources/orders.md` has the order for each operation.
89
+
90
+ 1. **Write the order** to `<run>/orders/<stem>.json` from the template for the operation. It carries the substrate (the globs the worker may write,
91
+ copied from the scope contract for a build) and the payload the worker needs, as paths where a path will do.
92
+ 2. **Open it**: `K order open --slug <slug> --order "<run>/orders/<stem>.json"`. This stamps the order's time and names the live order to the fence; without it the fence allows every write.
93
+ 3. **Spawn** the agent `shapeup-sdlc-plugin:<worker>` with the prompt `--order "<run>/orders/<stem>.json"` and one line of note, and pass the
94
+ **model** the launch record names for the role: `models.exec` for `orient` and `task-executor`, `models.eval` for `spec-evaluator`, `models.qa`
95
+ for `qa-edge-hunter`. The agent definitions say `inherit`, so a dispatch that carries no model runs on *your* session's model, whatever the
96
+ record asked for. The dispatch is checked against the order schema before it leaves, and leaves a receipt naming the agent that ran, the model
97
+ the call asked for and the model the host says ran. GATE L4 reads those receipts: an `exec` or `eval` worker that ran below the floor refuses
98
+ `ship`, and a model other than the record's is written into the gate's row — say so in the ship report.
99
+ 4. **Read the result** at `<run>/results/<stem>.json`: `K verify envelope "<run>/results/<stem>.json" "${CLAUDE_PLUGIN_ROOT}/kernel/schemas/work-result.schema.json"`.
100
+ Invalid, or absent, goes back **once** with the reason; a second failure is a phase that did not complete — name it and stop at that phase.
101
+ 5. **Apply it yourself**: update the board's `status:` for the tasks the result closed, append each discovery to `<run>/discovery/ledger.md`, append the
102
+ evaluator's verdict-ledger lines to `<run>/evaluation/.verdicts-<target>.jsonl`, and state what the result changed. Nobody else writes these.
103
+
104
+ ## Build a scope
105
+
106
+ For scope `S` in round `R`, attempt `A` (start at 1): dispatch `task-executor` with operation `execute` (round 1, or `fix` with the verdict's bugs on later rounds),
107
+ whose substrate is the scope contract's `allowed_file_substrate` and `shared_substrate`. The worker runs `K verify t0 "<spec>scopes/S.md" --round R --attempt A`
108
+ itself. After its result lands, **run the same command yourself** and read `status` from the JSON on stdout, never from the exit code (a `kept` red-but-improved attempt exits 1):
109
+
110
+ | `status` | You |
111
+ |---|---|
112
+ | `kept`, overall green | the scope is green for round R |
113
+ | `kept`, red | attempt A+1 builds on this tree; fold the digested errors into the next order |
114
+ | `reverted` or `crash` | attempt A+1; the tree was restored |
115
+
116
+ A scope that reaches `attemptBudget` attempts without a green is **out of attempts**: stop building it, record it as a proposal for GATE H, and go on. It never stops the round.
117
+ Build a scope only after the scopes in its contract's `depends_on` are green. Two scopes build at once only when no path is writable by both (read the contracts' substrates); otherwise one at a time.
118
+ Count an attempt from the dispatch receipts in `<run>/receipts/dispatch.jsonl`, not from your memory: a dispatch with no receipt did not run the shipped worker.
119
+
120
+ ## The breakers
121
+
122
+ `maxRounds` ends the run: after a failed round R = `maxRounds`, go to the census. `attemptBudget` ends one scope. Neither ends the run from outside — both route to GATE H, where the
123
+ census compares what is green against the baseline and ships what works. A run killed from outside ships nothing.
124
+
125
+ ## Sub-commands
126
+
127
+ `/ship` with none runs the whole loop. A sub-command does one activity of it:
128
+ `plan` (`/scopes`, `/wire`) — the planning substeps; `stop` (`/hammer`) — the census over the run in hand;
129
+ `retro` (`/retro`, `/retro --scan`, `/retro --research <stack>`) — `resources/retro.md`, `retro-scan.md`, `retro-research.md`;
130
+ `intake <path>…` (`--check` writes nothing) — the language gate alone, `resources/intake.md` §2.
131
+
132
+ ## Resume
133
+
134
+ `/ship` again over an open run is the resume (over a closed one, phase 0 reports the ending and stops): `init run` refuses and prints what is on disk, and you continue from the phase table, reading files and nothing else.
135
+ A run closed without shipping is reopened by `init run --force`, which resolves every order nobody answered as abandoned before it writes.
136
+
137
+ > **Intake, language check and translation, profile, the launch record** → `resources/intake.md`
138
+ > **The order for each operation: substrate, payload, where each field comes from** → `resources/orders.md`
139
+ > **Planning: how a substep runs, requirements; the spec, wiring and scope formats** → `resources/plan.md` and its `plan-*.md` siblings
140
+ > **Which knowledge-base file is read where, and under what name a rule is filed** → `resources/guidance.md`
141
+ > **How to put a gate to the PO, and what to have read first** → `resources/gates.md`
142
+ > **What a round is; the attempt loop; why the loop stops where it does** → `resources/rounds.md`
143
+ > **The census, the baseline comparison, the cut list, the ship report (GATE H)** → `resources/stop.md`
144
+ > **After a ship: feedback, the retro gate, `--scan`, `--research`** → `resources/retro.md`, `retro-scan.md`, `retro-research.md`
@@ -0,0 +1,76 @@
1
+ # Putting a gate to the PO
2
+
3
+ A gate resolves through the kernel, never through a paragraph of yours. When `gate --resolve` exits 4
4
+ it is your job to ask well: print the `block` verbatim, then **one question, the valid decisions, your
5
+ recommendation first**. The recommendation is yours; the answer is the PO's.
6
+
7
+ | Gate | What the PO is deciding | Recommend |
8
+ |---|---|---|
9
+ | `L1a` Orient Review | the Scout's code-surface map and the spike result, before any board exists | `proceed` unless the spike found the shape does not fit the code; `abort` when it did |
10
+ | `L1a.5` Wiring Review | every use case traced to its seam and entry point | `proceed` when each has one; name any that does not |
11
+ | `L1b` Board Review | the scope board and its disjointness — where scope is actually decided | read the REQ → AC table in the block's neighbourhood first: a requirement no acceptance criterion grades and no scope claims is **red**. The ways out are an AC carrying `(covers: REQ-…)` or the PO marking the clause `CUT (PO-approved)`. `proceed` only when none is red. |
12
+ | `L2` Build Round Complete | whether the round's work goes to evaluation | `proceed`; over unfinished tasks it is a warning, not a block. A board with no tasks at all forces a stop however it is answered |
13
+ | `L3` Verdict & Loop | the judge's verdict for the round | on FAIL `loop` while rounds remain, `stop` to cut; on PASS the answer only matters for the next phase |
14
+ | `QA` QA Edge Hunt | whether to hunt past what the judge probed | `run` unless the PO is out of time; a hunt discovers and never blocks |
15
+ | `H` Decide When to Stop | the census: what ships and what is cut, against the baseline and never the ideal | `accept-cut-list` for `ship-now` or `ship-after-fixes`; `cannot-ship` never reaches this question |
16
+ | `L4` Ship Sign-Off | final go/no-go; `ship` is only offered when a census cleared the run, any QA hunt the run owed ran (or GATE QA was answered `skip`), and no `exec` or `eval` worker ran below the model floor by its receipt; a model other than the launch record's is written into the row, not refused | `ship` only after reading the status line the block carries |
17
+
18
+ An unattended run puts none of these to anyone: its answer set resolves them and the ledger names the
19
+ set as the source. A gate with no answer and no human is a fast, attributable abort, not a silent wait.
20
+
21
+ ## What to have read, and printed, before you ask
22
+
23
+ The `block` is the kernel's facts; the PO decides on more than those, so read what the gate is about first and
24
+ print the headline from the artifact — never composed from memory. Guidance may add a question to any of these;
25
+ it never answers one.
26
+
27
+ **L1a — Orient Review.** Read `.shapeup/<slug>/orient/`. Render the area-level Hill from `hill-signal.md` (each
28
+ suspected area uphill — open unknowns · crest — approach proven by the spike · downhill). Print the breadboard
29
+ source (flag, sibling, shaping dir, shared root, embedded, or none), the code-surface headline, the spiked area
30
+ and its result, and the riskiest open unknowns going into mapping. Ask at most two: is the riskiest area the one
31
+ that was spiked, and is there an unknown that needs another spike before scopes are mapped?
32
+
33
+ **L1a.5 — Wiring Review.** Every use case has one declared engine → seam → entry-point call site → affordance in
34
+ `wiring-map.md`. Name any that does not.
35
+
36
+ **L1b — Board Review.** The PO reviews the committed plan — `usecases/_index.md`, `scopes/*.md`,
37
+ `scope-summary.md`'s Done-when headlines — never the per-machine task board; task-level detail stays hidden here
38
+ by design. Print: use-case count and actors; the scope board (scope id, topology, substrate file count); any spike
39
+ blockers; the Done-when headlines; the **Deferred Places** from `ux-behavior.md` — breadboard Places the shape will
40
+ not build, each needing the PO's yes, a rejected deferral going back to planning as a screen; and the
41
+ `REQ → AC` table, one row per registered requirement (`REQ-12 ← shaping.md R12`, the criterion that grades it,
42
+ or the scope that claims it, or `CUT (PO-approved)`), omitted when the run has no registry. The table is printed,
43
+ never asked: it decides nothing at this gate.
44
+ Read the plan back here yourself, whatever the planning step already checked, because a human may have approved past a
45
+ problem and no script lints it for you. A problem is a hard stop: a file in two scopes' substrate without both declaring it
46
+ shared, a scope aligned with a directory (PA1), a scope whose use case does not resolve, a `depends_on` naming a scope that is
47
+ not there, a requirement no criterion grades and no scope claims, a Place with UI affordances folded into another screen. A scope over
48
+ ~15 files is a warning. The breadboard problems are planning's to fix — add the screen or defer the Place, never fold it into another
49
+ screen. Scopes are released in dependency order: a scope opens the moment the scopes it declares in `depends_on` have settled, up to
50
+ `maxParallelScopes`, and contracts declaring none are one wave, every scope eligible at once. Ask at most two: scope cuts? any spike to resolve before build? Frame cuts against
51
+ the pitch's appetite, and surface the pitch's rabbit holes — a cut here is cheap, after round 1 it is expensive.
52
+
53
+ **L2 — Round Close.** The block carries `green_scopes`, `hammer_proposals` and the build gate (`green`, `red —
54
+ <failing step>`, or `undeclared`). `red` means the judge is not dispatched this round and the failing step
55
+ becomes round r + 1's bugs; `undeclared` means the round goes to evaluation over an unproven build, and the
56
+ block says so. Over unfinished tasks it is a warning, not a block.
57
+
58
+ **L3 — Verdict.** Report progress by hill position per scope (from the committed hill shards), never by "N of M
59
+ tasks done" — a 90%-done slice can be stuck uphill on the one unknown that matters. On FAIL, print the bug list
60
+ grouped by scope: the failed Done-when criterion and its repro, and **nothing about causes or fixes** — the
61
+ orchestrator names the scope; the implementer diagnoses. A round whose build gate was red never reached the
62
+ judge: the "bug list" is the gate's failing step. Ask at most one: fix these in round r + 1, cut scope, or waive a
63
+ bug? Past the round budget the answer is the census, with the residual bug list.
64
+
65
+ **QA.** A hunt discovers; the run's verdict stays the judge's PASS. Triage happens at H and L4.
66
+
67
+ **H — Cut List.** See `resources/stop.md`: the census against the baseline, never the ideal.
68
+
69
+ **L4 — Ship Sign-Off.** Print the feature as `SHIPPED (deployed)` or `BUILT & VERIFIED — deploy pending (PO)`;
70
+ rounds; the verdict with the dimensions evaluated **and** not evaluated, so "shipped" never reads as "verified
71
+ for all"; QA findings (all held as `~`) or skipped; and the `Requirements:` line **transcribed** from
72
+ the report's Requirements table, which you read off the verdict and `requirements.md`, never composed from memory (it decides nothing: a clause with no PASS
73
+ evidence is a fact the census weighs, not a veto). Deploy is outward-facing and the PO's: the loop stops at built and verified, records
74
+ `deploy pending (PO)` unless the PO says to run the project's own deploy, and never deploys itself. Ask at most
75
+ one: anything to record before closing? Substantive feedback goes to the retro (`resources/retro.md`), which
76
+ asks the PO which rule belongs where; the loop never categorises feedback itself.
@@ -0,0 +1,23 @@
1
+ # The knowledge base — which file is read where
2
+
3
+ `shapeup/knowledge-base/<name>.md` holds the rules the team has filed. Guidance steers craft: **a rule may
4
+ add a question or a check to a gate block, never an answer, a skip, a reorder or a wider substrate.** A rule
5
+ that disagrees with the spec, a contract, a gate or a kernel check loses, and the conflict is told to the PO.
6
+
7
+ Files are named after the skill a rule was first filed under, and a consumer's existing files keep working.
8
+ New rules are written under the **activity** name. The loop reads, in order:
9
+
10
+ | Read at | Files | Why those names |
11
+ |---|---|---|
12
+ | L0, before the intake questions | `building.md`, then `tech-lead.md` | `tech-lead.md` is what the loop's guidance was filed as before it had its own name; it is read as `building` guidance |
13
+ | every `plan` step (its `guidance` field lists the ones that exist; the order's `payload.kb_rules_paths` names all four) | `plan.md`, `ba-pitch-analyzer.md`, `scope-architect.md`, `solution-architect.md` | the planning activity was three skills; each file's rules still apply to the substep that skill's craft became (analysis, scope contracts, wiring) |
14
+ | a dispatched worker's order | `task-executor.md`, `orient.md`, `qa-edge-hunter.md` — the worker reads its own, from `payload.kb_rules_path` | unchanged |
15
+
16
+ Never read: a file for `spec-evaluator` (the judge is not coachable — a coached judge is a second grader) or
17
+ for the stop step's census (its ownership, exhaustion and requirement claims come from files, not
18
+ from guidance). A file left behind under the name of a retired skill — `scope-hammer.md`, `coach.md`,
19
+ `translator.md` — is read by nobody; its rules are filed again under a category at the next retro.
20
+
21
+ A rule filed against `ba-pitch-analyzer`, `scope-architect` or `solution-architect` is read by the plan
22
+ step and is rewritten under `plan` the next time the retro touches it; the old file is never deleted by the
23
+ loop.
@@ -1,6 +1,6 @@
1
1
  # Preservation Rules
2
2
 
3
- What the translator touches, what it must never touch, and how it proves the result.
3
+ What the intake translation touches, what it must never touch, and how it proves the result.
4
4
  Read this before translating any file. The governing principle: **translate meaning,
5
5
  preserve everything that machines parse.** A `.en.md` that reads well but breaks the spec
6
6
  tree's wikilinks or drops a table row is a failed translation.
@@ -0,0 +1,157 @@
1
+ # Intake — opening a run
2
+
3
+ Everything the run needs is pinned once, here, so the loop never has to guess. The intake is a
4
+ **kicked-off pitch**: shaping, betting and kick-off are the PO's own and happen upstream. A raw idea is
5
+ not an intake.
6
+
7
+ ## 1. Resolve the pitch
8
+
9
+ In order: `--pitch <path>` (a shaping or pitch file), `--spec <folder>`, requirement text passed to the
10
+ skill. **None resolvable → stop.** Print "✋ NO INTAKE — name a kicked-off pitch (`--pitch <path>`)" and
11
+ nothing else: do not emit the L0 block, list downstream gates, or describe the pipeline that "will" run.
12
+ A run with no spec has nothing to drive, and narrating one reads exactly like a run that worked.
13
+
14
+ A pitch is `shaping.md` plus its `breadboard.md`. You find the breadboard beside the pitch, in
15
+ `shapeup/<slug>/shaping/`, one the PO names, or inline in a single `pitch.md`, and you copy it to
16
+ `.shapeup/<slug>/breadboard.md` once the run is open: that is the path every planning order freezes and every worker reads.
17
+
18
+ ## 2. Language check — the harness is English end to end
19
+
20
+ The planner, the doers and the judge all assume English and fail hard on anything else, so this is the one
21
+ place a non-English intake is made English: **faithfully, once, by you, in this context** — no sub-agent. It
22
+ normalises language and nothing else: it never plans, builds or judges, never summarises, adds or drops a
23
+ requirement, and never translates harness *output* back into the PO's language. `/ship intake <path>…` (the
24
+ `intake` sub-command) runs just this step over named files, and with `--check` stops after the detection and
25
+ writes nothing.
26
+
27
+ **Detect.** For the pitch **and** its breadboard, sample headings and body prose (ignore code, identifiers and
28
+ URLs): `English` → used as it is, no `.en.md` written (idempotent, so a re-run and `--check` are safe and
29
+ cheap); `non-English` → queue; `mixed` → queue, and leave the English spans exactly as written.
30
+
31
+ **Glossary.** One English term per source term, across every document and every run — two spellings read as two
32
+ concepts to the planner's domain pass. Load the feature's `shapeup/<slug>/shaping/glossary.md` when it exists as
33
+ the base map; extract domain nouns, actor names, status/enum values, screen names and feature jargon with a
34
+ proposed English term each; mark the do-not-translate tokens (proper nouns, brand and product names, code
35
+ identifiers, API names, env vars, file paths), which pass through verbatim. **An ambiguous term (one source
36
+ word, several valid English terms) is asked of the PO and never guessed** — a wrong canonical term cascades
37
+ into every document and every round. `auto` and `unattended` runs go on when nothing is ambiguous, and still
38
+ stop when something is.
39
+
40
+ **Translate.** Write `<name>.en.md` beside its source — under `shapeup/<slug>/shaping/` when the source lives
41
+ there; the **original is never overwritten**. This is the committed tier, and the loop is its writer. Prose
42
+ becomes English with the glossary applied to every domain term; everything a machine parses stays byte
43
+ identical, and structure stays 1:1 — same headings, table rows, list items, order. What is kept and what is
44
+ translated, the glossary protocol and the verification scan are in `resources/intake-preservation.md`; read it
45
+ before translating any file.
46
+
47
+ **Verify, then sign off.** A residual-language scan of every `.en.md` outside code and do-not-translate tokens
48
+ (any hit lists `file:line` and the file does not pass), a structural diff against the source (heading, table-row,
49
+ list-item, wikilink and code-block counts must match — a mismatch is a requirement dropped or added), and a
50
+ glossary with no unresolved term. A dirty scan stops the run in every lane: a half-translated intake makes the
51
+ planner fail mid-run, which is worse than stopping here. Clean →
52
+
53
+ ```
54
+ Translated : <k> files → <name>.en.md
55
+ Glossary : shapeup/<slug>/shaping/glossary.md (<t> terms, <a> resolved ambiguities)
56
+ Residual scan: clean | <n> non-English spans → [file:line …]
57
+ Structure : matches source | <diff>
58
+ ```
59
+
60
+ The run **opens on the `.en.md` files** (`--intake-file <name>.en.md`, and the `<breadboard>.en.md` copied to `.shapeup/<slug>/breadboard.md`):
61
+ the intake is what every planning step reads, so a translation made after the run opened reaches nobody. A run
62
+ already open on the original is reopened with `init run --force` — nothing has been planned yet. Once the run
63
+ is open, write the audit trail (what was detected, skipped or flagged, the glossary diff, the scan result) to
64
+ `.shapeup/<slug>/translation-report.md`.
65
+
66
+ ## 3. Collect, explicitly
67
+
68
+ Never inferred; ask for what the pitch does not say.
69
+
70
+ | | |
71
+ |---|---|
72
+ | Appetite | the pitch frontmatter's `appetite`. Missing or uncapped is a risk: say so at L0 and again at the board gate. It sizes the round budget: 1 week → 2 rounds, 2 weeks → 3, 6 weeks → 4. |
73
+ | Lens | `lite` \| `standard` \| `cross-context` (default `standard`) — carried as `lens` in every `plan` order's payload |
74
+ | Stack hint | aims the Scout's sweeps and the run commands (e.g. "pnpm, Next 16 web :3000") |
75
+ | Eval dimensions | default `auto`: the order resolves the set from the spec. Name a set only on request; it must reach every `evaluate` order's `dimensions`, or it grades nothing. What is left out is reported at the ship gate as not evaluated. |
76
+ | Rounds, attempts | default 3 rounds, 5 attempts per scope per round. `resources/rounds.md` says why there are two breakers |
77
+ | Auto level | `interactive` (default): pause at every gate · `auto`: low-risk gates pre-answered, still pause at the judgment gates and ship · `unattended`: headless, needs an answer set |
78
+ | Models | resolve once: flags, then `.claude/settings.local.json`, then `.claude/settings.json`, then defaults, and pass the result as `--exec-model` / `--eval-model` / `--qa-model`. Exec and eval must be sonnet or above — `init run` refuses a cheaper tier. A model the member's plan does not offer degrades one tier down, and the degrade is said at the L0 gate, never silent. |
79
+ | Run commands | the build command (`run_cmd`), and the profile's `build_probe` and `launch_probe`. A `mobile` profile with no launch probe has nobody owning the install and launch risk: say so. |
80
+ | Knowledge base | read `shapeup/knowledge-base/building.md` and then `tech-lead.md` (the same guidance under its old name; `resources/guidance.md`) if they exist. It may add a question or a check to a gate block and may propose run values (confirm each with the PO and note `(source: knowledge-base)`). It never answers, skips or reorders a gate. With no file at all, offer `/retro --scan` once and go on whether or not the PO takes it. |
81
+
82
+ ## 4. Open the run
83
+
84
+ Write the requirement to a file first and pass the path; a multi-line requirement inlined into a shell
85
+ argument is where this step goes wrong. **Every switch the operator typed goes on this one command**: `init
86
+ run` writes the launch record (§7) in the same act as the receipt, so a switch left off it does nothing.
87
+
88
+ ```bash
89
+ node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" init run --slug <slug> --intake-file <path> --auto-level <interactive|auto|unattended> [--gate-answers <ci|guarded|path.json>] [--max-rounds 3] [--attempts 5] [--exec-model <m>] [--eval-model <m>] [--qa-model <m>] [--no-eval] [--no-qa] [--parallel-scopes <N>]
90
+ ```
91
+
92
+ Ask for every value in §3 *before* this command, so the record is right the first time; a change the PO asks
93
+ for at the L0 gate (§6) re-opens the run with `--force` — nothing has been planned yet.
94
+
95
+ **Exit 2 naming a role** means a model is below the floor (`exec` and `eval` must be sonnet or above; `qa` and,
96
+ under `--no-eval`, `eval` are not checked): say which, and ask for another. An unknown switch exits 2 too, naming it.
97
+
98
+ **Exit 3 means a run is already open, or the worker roster is missing.** For an open run the refusal prints the
99
+ launch record it keeps — the switches typed to *this* call were not applied — and the loop continues from the phase
100
+ table in `SKILL.md`. `--force` reopens deliberately: it answers every order nobody answered as abandoned, retires the
101
+ fence's pointer and writes a fresh record; only the PO asks for it.
102
+
103
+ ## 5. The shared profile
104
+
105
+ Write `shapeup/<slug>/project-profile.md`: frontmatter `{schema_version: 1, archetype, entry_point}` plus,
106
+ when the project has them, `build_probe` and `launch_probe`. Nothing downstream can be
107
+ wired without it, and a typo in the `archetype` enum must fail rather than silently disable a check.
108
+
109
+ | Field | Meaning |
110
+ |---|---|
111
+ | `archetype` | `client-only-game` · `web-service` · `mobile` · `library` · `data-pipeline` |
112
+ | `entry_point` | the composition root the wiring map names its call sites against. Where some module composes the app, name that one rather than the file the platform happens to start |
113
+ | `build_probe` | asserts the BUILT ARTIFACT covers what the run wrote — a green exit code is not proof the feature compiled when the toolchain compiles only what an entry point reaches |
114
+ | `launch_probe` | installs, starts and asserts the first screen. A `mobile` profile without one is worth saying at L0, because nothing else launches the app |
115
+
116
+ The loop runs them itself, once per round before it dispatches the evaluator: a scope's fixture can be green while its
117
+ code never compiles, on any toolchain that compiles only what the entry point reaches, so `build_probe` asserts the
118
+ built artifact. A red step ends the round with no verdict, and its failure is the next round's bug.
119
+
120
+ ## 6. The L0 gate
121
+
122
+ Emit the block, then resolve it like every other gate:
123
+
124
+ ```
125
+ ⏸ GATE L0 — Intake & Run Config
126
+ Feature : <slug> (kicked-off pitch: <path>)
127
+ Intake lang : English | translated → <name>.en.md
128
+ Appetite : ~1 week | ~2 weeks | ~6 weeks | ⚠ missing — scope uncapped
129
+ Eval dims : auto | the named set Rounds: <N> Auto: <level>
130
+ Run commands : <run_cmd> · build_probe <set|—> · launch_probe <set|— ⚠ mobile>
131
+ Model matrix : exec=<m> eval=<m> qa=<m> (source: flags | settings.local | settings.json | default)
132
+ Budgets : round_budget=<N> (outer) attempt_budget=<N> (inner, per scope)
133
+ Knowledge : building.md — <N> rules | none
134
+ ```
135
+
136
+ ```bash
137
+ node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" gate --resolve L0 --slug <slug> [--file <path>|--preset <name>]
138
+ ```
139
+
140
+ Exit 4: put the block to the PO and wait. Exit 0 `proceed`: continue. Exit 5: stop; do not launch.
141
+
142
+ ## 7. The launch record
143
+
144
+ `.shapeup/<slug>/run-args.json` is what this run was launched with, written by `init run` and read by the loop;
145
+ it is the only place a typed switch survives. The loop reads nothing but the record and the artifacts.
146
+
147
+ | Switch on `init run` | Field |
148
+ |---|---|
149
+ | `--auto-level` | `autoLevel` |
150
+ | `--gate-answers <set>` | `answers` — the answer set the gates resolve through |
151
+ | `--exec-model` `--eval-model` `--qa-model` | `models.{exec,eval,qa}` — a flag, else `SHAPEUP_EXEC_MODEL` / `SHAPEUP_EVAL_MODEL` / `SHAPEUP_QA_MODEL`, else `sonnet`; `qa` follows `exec` |
152
+ | `--max-rounds` `--attempts` | `budgets.{maxRounds,attemptBudget}` |
153
+ | `--no-eval` | `noEval` — skips the evaluation; the ship report says so in its first line and never reads as verified; you do not write PASS over a run launched with it |
154
+ | `--no-qa` | `noQa` — skips the QA hunt |
155
+ | `--parallel-scopes N` | `maxParallelScopes` — how many scopes build at once (default 4; `1` = sequential) |
156
+
157
+ Then go to the loop.