fix(team): treat stale observe refresh marker as recoverable

This commit is contained in:
777genius 2026-05-31 09:31:26 +03:00
parent 8df2a8797b
commit 9924e447c8
6 changed files with 34 additions and 5 deletions

View file

@ -976,6 +976,7 @@ function isOpenCodeSessionRefreshScheduledReason(message: string | null | undefi
normalized === 'opencode_prompt_delivery_session_refresh_scheduled' ||
normalized === 'opencode session refresh scheduled after resolved behavior changed' ||
normalized === 'opencode_session_refresh_scheduled_after_resolved_behavior_changed' ||
normalized === 'opencode_session_stale_observe_scheduled_after_accepted_prompt' ||
normalized === 'opencode session changed; refreshing the session before retry'
);
}

View file

@ -61,6 +61,7 @@ function isOpenCodeRuntimeDeliverySessionRefreshScheduledDiagnostic(message: str
normalized === 'opencode_prompt_delivery_session_refresh_scheduled' ||
normalized === 'opencode session refresh scheduled after resolved behavior changed' ||
normalized === 'opencode_session_refresh_scheduled_after_resolved_behavior_changed' ||
normalized === 'opencode_session_stale_observe_scheduled_after_accepted_prompt' ||
normalized === 'opencode session changed; refreshing the session before retry'
);
}

View file

@ -49,7 +49,8 @@ function isCleanOpenCodeSessionRefreshDiagnostic(message: string): boolean {
refreshMarkerText === 'opencode session changed; refreshing the session before retry' ||
refreshMarkerText === 'opencode session refresh scheduled after resolved behavior changed' ||
refreshMarkerText === 'opencode_prompt_delivery_session_refresh_scheduled' ||
refreshMarkerText === 'opencode_session_refresh_scheduled_after_resolved_behavior_changed'
refreshMarkerText === 'opencode_session_refresh_scheduled_after_resolved_behavior_changed' ||
refreshMarkerText === 'opencode_session_stale_observe_scheduled_after_accepted_prompt'
) {
return true;
}

View file

@ -163,6 +163,25 @@ describe('OpenCodeRuntimeDeliveryDiagnostics', () => {
);
});
it('treats stale observe scheduled diagnostics after an accepted prompt as session refresh', () => {
const record = {
diagnostics: [
'OpenCode API error',
'OpenCode API error. opencode_session_stale_observe_scheduled_after_accepted_prompt',
],
lastReason: 'OpenCode API error',
responseState: 'not_observed',
status: 'retry_scheduled',
} as Parameters<typeof selectOpenCodeRuntimeDeliveryReason>[0];
expect(selectOpenCodeRuntimeDeliveryReason(record)).toBe(
'OpenCode session changed; refreshing the session before retry.'
);
expect(
isActionRequiredOpenCodeRuntimeDeliveryReason(selectOpenCodeRuntimeDeliveryReason(record))
).toBe(false);
});
it('treats colon-terminated generic OpenCode API errors plus clean refresh evidence as session refresh', () => {
const record = {
diagnostics: ['OpenCode API error:', 'resolved_behavior_changed:old->new'],

View file

@ -228,6 +228,16 @@ describe('RuntimeDiagnosticClassifier', () => {
generic: true,
actionRequired: false,
});
expect(
classifyRuntimeDiagnostic(
'OpenCode API error. opencode_session_stale_observe_scheduled_after_accepted_prompt'
)
).toMatchObject({
reasonCode: 'backend_error',
normalizedMessage: 'OpenCode session changed; refreshing the session before retry.',
generic: true,
actionRequired: false,
});
});
it('does not classify refresh markers with unknown extra text as clean refresh', () => {

View file

@ -129,7 +129,6 @@ function buildOpenCodeDeliveryRecord(
lastReason: 'OpenCode bridge command timed out',
diagnostics: [
'OpenCode prompt_async accepted; response observation will continue through durable app-side ledger reconciliation.',
'project_behavior_changed',
'opencode_session_stale_observe_scheduled_after_accepted_prompt',
'OpenCode bridge command timed out',
],
@ -762,9 +761,7 @@ describe('TeamMemberRuntimeAdvisoryService', () => {
kind: 'api_error',
reasonCode: 'backend_error',
});
expect(advisory?.message).toContain(
'opencode_session_stale_observe_scheduled_after_accepted_prompt'
);
expect(advisory?.message).toBe('OpenCode runtime delivery did not complete.');
});
it('keeps stale OpenCode advisories visible after unrelated later delivery success', async () => {