import fs from "node:fs/promises"; import path from "node:path"; import { describe, expect, it } from "vitest"; import type { ResolvedMemoryWikiConfig } from "./config.js"; import { createWikiApplyTool, createWikiLintTool } from "./tool.js"; import { lintMemoryWikiVault } from "./lint.js"; import { createMemoryWikiTestHarness } from "./test-helpers.js"; function asSchemaObject(value: unknown): Record { if (typeof value !== "object" || value === null || Array.isArray(value)) { throw new Error("Expected JSON schema object"); } return value as Record; } describe("memory-wiki tools", () => { const harness = createMemoryWikiTestHarness(); it("allows provenance metadata in wiki_apply claim evidence", () => { const tool = createWikiApplyTool({} as ResolvedMemoryWikiConfig); const applyProperties = asSchemaObject(asSchemaObject(tool.parameters).properties); const claimsSchema = asSchemaObject(applyProperties.claims); const claimSchema = asSchemaObject(claimsSchema.items); const claimProperties = asSchemaObject(claimSchema.properties); const evidenceSchema = asSchemaObject(claimProperties.evidence); const evidenceArraySchema = asSchemaObject(evidenceSchema.items); const evidenceProperties = asSchemaObject(evidenceArraySchema.properties); expect(Object.keys(evidenceProperties).toSorted()).toEqual([ "confidence", "kind", "lines", "note", "path", "privacyTier", "sourceId", "updatedAt", "weight", ]); expect(evidenceProperties.confidence).toEqual({ type: "number", minimum: 0, maximum: 1 }); }); it("returns tool-safe relative report paths from wiki_lint", async () => { const { rootDir, config } = await harness.createVault({ initialize: true }); await fs.mkdir(path.join(rootDir, "syntheses"), { recursive: true }); await fs.writeFile( path.join(rootDir, "syntheses", "bad.md"), [ "---", "id: synth-bad", "pageType: synthesis", "title: Bad Page", "---", "", "This links to [[Missing Page]].", ].join("\n"), "utf8", ); const tool = createWikiLintTool(config); const result = await tool.execute("lint-call", {}); const text = result.content.find((part) => part.type === "text")?.text ?? ""; const details = asSchemaObject(result.details); expect(text).toContain("Report: reports/lint.md"); expect(text).not.toContain(rootDir); expect(details.reportPath).toBe("reports/lint.md"); expect(details).not.toHaveProperty("vaultRoot"); expect(JSON.stringify(details)).not.toContain(rootDir); expect(asSchemaObject(details.issuesByCategory).links).toEqual( expect.arrayContaining([expect.objectContaining({ code: "broken-wikilink" })]), ); const lintResult = await lintMemoryWikiVault(config); expect(path.isAbsolute(lintResult.reportPath)).toBe(true); expect(lintResult.reportPath).toContain(rootDir); }); });