7c4d3ed79f
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
57 lines
2.1 KiB
TypeScript
57 lines
2.1 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import { emptyArtifact, serializeArtifact, type Artifact } from "../src/model";
|
|
import { expectValidSidecar, validateSidecar } from "./helpers/validateSidecar";
|
|
|
|
function fullArtifact(): Artifact {
|
|
const a = emptyArtifact("docs/x.md");
|
|
a.anchors["a_1"] = { fingerprint: { text: "alpha", before: "", after: " beta", lineHint: 0 } };
|
|
a.threads.push({
|
|
id: "t_1",
|
|
anchorId: "a_1",
|
|
status: "open",
|
|
messages: [{ id: "m_1", author: { kind: "human", id: "ben" }, body: "hi", createdAt: "2026-06-10T00:00:00.000Z" }],
|
|
});
|
|
a.attributions.push({
|
|
id: "at_1",
|
|
anchorId: "a_1",
|
|
author: { kind: "agent", id: "claude", agent: { sdk: "@cline/sdk", model: "sonnet", sessionId: "run-1" } },
|
|
createdAt: "2026-06-10T00:00:00.000Z",
|
|
updatedAt: "2026-06-10T00:00:00.000Z",
|
|
turnId: "turn-1",
|
|
});
|
|
a.proposals.push({
|
|
id: "p_1",
|
|
anchorId: "a_1",
|
|
replacement: "ALPHA",
|
|
author: { kind: "agent", id: "claude", agent: { sdk: "@cline/sdk", model: "sonnet", sessionId: "run-1" } },
|
|
createdAt: "2026-06-10T00:00:00.000Z",
|
|
instruction: "shout",
|
|
});
|
|
return a;
|
|
}
|
|
|
|
describe("coauthoring-sidecar JSON Schema (F5 SLICE-1, PUC-5)", () => {
|
|
it("validates the empty artifact and a full artifact", () => {
|
|
expectValidSidecar(emptyArtifact("docs/x.md"));
|
|
expectValidSidecar(fullArtifact());
|
|
});
|
|
|
|
it("rejects a structurally broken sidecar with error paths", () => {
|
|
const broken = JSON.parse(serializeArtifact(fullArtifact()));
|
|
broken.threads[0].status = "closed"; // not in the enum
|
|
delete broken.schemaVersion;
|
|
const { valid, errors } = validateSidecar(broken);
|
|
expect(valid).toBe(false);
|
|
expect(errors.some((e) => e.includes("schemaVersion"))).toBe(true);
|
|
});
|
|
|
|
it("accepts unknown fields everywhere (forward compat, INV-16)", () => {
|
|
const data = JSON.parse(serializeArtifact(fullArtifact()));
|
|
data.futureSection = [{ id: "f_1" }];
|
|
data.threads[0].futureField = true;
|
|
data.threads[0].messages[0].reactions = ["+1"];
|
|
const { valid } = validateSidecar(data);
|
|
expect(valid).toBe(true);
|
|
});
|
|
});
|