@slowcook-ai/cli 0.25.0 → 0.28.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 (119) hide show
  1. package/dist/cli.js +16 -0
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/amend.d.ts +12 -0
  4. package/dist/commands/amend.d.ts.map +1 -0
  5. package/dist/commands/amend.js +99 -0
  6. package/dist/commands/amend.js.map +1 -0
  7. package/dist/commands/bench-browser.d.ts +2 -0
  8. package/dist/commands/bench-browser.d.ts.map +1 -0
  9. package/dist/commands/bench-browser.js +31 -0
  10. package/dist/commands/bench-browser.js.map +1 -0
  11. package/dist/commands/check/index.d.ts.map +1 -1
  12. package/dist/commands/check/index.js +13 -0
  13. package/dist/commands/check/index.js.map +1 -1
  14. package/dist/commands/check/style-drift.d.ts +18 -0
  15. package/dist/commands/check/style-drift.d.ts.map +1 -0
  16. package/dist/commands/check/style-drift.js +175 -0
  17. package/dist/commands/check/style-drift.js.map +1 -0
  18. package/dist/commands/check/surface-parity.d.ts +123 -0
  19. package/dist/commands/check/surface-parity.d.ts.map +1 -0
  20. package/dist/commands/check/surface-parity.js +328 -0
  21. package/dist/commands/check/surface-parity.js.map +1 -0
  22. package/dist/commands/chef/orchestrate.d.ts.map +1 -1
  23. package/dist/commands/chef/orchestrate.js +22 -2
  24. package/dist/commands/chef/orchestrate.js.map +1 -1
  25. package/dist/commands/extract/as-built-cli.d.ts +7 -0
  26. package/dist/commands/extract/as-built-cli.d.ts.map +1 -0
  27. package/dist/commands/extract/as-built-cli.js +67 -0
  28. package/dist/commands/extract/as-built-cli.js.map +1 -0
  29. package/dist/commands/extract/as-built.d.ts +21 -0
  30. package/dist/commands/extract/as-built.d.ts.map +1 -0
  31. package/dist/commands/extract/as-built.js +113 -0
  32. package/dist/commands/extract/as-built.js.map +1 -0
  33. package/dist/commands/extract/history-cli.d.ts +6 -0
  34. package/dist/commands/extract/history-cli.d.ts.map +1 -0
  35. package/dist/commands/extract/history-cli.js +58 -0
  36. package/dist/commands/extract/history-cli.js.map +1 -0
  37. package/dist/commands/extract/history.d.ts +42 -0
  38. package/dist/commands/extract/history.d.ts.map +1 -0
  39. package/dist/commands/extract/history.js +114 -0
  40. package/dist/commands/extract/history.js.map +1 -0
  41. package/dist/commands/extract/index.d.ts.map +1 -1
  42. package/dist/commands/extract/index.js +63 -3
  43. package/dist/commands/extract/index.js.map +1 -1
  44. package/dist/commands/extract/survey.d.ts +17 -0
  45. package/dist/commands/extract/survey.d.ts.map +1 -0
  46. package/dist/commands/extract/survey.js +176 -0
  47. package/dist/commands/extract/survey.js.map +1 -0
  48. package/dist/commands/eye/run.d.ts.map +1 -1
  49. package/dist/commands/eye/run.js +6 -0
  50. package/dist/commands/eye/run.js.map +1 -1
  51. package/dist/commands/guard.d.ts +4 -0
  52. package/dist/commands/guard.d.ts.map +1 -1
  53. package/dist/commands/guard.js +46 -2
  54. package/dist/commands/guard.js.map +1 -1
  55. package/dist/commands/init/templates.d.ts.map +1 -1
  56. package/dist/commands/init/templates.js +5 -3
  57. package/dist/commands/init/templates.js.map +1 -1
  58. package/dist/commands/recall/brief.d.ts +15 -0
  59. package/dist/commands/recall/brief.d.ts.map +1 -0
  60. package/dist/commands/recall/brief.js +32 -0
  61. package/dist/commands/recall/brief.js.map +1 -0
  62. package/dist/commands/recall/context.d.ts +18 -0
  63. package/dist/commands/recall/context.d.ts.map +1 -0
  64. package/dist/commands/recall/context.js +19 -0
  65. package/dist/commands/recall/context.js.map +1 -0
  66. package/dist/commands/recall/ctx.d.ts +31 -0
  67. package/dist/commands/recall/ctx.d.ts.map +1 -0
  68. package/dist/commands/recall/ctx.js +77 -0
  69. package/dist/commands/recall/ctx.js.map +1 -0
  70. package/dist/commands/recall/index.d.ts +2 -0
  71. package/dist/commands/recall/index.d.ts.map +1 -0
  72. package/dist/commands/recall/index.js +73 -0
  73. package/dist/commands/recall/index.js.map +1 -0
  74. package/dist/commands/vibe/app-gen.d.ts.map +1 -1
  75. package/dist/commands/vibe/app-gen.js +5 -3
  76. package/dist/commands/vibe/app-gen.js.map +1 -1
  77. package/dist/commands/vibe/as-built.d.ts +25 -0
  78. package/dist/commands/vibe/as-built.d.ts.map +1 -0
  79. package/dist/commands/vibe/as-built.js +115 -0
  80. package/dist/commands/vibe/as-built.js.map +1 -0
  81. package/dist/commands/vibe/index.d.ts.map +1 -1
  82. package/dist/commands/vibe/index.js +49 -1
  83. package/dist/commands/vibe/index.js.map +1 -1
  84. package/dist/commands.manifest.d.ts.map +1 -1
  85. package/dist/commands.manifest.js +22 -4
  86. package/dist/commands.manifest.js.map +1 -1
  87. package/dist/lib/browser/bench-worker.d.ts +2 -0
  88. package/dist/lib/browser/bench-worker.d.ts.map +1 -0
  89. package/dist/lib/browser/bench-worker.js +71 -0
  90. package/dist/lib/browser/bench-worker.js.map +1 -0
  91. package/dist/lib/browser/bench.d.ts +26 -0
  92. package/dist/lib/browser/bench.d.ts.map +1 -0
  93. package/dist/lib/browser/bench.js +68 -0
  94. package/dist/lib/browser/bench.js.map +1 -0
  95. package/dist/lib/browser/driver.d.ts +59 -0
  96. package/dist/lib/browser/driver.d.ts.map +1 -0
  97. package/dist/lib/browser/driver.js +19 -0
  98. package/dist/lib/browser/driver.js.map +1 -0
  99. package/dist/lib/browser/index.d.ts +8 -0
  100. package/dist/lib/browser/index.d.ts.map +1 -0
  101. package/dist/lib/browser/index.js +7 -0
  102. package/dist/lib/browser/index.js.map +1 -0
  103. package/dist/lib/browser/playwright-driver.d.ts +3 -0
  104. package/dist/lib/browser/playwright-driver.d.ts.map +1 -0
  105. package/dist/lib/browser/playwright-driver.js +44 -0
  106. package/dist/lib/browser/playwright-driver.js.map +1 -0
  107. package/dist/lib/browser/qa-replay.d.ts +47 -0
  108. package/dist/lib/browser/qa-replay.d.ts.map +1 -0
  109. package/dist/lib/browser/qa-replay.js +69 -0
  110. package/dist/lib/browser/qa-replay.js.map +1 -0
  111. package/dist/lib/browser/rustwright-driver.d.ts +5 -0
  112. package/dist/lib/browser/rustwright-driver.d.ts.map +1 -0
  113. package/dist/lib/browser/rustwright-driver.js +50 -0
  114. package/dist/lib/browser/rustwright-driver.js.map +1 -0
  115. package/dist/lib/browser/select.d.ts +21 -0
  116. package/dist/lib/browser/select.d.ts.map +1 -0
  117. package/dist/lib/browser/select.js +30 -0
  118. package/dist/lib/browser/select.js.map +1 -0
  119. package/package.json +9 -6
@@ -0,0 +1,67 @@
1
+ /** CLI half of `extract --as-built` — wires the survey + dossier + LLM +
2
+ * citation validator together and owns process exit semantics. Kept apart
3
+ * from as-built.ts so the core stays pure for tests. */
4
+ import { readdirSync, statSync, writeFileSync } from "node:fs";
5
+ import { join, relative } from "node:path";
6
+ import { createLlmClient } from "../refine/llm.js";
7
+ import { buildDossier, generateAsBuilt, validateCitations, validateSections } from "./as-built.js";
8
+ export const DEFAULT_MODEL = "claude-opus-4-8";
9
+ function walk(dir, root, acc = []) {
10
+ let entries;
11
+ try {
12
+ entries = readdirSync(dir);
13
+ }
14
+ catch {
15
+ return acc;
16
+ }
17
+ for (const name of entries) {
18
+ if (name === "node_modules" || name === ".git" || name === "dist")
19
+ continue;
20
+ const full = join(dir, name);
21
+ let st;
22
+ try {
23
+ st = statSync(full);
24
+ }
25
+ catch {
26
+ continue;
27
+ }
28
+ if (st.isDirectory())
29
+ walk(full, root, acc);
30
+ else
31
+ acc.push(relative(root, full).replace(/\\/g, "/"));
32
+ }
33
+ return acc;
34
+ }
35
+ export async function runAsBuiltCli(repoRoot, survey, opts) {
36
+ let llm;
37
+ try {
38
+ llm = await createLlmClient();
39
+ }
40
+ catch (err) {
41
+ console.error(`extract --as-built: ${err instanceof Error ? err.message : String(err)}`);
42
+ process.exit(1);
43
+ }
44
+ const paths = walk(repoRoot, repoRoot);
45
+ const dossier = buildDossier(repoRoot, survey, paths);
46
+ console.log(`extract --as-built: dossier holds ${dossier.filesIncluded.length} files + survey (${survey.claims.length} claims); calling the model…`);
47
+ const { md } = await generateAsBuilt(llm, opts.model ?? DEFAULT_MODEL, dossier);
48
+ const missing = validateSections(md);
49
+ if (missing.length > 0) {
50
+ console.error(`extract --as-built: output is missing required section(s): ${missing.join(", ")} — not writing.`);
51
+ process.exit(1);
52
+ }
53
+ const cites = validateCitations(md);
54
+ if (cites.uncited.length > 0 && !opts.allowUncited) {
55
+ console.error(`extract --as-built: ${cites.uncited.length}/${cites.bullets} bullets carry NO citation — an uncited claim is a guess. Offenders:`);
56
+ for (const u of cites.uncited.slice(0, 10))
57
+ console.error(` · ${u}`);
58
+ console.error(`Re-run, or accept with --allow-uncited (the doc will keep an UNCITED marker).`);
59
+ process.exit(1);
60
+ }
61
+ const banner = `> Generated by \`slowcook extract --as-built\` from ${survey.repo_head ?? "HEAD"} on ${survey.generated_at.slice(0, 10)}. Code-as-truth, as observed; regenerate when main moves.${cites.uncited.length > 0 ? ` ⚠ ${cites.uncited.length} UNCITED bullet(s) accepted via --allow-uncited.` : ""}\n\n`;
62
+ const withBanner = md.replace(/^(# .+\n)/, `$1\n${banner}`);
63
+ const file = join(repoRoot, ".brewing", "as-built.md");
64
+ writeFileSync(file, withBanner, "utf8");
65
+ console.log(`Wrote ${file} (${cites.bullets} cited bullets, ${md.split("\n## ").length - 1} sections).`);
66
+ }
67
+ //# sourceMappingURL=as-built-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"as-built-cli.js","sourceRoot":"","sources":["../../../src/commands/extract/as-built-cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { LlmClient } from "@slowcook-ai/core";
2
+ import type { SurveyOutput } from "./survey.js";
3
+ export declare const AS_BUILT_SYSTEM = "You are slowcook's brownfield extraction agent. You produce AS-BUILT\ndocumentation of an EXISTING product from its repository: what IS, as\nobserved in the code \u2014 never what docs promise, never invented intent.\n\nRules, non-negotiable:\n- Output ONLY the markdown document, no preamble.\n- Structure EXACTLY: a single \"# <repo name> \u2014 as-built\" title line, then the\n sections \"## What the product is\", \"## Map\", \"## Data model (as-built)\",\n \"## Honesty notes\", \"## Founder questions (intake queue)\".\n- Every bullet in every section EXCEPT the questions section MUST end with a\n citation in parentheses naming the file(s) it was observed in, e.g.\n (src/lib/emotions/index.ts:1-14) or (supabase/migrations/00013.sql). No\n citation = the bullet will be rejected by a validator.\n- When repo documents CONTRADICT the code, the code is truth: state the code's\n behaviour and flag the contradiction in \"Honesty notes\" citing both sides.\n- \"Founder questions\" = numbered questions only a human can answer (unclear\n intent, missing infra facts, dead features to rule on). No citations needed.\n- Be dense and specific. 40-70 bullets total. Never pad, never speculate \u2014\n what you cannot see, you either omit or turn into a founder question.";
4
+ export interface Dossier {
5
+ userPrompt: string;
6
+ filesIncluded: string[];
7
+ }
8
+ /** assemble the model's evidence pack: survey + key files (truncated) + route inventory. */
9
+ export declare function buildDossier(repoRoot: string, survey: SurveyOutput, allPaths: string[]): Dossier;
10
+ export interface CitationReport {
11
+ bullets: number;
12
+ uncited: string[];
13
+ }
14
+ /** deterministic post-check: bullets outside the questions section need (path…) citations. */
15
+ export declare function validateCitations(md: string): CitationReport;
16
+ export declare function validateSections(md: string): string[];
17
+ export declare function generateAsBuilt(llm: LlmClient, model: string, dossier: Dossier): Promise<{
18
+ md: string;
19
+ usage: unknown;
20
+ }>;
21
+ //# sourceMappingURL=as-built.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"as-built.d.ts","sourceRoot":"","sources":["../../../src/commands/extract/as-built.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,eAAO,MAAM,eAAe,uwCAkB4C,CAAC;AAEzE,MAAM,WAAW,OAAO;IAAG,UAAU,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,EAAE,CAAA;CAAE;AAWxE,4FAA4F;AAC5F,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAsBhG;AAED,MAAM,WAAW,cAAc;IAAG,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE;AAEtE,8FAA8F;AAC9F,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc,CAmB5D;AAID,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,CAErD;AAED,wBAAsB,eAAe,CACnC,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,OAAO,GACf,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,CAWzC"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * `slowcook extract --as-built` — tier 1 of #262: the LLM pass that turns an
3
+ * existing repo into `.brewing/as-built.md`: what the product IS, as observed,
4
+ * every statement citing its source. Section contract mirrors the hand-made
5
+ * originals (dash's brownfield intake ingests these sections directly):
6
+ *
7
+ * ## What the product is
8
+ * ## Map
9
+ * ## Data model (as-built)
10
+ * ## Honesty notes (docs-vs-code lies, stubs, dead features)
11
+ * ## Founder questions (intake queue)
12
+ *
13
+ * CITATION DISCIPLINE is enforced deterministically after generation: every
14
+ * bullet outside the questions section must carry a `(path[:line…])` citation;
15
+ * violations are reported and the run fails without --allow-uncited. This is
16
+ * verify-before-spec's foundation — an uncited claim is a guess.
17
+ */
18
+ import { readFileSync } from "node:fs";
19
+ import { join } from "node:path";
20
+ export const AS_BUILT_SYSTEM = `You are slowcook's brownfield extraction agent. You produce AS-BUILT
21
+ documentation of an EXISTING product from its repository: what IS, as
22
+ observed in the code — never what docs promise, never invented intent.
23
+
24
+ Rules, non-negotiable:
25
+ - Output ONLY the markdown document, no preamble.
26
+ - Structure EXACTLY: a single "# <repo name> — as-built" title line, then the
27
+ sections "## What the product is", "## Map", "## Data model (as-built)",
28
+ "## Honesty notes", "## Founder questions (intake queue)".
29
+ - Every bullet in every section EXCEPT the questions section MUST end with a
30
+ citation in parentheses naming the file(s) it was observed in, e.g.
31
+ (src/lib/emotions/index.ts:1-14) or (supabase/migrations/00013.sql). No
32
+ citation = the bullet will be rejected by a validator.
33
+ - When repo documents CONTRADICT the code, the code is truth: state the code's
34
+ behaviour and flag the contradiction in "Honesty notes" citing both sides.
35
+ - "Founder questions" = numbered questions only a human can answer (unclear
36
+ intent, missing infra facts, dead features to rule on). No citations needed.
37
+ - Be dense and specific. 40-70 bullets total. Never pad, never speculate —
38
+ what you cannot see, you either omit or turn into a founder question.`;
39
+ const KEY_DOC = /^(readme|claude)\.md$/i;
40
+ const INTERESTING = [
41
+ /^docs\/[^/]+\.md$/i,
42
+ /^(package|pnpm-workspace|foundry|cargo|go)\.(json|yaml|toml|mod)$/i,
43
+ /migrations?\/[^/]+\.(sql|ts|js)$/i,
44
+ /schema[^/]*\.(ts|sql|prisma)$/i,
45
+ ];
46
+ const ROUTEISH = /(app|pages|routes|src\/app)\/.*\.(tsx?|jsx?|vue|svelte)$/i;
47
+ /** assemble the model's evidence pack: survey + key files (truncated) + route inventory. */
48
+ export function buildDossier(repoRoot, survey, allPaths) {
49
+ const parts = [];
50
+ const included = [];
51
+ parts.push(`# Deterministic survey (tier 0)\n${JSON.stringify({ repo_head: survey.repo_head, claims: survey.claims.map((c) => c.statement), skipped: survey.skipped }, null, 1)}`);
52
+ const read = (p, cap) => {
53
+ try {
54
+ const body = readFileSync(join(repoRoot, p), "utf8");
55
+ included.push(p);
56
+ parts.push(`\n===== FILE: ${p} =====\n${body.slice(0, cap)}${body.length > cap ? "\n…(truncated)" : ""}`);
57
+ }
58
+ catch { /* unreadable */ }
59
+ };
60
+ for (const p of allPaths)
61
+ if (KEY_DOC.test(p))
62
+ read(p, 6000);
63
+ for (const p of allPaths.filter((p) => INTERESTING.some((re) => re.test(p))).sort().slice(0, 25))
64
+ read(p, 4000);
65
+ const routes = allPaths.filter((p) => ROUTEISH.test(p) && !/test|spec|stories/.test(p)).sort().slice(0, 120);
66
+ parts.push(`\n===== ROUTE/SURFACE FILE INVENTORY (${routes.length}) =====\n${routes.join("\n")}`);
67
+ // a few route files in full — the product's actual behaviour lives here.
68
+ for (const p of routes.filter((p) => /route\.|page\.|index\./i.test(p)).slice(0, 8))
69
+ read(p, 3000);
70
+ return { userPrompt: parts.join("\n"), filesIncluded: included };
71
+ }
72
+ /** deterministic post-check: bullets outside the questions section need (path…) citations. */
73
+ export function validateCitations(md) {
74
+ const lines = md.split("\n");
75
+ let inQuestions = false;
76
+ let bullets = 0;
77
+ const uncited = [];
78
+ for (const l of lines) {
79
+ if (/^##\s/.test(l))
80
+ inQuestions = /founder questions/i.test(l);
81
+ if (inQuestions)
82
+ continue;
83
+ const t = l.trim();
84
+ if (!/^[-*]\s/.test(t))
85
+ continue;
86
+ bullets++;
87
+ // a citation is a paren group naming a path or file — allowing ONE level
88
+ // of nested parens because real paths contain them (Next.js route groups
89
+ // like src/app/(landing)/page.tsx — found by the rewo dogfood).
90
+ const groups = t.match(/\((?:[^()]|\([^()]*\))*\)/g) ?? [];
91
+ const cited = groups.some((g) => /[\w)\].-]\/[\w(.-]/.test(g) || /\.(ts|tsx|js|jsx|sql|md|mdx|ya?ml|toml|json|sol|py|go|rs|css|prisma)\b/.test(g));
92
+ if (!cited)
93
+ uncited.push(t.slice(0, 110));
94
+ }
95
+ return { bullets, uncited };
96
+ }
97
+ const REQUIRED_SECTIONS = ["## What the product is", "## Map", "## Data model (as-built)", "## Honesty notes", "## Founder questions (intake queue)"];
98
+ export function validateSections(md) {
99
+ return REQUIRED_SECTIONS.filter((s) => !md.includes(s));
100
+ }
101
+ export async function generateAsBuilt(llm, model, dossier) {
102
+ const res = await llm.complete({
103
+ system: AS_BUILT_SYSTEM,
104
+ cacheSystem: false,
105
+ model,
106
+ messages: [{ role: "user", content: dossier.userPrompt }],
107
+ maxTokens: 16000,
108
+ });
109
+ // strip accidental fences
110
+ const md = res.text.replace(/^```(?:markdown|md)?\n/, "").replace(/\n```\s*$/, "").trim() + "\n";
111
+ return { md, usage: res.usage };
112
+ }
113
+ //# sourceMappingURL=as-built.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"as-built.js","sourceRoot":"","sources":["../../../src/commands/extract/as-built.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { type HistoryExcerpt } from "./history.js";
2
+ export declare function buildHistoryPrompt(excerpts: HistoryExcerpt[]): string;
3
+ export declare function runHistoryCli(repoRoot: string, opts: {
4
+ model: string | null;
5
+ }): Promise<void>;
6
+ //# sourceMappingURL=history-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history-cli.d.ts","sourceRoot":"","sources":["../../../src/commands/extract/history-cli.ts"],"names":[],"mappings":"AASA,OAAO,EAEW,KAAK,cAAc,EACpC,MAAM,cAAc,CAAC;AAEtB,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,MAAM,CAGrE;AAED,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA2CnG"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * CLI runner for `slowcook extract --history` — gather build-history excerpts
3
+ * via ctx, one LLM pass to distill claims (citation-enforced against real
4
+ * session ids), write `.brewing/extract-history.json` in the survey shape.
5
+ */
6
+ import { mkdirSync, writeFileSync } from "node:fs";
7
+ import { dirname } from "node:path";
8
+ import { createLlmClient } from "../refine/llm.js";
9
+ import { DEFAULT_MODEL } from "./as-built-cli.js";
10
+ import { gatherHistory, parseHistoryClaims, toSurveyShape, historyOutputPath, HISTORY_SYSTEM, } from "./history.js";
11
+ export function buildHistoryPrompt(excerpts) {
12
+ return "Build-history excerpts (each: [kind-hint | session | date] text):\n\n" +
13
+ excerpts.map((e) => `[${e.kind} | ${e.sessionId} | ${(e.timestamp ?? "").slice(0, 10)}]\n${e.snippet}`).join("\n\n");
14
+ }
15
+ export async function runHistoryCli(repoRoot, opts) {
16
+ const { workspace, excerpts } = gatherHistory(repoRoot);
17
+ if (excerpts.length === 0) {
18
+ // honest degradation — this repo wasn't built (here) with indexed agents.
19
+ console.log("extract --history: no build history found for this repo in the local ctx index.");
20
+ console.log(" (needs ctxrs/ctx installed + `ctx setup`, and the repo built with a coding agent on THIS machine)");
21
+ return;
22
+ }
23
+ console.log(`extract --history: ${excerpts.length} excerpt(s) from build sessions (workspace: ${workspace}); distilling…`);
24
+ let llm;
25
+ try {
26
+ llm = await createLlmClient();
27
+ }
28
+ catch (err) {
29
+ console.error(`extract --history: ${err instanceof Error ? err.message : String(err)}`);
30
+ process.exit(1);
31
+ }
32
+ const res = await llm.complete({
33
+ system: HISTORY_SYSTEM,
34
+ cacheSystem: false,
35
+ model: opts.model ?? DEFAULT_MODEL,
36
+ messages: [{ role: "user", content: buildHistoryPrompt(excerpts) }],
37
+ maxTokens: 8000,
38
+ });
39
+ const validSessions = new Set(excerpts.map((e) => e.sessionId));
40
+ const claims = parseHistoryClaims(res.text, validSessions);
41
+ if (claims.length === 0) {
42
+ console.log("extract --history: the model distilled no citable claims from the excerpts — nothing written.");
43
+ return;
44
+ }
45
+ const out = {
46
+ generated_by: "slowcook extract --history",
47
+ workspace,
48
+ excerpts_seen: excerpts.length,
49
+ claims: toSurveyShape(claims),
50
+ };
51
+ const path = historyOutputPath(repoRoot);
52
+ mkdirSync(dirname(path), { recursive: true });
53
+ writeFileSync(path, JSON.stringify(out, null, 2) + "\n");
54
+ const byKind = claims.reduce((m, c) => ((m[c.kind] = (m[c.kind] ?? 0) + 1), m), {});
55
+ console.log(`extract --history: wrote ${claims.length} claim(s) → ${path}`);
56
+ console.log(` ${Object.entries(byKind).map(([k, n]) => `${k}: ${n}`).join(" · ")}`);
57
+ }
58
+ //# sourceMappingURL=history-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history-cli.js","sourceRoot":"","sources":["../../../src/commands/extract/history-cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import { type CtxRunner } from "../recall/ctx.js";
2
+ /** claude code stores transcripts under ~/.claude/projects/<path-with-dashes>;
3
+ * ctx records THAT as the workspace. Map a repo root to candidate workspaces. */
4
+ export declare function workspaceCandidates(repoRoot: string, home?: string): string[];
5
+ /** themed probes — SHORT queries, several per theme: ctx's ranked match wants
6
+ * most words present, so long keyword soups zero out on a workspace-filtered
7
+ * subset. Short probes hit; the merge dedupes. */
8
+ export declare const HISTORY_THEMES: {
9
+ kind: string;
10
+ probes: string[];
11
+ }[];
12
+ export interface HistoryExcerpt {
13
+ kind: string;
14
+ sessionId: string;
15
+ timestamp?: string;
16
+ snippet: string;
17
+ }
18
+ /** search the build history per theme; dedupe by (session, snippet-prefix). */
19
+ export declare function gatherHistory(repoRoot: string, run?: CtxRunner, limitPerTheme?: number): {
20
+ workspace: string | null;
21
+ excerpts: HistoryExcerpt[];
22
+ };
23
+ export declare const HISTORY_SYSTEM = "You are slowcook's build-history archaeologist. The excerpts below come\nfrom the CODING-AGENT SESSIONS THAT BUILT this repository \u2014 the discussions\nwhere decisions were made, approaches were tried and abandoned, and bugs were\ndiscovered. Each excerpt is tagged with a candidate kind and its session id.\n\nExtract the durable knowledge: statements a newcomer (or a product intake)\nshould know that the CODE ITSELF does not say. For each, output:\n- kind: \"decision\" | \"rejected_approach\" | \"known_issue\" | \"constraint\"\n- statement: one clear sentence, past tense for history (\"X was tried and\n reverted because Y\"), present for standing facts.\n- session: the session id of the excerpt(s) you drew it from (REQUIRED \u2014\n uncited claims are dropped).\n- when: the excerpt's date (YYYY-MM-DD) if present.\n\nRules: only what the excerpts actually support \u2014 no invention, no padding.\nMerge duplicates. Skip excerpts that are just command output or pleasantries.\nOutput STRICT JSON only: {\"claims\":[{\"kind\":\"...\",\"statement\":\"...\",\"session\":\"...\",\"when\":\"...\"}]}";
24
+ export interface HistoryClaim {
25
+ kind: string;
26
+ statement: string;
27
+ session: string;
28
+ when?: string;
29
+ }
30
+ /** validate + citation-enforce the model's output against real session ids. */
31
+ export declare function parseHistoryClaims(text: string, validSessions: Set<string>): HistoryClaim[];
32
+ /** survey-claim-shaped output, so dash's knowledge sync ingests it as-is. */
33
+ export declare function toSurveyShape(claims: HistoryClaim[]): {
34
+ source: string;
35
+ area: string;
36
+ statement: string;
37
+ status: string;
38
+ evidence: Record<string, unknown>;
39
+ }[];
40
+ export declare function historyOutputPath(repoRoot: string): string;
41
+ export declare function brewingDirExists(repoRoot: string): boolean;
42
+ //# sourceMappingURL=history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../../src/commands/extract/history.ts"],"names":[],"mappings":"AAkBA,OAAO,EAA2C,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE3F;kFACkF;AAClF,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,MAAkB,GAAG,MAAM,EAAE,CAIxF;AAED;;mDAEmD;AACnD,eAAO,MAAM,cAAc,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,EAK9D,CAAC;AAEF,MAAM,WAAW,cAAc;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AAExG,+EAA+E;AAC/E,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,SAAS,EAAE,aAAa,SAAI,GAAG;IAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,EAAE,cAAc,EAAE,CAAA;CAAE,CAqB5I;AAED,eAAO,MAAM,cAAc,2lCAgByE,CAAC;AAErG,MAAM,WAAW,YAAY;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE;AAEjG,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,YAAY,EAAE,CAY3F;AAED,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG;IACrD,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpG,EAAE,CAWF;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE1D"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * `slowcook extract --history` — tier 1.5 — mine the AGENT SESSIONS THAT BUILT
3
+ * this repo for the knowledge no other source carries: design decisions,
4
+ * REJECTED approaches ("tried X, it deadlocked, so Y"), known issues, and
5
+ * constraints. The code shows what IS; the build history shows WHY.
6
+ *
7
+ * Source: the local ctx index (ctxrs/ctx, Apache-2.0 — see `slowcook recall`),
8
+ * searched per theme over MESSAGE events (decisions live in messages, not
9
+ * command echoes). Only works where the histories live — the builder's own
10
+ * machine — so it's opt-in and degrades honestly: "no build history found".
11
+ *
12
+ * Output: `.brewing/extract-history.json`, survey-claim-shaped so consumers
13
+ * (dash's knowledge sync) ingest it exactly like `--survey` output — every
14
+ * claim cites its session id (inspect with `ctx show session <id>`).
15
+ */
16
+ import { homedir } from "node:os";
17
+ import { existsSync } from "node:fs";
18
+ import { join, resolve } from "node:path";
19
+ import { ctxAvailable, ctxSearch } from "../recall/ctx.js";
20
+ /** claude code stores transcripts under ~/.claude/projects/<path-with-dashes>;
21
+ * ctx records THAT as the workspace. Map a repo root to candidate workspaces. */
22
+ export function workspaceCandidates(repoRoot, home = homedir()) {
23
+ const abs = resolve(repoRoot);
24
+ const dashed = abs.replace(/\//g, "-"); // "/a/b" → "-a-b"
25
+ return [abs, join(home, ".claude", "projects", dashed)];
26
+ }
27
+ /** themed probes — SHORT queries, several per theme: ctx's ranked match wants
28
+ * most words present, so long keyword soups zero out on a workspace-filtered
29
+ * subset. Short probes hit; the merge dedupes. */
30
+ export const HISTORY_THEMES = [
31
+ { kind: "decision", probes: ["decided", "chose instead", "architecture decision", "settled on"] },
32
+ { kind: "rejected_approach", probes: ["reverted", "abandoned", "didn't work", "failed approach", "dead end"] },
33
+ { kind: "known_issue", probes: ["known bug", "workaround", "flaky", "still broken"] },
34
+ { kind: "constraint", probes: ["invariant", "must never", "hard requirement", "by design"] },
35
+ ];
36
+ /** search the build history per theme; dedupe by (session, snippet-prefix). */
37
+ export function gatherHistory(repoRoot, run, limitPerTheme = 6) {
38
+ if (!ctxAvailable(run))
39
+ return { workspace: null, excerpts: [] };
40
+ for (const ws of workspaceCandidates(repoRoot)) {
41
+ // the transcript-dir candidate may exist even when ctx has nothing for the
42
+ // repo path itself; probe each until one yields results.
43
+ const all = [];
44
+ const seen = new Set();
45
+ for (const theme of HISTORY_THEMES) {
46
+ for (const probe of theme.probes) {
47
+ const results = ctxSearch({ query: probe, workspace: ws, limit: limitPerTheme }, run);
48
+ for (const r of results) {
49
+ const key = `${r.sessionId}:${r.snippet.slice(0, 60)}`;
50
+ if (seen.has(key))
51
+ continue;
52
+ seen.add(key);
53
+ all.push({ kind: theme.kind, sessionId: r.sessionId, timestamp: r.timestamp, snippet: r.snippet });
54
+ }
55
+ }
56
+ }
57
+ if (all.length > 0)
58
+ return { workspace: ws, excerpts: all };
59
+ }
60
+ return { workspace: null, excerpts: [] };
61
+ }
62
+ export const HISTORY_SYSTEM = `You are slowcook's build-history archaeologist. The excerpts below come
63
+ from the CODING-AGENT SESSIONS THAT BUILT this repository — the discussions
64
+ where decisions were made, approaches were tried and abandoned, and bugs were
65
+ discovered. Each excerpt is tagged with a candidate kind and its session id.
66
+
67
+ Extract the durable knowledge: statements a newcomer (or a product intake)
68
+ should know that the CODE ITSELF does not say. For each, output:
69
+ - kind: "decision" | "rejected_approach" | "known_issue" | "constraint"
70
+ - statement: one clear sentence, past tense for history ("X was tried and
71
+ reverted because Y"), present for standing facts.
72
+ - session: the session id of the excerpt(s) you drew it from (REQUIRED —
73
+ uncited claims are dropped).
74
+ - when: the excerpt's date (YYYY-MM-DD) if present.
75
+
76
+ Rules: only what the excerpts actually support — no invention, no padding.
77
+ Merge duplicates. Skip excerpts that are just command output or pleasantries.
78
+ Output STRICT JSON only: {"claims":[{"kind":"...","statement":"...","session":"...","when":"..."}]}`;
79
+ /** validate + citation-enforce the model's output against real session ids. */
80
+ export function parseHistoryClaims(text, validSessions) {
81
+ const body = text.replace(/^```(?:json)?\s*/i, "").replace(/```\s*$/i, "").trim();
82
+ const a = body.indexOf("{"), b = body.lastIndexOf("}");
83
+ if (a < 0 || b < 0)
84
+ return [];
85
+ try {
86
+ const parsed = JSON.parse(body.slice(a, b + 1));
87
+ return (parsed.claims ?? []).filter((c) => typeof c.statement === "string" && c.statement.length > 10 &&
88
+ ["decision", "rejected_approach", "known_issue", "constraint"].includes(c.kind) &&
89
+ typeof c.session === "string" && validSessions.has(c.session));
90
+ }
91
+ catch {
92
+ return [];
93
+ }
94
+ }
95
+ /** survey-claim-shaped output, so dash's knowledge sync ingests it as-is. */
96
+ export function toSurveyShape(claims) {
97
+ return claims.map((c) => ({
98
+ source: "build_history",
99
+ area: c.kind === "known_issue" ? "quality" : "architecture",
100
+ statement: c.statement,
101
+ // rejected approaches + decisions are testimony from the builder's own
102
+ // sessions — verified-grade provenance; known issues stay unverified
103
+ // (they may have been fixed since).
104
+ status: c.kind === "known_issue" ? "unverified" : "verified",
105
+ evidence: { kind: `history-${c.kind}`, session: c.session, when: c.when ?? null, inspect: `ctx show session ${c.session}` },
106
+ }));
107
+ }
108
+ export function historyOutputPath(repoRoot) {
109
+ return join(repoRoot, ".brewing", "extract-history.json");
110
+ }
111
+ export function brewingDirExists(repoRoot) {
112
+ return existsSync(join(repoRoot, ".brewing"));
113
+ }
114
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.js","sourceRoot":"","sources":["../../../src/commands/extract/history.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/extract/index.ts"],"names":[],"mappings":"AA4GA,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmChF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/extract/index.ts"],"names":[],"mappings":"AAsJA,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDhF"}
@@ -1,10 +1,18 @@
1
1
  import { emitSchemaDiagram, emitTokensCatalog, emitEntitiesDiagram, } from "../map/index.js";
2
+ import { runSurvey, writeSurvey } from "./survey.js";
3
+ import { runAsBuiltCli } from "./as-built-cli.js";
4
+ import { runHistoryCli } from "./history-cli.js";
2
5
  function parseArgs(argv) {
3
6
  const args = {
4
7
  repoRoot: process.cwd(),
5
8
  schema: false,
6
9
  tokens: false,
7
10
  entities: false,
11
+ survey: false,
12
+ asBuilt: false,
13
+ history: false,
14
+ allowUncited: false,
15
+ model: null,
8
16
  };
9
17
  let any = false;
10
18
  for (let i = 0; i < argv.length; i++) {
@@ -26,6 +34,24 @@ function parseArgs(argv) {
26
34
  args.entities = true;
27
35
  any = true;
28
36
  }
37
+ else if (a === "--survey") {
38
+ args.survey = true;
39
+ any = true;
40
+ }
41
+ else if (a === "--as-built") {
42
+ args.asBuilt = true;
43
+ }
44
+ else if (a === "--history") {
45
+ args.history = true;
46
+ any = true;
47
+ }
48
+ else if (a === "--allow-uncited") {
49
+ args.allowUncited = true;
50
+ }
51
+ else if (a === "--model" && next) {
52
+ args.model = next;
53
+ i++;
54
+ }
29
55
  else if (a === "--help" || a === "-h") {
30
56
  printHelp();
31
57
  process.exit(0);
@@ -54,10 +80,14 @@ investigate so their proposals align with the project's existing
54
80
  schema + design tokens instead of inventing.
55
81
 
56
82
  Usage:
57
- slowcook extract [--schema] [--tokens] [--cwd <path>]
83
+ slowcook extract [--schema] [--tokens] [--entities] [--cwd <path>]
84
+ slowcook extract --survey [--cwd <path>]
85
+ slowcook extract --as-built [--cwd <path>] [--model <id>] [--allow-uncited]
86
+ slowcook extract --history [--cwd <path>] [--model <id>] # mine the agent sessions that BUILT this repo (via ctxrs/ctx)
58
87
 
59
- No flag = extract everything (currently --schema + --tokens).
60
- Outputs are gitignored; regenerate per refine run.
88
+ No flag = the diagram extracts (--schema + --tokens + --entities).
89
+ Diagram outputs are gitignored; regenerate per refine run.
90
+ --survey / --as-built outputs are INTAKE ARTIFACTS — commit them.
61
91
 
62
92
  Targets:
63
93
  --schema .brewing/diagrams/schema.mmd
@@ -75,12 +105,42 @@ Targets:
75
105
  by default; the init gitignore template carves out an
76
106
  exception for this file.
77
107
 
108
+ --survey .brewing/extract-survey.json (#262 tier 0 — deterministic).
109
+ Doc catalog dated via git (stale-honest), story-spec
110
+ aggregate, commit/branch evidence, issues/PRs via gh when
111
+ available. Entries are knowledge-claim shaped for direct
112
+ ingestion by §7.18-style intakes.
113
+ --as-built .brewing/as-built.md (#262 tier 1 — LLM, key-less capable
114
+ via SLOWCOOK_LLM=claude-cli). AS-OBSERVED product truth in
115
+ five fixed sections; every bullet must carry a (path)
116
+ citation — enforced by a validator; founder questions
117
+ close the doc. Fails on uncited bullets unless
118
+ --allow-uncited.
119
+
78
120
  This command does NOT run the ts-morph code-map scan; for that,
79
121
  use \`slowcook map generate\`.
80
122
  `);
81
123
  }
82
124
  export async function extract(argv, _cliVersion) {
83
125
  const args = parseArgs(argv);
126
+ if (args.survey || args.asBuilt || args.history) {
127
+ if (args.survey || args.asBuilt) {
128
+ const survey = runSurvey(args.repoRoot);
129
+ if (args.survey) {
130
+ const file = writeSurvey(args.repoRoot, survey);
131
+ console.log(`Wrote ${file} (${survey.claims.length} claims${survey.skipped.length ? `; skipped: ${survey.skipped.join("; ")}` : ""}).`);
132
+ }
133
+ if (args.asBuilt) {
134
+ await runAsBuiltCli(args.repoRoot, survey, { model: args.model, allowUncited: args.allowUncited });
135
+ }
136
+ }
137
+ if (args.history) {
138
+ // tier 1.5 — the agent sessions that BUILT the repo (opt-in; degrades
139
+ // honestly when no local build history exists).
140
+ await runHistoryCli(args.repoRoot, { model: args.model });
141
+ }
142
+ return;
143
+ }
84
144
  if (args.schema) {
85
145
  const r = emitSchemaDiagram(args.repoRoot);
86
146
  if (r.written) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/extract/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/extract/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export interface SurveyClaim {
2
+ source: "doc" | "extraction";
3
+ area: "product" | "behaviour" | "brand" | "architecture" | "data";
4
+ statement: string;
5
+ status: "unverified" | "verified";
6
+ evidence: Record<string, unknown>;
7
+ doc_name?: string;
8
+ }
9
+ export interface SurveyOutput {
10
+ generated_at: string;
11
+ repo_head: string | null;
12
+ claims: SurveyClaim[];
13
+ skipped: string[];
14
+ }
15
+ export declare function runSurvey(repoRoot: string, now?: Date): SurveyOutput;
16
+ export declare function writeSurvey(repoRoot: string, out: SurveyOutput): string;
17
+ //# sourceMappingURL=survey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"survey.d.ts","sourceRoot":"","sources":["../../../src/commands/extract/survey.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,KAAK,GAAG,YAAY,CAAC;IAC7B,IAAI,EAAE,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,cAAc,GAAG,MAAM,CAAC;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,YAAY,GAAG,UAAU,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAmDD,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAa,GAAG,YAAY,CAmF1E;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,GAAG,MAAM,CAMvE"}