mcp-context-sync 1.0.0

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 (72) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +85 -0
  3. package/dist/cli.d.ts +12 -0
  4. package/dist/cli.js +255 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/db/connection.d.ts +3 -0
  7. package/dist/db/connection.js +44 -0
  8. package/dist/db/connection.js.map +1 -0
  9. package/dist/db/queries.d.ts +23 -0
  10. package/dist/db/queries.js +121 -0
  11. package/dist/db/queries.js.map +1 -0
  12. package/dist/db/schema.d.ts +2 -0
  13. package/dist/db/schema.js +103 -0
  14. package/dist/db/schema.js.map +1 -0
  15. package/dist/index.d.ts +1 -0
  16. package/dist/index.js +56 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/lib/project-id.d.ts +13 -0
  19. package/dist/lib/project-id.js +27 -0
  20. package/dist/lib/project-id.js.map +1 -0
  21. package/dist/lib/snapshot-renderer.d.ts +9 -0
  22. package/dist/lib/snapshot-renderer.js +77 -0
  23. package/dist/lib/snapshot-renderer.js.map +1 -0
  24. package/dist/lib/types.d.ts +290 -0
  25. package/dist/lib/types.js +122 -0
  26. package/dist/lib/types.js.map +1 -0
  27. package/dist/lib/uuid.d.ts +1 -0
  28. package/dist/lib/uuid.js +5 -0
  29. package/dist/lib/uuid.js.map +1 -0
  30. package/dist/lib/validation.d.ts +18 -0
  31. package/dist/lib/validation.js +63 -0
  32. package/dist/lib/validation.js.map +1 -0
  33. package/dist/prompts/auto-resume.d.ts +3 -0
  34. package/dist/prompts/auto-resume.js +70 -0
  35. package/dist/prompts/auto-resume.js.map +1 -0
  36. package/dist/prompts/resume-work.d.ts +2 -0
  37. package/dist/prompts/resume-work.js +29 -0
  38. package/dist/prompts/resume-work.js.map +1 -0
  39. package/dist/prompts/sync-session.d.ts +2 -0
  40. package/dist/prompts/sync-session.js +33 -0
  41. package/dist/prompts/sync-session.js.map +1 -0
  42. package/dist/resources/project-decisions.d.ts +3 -0
  43. package/dist/resources/project-decisions.js +69 -0
  44. package/dist/resources/project-decisions.js.map +1 -0
  45. package/dist/resources/project-snapshot.d.ts +3 -0
  46. package/dist/resources/project-snapshot.js +49 -0
  47. package/dist/resources/project-snapshot.js.map +1 -0
  48. package/dist/resources/status.d.ts +3 -0
  49. package/dist/resources/status.js +25 -0
  50. package/dist/resources/status.js.map +1 -0
  51. package/dist/tools/amend-snapshot.d.ts +3 -0
  52. package/dist/tools/amend-snapshot.js +126 -0
  53. package/dist/tools/amend-snapshot.js.map +1 -0
  54. package/dist/tools/get-history.d.ts +3 -0
  55. package/dist/tools/get-history.js +58 -0
  56. package/dist/tools/get-history.js.map +1 -0
  57. package/dist/tools/list-projects.d.ts +3 -0
  58. package/dist/tools/list-projects.js +40 -0
  59. package/dist/tools/list-projects.js.map +1 -0
  60. package/dist/tools/log-decision.d.ts +3 -0
  61. package/dist/tools/log-decision.js +46 -0
  62. package/dist/tools/log-decision.js.map +1 -0
  63. package/dist/tools/resume.d.ts +3 -0
  64. package/dist/tools/resume.js +113 -0
  65. package/dist/tools/resume.js.map +1 -0
  66. package/dist/tools/search-snapshots.d.ts +3 -0
  67. package/dist/tools/search-snapshots.js +71 -0
  68. package/dist/tools/search-snapshots.js.map +1 -0
  69. package/dist/tools/sync.d.ts +3 -0
  70. package/dist/tools/sync.js +102 -0
  71. package/dist/tools/sync.js.map +1 -0
  72. package/package.json +48 -0
@@ -0,0 +1,103 @@
1
+ const SCHEMA_SQL = `
2
+ CREATE TABLE IF NOT EXISTS projects (
3
+ id TEXT PRIMARY KEY,
4
+ normalized_path TEXT NOT NULL UNIQUE,
5
+ display_name TEXT NOT NULL,
6
+ created_at TEXT NOT NULL,
7
+ last_synced_at TEXT,
8
+ snapshot_count INTEGER DEFAULT 0,
9
+ handoff_count INTEGER DEFAULT 0
10
+ );
11
+
12
+ CREATE TABLE IF NOT EXISTS snapshots (
13
+ id TEXT PRIMARY KEY,
14
+ project_id TEXT NOT NULL REFERENCES projects(id),
15
+ sequence_number INTEGER NOT NULL,
16
+ agent TEXT NOT NULL,
17
+ summary TEXT NOT NULL,
18
+ tasks_completed TEXT NOT NULL DEFAULT '[]',
19
+ tasks_remaining TEXT NOT NULL DEFAULT '[]',
20
+ decisions TEXT NOT NULL DEFAULT '[]',
21
+ files_modified TEXT NOT NULL DEFAULT '[]',
22
+ blockers TEXT NOT NULL DEFAULT '[]',
23
+ next_steps TEXT NOT NULL,
24
+ tags TEXT NOT NULL DEFAULT '[]',
25
+ created_at TEXT NOT NULL,
26
+ amended_at TEXT,
27
+ amended_by TEXT,
28
+ UNIQUE(project_id, sequence_number)
29
+ );
30
+
31
+ CREATE INDEX IF NOT EXISTS idx_snapshots_project_seq
32
+ ON snapshots(project_id, sequence_number DESC);
33
+ CREATE INDEX IF NOT EXISTS idx_snapshots_agent
34
+ ON snapshots(agent);
35
+ CREATE INDEX IF NOT EXISTS idx_snapshots_created
36
+ ON snapshots(created_at);
37
+
38
+ CREATE TABLE IF NOT EXISTS decisions (
39
+ id TEXT PRIMARY KEY,
40
+ project_id TEXT NOT NULL REFERENCES projects(id),
41
+ snapshot_id TEXT REFERENCES snapshots(id),
42
+ agent TEXT NOT NULL,
43
+ decision TEXT NOT NULL,
44
+ reasoning TEXT NOT NULL,
45
+ alternatives TEXT NOT NULL DEFAULT '[]',
46
+ category TEXT,
47
+ related_files TEXT NOT NULL DEFAULT '[]',
48
+ created_at TEXT NOT NULL
49
+ );
50
+
51
+ CREATE INDEX IF NOT EXISTS idx_decisions_project
52
+ ON decisions(project_id, created_at DESC);
53
+ CREATE INDEX IF NOT EXISTS idx_decisions_category
54
+ ON decisions(category);
55
+
56
+ CREATE TABLE IF NOT EXISTS handoffs (
57
+ id TEXT PRIMARY KEY,
58
+ project_id TEXT NOT NULL REFERENCES projects(id),
59
+ snapshot_id TEXT NOT NULL REFERENCES snapshots(id),
60
+ from_agent TEXT NOT NULL,
61
+ to_agent TEXT NOT NULL,
62
+ from_timestamp TEXT NOT NULL,
63
+ to_timestamp TEXT NOT NULL,
64
+ created_at TEXT NOT NULL
65
+ );
66
+
67
+ CREATE INDEX IF NOT EXISTS idx_handoffs_project
68
+ ON handoffs(project_id, created_at DESC);
69
+
70
+ CREATE VIRTUAL TABLE IF NOT EXISTS snapshots_fts USING fts5(
71
+ summary,
72
+ tasks_completed,
73
+ tasks_remaining,
74
+ decisions,
75
+ next_steps,
76
+ tags,
77
+ content=snapshots,
78
+ content_rowid=rowid
79
+ );
80
+
81
+ -- Triggers to keep FTS in sync
82
+ CREATE TRIGGER IF NOT EXISTS snapshots_ai AFTER INSERT ON snapshots BEGIN
83
+ INSERT INTO snapshots_fts(rowid, summary, tasks_completed, tasks_remaining, decisions, next_steps, tags)
84
+ VALUES (new.rowid, new.summary, new.tasks_completed, new.tasks_remaining, new.decisions, new.next_steps, new.tags);
85
+ END;
86
+
87
+ CREATE TRIGGER IF NOT EXISTS snapshots_au AFTER UPDATE ON snapshots BEGIN
88
+ INSERT INTO snapshots_fts(snapshots_fts, rowid, summary, tasks_completed, tasks_remaining, decisions, next_steps, tags)
89
+ VALUES ('delete', old.rowid, old.summary, old.tasks_completed, old.tasks_remaining, old.decisions, old.next_steps, old.tags);
90
+ INSERT INTO snapshots_fts(rowid, summary, tasks_completed, tasks_remaining, decisions, next_steps, tags)
91
+ VALUES (new.rowid, new.summary, new.tasks_completed, new.tasks_remaining, new.decisions, new.next_steps, new.tags);
92
+ END;
93
+
94
+ CREATE TRIGGER IF NOT EXISTS snapshots_ad AFTER DELETE ON snapshots BEGIN
95
+ INSERT INTO snapshots_fts(snapshots_fts, rowid, summary, tasks_completed, tasks_remaining, decisions, next_steps, tags)
96
+ VALUES ('delete', old.rowid, old.summary, old.tasks_completed, old.tasks_remaining, old.decisions, old.next_steps, old.tags);
97
+ END;
98
+ `;
99
+ export function initSchema(db) {
100
+ // PRAGMAs are set in connection.ts
101
+ db.exec(SCHEMA_SQL);
102
+ }
103
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiGlB,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,EAAqB;IAC9C,mCAAmC;IACnC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AACtB,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,56 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { getDatabase, closeDatabase } from './db/connection.js';
4
+ import { registerSyncTool } from './tools/sync.js';
5
+ import { registerResumeTool } from './tools/resume.js';
6
+ import { registerLogDecisionTool } from './tools/log-decision.js';
7
+ import { registerGetHistoryTool } from './tools/get-history.js';
8
+ import { registerListProjectsTool } from './tools/list-projects.js';
9
+ import { registerSearchSnapshotsTool } from './tools/search-snapshots.js';
10
+ import { registerAmendSnapshotTool } from './tools/amend-snapshot.js';
11
+ import { registerStatusResource } from './resources/status.js';
12
+ import { registerProjectSnapshotResource } from './resources/project-snapshot.js';
13
+ import { registerProjectDecisionsResource } from './resources/project-decisions.js';
14
+ import { registerSyncSessionPrompt } from './prompts/sync-session.js';
15
+ import { registerResumeWorkPrompt } from './prompts/resume-work.js';
16
+ import { registerAutoResumePrompt } from './prompts/auto-resume.js';
17
+ async function main() {
18
+ const db = getDatabase();
19
+ const server = new McpServer({
20
+ name: 'context-sync',
21
+ version: '1.0.0',
22
+ });
23
+ // Tools
24
+ registerSyncTool(server, db);
25
+ registerResumeTool(server, db);
26
+ registerLogDecisionTool(server, db);
27
+ registerGetHistoryTool(server, db);
28
+ registerListProjectsTool(server, db);
29
+ registerSearchSnapshotsTool(server, db);
30
+ registerAmendSnapshotTool(server, db);
31
+ // Resources
32
+ registerStatusResource(server, db);
33
+ registerProjectSnapshotResource(server, db);
34
+ registerProjectDecisionsResource(server, db);
35
+ // Prompts
36
+ registerSyncSessionPrompt(server);
37
+ registerResumeWorkPrompt(server);
38
+ registerAutoResumePrompt(server, db);
39
+ // Connect via stdio
40
+ const transport = new StdioServerTransport();
41
+ await server.connect(transport);
42
+ // Cleanup on exit
43
+ process.on('SIGINT', () => {
44
+ closeDatabase();
45
+ process.exit(0);
46
+ });
47
+ process.on('SIGTERM', () => {
48
+ closeDatabase();
49
+ process.exit(0);
50
+ });
51
+ }
52
+ main().catch((error) => {
53
+ console.error('Fatal error:', error);
54
+ process.exit(1);
55
+ });
56
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,+BAA+B,EAAE,MAAM,iCAAiC,CAAC;AAClF,OAAO,EAAE,gCAAgC,EAAE,MAAM,kCAAkC,CAAC;AACpF,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,KAAK,UAAU,IAAI;IACjB,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;IAEzB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,QAAQ;IACR,gBAAgB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC7B,kBAAkB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC/B,uBAAuB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACpC,sBAAsB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACnC,wBAAwB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACrC,2BAA2B,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACxC,yBAAyB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAEtC,YAAY;IACZ,sBAAsB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACnC,+BAA+B,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC5C,gCAAgC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAE7C,UAAU;IACV,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAClC,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACjC,wBAAwB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAErC,oBAAoB;IACpB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,kBAAkB;IAClB,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QACxB,aAAa,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;QACzB,aAAa,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Normalize a path so that the same project directory always produces
3
+ * the same ID regardless of OS, casing, or trailing separators.
4
+ */
5
+ export declare function normalizePath(raw: string): string;
6
+ /**
7
+ * Derive a deterministic 16-char hex project ID from an absolute path.
8
+ */
9
+ export declare function projectIdFromPath(raw: string): string;
10
+ /**
11
+ * Extract a human-friendly display name from a path (last segment).
12
+ */
13
+ export declare function displayNameFromPath(raw: string): string;
@@ -0,0 +1,27 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { basename } from 'node:path';
3
+ /**
4
+ * Normalize a path so that the same project directory always produces
5
+ * the same ID regardless of OS, casing, or trailing separators.
6
+ */
7
+ export function normalizePath(raw) {
8
+ return raw
9
+ .replace(/\\/g, '/')
10
+ .replace(/\/+$/, '')
11
+ .toLowerCase();
12
+ }
13
+ /**
14
+ * Derive a deterministic 16-char hex project ID from an absolute path.
15
+ */
16
+ export function projectIdFromPath(raw) {
17
+ const normalized = normalizePath(raw);
18
+ return createHash('sha256').update(normalized).digest('hex').substring(0, 16);
19
+ }
20
+ /**
21
+ * Extract a human-friendly display name from a path (last segment).
22
+ */
23
+ export function displayNameFromPath(raw) {
24
+ const normalized = normalizePath(raw);
25
+ return basename(normalized);
26
+ }
27
+ //# sourceMappingURL=project-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-id.js","sourceRoot":"","sources":["../../src/lib/project-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,OAAO,GAAG;SACP,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;SACnB,WAAW,EAAE,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,MAAM,UAAU,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IACtC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAChF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAW;IAC7C,MAAM,UAAU,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IACtC,OAAO,QAAQ,CAAC,UAAU,CAAC,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { SnapshotRow } from './types.js';
2
+ /**
3
+ * Render a snapshot row as readable Markdown for agent context windows.
4
+ */
5
+ export declare function renderSnapshotMarkdown(snapshot: SnapshotRow, displayName: string, historyStats?: {
6
+ totalSnapshots: number;
7
+ totalHandoffs: number;
8
+ agents: string[];
9
+ }): string;
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Render a snapshot row as readable Markdown for agent context windows.
3
+ */
4
+ export function renderSnapshotMarkdown(snapshot, displayName, historyStats) {
5
+ const tasksCompleted = JSON.parse(snapshot.tasks_completed);
6
+ const tasksRemaining = JSON.parse(snapshot.tasks_remaining);
7
+ const decisions = JSON.parse(snapshot.decisions);
8
+ const filesModified = JSON.parse(snapshot.files_modified);
9
+ const blockers = JSON.parse(snapshot.blockers);
10
+ const tags = JSON.parse(snapshot.tags);
11
+ const lines = [];
12
+ lines.push(`# Context Snapshot: ${displayName}`);
13
+ lines.push(`**Snapshot:** #${snapshot.sequence_number} | **Agent:** ${snapshot.agent} | **Time:** ${snapshot.created_at}`);
14
+ if (snapshot.amended_at) {
15
+ lines.push(`**Amended:** ${snapshot.amended_at} by ${snapshot.amended_by}`);
16
+ }
17
+ lines.push('');
18
+ lines.push('## Summary');
19
+ lines.push(snapshot.summary);
20
+ lines.push('');
21
+ if (tasksCompleted.length > 0) {
22
+ lines.push('## Completed Tasks');
23
+ for (const t of tasksCompleted)
24
+ lines.push(`- [x] ${t}`);
25
+ lines.push('');
26
+ }
27
+ if (tasksRemaining.length > 0) {
28
+ lines.push('## Remaining Tasks');
29
+ for (const t of tasksRemaining)
30
+ lines.push(`- [ ] ${t}`);
31
+ lines.push('');
32
+ }
33
+ if (decisions.length > 0) {
34
+ lines.push('## Decisions');
35
+ for (let i = 0; i < decisions.length; i++) {
36
+ const d = decisions[i];
37
+ let line = `${i + 1}. **${d.decision}** -- ${d.reasoning}`;
38
+ if (d.alternatives && d.alternatives.length > 0) {
39
+ line += ` Rejected: ${d.alternatives.join(', ')}.`;
40
+ }
41
+ lines.push(line);
42
+ }
43
+ lines.push('');
44
+ }
45
+ if (filesModified.length > 0) {
46
+ lines.push('## Files Modified');
47
+ for (const f of filesModified) {
48
+ lines.push(`- \`${f.path}\` (${f.action}) -- ${f.description}`);
49
+ }
50
+ lines.push('');
51
+ }
52
+ if (blockers.length > 0) {
53
+ lines.push('## Blockers');
54
+ for (const b of blockers)
55
+ lines.push(`- ${b}`);
56
+ lines.push('');
57
+ }
58
+ else {
59
+ lines.push('## Blockers');
60
+ lines.push('None currently');
61
+ lines.push('');
62
+ }
63
+ lines.push('## Next Steps');
64
+ lines.push(snapshot.next_steps);
65
+ lines.push('');
66
+ if (tags.length > 0) {
67
+ lines.push('## Tags');
68
+ lines.push(tags.map((t) => `\`${t}\``).join(', '));
69
+ lines.push('');
70
+ }
71
+ if (historyStats) {
72
+ lines.push('---');
73
+ lines.push(`*Handoff history: ${historyStats.totalSnapshots} snapshots, ${historyStats.totalHandoffs} handoffs across [${historyStats.agents.join(', ')}]*`);
74
+ }
75
+ return lines.join('\n');
76
+ }
77
+ //# sourceMappingURL=snapshot-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot-renderer.js","sourceRoot":"","sources":["../../src/lib/snapshot-renderer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,290 @@
1
+ import { z } from 'zod';
2
+ export declare const AgentEnum: z.ZodEnum<["claude-code", "codex", "gemini-cli", "cursor", "cline", "amp", "other"]>;
3
+ export type Agent = z.infer<typeof AgentEnum>;
4
+ export declare const DecisionSchema: z.ZodObject<{
5
+ decision: z.ZodString;
6
+ reasoning: z.ZodString;
7
+ alternatives: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
8
+ }, "strip", z.ZodTypeAny, {
9
+ decision: string;
10
+ reasoning: string;
11
+ alternatives?: string[] | undefined;
12
+ }, {
13
+ decision: string;
14
+ reasoning: string;
15
+ alternatives?: string[] | undefined;
16
+ }>;
17
+ export type Decision = z.infer<typeof DecisionSchema>;
18
+ export declare const FileModSchema: z.ZodObject<{
19
+ path: z.ZodString;
20
+ action: z.ZodEnum<["created", "modified", "deleted", "renamed"]>;
21
+ description: z.ZodString;
22
+ }, "strip", z.ZodTypeAny, {
23
+ path: string;
24
+ action: "created" | "modified" | "deleted" | "renamed";
25
+ description: string;
26
+ }, {
27
+ path: string;
28
+ action: "created" | "modified" | "deleted" | "renamed";
29
+ description: string;
30
+ }>;
31
+ export type FileMod = z.infer<typeof FileModSchema>;
32
+ export declare const DecisionCategoryEnum: z.ZodEnum<["architecture", "dependency", "api-design", "data-model", "tooling", "testing", "deployment", "other"]>;
33
+ export declare const SyncInputSchema: z.ZodObject<{
34
+ projectDir: z.ZodString;
35
+ agent: z.ZodEnum<["claude-code", "codex", "gemini-cli", "cursor", "cline", "amp", "other"]>;
36
+ summary: z.ZodString;
37
+ tasksCompleted: z.ZodArray<z.ZodString, "many">;
38
+ tasksRemaining: z.ZodArray<z.ZodString, "many">;
39
+ decisions: z.ZodOptional<z.ZodArray<z.ZodObject<{
40
+ decision: z.ZodString;
41
+ reasoning: z.ZodString;
42
+ alternatives: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
43
+ }, "strip", z.ZodTypeAny, {
44
+ decision: string;
45
+ reasoning: string;
46
+ alternatives?: string[] | undefined;
47
+ }, {
48
+ decision: string;
49
+ reasoning: string;
50
+ alternatives?: string[] | undefined;
51
+ }>, "many">>;
52
+ filesModified: z.ZodOptional<z.ZodArray<z.ZodObject<{
53
+ path: z.ZodString;
54
+ action: z.ZodEnum<["created", "modified", "deleted", "renamed"]>;
55
+ description: z.ZodString;
56
+ }, "strip", z.ZodTypeAny, {
57
+ path: string;
58
+ action: "created" | "modified" | "deleted" | "renamed";
59
+ description: string;
60
+ }, {
61
+ path: string;
62
+ action: "created" | "modified" | "deleted" | "renamed";
63
+ description: string;
64
+ }>, "many">>;
65
+ blockers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
66
+ nextSteps: z.ZodString;
67
+ tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
68
+ }, "strip", z.ZodTypeAny, {
69
+ projectDir: string;
70
+ agent: "claude-code" | "codex" | "gemini-cli" | "cursor" | "cline" | "amp" | "other";
71
+ summary: string;
72
+ tasksCompleted: string[];
73
+ tasksRemaining: string[];
74
+ nextSteps: string;
75
+ decisions?: {
76
+ decision: string;
77
+ reasoning: string;
78
+ alternatives?: string[] | undefined;
79
+ }[] | undefined;
80
+ filesModified?: {
81
+ path: string;
82
+ action: "created" | "modified" | "deleted" | "renamed";
83
+ description: string;
84
+ }[] | undefined;
85
+ blockers?: string[] | undefined;
86
+ tags?: string[] | undefined;
87
+ }, {
88
+ projectDir: string;
89
+ agent: "claude-code" | "codex" | "gemini-cli" | "cursor" | "cline" | "amp" | "other";
90
+ summary: string;
91
+ tasksCompleted: string[];
92
+ tasksRemaining: string[];
93
+ nextSteps: string;
94
+ decisions?: {
95
+ decision: string;
96
+ reasoning: string;
97
+ alternatives?: string[] | undefined;
98
+ }[] | undefined;
99
+ filesModified?: {
100
+ path: string;
101
+ action: "created" | "modified" | "deleted" | "renamed";
102
+ description: string;
103
+ }[] | undefined;
104
+ blockers?: string[] | undefined;
105
+ tags?: string[] | undefined;
106
+ }>;
107
+ export type SyncInput = z.infer<typeof SyncInputSchema>;
108
+ export declare const ResumeInputSchema: z.ZodObject<{
109
+ projectDir: z.ZodString;
110
+ agent: z.ZodEnum<["claude-code", "codex", "gemini-cli", "cursor", "cline", "amp", "other"]>;
111
+ snapshotId: z.ZodOptional<z.ZodString>;
112
+ }, "strip", z.ZodTypeAny, {
113
+ projectDir: string;
114
+ agent: "claude-code" | "codex" | "gemini-cli" | "cursor" | "cline" | "amp" | "other";
115
+ snapshotId?: string | undefined;
116
+ }, {
117
+ projectDir: string;
118
+ agent: "claude-code" | "codex" | "gemini-cli" | "cursor" | "cline" | "amp" | "other";
119
+ snapshotId?: string | undefined;
120
+ }>;
121
+ export type ResumeInput = z.infer<typeof ResumeInputSchema>;
122
+ export declare const LogDecisionInputSchema: z.ZodObject<{
123
+ projectDir: z.ZodString;
124
+ agent: z.ZodEnum<["claude-code", "codex", "gemini-cli", "cursor", "cline", "amp", "other"]>;
125
+ decision: z.ZodString;
126
+ reasoning: z.ZodString;
127
+ alternatives: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
128
+ category: z.ZodOptional<z.ZodEnum<["architecture", "dependency", "api-design", "data-model", "tooling", "testing", "deployment", "other"]>>;
129
+ relatedFiles: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
130
+ }, "strip", z.ZodTypeAny, {
131
+ decision: string;
132
+ reasoning: string;
133
+ projectDir: string;
134
+ agent: "claude-code" | "codex" | "gemini-cli" | "cursor" | "cline" | "amp" | "other";
135
+ alternatives?: string[] | undefined;
136
+ category?: "other" | "architecture" | "dependency" | "api-design" | "data-model" | "tooling" | "testing" | "deployment" | undefined;
137
+ relatedFiles?: string[] | undefined;
138
+ }, {
139
+ decision: string;
140
+ reasoning: string;
141
+ projectDir: string;
142
+ agent: "claude-code" | "codex" | "gemini-cli" | "cursor" | "cline" | "amp" | "other";
143
+ alternatives?: string[] | undefined;
144
+ category?: "other" | "architecture" | "dependency" | "api-design" | "data-model" | "tooling" | "testing" | "deployment" | undefined;
145
+ relatedFiles?: string[] | undefined;
146
+ }>;
147
+ export declare const GetHistoryInputSchema: z.ZodObject<{
148
+ projectDir: z.ZodString;
149
+ limit: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
150
+ agentFilter: z.ZodDefault<z.ZodOptional<z.ZodUnion<[z.ZodEnum<["claude-code", "codex", "gemini-cli", "cursor", "cline", "amp", "other"]>, z.ZodLiteral<"all">]>>>;
151
+ includeDecisions: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
152
+ }, "strip", z.ZodTypeAny, {
153
+ projectDir: string;
154
+ limit: number;
155
+ agentFilter: "claude-code" | "codex" | "gemini-cli" | "cursor" | "cline" | "amp" | "other" | "all";
156
+ includeDecisions: boolean;
157
+ }, {
158
+ projectDir: string;
159
+ limit?: number | undefined;
160
+ agentFilter?: "claude-code" | "codex" | "gemini-cli" | "cursor" | "cline" | "amp" | "other" | "all" | undefined;
161
+ includeDecisions?: boolean | undefined;
162
+ }>;
163
+ export declare const ListProjectsInputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
164
+ export declare const SearchSnapshotsInputSchema: z.ZodObject<{
165
+ projectDir: z.ZodOptional<z.ZodString>;
166
+ query: z.ZodOptional<z.ZodString>;
167
+ tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
168
+ agent: z.ZodOptional<z.ZodEnum<["claude-code", "codex", "gemini-cli", "cursor", "cline", "amp", "other"]>>;
169
+ since: z.ZodOptional<z.ZodString>;
170
+ until: z.ZodOptional<z.ZodString>;
171
+ limit: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
172
+ }, "strip", z.ZodTypeAny, {
173
+ limit: number;
174
+ projectDir?: string | undefined;
175
+ agent?: "claude-code" | "codex" | "gemini-cli" | "cursor" | "cline" | "amp" | "other" | undefined;
176
+ tags?: string[] | undefined;
177
+ query?: string | undefined;
178
+ since?: string | undefined;
179
+ until?: string | undefined;
180
+ }, {
181
+ projectDir?: string | undefined;
182
+ agent?: "claude-code" | "codex" | "gemini-cli" | "cursor" | "cline" | "amp" | "other" | undefined;
183
+ tags?: string[] | undefined;
184
+ limit?: number | undefined;
185
+ query?: string | undefined;
186
+ since?: string | undefined;
187
+ until?: string | undefined;
188
+ }>;
189
+ export declare const AmendSnapshotInputSchema: z.ZodObject<{
190
+ projectDir: z.ZodString;
191
+ agent: z.ZodEnum<["claude-code", "codex", "gemini-cli", "cursor", "cline", "amp", "other"]>;
192
+ addTasksCompleted: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
193
+ addTasksRemaining: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
194
+ removeTasksRemaining: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
195
+ addDecisions: z.ZodOptional<z.ZodArray<z.ZodObject<{
196
+ decision: z.ZodString;
197
+ reasoning: z.ZodString;
198
+ alternatives: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
199
+ }, "strip", z.ZodTypeAny, {
200
+ decision: string;
201
+ reasoning: string;
202
+ alternatives?: string[] | undefined;
203
+ }, {
204
+ decision: string;
205
+ reasoning: string;
206
+ alternatives?: string[] | undefined;
207
+ }>, "many">>;
208
+ updateNextSteps: z.ZodOptional<z.ZodString>;
209
+ addBlockers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
210
+ removeBlockers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
211
+ addTags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
212
+ }, "strip", z.ZodTypeAny, {
213
+ projectDir: string;
214
+ agent: "claude-code" | "codex" | "gemini-cli" | "cursor" | "cline" | "amp" | "other";
215
+ addTasksCompleted?: string[] | undefined;
216
+ addTasksRemaining?: string[] | undefined;
217
+ removeTasksRemaining?: string[] | undefined;
218
+ addDecisions?: {
219
+ decision: string;
220
+ reasoning: string;
221
+ alternatives?: string[] | undefined;
222
+ }[] | undefined;
223
+ updateNextSteps?: string | undefined;
224
+ addBlockers?: string[] | undefined;
225
+ removeBlockers?: string[] | undefined;
226
+ addTags?: string[] | undefined;
227
+ }, {
228
+ projectDir: string;
229
+ agent: "claude-code" | "codex" | "gemini-cli" | "cursor" | "cline" | "amp" | "other";
230
+ addTasksCompleted?: string[] | undefined;
231
+ addTasksRemaining?: string[] | undefined;
232
+ removeTasksRemaining?: string[] | undefined;
233
+ addDecisions?: {
234
+ decision: string;
235
+ reasoning: string;
236
+ alternatives?: string[] | undefined;
237
+ }[] | undefined;
238
+ updateNextSteps?: string | undefined;
239
+ addBlockers?: string[] | undefined;
240
+ removeBlockers?: string[] | undefined;
241
+ addTags?: string[] | undefined;
242
+ }>;
243
+ export interface ProjectRow {
244
+ id: string;
245
+ normalized_path: string;
246
+ display_name: string;
247
+ created_at: string;
248
+ last_synced_at: string | null;
249
+ snapshot_count: number;
250
+ handoff_count: number;
251
+ }
252
+ export interface SnapshotRow {
253
+ id: string;
254
+ project_id: string;
255
+ sequence_number: number;
256
+ agent: string;
257
+ summary: string;
258
+ tasks_completed: string;
259
+ tasks_remaining: string;
260
+ decisions: string;
261
+ files_modified: string;
262
+ blockers: string;
263
+ next_steps: string;
264
+ tags: string;
265
+ created_at: string;
266
+ amended_at: string | null;
267
+ amended_by: string | null;
268
+ }
269
+ export interface DecisionRow {
270
+ id: string;
271
+ project_id: string;
272
+ snapshot_id: string | null;
273
+ agent: string;
274
+ decision: string;
275
+ reasoning: string;
276
+ alternatives: string;
277
+ category: string | null;
278
+ related_files: string;
279
+ created_at: string;
280
+ }
281
+ export interface HandoffRow {
282
+ id: string;
283
+ project_id: string;
284
+ snapshot_id: string;
285
+ from_agent: string;
286
+ to_agent: string;
287
+ from_timestamp: string;
288
+ to_timestamp: string;
289
+ created_at: string;
290
+ }