forgecraft-mcp 1.7.0 → 1.8.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 (52) hide show
  1. package/README.md +79 -0
  2. package/dist/registry/remote-gates.d.ts +16 -0
  3. package/dist/registry/remote-gates.d.ts.map +1 -1
  4. package/dist/registry/remote-gates.js +56 -0
  5. package/dist/registry/remote-gates.js.map +1 -1
  6. package/dist/registry/sentinel-domain-map.d.ts.map +1 -1
  7. package/dist/registry/sentinel-domain-map.js +16 -9
  8. package/dist/registry/sentinel-domain-map.js.map +1 -1
  9. package/dist/registry/sentinel-renderer.d.ts +13 -8
  10. package/dist/registry/sentinel-renderer.d.ts.map +1 -1
  11. package/dist/registry/sentinel-renderer.js +440 -162
  12. package/dist/registry/sentinel-renderer.js.map +1 -1
  13. package/dist/shared/harness-budget.d.ts +49 -0
  14. package/dist/shared/harness-budget.d.ts.map +1 -0
  15. package/dist/shared/harness-budget.js +123 -0
  16. package/dist/shared/harness-budget.js.map +1 -0
  17. package/dist/shared/hook-installer.d.ts.map +1 -1
  18. package/dist/shared/hook-installer.js +2 -1
  19. package/dist/shared/hook-installer.js.map +1 -1
  20. package/dist/tools/close-cycle-helpers.d.ts +9 -0
  21. package/dist/tools/close-cycle-helpers.d.ts.map +1 -1
  22. package/dist/tools/close-cycle-helpers.js.map +1 -1
  23. package/dist/tools/close-cycle.d.ts.map +1 -1
  24. package/dist/tools/close-cycle.js +29 -0
  25. package/dist/tools/close-cycle.js.map +1 -1
  26. package/dist/tools/contribute-gate.d.ts +30 -4
  27. package/dist/tools/contribute-gate.d.ts.map +1 -1
  28. package/dist/tools/contribute-gate.js +180 -66
  29. package/dist/tools/contribute-gate.js.map +1 -1
  30. package/dist/tools/gate-genesis.d.ts +47 -0
  31. package/dist/tools/gate-genesis.d.ts.map +1 -0
  32. package/dist/tools/gate-genesis.js +241 -0
  33. package/dist/tools/gate-genesis.js.map +1 -0
  34. package/dist/tools/learning-graph.d.ts +31 -0
  35. package/dist/tools/learning-graph.d.ts.map +1 -0
  36. package/dist/tools/learning-graph.js +266 -0
  37. package/dist/tools/learning-graph.js.map +1 -0
  38. package/dist/tools/setup-artifact-writers.d.ts +15 -3
  39. package/dist/tools/setup-artifact-writers.d.ts.map +1 -1
  40. package/dist/tools/setup-artifact-writers.js +149 -13
  41. package/dist/tools/setup-artifact-writers.js.map +1 -1
  42. package/dist/tools/setup-phase2.d.ts +9 -0
  43. package/dist/tools/setup-phase2.d.ts.map +1 -1
  44. package/dist/tools/setup-phase2.js +13 -0
  45. package/dist/tools/setup-phase2.js.map +1 -1
  46. package/dist/tools/setup-project.d.ts +6 -0
  47. package/dist/tools/setup-project.d.ts.map +1 -1
  48. package/dist/tools/setup-project.js +21 -4
  49. package/dist/tools/setup-project.js.map +1 -1
  50. package/package.json +99 -98
  51. package/templates/api/instructions.yaml +50 -188
  52. package/templates/universal/instructions.yaml +194 -1003
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-genesis.js","sourceRoot":"","sources":["../../src/tools/gate-genesis.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * learning-graph.csv emission — the harness as a literal Compact Knowledge Graph.
3
+ *
4
+ * Serializes the project's knowledge structure as a learning graph per
5
+ * Yarmoluk & McCreary's Definition 1: G = (C, E, T, τ) in the 4-column CSV
6
+ * schema `ConceptID,ConceptLabel,Dependencies,TaxonomyID` (Dependencies =
7
+ * pipe-delimited prerequisite ConceptIDs; the pair (C,E) must be a DAG).
8
+ *
9
+ * Concepts are the harness artifacts; edges encode reading order ("understand
10
+ * X before Y"): the routing table, the doc obligation table, and @gs-links.
11
+ * Empirical basis: the KX experiment (experiments/kx) measured CNT-routed
12
+ * retrieval at RDS 1.7–5.6× over dump/search baselines — the CKG economics.
13
+ *
14
+ * This is a DERIVED artifact (Living Documentation): regenerated on every
15
+ * setup/refresh, never hand-edited. It is machine data, not session prose —
16
+ * it is not part of the routed CNT and does not count against the harness budget.
17
+ */
18
+ export interface LearningGraphResult {
19
+ readonly written: boolean;
20
+ readonly concepts: number;
21
+ readonly edges: number;
22
+ }
23
+ /**
24
+ * Emit docs/learning-graph.csv from the project's harness artifacts.
25
+ * Always regenerates (derived artifact). Returns counts for reporting.
26
+ *
27
+ * @param projectDir - Project root
28
+ * @returns written flag + concept/edge counts (written=false when no harness)
29
+ */
30
+ export declare function emitLearningGraph(projectDir: string): LearningGraphResult;
31
+ //# sourceMappingURL=learning-graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learning-graph.d.ts","sourceRoot":"","sources":["../../src/tools/learning-graph.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAsBD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,mBAAmB,CAmOzE"}
@@ -0,0 +1,266 @@
1
+ /**
2
+ * learning-graph.csv emission — the harness as a literal Compact Knowledge Graph.
3
+ *
4
+ * Serializes the project's knowledge structure as a learning graph per
5
+ * Yarmoluk & McCreary's Definition 1: G = (C, E, T, τ) in the 4-column CSV
6
+ * schema `ConceptID,ConceptLabel,Dependencies,TaxonomyID` (Dependencies =
7
+ * pipe-delimited prerequisite ConceptIDs; the pair (C,E) must be a DAG).
8
+ *
9
+ * Concepts are the harness artifacts; edges encode reading order ("understand
10
+ * X before Y"): the routing table, the doc obligation table, and @gs-links.
11
+ * Empirical basis: the KX experiment (experiments/kx) measured CNT-routed
12
+ * retrieval at RDS 1.7–5.6× over dump/search baselines — the CKG economics.
13
+ *
14
+ * This is a DERIVED artifact (Living Documentation): regenerated on every
15
+ * setup/refresh, never hand-edited. It is machine data, not session prose —
16
+ * it is not part of the routed CNT and does not count against the harness budget.
17
+ */
18
+ import { existsSync, readFileSync, writeFileSync, readdirSync } from "fs";
19
+ import { join, relative } from "path";
20
+ /** Taxonomy categories (τ): coarse artifact classes, per LG convention (≤16). */
21
+ const TAXONOMY = {
22
+ CNT: "CNT", // navigation tree branches
23
+ DOC: "DOC", // core documents (PRD, TechSpec, status, manifest)
24
+ ARCH: "ARCH", // architecture branch docs
25
+ ADR: "ADR", // decision records
26
+ UC: "UC", // use cases
27
+ SPEC: "SPEC", // spec decision records
28
+ GATE: "GATE", // quality gates
29
+ STD: "STD", // domain standards
30
+ CODE: "CODE", // source files carrying @gs-links
31
+ };
32
+ /**
33
+ * Emit docs/learning-graph.csv from the project's harness artifacts.
34
+ * Always regenerates (derived artifact). Returns counts for reporting.
35
+ *
36
+ * @param projectDir - Project root
37
+ * @returns written flag + concept/edge counts (written=false when no harness)
38
+ */
39
+ export function emitLearningGraph(projectDir) {
40
+ const rootMd = join(projectDir, "CLAUDE.md");
41
+ if (!existsSync(rootMd))
42
+ return { written: false, concepts: 0, edges: 0 };
43
+ const nodes = [];
44
+ const byLabel = new Map();
45
+ let nextId = 1;
46
+ const addNode = (label, taxonomy) => {
47
+ const clean = sanitizeLabel(label);
48
+ const existing = byLabel.get(clean);
49
+ if (existing)
50
+ return existing;
51
+ const node = {
52
+ id: nextId++,
53
+ label: clean,
54
+ taxonomy,
55
+ deps: new Set(),
56
+ };
57
+ nodes.push(node);
58
+ byLabel.set(clean, node);
59
+ return node;
60
+ };
61
+ const addEdge = (from, prerequisite) => {
62
+ // Self-references and forward cycles are excluded by construction:
63
+ // prerequisites are always added before their dependents, and we never
64
+ // point a node at itself.
65
+ if (from.id !== prerequisite.id)
66
+ from.deps.add(prerequisite.id);
67
+ };
68
+ // ── Foundational layer: CNT root + always-load ──────────────────────
69
+ const root = addNode("CLAUDE.md (CNT root)", TAXONOMY.CNT);
70
+ const constitution = maybeNode(projectDir, ".claude/constitution.md", "Constitution", TAXONOMY.CNT, addNode);
71
+ const corrections = maybeNode(projectDir, ".claude/corrections.md", "Corrections Log", TAXONOMY.CNT, addNode);
72
+ for (const n of [constitution, corrections])
73
+ if (n)
74
+ addEdge(n, root);
75
+ // CNT branches depend on the root (read root first, then descend)
76
+ const lifecycle = maybeNode(projectDir, ".claude/lifecycle.md", "Lifecycle", TAXONOMY.CNT, addNode);
77
+ const routesCode = maybeNode(projectDir, ".claude/routes/code.md", "Code Routes", TAXONOMY.CNT, addNode);
78
+ const routesDocs = maybeNode(projectDir, ".claude/routes/docs.md", "Docs Routes", TAXONOMY.CNT, addNode);
79
+ for (const n of [lifecycle, routesCode, routesDocs])
80
+ if (n)
81
+ addEdge(n, root);
82
+ // ── Core documents ───────────────────────────────────────────────────
83
+ const prd = maybeNode(projectDir, "docs/PRD.md", "PRD", TAXONOMY.DOC, addNode);
84
+ const techSpec = maybeNode(projectDir, "docs/TechSpec.md", "TechSpec", TAXONOMY.DOC, addNode);
85
+ const status = maybeNode(projectDir, "docs/status.md", "Status", TAXONOMY.DOC, addNode);
86
+ const manifest = maybeNode(projectDir, "docs/manifest.yaml", "Docs Manifest", TAXONOMY.DOC, addNode);
87
+ if (techSpec && prd)
88
+ addEdge(techSpec, prd); // architecture derives from spec
89
+ if (status && root)
90
+ addEdge(status, root);
91
+ if (manifest && root)
92
+ addEdge(manifest, root);
93
+ // ── Architecture branch docs (depend on TechSpec when present) ──────
94
+ const archDir = join(projectDir, "docs", "architecture");
95
+ if (existsSync(archDir)) {
96
+ for (const f of readdirSync(archDir).filter((x) => x.endsWith(".md"))) {
97
+ const n = addNode(`Architecture: ${f.replace(/\.md$/, "")}`, TAXONOMY.ARCH);
98
+ if (techSpec)
99
+ addEdge(n, techSpec);
100
+ else if (prd)
101
+ addEdge(n, prd);
102
+ }
103
+ }
104
+ // ── ADRs (decisions derive from the spec context) ───────────────────
105
+ const adrNodesByFile = new Map();
106
+ for (const adrDir of ["docs/adrs/active", "docs/adrs"]) {
107
+ const dir = join(projectDir, ...adrDir.split("/"));
108
+ if (!existsSync(dir))
109
+ continue;
110
+ for (const f of readdirSync(dir).filter((x) => /^ADR-.*\.md$/i.test(x) || /^\d{4}-.*\.md$/.test(x))) {
111
+ const label = `ADR: ${f.replace(/\.md$/, "")}`;
112
+ if (byLabel.has(sanitizeLabel(label)))
113
+ continue;
114
+ const n = addNode(label, TAXONOMY.ADR);
115
+ adrNodesByFile.set(`${adrDir}/${f}`.replace("docs/adrs/active", "docs/adrs"), n);
116
+ adrNodesByFile.set(`docs/adrs/${f}`, n);
117
+ if (prd)
118
+ addEdge(n, prd);
119
+ }
120
+ }
121
+ // ── Use cases (behavioral contracts derive from the PRD) ────────────
122
+ const ucNodesById = new Map();
123
+ const ucFile = join(projectDir, "docs", "use-cases.md");
124
+ if (existsSync(ucFile)) {
125
+ for (const line of readFileSync(ucFile, "utf-8").split("\n")) {
126
+ const m = /^## (UC-\d+):\s*(.+)$/.exec(line.trim());
127
+ if (!m)
128
+ continue;
129
+ const n = addNode(`${m[1]}: ${m[2]}`, TAXONOMY.UC);
130
+ ucNodesById.set(m[1], n);
131
+ if (prd)
132
+ addEdge(n, prd);
133
+ }
134
+ }
135
+ // ── Spec decision records (derive from PRD + their use cases) ───────
136
+ const specNodesByFile = new Map();
137
+ const specsDir = join(projectDir, "docs", "specs");
138
+ if (existsSync(specsDir)) {
139
+ for (const f of readdirSync(specsDir).filter((x) => x.endsWith(".md") && x !== "README.md")) {
140
+ const n = addNode(`Spec: ${f.replace(/\.md$/, "")}`, TAXONOMY.SPEC);
141
+ specNodesByFile.set(`docs/specs/${f}`, n);
142
+ if (prd)
143
+ addEdge(n, prd);
144
+ }
145
+ }
146
+ // ── Quality gates (mandated by the constitution) ────────────────────
147
+ for (const gatesSub of ["active", "registry"]) {
148
+ const base = join(projectDir, ".forgecraft", "gates", gatesSub);
149
+ if (!existsSync(base))
150
+ continue;
151
+ walkYaml(base, (full) => {
152
+ const rel = relative(base, full).split("\\").join("/");
153
+ const id = rel
154
+ .replace(/\.ya?ml$/, "")
155
+ .split("/")
156
+ .pop();
157
+ const label = `Gate: ${id}`;
158
+ if (byLabel.has(sanitizeLabel(label)))
159
+ return;
160
+ const n = addNode(label, TAXONOMY.GATE);
161
+ if (constitution)
162
+ addEdge(n, constitution);
163
+ else
164
+ addEdge(n, root);
165
+ });
166
+ }
167
+ // ── Standards (expand the constitution per domain) ──────────────────
168
+ const stdDir = join(projectDir, ".claude", "standards");
169
+ if (existsSync(stdDir)) {
170
+ for (const f of readdirSync(stdDir).filter((x) => x.endsWith(".md"))) {
171
+ const n = addNode(`Standards: ${f.replace(/\.md$/, "")}`, TAXONOMY.STD);
172
+ if (constitution)
173
+ addEdge(n, constitution);
174
+ else
175
+ addEdge(n, root);
176
+ }
177
+ }
178
+ // ── @gs-links: code nodes depend on their governing documents ───────
179
+ const srcDir = join(projectDir, "src");
180
+ if (existsSync(srcDir)) {
181
+ walkSource(srcDir, (full) => {
182
+ const head = readFileSync(full, "utf-8").slice(0, 2000);
183
+ const m = /@gs-links:\s*(.+)/.exec(head);
184
+ if (!m)
185
+ return;
186
+ const rel = relative(projectDir, full).split("\\").join("/");
187
+ const codeNode = addNode(`Code: ${rel}`, TAXONOMY.CODE);
188
+ for (const linkRaw of m[1].split(",")) {
189
+ const link = linkRaw
190
+ .trim()
191
+ .replace(/\*\/?\s*$/, "")
192
+ .trim();
193
+ const target = specNodesByFile.get(link) ??
194
+ adrNodesByFile.get(link) ??
195
+ resolveLooseLink(link, ucNodesById, byLabel);
196
+ if (target)
197
+ addEdge(codeNode, target);
198
+ }
199
+ if (codeNode.deps.size === 0 && routesCode)
200
+ addEdge(codeNode, routesCode);
201
+ });
202
+ }
203
+ // ── Serialize (4-column CSV per Definition 1) ────────────────────────
204
+ const lines = ["ConceptID,ConceptLabel,Dependencies,TaxonomyID"];
205
+ let edgeCount = 0;
206
+ for (const n of nodes) {
207
+ const deps = [...n.deps].sort((a, b) => a - b).join("|");
208
+ edgeCount += n.deps.size;
209
+ lines.push(`${n.id},${csvField(n.label)},${deps},${n.taxonomy}`);
210
+ }
211
+ const outPath = join(projectDir, "docs", "learning-graph.csv");
212
+ writeFileSync(outPath, lines.join("\n") + "\n", "utf-8");
213
+ return { written: true, concepts: nodes.length, edges: edgeCount };
214
+ }
215
+ // ── Helpers ───────────────────────────────────────────────────────────
216
+ function maybeNode(projectDir, rel, label, taxonomy, addNode) {
217
+ return existsSync(join(projectDir, ...rel.split("/")))
218
+ ? addNode(label, taxonomy)
219
+ : null;
220
+ }
221
+ function walkYaml(dir, visit) {
222
+ for (const e of readdirSync(dir, { withFileTypes: true })) {
223
+ const full = join(dir, e.name);
224
+ if (e.isDirectory())
225
+ walkYaml(full, visit);
226
+ else if (/\.ya?ml$/.test(e.name))
227
+ visit(full);
228
+ }
229
+ }
230
+ function walkSource(dir, visit) {
231
+ for (const e of readdirSync(dir, { withFileTypes: true })) {
232
+ const full = join(dir, e.name);
233
+ if (e.isDirectory())
234
+ walkSource(full, visit);
235
+ else if (/\.(ts|tsx|js|py)$/.test(e.name) &&
236
+ !/\.test\.|\.spec\./.test(e.name))
237
+ visit(full);
238
+ }
239
+ }
240
+ function resolveLooseLink(link, ucNodesById, byLabel) {
241
+ const uc = /UC-\d+/.exec(link);
242
+ if (uc)
243
+ return ucNodesById.get(uc[0]);
244
+ if (/use-cases\.md/.test(link)) {
245
+ // generic use-cases link → first UC node if any (closest stable anchor)
246
+ return ucNodesById.values().next().value;
247
+ }
248
+ const adr = /ADR-[\w-]+/.exec(link);
249
+ if (adr) {
250
+ for (const [label, node] of byLabel) {
251
+ if (label.includes(adr[0]))
252
+ return node;
253
+ }
254
+ }
255
+ return undefined;
256
+ }
257
+ function sanitizeLabel(label) {
258
+ return label
259
+ .replace(/[,\r\n"]+/g, " ")
260
+ .replace(/\s+/g, " ")
261
+ .trim();
262
+ }
263
+ function csvField(s) {
264
+ return /[,"]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
265
+ }
266
+ //# sourceMappingURL=learning-graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learning-graph.js","sourceRoot":"","sources":["../../src/tools/learning-graph.ts"],"names":[],"mappings":"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"}
@@ -40,7 +40,7 @@ export declare function initGitRepo(projectDir: string): string;
40
40
  * @param brownfield - Whether this is a brownfield project
41
41
  * @returns True if the file was written or updated
42
42
  */
43
- export declare function writeForgeYaml(projectDir: string, projectName: string, tags: string[], decisions: CascadeDecision[], sensitiveData?: boolean, brownfield?: boolean): boolean;
43
+ export declare function writeForgeYaml(projectDir: string, projectName: string, tags: string[], decisions: CascadeDecision[], sensitiveData?: boolean, brownfield?: boolean, language?: string): boolean;
44
44
  /**
45
45
  * If forgecraft.yaml has an experiment block with an id but no group,
46
46
  * sets experiment.group = 'gs'.
@@ -69,15 +69,17 @@ export interface UseCaseInput {
69
69
  }
70
70
  /**
71
71
  * Write docs/PRD.md using AI-extracted fields when available.
72
+ * When AI fields are absent but a raw spec exists (CLI-only path, no AI in
73
+ * the loop), the source spec is embedded so its content is never lost.
72
74
  * Never overwrites an existing PRD.
73
75
  *
74
76
  * @param projectDir - Project root
75
77
  * @param projectName - Project name for the PRD title
76
78
  * @param aiFields - AI-extracted problem, users, criteria
77
- * @param _specContent - Raw spec text (reserved for future use)
79
+ * @param specContent - Raw spec text embedded when AI fields are absent
78
80
  * @returns True if a new PRD was written
79
81
  */
80
- export declare function writePrd(projectDir: string, projectName: string, aiFields: AiExtractedFields, _specContent: string | null): boolean;
82
+ export declare function writePrd(projectDir: string, projectName: string, aiFields: AiExtractedFields, specContent: string | null): boolean;
81
83
  /**
82
84
  * Write docs/use-cases.md from structured spec-derived use cases when available,
83
85
  * or from AI-extracted fields as a fallback. Never overwrites an existing use-cases.md.
@@ -155,6 +157,16 @@ export declare function writeProjectManifest(projectDir: string, projectName: st
155
157
  * @returns True if the file was written
156
158
  */
157
159
  export declare function writeStatusMd(projectDir: string, projectName: string): boolean;
160
+ /**
161
+ * Write docs/architecture/ CNT branch stubs — four scoped nodes for
162
+ * layers, modules, data-model, and integrations.
163
+ * Never overwrites existing files.
164
+ *
165
+ * @param projectDir - Project root
166
+ * @param projectName - Project name
167
+ * @returns Array of relative paths written
168
+ */
169
+ export declare function writeArchitectureCntStubs(projectDir: string, projectName: string): string[];
158
170
  /**
159
171
  * Load cascade decisions from forgecraft.yaml (convenience re-used in writers).
160
172
  */
@@ -1 +1 @@
1
- {"version":3,"file":"setup-artifact-writers.d.ts","sourceRoot":"","sources":["../../src/tools/setup-artifact-writers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"setup-artifact-writers.d.ts","sourceRoot":"","sources":["../../src/tools/setup-artifact-writers.ts"],"names":[],"mappings":"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"}
@@ -69,7 +69,7 @@ export function initGitRepo(projectDir) {
69
69
  * @param brownfield - Whether this is a brownfield project
70
70
  * @returns True if the file was written or updated
71
71
  */
72
- export function writeForgeYaml(projectDir, projectName, tags, decisions, sensitiveData, brownfield) {
72
+ export function writeForgeYaml(projectDir, projectName, tags, decisions, sensitiveData, brownfield, language) {
73
73
  const yamlPath = join(projectDir, "forgecraft.yaml");
74
74
  let config;
75
75
  if (existsSync(yamlPath)) {
@@ -82,6 +82,8 @@ export function writeForgeYaml(projectDir, projectName, tags, decisions, sensiti
82
82
  }
83
83
  else {
84
84
  config = { projectName, tags: tags.length > 0 ? tags : ["UNIVERSAL"] };
85
+ if (language && language !== "typescript")
86
+ config["language"] = language;
85
87
  if (sensitiveData !== undefined)
86
88
  config["sensitiveData"] = sensitiveData;
87
89
  if (brownfield === true)
@@ -127,23 +129,25 @@ export function setExperimentGroupIfMissing(projectDir) {
127
129
  }
128
130
  /**
129
131
  * Write docs/PRD.md using AI-extracted fields when available.
132
+ * When AI fields are absent but a raw spec exists (CLI-only path, no AI in
133
+ * the loop), the source spec is embedded so its content is never lost.
130
134
  * Never overwrites an existing PRD.
131
135
  *
132
136
  * @param projectDir - Project root
133
137
  * @param projectName - Project name for the PRD title
134
138
  * @param aiFields - AI-extracted problem, users, criteria
135
- * @param _specContent - Raw spec text (reserved for future use)
139
+ * @param specContent - Raw spec text embedded when AI fields are absent
136
140
  * @returns True if a new PRD was written
137
141
  */
138
- export function writePrd(projectDir, projectName, aiFields, _specContent) {
142
+ export function writePrd(projectDir, projectName, aiFields, specContent) {
139
143
  const prdPath = join(projectDir, "docs", "PRD.md");
140
144
  if (existsSync(prdPath))
141
145
  return false;
142
146
  mkdirSync(join(projectDir, "docs"), { recursive: true });
143
- writeFileSync(prdPath, buildPrdContent(projectName, aiFields), "utf-8");
147
+ writeFileSync(prdPath, buildPrdContent(projectName, aiFields, specContent), "utf-8");
144
148
  return true;
145
149
  }
146
- function buildPrdContent(projectName, aiFields) {
150
+ function buildPrdContent(projectName, aiFields, specContent) {
147
151
  const fill = (placeholder) => `<!-- FILL: ${placeholder} -->`;
148
152
  const listOrFill = (csv, placeholder) => csv
149
153
  ? csv
@@ -151,14 +155,24 @@ function buildPrdContent(projectName, aiFields) {
151
155
  .map((s) => `- ${s.trim()}`)
152
156
  .join("\n")
153
157
  : fill(placeholder);
154
- return [
158
+ const sections = [
155
159
  `# ${projectName}\n`,
156
160
  `## Problem\n\n${aiFields.problemStatement ?? fill("describe the problem this project solves")}\n`,
157
161
  `## Users\n\n${listOrFill(aiFields.primaryUsers, "list the target users or personas")}\n`,
158
162
  `## Success Criteria\n\n${listOrFill(aiFields.successCriteria, "define measurable success criteria")}\n`,
159
163
  `## Components\n\n${fill("list the major components or modules")}\n`,
160
164
  `## External Systems\n\n${fill("list external APIs, services, or integrations")}\n`,
161
- ].join("\n");
165
+ ];
166
+ // No AI extraction happened but the user provided a spec — preserve it.
167
+ // The sections above stay as FILL markers; the source is the ground truth
168
+ // the AI (or human) extracts from on the next pass.
169
+ const noAiFields = !aiFields.problemStatement &&
170
+ !aiFields.primaryUsers &&
171
+ !aiFields.successCriteria;
172
+ if (noAiFields && specContent?.trim()) {
173
+ sections.push(`## Source Specification\n`, `> Original spec provided at setup. Extract the sections above from this`, `> content, then remove this section once the PRD is fully derived.\n`, specContent.trim(), ``);
174
+ }
175
+ return sections.join("\n");
162
176
  }
163
177
  /**
164
178
  * Write docs/use-cases.md from structured spec-derived use cases when available,
@@ -933,9 +947,9 @@ export function writeStatusMd(projectDir, projectName) {
933
947
  `> Update this file at the end of each session. The Session Loop Invariant in CLAUDE.md`,
934
948
  `> references this file for any unresolved items.`,
935
949
  ``,
936
- `## Current State`,
950
+ `## Completed (this session)`,
937
951
  ``,
938
- `<!-- FILL: brief 1-2 sentence description of the current project state -->`,
952
+ `<!-- FILL: what was finished in the most recent session -->`,
939
953
  ``,
940
954
  `## In Progress`,
941
955
  ``,
@@ -945,17 +959,139 @@ export function writeStatusMd(projectDir, projectName) {
945
959
  ``,
946
960
  `<!-- FILL: first roadmap item or pending task — be specific enough to resume without re-reading everything -->`,
947
961
  ``,
948
- `## Open Issues / Blockers`,
962
+ `## Decisions Made (this session)`,
949
963
  ``,
950
- `<!-- FILL: known issues, blockers, or technical debt that need resolution -->`,
964
+ `<!-- FILL: key decisions made link to ADRs where they exist -->`,
951
965
  ``,
952
- `## Recent Decisions`,
966
+ `## Blockers / Dependencies`,
953
967
  ``,
954
- `<!-- FILL: key decisions made recently link to ADRs where they exist -->`,
968
+ `<!-- FILL: known blockers, open questions, or external dependencies -->`,
955
969
  ].join("\n");
956
970
  writeFileSync(statusPath, content, "utf-8");
957
971
  return true;
958
972
  }
973
+ // ── Architecture CNT stub writer ─────────────────────────────────────
974
+ /**
975
+ * Write docs/architecture/ CNT branch stubs — four scoped nodes for
976
+ * layers, modules, data-model, and integrations.
977
+ * Never overwrites existing files.
978
+ *
979
+ * @param projectDir - Project root
980
+ * @param projectName - Project name
981
+ * @returns Array of relative paths written
982
+ */
983
+ export function writeArchitectureCntStubs(projectDir, projectName) {
984
+ const archDir = join(projectDir, "docs", "architecture");
985
+ mkdirSync(archDir, { recursive: true });
986
+ const written = [];
987
+ const stubs = [
988
+ {
989
+ file: "layers.md",
990
+ content: [
991
+ `# Architecture: Layer Diagram & Boundary Rules`,
992
+ ``,
993
+ `> CNT node — read when: changing or reviewing layer structure, adding a new module, or diagnosing layer violations.`,
994
+ ``,
995
+ `## Layers`,
996
+ ``,
997
+ `<!-- FILL: document the layer stack (e.g. Entry → Dispatch → Handlers → Domain → Adapters) -->`,
998
+ ``,
999
+ `## Boundary Rules`,
1000
+ ``,
1001
+ `| From | To | Allowed | Rule |`,
1002
+ `|---|---|---|---|`,
1003
+ `| <!-- FILL --> | <!-- FILL --> | ✅/❌ | <!-- FILL --> |`,
1004
+ ``,
1005
+ `## Key Invariants`,
1006
+ ``,
1007
+ `<!-- FILL: list the non-negotiable structural invariants (e.g. "no circular imports", "domain has zero external imports") -->`,
1008
+ ].join("\n"),
1009
+ },
1010
+ {
1011
+ file: "modules.md",
1012
+ content: [
1013
+ `# Architecture: Module Registry`,
1014
+ ``,
1015
+ `> CNT node — read when: adding a new module, understanding file ownership, or debugging an unexpected dependency.`,
1016
+ ``,
1017
+ `## Core Modules`,
1018
+ ``,
1019
+ `| Module | File | Owns | Does NOT own |`,
1020
+ `|---|---|---|---|`,
1021
+ `| <!-- FILL: module name --> | <!-- FILL: path --> | <!-- FILL: responsibility --> | <!-- FILL: what it delegates --> |`,
1022
+ ``,
1023
+ `## Shared Utilities`,
1024
+ ``,
1025
+ `<!-- FILL: list shared utility modules and their purpose -->`,
1026
+ ``,
1027
+ `## Addition Protocol`,
1028
+ ``,
1029
+ `When adding a new module: <!-- FILL: define the decision tree for where new code goes -->`,
1030
+ ].join("\n"),
1031
+ },
1032
+ {
1033
+ file: "data-model.md",
1034
+ content: [
1035
+ `# Architecture: Data Model & Schema`,
1036
+ ``,
1037
+ `> CNT node — read when: changing the data model, adding entities, modifying schema, or updating the ERD.`,
1038
+ ``,
1039
+ `## Core Entities`,
1040
+ ``,
1041
+ `<!-- FILL: describe primary entities with their fields and invariants -->`,
1042
+ ``,
1043
+ `## Entity Relationships`,
1044
+ ``,
1045
+ `\`\`\`mermaid`,
1046
+ `erDiagram`,
1047
+ ` %% FILL: replace with actual entities and relationships`,
1048
+ ` ENTITY_A ||--o{ ENTITY_B : "has"`,
1049
+ `\`\`\``,
1050
+ ``,
1051
+ `## Schema Notes`,
1052
+ ``,
1053
+ `<!-- FILL: naming conventions, migration strategy, DB / persistence approach -->`,
1054
+ ``,
1055
+ `## DB / State`,
1056
+ ``,
1057
+ `<!-- FILL: where does state live? (DB, file system, in-memory, external service) -->`,
1058
+ `<!-- If using a DB: describe the migration strategy and any ORM/query builder choices -->`,
1059
+ ].join("\n"),
1060
+ },
1061
+ {
1062
+ file: "integrations.md",
1063
+ content: [
1064
+ `# Architecture: External Integrations`,
1065
+ ``,
1066
+ `> CNT node — read when: adding a new external dependency, changing a protocol, or understanding network access.`,
1067
+ ``,
1068
+ `## Integration Map`,
1069
+ ``,
1070
+ `| Integration | Direction | When | Protocol |`,
1071
+ `|---|---|---|---|`,
1072
+ `| <!-- FILL: name --> | Inbound/Outbound | <!-- FILL: when --> | <!-- FILL: HTTP/gRPC/stdio/etc --> |`,
1073
+ ``,
1074
+ `## File System Contract`,
1075
+ ``,
1076
+ `<!-- FILL: what paths does this project read/write? what is out of bounds? -->`,
1077
+ ``,
1078
+ `## Network Policy`,
1079
+ ``,
1080
+ `<!-- FILL: which operations require network access? which must work offline? -->`,
1081
+ ].join("\n"),
1082
+ },
1083
+ ];
1084
+ for (const stub of stubs) {
1085
+ const filePath = join(archDir, stub.file);
1086
+ if (!existsSync(filePath)) {
1087
+ writeFileSync(filePath, stub.content, "utf-8");
1088
+ written.push(`docs/architecture/${stub.file}`);
1089
+ }
1090
+ }
1091
+ // Suppress unused variable warning
1092
+ void projectName;
1093
+ return written;
1094
+ }
959
1095
  // ── Load cascade decisions ────────────────────────────────────────────
960
1096
  /**
961
1097
  * Load cascade decisions from forgecraft.yaml (convenience re-used in writers).