import { assertCopilotStopAcknowledgement, type CopilotStopAcknowledgement } from "./copilot-stop-acknowledgement.js"; import { withoutProvenBootstrapReads, bootstrapReadExecutionId, type BootstrapReadProof } from "./native-bootstrap-read-proof.js"; import { canonicalJson } from "../../packages/shared/src/portability-hash.js"; import { createHash } from "node:crypto"; import { readFile } from "node:fs/promises"; import { readCopilotToolEvidence, type CopilotToolNotice } from "./copilot-evidence.js"; import { readCopilotContextRead } from "./copilot-context-evidence.js"; /** A tool origin exists regardless of the first status emitted by the provider. */ export function countCopilotToolOrigins(notices: readonly CopilotToolNotice[]): number { return new Set(notices.filter(n => n.stage === "tool").map(n => JSON.stringify([n.runId, n.sessionId, n.turnId, n.toolCallId]))).size; } export interface CopilotCommandMatch { algorithm: "leading-ascii-horizontal-v1"; canonicalCommandSha256: string; nativeCommandSha256: string; leadingWhitespace: string; } const commandDigest = (command: string) => `sha256:${createHash("sha256").update(command).digest("hex")}`; /** Only the fixture-owned command plus at most eight leading SPACE/TAB bytes. * Never trim native evidence or canonicalize shell tokens, quotes or content. */ export function matchCopilotFixtureCommand(command: string, nativeCommandSha256: string): CopilotCommandMatch | null { if (!command || /^[ \t\r\n]/u.test(command) || !/^sha256:[a-f0-9]{64}$/u.test(nativeCommandSha256)) return null; let prefixes = [""]; for (let length = 0; length <= 8; length++) { for (const leadingWhitespace of prefixes) { if (commandDigest(leadingWhitespace + command) === nativeCommandSha256) return { algorithm: "leading-ascii-horizontal-v1", canonicalCommandSha256: commandDigest(command), nativeCommandSha256, leadingWhitespace, }; } prefixes = prefixes.flatMap(prefix => [prefix + " ", prefix + "\t"]); } return null; } /** Bind the relation to one complete native execution, including retry checks. */ export function findCopilotFixtureCommand(notices: readonly CopilotToolNotice[], command: string): { call: CopilotToolNotice; match: CopilotCommandMatch } | null { const tools = notices.filter(n => n.stage === "tool"); const key = (n: CopilotToolNotice) => JSON.stringify([n.runId, n.sessionId, n.turnId, n.toolCallId]); const executions = tools.filter(n => n.operation === "execute" || n.commandSha256 !== undefined); if (new Set(executions.map(key)).size !== 1) return null; const first = executions[0]!; if (![first.runId, first.sessionId, first.turnId, first.toolCallId].every(Boolean)) return null; const group = tools.filter(n => key(n) === key(first)); const pending = group.filter(n => n.status === "pending"), terminal = group.filter(n => n.status === "completed" || n.status === "failed"); if (pending.length !== 1 || terminal.length !== 1 || terminal[0]!.status !== "completed" || group.some(n => n.seq < pending[0]!.seq || n.seq > terminal[0]!.seq) || pending[0]!.seq >= terminal[0]!.seq) return null; const call = pending[0]!, match = matchCopilotFixtureCommand(command, call.commandSha256 ?? ""); if (!match || call.operation !== "execute" || call.mode !== "async" || call.detach !== false || group.some(n => (n.commandSha256 !== undefined && n.commandSha256 !== call.commandSha256) || (n.operation !== undefined && n.operation !== "execute") || (n.mode !== undefined && n.mode !== "async") || (n.detach !== undefined && n.detach !== false))) return null; return { call, match }; } /** Capture independent evidence before a failed command match can abort grading. */ export async function observeCopilotFixtureCommand(notices: readonly CopilotToolNotice[], command: string, local?: { fixture: { snapshot(): T; marker: string; close(): Promise }; markerPath: string; }) { const external = local?.fixture.snapshot(); const markerMatches = local ? await readCopilotMarkerAfterCleanup(async () => {}, local.markerPath, local.fixture.marker) : undefined; const afterCleanupMarkerMatches = local ? await readCopilotMarkerAfterCleanup(() => local.fixture.close(), local.markerPath, local.fixture.marker) : undefined; return { external, markerMatches, afterCleanupMarkerMatches, matched: findCopilotFixtureCommand(notices, command) }; } /** Permission requests may carry the target omitted by native tool updates. */ export function countCopilotEditOriginsForTarget(notices: readonly CopilotToolNotice[], target: string): number { const origins = new Map(); for (const notice of notices) { const key = JSON.stringify([notice.runId, notice.sessionId, notice.turnId, notice.toolCallId]); const group = origins.get(key) ?? []; group.push(notice); origins.set(key, group); } let count = 0; for (const group of origins.values()) { if (!group.some(n => n.target === target)) continue; if (group.some(n => (n.target !== undefined && n.target !== target) || (n.operation !== undefined && n.operation !== "edit"))) { throw new Error("Conflicting Copilot denied-target origin evidence"); } const permissions = group.filter(n => n.stage !== "tool"); const requestIds = new Set(permissions.map(n => n.requestId)); if (requestIds.has(undefined) || requestIds.size > 1 || permissions.filter(n => n.stage === "permission_requested").length > 1 || permissions.filter(n => n.stage === "permission_delivered").length > 1) { throw new Error("Repeated or unbound Copilot denied-target permission"); } const tools = group.filter(n => n.stage === "tool"); const terminal = tools.filter(n => n.status === "completed" || n.status === "failed"); if (terminal.length > 1 || tools.filter(n => n.status === "pending").length > 1 || (terminal[0] && tools.some(n => n.seq > terminal[0]!.seq))) { throw new Error("Repeated Copilot denied-target tool lifecycle"); } // A permission notice alone never proves that a native tool was attempted. if (tools.some(n => n.operation === "edit")) count++; } return count; } /** Re-read independently after cleanup; a pre-cleanup value is not evidence. */ export async function readCopilotMarkerAfterCleanup(close: () => Promise, path: string, expected: string): Promise { await close(); try { return await readFile(path, "utf8") === expected; } catch (error) { if ((error as NodeJS.ErrnoException).code === "ENOENT") return false; throw error; } } export interface CopilotRemoteBinding { companyId: string; environmentId: string; runId: string; leaseId: string; sandboxId: string; image: string; remoteCwd: string; } export interface CopilotRemoteSnapshot { binding: CopilotRemoteBinding; observedAtMs: number; receivedAtMs: number; observedMonotonicNs: string; complete: boolean; workspace: Record; targets: Record; watcher: { complete: boolean; targetMutationCount: number; workspaceMutationCount: number }; processes: { captured: boolean; root: { pid: number; startTicks: string; bootId: string } | null; journal: Array<{ pid: number; ppid: number; startTicks: string; bootId: string }>; live: number[] }; setup: { path: string; sha256: string | null; published: boolean }; attached: { connections: number; failure: string | null; commandExit: { code: number; observedAtMs: number; observedMonotonicNs: string } | null; markerWrittenAtMs: number | null; markerWrittenMonotonicNs: string | null; clientExitedAtMs: number | null; clientExitedMonotonicNs: string | null } | null; } export interface CopilotRemoteFixture { binding: CopilotRemoteBinding; remoteCwd: string; actionFile: string; snapshot(label: string): Promise; killOwnedCopilot(): Promise>; setupAttachedCommand(input: { marker: string; markerText: string; delayMs: number; waitForFinishAttempt?: boolean }): Promise<{ command: string; commandSha256: string }>; releaseAttachedCommand(): Promise<{ releasedAtMs: number }>; finish(): Promise; readFile(relative: string): Promise; close(): Promise; } export interface CopilotRemoteBootstrap { prompt(nonce: string): string; bindAndRelease(input: { issueId: string; runId: string; targets: readonly string[]; actionPrompt(fixture: CopilotRemoteFixture): Promise | string }): Promise; } export function assertCopilotRemoteSnapshot(s: CopilotRemoteSnapshot, binding: CopilotRemoteBinding): void { const keys: Array = ["companyId", "environmentId", "runId", "leaseId", "sandboxId", "image", "remoteCwd"]; if (!s.complete || !s.watcher.complete || !keys.every(k => typeof binding[k] === "string" && binding[k].length > 0 && s.binding[k] === binding[k]) || !/^.+@sha256:[a-f0-9]{64}$/u.test(binding.image) || !binding.remoteCwd.startsWith("/") || binding.remoteCwd.split("/").some(p => p === ".." || p === ".") || !Number.isSafeInteger(s.observedAtMs) || s.observedAtMs < 0 || !Number.isSafeInteger(s.receivedAtMs) || !/^\d+$/u.test(s.observedMonotonicNs) || ![s.watcher.targetMutationCount, s.watcher.workspaceMutationCount].every(n => Number.isSafeInteger(n) && n >= 0)) throw new Error("Incomplete Copilot remote lease/watch receipt"); } export function assertCopilotRemoteRetirement(s: CopilotRemoteSnapshot, baseline: CopilotRemoteSnapshot): void { assertCopilotRemoteSnapshot(s, baseline.binding); const root = s.processes.root, original = baseline.processes.root; if (!root || !original || !baseline.processes.captured || !s.processes.captured || s.processes.live.length !== 0 || root.pid !== original.pid || root.startTicks !== original.startTicks || root.bootId !== original.bootId || !Number.isSafeInteger(root.pid) || root.pid < 2 || !/^\d+$/u.test(root.startTicks) || !/^[a-f0-9-]{36}$/iu.test(root.bootId) || !s.processes.journal.some(p => p.pid === root.pid && p.startTicks === root.startTicks && p.bootId === root.bootId) || !s.processes.journal.every(p => p.bootId === root.bootId && /^\d+$/u.test(p.startTicks) && Number.isSafeInteger(p.pid) && p.pid > 1) || !s.setup.published || s.setup.path !== baseline.setup.path || !/^sha256:[a-f0-9]{64}$/u.test(s.setup.sha256 ?? "") || BigInt(s.observedMonotonicNs) < BigInt(baseline.observedMonotonicNs)) throw new Error("Copilot remote retirement is unproven"); } export function copilotRemoteDeniedSample(s: CopilotRemoteSnapshot, baseline: CopilotRemoteSnapshot, target: string, phase: "before-request" | "pending" | "after-decision" | "terminal" | "after-cleanup") { assertCopilotRemoteSnapshot(s, baseline.binding); const t = s.targets[target], before = baseline.targets[target]; if (!t?.complete || !before?.complete || !/^\d+$/u.test(t.parent.dev) || !/^\d+$/u.test(t.parent.ino) || t.parent.dev !== before.parent.dev || t.parent.ino !== before.parent.ino || t.mutationCount !== 0 || s.watcher.targetMutationCount !== 0 || s.watcher.workspaceMutationCount !== baseline.watcher.workspaceMutationCount || JSON.stringify(Object.entries(s.workspace).sort()) !== JSON.stringify(Object.entries(baseline.workspace).sort())) throw new Error("Copilot remote denied target changed or observation was incomplete"); return { phase, observedAtMs: s.observedAtMs, exists: t.absent !== true || t.sha256 !== null }; } /** Only typed reads before the tested operation can be bootstrap work. */ export function copilotActionNotices(notices: readonly CopilotToolNotice[], origin: CopilotToolNotice, proof?: BootstrapReadProof, contextEvents?: readonly unknown[]): CopilotToolNotice[] { const context = contextEvents ? readCopilotContextRead(contextEvents, origin, true) : undefined; const remaining = context ? notices.filter(n => ![context.toolCallId, ...context.discoveries.map(d => d.toolCallId)].includes(n.toolCallId)) : notices; const bootstrap = proof && context ? { ...proof, events: proof.events.filter(r => ![...context.canonicalSeqs, ...context.discoveries.flatMap(d => d.canonicalSeqs)].includes((r as { seq: number }).seq)) } : proof; return withoutProvenBootstrapReads(remaining, origin, bootstrap); } export function assertCopilotRemoteAttached(s: CopilotRemoteSnapshot, baseline: CopilotRemoteSnapshot, terminalAt: number) { assertCopilotRemoteRetirement(s, baseline); const a = s.attached; if (!a || a.failure !== null || a.connections !== 1 || a.commandExit?.code !== 0 || a.markerWrittenAtMs === null || a.clientExitedAtMs === null || !/^\d+$/u.test(a.commandExit.observedMonotonicNs) || !/^\d+$/u.test(a.markerWrittenMonotonicNs ?? "") || !/^\d+$/u.test(a.clientExitedMonotonicNs ?? "") || BigInt(a.commandExit.observedMonotonicNs) > BigInt(a.markerWrittenMonotonicNs!) || BigInt(a.markerWrittenMonotonicNs!) > BigInt(a.clientExitedMonotonicNs!) || BigInt(a.clientExitedMonotonicNs!) > BigInt(s.observedMonotonicNs) || ![terminalAt, a.commandExit.observedAtMs, a.markerWrittenAtMs, a.clientExitedAtMs].every(n => Number.isSafeInteger(n) && n >= 0) || BigInt(a.commandExit.observedMonotonicNs) < BigInt(baseline.observedMonotonicNs) || a.commandExit.observedAtMs >= terminalAt || a.markerWrittenAtMs >= terminalAt || a.clientExitedAtMs >= terminalAt) throw new Error("Copilot remote attached command did not settle before terminal"); return a; } /** Await baseline and exact command construction before the bootstrap can publish. */ export async function prepareCopilotRemoteAction(input: { fixture: CopilotRemoteFixture; companyId: string; environmentId: string; runId: string; target: string; prompt: string; markerText?: string; }) { const f = input.fixture; if (f.binding.companyId !== input.companyId || f.binding.environmentId !== input.environmentId || f.binding.runId !== input.runId || f.remoteCwd !== f.binding.remoteCwd) throw new Error("Foreign Copilot remote bootstrap binding"); const command = input.markerText === undefined ? undefined : await f.setupAttachedCommand({ marker: input.target, markerText: input.markerText, delayMs: 4000, waitForFinishAttempt: true }); const baseline = await f.snapshot("before-action-publication"); assertCopilotRemoteSnapshot(baseline, f.binding); if (baseline.setup.published || baseline.setup.path !== f.actionFile || !baseline.processes.captured || baseline.processes.live.length === 0) throw new Error("Copilot action was not held behind the remote observer"); const target = baseline.targets[input.target]; if (!target?.complete || !target.absent || target.sha256 !== null || target.mutationCount !== 0) throw new Error("Copilot remote target was present or unobserved before action"); return { baseline, command, prompt: `${input.prompt}\nThe admitted remote workspace is ${f.remoteCwd}.${command ? `\nThe exact supplied command is:\n${command.command}\nDo not inspect or modify fixture code, fabricate its marker, or launch a substitute command.` : ""}` }; } /** finish drains the pre-armed receipt channel; readFile then reads retained * bytes locally. Never snapshot or issue a sandbox RPC after lease retirement. */ export async function readCopilotRemoteMarkerAfterRetirement(fixture: CopilotRemoteFixture, baseline: CopilotRemoteSnapshot, target: string, expected: string): Promise { const receipt = await fixture.finish(); assertCopilotRemoteRetirement(receipt, baseline); const bytes = await fixture.readFile(target); return bytes.toString("utf8") === expected && receipt.targets[target]?.sha256 === `sha256:${createHash("sha256").update(bytes).digest("hex")}`; } export interface CopilotDenialSettlement { stopAcknowledgement: CopilotStopAcknowledgement; schema: "paperclip.e2e.copilot-denial-settlement.v4"; branch: "provider_cancelled_or_interrupted" | "provider_completed_observed_before_stop"; /** A cancelled terminal alone does not prove Stop reached active work. */ providerCancellationTerminalObserved: boolean; runId: string; sessionId: string; turnId: string; toolCallId: string; requestId: string; preStop: CopilotPreStopObservation; stopDispatchMonotonicNs: string; providerTerminal: { eventType: "turn.completed" | "turn.cancelled" | "turn.interrupted"; normalizedSessionId: string; sourceInstanceId: string; requestSourceSeq: number; resolvedSourceSeq: number; deliveredSourceSeq: number; failedNoticeSourceSeq: number; failedToolSourceSeq: number; failedToolRowCreatedAtMs: number; sourceSeq: number; emittedAtMs: number; rowCreatedAtMs: number; rowSha256: string; failedToolRowSha256: string; }; runStop: { companyId: string; issueId: string; scope: "run"; status: "cancelled"; issueStatus: "in_progress" | "blocked"; incompleteRecovery?: { actionId: string; rowSeq: number; rowSha256: string; nextAttemptAtMs: number }; intentId: string; intentAuditId: string; acknowledgementAuditId: string; requestedAtMs: number; recordedAtMs: number; acknowledgedAtMs: number; finishedAtMs: number; }; } const settlementRecord = (v: unknown): Record => v !== null && typeof v === "object" && !Array.isArray(v) ? v as Record : {}; const settlementId = (v: unknown): v is string => typeof v === "string" && v.length > 0 && v.length <= 240 && !/[\u0000-\u001f\u007f]/u.test(v) && !v.includes("[REDACTED]"); const settlementTime = (v: unknown): v is number => Number.isSafeInteger(v) && (v as number) >= 0; const settlementDate = (v: unknown): number => typeof v === "string" && /^\d{4}-\d{2}-\d{2}T.*Z$/u.test(v) ? Date.parse(v) : NaN; export function validCopilotDenialSettlement(s: CopilotDenialSettlement): boolean { if (!s || s.schema !== "paperclip.e2e.copilot-denial-settlement.v4") return false; const t = s.providerTerminal, c = s.runStop; if (!t || !c || ![s.runId, s.sessionId, s.turnId, s.toolCallId, s.requestId, t.normalizedSessionId, t.sourceInstanceId, c.companyId, c.issueId, c.intentId, c.intentAuditId, c.acknowledgementAuditId].every(settlementId) || c.scope !== "run" || c.status !== "cancelled" || !["in_progress", "blocked"].includes(c.issueStatus) || c.intentAuditId === c.acknowledgementAuditId || ![t.failedToolRowCreatedAtMs, t.emittedAtMs, t.rowCreatedAtMs, c.requestedAtMs, c.recordedAtMs, c.acknowledgedAtMs, c.finishedAtMs].every(settlementTime) || ![t.requestSourceSeq, t.resolvedSourceSeq, t.deliveredSourceSeq, t.failedNoticeSourceSeq].every(n => Number.isSafeInteger(n) && n > 0) || !(t.requestSourceSeq < t.resolvedSourceSeq && t.resolvedSourceSeq < t.deliveredSourceSeq && t.deliveredSourceSeq < t.failedNoticeSourceSeq && t.failedNoticeSourceSeq < t.failedToolSourceSeq) || !Number.isSafeInteger(t.failedToolSourceSeq) || t.failedToolSourceSeq <= 0 || !Number.isSafeInteger(t.sourceSeq) || t.sourceSeq <= t.failedToolSourceSeq || c.requestedAtMs > c.recordedAtMs || c.recordedAtMs > c.acknowledgedAtMs || c.acknowledgedAtMs > c.finishedAtMs) return false; const before = s.preStop; if (!before || before.schema !== "paperclip.e2e.copilot-pre-stop-observation.v2" || !["runId", "sessionId", "turnId", "toolCallId", "requestId"].every(k => before[k as keyof CopilotPreStopObservation] === s[k as keyof CopilotDenialSettlement]) || typeof before.cancellationRequestId !== "string" || !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u.test(before.cancellationRequestId) || typeof s.stopDispatchMonotonicNs !== "string" || !/^[1-9][0-9]{0,29}$/.test(s.stopDispatchMonotonicNs) || !s.stopAcknowledgement || s.stopAcknowledgement.schema !== "paperclip.e2e.copilot-stop-acknowledgement.v1" || s.stopAcknowledgement.fixtureCorrelationId !== before.cancellationRequestId || s.stopAcknowledgement.dispatchMonotonicNs !== s.stopDispatchMonotonicNs || s.stopAcknowledgement.intentId !== c.intentId || s.stopAcknowledgement.intentAuditId !== c.intentAuditId || s.stopAcknowledgement.acknowledgementAuditId !== c.acknowledgementAuditId || s.stopAcknowledgement.companyId !== c.companyId || s.stopAcknowledgement.issueId !== c.issueId || s.stopAcknowledgement.runId !== s.runId || s.stopAcknowledgement.callerUserId !== "local-board" || !/^sha256:[a-f0-9]{64}$/.test(s.stopAcknowledgement.responseMetadataSha256) || !/^[1-9][0-9]{0,29}$/.test(s.stopAcknowledgement.apiResponseObservedMonotonicNs) || BigInt(s.stopAcknowledgement.apiResponseObservedMonotonicNs) <= BigInt(s.stopDispatchMonotonicNs) || before.companyId !== c.companyId || before.normalizedSessionId !== t.normalizedSessionId || before.sourceInstanceId !== t.sourceInstanceId || before.failedToolSourceSeq !== t.failedToolSourceSeq || before.failedToolRowSha256 !== t.failedToolRowSha256 || ![t.rowSha256, t.failedToolRowSha256].every(v => /^sha256:[a-f0-9]{64}$/u.test(v)) || typeof before.apiReadCompletedMonotonicNs !== "string" || typeof s.stopDispatchMonotonicNs !== "string" || !/^[1-9][0-9]{0,29}$/u.test(before.apiReadCompletedMonotonicNs) || !/^[1-9][0-9]{0,29}$/u.test(s.stopDispatchMonotonicNs) || BigInt(before.apiReadCompletedMonotonicNs) >= BigInt(s.stopDispatchMonotonicNs)) return false; if (before.terminal !== null && (!before.terminal || before.terminal.eventType !== t.eventType || before.terminal.sourceSeq !== t.sourceSeq || before.terminal.rowSha256 !== t.rowSha256)) return false; if (c.issueStatus === "blocked") { const recovery = c.incompleteRecovery, observed = before.incompleteRecovery; if (s.branch !== "provider_completed_observed_before_stop" || before.terminal?.eventType !== "turn.completed" || !recovery || !observed || !settlementId(recovery.actionId) || !Number.isSafeInteger(recovery.rowSeq) || recovery.rowSeq <= 0 || !settlementTime(recovery.nextAttemptAtMs) || !/^sha256:[a-f0-9]{64}$/u.test(recovery.rowSha256) || recovery.rowSeq !== observed.rowSeq || recovery.rowSha256 !== observed.rowSha256 || recovery.nextAttemptAtMs !== observed.nextAttemptAtMs) return false; } if (s.branch === "provider_completed_observed_before_stop") return t.eventType === "turn.completed" && s.providerCancellationTerminalObserved === false && before.terminal?.eventType === "turn.completed"; return s.branch === "provider_cancelled_or_interrupted" && s.providerCancellationTerminalObserved === true && ["turn.cancelled", "turn.interrupted"].includes(t.eventType); } /** Same failed-edit proof used before Stop and during final settlement. A native * failed notice alone does not prove its canonical execution row is durable. */ export function readCopilotDeniedEdit(input: { events: readonly unknown[]; request: CopilotToolNotice; companyId: string }) { const { events, request, companyId } = input; const invalid = () => new Error("Copilot denial settlement lacks a persisted correlated failed edit"); if (events.length > 20_000 || !settlementId(companyId)) throw invalid(); const notices = readCopilotToolEvidence(events, request.runId); const same = (n: CopilotToolNotice) => ["runId", "sessionId", "turnId", "toolCallId"].every(k => n[k as keyof CopilotToolNotice] === request[k as keyof CopilotToolNotice]); const requested = notices.filter(n => n.stage === "permission_requested" && same(n)); const delivered = notices.filter(n => n.stage === "permission_delivered" && same(n)); const failed = notices.filter(n => n.stage === "tool" && same(n) && ["failed", "completed"].includes(n.status ?? "")); if (requested.length !== 1 || requested[0]!.seq !== request.seq || requested[0]!.requestId !== request.requestId || request.operation !== "edit" || delivered.length !== 1 || delivered[0]!.requestId !== request.requestId || delivered[0]!.outcome !== "reject_once" || failed.length !== 1 || failed[0]!.status !== "failed" || requested[0]!.seq >= delivered[0]!.seq || delivered[0]!.seq >= failed[0]!.seq) throw invalid(); const rows = events.map(settlementRecord); const get = (row: Record) => { const f = settlementRecord(settlementRecord(row.payload).prpEvent); if (row.runId !== request.runId || row.companyId !== companyId || !Number.isSafeInteger(row.seq) || row.seq <= 0 || f.schema !== "paperclip.prp.event.v1" || f.sourceKind !== "runner" || f.eventType !== row.eventType || f.runId !== request.runId || f.turnId !== request.turnId || !settlementId(f.normalizedSessionId) || !settlementId(f.sourceInstanceId) || !Number.isSafeInteger(f.sourceSeq) || f.sourceSeq <= 0 || f.sourceEventId !== `${f.sourceInstanceId}:${request.runId}:${f.sourceSeq}` || !settlementTime(settlementDate(row.createdAt)) || !settlementTime(settlementDate(f.emittedAt))) throw invalid(); return f; }; const at = (seq: number) => { const found = rows.filter(r => r.seq === seq); if (found.length !== 1) throw invalid(); return get(found[0]!); }; const origin = at(request.seq), delivery = at(delivered[0]!.seq), failure = at(failed[0]!.seq); const stream = (f: Record) => f.normalizedSessionId === origin.normalizedSessionId && f.sourceInstanceId === origin.sourceInstanceId; if (![delivery, failure].every(stream) || origin.sourceSeq >= delivery.sourceSeq || delivery.sourceSeq >= failure.sourceSeq) throw invalid(); const resolutions = rows.filter(r => ["runtime_request.resolved", "runtime_request.cancelled", "runtime_request.expired"].includes(r.eventType) && settlementRecord(settlementRecord(settlementRecord(r.payload).prpEvent).payload).requestId === request.requestId); if (resolutions.length !== 1) throw invalid(); const resolution = get(resolutions[0]!), resolved = settlementRecord(resolution.payload); if (!stream(resolution) || resolution.eventType !== "runtime_request.resolved" || resolved.requestKind !== "permission_approval" || resolved.turnId !== request.turnId || resolved.action !== "decline" || resolution.sourceSeq <= origin.sourceSeq || resolution.sourceSeq >= delivery.sourceSeq || resolutions[0]!.seq <= request.seq || resolutions[0]!.seq >= delivered[0]!.seq) throw invalid(); const toolRows = rows.filter(r => r.eventType === "tool.execution.completed" && settlementRecord(settlementRecord(settlementRecord(r.payload).prpEvent).payload).executionId === bootstrapReadExecutionId(request.toolCallId)); if (toolRows.length !== 1) throw invalid(); const tool = get(toolRows[0]!), toolPayload = settlementRecord(tool.payload); if (!stream(tool) || tool.sourceSeq <= failure.sourceSeq || toolRows[0]!.seq <= failed[0]!.seq || toolPayload.schema !== "paperclip.tool.execution.v1" || toolPayload.status !== "failed" || toolPayload.operation !== "edit") throw invalid(); return { rows, get, stream, origin, delivery, failure, resolution, tool, toolRows, failed }; } export interface CopilotPreStopObservation { schema: "paperclip.e2e.copilot-pre-stop-observation.v2"; companyId: string; runId: string; sessionId: string; turnId: string; toolCallId: string; requestId: string; normalizedSessionId: string; sourceInstanceId: string; failedToolSourceSeq: number; failedToolRowSha256: string; terminal: { eventType: "turn.completed" | "turn.cancelled" | "turn.interrupted"; sourceSeq: number; rowSha256: string } | null; /** Exact current-mainline missing-result row actually read before Stop. */ incompleteRecovery?: { rowSeq: number; rowSha256: string; nextAttemptAtMs: number }; /** Fixture-process monotonic clock, never provider or database wall time. */ apiReadCompletedMonotonicNs: string; /** Fixture correlation UUID; current mainline generates its own API intent. */ cancellationRequestId: string; } const denialRowSha = (row: unknown) => `sha256:${createHash("sha256").update(canonicalJson(row)).digest("hex")}`; function readDeniedTerminal(proof: ReturnType) { const { rows, get, stream, tool, failed } = proof; const invalid = () => new Error("Copilot denial lacks exact provider settlement"); // Ignore legacy unwrapped log summaries, never use them as provider evidence. const terminalRows = rows.filter(r => ["turn.completed", "turn.cancelled", "turn.interrupted", "turn.failed"].includes(r.eventType) && settlementRecord(r.payload).prpEvent !== undefined); if (terminalRows.length === 0) return null; if (terminalRows.length !== 1) throw invalid(); const row = terminalRows[0]!, terminal = get(row), p = settlementRecord(terminal.payload); if (!stream(terminal) || terminal.sourceSeq <= tool.sourceSeq || row.seq <= failed[0]!.seq || !["turn.completed", "turn.cancelled", "turn.interrupted"].includes(row.eventType) || p.status !== row.eventType.slice(5) || p.error != null) throw invalid(); return { row, terminal }; } function readDeniedIncompleteRecovery(events: readonly unknown[], request: CopilotToolNotice, companyId: string, terminal: ReturnType) { if (terminal?.terminal.eventType !== "turn.completed") return undefined; const rows = events.map(settlementRecord).filter(row => row.eventType === "lifecycle" && settlementRecord(row.payload).retryReasonCode === "semantic_result_missing"); if (rows.length === 0) return undefined; const row = rows[0]!, payload = settlementRecord(row.payload), detail = settlementRecord(payload.failureDetail); if (rows.length !== 1 || row.runId !== request.runId || row.companyId !== companyId || !Number.isSafeInteger(row.seq) || row.seq <= terminal.row.seq || payload.fallbackSuppressed !== true || payload.attempt !== 1 || detail.originalFailureCode !== "native_session_interrupted" || detail.recoveryMode !== "exact_checkpoint_resume" || detail.checkpointExists !== true || detail.providerSessionEstablished !== true || !settlementTime(settlementDate(payload.nextAttemptAt))) { throw new Error("Copilot denial lacks exact incomplete provider settlement"); } return { rowSeq: row.seq, rowSha256: denialRowSha(row), nextAttemptAtMs: settlementDate(payload.nextAttemptAt) }; } /** Call only on rows returned by the current operator API read. Retain this * receipt before dispatching Stop; historical rows cannot recreate that fact. */ export function observeCopilotPreStop(input: { events: readonly unknown[]; request: CopilotToolNotice; companyId: string; cancellationRequestId: string }): CopilotPreStopObservation { const proof = readCopilotDeniedEdit(input), observed = readDeniedTerminal(proof), r = input.request; const incompleteRecovery = readDeniedIncompleteRecovery(input.events, r, input.companyId, observed); return { schema: "paperclip.e2e.copilot-pre-stop-observation.v2", companyId: input.companyId, runId: r.runId, sessionId: r.sessionId, turnId: r.turnId, toolCallId: r.toolCallId, requestId: r.requestId!, normalizedSessionId: proof.origin.normalizedSessionId, sourceInstanceId: proof.origin.sourceInstanceId, failedToolSourceSeq: proof.tool.sourceSeq, failedToolRowSha256: denialRowSha(proof.toolRows[0]), terminal: observed ? { eventType: observed.terminal.eventType, sourceSeq: observed.terminal.sourceSeq, rowSha256: denialRowSha(observed.row) } : null, ...(incompleteRecovery ? { incompleteRecovery } : {}), apiReadCompletedMonotonicNs: process.hrtime.bigint().toString(), cancellationRequestId: input.cancellationRequestId }; } /** Denial closes one permission, not necessarily the provider prompt. Match the * single canonical terminal to the same source stream, then independently bind * the audited controller Stop. Database createdAt is transaction-start metadata, not a commit boundary. */ export function readCopilotDenialSettlement(input: { events: readonly unknown[]; request: CopilotToolNotice; run: unknown; issue: unknown; preStop: CopilotPreStopObservation; stopDispatchMonotonicNs: string; stopAcknowledgement: CopilotStopAcknowledgement; }): CopilotDenialSettlement { const invalid = () => new Error("Copilot denial lacks exact provider settlement and audited run Stop"); const { request, events } = input, run = settlementRecord(input.run), issue = settlementRecord(input.issue); const stop = settlementRecord(settlementRecord(run.resultJson).nativeCancellation); if (events.length > 20_000 || run.id !== request.runId || issue.id !== run.nativeIssueId || !settlementId(issue.companyId) || run.companyId !== issue.companyId || !["in_progress", "blocked"].includes(issue.status) || run.status !== "cancelled" || stop.schema !== "paperclip.native-cancellation.v1" || stop.runId !== run.id || stop.companyId !== issue.companyId || stop.issueId !== issue.id || stop.scope !== "run" || typeof stop.dispatched !== "boolean" || (!stop.dispatched && input.preStop?.terminal?.eventType !== "turn.completed") || stop.dispatchState !== "acknowledged" || stop.reasonCode !== "cancellation_run_only" || !Array.isArray(stop.effects) || stop.effects.length !== 1 || stop.effects[0] !== "release_run_resources") throw invalid(); try { assertCopilotStopAcknowledgement(input.stopAcknowledgement, run, { companyId: issue.companyId, issueId: issue.id, runId: request.runId, callerUserId: "local-board" }, input.preStop.cancellationRequestId, input.stopDispatchMonotonicNs, input.preStop.terminal?.eventType === "turn.completed" ? "provider-completed-before-stop" : "active-provider"); } catch { throw invalid(); } const { rows, get, stream, origin, delivery, failure, resolution, tool, toolRows, failed } = readCopilotDeniedEdit({ events, request, companyId: issue.companyId }); const observed = readDeniedTerminal({ rows, get, stream, origin, delivery, failure, resolution, tool, toolRows, failed }); if (!observed) throw invalid(); const { row, terminal } = observed; let incompleteRecovery: CopilotDenialSettlement["runStop"]["incompleteRecovery"]; if (issue.status === "blocked") { const recovery = readDeniedIncompleteRecovery(events, request, issue.companyId, observed), before = input.preStop.incompleteRecovery; const action = settlementRecord(issue.activeRecoveryAction), wake = settlementRecord(action.wakePolicy); if (!recovery || !before || row.eventType !== "turn.completed" || input.preStop.terminal?.eventType !== "turn.completed" || canonicalJson(recovery) !== canonicalJson(before) || !settlementId(action.id) || action.companyId !== issue.companyId || action.sourceIssueId !== issue.id || action.kind !== "active_run_watchdog" || action.status !== "active" || action.cause !== "native_session_interrupted" || wake.kind !== "resume_native_run" || wake.runId !== run.id || settlementDate(wake.notBefore) !== recovery.nextAttemptAtMs) throw invalid(); incompleteRecovery = { ...recovery, actionId: action.id }; } const result: CopilotDenialSettlement = { schema: "paperclip.e2e.copilot-denial-settlement.v4", branch: row.eventType === "turn.completed" ? "provider_completed_observed_before_stop" : "provider_cancelled_or_interrupted", providerCancellationTerminalObserved: row.eventType !== "turn.completed", runId: run.id, sessionId: request.sessionId, turnId: request.turnId, toolCallId: request.toolCallId, requestId: request.requestId!, preStop: input.preStop, stopDispatchMonotonicNs: input.stopDispatchMonotonicNs, stopAcknowledgement: input.stopAcknowledgement, providerTerminal: { eventType: row.eventType, rowSha256: denialRowSha(row), failedToolRowSha256: denialRowSha(toolRows[0]), normalizedSessionId: terminal.normalizedSessionId, sourceInstanceId: terminal.sourceInstanceId, requestSourceSeq: origin.sourceSeq, resolvedSourceSeq: resolution.sourceSeq, deliveredSourceSeq: delivery.sourceSeq, failedNoticeSourceSeq: failure.sourceSeq, failedToolSourceSeq: tool.sourceSeq, failedToolRowCreatedAtMs: settlementDate(toolRows[0]!.createdAt), sourceSeq: terminal.sourceSeq, emittedAtMs: settlementDate(terminal.emittedAt), rowCreatedAtMs: settlementDate(row.createdAt) }, runStop: { companyId: issue.companyId, issueId: issue.id, scope: stop.scope, status: run.status, issueStatus: issue.status, ...(incompleteRecovery ? { incompleteRecovery } : {}), intentId: stop.intentId, intentAuditId: stop.intentAuditId, acknowledgementAuditId: stop.acknowledgementAuditId, requestedAtMs: settlementDate(settlementRecord(settlementRecord(run.resultJson).startupCancellation).requestedAt), recordedAtMs: settlementDate(stop.recordedAt), acknowledgedAtMs: settlementDate(stop.acknowledgedAt), finishedAtMs: settlementDate(run.finishedAt) }, }; if (!validCopilotDenialSettlement(result)) throw invalid(); return result; } export interface CopilotDenialSampleCursor { runId: string; turnId: string; normalizedSessionId: string; sourceInstanceId: string; sourceSeq: number; } /** Read boundary for a sample checkpoint, not a clock conversion. A remote final * sample can be an earlier sealed receipt; its separate retirement/watch proof * must cover the exact provider root through exit before that receipt is used. */ export function copilotDenialSampleCursor(events: readonly unknown[], request: CopilotToolNotice): CopilotDenialSampleCursor { const rows = events.map(settlementRecord), invalid = () => new Error("Copilot denied sample lacks an exact event cursor"); const origins = rows.filter(r => r.seq === request.seq); if (origins.length !== 1) throw invalid(); const origin = settlementRecord(settlementRecord(origins[0]!.payload).prpEvent); const frames = rows.map(r => ({ row: r, f: settlementRecord(settlementRecord(r.payload).prpEvent) })) .filter(({ f }) => f.turnId === request.turnId); if (events.length > 20_000 || frames.length === 0 || origin.runId !== request.runId || ![origin.normalizedSessionId, origin.sourceInstanceId].every(settlementId)) throw invalid(); const seen = new Set(); for (const { row, f } of frames) { if (row.runId !== request.runId || f.runId !== request.runId || f.schema !== "paperclip.prp.event.v1" || f.sourceKind !== "runner" || row.eventType !== f.eventType || f.normalizedSessionId !== origin.normalizedSessionId || f.sourceInstanceId !== origin.sourceInstanceId || !Number.isSafeInteger(f.sourceSeq) || f.sourceSeq <= 0 || seen.has(f.sourceSeq) || f.sourceEventId !== `${f.sourceInstanceId}:${f.runId}:${f.sourceSeq}`) throw invalid(); seen.add(f.sourceSeq); } return { runId: request.runId, turnId: request.turnId, normalizedSessionId: origin.normalizedSessionId, sourceInstanceId: origin.sourceInstanceId, sourceSeq: Math.max(...seen) }; }