reasoning: use structured semantic fidelity contract
This commit is contained in:
@@ -122,12 +122,36 @@ describe("buildGraphUpdatePrompt", () => {
|
||||
"Put any stronger interpretation in answerMeaning.possibleInference",
|
||||
);
|
||||
expect(prompt).toContain(
|
||||
"supportCategory and resolutionGuidance are optional descriptive hints only",
|
||||
"populate supportCategory with one of the allowed values whenever the user's meaning fits an existing category",
|
||||
);
|
||||
expect(prompt).toContain(
|
||||
"leave them null rather than inventing rigid category labels",
|
||||
"Do not leave supportCategory null merely because the wording is uncertain",
|
||||
);
|
||||
});
|
||||
|
||||
it("lists allowed structured semantic enum values", () => {
|
||||
const prompt = buildGraphUpdatePrompt(makeContext());
|
||||
|
||||
expect(prompt).toContain("## Allowed answerMeaning.supportCategory Values");
|
||||
expect(prompt).toContain(
|
||||
"relative_priority_only | conditional_tradeoff | uncertain | explicit_hard_constraint | other",
|
||||
);
|
||||
expect(prompt).toContain(
|
||||
"must_remain_unresolved | may_resolve | must_resolve",
|
||||
);
|
||||
});
|
||||
|
||||
it("strengthens resolutionGuidance population guidance without provider-specific wording", () => {
|
||||
const prompt = buildGraphUpdatePrompt(makeContext());
|
||||
|
||||
expect(prompt).toContain(
|
||||
"Populate resolutionGuidance when the user's meaning genuinely implies must_remain_unresolved, may_resolve, or must_resolve",
|
||||
);
|
||||
expect(prompt).toContain(
|
||||
"Keep it null only when no existing resolution state actually applies",
|
||||
);
|
||||
expect(prompt).not.toContain("qwen");
|
||||
});
|
||||
});
|
||||
|
||||
// ── Semantic-to-mutation contract (57J.39) ──────────────
|
||||
@@ -135,7 +159,9 @@ describe("buildGraphUpdatePrompt", () => {
|
||||
describe("buildGraphUpdatePrompt — semantic-to-mutation MUST rule", () => {
|
||||
it("contains the explicit structural-materialization MUST rule", () => {
|
||||
const prompt = buildGraphUpdatePrompt(makeContext());
|
||||
expect(prompt).toContain("MUST express its effect through structural mutation");
|
||||
expect(prompt).toContain(
|
||||
"MUST express its effect through structural mutation",
|
||||
);
|
||||
});
|
||||
|
||||
it("rule permits update/refine of existing structure", () => {
|
||||
@@ -162,9 +188,7 @@ describe("buildGraphUpdatePrompt — semantic-to-mutation MUST rule", () => {
|
||||
const prompt = buildGraphUpdatePrompt(makeContext());
|
||||
// The rule should be silent about forcing new nodes — this is preserved by existing rule #7.
|
||||
// Verify the MUST rule exists but doesn't contain "must add a new node" or similar.
|
||||
const mustRuleMatch = prompt.match(
|
||||
/6\..*?(?=\n7\.)/s,
|
||||
);
|
||||
const mustRuleMatch = prompt.match(/6\..*?(?=\n7\.)/s);
|
||||
expect(mustRuleMatch).not.toBe(null);
|
||||
expect(mustRuleMatch[0]).not.toContain("must add a new node");
|
||||
});
|
||||
@@ -172,9 +196,7 @@ describe("buildGraphUpdatePrompt — semantic-to-mutation MUST rule", () => {
|
||||
it("does not imply possibleInference alone triggers mutation", () => {
|
||||
const prompt = buildGraphUpdatePrompt(makeContext());
|
||||
// The rule must reference userSupportedMeaning specifically, not possibleInference as a trigger.
|
||||
const mustRuleMatch = prompt.match(
|
||||
/6\..*?(?=\n7\.)/s,
|
||||
);
|
||||
const mustRuleMatch = prompt.match(/6\..*?(?=\n7\.)/s);
|
||||
expect(mustRuleMatch[0]).toContain("userSupportedMeaning");
|
||||
});
|
||||
|
||||
@@ -234,7 +256,9 @@ describe("buildGraphUpdatePrompt — semantic-to-mutation MUST rule", () => {
|
||||
expect(prompt).toContain("duplicate unknowns");
|
||||
// Additional Guidance preference for update over add:
|
||||
const additionalGuidance = prompt.split("## Additional Guidance")[1];
|
||||
expect(additionalGuidance).toContain("prefer updatedNodes and resolvedUnknownNodeIds over creating duplicate nodes");
|
||||
expect(additionalGuidance).toContain(
|
||||
"prefer updatedNodes and resolvedUnknownNodeIds over creating duplicate nodes",
|
||||
);
|
||||
});
|
||||
|
||||
it("PASS: update/refine route preserved — no new mandatory-add requirement", () => {
|
||||
@@ -244,8 +268,12 @@ describe("buildGraphUpdatePrompt — semantic-to-mutation MUST rule", () => {
|
||||
expect(prompt).toContain("update/refinement of existing structure");
|
||||
// Additional guidance still encourages preferring updates:
|
||||
const additionalGuidance = prompt.split("## Additional Guidance")[1];
|
||||
expect(additionalGuidance).toContain("prefer updatedNodes and resolvedUnknownNodeIds over creating duplicate nodes");
|
||||
expect(additionalGuidance).toContain("update that node rather than creating only a parallel observation");
|
||||
expect(additionalGuidance).toContain(
|
||||
"prefer updatedNodes and resolvedUnknownNodeIds over creating duplicate nodes",
|
||||
);
|
||||
expect(additionalGuidance).toContain(
|
||||
"update that node rather than creating only a parallel observation",
|
||||
);
|
||||
});
|
||||
|
||||
it("PASS: possibleInference separation preserved — not converted to mandatory mutation", () => {
|
||||
@@ -263,7 +291,9 @@ describe("buildGraphUpdatePrompt — semantic-to-mutation MUST rule", () => {
|
||||
expect(additionalGuidance).not.toContain("possibleInference");
|
||||
|
||||
// Rule #27 exists in the prompt (separation preserved):
|
||||
expect(fullPrompt).toContain("answerMeaning.possibleInference, not in userSupportedMeaning");
|
||||
expect(fullPrompt).toContain(
|
||||
"answerMeaning.possibleInference, not in userSupportedMeaning",
|
||||
);
|
||||
});
|
||||
|
||||
it("PASS: no action-selection machinery added — no keyword routing or node-kind decision table", () => {
|
||||
@@ -293,7 +323,9 @@ describe("buildGraphUpdatePrompt — 57J.46 existing-first uncertainty fallback"
|
||||
it("test 1: assembled prompt explicitly says to check for an equivalent unresolved unknown first", () => {
|
||||
const prompt = buildGraphUpdatePrompt(makeContext());
|
||||
const guidance = getAdditionalGuidance(prompt);
|
||||
expect(guidance).toContain("first check whether an existing unresolved node");
|
||||
expect(guidance).toContain(
|
||||
"first check whether an existing unresolved node",
|
||||
);
|
||||
expect(guidance).toContain("represents the same uncertainty");
|
||||
});
|
||||
|
||||
@@ -310,7 +342,9 @@ describe("buildGraphUpdatePrompt — 57J.46 existing-first uncertainty fallback"
|
||||
const prompt = buildGraphUpdatePrompt(makeContext());
|
||||
const guidance = getAdditionalGuidance(prompt);
|
||||
expect(guidance).toContain("if no such node exists");
|
||||
expect(guidance).toContain("add a new unknown that directly represents the unresolved uncertainty");
|
||||
expect(guidance).toContain(
|
||||
"add a new unknown that directly represents the unresolved uncertainty",
|
||||
);
|
||||
});
|
||||
|
||||
// Test 4 — ordered fallback means: existing first, otherwise add
|
||||
@@ -361,9 +395,13 @@ describe("buildGraphUpdatePrompt — 57J.46 existing-first uncertainty fallback"
|
||||
expect(prompt).toContain(
|
||||
"include that existing node ID in resolvedUnknownNodeIds",
|
||||
);
|
||||
expect(prompt).toContain("update that node rather than creating only a parallel observation");
|
||||
expect(prompt).toContain(
|
||||
"update that node rather than creating only a parallel observation",
|
||||
);
|
||||
// Rule #5 (resolve answered unknown first) must still exist:
|
||||
expect(prompt).toContain("Resolve the answered unknown first when the answer supports it");
|
||||
expect(prompt).toContain(
|
||||
"Resolve the answered unknown first when the answer supports it",
|
||||
);
|
||||
});
|
||||
|
||||
// Test 9 — duplicate validator/contract preserved
|
||||
@@ -372,7 +410,9 @@ describe("buildGraphUpdatePrompt — 57J.46 existing-first uncertainty fallback"
|
||||
expect(prompt).toContain("Do not add duplicate unknowns");
|
||||
expect(prompt).toContain("genuinely new concepts");
|
||||
const guidance = getAdditionalGuidance(prompt);
|
||||
expect(guidance).toContain("prefer updatedNodes and resolvedUnknownNodeIds over creating duplicate nodes");
|
||||
expect(guidance).toContain(
|
||||
"prefer updatedNodes and resolvedUnknownNodeIds over creating duplicate nodes",
|
||||
);
|
||||
});
|
||||
|
||||
// Test 10 — scope remains uncertainty-only (not universal to all categories)
|
||||
|
||||
Reference in New Issue
Block a user