pmem-ai 0.5.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.
- package/CHANGELOG.md +57 -0
- package/LICENSE +21 -0
- package/README.md +349 -0
- package/dist/commands/ask.d.ts +3 -0
- package/dist/commands/ask.d.ts.map +1 -0
- package/dist/commands/ask.js +303 -0
- package/dist/commands/ask.js.map +1 -0
- package/dist/commands/distill.d.ts +6 -0
- package/dist/commands/distill.d.ts.map +1 -0
- package/dist/commands/distill.js +425 -0
- package/dist/commands/distill.js.map +1 -0
- package/dist/commands/graph.d.ts +6 -0
- package/dist/commands/graph.d.ts.map +1 -0
- package/dist/commands/graph.js +216 -0
- package/dist/commands/graph.js.map +1 -0
- package/dist/commands/init.d.ts +5 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +566 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/integration.d.ts +2 -0
- package/dist/commands/integration.d.ts.map +1 -0
- package/dist/commands/integration.js +216 -0
- package/dist/commands/integration.js.map +1 -0
- package/dist/commands/migrate.d.ts +6 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +379 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/rebuild.d.ts +8 -0
- package/dist/commands/rebuild.d.ts.map +1 -0
- package/dist/commands/rebuild.js +299 -0
- package/dist/commands/rebuild.js.map +1 -0
- package/dist/commands/recall.d.ts +3 -0
- package/dist/commands/recall.d.ts.map +1 -0
- package/dist/commands/recall.js +140 -0
- package/dist/commands/recall.js.map +1 -0
- package/dist/commands/session.d.ts +3 -0
- package/dist/commands/session.d.ts.map +1 -0
- package/dist/commands/session.js +147 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/commands/status.d.ts +5 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +275 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/update.d.ts +14 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +536 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/verify.d.ts +4 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +296 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/core/db.d.ts +47 -0
- package/dist/core/db.d.ts.map +1 -0
- package/dist/core/db.js +326 -0
- package/dist/core/db.js.map +1 -0
- package/dist/core/format.d.ts +3 -0
- package/dist/core/format.d.ts.map +1 -0
- package/dist/core/format.js +221 -0
- package/dist/core/format.js.map +1 -0
- package/dist/core/fs.d.ts +16 -0
- package/dist/core/fs.d.ts.map +1 -0
- package/dist/core/fs.js +175 -0
- package/dist/core/fs.js.map +1 -0
- package/dist/core/git.d.ts +6 -0
- package/dist/core/git.d.ts.map +1 -0
- package/dist/core/git.js +20 -0
- package/dist/core/git.js.map +1 -0
- package/dist/core/hash.d.ts +10 -0
- package/dist/core/hash.d.ts.map +1 -0
- package/dist/core/hash.js +25 -0
- package/dist/core/hash.js.map +1 -0
- package/dist/core/manifest.d.ts +6 -0
- package/dist/core/manifest.d.ts.map +1 -0
- package/dist/core/manifest.js +207 -0
- package/dist/core/manifest.js.map +1 -0
- package/dist/core/yaml.d.ts +11 -0
- package/dist/core/yaml.d.ts.map +1 -0
- package/dist/core/yaml.js +94 -0
- package/dist/core/yaml.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +167 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +351 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/docs/Voorlopige projekidee.md +695 -0
- package/docs/handover-v0.3.md +355 -0
- package/docs/handover-v0.4.md +367 -0
- package/docs/prd.md +318 -0
- package/docs/project-roadmap.md +279 -0
- package/docs/release-checklist-v0.5.md +109 -0
- package/docs/v0.2 pre-design.md +182 -0
- package/docs/v0.2 pre-roadmap.md +270 -0
- package/docs/v0.3 pre-design.md +686 -0
- package/docs/v0.4 pre-design.md +417 -0
- package/docs/v0.5 pre-design.md +481 -0
- package/package.json +67 -0
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.distillCommand = distillCommand;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const manifest_1 = require("../core/manifest");
|
|
39
|
+
const fs_1 = require("../core/fs");
|
|
40
|
+
const db_1 = require("../core/db");
|
|
41
|
+
const PMEM_DIR = '.pmem';
|
|
42
|
+
function distillCommand(options) {
|
|
43
|
+
const cwd = process.cwd();
|
|
44
|
+
const pmemPath = path.join(cwd, PMEM_DIR);
|
|
45
|
+
const manifest = (0, manifest_1.loadManifest)(pmemPath);
|
|
46
|
+
if (!manifest) {
|
|
47
|
+
console.log('No .pmem/manifest.yml found. Run `pmem init` first.');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
// Eagerly open DB if it exists, so downstream helpers can use getDatabase()
|
|
51
|
+
const dbPath = path.join(pmemPath, 'pmem.db');
|
|
52
|
+
if ((0, fs_1.fileExists)(dbPath)) {
|
|
53
|
+
try {
|
|
54
|
+
(0, db_1.openDatabase)(pmemPath);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// DB exists but can't be opened — will fall back to file scanning
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (options.applySuggestion) {
|
|
61
|
+
applySuggestionAction(pmemPath, options.applySuggestion);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (options.suggestSplits) {
|
|
65
|
+
suggestCardSplits(pmemPath, manifest);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const traceFiles = (0, fs_1.listFiles)(path.join(pmemPath, 'traces'), /\.md$/);
|
|
69
|
+
if (traceFiles.length === 0) {
|
|
70
|
+
console.log('No trace files found to distill.');
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
// Parse all traces
|
|
74
|
+
const traces = [];
|
|
75
|
+
for (const file of traceFiles) {
|
|
76
|
+
const card = parseCard(file);
|
|
77
|
+
if (card && !isDistilled(card.frontmatter)) {
|
|
78
|
+
traces.push(card);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const undistilledCount = traces.length;
|
|
82
|
+
if (undistilledCount === 0) {
|
|
83
|
+
console.log('All traces are already distilled.');
|
|
84
|
+
process.exit(0);
|
|
85
|
+
}
|
|
86
|
+
// Group by related node (DB-backed if available, frontmatter fallback otherwise)
|
|
87
|
+
const groups = groupTracesByRelated(traces);
|
|
88
|
+
console.log(`Found ${undistilledCount} undistilled trace(s) in ${groups.length} group(s).\n`);
|
|
89
|
+
if (options.confirm) {
|
|
90
|
+
applyDistillation(pmemPath, groups);
|
|
91
|
+
// Mark traces as distilled
|
|
92
|
+
markTracesDistilled(traceFiles, traces);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// Dry-run: show suggestions
|
|
96
|
+
for (const group of groups) {
|
|
97
|
+
console.log(`## Target: ${group.relatedNode}`);
|
|
98
|
+
console.log(` Traces: ${group.traces.length}`);
|
|
99
|
+
console.log(` Suggested update:`);
|
|
100
|
+
console.log(`${group.suggestedUpdate.split('\n').map(l => ' ' + l).join('\n')}`);
|
|
101
|
+
console.log('');
|
|
102
|
+
}
|
|
103
|
+
console.log('Run with --confirm to apply these changes.');
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function applySuggestionAction(pmemPath, targetNodeId) {
|
|
108
|
+
const traceFiles = (0, fs_1.listFiles)(path.join(pmemPath, 'traces'), /\.md$/);
|
|
109
|
+
if (traceFiles.length === 0) {
|
|
110
|
+
console.log('No trace files found to distill.');
|
|
111
|
+
process.exit(2);
|
|
112
|
+
}
|
|
113
|
+
// Parse all traces
|
|
114
|
+
const traces = [];
|
|
115
|
+
for (const file of traceFiles) {
|
|
116
|
+
const card = parseCard(file);
|
|
117
|
+
if (card && !isDistilled(card.frontmatter)) {
|
|
118
|
+
traces.push(card);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (traces.length === 0) {
|
|
122
|
+
console.log('All traces are already distilled.');
|
|
123
|
+
process.exit(0);
|
|
124
|
+
}
|
|
125
|
+
// Group by related node (reuse existing function)
|
|
126
|
+
const groups = groupTracesByRelated(traces);
|
|
127
|
+
// Find the group matching targetNodeId
|
|
128
|
+
const matchingGroup = groups.find(g => g.relatedNode === targetNodeId);
|
|
129
|
+
if (!matchingGroup) {
|
|
130
|
+
console.log(`No undistilled traces found for target: ${targetNodeId}`);
|
|
131
|
+
console.log('Available targets: ' + groups.map(g => g.relatedNode).join(', '));
|
|
132
|
+
process.exit(2);
|
|
133
|
+
}
|
|
134
|
+
// Apply distillation for this group only
|
|
135
|
+
applyDistillation(pmemPath, [matchingGroup]);
|
|
136
|
+
markTracesDistilled(traceFiles, matchingGroup.traces);
|
|
137
|
+
console.log(`Applied distillation to ${targetNodeId}: ${matchingGroup.traces.length} trace(s) merged.`);
|
|
138
|
+
console.log('Run `pmem rebuild` to update indexes.');
|
|
139
|
+
process.exit(0);
|
|
140
|
+
}
|
|
141
|
+
function parseCard(filePath) {
|
|
142
|
+
const content = (0, fs_1.readFile)(filePath);
|
|
143
|
+
if (!content)
|
|
144
|
+
return null;
|
|
145
|
+
return parseFrontmatterAndBody(content, filePath);
|
|
146
|
+
}
|
|
147
|
+
function parseFrontmatterAndBody(content, filePath) {
|
|
148
|
+
if (!content.startsWith('---'))
|
|
149
|
+
return null;
|
|
150
|
+
const endIdx = content.indexOf('---', 4);
|
|
151
|
+
if (endIdx < 0)
|
|
152
|
+
return null;
|
|
153
|
+
const fmText = content.substring(4, endIdx);
|
|
154
|
+
const body = content.substring(endIdx + 3).trim();
|
|
155
|
+
const frontmatter = { id: '', type: 'trace' };
|
|
156
|
+
for (const line of fmText.split('\n')) {
|
|
157
|
+
const match = line.match(/^(\w+):\s*(.+)/);
|
|
158
|
+
if (match) {
|
|
159
|
+
const key = match[1];
|
|
160
|
+
let val = match[2].trim();
|
|
161
|
+
if (key === 'tags' && val.startsWith('[')) {
|
|
162
|
+
val = val.slice(1, -1).split(',').map((s) => s.trim());
|
|
163
|
+
}
|
|
164
|
+
if (key === 'related' && val.startsWith('[')) {
|
|
165
|
+
val = val.slice(1, -1).split(',').map((s) => s.trim());
|
|
166
|
+
}
|
|
167
|
+
frontmatter[key] = val;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return { frontmatter, body, filePath };
|
|
171
|
+
}
|
|
172
|
+
function isDistilled(fm) {
|
|
173
|
+
return fm.distilled === true || fm.distilled === 'true';
|
|
174
|
+
}
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
// groupTracesByRelated — DB-backed grouping via edges table, with fallback
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
function groupTracesByRelated(traces) {
|
|
179
|
+
const db = (0, db_1.getDatabase)();
|
|
180
|
+
if (db) {
|
|
181
|
+
try {
|
|
182
|
+
return groupTracesByRelatedDb(traces, db);
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
// DB query failed — fall back
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return groupTracesByRelatedFallback(traces);
|
|
189
|
+
}
|
|
190
|
+
function groupTracesByRelatedDb(traces, db) {
|
|
191
|
+
const map = new Map();
|
|
192
|
+
// For each trace, look up edges to find related module/decision/task/feature cards
|
|
193
|
+
const relatedStmt = db.prepare(`
|
|
194
|
+
SELECT e.to_id AS related_id FROM edges e
|
|
195
|
+
JOIN cards c ON e.to_id = c.id
|
|
196
|
+
WHERE e.from_id = ? AND c.type IN ('module', 'decision', 'task', 'feature') AND c.is_deleted = 0
|
|
197
|
+
UNION
|
|
198
|
+
SELECT e.from_id AS related_id FROM edges e
|
|
199
|
+
JOIN cards c ON e.from_id = c.id
|
|
200
|
+
WHERE e.to_id = ? AND c.type IN ('module', 'decision', 'task', 'feature') AND c.is_deleted = 0
|
|
201
|
+
`);
|
|
202
|
+
for (const trace of traces) {
|
|
203
|
+
const traceId = trace.frontmatter.id;
|
|
204
|
+
const edgeRows = relatedStmt.all(traceId, traceId);
|
|
205
|
+
const key = edgeRows.length > 0 ? edgeRows[0].related_id : 'project';
|
|
206
|
+
if (!map.has(key))
|
|
207
|
+
map.set(key, []);
|
|
208
|
+
map.get(key).push(trace);
|
|
209
|
+
}
|
|
210
|
+
return buildTraceGroups(map);
|
|
211
|
+
}
|
|
212
|
+
function groupTracesByRelatedFallback(traces) {
|
|
213
|
+
const map = new Map();
|
|
214
|
+
for (const trace of traces) {
|
|
215
|
+
const related = trace.frontmatter.related || [];
|
|
216
|
+
const key = related.length > 0 ? related[0] : 'project';
|
|
217
|
+
if (!map.has(key))
|
|
218
|
+
map.set(key, []);
|
|
219
|
+
map.get(key).push(trace);
|
|
220
|
+
}
|
|
221
|
+
return buildTraceGroups(map);
|
|
222
|
+
}
|
|
223
|
+
function buildTraceGroups(map) {
|
|
224
|
+
const groups = [];
|
|
225
|
+
for (const [node, nodeTraces] of map) {
|
|
226
|
+
const summaryParts = nodeTraces.map(t => {
|
|
227
|
+
const title = extractMarkdownTitle(t.body) || path.basename(t.filePath, '.md');
|
|
228
|
+
return `- ${title}`;
|
|
229
|
+
});
|
|
230
|
+
groups.push({
|
|
231
|
+
relatedNode: node,
|
|
232
|
+
traces: nodeTraces,
|
|
233
|
+
suggestedUpdate: `Add distilled insights from ${nodeTraces.length} trace(s):\n${summaryParts.join('\n')}`,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
return groups;
|
|
237
|
+
}
|
|
238
|
+
function extractMarkdownTitle(body) {
|
|
239
|
+
const match = body.match(/^#\s+(.+)/m);
|
|
240
|
+
return match ? match[1].trim() : null;
|
|
241
|
+
}
|
|
242
|
+
// ---------------------------------------------------------------------------
|
|
243
|
+
// findCardFile — DB-backed card lookup, with file-scanning fallback
|
|
244
|
+
// ---------------------------------------------------------------------------
|
|
245
|
+
function findCardFile(pmemPath, nodeId) {
|
|
246
|
+
const db = (0, db_1.getDatabase)();
|
|
247
|
+
if (db) {
|
|
248
|
+
try {
|
|
249
|
+
const row = db.prepare("SELECT file_path FROM cards WHERE id = ? AND is_deleted = 0").get(nodeId);
|
|
250
|
+
if (row)
|
|
251
|
+
return row.file_path;
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
// DB query failed — fall back
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
// Fall back to file scanning through modules/, features/, decisions/, tasks/
|
|
258
|
+
for (const dir of ['modules', 'features', 'decisions', 'tasks']) {
|
|
259
|
+
const dirPath = path.join(pmemPath, dir);
|
|
260
|
+
if (!(0, fs_1.fileExists)(dirPath))
|
|
261
|
+
continue;
|
|
262
|
+
const files = (0, fs_1.listFiles)(dirPath, /\.md$/);
|
|
263
|
+
for (const file of files) {
|
|
264
|
+
const content = (0, fs_1.readFile)(file);
|
|
265
|
+
if (content) {
|
|
266
|
+
const fmMatch = content.match(/^id:\s*(.+)$/m);
|
|
267
|
+
if (fmMatch && fmMatch[1].trim() === nodeId) {
|
|
268
|
+
return file;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
// ---------------------------------------------------------------------------
|
|
276
|
+
// applyDistillation / markTracesDistilled — unchanged core logic
|
|
277
|
+
// ---------------------------------------------------------------------------
|
|
278
|
+
function applyDistillation(pmemPath, groups) {
|
|
279
|
+
for (const group of groups) {
|
|
280
|
+
// Find the target card file
|
|
281
|
+
const cardPath = findCardFile(pmemPath, group.relatedNode);
|
|
282
|
+
if (!cardPath) {
|
|
283
|
+
console.log(` ⚠ Target card not found for ${group.relatedNode}, skipping.`);
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
const content = (0, fs_1.readFile)(cardPath);
|
|
287
|
+
if (!content)
|
|
288
|
+
continue;
|
|
289
|
+
// Append distilled content to the card
|
|
290
|
+
const distilledSection = `\n\n## Distilled from Traces (${new Date().toISOString().split('T')[0]})\n${group.suggestedUpdate.split('\n').map(l => '> ' + l.replace(/^- /, '• ')).join('\n')}\n`;
|
|
291
|
+
const updated = content.trimEnd() + distilledSection;
|
|
292
|
+
(0, fs_1.atomicWrite)(cardPath, updated);
|
|
293
|
+
console.log(` ✓ Updated ${group.relatedNode} (${cardPath})`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
function markTracesDistilled(allTraceFiles, allTraces) {
|
|
297
|
+
let marked = 0;
|
|
298
|
+
for (const file of allTraceFiles) {
|
|
299
|
+
const content = (0, fs_1.readFile)(file);
|
|
300
|
+
if (!content || !content.startsWith('---'))
|
|
301
|
+
continue;
|
|
302
|
+
// Check if this trace is in our undistilled set
|
|
303
|
+
const isUndistilled = allTraces.some(t => t.filePath === file);
|
|
304
|
+
if (!isUndistilled)
|
|
305
|
+
continue;
|
|
306
|
+
// Add distilled: true to frontmatter
|
|
307
|
+
const endIdx = content.indexOf('---', 4);
|
|
308
|
+
if (endIdx < 0)
|
|
309
|
+
continue;
|
|
310
|
+
const before = content.substring(0, endIdx);
|
|
311
|
+
let fmText = content.substring(4, endIdx);
|
|
312
|
+
const after = content.substring(endIdx);
|
|
313
|
+
if (!fmText.includes('distilled:')) {
|
|
314
|
+
fmText = fmText.trimEnd() + '\ndistilled: true';
|
|
315
|
+
const updated = '---' + fmText + after;
|
|
316
|
+
(0, fs_1.atomicWrite)(file, updated);
|
|
317
|
+
marked++;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
if (marked > 0) {
|
|
321
|
+
console.log(` ✓ Marked ${marked} trace(s) as distilled.`);
|
|
322
|
+
console.log(' Run `pmem rebuild` to update indexes.');
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
// ---------------------------------------------------------------------------
|
|
326
|
+
// suggestCardSplits — DB-backed token counts, file-reading fallback
|
|
327
|
+
// ---------------------------------------------------------------------------
|
|
328
|
+
function suggestCardSplits(pmemPath, manifest) {
|
|
329
|
+
if (!manifest?.card_policy) {
|
|
330
|
+
console.log('No card_policy defined in manifest.');
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
const policy = manifest.card_policy;
|
|
334
|
+
const suggestions = [];
|
|
335
|
+
const db = (0, db_1.getDatabase)();
|
|
336
|
+
if (db) {
|
|
337
|
+
try {
|
|
338
|
+
suggestCardSplitsDb(db, policy, suggestions);
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
// DB query failed — fall back to file scanning
|
|
342
|
+
suggestCardSplitsFallback(pmemPath, policy, suggestions);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
suggestCardSplitsFallback(pmemPath, policy, suggestions);
|
|
347
|
+
}
|
|
348
|
+
if (suggestions.length === 0) {
|
|
349
|
+
console.log('No oversized cards detected.');
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
console.log('Card Split Suggestions:\n');
|
|
353
|
+
for (const s of suggestions) {
|
|
354
|
+
console.log(`## ${s.cardId}`);
|
|
355
|
+
console.log(` File: ${s.cardFile}`);
|
|
356
|
+
console.log(` Tokens: ~${s.currentTokens} / max ${s.maxTokens}`);
|
|
357
|
+
console.log(` Suggested splits:`);
|
|
358
|
+
for (const split of s.suggestedSplits) {
|
|
359
|
+
console.log(` - ${s.cardId}.${toSlug(split)}`);
|
|
360
|
+
}
|
|
361
|
+
console.log('');
|
|
362
|
+
}
|
|
363
|
+
console.log('Review each card and split manually, or use a future `pmem split --interactive` command.');
|
|
364
|
+
}
|
|
365
|
+
function suggestCardSplitsDb(db, policy, suggestions) {
|
|
366
|
+
const rows = db.prepare(`
|
|
367
|
+
SELECT id, type, file_path, token_count FROM cards
|
|
368
|
+
WHERE is_deleted = 0
|
|
369
|
+
AND type != 'trace'
|
|
370
|
+
AND file_path NOT LIKE '%/traces/%'
|
|
371
|
+
AND file_path NOT LIKE '%/backups/%'
|
|
372
|
+
AND file_path NOT LIKE '%/indexes/%'
|
|
373
|
+
AND file_path NOT LIKE '%/integrations/%'
|
|
374
|
+
ORDER BY token_count DESC
|
|
375
|
+
`).all();
|
|
376
|
+
for (const row of rows) {
|
|
377
|
+
const maxForType = policy.max_tokens[row.type];
|
|
378
|
+
const currentTokens = row.token_count > 0 ? row.token_count : 0;
|
|
379
|
+
if (!maxForType || currentTokens <= maxForType)
|
|
380
|
+
continue;
|
|
381
|
+
// Still need to read the file for h2 section splitting suggestions
|
|
382
|
+
const content = (0, fs_1.readFile)(row.file_path);
|
|
383
|
+
const h2s = content ? content.match(/^##\s+(.+)$/gm) : null;
|
|
384
|
+
const splitNames = h2s ? h2s.slice(0, 4).map(h => h.replace(/^##\s+/, '').trim()) : [];
|
|
385
|
+
suggestions.push({
|
|
386
|
+
cardId: row.id,
|
|
387
|
+
cardFile: row.file_path,
|
|
388
|
+
currentTokens,
|
|
389
|
+
maxTokens: maxForType,
|
|
390
|
+
suggestedSplits: splitNames.length > 0 ? splitNames : ['(No H2 sections to suggest splits from)'],
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
function suggestCardSplitsFallback(pmemPath, policy, suggestions) {
|
|
395
|
+
// Scan all cards
|
|
396
|
+
const cardFiles = (0, fs_1.listFiles)(pmemPath, /\.md$/);
|
|
397
|
+
for (const file of cardFiles) {
|
|
398
|
+
if (file.includes('/traces/') || file.includes('/backups/') || file.includes('/indexes/') || file.includes('/integrations/'))
|
|
399
|
+
continue;
|
|
400
|
+
const content = (0, fs_1.readFile)(file);
|
|
401
|
+
if (!content)
|
|
402
|
+
continue;
|
|
403
|
+
const estimatedTokens = Math.ceil(content.length / 4);
|
|
404
|
+
const card = parseCard(file);
|
|
405
|
+
if (!card)
|
|
406
|
+
continue;
|
|
407
|
+
const maxForType = policy.max_tokens[card.frontmatter.type];
|
|
408
|
+
if (maxForType && estimatedTokens > maxForType) {
|
|
409
|
+
// Count markdown sections
|
|
410
|
+
const h2s = content.match(/^##\s+(.+)$/gm);
|
|
411
|
+
const splitNames = h2s ? h2s.slice(0, 4).map(h => h.replace(/^##\s+/, '').trim()) : [];
|
|
412
|
+
suggestions.push({
|
|
413
|
+
cardId: card.frontmatter.id || path.basename(file, '.md'),
|
|
414
|
+
cardFile: file,
|
|
415
|
+
currentTokens: estimatedTokens,
|
|
416
|
+
maxTokens: maxForType,
|
|
417
|
+
suggestedSplits: splitNames.length > 0 ? splitNames : ['(No H2 sections to suggest splits from)'],
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
function toSlug(text) {
|
|
423
|
+
return text.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_|_$/g, '');
|
|
424
|
+
}
|
|
425
|
+
//# sourceMappingURL=distill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"distill.js","sourceRoot":"","sources":["../../src/commands/distill.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../src/commands/graph.ts"],"names":[],"mappings":"AAOA,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAuH5F;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAgF7C"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.relatedCommand = relatedCommand;
|
|
37
|
+
exports.traceCommand = traceCommand;
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const fs_1 = require("../core/fs");
|
|
40
|
+
const db_1 = require("../core/db");
|
|
41
|
+
const PMEM_DIR = '.pmem';
|
|
42
|
+
function relatedCommand(id, options) {
|
|
43
|
+
const cwd = process.cwd();
|
|
44
|
+
const pmemPath = path.join(cwd, PMEM_DIR);
|
|
45
|
+
const depth = options?.depth ?? 1;
|
|
46
|
+
const edgeTypeFilter = options?.type;
|
|
47
|
+
const db = (0, db_1.openDatabase)(pmemPath);
|
|
48
|
+
(0, db_1.createSchema)(db);
|
|
49
|
+
// Query card by ID
|
|
50
|
+
const card = db.prepare('SELECT * FROM cards WHERE id = ? AND is_deleted = 0').get(id);
|
|
51
|
+
if (!card) {
|
|
52
|
+
console.log(`Node "${id}" not found in database.`);
|
|
53
|
+
console.log(`Try: pmem ask "${id}" to search for related nodes.`);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
// Query direct edges
|
|
57
|
+
let directQuery = 'SELECT * FROM edges WHERE (from_id = ? OR to_id = ?)';
|
|
58
|
+
const directParams = [id, id];
|
|
59
|
+
if (edgeTypeFilter) {
|
|
60
|
+
directQuery += ' AND type = ?';
|
|
61
|
+
directParams.push(edgeTypeFilter);
|
|
62
|
+
}
|
|
63
|
+
const directEdges = db.prepare(directQuery).all(...directParams);
|
|
64
|
+
// Helper to fetch a card by ID
|
|
65
|
+
const getCard = (cardId) => {
|
|
66
|
+
return db.prepare('SELECT * FROM cards WHERE id = ? AND is_deleted = 0').get(cardId);
|
|
67
|
+
};
|
|
68
|
+
// Output node info
|
|
69
|
+
console.log(`${card.id}`);
|
|
70
|
+
console.log(`Type: ${card.type}`);
|
|
71
|
+
console.log(`Title: ${card.title}`);
|
|
72
|
+
if (card.status) {
|
|
73
|
+
console.log(`Status: ${card.status}`);
|
|
74
|
+
}
|
|
75
|
+
if (directEdges.length === 0) {
|
|
76
|
+
console.log('\nNo related nodes.');
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
// Group direct edges by type
|
|
80
|
+
const grouped = new Map();
|
|
81
|
+
for (const edge of directEdges) {
|
|
82
|
+
const isOut = edge.from_id === id;
|
|
83
|
+
const targetId = isOut ? edge.to_id : edge.from_id;
|
|
84
|
+
const targetCard = getCard(targetId);
|
|
85
|
+
const targetTitle = targetCard ? targetCard.title : targetId;
|
|
86
|
+
if (!grouped.has(edge.type)) {
|
|
87
|
+
grouped.set(edge.type, []);
|
|
88
|
+
}
|
|
89
|
+
grouped.get(edge.type).push({
|
|
90
|
+
targetId,
|
|
91
|
+
targetTitle,
|
|
92
|
+
direction: isOut ? 'out' : 'in',
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
console.log('\nDirect Relations:');
|
|
96
|
+
for (const [edgeType, targets] of grouped) {
|
|
97
|
+
for (const t of targets) {
|
|
98
|
+
const prefix = t.direction === 'in' ? '←' : '';
|
|
99
|
+
console.log(` ${prefix}${edgeType}: ${t.targetId} (${t.targetTitle})`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// BFS for multi-hop traversal when depth > 1
|
|
103
|
+
if (depth > 1) {
|
|
104
|
+
const visited = new Set([id]);
|
|
105
|
+
// Seed frontier with direct neighbors
|
|
106
|
+
let frontier = new Set();
|
|
107
|
+
for (const edge of directEdges) {
|
|
108
|
+
const neighborId = edge.from_id === id ? edge.to_id : edge.from_id;
|
|
109
|
+
if (!visited.has(neighborId)) {
|
|
110
|
+
visited.add(neighborId);
|
|
111
|
+
frontier.add(neighborId);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
let totalExtendedEdges = 0;
|
|
115
|
+
for (let hop = 1; hop < depth; hop++) {
|
|
116
|
+
if (frontier.size === 0)
|
|
117
|
+
break;
|
|
118
|
+
const frontierArr = Array.from(frontier);
|
|
119
|
+
const nextFrontier = new Set();
|
|
120
|
+
const placeholders = frontierArr.map(() => '?').join(',');
|
|
121
|
+
let edgeQuery = `SELECT * FROM edges WHERE (from_id IN (${placeholders}) OR to_id IN (${placeholders}))`;
|
|
122
|
+
const params = [...frontierArr, ...frontierArr];
|
|
123
|
+
if (edgeTypeFilter) {
|
|
124
|
+
edgeQuery += ' AND type = ?';
|
|
125
|
+
params.push(edgeTypeFilter);
|
|
126
|
+
}
|
|
127
|
+
const hopEdges = db.prepare(edgeQuery).all(...params);
|
|
128
|
+
totalExtendedEdges += hopEdges.length;
|
|
129
|
+
for (const edge of hopEdges) {
|
|
130
|
+
const neighborId = frontier.has(edge.from_id) ? edge.to_id : edge.from_id;
|
|
131
|
+
if (!visited.has(neighborId)) {
|
|
132
|
+
visited.add(neighborId);
|
|
133
|
+
nextFrontier.add(neighborId);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
frontier = nextFrontier;
|
|
137
|
+
}
|
|
138
|
+
const totalReachable = visited.size - 1; // excluding the target itself
|
|
139
|
+
if (totalReachable > 0) {
|
|
140
|
+
console.log(`\nExtended Network (depth ${depth}):`);
|
|
141
|
+
console.log(` ${totalReachable} reachable node(s) via ${totalExtendedEdges + directEdges.length} edge(s) across all hops`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function traceCommand(id) {
|
|
146
|
+
const cwd = process.cwd();
|
|
147
|
+
const pmemPath = path.join(cwd, PMEM_DIR);
|
|
148
|
+
const db = (0, db_1.openDatabase)(pmemPath);
|
|
149
|
+
(0, db_1.createSchema)(db);
|
|
150
|
+
// Query card by ID
|
|
151
|
+
const card = db.prepare('SELECT * FROM cards WHERE id = ? AND is_deleted = 0').get(id);
|
|
152
|
+
if (!card) {
|
|
153
|
+
console.log(`Node "${id}" not found in database.`);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
console.log(`Trace for ${card.id}:`);
|
|
157
|
+
console.log(`Type: ${card.type}`);
|
|
158
|
+
console.log(`Title: ${card.title}`);
|
|
159
|
+
console.log(`File: ${card.file_path}`);
|
|
160
|
+
// Find evidence: decision and trace type cards connected via edges
|
|
161
|
+
const evidenceRows = db.prepare(`
|
|
162
|
+
SELECT DISTINCT c.id, c.type, c.title, c.file_path
|
|
163
|
+
FROM edges e
|
|
164
|
+
JOIN cards c ON (c.id = e.from_id OR c.id = e.to_id) AND c.id != ?
|
|
165
|
+
WHERE (e.from_id = ? OR e.to_id = ?)
|
|
166
|
+
AND (c.type = 'decision' OR c.type = 'trace')
|
|
167
|
+
AND c.is_deleted = 0
|
|
168
|
+
`).all(id, id, id);
|
|
169
|
+
if (evidenceRows.length > 0) {
|
|
170
|
+
console.log('');
|
|
171
|
+
console.log('Evidence Sources:');
|
|
172
|
+
for (const row of evidenceRows) {
|
|
173
|
+
console.log(` - ${row.id}: ${row.title}`);
|
|
174
|
+
console.log(` ${row.file_path}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// Find depends_on chain: edges where this node depends on others
|
|
178
|
+
const dependsOn = db.prepare(`
|
|
179
|
+
SELECT e.to_id, c.title as to_title
|
|
180
|
+
FROM edges e
|
|
181
|
+
LEFT JOIN cards c ON c.id = e.to_id AND c.is_deleted = 0
|
|
182
|
+
WHERE e.from_id = ? AND e.type = 'depends_on'
|
|
183
|
+
`).all(id);
|
|
184
|
+
if (dependsOn.length > 0) {
|
|
185
|
+
console.log('\nDepends On:');
|
|
186
|
+
for (const row of dependsOn) {
|
|
187
|
+
console.log(` - ${row.to_id}${row.to_title ? ` (${row.to_title})` : ''}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// Find depended_by: edges where other nodes depend on this node
|
|
191
|
+
const dependedBy = db.prepare(`
|
|
192
|
+
SELECT e.from_id, c.title as from_title
|
|
193
|
+
FROM edges e
|
|
194
|
+
LEFT JOIN cards c ON c.id = e.from_id AND c.is_deleted = 0
|
|
195
|
+
WHERE e.to_id = ? AND e.type = 'depends_on'
|
|
196
|
+
`).all(id);
|
|
197
|
+
if (dependedBy.length > 0) {
|
|
198
|
+
console.log('\nDepended On By:');
|
|
199
|
+
for (const row of dependedBy) {
|
|
200
|
+
console.log(` - ${row.from_id}${row.from_title ? ` (${row.from_title})` : ''}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// Read and display card body content (first 3000 chars after frontmatter)
|
|
204
|
+
const filePath = path.join(cwd, card.file_path);
|
|
205
|
+
if ((0, fs_1.fileExists)(filePath)) {
|
|
206
|
+
const content = (0, fs_1.readFile)(filePath);
|
|
207
|
+
if (content) {
|
|
208
|
+
const bodyMatch = content.match(/^---\n[\s\S]*?\n---\n([\s\S]*)/);
|
|
209
|
+
if (bodyMatch) {
|
|
210
|
+
console.log('\n--- Card Content ---');
|
|
211
|
+
console.log(bodyMatch[1].trim().substring(0, 3000));
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=graph.js.map
|