fix(confidence-engine): define focused relationship contract

This commit is contained in:
2026-09-07 13:28:38 +01:00
parent 14630cf6b7
commit 3f2e2e05ae
3 changed files with 72 additions and 8 deletions
+32 -5
View File
@@ -7,7 +7,7 @@
*/
import { afterEach, beforeEach, describe, it, expect, vi } from "vitest";
import { focusedDeconstructJsonSchema } from "@/lib/graph/focused-investigation";
import { focusedDeconstructJsonSchema, validateFocusedDeconstructSchema } from "@/lib/graph/focused-investigation";
// ── helpers ──────────────────────────────────────────────────────────────
@@ -20,8 +20,8 @@ function makeMockProvider(inventedTargetNodeId) {
uncertainties: ["whether formal docs can capture tacit knowledge"],
assumptions: ["documentation is primary mechanism for knowledge transfer"],
relationships: [
{ from: "founder", to: "processes", type: "holds", rationale: "tacit" },
{ from: "ops-context", to: "docs-infra", type: "depends_on", rationale: "formal docs required" },
{ from: "founder", to: "processes", type: "holds" },
{ from: "ops-context", to: "docs-infra", type: "depends_on" },
],
possibleFollowUpQuestions: [
"What processes does the founder hold tacitly?",
@@ -45,6 +45,33 @@ describe("focused-deconstruct targetNodeId identity boundary", () => {
vi.doUnmock("@/lib/llm/provider");
});
it("enforces the canonical focused relationship structure", () => {
const base = {
targetNodeId: "node-id", observations: [], uncertainties: [], assumptions: [],
possibleFollowUpQuestions: [],
};
expect(validateFocusedDeconstructSchema({ ...base, relationships: [] })).toEqual([]);
expect(validateFocusedDeconstructSchema({
...base,
relationships: [{ from: "supplier changed", to: "defect rate increased", type: "associated with" }],
})).toEqual([]);
const invalidRelationships = [
"not an array",
[{}],
[{ from: "a", type: "links" }],
[{ from: "a", to: "b" }],
[{ from: "", to: "b", type: "links" }],
[{ from: "a", to: "", type: "links" }],
[{ from: "a", to: "b", type: "" }],
[{ from: "a", to: "b", type: "links", rationale: "extra" }],
[{ from: "a", to: "b", type: "links", extra: "extra" }],
];
invalidRelationships.forEach((relationships) => {
expect(validateFocusedDeconstructSchema({ ...base, relationships }).length).toBeGreaterThan(0);
});
});
it("request targetNodeId overrides model-invented targetNodeId", async () => {
const requestTargetNodeId = "nk04xvk"; // original graph node ID
const inventedModelId = "invented-model-id";
@@ -128,8 +155,8 @@ describe("focused-deconstruct targetNodeId identity boundary", () => {
const mockUnc = ["whether formal docs can capture tacit knowledge"];
const mockAssm = ["documentation is primary mechanism for knowledge transfer"];
const mockRel = [
{ from: "founder", to: "processes", type: "holds", rationale: "tacit" },
{ from: "ops-context", to: "docs-infra", type: "depends_on", rationale: "formal docs required" },
{ from: "founder", to: "processes", type: "holds" },
{ from: "ops-context", to: "docs-infra", type: "depends_on" },
];
const mockFuq = [
"What processes does the founder hold tacitly?",