@slowcook-ai/cli 0.19.5 → 0.20.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 (99) hide show
  1. package/README.md +192 -28
  2. package/dist/cli.js +65 -73
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/brew/fidelity-loop.d.ts +71 -0
  5. package/dist/commands/brew/fidelity-loop.d.ts.map +1 -0
  6. package/dist/commands/brew/fidelity-loop.js +108 -0
  7. package/dist/commands/brew/fidelity-loop.js.map +1 -0
  8. package/dist/commands/brew/fidelity-phase.d.ts +49 -0
  9. package/dist/commands/brew/fidelity-phase.d.ts.map +1 -0
  10. package/dist/commands/brew/fidelity-phase.js +75 -0
  11. package/dist/commands/brew/fidelity-phase.js.map +1 -0
  12. package/dist/commands/eye/index.d.ts +2 -0
  13. package/dist/commands/eye/index.d.ts.map +1 -0
  14. package/dist/commands/eye/index.js +64 -0
  15. package/dist/commands/eye/index.js.map +1 -0
  16. package/dist/commands/eye/plan.d.ts +61 -0
  17. package/dist/commands/eye/plan.d.ts.map +1 -0
  18. package/dist/commands/eye/plan.js +81 -0
  19. package/dist/commands/eye/plan.js.map +1 -0
  20. package/dist/commands/eye/run.d.ts +19 -0
  21. package/dist/commands/eye/run.d.ts.map +1 -0
  22. package/dist/commands/eye/run.js +47 -0
  23. package/dist/commands/eye/run.js.map +1 -0
  24. package/dist/commands/eye/spec-modes.d.ts +5 -0
  25. package/dist/commands/eye/spec-modes.d.ts.map +1 -0
  26. package/dist/commands/eye/spec-modes.js +36 -0
  27. package/dist/commands/eye/spec-modes.js.map +1 -0
  28. package/dist/commands/gate/github.d.ts +27 -0
  29. package/dist/commands/gate/github.d.ts.map +1 -0
  30. package/dist/commands/gate/github.js +46 -0
  31. package/dist/commands/gate/github.js.map +1 -0
  32. package/dist/commands/gate/index.d.ts +2 -0
  33. package/dist/commands/gate/index.d.ts.map +1 -0
  34. package/dist/commands/gate/index.js +68 -0
  35. package/dist/commands/gate/index.js.map +1 -0
  36. package/dist/commands/gate/model.d.ts +55 -0
  37. package/dist/commands/gate/model.d.ts.map +1 -0
  38. package/dist/commands/gate/model.js +64 -0
  39. package/dist/commands/gate/model.js.map +1 -0
  40. package/dist/commands/gate/reviewers.d.ts +24 -0
  41. package/dist/commands/gate/reviewers.d.ts.map +1 -0
  42. package/dist/commands/gate/reviewers.js +69 -0
  43. package/dist/commands/gate/reviewers.js.map +1 -0
  44. package/dist/commands/recon/shape-preserve.d.ts +38 -0
  45. package/dist/commands/recon/shape-preserve.d.ts.map +1 -1
  46. package/dist/commands/recon/shape-preserve.js +112 -1
  47. package/dist/commands/recon/shape-preserve.js.map +1 -1
  48. package/dist/commands/refine/spec-yaml.d.ts +3 -0
  49. package/dist/commands/refine/spec-yaml.d.ts.map +1 -1
  50. package/dist/commands/refine/spec-yaml.js +4 -0
  51. package/dist/commands/refine/spec-yaml.js.map +1 -1
  52. package/dist/commands/serve/config.d.ts +159 -0
  53. package/dist/commands/serve/config.d.ts.map +1 -0
  54. package/dist/commands/serve/config.js +216 -0
  55. package/dist/commands/serve/config.js.map +1 -0
  56. package/dist/commands/serve/detect.d.ts +31 -0
  57. package/dist/commands/serve/detect.d.ts.map +1 -0
  58. package/dist/commands/serve/detect.js +56 -0
  59. package/dist/commands/serve/detect.js.map +1 -0
  60. package/dist/commands/serve/dev.d.ts +46 -0
  61. package/dist/commands/serve/dev.d.ts.map +1 -0
  62. package/dist/commands/serve/dev.js +122 -0
  63. package/dist/commands/serve/dev.js.map +1 -0
  64. package/dist/commands/serve/index.d.ts +28 -0
  65. package/dist/commands/serve/index.d.ts.map +1 -0
  66. package/dist/commands/serve/index.js +224 -0
  67. package/dist/commands/serve/index.js.map +1 -0
  68. package/dist/commands/serve/mock.d.ts +24 -0
  69. package/dist/commands/serve/mock.d.ts.map +1 -0
  70. package/dist/commands/serve/mock.js +111 -0
  71. package/dist/commands/serve/mock.js.map +1 -0
  72. package/dist/commands/serve/runner.d.ts +52 -0
  73. package/dist/commands/serve/runner.d.ts.map +1 -0
  74. package/dist/commands/serve/runner.js +53 -0
  75. package/dist/commands/serve/runner.js.map +1 -0
  76. package/dist/commands/serve/staging.d.ts +28 -0
  77. package/dist/commands/serve/staging.d.ts.map +1 -0
  78. package/dist/commands/serve/staging.js +152 -0
  79. package/dist/commands/serve/staging.js.map +1 -0
  80. package/dist/commands/stories/index.d.ts +15 -0
  81. package/dist/commands/stories/index.d.ts.map +1 -0
  82. package/dist/commands/stories/index.js +280 -0
  83. package/dist/commands/stories/index.js.map +1 -0
  84. package/dist/commands/stories/status.d.ts +74 -0
  85. package/dist/commands/stories/status.d.ts.map +1 -0
  86. package/dist/commands/stories/status.js +176 -0
  87. package/dist/commands/stories/status.js.map +1 -0
  88. package/dist/commands/upsert-agent-docs.d.ts.map +1 -1
  89. package/dist/commands/upsert-agent-docs.js +12 -0
  90. package/dist/commands/upsert-agent-docs.js.map +1 -1
  91. package/dist/commands.manifest.d.ts +37 -0
  92. package/dist/commands.manifest.d.ts.map +1 -0
  93. package/dist/commands.manifest.js +301 -0
  94. package/dist/commands.manifest.js.map +1 -0
  95. package/dist/help.d.ts +43 -0
  96. package/dist/help.d.ts.map +1 -0
  97. package/dist/help.js +131 -0
  98. package/dist/help.js.map +1 -0
  99. package/package.json +8 -6
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Shell-command execution layer for `slowcook serve`.
3
+ *
4
+ * Closes sc#173 finding #1: prior to this, planners emitted command
5
+ * strings into `output[]` and exited without executing them, even when
6
+ * `profile.ssh_target` was set. Operators had to copy-paste the emitted
7
+ * command and run it themselves — the verb was documentation, not
8
+ * automation.
9
+ *
10
+ * Now planners populate `result.commands[]` with structured ShellCommand
11
+ * records; `runCommands()` wraps `remote: true` commands in
12
+ * `ssh user@host 'cd checkout_dir && <cmd>'` and executes (unless
13
+ * --dry-run, in which case the wrapped form is just printed).
14
+ *
15
+ * Local commands run via execSync in the repoRoot. Remote commands run
16
+ * via execSync of an ssh invocation. Either way: stdio inherited so the
17
+ * operator sees docker / git output in real time.
18
+ */
19
+ import { execSync } from "node:child_process";
20
+ /**
21
+ * Resolve a single ShellCommand into the wire-form string we'd actually
22
+ * pass to /bin/sh. Pure; useful for tests + the dry-run print path.
23
+ */
24
+ export function resolveCommand(cmd, profile) {
25
+ if (cmd.remote && profile.ssh_target) {
26
+ const { user, host, checkout_dir } = profile.ssh_target;
27
+ // Single-quote the remote command. Inner single quotes get escaped via
28
+ // the bash `'\''` trick so paths/cmds containing `'` survive.
29
+ const inner = cmd.cmd.replace(/'/g, `'\\''`);
30
+ return `ssh ${user}@${host} 'cd ${checkout_dir} && ${inner}'`;
31
+ }
32
+ return cmd.cmd;
33
+ }
34
+ export function runCommands(args) {
35
+ const out = [];
36
+ for (const c of args.commands) {
37
+ const wire = resolveCommand(c, args.profile);
38
+ if (c.label)
39
+ out.push(` ${c.label}:`);
40
+ out.push(` ${args.dryRun ? "would run" : "run"}: ${wire}`);
41
+ if (args.dryRun)
42
+ continue;
43
+ try {
44
+ execSync(wire, { cwd: args.repoRoot, stdio: "inherit" });
45
+ }
46
+ catch {
47
+ out.push(` ✗ command failed: ${wire}`);
48
+ return { exitCode: 1, output: out };
49
+ }
50
+ }
51
+ return { exitCode: 0, output: out };
52
+ }
53
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/commands/serve/runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAgC9C;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,GAAiB,EAAE,OAAsB;IACtE,IAAI,GAAG,CAAC,MAAM,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACrC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC;QACxD,uEAAuE;QACvE,8DAA8D;QAC9D,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC7C,OAAO,OAAO,IAAI,IAAI,IAAI,QAAQ,YAAY,OAAO,KAAK,GAAG,CAAC;IAChE,CAAC;IACD,OAAO,GAAG,CAAC,GAAG,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAqB;IAC/C,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7C,IAAI,CAAC,CAAC,KAAK;YAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;QACvC,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC,CAAC;QAC5D,IAAI,IAAI,CAAC,MAAM;YAAE,SAAS;QAC1B,IAAI,CAAC;YACH,QAAQ,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAC3D,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,CAAC,IAAI,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;YACxC,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;QACtC,CAAC;IACH,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;AACtC,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * `slowcook serve staging <verb>` — Phase 3 implementation.
3
+ *
4
+ * The staging profile runs a built-image deployment for PM walkthroughs.
5
+ *
6
+ * 0.19.7 (sc#173): same refactor as dev.ts / mock.ts — emit
7
+ * ShellCommand[] for the cli wrapper to execute via runCommands(),
8
+ * supporting ssh-wrap when `ssh_target` is set; honour `compose_files`
9
+ * multi-`-f`; pass `--build` (staging IS built-image).
10
+ *
11
+ * `reset --scenario <name>` re-runs the named scenario's seed scripts.
12
+ * Idempotency is the seed-script author's contract; slowcook bails on
13
+ * any non-zero exit. Optional `seed.guard_env` blocks accidental wipes.
14
+ */
15
+ import type { ProfileConfig, ServeConfig } from "./config.js";
16
+ import type { DevVerbResult } from "./dev.js";
17
+ export interface StagingVerbArgs {
18
+ verb: string;
19
+ branch?: string;
20
+ scenario?: string;
21
+ service?: string;
22
+ follow?: boolean;
23
+ prune?: boolean;
24
+ repoRoot: string;
25
+ dryRun?: boolean;
26
+ }
27
+ export declare function planServeStaging(args: StagingVerbArgs, _config: ServeConfig, profile: ProfileConfig): DevVerbResult;
28
+ //# sourceMappingURL=staging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staging.d.ts","sourceRoot":"","sources":["../../../src/commands/serve/staging.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9C,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,eAAe,EACrB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,aAAa,GACrB,aAAa,CAef"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * `slowcook serve staging <verb>` — Phase 3 implementation.
3
+ *
4
+ * The staging profile runs a built-image deployment for PM walkthroughs.
5
+ *
6
+ * 0.19.7 (sc#173): same refactor as dev.ts / mock.ts — emit
7
+ * ShellCommand[] for the cli wrapper to execute via runCommands(),
8
+ * supporting ssh-wrap when `ssh_target` is set; honour `compose_files`
9
+ * multi-`-f`; pass `--build` (staging IS built-image).
10
+ *
11
+ * `reset --scenario <name>` re-runs the named scenario's seed scripts.
12
+ * Idempotency is the seed-script author's contract; slowcook bails on
13
+ * any non-zero exit. Optional `seed.guard_env` blocks accidental wipes.
14
+ */
15
+ import { execSync } from "node:child_process";
16
+ import { composeFiles, shouldBuildOnUp } from "./config.js";
17
+ export function planServeStaging(args, _config, profile) {
18
+ switch (args.verb) {
19
+ case "up":
20
+ return planUp(args, profile);
21
+ case "sync":
22
+ return planSync(args, profile);
23
+ case "down":
24
+ return planDown(args, profile);
25
+ case "logs":
26
+ return planLogs(args, profile);
27
+ case "reset":
28
+ return planReset(args, profile);
29
+ default:
30
+ return { exitCode: 64, output: [`Unknown verb: ${args.verb}. See \`slowcook serve --help\`.`] };
31
+ }
32
+ }
33
+ function planUp(_args, profile) {
34
+ const output = [`[serve staging up] mode: ${profile.mode}`];
35
+ // Trade-off #3: when consumer's bringup_cmd is set, slowcook just shells it out.
36
+ if (profile.bringup_cmd) {
37
+ return {
38
+ exitCode: 0,
39
+ output,
40
+ commands: [{ cmd: profile.bringup_cmd, remote: true, label: "bring up" }],
41
+ };
42
+ }
43
+ const files = composeFiles(profile);
44
+ if (files.length === 0) {
45
+ return {
46
+ exitCode: 64,
47
+ output: ["[serve staging up] neither bringup_cmd nor compose_files / compose_overlay set; nothing to bring up."],
48
+ };
49
+ }
50
+ const fileFlags = files.map((f) => `-f ${f}`).join(" ");
51
+ const buildFlag = shouldBuildOnUp(profile) ? " --build" : "";
52
+ return {
53
+ exitCode: 0,
54
+ output,
55
+ commands: [{ cmd: `docker compose ${fileFlags} up -d${buildFlag}`, remote: true, label: "bring up" }],
56
+ };
57
+ }
58
+ function planSync(args, profile) {
59
+ const sourceBranch = profile.source_branch;
60
+ let localBranch = args.branch;
61
+ if (!localBranch && !args.dryRun) {
62
+ try {
63
+ localBranch = execSync("git rev-parse --abbrev-ref HEAD", {
64
+ cwd: args.repoRoot,
65
+ encoding: "utf8",
66
+ }).trim();
67
+ }
68
+ catch {
69
+ // handled below
70
+ }
71
+ }
72
+ else if (!localBranch && args.dryRun) {
73
+ localBranch = "<current-branch>";
74
+ }
75
+ if (!localBranch || localBranch === "HEAD") {
76
+ return {
77
+ exitCode: 64,
78
+ output: ["[serve staging sync] couldn't resolve a local branch (detached HEAD?). Pass --branch <name>."],
79
+ };
80
+ }
81
+ return {
82
+ exitCode: 0,
83
+ output: [`[serve staging sync] ${localBranch} → origin/${sourceBranch} (staging-deploy CI rebuilds)`],
84
+ commands: [{ cmd: `git push --force origin ${localBranch}:${sourceBranch}`, remote: false, label: "git push" }],
85
+ };
86
+ }
87
+ function planDown(args, profile) {
88
+ const files = composeFiles(profile);
89
+ if (files.length === 0) {
90
+ return { exitCode: 64, output: ["[serve staging down] no compose_files / compose_overlay set; nothing to stop."] };
91
+ }
92
+ const fileFlags = files.map((f) => `-f ${f}`).join(" ");
93
+ const cmd = args.prune
94
+ ? `docker compose ${fileFlags} down -v`
95
+ : `docker compose ${fileFlags} down`;
96
+ return { exitCode: 0, output: ["[serve staging down]"], commands: [{ cmd, remote: true, label: "compose down" }] };
97
+ }
98
+ function planLogs(args, profile) {
99
+ const files = composeFiles(profile);
100
+ if (files.length === 0) {
101
+ return { exitCode: 64, output: ["[serve staging logs] no compose_files / compose_overlay set; nothing to tail."] };
102
+ }
103
+ const fileFlags = files.map((f) => `-f ${f}`).join(" ");
104
+ const follow = args.follow ? "-f" : "";
105
+ const service = args.service ?? "";
106
+ const cmd = `docker compose ${fileFlags} logs ${follow} ${service}`.replace(/\s+/g, " ").trim();
107
+ return { exitCode: 0, output: ["[serve staging logs]"], commands: [{ cmd, remote: true, label: "compose logs" }] };
108
+ }
109
+ function planReset(args, profile) {
110
+ if (!args.scenario) {
111
+ const available = profile.seed?.scenarios ? Object.keys(profile.seed.scenarios) : [];
112
+ return {
113
+ exitCode: 64,
114
+ output: [
115
+ "[serve staging reset] --scenario <name> required.",
116
+ ` available scenarios: ${available.length ? available.join(", ") : "(none — declare seed.scenarios in serve.yaml)"}`,
117
+ ],
118
+ };
119
+ }
120
+ const scenario = profile.seed?.scenarios[args.scenario];
121
+ if (!scenario) {
122
+ const available = profile.seed?.scenarios ? Object.keys(profile.seed.scenarios) : [];
123
+ return {
124
+ exitCode: 64,
125
+ output: [
126
+ `[serve staging reset] scenario "${args.scenario}" not found in seed.scenarios.`,
127
+ ` available: ${available.length ? available.join(", ") : "(none)"}`,
128
+ ],
129
+ };
130
+ }
131
+ if (profile.seed?.guard_env) {
132
+ const guard = profile.seed.guard_env;
133
+ const value = process.env[guard];
134
+ if (!value) {
135
+ return {
136
+ exitCode: 1,
137
+ output: [
138
+ `[serve staging reset] blocked — guard env \`${guard}\` is not set.`,
139
+ ` set ${guard}=1 in this shell to authorise a reset.`,
140
+ ],
141
+ };
142
+ }
143
+ }
144
+ const output = [`[serve staging reset] scenario=${args.scenario}`];
145
+ const commands = scenario.scripts.map((script) => ({
146
+ cmd: `pnpm exec ts-node ${script}`,
147
+ remote: true,
148
+ label: `seed ${script}`,
149
+ }));
150
+ return { exitCode: 0, output, commands };
151
+ }
152
+ //# sourceMappingURL=staging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staging.js","sourceRoot":"","sources":["../../../src/commands/serve/staging.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * `slowcook stories <subcommand>` — 0.19.5-α (sc#146 #6).
3
+ *
4
+ * Subcommands:
5
+ * - `status` — per-story stage table (refine / testgen / vibe / brew / chef)
6
+ *
7
+ * Future subcommands tracked in sc#146:
8
+ * - `release` — release a story-id after supersede (parked, needs design)
9
+ *
10
+ * Stage detection delegates to the pure helper in `./status.ts`. This
11
+ * file is just the IO wrapper: read `specs/_index.yaml`, query the
12
+ * forge for PRs, render.
13
+ */
14
+ export declare function stories(argv: string[]): Promise<void>;
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/stories/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAoBH,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB3D"}
@@ -0,0 +1,280 @@
1
+ /**
2
+ * `slowcook stories <subcommand>` — 0.19.5-α (sc#146 #6).
3
+ *
4
+ * Subcommands:
5
+ * - `status` — per-story stage table (refine / testgen / vibe / brew / chef)
6
+ *
7
+ * Future subcommands tracked in sc#146:
8
+ * - `release` — release a story-id after supersede (parked, needs design)
9
+ *
10
+ * Stage detection delegates to the pure helper in `./status.ts`. This
11
+ * file is just the IO wrapper: read `specs/_index.yaml`, query the
12
+ * forge for PRs, render.
13
+ */
14
+ import { execSync } from "node:child_process";
15
+ import { readIndex } from "../refine/spec-yaml.js";
16
+ import { GitHubAdapter } from "@slowcook-ai/forge-github";
17
+ import { buildStoriesStatus, renderStoriesStatusTable, } from "./status.js";
18
+ import { Octokit } from "@octokit/rest";
19
+ export async function stories(argv) {
20
+ const sub = argv[0];
21
+ switch (sub) {
22
+ case "status":
23
+ return runStatus(argv.slice(1));
24
+ case undefined:
25
+ case "help":
26
+ case "--help":
27
+ case "-h":
28
+ printHelp();
29
+ return;
30
+ default:
31
+ console.error(`Unknown stories subcommand: ${sub}`);
32
+ printHelp();
33
+ process.exit(64);
34
+ }
35
+ }
36
+ async function runStatus(argv) {
37
+ const args = parseArgs(argv);
38
+ const index = readIndex(args.repoRoot);
39
+ const stories = index.stories ?? {};
40
+ const storyIds = Object.keys(stories);
41
+ if (storyIds.length === 0) {
42
+ console.log("(no stories in specs/_index.yaml)");
43
+ return;
44
+ }
45
+ // Resolve owner/repo from git remote if not passed.
46
+ const { owner, repo } = resolveOwnerRepo(args);
47
+ let prs = [];
48
+ const token = process.env["GITHUB_TOKEN"] ?? process.env["GH_TOKEN"];
49
+ if (owner && repo && token) {
50
+ try {
51
+ prs = await fetchAllRelevantPRs({ owner, repo, token });
52
+ }
53
+ catch (e) {
54
+ console.error(`Warning: failed to fetch PRs (${e.message}). Status table will report all stages as absent.`);
55
+ prs = [];
56
+ }
57
+ }
58
+ else if (!token) {
59
+ console.error("Warning: GITHUB_TOKEN / GH_TOKEN not set. Status table will report all stages as absent.\n" +
60
+ " Set the env var to query the forge; story metadata still renders from specs/_index.yaml.");
61
+ }
62
+ const rows = buildStoriesStatus(index, prs);
63
+ if (args.format === "json") {
64
+ console.log(JSON.stringify(rows, null, 2));
65
+ return;
66
+ }
67
+ process.stdout.write(renderStoriesStatusTable(rows));
68
+ }
69
+ /**
70
+ * Fetch every PR that's relevant to the slowcook pipeline for this
71
+ * consumer. Two sources, unioned by PR number:
72
+ *
73
+ * 1. **Branch-prefix search** (`head:slowcook/`) — catches all slowcook-
74
+ * shaped branches whether or not the PR carries slowcook-* labels.
75
+ * This is the primary source — local-pipeline PRs (per
76
+ * `docs/local-pipeline-role.md`) frequently lack labels but always
77
+ * use the branch convention.
78
+ * 2. **Label scan** — catches any slowcook PRs (bot or human) that
79
+ * DID get labelled but happen to NOT live on a slowcook/ branch
80
+ * (e.g. a Bijan-cumulative branch with a slowcook-spec label).
81
+ *
82
+ * The branch search uses GitHub's search API (single endpoint, single
83
+ * page for most consumers). The label scan uses the issues endpoint
84
+ * per-label (one paginated request per label).
85
+ */
86
+ async function fetchAllRelevantPRs(args) {
87
+ const octokit = new Octokit({
88
+ auth: args.token,
89
+ userAgent: "slowcook-ai/cli",
90
+ });
91
+ const byNumber = new Map();
92
+ // 1. Branch-prefix search.
93
+ try {
94
+ const q = `is:pr repo:${args.owner}/${args.repo} head:slowcook/`;
95
+ const found = await octokit.paginate(octokit.search.issuesAndPullRequests, {
96
+ q,
97
+ per_page: 100,
98
+ });
99
+ for (const item of found) {
100
+ if (!item.pull_request)
101
+ continue;
102
+ const labels = (item.labels ?? [])
103
+ .map((l) => (typeof l === "string" ? l : l.name ?? ""))
104
+ .filter((s) => typeof s === "string" && s.length > 0);
105
+ // search API result doesn't give us head.ref or merged_at — need a
106
+ // pulls.get to fill these in. Batch via Promise.all later if perf
107
+ // becomes a concern.
108
+ let headBranch = "";
109
+ let merged = false;
110
+ try {
111
+ const { data: pr } = await octokit.pulls.get({
112
+ owner: args.owner,
113
+ repo: args.repo,
114
+ pull_number: item.number,
115
+ });
116
+ headBranch = pr.head?.ref ?? "";
117
+ merged = Boolean(pr.merged_at);
118
+ }
119
+ catch {
120
+ // Best-effort — keep title/state from the search result.
121
+ }
122
+ byNumber.set(item.number, {
123
+ number: item.number,
124
+ title: item.title,
125
+ labels,
126
+ headBranch,
127
+ state: item.state === "closed" ? "closed" : "open",
128
+ merged,
129
+ });
130
+ }
131
+ }
132
+ catch (e) {
133
+ console.error(`Warning: branch-prefix search failed (${e.message}). Continuing with label scan only.`);
134
+ }
135
+ // 2. Label scan — catches any slowcook PR that lacks a slowcook/
136
+ // branch but DID get labelled.
137
+ const labels = [
138
+ "slowcook-spec",
139
+ "slowcook-tests",
140
+ "slowcook-mockup",
141
+ "slowcook-brew",
142
+ "slowcook-chef",
143
+ ];
144
+ for (const label of labels) {
145
+ try {
146
+ const issues = await octokit.paginate(octokit.issues.listForRepo, {
147
+ owner: args.owner,
148
+ repo: args.repo,
149
+ state: "all",
150
+ labels: label,
151
+ per_page: 100,
152
+ });
153
+ for (const issue of issues) {
154
+ if (!issue.pull_request)
155
+ continue;
156
+ if (byNumber.has(issue.number)) {
157
+ // Already counted — merge labels in case we missed one.
158
+ const existing = byNumber.get(issue.number);
159
+ if (!existing.labels.includes(label))
160
+ existing.labels.push(label);
161
+ continue;
162
+ }
163
+ let headBranch = "";
164
+ let merged = false;
165
+ try {
166
+ const { data: pr } = await octokit.pulls.get({
167
+ owner: args.owner,
168
+ repo: args.repo,
169
+ pull_number: issue.number,
170
+ });
171
+ headBranch = pr.head?.ref ?? "";
172
+ merged = Boolean(pr.merged_at);
173
+ }
174
+ catch {
175
+ // Best-effort.
176
+ }
177
+ byNumber.set(issue.number, {
178
+ number: issue.number,
179
+ title: issue.title,
180
+ labels: (issue.labels ?? [])
181
+ .map((l) => (typeof l === "string" ? l : l.name ?? ""))
182
+ .filter((s) => typeof s === "string" && s.length > 0),
183
+ headBranch,
184
+ state: issue.state === "closed" ? "closed" : "open",
185
+ merged,
186
+ });
187
+ }
188
+ }
189
+ catch {
190
+ // Label may not exist on the repo (e.g. consumer never used vibe).
191
+ // Skip silently — fine to be missing some categories.
192
+ }
193
+ }
194
+ return Array.from(byNumber.values());
195
+ }
196
+ function parseArgs(argv) {
197
+ const out = {
198
+ repoRoot: process.cwd(),
199
+ owner: undefined,
200
+ repo: undefined,
201
+ format: "table",
202
+ };
203
+ for (let i = 0; i < argv.length; i++) {
204
+ const a = argv[i];
205
+ const next = argv[i + 1];
206
+ if (a === "--cwd" && next) {
207
+ out.repoRoot = next;
208
+ i++;
209
+ }
210
+ else if (a === "--owner" && next) {
211
+ out.owner = next;
212
+ i++;
213
+ }
214
+ else if (a === "--repo" && next) {
215
+ out.repo = next;
216
+ i++;
217
+ }
218
+ else if (a === "--json") {
219
+ out.format = "json";
220
+ }
221
+ else if (a === "--help" || a === "-h") {
222
+ printHelp();
223
+ process.exit(0);
224
+ }
225
+ }
226
+ return out;
227
+ }
228
+ function resolveOwnerRepo(args) {
229
+ if (args.owner && args.repo)
230
+ return { owner: args.owner, repo: args.repo };
231
+ // Detect from git remote.
232
+ try {
233
+ const url = execSync("git remote get-url origin", {
234
+ cwd: args.repoRoot,
235
+ encoding: "utf8",
236
+ stdio: ["ignore", "pipe", "ignore"],
237
+ }).trim();
238
+ const m = url.match(/github\.com[:/]([^/]+)\/([^/.]+)(?:\.git)?$/);
239
+ if (m) {
240
+ return { owner: args.owner ?? m[1], repo: args.repo ?? m[2] };
241
+ }
242
+ }
243
+ catch {
244
+ // not a git repo, or no origin — fine
245
+ }
246
+ return { owner: args.owner, repo: args.repo };
247
+ }
248
+ // Silence the unused-import warning when stories status doesn't need
249
+ // the adapter directly. Keep the import handy for future subcommands
250
+ // (e.g. `stories close --pr N` could use addIssueLabels).
251
+ void GitHubAdapter;
252
+ function printHelp() {
253
+ console.log(`
254
+ slowcook stories — per-story status across the slowcook pipeline (0.19.5-α)
255
+
256
+ Usage:
257
+ slowcook stories status [--cwd <path>] [--owner <login>] [--repo <name>] [--json]
258
+
259
+ Subcommands:
260
+ status Render a table of story id × pipeline stage (refine / testgen
261
+ / vibe / brew / chef). Reads specs/_index.yaml + queries the
262
+ forge for PRs labelled with the slowcook-* stage labels.
263
+
264
+ Cell semantics:
265
+ ✓ — merged PR exists for this stage
266
+ → — open PR exists for this stage
267
+ ✗ — PR was opened but closed unmerged
268
+ — — no PR found for this stage
269
+
270
+ With --json, emits the same data as machine-readable JSON.
271
+
272
+ Environment:
273
+ GITHUB_TOKEN | GH_TOKEN Required to query the forge. Without it,
274
+ the table renders from specs/_index.yaml
275
+ only and reports all stages as absent.
276
+
277
+ Refs: aminazar/slowcook#146 finding 6.
278
+ `);
279
+ }
280
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/stories/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * `slowcook stories status` pure helper — 0.19.5-α (sc#146 #6).
3
+ *
4
+ * Cross-references the consumer's `specs/_index.yaml` against PR/label
5
+ * facts to produce a per-story stage table. Pure function — no fs, no
6
+ * network. The CLI wrapper (`./index.ts`) gathers the inputs.
7
+ *
8
+ * Stage mapping (per slowcook conventions):
9
+ *
10
+ * | Stage | Slowcook label evidence |
11
+ * |---------|-------------------------------|
12
+ * | refine | a `slowcook-spec` PR exists |
13
+ * | testgen | a `slowcook-tests` PR exists |
14
+ * | vibe | a `slowcook-mockup` PR exists |
15
+ * | brew | a `slowcook-brew` PR exists |
16
+ * | chef | a `slowcook-chef` PR exists |
17
+ *
18
+ * Per-stage cell semantics:
19
+ *
20
+ * - `✓` — a PR with the matching label exists AND is merged
21
+ * - `→` — a PR with the matching label exists AND is open
22
+ * - `✗` — a PR was opened but closed unmerged
23
+ * - `—` — no PR found for this stage
24
+ *
25
+ * For consumers running the local-pipeline pattern (see
26
+ * `docs/local-pipeline-role.md`), the slowcook labels may not be
27
+ * applied to human-driven PRs. In that case the helper falls back
28
+ * to matching by PR-branch-name (`slowcook/<kind>/story-N` →
29
+ * stage=<kind>).
30
+ *
31
+ * Gantt-style stage-by-stage output is parked for a follow-up
32
+ * (sc#146 #6 acceptance: "Defer the Gantt-style output to a follow-up.
33
+ * Just ship the underlying table first.").
34
+ */
35
+ import type { SpecIndex, SpecIndexEntry } from "@slowcook-ai/core";
36
+ export type StoriesStatusCell = "merged" | "open" | "closed_unmerged" | "absent";
37
+ export interface StoriesStatusRow {
38
+ storyId: string;
39
+ title: string;
40
+ status: SpecIndexEntry["status"];
41
+ sourceIssue: string | undefined;
42
+ /** Per-stage status. Stages: refine / testgen / vibe / brew / chef. */
43
+ stages: Record<"refine" | "testgen" | "vibe" | "brew" | "chef", StoriesStatusCell>;
44
+ }
45
+ export interface PullRequestFact {
46
+ number: number;
47
+ title: string;
48
+ /** Source-of-truth labels on the PR. */
49
+ labels: string[];
50
+ /** Branch name; used as the fallback signal when labels are absent. */
51
+ headBranch: string;
52
+ /** "open" | "closed". */
53
+ state: "open" | "closed";
54
+ /** True iff the PR is closed AND was merged. */
55
+ merged: boolean;
56
+ }
57
+ /**
58
+ * Build the status table for every story in the index.
59
+ *
60
+ * @param specIndex - the parsed `specs/_index.yaml` content
61
+ * @param pullRequests - all PRs in the repo (merged + open + closed-unmerged).
62
+ * The CLI wrapper passes the union of label-matched
63
+ * results; pass an empty array if GH access is
64
+ * unavailable + the row will report all stages as
65
+ * absent (still useful for spec-only summary).
66
+ */
67
+ export declare function buildStoriesStatus(specIndex: SpecIndex, pullRequests: PullRequestFact[]): StoriesStatusRow[];
68
+ /**
69
+ * Render a status row set as an ASCII-art table. Used by the CLI
70
+ * wrapper's stdout. Pure function — no colour codes, no terminal
71
+ * width detection.
72
+ */
73
+ export declare function renderStoriesStatusTable(rows: StoriesStatusRow[]): string;
74
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/commands/stories/status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnE,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,MAAM,GAAG,iBAAiB,GAAG,QAAQ,CAAC;AAEjF,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IACjC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,uEAAuE;IACvE,MAAM,EAAE,MAAM,CAAC,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,iBAAiB,CAAC,CAAC;CACpF;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC;IACzB,gDAAgD;IAChD,MAAM,EAAE,OAAO,CAAC;CACjB;AA2BD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,eAAe,EAAE,GAC9B,gBAAgB,EAAE,CAsBpB;AAiCD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAuDzE"}