@slowcook-ai/cli 0.4.4 → 0.4.6

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 (38) hide show
  1. package/dist/cli.js +29 -5
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/init/plan.d.ts.map +1 -1
  4. package/dist/commands/init/plan.js +7 -1
  5. package/dist/commands/init/plan.js.map +1 -1
  6. package/dist/commands/init/templates.d.ts +3 -1
  7. package/dist/commands/init/templates.d.ts.map +1 -1
  8. package/dist/commands/init/templates.js +98 -4
  9. package/dist/commands/init/templates.js.map +1 -1
  10. package/dist/commands/on-spec-merged/index.d.ts +2 -0
  11. package/dist/commands/on-spec-merged/index.d.ts.map +1 -0
  12. package/dist/commands/on-spec-merged/index.js +176 -0
  13. package/dist/commands/on-spec-merged/index.js.map +1 -0
  14. package/dist/commands/refine/agent.d.ts +1 -0
  15. package/dist/commands/refine/agent.d.ts.map +1 -1
  16. package/dist/commands/refine/agent.js +6 -3
  17. package/dist/commands/refine/agent.js.map +1 -1
  18. package/dist/commands/refine/context.d.ts +17 -0
  19. package/dist/commands/refine/context.d.ts.map +1 -0
  20. package/dist/commands/refine/context.js +69 -0
  21. package/dist/commands/refine/context.js.map +1 -0
  22. package/dist/commands/refine/prompts.d.ts +1 -1
  23. package/dist/commands/refine/prompts.d.ts.map +1 -1
  24. package/dist/commands/refine/prompts.js +7 -1
  25. package/dist/commands/refine/prompts.js.map +1 -1
  26. package/dist/commands/testgen/agent.d.ts +55 -0
  27. package/dist/commands/testgen/agent.d.ts.map +1 -0
  28. package/dist/commands/testgen/agent.js +317 -0
  29. package/dist/commands/testgen/agent.js.map +1 -0
  30. package/dist/commands/testgen/index.d.ts +2 -0
  31. package/dist/commands/testgen/index.d.ts.map +1 -0
  32. package/dist/commands/testgen/index.js +173 -0
  33. package/dist/commands/testgen/index.js.map +1 -0
  34. package/dist/commands/testgen/prompts.d.ts +12 -0
  35. package/dist/commands/testgen/prompts.d.ts.map +1 -0
  36. package/dist/commands/testgen/prompts.js +54 -0
  37. package/dist/commands/testgen/prompts.js.map +1 -0
  38. package/package.json +4 -3
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Build the "project context" block that gets injected into the refinement
3
+ * agent's system prompt. Purpose: give the agent enough grounding in the
4
+ * consumer's domain that the PM doesn't have to re-explain vocabulary /
5
+ * invariants / architectural basics on every issue.
6
+ *
7
+ * Composition (in order):
8
+ * 1. Contents of `.brewing/context.md` verbatim (consumer-authored,
9
+ * deliberately distilled — not a full PRD).
10
+ * 2. One-line summary of each active story in `specs/_index.yaml` so
11
+ * the agent can cross-reference prior decisions proactively.
12
+ *
13
+ * Both parts are optional — on a greenfield project with neither, this
14
+ * returns a short "no context provided" note instead.
15
+ */
16
+ export declare function buildProjectContext(repoRoot: string): string;
17
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/commands/refine/context.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAoB5D"}
@@ -0,0 +1,69 @@
1
+ import { readFileSync, existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import YAML from "yaml";
4
+ /**
5
+ * Build the "project context" block that gets injected into the refinement
6
+ * agent's system prompt. Purpose: give the agent enough grounding in the
7
+ * consumer's domain that the PM doesn't have to re-explain vocabulary /
8
+ * invariants / architectural basics on every issue.
9
+ *
10
+ * Composition (in order):
11
+ * 1. Contents of `.brewing/context.md` verbatim (consumer-authored,
12
+ * deliberately distilled — not a full PRD).
13
+ * 2. One-line summary of each active story in `specs/_index.yaml` so
14
+ * the agent can cross-reference prior decisions proactively.
15
+ *
16
+ * Both parts are optional — on a greenfield project with neither, this
17
+ * returns a short "no context provided" note instead.
18
+ */
19
+ export function buildProjectContext(repoRoot) {
20
+ const sections = [];
21
+ const contextMd = readContextMd(repoRoot);
22
+ if (contextMd) {
23
+ sections.push("### Project overview (from `.brewing/context.md`)\n");
24
+ sections.push(contextMd.trim());
25
+ }
26
+ else {
27
+ sections.push("### Project overview\n\n*(No `.brewing/context.md` present — consider adding one so agents don't start from zero on every issue.)*");
28
+ }
29
+ const activeSpecs = readActiveSpecsSummary(repoRoot);
30
+ if (activeSpecs.length > 0) {
31
+ sections.push("\n### Active specs (cross-reference via `related_specs` when applicable)\n");
32
+ for (const line of activeSpecs)
33
+ sections.push(line);
34
+ }
35
+ return sections.join("\n");
36
+ }
37
+ function readContextMd(repoRoot) {
38
+ const path = join(repoRoot, ".brewing", "context.md");
39
+ if (!existsSync(path))
40
+ return null;
41
+ try {
42
+ return readFileSync(path, "utf8");
43
+ }
44
+ catch {
45
+ return null;
46
+ }
47
+ }
48
+ function readActiveSpecsSummary(repoRoot) {
49
+ const path = join(repoRoot, "specs", "_index.yaml");
50
+ if (!existsSync(path))
51
+ return [];
52
+ try {
53
+ const doc = YAML.parse(readFileSync(path, "utf8"));
54
+ const stories = doc.stories ?? {};
55
+ const lines = [];
56
+ for (const [id, entry] of Object.entries(stories)) {
57
+ if (entry.status !== "active")
58
+ continue;
59
+ const src = entry.source_issue ? ` (from ${entry.source_issue})` : "";
60
+ const sum = entry.summary ? ` — ${entry.summary}` : "";
61
+ lines.push(`- **story-${id}**${src}: ${entry.title ?? "(no title)"}${sum}`);
62
+ }
63
+ return lines;
64
+ }
65
+ catch {
66
+ return [];
67
+ }
68
+ }
69
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/commands/refine/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IAClD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,MAAM,SAAS,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC1C,IAAI,SAAS,EAAE,CAAC;QACd,QAAQ,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;QACrE,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;IAClC,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,IAAI,CACX,oIAAoI,CACrI,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IACrD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,QAAQ,CAAC,IAAI,CAAC,4EAA4E,CAAC,CAAC;QAC5F,KAAK,MAAM,IAAI,IAAI,WAAW;YAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,aAAa,CAAC,QAAgB;IACrC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;IACtD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAUD,SAAS,sBAAsB,CAAC,QAAgB;IAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;IACpD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAEhD,CAAC;QACF,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;QAClC,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAClD,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ;gBAAE,SAAS;YACxC,MAAM,GAAG,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACtE,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvD,KAAK,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,KAAK,KAAK,CAAC,KAAK,IAAI,YAAY,GAAG,GAAG,EAAE,CAAC,CAAC;QAC9E,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
@@ -12,7 +12,7 @@
12
12
  */
13
13
  export declare const SPEC_CHECKLIST_MD = "\nA complete, testable spec covers ALL of these items. If any are missing or ambiguous, ask about them:\n\n1. **Actors** \u2014 who performs the action? (e.g., authenticated member, admin, anonymous visitor)\n2. **Preconditions** \u2014 what must be true before the action can happen? Auth status, state of prior data, feature flags, etc.\n3. **Invariants** \u2014 what must remain true regardless of input or timing? (e.g., \"ration never exceeds 15\", \"one vote per user per poll\")\n4. **API contract** (if applicable) \u2014 HTTP method, path, request shape, success response shape, error codes and when each fires\n5. **UI behavior** per relevant viewport \u00D7 color scheme \u2014 what the user sees and how they interact, at minimum: desktop_light, mobile_light, and mobile_dark\n6. **Acceptance scenarios** \u2014 concrete Given/When/Then examples that an engineer can turn into tests. Aim for 3-6, covering happy path AND edge cases.\n7. **Non-goals** \u2014 what is explicitly out of scope for this story? (e.g., \"editing reactions is a separate story\")\n";
14
14
  export declare const RELATIONSHIP_ANALYST_SYSTEM = "You are a careful spec analyst for the slowcook brewing harness.\n\nGiven a new GitHub issue and a list of existing specs (summaries + selected full bodies), classify the relationship. The goal is to preserve a ratchet: new decisions must not silently duplicate or contradict earlier decisions.\n\nClassify as one of:\n - \"new_or_independent\": this issue addresses a concern not covered by any active spec\n - \"overlap\": this issue substantially intersects with one or more active specs (same API, same feature, same user journey, same invariant). Could be resolved by merging, scoping to a delta, or closing as duplicate.\n - \"contradiction\": this issue proposes something incompatible with an active spec \u2014 reverses a rule, changes a decision, breaks an invariant. The caller will check for a \"change-of-mind\" label: if present, it is authorized revocation; if absent, it is a blocker.\n\nReturn STRICTLY the following JSON, no prose before or after:\n\n{\n \"kind\": \"new_or_independent\" | \"overlap\" | \"contradiction\",\n \"conflicting_ids\": [\"042\", \"007\"],\n \"reasoning\": \"one-paragraph explanation citing specific spec ids and the exact overlap/contradiction\"\n}\n\n- For \"new_or_independent\", set conflicting_ids to [].\n- For \"overlap\" and \"contradiction\", list every spec id you find, not just the strongest match.\n- \"reasoning\" should name the specs by id and cite what specifically overlaps or contradicts. Be concrete \u2014 \"story-042 defines POST /api/reactions with a 15/week ration; this issue changes the ration to 20/week\" is good.\n- If information is insufficient to classify with confidence, pick the most conservative outcome (contradiction > overlap > independent).";
15
- export declare const REFINEMENT_ANALYST_SYSTEM: (checklist: string) => string;
15
+ export declare const REFINEMENT_ANALYST_SYSTEM: (checklist: string, projectContext: string) => string;
16
16
  /** Trivial, used only as a title for the draft PR. */
17
17
  export declare function draftPrTitle(storyId: string, title: string): string;
18
18
  export declare function draftPrBody(args: {
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../src/commands/refine/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,iBAAiB,kjCAU7B,CAAC;AAEF,eAAO,MAAM,2BAA2B,wsDAoBkG,CAAC;AAE3I,eAAO,MAAM,yBAAyB,GAAI,WAAW,MAAM,WAyEwE,CAAC;AAEpI,sDAAsD;AACtD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,GAAG,MAAM,CAaT"}
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../src/commands/refine/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,iBAAiB,kjCAU7B,CAAC;AAEF,eAAO,MAAM,2BAA2B,wsDAoBkG,CAAC;AAE3I,eAAO,MAAM,yBAAyB,GAAI,WAAW,MAAM,EAAE,gBAAgB,MAAM,WA+EgD,CAAC;AAEpI,sDAAsD;AACtD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,GAAG,MAAM,CAaT"}
@@ -42,10 +42,16 @@ Return STRICTLY the following JSON, no prose before or after:
42
42
  - For "overlap" and "contradiction", list every spec id you find, not just the strongest match.
43
43
  - "reasoning" should name the specs by id and cite what specifically overlaps or contradicts. Be concrete — "story-042 defines POST /api/reactions with a 15/week ration; this issue changes the ration to 20/week" is good.
44
44
  - If information is insufficient to classify with confidence, pick the most conservative outcome (contradiction > overlap > independent).`;
45
- export const REFINEMENT_ANALYST_SYSTEM = (checklist) => `You are a rigorous product analyst for the slowcook brewing harness.
45
+ export const REFINEMENT_ANALYST_SYSTEM = (checklist, projectContext) => `You are a rigorous product analyst for the slowcook brewing harness.
46
46
 
47
47
  Your job is to help the PM turn a GitHub issue into a precise, testable spec. You operate in rounds: each round, you either (a) ask the PM clarifying questions OR (b) emit the final spec as YAML. You do not both ask AND emit in the same round.
48
48
 
49
+ ## Project context
50
+
51
+ ${projectContext}
52
+
53
+ Use this context to anchor vocabulary and invariants. Do NOT ask the PM to re-explain anything that is already covered here — reference it directly (e.g., "given story-042's ration rule, I'll assume..."). Only ask about things that are genuinely unclear or unspecified in both the issue AND the context.
54
+
49
55
  ## The spec must be complete
50
56
 
51
57
  ${checklist}
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/commands/refine/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;CAUhC,CAAC;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG;;;;;;;;;;;;;;;;;;;;0IAoB+F,CAAC;AAE3I,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,SAAiB,EAAE,EAAE,CAAC;;;;;;EAM9D,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mIAmEwH,CAAC;AAEpI,sDAAsD;AACtD,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,KAAa;IACzD,OAAO,eAAe,OAAO,MAAM,KAAK,EAAE,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAI3B;IACC,MAAM,iBAAiB,GACrB,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;QACxB,CAAC,CAAC,uDAAuD,IAAI,CAAC,UAAU;aACnE,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC;aAC1B,IAAI,CAAC,IAAI,CAAC,qEAAqE;QACpF,CAAC,CAAC,EAAE,CAAC;IACT,OAAO,sBAAsB,IAAI,CAAC,WAAW;;;EAG7C,iBAAiB;;oCAEiB,CAAC;AACrC,CAAC"}
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/commands/refine/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;CAUhC,CAAC;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG;;;;;;;;;;;;;;;;;;;;0IAoB+F,CAAC;AAE3I,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,SAAiB,EAAE,cAAsB,EAAE,EAAE,CAAC;;;;;;EAMtF,cAAc;;;;;;EAMd,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mIAmEwH,CAAC;AAEpI,sDAAsD;AACtD,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,KAAa;IACzD,OAAO,eAAe,OAAO,MAAM,KAAK,EAAE,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAI3B;IACC,MAAM,iBAAiB,GACrB,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;QACxB,CAAC,CAAC,uDAAuD,IAAI,CAAC,UAAU;aACnE,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC;aAC1B,IAAI,CAAC,IAAI,CAAC,qEAAqE;QACpF,CAAC,CAAC,EAAE,CAAC;IACT,OAAO,sBAAsB,IAAI,CAAC,WAAW;;;EAG7C,iBAAiB;;oCAEiB,CAAC;AACrC,CAAC"}
@@ -0,0 +1,55 @@
1
+ import type { ForgeAdapter } from "@slowcook-ai/core";
2
+ import type { LlmClient } from "../refine/llm.js";
3
+ export declare const LABEL_TESTS_READY = "tests-ready";
4
+ export declare const LABEL_OVERRIDE_FREEZE = "override-freeze";
5
+ export declare const TESTS_INTEGRATION_DIR = "tests/integration";
6
+ export declare const MANIFESTS_DIR = ".brewing/manifests";
7
+ export interface TestgenContext {
8
+ repoRoot: string;
9
+ forge: ForgeAdapter;
10
+ llm: LlmClient;
11
+ model: string;
12
+ cliVersion: string;
13
+ baseBranch: string;
14
+ /** When true, generate tests for every active spec that lacks them (CI path). */
15
+ all: boolean;
16
+ /** When set, generate tests for this spec ID only (ops path / re-runs). */
17
+ specId: string | null;
18
+ /** Idempotent base branch name. */
19
+ branchName: string;
20
+ /** Injectable now for tests. */
21
+ now: Date;
22
+ }
23
+ export type TestgenOutcome = {
24
+ kind: "tests-emitted";
25
+ storyIds: string[];
26
+ prUrl: string;
27
+ prNumber: number;
28
+ removedStoryIds: string[];
29
+ } | {
30
+ kind: "nothing-to-generate";
31
+ reason: string;
32
+ } | {
33
+ kind: "pr-creation-blocked";
34
+ storyIds: string[];
35
+ branchName: string;
36
+ };
37
+ /**
38
+ * Main entry: for every spec in scope, if tests don't exist yet, generate them.
39
+ * If the spec supersedes prior stories, remove the old tests + manifests for
40
+ * those stories as part of the same PR (auto-applies `override-freeze` label,
41
+ * citing the supersede chain in the PR body for auditability).
42
+ */
43
+ export declare function runTestgen(ctx: TestgenContext): Promise<TestgenOutcome>;
44
+ /**
45
+ * Parse the emitted TS file and pull out test IDs in the format
46
+ * <file> > <describe-chain> > <test-name>
47
+ * matching what `vitest list` would emit.
48
+ *
49
+ * This is a lightweight text-level extraction — we parse for `describe(` and
50
+ * `it(` invocations and their string literal arguments, tracking nesting.
51
+ * Robust against typical usage; falls back to a single synthetic entry if
52
+ * nothing recognisable is found.
53
+ */
54
+ export declare function extractTestIdsFromFile(filePath: string, source: string): string[];
55
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/commands/testgen/agent.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,YAAY,EAAQ,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAQlD,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAC/C,eAAO,MAAM,qBAAqB,oBAAoB,CAAC;AAEvD,eAAO,MAAM,qBAAqB,sBAAsB,CAAC;AACzD,eAAO,MAAM,aAAa,uBAAuB,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,YAAY,CAAC;IACpB,GAAG,EAAE,SAAS,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,GAAG,EAAE,OAAO,CAAC;IACb,2EAA2E;IAC3E,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,mCAAmC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,GAAG,EAAE,IAAI,CAAC;CACX;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,EAAE,CAAA;CAAE,GACzG;IAAE,IAAI,EAAE,qBAAqB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,qBAAqB,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5E;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAgG7E;AA2FD;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAyCjF"}
@@ -0,0 +1,317 @@
1
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, rmSync, readdirSync, } from "node:fs";
2
+ import { join, dirname } from "node:path";
3
+ import YAML from "yaml";
4
+ import { buildManifest, } from "@slowcook-ai/core";
5
+ import { readIndex, readSpec } from "../refine/spec-yaml.js";
6
+ import { TESTGEN_SYSTEM } from "./prompts.js";
7
+ export const LABEL_TESTS_READY = "tests-ready";
8
+ export const LABEL_OVERRIDE_FREEZE = "override-freeze";
9
+ export const TESTS_INTEGRATION_DIR = "tests/integration";
10
+ export const MANIFESTS_DIR = ".brewing/manifests";
11
+ /**
12
+ * Main entry: for every spec in scope, if tests don't exist yet, generate them.
13
+ * If the spec supersedes prior stories, remove the old tests + manifests for
14
+ * those stories as part of the same PR (auto-applies `override-freeze` label,
15
+ * citing the supersede chain in the PR body for auditability).
16
+ */
17
+ export async function runTestgen(ctx) {
18
+ const specs = collectTargetSpecs(ctx);
19
+ if (specs.length === 0) {
20
+ return { kind: "nothing-to-generate", reason: "no active specs without tests" };
21
+ }
22
+ // Produce per-spec artifacts in a scratch area; commit together at the end.
23
+ const generated = [];
24
+ const toRemove = [];
25
+ for (const spec of specs) {
26
+ const projectContext = buildProjectContext(ctx.repoRoot);
27
+ const fileContents = await generateTestFile(spec, ctx, projectContext);
28
+ const testPath = join(TESTS_INTEGRATION_DIR, `story-${spec.story_id}.test.ts`);
29
+ const manifestIds = extractTestIdsFromFile(testPath, fileContents);
30
+ const manifest = buildManifest({
31
+ slowcookVersion: ctx.cliVersion,
32
+ storyId: spec.story_id,
33
+ tests: manifestIds.map((id) => ({ id, file: testPath })),
34
+ suites: [{ suite: "backend", command: "npx vitest list", test_count: manifestIds.length }],
35
+ now: ctx.now,
36
+ });
37
+ generated.push({ spec, testPath, fileContents, manifest });
38
+ for (const superseded of spec.supersedes) {
39
+ toRemove.push(superseded);
40
+ }
41
+ }
42
+ // Apply to disk: write new, delete superseded
43
+ for (const g of generated) {
44
+ writeFileAt(ctx.repoRoot, g.testPath, g.fileContents);
45
+ const manifestPath = join(MANIFESTS_DIR, `story-${g.spec.story_id}.json`);
46
+ writeFileAt(ctx.repoRoot, manifestPath, JSON.stringify(g.manifest, null, 2) + "\n");
47
+ }
48
+ const actuallyRemoved = [];
49
+ for (const id of toRemove) {
50
+ const removed = removeIfExists(ctx.repoRoot, [
51
+ join(TESTS_INTEGRATION_DIR, `story-${id}.test.ts`),
52
+ join(MANIFESTS_DIR, `story-${id}.json`),
53
+ ]);
54
+ if (removed > 0)
55
+ actuallyRemoved.push(id);
56
+ }
57
+ // Git: branch, stage, commit, push
58
+ await ctx.forge.git.createBranch(ctx.branchName);
59
+ for (const g of generated) {
60
+ await ctx.forge.git.stage(g.testPath);
61
+ await ctx.forge.git.stage(join(MANIFESTS_DIR, `story-${g.spec.story_id}.json`));
62
+ }
63
+ for (const id of actuallyRemoved) {
64
+ await ctx.forge.git.stage(join(TESTS_INTEGRATION_DIR, `story-${id}.test.ts`));
65
+ await ctx.forge.git.stage(join(MANIFESTS_DIR, `story-${id}.json`));
66
+ }
67
+ const storyIds = generated.map((g) => g.spec.story_id);
68
+ await ctx.forge.git.commit(`slowcook: tests for ${storyIds.map((s) => `story-${s}`).join(", ")}` +
69
+ (actuallyRemoved.length > 0
70
+ ? `\n\nRemoves tests for superseded: ${actuallyRemoved.map((s) => `story-${s}`).join(", ")}`
71
+ : ""));
72
+ await ctx.forge.git.push(ctx.branchName);
73
+ // PR
74
+ const labels = ["slowcook-tests"];
75
+ if (actuallyRemoved.length > 0) {
76
+ labels.push(LABEL_OVERRIDE_FREEZE);
77
+ }
78
+ try {
79
+ const pr = await ctx.forge.createPullRequest({
80
+ title: `tests: ${storyIds.map((s) => `story-${s}`).join(", ")}`,
81
+ body: buildPrBody({ generated, removedStoryIds: actuallyRemoved }),
82
+ head: ctx.branchName,
83
+ base: ctx.baseBranch,
84
+ draft: true,
85
+ labels,
86
+ });
87
+ return {
88
+ kind: "tests-emitted",
89
+ storyIds,
90
+ prUrl: pr.url,
91
+ prNumber: pr.number,
92
+ removedStoryIds: actuallyRemoved,
93
+ };
94
+ }
95
+ catch (e) {
96
+ const status = e.status;
97
+ if (status === 403) {
98
+ return {
99
+ kind: "pr-creation-blocked",
100
+ storyIds,
101
+ branchName: ctx.branchName,
102
+ };
103
+ }
104
+ throw e;
105
+ }
106
+ }
107
+ function collectTargetSpecs(ctx) {
108
+ const index = readIndex(ctx.repoRoot);
109
+ const all = Object.entries(index.stories)
110
+ .filter(([, entry]) => entry.status === "active")
111
+ .map(([id]) => id);
112
+ const targetIds = ctx.specId ? [ctx.specId] : all;
113
+ const specs = [];
114
+ for (const id of targetIds) {
115
+ const testPath = join(ctx.repoRoot, TESTS_INTEGRATION_DIR, `story-${id}.test.ts`);
116
+ if (existsSync(testPath) && !ctx.specId)
117
+ continue; // skip specs already tested, unless explicit --spec
118
+ try {
119
+ specs.push(readSpec(ctx.repoRoot, id));
120
+ }
121
+ catch {
122
+ // spec file missing despite being in index — skip
123
+ }
124
+ }
125
+ return specs;
126
+ }
127
+ function buildProjectContext(repoRoot) {
128
+ const bits = [];
129
+ try {
130
+ const pkg = JSON.parse(readFileSync(join(repoRoot, "package.json"), "utf8"));
131
+ bits.push(`package.json name: ${pkg.name}`);
132
+ if (pkg.description)
133
+ bits.push(`package.json description: ${pkg.description}`);
134
+ if (pkg.scripts?.test)
135
+ bits.push(`test script: ${pkg.scripts.test}`);
136
+ }
137
+ catch {
138
+ /* ignore */
139
+ }
140
+ // Show up to 2 existing integration test files as style references
141
+ const testsDir = join(repoRoot, TESTS_INTEGRATION_DIR);
142
+ if (existsSync(testsDir)) {
143
+ const existing = readdirSync(testsDir).filter((f) => f.endsWith(".test.ts")).slice(0, 2);
144
+ for (const f of existing) {
145
+ const p = join(testsDir, f);
146
+ try {
147
+ const content = readFileSync(p, "utf8");
148
+ const excerpt = content.split("\n").slice(0, 40).join("\n");
149
+ bits.push(`\n### Style reference: ${f} (first 40 lines)\n\n\`\`\`ts\n${excerpt}\n\`\`\``);
150
+ }
151
+ catch {
152
+ /* ignore */
153
+ }
154
+ }
155
+ }
156
+ else {
157
+ bits.push("No existing integration tests — this will be the first in the repo.");
158
+ }
159
+ return bits.join("\n");
160
+ }
161
+ async function generateTestFile(spec, ctx, projectContext) {
162
+ const systemPrompt = TESTGEN_SYSTEM(projectContext);
163
+ const userMessage = `Here is the spec YAML. Generate the Vitest integration test file:\n\n\`\`\`yaml\n${YAML.stringify(spec)}\n\`\`\``;
164
+ const raw = await ctx.llm.complete({
165
+ system: systemPrompt,
166
+ cacheSystem: true,
167
+ model: ctx.model,
168
+ messages: [{ role: "user", content: userMessage }],
169
+ maxTokens: 8192,
170
+ });
171
+ return stripCodeFence(raw);
172
+ }
173
+ function stripCodeFence(raw) {
174
+ const t = raw.trim();
175
+ const fence = t.match(/^```(?:typescript|ts)?\s*\n([\s\S]*)\n```$/);
176
+ if (fence && fence[1])
177
+ return fence[1];
178
+ return t;
179
+ }
180
+ /**
181
+ * Parse the emitted TS file and pull out test IDs in the format
182
+ * <file> > <describe-chain> > <test-name>
183
+ * matching what `vitest list` would emit.
184
+ *
185
+ * This is a lightweight text-level extraction — we parse for `describe(` and
186
+ * `it(` invocations and their string literal arguments, tracking nesting.
187
+ * Robust against typical usage; falls back to a single synthetic entry if
188
+ * nothing recognisable is found.
189
+ */
190
+ export function extractTestIdsFromFile(filePath, source) {
191
+ const ids = [];
192
+ const stack = [];
193
+ // Match describe("...", OR it("...", — minimal, single-quote-or-double-quote strings only
194
+ const re = /\b(describe|it|test)\s*\(\s*(['"])((?:\\.|[^\\])*?)\2/g;
195
+ // Track blocks by matching braces simply — naive but works for well-formed
196
+ // source. We use line-by-line depth for describes because inferring block
197
+ // close on a braces level requires a full parser.
198
+ //
199
+ // Simpler heuristic: treat each `describe(...)` as pushing onto the stack,
200
+ // and assume it stays on the stack for everything until a balanced close.
201
+ // For initial impl, we approximate by scanning in order and inserting
202
+ // markers at `});` following each opening. For the shape Vitest produces,
203
+ // this works in practice.
204
+ //
205
+ // To keep this minimal, use a pre-pass to find describe block ranges by
206
+ // brace balancing, then walk the match list in order.
207
+ const blocks = findDescribeBlocks(source);
208
+ let m;
209
+ while ((m = re.exec(source)) !== null) {
210
+ const kind = m[1];
211
+ const name = m[3] ?? "";
212
+ const idx = m.index;
213
+ const describesHere = blocks
214
+ .filter((b) => b.start <= idx && idx <= b.end)
215
+ .map((b) => b.name);
216
+ if (kind === "describe") {
217
+ // describe itself contributes its name to the stack; skip adding it as a test id
218
+ continue;
219
+ }
220
+ // it / test → build id
221
+ const parts = [filePath, ...describesHere, name];
222
+ ids.push(parts.join(" > "));
223
+ }
224
+ if (ids.length === 0) {
225
+ ids.push(`${filePath} > (no tests parsed — review generated file)`);
226
+ }
227
+ // Deduplicate while preserving order
228
+ return Array.from(new Set(ids));
229
+ }
230
+ function findDescribeBlocks(source) {
231
+ const blocks = [];
232
+ const describeRe = /\bdescribe\s*\(\s*(['"])((?:\\.|[^\\])*?)\1\s*,/g;
233
+ let m;
234
+ while ((m = describeRe.exec(source)) !== null) {
235
+ const name = m[2] ?? "";
236
+ // Find the opening `{` of the describe's callback body
237
+ const open = source.indexOf("{", m.index);
238
+ if (open === -1)
239
+ continue;
240
+ let depth = 1;
241
+ let i = open + 1;
242
+ while (i < source.length && depth > 0) {
243
+ const c = source[i];
244
+ if (c === "{")
245
+ depth++;
246
+ else if (c === "}")
247
+ depth--;
248
+ else if (c === "/" && source[i + 1] === "/") {
249
+ // line comment — skip to EOL
250
+ while (i < source.length && source[i] !== "\n")
251
+ i++;
252
+ }
253
+ else if (c === "/" && source[i + 1] === "*") {
254
+ // block comment
255
+ i += 2;
256
+ while (i < source.length - 1 && !(source[i] === "*" && source[i + 1] === "/"))
257
+ i++;
258
+ i += 2;
259
+ continue;
260
+ }
261
+ else if (c === '"' || c === "'" || c === "`") {
262
+ // skip string literal
263
+ const quote = c;
264
+ i++;
265
+ while (i < source.length && source[i] !== quote) {
266
+ if (source[i] === "\\")
267
+ i++;
268
+ i++;
269
+ }
270
+ }
271
+ i++;
272
+ }
273
+ blocks.push({ name, start: m.index, end: i });
274
+ }
275
+ return blocks;
276
+ }
277
+ function writeFileAt(repoRoot, rel, content) {
278
+ const full = join(repoRoot, rel);
279
+ mkdirSync(dirname(full), { recursive: true });
280
+ writeFileSync(full, content, "utf8");
281
+ }
282
+ function removeIfExists(repoRoot, rels) {
283
+ let count = 0;
284
+ for (const rel of rels) {
285
+ const full = join(repoRoot, rel);
286
+ if (existsSync(full)) {
287
+ rmSync(full);
288
+ count++;
289
+ }
290
+ }
291
+ return count;
292
+ }
293
+ function buildPrBody(args) {
294
+ const sections = [];
295
+ sections.push(`Generated Vitest integration tests for ${args.generated.length} spec(s), written by the slowcook testgen agent.`);
296
+ sections.push("");
297
+ sections.push("## Tests added");
298
+ for (const g of args.generated) {
299
+ const manifestCount = g.manifest.tests.length;
300
+ sections.push(`- \`story-${g.spec.story_id}\` — *${g.spec.title}* — ${manifestCount} test(s) in \`${g.testPath}\``);
301
+ }
302
+ if (args.removedStoryIds.length > 0) {
303
+ sections.push("");
304
+ sections.push("## Tests removed (supersede chain)");
305
+ sections.push(`The following stories are superseded by specs in this PR; their frozen tests were removed as part of the same change:`);
306
+ for (const id of args.removedStoryIds) {
307
+ sections.push(`- \`story-${id}\``);
308
+ }
309
+ sections.push("");
310
+ sections.push(`Because this PR modifies frozen paths (removing old tests + manifests), the \`override-freeze\` label is applied automatically. Reviewer can audit the supersede chain via the \`supersedes\` field on each new spec.`);
311
+ }
312
+ sections.push("");
313
+ sections.push("---");
314
+ sections.push("*Generated by `slowcook testgen`.*");
315
+ return sections.join("\n");
316
+ }
317
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../../src/commands/testgen/agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function testgen(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/testgen/index.ts"],"names":[],"mappings":"AA6GA,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkF/E"}