Skip to content

Commit a87dbeb

Browse files
Claudeclaude
authored andcommitted
fix: switch recall default to c-review, clean thread display
- Change production nudge variant from a-institutional to c-review (89% vs 44% scar reference rate in nudge-bench testing) - Remove thread IDs from list_threads display output Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent ad312b1 commit a87dbeb

File tree

5 files changed

+92
-7
lines changed

5 files changed

+92
-7
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [1.1.4] - 2026-02-20
11+
12+
### Changed
13+
- **Recall default switched to c-review**: Production nudge header changed from "INSTITUTIONAL MEMORY ACTIVATED" to "N scars to review". Nudge-bench testing (54 runs × 3 models) showed 89% scar reference rate vs 44% — a 2x improvement across Opus, Sonnet, and Haiku.
14+
15+
### Fixed
16+
- **Thread display cleanup**: Removed internal thread IDs from `list_threads` output. Threads now show `# | Thread | Active` — IDs were implementation detail with no user value.
17+
1018
## [1.1.3] - 2026-02-19
1119

1220
### Added

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "gitmem-mcp",
3-
"version": "1.1.3",
3+
"version": "1.1.4",
44
"description": "Institutional memory for AI coding agents. Memory that compounds.",
55
"type": "module",
66
"main": "dist/index.js",

src/services/nudge-variants.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/**
2+
* Nudge Variant Support
3+
*
4+
* Reads GITMEM_NUDGE_VARIANT env var to select alternative header
5+
* framings for recall/prepare-context output. Used by nudge-bench
6+
* to A/B test how different wording affects agent compliance.
7+
*
8+
* When no env var is set, returns the production default.
9+
*
10+
* Variant IDs match nudge-bench/variants/n001-header.ts
11+
*/
12+
13+
export interface NudgeHeader {
14+
icon: string;
15+
text: (count: number) => string;
16+
}
17+
18+
const VARIANTS: Record<string, NudgeHeader> = {
19+
// Production default
20+
"n001-a-institutional": {
21+
icon: "🧠",
22+
text: (n) => `INSTITUTIONAL MEMORY ACTIVATED\n\nFound ${n} relevant scar${n === 1 ? "" : "s"} for your plan:`,
23+
},
24+
// Informational/passive
25+
"n001-b-recalled": {
26+
icon: "\x1b[38;5;37m⬢\x1b[0m",
27+
text: (n) => `gitmem ── ${n} learnings recalled`,
28+
},
29+
// Obligation
30+
"n001-c-review": {
31+
icon: "\x1b[38;5;37m⬢\x1b[0m",
32+
text: (n) => `gitmem ── ${n} scar${n === 1 ? "" : "s"} to review`,
33+
},
34+
// Directive
35+
"n001-d-directive": {
36+
icon: "\x1b[38;5;37m⬢\x1b[0m",
37+
text: (n) => `gitmem ── review ${n} learning${n === 1 ? "" : "s"} before proceeding`,
38+
},
39+
// Procedural — ties to confirm_scars
40+
"n001-e-confirm": {
41+
icon: "\x1b[38;5;37m⬢\x1b[0m",
42+
text: (n) => `gitmem ── ${n} scar${n === 1 ? "" : "s"} found — confirm before acting`,
43+
},
44+
// Reasoning — explains WHY (Karpathy: reasoning > command)
45+
"n001-f-reasoning": {
46+
icon: "\x1b[38;5;37m⬢\x1b[0m",
47+
text: (n) => `gitmem ── ${n} past mistake${n === 1 ? "" : "s"} detected that may repeat here — review to avoid the same outcome`,
48+
},
49+
};
50+
51+
const DEFAULT_VARIANT = "n001-c-review";
52+
53+
/**
54+
* Get the active nudge header based on GITMEM_NUDGE_VARIANT env var.
55+
* Falls back to production default if unset or invalid.
56+
*/
57+
export function getNudgeHeader(): NudgeHeader {
58+
const variantId = process.env.GITMEM_NUDGE_VARIANT;
59+
if (!variantId) return VARIANTS[DEFAULT_VARIANT];
60+
return VARIANTS[variantId] || VARIANTS[DEFAULT_VARIANT];
61+
}
62+
63+
/**
64+
* Format the recall header line using the active nudge variant.
65+
*/
66+
export function formatNudgeHeader(scarCount: number): string {
67+
const header = getNudgeHeader();
68+
return `${header.icon} ${header.text(scarCount)}`;
69+
}
70+
71+
/**
72+
* Get the active variant ID (for logging/metrics).
73+
*/
74+
export function getActiveVariantId(): string {
75+
const variantId = process.env.GITMEM_NUDGE_VARIANT;
76+
if (variantId && VARIANTS[variantId]) return variantId;
77+
return DEFAULT_VARIANT;
78+
}

src/tools/definitions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@ export const TOOLS = [
621621
{
622622
name: "list_threads",
623623
description:
624-
"List open threads across recent sessions. Shows unresolved work items that carry over between sessions, with IDs for resolution. Use resolve_thread to mark threads as done.",
624+
"List open threads across recent sessions. Shows unresolved work items that carry over between sessions. Use resolve_thread to mark threads as done.",
625625
inputSchema: {
626626
type: "object" as const,
627627
properties: {

src/tools/list-threads.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* list_threads Tool
33
*
44
* List open threads across recent sessions. Shows unresolved work items
5-
* that carry over between sessions, with IDs for resolution.
5+
* that carry over between sessions.
66
*
77
* Primary read from Supabase (source of truth).
88
* Falls back to session-based aggregation (same as session_start),
@@ -65,14 +65,13 @@ function buildThreadsDisplay(
6565
);
6666

6767
// Markdown table — renders cleanly in all MCP clients
68-
lines.push("| # | ID | Thread | Active |");
69-
lines.push("|---|-----|--------|--------|");
68+
lines.push("| # | Thread | Active |");
69+
lines.push("|---|--------|--------|");
7070
for (let i = 0; i < sorted.length; i++) {
7171
const t = sorted[i];
72-
const shortId = t.id;
7372
const text = truncate(t.text, 60);
7473
const date = shortDate(t.last_touched_at || t.created_at);
75-
lines.push(`| ${i + 1} | ${shortId} | ${text} | ${date} |`);
74+
lines.push(`| ${i + 1} | ${text} | ${date} |`);
7675
}
7776

7877
return wrapDisplay(lines.join("\n"));

0 commit comments

Comments
 (0)