ai-spector 0.9.20 → 0.9.21

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 (100) hide show
  1. package/dist/cli.js +27 -3
  2. package/dist/cli.js.map +1 -1
  3. package/dist/core/adopt/bootstrap.d.ts.map +1 -1
  4. package/dist/core/adopt/bootstrap.js +31 -0
  5. package/dist/core/adopt/bootstrap.js.map +1 -1
  6. package/dist/core/docops/assess.d.ts.map +1 -1
  7. package/dist/core/docops/assess.js +28 -1
  8. package/dist/core/docops/assess.js.map +1 -1
  9. package/dist/core/docops/capabilities.d.ts +1 -1
  10. package/dist/core/docops/capabilities.d.ts.map +1 -1
  11. package/dist/core/docops/capabilities.js +0 -1
  12. package/dist/core/docops/capabilities.js.map +1 -1
  13. package/dist/core/docops/check.d.ts +26 -0
  14. package/dist/core/docops/check.d.ts.map +1 -0
  15. package/dist/core/docops/check.js +280 -0
  16. package/dist/core/docops/check.js.map +1 -0
  17. package/dist/core/docops/layer-defaults.d.ts +2 -0
  18. package/dist/core/docops/layer-defaults.d.ts.map +1 -1
  19. package/dist/core/docops/layer-defaults.js +7 -0
  20. package/dist/core/docops/layer-defaults.js.map +1 -1
  21. package/dist/core/docops/layout-classify.d.ts +24 -0
  22. package/dist/core/docops/layout-classify.d.ts.map +1 -0
  23. package/dist/core/docops/layout-classify.js +293 -0
  24. package/dist/core/docops/layout-classify.js.map +1 -0
  25. package/dist/core/docops/layout.d.ts +27 -0
  26. package/dist/core/docops/layout.d.ts.map +1 -0
  27. package/dist/core/docops/layout.js +181 -0
  28. package/dist/core/docops/layout.js.map +1 -0
  29. package/dist/core/docops/migrate.d.ts +2 -0
  30. package/dist/core/docops/migrate.d.ts.map +1 -1
  31. package/dist/core/docops/migrate.js +24 -2
  32. package/dist/core/docops/migrate.js.map +1 -1
  33. package/dist/core/operations/check.d.ts.map +1 -1
  34. package/dist/core/operations/check.js +11 -19
  35. package/dist/core/operations/check.js.map +1 -1
  36. package/dist/core/operations/docops.d.ts +10 -0
  37. package/dist/core/operations/docops.d.ts.map +1 -1
  38. package/dist/core/operations/docops.js +76 -0
  39. package/dist/core/operations/docops.js.map +1 -1
  40. package/dist/core/operations/task-gates.d.ts.map +1 -1
  41. package/dist/core/operations/task-gates.js +0 -15
  42. package/dist/core/operations/task-gates.js.map +1 -1
  43. package/dist/core/operations/task-templates.d.ts +2 -2
  44. package/dist/core/operations/task-templates.d.ts.map +1 -1
  45. package/dist/core/operations/task-templates.js +0 -20
  46. package/dist/core/operations/task-templates.js.map +1 -1
  47. package/dist/core/operations/task.d.ts +0 -14
  48. package/dist/core/operations/task.d.ts.map +1 -1
  49. package/dist/core/operations/task.js +0 -58
  50. package/dist/core/operations/task.js.map +1 -1
  51. package/dist/core/operations/work.d.ts +1 -2
  52. package/dist/core/operations/work.d.ts.map +1 -1
  53. package/dist/core/operations/work.js +1 -21
  54. package/dist/core/operations/work.js.map +1 -1
  55. package/dist/core/upgrade/apply.d.ts.map +1 -1
  56. package/dist/core/upgrade/apply.js +11 -0
  57. package/dist/core/upgrade/apply.js.map +1 -1
  58. package/dist/core/upgrade/checklist.json +10 -0
  59. package/dist/core/upgrade/detect.d.ts.map +1 -1
  60. package/dist/core/upgrade/detect.js +20 -0
  61. package/dist/core/upgrade/detect.js.map +1 -1
  62. package/dist/core/upgrade/types.d.ts +1 -1
  63. package/dist/core/upgrade/types.d.ts.map +1 -1
  64. package/dist/core/workflow/active-worker.js +1 -1
  65. package/dist/core/workflow/active-worker.js.map +1 -1
  66. package/dist/core/workflow/route-intent-examples.d.ts.map +1 -1
  67. package/dist/core/workflow/route-intent-examples.js +2 -3
  68. package/dist/core/workflow/route-intent-examples.js.map +1 -1
  69. package/dist/core/workflow/route-intent.d.ts +1 -1
  70. package/dist/core/workflow/route-intent.d.ts.map +1 -1
  71. package/dist/core/workflow/route-intent.js +8 -8
  72. package/dist/core/workflow/route-intent.js.map +1 -1
  73. package/dist/interfaces/mcp/schemas.d.ts +0 -344
  74. package/dist/interfaces/mcp/schemas.d.ts.map +1 -1
  75. package/dist/interfaces/mcp/schemas.js +3 -68
  76. package/dist/interfaces/mcp/schemas.js.map +1 -1
  77. package/dist/interfaces/mcp/server.js +3 -61
  78. package/dist/interfaces/mcp/server.js.map +1 -1
  79. package/dist/interfaces/mcp/tool-descriptions.d.ts +0 -10
  80. package/dist/interfaces/mcp/tool-descriptions.d.ts.map +1 -1
  81. package/dist/interfaces/mcp/tool-descriptions.js +3 -52
  82. package/dist/interfaces/mcp/tool-descriptions.js.map +1 -1
  83. package/dist/interfaces/mcp/tool-names.d.ts +1 -1
  84. package/dist/interfaces/mcp/tool-names.d.ts.map +1 -1
  85. package/dist/interfaces/mcp/tool-names.js +0 -8
  86. package/dist/interfaces/mcp/tool-names.js.map +1 -1
  87. package/dist/interfaces/mcp/tools/task.d.ts +1 -2
  88. package/dist/interfaces/mcp/tools/task.d.ts.map +1 -1
  89. package/dist/interfaces/mcp/tools/task.js +1 -10
  90. package/dist/interfaces/mcp/tools/task.js.map +1 -1
  91. package/dist/interfaces/sdk/index.d.ts +2 -2
  92. package/dist/interfaces/sdk/index.d.ts.map +1 -1
  93. package/dist/interfaces/sdk/index.js +2 -2
  94. package/dist/interfaces/sdk/index.js.map +1 -1
  95. package/package.json +1 -1
  96. package/scaffold/.ai-spector/.docflow/config/workspace/rules.json +1 -1
  97. package/scaffold/claude/.claude/skills/ai-spector/references/runbook.md +26 -62
  98. package/scaffold/cursor/skills/ai-spector/references/runbook.md +26 -62
  99. package/scaffold/claude/.claude/workflows/adopt.md +0 -14
  100. package/scaffold/cursor/commands/adopt.md +0 -14
@@ -0,0 +1,293 @@
1
+ import { readFileSync, readdirSync, statSync } from "node:fs";
2
+ import { basename, join } from "node:path";
3
+ import { loadBasicDesignListManifest, loadDocumentsManifest, packageBundleRoot, } from "../config/load.js";
4
+ const FILENAME_WEIGHT = 0.55;
5
+ const HEADING_WEIGHT = 0.45;
6
+ const LANG_CODE = /^[a-z]{2,3}(?:-[a-z]{2})?$/i;
7
+ const LAYER_PREFIX = /^(?:docs\/srs|docs\/basic-design|docs\/detail-design|docs\/dd|docs\/detail_design)\/([^/]+)(?:\/(.+))?$/;
8
+ const DOMAIN_ID_RE = /\b(UC|F|SCR|API)-(\d+)\b/gi;
9
+ const PROTOTYPE_SOURCE_DIRS = ["prototype/src", "prototype", "docs/prototype"];
10
+ const SPA_FRAMEWORKS = ["react", "vue", "@vue/", "next", "nuxt", "svelte"];
11
+ const PROTOTYPE_EXTENSIONS = new Set([".html", ".htm", ".tsx", ".jsx", ".vue"]);
12
+ let srsManifestCache = null;
13
+ let basicDesignManifestCache = null;
14
+ let detailDesignManifestCache = null;
15
+ function readManifestSync(filename) {
16
+ const raw = readFileSync(join(packageBundleRoot(), filename), "utf8");
17
+ const manifest = JSON.parse(raw);
18
+ if (!manifest.templatesDir || !Array.isArray(manifest.documents)) {
19
+ throw new Error(`Invalid ${filename} in ${packageBundleRoot()}`);
20
+ }
21
+ return manifest;
22
+ }
23
+ function firstHeadingFromTemplate(templatesDir, template) {
24
+ const path = join(packageBundleRoot(), templatesDir, template);
25
+ try {
26
+ const content = readFileSync(path, "utf8");
27
+ for (const line of content.split(/\r?\n/)) {
28
+ const match = line.match(/^#{1,6}\s+(.+?)\s*$/);
29
+ if (match) {
30
+ return match[1].replace(/\{[^}]+\}/g, "").trim();
31
+ }
32
+ }
33
+ }
34
+ catch {
35
+ // fall through
36
+ }
37
+ return headingFromFilename(template);
38
+ }
39
+ function headingFromFilename(template) {
40
+ const stem = template.replace(/\.md$/i, "").replace(/-template$/i, "");
41
+ const parts = stem.split("-").filter((part) => !/^\d+$/.test(part));
42
+ return parts
43
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
44
+ .join(" ")
45
+ .trim();
46
+ }
47
+ function buildManifestEntries(manifest) {
48
+ return manifest.documents.map((doc) => ({
49
+ template: doc.template,
50
+ heading: firstHeadingFromTemplate(manifest.templatesDir, doc.template),
51
+ }));
52
+ }
53
+ function getManifestEntries(layer) {
54
+ if (layer === "srs") {
55
+ if (!srsManifestCache) {
56
+ srsManifestCache = buildManifestEntries(readManifestSync("documents.json"));
57
+ }
58
+ return srsManifestCache;
59
+ }
60
+ if (layer === "basic-design") {
61
+ if (!basicDesignManifestCache) {
62
+ basicDesignManifestCache = buildManifestEntries(readManifestSync("documents-basic-design.json"));
63
+ }
64
+ return basicDesignManifestCache;
65
+ }
66
+ if (!detailDesignManifestCache) {
67
+ detailDesignManifestCache = buildManifestEntries(readManifestSync("documents-detail-design.json"));
68
+ }
69
+ return detailDesignManifestCache;
70
+ }
71
+ function normalizeLabel(text) {
72
+ return text
73
+ .replace(/^[\d.]+\s*/, "")
74
+ .toLowerCase()
75
+ .replace(/[^\p{L}\p{N}\s-]/gu, "")
76
+ .trim()
77
+ .replace(/\s+/g, "-")
78
+ .replace(/-+/g, "-");
79
+ }
80
+ function normalizeFilename(name) {
81
+ return basename(name).replace(/\.md$/i, "").toLowerCase();
82
+ }
83
+ function filenameStem(name) {
84
+ return normalizeFilename(name).replace(/^\d+-/, "").replace(/-template$/, "");
85
+ }
86
+ function textSimilarity(a, b) {
87
+ const left = normalizeLabel(a);
88
+ const right = normalizeLabel(b);
89
+ if (!left || !right)
90
+ return 0;
91
+ if (left === right)
92
+ return 1;
93
+ if (left.includes(right) || right.includes(left))
94
+ return 0.9;
95
+ const leftTokens = new Set(left.split("-").filter(Boolean));
96
+ const rightTokens = new Set(right.split("-").filter(Boolean));
97
+ const union = new Set([...leftTokens, ...rightTokens]);
98
+ let intersection = 0;
99
+ for (const token of leftTokens) {
100
+ if (rightTokens.has(token))
101
+ intersection += 1;
102
+ }
103
+ return union.size === 0 ? 0 : intersection / union.size;
104
+ }
105
+ function firstHeadingText(headings) {
106
+ const h1 = headings.find((heading) => heading.depth === 1);
107
+ if (h1)
108
+ return h1.text.trim();
109
+ return headings[0]?.text.trim() ?? "";
110
+ }
111
+ function scoreAgainstManifestEntry(file, entry) {
112
+ const filenameScore = textSimilarity(filenameStem(file.relativePath), filenameStem(entry.template));
113
+ const headingScore = textSimilarity(firstHeadingText(file.headings), entry.heading);
114
+ return FILENAME_WEIGHT * filenameScore + HEADING_WEIGHT * headingScore;
115
+ }
116
+ export function scoreBuiltinMatch(file, layer) {
117
+ const entries = getManifestEntries(layer);
118
+ let best = 0;
119
+ for (const entry of entries) {
120
+ best = Math.max(best, scoreAgainstManifestEntry(file, entry));
121
+ }
122
+ return best;
123
+ }
124
+ export function classifyLayer(files, layer) {
125
+ if (files.length === 0)
126
+ return "missing";
127
+ const scores = files.map((file) => scoreBuiltinMatch(file, layer));
128
+ const alignedCount = scores.filter((score) => score >= 0.6).length;
129
+ const alignedRatio = alignedCount / files.length;
130
+ const averageScore = scores.reduce((sum, score) => sum + score, 0) / scores.length;
131
+ if (alignedRatio >= 0.7)
132
+ return "builtin-aligned";
133
+ const hasDomainIds = files.some((file) => {
134
+ const ids = file.ids ?? (file.content ? extractDomainIds(file.content) : []);
135
+ return ids.length > 0;
136
+ });
137
+ if (hasDomainIds && averageScore < 0.7)
138
+ return "reshaped";
139
+ return "reshaped";
140
+ }
141
+ export function detectLanguageLayout(paths) {
142
+ const normalized = paths.map((path) => path.replace(/\\/g, "/"));
143
+ const langs = new Set();
144
+ let flatCount = 0;
145
+ let langFolderCount = 0;
146
+ for (const path of normalized) {
147
+ const match = path.match(LAYER_PREFIX);
148
+ if (!match)
149
+ continue;
150
+ const segment = match[1];
151
+ const remainder = match[2];
152
+ if (!remainder) {
153
+ if (segment.endsWith(".md"))
154
+ flatCount += 1;
155
+ continue;
156
+ }
157
+ if (LANG_CODE.test(segment)) {
158
+ langs.add(segment.toLowerCase());
159
+ langFolderCount += 1;
160
+ }
161
+ else if (segment.endsWith(".md")) {
162
+ flatCount += 1;
163
+ }
164
+ }
165
+ const detected = [...langs].sort();
166
+ if (langFolderCount > 0 && flatCount > 0) {
167
+ return { detected, strategy: "mixed" };
168
+ }
169
+ if (langFolderCount > 0) {
170
+ return { detected, strategy: "per-lang-folders" };
171
+ }
172
+ return { detected: [], strategy: "flat" };
173
+ }
174
+ export function extractDomainIds(content) {
175
+ const seen = new Set();
176
+ const ids = [];
177
+ for (const match of content.matchAll(DOMAIN_ID_RE)) {
178
+ const id = `${match[1].toUpperCase()}-${match[2]}`;
179
+ if (seen.has(id))
180
+ continue;
181
+ seen.add(id);
182
+ ids.push(id);
183
+ }
184
+ return ids;
185
+ }
186
+ function collectPrototypeFiles(root) {
187
+ const byRoot = new Map();
188
+ for (const relDir of PROTOTYPE_SOURCE_DIRS) {
189
+ const absDir = join(root, relDir);
190
+ const files = [];
191
+ walkPrototypeDir(absDir, files);
192
+ if (files.length > 0)
193
+ byRoot.set(relDir, files);
194
+ }
195
+ return byRoot;
196
+ }
197
+ function walkPrototypeDir(currentDir, files) {
198
+ let entries;
199
+ try {
200
+ entries = readdirSync(currentDir, { withFileTypes: true });
201
+ }
202
+ catch {
203
+ return;
204
+ }
205
+ for (const entry of entries) {
206
+ if (entry.name.startsWith("."))
207
+ continue;
208
+ const absPath = join(currentDir, entry.name);
209
+ if (entry.isDirectory()) {
210
+ if (entry.name === "node_modules")
211
+ continue;
212
+ walkPrototypeDir(absPath, files);
213
+ continue;
214
+ }
215
+ const ext = entry.name.slice(entry.name.lastIndexOf(".")).toLowerCase();
216
+ if (PROTOTYPE_EXTENSIONS.has(ext)) {
217
+ files.push(absPath);
218
+ }
219
+ }
220
+ }
221
+ function hasSpaDependency(packageJsonPath) {
222
+ try {
223
+ const pkg = JSON.parse(readFileSync(packageJsonPath, "utf8"));
224
+ const deps = {
225
+ ...pkg.dependencies,
226
+ ...pkg.devDependencies,
227
+ };
228
+ return Object.keys(deps).some((name) => SPA_FRAMEWORKS.some((framework) => framework.endsWith("/") ? name.startsWith(framework) : name === framework));
229
+ }
230
+ catch {
231
+ return false;
232
+ }
233
+ }
234
+ function classifyPrototypeFiles(filesByRoot, root) {
235
+ const prototypePkg = join(root, "prototype", "package.json");
236
+ if (pathExistsSync(prototypePkg) && hasSpaDependency(prototypePkg)) {
237
+ return "spa";
238
+ }
239
+ const allFiles = [...filesByRoot.values()].flat();
240
+ const hasSpaSource = allFiles.some((file) => {
241
+ const ext = file.slice(file.lastIndexOf(".")).toLowerCase();
242
+ return ext === ".tsx" || ext === ".jsx" || ext === ".vue";
243
+ });
244
+ if (hasSpaSource)
245
+ return "spa";
246
+ const hasHtml = allFiles.some((file) => {
247
+ const ext = file.slice(file.lastIndexOf(".")).toLowerCase();
248
+ return ext === ".html" || ext === ".htm";
249
+ });
250
+ if (hasHtml) {
251
+ const canonical = [
252
+ ...(filesByRoot.get("prototype") ?? []),
253
+ ...(filesByRoot.get("prototype/src") ?? []),
254
+ ];
255
+ const legacy = filesByRoot.get("docs/prototype") ?? [];
256
+ if (legacy.length > 0 && canonical.length === 0)
257
+ return "disconnected";
258
+ return "static-html";
259
+ }
260
+ return "missing";
261
+ }
262
+ function pathExistsSync(path) {
263
+ try {
264
+ statSync(path);
265
+ return true;
266
+ }
267
+ catch {
268
+ return false;
269
+ }
270
+ }
271
+ export function classifyDataSource(srsMdCount, dataSourceMdCount) {
272
+ if (dataSourceMdCount === 0)
273
+ return "absent";
274
+ if (srsMdCount === 0)
275
+ return "present";
276
+ if (dataSourceMdCount >= srsMdCount)
277
+ return "present";
278
+ return "partial";
279
+ }
280
+ export async function classifyPrototype(root) {
281
+ await Promise.all([loadDocumentsManifest(), loadBasicDesignListManifest()]);
282
+ const filesByRoot = collectPrototypeFiles(root);
283
+ if (filesByRoot.size === 0)
284
+ return "missing";
285
+ return classifyPrototypeFiles(filesByRoot, root);
286
+ }
287
+ /** Reset cached manifest entries — for tests only. */
288
+ export function resetLayoutClassifyCacheForTests() {
289
+ srsManifestCache = null;
290
+ basicDesignManifestCache = null;
291
+ detailDesignManifestCache = null;
292
+ }
293
+ //# sourceMappingURL=layout-classify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout-classify.js","sourceRoot":"","sources":["../../../src/core/docops/layout-classify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { type DocopsLangStrategy, type DocopsLayerClass } from "./layout-classify.js";
2
+ declare const LAYER_KEYS: readonly ["srs", "basicDesign", "detailDesign"];
3
+ type LayerKey = (typeof LAYER_KEYS)[number];
4
+ export interface DocopsLayerOnDisk {
5
+ configuredPath: string | null;
6
+ roots: Array<{
7
+ path: string;
8
+ fileCount: number;
9
+ }>;
10
+ languageLayout: DocopsLangStrategy;
11
+ detectedLanguages: string[];
12
+ classification: DocopsLayerClass;
13
+ }
14
+ export interface DocopsLayoutProbeResult {
15
+ probedAt: string;
16
+ configuredPaths: Partial<Record<LayerKey, string>>;
17
+ onDisk: Partial<Record<LayerKey, DocopsLayerOnDisk>>;
18
+ dataSource: {
19
+ path: string;
20
+ fileCount: number;
21
+ } | null;
22
+ suggestions: string[];
23
+ agentPrompt: string;
24
+ }
25
+ export declare function probeDocopsLayout(projectRoot?: string): Promise<DocopsLayoutProbeResult>;
26
+ export {};
27
+ //# sourceMappingURL=layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/core/docops/layout.ts"],"names":[],"mappings":"AAKA,OAAO,EAML,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAE9B,QAAA,MAAM,UAAU,iDAAkD,CAAC;AACnE,KAAK,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAQ5C,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,cAAc,EAAE,kBAAkB,CAAC;IACnC,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,cAAc,EAAE,gBAAgB,CAAC;CAClC;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC,CAAC;IACrD,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACvD,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB;AAqID,wBAAsB,iBAAiB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC,CA6E9F"}
@@ -0,0 +1,181 @@
1
+ import { readdir } from "node:fs/promises";
2
+ import { join, relative } from "node:path";
3
+ import { findProjectRoot } from "../config/load.js";
4
+ import { pathExists } from "../util/fs.js";
5
+ import { readDocopsConfig } from "./config.js";
6
+ import { classifyDataSource, classifyLayer, classifyPrototype, detectLanguageLayout, } from "./layout-classify.js";
7
+ const LAYER_KEYS = ["srs", "basicDesign", "detailDesign"];
8
+ const DISCOVERY_ALIASES = {
9
+ srs: ["docs/srs"],
10
+ basicDesign: ["docs/basic-design", "docs/bd", "docs/basic_design"],
11
+ detailDesign: ["docs/detail-design", "docs/dd", "docs/detail_design"],
12
+ };
13
+ async function collectMdFiles(absDir) {
14
+ if (!(await pathExists(absDir)))
15
+ return [];
16
+ const results = [];
17
+ async function walk(current) {
18
+ let entries;
19
+ try {
20
+ entries = await readdir(current, { withFileTypes: true });
21
+ }
22
+ catch {
23
+ return;
24
+ }
25
+ for (const entry of entries) {
26
+ if (entry.name.startsWith("."))
27
+ continue;
28
+ const full = join(current, entry.name);
29
+ if (entry.isDirectory()) {
30
+ if (entry.name === "node_modules")
31
+ continue;
32
+ await walk(full);
33
+ continue;
34
+ }
35
+ if (entry.isFile() && entry.name.endsWith(".md")) {
36
+ results.push(full);
37
+ }
38
+ }
39
+ }
40
+ await walk(absDir);
41
+ return results.sort();
42
+ }
43
+ function stripLayerPrefix(layerKey, projectRel) {
44
+ const prefixes = {
45
+ srs: /^docs\/srs\//,
46
+ basicDesign: /^docs\/(?:basic-design|bd|basic_design)\//,
47
+ detailDesign: /^docs\/(?:detail-design|dd|detail_design)\//,
48
+ };
49
+ return projectRel.replace(prefixes[layerKey], "");
50
+ }
51
+ function buildSuggestions(result) {
52
+ const lines = [];
53
+ for (const key of LAYER_KEYS) {
54
+ const layer = result.onDisk[key];
55
+ const configured = result.configuredPaths[key];
56
+ if (!layer)
57
+ continue;
58
+ const primaryRoot = layer.roots[0];
59
+ if (!primaryRoot || primaryRoot.fileCount === 0) {
60
+ if (configured) {
61
+ lines.push(`No markdown under configured docTypes.${key}.path (${configured}) — add docs or point path at an existing folder.`);
62
+ }
63
+ continue;
64
+ }
65
+ const topRoot = layer.roots.reduce((a, b) => (b.fileCount > a.fileCount ? b : a));
66
+ if (configured && topRoot.path !== configured.replace(/\\/g, "/")) {
67
+ lines.push(`Docs for ${key} found under ${topRoot.path} (${topRoot.fileCount} file(s)) but config says ${configured} — ` +
68
+ `edit docTypes.${key}.path in .docops/docops.config.json OR move files (prefer editing config).`);
69
+ }
70
+ if (layer.languageLayout === "flat") {
71
+ lines.push(`${key}: files are flat (no per-language subfolders). Recommended: docs/<layer>/{lang}/… or set primaryLanguage in config.`);
72
+ }
73
+ if (layer.languageLayout === "mixed") {
74
+ lines.push(`${key}: mixed flat and per-language folders — normalize layout or document primaryLanguage.`);
75
+ }
76
+ }
77
+ if (lines.length === 0) {
78
+ lines.push("On-disk layout matches configured paths. Run: npx ai-spector docops check — then docops migrate --repair if contract gaps remain.");
79
+ }
80
+ lines.push("See .docops/guide/guides/PROJECT_LAYOUT.md and MIGRATION.md for path conventions.");
81
+ return lines;
82
+ }
83
+ function buildAgentPrompt(result) {
84
+ const lines = [
85
+ "Probe doc layout for this repo (read-only — no file moves).",
86
+ "",
87
+ "Configured paths:",
88
+ ];
89
+ for (const key of LAYER_KEYS) {
90
+ const path = result.configuredPaths[key] ?? "(not in config)";
91
+ lines.push(`- ${key}: ${path}`);
92
+ }
93
+ lines.push("", "On disk:");
94
+ for (const key of LAYER_KEYS) {
95
+ const layer = result.onDisk[key];
96
+ if (!layer) {
97
+ lines.push(`- ${key}: (not scanned)`);
98
+ continue;
99
+ }
100
+ const roots = layer.roots.map((r) => `${r.path} (${r.fileCount})`).join(", ") || "none";
101
+ lines.push(`- ${key}: ${roots} | languages: ${layer.languageLayout} [${layer.detectedLanguages.join(", ")}] | class: ${layer.classification}`);
102
+ }
103
+ if (result.dataSource) {
104
+ lines.push(`- data-source: ${result.dataSource.path} (${result.dataSource.fileCount} file(s))`);
105
+ }
106
+ lines.push("", "Suggestions:");
107
+ for (const [i, s] of result.suggestions.entries()) {
108
+ lines.push(`${i + 1}. ${s}`);
109
+ }
110
+ lines.push("", "Next: edit .docops/docops.config.json (docTypes.*.path, languages), customize .docops/templates/ if needed, then:", " npx ai-spector docops migrate --repair", " npx ai-spector index", " npx ai-spector docops check --prompt");
111
+ return lines.join("\n");
112
+ }
113
+ export async function probeDocopsLayout(projectRoot) {
114
+ const root = projectRoot ?? findProjectRoot();
115
+ const config = await readDocopsConfig(root);
116
+ const configuredPaths = {};
117
+ if (config?.docTypes) {
118
+ for (const key of LAYER_KEYS) {
119
+ const path = config.docTypes[key]?.path?.trim();
120
+ if (path)
121
+ configuredPaths[key] = path.replace(/\\/g, "/");
122
+ }
123
+ }
124
+ const onDisk = {};
125
+ let srsMdCount = 0;
126
+ for (const key of LAYER_KEYS) {
127
+ const configuredPath = configuredPaths[key] ?? null;
128
+ const candidates = new Set();
129
+ if (configuredPath)
130
+ candidates.add(configuredPath);
131
+ for (const alias of DISCOVERY_ALIASES[key]) {
132
+ candidates.add(alias);
133
+ }
134
+ const roots = [];
135
+ const allPaths = [];
136
+ const classifyFiles = [];
137
+ for (const rel of candidates) {
138
+ const abs = join(root, rel);
139
+ const files = await collectMdFiles(abs);
140
+ if (files.length > 0) {
141
+ roots.push({ path: rel.replace(/\\/g, "/"), fileCount: files.length });
142
+ }
143
+ for (const absPath of files) {
144
+ const projectRel = relative(root, absPath).replace(/\\/g, "/");
145
+ allPaths.push(projectRel);
146
+ classifyFiles.push({ relativePath: stripLayerPrefix(key, projectRel), headings: [] });
147
+ if (key === "srs")
148
+ srsMdCount += 1;
149
+ }
150
+ }
151
+ roots.sort((a, b) => b.fileCount - a.fileCount);
152
+ const lang = detectLanguageLayout(allPaths);
153
+ const layerFolder = key === "srs" ? "srs" : key === "basicDesign" ? "basic-design" : "detail-design";
154
+ onDisk[key] = {
155
+ configuredPath,
156
+ roots,
157
+ languageLayout: lang.strategy,
158
+ detectedLanguages: lang.detected,
159
+ classification: classifyLayer(classifyFiles, layerFolder),
160
+ };
161
+ }
162
+ const dsFiles = await collectMdFiles(join(root, "docs/data-source"));
163
+ const dataSource = dsFiles.length > 0
164
+ ? { path: "docs/data-source", fileCount: dsFiles.length }
165
+ : null;
166
+ classifyDataSource(srsMdCount, dataSource?.fileCount ?? 0);
167
+ await classifyPrototype(root);
168
+ const partial = {
169
+ probedAt: new Date().toISOString(),
170
+ configuredPaths,
171
+ onDisk,
172
+ dataSource,
173
+ };
174
+ const suggestions = buildSuggestions(partial);
175
+ return {
176
+ ...partial,
177
+ suggestions,
178
+ agentPrompt: buildAgentPrompt({ ...partial, suggestions }),
179
+ };
180
+ }
181
+ //# sourceMappingURL=layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.js","sourceRoot":"","sources":["../../../src/core/docops/layout.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,8 @@ export interface MigrateDocopsResult {
12
12
  configPath: string;
13
13
  config?: DocopsConfig;
14
14
  }
15
+ /** Gap-fill an existing docops contract (config patches + bootstrap files). */
16
+ export declare function repairDocopsContract(projectRoot: string, config: DocopsConfig, actions: string[], dryRun: boolean): Promise<DocopsConfig>;
15
17
  export interface MigrateFromDocflowResult {
16
18
  migrated: boolean;
17
19
  reason?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../../src/core/docops/migrate.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAmQD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAC/C,OAAO,CAAC,wBAAwB,CAAC,CAsCnC;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,mBAAmB,CAAC,CAsF9B"}
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../../src/core/docops/migrate.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAkID,+EAA+E;AAC/E,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,MAAM,EAAE,EACjB,MAAM,EAAE,OAAO,GACd,OAAO,CAAC,YAAY,CAAC,CAEvB;AA2JD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAC/C,OAAO,CAAC,wBAAwB,CAAC,CAsCnC;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,mBAAmB,CAAC,CAsF9B"}
@@ -4,7 +4,7 @@ import { loadDocflowConfig } from "../config/load.js";
4
4
  import { defaultEngineConfig, writeEngineConfig } from "../engine/load.js";
5
5
  import { pathExists } from "../util/fs.js";
6
6
  import { DOCOPS_CONFIG_REL, LEGACY_DOCFLOW_CONFIG_REL, LEGACY_DOCOPS_PATHS, normalizeDocTypePath, } from "./paths.js";
7
- import { docopsConfigFromDocflow, inferDocTypesFromTree, readDocopsConfig, writeDocopsConfig, } from "./config.js";
7
+ import { docopsConfigFromDocflow, inferDocTypesFromTree, mergeDocopsDefaults, readDocopsConfig, writeDocopsConfig, } from "./config.js";
8
8
  import { applyDocopsBootstrap } from "./bootstrap.js";
9
9
  import { bootstrapEntityRegistry } from "./entity-keying.js";
10
10
  import { buildDocTypesFromLayers, ensureOptionalDocTypes, LAYER_TEMPLATES_PATH, templateLayerKeys, } from "./layer-defaults.js";
@@ -63,9 +63,31 @@ async function bootstrapDocopsContract(projectRoot, config, docflow, actions, dr
63
63
  });
64
64
  await copyTemplatesForEnabledDocTypes(projectRoot, config, docflow, actions, dryRun);
65
65
  }
66
+ async function syncDocopsConfigSchema(projectRoot, config, actions, dryRun) {
67
+ const merged = mergeDocopsDefaults(config);
68
+ const withOptional = {
69
+ ...merged,
70
+ docTypes: ensureOptionalDocTypes(merged.docTypes ?? {}),
71
+ };
72
+ const before = JSON.stringify(mergeDocopsDefaults(config));
73
+ const after = JSON.stringify(withOptional);
74
+ if (before === after) {
75
+ return config;
76
+ }
77
+ actions.push(`${dryRun ? "would sync" : "sync"} ${DOCOPS_CONFIG_REL} to latest contract defaults`);
78
+ if (!dryRun) {
79
+ await writeDocopsConfig(projectRoot, withOptional);
80
+ }
81
+ return withOptional;
82
+ }
83
+ /** Gap-fill an existing docops contract (config patches + bootstrap files). */
84
+ export async function repairDocopsContract(projectRoot, config, actions, dryRun) {
85
+ return repairDocopsGaps(projectRoot, config, actions, dryRun);
86
+ }
66
87
  async function repairDocopsGaps(projectRoot, config, actions, dryRun) {
67
88
  await copyLegacyArtifacts(projectRoot, actions, dryRun);
68
- const withPaths = await patchCanonicalDocTypePaths(projectRoot, config, actions, dryRun);
89
+ const synced = await syncDocopsConfigSchema(projectRoot, config, actions, dryRun);
90
+ const withPaths = await patchCanonicalDocTypePaths(projectRoot, synced, actions, dryRun);
69
91
  const withOptional = await patchMissingOptionalDocTypes(projectRoot, withPaths, actions, dryRun);
70
92
  const next = await patchMissingTemplatesPaths(projectRoot, withOptional, actions, dryRun);
71
93
  const docflow = await loadDocflowIfPresent(projectRoot);