@tyroneross/bookmark 0.1.0 → 0.3.2

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 (109) hide show
  1. package/.claude-plugin/marketplace.json +29 -12
  2. package/.claude-plugin/plugin.json +12 -8
  3. package/.codex-plugin/plugin.json +31 -0
  4. package/.mcp.json +8 -0
  5. package/CLAUDE.md +83 -49
  6. package/LICENSE +202 -21
  7. package/README.md +150 -57
  8. package/agents/snapshot-analyst.md +1 -1
  9. package/commands/bookmark.md +29 -0
  10. package/commands/feedback.md +37 -0
  11. package/commands/restore.md +14 -4
  12. package/commands/snapshot.md +19 -7
  13. package/commands/status.md +1 -1
  14. package/dist/cli/index.js +627 -87
  15. package/dist/cli/index.js.map +1 -1
  16. package/dist/cli/snapshot-resolution.d.ts +15 -0
  17. package/dist/cli/snapshot-resolution.d.ts.map +1 -0
  18. package/dist/cli/snapshot-resolution.js +21 -0
  19. package/dist/cli/snapshot-resolution.js.map +1 -0
  20. package/dist/config.d.ts +19 -0
  21. package/dist/config.d.ts.map +1 -1
  22. package/dist/config.js +149 -23
  23. package/dist/config.js.map +1 -1
  24. package/dist/context/freshness.d.ts +3 -0
  25. package/dist/context/freshness.d.ts.map +1 -0
  26. package/dist/context/freshness.js +29 -0
  27. package/dist/context/freshness.js.map +1 -0
  28. package/dist/context/handoff-prompt.d.ts +12 -0
  29. package/dist/context/handoff-prompt.d.ts.map +1 -0
  30. package/dist/context/handoff-prompt.js +29 -0
  31. package/dist/context/handoff-prompt.js.map +1 -0
  32. package/dist/index.d.ts +7 -4
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +5 -3
  35. package/dist/index.js.map +1 -1
  36. package/dist/mcp/server.d.ts +9 -0
  37. package/dist/mcp/server.d.ts.map +1 -0
  38. package/dist/mcp/server.js +85 -0
  39. package/dist/mcp/server.js.map +1 -0
  40. package/dist/mcp/tools.d.ts +97 -0
  41. package/dist/mcp/tools.d.ts.map +1 -0
  42. package/dist/mcp/tools.js +304 -0
  43. package/dist/mcp/tools.js.map +1 -0
  44. package/dist/registry.d.ts +40 -0
  45. package/dist/registry.d.ts.map +1 -0
  46. package/dist/registry.js +134 -0
  47. package/dist/registry.js.map +1 -0
  48. package/dist/restore/index.d.ts +13 -1
  49. package/dist/restore/index.d.ts.map +1 -1
  50. package/dist/restore/index.js +163 -43
  51. package/dist/restore/index.js.map +1 -1
  52. package/dist/setup/auto-setup.d.ts +8 -2
  53. package/dist/setup/auto-setup.d.ts.map +1 -1
  54. package/dist/setup/auto-setup.js +287 -67
  55. package/dist/setup/auto-setup.js.map +1 -1
  56. package/dist/setup/configure-hooks.d.ts +14 -3
  57. package/dist/setup/configure-hooks.d.ts.map +1 -1
  58. package/dist/setup/configure-hooks.js +156 -24
  59. package/dist/setup/configure-hooks.js.map +1 -1
  60. package/dist/snapshot/capture.d.ts +13 -9
  61. package/dist/snapshot/capture.d.ts.map +1 -1
  62. package/dist/snapshot/capture.js +42 -105
  63. package/dist/snapshot/capture.js.map +1 -1
  64. package/dist/snapshot/compress.d.ts +3 -3
  65. package/dist/snapshot/compress.d.ts.map +1 -1
  66. package/dist/snapshot/compress.js +35 -67
  67. package/dist/snapshot/compress.js.map +1 -1
  68. package/dist/snapshot/storage.d.ts +7 -0
  69. package/dist/snapshot/storage.d.ts.map +1 -1
  70. package/dist/snapshot/storage.js +31 -6
  71. package/dist/snapshot/storage.js.map +1 -1
  72. package/dist/threshold/state.d.ts +5 -0
  73. package/dist/threshold/state.d.ts.map +1 -1
  74. package/dist/threshold/state.js +28 -2
  75. package/dist/threshold/state.js.map +1 -1
  76. package/dist/threshold/token-usage.d.ts +29 -0
  77. package/dist/threshold/token-usage.d.ts.map +1 -0
  78. package/dist/threshold/token-usage.js +128 -0
  79. package/dist/threshold/token-usage.js.map +1 -0
  80. package/dist/trails/identity.d.ts +76 -0
  81. package/dist/trails/identity.d.ts.map +1 -0
  82. package/dist/trails/identity.js +117 -0
  83. package/dist/trails/identity.js.map +1 -0
  84. package/dist/trails/reader.d.ts +7 -0
  85. package/dist/trails/reader.d.ts.map +1 -0
  86. package/dist/trails/reader.js +22 -0
  87. package/dist/trails/reader.js.map +1 -0
  88. package/dist/trails/writer.d.ts +9 -0
  89. package/dist/trails/writer.d.ts.map +1 -0
  90. package/dist/trails/writer.js +110 -0
  91. package/dist/trails/writer.js.map +1 -0
  92. package/dist/transcript/extractor.d.ts +17 -4
  93. package/dist/transcript/extractor.d.ts.map +1 -1
  94. package/dist/transcript/extractor.js +141 -174
  95. package/dist/transcript/extractor.js.map +1 -1
  96. package/dist/transcript/parser.d.ts.map +1 -1
  97. package/dist/transcript/parser.js +69 -7
  98. package/dist/transcript/parser.js.map +1 -1
  99. package/dist/types.d.ts +37 -38
  100. package/dist/types.d.ts.map +1 -1
  101. package/hooks/hooks.json +12 -14
  102. package/package.json +13 -10
  103. package/scripts/install-plugin.sh +48 -0
  104. package/skills/context-continuity/SKILL.md +43 -24
  105. package/commands/activate.md +0 -20
  106. package/dist/transcript/estimator.d.ts +0 -20
  107. package/dist/transcript/estimator.d.ts.map +0 -1
  108. package/dist/transcript/estimator.js +0 -95
  109. package/dist/transcript/estimator.js.map +0 -1
@@ -1,45 +1,76 @@
1
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
1
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, realpathSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  const BOOKMARK_HOOKS = {
4
- PreCompact: {
4
+ Stop: {
5
5
  matcher: '',
6
6
  hooks: [{
7
7
  type: 'command',
8
- command: 'npx @tyroneross/bookmark snapshot --trigger pre_compact 2>/dev/null || true',
9
- timeout: 30000,
10
- async: true,
8
+ command: `npx @tyroneross/bookmark stop 2>/dev/null || echo '{"decision": "approve"}'`,
9
+ timeout: 10000,
11
10
  }],
12
11
  },
13
- SessionStart: {
12
+ PreCompact: {
14
13
  matcher: '',
15
14
  hooks: [{
16
15
  type: 'command',
17
- command: 'npx @tyroneross/bookmark restore 2>/dev/null || echo \'{}\'',
18
- timeout: 5000,
16
+ command: `npx @tyroneross/bookmark precompact 2>/dev/null || echo '{}'`,
17
+ timeout: 10000,
19
18
  }],
20
19
  },
21
- UserPromptSubmit: {
20
+ SessionStart: {
22
21
  matcher: '',
23
22
  hooks: [{
24
23
  type: 'command',
25
- command: 'npx @tyroneross/bookmark check 2>/dev/null || true',
26
- timeout: 3000,
27
- async: true,
24
+ command: `npx @tyroneross/bookmark restore 2>/dev/null || echo '{}'`,
25
+ timeout: 5000,
28
26
  }],
29
27
  },
30
- Stop: {
28
+ UserPromptSubmit: {
31
29
  matcher: '',
32
30
  hooks: [{
33
31
  type: 'command',
34
- command: 'npx @tyroneross/bookmark snapshot --trigger session_end 2>/dev/null || true',
35
- timeout: 15000,
32
+ command: `npx @tyroneross/bookmark context-check 2>/dev/null || echo '{}'`,
33
+ timeout: 10000,
36
34
  }],
37
35
  },
38
36
  };
39
37
  const BOOKMARK_MARKER = '@tyroneross/bookmark';
38
+ const BOOKMARK_PROMPT_MARKER = '.bookmark/bookmark.context.md';
39
+ /**
40
+ * Resolve the plugin path for the settings.json plugins array.
41
+ * Checks for local npm install first, then global symlink.
42
+ */
43
+ function resolvePluginPath(cwd) {
44
+ // Check local npm install
45
+ const localPlugin = join(cwd, 'node_modules', '@tyroneross', 'bookmark', '.claude-plugin');
46
+ if (existsSync(localPlugin)) {
47
+ return 'node_modules/@tyroneross/bookmark/.claude-plugin';
48
+ }
49
+ // Check global symlink
50
+ const home = process.env.HOME || process.env.USERPROFILE || '';
51
+ if (home) {
52
+ const globalLink = join(home, '.claude', 'plugins', 'bookmark');
53
+ if (existsSync(globalLink)) {
54
+ try {
55
+ const resolved = realpathSync(globalLink);
56
+ return join(resolved, '.claude-plugin');
57
+ }
58
+ catch { /* fall through */ }
59
+ }
60
+ }
61
+ return null;
62
+ }
63
+ /**
64
+ * Check if a hook group contains a bookmark hook (command or prompt type).
65
+ */
66
+ function isBookmarkHook(hookGroup) {
67
+ return hookGroup.hooks.some(hh => hh.command?.includes(BOOKMARK_MARKER) ||
68
+ hh.prompt?.includes(BOOKMARK_PROMPT_MARKER));
69
+ }
40
70
  /**
41
- * Configure hooks in the project's .claude/settings.json.
42
- * Adds bookmark hooks without duplicating or overwriting existing hooks.
71
+ * Configure hooks and plugin registration in the project's .claude/settings.json.
72
+ * All hooks are command-type. One synchronous `context-check` hook handles
73
+ * interval capture and token alerts through a single state writer.
43
74
  */
44
75
  export function configureHooks(cwd) {
45
76
  const settingsDir = join(cwd, '.claude');
@@ -56,6 +87,18 @@ export function configureHooks(cwd) {
56
87
  settings = {};
57
88
  }
58
89
  }
90
+ // ─── Plugin registration in settings.plugins ───
91
+ if (!settings.plugins) {
92
+ settings.plugins = [];
93
+ }
94
+ const pluginPath = resolvePluginPath(cwd);
95
+ if (pluginPath) {
96
+ const alreadyRegistered = settings.plugins.some(p => p.includes('bookmark'));
97
+ if (!alreadyRegistered) {
98
+ settings.plugins.push(pluginPath);
99
+ }
100
+ }
101
+ // ─── Hook configuration ───
59
102
  if (!settings.hooks) {
60
103
  settings.hooks = {};
61
104
  }
@@ -63,19 +106,77 @@ export function configureHooks(cwd) {
63
106
  if (!settings.hooks[event]) {
64
107
  settings.hooks[event] = [];
65
108
  }
66
- // Check if bookmark hook already exists
67
- const exists = settings.hooks[event].some(h => h.hooks.some(hh => hh.command?.includes(BOOKMARK_MARKER)));
68
- if (!exists) {
109
+ const existingIdx = settings.hooks[event].findIndex(isBookmarkHook);
110
+ if (existingIdx === -1) {
111
+ // No existing bookmark hook — add the new one
69
112
  settings.hooks[event].push(hookConfig);
70
113
  }
114
+ else {
115
+ // Replace existing bookmark hook (upgrades old prompt hooks to command hooks)
116
+ settings.hooks[event][existingIdx] = hookConfig;
117
+ }
71
118
  }
72
119
  writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf-8');
73
120
  }
74
121
  /**
75
- * Remove bookmark hooks from settings.json.
122
+ * Configure hooks in the GLOBAL ~/.claude/settings.json.
123
+ * This makes bookmark fire in every project without per-project setup.
124
+ * Merges with existing hooks — never overwrites user's other hooks.
76
125
  */
77
- export function removeHooks(cwd) {
78
- const settingsPath = join(cwd, '.claude', 'settings.json');
126
+ export function configureGlobalHooks() {
127
+ const home = process.env.HOME || process.env.USERPROFILE || '';
128
+ if (!home)
129
+ return;
130
+ const settingsDir = join(home, '.claude');
131
+ const settingsPath = join(settingsDir, 'settings.json');
132
+ if (!existsSync(settingsDir)) {
133
+ mkdirSync(settingsDir, { recursive: true });
134
+ }
135
+ let settings = {};
136
+ if (existsSync(settingsPath)) {
137
+ try {
138
+ settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
139
+ }
140
+ catch {
141
+ settings = {};
142
+ }
143
+ }
144
+ if (!settings.hooks) {
145
+ settings.hooks = {};
146
+ }
147
+ let changed = false;
148
+ for (const [event, hookConfig] of Object.entries(BOOKMARK_HOOKS)) {
149
+ if (!settings.hooks[event]) {
150
+ settings.hooks[event] = [];
151
+ }
152
+ const existingIdx = settings.hooks[event].findIndex(isBookmarkHook);
153
+ if (existingIdx === -1) {
154
+ // No existing bookmark hook — append (don't replace user's other hooks)
155
+ settings.hooks[event].push(hookConfig);
156
+ changed = true;
157
+ }
158
+ else {
159
+ // Update existing bookmark hook in place
160
+ const existing = JSON.stringify(settings.hooks[event][existingIdx]);
161
+ const updated = JSON.stringify(hookConfig);
162
+ if (existing !== updated) {
163
+ settings.hooks[event][existingIdx] = hookConfig;
164
+ changed = true;
165
+ }
166
+ }
167
+ }
168
+ if (changed) {
169
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf-8');
170
+ }
171
+ }
172
+ /**
173
+ * Remove bookmark hooks from the GLOBAL ~/.claude/settings.json.
174
+ */
175
+ export function removeGlobalHooks() {
176
+ const home = process.env.HOME || process.env.USERPROFILE || '';
177
+ if (!home)
178
+ return;
179
+ const settingsPath = join(home, '.claude', 'settings.json');
79
180
  if (!existsSync(settingsPath))
80
181
  return;
81
182
  try {
@@ -83,7 +184,7 @@ export function removeHooks(cwd) {
83
184
  if (!settings.hooks)
84
185
  return;
85
186
  for (const event of Object.keys(settings.hooks)) {
86
- settings.hooks[event] = settings.hooks[event].filter(h => !h.hooks.some(hh => hh.command?.includes(BOOKMARK_MARKER)));
187
+ settings.hooks[event] = settings.hooks[event].filter(h => !isBookmarkHook(h));
87
188
  if (settings.hooks[event].length === 0) {
88
189
  delete settings.hooks[event];
89
190
  }
@@ -94,4 +195,35 @@ export function removeHooks(cwd) {
94
195
  // Silent
95
196
  }
96
197
  }
198
+ /**
199
+ * Remove bookmark hooks and plugin entry from a project's settings.json.
200
+ */
201
+ export function removeHooks(cwd) {
202
+ const settingsPath = join(cwd, '.claude', 'settings.json');
203
+ if (!existsSync(settingsPath))
204
+ return;
205
+ try {
206
+ const settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
207
+ // Remove from plugins array
208
+ if (settings.plugins) {
209
+ settings.plugins = settings.plugins.filter(p => !p.includes('bookmark'));
210
+ if (settings.plugins.length === 0) {
211
+ delete settings.plugins;
212
+ }
213
+ }
214
+ // Remove hooks (both command and prompt types)
215
+ if (settings.hooks) {
216
+ for (const event of Object.keys(settings.hooks)) {
217
+ settings.hooks[event] = settings.hooks[event].filter(h => !isBookmarkHook(h));
218
+ if (settings.hooks[event].length === 0) {
219
+ delete settings.hooks[event];
220
+ }
221
+ }
222
+ }
223
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf-8');
224
+ }
225
+ catch {
226
+ // Silent
227
+ }
228
+ }
97
229
  //# sourceMappingURL=configure-hooks.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"configure-hooks.js","sourceRoot":"","sources":["../../src/setup/configure-hooks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"configure-hooks.js","sourceRoot":"","sources":["../../src/setup/configure-hooks.ts"],"names":[],"mappings":"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"}
@@ -1,21 +1,25 @@
1
1
  import type { Snapshot, SnapshotTrigger } from '../types.js';
2
+ import type { ContextUsage } from '../threshold/token-usage.js';
2
3
  export interface CaptureOptions {
3
4
  trigger: SnapshotTrigger;
4
5
  transcriptPath: string;
5
6
  cwd: string;
6
7
  sessionId?: string;
7
- smart?: boolean;
8
+ contextUsage?: ContextUsage;
8
9
  }
9
10
  /**
10
- * Full snapshot capture pipeline:
11
+ * Snapshot capture pipeline (v0.3 — file tracking only):
11
12
  * 1. Parse transcript
12
- * 2. Estimate token usage
13
- * 3. Extract decisions/status/files/errors
14
- * 4. Optionally enhance with LLM (--smart)
15
- * 5. Build snapshot object
16
- * 6. Store snapshot JSON
17
- * 7. Generate and write LATEST.md
18
- * 8. Update state
13
+ * 2. Extract file changes + tool usage (the parts that actually work)
14
+ * 3. Build snapshot object
15
+ * 4. Store snapshot JSON + write LATEST.md + trail files
16
+ * 5. Update state
17
+ *
18
+ * Intent, decisions, and progress are NOT extracted from transcripts —
19
+ * regex can't do semantic extraction reliably. Instead, Claude writes
20
+ * bookmark.context.md directly after the token hook requests a handoff or the
21
+ * Stop hook blocks for one.
22
+ * This pipeline provides supplementary file tracking data.
19
23
  */
20
24
  export declare function captureSnapshot(options: CaptureOptions): Promise<Snapshot>;
21
25
  //# sourceMappingURL=capture.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/snapshot/capture.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,eAAe,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC,CAyDhF"}
1
+ {"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/snapshot/capture.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,eAAe,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC,CAwDhF"}
@@ -1,20 +1,25 @@
1
+ import { join } from 'node:path';
1
2
  import { parseTranscript } from '../transcript/parser.js';
2
- import { estimateFromTranscript } from '../transcript/estimator.js';
3
- import { extractFromEntries } from '../transcript/extractor.js';
4
- import { storeSnapshot, writeLatestMd, loadLatestSnapshot } from './storage.js';
3
+ import { extractFilesAndTools } from '../transcript/extractor.js';
4
+ import { storeSnapshot, writeLatestMd, loadLatestSnapshot, getSnapshotsDir, generateSnapshotId } from './storage.js';
5
5
  import { compressToMarkdown } from './compress.js';
6
- import { loadState, saveState, updateSnapshotTime } from '../threshold/state.js';
6
+ import { writeTrails } from '../trails/writer.js';
7
+ import { loadState, saveState, updateSnapshotTime, incrementSnapshotCount } from '../threshold/state.js';
7
8
  import { loadConfig, getStoragePath } from '../config.js';
9
+ import { appendToRegistry } from '../registry.js';
8
10
  /**
9
- * Full snapshot capture pipeline:
11
+ * Snapshot capture pipeline (v0.3 — file tracking only):
10
12
  * 1. Parse transcript
11
- * 2. Estimate token usage
12
- * 3. Extract decisions/status/files/errors
13
- * 4. Optionally enhance with LLM (--smart)
14
- * 5. Build snapshot object
15
- * 6. Store snapshot JSON
16
- * 7. Generate and write LATEST.md
17
- * 8. Update state
13
+ * 2. Extract file changes + tool usage (the parts that actually work)
14
+ * 3. Build snapshot object
15
+ * 4. Store snapshot JSON + write LATEST.md + trail files
16
+ * 5. Update state
17
+ *
18
+ * Intent, decisions, and progress are NOT extracted from transcripts —
19
+ * regex can't do semantic extraction reliably. Instead, Claude writes
20
+ * bookmark.context.md directly after the token hook requests a handoff or the
21
+ * Stop hook blocks for one.
22
+ * This pipeline provides supplementary file tracking data.
18
23
  */
19
24
  export async function captureSnapshot(options) {
20
25
  const config = loadConfig(options.cwd);
@@ -22,18 +27,10 @@ export async function captureSnapshot(options) {
22
27
  const state = loadState(storagePath);
23
28
  // 1. Parse transcript
24
29
  const { entries } = parseTranscript(options.transcriptPath);
25
- // 2. Estimate token usage
26
- const estimate = estimateFromTranscript(options.transcriptPath, {
27
- contextLimit: config.contextLimitTokens,
28
- charsPerToken: config.charsPerToken,
29
- });
30
- // 3. Extract structured content
31
- let extraction = extractFromEntries(entries);
32
- // 4. Optional LLM enhancement
33
- if (options.smart ?? config.smartDefault) {
34
- extraction = await enhanceWithLLM(extraction, entries);
35
- }
36
- // 5. Build snapshot
30
+ // 2. Extract file changes + tool usage only (working parts of extractor)
31
+ // Intent, decisions, and progress are NOT extracted — Claude writes the handoff.
32
+ const extraction = extractFilesAndTools(entries, { projectPath: options.cwd });
33
+ // 3. Build snapshot
37
34
  const snapshotId = generateSnapshotId();
38
35
  const priorSnapshot = loadLatestSnapshot(storagePath);
39
36
  const snapshot = {
@@ -43,92 +40,32 @@ export async function captureSnapshot(options) {
43
40
  project_path: options.cwd,
44
41
  trigger: options.trigger,
45
42
  compaction_cycle: state.compaction_count,
46
- context_remaining_pct: estimate.remaining_pct,
47
- token_estimate: estimate.total_tokens,
48
- current_status: extraction.current_status,
49
- decisions: extraction.decisions,
50
- open_items: extraction.open_items,
51
- unknowns: extraction.unknowns,
52
43
  files_changed: extraction.files_changed,
53
- errors_encountered: extraction.errors_encountered,
54
44
  tools_summary: extraction.tools_summary,
55
45
  prior_snapshot_id: priorSnapshot?.snapshot_id,
46
+ context_remaining_pct: options.contextUsage?.remainingFraction,
47
+ context_used_pct: options.contextUsage?.usedFraction,
48
+ token_estimate: options.contextUsage?.usedTokens,
49
+ context_limit_tokens: options.contextUsage?.contextLimitTokens,
50
+ model: options.contextUsage?.model,
56
51
  };
57
- // 6. Store snapshot
58
- storeSnapshot(storagePath, snapshot);
59
- // 7. Generate LATEST.md
60
- const markdown = compressToMarkdown(snapshot);
61
- writeLatestMd(storagePath, markdown);
62
- // 8. Update state
52
+ // 4. Skip empty snapshots — don't write JSON/index for 0-file non-manual captures
53
+ // This prevents accumulation of empty session_end snapshots
54
+ const hasContent = snapshot.files_changed.length > 0 ||
55
+ snapshot.trigger === 'manual' ||
56
+ snapshot.trigger === 'token_threshold';
57
+ if (hasContent) {
58
+ storeSnapshot(storagePath, snapshot);
59
+ const markdown = compressToMarkdown(snapshot);
60
+ writeLatestMd(storagePath, markdown);
61
+ writeTrails(storagePath, snapshot);
62
+ const canonicalFile = join(getSnapshotsDir(storagePath), `${snapshot.snapshot_id}.json`);
63
+ appendToRegistry(snapshot, canonicalFile);
64
+ }
65
+ // 6. Update state + increment snapshot counter
63
66
  const updatedState = updateSnapshotTime(state);
64
- saveState(storagePath, updatedState);
67
+ const finalState = incrementSnapshotCount(updatedState);
68
+ saveState(storagePath, finalState);
65
69
  return snapshot;
66
70
  }
67
- function generateSnapshotId() {
68
- const now = new Date();
69
- const pad = (n, len = 2) => String(n).padStart(len, '0');
70
- const date = `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}`;
71
- const time = `${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
72
- return `SNAP_${date}_${time}`;
73
- }
74
- /**
75
- * Enhance extraction with Claude Haiku for higher-quality summaries.
76
- * Falls back to original extraction if SDK not available or API key missing.
77
- */
78
- async function enhanceWithLLM(extraction, entries) {
79
- const apiKey = process.env.ANTHROPIC_API_KEY;
80
- if (!apiKey)
81
- return extraction;
82
- try {
83
- // Dynamic import — @anthropic-ai/sdk is an optional dependency
84
- const { default: Anthropic } = await import('@anthropic-ai/sdk');
85
- const client = new Anthropic({ apiKey });
86
- // Build a compressed transcript excerpt (last ~2000 tokens worth)
87
- const recentEntries = entries.slice(-50); // Last 50 entries
88
- const transcript = recentEntries
89
- .filter(e => e.type === 'assistant' || e.type === 'user')
90
- .map(e => `[${e.type}]: ${typeof e.content === 'string' ? e.content.slice(0, 200) : ''}`)
91
- .join('\n')
92
- .slice(-4000);
93
- const response = await client.messages.create({
94
- model: 'claude-haiku-4-5-20251001',
95
- max_tokens: 1000,
96
- messages: [{
97
- role: 'user',
98
- content: `Analyze this coding session transcript and extract:
99
- 1. Key decisions made (with brief rationale)
100
- 2. Current status (1-2 sentences)
101
- 3. Open items/TODOs (with priority: high/medium/low)
102
- 4. Unknowns or blockers
103
-
104
- Transcript excerpt:
105
- ${transcript}
106
-
107
- Respond in JSON format:
108
- {
109
- "current_status": "...",
110
- "decisions": [{"description": "...", "rationale": "..."}],
111
- "open_items": [{"description": "...", "priority": "high|medium|low"}],
112
- "unknowns": ["..."]
113
- }`,
114
- }],
115
- });
116
- const text = response.content[0]?.type === 'text' ? response.content[0].text : '';
117
- const jsonMatch = text.match(/\{[\s\S]*\}/);
118
- if (jsonMatch) {
119
- const enhanced = JSON.parse(jsonMatch[0]);
120
- return {
121
- ...extraction,
122
- current_status: enhanced.current_status ?? extraction.current_status,
123
- decisions: enhanced.decisions?.length ? enhanced.decisions : extraction.decisions,
124
- open_items: enhanced.open_items?.length ? enhanced.open_items : extraction.open_items,
125
- unknowns: enhanced.unknowns?.length ? enhanced.unknowns : extraction.unknowns,
126
- };
127
- }
128
- }
129
- catch {
130
- // Fall back silently to pattern-based extraction
131
- }
132
- return extraction;
133
- }
134
71
  //# sourceMappingURL=capture.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/snapshot/capture.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/snapshot/capture.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import type { Snapshot } from '../types.js';
2
2
  /**
3
- * Compress a full snapshot into a concise markdown summary.
4
- * Target: <150 lines, <1000 tokens.
5
- * This becomes LATEST.md — the hot context tier.
3
+ * Compress a snapshot into markdown now focused on file tracking data only.
4
+ * Intent/decisions/progress come from Claude-written bookmark.context.md, not this.
5
+ * This becomes LATEST.md — supplementary file change data.
6
6
  */
7
7
  export declare function compressToMarkdown(snapshot: Snapshot): string;
8
8
  //# sourceMappingURL=compress.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compress.d.ts","sourceRoot":"","sources":["../../src/snapshot/compress.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CA2F7D"}
1
+ {"version":3,"file":"compress.d.ts","sourceRoot":"","sources":["../../src/snapshot/compress.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAG5C;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CA6C7D"}