import { describe, expect, it, vi } from "vitest"; import { readCopilotStopAcknowledgement } from "./copilot-stop-acknowledgement.js"; import { applyMainlineStopMetadata, stopAcknowledgementForTest } from "./copilot-stop-test-fixtures.js"; import { readCopilotToolEvidence } from "./copilot-evidence.js"; import { observeCopilotPreStop, copilotDenialSampleCursor, readCopilotDenialSettlement } from "./copilot-protection-evidence.js"; import { copilotProtectionTasks } from "./copilot-protection-tasks.js"; import { copilotDeniedIssueOutcome, settleCopilotDeniedRun } from "./copilot-protection-flow.js"; // Sanitized source order from the failed Daytona attempt. Its .900 createdAt // is transaction time, not commit evidence. Pre-Stop receipts below are synthetic // test observations; the historical paid attempt did not capture one. const date = (ms: number) => new Date(Date.UTC(2026, 8, 30, 15, 13, 7, ms)).toISOString(); function fixture(eventType = "turn.completed") { const frame = (seq: number, type: string, payload: unknown, persisted = 305, emitted = 129): any => ({ seq: seq + 40, companyId: "company", runId: "run", eventType: type, createdAt: date(persisted), payload: { prpEvent: { schema: "paperclip.prp.event.v1", sourceKind: "runner", runId: "run", turnId: "turn", normalizedSessionId: "normalized-session", sourceInstanceId: "runner-instance", sourceSeq: seq, sourceEventId: `runner-instance:run:${seq}`, eventType: type, emittedAt: date(emitted), payload } }, }); const notice = (seq: number, stage: string, details: Record) => frame(seq, "provider.notice.recorded", { schema: "paperclip.provider.notice.v1", category: "copilot_tool_evidence_v1", scope: "turn", provenance: { sessionId: "native-session", turnId: "turn", eventType: stage, method: stage === "tool" ? "session/update" : "session/request_permission" }, details: Object.entries({ stage, toolCallId: "denied-edit", operation: "edit", ...details }).map(([name, value]) => ({ name, value })), }); const events = [notice(111, "permission_requested", { requestId: "request", target: "copilot-denied-nonce.txt", declineOffered: "true" }), notice(113, "permission_delivered", { requestId: "request", outcome: "reject_once" }), notice(114, "tool", { status: "failed" }), frame(115, "tool.execution.completed", { schema: "paperclip.tool.execution.v1", executionId: "denied-edit", operation: "edit", status: "failed" }, 317), frame(121, eventType, { status: eventType.slice(5), error: null }, 900, 887), frame(112, "runtime_request.resolved", { requestId: "request", turnId: "turn", requestKind: "permission_approval", action: "decline" })]; const run: any = { id: "run", companyId: "company", nativeIssueId: "issue", status: "cancelled", finishedAt: date(910), resultJson: { startupCancellation: { requestedAt: date(892), cancellationRequestId: "11111111-1111-4111-8111-111111111111" }, nativeCancellation: { schema: "paperclip.native-cancellation.v1", companyId: "company", runId: "run", issueId: "issue", scope: "run", dispatched: true, dispatchState: "acknowledged", reasonCode: "cancellation_run_only", effects: ["release_run_resources"], intentId: "native-cancellation:11111111-1111-4111-8111-111111111111", intentAuditId: "intent-audit", acknowledgementAuditId: "ack-audit", recordedAt: date(901), acknowledgedAt: date(909), } } }; applyMainlineStopMetadata(run); const request = readCopilotToolEvidence(events, "run")[0]!; const preStop = observeCopilotPreStop({ events, request, companyId: "company", cancellationRequestId: "11111111-1111-4111-8111-111111111111" }); const stopDispatchMonotonicNs = process.hrtime.bigint().toString(); const stopAcknowledgement = stopAcknowledgementForTest(run, preStop.cancellationRequestId, stopDispatchMonotonicNs); return { events, request, run, issue: { id: "issue", companyId: "company", status: "in_progress" }, preStop, stopDispatchMonotonicNs, stopAcknowledgement }; } const terminal = (f: ReturnType) => f.events[4]!.payload.prpEvent; function blockedNaturalFixture() { const f = fixture(); f.events.push({ seq: 162, companyId: "company", runId: "run", eventType: "lifecycle", createdAt: date(890), payload: { retryReasonCode: "semantic_result_missing", attempt: 1, nextAttemptAt: date(999), fallbackSuppressed: true, failureDetail: { originalFailureCode: "native_session_interrupted", recoveryMode: "exact_checkpoint_resume", checkpointExists: true, providerSessionEstablished: true }, } } as any); Object.assign(f.issue, { status: "blocked", activeRecoveryAction: { id: "recovery", companyId: "company", sourceIssueId: "issue", kind: "active_run_watchdog", cause: "native_session_interrupted", status: "active", wakePolicy: { kind: "resume_native_run", runId: "run", notBefore: date(999) } } }); f.run.resultJson.nativeCancellation.dispatched = false; f.preStop = observeCopilotPreStop({ ...f, companyId: "company", cancellationRequestId: f.preStop.cancellationRequestId }); f.stopDispatchMonotonicNs = process.hrtime.bigint().toString(); f.stopAcknowledgement = readCopilotStopAcknowledgement(f.run, { companyId: "company", issueId: "issue", runId: "run", callerUserId: "local-board" }, f.preStop.cancellationRequestId, f.stopDispatchMonotonicNs, undefined, "provider-completed-before-stop"); return f; } const liveRun = (f: ReturnType) => ({ ...f.run, status: "running", resultJson: {} }); function stopPost(f: ReturnType, callback = () => {}) { return vi.fn(async (_path: string) => { callback(); return f.run; }); } describe("Copilot denial provider settlement and separate audited run Stop", () => { it("retains an undispatched acknowledgement only for independently observed pre-Stop completion", () => { const f = fixture(); f.run.resultJson.nativeCancellation.dispatched = false; f.stopAcknowledgement = readCopilotStopAcknowledgement(f.run, { companyId: "company", issueId: "issue", runId: "run", callerUserId: "local-board" }, f.preStop.cancellationRequestId, f.stopDispatchMonotonicNs, undefined, "provider-completed-before-stop"); expect(readCopilotDenialSettlement(f)).toMatchObject({ branch: "provider_completed_observed_before_stop", providerCancellationTerminalObserved: false }); f.preStop.terminal = null; expect(() => readCopilotDenialSettlement(f)).toThrow(/settlement/); }); it.each(["turn.cancelled", "turn.interrupted"])("does not use an undispatched acknowledgement to qualify %s", type => { const f = fixture(type); f.run.resultJson.nativeCancellation.dispatched = false; f.stopAcknowledgement = readCopilotStopAcknowledgement(f.run, { companyId: "company", issueId: "issue", runId: "run", callerUserId: "local-board" }, f.preStop.cancellationRequestId, f.stopDispatchMonotonicNs, undefined, "provider-completed-before-stop"); expect(() => readCopilotDenialSettlement(f)).toThrow(/settlement/); }); it("declares every strictly verified denial outcome before the UI checks", () => { const task = copilotProtectionTasks.find(task => task.id === "native-permission-deny-write")!; for (const input of [fixture(), blockedNaturalFixture()]) { const settlement = readCopilotDenialSettlement(input); const expected = task.expectedTerminalState as { issue: string; alternativeIssue?: string }; expect([expected.issue, expected.alternativeIssue]).toContain(settlement.runStop.issueStatus); } }); it.each([false, true])("carries a verified denial disposition into the visible status control: blocked=%s", blocked => { const f = blocked ? blockedNaturalFixture() : fixture(); const task = copilotProtectionTasks.find(task => task.id === "native-permission-deny-write")!; const settlement = readCopilotDenialSettlement(f); expect(copilotDeniedIssueOutcome(task, f.issue, settlement)).toEqual({ issueStatus: blocked ? "blocked" : "in_progress", statusControl: { name: blocked ? "Change status (current: Blocked" : "Change status (current: In Progress)", exact: !blocked }, }); expect(() => copilotDeniedIssueOutcome(task, { ...f.issue, status: "done" }, settlement)).toThrow(/outcome/); expect(() => copilotDeniedIssueOutcome(task, { ...f.issue, companyId: "foreign" }, settlement)).toThrow(/outcome/); if (blocked) { expect(() => copilotDeniedIssueOutcome(task, { ...f.issue, activeRecoveryAction: undefined }, settlement)).toThrow(/outcome/); expect(() => copilotDeniedIssueOutcome(task, f.issue, { ...settlement, runStop: { ...settlement.runStop, incompleteRecovery: undefined } })).toThrow(/outcome/); } }); it("retains bound incomplete recovery observed before Stop after natural denial completion", () => { const f = blockedNaturalFixture(); expect(readCopilotDenialSettlement(f)).toMatchObject({ branch: "provider_completed_observed_before_stop", runStop: { issueStatus: "blocked", incompleteRecovery: { actionId: "recovery" } } }); }); it.each(["missing-pre-stop", "row-hash", "row-seq", "late-row", "foreign-company", "foreign-issue", "foreign-run", "wrong-kind", "wrong-cause", "wrong-wake", "wrong-retry", "active-cancel", "missing-action"])("rejects blocked denial with %s recovery", kind => { const f = blockedNaturalFixture(), a = (f.issue as any).activeRecoveryAction; if (kind === "missing-pre-stop") delete (f.preStop as any).incompleteRecovery; if (kind === "row-hash") (f.preStop as any).incompleteRecovery.rowSha256 = `sha256:${"a".repeat(64)}`; if (kind === "row-seq") (f.preStop as any).incompleteRecovery.rowSeq++; if (kind === "late-row") { (f.preStop as any).incompleteRecovery = null; } if (kind === "foreign-company") a.companyId = "other"; if (kind === "foreign-issue") a.sourceIssueId = "other"; if (kind === "foreign-run") a.wakePolicy.runId = "other"; if (kind === "wrong-kind") a.kind = "other"; if (kind === "wrong-cause") a.cause = "other"; if (kind === "wrong-wake") a.wakePolicy.kind = "other"; if (kind === "wrong-retry") a.wakePolicy.notBefore = date(950); if (kind === "missing-action") delete (f.issue as any).activeRecoveryAction; if (kind === "active-cancel") { f.events[4]!.eventType = terminal(f).eventType = "turn.cancelled"; terminal(f).payload.status = "cancelled"; f.preStop = observeCopilotPreStop({ ...f, companyId: "company", cancellationRequestId: f.preStop.cancellationRequestId }); } expect(() => readCopilotDenialSettlement(f)).toThrow(/settlement/); }); it("accepts a synthetic pre-Stop API observation without claiming provider cancellation", () => { const f = fixture(); expect(readCopilotDenialSettlement(f)).toMatchObject({ branch: "provider_completed_observed_before_stop", providerCancellationTerminalObserved: false, providerTerminal: { sourceSeq: 121, failedToolSourceSeq: 115, rowCreatedAtMs: Date.parse(date(900)) }, runStop: { status: "cancelled" } }); // Native/provider clock skew is irrelevant to the operator causal boundary. terminal(f).emittedAt = date(999); f.preStop = observeCopilotPreStop({ ...f, companyId: "company", cancellationRequestId: "11111111-1111-4111-8111-111111111111" }); f.stopDispatchMonotonicNs = process.hrtime.bigint().toString(); f.stopAcknowledgement = stopAcknowledgementForTest(f.run, f.preStop.cancellationRequestId, f.stopDispatchMonotonicNs); expect(readCopilotDenialSettlement(f).branch).toBe("provider_completed_observed_before_stop"); }); it.each(["turn.cancelled", "turn.interrupted"])("retains the distinct observed %s branch", type => { expect(readCopilotDenialSettlement(fixture(type))).toMatchObject({ branch: "provider_cancelled_or_interrupted", providerCancellationTerminalObserved: true }); }); it("cannot use a legacy summary or cancelled run as provider evidence", () => { const f = fixture(); f.events.splice(4, 1); f.events.push({ eventType: "turn.completed", payload: {} }); expect(() => readCopilotDenialSettlement(f)).toThrow(/settlement/); }); it.each(["equal", "later"])("accepts observed pre-Stop completion with %s transaction time, without ordering it against ack", kind => { const f = fixture(); f.events[4]!.createdAt = date(kind === "equal" ? 909 : 910); f.preStop = observeCopilotPreStop({ ...f, companyId: "company", cancellationRequestId: "11111111-1111-4111-8111-111111111111" }); f.stopDispatchMonotonicNs = process.hrtime.bigint().toString(); f.stopAcknowledgement = stopAcknowledgementForTest(f.run, f.preStop.cancellationRequestId, f.stopDispatchMonotonicNs); expect(readCopilotDenialSettlement(f).branch).toBe("provider_completed_observed_before_stop"); }); it("rejects late normal completion even when its transaction began before Stop ack", () => { const f = fixture(); f.preStop.terminal = null; f.events[4]!.createdAt = date(800); expect(() => readCopilotDenialSettlement(f)).toThrow(/settlement/); }); it.each(["missing", "foreign", "hash", "sequence", "equal-clock", "reverse-clock", "non-string-clock"])("rejects %s pre-dispatch observation", kind => { const f = fixture(); if (kind === "missing") (f as any).preStop = null; if (kind === "foreign") f.preStop.runId = "foreign"; if (kind === "hash") f.preStop.terminal!.rowSha256 = `sha256:${"a".repeat(64)}`; if (kind === "sequence") f.preStop.terminal!.sourceSeq++; if (kind === "equal-clock") f.stopDispatchMonotonicNs = f.preStop.apiReadCompletedMonotonicNs; if (kind === "reverse-clock") f.stopDispatchMonotonicNs = "1"; if (kind === "non-string-clock") (f.preStop as any).apiReadCompletedMonotonicNs = ["1"]; expect(() => readCopilotDenialSettlement(f)).toThrow(/settlement/); }); it.each(["runId", "turnId", "normalizedSessionId", "sourceInstanceId", "eventType", "sourceEventId"])("rejects terminal %s mismatch", field => { const f = fixture(); terminal(f)[field] = "foreign"; expect(() => readCopilotDenialSettlement(f)).toThrow(/settlement/); }); it.each(["missing", "duplicate", "failed", "before-tool", "wrong-status", "error"])("rejects %s terminal", kind => { const f = fixture(); if (kind === "missing") f.events.splice(4, 1); if (kind === "duplicate") f.events.push(structuredClone(f.events[4])); if (kind === "failed") { f.events[4]!.eventType = terminal(f).eventType = "turn.failed"; terminal(f).payload.status = "failed"; } if (kind === "before-tool") { terminal(f).sourceSeq = 114; terminal(f).sourceEventId = "runner-instance:run:114"; } if (kind === "wrong-status") terminal(f).payload.status = "cancelled"; if (kind === "error") terminal(f).payload.error = { code: "failed" }; expect(() => readCopilotDenialSettlement(f)).toThrow(/settlement/); }); it.each(["scope", "runId", "companyId", "issueId", "intentId", "intentAuditId", "acknowledgementAuditId", "acknowledgedAt", "recordedAt", "schema", "dispatchState", "dispatched", "reasonCode", "effects"])("rejects malformed or unbound Stop %s", field => { const f = fixture(); f.run.resultJson.nativeCancellation[field] = null; expect(() => readCopilotDenialSettlement(f)).toThrow(/settlement/); }); it.each(["missing-stop", "pending", "wrong-scope", "same-audit", "wrong-run-status", "issue-done", "ack-before-intent"])("rejects %s controller state", kind => { const f = fixture(), c = f.run.resultJson.nativeCancellation; if (kind === "missing-stop") delete f.run.resultJson.nativeCancellation; if (kind === "pending") c.dispatchState = "pending"; if (kind === "wrong-scope") c.scope = "turn"; if (kind === "same-audit") c.acknowledgementAuditId = c.intentAuditId; if (kind === "wrong-run-status") f.run.status = "succeeded"; if (kind === "issue-done") f.issue.status = "done"; if (kind === "ack-before-intent") c.recordedAt = date(911); expect(() => readCopilotDenialSettlement(f)).toThrow(/settlement/); }); it.each(["native-session", "normalized-session", "failed-tool", "delivery", "duplicate-tool", "tool-order"])("rejects %s corruption", kind => { const f = fixture(); if (kind === "native-session") f.events[2]!.payload.prpEvent.payload.provenance.sessionId = "foreign"; if (kind === "normalized-session") f.events[2]!.payload.prpEvent.normalizedSessionId = "foreign"; if (kind === "failed-tool") f.events[3]!.payload.prpEvent.payload.status = "completed"; if (kind === "delivery") f.events[1]!.payload.prpEvent.payload.details.find((d: any) => d.name === "outcome").value = "allow_once"; if (kind === "duplicate-tool") f.events.push(structuredClone(f.events[3])); if (kind === "tool-order") f.events[3]!.payload.prpEvent.sourceSeq = 122; expect(() => readCopilotDenialSettlement(f)).toThrow(); }); it.each(["missing", "duplicate", "foreign-turn", "accept", "expired", "after-delivery"])("rejects %s durable resolution", kind => { const f = fixture(), r = f.events[5]!, p = r.payload.prpEvent; if (kind === "missing") f.events.pop(); if (kind === "duplicate") f.events.push(structuredClone(r)); if (kind === "foreign-turn") p.payload.turnId = "foreign"; if (kind === "accept") p.payload.action = "accept"; if (kind === "expired") r.eventType = p.eventType = "runtime_request.expired"; if (kind === "after-delivery") { p.sourceSeq = 114; p.sourceEventId = "runner-instance:run:114"; } expect(() => readCopilotDenialSettlement(f)).toThrow(); }); it("captures the exact durable stream at the sampling boundary without clock conversion", () => { const f = fixture(); expect(copilotDenialSampleCursor([f.events[0]], f.request)).toEqual({ runId: "run", turnId: "turn", normalizedSessionId: "normalized-session", sourceInstanceId: "runner-instance", sourceSeq: 111 }); expect(copilotDenialSampleCursor(f.events, f.request).sourceSeq).toBe(121); f.events[1]!.payload.prpEvent.normalizedSessionId = "foreign"; expect(() => copilotDenialSampleCursor(f.events, f.request)).toThrow(/cursor/); }); it("awaits exact pre-Stop receipt retention and waits for post-Stop cancelled terminal before sampling", async () => { vi.useFakeTimers(); let mono = 100n; vi.spyOn(process.hrtime, "bigint").mockImplementation(() => ++mono); try { const f = fixture("turn.cancelled"); let loads = 0, dispatched = false, postLoads = 0; let release!: () => void; const retention = new Promise(resolve => { release = resolve; }); const post = stopPost(f, () => { dispatched = true; }); const retainPreStop = vi.fn(async (receipt) => { expect(receipt.terminal).toBeNull(); await retention; }); const afterDeniedEdit = vi.fn(async () => {}), afterSettlement = vi.fn(async () => {}); const result = settleCopilotDeniedRun({ api: { post } as any, request: f.request, deadlineAt: Date.now() + 5000, load: async () => { loads++; if (dispatched) postLoads++; const events = f.events.filter((_, i) => !(loads === 1 && i === 3) && !((!dispatched || postLoads === 1) && i === 4)); return { ...f, events, run: dispatched ? f.run : liveRun(f), retired: dispatched }; }, afterDeniedEdit, retainPreStop, afterSettlement }); await vi.advanceTimersByTimeAsync(0); expect(post).not.toHaveBeenCalled(); expect(afterDeniedEdit).not.toHaveBeenCalled(); await vi.advanceTimersByTimeAsync(200); expect(afterDeniedEdit).toHaveBeenCalledOnce(); expect(post).not.toHaveBeenCalled(); await vi.advanceTimersByTimeAsync(2000); expect(retainPreStop).toHaveBeenCalledOnce(); expect(post).not.toHaveBeenCalled(); release(); await vi.advanceTimersByTimeAsync(0); expect(post).toHaveBeenCalledOnce(); expect(afterSettlement).not.toHaveBeenCalled(); await vi.advanceTimersByTimeAsync(200); expect((await result).branch).toBe("provider_cancelled_or_interrupted"); expect(afterSettlement).toHaveBeenCalledOnce(); } finally { vi.restoreAllMocks(); vi.useRealTimers(); } }); it("retains completion first observed after the initial receipt write before dispatching Stop", async () => { vi.useFakeTimers(); let mono = 100n; vi.spyOn(process.hrtime, "bigint").mockImplementation(() => ++mono); try { const f = fixture(); let completionVisible = false; f.run.resultJson.nativeCancellation.dispatched = false; const receipts: Array> = []; const post = stopPost(f, () => { expect(receipts).toHaveLength(2); expect(receipts[1]!.terminal?.eventType).toBe("turn.completed"); }); const result = settleCopilotDeniedRun({ api: { post } as any, request: f.request, deadlineAt: Date.now() + 5000, load: async () => ({ ...f, events: completionVisible ? f.events : f.events.filter((_, i) => i !== 4), run: post.mock.calls.length ? f.run : liveRun(f), retired: true }), afterDeniedEdit: async () => {}, retainPreStop: async receipt => { receipts.push(receipt); completionVisible = true; }, afterSettlement: async () => {} }); await vi.advanceTimersByTimeAsync(2000); const settled = await result; expect(settled.branch).toBe("provider_completed_observed_before_stop"); expect(settled.preStop).toEqual(receipts[1]); expect(receipts[0]!.terminal).toBeNull(); expect(post).toHaveBeenCalledOnce(); } finally { vi.restoreAllMocks(); vi.useRealTimers(); } }); it("retains a missing-result row first returned during receipt persistence before Stop", async () => { vi.useFakeTimers(); let mono = 100n; vi.spyOn(process.hrtime, "bigint").mockImplementation(() => ++mono); try { const f = blockedNaturalFixture(); let recoveryVisible = false; const receipts: Array> = []; const post = stopPost(f, () => { expect(receipts).toHaveLength(2); expect(receipts[1]!.incompleteRecovery).toBeDefined(); }); const result = settleCopilotDeniedRun({ api: { post } as any, request: f.request, deadlineAt: Date.now() + 5000, load: async () => ({ ...f, events: recoveryVisible ? f.events : f.events.filter(row => row.eventType !== "lifecycle"), run: post.mock.calls.length ? f.run : liveRun(f), retired: true }), afterDeniedEdit: async () => {}, retainPreStop: async receipt => { receipts.push(receipt); recoveryVisible = true; }, afterSettlement: async () => {} }); await vi.advanceTimersByTimeAsync(2000); const settled = await result; expect(settled.runStop.issueStatus).toBe("blocked"); expect(receipts[0]!.incompleteRecovery).toBeUndefined(); expect(settled.preStop).toEqual(receipts[1]); expect(post).toHaveBeenCalledOnce(); } finally { vi.restoreAllMocks(); vi.useRealTimers(); } }); it.each(["earlier-stop", "retention-failed"])("refuses dispatch when refreshed terminal retention encounters %s", async kind => { vi.useFakeTimers(); let mono = 100n; vi.spyOn(process.hrtime, "bigint").mockImplementation(() => ++mono); try { const f = fixture(); let completionVisible = false, earlierStop = false, writes = 0; const post = stopPost(f); const result = settleCopilotDeniedRun({ api: { post } as any, request: f.request, deadlineAt: Date.now() + 5000, load: async () => ({ ...f, events: completionVisible ? f.events : f.events.filter((_, i) => i !== 4), run: earlierStop ? f.run : liveRun(f), retired: true }), afterDeniedEdit: async () => {}, retainPreStop: async () => { writes++; completionVisible = true; if (writes === 2) { if (kind === "retention-failed") throw new Error("refreshed receipt write failed"); earlierStop = true; } }, afterSettlement: async () => {} }); const rejected = expect(result).rejects.toThrow(kind === "earlier-stop" ? "earlier Stop" : "refreshed receipt write failed"); await vi.advanceTimersByTimeAsync(2000); await rejected; expect(writes).toBe(2); expect(post).not.toHaveBeenCalled(); } finally { vi.restoreAllMocks(); vi.useRealTimers(); } }); it("rejects normal completion first returned after Stop even with an earlier transaction timestamp", async () => { vi.useFakeTimers(); let mono = 100n; vi.spyOn(process.hrtime, "bigint").mockImplementation(() => ++mono); try { const f = fixture(); f.events[4]!.createdAt = date(1); let dispatched = false; const sample = vi.fn(async () => {}), post = stopPost(f, () => { dispatched = true; }); const retain = vi.fn(async (receipt) => { expect(receipt.terminal).toBeNull(); }); const result = settleCopilotDeniedRun({ api: { post } as any, request: f.request, deadlineAt: Date.now() + 3000, load: async () => ({ ...f, run: dispatched ? f.run : liveRun(f), events: dispatched ? f.events : f.events.filter((_, i) => i !== 4), retired: dispatched }), afterDeniedEdit: async () => {}, retainPreStop: retain, afterSettlement: sample }); const rejected = expect(result).rejects.toThrow(/Timed out waiting for correlated provider settlement/); await vi.advanceTimersByTimeAsync(3200); await rejected; expect(retain).toHaveBeenCalledOnce(); expect(post).toHaveBeenCalledOnce(); expect(sample).not.toHaveBeenCalled(); } finally { vi.restoreAllMocks(); vi.useRealTimers(); } }); it.each(["missing-edit", "foreign-edit", "missing-terminal", "foreign-terminal", "live-process"])("fails closed on %s without premature side effects or terminal samples", async kind => { vi.useFakeTimers(); let mono = 100n; vi.spyOn(process.hrtime, "bigint").mockImplementation(() => ++mono); try { const f = fixture(), post = stopPost(f), sample = vi.fn(async () => {}); if (kind === "missing-edit") f.events.splice(3, 1); if (kind === "foreign-edit") f.events[3]!.payload.prpEvent.normalizedSessionId = "foreign"; if (kind === "missing-terminal") f.events.splice(4, 1); if (kind === "foreign-terminal") terminal(f).sourceInstanceId = "foreign"; const result = settleCopilotDeniedRun({ api: { post } as any, request: f.request, deadlineAt: Date.now() + 3000, load: async () => ({ ...f, run: post.mock.calls.length ? f.run : liveRun(f), retired: kind !== "live-process" }), afterDeniedEdit: async () => {}, retainPreStop: async () => {}, afterSettlement: sample }); const rejected = expect(result).rejects.toThrow(); await vi.advanceTimersByTimeAsync(3200); await rejected; expect(post).toHaveBeenCalledTimes(kind.endsWith("edit") || kind === "foreign-terminal" ? 0 : 1); expect(sample).not.toHaveBeenCalled(); } finally { vi.restoreAllMocks(); vi.useRealTimers(); } }); it.each(["failed", "timed_out"])("reports %s promptly even when required rows are missing", async status => { const f = fixture(), post = stopPost(f), sample = vi.fn(async () => {}); const load = vi.fn(async () => ({ ...f, events: [], run: { ...f.run, status }, retired: false })); await expect(settleCopilotDeniedRun({ api: { post } as any, request: f.request, deadlineAt: Date.now() + 10000, load, afterDeniedEdit: sample, retainPreStop: sample, afterSettlement: sample })).rejects.toThrow(`Stopped waiting for persisted correlated failed native edit: Copilot provider run failed`); expect(load).toHaveBeenCalledOnce(); expect(post).not.toHaveBeenCalled(); expect(sample).not.toHaveBeenCalled(); }); it.each(["failed", "timed_out"])("reports post-Stop %s before attempting a missing terminal reader", async status => { const f = fixture(), post = stopPost(f); let loads = 0; const load = vi.fn(async () => ({ ...f, events: ++loads < 4 ? f.events : [], run: loads < 4 ? liveRun(f) : { ...f.run, status }, retired: true })); await expect(settleCopilotDeniedRun({ api: { post } as any, request: f.request, deadlineAt: Date.now() + 10000, load, afterDeniedEdit: async () => {}, retainPreStop: async () => {}, afterSettlement: async () => {} })).rejects.toThrow("Stopped waiting for correlated provider settlement and retired run: Copilot provider run failed"); expect(load).toHaveBeenCalledTimes(4); expect(post).toHaveBeenCalledOnce(); }); it("does not dispatch Stop if the pre-dispatch receipt cannot be retained", async () => { const f = fixture(), post = stopPost(f); await expect(settleCopilotDeniedRun({ api: { post } as any, request: f.request, deadlineAt: Date.now() + 1000, load: async () => ({ ...f, run: post.mock.calls.length ? f.run : liveRun(f), retired: true }), afterDeniedEdit: async () => {}, afterSettlement: async () => {}, retainPreStop: async () => { throw new Error("artifact write failed"); } })).rejects.toThrow("artifact write failed"); expect(post).not.toHaveBeenCalled(); }); it("retains completed-before-Stop settlement and propagates retirement sampling failure", async () => { const f = fixture(), post = stopPost(f); const input = { api: { post } as any, request: f.request, deadlineAt: Date.now() + 1000, load: async () => ({ ...f, run: post.mock.calls.length ? f.run : liveRun(f), retired: true }), afterDeniedEdit: async () => {}, retainPreStop: async () => {}, afterSettlement: async () => {} }; expect((await settleCopilotDeniedRun(input)).branch).toBe("provider_completed_observed_before_stop"); post.mockClear(); await expect(settleCopilotDeniedRun({ ...input, afterSettlement: async () => { throw new Error("remote descendants live"); } })).rejects.toThrow("remote descendants live"); }); it.each(["cancelled", "pending-intent", "startup-only"])("rejects visible earlier Stop %s before dispatch", async kind => { const f = fixture(), post = stopPost(f); const run = kind === "cancelled" ? f.run : { ...liveRun(f), resultJson: kind === "startup-only" ? { startupCancellation: { requestedAt: date(1) } } : { nativeCancellation: { intentId: "earlier", dispatchState: "pending" } } }; await expect(settleCopilotDeniedRun({ api: { post } as any, request: f.request, deadlineAt: Date.now() + 1000, load: async () => ({ ...f, run, retired: false }), afterDeniedEdit: async () => {}, retainPreStop: async () => {}, afterSettlement: async () => {}, })).rejects.toThrow("earlier Stop"); expect(post).not.toHaveBeenCalled(); }); it("rejects Stop racing during artifact retention", async () => { const f = fixture(), post = stopPost(f); let earlier = false; await expect(settleCopilotDeniedRun({ api: { post } as any, request: f.request, deadlineAt: Date.now() + 1000, load: async () => ({ ...f, run: earlier ? f.run : liveRun(f), retired: false }), afterDeniedEdit: async () => {}, retainPreStop: async () => { earlier = true; }, afterSettlement: async () => {}, })).rejects.toThrow("earlier Stop"); expect(post).not.toHaveBeenCalled(); }); it.each(["conflict", "foreign-response"])("rejects a conflicting or foreign-caller Stop API response: %s", async kind => { const f = fixture(); const post = vi.fn(async (_path: string) => { if (kind === "conflict") throw new Error("409 cancellation intent conflict"); f.run.resultJson.cancelledByUserId = "foreign-caller"; return f.run; }); const sampled = vi.fn(async () => {}); await expect(settleCopilotDeniedRun({ api: { post } as any, request: f.request, deadlineAt: Date.now() + 1000, load: async () => ({ ...f, run: liveRun(f), retired: false }), afterDeniedEdit: async () => {}, retainPreStop: async () => {}, afterSettlement: sampled, })).rejects.toThrow(kind === "conflict" ? "409" : "Stop acknowledgement"); expect(post).toHaveBeenCalledOnce(); expect(sampled).not.toHaveBeenCalled(); expect(post.mock.calls[0]).toEqual(["/api/heartbeat-runs/run/cancel"]); }); });