Files
stack/scripts/foundation/fixtures/build-fixtures.mjs
T
jason.woltje 8ebddd6f93 feat(foundation): offline synthetic scope/permission inspector (FI-FILBERT-8 APPROVED r6)
Rocko-authored, Filbert-reviewed inspector (r6 manifest
a4a44930...) with full review/build/verdict evidence under
docs/plans/reviews. 43/0 selftests, oracle zero-disagreement,
foundation checker PASS. Owner A9 acceptance recorded separately.
2026-09-07 14:06:35 -05:00

1365 lines
87 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Deterministic fixture generator for the foundation synthetic inspector.
*
* node scripts/foundation/fixtures/build-fixtures.mjs <output-dir>
*
* Writes bundles/<name>.json (one per case), raw/<name>.json (byte-exact lexical
* cases), index.json (expected verdict per case) and demo/*.json (owner demo).
* The checked-in copies under scripts/foundation/fixtures/ must equal a fresh run;
* scripts/test-foundation.sh regenerates into a scratch directory and diffs.
*
* Everything here is synthetic. No live identities, credentials or paths.
*/
import { writeFileSync, mkdirSync } from "node:fs";
import { join } from "node:path";
import { createHash } from "node:crypto";
import { digestOf } from "../canonical.mjs";
import { OPERATION_CATALOG } from "../resolve.mjs";
const AUTH = "00000000-0000-4000-8000-000000000001";
const AUTH_2 = "00000000-0000-4000-8000-000000000002";
const AUTH_UNDECLARED = "00000000-0000-4000-8000-000000000099"; // well-formed, never declared (FI-FILBERT-6 F1)
const T = "2026-09-06T03:00:00.000Z";
const OWNER = { kind: "human", principalId: "owner", executionId: null };
function fakeDigest(label) {
return `sha256:${createHash("sha256").update(`synthetic:${label}`).digest("hex")}`;
}
// ---------------------------------------------------------------------------
// Restrictions and registries
// ---------------------------------------------------------------------------
const ROOT = { root: "workspace", path: null };
const NO_NET = { network: "none", endpointRefs: [] };
function restrictions(operations, readPaths, writePaths) {
return { operations, readPaths, writePaths, ...NO_NET };
}
const R_FULL = restrictions([...OPERATION_CATALOG], [ROOT], [ROOT]);
const R_READER = restrictions(["work.read", "file.read"], [ROOT], []);
const R_WRITER = restrictions(["work.read", "file.read", "file.change"], [ROOT], [{ root: "workspace", path: "src" }]);
const R_MANAGER = restrictions(["work.read", "file.read", "file.change", "assignment.change"], [ROOT], [ROOT]);
const R_NO_WORK = restrictions(["file.read", "file.change"], [ROOT], [ROOT]);
const R_NO_DELEGATE = restrictions(["work.read", "file.read", "file.change"], [ROOT], [ROOT]);
const R_NO_FILE_READ = restrictions(["work.read", "file.change"], [ROOT], [ROOT]);
function contentEntry(registry, id, revision, r) {
const content = { restrictions: r };
return { registry, id, revision, digest: digestOf(content), content };
}
function plainEntry(registry, id, revision) {
return { registry, id, revision, digest: fakeDigest(`${registry}/${id}/${revision}`) };
}
function regRef(entry) {
return { registry: entry.registry, id: entry.id, revision: entry.revision, digest: entry.digest };
}
const REG = {
harness: plainEntry("harness", "pi", 1),
settings: plainEntry("settings", "default", 1),
soul: plainEntry("context-content", "soul", 1),
apFull: contentEntry("agent-policy", "ap-full", 1, R_FULL),
apReader: contentEntry("agent-policy", "ap-reader", 1, R_READER),
roleReader: contentEntry("scope-role", "role-reader", 1, R_READER),
roleWriter: contentEntry("scope-role", "role-writer", 1, R_WRITER),
roleManager: contentEntry("scope-role", "role-manager", 1, R_MANAGER),
ppP1: contentEntry("project-policy", "pp-p1", 1, R_FULL),
ppP2: contentEntry("project-policy", "pp-p2", 1, R_FULL),
};
const ART_1 = { runId: "run-1", artifactId: "art-1", digest: fakeDigest("art-1") };
const ART_2 = { runId: "run-1", artifactId: "art-2", digest: fakeDigest("art-2") };
// ---------------------------------------------------------------------------
// Records
// ---------------------------------------------------------------------------
const SYSTEM = { kind: "system" };
const P1 = { kind: "project", projectId: "p1" };
const P2 = { kind: "project", projectId: "p2" };
const W1 = { kind: "workspace", projectId: "p1", workspaceId: "w1" };
const W2 = { kind: "workspace", projectId: "p1", workspaceId: "w2" };
const W3 = { kind: "workspace", projectId: "p2", workspaceId: "w3" };
function rec(kind, id, scope, payload, extra = {}) {
return {
schemaVersion: 1,
kind,
id,
scope,
revision: 1,
createdAt: T,
createdBy: OWNER,
supersedes: null,
authorizationRef: AUTH,
payload,
...extra,
};
}
function ref(r) {
return { kind: r.kind, id: r.id, scope: r.scope, revision: r.revision };
}
function agent(id, policy) {
return rec("agent-definition", id, SYSTEM, {
displayName: `Agent ${id}`,
agentType: "worker",
harnessRef: regRef(REG.harness),
settingsRef: regRef(REG.settings),
soulRef: regRef(REG.soul),
instructionRefs: [],
skillRefs: [],
policyRef: regRef(policy),
status: "enabled",
});
}
function project(scope, policy) {
return rec("project", scope.projectId, scope, { displayName: `Project ${scope.projectId}`, policyRef: regRef(policy), status: "active" });
}
function workspace(scope, policy) {
return rec("workspace", scope.workspaceId, scope, {
displayName: `Workspace ${scope.workspaceId}`, policyRef: regRef(policy), status: "active", fileRootId: `root-${scope.workspaceId}`,
});
}
function registration(id, scope, agentId, role, parent) {
return rec("registration", id, scope, {
agentId,
scopeRoleRef: regRef(role),
restrictions: null,
projectRegistrationRef: parent ? ref(parent) : null,
status: "active",
delegationRef: null,
});
}
function decision(id, scope, decisionKind, subjectRefs, extra = {}) {
return rec("decision", id, scope, {
decisionKind,
subjectRefs,
outcome: "approved",
basisRef: ART_1,
evidenceRefs: [ART_2],
delegatedOperations: [],
...extra,
});
}
function mission(id, scope, parent) {
return rec("mission", id, scope, {
objective: `Mission ${id}`,
criteria: [{ id: "c1", text: "done" }],
parentMissionRef: parent ? ref(parent) : null,
restrictions: null,
status: "active",
});
}
function task(id, scope, missionRec, intentId, status, deps = []) {
return rec("task", id, scope, {
purpose: `Task ${id}`,
criteria: [{ id: "c1", text: "done" }],
missionRef: missionRec ? ref(missionRec) : null,
intentRef: { kind: "decision", id: intentId, scope, revision: 1 },
dependencies: deps.map(ref),
restrictions: null,
status,
});
}
function assignment(id, scope, taskRec, agentId, intentId) {
return rec("assignment", id, scope, {
taskRef: ref(taskRec),
agentId,
intentRef: { kind: "decision", id: intentId, scope, revision: 1 },
status: "selected",
endReason: null,
});
}
function buildBase() {
const agentA = agent("agent-a", REG.apFull);
const agentB = agent("agent-b", REG.apFull);
const p1 = project(P1, REG.ppP1);
const p2 = project(P2, REG.ppP2);
const w1 = workspace(W1, REG.ppP1);
const w2 = workspace(W2, REG.ppP1);
const w3 = workspace(W3, REG.ppP2);
const regAP1 = registration("reg-a-p1", P1, "agent-a", REG.roleWriter, null);
const regAW1 = registration("reg-a-w1", W1, "agent-a", REG.roleWriter, regAP1);
const regBP1 = registration("reg-b-p1", P1, "agent-b", REG.roleManager, null);
const regBW1 = registration("reg-b-w1", W1, "agent-b", REG.roleManager, regBP1);
const regBW2 = registration("reg-b-w2", W2, "agent-b", REG.roleManager, regBP1);
const regBP2 = registration("reg-b-p2", P2, "agent-b", REG.roleManager, null);
const regBW3 = registration("reg-b-w3", W3, "agent-b", REG.roleManager, regBP2);
const mP1 = mission("m-p1", P1, null);
const mW1 = mission("m-w1", W1, mP1);
const mW2 = mission("m-w2", W2, mP1);
const mP2 = mission("m-p2", P2, null);
const taskW1Dep = task("task-w1-dep", W1, null, "d-plan-dep", "accepted");
const taskW1 = task("task-w1", W1, mW1, "d-plan-1", "active", [taskW1Dep]);
const taskW2 = task("task-w2", W2, mW2, "d-plan-w2", "ready");
const taskW1B = task("task-w1-b", W1, null, "d-plan-w1b", "active");
const taskW2B = task("task-w2-b", W2, null, "d-plan-w2b", "active");
const taskW3 = task("task-w3", W3, null, "d-plan-w3", "accepted");
const asgAW1 = assignment("asg-a-w1", W1, taskW1, "agent-a", "d-plan-1");
const asgBW1 = assignment("asg-b-w1", W1, taskW1B, "agent-b", "d-plan-w1b");
const asgBW2 = assignment("asg-b-w2", W2, taskW2B, "agent-b", "d-plan-w2b");
const dPlan1 = decision("d-plan-1", W1, "plan-approval", [ref(taskW1), ref(asgAW1)]);
const dPlanDep = decision("d-plan-dep", W1, "plan-approval", [ref(taskW1Dep)]);
const dPlanW2 = decision("d-plan-w2", W2, "plan-approval", [ref(taskW2)]);
const dPlanW1B = decision("d-plan-w1b", W1, "plan-approval", [ref(taskW1B), ref(asgBW1)]);
const dPlanW2B = decision("d-plan-w2b", W2, "plan-approval", [ref(taskW2B), ref(asgBW2)]);
const dPlanW3 = decision("d-plan-w3", W3, "plan-approval", [ref(taskW3)]);
const dDelegB = decision("d-deleg-b", W1, "delegation", [ref(agentB), ref(asgAW1)], { delegatedOperations: ["assignment.change"] });
const dChange1 = decision("d-change-1", W1, "assignment-change", [ref(asgAW1), ref(taskW2)]);
// Deep-cloned so per-case mutations never leak through shared module-level objects.
return clone({
bundleVersion: 1,
kind: "foundation-inspector-bundle",
simulation: true,
records: [
agentA, agentB, p1, p2, w1, w2, w3,
regAP1, regAW1, regBP1, regBW1, regBW2, regBP2, regBW3,
mP1, mW1, mW2, mP2,
taskW1Dep, taskW1, taskW2, taskW1B, taskW2B, taskW3,
asgAW1, asgBW1, asgBW2,
dPlan1, dPlanDep, dPlanW2, dPlanW1B, dPlanW2B, dPlanW3, dDelegB, dChange1,
],
registries: Object.values(REG),
artifacts: [ART_1, ART_2],
authorizations: [AUTH],
selection: {
agentId: "agent-a",
projectId: "p1",
workspaceId: "w1",
assignmentRef: ref(asgAW1),
execution: { kind: "unrestricted-simulation" },
},
operation: { name: "work.read", target: null },
proposal: null,
delegationInputs: [],
});
}
// ---------------------------------------------------------------------------
// Mutation helpers
// ---------------------------------------------------------------------------
function clone(v) {
return JSON.parse(JSON.stringify(v));
}
function find(b, kind, id) {
const r = b.records.find((x) => x.kind === kind && x.id === id);
if (!r) throw new Error(`fixture: no ${kind} ${id}`);
return r;
}
function findReg(b, id) {
const e = b.registries.find((x) => x.id === id);
if (!e) throw new Error(`fixture: no registry ${id}`);
return e;
}
/** Append revision 2 of a record (supersedes rev 1) with a payload patch; returns it. */
function reviseRecord(b, kind, id, patch) {
const head = find(b, kind, id);
const next = clone(head);
next.revision = 2;
next.supersedes = ref(head);
Object.assign(next.payload, patch);
b.records.push(next);
return next;
}
function fileOp(name, path) {
return { name, target: { root: "workspace", path } };
}
function restricted(r) {
return { kind: "restrictions", restrictions: r };
}
function withRegistrationDelegation(b, ops = ["work.read", "file.read"], ceiling = R_FULL) {
const agentA = find(b, "agent-definition", "agent-a");
const regAW1 = find(b, "registration", "reg-a-w1");
const d = decision("d-deleg-reg", W1, "delegation", [ref(agentA), ref(regAW1)], { delegatedOperations: ops });
b.records.push(d);
regAW1.payload.delegationRef = ref(d);
b.delegationInputs.push({ decisionRef: ref(d), mode: "direct-declared", issuerCeiling: ceiling });
return d;
}
/** Clear every mission/dependency reference so each task is consulted work on its own (F2). */
function clearWorkReferences(b) {
for (const r of b.records) {
if (r.kind === "task") { r.payload.missionRef = null; r.payload.dependencies = []; }
}
}
/**
* F4 witness: a contiguous revision-2 history where task-w1 rev 2 has no dependencies
* and task-w1-dep rev 2 depends on task-w1 rev 2. Exact-reference graphs are acyclic;
* an identity-merged graph would see task-w1 -> task-w1-dep -> task-w1.
*/
function versionedHistory(b) {
const t2 = reviseRecord(b, "task", "task-w1", { dependencies: [] });
const d2 = reviseRecord(b, "task", "task-w1-dep", { dependencies: [ref(t2)] });
const a2 = reviseRecord(b, "assignment", "asg-a-w1", { taskRef: ref(t2) });
const p2 = reviseRecord(b, "decision", "d-plan-1", { subjectRefs: [ref(t2), ref(a2)] });
const pd2 = reviseRecord(b, "decision", "d-plan-dep", { subjectRefs: [ref(d2)] });
t2.payload.intentRef = ref(p2);
a2.payload.intentRef = ref(p2);
d2.payload.intentRef = ref(pd2);
b.selection.assignmentRef = ref(a2);
return { t2, d2, a2, p2, pd2 };
}
function makeProposal(b) {
const asgAW1 = find(b, "assignment", "asg-a-w1");
const taskW2 = find(b, "task", "task-w2");
const dDelegB = find(b, "decision", "d-deleg-b");
const dChange1 = find(b, "decision", "d-change-1");
const asgBW1 = find(b, "assignment", "asg-b-w1");
const asgBW2 = find(b, "assignment", "asg-b-w2");
b.operation = { name: "assignment.change", target: null };
b.proposal = {
kind: "assignment-change",
requesterAgentId: "agent-b",
subjectAssignmentRef: ref(asgAW1),
targetTaskRef: ref(taskW2),
delegationRef: ref(dDelegB),
changeDecisionRef: ref(dChange1),
requesterContexts: {
original: { assignmentRef: ref(asgBW1), execution: { kind: "unrestricted-simulation" } },
target: { assignmentRef: ref(asgBW2), execution: { kind: "unrestricted-simulation" } },
},
};
b.delegationInputs = [{ decisionRef: ref(dDelegB), mode: "direct-declared", issuerCeiling: R_FULL }];
return b;
}
// ---------------------------------------------------------------------------
// Case table
// ---------------------------------------------------------------------------
const ALLOWED = { exit: 0, result: "allowed", reason: "allowed", rule: null, proposalRule: null };
const invalid = (rule, reason = "invalid-request") => ({ exit: 2, result: "invalid", reason, rule, proposalRule: null });
const refused = (rule, reason = "not-authorized") => ({ exit: 3, result: "refused", reason, rule, proposalRule: null });
const proposalRefused = (step, rule, reason = "not-authorized") => ({ exit: 3, result: "refused", reason, rule, proposalRule: step });
const UNRESOLVED = { exit: 3, result: "unresolved", reason: "unknown-effects", rule: "runtime-reconciliation-required", proposalRule: "runtime-reconciliation-required" };
const cases = [];
function add(name, group, expect, mutate) {
const b = buildBase();
mutate(b);
cases.push({ name, group, expect, bundle: b });
}
// --- A1/A2 positives -------------------------------------------------------
add("demo-read-w1", "positive", ALLOWED, () => {});
add("demo-file-read-src", "positive", ALLOWED, (b) => { b.operation = fileOp("file.read", "src/main.mjs"); });
add("demo-file-change-src", "positive", ALLOWED, (b) => { b.operation = fileOp("file.change", "src/main.mjs"); });
add("taskless-work-read", "positive", ALLOWED, (b) => { b.selection.assignmentRef = null; });
add("taskless-file-read", "positive", ALLOWED, (b) => { b.selection.assignmentRef = null; b.operation = fileOp("file.read", "docs/readme.md"); });
add("deleg-approved-file-read", "positive", ALLOWED, (b) => { withRegistrationDelegation(b); b.operation = fileOp("file.read", "src/x.mjs"); });
add("work-parent-project-mission", "positive", ALLOWED, (b) => {
find(b, "task", "task-w1").payload.missionRef = ref(find(b, "mission", "m-p1"));
});
add("p2-inventory-unselected", "positive", ALLOWED, (b) => {
// p2/w3 inventory present but unselected; p2 retired must not matter for a w1 read
find(b, "project", "p2").payload.status = "retired";
});
add("file-read-with-unaccepted-dependency", "positive", ALLOWED, (b) => {
find(b, "task", "task-w1-dep").payload.status = "active";
b.operation = fileOp("file.read", "src/main.mjs");
});
add("execution-restrictions-narrow-ok", "positive", ALLOWED, (b) => {
b.selection.execution = restricted(restrictions(["work.read", "file.read"], [{ root: "workspace", path: "src" }], []));
b.operation = fileOp("file.read", "src/deep/file.txt");
});
add("mission-restrictions-narrow-ok", "positive", ALLOWED, (b) => {
find(b, "mission", "m-w1").payload.restrictions = restrictions(["work.read", "file.read", "file.change"], [ROOT], [{ root: "workspace", path: "src" }]);
b.operation = fileOp("file.change", "src/a.txt");
});
add("registration-restrictions-narrow-ok", "positive", ALLOWED, (b) => {
find(b, "registration", "reg-a-w1").payload.restrictions = restrictions(["work.read", "file.read", "file.change"], [{ root: "workspace", path: "src" }], [ROOT]);
b.operation = fileOp("file.read", "src/b.txt");
});
add("demo-change-w1", "proposal", UNRESOLVED, (b) => { makeProposal(b); });
// --- stage 2: shapes / profile --------------------------------------------
add("shape-unknown-top-field", "shape", invalid("shape-unknown-field"), (b) => { b.extra = 1; });
add("shape-proto-key", "shape", invalid("shape-unknown-field"), (b) => { b.__proto__x = 1; });
add("shape-missing-execution", "shape", invalid("shape-missing-field"), (b) => { delete b.selection.execution; });
add("shape-missing-operation", "shape", invalid("shape-missing-field"), (b) => { delete b.operation; });
add("shape-simulation-false", "shape", invalid("shape-enum-mismatch"), (b) => { b.simulation = false; });
add("shape-bundle-version-2", "shape", invalid("shape-enum-mismatch"), (b) => { b.bundleVersion = 2; });
add("shape-record-unknown-field", "shape", invalid("shape-unknown-field"), (b) => { find(b, "task", "task-w1").payload.note = "x"; });
add("shape-record-missing-field", "shape", invalid("shape-missing-field"), (b) => { delete find(b, "task", "task-w1").payload.criteria; });
add("shape-record-bad-id", "shape", invalid("shape-pattern-mismatch"), (b) => { find(b, "task", "task-w1").id = "Task-W1"; });
add("shape-record-bad-time", "shape", invalid("shape-pattern-mismatch"), (b) => { find(b, "task", "task-w1").createdAt = "2026-09-06T03:00:00Z"; });
add("shape-record-calendar-invalid", "shape", invalid("calendar-invalid"), (b) => { find(b, "task", "task-w1").createdAt = "2026-02-30T03:00:00.000Z"; });
add("shape-record-leap-second", "shape", invalid("calendar-invalid"), (b) => { find(b, "task", "task-w1").createdAt = "2026-06-30T23:59:60.000Z"; });
add("shape-record-status-enum", "shape", invalid("shape-enum-mismatch"), (b) => { find(b, "task", "task-w1").payload.status = "done"; });
add("shape-record-criteria-empty", "shape", invalid("shape-bound-exceeded"), (b) => { find(b, "task", "task-w1").payload.criteria = []; });
add("shape-record-criteria-duplicate", "shape", invalid("shape-unique-violation"), (b) => {
const t = find(b, "task", "task-w1"); t.payload.criteria = [{ id: "c1", text: "done" }, { text: "done", id: "c1" }];
});
add("shape-record-displayname-too-long", "shape", invalid("shape-bound-exceeded"), (b) => { find(b, "project", "p1").payload.displayName = "x".repeat(129); });
add("shape-record-agent-actor-null-execution", "shape", invalid("shape-conditional-mismatch"), (b) => {
find(b, "task", "task-w1").createdBy = { kind: "agent", principalId: "agent-a", executionId: null };
});
add("shape-record-rev1-with-supersedes", "shape", invalid("shape-conditional-mismatch"), (b) => {
const t = find(b, "task", "task-w1"); t.supersedes = ref(t);
});
add("shape-project-registration-with-parent", "shape", invalid("shape-conditional-mismatch"), (b) => {
find(b, "registration", "reg-a-p1").payload.projectRegistrationRef = ref(find(b, "registration", "reg-b-p1"));
});
add("shape-project-mission-with-parent", "shape", invalid("shape-conditional-mismatch"), (b) => {
find(b, "mission", "m-p1").payload.parentMissionRef = ref(find(b, "mission", "m-p2"));
});
add("shape-assignment-ended-without-reason", "shape", invalid("shape-conditional-mismatch"), (b) => {
find(b, "assignment", "asg-b-w2").payload.status = "ended";
});
add("shape-delegation-without-operations", "shape", invalid("shape-conditional-mismatch"), (b) => {
find(b, "decision", "d-deleg-b").payload.delegatedOperations = [];
});
add("shape-plan-with-delegated-operations", "shape", invalid("shape-conditional-mismatch"), (b) => {
find(b, "decision", "d-plan-1").payload.delegatedOperations = ["file.read"];
});
add("shape-restrictions-none-with-endpoints", "shape", invalid("shape-conditional-mismatch"), (b) => {
find(b, "task", "task-w1").payload.restrictions = { operations: ["work.read"], readPaths: [], writePaths: [], network: "none", endpointRefs: [plainEntry("endpoint", "ep", 1)] };
});
add("shape-restrictions-unknown-operation", "shape", invalid("shape-enum-mismatch"), (b) => {
find(b, "task", "task-w1").payload.restrictions = restrictions(["file.delete"], [], []);
});
add("shape-path-grant-absolute", "shape", invalid("path-invalid"), (b) => {
find(b, "task", "task-w1").payload.restrictions = restrictions(["work.read"], [{ root: "workspace", path: "/etc" }], []);
});
add("shape-target-dotdot", "shape", invalid("path-invalid"), (b) => { b.operation = fileOp("file.read", "src/../etc/passwd"); });
add("shape-target-backslash", "shape", invalid("path-invalid"), (b) => { b.operation = fileOp("file.read", "src\\x"); });
add("shape-target-empty-segment", "shape", invalid("path-invalid"), (b) => { b.operation = fileOp("file.read", "src//x"); });
add("shape-target-control-char", "shape", invalid("path-invalid"), (b) => { b.operation = fileOp("file.read", "src/x\u001b[31m"); });
// U+2028 is not Cc/Cf/Cs: the pinned checker accepts it as a path character; the text renderer must escape it on echo.
add("shape-target-line-separator-echo-ok", "positive", ALLOWED, (b) => { b.operation = fileOp("file.read", "src/x\u2028y"); });
add("shape-target-unicode-ok", "positive", ALLOWED, (b) => { b.operation = fileOp("file.read", "src/café/\u{1F600}.txt"); });
add("shape-target-wrong-root", "shape", invalid("shape-enum-mismatch"), (b) => { b.operation = { name: "file.read", target: { root: "home", path: "x" } }; });
add("shape-registry-digest-mismatch", "profile", invalid("registry-digest-mismatch"), (b) => {
findReg(b, "role-writer").content.restrictions.operations.push("command.execute");
});
add("shape-registry-content-non-ascii", "profile", invalid("mock-content-unsupported", "unsupported-capability"), (b) => {
const e = findReg(b, "role-writer"); e.content.restrictions.readPaths = [{ root: "workspace", path: "café" }]; e.digest = fakeDigest("whatever");
});
add("shape-registry-missing-content", "shape", invalid("shape-missing-field"), (b) => { delete findReg(b, "role-writer").content; });
add("shape-registry-plain-with-content", "shape", invalid("shape-unknown-field"), (b) => { findReg(b, "pi").content = { restrictions: R_FULL }; });
add("shape-unsupported-kind-session", "profile", invalid("record-kind-unsupported", "unsupported-kind"), (b) => {
b.records.push({ schemaVersion: 1, kind: "session", id: "s1", scope: W1, revision: 1, createdAt: T, createdBy: OWNER, supersedes: null, authorizationRef: AUTH, payload: {} });
});
add("shape-unknown-kind", "shape", invalid("shape-enum-mismatch"), (b) => {
b.records.push({ schemaVersion: 1, kind: "widget", id: "s1", scope: W1, revision: 1, createdAt: T, createdBy: OWNER, supersedes: null, authorizationRef: AUTH, payload: {} });
});
// --- stage 2 profile: strict typed-string grammar (addendum FI-C2-1) ----------------
// The pinned checker's "$" tolerates exactly one final LF on id/runtimeId/digest values;
// the inspector's schema column reproduces that verdict and the strict profile refuses
// the value before any identity lookup (exit 2, profile-pattern-mismatch). Every other
// line-ending form fails the schema pattern in both implementations.
const LF1 = "\n";
const NEWLINE_VARIANTS = [
["two-final-lf", (v) => `${v}\n\n`], ["crlf", (v) => `${v}\r\n`], ["cr", (v) => `${v}\r`],
["interior-lf", (v) => `${v.slice(0, 3)}\n${v.slice(3)}`],
["u2028", (v) => `${v}\u2028`], ["u2029", (v) => `${v}\u2029`],
];
const PROFILE_MISMATCH = invalid("profile-pattern-mismatch");
const PATTERN_MISMATCH = invalid("shape-pattern-mismatch");
// One site per type family, run through the whole line-ending matrix.
const FAMILY_SITES = [
["id-record-id", (b, f) => { const t = find(b, "task", "task-w1"); t.id = f(t.id); }],
["runtime-id-authorization-ref", (b, f) => { const t = find(b, "task", "task-w1"); t.authorizationRef = f(t.authorizationRef); }],
["digest-registry-ref", (b, f) => { const r = find(b, "project", "p1").payload.policyRef; r.digest = f(r.digest); }],
];
for (const [site, mutate] of FAMILY_SITES) {
add(`profile-${site}-one-final-lf`, "profile", PROFILE_MISMATCH, (b) => mutate(b, (v) => `${v}${LF1}`));
for (const [variant, f] of NEWLINE_VARIANTS) add(`profile-${site}-${variant}`, "shape", PATTERN_MISMATCH, (b) => mutate(b, f));
}
// One final LF at every other typed occurrence: record envelope/payload references,
// unselected inventory, wrapper inventories, selection, proposal and declared inputs.
const ONE_FINAL_LF_SITES = {
"record-scope-project-id": (b) => { find(b, "task", "task-w1").scope.projectId += LF1; },
"record-scope-workspace-id": (b) => { find(b, "task", "task-w1").scope.workspaceId += LF1; },
"record-actor-principal-id": (b) => { find(b, "task", "task-w1").createdBy.principalId += LF1; },
"record-actor-execution-id": (b) => { find(b, "task", "task-w1").createdBy = { kind: "agent", principalId: "agent-a", executionId: `${AUTH}${LF1}` }; },
"record-supersedes-id": (b) => { reviseRecord(b, "task", "task-w1-b", {}).supersedes.id += LF1; },
// Without the LF this is the existing ref-missing-dependency case (record-reference-missing):
// the profile refuses before identity lookup, so the two outcomes stay distinguishable.
"record-dependency-ref-id-dangling": (b) => { find(b, "task", "task-w1").payload.dependencies[0].id = `task-nope${LF1}`; },
"record-registry-ref-id": (b) => { find(b, "project", "p1").payload.policyRef.id += LF1; },
"record-agent-type": (b) => { find(b, "agent-definition", "agent-a").payload.agentType += LF1; },
"record-file-root-id": (b) => { find(b, "workspace", "w1").payload.fileRootId += LF1; },
"record-registration-agent-id": (b) => { find(b, "registration", "reg-a-w1").payload.agentId += LF1; },
"record-assignment-agent-id": (b) => { find(b, "assignment", "asg-a-w1").payload.agentId += LF1; },
"record-criterion-id": (b) => { find(b, "mission", "m-w1").payload.criteria[0].id += LF1; },
"record-decision-subject-ref-id": (b) => { find(b, "decision", "d-plan-1").payload.subjectRefs[0].id += LF1; },
"unselected-record-id": (b) => { find(b, "project", "p2").id += LF1; },
"unselected-record-scope-project-id": (b) => { find(b, "task", "task-w3").scope.projectId += LF1; },
"registry-id": (b) => { findReg(b, "pi").id += LF1; },
"registry-digest-plain": (b) => { findReg(b, "pi").digest += LF1; },
// Content-bearing entry: the pattern profile precedes the content-digest profile.
"registry-digest-content-bearing": (b) => { findReg(b, "role-writer").digest += LF1; },
"artifact-run-id": (b) => { b.artifacts[0].runId += LF1; },
"artifact-id": (b) => { b.artifacts[0].artifactId += LF1; },
"artifact-digest": (b) => { b.artifacts[0].digest += LF1; },
"authorization": (b) => { b.authorizations[0] += LF1; },
"selection-agent-id": (b) => { b.selection.agentId += LF1; },
"selection-project-id": (b) => { b.selection.projectId += LF1; },
"selection-workspace-id": (b) => { b.selection.workspaceId += LF1; },
"selection-assignment-ref-id": (b) => { b.selection.assignmentRef.id += LF1; },
"selection-assignment-ref-scope-workspace-id": (b) => { b.selection.assignmentRef.scope.workspaceId += LF1; },
"proposal-requester-agent-id": (b) => { makeProposal(b); b.proposal.requesterAgentId += LF1; },
"proposal-target-task-ref-id": (b) => { makeProposal(b); b.proposal.targetTaskRef.id += LF1; },
"proposal-requester-context-assignment-ref-id": (b) => { makeProposal(b); b.proposal.requesterContexts.original.assignmentRef.id += LF1; },
"delegation-input-decision-ref-id": (b) => { withRegistrationDelegation(b); b.delegationInputs[0].decisionRef.id += LF1; },
};
for (const [site, mutate] of Object.entries(ONE_FINAL_LF_SITES)) add(`profile-${site}-one-final-lf`, "profile", PROFILE_MISMATCH, mutate);
// Negative control: free-form text with (escaped) newlines is not a typed grammar and stays admitted.
add("profile-escaped-newline-free-text-allowed", "positive", ALLOWED, (b) => {
find(b, "mission", "m-w1").payload.objective = "line one\nline two\n";
find(b, "task", "task-w1").payload.purpose = "multi\r\nline";
});
// time/path keep their existing semantics: a final LF fails the format in both implementations.
add("profile-time-one-final-lf", "shape", PATTERN_MISMATCH, (b) => { find(b, "task", "task-w1").createdAt += LF1; });
add("profile-path-one-final-lf", "shape", invalid("path-invalid"), (b) => { b.operation = fileOp("file.read", `src/main.mjs${LF1}`); });
add("shape-too-many-records", "shape", invalid("shape-bound-exceeded"), (b) => {
for (let i = 0; i < 260; i += 1) b.records.push(decision(`d-bulk-${i}`, W1, "plan-approval", [ref(find(b, "task", "task-w1"))]));
});
add("shape-delegation-input-other-mode", "shape", invalid("shape-enum-mismatch"), (b) => {
b.delegationInputs.push({ decisionRef: ref(find(b, "decision", "d-deleg-b")), mode: "parent-delegation", issuerCeiling: R_FULL });
});
add("shape-delegation-input-parent-ref", "shape", invalid("shape-unknown-field"), (b) => {
b.delegationInputs.push({ decisionRef: ref(find(b, "decision", "d-deleg-b")), mode: "direct-declared", issuerCeiling: R_FULL, parentDelegationRef: null });
});
add("shape-proposal-on-read", "operation", invalid("proposal-not-applicable"), (b) => { makeProposal(b); b.operation = { name: "work.read", target: null }; });
// --- stage 3: duplicates ---------------------------------------------------
add("dup-record-identity", "identity", invalid("duplicate-record-identity"), (b) => { b.records.push(clone(find(b, "task", "task-w1"))); });
add("dup-registry-identity", "identity", invalid("duplicate-registry-identity"), (b) => { b.registries.push(clone(findReg(b, "role-writer"))); });
add("dup-artifact-identity", "identity", invalid("duplicate-artifact-identity"), (b) => { b.artifacts.push({ ...ART_1, digest: fakeDigest("other") }); });
add("dup-authorization", "identity", invalid("duplicate-authorization-id"), (b) => { b.authorizations.push(AUTH); });
add("dup-delegation-input", "identity", invalid("duplicate-delegation-input"), (b) => {
makeProposal(b); b.delegationInputs.push(clone(b.delegationInputs[0]));
});
// --- stage 4: structural refs ---------------------------------------------
add("ref-missing-task-intent", "structure", invalid("record-reference-missing", "missing-state"), (b) => { find(b, "task", "task-w1").payload.intentRef.id = "d-nope"; });
add("ref-missing-selection-assignment", "structure", invalid("record-reference-missing", "missing-state"), (b) => { b.selection.assignmentRef.id = "asg-nope"; });
add("ref-missing-supersedes", "structure", invalid("record-reference-missing", "missing-state"), (b) => {
const t = find(b, "task", "task-w1"); t.revision = 2; t.supersedes = { kind: "task", id: "task-w1", scope: W1, revision: 1 };
});
add("ref-missing-dependency", "structure", invalid("record-reference-missing", "missing-state"), (b) => { find(b, "task", "task-w1").payload.dependencies[0].id = "task-nope"; });
add("ref-missing-decision-subject", "structure", invalid("record-reference-missing", "missing-state"), (b) => { find(b, "decision", "d-plan-1").payload.subjectRefs[0].revision = 7; });
// --- stage 5: cycles -------------------------------------------------------
add("cycle-dependency-self", "cycle", invalid("dependency-cycle"), (b) => { const t = find(b, "task", "task-w1"); t.payload.dependencies = [ref(t)]; });
add("cycle-dependency-pair", "cycle", invalid("dependency-cycle"), (b) => {
const t = find(b, "task", "task-w1"); const d = find(b, "task", "task-w1-dep"); d.payload.dependencies = [ref(t)];
});
add("cycle-mission-self-parent", "cycle", invalid("mission-parent-cycle"), (b) => { const m = find(b, "mission", "m-w1"); m.payload.parentMissionRef = ref(m); });
add("cycle-supersedes-self-rev2", "cycle", invalid("supersedes-cycle"), (b) => {
const t = find(b, "task", "task-w1"); t.revision = 2; t.supersedes = ref(t);
find(b, "assignment", "asg-a-w1").payload.taskRef.revision = 2;
find(b, "decision", "d-plan-1").payload.subjectRefs[0].revision = 2;
});
// --- stage 6: continuity ---------------------------------------------------
add("continuity-revision-gap", "continuity", invalid("revision-chain-gap"), (b) => {
const head = find(b, "task", "task-w1-b");
const r3 = clone(head); r3.revision = 3; r3.supersedes = { kind: "task", id: "task-w1-b", scope: W1, revision: 1 };
b.records.push(r3);
});
add("continuity-supersedes-other-identity", "continuity", invalid("supersedes-mismatch"), (b) => {
const head = find(b, "task", "task-w1-b");
const r2 = clone(head); r2.revision = 2; r2.supersedes = ref(find(b, "task", "task-w2-b"));
b.records.push(r2);
});
// --- stage 7: ownership ----------------------------------------------------
add("own-project-id-scope", "ownership", invalid("project-id-scope-mismatch"), (b) => { find(b, "project", "p2").id = "p9"; });
add("own-workspace-id-scope", "ownership", invalid("workspace-id-scope-mismatch"), (b) => { find(b, "workspace", "w3").id = "w9"; });
add("own-workspace-project-missing", "ownership", invalid("workspace-project-missing", "missing-state"), (b) => {
b.records = b.records.filter((r) => !(r.kind === "project" && r.id === "p2"));
b.records = b.records.filter((r) => !(r.kind === "mission" && r.id === "m-p2"));
});
add("own-registration-parent-other-agent", "ownership", invalid("registration-parent-mismatch"), (b) => {
find(b, "registration", "reg-a-w1").payload.projectRegistrationRef = ref(find(b, "registration", "reg-b-p1"));
});
add("own-registration-parent-other-project", "ownership", invalid("registration-parent-mismatch"), (b) => {
find(b, "registration", "reg-b-w3").payload.projectRegistrationRef = ref(find(b, "registration", "reg-b-p1"));
});
add("own-mission-parent-other-project", "ownership", invalid("mission-parent-scope-mismatch"), (b) => {
find(b, "mission", "m-w1").payload.parentMissionRef = ref(find(b, "mission", "m-p2"));
});
add("own-mission-parent-workspace", "ownership", invalid("mission-parent-scope-mismatch"), (b) => {
find(b, "mission", "m-w1").payload.parentMissionRef = ref(find(b, "mission", "m-w2"));
});
add("own-mission-owning-project-mismatch", "ownership", invalid("mission-owning-project-mismatch"), (b) => {
find(b, "task", "task-w1").payload.missionRef = ref(find(b, "mission", "m-p2"));
});
add("own-assignment-task-other-workspace", "ownership", invalid("assignment-task-scope-mismatch"), (b) => {
find(b, "assignment", "asg-a-w1").payload.taskRef = ref(find(b, "task", "task-w2"));
});
// --- stage 8: operation ----------------------------------------------------
add("op-unknown-name", "operation", invalid("operation-unknown"), (b) => { b.operation = { name: "file.delete", target: null }; });
add("op-unsupported-catalog", "operation", invalid("operation-unsupported", "unsupported-capability"), (b) => { b.operation = { name: "command.execute", target: null }; });
add("op-unsupported-workspace-retire", "operation", invalid("operation-unsupported", "unsupported-capability"), (b) => { b.operation = { name: "workspace.retire", target: null }; });
add("op-work-read-with-target", "operation", invalid("operation-target-mismatch"), (b) => { b.operation = fileOp("work.read", "x"); });
add("op-file-read-without-target", "operation", invalid("operation-target-mismatch"), (b) => { b.operation = { name: "file.read", target: null }; });
add("op-change-without-proposal", "operation", invalid("proposal-required"), (b) => { b.operation = { name: "assignment.change", target: null }; });
// --- stage 9: admission ----------------------------------------------------
add("adm-selected-agent-missing", "admission", invalid("selected-agent-missing", "missing-state"), (b) => { b.selection.agentId = "agent-z"; b.selection.assignmentRef = null; });
add("adm-selected-project-missing", "admission", invalid("selected-project-missing", "missing-state"), (b) => {
b.selection.projectId = "p9"; b.selection.workspaceId = "w9"; b.selection.assignmentRef = null;
});
add("adm-selected-workspace-missing", "admission", invalid("selected-workspace-missing", "missing-state"), (b) => { b.selection.workspaceId = "w9"; b.selection.assignmentRef = null; });
add("adm-authorization-undeclared", "admission", refused("authorization-undeclared", "missing-state"), (b) => { find(b, "agent-definition", "agent-a").authorizationRef = AUTH_2; });
add("adm-agent-disabled", "admission", refused("agent-disabled"), (b) => { find(b, "agent-definition", "agent-a").payload.status = "disabled"; });
add("adm-agent-policy-missing", "admission", refused("agent-policy-missing", "missing-state"), (b) => { b.registries = b.registries.filter((e) => e.id !== "ap-full"); });
add("adm-policy-ceiling-stale", "admission", refused("policy-ceiling-stale", "stale-revision"), (b) => { b.registries.push(contentEntry("agent-policy", "ap-full", 2, R_READER)); });
add("adm-project-retired", "admission", refused("project-not-active"), (b) => { find(b, "project", "p1").payload.status = "retired"; });
add("adm-project-policy-missing", "admission", refused("project-policy-missing", "missing-state"), (b) => {
find(b, "project", "p1").payload.policyRef = regRef(contentEntry("project-policy", "pp-gone", 1, R_FULL));
});
add("adm-workspace-retiring", "admission", refused("workspace-not-active"), (b) => { find(b, "workspace", "w1").payload.status = "retiring"; });
add("adm-workspace-policy-missing", "admission", refused("workspace-policy-missing", "missing-state"), (b) => {
find(b, "workspace", "w1").payload.policyRef = regRef(contentEntry("project-policy", "pp-gone", 1, R_FULL));
});
add("adm-project-registration-missing", "admission", refused("project-registration-missing"), (b) => {
b.records = b.records.filter((r) => !(r.kind === "registration" && r.id === "reg-a-p1"));
find(b, "registration", "reg-a-w1").payload.projectRegistrationRef = ref(find(b, "registration", "reg-b-p1"));
find(b, "registration", "reg-a-w1").payload.agentId = "agent-b";
b.selection.assignmentRef = null;
});
add("adm-workspace-registration-missing", "admission", refused("workspace-registration-missing"), (b) => {
b.records = b.records.filter((r) => !(r.kind === "registration" && r.id === "reg-a-w1"));
b.selection.assignmentRef = null;
});
add("adm-registration-revoked", "admission", refused("registration-revoked"), (b) => { reviseRecord(b, "registration", "reg-a-w1", { status: "revoked" }); });
add("adm-registration-ambiguous", "admission", invalid("registration-ambiguous"), (b) => {
const r = clone(find(b, "registration", "reg-a-w1")); r.id = "reg-a-w1-dup"; b.records.push(r);
});
add("adm-registration-parent-stale", "admission", refused("registration-parent-stale", "stale-revision"), (b) => { reviseRecord(b, "registration", "reg-a-p1", {}); });
add("adm-registration-parent-not-current", "admission", refused("registration-parent-not-current"), (b) => {
// A second, revoked project registration of the same agent at p1; the workspace
// registration names it as parent. Same agent and scope (ownership passes), but
// not the active project registration and not a stale revision of it.
const old = clone(find(b, "registration", "reg-a-p1")); old.id = "reg-a-p1-old"; old.payload.status = "revoked"; b.records.push(old);
find(b, "registration", "reg-a-w1").payload.projectRegistrationRef = ref(old);
});
add("adm-scope-role-missing", "admission", refused("scope-role-missing", "missing-state"), (b) => { b.registries = b.registries.filter((e) => e.id !== "role-writer"); });
add("adm-assignment-required-for-change", "admission", refused("assignment-required"), (b) => { b.selection.assignmentRef = null; b.operation = fileOp("file.change", "src/x"); });
add("adm-assignment-stale", "admission", refused("assignment-stale", "stale-revision"), (b) => { reviseRecord(b, "assignment", "asg-a-w1", {}); });
add("adm-assignment-paused", "admission", refused("assignment-not-selected"), (b) => { find(b, "assignment", "asg-a-w1").payload.status = "paused"; });
add("adm-assignment-ended", "admission", refused("assignment-not-selected"), (b) => {
const a = find(b, "assignment", "asg-a-w1"); a.payload.status = "ended"; a.payload.endReason = "completed";
});
add("adm-assignment-other-agent", "admission", refused("assignment-agent-mismatch"), (b) => {
b.selection.assignmentRef = ref(find(b, "assignment", "asg-b-w1"));
});
add("adm-assignment-other-workspace", "admission", refused("assignment-workspace-mismatch"), (b) => {
const a = find(b, "assignment", "asg-b-w2"); a.payload.agentId = "agent-a";
b.selection.assignmentRef = ref(a);
});
add("adm-task-ref-stale", "admission", refused("task-ref-stale", "stale-revision"), (b) => {
reviseRecord(b, "task", "task-w1", {});
});
add("adm-assignment-intent-stale", "admission", refused("assignment-intent-stale", "stale-revision"), (b) => {
const r2 = reviseRecord(b, "decision", "d-plan-1", {});
find(b, "task", "task-w1").payload.intentRef = ref(r2);
});
add("adm-assignment-intent-rejected", "admission", refused("assignment-intent-not-applicable"), (b) => { find(b, "decision", "d-plan-1").payload.outcome = "rejected"; });
add("adm-assignment-intent-other-subject", "admission", refused("assignment-intent-not-applicable"), (b) => {
find(b, "assignment", "asg-a-w1").payload.intentRef = { kind: "decision", id: "d-plan-w1b", scope: W1, revision: 1 };
});
add("adm-task-proposed", "admission", refused("task-not-ready"), (b) => { find(b, "task", "task-w1").payload.status = "proposed"; });
add("adm-task-intent-stale", "admission", refused("task-intent-stale", "stale-revision"), (b) => {
const r2 = reviseRecord(b, "decision", "d-plan-1", {});
find(b, "assignment", "asg-a-w1").payload.intentRef = ref(r2);
});
add("adm-task-intent-not-plan", "admission", refused("task-intent-not-approved"), (b) => {
find(b, "task", "task-w1").payload.intentRef = { kind: "decision", id: "d-change-1", scope: W1, revision: 1 };
find(b, "assignment", "asg-a-w1").payload.intentRef = { kind: "decision", id: "d-change-1", scope: W1, revision: 1 };
});
add("adm-artifact-undeclared", "admission", refused("artifact-undeclared", "missing-state"), (b) => { b.artifacts = [ART_1]; });
add("adm-mission-stale", "admission", refused("mission-stale", "stale-revision"), (b) => { reviseRecord(b, "mission", "m-w1", {}); });
add("adm-parent-mission-stale", "admission", refused("mission-stale", "stale-revision"), (b) => { reviseRecord(b, "mission", "m-p1", {}); });
add("adm-mission-blocked", "admission", refused("mission-not-active"), (b) => { find(b, "mission", "m-w1").payload.status = "blocked"; });
add("adm-parent-mission-accepted", "admission", refused("mission-not-active"), (b) => { find(b, "mission", "m-p1").payload.status = "accepted"; });
add("adm-dependency-stale", "admission", refused("dependency-stale", "stale-revision"), (b) => { reviseRecord(b, "task", "task-w1-dep", {}); });
add("adm-dependency-not-accepted-change", "admission", refused("dependency-not-accepted"), (b) => {
find(b, "task", "task-w1-dep").payload.status = "active"; b.operation = fileOp("file.change", "src/x");
});
add("adm-cross-workspace-mission", "admission", refused("cross-workspace-work-reference-not-modelled", "unsupported-capability"), (b) => {
find(b, "task", "task-w1").payload.missionRef = ref(find(b, "mission", "m-w2"));
});
add("adm-cross-project-dependency", "admission", refused("cross-project-work-reference-not-modelled", "unsupported-capability"), (b) => {
find(b, "task", "task-w1").payload.dependencies.push(ref(find(b, "task", "task-w3")));
});
add("adm-consulted-work-not-readable", "admission", refused("consulted-work-not-readable"), (b) => {
b.selection.execution = restricted(R_NO_WORK); b.operation = fileOp("file.read", "src/x");
});
add("adm-operation-not-permitted-role", "admission", refused("operation-not-permitted"), (b) => {
find(b, "registration", "reg-a-w1").payload.scopeRoleRef = regRef(REG.roleReader); b.operation = fileOp("file.change", "src/x");
});
add("adm-operation-not-permitted-agent-policy", "admission", refused("operation-not-permitted"), (b) => {
find(b, "agent-definition", "agent-a").payload.policyRef = regRef(REG.apReader); b.operation = fileOp("file.change", "src/x");
});
add("adm-operation-not-permitted-execution", "admission", refused("operation-not-permitted"), (b) => {
b.selection.execution = restricted(R_NO_FILE_READ); b.operation = fileOp("file.read", "src/x");
});
add("adm-path-not-permitted-write-outside", "admission", refused("path-not-permitted"), (b) => { b.operation = fileOp("file.change", "docs/x.md"); });
add("adm-path-not-permitted-prefix-string", "admission", refused("path-not-permitted"), (b) => { b.operation = fileOp("file.change", "srcx/x.md"); });
add("adm-path-not-permitted-task-narrows", "admission", refused("path-not-permitted"), (b) => {
find(b, "task", "task-w1").payload.restrictions = restrictions(["work.read", "file.read", "file.change"], [ROOT], [{ root: "workspace", path: "src/only" }]);
b.operation = fileOp("file.change", "src/other/x");
});
add("adm-path-not-permitted-read-execution", "admission", refused("path-not-permitted"), (b) => {
b.selection.execution = restricted(restrictions(["work.read", "file.read"], [{ root: "workspace", path: "docs" }], []));
b.operation = fileOp("file.read", "src/x");
});
add("adm-dependency-grants-nothing", "admission", refused("path-not-permitted"), (b) => {
// an accepted dependency with wide restrictions must not widen the selected task
find(b, "task", "task-w1-dep").payload.restrictions = R_FULL;
find(b, "task", "task-w1").payload.restrictions = restrictions(["work.read", "file.read", "file.change"], [ROOT], [{ root: "workspace", path: "src/only" }]);
b.operation = fileOp("file.change", "src/x");
});
// --- §10.1 registration delegation ----------------------------------------
add("rdeleg-stale", "registration-delegation", refused("registration-delegation-stale", "stale-revision"), (b) => {
withRegistrationDelegation(b); reviseRecord(b, "decision", "d-deleg-reg", {}); b.operation = fileOp("file.read", "src/x");
});
add("rdeleg-not-approved", "registration-delegation", refused("registration-delegation-not-approved"), (b) => {
withRegistrationDelegation(b);
const d = find(b, "decision", "d-deleg-reg"); d.payload.outcome = "rejected"; d.payload.delegatedOperations = [];
b.operation = fileOp("file.read", "src/x");
});
add("rdeleg-wrong-kind", "registration-delegation", refused("registration-delegation-not-approved"), (b) => {
withRegistrationDelegation(b);
const d = find(b, "decision", "d-deleg-reg"); d.payload.decisionKind = "plan-approval"; d.payload.delegatedOperations = [];
b.operation = fileOp("file.read", "src/x");
});
add("rdeleg-scope-not-modelled", "registration-delegation", refused("registration-delegation-scope-not-modelled", "unsupported-capability"), (b) => {
withRegistrationDelegation(b);
const d = find(b, "decision", "d-deleg-reg"); d.scope = P1;
find(b, "registration", "reg-a-w1").payload.delegationRef = ref(d);
b.delegationInputs[0].decisionRef = ref(d);
b.operation = fileOp("file.read", "src/x");
});
add("rdeleg-subject-form-three", "registration-delegation", refused("registration-delegation-subject-form", "unsupported-capability"), (b) => {
withRegistrationDelegation(b);
find(b, "decision", "d-deleg-reg").payload.subjectRefs.push(ref(find(b, "task", "task-w1")));
b.operation = fileOp("file.read", "src/x");
});
add("rdeleg-subject-form-task", "registration-delegation", refused("registration-delegation-subject-form", "unsupported-capability"), (b) => {
withRegistrationDelegation(b);
find(b, "decision", "d-deleg-reg").payload.subjectRefs[1] = ref(find(b, "task", "task-w1"));
b.operation = fileOp("file.read", "src/x");
});
add("rdeleg-bounds-other-agent", "registration-delegation", refused("registration-delegation-bounds"), (b) => {
withRegistrationDelegation(b);
find(b, "decision", "d-deleg-reg").payload.subjectRefs[0] = ref(find(b, "agent-definition", "agent-b"));
b.operation = fileOp("file.read", "src/x");
});
add("rdeleg-bounds-other-registration", "registration-delegation", refused("registration-delegation-bounds"), (b) => {
withRegistrationDelegation(b);
find(b, "decision", "d-deleg-reg").payload.subjectRefs[1] = ref(find(b, "registration", "reg-b-w1"));
b.operation = fileOp("file.read", "src/x");
});
add("rdeleg-input-missing", "registration-delegation", refused("delegation-input-missing", "missing-state"), (b) => {
withRegistrationDelegation(b); b.delegationInputs = []; b.operation = fileOp("file.read", "src/x");
});
add("rdeleg-exceeds-issuer-ceiling", "registration-delegation", refused("delegation-exceeds-issuer-ceiling"), (b) => {
withRegistrationDelegation(b, ["work.read", "file.read"], R_NO_FILE_READ); b.operation = fileOp("file.read", "src/x");
});
add("rdeleg-narrows-to-delegated-ops", "registration-delegation", refused("operation-not-permitted"), (b) => {
withRegistrationDelegation(b, ["work.read", "file.read"]); b.operation = fileOp("file.change", "src/x");
});
add("rdeleg-issuer-ceiling-narrows-path", "registration-delegation", refused("path-not-permitted"), (b) => {
withRegistrationDelegation(b, ["work.read", "file.read"], restrictions(["work.read", "file.read"], [{ root: "workspace", path: "docs" }], []));
b.operation = fileOp("file.read", "src/x");
});
add("rdeleg-policy-ceiling-stale", "registration-delegation", refused("policy-ceiling-stale", "stale-revision"), (b) => {
withRegistrationDelegation(b); b.registries.push(contentEntry("scope-role", "role-writer", 2, R_READER)); b.operation = fileOp("file.read", "src/x");
});
// --- §5 proposal (assignment.change) ---------------------------------------
add("prop-subject-not-selected-assignment", "proposal", invalid("proposal-subject-mismatch"), (b) => {
makeProposal(b); b.proposal.subjectAssignmentRef = ref(find(b, "assignment", "asg-b-w1"));
});
add("prop-selection-null-assignment", "proposal", invalid("proposal-subject-mismatch"), (b) => { makeProposal(b); b.selection.assignmentRef = null; });
add("prop-selection-agent-mismatch", "proposal", invalid("proposal-selection-mismatch"), (b) => { makeProposal(b); b.selection.agentId = "agent-b"; });
add("prop-requester-agent-missing", "proposal", invalid("requester-agent-missing", "missing-state"), (b) => { makeProposal(b); b.proposal.requesterAgentId = "agent-z"; });
add("prop-requester-context-wrong-agent", "proposal", invalid("requester-context-mismatch"), (b) => {
makeProposal(b); b.proposal.requesterContexts.original.assignmentRef = ref(find(b, "assignment", "asg-a-w1"));
});
add("prop-requester-context-wrong-scope", "proposal", invalid("requester-context-mismatch"), (b) => {
makeProposal(b); b.proposal.requesterContexts.target.assignmentRef = ref(find(b, "assignment", "asg-b-w1"));
});
add("prop-subject-assignment-stale", "proposal", refused("assignment-stale", "stale-revision"), (b) => {
makeProposal(b); reviseRecord(b, "assignment", "asg-a-w1", {});
});
add("prop-target-task-stale", "proposal", refused("task-ref-stale", "stale-revision"), (b) => {
makeProposal(b); reviseRecord(b, "task", "task-w2", {});
});
add("prop-original-requester-lacks-change", "proposal", proposalRefused("requester-lacks-original-scope-authority", "operation-not-permitted"), (b) => {
makeProposal(b); find(b, "registration", "reg-b-w1").payload.scopeRoleRef = regRef(REG.roleWriter);
});
add("prop-original-requester-registration-revoked", "proposal", proposalRefused("requester-lacks-original-scope-authority", "registration-revoked"), (b) => {
makeProposal(b); reviseRecord(b, "registration", "reg-b-w1", { status: "revoked" });
});
add("prop-original-requester-assignment-paused", "proposal", proposalRefused("requester-lacks-original-scope-authority", "assignment-not-selected"), (b) => {
makeProposal(b); find(b, "assignment", "asg-b-w1").payload.status = "paused";
});
add("prop-original-context-no-work-read", "proposal", proposalRefused("requester-lacks-original-scope-authority", "consulted-work-not-readable"), (b) => {
makeProposal(b); b.proposal.requesterContexts.original.execution = restricted(restrictions(["file.read", "assignment.change"], [ROOT], [ROOT]));
});
add("prop-target-requester-lacks-change", "proposal", proposalRefused("requester-lacks-target-scope-authority", "operation-not-permitted"), (b) => {
makeProposal(b); find(b, "registration", "reg-b-w2").payload.scopeRoleRef = regRef(REG.roleWriter);
});
add("prop-target-workspace-retired", "proposal", proposalRefused("requester-lacks-target-scope-authority", "workspace-not-active"), (b) => {
makeProposal(b); find(b, "workspace", "w2").payload.status = "retired";
});
add("prop-target-cross-project-task", "proposal", invalid("requester-context-mismatch"), (b) => {
makeProposal(b); b.proposal.targetTaskRef = ref(find(b, "task", "task-w3"));
});
add("prop-target-cross-project-context", "proposal", proposalRefused("requester-lacks-target-scope-authority", "task-not-ready"), (b) => {
// requester holds a valid w3 context, but task-w3 is accepted (not ready/active) -> refused at step 2 via context task? no: context task is the requester's own.
makeProposal(b);
const taskW3 = find(b, "task", "task-w3"); taskW3.payload.status = "ready";
const asgBW3 = assignment("asg-b-w3", W3, taskW3, "agent-b", "d-plan-w3");
b.records.push(asgBW3);
find(b, "decision", "d-plan-w3").payload.subjectRefs.push(ref(asgBW3));
b.proposal.targetTaskRef = ref(taskW3);
b.proposal.requesterContexts.target.assignmentRef = ref(asgBW3);
find(b, "decision", "d-change-1").payload.subjectRefs[1] = ref(taskW3);
taskW3.payload.status = "proposed";
});
add("prop-message-is-not-authority", "proposal", proposalRefused("message-is-not-authority", "message-is-not-authority"), (b) => {
makeProposal(b); b.proposal.delegationRef = null; b.proposal.message = "owner said it is fine";
});
add("prop-delegation-missing", "proposal", proposalRefused("delegation-not-applicable", "delegation-missing"), (b) => {
makeProposal(b); b.proposal.delegationRef = null;
});
add("prop-delegation-stale", "proposal", proposalRefused("delegation-not-applicable", "delegation-stale", "stale-revision"), (b) => {
makeProposal(b); reviseRecord(b, "decision", "d-deleg-b", {});
});
add("prop-delegation-rejected", "proposal", proposalRefused("delegation-not-applicable", "delegation-not-approved"), (b) => {
makeProposal(b); const d = find(b, "decision", "d-deleg-b"); d.payload.outcome = "rejected"; d.payload.delegatedOperations = [];
});
add("prop-delegation-wrong-operation", "proposal", proposalRefused("delegation-not-applicable", "delegation-operation-not-covered"), (b) => {
makeProposal(b); find(b, "decision", "d-deleg-b").payload.delegatedOperations = ["file.read"];
});
add("prop-delegation-other-recipient", "proposal", proposalRefused("delegation-not-applicable", "delegation-bounds"), (b) => {
makeProposal(b); find(b, "decision", "d-deleg-b").payload.subjectRefs[0] = ref(find(b, "agent-definition", "agent-a"));
});
add("prop-delegation-other-subject", "proposal", proposalRefused("delegation-not-applicable", "delegation-bounds"), (b) => {
makeProposal(b); find(b, "decision", "d-deleg-b").payload.subjectRefs[1] = ref(find(b, "assignment", "asg-b-w2"));
});
add("prop-delegation-input-missing", "proposal", proposalRefused("delegation-not-applicable", "delegation-input-missing", "missing-state"), (b) => {
makeProposal(b); b.delegationInputs = [];
});
add("prop-delegation-exceeds-issuer-ceiling", "proposal", proposalRefused("delegation-not-applicable", "delegation-exceeds-issuer-ceiling"), (b) => {
makeProposal(b); b.delegationInputs[0].issuerCeiling = R_NO_DELEGATE;
});
add("prop-delegation-artifact-undeclared", "proposal", proposalRefused("delegation-not-applicable", "artifact-undeclared", "missing-state"), (b) => {
makeProposal(b); find(b, "decision", "d-deleg-b").payload.basisRef = { runId: "run-1", artifactId: "art-9", digest: fakeDigest("art-9") };
});
add("prop-change-not-recorded", "proposal", proposalRefused("change-not-recorded", "change-not-recorded"), (b) => {
makeProposal(b); b.proposal.changeDecisionRef = null;
});
add("prop-change-stale", "proposal", proposalRefused("change-not-recorded", "change-decision-stale", "stale-revision"), (b) => {
makeProposal(b); reviseRecord(b, "decision", "d-change-1", {});
});
add("prop-change-rejected", "proposal", proposalRefused("change-not-recorded", "change-not-approved"), (b) => {
makeProposal(b); find(b, "decision", "d-change-1").payload.outcome = "rejected";
});
add("prop-change-wrong-kind", "proposal", proposalRefused("change-not-recorded", "change-not-approved"), (b) => {
makeProposal(b); find(b, "decision", "d-change-1").payload.decisionKind = "owner-checkpoint";
});
add("prop-change-subjects-mismatch", "proposal", proposalRefused("change-not-recorded", "change-subjects-mismatch"), (b) => {
makeProposal(b); find(b, "decision", "d-change-1").payload.subjectRefs = [ref(find(b, "assignment", "asg-a-w1"))];
});
add("prop-intent-subject-paused", "proposal", proposalRefused("intent-not-current", "assignment-not-selected"), (b) => {
makeProposal(b);
find(b, "assignment", "asg-a-w1").payload.status = "paused";
});
add("prop-intent-subject-intent-stale", "proposal", proposalRefused("intent-not-current", "assignment-intent-stale", "stale-revision"), (b) => {
makeProposal(b);
const r2 = reviseRecord(b, "decision", "d-plan-1", {});
find(b, "task", "task-w1").payload.intentRef = ref(r2);
});
add("prop-intent-target-task-blocked", "proposal", proposalRefused("intent-not-current", "task-not-ready"), (b) => {
makeProposal(b); find(b, "task", "task-w2").payload.status = "blocked";
});
add("prop-intent-target-task-intent-rejected", "proposal", proposalRefused("intent-not-current", "task-intent-not-approved"), (b) => {
makeProposal(b); find(b, "decision", "d-plan-w2").payload.outcome = "rejected";
});
add("prop-all-pass-restricted-contexts", "proposal", UNRESOLVED, (b) => {
makeProposal(b);
b.proposal.requesterContexts.original.execution = restricted(R_MANAGER);
b.proposal.requesterContexts.target.execution = restricted(R_MANAGER);
});
// --- FI-FILBERT-6 corrections (F1F5): witness recipes and positive controls ----
// F1: exact registry declarations for every consulted registry reference
add("adm-registry-declaration-missing-agent-refs", "admission", refused("registry-declaration-missing", "missing-state"), (b) => {
// verdict witness: harness/settings/context-content declarations removed, references intact
b.registries = b.registries.filter((e) => !["harness", "settings", "context-content"].includes(e.registry));
});
add("adm-registry-declaration-missing-settings", "admission", refused("registry-declaration-missing", "missing-state"), (b) => {
b.registries = b.registries.filter((e) => e.registry !== "settings");
});
add("adm-registry-declaration-missing-soul", "admission", refused("registry-declaration-missing", "missing-state"), (b) => {
b.registries = b.registries.filter((e) => e.registry !== "context-content");
});
add("adm-registry-declaration-digest-mismatch", "admission", refused("registry-declaration-missing", "missing-state"), (b) => {
// declared entry exists, reference names another digest: not an exact four-field match
find(b, "agent-definition", "agent-a").payload.harnessRef.digest = fakeDigest("harness/pi/1/other");
});
add("adm-registry-declaration-revision-mismatch", "admission", refused("registry-declaration-missing", "missing-state"), (b) => {
// harness is not a ceiling registry: a newer declared revision is not "stale", the exact ref is simply absent
const r = find(b, "agent-definition", "agent-a").payload.settingsRef; r.revision = 2; r.digest = fakeDigest("settings/default/2");
});
add("adm-registry-declaration-missing-instruction", "admission", refused("registry-declaration-missing", "missing-state"), (b) => {
find(b, "agent-definition", "agent-a").payload.instructionRefs = [regRef(plainEntry("context-content", "instr-1", 1))];
});
add("adm-registry-declaration-missing-skill", "admission", refused("registry-declaration-missing", "missing-state"), (b) => {
find(b, "agent-definition", "agent-a").payload.skillRefs = [regRef(plainEntry("context-content", "skill-1", 1))];
});
add("adm-registry-declaration-missing-endpoint-execution", "admission", refused("registry-declaration-missing", "missing-state"), (b) => {
const r = restrictions(["work.read", "file.read"], [ROOT], []); r.network = "approved-endpoints"; r.endpointRefs = [regRef(plainEntry("endpoint", "ep-1", 1))];
b.selection.execution = restricted(r);
});
add("adm-registry-declaration-missing-endpoint-task", "admission", refused("registry-declaration-missing", "missing-state"), (b) => {
const r = restrictions(["work.read", "file.read"], [ROOT], []); r.network = "approved-endpoints"; r.endpointRefs = [regRef(plainEntry("endpoint", "ep-1", 1))];
find(b, "task", "task-w1").payload.restrictions = r;
});
add("adm-registry-declaration-unselected-agent-ignored", "positive", ALLOWED, (b) => {
// an unconsulted record's dangling declaration is not consulted: agent-b is not selected
find(b, "agent-definition", "agent-b").payload.harnessRef.digest = fakeDigest("harness/pi/1/other");
});
add("adm-registry-declaration-endpoint-declared", "positive", ALLOWED, (b) => {
// positive control: the endpoint reference is declared exactly; network still intersects to none
const ep = plainEntry("endpoint", "ep-1", 1); b.registries.push(ep);
const r = restrictions(["work.read", "file.read"], [ROOT], []); r.network = "approved-endpoints"; r.endpointRefs = [regRef(ep)];
b.selection.execution = restricted(r);
});
add("adm-dependency-authorization-undeclared", "admission", refused("authorization-undeclared", "missing-state"), (b) => {
// verdict witness: the consulted dependency names a well-formed, undeclared authorization
find(b, "task", "task-w1-dep").authorizationRef = AUTH_UNDECLARED;
});
add("adm-mission-authorization-undeclared", "admission", refused("authorization-undeclared", "missing-state"), (b) => {
find(b, "mission", "m-p1").authorizationRef = AUTH_UNDECLARED;
});
add("adm-unconsulted-authorization-ignored", "positive", ALLOWED, (b) => {
// task-w3 is never consulted by a w1 read; its undeclared authorization is not an admission input
find(b, "task", "task-w3").authorizationRef = AUTH_UNDECLARED;
});
// F2: the assigned task is consulted work even without mission/dependency references
add("adm-assigned-task-without-work-read", "admission", refused("consulted-work-not-readable"), (b) => {
// verdict witness: task-only selected task, execution grants file.change only
const t = find(b, "task", "task-w1"); t.payload.missionRef = null; t.payload.dependencies = [];
b.selection.execution = restricted(restrictions(["file.change"], [], [ROOT]));
b.operation = fileOp("file.change", "src/main.mjs");
});
add("adm-assigned-task-without-work-read-read-op", "admission", refused("consulted-work-not-readable"), (b) => {
const t = find(b, "task", "task-w1"); t.payload.missionRef = null; t.payload.dependencies = [];
b.selection.execution = restricted(restrictions(["file.read"], [ROOT], []));
b.operation = fileOp("file.read", "src/main.mjs");
});
add("assigned-task-only-with-work-read", "positive", ALLOWED, (b) => {
// positive control: same task-only context with work.read granted
const t = find(b, "task", "task-w1"); t.payload.missionRef = null; t.payload.dependencies = [];
b.selection.execution = restricted(restrictions(["work.read", "file.change"], [], [ROOT]));
b.operation = fileOp("file.change", "src/main.mjs");
});
add("prop-task-only-contexts-without-work-read", "proposal", proposalRefused("requester-lacks-original-scope-authority", "consulted-work-not-readable"), (b) => {
// verdict witness: every task is reference-free; both requester executions grant assignment.change only
makeProposal(b); clearWorkReferences(b);
b.proposal.requesterContexts.original.execution = restricted(restrictions(["assignment.change"], [], []));
b.proposal.requesterContexts.target.execution = restricted(restrictions(["assignment.change"], [], []));
});
add("prop-task-only-target-context-without-work-read", "proposal", proposalRefused("requester-lacks-target-scope-authority", "consulted-work-not-readable"), (b) => {
makeProposal(b); clearWorkReferences(b);
b.proposal.requesterContexts.original.execution = restricted(restrictions(["work.read", "assignment.change"], [], []));
b.proposal.requesterContexts.target.execution = restricted(restrictions(["assignment.change"], [], []));
});
add("prop-task-only-contexts-with-work-read", "proposal", UNRESOLVED, (b) => {
// positive control: task-only contexts with work.read reach the runtime-reconciliation step
makeProposal(b); clearWorkReferences(b);
b.proposal.requesterContexts.original.execution = restricted(restrictions(["work.read", "assignment.change"], [], []));
b.proposal.requesterContexts.target.execution = restricted(restrictions(["work.read", "assignment.change"], [], []));
});
// F3: the issuer ceiling narrows both requester calculations; work access is rechecked
add("prop-issuer-denies-work-read", "proposal", proposalRefused("requester-lacks-original-scope-authority", "consulted-work-not-readable"), (b) => {
// verdict witness: delegated operation within the ceiling, but the narrowed intersection lacks work.read
makeProposal(b); b.delegationInputs[0].issuerCeiling = restrictions(["assignment.change"], [ROOT], [ROOT]);
});
add("prop-issuer-denies-work-read-task-only", "proposal", proposalRefused("requester-lacks-original-scope-authority", "consulted-work-not-readable"), (b) => {
makeProposal(b); clearWorkReferences(b); b.delegationInputs[0].issuerCeiling = restrictions(["assignment.change"], [ROOT], [ROOT]);
});
add("prop-issuer-grants-work-read", "proposal", UNRESOLVED, (b) => {
// positive control: the minimal issuer ceiling that keeps work.read passes the recheck
makeProposal(b); b.delegationInputs[0].issuerCeiling = restrictions(["work.read", "assignment.change"], [ROOT], [ROOT]);
});
add("prop-subject-task-authorization-undeclared", "proposal", proposalRefused("intent-not-current", "authorization-undeclared", "missing-state"), (b) => {
makeProposal(b); find(b, "task", "task-w1").authorizationRef = AUTH_UNDECLARED;
});
// F4: revision-exact cycle graphs
add("cycle-acyclic-versioned-history", "positive", ALLOWED, (b) => { versionedHistory(b); });
add("cycle-acyclic-versioned-history-file-change", "positive", ALLOWED, (b) => {
versionedHistory(b); b.operation = fileOp("file.change", "src/main.mjs");
});
add("cycle-dependency-cross-revision", "cycle", invalid("dependency-cycle"), (b) => {
// a real cycle at exact revisions: task-w1 rev 2 <-> task-w1-dep rev 2
const { t2, d2 } = versionedHistory(b); t2.payload.dependencies = [ref(d2)];
});
add("cycle-mission-parent-previous-revision-not-a-cycle", "ownership", invalid("mission-parent-scope-mismatch"), (b) => {
// m-w1 rev 2 names m-w1 rev 1 as parent: an identity-merged graph would see a self-loop,
// the exact graph is acyclic, so the later ownership rule (parent must be a project mission) fires
const mw1 = find(b, "mission", "m-w1");
const mw1r2 = reviseRecord(b, "mission", "m-w1", { parentMissionRef: ref(mw1) });
find(b, "task", "task-w1").payload.missionRef = ref(mw1r2);
});
add("cycle-mission-parent-old-revision-only", "cycle", invalid("mission-parent-cycle"), (b) => {
// the self-parent cycle lives entirely in revision 1; a clean revision 2 does not repair it
const mw1 = find(b, "mission", "m-w1");
mw1.payload.parentMissionRef = ref(mw1);
const mw1r2 = reviseRecord(b, "mission", "m-w1", { parentMissionRef: ref(find(b, "mission", "m-p1")) });
find(b, "task", "task-w1").payload.missionRef = ref(mw1r2);
});
// F5: deterministic first failure — record order and message precedence
add("shape-order-forward", "shape", invalid("shape-enum-mismatch"), (b) => {
// verdict witness: agent-a invalid status enum, agent-b unknown payload field; input order forward
find(b, "agent-definition", "agent-a").payload.status = "sleeping";
find(b, "agent-definition", "agent-b").payload.extra = true;
});
add("shape-order-reversed", "shape", invalid("shape-enum-mismatch"), (b) => {
find(b, "agent-definition", "agent-a").payload.status = "sleeping";
find(b, "agent-definition", "agent-b").payload.extra = true;
b.records.reverse();
});
add("shape-order-malformed-record-sorts-last", "shape", invalid("shape-enum-mismatch"), (b) => {
// a record without a readable identity is validated after every identified record
find(b, "agent-definition", "agent-b").payload.status = "sleeping";
b.records.unshift({ schemaVersion: 1 });
});
add("shape-order-only-malformed-record", "shape", invalid("shape-missing-field"), (b) => {
b.records.unshift({ schemaVersion: 1 });
});
// FI-ROCKO-7: stable traversal of the declared inventories (registries, artifacts,
// authorizations, delegationInputs) at the shape, profile, digest, identity and structural
// stages. Each pair carries two different failures; the typed key decides which is first,
// never input position. Forward/reversed pairs share one expectation.
function orderRegistries(b) {
// ap-full (key agent-policy/ap-full) sorts before pp-p1 (project-policy/pp-p1): a missing
// field on ap-full precedes an unknown field on pp-p1 wherever the two sit
delete findReg(b, "ap-full").digest;
findReg(b, "pp-p1").extra = true;
}
add("shape-order-registries-forward", "shape", invalid("shape-missing-field"), (b) => { orderRegistries(b); });
add("shape-order-registries-reversed", "shape", invalid("shape-missing-field"), (b) => { orderRegistries(b); b.registries.reverse(); });
function orderRegistriesSwapped(b) {
// the same two failures with the roles swapped: the first key now carries the unknown field
findReg(b, "ap-full").extra = true;
delete findReg(b, "pp-p1").digest;
}
add("shape-order-registries-swapped-forward", "shape", invalid("shape-unknown-field"), (b) => { orderRegistriesSwapped(b); });
add("shape-order-registries-swapped-reversed", "shape", invalid("shape-unknown-field"), (b) => { orderRegistriesSwapped(b); b.registries.reverse(); });
add("shape-order-registries-malformed-sorts-last", "shape", invalid("shape-enum-mismatch"), (b) => {
// an entry without a readable registry/id sorts after every keyed entry; the keyed failure is first
findReg(b, "role-writer").registry = "no-such-registry";
b.registries.unshift({ registry: 7 });
});
add("shape-order-registries-only-malformed", "shape", invalid("shape-type-mismatch"), (b) => { b.registries.unshift("not-an-entry"); });
function orderArtifacts(b) {
// run-1/art-1 sorts before run-1/art-2: a digest pattern failure on art-1 precedes an unknown field on art-2
b.artifacts[0].digest = "sha256:short";
b.artifacts[1].extra = true;
}
add("shape-order-artifacts-forward", "shape", invalid("shape-pattern-mismatch"), (b) => { orderArtifacts(b); });
add("shape-order-artifacts-reversed", "shape", invalid("shape-pattern-mismatch"), (b) => { orderArtifacts(b); b.artifacts.reverse(); });
function orderArtifactsSwapped(b) {
b.artifacts[0].extra = true;
b.artifacts[1].digest = "sha256:short";
}
add("shape-order-artifacts-swapped-forward", "shape", invalid("shape-unknown-field"), (b) => { orderArtifactsSwapped(b); });
add("shape-order-artifacts-swapped-reversed", "shape", invalid("shape-unknown-field"), (b) => { orderArtifactsSwapped(b); b.artifacts.reverse(); });
add("shape-order-artifacts-malformed-sorts-last", "shape", invalid("shape-pattern-mismatch"), (b) => {
b.artifacts[1].digest = "sha256:short";
b.artifacts.unshift({ runId: 1 });
});
function orderAuthorizations(b) {
// two pattern failures: the locator is the lower value either way (asserted in ../resolve.test.mjs)
b.authorizations = [AUTH_2.replace("-4000-", "-1000-"), `${AUTH}-x`];
}
add("shape-order-authorizations-forward", "shape", invalid("shape-pattern-mismatch"), (b) => { orderAuthorizations(b); });
add("shape-order-authorizations-reversed", "shape", invalid("shape-pattern-mismatch"), (b) => { orderAuthorizations(b); b.authorizations.reverse(); });
add("shape-order-authorizations-malformed-sorts-last", "shape", invalid("shape-pattern-mismatch"), (b) => {
// a non-string entry has no readable key and is validated after every string entry
b.authorizations = [7, `${AUTH}-x`];
});
function orderDelegationInputs(b) {
// decision d-deleg-b (W1) sorts before d-deleg-reg (W1) by id: a missing field on the
// d-deleg-b input precedes an enum failure on the d-deleg-reg input
makeProposal(b);
const d = withRegistrationDelegation(b);
b.delegationInputs.find((x) => x.decisionRef.id === "d-deleg-b").mode = "parent-delegation";
delete b.delegationInputs.find((x) => x.decisionRef.id === "d-deleg-reg").issuerCeiling;
return d;
}
add("shape-order-delegation-inputs-forward", "shape", invalid("shape-enum-mismatch"), (b) => { orderDelegationInputs(b); });
add("shape-order-delegation-inputs-reversed", "shape", invalid("shape-enum-mismatch"), (b) => { orderDelegationInputs(b); b.delegationInputs.reverse(); });
function orderDelegationInputsSwapped(b) {
makeProposal(b);
withRegistrationDelegation(b);
delete b.delegationInputs.find((x) => x.decisionRef.id === "d-deleg-b").issuerCeiling;
b.delegationInputs.find((x) => x.decisionRef.id === "d-deleg-reg").mode = "parent-delegation";
}
add("shape-order-delegation-inputs-swapped-forward", "shape", invalid("shape-missing-field"), (b) => { orderDelegationInputsSwapped(b); });
add("shape-order-delegation-inputs-swapped-reversed", "shape", invalid("shape-missing-field"), (b) => { orderDelegationInputsSwapped(b); b.delegationInputs.reverse(); });
add("shape-order-delegation-inputs-malformed-sorts-last", "shape", invalid("shape-enum-mismatch"), (b) => {
makeProposal(b);
b.delegationInputs[0].mode = "parent-delegation";
b.delegationInputs.unshift({ decisionRef: null });
});
// stage precedence across families is fixed: records, registries, artifacts, authorizations, delegationInputs
add("shape-order-family-precedence-registries-before-artifacts", "shape", invalid("shape-unknown-field"), (b) => {
b.artifacts[0].digest = "sha256:short";
findReg(b, "pp-p2").extra = true;
});
add("shape-order-family-precedence-artifacts-before-authorizations", "shape", invalid("shape-pattern-mismatch"), (b) => {
b.authorizations = [7];
b.artifacts[1].digest = "sha256:short";
});
add("shape-order-family-precedence-authorizations-before-delegation-inputs", "shape", invalid("shape-type-mismatch"), (b) => {
makeProposal(b);
b.delegationInputs[0].mode = "parent-delegation";
b.authorizations = [7];
});
// profile stage: the first strict-profile violation in stable order, after every shape failure
function orderProfileRegistries(b) {
// ap-reader sorts before role-reader: two one-final-LF ids, the lower key is the locator either way
findReg(b, "role-reader").id += LF1;
findReg(b, "ap-reader").id += LF1;
}
add("profile-order-registries-forward", "profile", PROFILE_MISMATCH, (b) => { orderProfileRegistries(b); });
add("profile-order-registries-reversed", "profile", PROFILE_MISMATCH, (b) => { orderProfileRegistries(b); b.registries.reverse(); });
add("profile-order-shape-precedes-profile-registries", "shape", invalid("shape-unknown-field"), (b) => {
// a shape failure on a later key still precedes a profile violation on an earlier key
findReg(b, "ap-reader").id += LF1;
findReg(b, "pp-p2").extra = true;
});
add("profile-order-artifacts-reversed", "profile", PROFILE_MISMATCH, (b) => {
b.artifacts[0].runId += LF1; b.artifacts[1].artifactId += LF1; b.artifacts.reverse();
});
add("profile-order-authorizations-reversed", "profile", PROFILE_MISMATCH, (b) => {
b.authorizations = [`${AUTH_2}${LF1}`, `${AUTH}${LF1}`];
});
add("profile-order-shape-precedes-profile-authorizations", "shape", invalid("shape-pattern-mismatch"), (b) => {
// a shape failure on the higher value still precedes a profile violation on the lower one
b.authorizations = [`${AUTH}${LF1}`, `${AUTH_2}-x`];
});
// digest stage: content digests are checked in stable order after the profile stage
function orderDigests(b) {
// ap-full (unsupported content) sorts before role-writer (digest mismatch)
const apFull = findReg(b, "ap-full"); apFull.content.restrictions.readPaths = [{ root: "workspace", path: "caf\u00e9" }];
findReg(b, "role-writer").content.restrictions.operations.push("command.execute");
}
add("shape-order-registry-digest-forward", "profile", invalid("mock-content-unsupported", "unsupported-capability"), (b) => { orderDigests(b); });
add("shape-order-registry-digest-reversed", "profile", invalid("mock-content-unsupported", "unsupported-capability"), (b) => { orderDigests(b); b.registries.reverse(); });
function orderDigestsSwapped(b) {
findReg(b, "ap-full").content.restrictions.operations.pop();
const rw = findReg(b, "role-writer"); rw.content.restrictions.readPaths = [{ root: "workspace", path: "caf\u00e9" }];
}
add("shape-order-registry-digest-swapped-forward", "profile", invalid("registry-digest-mismatch"), (b) => { orderDigestsSwapped(b); });
add("shape-order-registry-digest-swapped-reversed", "profile", invalid("registry-digest-mismatch"), (b) => { orderDigestsSwapped(b); b.registries.reverse(); });
add("shape-order-profile-precedes-digest-registries", "profile", PROFILE_MISMATCH, (b) => {
// a profile violation on a later key precedes a digest failure on an earlier key
findReg(b, "ap-full").content.restrictions.operations.pop();
findReg(b, "pp-p2").id += LF1;
});
add("shape-order-two-digest-mismatches-reversed", "profile", invalid("registry-digest-mismatch"), (b) => {
findReg(b, "role-writer").content.restrictions.operations.push("command.execute");
findReg(b, "role-reader").content.restrictions.operations.push("command.execute");
b.registries.reverse();
});
// identity stage: duplicates are detected in stable order across every family
add("dup-order-registries-precede-artifacts", "identity", invalid("duplicate-registry-identity"), (b) => {
// registries precede artifacts at the identity stage wherever the duplicates sit
b.artifacts.unshift({ ...ART_2, digest: fakeDigest("other") });
b.registries.unshift(clone(findReg(b, "role-writer")));
});
add("dup-order-delegation-inputs-reversed", "identity", invalid("duplicate-delegation-input"), (b) => {
// the duplicate pair is listed before a valid lower-key input; the duplicate is still found
makeProposal(b); withRegistrationDelegation(b); b.delegationInputs.reverse(); b.delegationInputs.unshift(clone(b.delegationInputs[0]));
});
// structural stage: the first missing delegation decision is the lowest key, not the first listed
function orderStructuralDelegationInputs(b) {
makeProposal(b);
withRegistrationDelegation(b);
for (const d of b.delegationInputs) d.decisionRef.revision = 9;
}
add("struct-order-delegation-inputs-forward", "structure", invalid("record-reference-missing", "missing-state"), (b) => { orderStructuralDelegationInputs(b); });
add("struct-order-delegation-inputs-reversed", "structure", invalid("record-reference-missing", "missing-state"), (b) => { orderStructuralDelegationInputs(b); b.delegationInputs.reverse(); });
// FI-ROCKO-8 (FI-FILBERT-7 R5-1): the equal-key / unkeyed tie-break is a total ordering
// form over the strict-JSON domain, not the ASCII-only mock-digest canonicalizer, so
// distinct non-ASCII entries never collapse to one form. Recipes are the verdict's
// witnesses rebuilt from the base bundle, forward and reversed.
for (const family of ["records", "registries", "artifacts", "delegationInputs"]) {
const slug = family === "delegationInputs" ? "delegation-inputs" : family;
// two unkeyed entries, both non-ASCII: the string form ("\"…") sorts before the object form ("{…")
add(`shape-order-unkeyed-unicode-${slug}-forward`, "shape", invalid("shape-type-mismatch"), (b) => { b[family] = [{ extra: "\u00e9" }, "\u00e9"]; });
add(`shape-order-unkeyed-unicode-${slug}-reversed`, "shape", invalid("shape-type-mismatch"), (b) => { b[family] = ["\u00e9", { extra: "\u00e9" }]; });
}
function equalKeyUnicodeRecords(b) {
// two agent-a copies with the same kind/id/scope/revision and a legitimate non-ASCII displayName;
// sorted-key form: the copy with the extra payload key ("extra" < "harnessRef") sorts first
const a = find(b, "agent-definition", "agent-a");
a.payload.displayName = "Caf\u00e9";
const c = clone(a);
a.payload.status = "invalid-status";
c.payload.extra = true;
b.records.splice(b.records.indexOf(a) + 1, 0, c);
}
add("shape-order-equal-key-unicode-records-forward", "shape", invalid("shape-unknown-field"), (b) => { equalKeyUnicodeRecords(b); });
add("shape-order-equal-key-unicode-records-reversed", "shape", invalid("shape-unknown-field"), (b) => { equalKeyUnicodeRecords(b); b.records.reverse(); });
function equalKeyUnicodeRegistries(b) {
// two ap-full copies with identical registry/id/revision/digest and a non-ASCII logical path;
// sorted-key form: the copy with the extra restrictions key ("extra" < "network") sorts first
const e = findReg(b, "ap-full");
e.content.restrictions.readPaths = [{ root: "workspace", path: "caf\u00e9" }];
const c = clone(e);
e.content.restrictions.network = "everything";
c.content.restrictions.extra = true;
b.registries.splice(b.registries.indexOf(e) + 1, 0, c);
}
add("shape-order-equal-key-unicode-registries-forward", "shape", invalid("shape-unknown-field"), (b) => { equalKeyUnicodeRegistries(b); });
add("shape-order-equal-key-unicode-registries-reversed", "shape", invalid("shape-unknown-field"), (b) => { equalKeyUnicodeRegistries(b); b.registries.reverse(); });
// Unicode positives stay allowed: the ordering form is not a validity judgement
add("positive-unicode-display-name-allowed", "positive", ALLOWED, (b) => { find(b, "agent-definition", "agent-a").payload.displayName = "Caf\u00e9 \u{1F600}"; });
add("prop-message-precedes-requester-admission", "proposal", proposalRefused("message-is-not-authority", "message-is-not-authority"), (b) => {
// verdict witness: no delegation plus a message; the original requester context lacks assignment.change
makeProposal(b); b.proposal.delegationRef = null; b.proposal.message = "owner said it is fine";
b.proposal.requesterContexts.original.execution = restricted(restrictions(["work.read"], [ROOT], []));
});
add("prop-delegation-missing-after-requester-admission", "proposal", proposalRefused("requester-lacks-original-scope-authority", "operation-not-permitted"), (b) => {
// without a message the missing delegation stays at step 3, after the requester's original-scope admission
makeProposal(b); b.proposal.delegationRef = null;
b.proposal.requesterContexts.original.execution = restricted(restrictions(["work.read"], [ROOT], []));
});
add("prop-message-after-structural-failure", "proposal", invalid("requester-context-mismatch"), (b) => {
// a structural proposal failure still precedes the message rule
makeProposal(b); b.proposal.delegationRef = null; b.proposal.message = "owner said it is fine";
b.proposal.requesterContexts.original.assignmentRef = ref(find(b, "assignment", "asg-a-w1"));
});
add("prop-message-precedes-stale-subject", "proposal", proposalRefused("message-is-not-authority", "message-is-not-authority"), (b) => {
// current-head admission (stale subject assignment) is not structural validation: the message rule comes first
makeProposal(b); b.proposal.delegationRef = null; b.proposal.message = "owner said it is fine";
reviseRecord(b, "assignment", "asg-a-w1", {});
});
// ---------------------------------------------------------------------------
// Raw lexical cases (byte-exact)
// ---------------------------------------------------------------------------
const rawCases = [];
function addRaw(name, bytes, expect, byteOffset = null) {
rawCases.push({ name, bytes: bytes instanceof Uint8Array ? bytes : new TextEncoder().encode(bytes), expect, byteOffset });
}
const PARSE = { exit: 2, result: "invalid", reason: "invalid-request", rule: "input-parse-failed", proposalRule: null };
const baseText = JSON.stringify(buildBase(), null, 2);
addRaw("raw-duplicate-key", '{"bundleVersion": 1, "bundleVersion": 1}', PARSE, 21);
addRaw("raw-bom-prefix", `\ufeff${baseText}`, PARSE, 0);
addRaw("raw-trailing-content", `${baseText}\n{}`, PARSE, baseText.length + 1);
addRaw("raw-fraction-number", baseText.replace('"bundleVersion": 1', '"bundleVersion": 1.0'), PARSE, 21);
addRaw("raw-negative-zero", baseText.replace('"bundleVersion": 1', '"bundleVersion": -0'), PARSE, 21);
addRaw("raw-exponent", baseText.replace('"bundleVersion": 1', '"bundleVersion": 1e0'), PARSE, 21);
addRaw("raw-unsafe-integer", baseText.replace('"bundleVersion": 1', '"bundleVersion": 9007199254740992'), PARSE, 21);
addRaw("raw-depth-33", `${"[".repeat(33)}${"]".repeat(33)}`, PARSE, 32);
addRaw("raw-invalid-utf8", new Uint8Array([0x7b, 0x22, 0x61, 0xc0, 0x80, 0x22, 0x3a, 0x31, 0x7d]), PARSE, 3);
addRaw("raw-utf8-surrogate", new Uint8Array([0x7b, 0x22, 0x61, 0xed, 0xa0, 0x80, 0x22, 0x3a, 0x31, 0x7d]), PARSE, 3);
addRaw("raw-lone-escape-surrogate", '{"a": "\\ud800"}', PARSE, 7);
addRaw("raw-raw-control-in-string", '{"a": "x\u0001y"}', PARSE, 8);
addRaw("raw-empty-file", "", PARSE, 0);
addRaw("raw-not-object", "[]", invalid("shape-type-mismatch"));
addRaw("raw-proto-key", '{"__proto__": {"polluted": true}}', invalid("shape-unknown-field"));
addRaw("raw-constructor-key", '{"constructor": {"prototype": {"polluted": true}}}', invalid("shape-unknown-field"));
addRaw("raw-string-too-long", `{"a": "${"x".repeat(4097)}"}`, PARSE, 6);
addRaw("raw-array-too-long", `[${new Array(1025).fill("1").join(",")}]`, PARSE, 0);
{
// exactly 1 MiB + 1 bytes: refused by the CLI size gate (exit 2 input-too-large) before parsing
const big = new Uint8Array(1024 * 1024 + 1);
big.fill(0x20);
big[0] = 0x5b; big[big.length - 1] = 0x5d; // "[ ... ]"
addRaw("raw-oversize-file", big, { exit: 2, result: "invalid", reason: "invalid-request", rule: "input-too-large", proposalRule: null });
}
// ---------------------------------------------------------------------------
// Output
// ---------------------------------------------------------------------------
function writeJson(path, value) {
writeFileSync(path, `${JSON.stringify(value, null, 2)}\n`);
}
function main() {
const out = process.argv[2];
if (!out) {
process.stderr.write("usage: build-fixtures.mjs <output-dir>\n");
process.exit(2);
}
mkdirSync(join(out, "bundles"), { recursive: true });
mkdirSync(join(out, "raw"), { recursive: true });
mkdirSync(join(out, "demo"), { recursive: true });
const names = new Set();
const index = [];
for (const c of cases) {
if (names.has(c.name)) throw new Error(`duplicate case ${c.name}`);
names.add(c.name);
writeJson(join(out, "bundles", `${c.name}.json`), c.bundle);
index.push({ name: c.name, group: c.group, file: `bundles/${c.name}.json`, raw: false, expect: c.expect });
}
for (const c of rawCases) {
if (names.has(c.name)) throw new Error(`duplicate case ${c.name}`);
names.add(c.name);
writeFileSync(join(out, "raw", `${c.name}.json`), c.bytes);
index.push({ name: c.name, group: "lexical", file: `raw/${c.name}.json`, raw: true, expect: { ...c.expect, byteOffset: c.byteOffset } });
}
index.sort((a, b) => (a.name < b.name ? -1 : 1));
writeJson(join(out, "index.json"), { generator: "build-fixtures.mjs", count: index.length, cases: index });
// Owner demo copies
for (const name of ["demo-read-w1", "demo-file-change-src", "demo-change-w1", "adm-registration-revoked", "prop-message-is-not-authority"]) {
writeJson(join(out, "demo", `${name}.json`), cases.find((c) => c.name === name).bundle);
}
process.stdout.write(`${index.length} cases written to ${out}\n`);
}
main();