@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.
Files changed (187) hide show
  1. package/README.md +97 -0
  2. package/bin/contorium-mcp.js +34 -0
  3. package/dist/autoContext.d.ts +2 -0
  4. package/dist/autoContext.js +2 -0
  5. package/dist/bootstrapCli.d.ts +2 -0
  6. package/dist/bootstrapCli.js +21 -0
  7. package/dist/conflicts.d.ts +19 -0
  8. package/dist/conflicts.js +49 -0
  9. package/dist/dashboardEnsure.d.ts +10 -0
  10. package/dist/dashboardEnsure.js +41 -0
  11. package/dist/intelligence.d.ts +16 -0
  12. package/dist/intelligence.js +38 -0
  13. package/dist/intentGraph.d.ts +20 -0
  14. package/dist/intentGraph.js +51 -0
  15. package/dist/mcpBootstrap.d.ts +8 -0
  16. package/dist/mcpBootstrap.js +81 -0
  17. package/dist/memoryStore.d.ts +18 -0
  18. package/dist/memoryStore.js +57 -0
  19. package/dist/paths.d.ts +12 -0
  20. package/dist/paths.js +66 -0
  21. package/dist/runtimeState.d.ts +14 -0
  22. package/dist/runtimeState.js +36 -0
  23. package/dist/server.d.ts +3 -0
  24. package/dist/server.js +567 -0
  25. package/dist/stateBuilder.d.ts +16 -0
  26. package/dist/stateBuilder.js +40 -0
  27. package/dist/understanding.d.ts +1 -0
  28. package/dist/understanding.js +1 -0
  29. package/dist/workspace.d.ts +12 -0
  30. package/dist/workspace.js +40 -0
  31. package/dist/workspaceConfig.d.ts +14 -0
  32. package/dist/workspaceConfig.js +80 -0
  33. package/node_modules/@contora/state-core/dist/adapterSync.d.ts +29 -0
  34. package/node_modules/@contora/state-core/dist/adapterSync.d.ts.map +1 -0
  35. package/node_modules/@contora/state-core/dist/adapterSync.js +142 -0
  36. package/node_modules/@contora/state-core/dist/adapters.d.ts +20 -0
  37. package/node_modules/@contora/state-core/dist/adapters.d.ts.map +1 -0
  38. package/node_modules/@contora/state-core/dist/adapters.js +24 -0
  39. package/node_modules/@contora/state-core/dist/bootstrap/bootstrapState.d.ts +6 -0
  40. package/node_modules/@contora/state-core/dist/bootstrap/bootstrapState.d.ts.map +1 -0
  41. package/node_modules/@contora/state-core/dist/bootstrap/bootstrapState.js +116 -0
  42. package/node_modules/@contora/state-core/dist/bootstrapArtifacts.d.ts +18 -0
  43. package/node_modules/@contora/state-core/dist/bootstrapArtifacts.d.ts.map +1 -0
  44. package/node_modules/@contora/state-core/dist/bootstrapArtifacts.js +43 -0
  45. package/node_modules/@contora/state-core/dist/bootstrapState.d.ts +6 -0
  46. package/node_modules/@contora/state-core/dist/bootstrapState.d.ts.map +1 -0
  47. package/node_modules/@contora/state-core/dist/bootstrapState.js +60 -0
  48. package/node_modules/@contora/state-core/dist/dashboardActivity.d.ts +12 -0
  49. package/node_modules/@contora/state-core/dist/dashboardActivity.d.ts.map +1 -0
  50. package/node_modules/@contora/state-core/dist/dashboardActivity.js +58 -0
  51. package/node_modules/@contora/state-core/dist/dualMode.d.ts +11 -0
  52. package/node_modules/@contora/state-core/dist/dualMode.d.ts.map +1 -0
  53. package/node_modules/@contora/state-core/dist/dualMode.js +38 -0
  54. package/node_modules/@contora/state-core/dist/gitScan.d.ts +7 -0
  55. package/node_modules/@contora/state-core/dist/gitScan.d.ts.map +1 -0
  56. package/node_modules/@contora/state-core/dist/gitScan.js +39 -0
  57. package/node_modules/@contora/state-core/dist/index.d.ts +44 -0
  58. package/node_modules/@contora/state-core/dist/index.d.ts.map +1 -0
  59. package/node_modules/@contora/state-core/dist/index.js +141 -0
  60. package/node_modules/@contora/state-core/dist/minimalSnapshot.d.ts +4 -0
  61. package/node_modules/@contora/state-core/dist/minimalSnapshot.d.ts.map +1 -0
  62. package/node_modules/@contora/state-core/dist/minimalSnapshot.js +60 -0
  63. package/node_modules/@contora/state-core/dist/scanner/gitScan.d.ts +7 -0
  64. package/node_modules/@contora/state-core/dist/scanner/gitScan.d.ts.map +1 -0
  65. package/node_modules/@contora/state-core/dist/scanner/gitScan.js +42 -0
  66. package/node_modules/@contora/state-core/dist/scanner/workspaceScanner.d.ts +4 -0
  67. package/node_modules/@contora/state-core/dist/scanner/workspaceScanner.d.ts.map +1 -0
  68. package/node_modules/@contora/state-core/dist/scanner/workspaceScanner.js +148 -0
  69. package/node_modules/@contora/state-core/dist/semiAutoHandoff.d.ts +46 -0
  70. package/node_modules/@contora/state-core/dist/semiAutoHandoff.d.ts.map +1 -0
  71. package/node_modules/@contora/state-core/dist/semiAutoHandoff.js +227 -0
  72. package/node_modules/@contora/state-core/dist/sourceMetadata.d.ts +4 -0
  73. package/node_modules/@contora/state-core/dist/sourceMetadata.d.ts.map +1 -0
  74. package/node_modules/@contora/state-core/dist/sourceMetadata.js +27 -0
  75. package/node_modules/@contora/state-core/dist/state-builder/buildFromScan.d.ts +5 -0
  76. package/node_modules/@contora/state-core/dist/state-builder/buildFromScan.d.ts.map +1 -0
  77. package/node_modules/@contora/state-core/dist/state-builder/buildFromScan.js +33 -0
  78. package/node_modules/@contora/state-core/dist/state-builder/normalization.d.ts +5 -0
  79. package/node_modules/@contora/state-core/dist/state-builder/normalization.d.ts.map +1 -0
  80. package/node_modules/@contora/state-core/dist/state-builder/normalization.js +107 -0
  81. package/node_modules/@contora/state-core/dist/state-builder/rebuildFromScan.d.ts +4 -0
  82. package/node_modules/@contora/state-core/dist/state-builder/rebuildFromScan.d.ts.map +1 -0
  83. package/node_modules/@contora/state-core/dist/state-builder/rebuildFromScan.js +22 -0
  84. package/node_modules/@contora/state-core/dist/state-builder/snapshot.d.ts +5 -0
  85. package/node_modules/@contora/state-core/dist/state-builder/snapshot.d.ts.map +1 -0
  86. package/node_modules/@contora/state-core/dist/state-builder/snapshot.js +53 -0
  87. package/node_modules/@contora/state-core/dist/state-builder/store.d.ts +7 -0
  88. package/node_modules/@contora/state-core/dist/state-builder/store.d.ts.map +1 -0
  89. package/node_modules/@contora/state-core/dist/state-builder/store.js +99 -0
  90. package/node_modules/@contora/state-core/dist/state-builder/types.d.ts +18 -0
  91. package/node_modules/@contora/state-core/dist/state-builder/types.d.ts.map +1 -0
  92. package/node_modules/@contora/state-core/dist/state-builder/types.js +20 -0
  93. package/node_modules/@contora/state-core/dist/types.d.ts +42 -0
  94. package/node_modules/@contora/state-core/dist/types.d.ts.map +1 -0
  95. package/node_modules/@contora/state-core/dist/types.js +3 -0
  96. package/node_modules/@contora/state-core/dist/understanding/buildUnderstanding.d.ts +22 -0
  97. package/node_modules/@contora/state-core/dist/understanding/buildUnderstanding.d.ts.map +1 -0
  98. package/node_modules/@contora/state-core/dist/understanding/buildUnderstanding.js +87 -0
  99. package/node_modules/@contora/state-core/dist/understanding/changeDetector.d.ts +7 -0
  100. package/node_modules/@contora/state-core/dist/understanding/changeDetector.d.ts.map +1 -0
  101. package/node_modules/@contora/state-core/dist/understanding/changeDetector.js +68 -0
  102. package/node_modules/@contora/state-core/dist/understanding/chpHandoff.d.ts +49 -0
  103. package/node_modules/@contora/state-core/dist/understanding/chpHandoff.d.ts.map +1 -0
  104. package/node_modules/@contora/state-core/dist/understanding/chpHandoff.js +214 -0
  105. package/node_modules/@contora/state-core/dist/understanding/extractor.d.ts +21 -0
  106. package/node_modules/@contora/state-core/dist/understanding/extractor.d.ts.map +1 -0
  107. package/node_modules/@contora/state-core/dist/understanding/extractor.js +173 -0
  108. package/node_modules/@contora/state-core/dist/understanding/formatCanonicalExport.d.ts +30 -0
  109. package/node_modules/@contora/state-core/dist/understanding/formatCanonicalExport.d.ts.map +1 -0
  110. package/node_modules/@contora/state-core/dist/understanding/formatCanonicalExport.js +363 -0
  111. package/node_modules/@contora/state-core/dist/understanding/formatHandoff.d.ts +20 -0
  112. package/node_modules/@contora/state-core/dist/understanding/formatHandoff.d.ts.map +1 -0
  113. package/node_modules/@contora/state-core/dist/understanding/formatHandoff.js +57 -0
  114. package/node_modules/@contora/state-core/dist/understanding/graphBuilder.d.ts +9 -0
  115. package/node_modules/@contora/state-core/dist/understanding/graphBuilder.d.ts.map +1 -0
  116. package/node_modules/@contora/state-core/dist/understanding/graphBuilder.js +107 -0
  117. package/node_modules/@contora/state-core/dist/understanding/handoffBuilder.d.ts +12 -0
  118. package/node_modules/@contora/state-core/dist/understanding/handoffBuilder.d.ts.map +1 -0
  119. package/node_modules/@contora/state-core/dist/understanding/handoffBuilder.js +101 -0
  120. package/node_modules/@contora/state-core/dist/understanding/impactAnalyzer.d.ts +5 -0
  121. package/node_modules/@contora/state-core/dist/understanding/impactAnalyzer.d.ts.map +1 -0
  122. package/node_modules/@contora/state-core/dist/understanding/impactAnalyzer.js +58 -0
  123. package/node_modules/@contora/state-core/dist/understanding/intentFusion.d.ts +9 -0
  124. package/node_modules/@contora/state-core/dist/understanding/intentFusion.d.ts.map +1 -0
  125. package/node_modules/@contora/state-core/dist/understanding/intentFusion.js +54 -0
  126. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/closureConstants.d.ts +24 -0
  127. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/closureConstants.d.ts.map +1 -0
  128. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/closureConstants.js +33 -0
  129. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/confidence.d.ts +20 -0
  130. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/confidence.d.ts.map +1 -0
  131. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/confidence.js +53 -0
  132. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/gitFrequency.d.ts +5 -0
  133. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/gitFrequency.d.ts.map +1 -0
  134. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/gitFrequency.js +19 -0
  135. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/hotspotBuilder.d.ts +13 -0
  136. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/hotspotBuilder.d.ts.map +1 -0
  137. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/hotspotBuilder.js +101 -0
  138. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/intentFunctionMapper.d.ts +22 -0
  139. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/intentFunctionMapper.d.ts.map +1 -0
  140. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/intentFunctionMapper.js +106 -0
  141. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/knowledgeGraphBuilder.d.ts +23 -0
  142. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/knowledgeGraphBuilder.d.ts.map +1 -0
  143. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/knowledgeGraphBuilder.js +415 -0
  144. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/normalize.d.ts +11 -0
  145. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/normalize.d.ts.map +1 -0
  146. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/normalize.js +136 -0
  147. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/rebuildTrigger.d.ts +13 -0
  148. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/rebuildTrigger.d.ts.map +1 -0
  149. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/rebuildTrigger.js +34 -0
  150. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/snapshotBuilder.d.ts +17 -0
  151. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/snapshotBuilder.d.ts.map +1 -0
  152. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/snapshotBuilder.js +73 -0
  153. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/store.d.ts +7 -0
  154. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/store.d.ts.map +1 -0
  155. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/store.js +127 -0
  156. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/types.d.ts +116 -0
  157. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/types.d.ts.map +1 -0
  158. package/node_modules/@contora/state-core/dist/understanding/knowledgeGraph/types.js +6 -0
  159. package/node_modules/@contora/state-core/dist/understanding/miniGraph.d.ts +4 -0
  160. package/node_modules/@contora/state-core/dist/understanding/miniGraph.d.ts.map +1 -0
  161. package/node_modules/@contora/state-core/dist/understanding/miniGraph.js +18 -0
  162. package/node_modules/@contora/state-core/dist/understanding/store.d.ts +24 -0
  163. package/node_modules/@contora/state-core/dist/understanding/store.d.ts.map +1 -0
  164. package/node_modules/@contora/state-core/dist/understanding/store.js +243 -0
  165. package/node_modules/@contora/state-core/dist/understanding/symbolValidator.d.ts +9 -0
  166. package/node_modules/@contora/state-core/dist/understanding/symbolValidator.d.ts.map +1 -0
  167. package/node_modules/@contora/state-core/dist/understanding/symbolValidator.js +51 -0
  168. package/node_modules/@contora/state-core/dist/understanding/timelineTracker.d.ts +3 -0
  169. package/node_modules/@contora/state-core/dist/understanding/timelineTracker.d.ts.map +1 -0
  170. package/node_modules/@contora/state-core/dist/understanding/timelineTracker.js +129 -0
  171. package/node_modules/@contora/state-core/dist/understanding/treeSitterParser.d.ts +24 -0
  172. package/node_modules/@contora/state-core/dist/understanding/treeSitterParser.d.ts.map +1 -0
  173. package/node_modules/@contora/state-core/dist/understanding/treeSitterParser.js +56 -0
  174. package/node_modules/@contora/state-core/dist/understanding/types.d.ts +136 -0
  175. package/node_modules/@contora/state-core/dist/understanding/types.d.ts.map +1 -0
  176. package/node_modules/@contora/state-core/dist/understanding/types.js +5 -0
  177. package/node_modules/@contora/state-core/dist/understanding/understandingGraphBuilder.d.ts +23 -0
  178. package/node_modules/@contora/state-core/dist/understanding/understandingGraphBuilder.d.ts.map +1 -0
  179. package/node_modules/@contora/state-core/dist/understanding/understandingGraphBuilder.js +67 -0
  180. package/node_modules/@contora/state-core/dist/version.d.ts +3 -0
  181. package/node_modules/@contora/state-core/dist/version.d.ts.map +1 -0
  182. package/node_modules/@contora/state-core/dist/version.js +21 -0
  183. package/node_modules/@contora/state-core/dist/workspaceScanner.d.ts +4 -0
  184. package/node_modules/@contora/state-core/dist/workspaceScanner.d.ts.map +1 -0
  185. package/node_modules/@contora/state-core/dist/workspaceScanner.js +112 -0
  186. package/node_modules/@contora/state-core/package.json +49 -0
  187. 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
+ }