test(sf): lock escalation→memory persistence contract

Commit 00c13bc5a added "createMemory on resolveEscalation" but the
behavior was untested — a regression that broke it would silently
disable the cross-session learning surface (the [escalation:T##]
memories are what carry agent rationales forward via getRelevantMemories
ranking).

Two new tests:
1. resolveEscalation with explicit user rationale → memory contains
   the question, choice, and user rationale, category=architecture.
2. resolveEscalation with empty rationale → falls back to the
   artifact's recommendationRationale (the formatEscalationMemoryContent
   contract).

23 tests in the file now (was 21).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mikael Hugo 2026-05-02 23:33:18 +02:00
parent c1ce9aac15
commit 3b5e6588e9

View file

@ -298,4 +298,54 @@ describe("claimOverrideForInjection (carry-forward)", () => {
assert.equal(after?.escalation_awaiting_review, 0); assert.equal(after?.escalation_awaiting_review, 0);
assert.equal(after?.escalation_artifact_path, before); assert.equal(after?.escalation_artifact_path, before);
}); });
test("resolveEscalation persists choice + rationale as a memory", async () => {
writeEscalationArtifact(dir, buildEscalationArtifact(baseArtifact));
const result = resolveEscalation(
dir,
"M001",
"S01",
"T01",
"fail",
"explicit user rationale here",
);
assert.equal(result.status, "resolved");
const { getActiveMemories } = await import("../memory-store.ts");
const memories = getActiveMemories();
assert.ok(
memories.length >= 1,
`expected at least 1 memory, got ${memories.length}`,
);
const escalationMemory = memories.find((m) =>
m.content.startsWith("[escalation:T01]"),
);
assert.ok(escalationMemory, "no [escalation:T01] memory was written");
assert.equal(escalationMemory!.category, "architecture");
assert.match(escalationMemory!.content, /Overwrite or fail\?/);
assert.match(escalationMemory!.content, /Chose:/);
assert.match(escalationMemory!.content, /explicit user rationale here/);
});
test("auto-mode resolveEscalation falls back to recommendationRationale when no user rationale", async () => {
writeEscalationArtifact(dir, buildEscalationArtifact(baseArtifact));
resolveEscalation(
dir,
"M001",
"S01",
"T01",
"accept",
"", // empty rationale — should fall back to art.recommendationRationale
);
const { getActiveMemories } = await import("../memory-store.ts");
const memories = getActiveMemories();
const escalationMemory = memories.find((m) =>
m.content.startsWith("[escalation:T01]"),
);
assert.ok(escalationMemory);
assert.match(
escalationMemory!.content,
/data loss is irreversible/,
"empty user rationale should fall back to recommendationRationale",
);
});
}); });