@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,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateSymbols = validateSymbols;
4
+ exports.validateCalls = validateCalls;
5
+ exports.refineExtraction = refineExtraction;
6
+ const NOISE_NAMES = new Set([
7
+ 'constructor', 'toString', 'valueOf', 'then', 'catch', 'finally', 'map', 'filter', 'reduce',
8
+ 'forEach', 'push', 'pop', 'slice', 'join', 'length', 'log', 'error', 'warn',
9
+ ]);
10
+ const TS_TYPE_LIKE = /^[A-Z][A-Z0-9_]*$/;
11
+ /**
12
+ * Hybrid precision layer (V3.1) — post-filters regex noise.
13
+ * Tree-sitter can replace/enhance this module later without changing the pipeline.
14
+ */
15
+ function validateSymbols(symbols) {
16
+ const seen = new Set();
17
+ const out = [];
18
+ for (const sym of symbols) {
19
+ if (sym.kind === 'import') {
20
+ if (sym.name.startsWith('.') || sym.name.includes('/')) {
21
+ out.push(sym);
22
+ }
23
+ continue;
24
+ }
25
+ if (sym.name.length < 2 || NOISE_NAMES.has(sym.name)) {
26
+ continue;
27
+ }
28
+ if (sym.kind === 'function' && TS_TYPE_LIKE.test(sym.name) && sym.name.length <= 3) {
29
+ continue;
30
+ }
31
+ const key = `${sym.kind}::${sym.name}::${sym.line}`;
32
+ if (seen.has(key)) {
33
+ continue;
34
+ }
35
+ seen.add(key);
36
+ out.push(sym);
37
+ }
38
+ return out;
39
+ }
40
+ function validateCalls(calls, symbols) {
41
+ const fnNames = new Set(symbols.filter((s) => s.kind === 'function').map((s) => s.name));
42
+ return calls.filter((c) => fnNames.has(c) || (!NOISE_NAMES.has(c) && c.length > 2));
43
+ }
44
+ function refineExtraction(ext) {
45
+ const symbols = validateSymbols(ext.symbols);
46
+ return {
47
+ file: ext.file,
48
+ symbols,
49
+ calls: validateCalls(ext.calls, symbols),
50
+ };
51
+ }
@@ -0,0 +1,3 @@
1
+ import type { ChangeArtifact, ProjectGraph, ProjectTimeline } from './types.js';
2
+ export declare function buildProjectTimeline(workspaceRoot: string, changedFiles: string[], change: ChangeArtifact, graph: ProjectGraph, now?: number, maxCommits?: number): Promise<ProjectTimeline>;
3
+ //# sourceMappingURL=timelineTracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timelineTracker.d.ts","sourceRoot":"","sources":["../../src/understanding/timelineTracker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAa,YAAY,EAAE,eAAe,EAA4B,MAAM,YAAY,CAAC;AA4FrH,wBAAsB,oBAAoB,CACxC,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,EAAE,EACtB,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,YAAY,EACnB,GAAG,SAAa,EAChB,UAAU,SAAI,GACb,OAAO,CAAC,eAAe,CAAC,CAsD1B"}
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildProjectTimeline = buildProjectTimeline;
4
+ const node_child_process_1 = require("node:child_process");
5
+ const node_util_1 = require("node:util");
6
+ const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
7
+ function norm(p) {
8
+ return p.replace(/\\/g, '/');
9
+ }
10
+ function graphRef(kind, name) {
11
+ return `${kind}:${name}`;
12
+ }
13
+ function riskFromChangeCount(n) {
14
+ if (n >= 4) {
15
+ return 'high';
16
+ }
17
+ if (n >= 2) {
18
+ return 'medium';
19
+ }
20
+ return 'low';
21
+ }
22
+ async function recentGitCommits(workspaceRoot, max = 5) {
23
+ try {
24
+ const { stdout } = await execFileAsync('git', ['-C', workspaceRoot, 'log', `-${max}`, '--pretty=format:---%n%H|%ct', '--name-status'], { timeout: 15_000, maxBuffer: 2 * 1024 * 1024 });
25
+ const rows = [];
26
+ let current;
27
+ for (const line of stdout.split('\n')) {
28
+ if (line === '---') {
29
+ current = undefined;
30
+ continue;
31
+ }
32
+ const header = line.match(/^([0-9a-f]{7,40})\|(\d+)$/);
33
+ if (header) {
34
+ current = { hash: header[1], timestamp: Number(header[2]) * 1000 };
35
+ continue;
36
+ }
37
+ if (!current || line.length < 2) {
38
+ continue;
39
+ }
40
+ const status = line[0];
41
+ const file = norm(line.slice(1).trim().split('\t').pop() ?? line.slice(2).trim());
42
+ if (!file) {
43
+ continue;
44
+ }
45
+ let type = 'modify';
46
+ if (status === 'A') {
47
+ type = 'add';
48
+ }
49
+ else if (status === 'D') {
50
+ type = 'delete';
51
+ }
52
+ else if (status === 'R') {
53
+ type = 'rename';
54
+ }
55
+ rows.push({ hash: current.hash, timestamp: current.timestamp, type, file });
56
+ }
57
+ return rows;
58
+ }
59
+ catch {
60
+ return [];
61
+ }
62
+ }
63
+ function keyChangesForFile(change, file) {
64
+ return change.key_changes.filter((k) => (k.kind === 'file' && k.symbol === file) || k.symbol.startsWith(`${file}::`));
65
+ }
66
+ function linkedNodes(graph, file, keyChanges) {
67
+ const names = new Set(keyChanges.map((k) => k.symbol.split('::').pop() ?? k.symbol));
68
+ const refs = [];
69
+ for (const n of graph.nodes) {
70
+ if (n.file !== file) {
71
+ continue;
72
+ }
73
+ if (names.has(n.name)) {
74
+ refs.push(graphRef(n.kind, n.name));
75
+ }
76
+ }
77
+ return refs.slice(0, 8);
78
+ }
79
+ async function buildProjectTimeline(workspaceRoot, changedFiles, change, graph, now = Date.now(), maxCommits = 5) {
80
+ const commits = await recentGitCommits(workspaceRoot, maxCommits);
81
+ const watch = new Set(changedFiles.map(norm));
82
+ const byFile = new Map();
83
+ for (const row of commits) {
84
+ if (!watch.has(row.file) && !changedFiles.some((f) => row.file.startsWith(f))) {
85
+ continue;
86
+ }
87
+ const kc = keyChangesForFile(change, row.file);
88
+ const entry = {
89
+ commit: row.hash.slice(0, 7),
90
+ timestamp: row.timestamp,
91
+ type: row.type,
92
+ file: row.file,
93
+ changes: kc.map((k) => ({
94
+ symbol: k.symbol.split('::').pop() ?? k.symbol,
95
+ change: k.change_type === 'added' ? 'symbol_added' : 'logic_modified',
96
+ })),
97
+ impact_level: riskFromChangeCount(kc.length),
98
+ linked_graph_nodes: linkedNodes(graph, row.file, kc),
99
+ };
100
+ const list = byFile.get(row.file) ?? [];
101
+ list.push(entry);
102
+ byFile.set(row.file, list);
103
+ }
104
+ const files = [...byFile.entries()].map(([file, history]) => ({ file, history }));
105
+ const recent = commits
106
+ .filter((r) => watch.has(r.file))
107
+ .slice(0, maxCommits)
108
+ .map((row) => {
109
+ const kc = keyChangesForFile(change, row.file);
110
+ return {
111
+ commit: row.hash.slice(0, 7),
112
+ timestamp: row.timestamp,
113
+ type: row.type,
114
+ file: row.file,
115
+ changes: kc.map((k) => ({
116
+ symbol: k.symbol.split('::').pop() ?? k.symbol,
117
+ change: k.change_type === 'added' ? 'symbol_added' : 'logic_modified',
118
+ })),
119
+ impact_level: riskFromChangeCount(kc.length),
120
+ linked_graph_nodes: linkedNodes(graph, row.file, kc),
121
+ };
122
+ });
123
+ return {
124
+ version: 1,
125
+ generatedAt: now,
126
+ files,
127
+ recent,
128
+ };
129
+ }
@@ -0,0 +1,24 @@
1
+ import type { FileExtraction } from './extractor.js';
2
+ export type ParseBackend = 'regex' | 'tree-sitter';
3
+ export interface ParseFileOptions {
4
+ content?: string;
5
+ /** Reserved for tree-sitter incremental parse (previous AST snapshot). */
6
+ previous?: FileExtraction;
7
+ }
8
+ /**
9
+ * Hybrid parser adapter (V3.1).
10
+ * Default: regex fast path. Tree-sitter activates when `web-tree-sitter` is installed.
11
+ */
12
+ export declare function parseFileWithAdapter(workspaceRoot: string, relFile: string, options?: ParseFileOptions): Promise<{
13
+ extraction: FileExtraction;
14
+ backend: ParseBackend;
15
+ } | undefined>;
16
+ /** In-memory incremental parse cache for IDE live edits. */
17
+ export declare class IncrementalParseCache {
18
+ private readonly byFile;
19
+ get(file: string): FileExtraction | undefined;
20
+ set(file: string, extraction: FileExtraction): void;
21
+ invalidate(file: string): void;
22
+ clear(): void;
23
+ }
24
+ //# sourceMappingURL=treeSitterParser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"treeSitterParser.d.ts","sourceRoot":"","sources":["../../src/understanding/treeSitterParser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAIrD,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,aAAa,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC;IAAE,UAAU,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GAAG,SAAS,CAAC,CAqB5E;AAeD,4DAA4D;AAC5D,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;IAE5D,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAI7C,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,GAAG,IAAI;IAInD,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI9B,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IncrementalParseCache = void 0;
4
+ exports.parseFileWithAdapter = parseFileWithAdapter;
5
+ const extractor_js_1 = require("./extractor.js");
6
+ const symbolValidator_js_1 = require("./symbolValidator.js");
7
+ /**
8
+ * Hybrid parser adapter (V3.1).
9
+ * Default: regex fast path. Tree-sitter activates when `web-tree-sitter` is installed.
10
+ */
11
+ async function parseFileWithAdapter(workspaceRoot, relFile, options = {}) {
12
+ const normalized = relFile.replace(/\\/g, '/');
13
+ if (!(0, extractor_js_1.isCodeFile)(normalized)) {
14
+ return undefined;
15
+ }
16
+ const ts = await tryTreeSitterParse(normalized, options.content, workspaceRoot);
17
+ if (ts) {
18
+ return { extraction: (0, symbolValidator_js_1.refineExtraction)(ts), backend: 'tree-sitter' };
19
+ }
20
+ let raw;
21
+ if (options.content !== undefined) {
22
+ raw = (0, extractor_js_1.extractFromSource)(normalized, options.content);
23
+ }
24
+ else {
25
+ raw = await (0, extractor_js_1.extractFile)(workspaceRoot, normalized);
26
+ }
27
+ if (!raw) {
28
+ return undefined;
29
+ }
30
+ return { extraction: (0, symbolValidator_js_1.refineExtraction)(raw), backend: 'regex' };
31
+ }
32
+ async function tryTreeSitterParse(relFile, content, workspaceRoot) {
33
+ // V3.2: wire web-tree-sitter + language grammars here (optional peer dependency).
34
+ // Until then, incremental live edits use regex extractFromSource via parseFileWithAdapter.
35
+ void relFile;
36
+ void content;
37
+ void workspaceRoot;
38
+ return undefined;
39
+ }
40
+ /** In-memory incremental parse cache for IDE live edits. */
41
+ class IncrementalParseCache {
42
+ byFile = new Map();
43
+ get(file) {
44
+ return this.byFile.get(file.replace(/\\/g, '/'));
45
+ }
46
+ set(file, extraction) {
47
+ this.byFile.set(file.replace(/\\/g, '/'), extraction);
48
+ }
49
+ invalidate(file) {
50
+ this.byFile.delete(file.replace(/\\/g, '/'));
51
+ }
52
+ clear() {
53
+ this.byFile.clear();
54
+ }
55
+ }
56
+ exports.IncrementalParseCache = IncrementalParseCache;
@@ -0,0 +1,136 @@
1
+ /** V3.1 Project Understanding — 3+1 artifacts: graph, change, handoff, timeline. */
2
+ export type GraphNodeKind = 'function' | 'class' | 'module' | 'import';
3
+ export interface GraphNode {
4
+ id: string;
5
+ kind: GraphNodeKind;
6
+ name: string;
7
+ file: string;
8
+ line?: number;
9
+ }
10
+ export type GraphEdgeKind = 'calls' | 'imports' | 'contains';
11
+ export interface GraphEdge {
12
+ from: string;
13
+ to: string;
14
+ kind: GraphEdgeKind;
15
+ }
16
+ export interface ProjectGraph {
17
+ version: 2;
18
+ generatedAt: number;
19
+ scope: 'change-neighborhood';
20
+ nodes: GraphNode[];
21
+ edges: GraphEdge[];
22
+ }
23
+ export type RiskLevel = 'low' | 'medium' | 'high';
24
+ export type ChangeType = 'added' | 'modified' | 'removed' | 'unknown';
25
+ export interface KeyChange {
26
+ symbol: string;
27
+ kind: 'function' | 'class' | 'file';
28
+ change_type: ChangeType;
29
+ }
30
+ export interface ChangeArtifact {
31
+ version: 2;
32
+ generatedAt: number;
33
+ changed_files: string[];
34
+ key_changes: KeyChange[];
35
+ }
36
+ export type HandoffActionKind = 'refactor' | 'fix' | 'extend' | 'review' | 'continue';
37
+ export interface HandoffNextAction {
38
+ action: HandoffActionKind;
39
+ target: string;
40
+ reason: string;
41
+ }
42
+ export interface HandoffImpactSummary {
43
+ risk: RiskLevel;
44
+ affected_modules: string[];
45
+ affected_functions: string[];
46
+ details: string[];
47
+ }
48
+ /** V3.1 — sole AI entry point; intent + impact merged here. */
49
+ export interface HandoffArtifact {
50
+ version: 2;
51
+ generatedAt: number;
52
+ goal: string;
53
+ current_focus: string;
54
+ key_changes: KeyChange[];
55
+ impact_summary: HandoffImpactSummary;
56
+ next_actions: HandoffNextAction[];
57
+ context_graph_refs: string[];
58
+ summary: string;
59
+ }
60
+ export interface TimelineSymbolChange {
61
+ symbol: string;
62
+ change: string;
63
+ }
64
+ export interface TimelineEntry {
65
+ commit: string;
66
+ timestamp: number;
67
+ type: 'modify' | 'add' | 'delete' | 'rename';
68
+ file: string;
69
+ changes: TimelineSymbolChange[];
70
+ impact_level: RiskLevel;
71
+ linked_graph_nodes: string[];
72
+ }
73
+ export interface FileTimeline {
74
+ file: string;
75
+ history: TimelineEntry[];
76
+ }
77
+ export interface ProjectTimeline {
78
+ version: 1;
79
+ generatedAt: number;
80
+ files: FileTimeline[];
81
+ /** Last N commits flattened for quick AI scan */
82
+ recent: TimelineEntry[];
83
+ }
84
+ /** Internal — used during pipeline, not persisted as separate artifact. */
85
+ export interface ImpactAnalysis {
86
+ affected_functions: string[];
87
+ affected_modules: string[];
88
+ risk: RiskLevel;
89
+ details: string[];
90
+ }
91
+ export interface IntentFusion {
92
+ focus: string;
93
+ confidence: number;
94
+ signals: string[];
95
+ }
96
+ export declare const UNDERSTANDING_VERSION: 2;
97
+ /** @deprecated V3.0 standalone artifact — read from handoff in V3.1 */
98
+ export interface ImpactArtifact {
99
+ version: 1;
100
+ generatedAt: number;
101
+ affected_functions: string[];
102
+ affected_modules: string[];
103
+ risk: RiskLevel;
104
+ risk_level: RiskLevel;
105
+ details: string[];
106
+ }
107
+ /** @deprecated V3.0 standalone artifact — read from handoff in V3.1 */
108
+ export interface IntentArtifact {
109
+ version: 1;
110
+ generatedAt: number;
111
+ intent: string;
112
+ confidence: number;
113
+ signals: string[];
114
+ }
115
+ /** @deprecated V3.0 handoff shape — normalized on read */
116
+ export interface HandoffArtifactV1 {
117
+ version: 1;
118
+ generatedAt: number;
119
+ goal: string;
120
+ intent: string;
121
+ changed: {
122
+ changedFiles: string[];
123
+ changed_functions: string[];
124
+ changed_classes: string[];
125
+ };
126
+ impact: {
127
+ affected_functions: string[];
128
+ affected_modules: string[];
129
+ risk_level: RiskLevel;
130
+ details: string[];
131
+ };
132
+ next_actions: string[];
133
+ summary: string;
134
+ }
135
+ export type AnyHandoffArtifact = HandoffArtifact | HandoffArtifactV1;
136
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/understanding/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ /** V3.1 Project Understanding — 3+1 artifacts: graph, change, handoff, timeline. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.UNDERSTANDING_VERSION = void 0;
5
+ exports.UNDERSTANDING_VERSION = 2;
@@ -0,0 +1,23 @@
1
+ import type { AdapterKind } from '../types.js';
2
+ import type { ChangeArtifact, HandoffArtifact, ProjectGraph } from './types.js';
3
+ /** Runtime Understanding Graph — call chains + impact from recent changes. */
4
+ export interface UnderstandingGraph {
5
+ version: 1;
6
+ generatedAt: number;
7
+ recent_change: {
8
+ name: string;
9
+ file?: string;
10
+ change_type?: string;
11
+ };
12
+ call_chain: string[];
13
+ affected: string[];
14
+ agent: string;
15
+ }
16
+ export declare function buildUnderstandingGraph(args: {
17
+ graph: ProjectGraph;
18
+ change: ChangeArtifact;
19
+ handoff: HandoffArtifact;
20
+ agent?: AdapterKind | string;
21
+ now?: number;
22
+ }): UnderstandingGraph | undefined;
23
+ //# sourceMappingURL=understandingGraphBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"understandingGraphBuilder.d.ts","sourceRoot":"","sources":["../../src/understanding/understandingGraphBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEhF,8EAA8E;AAC9E,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,CAAC,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAoCD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAC5C,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE,eAAe,CAAC;IACzB,KAAK,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,kBAAkB,GAAG,SAAS,CAwCjC"}
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildUnderstandingGraph = buildUnderstandingGraph;
4
+ function nodeName(graph, id) {
5
+ return graph.nodes.find((n) => n.id === id)?.name;
6
+ }
7
+ function buildCallChain(graph, seedSymbol, maxDepth = 6) {
8
+ const seed = graph.nodes.find((n) => n.name === seedSymbol && (n.kind === 'function' || n.kind === 'class'));
9
+ if (!seed) {
10
+ return [seedSymbol];
11
+ }
12
+ const chain = [seed.name];
13
+ const callEdges = graph.edges.filter((e) => e.kind === 'calls');
14
+ let current = seed.id;
15
+ const visited = new Set([current]);
16
+ for (let depth = 0; depth < maxDepth; depth++) {
17
+ const edge = callEdges.find((e) => e.from === current);
18
+ if (!edge || visited.has(edge.to)) {
19
+ break;
20
+ }
21
+ visited.add(edge.to);
22
+ const name = nodeName(graph, edge.to);
23
+ if (!name) {
24
+ break;
25
+ }
26
+ chain.push(name);
27
+ current = edge.to;
28
+ }
29
+ return chain;
30
+ }
31
+ function buildUnderstandingGraph(args) {
32
+ const fnChange = args.handoff.key_changes.find((k) => k.kind === 'function' || k.kind === 'class') ??
33
+ args.change.key_changes.find((k) => k.kind === 'function' || k.kind === 'class');
34
+ if (!fnChange) {
35
+ const affected = args.handoff.impact_summary.affected_functions.slice(0, 8);
36
+ if (!affected.length) {
37
+ return undefined;
38
+ }
39
+ return {
40
+ version: 1,
41
+ generatedAt: args.now ?? Date.now(),
42
+ recent_change: { name: '(file-level)', change_type: 'modified' },
43
+ call_chain: affected.slice(0, 4),
44
+ affected,
45
+ agent: String(args.agent ?? 'runtime'),
46
+ };
47
+ }
48
+ const displayName = fnChange.kind === 'function' ? `${fnChange.symbol}()` : fnChange.symbol;
49
+ const call_chain = buildCallChain(args.graph, fnChange.symbol);
50
+ const affected = [
51
+ ...new Set([
52
+ ...args.handoff.impact_summary.affected_functions,
53
+ ...call_chain.map((n) => (n.endsWith('()') ? n : `${n}()`)),
54
+ ]),
55
+ ].slice(0, 12);
56
+ return {
57
+ version: 1,
58
+ generatedAt: args.now ?? Date.now(),
59
+ recent_change: {
60
+ name: displayName,
61
+ change_type: fnChange.change_type,
62
+ },
63
+ call_chain: call_chain.map((n) => (n.endsWith('()') ? n : `${n}()`)),
64
+ affected,
65
+ agent: String(args.agent ?? 'runtime'),
66
+ };
67
+ }
@@ -0,0 +1,3 @@
1
+ /** Read @contora/state-core version from package.json (not hardcoded). */
2
+ export declare function getContoriumPackageVersion(): string;
3
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAKA,0EAA0E;AAC1E,wBAAgB,0BAA0B,IAAI,MAAM,CAYnD"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getContoriumPackageVersion = getContoriumPackageVersion;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ let cachedVersion;
7
+ /** Read @contora/state-core version from package.json (not hardcoded). */
8
+ function getContoriumPackageVersion() {
9
+ if (cachedVersion) {
10
+ return cachedVersion;
11
+ }
12
+ try {
13
+ const pkgPath = (0, node_path_1.join)(__dirname, '..', 'package.json');
14
+ const pkg = JSON.parse((0, node_fs_1.readFileSync)(pkgPath, 'utf8'));
15
+ cachedVersion = pkg.version ?? '0.0.0';
16
+ }
17
+ catch {
18
+ cachedVersion = '0.0.0';
19
+ }
20
+ return cachedVersion;
21
+ }
@@ -0,0 +1,4 @@
1
+ import type { WorkspaceScanFacts } from './types.js';
2
+ /** Mode B — workspace filesystem scan (no IDE required). */
3
+ export declare function scanWorkspace(workspaceRoot: string): Promise<WorkspaceScanFacts>;
4
+ //# sourceMappingURL=workspaceScanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaceScanner.d.ts","sourceRoot":"","sources":["../src/workspaceScanner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AA6FrD,4DAA4D;AAC5D,wBAAsB,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAmBtF"}
@@ -0,0 +1,112 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ import { scanGitPorcelain } from './gitScan.js';
4
+ const SKIP_DIRS = new Set([
5
+ 'node_modules',
6
+ '.git',
7
+ '.contora',
8
+ '.context-recall',
9
+ 'dist',
10
+ 'out',
11
+ '.vscode',
12
+ 'coverage',
13
+ ]);
14
+ const SKIP_EXT = /\.(png|jpg|jpeg|gif|ico|woff2?|ttf|eot|zip|vsix|map)$/i;
15
+ async function readReadmeHint(root) {
16
+ for (const name of ['README.md', 'readme.md', 'Readme.md']) {
17
+ try {
18
+ const text = await fs.readFile(path.join(root, name), 'utf8');
19
+ for (const line of text.split('\n')) {
20
+ const t = line.replace(/^#+\s*/, '').trim();
21
+ if (t.length >= 12 && !/^contorium|table of contents/i.test(t)) {
22
+ return t.length > 160 ? t.slice(0, 157) + '…' : t;
23
+ }
24
+ }
25
+ }
26
+ catch {
27
+ /* try next */
28
+ }
29
+ }
30
+ return undefined;
31
+ }
32
+ async function listTopLevelModules(root) {
33
+ const out = [];
34
+ try {
35
+ const entries = await fs.readdir(root, { withFileTypes: true });
36
+ for (const e of entries) {
37
+ if (!e.isDirectory() || e.name.startsWith('.') || SKIP_DIRS.has(e.name)) {
38
+ continue;
39
+ }
40
+ out.push(e.name);
41
+ }
42
+ }
43
+ catch {
44
+ return out;
45
+ }
46
+ return out.slice(0, 12);
47
+ }
48
+ async function collectRecentFiles(root, maxFiles, maxDepth) {
49
+ const scored = [];
50
+ async function walk(dir, depth) {
51
+ if (depth > maxDepth || scored.length >= maxFiles * 3) {
52
+ return;
53
+ }
54
+ let entries;
55
+ try {
56
+ entries = await fs.readdir(dir, { withFileTypes: true });
57
+ }
58
+ catch {
59
+ return;
60
+ }
61
+ for (const e of entries) {
62
+ const name = e.name;
63
+ if (name.startsWith('.') && name !== '.env') {
64
+ if (SKIP_DIRS.has(name)) {
65
+ continue;
66
+ }
67
+ }
68
+ const full = path.join(dir, name);
69
+ const rel = path.relative(root, full).replace(/\\/g, '/');
70
+ if (e.isDirectory()) {
71
+ if (!SKIP_DIRS.has(name)) {
72
+ await walk(full, depth + 1);
73
+ }
74
+ continue;
75
+ }
76
+ if (SKIP_EXT.test(name)) {
77
+ continue;
78
+ }
79
+ try {
80
+ const st = await fs.stat(full);
81
+ scored.push({ rel, mtime: st.mtimeMs });
82
+ }
83
+ catch {
84
+ /* skip */
85
+ }
86
+ }
87
+ }
88
+ await walk(root, 0);
89
+ scored.sort((a, b) => b.mtime - a.mtime);
90
+ return scored.slice(0, maxFiles).map((s) => s.rel);
91
+ }
92
+ /** Mode B — workspace filesystem scan (no IDE required). */
93
+ export async function scanWorkspace(workspaceRoot) {
94
+ const root = path.resolve(workspaceRoot);
95
+ const now = Date.now();
96
+ const [git, topLevelModules, recentFiles, readmeHint] = await Promise.all([
97
+ scanGitPorcelain(root),
98
+ listTopLevelModules(root),
99
+ collectRecentFiles(root, 24, 5),
100
+ readReadmeHint(root),
101
+ ]);
102
+ return {
103
+ workspaceRoot: root,
104
+ scannedAt: now,
105
+ topLevelModules,
106
+ recentFiles,
107
+ gitStaged: git.staged,
108
+ gitWorking: git.working,
109
+ readmeHint,
110
+ isGitRepo: git.isRepo,
111
+ };
112
+ }