mindnet_obsidian/src/tests/analysis/chainInspector.confidence.test.ts
Lars 3bb59afdda
Some checks are pending
Node.js build / build (20.x) (push) Waiting to run
Node.js build / build (22.x) (push) Waiting to run
Enhance template matching and chain inspection features
- Added new properties to TemplateMatch interface for tracking slots and links completeness, and confidence levels.
- Updated resolveCanonicalEdgeType function to handle optional edge vocabulary.
- Enhanced computeFindings function to include missing link constraints findings.
- Improved inspectChains function to report on links completeness and confidence levels.
- Refactored tests to utilize real configuration files and improve integration with the vault structure.
- Updated helper functions to support loading from real vault paths, enhancing test reliability.
2026-01-18 22:10:44 +01:00

220 lines
6.6 KiB
TypeScript

/**
* Tests for Chain Inspector confidence and missing_link_constraints finding using real files.
*/
import { describe, it, expect } from "vitest";
import { inspectChains } from "../../analysis/chainInspector";
import { createVaultAppFromFixtures } from "../helpers/vaultHelper";
import { loadChainRolesFromFixtures, loadChainTemplatesFromFixtures } from "../helpers/configHelper";
import type { SectionContext } from "../../analysis/sectionContext";
import type { ChainTemplatesConfig } from "../../dictionary/types";
describe("Chain Inspector confidence and missing_link_constraints", () => {
it("should emit missing_link_constraints (INFO) for discovery profile with complete slots but incomplete links", async () => {
const app = createVaultAppFromFixtures();
const chainRoles = loadChainRolesFromFixtures();
const baseTemplates = loadChainTemplatesFromFixtures();
if (!chainRoles || !baseTemplates) {
console.warn("Skipping test: real config files not found in fixtures");
return;
}
// Create templates config with discovery profile and a template that requires causal links
const chainTemplates: ChainTemplatesConfig = {
...baseTemplates,
defaults: {
...baseTemplates.defaults,
profiles: {
discovery: {
required_links: false,
min_slots_filled_for_gap_findings: 1,
min_score_for_gap_findings: 0,
},
},
},
templates: [
{
name: "loop_learning",
slots: [
{ id: "trigger", allowed_node_types: ["experience"] },
{ id: "transformation", allowed_node_types: ["insight"] },
],
links: [
{ from: "trigger", to: "transformation", allowed_edge_roles: ["causal"] },
],
},
],
};
const context: SectionContext = {
file: "Tests/01_experience_trigger.md",
heading: "Kontext",
zoneKind: "content",
sectionIndex: 0,
};
const report = await inspectChains(
app,
context,
{
includeNoteLinks: true,
includeCandidates: false,
maxDepth: 3,
direction: "both",
},
chainRoles,
"_system/dictionary/edge_vocabulary.md",
chainTemplates,
undefined,
"discovery"
);
// Should have template match
if (!report.templateMatches || report.templateMatches.length === 0) {
return; // Skip if no matches
}
const match = report.templateMatches[0];
expect(match).toBeDefined();
if (!match) return;
// If slots are complete but links incomplete, should be plausible
if (match.slotsComplete && !match.linksComplete) {
expect(match.confidence).toBe("plausible");
// Should emit missing_link_constraints finding with INFO severity
const missingLinkFinding = report.findings.find((f) => f.code === "missing_link_constraints");
expect(missingLinkFinding).toBeDefined();
expect(missingLinkFinding?.severity).toBe("info");
}
});
it("should emit missing_link_constraints (WARN) for decisioning profile with complete slots but incomplete links", async () => {
const app = createVaultAppFromFixtures();
const chainRoles = loadChainRolesFromFixtures();
const baseTemplates = loadChainTemplatesFromFixtures();
if (!chainRoles || !baseTemplates) {
console.warn("Skipping test: real config files not found in fixtures");
return;
}
const chainTemplates: ChainTemplatesConfig = {
...baseTemplates,
defaults: {
...baseTemplates.defaults,
profiles: {
decisioning: {
required_links: true,
min_slots_filled_for_gap_findings: 3,
min_score_for_gap_findings: 20,
},
},
},
templates: [
{
name: "loop_learning",
slots: [
{ id: "trigger", allowed_node_types: ["experience"] },
{ id: "transformation", allowed_node_types: ["insight"] },
],
links: [
{ from: "trigger", to: "transformation", allowed_edge_roles: ["causal"] },
],
},
],
};
const context: SectionContext = {
file: "Tests/01_experience_trigger.md",
heading: "Kontext",
zoneKind: "content",
sectionIndex: 0,
};
const report = await inspectChains(
app,
context,
{
includeNoteLinks: true,
includeCandidates: false,
maxDepth: 3,
direction: "both",
},
chainRoles,
"_system/dictionary/edge_vocabulary.md",
chainTemplates,
undefined,
"decisioning"
);
// Should emit missing_link_constraints finding with WARN severity
if (!report.templateMatches || report.templateMatches.length === 0) {
return; // Skip if no matches
}
const match = report.templateMatches[0];
if (!match) return;
if (match.slotsComplete && !match.linksComplete) {
const missingLinkFinding = report.findings.find((f) => f.code === "missing_link_constraints");
expect(missingLinkFinding).toBeDefined();
expect(missingLinkFinding?.severity).toBe("warn");
}
});
it("should compute confirmed confidence for complete chain with causal roles", async () => {
const app = createVaultAppFromFixtures();
const chainRoles = loadChainRolesFromFixtures();
const chainTemplates = loadChainTemplatesFromFixtures();
if (!chainRoles || !chainTemplates) {
console.warn("Skipping test: real config files not found in fixtures");
return;
}
const context: SectionContext = {
file: "Tests/01_experience_trigger.md",
heading: "Kontext",
zoneKind: "content",
sectionIndex: 0,
};
const report = await inspectChains(
app,
context,
{
includeNoteLinks: true,
includeCandidates: false,
maxDepth: 3,
direction: "both",
},
chainRoles,
"_system/dictionary/edge_vocabulary.md",
chainTemplates,
undefined,
"decisioning"
);
// Should have complete match with confirmed confidence if all slots and links are found
if (!report.templateMatches || report.templateMatches.length === 0) {
return; // Skip if no matches
}
const match = report.templateMatches[0];
if (!match) return;
if (match.slotsComplete && match.linksComplete) {
expect(match.confidence).toBe("confirmed");
// Should NOT emit missing_link_constraints finding
const missingLinkFinding = report.findings.find((f) => f.code === "missing_link_constraints");
expect(missingLinkFinding).toBeUndefined();
}
});
});