fix(team): surface runtime launch stages

This commit is contained in:
777genius 2026-06-05 16:51:47 +03:00
parent 9cfbb3898d
commit 6fb83676e7
4 changed files with 51 additions and 2 deletions

View file

@ -54,6 +54,7 @@ const TRANSPORT_STAGE_LABELS: Record<string, string> = {
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',

View file

@ -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 {

View file

@ -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([
{

View file

@ -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',