practice: resolveTargetId + ids-first context marker (round 9 slice 1)

The mastery-trace contract: problem targets must be traceable to
propositions. resolveTargetId (pure, chains.ts) resolves a target
string to a canonical node id — id exact first, then name
case-insensitive — against the WHOLE graph (pickless sessions and
future graph-tools poses stay valid). The graph-context marker now
introduces each pick as [id] name: statement (ids were never shown to
the model before — names only); chains stay names: comprehension
context, not tags.
This commit is contained in:
amosblomqvist
2026-10-05 06:26:21 +03:00
parent 1cac08117a
commit d47b3564ce
4 changed files with 37 additions and 7 deletions
+5 -3
View File
@@ -49,7 +49,9 @@ describe("newGraphContextMessage", () => {
const m = newGraphContextMessage(PICKS, ["Modus ponens → Soundness"]);
assert.equal(m.customType, "graph-context");
assert.match(m.content, /Contextualization — the learner picked these propositions/);
assert.ok(m.content.includes("- Modus ponens: If P implies Q and P holds, Q holds."));
// IDS FIRST (owner round 9): every pick carries its id — the problem
// tool's target field references these; names alone no longer.
assert.ok(m.content.includes(`- [${PICKS[0]!.id}] Modus ponens: If P implies Q and P holds, Q holds.`));
assert.ok(m.content.includes("Reasoning chains among them"));
assert.ok(m.content.includes("- Modus ponens → Soundness"));
// the UI payload is the structured pick, not the flattened text
@@ -133,8 +135,8 @@ describe("POST /api/chats — graphContext becomes message[0]", () => {
const m = record.messages[0] as { role: string; customType: string; content: string };
assert.equal(m.role, "custom");
assert.equal(m.customType, "graph-context");
assert.ok(m.content.includes("- Modus ponens: If P implies Q and P holds, Q holds."));
// the chain AMONG the picks rides the marker (formatChainLine shape)
assert.ok(m.content.includes("- [n_a] Modus ponens: If P implies Q and P holds, Q holds."));
// the chain AMONG the picks rides the marker (formatChainLine shape — names)
assert.ok(m.content.includes("- Modus ponens → Soundness"));
});