From 6fb83676e7bb421dc9e08bf06e527e9b417e8efa Mon Sep 17 00:00:00 2001 From: 777genius Date: Fri, 5 Jun 2026 16:51:47 +0300 Subject: [PATCH] fix(team): surface runtime launch stages --- .../team/ProcessBootstrapTransportEvidence.ts | 1 + .../team/TeamLaunchFailureArtifactPack.ts | 8 +++++-- .../ProcessBootstrapTransportEvidence.test.ts | 24 +++++++++++++++++++ .../TeamLaunchFailureArtifactPack.test.ts | 20 ++++++++++++++++ 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/main/services/team/ProcessBootstrapTransportEvidence.ts b/src/main/services/team/ProcessBootstrapTransportEvidence.ts index 8b452e70..0581f96e 100644 --- a/src/main/services/team/ProcessBootstrapTransportEvidence.ts +++ b/src/main/services/team/ProcessBootstrapTransportEvidence.ts @@ -54,6 +54,7 @@ const TRANSPORT_STAGE_LABELS: Record = { process_spawned: 'process spawned', stdout_attached: 'stdout attached', cli_started: 'CLI started', + startup_checkpoint: 'startup checkpoint', runtime_ready: 'runtime ready', inbox_poller_ready: 'inbox poller ready', mailbox_bootstrap_written: 'bootstrap mailbox row written', diff --git a/src/main/services/team/TeamLaunchFailureArtifactPack.ts b/src/main/services/team/TeamLaunchFailureArtifactPack.ts index 52892155..4f447d58 100644 --- a/src/main/services/team/TeamLaunchFailureArtifactPack.ts +++ b/src/main/services/team/TeamLaunchFailureArtifactPack.ts @@ -226,6 +226,8 @@ const WORKSPACE_TRUST_FAILURE_PATTERN = const BOOTSTRAP_TRANSPORT_EVIDENCE_PATTERN = new RegExp( [ 'mailbox_bootstrap_written', + 'startup_checkpoint', + 'last runtime stage', 'bootstrap_prompt_observed', 'bootstrap_submit_attempted', 'bootstrap_submitted', @@ -341,13 +343,15 @@ export function extractLaunchBootstrapTransportBreadcrumb( ): LaunchBootstrapTransportBreadcrumb { const parts = collectLaunchFailureSearchParts(input); const combined = parts.join('\n'); - const lastStageMatches = [...combined.matchAll(/last transport stage:\s*([^;\n]+)/gi)]; + const lastStageMatches = [ + ...combined.matchAll(/last (?:transport|runtime) stage:\s*([^;\n]+)/gi), + ]; const retryableMatches = [ ...combined.matchAll(/bootstrap_submit_rejected[^\n]*(?:retryable[=:]\s*(true|false))/gi), ]; const evidence = firstEvidence( parts, - /bootstrap_submit_|mailbox_bootstrap_written|bootstrap_prompt_observed|bootstrap_submitted|last transport stage|no stdin data received|local prompt handler/i + /bootstrap_submit_|mailbox_bootstrap_written|startup_checkpoint|bootstrap_prompt_observed|bootstrap_submitted|last (?:transport|runtime) stage|no stdin data received|local prompt handler/i ).map(redactLaunchFailureArtifactText); const retryableRaw = retryableMatches.at(-1)?.[1]?.toLowerCase(); return { diff --git a/test/main/services/team/ProcessBootstrapTransportEvidence.test.ts b/test/main/services/team/ProcessBootstrapTransportEvidence.test.ts index c247ff2c..6daf309c 100644 --- a/test/main/services/team/ProcessBootstrapTransportEvidence.test.ts +++ b/test/main/services/team/ProcessBootstrapTransportEvidence.test.ts @@ -96,6 +96,30 @@ describe('ProcessBootstrapTransportEvidence', () => { expect(summary?.lastStage).toBe('process spawned'); }); + it('surfaces headless startup checkpoints as transport progress', () => { + const summary = summarizeProcessBootstrapTransportEvents([ + { + type: 'cli_started', + timestamp: '2026-05-07T10:00:00.000Z', + detail: 'teammateRuntime=headless', + }, + { + type: 'startup_checkpoint', + timestamp: '2026-05-07T10:00:01.000Z', + detail: 'commands_agents_loaded', + }, + ]); + + expect(summary).toMatchObject({ + submitted: false, + hasProgress: true, + lastStage: 'startup checkpoint: commands_agents_loaded', + }); + expect(buildProcessBootstrapTimeoutDiagnostic(summary!)).toBe( + 'Bootstrap prompt was not submitted before timeout. Last transport stage: startup checkpoint: commands_agents_loaded' + ); + }); + it('builds stable pending and timeout diagnostics from the last transport stage', () => { const summary = summarizeProcessBootstrapTransportEvents([ { diff --git a/test/main/services/team/TeamLaunchFailureArtifactPack.test.ts b/test/main/services/team/TeamLaunchFailureArtifactPack.test.ts index 620e04c8..f2cd1c63 100644 --- a/test/main/services/team/TeamLaunchFailureArtifactPack.test.ts +++ b/test/main/services/team/TeamLaunchFailureArtifactPack.test.ts @@ -276,6 +276,26 @@ describe('TeamLaunchFailureArtifactPack', () => { }); }); + it('extracts startup checkpoint runtime stages and keeps stdin warning secondary', () => { + const input = { + teamName: 'artifact-team', + runId: 'run-startup-checkpoint', + reason: + 'alice: Teammate process alice@signal-ops did not become runtime_ready: timed out waiting for runtime_ready; last runtime stage: startup_checkpoint: commands_agents_loaded Last stderr: Warning: no stdin data received in 3s, proceeding without it.', + progressTraceLines: [ + 'startup_checkpoint detail=commands_agents_loaded', + 'Warning: no stdin data received in 3s, proceeding without it.', + ], + }; + + expect(classifyLaunchFailureArtifact(input).code).toBe('process_readiness_timeout'); + expect(extractLaunchBootstrapTransportBreadcrumb(input)).toMatchObject({ + lastTransportStage: 'startup_checkpoint: commands_agents_loaded', + noStdinWarning: true, + bootstrapSubmitted: false, + }); + }); + it('keeps inbox poller bootstrap stalls out of stdin_missing classification', () => { const input = { teamName: 'artifact-team',