clawvault 2.1.2 → 2.2.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 (54) hide show
  1. package/bin/command-registration.test.js +6 -1
  2. package/bin/help-contract.test.js +2 -0
  3. package/bin/register-maintenance-commands.js +111 -0
  4. package/bin/register-query-commands.js +32 -1
  5. package/bin/register-session-lifecycle-commands.js +2 -0
  6. package/dist/{chunk-5MQB7B37.js → chunk-2HM7ZI4X.js} +268 -434
  7. package/dist/{chunk-TBVI4N53.js → chunk-6RIHODNR.js} +120 -95
  8. package/dist/chunk-73P7XCQM.js +104 -0
  9. package/dist/{chunk-MIIXBNO3.js → chunk-DHBDH4DN.js} +4 -0
  10. package/dist/chunk-GJEGPO7U.js +49 -0
  11. package/dist/chunk-GQVYQCY5.js +396 -0
  12. package/dist/{chunk-TXO34J3O.js → chunk-H7JW4L7H.js} +1 -1
  13. package/dist/{chunk-QFBKWDYR.js → chunk-IFGDPIFI.js} +3 -3
  14. package/dist/chunk-K6XHCUFL.js +123 -0
  15. package/dist/{chunk-PIJGYMQZ.js → chunk-KNDVXXKC.js} +1 -1
  16. package/dist/chunk-L6NB43WV.js +472 -0
  17. package/dist/{chunk-FEQ2CQ3Y.js → chunk-LB6P4CD5.js} +20 -7
  18. package/dist/chunk-MGDEINGP.js +99 -0
  19. package/dist/chunk-MQUJNOHK.js +58 -0
  20. package/dist/chunk-P5EPF6MB.js +182 -0
  21. package/dist/chunk-VR5NE7PZ.js +45 -0
  22. package/dist/chunk-WZI3OAE5.js +111 -0
  23. package/dist/chunk-Z2XBWN7A.js +247 -0
  24. package/dist/{chunk-O5V7SD5C.js → chunk-ZZA73MFY.js} +1 -1
  25. package/dist/commands/archive.d.ts +11 -0
  26. package/dist/commands/archive.js +11 -0
  27. package/dist/commands/context.d.ts +1 -1
  28. package/dist/commands/context.js +6 -4
  29. package/dist/commands/doctor.js +6 -6
  30. package/dist/commands/graph.js +2 -2
  31. package/dist/commands/link.js +1 -1
  32. package/dist/commands/migrate-observations.d.ts +19 -0
  33. package/dist/commands/migrate-observations.js +13 -0
  34. package/dist/commands/observe.js +5 -2
  35. package/dist/commands/rebuild.d.ts +11 -0
  36. package/dist/commands/rebuild.js +12 -0
  37. package/dist/commands/reflect.d.ts +11 -0
  38. package/dist/commands/reflect.js +13 -0
  39. package/dist/commands/replay.d.ts +16 -0
  40. package/dist/commands/replay.js +14 -0
  41. package/dist/commands/setup.js +2 -2
  42. package/dist/commands/sleep.d.ts +1 -0
  43. package/dist/commands/sleep.js +29 -6
  44. package/dist/commands/status.js +6 -6
  45. package/dist/commands/sync-bd.d.ts +10 -0
  46. package/dist/commands/sync-bd.js +9 -0
  47. package/dist/commands/wake.js +53 -35
  48. package/dist/{context-COo8oq1k.d.ts → context-BUGaWpyL.d.ts} +1 -0
  49. package/dist/index.d.ts +55 -20
  50. package/dist/index.js +67 -16
  51. package/hooks/clawvault/HOOK.md +3 -2
  52. package/hooks/clawvault/handler.js +51 -0
  53. package/hooks/clawvault/handler.test.js +20 -0
  54. package/package.json +2 -2
@@ -47,7 +47,7 @@ describe('CLI command registration modules', () => {
47
47
  });
48
48
 
49
49
  const names = listCommandNames(program);
50
- expect(names).toEqual(expect.arrayContaining(['search', 'vsearch', 'context', 'observe', 'session-recap']));
50
+ expect(names).toEqual(expect.arrayContaining(['search', 'vsearch', 'context', 'observe', 'reflect', 'session-recap']));
51
51
 
52
52
  const contextCommand = program.commands.find((command) => command.name() === 'context');
53
53
  const profileOption = contextCommand?.options.find((option) => option.flags.includes('--profile <profile>'));
@@ -115,6 +115,11 @@ describe('CLI command registration modules', () => {
115
115
  'graph',
116
116
  'entities',
117
117
  'link',
118
+ 'rebuild',
119
+ 'archive',
120
+ 'migrate-observations',
121
+ 'replay',
122
+ 'sync-bd',
118
123
  'checkpoint',
119
124
  'recover',
120
125
  'status',
@@ -8,6 +8,8 @@ describe('CLI help contract', () => {
8
8
  expect(help).toContain('context');
9
9
  expect(help).toContain('compat');
10
10
  expect(help).toContain('graph');
11
+ expect(help).toContain('reflect');
12
+ expect(help).toContain('replay');
11
13
  expect(help).toContain('repair-session');
12
14
  expect(help).toContain('template');
13
15
  });
@@ -134,4 +134,115 @@ export function registerMaintenanceCommands(program, { chalk }) {
134
134
  process.exit(1);
135
135
  }
136
136
  });
137
+
138
+ // === REBUILD ===
139
+ program
140
+ .command('rebuild')
141
+ .description('Rebuild observations from ledger/raw transcripts')
142
+ .option('--from <date>', 'Start date (YYYY-MM-DD)')
143
+ .option('--to <date>', 'End date (YYYY-MM-DD)')
144
+ .option('-v, --vault <path>', 'Vault path')
145
+ .action(async (options) => {
146
+ try {
147
+ const { rebuildCommand } = await import('../dist/commands/rebuild.js');
148
+ await rebuildCommand({
149
+ vaultPath: options.vault,
150
+ from: options.from,
151
+ to: options.to
152
+ });
153
+ } catch (err) {
154
+ console.error(chalk.red(`Error: ${err.message}`));
155
+ process.exit(1);
156
+ }
157
+ });
158
+
159
+ // === ARCHIVE ===
160
+ program
161
+ .command('archive')
162
+ .description('Archive old observations into ledger/archive')
163
+ .option('--older-than <days>', 'Archive observations older than this many days', '14')
164
+ .option('--dry-run', 'Show archive candidates without writing')
165
+ .option('-v, --vault <path>', 'Vault path')
166
+ .action(async (options) => {
167
+ try {
168
+ const { archiveCommand } = await import('../dist/commands/archive.js');
169
+ const olderThan = Number.parseInt(options.olderThan, 10);
170
+ if (!Number.isFinite(olderThan) || olderThan <= 0) {
171
+ throw new Error(`Invalid --older-than value: ${options.olderThan}`);
172
+ }
173
+ await archiveCommand({
174
+ vaultPath: options.vault,
175
+ olderThan,
176
+ dryRun: options.dryRun
177
+ });
178
+ } catch (err) {
179
+ console.error(chalk.red(`Error: ${err.message}`));
180
+ process.exit(1);
181
+ }
182
+ });
183
+
184
+ // === MIGRATE-OBSERVATIONS ===
185
+ program
186
+ .command('migrate-observations')
187
+ .description('Convert legacy emoji observations to scored format')
188
+ .option('--dry-run', 'Show migration candidates without writing')
189
+ .option('-v, --vault <path>', 'Vault path')
190
+ .action(async (options) => {
191
+ try {
192
+ const { migrateObservationsCommand } = await import('../dist/commands/migrate-observations.js');
193
+ await migrateObservationsCommand({
194
+ vaultPath: options.vault,
195
+ dryRun: options.dryRun
196
+ });
197
+ } catch (err) {
198
+ console.error(chalk.red(`Error: ${err.message}`));
199
+ process.exit(1);
200
+ }
201
+ });
202
+
203
+ // === REPLAY ===
204
+ program
205
+ .command('replay')
206
+ .description('Replay historical conversation exports through observe pipeline')
207
+ .requiredOption('--source <platform>', 'Source platform (chatgpt|claude|opencode|openclaw)')
208
+ .requiredOption('--input <path>', 'Input export file or directory')
209
+ .option('--from <date>', 'Start date (YYYY-MM-DD)')
210
+ .option('--to <date>', 'End date (YYYY-MM-DD)')
211
+ .option('--dry-run', 'Preview replay candidates without writing')
212
+ .option('-v, --vault <path>', 'Vault path')
213
+ .action(async (options) => {
214
+ try {
215
+ const { replayCommand } = await import('../dist/commands/replay.js');
216
+ await replayCommand({
217
+ source: options.source,
218
+ inputPath: options.input,
219
+ from: options.from,
220
+ to: options.to,
221
+ dryRun: options.dryRun,
222
+ vaultPath: options.vault
223
+ });
224
+ } catch (err) {
225
+ console.error(chalk.red(`Error: ${err.message}`));
226
+ process.exit(1);
227
+ }
228
+ });
229
+
230
+ // === SYNC-BD ===
231
+ program
232
+ .command('sync-bd')
233
+ .description('Sync active Beads tasks into views/now.md (optional)')
234
+ .option('--dry-run', 'Show sync output without writing')
235
+ .option('-v, --vault <path>', 'Vault path')
236
+ .action(async (options) => {
237
+ try {
238
+ const { syncBdCommand } = await import('../dist/commands/sync-bd.js');
239
+ await syncBdCommand({
240
+ vaultPath: options.vault,
241
+ dryRun: options.dryRun
242
+ });
243
+ } catch (err) {
244
+ console.error(chalk.red(`Error: ${err.message}`));
245
+ process.exit(1);
246
+ }
247
+ });
137
248
  }
@@ -132,15 +132,20 @@ export function registerQueryCommands(
132
132
  .option('--include-observations', 'Include observation memories in output', true)
133
133
  .option('--budget <number>', 'Optional token budget for assembled context')
134
134
  .option('--profile <profile>', 'Context profile (default|planning|incident|handoff|auto)', 'default')
135
+ .option('--max-hops <n>', 'Maximum graph expansion hops', '2')
135
136
  .option('-v, --vault <path>', 'Vault path')
136
137
  .action(async (task, options) => {
137
138
  try {
138
139
  const vaultPath = resolveVaultPath(options.vault);
139
140
  const format = options.format === 'json' ? 'json' : 'markdown';
140
141
  const parsedBudget = options.budget ? Number.parseInt(options.budget, 10) : undefined;
142
+ const parsedMaxHops = Number.parseInt(options.maxHops, 10);
141
143
  if (options.budget && (!Number.isFinite(parsedBudget) || parsedBudget <= 0)) {
142
144
  throw new Error(`Invalid --budget value: ${options.budget}`);
143
145
  }
146
+ if (!Number.isFinite(parsedMaxHops) || parsedMaxHops <= 0) {
147
+ throw new Error(`Invalid --max-hops value: ${options.maxHops}`);
148
+ }
144
149
 
145
150
  const { contextCommand } = await import('../dist/commands/context.js');
146
151
  await contextCommand(task, {
@@ -150,7 +155,8 @@ export function registerQueryCommands(
150
155
  recent: options.recent,
151
156
  includeObservations: options.includeObservations,
152
157
  budget: parsedBudget,
153
- profile: options.profile
158
+ profile: options.profile,
159
+ maxHops: parsedMaxHops
154
160
  });
155
161
  } catch (err) {
156
162
  if (err instanceof QmdUnavailableError) {
@@ -216,6 +222,31 @@ export function registerQueryCommands(
216
222
  }
217
223
  });
218
224
 
225
+ // === REFLECT ===
226
+ program
227
+ .command('reflect')
228
+ .description('Promote stable observations into weekly reflections')
229
+ .option('--days <n>', 'Observation window in days', '14')
230
+ .option('--dry-run', 'Show reflection output candidates without writing')
231
+ .option('-v, --vault <path>', 'Vault path')
232
+ .action(async (options) => {
233
+ try {
234
+ const { reflectCommand } = await import('../dist/commands/reflect.js');
235
+ const days = Number.parseInt(options.days, 10);
236
+ if (!Number.isFinite(days) || days <= 0) {
237
+ throw new Error(`Invalid --days value: ${options.days}`);
238
+ }
239
+ await reflectCommand({
240
+ vaultPath: resolveVaultPath(options.vault),
241
+ days,
242
+ dryRun: options.dryRun
243
+ });
244
+ } catch (err) {
245
+ console.error(chalk.red(`Error: ${err.message}`));
246
+ process.exit(1);
247
+ }
248
+ });
249
+
219
250
  // === SESSION-RECAP ===
220
251
  program
221
252
  .command('session-recap <sessionKey>')
@@ -54,6 +54,7 @@ export function registerSessionLifecycleCommands(
54
54
  .option('-f, --feeling <state>', 'Emotional/energy state')
55
55
  .option('-s, --session <key>', 'Session key')
56
56
  .option('--session-transcript <path>', 'Session transcript path for auto-observe')
57
+ .option('--reflect', 'Run weekly reflection pass after sleep handoff')
57
58
  .option('--index', 'Update qmd index after handoff')
58
59
  .option('--no-git', 'Skip git commit prompt')
59
60
  .option('-v, --vault <path>', 'Vault path')
@@ -70,6 +71,7 @@ export function registerSessionLifecycleCommands(
70
71
  feeling: options.feeling,
71
72
  sessionKey: options.session,
72
73
  sessionTranscript: options.sessionTranscript,
74
+ reflect: options.reflect,
73
75
  vaultPath,
74
76
  index: options.index,
75
77
  git: options.git