pmem-ai 0.7.6 → 0.8.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 (55) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +6 -4
  3. package/dist/commands/ask.d.ts +5 -1
  4. package/dist/commands/ask.d.ts.map +1 -1
  5. package/dist/commands/ask.js +48 -240
  6. package/dist/commands/ask.js.map +1 -1
  7. package/dist/commands/rebuild.d.ts.map +1 -1
  8. package/dist/commands/rebuild.js +74 -10
  9. package/dist/commands/rebuild.js.map +1 -1
  10. package/dist/commands/recall.d.ts +1 -0
  11. package/dist/commands/recall.d.ts.map +1 -1
  12. package/dist/commands/recall.js +1 -1
  13. package/dist/commands/recall.js.map +1 -1
  14. package/dist/commands/verify.d.ts.map +1 -1
  15. package/dist/commands/verify.js +30 -1
  16. package/dist/commands/verify.js.map +1 -1
  17. package/dist/core/db.d.ts +13 -0
  18. package/dist/core/db.d.ts.map +1 -1
  19. package/dist/core/db.js +36 -0
  20. package/dist/core/db.js.map +1 -1
  21. package/dist/core/format.d.ts.map +1 -1
  22. package/dist/core/format.js +37 -0
  23. package/dist/core/format.js.map +1 -1
  24. package/dist/core/query/ask.d.ts +14 -3
  25. package/dist/core/query/ask.d.ts.map +1 -1
  26. package/dist/core/query/ask.js +60 -200
  27. package/dist/core/query/ask.js.map +1 -1
  28. package/dist/core/query/context.d.ts.map +1 -1
  29. package/dist/core/query/context.js +8 -2
  30. package/dist/core/query/context.js.map +1 -1
  31. package/dist/core/query/engine/candidates.d.ts +11 -0
  32. package/dist/core/query/engine/candidates.d.ts.map +1 -0
  33. package/dist/core/query/engine/candidates.js +207 -0
  34. package/dist/core/query/engine/candidates.js.map +1 -0
  35. package/dist/core/query/engine/intent.d.ts +14 -0
  36. package/dist/core/query/engine/intent.d.ts.map +1 -0
  37. package/dist/core/query/engine/intent.js +53 -0
  38. package/dist/core/query/engine/intent.js.map +1 -0
  39. package/dist/core/query/engine/pack.d.ts +33 -0
  40. package/dist/core/query/engine/pack.d.ts.map +1 -0
  41. package/dist/core/query/engine/pack.js +92 -0
  42. package/dist/core/query/engine/pack.js.map +1 -0
  43. package/dist/core/query/engine/scoring.d.ts +50 -0
  44. package/dist/core/query/engine/scoring.d.ts.map +1 -0
  45. package/dist/core/query/engine/scoring.js +132 -0
  46. package/dist/core/query/engine/scoring.js.map +1 -0
  47. package/dist/index.js +15 -3
  48. package/dist/index.js.map +1 -1
  49. package/dist/mcp/server.js +2 -2
  50. package/dist/mcp/server.js.map +1 -1
  51. package/dist/types.d.ts +3 -0
  52. package/dist/types.d.ts.map +1 -1
  53. package/docs/v0.8 pre-design.md +203 -0
  54. package/package.json +2 -2
  55. package/skills/pmem/SKILL.md +4 -2
package/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  All notable changes to pmem are documented here.
4
4
 
5
+ ## v0.7.6-a — Stale Card Cleanup & missing_card_file Fix (2026-06-29)
6
+
7
+ ### Fixed
8
+
9
+ - **`missing_card_file` rebuild dead loop (#12)**: `pmem verify` previously reported `missing_card_file` and suggested `pmem rebuild`, but incremental rebuild only processed existing `.md` files on disk and never cleaned up DB rows for deleted cards — creating an unresolvable loop. Incremental rebuild now detects stale DB cards whose source files no longer exist, marks them `is_deleted = 1`, and cleans up their edges/aliases/tags/paths.
10
+ - **`deleteOrphanEdges` now runs unconditionally**: Previously only called during `--full` rebuild; now runs in all rebuild modes since stale card cleanup can create new orphan edges in incremental mode.
11
+ - **`--fix` / `--fix-stale` directly handle `missing_card_file`**: Before calling rebuild, these options now directly remove stale card rows from the database, providing an immediate repair path without waiting for index rebuild.
12
+
13
+ ### Changed
14
+
15
+ - **Verify fix hint updated**: `missing_card_file` now suggests `"pmem rebuild (incremental rebuild will clean up stale card references)"` instead of just `"pmem rebuild"`.
16
+ - **`card_id` added to `missing_card_file` verify issues**: Enables direct DB cleanup by `--fix` / `--fix-stale`.
17
+ - **Rebuild summary reports cleaned stale cards**: `"Cleaned N stale card(s) (source files deleted)"` when applicable.
18
+
5
19
  ## v0.7.6 — Agent Contract & Write-Path Integrity (2026-06-28)
6
20
 
7
21
  ### Added
package/README.md CHANGED
@@ -215,16 +215,18 @@ Do not edit SQLite directly. Edit Markdown cards or use pmem workflow commands,
215
215
 
216
216
  ### Recall And Ask
217
217
 
218
- Use `recall` for the current project state:
218
+ Use `recall` for the current project state. v0.8 (upcoming on `main` branch, not yet released to npm) adds budget modes: `brief` returns L0 + read-if-needed paths, `normal` is the default agent context, and `deep` preserves more detail when budget allows.
219
219
 
220
220
  ```bash
221
221
  pmem recall --budget 2000
222
+ pmem recall --mode brief --budget 500
222
223
  ```
223
224
 
224
- Use `ask` for targeted retrieval:
225
+ Use `ask` for targeted retrieval. v0.8 (upcoming on `main` branch, not yet released to npm) uses the Hybrid Recall Engine: exact IDs, aliases, tags, source file paths, always-on FTS5/BM25, graph expansion, recency, and stale/dirty penalties are fused into a deterministic score. Add `--explain` to see why each card was recalled.
225
226
 
226
227
  ```bash
227
228
  pmem ask "sqlite runtime" --format compact
229
+ pmem ask "src/core/query/recall.ts" --explain --limit 5
228
230
  pmem ask "release checklist" --format json
229
231
  ```
230
232
 
@@ -382,8 +384,8 @@ pmem init [project-name] [--guided] [--description <text>] [--stage <text>] [--n
382
384
  pmem context <task> [--budget N] [--format compact|json]
383
385
  pmem capture [--auto] [-s <summary>] [-n <next>] [--full] [--force]
384
386
 
385
- pmem recall [--budget N] [--format compact|json|paths|pack] [--since <duration>]
386
- pmem ask <query> [--format compact|json|paths|pack]
387
+ pmem recall [--budget N] [--mode brief|normal|deep] [--format compact|json|paths|pack] [--since <duration>]
388
+ pmem ask <query> [--format compact|json|paths|pack] [--explain] [--limit N]
387
389
  pmem discover [--dry-run] [--format compact|json] [--min-confidence <n>]
388
390
  [--lang auto|nodejs,python,rust,go,cpp,java]
389
391
  [--pattern-file <path>]
@@ -1,3 +1,7 @@
1
1
  import type { CliFormat } from '../types';
2
- export declare function askCommand(query: string, format?: CliFormat): void;
2
+ export interface AskCommandOptions {
3
+ explain?: boolean;
4
+ limit?: number;
5
+ }
6
+ export declare function askCommand(query: string, format?: CliFormat, options?: AskCommandOptions): void;
3
7
  //# sourceMappingURL=ask.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ask.d.ts","sourceRoot":"","sources":["../../src/commands/ask.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAoB,MAAM,UAAU,CAAC;AAyB5D,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,SAAqB,GAAG,IAAI,CA0S7E"}
1
+ {"version":3,"file":"ask.d.ts","sourceRoot":"","sources":["../../src/commands/ask.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAI1C,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,SAAqB,EAAE,OAAO,GAAE,iBAAsB,GAAG,IAAI,CAkF9G"}
@@ -36,11 +36,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.askCommand = askCommand;
37
37
  const path = __importStar(require("path"));
38
38
  const fs_1 = require("../core/fs");
39
- const db_1 = require("../core/db");
40
39
  const format_1 = require("../core/format");
41
- const manifest_1 = require("../core/manifest");
40
+ const ask_1 = require("../core/query/ask");
42
41
  const PMEM_DIR = '.pmem';
43
- function askCommand(query, format = 'compact') {
42
+ function askCommand(query, format = 'compact', options = {}) {
44
43
  const cwd = process.cwd();
45
44
  const pmemPath = path.join(cwd, PMEM_DIR);
46
45
  const dbPath = path.join(pmemPath, 'pmem.db');
@@ -52,222 +51,30 @@ function askCommand(query, format = 'compact') {
52
51
  console.log('No SQLite database found. Run `pmem rebuild` first.');
53
52
  return;
54
53
  }
55
- let db;
54
+ let result;
56
55
  try {
57
- db = (0, db_1.openDatabase)(pmemPath);
58
- (0, db_1.createSchema)(db);
56
+ result = (0, ask_1.askQuery)(pmemPath, query, {
57
+ explain: options.explain,
58
+ limit: options.limit,
59
+ });
59
60
  }
60
61
  catch (err) {
61
62
  if (err?.message?.includes('not a valid SQLite database')) {
62
63
  console.log(err.message);
63
64
  return;
64
65
  }
65
- console.log(`Failed to open database: ${err?.message || err}`);
66
+ console.log(`Ask query failed: ${err?.message || err}`);
66
67
  console.log('Run `pmem rebuild --full` to rebuild the database.');
67
68
  return;
68
69
  }
69
- const normalizedQuery = query.toLowerCase().trim();
70
- const queryTokens = tokenize(normalizedQuery);
71
- const matches = [];
72
- const seenIds = new Set();
73
- // Step 1: Exact match — card ID
74
- const idMatches = db.prepare("SELECT * FROM cards WHERE (id = ? OR id LIKE ?) AND is_deleted = 0").all(normalizedQuery, `%${normalizedQuery}%`);
75
- for (const card of idMatches) {
76
- if (seenIds.has(card.id))
77
- continue;
78
- seenIds.add(card.id);
79
- matches.push({
80
- id: card.id,
81
- title: card.title,
82
- match_type: card.id === normalizedQuery ? 'exact_id' : 'exact_title',
83
- confidence: card.id === normalizedQuery ? 0.95 : 0.85,
84
- graph_distance: 0,
85
- file: card.file_path,
86
- });
87
- }
88
- // Step 2: Exact match — aliases
89
- const aliasMatches = db.prepare(`SELECT c.* FROM cards c
90
- JOIN aliases a ON c.id = a.card_id
91
- WHERE (a.normalized_alias = ? OR a.normalized_alias LIKE ?)
92
- AND c.is_deleted = 0`).all(normalizedQuery, `%${normalizedQuery}%`);
93
- for (const card of aliasMatches) {
94
- if (seenIds.has(card.id))
95
- continue;
96
- seenIds.add(card.id);
97
- matches.push({
98
- id: card.id,
99
- title: card.title,
100
- match_type: 'alias',
101
- confidence: 0.9,
102
- graph_distance: 0,
103
- file: card.file_path,
104
- });
105
- }
106
- // Step 3: Exact match — tags
107
- const tagMatches = db.prepare(`SELECT c.* FROM cards c
108
- JOIN tags t ON c.id = t.card_id
109
- WHERE t.normalized_tag = ?
110
- AND c.is_deleted = 0`).all(normalizedQuery);
111
- for (const card of tagMatches) {
112
- if (seenIds.has(card.id))
113
- continue;
114
- seenIds.add(card.id);
115
- matches.push({
116
- id: card.id,
117
- title: card.title,
118
- match_type: 'tag',
119
- confidence: 0.7,
120
- graph_distance: 0,
121
- file: card.file_path,
122
- });
123
- }
124
- // Also try tag matching with individual query tokens
125
- for (const token of queryTokens) {
126
- const tokenTagMatches = db.prepare(`SELECT c.* FROM cards c
127
- JOIN tags t ON c.id = t.card_id
128
- WHERE t.normalized_tag LIKE ?
129
- AND c.is_deleted = 0`).all(`%${token}%`);
130
- for (const card of tokenTagMatches) {
131
- if (seenIds.has(card.id))
132
- continue;
133
- seenIds.add(card.id);
134
- matches.push({
135
- id: card.id,
136
- title: card.title,
137
- match_type: 'tag',
138
- confidence: 0.6,
139
- graph_distance: 0,
140
- file: card.file_path,
141
- });
142
- }
143
- }
144
- // Step 4: Graph expansion — 1-hop neighbors from matched cards
145
- const matchedIdsAtThisPoint = new Set(matches.map(m => m.id));
146
- for (const match of matches) {
147
- const edges = db.prepare("SELECT * FROM edges WHERE from_id = ? OR to_id = ?").all(match.id, match.id);
148
- for (const edge of edges) {
149
- const neighborId = edge.from_id === match.id ? edge.to_id : edge.from_id;
150
- if (matchedIdsAtThisPoint.has(neighborId) || seenIds.has(neighborId))
151
- continue;
152
- seenIds.add(neighborId);
153
- const neighborCard = db.prepare("SELECT * FROM cards WHERE id = ? AND is_deleted = 0").get(neighborId);
154
- if (neighborCard) {
155
- matches.push({
156
- id: neighborCard.id,
157
- title: neighborCard.title,
158
- match_type: 'graph_expansion',
159
- confidence: 0.6,
160
- graph_distance: 1,
161
- file: neighborCard.file_path,
162
- edge_type: edge.type,
163
- from_card: match.id,
164
- });
165
- }
166
- }
167
- }
168
- // Step 5: Keyword fallback — FTS5 if available, else LIKE
169
- if (matches.filter(m => m.match_type !== 'graph_expansion').length === 0) {
170
- // Filter out expansions for the "no direct matches" check
171
- const directMatchesBeforeFallback = matches.filter(m => m.match_type !== 'graph_expansion');
172
- if (directMatchesBeforeFallback.length === 0) {
173
- if ((0, db_1.hasFTS5)(db)) {
174
- try {
175
- const ftsResults = db.prepare("SELECT c.*, rank FROM card_fts JOIN cards c ON card_fts.card_id = c.id WHERE card_fts MATCH ? AND c.is_deleted = 0 ORDER BY rank").all(normalizedQuery);
176
- for (const row of ftsResults) {
177
- if (seenIds.has(row.id))
178
- continue;
179
- seenIds.add(row.id);
180
- matches.push({
181
- id: row.id,
182
- title: row.title,
183
- match_type: 'keyword_fallback',
184
- confidence: Math.min(0.5, 1 / (1 + (row.rank || 1))),
185
- graph_distance: 0,
186
- file: row.file_path,
187
- });
188
- }
189
- }
190
- catch {
191
- // FTS5 query failed, fall through to LIKE fallback
192
- }
193
- }
194
- // LIKE fallback (used if FTS5 unavailable or FTS5 returned no results)
195
- if (matches.filter(m => m.match_type === 'keyword_fallback').length === 0) {
196
- const likePattern = `%${normalizedQuery}%`;
197
- const likeResults = db.prepare("SELECT * FROM cards WHERE (title LIKE ? OR summary LIKE ?) AND is_deleted = 0").all(likePattern, likePattern);
198
- for (const card of likeResults) {
199
- if (seenIds.has(card.id))
200
- continue;
201
- seenIds.add(card.id);
202
- // Simple relevance: count token overlap in title
203
- const titleLower = card.title.toLowerCase();
204
- const tokenOverlap = queryTokens.filter(t => titleLower.includes(t)).length;
205
- matches.push({
206
- id: card.id,
207
- title: card.title,
208
- match_type: 'keyword_fallback',
209
- confidence: Math.min(0.5, tokenOverlap / Math.max(1, queryTokens.length)),
210
- graph_distance: 0,
211
- file: card.file_path,
212
- });
213
- }
214
- }
215
- }
216
- }
217
- // Step 6: Rerank
218
- const typeOrder = {
219
- exact_id: 5,
220
- exact_title: 4,
221
- alias: 3,
222
- tag: 2,
223
- graph_expansion: 1,
224
- keyword_fallback: 0,
225
- };
226
- matches.sort((a, b) => {
227
- return ((typeOrder[b.match_type] - typeOrder[a.match_type]) ||
228
- (b.confidence - a.confidence) ||
229
- (a.graph_distance - b.graph_distance));
230
- });
231
- // Step 7: Deduplicate (keep first/highest-ranked match per id)
232
- const dedupedIds = new Set();
233
- const deduped = [];
234
- for (const m of matches) {
235
- if (dedupedIds.has(m.id))
236
- continue;
237
- dedupedIds.add(m.id);
238
- deduped.push(m);
239
- }
240
- // Build recommended_files and evidence_paths
241
- const recommendedFiles = [];
242
- for (const m of deduped.slice(0, 8)) {
243
- recommendedFiles.push(m.file);
244
- }
245
- const manifest = (0, manifest_1.loadManifest)(pmemPath);
246
- const config = manifest ? (0, manifest_1.resolveConfig)(manifest) : { evidence_types: ['decision', 'trace'] };
247
- const evidenceTypes = config.evidence_types;
248
- const evidencePaths = [];
249
- for (const m of deduped) {
250
- const card = db.prepare("SELECT type, file_path FROM cards WHERE id = ? AND is_deleted = 0").get(m.id);
251
- if (card && evidenceTypes.includes(card.type)) {
252
- evidencePaths.push(card.file_path);
253
- }
254
- }
255
- const result = {
256
- query,
257
- matched: deduped,
258
- recommended_files: recommendedFiles,
259
- evidence_paths: evidencePaths,
260
- };
261
- // Build guidance for empty results
262
- const askMessage = deduped.length > 0
263
- ? `Found ${deduped.length} match(es).`
70
+ const askMessage = result.matched.length > 0
71
+ ? `Found ${result.matched.length} match(es).`
264
72
  : 'No matching memory cards found.';
265
- const askNextSteps = deduped.length > 0 ? [] : [
73
+ const askNextSteps = result.matched.length > 0 ? [] : [
266
74
  'Try a different query keyword',
267
75
  'Run `pmem recall` for full project context',
268
76
  'Check that cards have relevant aliases and tags',
269
77
  ];
270
- // Output
271
78
  if (format === 'json') {
272
79
  console.log(JSON.stringify({
273
80
  ...result,
@@ -275,46 +82,47 @@ function askCommand(query, format = 'compact') {
275
82
  next_steps: askNextSteps,
276
83
  }, null, 2));
277
84
  }
278
- else {
279
- // Adapt to formatOutput's expected shape
280
- const formatCompat = {
281
- query: result.query,
282
- matched: result.matched.map(m => ({
283
- id: m.id,
284
- title: m.title,
285
- matchType: m.match_type,
286
- match_type: m.match_type,
287
- confidence: m.confidence,
288
- graphDistance: m.graph_distance,
289
- graph_distance: m.graph_distance,
290
- file: m.file,
291
- edgeType: m.edge_type,
292
- edge_type: m.edge_type,
293
- fromCard: m.from_card,
294
- })),
295
- recommended_files: result.recommended_files,
296
- evidencePaths: result.evidence_paths,
297
- };
298
- console.log((0, format_1.formatOutput)(formatCompat, format, 2000));
85
+ else if (format === 'paths' || format === 'pack') {
86
+ console.log((0, format_1.formatOutput)(result, format, 2000));
299
87
  }
300
- }
301
- function tokenize(text) {
302
- const tokens = [];
303
- const words = text.split(/[\s,,。、;;::!!??()()\[\]【】{}]+/);
304
- for (const word of words) {
305
- if (word.length === 0)
306
- continue;
307
- if (/[一-鿿]/.test(word)) {
308
- const cjkChars = word.match(/[一-鿿]/g) || [];
309
- tokens.push(...cjkChars);
310
- const nonCjk = word.replace(/[一-鿿]/g, '').trim();
311
- if (nonCjk)
312
- tokens.push(nonCjk.toLowerCase());
88
+ else {
89
+ const lines = [`Query: ${result.query}`, ''];
90
+ if (result.matched.length === 0) {
91
+ lines.push('No matching memory cards found.');
92
+ lines.push('');
93
+ for (const step of askNextSteps)
94
+ lines.push(` - ${step}`);
313
95
  }
314
96
  else {
315
- tokens.push(word.toLowerCase());
97
+ lines.push('Matched:');
98
+ for (const m of result.matched) {
99
+ const score = m.score !== undefined ? ` (${m.score})` : '';
100
+ const stale = m.stale ? ' ⚠stale' : '';
101
+ let annotation = '';
102
+ if (options.explain && m.reasons && m.reasons.length > 0) {
103
+ const parts = m.reasons.map(r => `${r.channel}:${r.detail}`);
104
+ annotation = ` [${parts.join('; ')}]`;
105
+ }
106
+ else {
107
+ const via = m.match_type === 'graph_expansion' && m.from_card
108
+ ? `via ${m.from_card}`
109
+ : m.match_type;
110
+ annotation = ` [${via}]`;
111
+ }
112
+ lines.push(` - ${m.id}${score}${annotation}${stale}: "${m.title}"`);
113
+ }
114
+ lines.push('');
115
+ lines.push('Recommended:');
116
+ for (const f of result.recommended_files)
117
+ lines.push(` ${f}`);
118
+ if (result.evidence_paths.length > 0) {
119
+ lines.push('');
120
+ lines.push('Evidence:');
121
+ for (const f of result.evidence_paths.slice(0, 8))
122
+ lines.push(` ${f}`);
123
+ }
316
124
  }
125
+ console.log(lines.join('\n'));
317
126
  }
318
- return [...new Set(tokens)];
319
127
  }
320
128
  //# sourceMappingURL=ask.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ask.js","sourceRoot":"","sources":["../../src/commands/ask.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ask.js","sourceRoot":"","sources":["../../src/commands/ask.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"rebuild.d.ts","sourceRoot":"","sources":["../../src/commands/rebuild.ts"],"names":[],"mappings":"AAWA,UAAU,cAAc;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AASD,wBAAgB,cAAc,CAAC,OAAO,GAAE,cAAmB,GAAG,IAAI,CAYjE;AAmfD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ3D"}
1
+ {"version":3,"file":"rebuild.d.ts","sourceRoot":"","sources":["../../src/commands/rebuild.ts"],"names":[],"mappings":"AAWA,UAAU,cAAc;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AASD,wBAAgB,cAAc,CAAC,OAAO,GAAE,cAAmB,GAAG,IAAI,CAYjE;AAqjBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ3D"}
@@ -136,6 +136,11 @@ function rebuildLocked(pmemPath, options) {
136
136
  let skipped = 0;
137
137
  let updated = 0;
138
138
  let snappedEdges = [];
139
+ // v0.8: FTS rows collected during the card loop, written after createFTS5.
140
+ // For skipped (hash-match) cards we still collect so a missing FTS row can
141
+ // be backfilled — the card_fts table did not exist before v0.8.
142
+ const ftsRows = [];
143
+ const ftsSkippedIds = [];
139
144
  // Pre-scan all card IDs for wikilink validation (so [[card-id]] refs
140
145
  // resolve even when the target card hasn't been processed yet)
141
146
  const validCardIds = new Set();
@@ -201,6 +206,17 @@ function rebuildLocked(pmemPath, options) {
201
206
  if (card && !card.updated_at) {
202
207
  db.prepare('UPDATE cards SET updated_at = ? WHERE file_path = ?').run(resolveUpdatedAt(fm.updated, file), relPath);
203
208
  }
209
+ // v0.8 FTS backfill: card content unchanged, but its FTS row may
210
+ // not exist yet (table introduced in v0.8). Collect for backfill.
211
+ ftsRows.push({
212
+ id: fm.id,
213
+ title,
214
+ summary: extractCardSummary(fm, parsed.bodyText),
215
+ body: parsed.bodyText,
216
+ aliases: fm.aliases ?? [],
217
+ tags: fm.tags ?? [],
218
+ });
219
+ ftsSkippedIds.push(fm.id);
204
220
  skipped++;
205
221
  continue;
206
222
  }
@@ -232,6 +248,14 @@ function rebuildLocked(pmemPath, options) {
232
248
  is_candidate: isCandidate,
233
249
  };
234
250
  (0, db_1.upsertCard)(db, cardRow);
251
+ ftsRows.push({
252
+ id: fm.id,
253
+ title,
254
+ summary: cardRow.summary,
255
+ body: parsed.bodyText,
256
+ aliases: fm.aliases ?? [],
257
+ tags: fm.tags ?? [],
258
+ });
235
259
  // Clear existing explicit, mention, and inferred relations before
236
260
  // re-inserting from the current frontmatter. v0.7.3 (issue #6):
237
261
  // inferred edges (e.g. task→module next_step_of) must also be
@@ -331,17 +355,39 @@ function rebuildLocked(pmemPath, options) {
331
355
  });
332
356
  // Execute all SQLite writes in a single transaction
333
357
  doRebuild();
334
- // v0.7.3 (issue #6): prune orphan edges after a --full rebuild.
335
- // The rebuild loop inserts explicit edges (depends_on, related) from
336
- // each card's current frontmatter without checking that the target
337
- // card still has a file. If a target card was deleted but the
338
- // declaring card's frontmatter still names it (or a card was just
339
- // renamed and the caller hasn't yet propagated the rename), those
340
- // edges would otherwise dangle and trip `pmem verify`'s
341
- // orphan_edges / too_many_relations checks.
342
- if (isFull) {
343
- (0, db_1.deleteOrphanEdges)(db);
358
+ // v0.7.6-a (issue #12): clean up stale DB cards whose source .md files
359
+ // have been deleted from disk. The rebuild loop only processes files
360
+ // that exist it never removes DB rows for deleted files — so an
361
+ // incremental rebuild would otherwise dead-loop on `missing_card_file`
362
+ // verify warnings with no way to resolve them short of `--full`.
363
+ //
364
+ // Wrapped in a transaction so a crash mid-cleanup leaves the DB in a
365
+ // consistent state (all-or-nothing per stale card batch).
366
+ let cleanedStaleCards = 0;
367
+ {
368
+ const cleanupTx = db.transaction(() => {
369
+ const staleCards = db.prepare("SELECT id, file_path FROM cards WHERE is_deleted = 0").all();
370
+ for (const card of staleCards) {
371
+ const absPath = path.join(cwd, card.file_path);
372
+ if (!(0, fs_1.fileExists)(absPath)) {
373
+ db.prepare("UPDATE cards SET is_deleted = 1 WHERE id = ?").run(card.id);
374
+ // Bidirectional edge cleanup — covers both outgoing and incoming edges
375
+ // for the deleted card, matching the verify.ts cleanupMissingCards pattern.
376
+ db.prepare("DELETE FROM edges WHERE from_id = ? OR to_id = ?").run(card.id, card.id);
377
+ (0, db_1.deleteCardAliases)(db, card.id);
378
+ (0, db_1.deleteCardTags)(db, card.id);
379
+ (0, db_1.deleteCardPaths)(db, card.id);
380
+ (0, db_1.deleteCardFts)(db, card.id);
381
+ cleanedStaleCards++;
382
+ }
383
+ }
384
+ });
385
+ cleanupTx();
344
386
  }
387
+ // v0.7.3 (issue #6): prune orphan edges after rebuild.
388
+ // v0.7.7 (issue #12): run unconditionally — stale card cleanup above
389
+ // can create new orphan edges even in incremental mode.
390
+ (0, db_1.deleteOrphanEdges)(db);
345
391
  // v0.7.0-a (revised in v0.7.3, issue #6): restore edges that the
346
392
  // rebuild loop did not and could not have re-derived. We now
347
393
  // restrict restoration to:
@@ -397,6 +443,21 @@ function rebuildLocked(pmemPath, options) {
397
443
  }
398
444
  // Create FTS5 virtual table for full-text search (outside transaction)
399
445
  (0, db_1.createFTS5)(db);
446
+ // v0.8: populate FTS index. Updated cards always refresh; skipped cards
447
+ // only backfill when their FTS row is missing. Full rebuild starts clean.
448
+ {
449
+ const ftsSkipped = new Set(ftsSkippedIds);
450
+ const ftsTx = db.transaction(() => {
451
+ if (isFull)
452
+ (0, db_1.clearCardFts)(db);
453
+ for (const row of ftsRows) {
454
+ if (!isFull && ftsSkipped.has(row.id) && (0, db_1.cardFtsRowExists)(db, row.id))
455
+ continue;
456
+ (0, db_1.refreshCardFts)(db, row);
457
+ }
458
+ });
459
+ ftsTx();
460
+ }
400
461
  // Write legacy graph.json for backward compatibility
401
462
  const allContent = cardFiles.map(f => (0, fs_1.readFile)(f) || '').join('');
402
463
  const sourceHash = (0, hash_1.computeHash)(allContent);
@@ -433,6 +494,9 @@ function rebuildLocked(pmemPath, options) {
433
494
  const dbEdgeCount = db.prepare("SELECT COUNT(*) as cnt FROM edges").get().cnt;
434
495
  console.log(`${modeLabel}: ${processed} cards processed, ${skipped} skipped (hash match), ${updated} updated`);
435
496
  console.log(`Graph: ${nodes.length} nodes, ${dbEdgeCount} edges`);
497
+ if (cleanedStaleCards > 0) {
498
+ console.log(`Cleaned ${cleanedStaleCards} stale card(s) (source files deleted)`);
499
+ }
436
500
  (0, db_1.closeDatabase)();
437
501
  }
438
502
  /**