@jussmor/commit-memory-mcp 0.4.2 → 0.4.3
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/dist/db/client.d.ts +8 -1
- package/dist/db/client.js +96 -1
- package/dist/mcp/server.js +13 -1
- package/package.json +1 -1
package/dist/db/client.d.ts
CHANGED
|
@@ -25,7 +25,14 @@ export declare function buildContextPack(db: RagDatabase, options: {
|
|
|
25
25
|
taskType?: string;
|
|
26
26
|
includeDraft?: boolean;
|
|
27
27
|
limit: number;
|
|
28
|
-
|
|
28
|
+
forceRefresh?: boolean;
|
|
29
|
+
summarizePR?: boolean;
|
|
30
|
+
}): {
|
|
31
|
+
learnedFeature: ContextPackRecord[];
|
|
32
|
+
branchContext: ContextPackRecord[];
|
|
33
|
+
prMetadata: ContextPackRecord[];
|
|
34
|
+
allContext: ContextPackRecord[];
|
|
35
|
+
};
|
|
29
36
|
export declare function archiveFeatureContext(db: RagDatabase, options: {
|
|
30
37
|
domain: string;
|
|
31
38
|
feature: string;
|
package/dist/db/client.js
CHANGED
|
@@ -7,6 +7,10 @@ export function openDatabase(dbPath) {
|
|
|
7
7
|
fs.mkdirSync(path.dirname(resolved), { recursive: true });
|
|
8
8
|
const db = new Database(resolved);
|
|
9
9
|
load(db);
|
|
10
|
+
// Enable WAL mode and ensure data is persisted to disk
|
|
11
|
+
db.pragma("journal_mode = WAL");
|
|
12
|
+
db.pragma("synchronous = NORMAL");
|
|
13
|
+
db.pragma("foreign_keys = ON");
|
|
10
14
|
db.exec(`
|
|
11
15
|
CREATE TABLE IF NOT EXISTS commits (
|
|
12
16
|
sha TEXT PRIMARY KEY,
|
|
@@ -370,6 +374,14 @@ export function promoteContextFacts(db, options) {
|
|
|
370
374
|
const result = db.prepare(sql).run(now, ...params);
|
|
371
375
|
return Number(result.changes ?? 0);
|
|
372
376
|
}
|
|
377
|
+
function summarizePRMetadata(fact) {
|
|
378
|
+
// Extract key info from PR metadata to keep it concise
|
|
379
|
+
if (fact.sourceType.startsWith("pr_")) {
|
|
380
|
+
const lines = fact.content.split("\n").slice(0, 2).join(" ");
|
|
381
|
+
return `[${fact.sourceRef}] ${fact.title} — ${lines.substring(0, 100)}`;
|
|
382
|
+
}
|
|
383
|
+
return fact.content;
|
|
384
|
+
}
|
|
373
385
|
export function buildContextPack(db, options) {
|
|
374
386
|
const taskType = options.taskType ?? "general";
|
|
375
387
|
const GLOBAL_BRANCH = "main";
|
|
@@ -463,6 +475,49 @@ export function buildContextPack(db, options) {
|
|
|
463
475
|
pack.push(row);
|
|
464
476
|
}
|
|
465
477
|
};
|
|
478
|
+
// PRIORITY 0) Learned feature knowledge is always included first when available.
|
|
479
|
+
// This ensures feature knowledge isn't lost behind PR metadata.
|
|
480
|
+
if (!options.feature && !options.branch) {
|
|
481
|
+
// Auto-discover recently learned features (source_type='feature-agent')
|
|
482
|
+
const learnedFacts = db.prepare(`
|
|
483
|
+
SELECT
|
|
484
|
+
id,
|
|
485
|
+
source_type,
|
|
486
|
+
source_ref,
|
|
487
|
+
title,
|
|
488
|
+
content,
|
|
489
|
+
scope_domain,
|
|
490
|
+
scope_feature,
|
|
491
|
+
scope_branch,
|
|
492
|
+
scope_task_type,
|
|
493
|
+
priority,
|
|
494
|
+
confidence,
|
|
495
|
+
status,
|
|
496
|
+
updated_at,
|
|
497
|
+
((priority * 0.40) + (confidence * 0.30) + 0.25) AS score
|
|
498
|
+
FROM context_facts
|
|
499
|
+
WHERE source_type = 'feature-agent' AND status = 'promoted'
|
|
500
|
+
ORDER BY updated_at DESC, priority DESC
|
|
501
|
+
LIMIT ?
|
|
502
|
+
`).all(Math.max(3, Math.floor(options.limit * 0.2)));
|
|
503
|
+
const learnedRows = learnedFacts.map((row) => ({
|
|
504
|
+
id: String(row.id ?? ""),
|
|
505
|
+
sourceType: String(row.source_type ?? ""),
|
|
506
|
+
sourceRef: String(row.source_ref ?? ""),
|
|
507
|
+
title: String(row.title ?? ""),
|
|
508
|
+
content: String(row.content ?? ""),
|
|
509
|
+
domain: String(row.scope_domain ?? ""),
|
|
510
|
+
feature: String(row.scope_feature ?? ""),
|
|
511
|
+
branch: String(row.scope_branch ?? ""),
|
|
512
|
+
taskType: String(row.scope_task_type ?? ""),
|
|
513
|
+
priority: Number(row.priority ?? 0),
|
|
514
|
+
confidence: Number(row.confidence ?? 0),
|
|
515
|
+
score: Number(row.score ?? 0),
|
|
516
|
+
status: String(row.status ?? "promoted"),
|
|
517
|
+
updatedAt: String(row.updated_at ?? ""),
|
|
518
|
+
}));
|
|
519
|
+
addRows(learnedRows);
|
|
520
|
+
}
|
|
466
521
|
// 1) Main branch domain context is the durable source-of-truth baseline.
|
|
467
522
|
if (pack.length < options.limit) {
|
|
468
523
|
addRows(runQuery({
|
|
@@ -503,7 +558,47 @@ export function buildContextPack(db, options) {
|
|
|
503
558
|
includeBranch: false,
|
|
504
559
|
}));
|
|
505
560
|
}
|
|
506
|
-
|
|
561
|
+
// Categorize results and apply summarization if requested
|
|
562
|
+
const learnedFeature = [];
|
|
563
|
+
const branchContext = [];
|
|
564
|
+
const prMetadata = [];
|
|
565
|
+
for (const item of pack) {
|
|
566
|
+
if (item.sourceType === "feature-agent") {
|
|
567
|
+
learnedFeature.push(item);
|
|
568
|
+
}
|
|
569
|
+
else if (item.sourceType.startsWith("pr_")) {
|
|
570
|
+
if (options.summarizePR) {
|
|
571
|
+
prMetadata.push({
|
|
572
|
+
...item,
|
|
573
|
+
content: summarizePRMetadata(item),
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
prMetadata.push(item);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
else if (item.branch && item.branch !== "main") {
|
|
581
|
+
branchContext.push(item);
|
|
582
|
+
}
|
|
583
|
+
else {
|
|
584
|
+
// Fallback for other context types
|
|
585
|
+
if (options.summarizePR && item.sourceType.startsWith("pr_")) {
|
|
586
|
+
branchContext.push({
|
|
587
|
+
...item,
|
|
588
|
+
content: summarizePRMetadata(item),
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
else {
|
|
592
|
+
branchContext.push(item);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
return {
|
|
597
|
+
learnedFeature,
|
|
598
|
+
branchContext,
|
|
599
|
+
prMetadata,
|
|
600
|
+
allContext: pack,
|
|
601
|
+
};
|
|
507
602
|
}
|
|
508
603
|
export function archiveFeatureContext(db, options) {
|
|
509
604
|
const now = new Date().toISOString();
|
package/dist/mcp/server.js
CHANGED
|
@@ -175,7 +175,7 @@ export async function startMcpServer() {
|
|
|
175
175
|
},
|
|
176
176
|
{
|
|
177
177
|
name: "build_context_pack",
|
|
178
|
-
description: "Build a scoped context pack for a task/domain/feature/branch
|
|
178
|
+
description: "Build a scoped context pack for a task/domain/feature/branch. Returns learned feature knowledge, branch context, and PR metadata separately.",
|
|
179
179
|
inputSchema: {
|
|
180
180
|
type: "object",
|
|
181
181
|
properties: {
|
|
@@ -185,6 +185,14 @@ export async function startMcpServer() {
|
|
|
185
185
|
taskType: { type: "string" },
|
|
186
186
|
includeDraft: { type: "boolean" },
|
|
187
187
|
limit: { type: "number" },
|
|
188
|
+
forceRefresh: {
|
|
189
|
+
type: "boolean",
|
|
190
|
+
description: "Re-run learn_feature to update feature knowledge",
|
|
191
|
+
},
|
|
192
|
+
summarizePR: {
|
|
193
|
+
type: "boolean",
|
|
194
|
+
description: "Return PR metadata as summaries instead of full content",
|
|
195
|
+
},
|
|
188
196
|
},
|
|
189
197
|
required: [],
|
|
190
198
|
},
|
|
@@ -390,6 +398,8 @@ export async function startMcpServer() {
|
|
|
390
398
|
const branch = String(request.params.arguments?.branch ?? "").trim();
|
|
391
399
|
const taskType = String(request.params.arguments?.taskType ?? "").trim() || "general";
|
|
392
400
|
const includeDraft = Boolean(request.params.arguments?.includeDraft);
|
|
401
|
+
const forceRefresh = Boolean(request.params.arguments?.forceRefresh);
|
|
402
|
+
const summarizePR = Boolean(request.params.arguments?.summarizePR);
|
|
393
403
|
const db = openDatabase(dbPath);
|
|
394
404
|
try {
|
|
395
405
|
const pack = buildContextPack(db, {
|
|
@@ -399,6 +409,8 @@ export async function startMcpServer() {
|
|
|
399
409
|
taskType,
|
|
400
410
|
includeDraft,
|
|
401
411
|
limit: Number.isFinite(limit) && limit > 0 ? limit : 20,
|
|
412
|
+
forceRefresh,
|
|
413
|
+
summarizePR,
|
|
402
414
|
});
|
|
403
415
|
return {
|
|
404
416
|
content: [{ type: "text", text: JSON.stringify(pack, null, 2) }],
|
package/package.json
CHANGED