@contorium/mcp 0.8.1
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 +97 -0
- package/bin/contorium-mcp.js +34 -0
- package/dist/autoContext.d.ts +2 -0
- package/dist/autoContext.js +2 -0
- package/dist/bootstrapCli.d.ts +2 -0
- package/dist/bootstrapCli.js +21 -0
- package/dist/conflicts.d.ts +19 -0
- package/dist/conflicts.js +49 -0
- package/dist/dashboardEnsure.d.ts +10 -0
- package/dist/dashboardEnsure.js +41 -0
- package/dist/intelligence.d.ts +16 -0
- package/dist/intelligence.js +38 -0
- package/dist/intentGraph.d.ts +20 -0
- package/dist/intentGraph.js +51 -0
- package/dist/mcpBootstrap.d.ts +8 -0
- package/dist/mcpBootstrap.js +81 -0
- package/dist/memoryStore.d.ts +18 -0
- package/dist/memoryStore.js +57 -0
- package/dist/paths.d.ts +12 -0
- package/dist/paths.js +66 -0
- package/dist/runtimeState.d.ts +14 -0
- package/dist/runtimeState.js +36 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.js +567 -0
- package/dist/stateBuilder.d.ts +16 -0
- package/dist/stateBuilder.js +40 -0
- package/dist/understanding.d.ts +1 -0
- package/dist/understanding.js +1 -0
- package/dist/workspace.d.ts +12 -0
- package/dist/workspace.js +40 -0
- package/dist/workspaceConfig.d.ts +14 -0
- package/dist/workspaceConfig.js +80 -0
- package/node_modules/@contora/state-core/dist/adapterSync.d.ts +29 -0
- package/node_modules/@contora/state-core/dist/adapterSync.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/adapterSync.js +142 -0
- package/node_modules/@contora/state-core/dist/adapters.d.ts +20 -0
- package/node_modules/@contora/state-core/dist/adapters.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/adapters.js +24 -0
- package/node_modules/@contora/state-core/dist/bootstrap/bootstrapState.d.ts +6 -0
- package/node_modules/@contora/state-core/dist/bootstrap/bootstrapState.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/bootstrap/bootstrapState.js +116 -0
- package/node_modules/@contora/state-core/dist/bootstrapArtifacts.d.ts +18 -0
- package/node_modules/@contora/state-core/dist/bootstrapArtifacts.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/bootstrapArtifacts.js +43 -0
- package/node_modules/@contora/state-core/dist/bootstrapState.d.ts +6 -0
- package/node_modules/@contora/state-core/dist/bootstrapState.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/bootstrapState.js +60 -0
- package/node_modules/@contora/state-core/dist/dashboardActivity.d.ts +12 -0
- package/node_modules/@contora/state-core/dist/dashboardActivity.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/dashboardActivity.js +58 -0
- package/node_modules/@contora/state-core/dist/dualMode.d.ts +11 -0
- package/node_modules/@contora/state-core/dist/dualMode.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/dualMode.js +38 -0
- package/node_modules/@contora/state-core/dist/gitScan.d.ts +7 -0
- package/node_modules/@contora/state-core/dist/gitScan.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/gitScan.js +39 -0
- package/node_modules/@contora/state-core/dist/index.d.ts +44 -0
- package/node_modules/@contora/state-core/dist/index.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/index.js +141 -0
- package/node_modules/@contora/state-core/dist/minimalSnapshot.d.ts +4 -0
- package/node_modules/@contora/state-core/dist/minimalSnapshot.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/minimalSnapshot.js +60 -0
- package/node_modules/@contora/state-core/dist/scanner/gitScan.d.ts +7 -0
- package/node_modules/@contora/state-core/dist/scanner/gitScan.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/scanner/gitScan.js +42 -0
- package/node_modules/@contora/state-core/dist/scanner/workspaceScanner.d.ts +4 -0
- package/node_modules/@contora/state-core/dist/scanner/workspaceScanner.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/scanner/workspaceScanner.js +148 -0
- package/node_modules/@contora/state-core/dist/semiAutoHandoff.d.ts +46 -0
- package/node_modules/@contora/state-core/dist/semiAutoHandoff.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/semiAutoHandoff.js +227 -0
- package/node_modules/@contora/state-core/dist/sourceMetadata.d.ts +4 -0
- package/node_modules/@contora/state-core/dist/sourceMetadata.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/sourceMetadata.js +27 -0
- package/node_modules/@contora/state-core/dist/state-builder/buildFromScan.d.ts +5 -0
- package/node_modules/@contora/state-core/dist/state-builder/buildFromScan.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/state-builder/buildFromScan.js +33 -0
- package/node_modules/@contora/state-core/dist/state-builder/normalization.d.ts +5 -0
- package/node_modules/@contora/state-core/dist/state-builder/normalization.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/state-builder/normalization.js +107 -0
- package/node_modules/@contora/state-core/dist/state-builder/rebuildFromScan.d.ts +4 -0
- package/node_modules/@contora/state-core/dist/state-builder/rebuildFromScan.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/state-builder/rebuildFromScan.js +22 -0
- package/node_modules/@contora/state-core/dist/state-builder/snapshot.d.ts +5 -0
- package/node_modules/@contora/state-core/dist/state-builder/snapshot.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/state-builder/snapshot.js +53 -0
- package/node_modules/@contora/state-core/dist/state-builder/store.d.ts +7 -0
- package/node_modules/@contora/state-core/dist/state-builder/store.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/state-builder/store.js +99 -0
- package/node_modules/@contora/state-core/dist/state-builder/types.d.ts +18 -0
- package/node_modules/@contora/state-core/dist/state-builder/types.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/state-builder/types.js +20 -0
- package/node_modules/@contora/state-core/dist/types.d.ts +42 -0
- package/node_modules/@contora/state-core/dist/types.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/types.js +3 -0
- package/node_modules/@contora/state-core/dist/understanding/buildUnderstanding.d.ts +22 -0
- package/node_modules/@contora/state-core/dist/understanding/buildUnderstanding.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/buildUnderstanding.js +87 -0
- package/node_modules/@contora/state-core/dist/understanding/changeDetector.d.ts +7 -0
- package/node_modules/@contora/state-core/dist/understanding/changeDetector.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/changeDetector.js +68 -0
- package/node_modules/@contora/state-core/dist/understanding/chpHandoff.d.ts +49 -0
- package/node_modules/@contora/state-core/dist/understanding/chpHandoff.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/chpHandoff.js +214 -0
- package/node_modules/@contora/state-core/dist/understanding/extractor.d.ts +21 -0
- package/node_modules/@contora/state-core/dist/understanding/extractor.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/extractor.js +173 -0
- package/node_modules/@contora/state-core/dist/understanding/formatCanonicalExport.d.ts +30 -0
- package/node_modules/@contora/state-core/dist/understanding/formatCanonicalExport.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/formatCanonicalExport.js +363 -0
- package/node_modules/@contora/state-core/dist/understanding/formatHandoff.d.ts +20 -0
- package/node_modules/@contora/state-core/dist/understanding/formatHandoff.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/formatHandoff.js +57 -0
- package/node_modules/@contora/state-core/dist/understanding/graphBuilder.d.ts +9 -0
- package/node_modules/@contora/state-core/dist/understanding/graphBuilder.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/graphBuilder.js +107 -0
- package/node_modules/@contora/state-core/dist/understanding/handoffBuilder.d.ts +12 -0
- package/node_modules/@contora/state-core/dist/understanding/handoffBuilder.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/handoffBuilder.js +101 -0
- package/node_modules/@contora/state-core/dist/understanding/impactAnalyzer.d.ts +5 -0
- package/node_modules/@contora/state-core/dist/understanding/impactAnalyzer.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/impactAnalyzer.js +58 -0
- package/node_modules/@contora/state-core/dist/understanding/intentFusion.d.ts +9 -0
- package/node_modules/@contora/state-core/dist/understanding/intentFusion.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/intentFusion.js +54 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/closureConstants.d.ts +24 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/closureConstants.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/closureConstants.js +33 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/confidence.d.ts +20 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/confidence.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/confidence.js +53 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/gitFrequency.d.ts +5 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/gitFrequency.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/gitFrequency.js +19 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/hotspotBuilder.d.ts +13 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/hotspotBuilder.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/hotspotBuilder.js +101 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/intentFunctionMapper.d.ts +22 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/intentFunctionMapper.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/intentFunctionMapper.js +106 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/knowledgeGraphBuilder.d.ts +23 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/knowledgeGraphBuilder.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/knowledgeGraphBuilder.js +415 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/normalize.d.ts +11 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/normalize.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/normalize.js +136 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/rebuildTrigger.d.ts +13 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/rebuildTrigger.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/rebuildTrigger.js +34 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/snapshotBuilder.d.ts +17 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/snapshotBuilder.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/snapshotBuilder.js +73 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/store.d.ts +7 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/store.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/store.js +127 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/types.d.ts +116 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/types.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/types.js +6 -0
- package/node_modules/@contora/state-core/dist/understanding/miniGraph.d.ts +4 -0
- package/node_modules/@contora/state-core/dist/understanding/miniGraph.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/miniGraph.js +18 -0
- package/node_modules/@contora/state-core/dist/understanding/store.d.ts +24 -0
- package/node_modules/@contora/state-core/dist/understanding/store.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/store.js +243 -0
- package/node_modules/@contora/state-core/dist/understanding/symbolValidator.d.ts +9 -0
- package/node_modules/@contora/state-core/dist/understanding/symbolValidator.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/symbolValidator.js +51 -0
- package/node_modules/@contora/state-core/dist/understanding/timelineTracker.d.ts +3 -0
- package/node_modules/@contora/state-core/dist/understanding/timelineTracker.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/timelineTracker.js +129 -0
- package/node_modules/@contora/state-core/dist/understanding/treeSitterParser.d.ts +24 -0
- package/node_modules/@contora/state-core/dist/understanding/treeSitterParser.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/treeSitterParser.js +56 -0
- package/node_modules/@contora/state-core/dist/understanding/types.d.ts +136 -0
- package/node_modules/@contora/state-core/dist/understanding/types.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/types.js +5 -0
- package/node_modules/@contora/state-core/dist/understanding/understandingGraphBuilder.d.ts +23 -0
- package/node_modules/@contora/state-core/dist/understanding/understandingGraphBuilder.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/understanding/understandingGraphBuilder.js +67 -0
- package/node_modules/@contora/state-core/dist/version.d.ts +3 -0
- package/node_modules/@contora/state-core/dist/version.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/version.js +21 -0
- package/node_modules/@contora/state-core/dist/workspaceScanner.d.ts +4 -0
- package/node_modules/@contora/state-core/dist/workspaceScanner.d.ts.map +1 -0
- package/node_modules/@contora/state-core/dist/workspaceScanner.js +112 -0
- package/node_modules/@contora/state-core/package.json +49 -0
- package/package.json +61 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeGraphRef = normalizeGraphRef;
|
|
4
|
+
exports.formatNextActionPlain = formatNextActionPlain;
|
|
5
|
+
exports.formatAiHandoffExecutionBlock = formatAiHandoffExecutionBlock;
|
|
6
|
+
exports.formatCanonicalAiMarkdown = formatCanonicalAiMarkdown;
|
|
7
|
+
function norm(s) {
|
|
8
|
+
return s.trim().toLowerCase().replace(/\s+/g, ' ');
|
|
9
|
+
}
|
|
10
|
+
function textsSimilar(a, b) {
|
|
11
|
+
const na = norm(a);
|
|
12
|
+
const nb = norm(b);
|
|
13
|
+
if (!na || !nb) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
return na === nb || na.includes(nb) || nb.includes(na);
|
|
17
|
+
}
|
|
18
|
+
function basenamePath(p) {
|
|
19
|
+
const parts = p.replace(/\\/g, '/').split('/').filter(Boolean);
|
|
20
|
+
return parts[parts.length - 1] ?? p;
|
|
21
|
+
}
|
|
22
|
+
/** Machine-stable graph ref: fn:name, cls:name, mod:path */
|
|
23
|
+
function normalizeGraphRef(ref) {
|
|
24
|
+
const t = ref.trim();
|
|
25
|
+
if (!t) {
|
|
26
|
+
return t;
|
|
27
|
+
}
|
|
28
|
+
const colon = t.indexOf(':');
|
|
29
|
+
if (colon > 0) {
|
|
30
|
+
const kind = t.slice(0, colon).toLowerCase();
|
|
31
|
+
const name = t.slice(colon + 1);
|
|
32
|
+
if (kind === 'function' || kind === 'fn') {
|
|
33
|
+
return `fn:${name}`;
|
|
34
|
+
}
|
|
35
|
+
if (kind === 'class' || kind === 'cls') {
|
|
36
|
+
return `cls:${name}`;
|
|
37
|
+
}
|
|
38
|
+
if (kind === 'module' || kind === 'mod') {
|
|
39
|
+
return `mod:${name}`;
|
|
40
|
+
}
|
|
41
|
+
return `${kind}:${name}`;
|
|
42
|
+
}
|
|
43
|
+
return `fn:${t}`;
|
|
44
|
+
}
|
|
45
|
+
/** Plain next line for canonical export (no [action] tags). */
|
|
46
|
+
function formatNextActionPlain(a) {
|
|
47
|
+
const target = (a.target || '').trim();
|
|
48
|
+
const reason = (a.reason || '').trim();
|
|
49
|
+
if (!reason || norm(reason) === norm(target)) {
|
|
50
|
+
return target || reason;
|
|
51
|
+
}
|
|
52
|
+
if (reason.toLowerCase().startsWith(target.toLowerCase())) {
|
|
53
|
+
return reason;
|
|
54
|
+
}
|
|
55
|
+
if (target.toLowerCase().startsWith(reason.toLowerCase())) {
|
|
56
|
+
return target;
|
|
57
|
+
}
|
|
58
|
+
return target ? `${target}` : reason;
|
|
59
|
+
}
|
|
60
|
+
function listSection(title, items, empty) {
|
|
61
|
+
if (!items.length) {
|
|
62
|
+
return empty ? [title, empty] : [];
|
|
63
|
+
}
|
|
64
|
+
return [title, ...items.map((i) => `- ${i}`)];
|
|
65
|
+
}
|
|
66
|
+
function formatSnapshotFromBuilt(built) {
|
|
67
|
+
const lines = [];
|
|
68
|
+
const goal = built.project_goal.trim();
|
|
69
|
+
const stage = built.current_stage.trim();
|
|
70
|
+
if (goal) {
|
|
71
|
+
lines.push(`goal: ${goal}`);
|
|
72
|
+
}
|
|
73
|
+
if (stage) {
|
|
74
|
+
lines.push(`stage: ${stage}`);
|
|
75
|
+
}
|
|
76
|
+
if (built.active_modules.length) {
|
|
77
|
+
if (lines.length) {
|
|
78
|
+
lines.push('');
|
|
79
|
+
}
|
|
80
|
+
lines.push(...listSection('modules:', built.active_modules.slice(0, 12).map(basenamePath)));
|
|
81
|
+
}
|
|
82
|
+
if (built.completed_milestones.length) {
|
|
83
|
+
lines.push('');
|
|
84
|
+
lines.push(...listSection('milestones:', built.completed_milestones.slice(0, 8).map((m) => m.slice(0, 120))));
|
|
85
|
+
}
|
|
86
|
+
if (built.open_problems.length) {
|
|
87
|
+
lines.push('');
|
|
88
|
+
lines.push(...listSection('open_problems:', built.open_problems.slice(0, 6).map((p) => p.slice(0, 160))));
|
|
89
|
+
}
|
|
90
|
+
if (built.next_actions.length) {
|
|
91
|
+
lines.push('');
|
|
92
|
+
lines.push(...listSection('next_actions:', built.next_actions.slice(0, 6)));
|
|
93
|
+
}
|
|
94
|
+
return lines;
|
|
95
|
+
}
|
|
96
|
+
/** Fallback when only legacy snapshot markdown is available. */
|
|
97
|
+
function formatSnapshotFromMarkdown(md) {
|
|
98
|
+
const lines = md.replace(/\r\n/g, '\n').split('\n');
|
|
99
|
+
const out = [];
|
|
100
|
+
let section = '';
|
|
101
|
+
const buckets = {
|
|
102
|
+
goal: [],
|
|
103
|
+
stage: [],
|
|
104
|
+
modules: [],
|
|
105
|
+
milestones: [],
|
|
106
|
+
open_problems: [],
|
|
107
|
+
next_actions: [],
|
|
108
|
+
};
|
|
109
|
+
const pushItem = (key, item) => {
|
|
110
|
+
const t = item.trim();
|
|
111
|
+
if (t && !buckets[key].includes(t)) {
|
|
112
|
+
buckets[key].push(t);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
for (let i = 0; i < lines.length; i++) {
|
|
116
|
+
const t = lines[i].trim();
|
|
117
|
+
if (/^goal:?\s*$/i.test(t)) {
|
|
118
|
+
section = 'goal';
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (/^current stage:?\s*$/i.test(t)) {
|
|
122
|
+
section = 'stage';
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (/^active modules:?\s*$/i.test(t)) {
|
|
126
|
+
section = 'modules';
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (/^completed milestones:?\s*$/i.test(t)) {
|
|
130
|
+
section = 'milestones';
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (/^open problems:?\s*$/i.test(t)) {
|
|
134
|
+
section = 'open_problems';
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (/^next actions:?\s*$/i.test(t)) {
|
|
138
|
+
section = 'next_actions';
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (t.startsWith('- ')) {
|
|
142
|
+
const item = t.slice(2).trim();
|
|
143
|
+
if (section && section in buckets) {
|
|
144
|
+
pushItem(section, item);
|
|
145
|
+
}
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
if (section === 'goal' && t && !t.startsWith('-')) {
|
|
149
|
+
pushItem('goal', t.replace(/^goal:\s*/i, ''));
|
|
150
|
+
section = '';
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (section === 'stage' && t && !t.startsWith('-')) {
|
|
154
|
+
pushItem('stage', t.replace(/^current stage:\s*/i, ''));
|
|
155
|
+
section = '';
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
if (/^goal:\s+/i.test(t)) {
|
|
159
|
+
pushItem('goal', t.replace(/^goal:\s*/i, ''));
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (/^stage:\s+/i.test(t)) {
|
|
163
|
+
pushItem('stage', t.replace(/^stage:\s*/i, ''));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (buckets.goal[0]) {
|
|
167
|
+
out.push(`goal: ${buckets.goal[0]}`);
|
|
168
|
+
}
|
|
169
|
+
if (buckets.stage[0]) {
|
|
170
|
+
out.push(`stage: ${buckets.stage[0]}`);
|
|
171
|
+
}
|
|
172
|
+
if (buckets.modules.length) {
|
|
173
|
+
out.push('');
|
|
174
|
+
out.push(...listSection('modules:', buckets.modules));
|
|
175
|
+
}
|
|
176
|
+
if (buckets.milestones.length) {
|
|
177
|
+
out.push('');
|
|
178
|
+
out.push(...listSection('milestones:', buckets.milestones));
|
|
179
|
+
}
|
|
180
|
+
if (buckets.open_problems.length) {
|
|
181
|
+
out.push('');
|
|
182
|
+
out.push(...listSection('open_problems:', buckets.open_problems));
|
|
183
|
+
}
|
|
184
|
+
if (buckets.next_actions.length) {
|
|
185
|
+
out.push('');
|
|
186
|
+
out.push(...listSection('next_actions:', buckets.next_actions));
|
|
187
|
+
}
|
|
188
|
+
return out;
|
|
189
|
+
}
|
|
190
|
+
function deriveExecutionFocus(handoff) {
|
|
191
|
+
const focus = handoff.current_focus.trim();
|
|
192
|
+
const goal = handoff.goal.trim();
|
|
193
|
+
if (focus && !textsSimilar(focus, goal)) {
|
|
194
|
+
return focus;
|
|
195
|
+
}
|
|
196
|
+
const files = new Set();
|
|
197
|
+
for (const k of handoff.key_changes) {
|
|
198
|
+
if (k.kind === 'file') {
|
|
199
|
+
files.add(basenamePath(k.symbol));
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
const f = k.symbol.split('::')[0];
|
|
203
|
+
if (f) {
|
|
204
|
+
files.add(basenamePath(f));
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
const fileList = [...files].slice(0, 2);
|
|
209
|
+
const fnCount = handoff.key_changes.filter((k) => k.kind === 'function').length;
|
|
210
|
+
if (fileList.length) {
|
|
211
|
+
const mods = fileList.join(' + ');
|
|
212
|
+
return fnCount > 0 ? `${mods} modification (${fnCount} symbols)` : `${mods} modification`;
|
|
213
|
+
}
|
|
214
|
+
const parts = handoff.summary.split('|').map((p) => p.trim()).filter(Boolean);
|
|
215
|
+
const last = parts[parts.length - 1];
|
|
216
|
+
if (last && !/^goal:/i.test(last)) {
|
|
217
|
+
return last.replace(/^focus:\s*/i, '');
|
|
218
|
+
}
|
|
219
|
+
return focus || goal || 'continue current task';
|
|
220
|
+
}
|
|
221
|
+
/** V3.1 execution block — single AI decision entry (no duplicate snapshot lists). */
|
|
222
|
+
function formatAiHandoffExecutionBlock(handoff) {
|
|
223
|
+
const lines = ['# AI HANDOFF (V3.1)'];
|
|
224
|
+
const goal = handoff.goal.trim();
|
|
225
|
+
const focus = deriveExecutionFocus(handoff);
|
|
226
|
+
const risk = handoff.impact_summary.risk;
|
|
227
|
+
if (goal) {
|
|
228
|
+
lines.push(`goal: ${goal}`);
|
|
229
|
+
}
|
|
230
|
+
const execFocus = deriveExecutionFocus(handoff);
|
|
231
|
+
if (execFocus) {
|
|
232
|
+
lines.push(`focus: ${execFocus}`);
|
|
233
|
+
}
|
|
234
|
+
lines.push(`risk: ${risk}`);
|
|
235
|
+
if (handoff.next_actions.length) {
|
|
236
|
+
lines.push('next:');
|
|
237
|
+
const seen = new Set();
|
|
238
|
+
for (const a of handoff.next_actions.slice(0, 6)) {
|
|
239
|
+
const plain = formatNextActionPlain(a);
|
|
240
|
+
const key = norm(plain);
|
|
241
|
+
if (!plain || seen.has(key)) {
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
seen.add(key);
|
|
245
|
+
lines.push(`- ${plain}`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return lines.join('\n');
|
|
249
|
+
}
|
|
250
|
+
function collectModifiedSymbols(handoff) {
|
|
251
|
+
const out = [];
|
|
252
|
+
const seen = new Set();
|
|
253
|
+
for (const k of handoff.key_changes) {
|
|
254
|
+
if (k.kind === 'function' || k.kind === 'class') {
|
|
255
|
+
const sym = k.symbol.trim();
|
|
256
|
+
if (sym && !seen.has(sym)) {
|
|
257
|
+
seen.add(sym);
|
|
258
|
+
out.push(sym);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return out.slice(0, 12);
|
|
263
|
+
}
|
|
264
|
+
function formatCognitiveSnapshotSection(snap) {
|
|
265
|
+
const lines = ['# COGNITIVE SNAPSHOT'];
|
|
266
|
+
if (snap.topIntents.length) {
|
|
267
|
+
lines.push(...listSection('top_intents:', snap.topIntents));
|
|
268
|
+
}
|
|
269
|
+
if (snap.topHotspots.length) {
|
|
270
|
+
lines.push(...listSection('top_hotspots:', snap.topHotspots));
|
|
271
|
+
}
|
|
272
|
+
if (snap.topFunctions.length) {
|
|
273
|
+
lines.push(...listSection('top_functions:', snap.topFunctions));
|
|
274
|
+
}
|
|
275
|
+
if (snap.nextActions.length) {
|
|
276
|
+
lines.push(...listSection('next_graph_actions:', snap.nextActions));
|
|
277
|
+
}
|
|
278
|
+
lines.push(`avg_confidence: ${snap.graphSummary.avgConfidence}`);
|
|
279
|
+
return lines;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* V3.1 canonical markdown for IDE one-click copy (AI Mode).
|
|
283
|
+
* Layered: snapshot → working context → change/impact/graph → execution handoff → instruction.
|
|
284
|
+
*/
|
|
285
|
+
function formatCanonicalAiMarkdown(input) {
|
|
286
|
+
const lines = [];
|
|
287
|
+
lines.push('# TASK ANCHOR');
|
|
288
|
+
lines.push(input.taskAnchor.trim() || '(not set)');
|
|
289
|
+
lines.push('');
|
|
290
|
+
const snapLines = input.built
|
|
291
|
+
? formatSnapshotFromBuilt(input.built)
|
|
292
|
+
: input.snapshotMarkdown?.trim()
|
|
293
|
+
? formatSnapshotFromMarkdown(input.snapshotMarkdown)
|
|
294
|
+
: [];
|
|
295
|
+
if (snapLines.length) {
|
|
296
|
+
lines.push('# PROJECT SNAPSHOT');
|
|
297
|
+
lines.push(...snapLines);
|
|
298
|
+
lines.push('');
|
|
299
|
+
}
|
|
300
|
+
lines.push('# WORKING CONTEXT');
|
|
301
|
+
lines.push(...listSection('active_files:', input.activeFiles.length ? input.activeFiles : ['(none)']));
|
|
302
|
+
lines.push('');
|
|
303
|
+
lines.push(...listSection('recent_git_activity:', input.recentGitActivity.length ? input.recentGitActivity : ['(none)']));
|
|
304
|
+
lines.push('');
|
|
305
|
+
if (input.knowledgeSnapshot) {
|
|
306
|
+
lines.push(...formatCognitiveSnapshotSection(input.knowledgeSnapshot));
|
|
307
|
+
lines.push('');
|
|
308
|
+
}
|
|
309
|
+
const handoff = input.handoff;
|
|
310
|
+
if (handoff?.key_changes?.length) {
|
|
311
|
+
const modified = collectModifiedSymbols(handoff);
|
|
312
|
+
if (modified.length) {
|
|
313
|
+
lines.push('# CHANGE SET');
|
|
314
|
+
lines.push(...listSection('modified_symbols:', modified));
|
|
315
|
+
lines.push('');
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
if (handoff?.impact_summary.affected_functions.length) {
|
|
319
|
+
lines.push('# IMPACT SET');
|
|
320
|
+
lines.push(...listSection('impacted_symbols:', handoff.impact_summary.affected_functions.slice(0, 12)));
|
|
321
|
+
lines.push('');
|
|
322
|
+
}
|
|
323
|
+
const graphRefs = input.knowledgeSnapshot
|
|
324
|
+
? []
|
|
325
|
+
: (handoff?.context_graph_refs ?? []).map(normalizeGraphRef).filter(Boolean);
|
|
326
|
+
if (graphRefs.length) {
|
|
327
|
+
lines.push('# GRAPH REFS');
|
|
328
|
+
for (const ref of graphRefs.slice(0, 12)) {
|
|
329
|
+
lines.push(`- ${ref}`);
|
|
330
|
+
}
|
|
331
|
+
lines.push('');
|
|
332
|
+
}
|
|
333
|
+
if (handoff && (handoff.summary || handoff.current_focus || handoff.next_actions.length)) {
|
|
334
|
+
lines.push(formatAiHandoffExecutionBlock(handoff));
|
|
335
|
+
lines.push('');
|
|
336
|
+
}
|
|
337
|
+
const recent = input.timeline?.recent ?? [];
|
|
338
|
+
if (recent.length) {
|
|
339
|
+
lines.push('# CODE EVOLUTION');
|
|
340
|
+
for (const e of recent.slice(0, 5)) {
|
|
341
|
+
const syms = e.changes.map((c) => c.symbol).join(', ') || e.type;
|
|
342
|
+
lines.push(`- ${e.commit} · ${basenamePath(e.file)} · ${syms} (${e.impact_level})`);
|
|
343
|
+
}
|
|
344
|
+
lines.push('');
|
|
345
|
+
}
|
|
346
|
+
if (input.insights?.length) {
|
|
347
|
+
lines.push('# INSIGHTS');
|
|
348
|
+
for (const line of input.insights.slice(0, 4)) {
|
|
349
|
+
lines.push(`- ${line}`);
|
|
350
|
+
}
|
|
351
|
+
lines.push('');
|
|
352
|
+
}
|
|
353
|
+
const notes = (input.notes ?? '').trim();
|
|
354
|
+
if (notes && notes !== '(none)') {
|
|
355
|
+
lines.push('# NOTES');
|
|
356
|
+
lines.push(notes);
|
|
357
|
+
lines.push('');
|
|
358
|
+
}
|
|
359
|
+
lines.push('# INSTRUCTION');
|
|
360
|
+
lines.push(input.instruction.trim() || '(none)');
|
|
361
|
+
lines.push('');
|
|
362
|
+
return lines.join('\n');
|
|
363
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { HandoffArtifact, HandoffNextAction, ProjectTimeline } from './types.js';
|
|
2
|
+
import type { KnowledgeSnapshot } from './knowledgeGraph/types.js';
|
|
3
|
+
/** Single Next bullet — drops redundant "target: reason" when they repeat or overlap. */
|
|
4
|
+
export declare function formatNextActionBullet(a: HandoffNextAction): string;
|
|
5
|
+
/** CLI handoff markdown — execution block + optional timeline. */
|
|
6
|
+
export declare function formatHandoffMarkdown(handoff: HandoffArtifact, timeline?: ProjectTimeline): string;
|
|
7
|
+
/** Compact JSON export bundle for CLI `contorium export --format json`. */
|
|
8
|
+
export declare function buildUnderstandingExportJson(args: {
|
|
9
|
+
handoff: HandoffArtifact;
|
|
10
|
+
timeline?: ProjectTimeline;
|
|
11
|
+
projectSnapshot?: string;
|
|
12
|
+
knowledgeSnapshot?: KnowledgeSnapshot;
|
|
13
|
+
}): {
|
|
14
|
+
version: string;
|
|
15
|
+
projectSnapshot: string | undefined;
|
|
16
|
+
cognitiveSnapshot: KnowledgeSnapshot | undefined;
|
|
17
|
+
handoff: HandoffArtifact;
|
|
18
|
+
timeline: import("./types.js").TimelineEntry[] | undefined;
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=formatHandoff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatHandoff.d.ts","sourceRoot":"","sources":["../../src/understanding/formatHandoff.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACtF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAOnE,yFAAyF;AACzF,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAqBnE;AAED,kEAAkE;AAClE,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,eAAe,EACxB,QAAQ,CAAC,EAAE,eAAe,GACzB,MAAM,CAgBR;AAED,2EAA2E;AAC3E,wBAAgB,4BAA4B,CAAC,IAAI,EAAE;IACjD,OAAO,EAAE,eAAe,CAAC;IACzB,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC;;;;;;EAQA"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatNextActionBullet = formatNextActionBullet;
|
|
4
|
+
exports.formatHandoffMarkdown = formatHandoffMarkdown;
|
|
5
|
+
exports.buildUnderstandingExportJson = buildUnderstandingExportJson;
|
|
6
|
+
const formatCanonicalExport_js_1 = require("./formatCanonicalExport.js");
|
|
7
|
+
function normalizeNextText(s) {
|
|
8
|
+
return s.trim().toLowerCase().replace(/\s+/g, ' ');
|
|
9
|
+
}
|
|
10
|
+
/** Single Next bullet — drops redundant "target: reason" when they repeat or overlap. */
|
|
11
|
+
function formatNextActionBullet(a) {
|
|
12
|
+
const action = a.action;
|
|
13
|
+
const target = (a.target || '').trim();
|
|
14
|
+
const reason = (a.reason || '').trim();
|
|
15
|
+
const nt = normalizeNextText(target);
|
|
16
|
+
const nr = normalizeNextText(reason);
|
|
17
|
+
if (!target && !reason) {
|
|
18
|
+
return `- [${action}] (unspecified)`;
|
|
19
|
+
}
|
|
20
|
+
if (!reason || nr === nt) {
|
|
21
|
+
return `- [${action}] ${target || reason}`;
|
|
22
|
+
}
|
|
23
|
+
if (nr.startsWith(nt) || nt.startsWith(nr)) {
|
|
24
|
+
const text = reason.length >= target.length ? reason : target;
|
|
25
|
+
return `- [${action}] ${text}`;
|
|
26
|
+
}
|
|
27
|
+
if (reason.toLowerCase().startsWith(target.toLowerCase())) {
|
|
28
|
+
return `- [${action}] ${reason}`;
|
|
29
|
+
}
|
|
30
|
+
return `- [${action}] ${target}: ${reason}`;
|
|
31
|
+
}
|
|
32
|
+
/** CLI handoff markdown — execution block + optional timeline. */
|
|
33
|
+
function formatHandoffMarkdown(handoff, timeline) {
|
|
34
|
+
const lines = [(0, formatCanonicalExport_js_1.formatAiHandoffExecutionBlock)(handoff)];
|
|
35
|
+
const recent = timeline?.recent ?? [];
|
|
36
|
+
if (recent.length) {
|
|
37
|
+
lines.push('');
|
|
38
|
+
lines.push('# CODE EVOLUTION');
|
|
39
|
+
for (const e of recent.slice(0, 5)) {
|
|
40
|
+
const syms = e.changes.map((c) => c.symbol).join(', ') || e.type;
|
|
41
|
+
const file = e.file.replace(/\\/g, '/').split('/').pop() ?? e.file;
|
|
42
|
+
lines.push(`- ${e.commit} · ${file} · ${syms} (${e.impact_level})`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
lines.push('');
|
|
46
|
+
return lines.join('\n');
|
|
47
|
+
}
|
|
48
|
+
/** Compact JSON export bundle for CLI `contorium export --format json`. */
|
|
49
|
+
function buildUnderstandingExportJson(args) {
|
|
50
|
+
return {
|
|
51
|
+
version: 'v3.1',
|
|
52
|
+
projectSnapshot: args.projectSnapshot,
|
|
53
|
+
cognitiveSnapshot: args.knowledgeSnapshot,
|
|
54
|
+
handoff: args.handoff,
|
|
55
|
+
timeline: args.timeline?.recent?.slice(0, 5),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ProjectGraph } from './types.js';
|
|
2
|
+
import type { ChangeArtifact } from './types.js';
|
|
3
|
+
import { type FileExtraction } from './extractor.js';
|
|
4
|
+
export declare function buildChangeNeighborhoodGraph(workspaceRoot: string, changedFiles: string[], now?: number): Promise<{
|
|
5
|
+
graph: ProjectGraph;
|
|
6
|
+
extractions: Map<string, FileExtraction>;
|
|
7
|
+
}>;
|
|
8
|
+
export declare function deriveChangeArtifact(changedFiles: string[], extractions: Map<string, FileExtraction>, now?: number): ChangeArtifact;
|
|
9
|
+
//# sourceMappingURL=graphBuilder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphBuilder.d.ts","sourceRoot":"","sources":["../../src/understanding/graphBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAwB,YAAY,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAa,MAAM,YAAY,CAAC;AAE5D,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,gBAAgB,CAAC;AAUxB,wBAAsB,4BAA4B,CAChD,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,EAAE,EACtB,GAAG,SAAa,GACf,OAAO,CAAC;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;CAAE,CAAC,CA8E5E;AAED,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,EAAE,EACtB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,EACxC,GAAG,SAAa,GACf,cAAc,CAqBhB"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildChangeNeighborhoodGraph = buildChangeNeighborhoodGraph;
|
|
4
|
+
exports.deriveChangeArtifact = deriveChangeArtifact;
|
|
5
|
+
const types_js_1 = require("./types.js");
|
|
6
|
+
const extractor_js_1 = require("./extractor.js");
|
|
7
|
+
const symbolValidator_js_1 = require("./symbolValidator.js");
|
|
8
|
+
const MAX_NODES = 240;
|
|
9
|
+
const MAX_NEIGHBOR_FILES = 12;
|
|
10
|
+
function moduleNodeId(file) {
|
|
11
|
+
return (0, extractor_js_1.nodeId)(file, 'module', file);
|
|
12
|
+
}
|
|
13
|
+
async function buildChangeNeighborhoodGraph(workspaceRoot, changedFiles, now = Date.now()) {
|
|
14
|
+
const extractions = new Map();
|
|
15
|
+
const neighborFiles = new Set(changedFiles);
|
|
16
|
+
for (const file of changedFiles) {
|
|
17
|
+
const ext = await (0, extractor_js_1.extractFile)(workspaceRoot, file);
|
|
18
|
+
if (!ext) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
extractions.set(file, (0, symbolValidator_js_1.refineExtraction)(ext));
|
|
22
|
+
for (const sym of ext.symbols) {
|
|
23
|
+
if (sym.kind === 'import' && sym.importTarget) {
|
|
24
|
+
const resolved = (0, extractor_js_1.resolveRelativeImport)(file, sym.importTarget);
|
|
25
|
+
if (resolved && neighborFiles.size < changedFiles.length + MAX_NEIGHBOR_FILES) {
|
|
26
|
+
neighborFiles.add(resolved);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
for (const file of neighborFiles) {
|
|
32
|
+
if (extractions.has(file)) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const ext = await (0, extractor_js_1.extractFile)(workspaceRoot, file);
|
|
36
|
+
if (ext) {
|
|
37
|
+
extractions.set(file, (0, symbolValidator_js_1.refineExtraction)(ext));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const nodes = [];
|
|
41
|
+
const edges = [];
|
|
42
|
+
for (const [file, ext] of extractions) {
|
|
43
|
+
nodes.push({ id: moduleNodeId(file), kind: 'module', name: file, file });
|
|
44
|
+
for (const sym of ext.symbols) {
|
|
45
|
+
const id = (0, extractor_js_1.nodeId)(file, sym.kind, sym.name);
|
|
46
|
+
if (sym.kind === 'function' || sym.kind === 'class') {
|
|
47
|
+
nodes.push({ id, kind: sym.kind, name: sym.name, file, line: sym.line });
|
|
48
|
+
edges.push({ from: moduleNodeId(file), to: id, kind: 'contains' });
|
|
49
|
+
}
|
|
50
|
+
else if (sym.kind === 'import') {
|
|
51
|
+
nodes.push({ id, kind: 'import', name: sym.name, file, line: sym.line });
|
|
52
|
+
edges.push({ from: moduleNodeId(file), to: id, kind: 'imports' });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
for (const [file, ext] of extractions) {
|
|
57
|
+
const localFns = new Set((0, extractor_js_1.symbolNamesByKind)(ext, 'function'));
|
|
58
|
+
for (const call of ext.calls) {
|
|
59
|
+
if (!localFns.has(call)) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const fromCandidates = ext.symbols.filter((s) => s.kind === 'function');
|
|
63
|
+
for (const caller of fromCandidates) {
|
|
64
|
+
const fromId = (0, extractor_js_1.nodeId)(file, 'function', caller.name);
|
|
65
|
+
const toId = (0, extractor_js_1.nodeId)(file, 'function', call);
|
|
66
|
+
if (fromId !== toId) {
|
|
67
|
+
edges.push({ from: fromId, to: toId, kind: 'calls' });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const cappedNodes = nodes.slice(0, MAX_NODES);
|
|
73
|
+
const nodeIds = new Set(cappedNodes.map((n) => n.id));
|
|
74
|
+
const cappedEdges = edges.filter((e) => nodeIds.has(e.from) && nodeIds.has(e.to)).slice(0, MAX_NODES * 2);
|
|
75
|
+
return {
|
|
76
|
+
graph: {
|
|
77
|
+
version: 2,
|
|
78
|
+
generatedAt: now,
|
|
79
|
+
scope: 'change-neighborhood',
|
|
80
|
+
nodes: cappedNodes,
|
|
81
|
+
edges: cappedEdges,
|
|
82
|
+
},
|
|
83
|
+
extractions,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function deriveChangeArtifact(changedFiles, extractions, now = Date.now()) {
|
|
87
|
+
const key_changes = [];
|
|
88
|
+
for (const file of changedFiles) {
|
|
89
|
+
key_changes.push({ symbol: file, kind: 'file', change_type: 'modified' });
|
|
90
|
+
const ext = extractions.get(file);
|
|
91
|
+
if (!ext) {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
for (const fn of (0, extractor_js_1.symbolNamesByKind)(ext, 'function')) {
|
|
95
|
+
key_changes.push({ symbol: `${file}::${fn}`, kind: 'function', change_type: 'modified' });
|
|
96
|
+
}
|
|
97
|
+
for (const cls of (0, extractor_js_1.symbolNamesByKind)(ext, 'class')) {
|
|
98
|
+
key_changes.push({ symbol: `${file}::${cls}`, kind: 'class', change_type: 'modified' });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
version: types_js_1.UNDERSTANDING_VERSION,
|
|
103
|
+
generatedAt: now,
|
|
104
|
+
changed_files: changedFiles,
|
|
105
|
+
key_changes,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ChangeArtifact, HandoffArtifact, ImpactAnalysis, IntentFusion, ProjectGraph } from './types.js';
|
|
2
|
+
import type { ProjectBuiltState } from '../state-builder/types.js';
|
|
3
|
+
export declare function buildHandoff(args: {
|
|
4
|
+
goal: string;
|
|
5
|
+
intent: IntentFusion;
|
|
6
|
+
change: ChangeArtifact;
|
|
7
|
+
impact: ImpactAnalysis;
|
|
8
|
+
graph: ProjectGraph;
|
|
9
|
+
built?: ProjectBuiltState | null;
|
|
10
|
+
now?: number;
|
|
11
|
+
}): HandoffArtifact;
|
|
12
|
+
//# sourceMappingURL=handoffBuilder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handoffBuilder.d.ts","sourceRoot":"","sources":["../../src/understanding/handoffBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EAEf,cAAc,EACd,YAAY,EACZ,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAuEnE,wBAAgB,YAAY,CAAC,IAAI,EAAE;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,YAAY,CAAC;IACpB,KAAK,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,eAAe,CAsClB"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildHandoff = buildHandoff;
|
|
4
|
+
const types_js_1 = require("./types.js");
|
|
5
|
+
function inferAction(text) {
|
|
6
|
+
const t = text.toLowerCase();
|
|
7
|
+
if (/fix|bug|error|issue/.test(t)) {
|
|
8
|
+
return 'fix';
|
|
9
|
+
}
|
|
10
|
+
if (/refactor|clean|rename/.test(t)) {
|
|
11
|
+
return 'refactor';
|
|
12
|
+
}
|
|
13
|
+
if (/add|extend|implement|new feature/.test(t)) {
|
|
14
|
+
return 'extend';
|
|
15
|
+
}
|
|
16
|
+
if (/review|check|verify|audit/.test(t)) {
|
|
17
|
+
return 'review';
|
|
18
|
+
}
|
|
19
|
+
return 'continue';
|
|
20
|
+
}
|
|
21
|
+
function buildNextActions(built, impact, goal) {
|
|
22
|
+
const fromBuilt = (built?.next_actions ?? [])
|
|
23
|
+
.filter(Boolean)
|
|
24
|
+
.slice(0, 6)
|
|
25
|
+
.map((line) => {
|
|
26
|
+
const trimmed = line.trim();
|
|
27
|
+
return {
|
|
28
|
+
action: inferAction(trimmed),
|
|
29
|
+
target: trimmed,
|
|
30
|
+
reason: '',
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
if (fromBuilt.length) {
|
|
34
|
+
return fromBuilt;
|
|
35
|
+
}
|
|
36
|
+
const out = [];
|
|
37
|
+
if (impact.risk === 'high') {
|
|
38
|
+
out.push({
|
|
39
|
+
action: 'review',
|
|
40
|
+
target: impact.affected_functions[0] ?? 'changed symbols',
|
|
41
|
+
reason: 'High impact risk detected in change neighborhood',
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
if (goal) {
|
|
45
|
+
out.push({ action: 'continue', target: 'project goal', reason: goal });
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
out.push({
|
|
49
|
+
action: 'review',
|
|
50
|
+
target: 'recent changes',
|
|
51
|
+
reason: 'Review recent changes and continue the current task',
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
function graphRefs(graph, change) {
|
|
57
|
+
const names = new Set(change.key_changes
|
|
58
|
+
.filter((k) => k.kind !== 'file')
|
|
59
|
+
.map((k) => k.symbol.split('::').pop() ?? k.symbol));
|
|
60
|
+
const kindTag = (k) => (k === 'class' ? 'cls' : k === 'function' ? 'fn' : k);
|
|
61
|
+
return graph.nodes
|
|
62
|
+
.filter((n) => names.has(n.name))
|
|
63
|
+
.map((n) => `${kindTag(n.kind)}:${n.name}`)
|
|
64
|
+
.slice(0, 12);
|
|
65
|
+
}
|
|
66
|
+
function buildHandoff(args) {
|
|
67
|
+
const now = args.now ?? Date.now();
|
|
68
|
+
const next_actions = buildNextActions(args.built, args.impact, args.goal);
|
|
69
|
+
const context_graph_refs = graphRefs(args.graph, args.change);
|
|
70
|
+
const parts = [];
|
|
71
|
+
if (args.goal) {
|
|
72
|
+
parts.push(`Goal: ${args.goal}`);
|
|
73
|
+
}
|
|
74
|
+
parts.push(`Focus: ${args.intent.focus}`);
|
|
75
|
+
const fnChanges = args.change.key_changes.filter((k) => k.kind === 'function');
|
|
76
|
+
if (fnChanges.length) {
|
|
77
|
+
parts.push(`Changed: ${fnChanges.slice(0, 5).map((k) => k.symbol).join(', ')}`);
|
|
78
|
+
}
|
|
79
|
+
else if (args.change.changed_files.length) {
|
|
80
|
+
parts.push(`Changed files: ${args.change.changed_files.slice(0, 5).join(', ')}`);
|
|
81
|
+
}
|
|
82
|
+
if (args.impact.affected_functions.length) {
|
|
83
|
+
parts.push(`Impact (${args.impact.risk}): ${args.impact.affected_functions.slice(0, 4).join(', ')}`);
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
version: types_js_1.UNDERSTANDING_VERSION,
|
|
87
|
+
generatedAt: now,
|
|
88
|
+
goal: args.goal,
|
|
89
|
+
current_focus: args.intent.focus,
|
|
90
|
+
key_changes: args.change.key_changes,
|
|
91
|
+
impact_summary: {
|
|
92
|
+
risk: args.impact.risk,
|
|
93
|
+
affected_modules: args.impact.affected_modules,
|
|
94
|
+
affected_functions: args.impact.affected_functions,
|
|
95
|
+
details: args.impact.details,
|
|
96
|
+
},
|
|
97
|
+
next_actions,
|
|
98
|
+
context_graph_refs,
|
|
99
|
+
summary: parts.join(' | '),
|
|
100
|
+
};
|
|
101
|
+
}
|