@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 @@
1
+ export { readChangeArtifact, readHandoffArtifact, readImpactArtifact, readIntentArtifact, readProjectGraph, readProjectKnowledgeGraph, readKnowledgeSnapshot, readProjectTimeline, readUnderstandingGraph, readStateJson, readWorkspaceStatus, filterMappingsByConfidence, getProjectHandoff, } from '@contora/state-core';
@@ -0,0 +1,12 @@
1
+ export interface WorkspaceSnapshot {
2
+ workspaceRoot: string;
3
+ currentTask: string;
4
+ notes: string;
5
+ sessionId?: string;
6
+ openFiles: string[];
7
+ recentFiles: string[];
8
+ gitStaged: string[];
9
+ gitWorking: string[];
10
+ lastUpdated: number;
11
+ }
12
+ export declare function loadWorkspaceSnapshot(workspaceRoot: string): Promise<WorkspaceSnapshot | null>;
@@ -0,0 +1,40 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ const CONTORA_DATA_DIR = '.contora';
4
+ const LEGACY_DATA_DIR = '.context-recall';
5
+ async function readStateFile(dir, relData) {
6
+ const fp = path.join(dir, relData, 'state.json');
7
+ try {
8
+ const text = await fs.readFile(fp, 'utf8');
9
+ const o = JSON.parse(text);
10
+ if (!o || typeof o !== 'object') {
11
+ return undefined;
12
+ }
13
+ return {
14
+ workspaceRoot: dir,
15
+ sessionId: typeof o.sessionId === 'string' ? o.sessionId : undefined,
16
+ currentTask: typeof o.currentTask === 'string' ? o.currentTask : '',
17
+ notes: typeof o.notes === 'string' ? o.notes : '',
18
+ openFiles: Array.isArray(o.openFiles) ? o.openFiles.filter((x) => typeof x === 'string') : [],
19
+ recentFiles: Array.isArray(o.recentFiles)
20
+ ? o.recentFiles.filter((x) => typeof x === 'string')
21
+ : [],
22
+ gitStaged: Array.isArray(o.gitStaged) ? o.gitStaged.filter((x) => typeof x === 'string') : [],
23
+ gitWorking: Array.isArray(o.gitWorking)
24
+ ? o.gitWorking.filter((x) => typeof x === 'string')
25
+ : [],
26
+ lastUpdated: typeof o.lastUpdated === 'number' ? o.lastUpdated : 0,
27
+ };
28
+ }
29
+ catch {
30
+ return undefined;
31
+ }
32
+ }
33
+ export async function loadWorkspaceSnapshot(workspaceRoot) {
34
+ const primary = await readStateFile(workspaceRoot, CONTORA_DATA_DIR);
35
+ if (primary) {
36
+ return primary;
37
+ }
38
+ const legacy = await readStateFile(workspaceRoot, LEGACY_DATA_DIR);
39
+ return legacy ?? null;
40
+ }
@@ -0,0 +1,14 @@
1
+ export interface McpStartupConfig {
2
+ workspaceHint: string;
3
+ workspaceFromArgv: boolean;
4
+ }
5
+ /** Set once at process start from CLI --workspace (highest priority). */
6
+ export declare function setStartupWorkspace(workspace: string | undefined): void;
7
+ /**
8
+ * Workspace hint resolution (MCP v1 standard):
9
+ * 1. CLI --workspace
10
+ * 2. CONTORIUM_WORKSPACE (+ host env aliases)
11
+ * 3. .mcp.json / .cursor/mcp.json
12
+ * 4. process.cwd()
13
+ */
14
+ export declare function resolveMcpStartupConfig(argv?: string[]): McpStartupConfig;
@@ -0,0 +1,80 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ let startupWorkspaceOverride;
4
+ /** Set once at process start from CLI --workspace (highest priority). */
5
+ export function setStartupWorkspace(workspace) {
6
+ startupWorkspaceOverride = workspace?.trim() || undefined;
7
+ }
8
+ function parseWorkspaceArg(argv) {
9
+ for (let i = 0; i < argv.length; i++) {
10
+ const arg = argv[i];
11
+ if (arg === '--workspace' && argv[i + 1]) {
12
+ return argv[i + 1].trim();
13
+ }
14
+ if (arg.startsWith('--workspace=')) {
15
+ return arg.slice('--workspace='.length).trim();
16
+ }
17
+ }
18
+ return undefined;
19
+ }
20
+ function expandEnvPlaceholders(value) {
21
+ return value.replace(/\$\{([^}]+)\}/g, (_, name) => process.env[name]?.trim() ?? '');
22
+ }
23
+ function readMcpJsonWorkspace(startDir) {
24
+ const candidates = [
25
+ path.join(startDir, '.mcp.json'),
26
+ path.join(startDir, '.cursor', 'mcp.json'),
27
+ ];
28
+ for (const file of candidates) {
29
+ try {
30
+ const raw = fs.readFileSync(file, 'utf8');
31
+ const parsed = JSON.parse(raw);
32
+ const servers = parsed.mcpServers;
33
+ const contoriumBlock = parsed.contorium;
34
+ const env = servers?.contorium?.env ??
35
+ servers?.['@contorium/mcp']?.env ??
36
+ contoriumBlock?.env;
37
+ const ws = env?.CONTORIUM_WORKSPACE?.trim();
38
+ if (ws) {
39
+ const expanded = expandEnvPlaceholders(ws);
40
+ if (expanded) {
41
+ return path.resolve(expanded);
42
+ }
43
+ }
44
+ }
45
+ catch {
46
+ // try next candidate
47
+ }
48
+ }
49
+ return undefined;
50
+ }
51
+ /**
52
+ * Workspace hint resolution (MCP v1 standard):
53
+ * 1. CLI --workspace
54
+ * 2. CONTORIUM_WORKSPACE (+ host env aliases)
55
+ * 3. .mcp.json / .cursor/mcp.json
56
+ * 4. process.cwd()
57
+ */
58
+ export function resolveMcpStartupConfig(argv = process.argv.slice(2)) {
59
+ const fromArgv = parseWorkspaceArg(argv);
60
+ if (fromArgv) {
61
+ setStartupWorkspace(fromArgv);
62
+ return { workspaceHint: path.resolve(fromArgv), workspaceFromArgv: true };
63
+ }
64
+ if (startupWorkspaceOverride) {
65
+ return { workspaceHint: path.resolve(startupWorkspaceOverride), workspaceFromArgv: true };
66
+ }
67
+ const fromEnv = process.env.CONTORIUM_WORKSPACE?.trim() ||
68
+ process.env.CODEX_PROJECT_DIR?.trim() ||
69
+ process.env.CLAUDE_PROJECT_DIR?.trim() ||
70
+ process.env.CLAUDE_PROJECT_ROOT?.trim() ||
71
+ process.env.MCP_WORKSPACE_ROOT?.trim();
72
+ if (fromEnv) {
73
+ return { workspaceHint: path.resolve(fromEnv), workspaceFromArgv: false };
74
+ }
75
+ const fromMcpJson = readMcpJsonWorkspace(process.cwd());
76
+ if (fromMcpJson) {
77
+ return { workspaceHint: fromMcpJson, workspaceFromArgv: false };
78
+ }
79
+ return { workspaceHint: process.cwd(), workspaceFromArgv: false };
80
+ }
@@ -0,0 +1,29 @@
1
+ import type { AdapterKind, StateEngineMode, StateSourceMetadata } from './types.js';
2
+ export interface AdapterSyncResult {
3
+ mode: StateEngineMode;
4
+ /** true when .contora/state.json did not exist before this call */
5
+ created: boolean;
6
+ /** true when state.json or artifacts were written */
7
+ updated: boolean;
8
+ source?: StateSourceMetadata;
9
+ eventCount: number;
10
+ }
11
+ /**
12
+ * Shared one-shot sync for MCP / CLI adapters (runtime adapter pattern).
13
+ * Scans workspace, merges into state.json, optionally rebuilds L4 when no events.
14
+ */
15
+ export declare function syncWorkspaceState(workspaceRoot: string, writer: AdapterKind, options?: {
16
+ forceArtifacts?: boolean;
17
+ }): Promise<AdapterSyncResult>;
18
+ /** Read-only status for CLI `status` / IDE-less inspection. */
19
+ export declare function readWorkspaceStatus(workspaceRoot: string): Promise<{
20
+ workspaceRoot: string;
21
+ hasState: boolean;
22
+ mode: StateEngineMode | 'unknown';
23
+ source?: StateSourceMetadata;
24
+ eventCount: number;
25
+ gitWorking: number;
26
+ gitStaged: number;
27
+ currentTask: string;
28
+ }>;
29
+ //# sourceMappingURL=adapterSync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapterSync.d.ts","sourceRoot":"","sources":["../src/adapterSync.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AA4BpF,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,eAAe,CAAC;IACtB,mEAAmE;IACnE,OAAO,EAAE,OAAO,CAAC;IACjB,qDAAqD;IACrD,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,WAAW,EACnB,OAAO,CAAC,EAAE;IAAE,cAAc,CAAC,EAAE,OAAO,CAAA;CAAE,GACrC,OAAO,CAAC,iBAAiB,CAAC,CA8D5B;AAED,+DAA+D;AAC/D,wBAAsB,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC;IACxE,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,eAAe,GAAG,SAAS,CAAC;IAClC,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CAiBD"}
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.syncWorkspaceState = syncWorkspaceState;
37
+ exports.readWorkspaceStatus = readWorkspaceStatus;
38
+ const path = __importStar(require("node:path"));
39
+ const bootstrapState_js_1 = require("./bootstrap/bootstrapState.js");
40
+ const rebuildFromScan_js_1 = require("./state-builder/rebuildFromScan.js");
41
+ const buildUnderstanding_js_1 = require("./understanding/buildUnderstanding.js");
42
+ const dualMode_js_1 = require("./dualMode.js");
43
+ const dashboardActivity_js_1 = require("./dashboardActivity.js");
44
+ const workspaceScanner_js_1 = require("./scanner/workspaceScanner.js");
45
+ async function countEventLines(workspaceRoot) {
46
+ const { readdir, readFile } = await Promise.resolve().then(() => __importStar(require('node:fs/promises')));
47
+ const { join } = await Promise.resolve().then(() => __importStar(require('node:path')));
48
+ const dir = join(workspaceRoot, '.contora', 'events');
49
+ let total = 0;
50
+ try {
51
+ const files = await readdir(dir);
52
+ for (const f of files) {
53
+ if (!f.endsWith('.jsonl')) {
54
+ continue;
55
+ }
56
+ const text = await readFile(join(dir, f), 'utf8');
57
+ total += text.split('\n').filter((l) => l.trim()).length;
58
+ }
59
+ }
60
+ catch {
61
+ return 0;
62
+ }
63
+ return total;
64
+ }
65
+ /**
66
+ * Shared one-shot sync for MCP / CLI adapters (runtime adapter pattern).
67
+ * Scans workspace, merges into state.json, optionally rebuilds L4 when no events.
68
+ */
69
+ async function syncWorkspaceState(workspaceRoot, writer, options) {
70
+ const resolved = path.resolve(workspaceRoot);
71
+ const scan = await (0, workspaceScanner_js_1.scanWorkspace)(resolved);
72
+ const eventCount = await countEventLines(resolved);
73
+ const existing = await (0, bootstrapState_js_1.readStateJson)(resolved);
74
+ const created = !existing;
75
+ if (!existing) {
76
+ const state = (0, bootstrapState_js_1.bootstrapStateFromScan)(scan);
77
+ await (0, bootstrapState_js_1.writeStateJson)(resolved, state, { mode: 'scan-driven', writer });
78
+ await (0, rebuildFromScan_js_1.rebuildArtifactsFromScan)(resolved, scan, state, writer);
79
+ const written = await (0, bootstrapState_js_1.readStateJson)(resolved);
80
+ return {
81
+ mode: 'scan-driven',
82
+ created: true,
83
+ updated: true,
84
+ source: written?.source,
85
+ eventCount,
86
+ };
87
+ }
88
+ const dual = (0, dualMode_js_1.buildDualModeInput)({ state: existing, eventCount, scan });
89
+ const gitChanged = JSON.stringify(existing.gitStaged) !== JSON.stringify(dual.state.gitStaged) ||
90
+ JSON.stringify(existing.gitWorking) !== JSON.stringify(dual.state.gitWorking);
91
+ const recentChanged = eventCount === 0 &&
92
+ JSON.stringify(existing.recentFiles) !== JSON.stringify(dual.state.recentFiles);
93
+ const shouldWrite = gitChanged || recentChanged || options?.forceArtifacts;
94
+ if (shouldWrite) {
95
+ await (0, bootstrapState_js_1.writeStateJson)(resolved, dual.state, { mode: dual.mode, writer });
96
+ }
97
+ if (eventCount === 0 && (shouldWrite || options?.forceArtifacts)) {
98
+ await (0, rebuildFromScan_js_1.rebuildArtifactsFromScan)(resolved, scan, dual.state, writer);
99
+ }
100
+ if (gitChanged || options?.forceArtifacts) {
101
+ await (0, buildUnderstanding_js_1.buildAndWriteUnderstandingArtifacts)({
102
+ workspaceRoot: resolved,
103
+ state: dual.state,
104
+ scan,
105
+ }).catch(() => undefined);
106
+ }
107
+ const written = await (0, bootstrapState_js_1.readStateJson)(resolved);
108
+ const updated = shouldWrite || (eventCount === 0 && !!options?.forceArtifacts);
109
+ if (updated || gitChanged) {
110
+ await (0, dashboardActivity_js_1.bumpWorkspaceActivity)(resolved, {
111
+ source: writer,
112
+ kind: gitChanged ? 'git_change' : 'sync',
113
+ detail: gitChanged ? 'workspace sync' : undefined,
114
+ }).catch(() => undefined);
115
+ }
116
+ return {
117
+ mode: dual.mode,
118
+ created: false,
119
+ updated,
120
+ source: written?.source,
121
+ eventCount,
122
+ };
123
+ }
124
+ /** Read-only status for CLI `status` / IDE-less inspection. */
125
+ async function readWorkspaceStatus(workspaceRoot) {
126
+ const scan = await (0, workspaceScanner_js_1.scanWorkspace)(workspaceRoot);
127
+ const state = await (0, bootstrapState_js_1.readStateJson)(workspaceRoot);
128
+ const eventCount = await countEventLines(workspaceRoot);
129
+ const mode = state
130
+ ? (0, dualMode_js_1.buildDualModeInput)({ state, eventCount, scan }).mode
131
+ : 'unknown';
132
+ return {
133
+ workspaceRoot,
134
+ hasState: !!state,
135
+ mode,
136
+ source: state?.source,
137
+ eventCount,
138
+ gitWorking: state?.gitWorking.length ?? scan.gitWorking.length,
139
+ gitStaged: state?.gitStaged.length ?? scan.gitStaged.length,
140
+ currentTask: state?.currentTask ?? '',
141
+ };
142
+ }
@@ -0,0 +1,20 @@
1
+ import type { AdapterKind } from './types.js';
2
+ /** Tool adapter contract — adapters ingest; State Engine owns truth. */
3
+ export interface ContoriumAdapter {
4
+ readonly kind: AdapterKind;
5
+ /** Human-readable status for logs / MCP debug. */
6
+ describe(): string;
7
+ }
8
+ export declare class IdeAdapter implements ContoriumAdapter {
9
+ readonly kind: "ide";
10
+ describe(): string;
11
+ }
12
+ export declare class McpAdapter implements ContoriumAdapter {
13
+ readonly kind: "mcp";
14
+ describe(): string;
15
+ }
16
+ export declare class CliAdapter implements ContoriumAdapter {
17
+ readonly kind: "cli";
18
+ describe(): string;
19
+ }
20
+ //# sourceMappingURL=adapters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapters.d.ts","sourceRoot":"","sources":["../src/adapters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,wEAAwE;AACxE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,kDAAkD;IAClD,QAAQ,IAAI,MAAM,CAAC;CACpB;AAED,qBAAa,UAAW,YAAW,gBAAgB;IACjD,QAAQ,CAAC,IAAI,EAAG,KAAK,CAAU;IAC/B,QAAQ,IAAI,MAAM;CAGnB;AAED,qBAAa,UAAW,YAAW,gBAAgB;IACjD,QAAQ,CAAC,IAAI,EAAG,KAAK,CAAU;IAC/B,QAAQ,IAAI,MAAM;CAGnB;AAED,qBAAa,UAAW,YAAW,gBAAgB;IACjD,QAAQ,CAAC,IAAI,EAAG,KAAK,CAAU;IAC/B,QAAQ,IAAI,MAAM;CAGnB"}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CliAdapter = exports.McpAdapter = exports.IdeAdapter = void 0;
4
+ class IdeAdapter {
5
+ kind = 'ide';
6
+ describe() {
7
+ return 'IDE event streaming (Mode A)';
8
+ }
9
+ }
10
+ exports.IdeAdapter = IdeAdapter;
11
+ class McpAdapter {
12
+ kind = 'mcp';
13
+ describe() {
14
+ return 'MCP workspace scan + poll (Mode B)';
15
+ }
16
+ }
17
+ exports.McpAdapter = McpAdapter;
18
+ class CliAdapter {
19
+ kind = 'cli';
20
+ describe() {
21
+ return 'CLI scan command (Mode B)';
22
+ }
23
+ }
24
+ exports.CliAdapter = CliAdapter;
@@ -0,0 +1,6 @@
1
+ import type { BootstrapStateJson, WriteStateOptions, WorkspaceScanFacts } from '../types.js';
2
+ export declare function bootstrapStateFromScan(scan: WorkspaceScanFacts): BootstrapStateJson;
3
+ export declare function readStateJson(workspaceRoot: string): Promise<BootstrapStateJson | null>;
4
+ export declare function writeStateJson(workspaceRoot: string, state: BootstrapStateJson, meta?: WriteStateOptions): Promise<void>;
5
+ export declare function stateJsonExists(workspaceRoot: string): Promise<boolean>;
6
+ //# sourceMappingURL=bootstrapState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrapState.d.ts","sourceRoot":"","sources":["../../src/bootstrap/bootstrapState.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAQ7F,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,kBAAkB,GAAG,kBAAkB,CAWnF;AAED,wBAAsB,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CA2C7F;AAED,wBAAsB,cAAc,CAClC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,kBAAkB,EACzB,IAAI,CAAC,EAAE,iBAAiB,GACvB,OAAO,CAAC,IAAI,CAAC,CAKf;AAED,wBAAsB,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO7E"}
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.bootstrapStateFromScan = bootstrapStateFromScan;
37
+ exports.readStateJson = readStateJson;
38
+ exports.writeStateJson = writeStateJson;
39
+ exports.stateJsonExists = stateJsonExists;
40
+ const fs = __importStar(require("node:fs/promises"));
41
+ const path = __importStar(require("node:path"));
42
+ const sourceMetadata_js_1 = require("../sourceMetadata.js");
43
+ const CONTORA_DIR = '.contora';
44
+ function newSessionId() {
45
+ return `sess_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
46
+ }
47
+ function bootstrapStateFromScan(scan) {
48
+ return {
49
+ sessionId: newSessionId(),
50
+ currentTask: '',
51
+ openFiles: scan.recentFiles.slice(0, 8),
52
+ recentFiles: scan.recentFiles.slice(0, 24),
53
+ gitStaged: scan.gitStaged,
54
+ gitWorking: scan.gitWorking,
55
+ notes: '',
56
+ lastUpdated: scan.scannedAt,
57
+ };
58
+ }
59
+ async function readStateJson(workspaceRoot) {
60
+ const fp = path.join(workspaceRoot, CONTORA_DIR, 'state.json');
61
+ try {
62
+ const text = await fs.readFile(fp, 'utf8');
63
+ const o = JSON.parse(text);
64
+ const sourceRaw = o.source;
65
+ let source;
66
+ if (sourceRaw && typeof sourceRaw === 'object') {
67
+ const s = sourceRaw;
68
+ if ((s.mode === 'event-driven' || s.mode === 'scan-driven' || s.mode === 'merged') &&
69
+ (s.lastWriter === 'ide' || s.lastWriter === 'mcp' || s.lastWriter === 'cli') &&
70
+ typeof s.lastUpdated === 'string') {
71
+ source = {
72
+ mode: s.mode,
73
+ lastWriter: s.lastWriter,
74
+ lastUpdated: s.lastUpdated,
75
+ };
76
+ }
77
+ }
78
+ return {
79
+ sessionId: typeof o.sessionId === 'string' ? o.sessionId : newSessionId(),
80
+ currentTask: typeof o.currentTask === 'string' ? o.currentTask : '',
81
+ openFiles: Array.isArray(o.openFiles)
82
+ ? o.openFiles.filter((x) => typeof x === 'string')
83
+ : [],
84
+ recentFiles: Array.isArray(o.recentFiles)
85
+ ? o.recentFiles.filter((x) => typeof x === 'string')
86
+ : [],
87
+ gitStaged: Array.isArray(o.gitStaged)
88
+ ? o.gitStaged.filter((x) => typeof x === 'string')
89
+ : [],
90
+ gitWorking: Array.isArray(o.gitWorking)
91
+ ? o.gitWorking.filter((x) => typeof x === 'string')
92
+ : [],
93
+ notes: typeof o.notes === 'string' ? o.notes : '',
94
+ lastUpdated: typeof o.lastUpdated === 'number' ? o.lastUpdated : 0,
95
+ source,
96
+ };
97
+ }
98
+ catch {
99
+ return null;
100
+ }
101
+ }
102
+ async function writeStateJson(workspaceRoot, state, meta) {
103
+ const dir = path.join(workspaceRoot, CONTORA_DIR);
104
+ await fs.mkdir(dir, { recursive: true });
105
+ const toWrite = meta ? (0, sourceMetadata_js_1.attachStateSource)(state, meta.mode, meta.writer) : state;
106
+ await fs.writeFile(path.join(dir, 'state.json'), JSON.stringify(toWrite, null, 2), 'utf8');
107
+ }
108
+ async function stateJsonExists(workspaceRoot) {
109
+ try {
110
+ await fs.access(path.join(workspaceRoot, CONTORA_DIR, 'state.json'));
111
+ return true;
112
+ }
113
+ catch {
114
+ return false;
115
+ }
116
+ }
@@ -0,0 +1,18 @@
1
+ import type { BootstrapStateJson, WorkspaceScanFacts } from './types.js';
2
+ export interface BootstrapProjectBuiltState {
3
+ version: 1;
4
+ engine_version: 2;
5
+ generatedAt: number;
6
+ task_anchor?: string;
7
+ project_goal: string;
8
+ current_stage: string;
9
+ active_modules: string[];
10
+ recent_decisions: string[];
11
+ open_problems: string[];
12
+ completed_milestones: string[];
13
+ next_actions: string[];
14
+ confidence: number;
15
+ }
16
+ export declare function buildBootstrapProjectState(scan: WorkspaceScanFacts, state?: BootstrapStateJson): BootstrapProjectBuiltState;
17
+ export declare function writeBootstrapArtifacts(workspaceRoot: string, scan: WorkspaceScanFacts, state?: BootstrapStateJson): Promise<void>;
18
+ //# sourceMappingURL=bootstrapArtifacts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrapArtifacts.d.ts","sourceRoot":"","sources":["../src/bootstrapArtifacts.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAIzE,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,CAAC,CAAC;IACX,cAAc,EAAE,CAAC,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,kBAAkB,EACxB,KAAK,CAAC,EAAE,kBAAkB,GACzB,0BAA0B,CA8B5B;AAED,wBAAsB,uBAAuB,CAC3C,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE,kBAAkB,EACxB,KAAK,CAAC,EAAE,kBAAkB,GACzB,OAAO,CAAC,IAAI,CAAC,CASf"}
@@ -0,0 +1,43 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ import { formatBootstrapSnapshotMarkdown } from './minimalSnapshot.js';
4
+ const BUILDER_DIR = ['.contora', 'state-builder'];
5
+ export function buildBootstrapProjectState(scan, state) {
6
+ const modules = [
7
+ ...scan.topLevelModules.slice(0, 6),
8
+ ...scan.recentFiles.slice(0, 4).map((f) => f.split('/').pop() ?? f),
9
+ ];
10
+ const active = [...new Set(modules)].slice(0, 8);
11
+ const goal = scan.readmeHint?.trim() ||
12
+ (active.length ? `develop ${active.slice(0, 2).join(' and ')} areas` : 'ongoing workspace development');
13
+ const gitCount = scan.gitStaged.length + scan.gitWorking.length;
14
+ return {
15
+ version: 1,
16
+ engine_version: 2,
17
+ generatedAt: scan.scannedAt,
18
+ task_anchor: state?.currentTask?.trim() || undefined,
19
+ project_goal: goal,
20
+ current_stage: scan.isGitRepo
21
+ ? 'repository scan (tool-agnostic bootstrap)'
22
+ : 'workspace scan (no git)',
23
+ active_modules: active,
24
+ recent_decisions: [],
25
+ open_problems: gitCount >= 6 ? ['uncommitted changes across workspace'] : ['(light or undirected activity)'],
26
+ completed_milestones: [],
27
+ next_actions: [
28
+ 'review recent file activity',
29
+ ...(scan.isGitRepo ? ['review and commit pending changes'] : []),
30
+ ],
31
+ confidence: 0.35,
32
+ };
33
+ }
34
+ export async function writeBootstrapArtifacts(workspaceRoot, scan, state) {
35
+ const dir = path.join(workspaceRoot, ...BUILDER_DIR);
36
+ await fs.mkdir(dir, { recursive: true });
37
+ const built = buildBootstrapProjectState(scan, state);
38
+ const md = formatBootstrapSnapshotMarkdown(scan, state?.currentTask ?? '');
39
+ await Promise.all([
40
+ fs.writeFile(path.join(dir, 'project-state.json'), JSON.stringify(built, null, 2), 'utf8'),
41
+ fs.writeFile(path.join(dir, 'project-snapshot.md'), md, 'utf8'),
42
+ ]);
43
+ }
@@ -0,0 +1,6 @@
1
+ import type { BootstrapStateJson, WorkspaceScanFacts } from './types.js';
2
+ export declare function bootstrapStateFromScan(scan: WorkspaceScanFacts): BootstrapStateJson;
3
+ export declare function readStateJson(workspaceRoot: string): Promise<BootstrapStateJson | null>;
4
+ export declare function writeStateJson(workspaceRoot: string, state: BootstrapStateJson): Promise<void>;
5
+ export declare function stateJsonExists(workspaceRoot: string): Promise<boolean>;
6
+ //# sourceMappingURL=bootstrapState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrapState.d.ts","sourceRoot":"","sources":["../src/bootstrapState.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAQzE,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,kBAAkB,GAAG,kBAAkB,CAWnF;AAED,wBAAsB,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CA0B7F;AAED,wBAAsB,cAAc,CAClC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,IAAI,CAAC,CAQf;AAED,wBAAsB,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO7E"}
@@ -0,0 +1,60 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ const CONTORA_DIR = '.contora';
4
+ function newSessionId() {
5
+ return `sess_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
6
+ }
7
+ export function bootstrapStateFromScan(scan) {
8
+ return {
9
+ sessionId: newSessionId(),
10
+ currentTask: '',
11
+ openFiles: scan.recentFiles.slice(0, 8),
12
+ recentFiles: scan.recentFiles.slice(0, 24),
13
+ gitStaged: scan.gitStaged,
14
+ gitWorking: scan.gitWorking,
15
+ notes: '',
16
+ lastUpdated: scan.scannedAt,
17
+ };
18
+ }
19
+ export async function readStateJson(workspaceRoot) {
20
+ const fp = path.join(workspaceRoot, CONTORA_DIR, 'state.json');
21
+ try {
22
+ const text = await fs.readFile(fp, 'utf8');
23
+ const o = JSON.parse(text);
24
+ return {
25
+ sessionId: typeof o.sessionId === 'string' ? o.sessionId : newSessionId(),
26
+ currentTask: typeof o.currentTask === 'string' ? o.currentTask : '',
27
+ openFiles: Array.isArray(o.openFiles)
28
+ ? o.openFiles.filter((x) => typeof x === 'string')
29
+ : [],
30
+ recentFiles: Array.isArray(o.recentFiles)
31
+ ? o.recentFiles.filter((x) => typeof x === 'string')
32
+ : [],
33
+ gitStaged: Array.isArray(o.gitStaged)
34
+ ? o.gitStaged.filter((x) => typeof x === 'string')
35
+ : [],
36
+ gitWorking: Array.isArray(o.gitWorking)
37
+ ? o.gitWorking.filter((x) => typeof x === 'string')
38
+ : [],
39
+ notes: typeof o.notes === 'string' ? o.notes : '',
40
+ lastUpdated: typeof o.lastUpdated === 'number' ? o.lastUpdated : 0,
41
+ };
42
+ }
43
+ catch {
44
+ return null;
45
+ }
46
+ }
47
+ export async function writeStateJson(workspaceRoot, state) {
48
+ const dir = path.join(workspaceRoot, CONTORA_DIR);
49
+ await fs.mkdir(dir, { recursive: true });
50
+ await fs.writeFile(path.join(dir, 'state.json'), JSON.stringify(state, null, 2), 'utf8');
51
+ }
52
+ export async function stateJsonExists(workspaceRoot) {
53
+ try {
54
+ await fs.access(path.join(workspaceRoot, CONTORA_DIR, 'state.json'));
55
+ return true;
56
+ }
57
+ catch {
58
+ return false;
59
+ }
60
+ }
@@ -0,0 +1,12 @@
1
+ import type { AdapterKind } from './types.js';
2
+ export type WorkspaceActivityKind = 'file_change' | 'function_change' | 'git_change' | 'sync' | 'event';
3
+ export interface WorkspaceActivityBump {
4
+ at: number;
5
+ source: AdapterKind;
6
+ kind: WorkspaceActivityKind;
7
+ detail?: string;
8
+ }
9
+ /** Record workspace activity — universal trigger for dashboard auto-attach (IDE / MCP / CLI). */
10
+ export declare function bumpWorkspaceActivity(workspaceRoot: string, bump: Omit<WorkspaceActivityBump, 'at'>): Promise<void>;
11
+ export declare function readWorkspaceActivity(workspaceRoot: string): Promise<WorkspaceActivityBump | undefined>;
12
+ //# sourceMappingURL=dashboardActivity.d.ts.map