shapeup-sdlc 3.18.3 → 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 +14 -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,161 +0,0 @@
1
- // probe attempts — "how many of this scope's attempts are ATTESTED work, not writable artifacts?"
2
- //
3
- // CONTRACT. A bounded, read-only query over one scope's attested channels for one round: dispatch
4
- // receipts (`receipts/dispatch.jsonl`), leg-completion rows (`legs.jsonl`) and WorkResults
5
- // (`results/`). Prints `{scope_id, round, attempt_budget, spent, in_flight, unattested, green,
6
- // tripped, attempts}` on stdout; exits 0 when the breaker holds, 1 when it has tripped, 2 on a bad
7
- // argv. Writes nothing.
8
- //
9
- // WHY IT EXISTS. Measured on a real run: attempt 2 of a scope was compiled and T0-verified
10
- // several minutes BEFORE attempt 1 ingested — while attempt 1 was still in flight. No worker was
11
- // ever dispatched for attempt 2:
12
- // `receipts/dispatch.jsonl`, `legs.jsonl` and `results/` carried no row for it. A derivation keyed
13
- // off the order set (`orders/`) or the T0 verdict set (`t0/verdicts/`) alone counts a compiled
14
- // order or a green trial as a spent attempt regardless of whether a worker ever ran — both are
15
- // WRITABLE by the very leg whose exhaustion is being judged. This module counts an attempt as
16
- // SPENT only when a dispatch receipt attests it started AND either a leg-completion row or a
17
- // WorkResult on disk attests it closed. Neither channel alone is enough: a receipt with no result
18
- // is a leg still in flight (open, not spent — the breaker must not trip on unanswered work), and a
19
- // result or verdict with no receipt is unattested — no worker ran, which is the shape that
20
- // produced this module.
21
- //
22
- // WHY THE SAME FUNCTION SERVES THE BREAKER AND THE CENSUS. Before this module, the round loop's
23
- // inner breaker and `scope-hammer`'s GATE H0 census read different evidence for the same question
24
- // — the loop trusted the worker's own self-reported `attempts_used`/`breaker` (schema-shaped, not
25
- // re-verified), the census read `t0/verdicts/*.json` directly — and disagreed on the measured run.
26
- // One shared, attested derivation is what makes "the census and the breaker agree" true by
27
- // construction rather than by coincidence: `skills/scope-hammer/SKILL.md` cites this same probe
28
- // the way it already cites `probe owner` for ownership claims.
29
-
30
- import { existsSync, readdirSync, readFileSync } from "node:fs";
31
- import { join, resolve } from "node:path";
32
- import { runArgs } from "../lib/argv.mjs";
33
- import { dispatchReceipts, legLedger, resultsDir, readRunId, ordersDir } from "../lib/paths.mjs";
34
- import { readLegs } from "./leg.mjs";
35
- import { greenVerdict } from "./t0.mjs";
36
-
37
- /**
38
- * Every dispatch-receipt row on disk, tolerant of a torn last line (mirrors {@link readLegs}).
39
- * @param {string} path - `receipts/dispatch.jsonl`.
40
- * @returns {object[]} Parsed rows; an unparsable line is skipped rather than fatal.
41
- */
42
- export function readReceipts(path) {
43
- if (!existsSync(path)) return [];
44
- return readFileSync(path, "utf8").split("\n").filter(Boolean)
45
- .map((l) => { try { return JSON.parse(l); } catch { return null; } })
46
- .filter(Boolean);
47
- }
48
-
49
- /**
50
- * One attempt's evidence across the three attested channels, and the state it derives to.
51
- *
52
- * `unattested` (no receipt at all) counts as though the attempt never happened — the order and any
53
- * T0 verdict may still be sitting on disk, written by something other than a dispatched worker, and
54
- * neither is asked here. `in-flight` (a receipt, but no leg row and no result) is a real dispatch
55
- * whose leg has not yet closed: open, not spent. `spent` is closed either way a leg closes — via
56
- * `reduce ingest`'s own leg-completion row, or a WorkResult already on disk pending ingest.
57
- *
58
- * @param {string} cwd - Project root.
59
- * @param {string} slug - Feature slug.
60
- * @param {string} scopeId - Scope contract id (the order id's own address, e.g. `shell-r1-a2`).
61
- * @param {number} round - Build round.
62
- * @param {number} attempt - Attempt number within the round.
63
- * @param {object[]} receipts - Pre-read `receipts/dispatch.jsonl` rows (avoids re-reading per attempt).
64
- * @param {object[]} legs - Pre-read `legs.jsonl` rows.
65
- * @returns {{orderId:string, hasReceipt:boolean, hasResult:boolean, hasLeg:boolean, state:("unattested"|"in-flight"|"spent")}}
66
- */
67
- export function attemptEvidence(cwd, slug, scopeId, round, attempt, receipts, legs, runId = null) {
68
- const orderId = `${slug}/${scopeId}-r${round}-a${attempt}`;
69
- // SCOPED TO THIS RUN, and that qualifier is the whole correction. `receipts/dispatch.jsonl` and
70
- // `legs.jsonl` are per-slug and append-only, so they accumulate across every run of a pitch,
71
- // while `order_id` repeats — the run key is the only thing that separates two runs of one
72
- // feature. Matching on `order_id` alone answered "was this attempt spent?" with a PREVIOUS run's
73
- // receipt: measured on a consumer, a run that dispatched nothing was told its first attempt was
74
- // spent, complete with leg and result, by rows two launches old.
75
- //
76
- // A row carrying no run key belongs to NO run rather than to this one, and an unresolvable
77
- // current run (no receipt on disk) matches nothing. Both directions under-count rather than
78
- // over-count, which is the safe way to be wrong here: an under-count leaves a breaker un-tripped
79
- // and the round continues, where an over-count stops work that was never done.
80
- const mine = (r) => r?.order_id === orderId && runId != null && r?.run_id === runId;
81
- const hasReceipt = receipts.some(mine);
82
- const hasLeg = legs.some(mine);
83
- // A WorkResult carries no run key and reaches one only through its `order_id`, which repeats —
84
- // so this stays a file check and is deliberately NOT sufficient on its own. It can only turn an
85
- // already run-scoped receipt into `spent`; a result left behind by an earlier run cannot attest
86
- // an attempt this run never dispatched.
87
- // A WorkResult carries no run key of its own; it answers THIS run's attempt only through the
88
- // order of the same name, which this run's compile rewrote. A result left by a prior run over the
89
- // same slug used to close an attempt this run had not even opened.
90
- const stem = `${scopeId}-r${round}-a${attempt}.json`;
91
- let orderIsMine = true;
92
- if (runId != null) {
93
- try { const o = JSON.parse(readFileSync(join(ordersDir(cwd, slug), stem), "utf8")); orderIsMine = !o?.run_id || o.run_id === runId; }
94
- catch { orderIsMine = false; }
95
- }
96
- const hasResult = orderIsMine && existsSync(join(resultsDir(cwd, slug), stem));
97
- const state = !hasReceipt ? "unattested" : (hasResult || hasLeg) ? "spent" : "in-flight";
98
- return { orderId, hasReceipt, hasResult, hasLeg, state };
99
- }
100
-
101
- /**
102
- * A scope's attempt census for one round, derived ONLY from attested channels — the function both
103
- * the round loop's inner breaker and scope-hammer's GATE H0 census call, so they cannot drift apart
104
- * again the way a measured run found them.
105
- *
106
- * @param {string} cwd - Project root.
107
- * @param {string} slug - Feature slug.
108
- * @param {string} scopeId - Scope contract id.
109
- * @param {number} round - Build round.
110
- * @param {number} attemptBudget - The scope's configured `attempt_budget`.
111
- * @returns {{scope_id:string, round:number, attempt_budget:number, spent:number, in_flight:number,
112
- * unattested:number, green:boolean, tripped:boolean, attempts:object[]}} `tripped` is true only
113
- * when every attempt within budget is genuinely SPENT and none produced a green T0 — an attempt
114
- * still in flight holds the breaker open regardless of how many slots are nominally used.
115
- */
116
- export function scopeAttempts(cwd, slug, scopeId, round, attemptBudget) {
117
- const receipts = readReceipts(dispatchReceipts(cwd, slug));
118
- const legs = readLegs(legLedger(cwd, slug));
119
- const runId = readRunId(cwd, slug);
120
- const attempts = [];
121
- let spent = 0, inFlight = 0, unattested = 0;
122
- for (let a = 1; a <= attemptBudget; a++) {
123
- const ev = attemptEvidence(cwd, slug, scopeId, round, a, receipts, legs, runId);
124
- if (ev.state === "spent") spent++;
125
- else if (ev.state === "in-flight") inFlight++;
126
- else unattested++;
127
- attempts.push({ attempt: a, ...ev });
128
- }
129
- const { green } = greenVerdict(cwd, slug, scopeId, round);
130
- return {
131
- scope_id: scopeId, round, attempt_budget: attemptBudget,
132
- spent, in_flight: inFlight, unattested, green,
133
- tripped: !green && spent >= attemptBudget,
134
- attempts,
135
- };
136
- }
137
-
138
- export const ARGV_SPEC = {
139
- usage: "harness.mjs probe attempts --slug <slug> --scope <scope-id> --round N --attempt-budget N [--cwd <dir>]",
140
- _: { arity: 0, max: 0, name: "(no positional operands)" },
141
- slug: { type: "str", required: true },
142
- scope: { type: "str", required: true },
143
- round: { type: "int", min: 1, required: true },
144
- "attempt-budget": { type: "int", min: 1, required: true },
145
- cwd: { type: "path" },
146
- };
147
-
148
- /**
149
- * Report one scope's attested attempt census for one round.
150
- *
151
- * @param {string[]} rawArgv - The subcommand's own arguments (harness.mjs strips the verb words).
152
- * @returns {void} Exits 0 when the breaker holds, 1 when it has tripped — the shape a caller (or a
153
- * census citing this row) can branch on without parsing prose.
154
- */
155
- export function cli(rawArgv) {
156
- const args = runArgs(ARGV_SPEC, rawArgv);
157
- const cwd = resolve(args.cwd || process.cwd());
158
- const r = scopeAttempts(cwd, args.slug, args.scope, args.round, args.attemptBudget);
159
- console.log(JSON.stringify(r));
160
- process.exit(r.tripped ? 1 : 0);
161
- }