@slowcook-ai/cli 0.20.0 → 0.21.1

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 (79) hide show
  1. package/README.md +15 -3
  2. package/dist/cli.js +18 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/brand/index.d.ts.map +1 -1
  5. package/dist/commands/brand/index.js +6 -0
  6. package/dist/commands/brand/index.js.map +1 -1
  7. package/dist/commands/brand/logo-cmd.d.ts +2 -0
  8. package/dist/commands/brand/logo-cmd.d.ts.map +1 -0
  9. package/dist/commands/brand/logo-cmd.js +90 -0
  10. package/dist/commands/brand/logo-cmd.js.map +1 -0
  11. package/dist/commands/brand/logo.d.ts +23 -0
  12. package/dist/commands/brand/logo.d.ts.map +1 -0
  13. package/dist/commands/brand/logo.js +60 -0
  14. package/dist/commands/brand/logo.js.map +1 -0
  15. package/dist/commands/eye/index.d.ts.map +1 -1
  16. package/dist/commands/eye/index.js +21 -2
  17. package/dist/commands/eye/index.js.map +1 -1
  18. package/dist/commands/eye/plan.d.ts +8 -0
  19. package/dist/commands/eye/plan.d.ts.map +1 -1
  20. package/dist/commands/eye/plan.js +6 -0
  21. package/dist/commands/eye/plan.js.map +1 -1
  22. package/dist/commands/eye/run.d.ts +23 -0
  23. package/dist/commands/eye/run.d.ts.map +1 -1
  24. package/dist/commands/eye/run.js +69 -0
  25. package/dist/commands/eye/run.js.map +1 -1
  26. package/dist/commands/greenfield/index.d.ts +2 -0
  27. package/dist/commands/greenfield/index.d.ts.map +1 -0
  28. package/dist/commands/greenfield/index.js +80 -0
  29. package/dist/commands/greenfield/index.js.map +1 -0
  30. package/dist/commands/greenfield/status.d.ts +38 -0
  31. package/dist/commands/greenfield/status.d.ts.map +1 -0
  32. package/dist/commands/greenfield/status.js +52 -0
  33. package/dist/commands/greenfield/status.js.map +1 -0
  34. package/dist/commands/menu/assemble.d.ts +31 -0
  35. package/dist/commands/menu/assemble.d.ts.map +1 -0
  36. package/dist/commands/menu/assemble.js +37 -0
  37. package/dist/commands/menu/assemble.js.map +1 -0
  38. package/dist/commands/menu/index.d.ts +5 -0
  39. package/dist/commands/menu/index.d.ts.map +1 -0
  40. package/dist/commands/menu/index.js +111 -0
  41. package/dist/commands/menu/index.js.map +1 -0
  42. package/dist/commands/menu/prd.d.ts +33 -0
  43. package/dist/commands/menu/prd.d.ts.map +1 -0
  44. package/dist/commands/menu/prd.js +68 -0
  45. package/dist/commands/menu/prd.js.map +1 -0
  46. package/dist/commands/plate/index.d.ts.map +1 -1
  47. package/dist/commands/plate/index.js +5 -1
  48. package/dist/commands/plate/index.js.map +1 -1
  49. package/dist/commands/plate/route-hint.d.ts +18 -0
  50. package/dist/commands/plate/route-hint.d.ts.map +1 -0
  51. package/dist/commands/plate/route-hint.js +21 -0
  52. package/dist/commands/plate/route-hint.js.map +1 -0
  53. package/dist/commands/refine/spec-yaml.d.ts +23 -0
  54. package/dist/commands/refine/spec-yaml.d.ts.map +1 -1
  55. package/dist/commands/refine/spec-yaml.js +25 -0
  56. package/dist/commands/refine/spec-yaml.js.map +1 -1
  57. package/dist/commands/run-mock/index.d.ts.map +1 -1
  58. package/dist/commands/run-mock/index.js +69 -16
  59. package/dist/commands/run-mock/index.js.map +1 -1
  60. package/dist/commands/run-mock/reviewer-auth-server.d.ts +40 -0
  61. package/dist/commands/run-mock/reviewer-auth-server.d.ts.map +1 -0
  62. package/dist/commands/run-mock/reviewer-auth-server.js +124 -0
  63. package/dist/commands/run-mock/reviewer-auth-server.js.map +1 -0
  64. package/dist/commands/trace/check.d.ts +67 -0
  65. package/dist/commands/trace/check.d.ts.map +1 -0
  66. package/dist/commands/trace/check.js +82 -0
  67. package/dist/commands/trace/check.js.map +1 -0
  68. package/dist/commands/trace/index.d.ts +2 -0
  69. package/dist/commands/trace/index.d.ts.map +1 -0
  70. package/dist/commands/trace/index.js +86 -0
  71. package/dist/commands/trace/index.js.map +1 -0
  72. package/dist/commands.manifest.d.ts.map +1 -1
  73. package/dist/commands.manifest.js +21 -3
  74. package/dist/commands.manifest.js.map +1 -1
  75. package/dist/lib/mock-shape.d.ts +6 -0
  76. package/dist/lib/mock-shape.d.ts.map +1 -1
  77. package/dist/lib/mock-shape.js +26 -0
  78. package/dist/lib/mock-shape.js.map +1 -1
  79. package/package.json +5 -5
@@ -44,4 +44,73 @@ export async function runEyeMatrix(opts) {
44
44
  }
45
45
  return { result: gradeFidelity(pairs, opts.gate), screenshots };
46
46
  }
47
+ /** Pure: one-line pass summary for the watch loop (`violations: N → M (Δ)`). */
48
+ export function formatPassLine(pass, prevTotal, result) {
49
+ const c = result.violations.length;
50
+ const delta = prevTotal === null ? "" : ` (Δ${c - prevTotal >= 0 ? "+" : ""}${c - prevTotal})`;
51
+ return `pass ${pass}: ${c} violation(s)${delta} ${result.passed ? "PASS" : "FAIL"} ${JSON.stringify(result.summary.byAxis)}`;
52
+ }
53
+ /**
54
+ * sc#189 — warm-browser HMR re-eye loop. Captures the reference (static mock)
55
+ * ONCE per cell, keeps a warm candidate page per cell, and re-captures ONLY the
56
+ * candidate each pass (a `reload()` picks up HMR edits with no rebuild). Prints
57
+ * the per-axis violation delta each pass; with `untilConverged`, exits as soon
58
+ * as the gate passes. Bounded by `maxPasses`. The warm browser + reference-once
59
+ * capture is the win over re-running one-shot `eye` per iteration.
60
+ */
61
+ export async function runEyeWatch(opts) {
62
+ const log = opts.log ?? ((m) => console.log(m));
63
+ mkdirSync(opts.outDir, { recursive: true });
64
+ const browser = await chromium.launch();
65
+ const cells = [];
66
+ try {
67
+ const newCell = async (url, ctx) => {
68
+ const c = await browser.newContext({
69
+ colorScheme: ctx.scheme,
70
+ viewport: { width: ctx.width, height: ctx.height },
71
+ deviceScaleFactor: 2,
72
+ });
73
+ const p = await c.newPage();
74
+ await p.goto(url, { waitUntil: "networkidle" });
75
+ await p.waitForTimeout(400);
76
+ return { c, p };
77
+ };
78
+ for (const ctx of opts.matrix) {
79
+ const ref = await newCell(opts.referenceUrl, ctx);
80
+ const reference = await captureSnapshot(ref.p, { viewport: ctx.viewport, scheme: ctx.scheme });
81
+ await ref.c.close(); // reference is static — capture once, release it
82
+ const cand = await newCell(opts.candidateUrl, ctx);
83
+ cells.push({ ctx, reference, page: cand.p, close: () => cand.c.close() });
84
+ }
85
+ let prevTotal = null;
86
+ let result;
87
+ let converged = false;
88
+ let pass = 1;
89
+ for (; pass <= opts.maxPasses; pass++) {
90
+ const pairs = [];
91
+ for (const cell of cells) {
92
+ await cell.page.reload({ waitUntil: "networkidle" });
93
+ await cell.page.waitForTimeout(300);
94
+ const candidate = await captureSnapshot(cell.page, { viewport: cell.ctx.viewport, scheme: cell.ctx.scheme });
95
+ pairs.push({ reference: cell.reference, candidate });
96
+ }
97
+ result = gradeFidelity(pairs, opts.gate);
98
+ log(formatPassLine(pass, prevTotal, result));
99
+ prevTotal = result.violations.length;
100
+ if (opts.untilConverged && result.passed) {
101
+ converged = true;
102
+ log("converged ✓");
103
+ break;
104
+ }
105
+ if (pass < opts.maxPasses)
106
+ await new Promise((r) => setTimeout(r, opts.intervalMs));
107
+ }
108
+ return { result, passes: Math.min(pass, opts.maxPasses), converged };
109
+ }
110
+ finally {
111
+ for (const cell of cells)
112
+ await cell.close().catch(() => { });
113
+ await browser.close();
114
+ }
115
+ }
47
116
  //# sourceMappingURL=run.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/eye/run.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EACL,eAAe,EACf,aAAa,GAId,MAAM,oBAAoB,CAAC;AAmB5B,sFAAsF;AACtF,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAmB;IACpD,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5D,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,CAAC;IACxC,MAAM,WAAW,GAAa,EAAE,CAAC;IAEjC,MAAM,UAAU,GAAG,KAAK,EAAE,GAAW,EAAE,KAAa,EAAE,GAAe,EAA0B,EAAE;QAC/F,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC;YACjC,WAAW,EAAE,GAAG,CAAC,MAAM;YACvB,QAAQ,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE;YAClD,iBAAiB,EAAE,CAAC;SACrB,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC;QAC/B,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,CAAC;QACnD,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,kCAAkC;QAClE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,GAAG,KAAK,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC;QACtF,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvB,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACzF,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,KAAK,GAA6D,EAAE,CAAC;IAC3E,IAAI,CAAC;QACH,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAC9B,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;YACxE,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;YACxE,KAAK,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,CAAC;AAClE,CAAC"}
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/eye/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function greenfield(argv: string[], _cliVersion: string): Promise<void>;
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/greenfield/index.ts"],"names":[],"mappings":"AAoCA,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmDnF"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * GUCDI — `slowcook greenfield status`. The scope-completeness dashboard: where
3
+ * the project is in PRD → stories → brand → LCR → trace, and the single next
4
+ * action. Makes the step-by-step greenfield flow navigable (the individual
5
+ * agents — menu/brand/vibe/eye/trace — already exist).
6
+ *
7
+ * slowcook greenfield status [--prd <path>] [--cwd <dir>]
8
+ *
9
+ * Pure planner in ./status.ts; this is the IO shell.
10
+ */
11
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
12
+ import { join, relative, resolve } from "node:path";
13
+ import { listActiveSpecs } from "../refine/spec-yaml.js";
14
+ import { loadMockShapeConfig } from "../../lib/mock-shape.js";
15
+ import { parsePrdInitiatives } from "../menu/prd.js";
16
+ import { checkTrace, parseLcrProvenance } from "../trace/check.js";
17
+ import { computeGreenfieldStatus } from "./status.js";
18
+ function val(args, flag) {
19
+ const i = args.indexOf(flag);
20
+ return i >= 0 ? args[i + 1] : undefined;
21
+ }
22
+ function walkTsx(dir, exclude) {
23
+ if (!existsSync(dir))
24
+ return [];
25
+ const out = [];
26
+ for (const name of readdirSync(dir)) {
27
+ const p = join(dir, name);
28
+ if (exclude.has(p) || name === "node_modules")
29
+ continue;
30
+ const st = statSync(p);
31
+ if (st.isDirectory())
32
+ out.push(...walkTsx(p, exclude));
33
+ else if (name.endsWith(".tsx"))
34
+ out.push(p);
35
+ }
36
+ return out;
37
+ }
38
+ export async function greenfield(argv, _cliVersion) {
39
+ if (argv[0] !== "status") {
40
+ console.error("usage: slowcook greenfield status [--prd <path>] [--cwd <dir>]");
41
+ process.exit(64);
42
+ }
43
+ const rest = argv.slice(1);
44
+ const cwd = resolve(val(rest, "--cwd") ?? ".");
45
+ const specs = listActiveSpecs(cwd);
46
+ const prdRel = val(rest, "--prd") ?? "docs/PRD.md";
47
+ const prdAbs = resolve(cwd, prdRel);
48
+ const prdInitiatives = existsSync(prdAbs) ? parsePrdInitiatives(readFileSync(prdAbs, "utf8")) : [];
49
+ const mock = loadMockShapeConfig(cwd);
50
+ const designDir = resolve(cwd, mock.design_system_dir);
51
+ const lcrRoots = [resolve(cwd, mock.screens_root), resolve(cwd, mock.mock_root, "src/components")];
52
+ const files = [...new Set(lcrRoots.flatMap((r) => walkTsx(r, new Set([designDir]))))];
53
+ const lcrNodes = files.map((f) => ({
54
+ file: relative(cwd, f).replace(/\\/g, "/"),
55
+ provenance: parseLcrProvenance(readFileSync(f, "utf8")),
56
+ }));
57
+ const referenced = new Set(lcrNodes.flatMap((n) => n.provenance.filter((p) => p.kind === "story").map((p) => p.id)));
58
+ const brandPresent = existsSync(resolve(cwd, mock.design_system_dir, "tokens.ts"));
59
+ const specNodes = specs.map((s) => ({ storyId: s.story_id, prdAnchor: s.prd_ref?.anchor, sourceIssue: s.source_issue }));
60
+ const traceViolations = checkTrace({ specs: specNodes, prdAnchors: prdInitiatives.map((i) => i.anchor), lcrNodes }).violations.length;
61
+ const specFacts = specs.map((s) => ({
62
+ storyId: s.story_id,
63
+ anchored: Boolean(s.prd_ref?.anchor || s.source_issue),
64
+ addressableQuestions: s.open_questions?.addressable?.length ?? 0,
65
+ hasLcr: referenced.has(`story-${s.story_id}`),
66
+ }));
67
+ const status = computeGreenfieldStatus({
68
+ prdInitiatives: prdInitiatives.length,
69
+ specs: specFacts,
70
+ brandPresent,
71
+ traceViolations,
72
+ });
73
+ console.log("slowcook greenfield — scope status\n");
74
+ for (const st of status.stages) {
75
+ console.log(` ${st.done ? "✓" : "·"} ${st.name.padEnd(18)} ${st.detail}`);
76
+ }
77
+ console.log(`\n scope-complete: ${status.scopeComplete ? "YES ✓" : "not yet"}`);
78
+ console.log(` next: ${status.nextAction}`);
79
+ }
80
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/greenfield/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * GUCDI — `greenfield status` core (pure). Computes where a greenfield project
3
+ * is in the PRD → stories → brand → LCR → trace pipeline, and the next action.
4
+ * It is also the **scope-completeness signal**: a scope is "complete" when every
5
+ * addressable question is answered, the trace is green, every story is in the
6
+ * LCR, and the brand is set — only then does the backend phase begin.
7
+ *
8
+ * Pure + unit-tested; the IO (reading PRD/specs/brand/LCR) is in ./index.ts.
9
+ * See docs/plans/gucdi-greenfield.md.
10
+ */
11
+ export interface GreenfieldSpecFact {
12
+ storyId: string;
13
+ /** Has requirement provenance (prd_ref anchor or source_issue). */
14
+ anchored: boolean;
15
+ /** Count of unresolved *addressable* open questions (block scope-complete). */
16
+ addressableQuestions: number;
17
+ /** A mock LCR component references this story (it's been vibed). */
18
+ hasLcr: boolean;
19
+ }
20
+ export interface GreenfieldInput {
21
+ prdInitiatives: number;
22
+ specs: GreenfieldSpecFact[];
23
+ brandPresent: boolean;
24
+ traceViolations: number;
25
+ }
26
+ export interface GreenfieldStage {
27
+ name: string;
28
+ done: boolean;
29
+ detail: string;
30
+ }
31
+ export interface GreenfieldStatus {
32
+ stages: GreenfieldStage[];
33
+ scopeComplete: boolean;
34
+ /** The single next action to advance the pipeline (or the backend handoff). */
35
+ nextAction: string;
36
+ }
37
+ export declare function computeGreenfieldStatus(input: GreenfieldInput): GreenfieldStatus;
38
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/commands/greenfield/status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,QAAQ,EAAE,OAAO,CAAC;IAClB,+EAA+E;IAC/E,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oEAAoE;IACpE,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,+EAA+E;IAC/E,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,eAAe,GAAG,gBAAgB,CAqChF"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * GUCDI — `greenfield status` core (pure). Computes where a greenfield project
3
+ * is in the PRD → stories → brand → LCR → trace pipeline, and the next action.
4
+ * It is also the **scope-completeness signal**: a scope is "complete" when every
5
+ * addressable question is answered, the trace is green, every story is in the
6
+ * LCR, and the brand is set — only then does the backend phase begin.
7
+ *
8
+ * Pure + unit-tested; the IO (reading PRD/specs/brand/LCR) is in ./index.ts.
9
+ * See docs/plans/gucdi-greenfield.md.
10
+ */
11
+ export function computeGreenfieldStatus(input) {
12
+ const { prdInitiatives, specs, brandPresent, traceViolations } = input;
13
+ const anchored = specs.filter((s) => s.anchored).length;
14
+ const vibed = specs.filter((s) => s.hasLcr).length;
15
+ const addressable = specs.reduce((n, s) => n + s.addressableQuestions, 0);
16
+ const prdDone = prdInitiatives > 0;
17
+ const storiesDone = specs.length > 0 && anchored === specs.length;
18
+ const brandDone = brandPresent;
19
+ const lcrDone = specs.length > 0 && vibed === specs.length;
20
+ const traceDone = traceViolations === 0;
21
+ const questionsDone = addressable === 0;
22
+ const stages = [
23
+ { name: "PRD", done: prdDone, detail: `${prdInitiatives} initiative(s)` },
24
+ { name: "Stories (menu)", done: storiesDone, detail: `${specs.length} stories, ${anchored} anchored` },
25
+ { name: "Brand", done: brandDone, detail: brandPresent ? "design system present" : "no design system" },
26
+ { name: "LCR (vibe×eye)", done: lcrDone, detail: `${vibed}/${specs.length} stories vibed` },
27
+ { name: "Trace", done: traceDone, detail: traceViolations === 0 ? "provenance complete" : `${traceViolations} violation(s)` },
28
+ { name: "Open questions", done: questionsDone, detail: `${addressable} addressable unresolved` },
29
+ ];
30
+ const scopeComplete = prdDone && storiesDone && brandDone && lcrDone && traceDone && questionsDone;
31
+ let nextAction;
32
+ if (!prdDone)
33
+ nextAction = "Write the PRD (default docs/PRD.md), then run `slowcook menu`.";
34
+ else if (specs.length === 0)
35
+ nextAction = "Run `slowcook menu` to decompose the PRD into stories.";
36
+ else if (!storiesDone)
37
+ nextAction = `Fix provenance gaps: ${specs.length - anchored} story(ies) lack a PRD anchor / source_issue (see \`trace check\`).`;
38
+ else if (!brandDone)
39
+ nextAction = "Run `slowcook brand` to turn the brand brief into the design system.";
40
+ else if (!lcrDone) {
41
+ const next = specs.find((s) => !s.hasLcr);
42
+ nextAction = `Vibe story-${next.storyId} into the mock, then \`slowcook eye --story ${next.storyId}\` to converge it.`;
43
+ }
44
+ else if (!traceDone)
45
+ nextAction = "Resolve `trace check` violations (orphans / dangling refs).";
46
+ else if (!questionsDone)
47
+ nextAction = `Resolve ${addressable} addressable open question(s) before the scope is complete.`;
48
+ else
49
+ nextAction = "Scope complete ✓ — ready for backend: refine → recipe → brew → chef (data-source swap from the LCR's SQLite+ORM).";
50
+ return { stages, scopeComplete, nextAction };
51
+ }
52
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/commands/greenfield/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * GUCDI — pure assembler. Turns the `menu` agent's structured story drafts into
3
+ * full `Spec` objects (sequential ids, PRD back-anchor, data contract, open
4
+ * questions), and flags any draft whose prd_anchor isn't a real PRD initiative
5
+ * (a provenance gap `trace check` would later catch). The LLM dispatch +
6
+ * `writeSpec` live in ./index.ts; this part is pure + unit-tested.
7
+ */
8
+ import type { Spec } from "@slowcook-ai/core";
9
+ import type { MenuStoryDraft } from "@slowcook-ai/llm-anthropic";
10
+ export interface AssembleOptions {
11
+ /** PRD path (relative to repo root) recorded as `prd_ref.file`. */
12
+ prdFile: string;
13
+ /** First numeric story id; subsequent stories increment. */
14
+ startId: number;
15
+ /** ISO timestamp for `created_at`. */
16
+ now: string;
17
+ /** cli version → `refined_by`. */
18
+ cliVersion: string;
19
+ /** Known PRD anchors; drafts citing an unknown one are reported as gaps. */
20
+ validAnchors?: string[];
21
+ }
22
+ export interface AssembleResult {
23
+ specs: Spec[];
24
+ /** Drafts whose `prd_anchor` isn't a known PRD initiative (provenance gap). */
25
+ unanchored: {
26
+ title: string;
27
+ prd_anchor: string;
28
+ }[];
29
+ }
30
+ export declare function assembleStories(drafts: MenuStoryDraft[], opts: AssembleOptions): AssembleResult;
31
+ //# sourceMappingURL=assemble.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assemble.d.ts","sourceRoot":"","sources":["../../../src/commands/menu/assemble.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE,MAAM,WAAW,eAAe;IAC9B,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,+EAA+E;IAC/E,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACrD;AAMD,wBAAgB,eAAe,CAAC,MAAM,EAAE,cAAc,EAAE,EAAE,IAAI,EAAE,eAAe,GAAG,cAAc,CAgC/F"}
@@ -0,0 +1,37 @@
1
+ function pad(n) {
2
+ return String(n).padStart(3, "0");
3
+ }
4
+ export function assembleStories(drafts, opts) {
5
+ const valid = opts.validAnchors ? new Set(opts.validAnchors) : null;
6
+ const unanchored = [];
7
+ const specs = drafts.map((d, i) => {
8
+ if (valid && !valid.has(d.prd_anchor)) {
9
+ unanchored.push({ title: d.title, prd_anchor: d.prd_anchor });
10
+ }
11
+ const spec = {
12
+ story_id: pad(opts.startId + i),
13
+ title: d.title,
14
+ status: "active",
15
+ created_at: opts.now,
16
+ supersedes: [],
17
+ superseded_by: null,
18
+ estimate: d.estimate,
19
+ refined_by: `slowcook-menu@${opts.cliVersion}`,
20
+ actors: d.actors,
21
+ preconditions: [],
22
+ invariants: d.invariants,
23
+ acceptance_scenarios: d.acceptance_scenarios,
24
+ non_goals: d.non_goals,
25
+ prd_ref: { file: opts.prdFile, anchor: d.prd_anchor },
26
+ data_contract: d.data_contract,
27
+ open_questions: d.open_questions,
28
+ };
29
+ if (d.ui_behavior && Object.keys(d.ui_behavior).length > 0)
30
+ spec.ui_behavior = d.ui_behavior;
31
+ if (d.fidelity_modes && d.fidelity_modes.length > 0)
32
+ spec.fidelity = { modes: d.fidelity_modes };
33
+ return spec;
34
+ });
35
+ return { specs, unanchored };
36
+ }
37
+ //# sourceMappingURL=assemble.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assemble.js","sourceRoot":"","sources":["../../../src/commands/menu/assemble.ts"],"names":[],"mappings":"AA6BA,SAAS,GAAG,CAAC,CAAS;IACpB,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAwB,EAAE,IAAqB;IAC7E,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACpE,MAAM,UAAU,GAA4C,EAAE,CAAC;IAE/D,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAQ,EAAE;QACtC,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC;YACtC,UAAU,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;QAChE,CAAC;QACD,MAAM,IAAI,GAAS;YACjB,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;YAC/B,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,MAAM,EAAE,QAAQ;YAChB,UAAU,EAAE,IAAI,CAAC,GAAG;YACpB,UAAU,EAAE,EAAE;YACd,aAAa,EAAE,IAAI;YACnB,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,UAAU,EAAE,iBAAiB,IAAI,CAAC,UAAU,EAAE;YAC9C,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,aAAa,EAAE,EAAE;YACjB,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,oBAAoB,EAAE,CAAC,CAAC,oBAAoB;YAC5C,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,UAAU,EAAE;YACrD,aAAa,EAAE,CAAC,CAAC,aAAa;YAC9B,cAAc,EAAE,CAAC,CAAC,cAAc;SACjC,CAAC;QACF,IAAI,CAAC,CAAC,WAAW,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC;QAC7F,IAAI,CAAC,CAAC,cAAc,IAAI,CAAC,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC;YAAE,IAAI,CAAC,QAAQ,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,cAAc,EAAE,CAAC;QACjG,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { type MenuStoryDraft } from "@slowcook-ai/llm-anthropic";
2
+ /** Pull the first top-level JSON object out of an agent reply (fence-tolerant). */
3
+ export declare function extractStories(text: string): MenuStoryDraft[];
4
+ export declare function menu(argv: string[], cliVersion: string): Promise<void>;
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/menu/index.ts"],"names":[],"mappings":"AAYA,OAAO,EAAgC,KAAK,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAY/F,mFAAmF;AACnF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,CAQ7D;AAED,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgF5E"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * GUCDI — `slowcook menu`. The greenfield entry point: decompose a PRD into a
3
+ * comprehensive, anchored, data-contracted story set written under `specs/`.
4
+ * Each story traces back to a PRD initiative (provenance) and carries the data
5
+ * contract the LCR's SQLite+ORM mock will bake in. The LLM dispatch is the seam
6
+ * (needs ANTHROPIC_API_KEY); the planning (./prd.ts) + assembly (./assemble.ts)
7
+ * are pure + unit-tested.
8
+ *
9
+ * slowcook menu [--prd docs/PRD.md] [--cwd .] [--model <id>] [--dry-run]
10
+ */
11
+ import { existsSync, readFileSync } from "node:fs";
12
+ import { relative, resolve } from "node:path";
13
+ import { AnthropicClient, MENU_SYSTEM } from "@slowcook-ai/llm-anthropic";
14
+ import { parsePrdInitiatives } from "./prd.js";
15
+ import { assembleStories } from "./assemble.js";
16
+ import { writeSpec, nextStoryId } from "../refine/spec-yaml.js";
17
+ const DEFAULT_MODEL = "claude-sonnet-4-6";
18
+ function val(args, flag) {
19
+ const i = args.indexOf(flag);
20
+ return i >= 0 ? args[i + 1] : undefined;
21
+ }
22
+ /** Pull the first top-level JSON object out of an agent reply (fence-tolerant). */
23
+ export function extractStories(text) {
24
+ const fenced = /```(?:json)?\s*([\s\S]*?)```/.exec(text);
25
+ const body = fenced ? fenced[1] : text;
26
+ const start = body.indexOf("{");
27
+ const end = body.lastIndexOf("}");
28
+ if (start < 0 || end <= start)
29
+ throw new Error("no JSON object found");
30
+ const parsed = JSON.parse(body.slice(start, end + 1));
31
+ return parsed.stories ?? [];
32
+ }
33
+ export async function menu(argv, cliVersion) {
34
+ if (argv[0] === "--help" || argv[0] === "-h") {
35
+ console.log("usage: slowcook menu [--prd <path>] [--cwd <dir>] [--model <id>] [--dry-run]");
36
+ return;
37
+ }
38
+ const cwd = resolve(val(argv, "--cwd") ?? ".");
39
+ const prdRel = val(argv, "--prd") ?? "docs/PRD.md";
40
+ const prdAbs = resolve(cwd, prdRel);
41
+ if (!existsSync(prdAbs)) {
42
+ console.error(`menu: PRD not found at ${prdRel} (pass --prd <path>)`);
43
+ process.exit(64);
44
+ }
45
+ const anthropicKey = process.env["ANTHROPIC_API_KEY"];
46
+ if (!anthropicKey) {
47
+ console.error("menu: ANTHROPIC_API_KEY not set");
48
+ process.exit(64);
49
+ }
50
+ const model = val(argv, "--model") ?? DEFAULT_MODEL;
51
+ const dryRun = argv.includes("--dry-run");
52
+ const prdText = readFileSync(prdAbs, "utf8");
53
+ const initiatives = parsePrdInitiatives(prdText);
54
+ if (initiatives.length === 0) {
55
+ console.error("menu: PRD has no headings — nothing to anchor stories to");
56
+ process.exit(65);
57
+ }
58
+ const prdFile = relative(cwd, prdAbs).replace(/\\/g, "/");
59
+ console.log(`menu: decomposing ${prdFile} (${initiatives.length} initiative(s)) with ${model} ...`);
60
+ const llm = new AnthropicClient(anthropicKey);
61
+ const userMsg = `PRD initiative anchors (cite exactly one per story as prd_anchor): ${initiatives.map((i) => i.anchor).join(", ")}\n\n` +
62
+ `--- PRD ---\n${prdText}`;
63
+ const resp = await llm.complete({
64
+ system: MENU_SYSTEM,
65
+ messages: [{ role: "user", content: userMsg }],
66
+ model,
67
+ maxTokens: 16384,
68
+ cacheSystem: true,
69
+ });
70
+ let drafts;
71
+ try {
72
+ drafts = extractStories(resp.text);
73
+ }
74
+ catch (e) {
75
+ console.error(`menu: could not parse agent output as JSON — ${String(e instanceof Error ? e.message : e)}`);
76
+ process.exit(70);
77
+ }
78
+ if (drafts.length === 0) {
79
+ console.error("menu: agent emitted no stories");
80
+ process.exit(70);
81
+ }
82
+ const startId = Number.parseInt(await nextStoryId(cwd), 10);
83
+ const { specs, unanchored } = assembleStories(drafts, {
84
+ prdFile,
85
+ startId,
86
+ now: new Date().toISOString(),
87
+ cliVersion,
88
+ validAnchors: initiatives.map((i) => i.anchor),
89
+ });
90
+ console.log(`menu: ${specs.length} stories drafted from ${initiatives.length} initiatives.`);
91
+ for (const u of unanchored) {
92
+ console.warn(` ⚠ provenance gap: "${u.title}" cites unknown PRD anchor '${u.prd_anchor}'`);
93
+ }
94
+ const deferred = specs.flatMap((s) => s.open_questions?.deferred ?? []);
95
+ const addressable = specs.flatMap((s) => s.open_questions?.addressable ?? []);
96
+ if (addressable.length)
97
+ console.log(` ${addressable.length} addressable open question(s) — resolve before scope-complete.`);
98
+ if (deferred.length)
99
+ console.log(` ${deferred.length} deferred question(s) — parked for a future amendment.`);
100
+ if (dryRun) {
101
+ for (const s of specs)
102
+ console.log(` [dry] story-${s.story_id} — ${s.title} (#${s.prd_ref?.anchor})`);
103
+ return;
104
+ }
105
+ for (const s of specs) {
106
+ const p = writeSpec(cwd, s);
107
+ console.log(` wrote ${p} (#${s.prd_ref?.anchor})`);
108
+ }
109
+ console.log(`menu: ${specs.length} stories under specs/. Next: brand → vibe each into the LCR.`);
110
+ }
111
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/menu/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,WAAW,EAAuB,MAAM,4BAA4B,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAEhE,MAAM,aAAa,GAAG,mBAAmB,CAAC;AAE1C,SAAS,GAAG,CAAC,IAAc,EAAE,IAAY;IACvC,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1C,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,MAAM,MAAM,GAAG,8BAA8B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzD,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACxC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,KAAK,GAAG,CAAC,IAAI,GAAG,IAAI,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,GAAG,CAAC,CAAC,CAAmC,CAAC;IACxF,OAAO,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAc,EAAE,UAAkB;IAC3D,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,8EAA8E,CAAC,CAAC;QAC5F,OAAO;IACT,CAAC;IACD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,aAAa,CAAC;IACnD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACpC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,0BAA0B,MAAM,sBAAsB,CAAC,CAAC;QACtE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;IACD,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACtD,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACjD,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;IACD,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,aAAa,CAAC;IACpD,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAE1C,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,MAAM,WAAW,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACjD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;QAC1E,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;IACD,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAE1D,OAAO,CAAC,GAAG,CAAC,qBAAqB,OAAO,KAAK,WAAW,CAAC,MAAM,wBAAwB,KAAK,MAAM,CAAC,CAAC;IACpG,MAAM,GAAG,GAAG,IAAI,eAAe,CAAC,YAAY,CAAC,CAAC;IAC9C,MAAM,OAAO,GACX,sEAAsE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM;QACvH,gBAAgB,OAAO,EAAE,CAAC;IAC5B,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC;QAC9B,MAAM,EAAE,WAAW;QACnB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;QAC9C,KAAK;QACL,SAAS,EAAE,KAAK;QAChB,WAAW,EAAE,IAAI;KAClB,CAAC,CAAC;IAEH,IAAI,MAAwB,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,gDAAgD,MAAM,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC5G,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5D,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,eAAe,CAAC,MAAM,EAAE;QACpD,OAAO;QACP,OAAO;QACP,GAAG,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC7B,UAAU;QACV,YAAY,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;KAC/C,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,SAAS,KAAK,CAAC,MAAM,yBAAyB,WAAW,CAAC,MAAM,eAAe,CAAC,CAAC;IAC7F,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,OAAO,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,KAAK,+BAA+B,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC;IAC9F,CAAC;IACD,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC;IACxE,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC;IAC9E,IAAI,WAAW,CAAC,MAAM;QAAE,OAAO,CAAC,GAAG,CAAC,KAAK,WAAW,CAAC,MAAM,gEAAgE,CAAC,CAAC;IAC7H,IAAI,QAAQ,CAAC,MAAM;QAAE,OAAO,CAAC,GAAG,CAAC,KAAK,QAAQ,CAAC,MAAM,wDAAwD,CAAC,CAAC;IAE/G,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,MAAM,CAAC,IAAI,KAAK;YAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,QAAQ,MAAM,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;QACvG,OAAO;IACT,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,SAAS,KAAK,CAAC,MAAM,8DAA8D,CAAC,CAAC;AACnG,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * GUCDI — PRD parsing (pure). The `menu` agent decomposes a PRD into a story
3
+ * set; each story anchors back to a PRD initiative. This module turns a PRD
4
+ * markdown file into the list of anchorable initiatives (heading → GitHub-style
5
+ * slug) so those anchors are stable, grep-able, and traceable by `trace check`.
6
+ *
7
+ * See docs/plans/gucdi-greenfield.md.
8
+ */
9
+ export interface PrdInitiative {
10
+ /** GitHub-style slug anchor (or an explicit `{#id}`), stable across edits. */
11
+ anchor: string;
12
+ /** Heading text (the initiative title). */
13
+ title: string;
14
+ /** Heading depth (1–6). */
15
+ level: number;
16
+ /** Prose under this heading, up to the next heading of any level. */
17
+ body: string;
18
+ }
19
+ /**
20
+ * GitHub heading-anchor slug: lowercase, spaces → hyphens, drop characters that
21
+ * aren't alphanumeric/hyphen, collapse repeats. Matches GitHub's algorithm
22
+ * closely enough for stable in-repo anchors.
23
+ */
24
+ export declare function slugify(heading: string): string;
25
+ /**
26
+ * Parse a PRD markdown string into its initiatives. Each ATX heading
27
+ * (`#`…`######`) becomes an initiative. An explicit trailing `{#custom-anchor}`
28
+ * on the heading overrides the slug. Body text is captured up to the next
29
+ * heading of any level. Lines inside fenced code blocks are ignored (so a `#`
30
+ * comment in a code sample isn't mistaken for a heading).
31
+ */
32
+ export declare function parsePrdInitiatives(md: string): PrdInitiative[];
33
+ //# sourceMappingURL=prd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prd.d.ts","sourceRoot":"","sources":["../../../src/commands/menu/prd.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,aAAa;IAC5B,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAQ/C;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,EAAE,CAqC/D"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * GUCDI — PRD parsing (pure). The `menu` agent decomposes a PRD into a story
3
+ * set; each story anchors back to a PRD initiative. This module turns a PRD
4
+ * markdown file into the list of anchorable initiatives (heading → GitHub-style
5
+ * slug) so those anchors are stable, grep-able, and traceable by `trace check`.
6
+ *
7
+ * See docs/plans/gucdi-greenfield.md.
8
+ */
9
+ /**
10
+ * GitHub heading-anchor slug: lowercase, spaces → hyphens, drop characters that
11
+ * aren't alphanumeric/hyphen, collapse repeats. Matches GitHub's algorithm
12
+ * closely enough for stable in-repo anchors.
13
+ */
14
+ export function slugify(heading) {
15
+ return heading
16
+ .trim()
17
+ .toLowerCase()
18
+ .replace(/[^\w\s-]/g, "") // drop punctuation (keeps word chars, spaces, hyphens)
19
+ .replace(/\s+/g, "-")
20
+ .replace(/-+/g, "-")
21
+ .replace(/^-|-$/g, "");
22
+ }
23
+ /**
24
+ * Parse a PRD markdown string into its initiatives. Each ATX heading
25
+ * (`#`…`######`) becomes an initiative. An explicit trailing `{#custom-anchor}`
26
+ * on the heading overrides the slug. Body text is captured up to the next
27
+ * heading of any level. Lines inside fenced code blocks are ignored (so a `#`
28
+ * comment in a code sample isn't mistaken for a heading).
29
+ */
30
+ export function parsePrdInitiatives(md) {
31
+ const lines = md.split(/\r?\n/);
32
+ const inits = [];
33
+ let current = null;
34
+ let inFence = false;
35
+ const flush = () => {
36
+ if (current) {
37
+ current.body = current.body.replace(/\n+$/, "");
38
+ inits.push(current);
39
+ }
40
+ };
41
+ for (const line of lines) {
42
+ if (/^\s*(```|~~~)/.test(line)) {
43
+ inFence = !inFence;
44
+ if (current)
45
+ current.body += line + "\n";
46
+ continue;
47
+ }
48
+ const h = !inFence ? /^(#{1,6})\s+(.+?)\s*$/.exec(line) : null;
49
+ if (h) {
50
+ flush();
51
+ const level = h[1].length;
52
+ let title = h[2];
53
+ let anchor = null;
54
+ const explicit = /\{#([\w-]+)\}\s*$/.exec(title);
55
+ if (explicit) {
56
+ anchor = explicit[1];
57
+ title = title.replace(/\s*\{#[\w-]+\}\s*$/, "").trim();
58
+ }
59
+ current = { anchor: anchor ?? slugify(title), title, level, body: "" };
60
+ }
61
+ else if (current) {
62
+ current.body += line + "\n";
63
+ }
64
+ }
65
+ flush();
66
+ return inits;
67
+ }
68
+ //# sourceMappingURL=prd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prd.js","sourceRoot":"","sources":["../../../src/commands/menu/prd.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAaH;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,OAAe;IACrC,OAAO,OAAO;SACX,IAAI,EAAE;SACN,WAAW,EAAE;SACb,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,uDAAuD;SAChF,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AAC3B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAAU;IAC5C,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAChC,MAAM,KAAK,GAAoB,EAAE,CAAC;IAClC,IAAI,OAAO,GAAyB,IAAI,CAAC;IACzC,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAChD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,OAAO,GAAG,CAAC,OAAO,CAAC;YACnB,IAAI,OAAO;gBAAE,OAAO,CAAC,IAAI,IAAI,IAAI,GAAG,IAAI,CAAC;YACzC,SAAS;QACX,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC/D,IAAI,CAAC,EAAE,CAAC;YACN,KAAK,EAAE,CAAC;YACR,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC;YAC3B,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;YAClB,IAAI,MAAM,GAAkB,IAAI,CAAC;YACjC,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACjD,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAE,CAAC;gBACtB,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YACzD,CAAC;YACD,OAAO,GAAG,EAAE,MAAM,EAAE,MAAM,IAAI,OAAO,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;QACzE,CAAC;aAAM,IAAI,OAAO,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,IAAI,IAAI,GAAG,IAAI,CAAC;QAC9B,CAAC;IACH,CAAC;IACD,KAAK,EAAE,CAAC;IACR,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/plate/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAyQH,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0W7E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/plate/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA0QH,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6W7E"}