context-vault 3.19.0 → 3.20.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 (31) hide show
  1. package/bin/cli.js +516 -4
  2. package/node_modules/@context-vault/core/dist/main.d.ts +1 -0
  3. package/node_modules/@context-vault/core/dist/main.d.ts.map +1 -1
  4. package/node_modules/@context-vault/core/dist/main.js +2 -0
  5. package/node_modules/@context-vault/core/dist/main.js.map +1 -1
  6. package/node_modules/@context-vault/core/dist/search.d.ts +1 -0
  7. package/node_modules/@context-vault/core/dist/search.d.ts.map +1 -1
  8. package/node_modules/@context-vault/core/dist/search.js +10 -1
  9. package/node_modules/@context-vault/core/dist/search.js.map +1 -1
  10. package/node_modules/@context-vault/core/dist/search.test.d.ts +2 -0
  11. package/node_modules/@context-vault/core/dist/search.test.d.ts.map +1 -0
  12. package/node_modules/@context-vault/core/dist/search.test.js +49 -0
  13. package/node_modules/@context-vault/core/dist/search.test.js.map +1 -0
  14. package/node_modules/@context-vault/core/package.json +9 -1
  15. package/node_modules/@context-vault/core/src/main.ts +3 -0
  16. package/node_modules/@context-vault/core/src/search.test.ts +59 -0
  17. package/node_modules/@context-vault/core/src/search.ts +11 -1
  18. package/package.json +2 -2
  19. package/.claude-plugin/README.md +0 -219
  20. package/.claude-plugin/plugin.json +0 -11
  21. package/commands/vault-cleanup.md +0 -43
  22. package/commands/vault-snapshot.md +0 -43
  23. package/commands/vault-status.md +0 -35
  24. package/dist/tools/session-start.d.ts +0 -25
  25. package/dist/tools/session-start.d.ts.map +0 -1
  26. package/dist/tools/session-start.js +0 -469
  27. package/dist/tools/session-start.js.map +0 -1
  28. package/skills/context-assembly/SKILL.md +0 -308
  29. package/skills/knowledge-capture/SKILL.md +0 -303
  30. package/skills/memory-management/SKILL.md +0 -237
  31. package/src/tools/session-start.ts +0 -527
package/bin/cli.js CHANGED
@@ -240,6 +240,17 @@ function getFlag(name) {
240
240
  return idx !== -1 && args[idx + 1] ? args[idx + 1] : null;
241
241
  }
242
242
 
243
+ function getFlagAll(name) {
244
+ const results = [];
245
+ for (let i = 0; i < args.length - 1; i++) {
246
+ if (args[i] === name) {
247
+ const val = args[i + 1];
248
+ if (val && !val.startsWith('--')) results.push(val);
249
+ }
250
+ }
251
+ return results;
252
+ }
253
+
243
254
  function prompt(question, defaultVal) {
244
255
  if (isNonInteractive) return Promise.resolve(defaultVal || '');
245
256
  const rl = createInterface({ input: process.stdin, output: process.stdout });
@@ -447,6 +458,9 @@ ${bold('Commands:')}
447
458
  ${cyan('reconnect')} Fix vault path, kill stale servers, re-register MCP, reindex
448
459
  ${cyan('search')} Search vault entries from CLI
449
460
  ${cyan('save')} Save an entry to the vault from CLI
461
+ ${cyan('get')} <id|key> Fetch a single entry by ULID or identity key
462
+ ${cyan('buckets')} List registered buckets with entry counts
463
+ ${cyan('dupes')} Find near-duplicate entries (read-only)
450
464
  ${cyan('import')} <path> Import entries from file, directory, or .zip archive
451
465
  ${cyan('export')} Export vault entries (JSON, CSV, or portable ZIP)
452
466
  ${cyan('ingest')} <url> Fetch URL and save as vault entry
@@ -462,6 +476,7 @@ ${bold('Commands:')}
462
476
  ${cyan('archive')} Archive old ephemeral/event entries (use --dry-run to preview)
463
477
  ${cyan('restore')} <id> Restore an archived entry back into the vault
464
478
  ${cyan('prune')} Remove expired entries (use --dry-run to preview)
479
+ ${cyan('delete')} <id> Hard-delete entry by ULID (DB + vec + file; clears superseded_by refs)
465
480
  ${cyan('stale')} List entries with low freshness scores
466
481
  ${cyan('stats')} recall|co-retrieval Measure recall ratio and co-retrieval graph
467
482
  ${cyan('remote')} setup|status|sync|pull Connect to hosted vault (cloud sync)
@@ -2683,6 +2698,118 @@ async function runPrune() {
2683
2698
  }
2684
2699
  }
2685
2700
 
2701
+ async function runDelete() {
2702
+ if (flags.has('--help')) {
2703
+ console.log(`
2704
+ ${bold('context-vault delete')} <id> [options]
2705
+
2706
+ Hard-delete a vault entry by ULID. Removes the DB row, vector-index row,
2707
+ and the markdown file on disk. Also clears any ${cyan('superseded_by')} refs
2708
+ on other entries that pointed at this one (no dangling links).
2709
+
2710
+ Distinct from ${cyan('archive')} (soft, reversible via ${cyan('restore')})
2711
+ and ${cyan('prune')} (bulk by expiry policy).
2712
+
2713
+ ${bold('Usage:')}
2714
+ context-vault delete <id> Delete entry by ULID
2715
+ context-vault delete <id> --dry-run Show what would be deleted, no changes
2716
+ context-vault delete <id> --yes Skip confirmation prompt
2717
+
2718
+ ${bold('Examples:')}
2719
+ context-vault delete 01KQ0123456789ABCDEFGHJKMN
2720
+ context-vault delete 01KQ0123456789ABCDEFGHJKMN --yes
2721
+ `);
2722
+ return;
2723
+ }
2724
+
2725
+ const entryId = args[1];
2726
+ if (!entryId || entryId.startsWith('--')) {
2727
+ console.error(red('Error: entry id is required'));
2728
+ console.error(`Usage: ${cyan('context-vault delete <id>')}`);
2729
+ process.exit(1);
2730
+ }
2731
+
2732
+ const dryRun = flags.has('--dry-run');
2733
+
2734
+ const { resolveConfig } = await import('@context-vault/core/config');
2735
+ const { initDatabase, prepareStatements, deleteVec } = await import('@context-vault/core/db');
2736
+
2737
+ const config = resolveConfig();
2738
+ if (!config.vaultDirExists) {
2739
+ console.error(red(`Vault directory not found: ${config.vaultDir}`));
2740
+ console.error('Run ' + cyan('context-vault setup') + ' to configure.');
2741
+ process.exit(1);
2742
+ }
2743
+
2744
+ const db = await initDatabase(config.dbPath);
2745
+ try {
2746
+ const stmts = prepareStatements(db);
2747
+ const row = stmts.getEntryById.get(entryId);
2748
+ if (!row) {
2749
+ console.error(red(`Error: no entry found with id ${entryId}`));
2750
+ process.exit(1);
2751
+ }
2752
+
2753
+ const label = row.title ? `${row.kind}: ${row.title}` : `${row.kind} (${row.id})`;
2754
+ const filePath = row.file_path || null;
2755
+
2756
+ if (dryRun) {
2757
+ console.log(`\n Would delete: ${label}`);
2758
+ if (filePath) console.log(dim(` file: ${filePath}`));
2759
+ console.log(dim(` id: ${row.id}`));
2760
+ const referrers = db
2761
+ .prepare('SELECT id, kind, title FROM vault WHERE superseded_by = ?')
2762
+ .all(entryId);
2763
+ if (referrers.length) {
2764
+ console.log(dim(` ${referrers.length} entr${referrers.length === 1 ? 'y has' : 'ies have'} superseded_by pointing here; those refs would be cleared:`));
2765
+ for (const r of referrers) {
2766
+ const rlabel = r.title ? `${r.kind}: ${r.title}` : `${r.kind} (${r.id})`;
2767
+ console.log(dim(` - ${rlabel}`));
2768
+ }
2769
+ }
2770
+ console.log(dim('\n Dry run — nothing changed.'));
2771
+ return;
2772
+ }
2773
+
2774
+ if (!isNonInteractive) {
2775
+ const answer = await prompt(`Delete ${label}? (y/N)`, 'N');
2776
+ if (!/^y(es)?$/i.test((answer || '').trim())) {
2777
+ console.log(dim(' Aborted.'));
2778
+ return;
2779
+ }
2780
+ }
2781
+
2782
+ const rowidRow = stmts.getRowid.get(entryId);
2783
+ if (rowidRow?.rowid) {
2784
+ try {
2785
+ deleteVec(stmts, Number(rowidRow.rowid));
2786
+ } catch {}
2787
+ }
2788
+ try {
2789
+ stmts.clearSupersededByRef.run(entryId);
2790
+ } catch {}
2791
+ stmts.deleteEntry.run(entryId);
2792
+
2793
+ if (filePath) {
2794
+ try {
2795
+ unlinkSync(filePath);
2796
+ } catch (e) {
2797
+ if (e?.code !== 'ENOENT') {
2798
+ console.error(yellow(` Warning: could not remove file: ${e.message}`));
2799
+ }
2800
+ }
2801
+ }
2802
+
2803
+ console.log(`${green('✓')} Deleted ${label}`);
2804
+ console.log(dim(` id: ${entryId}`));
2805
+ if (filePath) console.log(dim(` file removed: ${filePath}`));
2806
+ } finally {
2807
+ try {
2808
+ db.close();
2809
+ } catch {}
2810
+ }
2811
+ }
2812
+
2686
2813
  async function runArchive() {
2687
2814
  const dryRun = flags.has('--dry-run');
2688
2815
 
@@ -2908,6 +3035,226 @@ async function runCompact() {
2908
3035
  console.log(dim(' Use context-vault restore <id> to recover full body.'));
2909
3036
  }
2910
3037
 
3038
+ async function runGet() {
3039
+ if (flags.has('--help')) {
3040
+ console.log(`
3041
+ ${bold('context-vault get')} <id|identity-key> [options]
3042
+
3043
+ Fetch a single vault entry by ULID or by identity key.
3044
+
3045
+ ${bold('Usage:')}
3046
+ context-vault get 01KQ0123456789ABCDEFGHJKMN
3047
+ context-vault get bucket:myproject --kind bucket
3048
+ context-vault get myproject --kind bucket
3049
+ context-vault get <id> --format json
3050
+
3051
+ ${bold('Options:')}
3052
+ --kind <kind> Resolve the argument as an identity key for this kind
3053
+ --format <fmt> Output format: plain (default), json
3054
+ --full Show full entry body (not truncated)
3055
+ `);
3056
+ return;
3057
+ }
3058
+
3059
+ const ref = args[1];
3060
+ if (!ref || ref.startsWith('--')) {
3061
+ console.error(red('Error: entry id or identity key is required'));
3062
+ console.error(`Usage: ${cyan('context-vault get <id|identity-key>')}`);
3063
+ process.exit(1);
3064
+ }
3065
+
3066
+ const kindFlag = getFlag('--kind');
3067
+ const format = getFlag('--format') || 'plain';
3068
+ const showFull = flags.has('--full');
3069
+
3070
+ const { resolveConfig } = await import('@context-vault/core/config');
3071
+ const { initDatabase, prepareStatements } = await import('@context-vault/core/db');
3072
+
3073
+ const config = resolveConfig();
3074
+ if (!config.vaultDirExists) {
3075
+ console.error(red('No vault found. Run: context-vault setup'));
3076
+ process.exit(1);
3077
+ }
3078
+
3079
+ const db = await initDatabase(config.dbPath);
3080
+ try {
3081
+ const stmts = prepareStatements(db);
3082
+
3083
+ let row = null;
3084
+ if (kindFlag) {
3085
+ const key = ref.includes(':') ? ref : `${kindFlag}:${ref}`;
3086
+ row = stmts.getByIdentityKey.get(kindFlag, key) || stmts.getByIdentityKey.get(kindFlag, ref);
3087
+ } else {
3088
+ row = stmts.getEntryById.get(ref);
3089
+ if (!row && ref.includes(':')) {
3090
+ const inferredKind = ref.slice(0, ref.indexOf(':'));
3091
+ row = stmts.getByIdentityKey.get(inferredKind, ref);
3092
+ }
3093
+ }
3094
+
3095
+ if (!row) {
3096
+ console.error(red(`Error: no entry found for "${ref}"${kindFlag ? ` (kind ${kindFlag})` : ''}`));
3097
+ process.exit(1);
3098
+ }
3099
+
3100
+ if (format === 'json') {
3101
+ console.log(JSON.stringify(row, null, 2));
3102
+ return;
3103
+ }
3104
+
3105
+ const tags = row.tags ? JSON.parse(row.tags) : [];
3106
+ console.log(`\n ${bold(row.title || `${row.kind} (${row.id})`)}`);
3107
+ console.log(dim(` id: ${row.id}`));
3108
+ console.log(dim(` kind: ${row.kind}${row.category ? ` category: ${row.category}` : ''}`));
3109
+ if (row.identity_key) console.log(dim(` key: ${row.identity_key}`));
3110
+ if (tags.length) console.log(dim(` tags: ${tags.join(', ')}`));
3111
+ console.log(dim(` created: ${row.created_at}${row.updated_at ? ` updated: ${row.updated_at}` : ''}`));
3112
+ if (row.superseded_by) console.log(yellow(` superseded_by: ${row.superseded_by}`));
3113
+ const body = row.body || '';
3114
+ const shown = showFull ? body : body.slice(0, 2000);
3115
+ console.log('\n' + shown + (shown.length < body.length ? dim('\n … (truncated; use --full)') : ''));
3116
+ } finally {
3117
+ db.close();
3118
+ }
3119
+ }
3120
+
3121
+ async function runBuckets() {
3122
+ if (flags.has('--help')) {
3123
+ console.log(`
3124
+ ${bold('context-vault buckets')} [options]
3125
+
3126
+ List all registered bucket entities with entry counts. Buckets are named
3127
+ scopes that group entries via ${cyan('bucket:')}-prefixed tags.
3128
+
3129
+ ${bold('Options:')}
3130
+ --format <fmt> Output format: plain (default), json
3131
+ `);
3132
+ return;
3133
+ }
3134
+
3135
+ const format = getFlag('--format') || 'plain';
3136
+
3137
+ const { resolveConfig } = await import('@context-vault/core/config');
3138
+ const { initDatabase } = await import('@context-vault/core/db');
3139
+
3140
+ const config = resolveConfig();
3141
+ if (!config.vaultDirExists) {
3142
+ console.error(red('No vault found. Run: context-vault setup'));
3143
+ process.exit(1);
3144
+ }
3145
+
3146
+ const db = await initDatabase(config.dbPath);
3147
+ try {
3148
+ const buckets = db
3149
+ .prepare(
3150
+ `SELECT id, title, identity_key, body, tags, created_at, updated_at
3151
+ FROM vault
3152
+ WHERE kind = 'bucket'
3153
+ AND (expires_at IS NULL OR expires_at > datetime('now'))
3154
+ AND superseded_by IS NULL
3155
+ ORDER BY title ASC`
3156
+ )
3157
+ .all();
3158
+
3159
+ const withCounts = buckets.map((b) => {
3160
+ const name = b.identity_key?.replace(/^bucket:/, '') || b.title;
3161
+ const c = db
3162
+ .prepare(
3163
+ `SELECT COUNT(*) AS c FROM vault
3164
+ WHERE superseded_by IS NULL
3165
+ AND (expires_at IS NULL OR expires_at > datetime('now'))
3166
+ AND tags LIKE ?`
3167
+ )
3168
+ .get(`%"bucket:${name}"%`);
3169
+ return { ...b, name, entry_count: c?.c ?? 0 };
3170
+ });
3171
+
3172
+ if (format === 'json') {
3173
+ console.log(JSON.stringify(withCounts, null, 2));
3174
+ return;
3175
+ }
3176
+
3177
+ if (!withCounts.length) {
3178
+ console.log(dim(' No buckets registered.'));
3179
+ return;
3180
+ }
3181
+
3182
+ console.log(`\n ${bold(`Registered buckets (${withCounts.length})`)}\n`);
3183
+ for (const b of withCounts) {
3184
+ const desc = b.body ? ` — ${b.body.split('\n')[0].slice(0, 60)}` : '';
3185
+ console.log(` ${cyan(b.name)} ${dim(`(${b.entry_count})`)}${dim(desc)}`);
3186
+ }
3187
+ } finally {
3188
+ db.close();
3189
+ }
3190
+ }
3191
+
3192
+ async function runDupes() {
3193
+ if (flags.has('--help')) {
3194
+ console.log(`
3195
+ ${bold('context-vault dupes')} [options]
3196
+
3197
+ Find near-duplicate entries by semantic + title similarity. Read-only —
3198
+ reports groups, changes nothing.
3199
+
3200
+ ${bold('Options:')}
3201
+ --threshold <n> Similarity threshold 0..1 (default: 0.85)
3202
+ --limit <n> Max duplicate groups (default: 50)
3203
+ --kind <kind> Restrict to a single kind
3204
+ --format <fmt> Output format: plain (default), json
3205
+ `);
3206
+ return;
3207
+ }
3208
+
3209
+ const threshold = parseFloat(getFlag('--threshold') || '0.85');
3210
+ const limit = parseInt(getFlag('--limit') || '50', 10);
3211
+ const kind = getFlag('--kind') || undefined;
3212
+ const format = getFlag('--format') || 'plain';
3213
+
3214
+ const { resolveConfig } = await import('@context-vault/core/config');
3215
+ const { initDatabase, prepareStatements } = await import('@context-vault/core/db');
3216
+ const { embed } = await import('@context-vault/core/embed');
3217
+ const { findDuplicates } = await import('@context-vault/core/consolidation');
3218
+
3219
+ const config = resolveConfig();
3220
+ if (!config.vaultDirExists) {
3221
+ console.error(red('No vault found. Run: context-vault setup'));
3222
+ process.exit(1);
3223
+ }
3224
+
3225
+ const db = await initDatabase(config.dbPath);
3226
+ try {
3227
+ const stmts = prepareStatements(db);
3228
+ const ctx = { db, config, stmts, embed };
3229
+ const groups = await findDuplicates(ctx, { threshold, limit, kind, dryRun: true });
3230
+
3231
+ if (format === 'json') {
3232
+ console.log(JSON.stringify(groups, null, 2));
3233
+ return;
3234
+ }
3235
+
3236
+ if (!groups.length) {
3237
+ console.log(dim(` No near-duplicates found (threshold ${threshold}).`));
3238
+ return;
3239
+ }
3240
+
3241
+ console.log(`\n ${bold(`Near-duplicate groups (${groups.length})`)} ${dim(`threshold ${threshold}`)}\n`);
3242
+ for (const g of groups) {
3243
+ const dupCount = (g.duplicate_ids?.length ?? 0) + 1;
3244
+ console.log(` ${yellow(`${dupCount}×`)} ${g.canonical_title || ''} ${dim(`sim ${g.similarity}`)}`);
3245
+ console.log(dim(` canonical: ${g.canonical_id}`));
3246
+ for (const id of g.duplicate_ids ?? []) {
3247
+ console.log(dim(` dup: ${id}`));
3248
+ }
3249
+ for (const t of g.sample_titles ?? []) {
3250
+ console.log(dim(` · ${t}`));
3251
+ }
3252
+ }
3253
+ } finally {
3254
+ db.close();
3255
+ }
3256
+ }
3257
+
2911
3258
  async function runStatus() {
2912
3259
  const { resolveConfig } = await import('@context-vault/core/config');
2913
3260
  const { initDatabase } = await import('@context-vault/core/db');
@@ -4181,7 +4528,7 @@ ${bold('Examples:')}
4181
4528
  const dryRun = flags.has('--dry-run');
4182
4529
  const verbose = flags.has('--verbose');
4183
4530
 
4184
- const GMAIL_CLI_PATH = '/Users/admin/omni/workspaces/_archive/agent-tools/gmail-cli/cli.ts';
4531
+ const GMAIL_CLI_PATH = join(homedir(), 'omni/workspaces/_archive/agent-tools/gmail-cli/cli.ts');
4185
4532
  const SKIP_LABELS = new Set([
4186
4533
  'CATEGORY_PROMOTIONS',
4187
4534
  'CATEGORY_SOCIAL',
@@ -4322,7 +4669,7 @@ ${bold('Examples:')}
4322
4669
  }
4323
4670
 
4324
4671
  async function runSlackBridge() {
4325
- const SLACK_CLI_PATH = '/Users/admin/omni/workspaces/_archive/agent-tools/slack-cli/cli.ts';
4672
+ const SLACK_CLI_PATH = join(homedir(), 'omni/workspaces/_archive/agent-tools/slack-cli/cli.ts');
4326
4673
 
4327
4674
  if (flags.has('--help') || (!flags.has('--list-channels') && !getFlag('--channels'))) {
4328
4675
  console.log(`
@@ -5156,10 +5503,19 @@ ${bold('Optional:')}
5156
5503
  --source <source> Source label (default: cli)
5157
5504
  --identity-key <key> Identity key (for entity kinds)
5158
5505
  --meta <json> Additional metadata as JSON
5506
+ --supersedes <id> Mark this entry as superseding an existing entry
5507
+ (can be passed multiple times; old entries get
5508
+ reciprocal superseded_by link to this new entry)
5509
+ --related-to <id> Add a related-to link to another entry by ULID
5510
+ (can be passed multiple times; builds the graph)
5159
5511
 
5160
5512
  ${bold('Examples:')}
5161
5513
  context-vault save --kind insight --title "Express 5 gotcha" --body "body parser changed"
5162
5514
  echo "content" | context-vault save --kind reference --title "API notes"
5515
+ context-vault save --kind decision --title "revised plan" --body "..." \\
5516
+ --supersedes 01K9... --supersedes 01KA...
5517
+ context-vault save --kind insight --title "graph node" --body "..." \\
5518
+ --related-to 01KB... --related-to 01KC...
5163
5519
  `);
5164
5520
  return;
5165
5521
  }
@@ -5173,6 +5529,8 @@ ${bold('Examples:')}
5173
5529
  const bodyFlag = getFlag('--body');
5174
5530
  const identityKey = getFlag('--identity-key');
5175
5531
  const metaRaw = getFlag('--meta');
5532
+ const supersedesList = getFlagAll('--supersedes');
5533
+ const relatedToList = getFlagAll('--related-to');
5176
5534
 
5177
5535
  if (!kind) {
5178
5536
  console.error(red('Error: --kind is required'));
@@ -5248,8 +5606,17 @@ ${bold('Examples:')}
5248
5606
  ...(tier ? { tier } : {}),
5249
5607
  ...(identityKey ? { identity_key: identityKey } : {}),
5250
5608
  ...(meta !== undefined ? { meta } : {}),
5609
+ ...(supersedesList.length ? { supersedes: supersedesList } : {}),
5610
+ ...(relatedToList.length ? { related_to: relatedToList } : {}),
5251
5611
  });
5252
5612
  console.log(`${green('✓')} Saved ${kind} — id: ${entry.id}`);
5613
+ if (supersedesList.length) {
5614
+ console.log(dim(` supersedes: ${supersedesList.join(', ')}`));
5615
+ console.log(dim(` (reciprocal superseded_by written to ${supersedesList.length} entr${supersedesList.length === 1 ? 'y' : 'ies'})`));
5616
+ }
5617
+ if (relatedToList.length) {
5618
+ console.log(dim(` related_to: ${relatedToList.join(', ')}`));
5619
+ }
5253
5620
  } catch (e) {
5254
5621
  console.error(`${red('x')} Failed to save: ${e.message}`);
5255
5622
  process.exit(1);
@@ -6557,6 +6924,104 @@ async function runDoctor() {
6557
6924
  console.log(` ${dim('Fix: run context-vault setup to download the model')}`);
6558
6925
  }
6559
6926
 
6927
+ // ── Save/search roundtrip ────────────────────────────────────────────
6928
+ // Canary save→search check against the LIVE vault. Detects within seconds
6929
+ // when captureAndIndex returns success but data didn't land in the DB or
6930
+ // isn't findable via search (the 2026-04-19 silent-drift incident class).
6931
+ // kind='event' so the canary is never embedded — keeps the test stable
6932
+ // when embeddings are degraded.
6933
+ if (db) {
6934
+ let canaryEntry = null;
6935
+ let canaryStmts = null;
6936
+ let dbMod = null;
6937
+ try {
6938
+ dbMod = await import('@context-vault/core/db');
6939
+ const { embed } = await import('@context-vault/core/embed');
6940
+ const { captureAndIndex } = await import('@context-vault/core/capture');
6941
+ const { hybridSearch } = await import('@context-vault/core/search');
6942
+
6943
+ canaryStmts = dbMod.prepareStatements(db);
6944
+
6945
+ // Single alphanumeric token: stays one FTS term (no hyphen/underscore
6946
+ // splitting), uniquely identifies the canary in tag-search fallback,
6947
+ // and avoids collisions with anything else in the live vault.
6948
+ const canaryRand =
6949
+ Math.random().toString(36).slice(2, 10) + Math.random().toString(36).slice(2, 10);
6950
+ const canaryToken = `dcanary${canaryRand}`;
6951
+
6952
+ const ctx = {
6953
+ db,
6954
+ config,
6955
+ stmts: canaryStmts,
6956
+ embed,
6957
+ insertVec: (rowid, embedding) => dbMod.insertVec(canaryStmts, rowid, embedding),
6958
+ deleteVec: (rowid) => dbMod.deleteVec(canaryStmts, rowid),
6959
+ insertCtxVec: () => {},
6960
+ deleteCtxVec: () => {},
6961
+ };
6962
+
6963
+ canaryEntry = await captureAndIndex(ctx, {
6964
+ kind: 'event',
6965
+ title: 'doctor-canary',
6966
+ body: canaryToken,
6967
+ tags: [canaryToken, 'doctor-canary'],
6968
+ source: 'doctor',
6969
+ });
6970
+
6971
+ // Verify the persisted DB row matches what we saved before searching —
6972
+ // catches the silent-wedge case where captureAndIndex returns success
6973
+ // but the row never landed.
6974
+ const persisted = canaryStmts.getEntryById.get(canaryEntry.id);
6975
+ if (!persisted) {
6976
+ throw new Error('canary save returned success but row missing from DB');
6977
+ }
6978
+ if (persisted.body !== canaryToken) {
6979
+ throw new Error('canary persisted with wrong body');
6980
+ }
6981
+
6982
+ // kindFilter='event' scopes the search to events only. Events are not
6983
+ // embedded, so the vec lane is bypassed and the canary doesn't have to
6984
+ // out-rank thousands of recalled knowledge entries to make the page.
6985
+ const results = await hybridSearch(ctx, canaryToken, {
6986
+ kindFilter: 'event',
6987
+ limit: 10,
6988
+ });
6989
+ const found = results.find((r) => r.id === canaryEntry.id);
6990
+ if (!found) {
6991
+ throw new Error('canary saved but not returned by search');
6992
+ }
6993
+ if (found.body !== canaryToken) {
6994
+ throw new Error('canary found but body mismatch');
6995
+ }
6996
+
6997
+ console.log(` ${green('✓')} Save/search roundtrip`);
6998
+ } catch (e) {
6999
+ console.log(` ${red('✘')} Save/search roundtrip: ${e.message}`);
7000
+ allOk = false;
7001
+ } finally {
7002
+ if (canaryEntry) {
7003
+ try {
7004
+ if (existsSync(canaryEntry.filePath)) {
7005
+ unlinkSync(canaryEntry.filePath);
7006
+ }
7007
+ } catch {}
7008
+ if (canaryStmts && dbMod) {
7009
+ try {
7010
+ const rowidRow = canaryStmts.getRowid.get(canaryEntry.id);
7011
+ if (rowidRow?.rowid) {
7012
+ try {
7013
+ dbMod.deleteVec(canaryStmts, Number(rowidRow.rowid));
7014
+ } catch {}
7015
+ }
7016
+ } catch {}
7017
+ try {
7018
+ canaryStmts.deleteEntry.run(canaryEntry.id);
7019
+ } catch {}
7020
+ }
7021
+ }
7022
+ }
7023
+ }
7024
+
6560
7025
  // ── DB/filesystem consistency ─────────────────────────────────────────
6561
7026
  if (db && existsSync(config.vaultDir)) {
6562
7027
  try {
@@ -7402,13 +7867,48 @@ async function runStats() {
7402
7867
  await runStatsRecall({ resolveConfig, initDatabase, gatherRecallSummary });
7403
7868
  } else if (sub === 'co-retrieval') {
7404
7869
  await runStatsCoRetrieval({ resolveConfig, initDatabase, gatherCoRetrievalSummary });
7870
+ } else if (sub === 'counts') {
7871
+ await runStatsCounts({ resolveConfig, initDatabase });
7405
7872
  } else {
7406
7873
  console.error(red(` Unknown stats subcommand: ${sub}`));
7407
- console.error(` Available: recall, co-retrieval`);
7874
+ console.error(` Available: recall, co-retrieval, counts`);
7408
7875
  process.exit(1);
7409
7876
  }
7410
7877
  }
7411
7878
 
7879
+ async function runStatsCounts({ resolveConfig, initDatabase }) {
7880
+ const format = getFlag('--format') || 'plain';
7881
+ const config = resolveConfig();
7882
+ if (!config.vaultDirExists) {
7883
+ console.error(red('No vault found. Run: context-vault setup'));
7884
+ process.exit(1);
7885
+ }
7886
+ const db = await initDatabase(config.dbPath);
7887
+ try {
7888
+ const live = `superseded_by IS NULL AND (expires_at IS NULL OR expires_at > datetime('now'))`;
7889
+ const total = db.prepare(`SELECT COUNT(*) AS c FROM vault WHERE ${live}`).get()?.c ?? 0;
7890
+ const byKind = db
7891
+ .prepare(`SELECT kind AS name, COUNT(*) AS count FROM vault WHERE ${live} GROUP BY kind ORDER BY count DESC`)
7892
+ .all();
7893
+ const byCategory = db
7894
+ .prepare(`SELECT category AS name, COUNT(*) AS count FROM vault WHERE ${live} GROUP BY category ORDER BY count DESC`)
7895
+ .all();
7896
+
7897
+ if (format === 'json') {
7898
+ console.log(JSON.stringify({ total_entries: total, by_kind: byKind, by_category: byCategory }, null, 2));
7899
+ return;
7900
+ }
7901
+
7902
+ console.log(`\n ${bold('Vault counts')} ${dim(`total ${total}`)}\n`);
7903
+ console.log(` ${bold('By category')}`);
7904
+ for (const c of byCategory) console.log(` ${cyan((c.name || 'unknown').padEnd(12))} ${c.count}`);
7905
+ console.log(`\n ${bold('By kind')}`);
7906
+ for (const k of byKind) console.log(` ${cyan((k.name || 'unknown').padEnd(16))} ${k.count}`);
7907
+ } finally {
7908
+ db.close();
7909
+ }
7910
+ }
7911
+
7412
7912
  async function runStatsRecall({ resolveConfig, initDatabase, gatherRecallSummary }) {
7413
7913
  const config = resolveConfig();
7414
7914
  let db;
@@ -9080,7 +9580,7 @@ async function main() {
9080
9580
 
9081
9581
  if (flags.has('--help') || command === 'help') {
9082
9582
  // Commands with their own --help handling: delegate to them
9083
- const commandsWithHelp = new Set(['save', 'search', 'rules', 'hooks', 'team', 'remote', 'ingest-comms', 'gmail-bridge', 'slack-bridge', 'contacts']);
9583
+ const commandsWithHelp = new Set(['save', 'search', 'rules', 'hooks', 'team', 'remote', 'ingest-comms', 'gmail-bridge', 'slack-bridge', 'contacts', 'delete', 'get', 'buckets', 'dupes']);
9084
9584
  if (!command || command === 'help' || !commandsWithHelp.has(command)) {
9085
9585
  showHelp(flags.has('--all'));
9086
9586
  return;
@@ -9193,6 +9693,18 @@ async function main() {
9193
9693
  case 'prune':
9194
9694
  await runPrune();
9195
9695
  break;
9696
+ case 'delete':
9697
+ await runDelete();
9698
+ break;
9699
+ case 'get':
9700
+ await runGet();
9701
+ break;
9702
+ case 'buckets':
9703
+ await runBuckets();
9704
+ break;
9705
+ case 'dupes':
9706
+ await runDupes();
9707
+ break;
9196
9708
  case 'status':
9197
9709
  await runStatus();
9198
9710
  break;
@@ -18,4 +18,5 @@ export { startWatcher } from './watch.js';
18
18
  export type { WatcherOptions, VaultWatcher } from './watch.js';
19
19
  export { findDuplicates, mergeEntries, computeDecayScores } from './consolidation.js';
20
20
  export type { DuplicateGroup, MergeResult, DecayScore } from './consolidation.js';
21
+ export { assembleContext } from './assemble.js';
21
22
  //# sourceMappingURL=main.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AACA,YAAY,EACV,WAAW,EACX,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,eAAe,EACf,YAAY,EACZ,OAAO,EACP,aAAa,GACd,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,OAAO,EACP,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,WAAW,EACX,cAAc,EACd,cAAc,EACd,aAAa,EACb,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGvD,OAAO,EACL,IAAI,EACJ,OAAO,EACP,SAAS,EACT,SAAS,EACT,aAAa,EACb,UAAU,EACV,QAAQ,EACR,OAAO,GACR,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,SAAS,EACT,cAAc,GACf,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGrF,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/D,OAAO,EACL,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG5E,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAC7D,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG9E,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGhF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/D,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACtF,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AACA,YAAY,EACV,WAAW,EACX,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,eAAe,EACf,YAAY,EACZ,OAAO,EACP,aAAa,GACd,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,OAAO,EACP,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,WAAW,EACX,cAAc,EACd,cAAc,EACd,aAAa,EACb,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGvD,OAAO,EACL,IAAI,EACJ,OAAO,EACP,SAAS,EACT,SAAS,EACT,aAAa,EACb,UAAU,EACV,QAAQ,EACR,OAAO,GACR,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,SAAS,EACT,cAAc,GACf,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGrF,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/D,OAAO,EACL,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG5E,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAC7D,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG9E,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGhF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/D,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACtF,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGlF,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
@@ -30,4 +30,6 @@ export { htmlToMarkdown, extractHtmlContent, ingestUrl } from './ingest-url.js';
30
30
  export { startWatcher } from './watch.js';
31
31
  // Consolidation
32
32
  export { findDuplicates, mergeEntries, computeDecayScores } from './consolidation.js';
33
+ // Assemble
34
+ export { assembleContext } from './assemble.js';
33
35
  //# sourceMappingURL=main.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAoBA,YAAY;AACZ,OAAO,EACL,OAAO,EACP,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAExB,aAAa;AACb,OAAO,EACL,WAAW,EACX,cAAc,EACd,cAAc,EACd,aAAa,EACb,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAEzB,SAAS;AACT,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEvD,QAAQ;AACR,OAAO,EACL,IAAI,EACJ,OAAO,EACP,SAAS,EACT,SAAS,EACT,aAAa,EACb,UAAU,EACV,QAAQ,EACR,OAAO,GACR,MAAM,YAAY,CAAC;AAEpB,cAAc;AACd,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAE1B,aAAa;AACb,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,WAAW;AACX,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,SAAS,EACT,cAAc,GACf,MAAM,SAAS,CAAC;AAEjB,aAAa;AACb,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAErF,+BAA+B;AAC/B,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/D,oBAAoB;AACpB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAErB,UAAU;AACV,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE5E,WAAW;AACX,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,UAAU;AACV,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAG7D,aAAa;AACb,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEhF,QAAQ;AACR,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1C,gBAAgB;AAChB,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAoBA,YAAY;AACZ,OAAO,EACL,OAAO,EACP,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAExB,aAAa;AACb,OAAO,EACL,WAAW,EACX,cAAc,EACd,cAAc,EACd,aAAa,EACb,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAEzB,SAAS;AACT,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEvD,QAAQ;AACR,OAAO,EACL,IAAI,EACJ,OAAO,EACP,SAAS,EACT,SAAS,EACT,aAAa,EACb,UAAU,EACV,QAAQ,EACR,OAAO,GACR,MAAM,YAAY,CAAC;AAEpB,cAAc;AACd,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAE1B,aAAa;AACb,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,WAAW;AACX,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,SAAS,EACT,cAAc,GACf,MAAM,SAAS,CAAC;AAEjB,aAAa;AACb,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAErF,+BAA+B;AAC/B,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/D,oBAAoB;AACpB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAErB,UAAU;AACV,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE5E,WAAW;AACX,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,UAAU;AACV,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAG7D,aAAa;AACb,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEhF,QAAQ;AACR,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1C,gBAAgB;AAChB,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAGtF,WAAW;AACX,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
@@ -9,6 +9,7 @@ export declare function dotProduct(a: Float32Array, b: Float32Array): number;
9
9
  export declare function buildFtsQuery(query: string): string | null;
10
10
  export declare function recencyBoost(createdAt: string, category: string, decayDays?: number): number;
11
11
  export declare function recallBoost(recallCount: number, lastRecalledAt: string | null): number;
12
+ export declare function kindBoost(kind: string | null | undefined): number;
12
13
  export declare function buildFilterClauses({ categoryFilter, excludeEvents, since, until, includeSuperseeded, includeEphemeral, }: {
13
14
  categoryFilter?: string | null;
14
15
  excludeEvents?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"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"}