@context-forge/core 0.1.0 → 0.2.2
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/README.md +12 -1
- package/assets/prompt.ai-project.system.md +919 -0
- package/dist/config/ConfigKeys.d.ts +9 -0
- package/dist/config/ConfigKeys.d.ts.map +1 -0
- package/dist/config/ConfigKeys.js +24 -0
- package/dist/config/ConfigKeys.js.map +1 -0
- package/dist/config/ConfigManager.d.ts +18 -0
- package/dist/config/ConfigManager.d.ts.map +1 -0
- package/dist/config/ConfigManager.js +129 -0
- package/dist/config/ConfigManager.js.map +1 -0
- package/dist/config/configPaths.d.ts +5 -0
- package/dist/config/configPaths.d.ts.map +1 -0
- package/dist/config/configPaths.js +11 -0
- package/dist/config/configPaths.js.map +1 -0
- package/dist/config/index.d.ts +4 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +4 -0
- package/dist/config/index.js.map +1 -0
- package/dist/guides/GuideDetector.d.ts +20 -0
- package/dist/guides/GuideDetector.d.ts.map +1 -0
- package/dist/guides/GuideDetector.js +142 -0
- package/dist/guides/GuideDetector.js.map +1 -0
- package/dist/guides/GuideManager.d.ts +21 -0
- package/dist/guides/GuideManager.d.ts.map +1 -0
- package/dist/guides/GuideManager.js +88 -0
- package/dist/guides/GuideManager.js.map +1 -0
- package/dist/guides/gitExec.d.ts +15 -0
- package/dist/guides/gitExec.d.ts.map +1 -0
- package/dist/guides/gitExec.js +39 -0
- package/dist/guides/gitExec.js.map +1 -0
- package/dist/guides/index.d.ts +4 -0
- package/dist/guides/index.d.ts.map +1 -0
- package/dist/guides/index.js +5 -0
- package/dist/guides/index.js.map +1 -0
- package/dist/guides/strategies/CloneStrategy.d.ts +7 -0
- package/dist/guides/strategies/CloneStrategy.d.ts.map +1 -0
- package/dist/guides/strategies/CloneStrategy.js +80 -0
- package/dist/guides/strategies/CloneStrategy.js.map +1 -0
- package/dist/guides/strategies/SubmoduleStrategy.d.ts +7 -0
- package/dist/guides/strategies/SubmoduleStrategy.d.ts.map +1 -0
- package/dist/guides/strategies/SubmoduleStrategy.js +74 -0
- package/dist/guides/strategies/SubmoduleStrategy.js.map +1 -0
- package/dist/guides/strategies/TarballStrategy.d.ts +19 -0
- package/dist/guides/strategies/TarballStrategy.d.ts.map +1 -0
- package/dist/guides/strategies/TarballStrategy.js +118 -0
- package/dist/guides/strategies/TarballStrategy.js.map +1 -0
- package/dist/guides/types.d.ts +44 -0
- package/dist/guides/types.d.ts.map +1 -0
- package/dist/guides/types.js +7 -0
- package/dist/guides/types.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/introspection/ArtifactIntrospector.d.ts +20 -0
- package/dist/introspection/ArtifactIntrospector.d.ts.map +1 -0
- package/dist/introspection/ArtifactIntrospector.js +140 -0
- package/dist/introspection/ArtifactIntrospector.js.map +1 -0
- package/dist/introspection/FutureWorkCollector.d.ts +7 -0
- package/dist/introspection/FutureWorkCollector.d.ts.map +1 -0
- package/dist/introspection/FutureWorkCollector.js +116 -0
- package/dist/introspection/FutureWorkCollector.js.map +1 -0
- package/dist/introspection/ProjectModelBuilder.d.ts +32 -0
- package/dist/introspection/ProjectModelBuilder.d.ts.map +1 -0
- package/dist/introspection/ProjectModelBuilder.js +321 -0
- package/dist/introspection/ProjectModelBuilder.js.map +1 -0
- package/dist/introspection/index.d.ts +4 -0
- package/dist/introspection/index.d.ts.map +1 -0
- package/dist/introspection/index.js +5 -0
- package/dist/introspection/index.js.map +1 -0
- package/dist/introspection/interfaces.d.ts +18 -0
- package/dist/introspection/interfaces.d.ts.map +1 -0
- package/dist/introspection/interfaces.js +2 -0
- package/dist/introspection/interfaces.js.map +1 -0
- package/dist/introspection/parsers/documentDetector.d.ts +12 -0
- package/dist/introspection/parsers/documentDetector.d.ts.map +1 -0
- package/dist/introspection/parsers/documentDetector.js +66 -0
- package/dist/introspection/parsers/documentDetector.js.map +1 -0
- package/dist/introspection/parsers/frontmatterParser.d.ts +8 -0
- package/dist/introspection/parsers/frontmatterParser.d.ts.map +1 -0
- package/dist/introspection/parsers/frontmatterParser.js +43 -0
- package/dist/introspection/parsers/frontmatterParser.js.map +1 -0
- package/dist/introspection/parsers/futureWorkParser.d.ts +8 -0
- package/dist/introspection/parsers/futureWorkParser.d.ts.map +1 -0
- package/dist/introspection/parsers/futureWorkParser.js +75 -0
- package/dist/introspection/parsers/futureWorkParser.js.map +1 -0
- package/dist/introspection/parsers/slicePlanParser.d.ts +8 -0
- package/dist/introspection/parsers/slicePlanParser.d.ts.map +1 -0
- package/dist/introspection/parsers/slicePlanParser.js +51 -0
- package/dist/introspection/parsers/slicePlanParser.js.map +1 -0
- package/dist/introspection/parsers/statusNormalizer.d.ts +4 -0
- package/dist/introspection/parsers/statusNormalizer.d.ts.map +1 -0
- package/dist/introspection/parsers/statusNormalizer.js +23 -0
- package/dist/introspection/parsers/statusNormalizer.js.map +1 -0
- package/dist/introspection/parsers/taskFileParser.d.ts +13 -0
- package/dist/introspection/parsers/taskFileParser.d.ts.map +1 -0
- package/dist/introspection/parsers/taskFileParser.js +66 -0
- package/dist/introspection/parsers/taskFileParser.js.map +1 -0
- package/dist/introspection/types.d.ts +178 -0
- package/dist/introspection/types.d.ts.map +1 -0
- package/dist/introspection/types.js +2 -0
- package/dist/introspection/types.js.map +1 -0
- package/dist/node.d.ts +10 -0
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +13 -0
- package/dist/node.js.map +1 -1
- package/dist/schema/projectSchema.d.ts +54 -0
- package/dist/schema/projectSchema.d.ts.map +1 -0
- package/dist/schema/projectSchema.js +127 -0
- package/dist/schema/projectSchema.js.map +1 -0
- package/dist/services/ContextGenerator.d.ts.map +1 -1
- package/dist/services/ContextGenerator.js +3 -5
- package/dist/services/ContextGenerator.js.map +1 -1
- package/dist/services/ContextIntegrator.d.ts.map +1 -1
- package/dist/services/ContextIntegrator.js +10 -14
- package/dist/services/ContextIntegrator.js.map +1 -1
- package/dist/services/ContextTemplateEngine.d.ts.map +1 -1
- package/dist/services/ContextTemplateEngine.js +8 -21
- package/dist/services/ContextTemplateEngine.js.map +1 -1
- package/dist/services/CoreServiceFactory.d.ts +3 -0
- package/dist/services/CoreServiceFactory.d.ts.map +1 -1
- package/dist/services/CoreServiceFactory.js +19 -1
- package/dist/services/CoreServiceFactory.js.map +1 -1
- package/dist/services/ProjectPathService.d.ts +1 -1
- package/dist/services/ProjectPathService.d.ts.map +1 -1
- package/dist/services/ProjectPathService.js +2 -4
- package/dist/services/ProjectPathService.js.map +1 -1
- package/dist/services/SectionBuilder.d.ts +0 -4
- package/dist/services/SectionBuilder.d.ts.map +1 -1
- package/dist/services/SectionBuilder.js +8 -35
- package/dist/services/SectionBuilder.js.map +1 -1
- package/dist/services/SystemPromptParser.d.ts +1 -2
- package/dist/services/SystemPromptParser.d.ts.map +1 -1
- package/dist/services/SystemPromptParser.js +3 -14
- package/dist/services/SystemPromptParser.js.map +1 -1
- package/dist/services/TemplateProcessor.d.ts.map +1 -1
- package/dist/services/TemplateProcessor.js +12 -11
- package/dist/services/TemplateProcessor.js.map +1 -1
- package/dist/services/constants.d.ts.map +1 -1
- package/dist/services/constants.js +0 -6
- package/dist/services/constants.js.map +1 -1
- package/dist/services/interfaces.d.ts +1 -1
- package/dist/services/interfaces.d.ts.map +1 -1
- package/dist/storage/FileProjectStore.d.ts.map +1 -1
- package/dist/storage/FileProjectStore.js +25 -8
- package/dist/storage/FileProjectStore.js.map +1 -1
- package/dist/types/context.d.ts +4 -6
- package/dist/types/context.d.ts.map +1 -1
- package/dist/types/project.d.ts +15 -11
- package/dist/types/project.d.ts.map +1 -1
- package/dist/types/sections.d.ts +0 -1
- package/dist/types/sections.d.ts.map +1 -1
- package/dist/types/sections.js +0 -1
- package/dist/types/sections.js.map +1 -1
- package/package.json +6 -2
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { basename } from 'node:path';
|
|
2
|
+
import { buildModel } from './ProjectModelBuilder.js';
|
|
3
|
+
const EMPTY_RESULT = (projectPath) => ({
|
|
4
|
+
projectPath,
|
|
5
|
+
groups: [],
|
|
6
|
+
totalItems: 0,
|
|
7
|
+
pendingItems: 0,
|
|
8
|
+
completedItems: 0,
|
|
9
|
+
markdown: '## Future Work\n\n*No future work items found.*',
|
|
10
|
+
});
|
|
11
|
+
function pad(index) {
|
|
12
|
+
return String(index).padStart(3, '0');
|
|
13
|
+
}
|
|
14
|
+
function generateMarkdown(groups, totals) {
|
|
15
|
+
const lines = ['## Future Work Summary', ''];
|
|
16
|
+
for (const group of groups) {
|
|
17
|
+
if (group.items.length === 0)
|
|
18
|
+
continue;
|
|
19
|
+
lines.push(`### ${group.initiativeIndex} — ${group.initiativeName}`);
|
|
20
|
+
lines.push(`*Source: ${group.sourceFile}*`);
|
|
21
|
+
for (const item of group.items) {
|
|
22
|
+
const box = item.done ? '[x]' : '[ ]';
|
|
23
|
+
lines.push(`- ${box} (${item.index}) ${item.name}`);
|
|
24
|
+
}
|
|
25
|
+
lines.push('');
|
|
26
|
+
}
|
|
27
|
+
lines.push(`**Total: ${totals.total} items (${totals.pending} pending, ${totals.completed} completed)**`);
|
|
28
|
+
return lines.join('\n');
|
|
29
|
+
}
|
|
30
|
+
export class FutureWorkCollector {
|
|
31
|
+
async collect(projectPath, statusFilter = 'all') {
|
|
32
|
+
let model;
|
|
33
|
+
try {
|
|
34
|
+
model = await buildModel(projectPath);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return EMPTY_RESULT(projectPath);
|
|
38
|
+
}
|
|
39
|
+
const groups = [];
|
|
40
|
+
for (const [initIndex, initiative] of Object.entries(model.initiatives)) {
|
|
41
|
+
const { slicePlan } = initiative;
|
|
42
|
+
if (!slicePlan)
|
|
43
|
+
continue;
|
|
44
|
+
const filepath = slicePlan.filepath ?? '';
|
|
45
|
+
const sourceFile = filepath
|
|
46
|
+
? filepath.replace(projectPath + '/', '').replace(projectPath, '')
|
|
47
|
+
: slicePlan.name;
|
|
48
|
+
let rawItems;
|
|
49
|
+
// Standalone detection: filename contains 'slices.future.'
|
|
50
|
+
if (basename(filepath).includes('slices.future.')) {
|
|
51
|
+
const entries = slicePlan.entries ?? [];
|
|
52
|
+
rawItems = entries.map((e) => ({
|
|
53
|
+
index: pad(e.index),
|
|
54
|
+
name: e.name,
|
|
55
|
+
done: e.isChecked,
|
|
56
|
+
sourceFile,
|
|
57
|
+
sourceInitiativeIndex: initIndex,
|
|
58
|
+
sourceInitiativeName: initiative.name,
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
rawItems = (slicePlan.futureWork ?? []).map((fw) => ({
|
|
63
|
+
index: fw.index,
|
|
64
|
+
name: fw.name,
|
|
65
|
+
done: fw.done,
|
|
66
|
+
sourceFile,
|
|
67
|
+
sourceInitiativeIndex: initIndex,
|
|
68
|
+
sourceInitiativeName: initiative.name,
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
if (rawItems.length === 0)
|
|
72
|
+
continue;
|
|
73
|
+
// Apply status filter
|
|
74
|
+
const items = statusFilter === 'pending'
|
|
75
|
+
? rawItems.filter((i) => !i.done)
|
|
76
|
+
: statusFilter === 'completed'
|
|
77
|
+
? rawItems.filter((i) => i.done)
|
|
78
|
+
: rawItems;
|
|
79
|
+
if (items.length === 0)
|
|
80
|
+
continue;
|
|
81
|
+
const completedItems = items.filter((i) => i.done).length;
|
|
82
|
+
const pendingItems = items.length - completedItems;
|
|
83
|
+
groups.push({
|
|
84
|
+
initiativeIndex: initIndex,
|
|
85
|
+
initiativeName: initiative.name,
|
|
86
|
+
sourceFile,
|
|
87
|
+
items,
|
|
88
|
+
totalItems: items.length,
|
|
89
|
+
pendingItems,
|
|
90
|
+
completedItems,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
// Sort groups by initiative index for deterministic output
|
|
94
|
+
groups.sort((a, b) => a.initiativeIndex.localeCompare(b.initiativeIndex));
|
|
95
|
+
const totalItems = groups.reduce((s, g) => s + g.totalItems, 0);
|
|
96
|
+
const pendingItems = groups.reduce((s, g) => s + g.pendingItems, 0);
|
|
97
|
+
const completedItems = groups.reduce((s, g) => s + g.completedItems, 0);
|
|
98
|
+
if (totalItems === 0) {
|
|
99
|
+
return EMPTY_RESULT(projectPath);
|
|
100
|
+
}
|
|
101
|
+
const markdown = generateMarkdown(groups, {
|
|
102
|
+
total: totalItems,
|
|
103
|
+
pending: pendingItems,
|
|
104
|
+
completed: completedItems,
|
|
105
|
+
});
|
|
106
|
+
return {
|
|
107
|
+
projectPath,
|
|
108
|
+
groups,
|
|
109
|
+
totalItems,
|
|
110
|
+
pendingItems,
|
|
111
|
+
completedItems,
|
|
112
|
+
markdown,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=FutureWorkCollector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FutureWorkCollector.js","sourceRoot":"","sources":["../../src/introspection/FutureWorkCollector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { TaskItem, ProjectModel } from './types.js';
|
|
2
|
+
/** Intermediate document entry from directory scanning */
|
|
3
|
+
interface DocEntry {
|
|
4
|
+
index: number;
|
|
5
|
+
docType: string;
|
|
6
|
+
name: string;
|
|
7
|
+
filename: string;
|
|
8
|
+
filepath: string;
|
|
9
|
+
status: string;
|
|
10
|
+
dateCreated?: string;
|
|
11
|
+
dateUpdated?: string;
|
|
12
|
+
project?: string;
|
|
13
|
+
parent?: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
taskItems: TaskItem[];
|
|
16
|
+
splitNum?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Scan project-documents/user/ subdirectories for methodology documents.
|
|
20
|
+
* Exported for testing — not part of public API.
|
|
21
|
+
*/
|
|
22
|
+
export declare function scanDirectory(userDir: string): Promise<DocEntry[]>;
|
|
23
|
+
/**
|
|
24
|
+
* Build the full project model from a project root path.
|
|
25
|
+
* Replicates parse.py's build_model() logic.
|
|
26
|
+
*/
|
|
27
|
+
export declare function buildModel(projectPath: string, options?: {
|
|
28
|
+
name?: string;
|
|
29
|
+
description?: string;
|
|
30
|
+
}): Promise<ProjectModel>;
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=ProjectModelBuilder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProjectModelBuilder.d.ts","sourceRoot":"","sources":["../../src/introspection/ProjectModelBuilder.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,QAAQ,EACR,YAAY,EAUb,MAAM,YAAY,CAAC;AAsBpB,0DAA0D;AAC1D,UAAU,QAAQ;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAqBD;;;GAGG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAuDxE;AAuDD;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAChD,OAAO,CAAC,YAAY,CAAC,CAwMvB"}
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import { readdir, access } from 'node:fs/promises';
|
|
2
|
+
import { join, basename } from 'node:path';
|
|
3
|
+
import { parseFrontmatter } from './parsers/frontmatterParser.js';
|
|
4
|
+
import { parseTaskItems } from './parsers/taskFileParser.js';
|
|
5
|
+
import { parseFutureWork } from './parsers/futureWorkParser.js';
|
|
6
|
+
import { parseSlicePlan } from './parsers/slicePlanParser.js';
|
|
7
|
+
import { normalizeStatus } from './parsers/statusNormalizer.js';
|
|
8
|
+
const USER_DOCS = 'project-documents/user';
|
|
9
|
+
// Subdirectories scanned under user/ (matching parse.py order)
|
|
10
|
+
const SCAN_DIRS = [
|
|
11
|
+
'architecture',
|
|
12
|
+
'slices',
|
|
13
|
+
'tasks',
|
|
14
|
+
'features',
|
|
15
|
+
'project-guides',
|
|
16
|
+
'reviews',
|
|
17
|
+
'analysis',
|
|
18
|
+
'maintenance',
|
|
19
|
+
];
|
|
20
|
+
/** Matches indexed methodology filenames: NNN-type.name[-N].md */
|
|
21
|
+
const INDEXED_RE = /^(\d{3})-(arch|slices|slice|tasks|feature|issue|review|analysis|concept|spec|hld)\.(.+?)(?:-(\d+))?\.md$/i;
|
|
22
|
+
/** Fallback for project-guides: NNN-type.name.md */
|
|
23
|
+
const GUIDE_RE = /^(\d{3})-(concept|spec|hld|slices|guide)\.(.+?)\.md$/i;
|
|
24
|
+
/** Safe directory listing — returns empty on error */
|
|
25
|
+
async function safeReaddir(dirPath) {
|
|
26
|
+
try {
|
|
27
|
+
return await readdir(dirPath);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** Check file existence */
|
|
34
|
+
async function fileExists(filePath) {
|
|
35
|
+
try {
|
|
36
|
+
await access(filePath);
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Scan project-documents/user/ subdirectories for methodology documents.
|
|
45
|
+
* Exported for testing — not part of public API.
|
|
46
|
+
*/
|
|
47
|
+
export async function scanDirectory(userDir) {
|
|
48
|
+
const docs = [];
|
|
49
|
+
for (const subdir of SCAN_DIRS) {
|
|
50
|
+
const dirPath = join(userDir, subdir);
|
|
51
|
+
const files = await safeReaddir(dirPath);
|
|
52
|
+
for (const filename of files) {
|
|
53
|
+
if (!filename.endsWith('.md'))
|
|
54
|
+
continue;
|
|
55
|
+
let m = INDEXED_RE.exec(filename);
|
|
56
|
+
let splitNum;
|
|
57
|
+
if (!m) {
|
|
58
|
+
// Try guide regex for project-guides
|
|
59
|
+
m = GUIDE_RE.exec(filename);
|
|
60
|
+
if (!m)
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
splitNum = m[4] ? parseInt(m[4], 10) : undefined;
|
|
65
|
+
}
|
|
66
|
+
const index = parseInt(m[1], 10);
|
|
67
|
+
const docType = m[2].toLowerCase();
|
|
68
|
+
const name = m[3];
|
|
69
|
+
const filepath = join(dirPath, filename);
|
|
70
|
+
// Parse frontmatter
|
|
71
|
+
const fm = await parseFrontmatter(filepath);
|
|
72
|
+
const status = normalizeStatus(fm.data.status);
|
|
73
|
+
// Parse task items for task docs
|
|
74
|
+
let taskItems = [];
|
|
75
|
+
if (docType === 'tasks') {
|
|
76
|
+
taskItems = await parseTaskItems(filepath);
|
|
77
|
+
}
|
|
78
|
+
docs.push({
|
|
79
|
+
index,
|
|
80
|
+
docType,
|
|
81
|
+
name,
|
|
82
|
+
filename,
|
|
83
|
+
filepath,
|
|
84
|
+
status,
|
|
85
|
+
dateCreated: fm.data.dateCreated || undefined,
|
|
86
|
+
dateUpdated: fm.data.dateUpdated || undefined,
|
|
87
|
+
project: fm.data.project || undefined,
|
|
88
|
+
parent: fm.data.parent || undefined,
|
|
89
|
+
description: fm.data.description || undefined,
|
|
90
|
+
taskItems,
|
|
91
|
+
splitNum,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return docs;
|
|
96
|
+
}
|
|
97
|
+
/** Format index as zero-padded string (matching parse.py f"{doc.index:03d}") */
|
|
98
|
+
function pad(index) {
|
|
99
|
+
return String(index).padStart(3, '0');
|
|
100
|
+
}
|
|
101
|
+
/** Convert DocEntry to base DocSummary shape (matching parse.py _d()) */
|
|
102
|
+
function toDocSummary(doc) {
|
|
103
|
+
const result = {
|
|
104
|
+
index: pad(doc.index),
|
|
105
|
+
name: doc.name,
|
|
106
|
+
status: doc.status,
|
|
107
|
+
};
|
|
108
|
+
if (doc.dateCreated)
|
|
109
|
+
result.dateCreated = doc.dateCreated;
|
|
110
|
+
if (doc.dateUpdated)
|
|
111
|
+
result.dateUpdated = doc.dateUpdated;
|
|
112
|
+
return result;
|
|
113
|
+
}
|
|
114
|
+
/** Title-case a string: hyphens/underscores/dots → spaces, capitalize words */
|
|
115
|
+
function titleCase(s) {
|
|
116
|
+
return s
|
|
117
|
+
.replace(/[-_.]/g, ' ')
|
|
118
|
+
.replace(/\b\w/g, (c) => c.toUpperCase());
|
|
119
|
+
}
|
|
120
|
+
/** Build task entry from one or more task docs at the same index */
|
|
121
|
+
function buildTaskEntry(taskDocs) {
|
|
122
|
+
const sorted = [...taskDocs].sort((a, b) => (a.splitNum ?? 0) - (b.splitNum ?? 0));
|
|
123
|
+
const first = sorted[0];
|
|
124
|
+
const allItems = sorted.flatMap((d) => d.taskItems);
|
|
125
|
+
const taskCount = allItems.length;
|
|
126
|
+
const completedTasks = allItems.filter((t) => t.done).length;
|
|
127
|
+
// Infer status from checkboxes if frontmatter says not-started
|
|
128
|
+
let status = first.status;
|
|
129
|
+
if (status === 'not-started' && taskCount > 0) {
|
|
130
|
+
if (completedTasks === taskCount)
|
|
131
|
+
status = 'complete';
|
|
132
|
+
else if (completedTasks > 0)
|
|
133
|
+
status = 'in-progress';
|
|
134
|
+
}
|
|
135
|
+
const entry = {
|
|
136
|
+
index: pad(first.index),
|
|
137
|
+
name: `tasks.${first.name}`,
|
|
138
|
+
status,
|
|
139
|
+
taskCount,
|
|
140
|
+
completedTasks,
|
|
141
|
+
};
|
|
142
|
+
if (first.dateCreated)
|
|
143
|
+
entry.dateCreated = first.dateCreated;
|
|
144
|
+
if (first.dateUpdated)
|
|
145
|
+
entry.dateUpdated = first.dateUpdated;
|
|
146
|
+
if (allItems.length > 0)
|
|
147
|
+
entry.items = allItems;
|
|
148
|
+
return entry;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Build the full project model from a project root path.
|
|
152
|
+
* Replicates parse.py's build_model() logic.
|
|
153
|
+
*/
|
|
154
|
+
export async function buildModel(projectPath, options) {
|
|
155
|
+
const userDir = join(projectPath, USER_DOCS);
|
|
156
|
+
const docs = await scanDirectory(userDir);
|
|
157
|
+
// Infer project name: from first doc with project field, then directory name
|
|
158
|
+
const projectDoc = docs.find((d) => d.project);
|
|
159
|
+
const inferredName = options?.name ?? titleCase(projectDoc?.project ?? basename(projectPath));
|
|
160
|
+
const model = {
|
|
161
|
+
name: inferredName,
|
|
162
|
+
description: options?.description ?? '',
|
|
163
|
+
foundation: [],
|
|
164
|
+
projectArchitecture: [],
|
|
165
|
+
initiatives: {},
|
|
166
|
+
futureSlices: [],
|
|
167
|
+
quality: [],
|
|
168
|
+
investigation: [],
|
|
169
|
+
maintenance: [],
|
|
170
|
+
devlog: false,
|
|
171
|
+
};
|
|
172
|
+
// Check DEVLOG.md at project root
|
|
173
|
+
model.devlog = await fileExists(join(projectPath, 'DEVLOG.md'));
|
|
174
|
+
// --- Foundation band (000-009) ---
|
|
175
|
+
const foundationTypes = new Set(['concept', 'spec', 'hld', 'slices']);
|
|
176
|
+
const foundationDocs = docs
|
|
177
|
+
.filter((d) => d.index >= 0 && d.index <= 9 && foundationTypes.has(d.docType))
|
|
178
|
+
.sort((a, b) => a.index - b.index || a.docType.localeCompare(b.docType));
|
|
179
|
+
model.foundation = foundationDocs.map((d) => ({
|
|
180
|
+
...toDocSummary(d),
|
|
181
|
+
type: d.docType,
|
|
182
|
+
}));
|
|
183
|
+
// --- Project architecture band (050-099) ---
|
|
184
|
+
const archTypes = new Set(['arch', 'hld']);
|
|
185
|
+
const projArchDocs = docs
|
|
186
|
+
.filter((d) => d.index >= 50 && d.index <= 99 && archTypes.has(d.docType))
|
|
187
|
+
.sort((a, b) => a.index - b.index);
|
|
188
|
+
model.projectArchitecture = projArchDocs.map((d) => ({
|
|
189
|
+
...toDocSummary(d),
|
|
190
|
+
type: (d.name.includes('hld') || d.docType === 'hld' ? 'hld' : 'arch'),
|
|
191
|
+
}));
|
|
192
|
+
// --- Initiative bands (100-799) ---
|
|
193
|
+
// Identify base indices from arch or slices docs
|
|
194
|
+
const baseIndices = new Set();
|
|
195
|
+
for (const d of docs) {
|
|
196
|
+
if (d.index >= 100 && d.index <= 799 && (d.docType === 'arch' || d.docType === 'slices')) {
|
|
197
|
+
baseIndices.add(d.index);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
const sortedBases = [...baseIndices].sort((a, b) => a - b);
|
|
201
|
+
for (let i = 0; i < sortedBases.length; i++) {
|
|
202
|
+
const base = sortedBases[i];
|
|
203
|
+
const upper = i + 1 < sortedBases.length ? sortedBases[i + 1] : 800;
|
|
204
|
+
const archDoc = docs.find((d) => d.index === base && d.docType === 'arch');
|
|
205
|
+
const slicesDoc = docs.find((d) => d.index === base && d.docType === 'slices');
|
|
206
|
+
const rawName = archDoc?.name ?? slicesDoc?.name ?? String(base);
|
|
207
|
+
const initiative = {
|
|
208
|
+
name: titleCase(rawName),
|
|
209
|
+
slices: [],
|
|
210
|
+
features: [],
|
|
211
|
+
};
|
|
212
|
+
if (archDoc) {
|
|
213
|
+
initiative.arch = toDocSummary(archDoc);
|
|
214
|
+
}
|
|
215
|
+
// Slice plan: parse both main-body entries and future work section
|
|
216
|
+
let planEntries = [];
|
|
217
|
+
if (slicesDoc) {
|
|
218
|
+
const [planResult, fwResult] = await Promise.all([
|
|
219
|
+
parseSlicePlan(slicesDoc.filepath),
|
|
220
|
+
parseFutureWork(slicesDoc.filepath, upper),
|
|
221
|
+
]);
|
|
222
|
+
planEntries = planResult.entries;
|
|
223
|
+
const planBlock = {
|
|
224
|
+
...toDocSummary(slicesDoc),
|
|
225
|
+
filepath: slicesDoc.filepath,
|
|
226
|
+
entries: planResult.entries,
|
|
227
|
+
futureWork: fwResult.items,
|
|
228
|
+
};
|
|
229
|
+
initiative.slicePlan = planBlock;
|
|
230
|
+
}
|
|
231
|
+
// Collect actual slice docs in this band
|
|
232
|
+
const bandSlices = docs
|
|
233
|
+
.filter((d) => d.index >= base && d.index < upper && d.docType === 'slice')
|
|
234
|
+
.sort((a, b) => a.index - b.index);
|
|
235
|
+
// Collect task docs in this band (grouped by index)
|
|
236
|
+
const bandTasks = docs.filter((d) => d.index >= base && d.index < upper && d.docType === 'tasks');
|
|
237
|
+
const tasksByIndex = new Map();
|
|
238
|
+
for (const t of bandTasks) {
|
|
239
|
+
const existing = tasksByIndex.get(t.index) ?? [];
|
|
240
|
+
existing.push(t);
|
|
241
|
+
tasksByIndex.set(t.index, existing);
|
|
242
|
+
}
|
|
243
|
+
// Collect feature/issue docs in this band (grouped by index)
|
|
244
|
+
const bandFeatures = docs.filter((d) => d.index >= base &&
|
|
245
|
+
d.index < upper &&
|
|
246
|
+
(d.docType === 'feature' || d.docType === 'issue'));
|
|
247
|
+
const featuresByIndex = new Map();
|
|
248
|
+
for (const f of bandFeatures) {
|
|
249
|
+
const existing = featuresByIndex.get(f.index) ?? [];
|
|
250
|
+
existing.push(f);
|
|
251
|
+
featuresByIndex.set(f.index, existing);
|
|
252
|
+
}
|
|
253
|
+
// Build slice entries
|
|
254
|
+
const sliceIndices = new Set(bandSlices.map((s) => s.index));
|
|
255
|
+
for (const sliceDoc of bandSlices) {
|
|
256
|
+
const entry = toDocSummary(sliceDoc);
|
|
257
|
+
// Attach tasks
|
|
258
|
+
const tasks = tasksByIndex.get(sliceDoc.index);
|
|
259
|
+
if (tasks && tasks.length > 0) {
|
|
260
|
+
entry.tasks = buildTaskEntry(tasks);
|
|
261
|
+
}
|
|
262
|
+
// Attach features
|
|
263
|
+
const features = featuresByIndex.get(sliceDoc.index);
|
|
264
|
+
if (features && features.length > 0) {
|
|
265
|
+
entry.features = features.map(toDocSummary);
|
|
266
|
+
}
|
|
267
|
+
initiative.slices.push(entry);
|
|
268
|
+
}
|
|
269
|
+
// Fill planned-but-unwritten slices from slice plan main body (matching parse.py)
|
|
270
|
+
for (const entry of planEntries) {
|
|
271
|
+
if (entry.index >= base && entry.index < upper && !sliceIndices.has(entry.index)) {
|
|
272
|
+
initiative.slices.push({
|
|
273
|
+
index: pad(entry.index),
|
|
274
|
+
name: entry.name,
|
|
275
|
+
status: entry.isChecked ? 'complete' : 'not-started',
|
|
276
|
+
planned: true,
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
// Re-sort all slices by index
|
|
281
|
+
initiative.slices.sort((a, b) => a.index.localeCompare(b.index));
|
|
282
|
+
// Collect unclaimed features as futureSlices
|
|
283
|
+
for (const [idx, feats] of featuresByIndex) {
|
|
284
|
+
if (!sliceIndices.has(idx)) {
|
|
285
|
+
for (const f of feats) {
|
|
286
|
+
const entry = {
|
|
287
|
+
...toDocSummary(f),
|
|
288
|
+
parent: pad(base),
|
|
289
|
+
};
|
|
290
|
+
model.futureSlices.push(entry);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
model.initiatives[pad(base)] = initiative;
|
|
295
|
+
}
|
|
296
|
+
// --- Operational band (900+) ---
|
|
297
|
+
// Quality: review docs 900+
|
|
298
|
+
model.quality = docs
|
|
299
|
+
.filter((d) => d.index >= 900 && d.docType === 'review')
|
|
300
|
+
.sort((a, b) => a.index - b.index)
|
|
301
|
+
.map(toDocSummary);
|
|
302
|
+
// Investigation: all analysis docs (no index filter per parse.py)
|
|
303
|
+
model.investigation = docs
|
|
304
|
+
.filter((d) => d.docType === 'analysis')
|
|
305
|
+
.sort((a, b) => a.index - b.index)
|
|
306
|
+
.map(toDocSummary);
|
|
307
|
+
// Maintenance: tasks docs 900+
|
|
308
|
+
model.maintenance = docs
|
|
309
|
+
.filter((d) => d.index >= 900 && d.docType === 'tasks')
|
|
310
|
+
.sort((a, b) => a.index - b.index)
|
|
311
|
+
.map((d) => {
|
|
312
|
+
const entry = toDocSummary(d);
|
|
313
|
+
if (d.taskItems.length > 0) {
|
|
314
|
+
entry.taskCount = d.taskItems.length;
|
|
315
|
+
entry.completedTasks = d.taskItems.filter((t) => t.done).length;
|
|
316
|
+
}
|
|
317
|
+
return entry;
|
|
318
|
+
});
|
|
319
|
+
return model;
|
|
320
|
+
}
|
|
321
|
+
//# sourceMappingURL=ProjectModelBuilder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProjectModelBuilder.js","sourceRoot":"","sources":["../../src/introspection/ProjectModelBuilder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/introspection/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAC;AAC3B,YAAY,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAG7D,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Introspection module — browser-safe exports (types, interfaces, pure functions)
|
|
2
|
+
export * from './types.js';
|
|
3
|
+
// normalizeStatus is a pure function with no fs dependency — browser-safe
|
|
4
|
+
export { normalizeStatus } from './parsers/statusNormalizer.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/introspection/index.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,cAAc,YAAY,CAAC;AAG3B,0EAA0E;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ProjectData } from '../types/project.js';
|
|
2
|
+
import type { SlicePlanResult, TaskFileResult, FrontmatterResult, FutureWorkResult, DocumentDetectionResult, IntrospectionSummary } from './types.js';
|
|
3
|
+
/** Public interface for artifact introspection — consumed by slices 164–166 and project_get enrichment */
|
|
4
|
+
export interface IArtifactIntrospector {
|
|
5
|
+
/** Parse a slice plan and return entries with completion state */
|
|
6
|
+
parseSlicePlan(slicePlanPath: string): Promise<SlicePlanResult>;
|
|
7
|
+
/** Parse a task file (or merged split files) and return checkbox items */
|
|
8
|
+
parseTaskFile(taskFilePaths: string | string[]): Promise<TaskFileResult>;
|
|
9
|
+
/** Extract YAML frontmatter from a markdown file */
|
|
10
|
+
parseFrontmatter(filePath: string): Promise<FrontmatterResult>;
|
|
11
|
+
/** Parse the Future Work section from a slice plan */
|
|
12
|
+
parseFutureWork(slicePlanPath: string, nextIndex?: number): Promise<FutureWorkResult>;
|
|
13
|
+
/** Check what methodology documents exist for a given slice index */
|
|
14
|
+
detectDocuments(projectPath: string, sliceIndex: number): Promise<DocumentDetectionResult>;
|
|
15
|
+
/** Generate an introspection summary for a project (for enriching project_get) */
|
|
16
|
+
summarize(project: ProjectData): Promise<IntrospectionSummary>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=interfaces.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/introspection/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,uBAAuB,EACvB,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAEpB,0GAA0G;AAC1G,MAAM,WAAW,qBAAqB;IACpC,kEAAkE;IAClE,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAEhE,0EAA0E;IAC1E,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAEzE,oDAAoD;IACpD,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAE/D,sDAAsD;IACtD,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAEtF,qEAAqE;IACrE,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAE3F,kFAAkF;IAClF,SAAS,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAChE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/introspection/interfaces.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { DocumentDetectionResult } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Check if a file exists at the given path.
|
|
4
|
+
*/
|
|
5
|
+
export declare function checkFileExists(projectPath: string, relativePath: string): Promise<boolean>;
|
|
6
|
+
/**
|
|
7
|
+
* Detect methodology documents for a given slice index under a project path.
|
|
8
|
+
* Checks project-documents/user/ subdirectories for matching files.
|
|
9
|
+
* Never throws — returns nulls for missing directories.
|
|
10
|
+
*/
|
|
11
|
+
export declare function detectDocuments(projectPath: string, sliceIndex: number): Promise<DocumentDetectionResult>;
|
|
12
|
+
//# sourceMappingURL=documentDetector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentDetector.d.ts","sourceRoot":"","sources":["../../../src/introspection/parsers/documentDetector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAI3D;;GAEG;AACH,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOjG;AAwBD;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,uBAAuB,CAAC,CA8BlC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { readdir, access } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
const USER_DOCS = 'project-documents/user';
|
|
4
|
+
/**
|
|
5
|
+
* Check if a file exists at the given path.
|
|
6
|
+
*/
|
|
7
|
+
export async function checkFileExists(projectPath, relativePath) {
|
|
8
|
+
try {
|
|
9
|
+
await access(join(projectPath, relativePath));
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Read a directory listing safely — returns empty array on error.
|
|
18
|
+
*/
|
|
19
|
+
async function safeReaddir(dirPath) {
|
|
20
|
+
try {
|
|
21
|
+
return await readdir(dirPath);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Find files in a directory matching a prefix pattern like `NNN-type.`.
|
|
29
|
+
* Returns full relative paths from projectPath.
|
|
30
|
+
*/
|
|
31
|
+
function matchFiles(files, prefix, dir) {
|
|
32
|
+
return files
|
|
33
|
+
.filter((f) => f.startsWith(prefix) && f.endsWith('.md'))
|
|
34
|
+
.sort()
|
|
35
|
+
.map((f) => join(dir, f));
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Detect methodology documents for a given slice index under a project path.
|
|
39
|
+
* Checks project-documents/user/ subdirectories for matching files.
|
|
40
|
+
* Never throws — returns nulls for missing directories.
|
|
41
|
+
*/
|
|
42
|
+
export async function detectDocuments(projectPath, sliceIndex) {
|
|
43
|
+
const idx = String(sliceIndex);
|
|
44
|
+
const slicesDir = join(projectPath, USER_DOCS, 'slices');
|
|
45
|
+
const tasksDir = join(projectPath, USER_DOCS, 'tasks');
|
|
46
|
+
const archDir = join(projectPath, USER_DOCS, 'architecture');
|
|
47
|
+
const [sliceFiles, taskFiles, archFiles] = await Promise.all([
|
|
48
|
+
safeReaddir(slicesDir),
|
|
49
|
+
safeReaddir(tasksDir),
|
|
50
|
+
safeReaddir(archDir),
|
|
51
|
+
]);
|
|
52
|
+
// slices/{index}-slice.*.md → sliceDesign
|
|
53
|
+
const sliceMatches = matchFiles(sliceFiles, `${idx}-slice.`, join(USER_DOCS, 'slices'));
|
|
54
|
+
const sliceDesign = sliceMatches.length > 0 ? sliceMatches[0] : null;
|
|
55
|
+
// tasks/{index}-tasks.*.md → taskFile (array, supports split files)
|
|
56
|
+
const taskMatches = matchFiles(taskFiles, `${idx}-tasks.`, join(USER_DOCS, 'tasks'));
|
|
57
|
+
const taskFile = taskMatches.length > 0 ? taskMatches : null;
|
|
58
|
+
// architecture/{index}-arch.*.md → architecture
|
|
59
|
+
const archMatches = matchFiles(archFiles, `${idx}-arch.`, join(USER_DOCS, 'architecture'));
|
|
60
|
+
const architecture = archMatches.length > 0 ? archMatches[0] : null;
|
|
61
|
+
// architecture/{index}-slices.*.md → slicePlan
|
|
62
|
+
const planMatches = matchFiles(archFiles, `${idx}-slices.`, join(USER_DOCS, 'architecture'));
|
|
63
|
+
const slicePlan = planMatches.length > 0 ? planMatches[0] : null;
|
|
64
|
+
return { sliceDesign, taskFile, architecture, slicePlan };
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=documentDetector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentDetector.js","sourceRoot":"","sources":["../../../src/introspection/parsers/documentDetector.ts"],"names":[],"mappings":"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"}
|