129 lines
5.5 KiB
TypeScript
129 lines
5.5 KiB
TypeScript
// T165 WP1 parser conformance fixtures derived from the cited Machine contract.
|
|
|
|
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import { dirname, join } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import { test } from "node:test";
|
|
|
|
import { parseExecutiveUpdate, validateAttestedGoalReport } from "../lib/executive-update.ts";
|
|
import type { GoalPolicyPublication } from "../../mosaic-core/lib/goal-policy.ts";
|
|
|
|
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
const CONTRACT = readFileSync(join(HERE, "fixtures", "skills-local", "ms-executive-update", "SKILL.md"), "utf8");
|
|
const NO_CHANGE = "No change since T165; still waiting on T165.";
|
|
|
|
const UPDATE = [
|
|
"Just Completed:",
|
|
"",
|
|
"* T165: completed contracts",
|
|
"",
|
|
"Next Step:",
|
|
"",
|
|
"* `fleet/extensions/goal/index.ts`: validate policy",
|
|
"",
|
|
"Blocked:",
|
|
"",
|
|
"* GOAL-PROACTIVE-LOOP-REV-Q107: review complete \u2014 nothing from you",
|
|
"",
|
|
].join("\n");
|
|
|
|
function publication(resolver: GoalPolicyPublication["resolver"]): GoalPolicyPublication {
|
|
return {
|
|
attestation: Object.freeze({
|
|
schemaVersion: 1,
|
|
role: "plan-ng",
|
|
roleRevision: 4,
|
|
manifestSha256: "a".repeat(64),
|
|
format: "ms-executive-update/v1",
|
|
contractPath: "skills-local/ms-executive-update/SKILL.md",
|
|
contractSection: "Machine contract (for `goal_report` payloads and any parser)",
|
|
contractBlob: "df30c6fbb54b4a65a298c9e51c07f742610d171c",
|
|
contractSha256: "bbea48a46b1f8da7bc759f86856fb52830b7dde456b826317163c6dc6ccab319",
|
|
enforcement: "pre-state-change-fail-closed",
|
|
identifierResolution: "consumer-fail-closed",
|
|
launchGeneration: 1,
|
|
incarnationId: "inc-goal-parser",
|
|
}),
|
|
resolver,
|
|
};
|
|
}
|
|
|
|
function resolved(options: { changed?: boolean; evidence?: string | null; frozen?: boolean } = {}) {
|
|
const value = {
|
|
outcome: "resolved" as const,
|
|
objectId: "tracked-object",
|
|
objectSha256: "b".repeat(64),
|
|
changedSincePreviousAcceptedReport: options.changed ?? true,
|
|
completionEvidenceId: options.evidence === undefined ? "immutable-evidence" : options.evidence,
|
|
};
|
|
return options.frozen === false ? value : Object.freeze(value);
|
|
}
|
|
|
|
test("C7: cited Machine contract remains the parser's one input authority", () => {
|
|
assert.equal(CONTRACT.includes("## Machine contract (for `goal_report` payloads and any parser)"), true);
|
|
assert.equal(CONTRACT.includes("update := section(\"Just Completed\")"), true);
|
|
const parsed = parseExecutiveUpdate(UPDATE);
|
|
assert.equal(parsed.ok, true, parsed.ok ? "" : parsed.reason);
|
|
if (parsed.ok) {
|
|
assert.deepEqual(parsed.items.map((item) => [item.section, item.token]), [
|
|
["Just Completed", "T165"],
|
|
["Next Step", "`fleet/extensions/goal/index.ts`"],
|
|
["Blocked", "GOAL-PROACTIVE-LOOP-REV-Q107"],
|
|
]);
|
|
}
|
|
});
|
|
|
|
test("C7: heading, LF, identifier, bullet count, and Blocked disposition violations reject", () => {
|
|
const tooMany = [
|
|
"Just Completed:", "", "* none", "", "Next Step:", "",
|
|
"* T1: one", "* T2: two", "* T3: three", "* T4: four", "* T5: five", "* T6: six",
|
|
"", "Blocked:", "", "* T1: none \u2014 nothing from you", "",
|
|
].join("\n");
|
|
for (const invalid of [
|
|
UPDATE.replace("Just Completed:", "just completed:"),
|
|
UPDATE.replace("\n", "\r\n"),
|
|
UPDATE.replace("T165", "task-165"),
|
|
UPDATE.replace("\u2014 nothing from you", "waiting"),
|
|
UPDATE.slice(0, -1),
|
|
tooMany,
|
|
]) {
|
|
assert.equal(parseExecutiveUpdate(invalid).ok, false);
|
|
}
|
|
});
|
|
|
|
test("C8: zero, multiple, unavailable, stale, malformed, and unproven completions reject", async () => {
|
|
for (const outcome of ["zero", "multiple", "unavailable", "stale"] as const) {
|
|
const result = await validateAttestedGoalReport(UPDATE, publication(async () => Object.freeze({ outcome })), "in_progress");
|
|
assert.equal(result.ok, false, outcome);
|
|
}
|
|
assert.equal((await validateAttestedGoalReport(UPDATE, publication(async () => resolved({ frozen: false }) as never), "in_progress")).ok, false);
|
|
assert.equal((await validateAttestedGoalReport(UPDATE, publication(async () => resolved({ evidence: null })), "in_progress")).ok, false);
|
|
assert.equal((await validateAttestedGoalReport(UPDATE, publication(async () => resolved({ changed: false })), "in_progress")).ok, false);
|
|
assert.equal((await validateAttestedGoalReport(UPDATE, publication(async () => resolved()), "in_progress")).ok, true);
|
|
});
|
|
|
|
test("Q118/F5: contract-authorized no-change form is status-aware and requires unchanged tracked state", async () => {
|
|
const parsed = parseExecutiveUpdate(NO_CHANGE);
|
|
assert.equal(parsed.ok, true);
|
|
if (parsed.ok) {
|
|
assert.equal(parsed.kind, "no-change");
|
|
assert.deepEqual(parsed.items.map((item) => [item.section, item.token]), [["Next Step", "T165"], ["Next Step", "T165"]]);
|
|
}
|
|
|
|
let resolverCalls = 0;
|
|
const unchanged = publication(async () => {
|
|
resolverCalls += 1;
|
|
return resolved({ changed: false, evidence: null });
|
|
});
|
|
assert.equal((await validateAttestedGoalReport(NO_CHANGE, unchanged, "in_progress")).ok, true);
|
|
assert.equal(resolverCalls, 2, "both no-change references resolve through the attested consumer");
|
|
|
|
resolverCalls = 0;
|
|
const terminal = await validateAttestedGoalReport(NO_CHANGE, unchanged, "satisfied");
|
|
assert.equal(terminal.ok, false, "no-change is never a terminal report");
|
|
assert.equal(resolverCalls, 0, "wrong status rejects before resolver or Goal state mutation");
|
|
|
|
assert.equal((await validateAttestedGoalReport(NO_CHANGE, publication(async () => resolved({ changed: true })), "in_progress")).ok, false);
|
|
});
|