ai-spector 0.6.6 → 0.6.8
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.
- package/dist/commands/graph-impact.d.ts.map +1 -1
- package/dist/commands/graph-impact.js +10 -1
- package/dist/commands/graph-impact.js.map +1 -1
- package/dist/commands/graph-query.d.ts.map +1 -1
- package/dist/commands/graph-query.js +10 -0
- package/dist/commands/graph-query.js.map +1 -1
- package/dist/commands/template.d.ts.map +1 -1
- package/dist/commands/template.js +395 -13
- package/dist/commands/template.js.map +1 -1
- package/dist/graph/merge.d.ts.map +1 -1
- package/dist/graph/merge.js +6 -0
- package/dist/graph/merge.js.map +1 -1
- package/package.json +1 -1
- package/scaffold/claude/.claude/skills/ai-spector-generate-srs/skill.md +4 -0
- package/scaffold/claude/CLAUDE.md +4 -2
- package/scaffold/cursor/skills/_skill-router.md +3 -3
- package/scaffold/cursor/skills/ai-spector/references/generate-graph.md +39 -4
- package/scaffold/cursor/skills/ai-spector/references/generate-workflow.md +11 -3
- package/scaffold/cursor/skills/ai-spector-generate/SKILL.md +23 -4
- package/scaffold/cursor/skills/ai-spector-generate-srs/references/runbook.md +6 -0
- package/scaffold/cursor/skills/ai-spector-template-import/SKILL.md +6 -0
- package/scaffold/cursor/skills/ai-spector-template-import/references/runbook.md +58 -4
- package/scaffold/cursor/skills/ai-spector-template-import/references/skill-outline.md +266 -0
- package/schemas/schema.graph.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-impact.d.ts","sourceRoot":"","sources":["../../src/commands/graph-impact.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAwBD,wBAAgB,qBAAqB,CACnC,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC,EAChD,IAAI,EAAE,IAAI,CAAC,qBAAqB,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC,GACjE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,cAAc,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"graph-impact.d.ts","sourceRoot":"","sources":["../../src/commands/graph-impact.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAwBD,wBAAgB,qBAAqB,CACnC,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC,EAChD,IAAI,EAAE,IAAI,CAAC,qBAAqB,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC,GACjE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,cAAc,CAAA;CAAE,CA8BjD;AAED,wBAAsB,qBAAqB,CACzC,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC,EAChD,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,IAAI,CAAC,CA4Hf;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkD/E"}
|
|
@@ -25,7 +25,16 @@ export function resolveImpactOriginId(g, opts) {
|
|
|
25
25
|
if (opts.originId?.trim()) {
|
|
26
26
|
const id = opts.originId.trim();
|
|
27
27
|
if (!g.nodesById.has(id)) {
|
|
28
|
-
|
|
28
|
+
// Suggest document ids from the active graph to help agents using stale builtin seeds
|
|
29
|
+
const docNodes = [...g.nodesById.values()]
|
|
30
|
+
.filter((n) => n.type === "document")
|
|
31
|
+
.map((n) => n.id)
|
|
32
|
+
.slice(0, 6);
|
|
33
|
+
const suggestion = docNodes.length > 0
|
|
34
|
+
? `\nDocument ids in current graph:\n${docNodes.map((d) => ` ${d}`).join("\n")}\n` +
|
|
35
|
+
`Run \`npx ai-spector template inspect <pack> --json\` to list all active pack documents.`
|
|
36
|
+
: "";
|
|
37
|
+
throw new Error(`Unknown node id: ${id}${suggestion}`);
|
|
29
38
|
}
|
|
30
39
|
return { originId: id };
|
|
31
40
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-impact.js","sourceRoot":"","sources":["../../src/commands/graph-impact.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxF,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAClB,oBAAoB,GAErB,MAAM,qBAAqB,CAAC;AAe7B,MAAM,kBAAkB,GAAG,6BAA6B,CAAC;AAEzD,SAAS,uBAAuB,CAC9B,IAAkE;IAElE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;IAC/B,IAAI,IAAI,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;QACnE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC9C,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,yBAAyB,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACxE,OAAO,CACL,mEAAmE,IAAI,IAAI;YAC3E,0FAA0F;YAC1F,eAAe;YACf,0FAA0F;YAC1F,wCAAwC,IAAI,sCAAsC;YAClF,gDAAgD,QAAQ,EAAE,CAC3D,CAAC;IACJ,CAAC;IACD,OAAO,gGAAgG,CAAC;AAC1G,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,CAAgD,EAChD,IAAkE;IAElE,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC;QAC1B,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QAChC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"graph-impact.js","sourceRoot":"","sources":["../../src/commands/graph-impact.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-query.d.ts","sourceRoot":"","sources":["../../src/commands/graph-query.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,MAAM,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"graph-query.d.ts","sourceRoot":"","sources":["../../src/commands/graph-query.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,MAAM,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2C7E"}
|
|
@@ -2,6 +2,16 @@ import { loadInMemoryGraph } from "../graph/loadGraph.js";
|
|
|
2
2
|
import { querySubgraph } from "../graph/query.js";
|
|
3
3
|
export async function runGraphQuery(opts) {
|
|
4
4
|
const g = await loadInMemoryGraph(opts.graphPath);
|
|
5
|
+
if (!g.nodesById.has(opts.seedId)) {
|
|
6
|
+
const docNodes = [...g.nodesById.values()]
|
|
7
|
+
.filter((n) => n.type === "document")
|
|
8
|
+
.map((n) => n.id);
|
|
9
|
+
const suggestion = docNodes.length > 0
|
|
10
|
+
? `\nDocument ids in the current graph:\n${docNodes.map((d) => ` ${d}`).join("\n")}\n` +
|
|
11
|
+
`\nTip: if you switched packs, run \`npx ai-spector template inspect <pack>\` to list valid seed ids.`
|
|
12
|
+
: "\nThe graph appears empty — run \`npx ai-spector registry build\` then retry.";
|
|
13
|
+
throw new Error(`Unknown node id: ${opts.seedId}${suggestion}`);
|
|
14
|
+
}
|
|
5
15
|
const queryOpts = {
|
|
6
16
|
direction: opts.direction,
|
|
7
17
|
depth: opts.depth,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-query.js","sourceRoot":"","sources":["../../src/commands/graph-query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAqB,MAAM,mBAAmB,CAAC;AAYrE,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAA0B;IAC5D,MAAM,CAAC,GAAG,MAAM,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"graph-query.js","sourceRoot":"","sources":["../../src/commands/graph-query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAqB,MAAM,mBAAmB,CAAC;AAYrE,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAA0B;IAC5D,MAAM,CAAC,GAAG,MAAM,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAElD,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;aACvC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC;aACpC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpB,MAAM,UAAU,GACd,QAAQ,CAAC,MAAM,GAAG,CAAC;YACjB,CAAC,CAAC,yCAAyC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;gBACrF,sGAAsG;YACxG,CAAC,CAAC,+EAA+E,CAAC;QACtF,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,MAAM,SAAS,GAAiB;QAC9B,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,KAAK,EAAE,IAAI,CAAC,KAAK;KAClB,CAAC;IACF,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,SAAS,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAe,CAAC;IACjF,CAAC;IAED,MAAM,MAAM,GAAG,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAExD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7C,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,UAAU,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IAC/C,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,UAAU,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IAC/C,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,qBAAqB,MAAM,CAAC,eAAe,CAAC,MAAM,IAAI,CAAC,CAAC;IACpE,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/commands/template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/commands/template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAigCpC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,QAkFvD"}
|
|
@@ -27,11 +27,13 @@ async function rebuildRegistryAndGraph(root, config) {
|
|
|
27
27
|
const graph = bootstrapFromRegistry(registry);
|
|
28
28
|
await writeJson(graphPath, graph.toTraceabilityGraph());
|
|
29
29
|
const totalSections = registry.documents.reduce((n, d) => n + d.sections.length, 0);
|
|
30
|
+
const tg = graph.toTraceabilityGraph();
|
|
30
31
|
return {
|
|
31
32
|
documents: registry.documents.length,
|
|
32
33
|
sections: totalSections,
|
|
33
34
|
graphNodes: graph.nodesById.size,
|
|
34
|
-
graphEdges:
|
|
35
|
+
graphEdges: tg.edges.length,
|
|
36
|
+
documentIds: tg.nodes.filter((n) => n.type === "document").map((n) => n.id),
|
|
35
37
|
};
|
|
36
38
|
}
|
|
37
39
|
async function listInstalledPackNames(root) {
|
|
@@ -79,33 +81,396 @@ async function runTemplateList(opts) {
|
|
|
79
81
|
}
|
|
80
82
|
}
|
|
81
83
|
// ---------------------------------------------------------------------------
|
|
84
|
+
// DAG generation from pack manifest
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
/**
|
|
87
|
+
* Derive a `dag.srs.json` + `dag.srs.graph-seeds.json` pair from a pack manifest.
|
|
88
|
+
*
|
|
89
|
+
* - Non-perDomain documents → flat DAG nodes (no dependsOn; AI refines ordering).
|
|
90
|
+
* - perDomain documents → DAG nodes with `mode: "perDomainBreakout"` and the
|
|
91
|
+
* `perDomainKey` field so the generate skill knows to produce one file per domain item.
|
|
92
|
+
*/
|
|
93
|
+
function buildDagFromManifest(manifest) {
|
|
94
|
+
const packSlug = manifest.packName.replace(/[^a-z0-9]/gi, "-").toLowerCase();
|
|
95
|
+
const dagNodes = [];
|
|
96
|
+
const seedsMap = {};
|
|
97
|
+
const primaryDagIds = [];
|
|
98
|
+
// Pass 1: primary (non-perDomain) documents
|
|
99
|
+
for (const doc of manifest.documents) {
|
|
100
|
+
if (doc.perDomain)
|
|
101
|
+
continue;
|
|
102
|
+
const docSlug = doc.documentId.replace(/^doc\.[^.]+\./, "").replace(/\./g, "-");
|
|
103
|
+
const dagId = `${packSlug}.${docSlug}`;
|
|
104
|
+
const output = doc.output ?? doc.outputPattern ?? `${docSlug}.md`;
|
|
105
|
+
dagNodes.push({ id: dagId, template: doc.template, output, dependsOn: [] });
|
|
106
|
+
seedsMap[dagId] = doc.documentId;
|
|
107
|
+
primaryDagIds.push(dagId);
|
|
108
|
+
}
|
|
109
|
+
// Pass 2: perDomain breakout documents — one DAG node each, depends on primary docs
|
|
110
|
+
for (const doc of manifest.documents) {
|
|
111
|
+
if (!doc.perDomain)
|
|
112
|
+
continue;
|
|
113
|
+
const docSlug = doc.documentId.replace(/^doc\.[^.]+\./, "").replace(/\./g, "-");
|
|
114
|
+
const dagId = `${packSlug}.${docSlug}-breakout`;
|
|
115
|
+
const outputPattern = doc.outputPattern ?? doc.output ?? `${docSlug}/{id}.md`;
|
|
116
|
+
dagNodes.push({
|
|
117
|
+
id: dagId,
|
|
118
|
+
template: doc.template,
|
|
119
|
+
outputPattern,
|
|
120
|
+
dependsOn: primaryDagIds,
|
|
121
|
+
mode: "perDomainBreakout",
|
|
122
|
+
perDomainKey: doc.perDomain,
|
|
123
|
+
});
|
|
124
|
+
seedsMap[dagId] = doc.documentId;
|
|
125
|
+
}
|
|
126
|
+
const dag = { version: 1, root: "docs/srs", nodes: dagNodes };
|
|
127
|
+
// perDomain section: maps domain keys to graph node type + template doc id
|
|
128
|
+
// graphNodeType is the NodeType enum value in the graph (e.g. "requirement", "useCase")
|
|
129
|
+
const perDomainSeeds = {};
|
|
130
|
+
if (manifest.perDomainTemplates) {
|
|
131
|
+
for (const [domain, templateDocId] of Object.entries(manifest.perDomainTemplates)) {
|
|
132
|
+
if (!templateDocId)
|
|
133
|
+
continue;
|
|
134
|
+
perDomainSeeds[domain] = {
|
|
135
|
+
graphNodeType: domain,
|
|
136
|
+
templateDocId,
|
|
137
|
+
seedFromDomainId: true,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const seeds = {
|
|
142
|
+
version: 1,
|
|
143
|
+
description: `Map dag.srs.json node ids to graph document ids for pack "${manifest.packName}"`,
|
|
144
|
+
seeds: seedsMap,
|
|
145
|
+
perDomain: perDomainSeeds,
|
|
146
|
+
};
|
|
147
|
+
return { dag, seeds };
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Write a human+AI-readable generate-hints.md into the pack directory.
|
|
151
|
+
* Describes the generation waves and breakout templates so the generate skill
|
|
152
|
+
* can drive the correct output without reading the manifest directly.
|
|
153
|
+
*/
|
|
154
|
+
async function writeGenerateHints(packDir, manifest) {
|
|
155
|
+
const primaryDocs = manifest.documents.filter((d) => !d.perDomain);
|
|
156
|
+
const breakoutDocs = manifest.documents.filter((d) => d.perDomain);
|
|
157
|
+
const lines = [
|
|
158
|
+
`# Generate hints for pack: ${manifest.packName}`,
|
|
159
|
+
"",
|
|
160
|
+
`> Auto-generated by \`template install\`. Update manually if generation order changes.`,
|
|
161
|
+
"",
|
|
162
|
+
"## Wave 0 — Primary documents",
|
|
163
|
+
"",
|
|
164
|
+
"Generate these first (no inter-document dependencies assumed):",
|
|
165
|
+
"",
|
|
166
|
+
];
|
|
167
|
+
for (const doc of primaryDocs) {
|
|
168
|
+
const output = doc.output ?? doc.outputPattern ?? "(see manifest)";
|
|
169
|
+
lines.push(`- **${doc.documentId}** → \`${output}\``);
|
|
170
|
+
lines.push(` Template: \`${doc.template}\``);
|
|
171
|
+
}
|
|
172
|
+
if (breakoutDocs.length > 0) {
|
|
173
|
+
lines.push("", "## Wave 1 — Per-domain breakout files", "", "**Start only after Wave 0 is complete and `npx ai-spector index` has run.**", "", "### Required per-item workflow", "", "Generate one item at a time — do NOT script or loop over knowledge.json:", "", "```", "1. npx ai-spector graph query <itemId> --direction both --depth 4 --edges CONTEXT --json", "2. Read projectionPaths — these are the only allowed source files", "3. Load the breakout template (listed below)", "4. Write output file with specific, verifiable content from graph context", "5. Repeat for next item", "```", "", "After all items: batch merge `rendersTo` edges → `graph validate` → `index`.", "", "For 10+ items: use sub-agents (3–5 items each). Load `generate-workflow.md` → `context-management.md`.", "", "⛔ **Anti-pattern:** do not run a script over `knowledge.json` to stamp all files at once.", "Script output passes validate/index but contains boilerplate, not real domain content.", "See `.cursor/skills/ai-spector/references/generate-graph.md §F` for the rule.", "");
|
|
174
|
+
for (const doc of breakoutDocs) {
|
|
175
|
+
const output = doc.outputPattern ?? doc.output ?? "(see manifest)";
|
|
176
|
+
lines.push(`### ${doc.perDomain} — \`${doc.documentId}\``);
|
|
177
|
+
lines.push("");
|
|
178
|
+
lines.push(`- Output pattern: \`${output}\``);
|
|
179
|
+
lines.push(`- Template: \`.ai-spector/packs/${manifest.packName}/templates/${doc.template}\``);
|
|
180
|
+
lines.push(`- Graph node type: \`${doc.perDomain}\``);
|
|
181
|
+
lines.push("");
|
|
182
|
+
lines.push("Get the item list:");
|
|
183
|
+
lines.push("```bash");
|
|
184
|
+
lines.push(`npx ai-spector graph query ${manifest.documents[0]?.documentId ?? `doc.${manifest.packName}`} --json`);
|
|
185
|
+
lines.push(`# look for nodes where type === "${doc.perDomain}"`);
|
|
186
|
+
lines.push("```");
|
|
187
|
+
lines.push("");
|
|
188
|
+
}
|
|
189
|
+
if (manifest.defaultListedIn) {
|
|
190
|
+
lines.push("### Breakout list anchors", "");
|
|
191
|
+
for (const [domain, sectionId] of Object.entries(manifest.defaultListedIn)) {
|
|
192
|
+
lines.push(`- \`${domain}\` items are listed in: \`${sectionId}\``);
|
|
193
|
+
}
|
|
194
|
+
lines.push("");
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
lines.push("", "> This pack has no per-domain breakout templates.");
|
|
199
|
+
}
|
|
200
|
+
lines.push("", "## Reference", "", `- Pack manifest: \`.ai-spector/packs/${manifest.packName}/manifest.json\``, `- Inspect pack: \`npx ai-spector template inspect ${manifest.packName}\``, `- Active graph seeds: see \`.ai-spector/.docflow/config/dag.srs.graph-seeds.json\``);
|
|
201
|
+
await writeFile(join(packDir, "generate-hints.md"), lines.join("\n") + "\n", "utf8");
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Write a dedicated Cursor + Claude generate skill for the installed pack.
|
|
205
|
+
*
|
|
206
|
+
* Priority: if the AI wrote generate-skill.md to staging during the import workflow,
|
|
207
|
+
* use it directly (it's tailored to the specific template). Otherwise fall back to
|
|
208
|
+
* auto-generating a structural skeleton from the manifest.
|
|
209
|
+
*/
|
|
210
|
+
async function writePackGenerateSkill(root, manifest, stagedSkillPath) {
|
|
211
|
+
const name = manifest.packName;
|
|
212
|
+
const slug = name.replace(/[^a-z0-9]/gi, "-").toLowerCase();
|
|
213
|
+
// If the AI wrote a tailored skill during the import workflow, use it directly
|
|
214
|
+
if (stagedSkillPath && existsSync(stagedSkillPath)) {
|
|
215
|
+
const tailoredContent = await readFile(stagedSkillPath, "utf8");
|
|
216
|
+
const cursorSkillDir = join(root, ".cursor", "skills", `ai-spector-generate-${slug}`);
|
|
217
|
+
await mkdir(cursorSkillDir, { recursive: true });
|
|
218
|
+
await writeFile(join(cursorSkillDir, "SKILL.md"), tailoredContent, "utf8");
|
|
219
|
+
// Derive a minimal Claude skill from the tailored content (strip frontmatter + reformat)
|
|
220
|
+
const claudeContent = [
|
|
221
|
+
`---`,
|
|
222
|
+
`name: ai-spector-generate-${slug}`,
|
|
223
|
+
`description: "Generates documents for the ${name} template pack. Use the pack-specific Cursor skill for full details."`,
|
|
224
|
+
`---`,
|
|
225
|
+
``,
|
|
226
|
+
`# AI Spector — Generate (${name} pack)`,
|
|
227
|
+
``,
|
|
228
|
+
`## When to use`,
|
|
229
|
+
``,
|
|
230
|
+
`- Any request to generate, write, or update documents for pack \`${name}\``,
|
|
231
|
+
``,
|
|
232
|
+
`## Step 0 — Load pack context`,
|
|
233
|
+
``,
|
|
234
|
+
`Read these files before generating:`,
|
|
235
|
+
`1. \`.ai-spector/packs/${name}/generate-hints.md\``,
|
|
236
|
+
`2. \`.ai-spector/.docflow/config/dag.srs.json\``,
|
|
237
|
+
`3. \`.ai-spector/.docflow/config/dag.srs.graph-seeds.json\``,
|
|
238
|
+
``,
|
|
239
|
+
`Then follow the wave structure from \`generate-hints.md\`.`,
|
|
240
|
+
``,
|
|
241
|
+
`## Checklist`,
|
|
242
|
+
``,
|
|
243
|
+
`\`\`\``,
|
|
244
|
+
`- [ ] Loaded generate-hints.md and DAG config`,
|
|
245
|
+
`- [ ] graph validate passes before starting`,
|
|
246
|
+
`- [ ] Wave 0 primary documents generated`,
|
|
247
|
+
`- [ ] Wave 1 breakout files generated (if any)`,
|
|
248
|
+
`- [ ] npx ai-spector index run after each wave`,
|
|
249
|
+
`\`\`\``,
|
|
250
|
+
].join("\n");
|
|
251
|
+
const claudeSkillDir = join(root, ".claude", "skills", `ai-spector-generate-${slug}`);
|
|
252
|
+
await mkdir(claudeSkillDir, { recursive: true });
|
|
253
|
+
await writeFile(join(claudeSkillDir, "skill.md"), claudeContent + "\n", "utf8");
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
// Fallback: auto-generate a structural skeleton from the manifest
|
|
257
|
+
// Derive description from primary docs
|
|
258
|
+
const primaryDocs = manifest.documents.filter((d) => !d.perDomain);
|
|
259
|
+
const breakoutDocs = manifest.documents.filter((d) => d.perDomain);
|
|
260
|
+
const primaryOutputs = primaryDocs
|
|
261
|
+
.map((d) => d.output ?? d.outputPattern ?? d.template)
|
|
262
|
+
.slice(0, 3)
|
|
263
|
+
.join(", ");
|
|
264
|
+
const breakoutNote = breakoutDocs.length > 0
|
|
265
|
+
? ` Plus ${breakoutDocs.length} breakout template(s): ${breakoutDocs.map((d) => d.perDomain).join(", ")}.`
|
|
266
|
+
: "";
|
|
267
|
+
// Infer docs/ path for `paths:` frontmatter
|
|
268
|
+
const outputPaths = new Set();
|
|
269
|
+
for (const doc of manifest.documents) {
|
|
270
|
+
const p = (doc.output ?? doc.outputPattern ?? "docs/").split("/").slice(0, 2).join("/") + "/**";
|
|
271
|
+
outputPaths.add(p);
|
|
272
|
+
}
|
|
273
|
+
const pathsYaml = [...outputPaths].map((p) => ` - "${p}"`).join("\n");
|
|
274
|
+
const cursorSkillContent = [
|
|
275
|
+
`---`,
|
|
276
|
+
`name: ai-spector-generate-${slug}`,
|
|
277
|
+
`description: >-`,
|
|
278
|
+
` Generates documents for the ${name} template pack. Use when the user asks to`,
|
|
279
|
+
` generate, write, or update documents produced by this pack. Outputs: ${primaryOutputs}.${breakoutNote}`,
|
|
280
|
+
` Active pack: ${name}.`,
|
|
281
|
+
`paths:`,
|
|
282
|
+
pathsYaml,
|
|
283
|
+
`---`,
|
|
284
|
+
``,
|
|
285
|
+
`# Generate — ${name} pack`,
|
|
286
|
+
``,
|
|
287
|
+
`## Load at start (in order)`,
|
|
288
|
+
`1. \`.ai-spector/packs/${name}/generate-hints.md\``,
|
|
289
|
+
`2. \`.ai-spector/.docflow/config/dag.srs.json\``,
|
|
290
|
+
`3. \`.ai-spector/.docflow/config/dag.srs.graph-seeds.json\``,
|
|
291
|
+
`4. [\`generate-workflow.md\`](../ai-spector/references/generate-workflow.md)`,
|
|
292
|
+
``,
|
|
293
|
+
`## Pack`,
|
|
294
|
+
``,
|
|
295
|
+
`- Name: \`${name}\``,
|
|
296
|
+
`- Templates: \`.ai-spector/packs/${name}/templates/\``,
|
|
297
|
+
`- Manifest: \`.ai-spector/packs/${name}/manifest.json\``,
|
|
298
|
+
``,
|
|
299
|
+
`## Workflow`,
|
|
300
|
+
``,
|
|
301
|
+
`Follow the wave structure from \`generate-hints.md\`.`,
|
|
302
|
+
``,
|
|
303
|
+
`**Wave 0 — Primary documents:**`,
|
|
304
|
+
`- For each node in \`dag.srs.json\` where \`mode\` is not set:`,
|
|
305
|
+
` - Graph seed: look up DAG id in \`dag.srs.graph-seeds.json\` → use that document id`,
|
|
306
|
+
` - Template: \`.ai-spector/packs/${name}/templates/<template-file>\``,
|
|
307
|
+
` - Output: \`output\` or \`outputPattern\` from \`dag.srs.json\` node`,
|
|
308
|
+
` - **Do NOT** use builtin \`doc.srs.*\` ids — they do not exist in this pack's graph`,
|
|
309
|
+
``,
|
|
310
|
+
...(breakoutDocs.length > 0
|
|
311
|
+
? [
|
|
312
|
+
`**Wave 1 — Breakout files (${breakoutDocs.map((d) => d.perDomain).join(", ")}):**`,
|
|
313
|
+
``,
|
|
314
|
+
`Start only after Wave 0 is complete and \`npx ai-spector index\` has run.`,
|
|
315
|
+
``,
|
|
316
|
+
`**Required per-item workflow — one item at a time:**`,
|
|
317
|
+
``,
|
|
318
|
+
`\`\`\``,
|
|
319
|
+
`1. npx ai-spector graph query <itemId> --direction both --depth 4 --edges CONTEXT --json`,
|
|
320
|
+
`2. Read projectionPaths — these are the only allowed source files`,
|
|
321
|
+
`3. Write output file with specific, verifiable content from graph context`,
|
|
322
|
+
`4. Repeat for next item`,
|
|
323
|
+
`\`\`\``,
|
|
324
|
+
``,
|
|
325
|
+
`After all items are written: batch merge rendersTo edges, then validate + index.`,
|
|
326
|
+
``,
|
|
327
|
+
`⛔ **Do NOT generate breakout files via a script or loop over knowledge.json.**`,
|
|
328
|
+
`Script-generated files pass validate/index but contain boilerplate, not real content.`,
|
|
329
|
+
`See [\`generate-graph.md §F\`](../ai-spector/references/generate-graph.md) for the full rule.`,
|
|
330
|
+
``,
|
|
331
|
+
`For 10+ items: use sub-agents (3–5 items each). Load context-management.md.`,
|
|
332
|
+
``,
|
|
333
|
+
]
|
|
334
|
+
: []),
|
|
335
|
+
`## After each wave`,
|
|
336
|
+
``,
|
|
337
|
+
`\`\`\`bash`,
|
|
338
|
+
`npx ai-spector graph validate`,
|
|
339
|
+
`npx ai-spector index`,
|
|
340
|
+
`\`\`\``,
|
|
341
|
+
``,
|
|
342
|
+
`## On CLI failure`,
|
|
343
|
+
``,
|
|
344
|
+
`Load [\`cli-failures.md\`](../ai-spector/references/cli-failures.md).`,
|
|
345
|
+
``,
|
|
346
|
+
`"generate ${name}", "write docs", "generate documents" → this skill.`,
|
|
347
|
+
].join("\n");
|
|
348
|
+
const claudeSkillContent = [
|
|
349
|
+
`---`,
|
|
350
|
+
`name: ai-spector-generate-${slug}`,
|
|
351
|
+
`description: "Generates documents for the ${name} template pack. Use when the user asks to generate, write, or update documents. Outputs: ${primaryOutputs}.${breakoutNote}"`,
|
|
352
|
+
`---`,
|
|
353
|
+
``,
|
|
354
|
+
`# AI Spector — Generate (${name} pack)`,
|
|
355
|
+
``,
|
|
356
|
+
`## When to use`,
|
|
357
|
+
``,
|
|
358
|
+
`- "generate ${name}", "write docs", "generate documents" when pack \`${name}\` is active`,
|
|
359
|
+
``,
|
|
360
|
+
`## Step 0 — Load pack context`,
|
|
361
|
+
``,
|
|
362
|
+
`Read these files before generating anything:`,
|
|
363
|
+
`1. \`.ai-spector/packs/${name}/generate-hints.md\` — wave structure`,
|
|
364
|
+
`2. \`.ai-spector/.docflow/config/dag.srs.json\` — DAG node order`,
|
|
365
|
+
`3. \`.ai-spector/.docflow/config/dag.srs.graph-seeds.json\` — graph seed ids`,
|
|
366
|
+
``,
|
|
367
|
+
`## Workflow`,
|
|
368
|
+
``,
|
|
369
|
+
`Follow wave structure from \`generate-hints.md\`.`,
|
|
370
|
+
``,
|
|
371
|
+
`\`\`\``,
|
|
372
|
+
`1. Load generate-hints.md + DAG config`,
|
|
373
|
+
`2. Wave 0: generate primary documents (use seed ids from dag.srs.graph-seeds.json)`,
|
|
374
|
+
...(breakoutDocs.length > 0
|
|
375
|
+
? [`3. Wave 1: generate breakout files (one per graph node of perDomainKey type)`]
|
|
376
|
+
: []),
|
|
377
|
+
`${breakoutDocs.length > 0 ? "4" : "3"}. After each wave: npx ai-spector index`,
|
|
378
|
+
`${breakoutDocs.length > 0 ? "5" : "4"}. Final: npx ai-spector graph validate`,
|
|
379
|
+
`\`\`\``,
|
|
380
|
+
``,
|
|
381
|
+
`**Important:** Use graph seed ids from \`dag.srs.graph-seeds.json\`, NOT builtin \`doc.srs.*\` ids.`,
|
|
382
|
+
``,
|
|
383
|
+
`## Checklist`,
|
|
384
|
+
``,
|
|
385
|
+
`\`\`\``,
|
|
386
|
+
`- [ ] Loaded generate-hints.md and DAG config`,
|
|
387
|
+
`- [ ] graph validate passes before starting`,
|
|
388
|
+
`- [ ] Wave 0 primary documents generated`,
|
|
389
|
+
...(breakoutDocs.length > 0 ? [`- [ ] Wave 1 breakout files generated`] : []),
|
|
390
|
+
`- [ ] npx ai-spector index run after each wave`,
|
|
391
|
+
`- [ ] npx ai-spector graph validate run at end`,
|
|
392
|
+
`\`\`\``,
|
|
393
|
+
].join("\n");
|
|
394
|
+
// Write Cursor skill
|
|
395
|
+
const cursorSkillDir = join(root, ".cursor", "skills", `ai-spector-generate-${slug}`);
|
|
396
|
+
await mkdir(cursorSkillDir, { recursive: true });
|
|
397
|
+
await writeFile(join(cursorSkillDir, "SKILL.md"), cursorSkillContent + "\n", "utf8");
|
|
398
|
+
// Write Claude skill
|
|
399
|
+
const claudeSkillDir = join(root, ".claude", "skills", `ai-spector-generate-${slug}`);
|
|
400
|
+
await mkdir(claudeSkillDir, { recursive: true });
|
|
401
|
+
await writeFile(join(claudeSkillDir, "skill.md"), claudeSkillContent + "\n", "utf8");
|
|
402
|
+
}
|
|
403
|
+
async function writeDagFiles(root, dag, seeds) {
|
|
404
|
+
const dagDir = join(root, ".ai-spector", ".docflow", "config");
|
|
405
|
+
await mkdir(dagDir, { recursive: true });
|
|
406
|
+
await writeJson(join(dagDir, "dag.srs.json"), dag);
|
|
407
|
+
await writeJson(join(dagDir, "dag.srs.graph-seeds.json"), seeds);
|
|
408
|
+
}
|
|
409
|
+
async function restoreBuiltinDagFiles(root) {
|
|
410
|
+
const { scaffoldBundleRoot } = await import("../config/load.js");
|
|
411
|
+
const srcDir = join(scaffoldBundleRoot(), ".ai-spector", ".docflow", "config");
|
|
412
|
+
const destDir = join(root, ".ai-spector", ".docflow", "config");
|
|
413
|
+
await mkdir(destDir, { recursive: true });
|
|
414
|
+
for (const name of ["dag.srs.json", "dag.srs.graph-seeds.json"]) {
|
|
415
|
+
const src = join(srcDir, name);
|
|
416
|
+
const dest = join(destDir, name);
|
|
417
|
+
if (existsSync(src)) {
|
|
418
|
+
await copyFile(src, dest);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
// ---------------------------------------------------------------------------
|
|
82
423
|
// template use <name>
|
|
83
424
|
// ---------------------------------------------------------------------------
|
|
84
425
|
async function runTemplateUse(name, opts) {
|
|
85
426
|
const { root, config, configFile } = await loadConfigAndRoot(opts.cwd);
|
|
86
427
|
if (name === "builtin" || name === "default") {
|
|
87
|
-
// Remove packs.active
|
|
88
428
|
if (config.packs) {
|
|
89
429
|
delete config.packs;
|
|
90
430
|
}
|
|
91
431
|
await saveConfig(configFile, config);
|
|
92
|
-
console.log("Switched to builtin templates.
|
|
432
|
+
console.log("Switched to builtin templates. Restoring builtin DAG config...");
|
|
433
|
+
await restoreBuiltinDagFiles(root);
|
|
93
434
|
}
|
|
94
435
|
else {
|
|
95
|
-
// Verify pack exists
|
|
96
436
|
const manifestPath = join(root, ".ai-spector", "packs", name, "manifest.json");
|
|
97
437
|
if (!existsSync(manifestPath)) {
|
|
98
438
|
console.error(`Pack "${name}" not found. Expected manifest at: ${manifestPath}`);
|
|
99
439
|
process.exitCode = 1;
|
|
100
440
|
return;
|
|
101
441
|
}
|
|
442
|
+
const manifest = await readJson(manifestPath);
|
|
102
443
|
config.packs = { active: name };
|
|
103
444
|
await saveConfig(configFile, config);
|
|
104
|
-
console.log(`Switched to pack "${name}". Rebuilding registry and
|
|
445
|
+
console.log(`Switched to pack "${name}". Rebuilding registry, graph, and DAG config...`);
|
|
446
|
+
// Write pack-derived DAG files, generate-hints.md, and dedicated generate skill
|
|
447
|
+
const packDir = join(root, ".ai-spector", "packs", name);
|
|
448
|
+
const { dag, seeds } = buildDagFromManifest(manifest);
|
|
449
|
+
await writeDagFiles(root, dag, seeds);
|
|
450
|
+
await writeGenerateHints(packDir, manifest);
|
|
451
|
+
await writePackGenerateSkill(root, manifest);
|
|
105
452
|
}
|
|
106
453
|
const stats = await rebuildRegistryAndGraph(root, config);
|
|
107
454
|
console.log(`Done. ${stats.documents} documents, ${stats.sections} sections, ` +
|
|
108
455
|
`${stats.graphNodes} graph nodes, ${stats.graphEdges} edges.`);
|
|
456
|
+
const activePack = config.packs?.active ?? "builtin";
|
|
457
|
+
const docIdList = stats.documentIds?.map((id) => ` - ${id}`).join("\n") ??
|
|
458
|
+
` (run \`npx ai-spector template inspect ${activePack}\` to list them)`;
|
|
459
|
+
console.log(`Active graph document ids (valid query seeds):\n${docIdList}`);
|
|
460
|
+
if (activePack !== "builtin") {
|
|
461
|
+
const activeManifestPath = join(root, ".ai-spector", "packs", activePack, "manifest.json");
|
|
462
|
+
if (existsSync(activeManifestPath)) {
|
|
463
|
+
const activeManifest = await readJson(activeManifestPath);
|
|
464
|
+
const breakoutDocs = activeManifest.documents.filter((d) => d.perDomain);
|
|
465
|
+
if (breakoutDocs.length > 0) {
|
|
466
|
+
console.log(`\n⚠ Pack has ${breakoutDocs.length} breakout template(s) — generate primary docs first, then ask:\n` +
|
|
467
|
+
breakoutDocs.map((d) => ` "generate breakout ${d.perDomain} files from the graph"`).join("\n") +
|
|
468
|
+
`\n See: .ai-spector/packs/${activePack}/generate-hints.md`);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
console.log(`\nNote: .cursor/skills/ai-spector-generate-srs/references/runbook.md still references` +
|
|
472
|
+
`\nbuiltin ids — update it or ask the agent to use the ids above when querying the graph.`);
|
|
473
|
+
}
|
|
109
474
|
}
|
|
110
475
|
// ---------------------------------------------------------------------------
|
|
111
476
|
// template inspect <name>
|
|
@@ -300,16 +665,15 @@ async function runTemplateInstall(opts) {
|
|
|
300
665
|
await saveConfig(configFile, config);
|
|
301
666
|
throw err;
|
|
302
667
|
}
|
|
303
|
-
//
|
|
668
|
+
// Write pack-derived DAG files, generate-hints.md, and dedicated generate skill
|
|
669
|
+
const { dag, seeds } = buildDagFromManifest(finalManifest);
|
|
670
|
+
await writeDagFiles(root, dag, seeds);
|
|
671
|
+
await writeGenerateHints(destDir, finalManifest);
|
|
672
|
+
const stagedSkillPath = join(stagingDir, "generate-skill.md");
|
|
673
|
+
await writePackGenerateSkill(root, finalManifest, stagedSkillPath);
|
|
674
|
+
// skill-hints.md — if the AI wrote one in staging, copy to pack dir
|
|
304
675
|
const skillHintsPath = join(stagingDir, "skill-hints.md");
|
|
305
676
|
if (await pathExists(skillHintsPath)) {
|
|
306
|
-
const hints = await readFile(skillHintsPath, "utf8");
|
|
307
|
-
const cursorSkillPath = join(root, ".cursor/skills/ai-spector-generate/SKILL.md");
|
|
308
|
-
if (await pathExists(cursorSkillPath)) {
|
|
309
|
-
const existing = await readFile(cursorSkillPath, "utf8");
|
|
310
|
-
await writeFile(cursorSkillPath, existing + "\n\n---\n\n## Pack hints: " + packName + "\n\n" + hints);
|
|
311
|
-
console.log(" Updated .cursor/skills/ai-spector-generate/SKILL.md with pack hints.");
|
|
312
|
-
}
|
|
313
677
|
await copyFile(skillHintsPath, join(destDir, "skill-hints.md"));
|
|
314
678
|
}
|
|
315
679
|
// Clear staging
|
|
@@ -320,8 +684,26 @@ async function runTemplateInstall(opts) {
|
|
|
320
684
|
console.log(` Sections : ${stats.sections}`);
|
|
321
685
|
console.log(` Graph : ${stats.graphNodes} nodes, ${stats.graphEdges} edges`);
|
|
322
686
|
console.log();
|
|
687
|
+
const usedAiSkill = existsSync(stagedSkillPath);
|
|
323
688
|
console.log(` Templates → .ai-spector/packs/${packName}/templates/`);
|
|
324
689
|
console.log(` Active → docflow.config.json updated`);
|
|
690
|
+
console.log(` DAG → .ai-spector/.docflow/config/dag.srs.json updated`);
|
|
691
|
+
console.log(` Skill → .cursor/skills/ai-spector-generate-${packName}/SKILL.md ${usedAiSkill ? "(AI-written)" : "(auto-generated from manifest)"}`);
|
|
692
|
+
console.log(` → .claude/skills/ai-spector-generate-${packName}/skill.md`);
|
|
693
|
+
const breakoutDocs = finalManifest.documents.filter((d) => d.perDomain);
|
|
694
|
+
if (breakoutDocs.length > 0) {
|
|
695
|
+
console.log();
|
|
696
|
+
console.log(` ⚠ This pack includes ${breakoutDocs.length} per-domain breakout template(s):`);
|
|
697
|
+
for (const d of breakoutDocs) {
|
|
698
|
+
console.log(` ${d.documentId} (perDomain: ${d.perDomain})`);
|
|
699
|
+
console.log(` output: ${d.outputPattern ?? d.output ?? "(see manifest)"}`);
|
|
700
|
+
}
|
|
701
|
+
console.log();
|
|
702
|
+
console.log(` Breakout files are NOT generated automatically.`);
|
|
703
|
+
console.log(` After "generate SRS", ask your AI IDE:`);
|
|
704
|
+
console.log(` "generate breakout ${breakoutDocs[0]?.perDomain ?? "requirement"} files from the graph"`);
|
|
705
|
+
console.log(` Reference: .ai-spector/packs/${packName}/generate-hints.md`);
|
|
706
|
+
}
|
|
325
707
|
console.log();
|
|
326
708
|
console.log(`Next: ask your AI to "generate <document>" to use the new template.`);
|
|
327
709
|
}
|