shapeup-sdlc 1.6.2
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.
- package/.claude/settings.local.example.json +20 -0
- package/.claude-plugin/marketplace.json +16 -0
- package/.claude-plugin/plugin.json +18 -0
- package/.env.shapeup.example +14 -0
- package/AGENTS.md +133 -0
- package/LICENSE +21 -0
- package/README.md +362 -0
- package/SECURITY.md +72 -0
- package/bin/init.mjs +329 -0
- package/commands/build.md +14 -0
- package/commands/eval.md +15 -0
- package/commands/hammer.md +12 -0
- package/commands/orient.md +11 -0
- package/commands/qa.md +12 -0
- package/commands/retro.md +13 -0
- package/commands/scopes.md +14 -0
- package/commands/shape.md +12 -0
- package/commands/ship.md +53 -0
- package/commands/wire.md +11 -0
- package/hooks/anti-rationalization.mjs +244 -0
- package/hooks/compact-snapshot.mjs +47 -0
- package/hooks/gate-deadline.mjs +151 -0
- package/hooks/gate-intake.mjs +110 -0
- package/hooks/gate-l2.mjs +161 -0
- package/hooks/gate-zerowork.mjs +264 -0
- package/hooks/hooks.json +118 -0
- package/hooks/lib/decision.mjs +183 -0
- package/hooks/safety-spine.mjs +296 -0
- package/hooks/sandbox-guard.mjs +172 -0
- package/hooks/session-rehydrate.mjs +109 -0
- package/hooks/slop-cleaner.mjs +176 -0
- package/oracles/_shared.mjs +46 -0
- package/oracles/http-oracle.mjs +155 -0
- package/oracles/index.mjs +36 -0
- package/oracles/process-oracle.mjs +146 -0
- package/oracles/snapshot-oracle.mjs +119 -0
- package/oracles/test-oracle.mjs +138 -0
- package/package.json +49 -0
- package/skills/advisor-protocol/SKILL.md +171 -0
- package/skills/ba-pitch-analyzer/SKILL.md +175 -0
- package/skills/ba-pitch-analyzer/assets/templates/_index.tmpl.md +84 -0
- package/skills/ba-pitch-analyzer/assets/templates/api-feasibility.tmpl.md +65 -0
- package/skills/ba-pitch-analyzer/assets/templates/assess-report.tmpl.md +127 -0
- package/skills/ba-pitch-analyzer/assets/templates/contracts/be-service.contract.tmpl.md +62 -0
- package/skills/ba-pitch-analyzer/assets/templates/contracts/offline-storage.contract.tmpl.md +92 -0
- package/skills/ba-pitch-analyzer/assets/templates/contracts/third-party-api.contract.tmpl.md +66 -0
- package/skills/ba-pitch-analyzer/assets/templates/cross-context/context-map.tmpl.md +64 -0
- package/skills/ba-pitch-analyzer/assets/templates/cross-context/event-choreography.tmpl.md +77 -0
- package/skills/ba-pitch-analyzer/assets/templates/cross-context/migration-plan.tmpl.md +104 -0
- package/skills/ba-pitch-analyzer/assets/templates/cross-context/team-handoff.tmpl.md +79 -0
- package/skills/ba-pitch-analyzer/assets/templates/domain-model.tmpl.md +79 -0
- package/skills/ba-pitch-analyzer/assets/templates/feedback.tmpl.md +87 -0
- package/skills/ba-pitch-analyzer/assets/templates/integration.tmpl.md +64 -0
- package/skills/ba-pitch-analyzer/assets/templates/run-state.tmpl.md +77 -0
- package/skills/ba-pitch-analyzer/assets/templates/scope-summary.tmpl.md +105 -0
- package/skills/ba-pitch-analyzer/assets/templates/synthesis.tmpl.md +215 -0
- package/skills/ba-pitch-analyzer/assets/templates/task-board.tmpl.md +35 -0
- package/skills/ba-pitch-analyzer/assets/templates/task-spike.tmpl.md +86 -0
- package/skills/ba-pitch-analyzer/assets/templates/task.tmpl.md +84 -0
- package/skills/ba-pitch-analyzer/assets/templates/usecase.tmpl.md +105 -0
- package/skills/ba-pitch-analyzer/assets/templates/ux-behavior.tmpl.md +65 -0
- package/skills/ba-pitch-analyzer/references/contract-patterns.md +152 -0
- package/skills/ba-pitch-analyzer/references/ddd-patterns.md +173 -0
- package/skills/ba-pitch-analyzer/references/doc-schemas.md +275 -0
- package/skills/ba-pitch-analyzer/references/integration-analysis.md +152 -0
- package/skills/ba-pitch-analyzer/references/task-generation.md +623 -0
- package/skills/ba-pitch-analyzer/references/test-surface.md +102 -0
- package/skills/ba-pitch-analyzer/references/ux-behavior-patterns.md +269 -0
- package/skills/ba-pitch-analyzer/scripts/board-derive.mjs +241 -0
- package/skills/ba-pitch-analyzer/scripts/spec-lint.mjs +239 -0
- package/skills/coach/SKILL.md +202 -0
- package/skills/orient/SKILL.md +262 -0
- package/skills/qa-edge-hunter/SKILL.md +369 -0
- package/skills/scope-architect/SKILL.md +111 -0
- package/skills/scope-hammer/SKILL.md +186 -0
- package/skills/shapeup/SKILL.md +403 -0
- package/skills/shapeup/resources/breadboard-reflection.md +88 -0
- package/skills/shapeup/resources/breadboarding.md +334 -0
- package/skills/shapeup/resources/context-compaction.md +240 -0
- package/skills/shapeup/resources/framing-doc.md +92 -0
- package/skills/shapeup/resources/kickoff-doc.md +95 -0
- package/skills/shapeup/resources/shaping.md +194 -0
- package/skills/shapeup/resources/spike.md +86 -0
- package/skills/solution-architect/SKILL.md +129 -0
- package/skills/spec-evaluator/README.md +93 -0
- package/skills/spec-evaluator/SKILL.md +213 -0
- package/skills/spec-evaluator/references/anti-leniency.md +50 -0
- package/skills/spec-evaluator/references/dimension-contract.md +126 -0
- package/skills/spec-evaluator/references/dimensions/_registry.md +40 -0
- package/skills/spec-evaluator/references/dimensions/completeness.md +102 -0
- package/skills/spec-evaluator/references/dimensions/integration.md +129 -0
- package/skills/spec-evaluator/references/dimensions/performance.md +48 -0
- package/skills/spec-evaluator/references/dimensions/security.md +60 -0
- package/skills/spec-evaluator/references/dimensions/spec-conformance.md +134 -0
- package/skills/spec-evaluator/references/dimensions/tdd-surface.md +110 -0
- package/skills/spec-evaluator/references/dimensions/test-surface-conformance.md +100 -0
- package/skills/spec-evaluator/references/probing.md +177 -0
- package/skills/spec-evaluator/references/report-schema.md +101 -0
- package/skills/spec-evaluator/references/verdict-ledger.md +92 -0
- package/skills/spec-evaluator/scripts/verdict-ledger.mjs +166 -0
- package/skills/task-executor/SKILL.md +194 -0
- package/skills/tech-lead/README.md +71 -0
- package/skills/tech-lead/SKILL.md +459 -0
- package/skills/tech-lead/references/delegation.md +254 -0
- package/skills/tech-lead/references/gates.md +379 -0
- package/skills/tech-lead/references/invocation.md +45 -0
- package/skills/tech-lead/references/ledger-schema.md +214 -0
- package/skills/tech-lead/references/round-protocol.md +184 -0
- package/skills/tech-lead/references/state-model.md +66 -0
- package/skills/tech-lead/references/tiny-lane.md +52 -0
- package/skills/tech-lead/schemas/domain.schema.json +2294 -0
- package/skills/tech-lead/schemas/gate-answers.schema.json +92 -0
- package/skills/tech-lead/schemas/work-order.schema.json +21 -0
- package/skills/tech-lead/schemas/work-result.schema.json +40 -0
- package/skills/tech-lead/scripts/aegis-digest.mjs +124 -0
- package/skills/tech-lead/scripts/budget-check.mjs +156 -0
- package/skills/tech-lead/scripts/compile-order.mjs +518 -0
- package/skills/tech-lead/scripts/fit-check.mjs +196 -0
- package/skills/tech-lead/scripts/gate-answers.mjs +338 -0
- package/skills/tech-lead/scripts/ingest-result.mjs +270 -0
- package/skills/tech-lead/scripts/init-run.mjs +326 -0
- package/skills/tech-lead/scripts/lib/argv.mjs +224 -0
- package/skills/tech-lead/scripts/lib/contract-md.mjs +481 -0
- package/skills/tech-lead/scripts/lib/is-main.mjs +82 -0
- package/skills/tech-lead/scripts/lib/paths.mjs +278 -0
- package/skills/tech-lead/scripts/lib/ratchet-tree.mjs +112 -0
- package/skills/tech-lead/scripts/run-snapshot.mjs +269 -0
- package/skills/tech-lead/scripts/ship-report.mjs +275 -0
- package/skills/tech-lead/scripts/stats.mjs +423 -0
- package/skills/tech-lead/scripts/t0-verify.mjs +470 -0
- package/skills/tech-lead/scripts/trace-lint.mjs +367 -0
- package/skills/tech-lead/scripts/validate-envelope.mjs +283 -0
- package/skills/translator/README.md +66 -0
- package/skills/translator/SKILL.md +258 -0
- package/skills/translator/references/preservation-rules.md +102 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
// parseArgs — the typed argv boundary.
|
|
2
|
+
//
|
|
3
|
+
// WHY THIS FILE EXISTS (measured by executing the shipped scripts, not theorized).
|
|
4
|
+
//
|
|
5
|
+
// This project's envelope boundary is rigorously typed: 38 `$defs` in `domain.schema.json`,
|
|
6
|
+
// both directions validated, and a `PreToolUse` hook that DENIES a malformed WorkOrder before a
|
|
7
|
+
// worker ever sees it. That discipline stopped dead at `process.argv` — which is where the
|
|
8
|
+
// pipeline actually executes.
|
|
9
|
+
//
|
|
10
|
+
// The reproduced defect. `t0-verify.mjs` parsed its own flags with
|
|
11
|
+
//
|
|
12
|
+
// if (a === "--round") out.round = Number(argv[++i]); // then: args.round ?? 1
|
|
13
|
+
//
|
|
14
|
+
// `Number(undefined)` is `NaN`, and `??` does not catch `NaN`. So passing a flag WITHOUT a value
|
|
15
|
+
// wrote a real verdict artifact to `t0/verdicts/rNaN-a1.json` and **exited 0**:
|
|
16
|
+
//
|
|
17
|
+
// $ t0-verify.mjs contract.json --round --attempt 1
|
|
18
|
+
// { "path": "t0/verdicts/rNaN-a1.json", "overall": "green", ... } exit=0
|
|
19
|
+
//
|
|
20
|
+
// The orchestrator then looks for `r1-a1.json`, finds nothing, and the evaluator's MANDATORY T0
|
|
21
|
+
// citation cannot resolve — on the single artifact the judge is structurally required to cite.
|
|
22
|
+
// A green verdict at an address nobody will look up is the same failure class as a silent no-op:
|
|
23
|
+
// indistinguishable from working.
|
|
24
|
+
//
|
|
25
|
+
// THE CONTRACT, mirroring `validate-envelope`'s: reject BEFORE anything runs, exit 2, and put a
|
|
26
|
+
// machine-readable reason on stderr. Nothing here touches the filesystem, so a rejected parse
|
|
27
|
+
// cannot leave a half-written artifact behind.
|
|
28
|
+
//
|
|
29
|
+
// const SPEC = {
|
|
30
|
+
// _: { arity: 1, name: "scope-contract.json" },
|
|
31
|
+
// round: { type: "int", min: 1, required: true },
|
|
32
|
+
// "no-seesaw": { type: "flag" },
|
|
33
|
+
// };
|
|
34
|
+
// const args = runArgs(SPEC, process.argv.slice(2)); // args.round, args.noSeesaw, args._
|
|
35
|
+
//
|
|
36
|
+
// Flag names reach the caller camelCased (`--no-seesaw` → `noSeesaw`), so adoption does not
|
|
37
|
+
// rewrite call sites. Unknown flags are rejected rather than silently swallowed as positionals:
|
|
38
|
+
// a typo'd `--rounds 2` that lands in `_` is the same defect wearing a different hat.
|
|
39
|
+
//
|
|
40
|
+
// `tests/structural/13-argv-contract.mjs` executes every entry point with each declared int flag
|
|
41
|
+
// both empty and non-numeric, and asserts exit 2 with a parseable reason and no artifact on disk.
|
|
42
|
+
|
|
43
|
+
/** Thrown by {@link parseArgs} when argv does not satisfy the spec. `detail` is the wire shape. */
|
|
44
|
+
export class ArgvError extends Error {
|
|
45
|
+
/**
|
|
46
|
+
* @param {object} detail - Machine-readable rejection record; `detail.error` names the class.
|
|
47
|
+
*/
|
|
48
|
+
constructor(detail) {
|
|
49
|
+
super(detail.error);
|
|
50
|
+
this.name = "ArgvError";
|
|
51
|
+
this.detail = detail;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** `--seesaw-registry` → `seesawRegistry`. */
|
|
56
|
+
function camel(name) {
|
|
57
|
+
return name.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase());
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Human-readable expectation for one flag, used in the rejection record. */
|
|
61
|
+
function expectation(def) {
|
|
62
|
+
switch (def.type) {
|
|
63
|
+
case "int":
|
|
64
|
+
if (def.min !== undefined && def.max !== undefined) return `int in [${def.min}, ${def.max}]`;
|
|
65
|
+
if (def.min !== undefined) return `int ≥ ${def.min}`;
|
|
66
|
+
if (def.max !== undefined) return `int ≤ ${def.max}`;
|
|
67
|
+
return "int";
|
|
68
|
+
case "num":
|
|
69
|
+
return def.min !== undefined ? `number ≥ ${def.min}` : "number";
|
|
70
|
+
case "enum": return `one of ${(def.values || []).join(" | ")}`;
|
|
71
|
+
case "json": return "JSON";
|
|
72
|
+
case "path": return "path";
|
|
73
|
+
case "flag": return "no value";
|
|
74
|
+
default: return "string";
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Coerce and range-check one raw flag value.
|
|
80
|
+
* @param {string} flagName - Flag name without dashes (for the rejection record).
|
|
81
|
+
* @param {object} def - The spec entry.
|
|
82
|
+
* @param {string} raw - The token following the flag.
|
|
83
|
+
* @returns {(string|number|object)} The coerced value.
|
|
84
|
+
* @throws {ArgvError} `invalid_value` when the token does not satisfy `def`.
|
|
85
|
+
*/
|
|
86
|
+
function coerce(flagName, def, raw) {
|
|
87
|
+
const bad = () => {
|
|
88
|
+
throw new ArgvError({ error: "invalid_value", flag: `--${flagName}`, got: raw, expected: expectation(def) });
|
|
89
|
+
};
|
|
90
|
+
switch (def.type) {
|
|
91
|
+
case "int": {
|
|
92
|
+
// Deliberately stricter than Number(): "1.5", "1e3", " 1 " and "0x2" are all rejected, so a
|
|
93
|
+
// round number is a round number on every platform rather than whatever the coercion did.
|
|
94
|
+
if (!/^-?\d+$/.test(raw)) bad();
|
|
95
|
+
const n = Number(raw);
|
|
96
|
+
if (!Number.isSafeInteger(n)) bad();
|
|
97
|
+
if (def.min !== undefined && n < def.min) bad();
|
|
98
|
+
if (def.max !== undefined && n > def.max) bad();
|
|
99
|
+
return n;
|
|
100
|
+
}
|
|
101
|
+
case "num": {
|
|
102
|
+
const n = Number(raw);
|
|
103
|
+
if (raw.trim() === "" || !Number.isFinite(n)) bad();
|
|
104
|
+
if (def.min !== undefined && n < def.min) bad();
|
|
105
|
+
if (def.max !== undefined && n > def.max) bad();
|
|
106
|
+
return n;
|
|
107
|
+
}
|
|
108
|
+
case "enum":
|
|
109
|
+
if (!(def.values || []).includes(raw)) bad();
|
|
110
|
+
return raw;
|
|
111
|
+
case "json":
|
|
112
|
+
try { return JSON.parse(raw); } catch { bad(); }
|
|
113
|
+
return undefined; // unreachable — bad() throws
|
|
114
|
+
case "path":
|
|
115
|
+
case "str":
|
|
116
|
+
default:
|
|
117
|
+
if (raw === "") bad();
|
|
118
|
+
return raw;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Parse argv against a declarative spec.
|
|
124
|
+
*
|
|
125
|
+
* Spec entries are keyed by flag name (no dashes). `_` declares positionals:
|
|
126
|
+
* `{ arity, max, name }` — `arity` is the minimum required count.
|
|
127
|
+
* Every other entry is `{ type, min, max, values, required, default, multiple }` where `type` is
|
|
128
|
+
* one of `int | num | str | path | enum | json | flag`.
|
|
129
|
+
*
|
|
130
|
+
* @param {Object<string,object>} spec - The flag spec (see above).
|
|
131
|
+
* @param {string[]} argv - Arguments after the script name (`process.argv.slice(2)`).
|
|
132
|
+
* @returns {Object<string,*>} Coerced values keyed by camelCased flag name, plus `_` (positionals).
|
|
133
|
+
* @throws {ArgvError} On an unknown flag, a missing value, a value that fails its type/range, a
|
|
134
|
+
* missing required flag, or too few/many positionals. Nothing is read or written before throwing.
|
|
135
|
+
*/
|
|
136
|
+
export function parseArgs(spec, argv) {
|
|
137
|
+
const positional = spec._ || { arity: 0 };
|
|
138
|
+
const out = { _: [] };
|
|
139
|
+
|
|
140
|
+
for (let i = 0; i < argv.length; i++) {
|
|
141
|
+
const token = argv[i];
|
|
142
|
+
if (token === "--") { out._.push(...argv.slice(i + 1)); break; }
|
|
143
|
+
if (!token.startsWith("--")) { out._.push(token); continue; }
|
|
144
|
+
|
|
145
|
+
// `--flag=value` and `--flag value` are the same thing to the caller.
|
|
146
|
+
const eq = token.indexOf("=");
|
|
147
|
+
const name = (eq === -1 ? token.slice(2) : token.slice(2, eq));
|
|
148
|
+
const inlineValue = eq === -1 ? null : token.slice(eq + 1);
|
|
149
|
+
const def = Object.hasOwn(spec, name) && name !== "_" ? spec[name] : null;
|
|
150
|
+
if (!def) throw new ArgvError({ error: "unknown_flag", flag: `--${name}` });
|
|
151
|
+
|
|
152
|
+
if (def.type === "flag") {
|
|
153
|
+
if (inlineValue !== null) {
|
|
154
|
+
throw new ArgvError({ error: "invalid_value", flag: `--${name}`, got: inlineValue, expected: "no value" });
|
|
155
|
+
}
|
|
156
|
+
out[camel(name)] = true;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
let raw = inlineValue;
|
|
161
|
+
if (raw === null) {
|
|
162
|
+
const next = argv[i + 1];
|
|
163
|
+
// The reproduced defect, verbatim: `--round --attempt 1` consumed `--attempt` as the value
|
|
164
|
+
// of `--round` (or, with Number(), consumed nothing and produced NaN). Both are rejections.
|
|
165
|
+
if (next === undefined) {
|
|
166
|
+
throw new ArgvError({ error: "missing_value", flag: `--${name}`, expected: expectation(def) });
|
|
167
|
+
}
|
|
168
|
+
if (next.startsWith("--")) {
|
|
169
|
+
throw new ArgvError({ error: "invalid_flag", flag: `--${name}`, got: next, expected: expectation(def) });
|
|
170
|
+
}
|
|
171
|
+
raw = next;
|
|
172
|
+
i++;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const value = coerce(name, def, raw);
|
|
176
|
+
if (def.multiple) (out[camel(name)] ||= []).push(value);
|
|
177
|
+
else out[camel(name)] = value;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
for (const [name, def] of Object.entries(spec)) {
|
|
181
|
+
if (name === "_" || def.type === "flag") continue;
|
|
182
|
+
const key = camel(name);
|
|
183
|
+
if (out[key] === undefined && def.default !== undefined) out[key] = def.default;
|
|
184
|
+
if (out[key] === undefined && def.required) {
|
|
185
|
+
throw new ArgvError({ error: "missing_required", flag: `--${name}`, expected: expectation(def) });
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (out._.length < (positional.arity || 0)) {
|
|
190
|
+
throw new ArgvError({
|
|
191
|
+
error: "missing_operand", expected: positional.name || "operand",
|
|
192
|
+
need: positional.arity || 0, got: out._.length,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
if (positional.max !== undefined && out._.length > positional.max) {
|
|
196
|
+
throw new ArgvError({
|
|
197
|
+
error: "unexpected_operand", expected: positional.name || "operand",
|
|
198
|
+
max: positional.max, got: out._.length,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
return out;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* CLI wrapper for {@link parseArgs}: on rejection, print the record to stderr and exit 2.
|
|
206
|
+
*
|
|
207
|
+
* Exit 2 is this project's established "the input was malformed, nothing ran" code — the same one
|
|
208
|
+
* `validate-envelope` uses for a WorkOrder that fails its schema. It is deliberately NOT 1, which
|
|
209
|
+
* every oracle here uses to mean "ran, and the answer is no".
|
|
210
|
+
*
|
|
211
|
+
* @param {Object<string,object>} spec - The flag spec.
|
|
212
|
+
* @param {string[]} [argv=process.argv.slice(2)] - Arguments after the script name.
|
|
213
|
+
* @returns {Object<string,*>} The parsed args (see {@link parseArgs}). Does not return on failure.
|
|
214
|
+
*/
|
|
215
|
+
export function runArgs(spec, argv = process.argv.slice(2)) {
|
|
216
|
+
try {
|
|
217
|
+
return parseArgs(spec, argv);
|
|
218
|
+
} catch (e) {
|
|
219
|
+
if (!(e instanceof ArgvError)) throw e;
|
|
220
|
+
process.stderr.write(JSON.stringify(e.detail) + "\n");
|
|
221
|
+
if (spec.usage) process.stderr.write(`usage: ${spec.usage}\n`);
|
|
222
|
+
process.exit(2);
|
|
223
|
+
}
|
|
224
|
+
}
|