Files
Merlin's CatGitHubCopilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>MerlinHCopilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
9fa9ac25a4 feat: add workflow eval framework (#32)
* feat: add workflow eval framework

Add workflow evaluation scenarios, rubrics, schemas, and runner scripts for installed Truthmark workflows.

Move research notes under docs/research and migrate tests from Vitest to node:test.

* Potential fix for pull request finding 'CodeQL / Replacement of a substring with itself'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: MerlinH <merlinh221@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-06-30 20:57:55 +10:00

254 lines
6.2 KiB
TypeScript

import { afterEach, describe, it } from "node:test";
import { expect } from "expect";
import { validateEvidenceReferences } from "../../src/evidence/validate.js";
import { createTempRepo, type TempRepo } from "../helpers/temp-repo.js";
describe("validateEvidenceReferences", () => {
const repos: TempRepo[] = [];
afterEach(async () => {
await Promise.all(repos.splice(0).map((repo) => repo.cleanup()));
});
it("reports deleted referenced files", async () => {
const repo = await createTempRepo();
repos.push(repo);
await repo.writeFile(
"docs/truthmark/truth/sample.md",
"---\nstatus: active\nsource_of_truth:\n - ../../src/missing.ts\n---\n# Sample\n",
);
const diagnostics = await validateEvidenceReferences(repo.rootDir, [
"docs/truthmark/truth/sample.md",
]);
expect(diagnostics).toContainEqual(
expect.objectContaining({
category: "source-traceability",
severity: "error",
file: "docs/truthmark/truth/sample.md",
}),
);
});
it("accepts source_of_truth glob references that match repository files", async () => {
const repo = await createTempRepo();
repos.push(repo);
await repo.writeFile("src/index.ts", "export const value = 1;\n");
await repo.writeFile(
"docs/truthmark/truth/sample.md",
"---\nstatus: active\nsource_of_truth:\n - ../../../src/**/*.ts\n---\n# Sample\n",
);
const diagnostics = await validateEvidenceReferences(repo.rootDir, [
"docs/truthmark/truth/sample.md",
]);
expect(diagnostics).toEqual([]);
});
it("resolves bare source_of_truth filenames relative to the truth doc", async () => {
const repo = await createTempRepo();
repos.push(repo);
await repo.writeFile("docs/truthmark/truth/overview.md", "# Overview\n");
await repo.writeFile(
"docs/truthmark/truth/sample.md",
"---\nstatus: active\nsource_of_truth:\n - overview.md\n---\n# Sample\n",
);
const diagnostics = await validateEvidenceReferences(repo.rootDir, [
"docs/truthmark/truth/sample.md",
]);
expect(diagnostics).toEqual([]);
});
it("validates final Source References bullets as traceability evidence", async () => {
const repo = await createTempRepo();
repos.push(repo);
await repo.writeFile("src/index.ts", "export const value = 1;\n");
await repo.writeFile(
"docs/truthmark/truth/valid.md",
`---
status: active
truth_kind: engineering-behavior
last_reviewed: 2026-06-14
---
# Valid
## Current Implementation Behavior
Uses the current source file.
## Source References
- ../../../src/index.ts
`,
);
await repo.writeFile(
"docs/truthmark/truth/missing.md",
`---
status: active
truth_kind: engineering-behavior
last_reviewed: 2026-06-14
---
# Missing
## Current Implementation Behavior
References a missing file.
## Source References
- ../../../src/missing.ts
`,
);
const diagnostics = await validateEvidenceReferences(repo.rootDir, [
"docs/truthmark/truth/valid.md",
"docs/truthmark/truth/missing.md",
]);
expect(diagnostics).toContainEqual(
expect.objectContaining({
category: "source-traceability",
severity: "error",
file: "docs/truthmark/truth/missing.md",
}),
);
expect(diagnostics).not.toContainEqual(
expect.objectContaining({
file: "docs/truthmark/truth/valid.md",
}),
);
});
it("reports evidence line spans outside the file even without a content hash", async () => {
const repo = await createTempRepo();
repos.push(repo);
await repo.writeFile("src/index.ts", "export const value = 1;\n");
await repo.writeFile(
"docs/truthmark/truth/sample.md",
`---
status: active
---
# Sample
\`\`\`yaml
evidence:
- path: ../../../src/index.ts
start_line: 10
end_line: 12
\`\`\`
`,
);
const diagnostics = await validateEvidenceReferences(repo.rootDir, [
"docs/truthmark/truth/sample.md",
]);
expect(diagnostics).toContainEqual(
expect.objectContaining({
category: "source-traceability",
severity: "error",
file: "docs/truthmark/truth/sample.md",
message: expect.stringContaining("outside the file"),
}),
);
});
it("treats evidence symbols as non-normative metadata", async () => {
const repo = await createTempRepo();
repos.push(repo);
await repo.writeFile("src/index.ts", "export const value = 1;\n");
await repo.writeFile(
"docs/truthmark/truth/symbol.md",
`---
status: active
---
# Symbol metadata
\`\`\`yaml
evidence:
- path: ../../../src/index.ts
symbol: missingSymbol
\`\`\`
`,
);
const diagnostics = await validateEvidenceReferences(repo.rootDir, [
"docs/truthmark/truth/symbol.md",
]);
expect(diagnostics).toEqual([]);
});
it("ignores malformed non-evidence YAML while reporting malformed evidence YAML", async () => {
const repo = await createTempRepo();
repos.push(repo);
await repo.writeFile("src/index.ts", "export const value = 1;\n");
await repo.writeFile(
"docs/truthmark/truth/non-evidence.md",
`---
status: active
source_of_truth:
- ../../../src/index.ts
---
# Non-evidence YAML
\`\`\`yaml
example:
- value: [
\`\`\`
`,
);
await repo.writeFile(
"docs/truthmark/truth/evidence.md",
`---
status: active
source_of_truth:
- ../../../src/index.ts
---
# Evidence YAML
\`\`\`yaml
evidence:
- path: ../../../src/index.ts
start_line: [
\`\`\`
`,
);
const diagnostics = await validateEvidenceReferences(repo.rootDir, [
"docs/truthmark/truth/non-evidence.md",
"docs/truthmark/truth/evidence.md",
]);
expect(diagnostics).toContainEqual(
expect.objectContaining({
category: "source-traceability",
severity: "error",
file: "docs/truthmark/truth/evidence.md",
message: expect.stringContaining("Malformed evidence YAML block"),
}),
);
expect(diagnostics).not.toContainEqual(
expect.objectContaining({
category: "source-traceability",
severity: "error",
file: "docs/truthmark/truth/non-evidence.md",
message: expect.stringContaining("Malformed evidence YAML block"),
}),
);
});
});