mirror of
https://github.com/sdwolf4103/opencode-working-memory.git
synced 2026-07-17 12:56:42 +02:00
fix: tighten compaction memory candidate prompt
This commit is contained in:
+21
-29
@@ -108,45 +108,37 @@ function buildCompactionPrompt(privateContext: string): string {
|
||||
"",
|
||||
"## Relevant Files",
|
||||
"",
|
||||
"At the end of the summary, extract durable memory entries for future sessions.",
|
||||
"At the end of the summary, include a Memory candidates section only if there are durable facts that will change future behavior.",
|
||||
"",
|
||||
"Memory quality bar:",
|
||||
"Extract only durable facts that will change future behavior: user preferences, decisions with rationale, stable constraints, or hard-to-rediscover references.",
|
||||
"",
|
||||
"Do not extract trivia: transient IDs/revisions, task progress, test/file counts, bare status updates, local UI details, or facts easily rediscovered from the repo.",
|
||||
"",
|
||||
"When unsure, skip it. Fewer high-signal memories are better than many low-value ones.",
|
||||
"CRITICAL MEMORY RULES:",
|
||||
"- Most compactions should produce ZERO memories. Empty is correct when nothing durable changed.",
|
||||
"- NO completion or progress statements: do not extract completed work, passing tests, commits, PR status, wave/task/phase completion, or current state.",
|
||||
"- NO session-internal implementation notes: do not extract what files were edited, what bug was just fixed, what command just ran, or what the assistant reviewed.",
|
||||
"- feedback ONLY means stable user preferences or user instructions, written in imperative/future-facing form.",
|
||||
"- decision ONLY means rules that apply to FUTURE work, not decisions already implemented in this session.",
|
||||
"- project/reference ONLY when the fact is stable across sessions and hard to rediscover from the repository.",
|
||||
"- If unsure, skip it.",
|
||||
"",
|
||||
"Good memory examples:",
|
||||
"- [feedback] User prefers architecture reviews in Traditional Chinese.",
|
||||
"- [decision] Use frozen workspace memory snapshots plus ephemeral hot state for cache stability.",
|
||||
"- [project] The plugin should piggyback memory extraction on OpenCode compaction and avoid extra LLM calls.",
|
||||
"- [reference] Workspace memory appears in frozen system[1]; pending memories appear in hot session state until compaction.",
|
||||
"- [decision] Do not add semantic merge to memory dedupe.",
|
||||
"- [project] This repository is an OpenCode plugin using local JSON stores.",
|
||||
"- [reference] Workspace memory is rendered as frozen system[1]; pending memories remain in hot state until compaction.",
|
||||
"",
|
||||
"Bad memory examples to skip:",
|
||||
"- 42 tests passed.",
|
||||
"- Wave 2 completed successfully.",
|
||||
"- Modified 5 files.",
|
||||
"- commit 4309cb8 contains the latest fix.",
|
||||
"- TypeError: Cannot read properties of undefined.",
|
||||
"- Currently running npm test.",
|
||||
"",
|
||||
"A memory should still be useful if a new agent opens this workspace next week.",
|
||||
"",
|
||||
"Only extract facts that are likely to stay true across sessions.",
|
||||
"Do not extract session-specific progress like exact test counts, file counts, or phase numbers.",
|
||||
"For progress, extract the stable goal or durable milestone, not the current number.",
|
||||
"For references, extract configuration values that do not usually change between sessions.",
|
||||
"For feedback, extract unresolved issues or user preferences that future sessions need to know.",
|
||||
"Use exactly this candidate format, including square brackets around the type:",
|
||||
"- 180 tests passed and CI is green.",
|
||||
"- Implemented owner-aware cleanup in plugin.ts.",
|
||||
"- The assistant reviewed code reviewer feedback and updated the plan.",
|
||||
"- Commit a762e86 contains the owner scope fix.",
|
||||
"",
|
||||
"Format when there ARE durable memories:",
|
||||
"Memory candidates:",
|
||||
"- [feedback] content",
|
||||
"- [project] content",
|
||||
"- [decision] content",
|
||||
"- [reference] content",
|
||||
"- [feedback|decision|project|reference] future-facing durable fact",
|
||||
"",
|
||||
"Do not write '- project content'; write '- [project] content'.",
|
||||
"Format when there are NO durable memories:",
|
||||
"Memory candidates:",
|
||||
"(none)",
|
||||
"",
|
||||
"Background context, use this to inform the summary above.",
|
||||
"Do not output this context verbatim:",
|
||||
|
||||
+23
-2
@@ -297,9 +297,9 @@ test("compaction hook sets output.prompt with ---free template", async () => {
|
||||
"Prompt should include concrete positive memory examples");
|
||||
assert.equal(prompt!.includes("Bad memory examples to skip:"), true,
|
||||
"Prompt should include concrete negative memory examples");
|
||||
assert.equal(prompt!.includes("42 tests passed"), true,
|
||||
assert.equal(prompt!.includes("180 tests passed"), true,
|
||||
"Prompt should explicitly reject test-count snapshots");
|
||||
assert.equal(prompt!.includes("commit 4309cb8"), true,
|
||||
assert.equal(prompt!.includes("Commit a762e86"), true,
|
||||
"Prompt should explicitly reject commit-hash snapshots");
|
||||
|
||||
// Should contain our context data (hot session state)
|
||||
@@ -317,6 +317,27 @@ test("compaction hook sets output.prompt with ---free template", async () => {
|
||||
}
|
||||
});
|
||||
|
||||
test("compaction prompt forbids progress and session-internal memory candidates", async () => {
|
||||
const tmpDir = await mkdtemp(join(tmpdir(), "memory-plugin-prompt-"));
|
||||
try {
|
||||
const plugin = await MemoryV2Plugin({ directory: tmpDir, client: mockRootClient() });
|
||||
const output = { prompt: "", context: [] as string[] };
|
||||
|
||||
await (plugin as Record<string, Function>)["experimental.session.compacting"](
|
||||
{ sessionID: "prompt-session", model: {} },
|
||||
output,
|
||||
);
|
||||
|
||||
assert.match(output.prompt, /CRITICAL MEMORY RULES/);
|
||||
assert.match(output.prompt, /NO completion or progress statements/i);
|
||||
assert.match(output.prompt, /NO session-internal implementation notes/i);
|
||||
assert.match(output.prompt, /feedback ONLY/i);
|
||||
assert.match(output.prompt, /Most compactions should produce ZERO memories/i);
|
||||
} finally {
|
||||
await rm(tmpDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("compaction hook merges existing output.context from other plugins", async () => {
|
||||
const tmpDir = await mkdtemp(join(tmpdir(), "memory-plugin-test-"));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user