fix(pi): retain ownership for uncertain mutations

This commit is contained in:
2026-08-25 23:53:54 +08:00
parent 621ebb1781
commit 019cbb115a
21 changed files with 1113 additions and 67 deletions

View File

@@ -74,6 +74,7 @@ type LocalProofProvider = {
releaseChildren(): void;
releaseParents(): void;
releaseAll(): void;
armDelayedCompaction(): void;
close(): Promise<void>;
};
@@ -239,6 +240,8 @@ export interface PiReleaseResilienceStatus {
errorCode: string | null;
recoverable: boolean;
bindingPreserved: boolean;
contextCompaction: 'idle' | 'running';
completedCompactions: number;
};
other: {
conversationId: string;
@@ -295,6 +298,7 @@ const PROOF_AGENT_ID = 'release-proof-agent';
const PROOF_MODEL_ID = 'release-proof-model';
const PROXY_PROOF_MODEL_ID = 'deepseek-v4-pro';
const PROOF_PROVIDER_FIRST_EVENT_DELAY_MS = 75;
const PROOF_MUTATION_CONFIRMATION_DELAY_MS = 12_000;
const EXPECTED_TURN_MILESTONES: readonly ProofMilestone[] = [
'worker.queue_wait',
'resources.ready',
@@ -482,6 +486,7 @@ async function startLocalProofProvider(mode: ProofProviderMode): Promise<LocalPr
const held = new Set<HeldProviderResponse>();
let closed = false;
let closeFlight: Promise<void> | null = null;
let delayedCompactionArmed = false;
const server: Server = createServer(async (request, response) => {
response.once('error', () => undefined);
try {
@@ -545,6 +550,26 @@ async function startLocalProofProvider(mode: ProofProviderMode): Promise<LocalPr
respondWithSubagentCall(response, model, 'coding');
return;
}
if (role === 'parent' && delayedCompactionArmed) {
delayedCompactionArmed = false;
const entry = { role, response } satisfies HeldProviderResponse;
held.add(entry);
response.once('close', () => held.delete(entry));
await delay(PROOF_MUTATION_CONFIRMATION_DELAY_MS);
if (!held.delete(entry)) return;
respondWithText(response, model, 'RESILIENCE_COMPACTION_SUMMARY');
return;
}
if (role === 'parent' && latestUserMessageContains(body, 'BACKGROUND_ACTIVE')) {
const entry = { role, response } satisfies HeldProviderResponse;
held.add(entry);
response.once('close', () => held.delete(entry));
await delay(PROOF_MUTATION_CONFIRMATION_DELAY_MS);
if (!held.has(entry)) return;
response.writeHead(200, { 'content-type': 'text/event-stream' });
writeChunk(response, model, { role: 'assistant', content: 'RESILIENCE_ACTIVE' }, null);
return;
}
response.writeHead(200, { 'content-type': 'text/event-stream' });
writeChunk(response, model, { role: 'assistant', content: 'RESILIENCE_ACTIVE' }, null);
const entry = { role, response };
@@ -634,6 +659,7 @@ async function startLocalProofProvider(mode: ProofProviderMode): Promise<LocalPr
releaseChildren: () => release('child'),
releaseParents: () => release('parent'),
releaseAll: () => release(),
armDelayedCompaction: () => { delayedCompactionArmed = true; },
close: async () => {
if (closed) return;
if (!closeFlight) {
@@ -1666,6 +1692,10 @@ export async function getFinalAsarResilienceStatus(): Promise<PiReleaseResilienc
errorCode: targetError?.code ?? null,
recoverable: targetError?.recoverable ?? false,
bindingPreserved: targetBindingPreserved,
contextCompaction: target.context.compaction,
completedCompactions: target.nodes.filter((node) => (
node.kind === 'compaction' && node.status === 'complete'
)).length,
},
other: {
conversationId: run.otherConversationId,
@@ -1860,6 +1890,13 @@ export function releaseFinalAsarResilienceParents(): void {
run.provider.releaseParents();
}
export function armFinalAsarResilienceCompactDelay(): { delayMs: number } {
const run = resilienceCompositionRun;
if (!run) throw new Error('PI resilience proof is not running');
run.provider.armDelayedCompaction();
return { delayMs: PROOF_MUTATION_CONFIRMATION_DELAY_MS };
}
export async function restartFinalAsarResilienceOther(): Promise<PiReleaseResilienceStatus> {
const run = resilienceCompositionRun;
if (!run) throw new Error('PI resilience proof is not running');