208 lines
5.7 KiB
JavaScript
208 lines
5.7 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { after, before, test } from "node:test";
|
|
|
|
import { createServer } from "vite";
|
|
|
|
let server;
|
|
let parseE30HumanReviewDraft;
|
|
let parseE30HumanReviewFinalized;
|
|
let createOrResumeE30HumanReview;
|
|
let saveE30HumanReviewDecision;
|
|
let finalizeE30HumanReview;
|
|
let E30ReviewContractError;
|
|
|
|
const resultId = `e30-materialization-${"a".repeat(64)}`;
|
|
const engineeringGenerationId =
|
|
`e30-engineering-generation-${"b".repeat(64)}`;
|
|
const draftId = `e30-human-draft-${"c".repeat(64)}`;
|
|
const reviewGenerationId = `e30-review-generation-${"d".repeat(64)}`;
|
|
const firstItemId = `e30-review-item-${"e".repeat(64)}`;
|
|
const secondItemId = `e30-review-item-${"f".repeat(64)}`;
|
|
const firstEventId = `e30-review-event-${"1".repeat(64)}`;
|
|
const secondEventId = `e30-review-event-${"2".repeat(64)}`;
|
|
|
|
function decision(overrides = {}) {
|
|
return {
|
|
item_id: firstItemId,
|
|
source_stratum: "conflict",
|
|
disposition: "object-present",
|
|
notes: null,
|
|
event_id: firstEventId,
|
|
decided_at_utc: "2026-07-27T06:00:00Z",
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
function draft(overrides = {}) {
|
|
return {
|
|
schema_version: "missioncore.e30-human-review-draft/v2",
|
|
draft_id: draftId,
|
|
materialization_id: resultId,
|
|
engineering_generation_id: engineeringGenerationId,
|
|
reviewer_id: "DC",
|
|
created_at_utc: "2026-07-27T06:00:00Z",
|
|
state: "active",
|
|
revision: 1,
|
|
item_count: 2,
|
|
reviewed_item_count: 1,
|
|
remaining_item_count: 1,
|
|
disposition_distribution: { "object-present": 1 },
|
|
generation_id: null,
|
|
decisions: [decision()],
|
|
lab_published: false,
|
|
access: "review-write",
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
function finalized() {
|
|
return {
|
|
schema_version: "missioncore.laboratory-e30-human-review-finalized/v2",
|
|
draft: draft({
|
|
state: "finalized",
|
|
revision: 2,
|
|
reviewed_item_count: 2,
|
|
remaining_item_count: 0,
|
|
disposition_distribution: {
|
|
"object-present": 1,
|
|
"background-or-noise": 1,
|
|
},
|
|
generation_id: reviewGenerationId,
|
|
decisions: [
|
|
decision(),
|
|
decision({
|
|
item_id: secondItemId,
|
|
source_stratum: "unknown",
|
|
disposition: "background-or-noise",
|
|
event_id: secondEventId,
|
|
}),
|
|
],
|
|
access: "read-only",
|
|
}),
|
|
generation: {
|
|
schema_version: "missioncore.e30-human-review-generation/v2",
|
|
generation_id: reviewGenerationId,
|
|
materialization_id: resultId,
|
|
engineering_generation_id: engineeringGenerationId,
|
|
reviewer_id: "DC",
|
|
created_at_utc: "2026-07-27T06:05:00Z",
|
|
item_count: 2,
|
|
disposition_distribution: {
|
|
"object-present": 1,
|
|
"background-or-noise": 1,
|
|
},
|
|
coverage: {
|
|
expected_item_count: 2,
|
|
reviewed_item_count: 2,
|
|
complete: true,
|
|
},
|
|
human_review_complete: true,
|
|
lab_published: false,
|
|
access: "read-only",
|
|
},
|
|
};
|
|
}
|
|
|
|
before(async () => {
|
|
server = await createServer({
|
|
appType: "custom",
|
|
logLevel: "silent",
|
|
server: { middlewareMode: true },
|
|
});
|
|
({
|
|
parseE30HumanReviewDraft,
|
|
parseE30HumanReviewFinalized,
|
|
createOrResumeE30HumanReview,
|
|
saveE30HumanReviewDecision,
|
|
finalizeE30HumanReview,
|
|
} = await server.ssrLoadModule(
|
|
"/src/core/laboratory/e30HumanReview.ts",
|
|
));
|
|
({ E30ReviewContractError } = await server.ssrLoadModule(
|
|
"/src/core/laboratory/e30Review.ts",
|
|
));
|
|
});
|
|
|
|
after(async () => {
|
|
await server?.close();
|
|
});
|
|
|
|
test("decodes an exception-only draft and immutable final generation", () => {
|
|
const active = parseE30HumanReviewDraft(draft());
|
|
const complete = parseE30HumanReviewFinalized(finalized());
|
|
|
|
assert.equal(active.engineeringGenerationId, engineeringGenerationId);
|
|
assert.equal(active.reviewedItemCount, 1);
|
|
assert.equal(active.decisions[0].disposition, "object-present");
|
|
assert.equal(complete.draft.state, "finalized");
|
|
assert.equal(complete.generation.humanReviewComplete, true);
|
|
assert.equal(complete.generation.labPublished, false);
|
|
});
|
|
|
|
test("rejects unknown dispositions and finalized writable access", () => {
|
|
assert.throws(
|
|
() => parseE30HumanReviewDraft(draft({
|
|
decisions: [decision({ disposition: "invented" })],
|
|
})),
|
|
E30ReviewContractError,
|
|
);
|
|
assert.throws(
|
|
() => parseE30HumanReviewDraft(draft({
|
|
state: "finalized",
|
|
access: "review-write",
|
|
})),
|
|
E30ReviewContractError,
|
|
);
|
|
});
|
|
|
|
test("uses generation-bound write endpoints and explicit finalization", async () => {
|
|
const requests = [];
|
|
const fetcher = async (input, init) => {
|
|
const body = init?.body ? JSON.parse(String(init.body)) : null;
|
|
requests.push({ input: String(input), method: init?.method, body });
|
|
const payload = String(input).includes("/finalize?")
|
|
? finalized()
|
|
: draft();
|
|
return new Response(JSON.stringify(payload), {
|
|
status: 200,
|
|
headers: { "Content-Type": "application/json" },
|
|
});
|
|
};
|
|
|
|
await createOrResumeE30HumanReview(
|
|
resultId,
|
|
engineeringGenerationId,
|
|
"DC",
|
|
{ fetcher },
|
|
);
|
|
await saveE30HumanReviewDecision(
|
|
resultId,
|
|
engineeringGenerationId,
|
|
draftId,
|
|
firstItemId,
|
|
{
|
|
expectedRevision: 1,
|
|
idempotencyKey: "ui-decision-001",
|
|
disposition: "insufficient-evidence",
|
|
notes: null,
|
|
},
|
|
{ fetcher },
|
|
);
|
|
await finalizeE30HumanReview(
|
|
resultId,
|
|
engineeringGenerationId,
|
|
draftId,
|
|
2,
|
|
{ fetcher },
|
|
);
|
|
|
|
assert.equal(requests[0].method, "POST");
|
|
assert.deepEqual(requests[0].body, {
|
|
reviewer_id: "DC",
|
|
engineering_generation_id: engineeringGenerationId,
|
|
});
|
|
assert.match(requests[1].input, /engineering_generation_id=/);
|
|
assert.equal(requests[1].body.disposition, "insufficient-evidence");
|
|
assert.equal(requests[2].body.confirm_generation, true);
|
|
});
|