feat(runner): add deterministic Phase 7 control plane

Implement seeded state, typed semantic commands, command claims, deterministic audit/wake/fault/replay behavior, and focused conformance tests.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-08-10 02:57:38 +00:00
1 parent b8875b2ec4
commit 5cd95a0e9f
4 files changed
+2789

No files matched your search

@@ -197,3 +197,6 @@ function canonicalJson(value: unknown): string {
}
return JSON.stringify(value) ?? "undefined";
}
export * from "./phase7-control-plane-types.js";
export * from "./phase7-mock-control-plane-adapter.js";
@@ -0,0 +1,555 @@
import type {
CompleteControlPlaneRunInput,
ControlPlanePort,
OpenControlPlaneRunInput,
} from "../contracts/control-plane-port.js";
import type { NativeRunEvent, NativeRunResult } from "../contracts/types.js";
import type { PersistedNativeSession } from "../contracts/native-session-backend.js";
import type { PrpEvent } from "../protocol/phase1-contract.js";
export type Phase7JsonPrimitive = string | number | boolean | null;
export type Phase7JsonValue =
| Phase7JsonPrimitive
| Phase7JsonValue[]
| { [key: string]: Phase7JsonValue };
export type Phase7TaskStatus =
| "backlog"
| "todo"
| "in_progress"
| "in_review"
| "done"
| "blocked"
| "cancelled";
export interface Phase7FixtureCompany {
id: string;
name: string;
issuePrefix: string;
status: "active" | "paused";
budgetId: string;
}
export interface Phase7FixtureActor {
id: string;
companyId: string;
name: string;
role: string;
status: "active" | "paused";
budgetId: string;
capabilityGrants: string[];
}
export interface Phase7FixtureTask {
id: string;
companyId: string;
identifier: string;
title: string;
description: string | null;
status: Phase7TaskStatus;
priority: "critical" | "high" | "medium" | "low";
workMode: "standard" | "ask" | "planning" | "skill_test";
parentId: string | null;
assigneeActorId: string | null;
checkoutRunId: string | null;
executionRunId: string | null;
startedAt: string | null;
completedAt: string | null;
}
export interface Phase7FixtureComment {
id: string;
taskId: string;
authorActorId: string | null;
body: string;
createdAt: string;
}
export interface Phase7FixtureDocumentRevision {
id: string;
documentId: string;
revision: number;
body: string;
changeSummary: string | null;
createdAt: string;
}
export interface Phase7FixtureDocument {
id: string;
taskId: string;
key: string;
title: string;
format: "markdown";
latestRevisionId: string;
revisions: Phase7FixtureDocumentRevision[];
}
export type Phase7InteractionKind =
| "confirmation"
| "checkbox"
| "questions"
| "suggest_tasks"
| "item_verdicts";
export interface Phase7FixtureInteraction {
id: string;
taskId: string;
kind: Phase7InteractionKind;
status: "pending" | "answered" | "accepted" | "rejected" | "expired";
title: string;
prompt: string;
payload: Phase7JsonValue;
targetRevisionId: string | null;
continuationPolicy: "none" | "wake_assignee" | "wake_assignee_on_accept";
result: Phase7JsonValue | null;
createdAt: string;
resolvedAt: string | null;
}
export interface Phase7FixtureApprovalComment {
id: string;
authorActorId: string | null;
body: string;
createdAt: string;
}
export interface Phase7FixtureApproval {
id: string;
companyId: string;
taskIds: string[];
type: string;
status: "pending" | "approved" | "rejected" | "cancelled";
requestedByActorId: string | null;
payload: Phase7JsonValue;
decisionNote: string | null;
comments: Phase7FixtureApprovalComment[];
createdAt: string;
decidedAt: string | null;
}
export interface Phase7FixtureArtifact {
id: string;
taskId: string;
filename: string;
contentType: string;
byteSize: number;
sha256: string;
contentRef: string;
createdAt: string;
}
export interface Phase7FixtureWorkProduct {
id: string;
taskId: string;
type: "artifact" | "document" | "pull_request" | "preview_url" | "runtime_service" | "commit" | "branch";
title: string;
metadata: Phase7JsonValue;
artifactId: string | null;
createdAt: string;
}
export interface Phase7FixtureBlocker {
id: string;
taskId: string;
blockedByTaskId: string;
createdAt: string;
}
export interface Phase7FixtureWorkspaceService {
id: string;
taskId: string;
name: string;
status: "stopped" | "starting" | "running" | "failed";
url: string | null;
lastTransitionAt: string;
}
export interface Phase7FixtureBudget {
id: string;
scope: "company" | "actor";
scopeId: string;
limitCents: number;
spentCents: number;
hardStop: boolean;
}
export type Phase7WakeReason =
| "manual"
| "issue_commented"
| "interaction_resolved"
| "approval_resolved"
| "blockers_resolved"
| "scheduled_retry"
| "resume";
export interface Phase7WakeContext {
reason: Phase7WakeReason;
payload: Phase7JsonValue;
}
export interface Phase7ScheduledWake {
id: string;
actorId: string;
taskId: string;
reason: Phase7WakeReason;
payload: Phase7JsonValue;
dueAt: string;
status: "scheduled" | "delivered" | "cancelled";
createdAt: string;
}
export interface Phase7FixtureRun {
id: string;
companyId: string;
actorId: string;
taskId: string;
sessionId: string;
backendKind: OpenControlPlaneRunInput["backendKind"];
sourceInstanceId: string;
status: "running" | "succeeded" | "failed" | "cancelled" | "budget_stopped";
attempt: number;
openedAt: string;
finishedAt: string | null;
wake: Phase7WakeContext;
capabilities: string[];
events: Array<NativeRunEvent | PrpEvent>;
result: NativeRunResult | CompleteControlPlaneRunInput | null;
sessionCheckpoint: PersistedNativeSession | null;
}
export interface Phase7AuditRecord {
id: string;
at: string;
runId: string | null;
actorId: string | null;
action: string;
entityType: string;
entityId: string;
details: Phase7JsonValue;
}
export interface Phase7DecisionRecord {
id: string;
at: string;
runId: string | null;
operation: string;
outcome: "allowed" | "denied" | "duplicate" | "reconciled" | "faulted";
reason: string;
stateRevision: number;
entityRefs: string[];
}
export interface Phase7FaultRule {
id: string;
operation: "open_run" | "append_event" | "apply_command" | "complete_run";
commandKind?: Phase7SemanticCommand["kind"];
effect: "retryable_error" | "lost_ack";
remaining: number;
code: string;
}
export interface Phase7IdempotencyRecord {
scope: string;
key: string;
inputCanonical: string;
result: Phase7CommandResult;
}
export interface Phase7FixtureState {
schema: "paperclip.phase7.mock-state.v1";
revision: number;
clock: { epochMs: number; tick: number };
counters: Record<string, number>;
lifecycle: "stopped" | "running";
activeRunId: string | null;
company: Phase7FixtureCompany;
actors: Phase7FixtureActor[];
tasks: Phase7FixtureTask[];
comments: Phase7FixtureComment[];
documents: Phase7FixtureDocument[];
interactions: Phase7FixtureInteraction[];
approvals: Phase7FixtureApproval[];
artifacts: Phase7FixtureArtifact[];
workProducts: Phase7FixtureWorkProduct[];
blockers: Phase7FixtureBlocker[];
workspaceServices: Phase7FixtureWorkspaceService[];
budgets: Phase7FixtureBudget[];
runs: Phase7FixtureRun[];
wakes: Phase7ScheduledWake[];
audit: Phase7AuditRecord[];
decisions: Phase7DecisionRecord[];
idempotency: Phase7IdempotencyRecord[];
faults: Phase7FaultRule[];
}
export interface Phase7RunContext {
schema: "paperclip.phase7.run-context.v1";
company: Pick<Phase7FixtureCompany, "id" | "name" | "issuePrefix" | "status">;
actor: Pick<Phase7FixtureActor, "id" | "name" | "role" | "status" | "capabilityGrants">;
activeTask: Phase7FixtureTask;
ancestors: Phase7FixtureTask[];
wake: Phase7WakeContext;
capabilities: string[];
budget: { limitCents: number; spentCents: number; remainingCents: number };
interactionResults: Array<Pick<Phase7FixtureInteraction, "id" | "kind" | "status" | "result">>;
}
export interface Phase7OpenFixtureRunInput extends OpenControlPlaneRunInput {
wake?: Phase7WakeContext;
capabilities?: string[];
resume?: boolean;
}
interface Phase7BaseCommand {
taskId?: string;
}
export type Phase7SemanticCommand =
| (Phase7BaseCommand & { kind: "report_progress"; body: string })
| (Phase7BaseCommand & {
kind: "write_document";
key: string;
title: string;
body: string;
baseRevisionId: string | null;
changeSummary?: string | null;
})
| (Phase7BaseCommand & {
kind: "request_human_input";
interactionKind: Phase7InteractionKind;
title: string;
prompt: string;
payload?: Phase7JsonValue;
targetRevisionId?: string | null;
continuationPolicy: Phase7FixtureInteraction["continuationPolicy"];
})
| (Phase7BaseCommand & {
kind: "resolve_human_input";
interactionId: string;
outcome: "answered" | "accepted" | "rejected" | "expired";
result: Phase7JsonValue;
})
| (Phase7BaseCommand & {
kind: "register_deliverable";
filename: string;
contentType: string;
byteSize: number;
sha256: string;
contentRef: string;
title: string;
})
| (Phase7BaseCommand & { kind: "set_dependencies"; blockedByTaskIds: string[] })
| (Phase7BaseCommand & {
kind: "create_task";
title: string;
description?: string | null;
assigneeActorId?: string | null;
priority?: Phase7FixtureTask["priority"];
blockedByTaskIds?: string[];
})
| (Phase7BaseCommand & {
kind: "request_approval";
approvalType: string;
payload: Phase7JsonValue;
})
| (Phase7BaseCommand & {
kind: "decide_approval";
approvalId: string;
decision: "approved" | "rejected" | "cancelled";
note: string;
})
| (Phase7BaseCommand & {
kind: "comment_on_approval";
approvalId: string;
body: string;
})
| (Phase7BaseCommand & {
kind: "control_workspace_service";
serviceId: string;
action: "start" | "stop" | "fail";
url?: string | null;
})
| (Phase7BaseCommand & { kind: "record_budget_usage"; cents: number })
| (Phase7BaseCommand & { kind: "finish_task"; summary: string })
| (Phase7BaseCommand & {
kind: "block_task";
reason: string;
blockedByTaskIds?: string[];
})
| (Phase7BaseCommand & { kind: "request_review"; summary: string })
| (Phase7BaseCommand & { kind: "release_task"; reason: string })
| (Phase7BaseCommand & {
kind: "schedule_wake";
reason: Phase7WakeReason;
payload?: Phase7JsonValue;
delayTicks: number;
});
export interface Phase7CommandEnvelope {
runId: string;
idempotencyKey: string;
expectedRevision?: number;
command: Phase7SemanticCommand;
}
export interface Phase7CommandResult {
commandId: string;
commandKind: Phase7SemanticCommand["kind"];
disposition: "applied" | "duplicate";
stateRevision: number;
entityRefs: string[];
scheduledWakeIds: string[];
}
export interface Phase7CommandErrorResult {
code: string;
message: string;
retryable: boolean;
}
export type Phase7CommandOutcome =
| { ok: true; result: Phase7CommandResult }
| {
ok: false;
commandKind: Phase7SemanticCommand["kind"];
stateRevision: number;
error: Phase7CommandErrorResult;
};
/**
* Claims enforced by the mock command boundary itself. The semantic catalog
* may hide ungranted operations earlier, but direct adapter consumers cannot
* bypass these checks.
*/
export const PHASE7_COMMAND_REQUIRED_CLAIMS = {
report_progress: [],
write_document: [],
request_human_input: [],
resolve_human_input: ["control_plane:interactions"],
register_deliverable: [],
set_dependencies: ["dependencies:write"],
create_task: ["delegation:tasks:create"],
request_approval: ["governance:approvals:request"],
decide_approval: ["governance:approvals:decide"],
comment_on_approval: ["governance:approvals:comment"],
control_workspace_service: ["workspace:control"],
record_budget_usage: ["control_plane:budget"],
finish_task: [],
block_task: [],
request_review: [],
release_task: ["control_plane:release"],
schedule_wake: ["control_plane:wakes"],
} as const satisfies Record<Phase7SemanticCommand["kind"], readonly string[]>;
export interface Phase7MockControlPlanePort extends ControlPlanePort {
start(): Promise<void>;
stop(): Promise<void>;
openFixtureRun(input: Phase7OpenFixtureRunInput): Promise<Phase7RunContext>;
context(runId: string): Phase7RunContext;
applyCommand(envelope: Phase7CommandEnvelope): Promise<Phase7CommandResult>;
tryApplyCommand(envelope: Phase7CommandEnvelope): Promise<Phase7CommandOutcome>;
snapshot(): Readonly<Phase7FixtureState>;
decisionRecords(): readonly Phase7DecisionRecord[];
serialize(): string;
}
export interface Phase7FixtureSeed {
epochMs?: number;
company?: Partial<Phase7FixtureCompany>;
actors?: Phase7FixtureActor[];
tasks?: Phase7FixtureTask[];
comments?: Phase7FixtureComment[];
documents?: Phase7FixtureDocument[];
interactions?: Phase7FixtureInteraction[];
approvals?: Phase7FixtureApproval[];
artifacts?: Phase7FixtureArtifact[];
workProducts?: Phase7FixtureWorkProduct[];
blockers?: Phase7FixtureBlocker[];
workspaceServices?: Phase7FixtureWorkspaceService[];
budgets?: Phase7FixtureBudget[];
faults?: Phase7FaultRule[];
}
export function createPhase7FixtureState(seed: Phase7FixtureSeed = {}): Phase7FixtureState {
const company: Phase7FixtureCompany = {
id: "company-1",
name: "Mock Paperclip Company",
issuePrefix: "MCK",
status: "active",
budgetId: "budget-company-1",
...seed.company,
};
const actors = seed.actors ?? [
{
id: "actor-1",
companyId: company.id,
name: "Mock Engineer",
role: "engineer",
status: "active",
budgetId: "budget-actor-1",
capabilityGrants: [],
},
];
const tasks = seed.tasks ?? [
{
id: "task-1",
companyId: company.id,
identifier: `${company.issuePrefix}-1`,
title: "Deterministic fixture task",
description: null,
status: "todo",
priority: "medium",
workMode: "standard",
parentId: null,
assigneeActorId: actors[0]?.id ?? null,
checkoutRunId: null,
executionRunId: null,
startedAt: null,
completedAt: null,
},
];
const budgets = seed.budgets ?? [
{
id: company.budgetId,
scope: "company",
scopeId: company.id,
limitCents: 10_000,
spentCents: 0,
hardStop: true,
},
...actors.map((actor) => ({
id: actor.budgetId,
scope: "actor" as const,
scopeId: actor.id,
limitCents: 1_000,
spentCents: 0,
hardStop: true,
})),
];
return {
schema: "paperclip.phase7.mock-state.v1",
revision: 0,
clock: { epochMs: seed.epochMs ?? Date.UTC(2026, 7, 9), tick: 0 },
counters: {},
lifecycle: "stopped",
activeRunId: null,
company,
actors: structuredClone(actors),
tasks: structuredClone(tasks),
comments: structuredClone(seed.comments ?? []),
documents: structuredClone(seed.documents ?? []),
interactions: structuredClone(seed.interactions ?? []),
approvals: structuredClone(seed.approvals ?? []),
artifacts: structuredClone(seed.artifacts ?? []),
workProducts: structuredClone(seed.workProducts ?? []),
blockers: structuredClone(seed.blockers ?? []),
workspaceServices: structuredClone(seed.workspaceServices ?? []),
budgets: structuredClone(budgets),
runs: [],
wakes: [],
audit: [],
decisions: [],
idempotency: [],
faults: structuredClone(seed.faults ?? []),
};
}
@@ -0,0 +1,700 @@
import { describe, expect, it, vi } from "vitest";
import {
CONTROL_PLANE_CONFORMANCE_OPEN,
runControlPlanePortConformance,
} from "../conformance/control-plane-port.js";
import type { Phase7FixtureSeed } from "./phase7-control-plane-types.js";
import {
Phase7MockControlPlaneAdapter,
Phase7MockControlPlaneError,
} from "./phase7-mock-control-plane-adapter.js";
const OPEN = {
identity: {
runId: "run-1",
sessionId: "session-1",
companyId: "company-1",
issueId: "task-1",
agentId: "actor-1",
},
backendKind: "mock" as const,
sourceInstanceId: "fixture-source",
};
function seeded(seed: Phase7FixtureSeed = {}) {
return new Phase7MockControlPlaneAdapter({
workspaceServices: [
{
id: "service-1",
taskId: "task-1",
name: "preview",
status: "stopped",
url: null,
lastTransitionAt: "2026-08-09T00:00:00.000Z",
},
],
...seed,
});
}
describe("Phase7MockControlPlaneAdapter", () => {
it("produces deterministic immutable context and state across every fixture domain", async () => {
const runScenario = async () => {
const adapter = seeded();
await adapter.start();
const context = await adapter.openFixtureRun({
...OPEN,
wake: {
reason: "issue_commented",
payload: {
commentId: "comment-wake",
apiKey: "must-not-be-visible",
nested: { authorization: "Bearer must-not-be-visible" },
},
},
capabilities: [
"control_plane:wakes",
"governance:approvals:comment",
"governance:approvals:request",
"workspace:control",
"task:write",
"task:write",
],
});
expect(context.capabilities).toEqual([
"control_plane:wakes",
"governance:approvals:comment",
"governance:approvals:request",
"task:write",
"workspace:control",
]);
expect(context.wake.payload).toEqual({
commentId: "comment-wake",
apiKey: "[REDACTED]",
nested: { authorization: "[REDACTED]" },
});
await adapter.applyCommand({
runId: "run-1",
idempotencyKey: "progress-1",
command: { kind: "report_progress", body: "Fixture work started." },
});
const documentResult = await adapter.applyCommand({
runId: "run-1",
idempotencyKey: "document-1",
command: {
kind: "write_document",
key: "plan",
title: "Plan",
body: "# Deterministic plan",
baseRevisionId: null,
},
});
const revisionId = documentResult.entityRefs
.find((ref) => ref.startsWith("revision:"))!
.slice("revision:".length);
await adapter.applyCommand({
runId: "run-1",
idempotencyKey: "interaction-1",
command: {
kind: "request_human_input",
interactionKind: "confirmation",
title: "Confirm plan",
prompt: "Accept the deterministic plan?",
targetRevisionId: revisionId,
continuationPolicy: "wake_assignee",
},
});
await adapter.applyCommand({
runId: "run-1",
idempotencyKey: "artifact-1",
command: {
kind: "register_deliverable",
filename: "report.json",
contentType: "application/json",
byteSize: 42,
sha256: "sha256-fixture",
contentRef: "fixture://artifacts/report.json",
title: "Fixture report",
},
});
const approvalResult = await adapter.applyCommand({
runId: "run-1",
idempotencyKey: "approval-1",
command: {
kind: "request_approval",
approvalType: "request_board_approval",
payload: { summary: "Approve fixture action" },
},
});
const approvalId = approvalResult.entityRefs
.find((ref) => ref.startsWith("approval:"))!
.slice("approval:".length);
await adapter.applyCommand({
runId: "run-1",
idempotencyKey: "approval-comment-1",
command: {
kind: "comment_on_approval",
approvalId,
body: "Deterministic approval context.",
},
});
await adapter.applyCommand({
runId: "run-1",
idempotencyKey: "workspace-1",
command: {
kind: "control_workspace_service",
serviceId: "service-1",
action: "start",
url: "http://fixture.invalid",
},
});
await adapter.applyCommand({
runId: "run-1",
idempotencyKey: "wake-1",
command: {
kind: "schedule_wake",
reason: "scheduled_retry",
payload: { attempt: 2 },
delayTicks: 3,
},
});
return { adapter, snapshot: adapter.snapshot() };
};
const left = await runScenario();
const right = await runScenario();
expect(left.adapter.serialize()).toBe(right.adapter.serialize());
expect(left.snapshot).toMatchObject({
schema: "paperclip.phase7.mock-state.v1",
comments: [{ body: "Fixture work started." }],
documents: [{ key: "plan", revisions: [{ revision: 1 }] }],
interactions: [{ kind: "confirmation", status: "pending" }],
approvals: [{
type: "request_board_approval",
status: "pending",
comments: [{ body: "Deterministic approval context." }],
}],
artifacts: [{ filename: "report.json" }],
workProducts: [{ type: "artifact" }],
workspaceServices: [{ id: "service-1", status: "running" }],
wakes: [{ reason: "scheduled_retry", status: "scheduled" }],
});
expect(Object.isFrozen(left.snapshot)).toBe(true);
expect(Object.isFrozen(left.snapshot.tasks)).toBe(true);
expect(left.snapshot.audit.length).toBeGreaterThanOrEqual(7);
expect(left.adapter.decisionRecords().every((decision) => Object.isFrozen(decision))).toBe(true);
});
it("commits a lost-ack command once and returns its stored result on retry", async () => {
const adapter = seeded({
faults: [
{
id: "lost-progress-ack",
operation: "apply_command",
commandKind: "report_progress",
effect: "lost_ack",
remaining: 1,
code: "fixture_ack_lost",
},
],
});
await adapter.start();
await adapter.openFixtureRun(OPEN);
const envelope = {
runId: "run-1",
idempotencyKey: "progress-retry",
command: { kind: "report_progress" as const, body: "Exactly once." },
};
await expect(adapter.applyCommand(envelope)).rejects.toMatchObject({
code: "fixture_ack_lost",
retryable: true,
});
const replayed = await adapter.applyCommand(envelope);
expect(replayed.disposition).toBe("duplicate");
expect(adapter.snapshot().comments.filter((comment) => comment.body === "Exactly once.")).toHaveLength(1);
expect(adapter.decisionRecords().map((decision) => decision.outcome)).toContain("faulted");
expect(adapter.decisionRecords().map((decision) => decision.outcome)).toContain("duplicate");
await expect(
adapter.applyCommand({
...envelope,
command: { kind: "report_progress", body: "Mutated retry." },
}),
).rejects.toMatchObject({ code: "idempotency_conflict" });
});
it("serializes, restores, and replays gapped events without a live service", async () => {
const adapter = seeded();
await adapter.start();
await adapter.openFixtureRun(OPEN);
const event = (sourceSeq: number) => ({
schema: "paperclip.prp.event.v1" as const,
sourceEventId: `fixture-source:event:${sourceSeq}`,
sourceSeq,
sourceInstanceId: "fixture-source",
sourceKind: "runner" as const,
runId: "run-1",
normalizedSessionId: "session-1",
turnId: "turn-1",
eventType: "session.started" as const,
schemaVersion: 1 as const,
priority: 1 as const,
emittedAt: `2026-08-09T00:00:0${sourceSeq}.000Z`,
payload: {},
});
expect((await adapter.appendEvent(event(2))).highestContiguousSourceSeq).toBe(0);
expect((await adapter.appendEvent(event(1))).highestContiguousSourceSeq).toBe(2);
const restored = Phase7MockControlPlaneAdapter.restore(adapter.serialize());
const replay = await restored.replayEvents({
runId: "run-1",
sourceInstanceId: "fixture-source",
afterSourceSeq: 0,
limit: 10,
});
expect(replay.events.map((entry) => entry.sourceSeq)).toEqual([1, 2]);
expect(replay.highestContiguousSourceSeq).toBe(2);
expect(restored.context("run-1")).toEqual(adapter.context("run-1"));
});
it("reconciles terminal state, releases locks, and schedules dependent wakes", async () => {
const adapter = new Phase7MockControlPlaneAdapter({
tasks: [
{
id: "task-1",
companyId: "company-1",
identifier: "MCK-1",
title: "Blocking task",
description: null,
status: "todo",
priority: "high",
workMode: "standard",
parentId: null,
assigneeActorId: "actor-1",
checkoutRunId: null,
executionRunId: null,
startedAt: null,
completedAt: null,
},
{
id: "task-2",
companyId: "company-1",
identifier: "MCK-2",
title: "Dependent task",
description: null,
status: "blocked",
priority: "high",
workMode: "standard",
parentId: null,
assigneeActorId: "actor-1",
checkoutRunId: null,
executionRunId: null,
startedAt: null,
completedAt: null,
},
],
blockers: [
{
id: "blocker-1",
taskId: "task-2",
blockedByTaskId: "task-1",
createdAt: "2026-08-09T00:00:00.000Z",
},
],
});
await adapter.start();
await adapter.openFixtureRun(OPEN);
await adapter.applyCommand({
runId: "run-1",
idempotencyKey: "finish-1",
command: { kind: "finish_task", summary: "Blocking work completed." },
});
const terminal = {
schema: "paperclip.prp.terminal.v1" as const,
turnTerminalState: "completed" as const,
runTerminalState: "succeeded" as const,
reportedWorkDisposition: "done" as const,
};
const result = {
schema: "paperclip.run_result.v1" as const,
reportedWorkDisposition: "done" as const,
summary: "Blocking work completed.",
completionClaim: {
contractRevision: "phase7-v1",
objectiveSatisfied: true,
criteria: [{ criterionId: "objective", status: "satisfied" as const, evidenceRefs: [] }],
remainingWork: [],
},
evidence: [],
verification: [],
attentionRequests: [],
artifacts: [],
};
await adapter.appendEvent({
schema: "paperclip.prp.event.v1",
sourceEventId: "fixture-source:terminal:1",
sourceSeq: 1,
sourceInstanceId: "fixture-source",
sourceKind: "runner",
runId: "run-1",
normalizedSessionId: "session-1",
turnId: "turn-1",
eventType: "run.terminal",
schemaVersion: 1,
priority: 0,
emittedAt: "2026-08-09T00:00:10.000Z",
payload: terminal,
});
await adapter.completeRun({ result, terminal });
const snapshot = adapter.snapshot();
expect(snapshot.tasks.find((task) => task.id === "task-1")).toMatchObject({
status: "done",
checkoutRunId: null,
executionRunId: null,
});
expect(snapshot.tasks.find((task) => task.id === "task-2")?.status).toBe("todo");
expect(snapshot.blockers).toEqual([]);
expect(snapshot.wakes).toMatchObject([
{ taskId: "task-2", reason: "blockers_resolved", status: "scheduled" },
]);
expect(snapshot.runs[0]?.status).toBe("succeeded");
});
it("enforces budget hard stops and releases run authority", async () => {
const adapter = seeded({
budgets: [
{
id: "budget-company-1",
scope: "company",
scopeId: "company-1",
limitCents: 100,
spentCents: 90,
hardStop: true,
},
{
id: "budget-actor-1",
scope: "actor",
scopeId: "actor-1",
limitCents: 100,
spentCents: 90,
hardStop: true,
},
],
});
await adapter.start();
await adapter.openFixtureRun({ ...OPEN, capabilities: ["control_plane:budget"] });
await adapter.applyCommand({
runId: "run-1",
idempotencyKey: "usage-1",
command: { kind: "record_budget_usage", cents: 10 },
});
const snapshot = adapter.snapshot();
expect(snapshot.actors[0]?.status).toBe("paused");
expect(snapshot.runs[0]?.status).toBe("budget_stopped");
expect(snapshot.tasks[0]).toMatchObject({
status: "blocked",
checkoutRunId: null,
executionRunId: null,
});
await expect(
adapter.applyCommand({
runId: "run-1",
idempotencyKey: "after-budget-stop",
command: { kind: "report_progress", body: "Should not be accepted." },
}),
).rejects.toMatchObject({ code: "budget_hard_stop" });
});
it("returns typed denials when a command claim is missing", async () => {
const adapter = seeded();
await adapter.start();
await adapter.openFixtureRun(OPEN);
const outcome = await adapter.tryApplyCommand({
runId: "run-1",
idempotencyKey: "workspace-without-claim",
command: {
kind: "control_workspace_service",
serviceId: "service-1",
action: "start",
},
});
expect(outcome).toEqual({
ok: false,
commandKind: "control_workspace_service",
stateRevision: 2,
error: {
code: "operation_not_authorized",
message: "the fixture run does not hold the required command claim",
retryable: false,
},
});
expect(adapter.snapshot().workspaceServices[0]?.status).toBe("stopped");
expect(adapter.decisionRecords().at(-1)).toMatchObject({
operation: "control_workspace_service",
outcome: "denied",
reason: "required_claim_missing",
});
});
it("enforces active-task ownership and legal transitions", async () => {
const adapter = seeded({
tasks: [
{
id: "task-1",
companyId: "company-1",
identifier: "MCK-1",
title: "Active task",
description: null,
status: "todo",
priority: "high",
workMode: "standard",
parentId: null,
assigneeActorId: "actor-1",
checkoutRunId: null,
executionRunId: null,
startedAt: null,
completedAt: null,
},
{
id: "task-2",
companyId: "company-1",
identifier: "MCK-2",
title: "Other task",
description: null,
status: "todo",
priority: "low",
workMode: "standard",
parentId: null,
assigneeActorId: "actor-1",
checkoutRunId: null,
executionRunId: null,
startedAt: null,
completedAt: null,
},
],
});
await adapter.start();
await adapter.openFixtureRun(OPEN);
await expect(adapter.tryApplyCommand({
runId: "run-1",
idempotencyKey: "cross-task-write",
command: { kind: "report_progress", taskId: "task-2", body: "Not allowed." },
})).resolves.toMatchObject({
ok: false,
error: { code: "task_scope_violation" },
});
await adapter.applyCommand({
runId: "run-1",
idempotencyKey: "review-once",
command: { kind: "request_review", summary: "Ready for review." },
});
await expect(adapter.tryApplyCommand({
runId: "run-1",
idempotencyKey: "review-twice",
command: { kind: "request_review", summary: "Still ready." },
})).resolves.toMatchObject({
ok: false,
error: { code: "task_transition_illegal" },
});
expect(adapter.snapshot().comments.map((comment) => comment.body)).toEqual([
"Ready for review.",
]);
});
it("rejects stale interaction targets and invalid interaction outcomes", async () => {
const adapter = seeded();
await adapter.start();
await adapter.openFixtureRun({
...OPEN,
capabilities: ["control_plane:interactions"],
});
const first = await adapter.applyCommand({
runId: "run-1",
idempotencyKey: "plan-v1",
command: {
kind: "write_document",
key: "plan",
title: "Plan",
body: "Version one",
baseRevisionId: null,
},
});
const firstRevisionId = first.entityRefs.find((ref) => ref.startsWith("revision:"))!.slice(9);
const second = await adapter.applyCommand({
runId: "run-1",
idempotencyKey: "plan-v2",
command: {
kind: "write_document",
key: "plan",
title: "Plan",
body: "Version two",
baseRevisionId: firstRevisionId,
},
});
const secondRevisionId = second.entityRefs.find((ref) => ref.startsWith("revision:"))!.slice(9);
await expect(adapter.tryApplyCommand({
runId: "run-1",
idempotencyKey: "stale-confirmation",
command: {
kind: "request_human_input",
interactionKind: "confirmation",
title: "Confirm",
prompt: "Accept?",
targetRevisionId: firstRevisionId,
continuationPolicy: "wake_assignee",
},
})).resolves.toMatchObject({
ok: false,
error: { code: "interaction_target_stale" },
});
const interaction = await adapter.applyCommand({
runId: "run-1",
idempotencyKey: "current-confirmation",
command: {
kind: "request_human_input",
interactionKind: "confirmation",
title: "Confirm",
prompt: "Accept?",
targetRevisionId: secondRevisionId,
continuationPolicy: "wake_assignee",
},
});
const interactionId = interaction.entityRefs.find((ref) => ref.startsWith("interaction:"))!.slice(12);
await expect(adapter.tryApplyCommand({
runId: "run-1",
idempotencyKey: "invalid-confirmation-answer",
command: {
kind: "resolve_human_input",
interactionId,
outcome: "answered",
result: { answer: "yes" },
},
})).resolves.toMatchObject({
ok: false,
error: { code: "interaction_outcome_invalid" },
});
});
it("performs complete mock operations without any Paperclip network request", async () => {
const fetch = vi.spyOn(globalThis, "fetch").mockRejectedValue(
new Error("network access is forbidden in the mock control plane"),
);
try {
const adapter = seeded();
await adapter.start();
await adapter.openFixtureRun(OPEN);
await adapter.applyCommand({
runId: "run-1",
idempotencyKey: "offline-progress",
command: { kind: "report_progress", body: "Committed offline." },
});
const restored = Phase7MockControlPlaneAdapter.restore(adapter.serialize());
expect(restored.snapshot().comments).toMatchObject([{ body: "Committed offline." }]);
expect(fetch).not.toHaveBeenCalled();
} finally {
fetch.mockRestore();
}
});
it("implements the existing ControlPlanePort conformance contract", async () => {
const identity = CONTROL_PLANE_CONFORMANCE_OPEN.identity;
const adapter = new Phase7MockControlPlaneAdapter({
company: {
id: identity.companyId,
name: "Conformance Company",
issuePrefix: "CNF",
status: "active",
budgetId: "budget-company-conformance",
},
actors: [
{
id: identity.agentId,
companyId: identity.companyId,
name: "Conformance Actor",
role: "engineer",
status: "active",
budgetId: "budget-actor-conformance",
capabilityGrants: [],
},
],
tasks: [
{
id: identity.issueId,
companyId: identity.companyId,
identifier: "CNF-1",
title: "Conformance task",
description: null,
status: "todo",
priority: "medium",
workMode: "standard",
parentId: null,
assigneeActorId: identity.agentId,
checkoutRunId: null,
executionRunId: null,
startedAt: null,
completedAt: null,
},
],
budgets: [
{
id: "budget-company-conformance",
scope: "company",
scopeId: identity.companyId,
limitCents: 100,
spentCents: 0,
hardStop: true,
},
{
id: "budget-actor-conformance",
scope: "actor",
scopeId: identity.agentId,
limitCents: 100,
spentCents: 0,
hardStop: true,
},
],
});
await expect(runControlPlanePortConformance({ port: adapter, start: () => adapter.start() }))
.resolves.toMatchObject({
eventCount: 3,
terminalReplayIdempotent: true,
openBindingRejected: true,
eventIdMutationRejected: true,
eventSequenceMutationRejected: true,
replayBindingRejected: true,
resultMutationRejected: true,
});
});
it("uses stable typed errors for retryable scripted failures", async () => {
const adapter = seeded({
faults: [
{
id: "retry-open",
operation: "open_run",
effect: "retryable_error",
remaining: 1,
code: "fixture_transient",
},
],
});
await adapter.start();
const error = await adapter.openFixtureRun(OPEN).catch((caught) => caught);
expect(error).toBeInstanceOf(Phase7MockControlPlaneError);
expect(error).toMatchObject({ code: "fixture_transient", retryable: true });
await expect(adapter.openFixtureRun(OPEN)).resolves.toMatchObject({
activeTask: { id: "task-1", status: "in_progress" },
});
});
});
File diff suppressed because it is too large. Load diff