From 5fcefb9b076f4be4ff118a9ecd7064f1c3e8781c Mon Sep 17 00:00:00 2001 From: 777genius Date: Tue, 19 May 2026 20:38:32 +0300 Subject: [PATCH] test: cover process bootstrap exit diagnostics --- .../ProcessBootstrapTransportEvidence.test.ts | 50 +++++++++++++++++++ .../TeamLaunchFailureArtifactPack.test.ts | 24 +++++++++ 2 files changed, 74 insertions(+) diff --git a/test/main/services/team/ProcessBootstrapTransportEvidence.test.ts b/test/main/services/team/ProcessBootstrapTransportEvidence.test.ts index dfe93e3a..492c15d2 100644 --- a/test/main/services/team/ProcessBootstrapTransportEvidence.test.ts +++ b/test/main/services/team/ProcessBootstrapTransportEvidence.test.ts @@ -141,6 +141,56 @@ describe('ProcessBootstrapTransportEvidence', () => { ); }); + it('treats runtime failure after mailbox write as terminal without marking bootstrap submitted', () => { + const summary = summarizeProcessBootstrapTransportEvents([ + { + type: 'mailbox_bootstrap_written', + timestamp: '2026-05-07T10:00:00.000Z', + detail: 'messageId=bootstrap-1', + }, + { + type: 'failed', + timestamp: '2026-05-07T10:00:01.000Z', + detail: 'teammate process exited before inbox_poller_ready', + }, + ]); + + expect(summary).toMatchObject({ + submitted: false, + hasProgress: true, + lastStage: 'runtime failed: teammate process exited before inbox_poller_ready', + terminalFailure: { + kind: 'runtime_failed_before_confirmation', + reason: 'runtime failed: teammate process exited before inbox_poller_ready', + }, + }); + }); + + it('treats process exit after submit attempt as terminal without durable submit proof', () => { + const summary = summarizeProcessBootstrapTransportEvents([ + { + type: 'bootstrap_submit_attempted', + timestamp: '2026-05-07T10:00:00.000Z', + detail: 'submitting bootstrap prompt', + }, + { + type: 'exited', + timestamp: '2026-05-07T10:00:01.000Z', + detail: 'process exited before bootstrap_submitted', + }, + ]); + + expect(summary).toMatchObject({ + submitted: false, + hasProgress: true, + lastStage: 'runtime exited: process exited before bootstrap_submitted', + terminalFailure: { + kind: 'process_exited_before_confirmation', + reason: 'runtime exited: process exited before bootstrap_submitted', + }, + }); + }); + it('distinguishes submitted bootstrap prompts from not-submitted transport timeouts', () => { const summary = summarizeProcessBootstrapTransportEvents([ { diff --git a/test/main/services/team/TeamLaunchFailureArtifactPack.test.ts b/test/main/services/team/TeamLaunchFailureArtifactPack.test.ts index 445cef1d..967eb163 100644 --- a/test/main/services/team/TeamLaunchFailureArtifactPack.test.ts +++ b/test/main/services/team/TeamLaunchFailureArtifactPack.test.ts @@ -241,6 +241,30 @@ describe('TeamLaunchFailureArtifactPack', () => { }); }); + it('keeps process exits after bootstrap transport evidence out of stdin_missing classification', () => { + const input = { + teamName: 'artifact-team', + runId: 'run-submit-attempt-process-exit', + reason: + 'alice: Teammate process alice@signal-ops did not submit bootstrap prompt: teammate process exited before bootstrap_submitted; last transport stage: bootstrap_submit_attempted: submitting bootstrap prompt Last stderr: Warning: no stdin data received in 3s, proceeding without it.', + progressTraceLines: [ + 'mailbox_bootstrap_written detail=messageId=bootstrap-alice-1', + 'bootstrap_submit_attempted detail=submitting bootstrap prompt', + 'process exited before bootstrap_submitted', + 'Warning: no stdin data received in 3s, proceeding without it.', + ], + }; + + expect(classifyLaunchFailureArtifact(input).code).toBe('model_no_bootstrap'); + expect(extractLaunchBootstrapTransportBreadcrumb(input)).toMatchObject({ + lastTransportStage: expect.stringContaining( + 'bootstrap_submit_attempted: submitting bootstrap prompt' + ), + noStdinWarning: true, + bootstrapSubmitted: false, + }); + }); + it('classifies provider quota separately from protocol errors', () => { expect( classifyLaunchFailureArtifact({