@kbediako/codex-orchestrator 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +43 -83
  2. package/dist/bin/codex-orchestrator.js +2 -0
  3. package/dist/orchestrator/src/cli/adapters/CommandBuilder.js +50 -0
  4. package/dist/orchestrator/src/cli/adapters/cloudFailureDiagnostics.js +117 -5
  5. package/dist/orchestrator/src/cli/coStatusAttachCliShell.js +2 -2
  6. package/dist/orchestrator/src/cli/coStatusCliShell.js +28 -6
  7. package/dist/orchestrator/src/cli/codexCliShell.js +48 -1
  8. package/dist/orchestrator/src/cli/codexDefaultsSetup.js +217 -26
  9. package/dist/orchestrator/src/cli/control/controlHostSupervision.js +28 -6
  10. package/dist/orchestrator/src/cli/control/controlRuntime.js +17 -6
  11. package/dist/orchestrator/src/cli/control/controlStatusDashboard.js +6 -1
  12. package/dist/orchestrator/src/cli/control/selectedRunProjection.js +49 -2
  13. package/dist/orchestrator/src/cli/doctor.js +142 -48
  14. package/dist/orchestrator/src/cli/init.js +94 -1
  15. package/dist/orchestrator/src/cli/providerLinearChildLaneRunner.js +64 -1
  16. package/dist/orchestrator/src/cli/providerLinearWorkerRunner.js +1165 -69
  17. package/dist/orchestrator/src/cli/rlm/alignment.js +3 -3
  18. package/dist/orchestrator/src/cli/services/commandRunner.js +31 -0
  19. package/dist/orchestrator/src/cli/utils/cloudPreflight.js +202 -6
  20. package/dist/orchestrator/src/cli/utils/codexFeatures.js +60 -0
  21. package/dist/orchestrator/src/manager.js +74 -4
  22. package/dist/scripts/lib/docs-catalog.js +35 -1
  23. package/docs/README.md +333 -0
  24. package/docs/book/README.md +19 -0
  25. package/docs/book/codex-cli-0124-adoption.md +68 -0
  26. package/docs/book/local-hook-impact.md +73 -0
  27. package/docs/book/operations.md +60 -0
  28. package/docs/book/public-posture.md +34 -0
  29. package/docs/book/setup.md +91 -0
  30. package/docs/book/skills.md +11 -0
  31. package/docs/guides/codex-version-policy.md +104 -0
  32. package/docs/public/downstream-setup.md +25 -18
  33. package/package.json +4 -1
  34. package/plugins/codex-orchestrator/.codex-plugin/plugin.json +1 -1
  35. package/plugins/codex-orchestrator/launcher.mjs +6 -4
  36. package/schemas/manifest.json +17 -0
  37. package/skills/README.md +26 -0
  38. package/skills/collab-subagents-first/SKILL.md +1 -1
  39. package/skills/delegation-usage/DELEGATION_GUIDE.md +12 -7
  40. package/skills/delegation-usage/SKILL.md +13 -8
  41. package/templates/codex/AGENTS.md +12 -10
@@ -39,6 +39,7 @@ export const PROVIDER_LINEAR_WORKER_CHILD_LANES_FILENAME = 'provider-linear-work
39
39
  export const PROVIDER_LINEAR_RESIDENT_SESSION_SEED_ENV = 'CODEX_ORCHESTRATOR_PROVIDER_RESIDENT_SESSION_SEED';
40
40
  export const PROVIDER_LINEAR_CHILD_LANE_PIPELINE_ID = 'provider-linear-child-lane';
41
41
  export const PROVIDER_LINEAR_CHILD_LANE_RESERVED_SUMMARY = 'Child lane reserved before child run startup.';
42
+ export const PROVIDER_LINEAR_CHILD_LANE_DIAGNOSTICS_FILENAME = 'provider-linear-child-lane-diagnostics.json';
42
43
  const PROVIDER_LINEAR_CHILD_LANE_PROOF_FILENAME = 'provider-linear-child-lane-proof.json';
43
44
  const PROVIDER_LINEAR_WORKER_SESSION_LOG_HYDRATION_FILENAME = 'provider-linear-worker-session-log-hydration.json';
44
45
  const PROVIDER_LINEAR_WORKER_PROOF_LOCK_FILENAME = `${PROVIDER_LINEAR_WORKER_PROOF_FILENAME}.lock`;
@@ -94,6 +95,9 @@ export const PROVIDER_SEMANTIC_STALL_RECHECK_DELAY_MS = 15 * 60 * 1000 + 1_000;
94
95
  const PROVIDER_WORKER_SESSION_LOG_POLL_INTERVAL_MS = 250;
95
96
  const PROVIDER_WORKER_SESSION_LOG_DISCOVERY_WINDOW_MS = 15 * 60 * 1000;
96
97
  const PROVIDER_WORKER_SESSION_LOG_HEADER_BYTES = 256 * 1024;
98
+ const PROVIDER_LINEAR_CHILD_LANE_POST_STARTUP_NO_OUTPUT_MIN_STALE_MS = 60 * 1000;
99
+ const PROVIDER_LINEAR_CHILD_LANE_RUNNER_IDENTITY_START_BEFORE_TOLERANCE_MS = 5 * 60 * 1000;
100
+ const PROVIDER_LINEAR_CHILD_LANE_RUNNER_PROCESS_LOOKUP_TIMEOUT_MS = 2000;
97
101
  export function buildEmptyProviderLinearWorkerTokenUsage() {
98
102
  return {
99
103
  input_tokens: null,
@@ -1391,7 +1395,7 @@ function applyProviderLinearWorkerJsonlRecord(state, parsed, activitySource, env
1391
1395
  }
1392
1396
  const observedTokens = extractProviderWorkerTokenUsage(parsed);
1393
1397
  if (observedTokens && hasProviderWorkerTokenUsage(observedTokens)) {
1394
- state.tokens = observedTokens;
1398
+ state.tokens = mergeProviderWorkerObservedTokenUsage(state.tokens, observedTokens);
1395
1399
  changed = true;
1396
1400
  }
1397
1401
  const observedRateLimits = extractProviderWorkerRateLimits(parsed);
@@ -1416,13 +1420,6 @@ function applyProviderLinearWorkerJsonlRecord(state, parsed, activitySource, env
1416
1420
  }
1417
1421
  return changed;
1418
1422
  }
1419
- function applyProviderLinearWorkerSessionJsonlLine(state, line, env = process.env) {
1420
- const parsed = parseProviderWorkerSessionJsonlLine(line);
1421
- if (!parsed) {
1422
- return false;
1423
- }
1424
- return applyProviderLinearWorkerSessionJsonlRecord(state, parsed, env);
1425
- }
1426
1423
  function applyProviderLinearWorkerSessionJsonlRecord(state, parsed, env = process.env) {
1427
1424
  return applyProviderLinearWorkerJsonlRecord(state, parsed, 'session_log_hydration', env);
1428
1425
  }
@@ -1440,7 +1437,10 @@ function isProviderLinearWorkerBookkeepingRecord(parsed) {
1440
1437
  return parsed.type === 'session_meta' || parsed.type === 'turn_context' || parsed.type === 'thread.started';
1441
1438
  }
1442
1439
  function hasProviderWorkerTokenUsage(value) {
1443
- return value.input_tokens !== null || value.output_tokens !== null || value.total_tokens !== null;
1440
+ return (value.input_tokens !== null ||
1441
+ value.output_tokens !== null ||
1442
+ value.total_tokens !== null ||
1443
+ value.reasoning_output_tokens != null);
1444
1444
  }
1445
1445
  function maxProviderWorkerNullableNumber(left, right) {
1446
1446
  if (left === null) {
@@ -1452,11 +1452,28 @@ function maxProviderWorkerNullableNumber(left, right) {
1452
1452
  return Math.max(left, right);
1453
1453
  }
1454
1454
  function mergeProviderWorkerTokenUsageFloor(current, observed) {
1455
- return {
1455
+ const merged = {
1456
1456
  input_tokens: maxProviderWorkerNullableNumber(current.input_tokens, observed.input_tokens),
1457
1457
  output_tokens: maxProviderWorkerNullableNumber(current.output_tokens, observed.output_tokens),
1458
1458
  total_tokens: maxProviderWorkerNullableNumber(current.total_tokens, observed.total_tokens)
1459
1459
  };
1460
+ const reasoningOutputTokens = maxProviderWorkerNullableNumber(current.reasoning_output_tokens ?? null, observed.reasoning_output_tokens ?? null);
1461
+ if (reasoningOutputTokens !== null) {
1462
+ merged.reasoning_output_tokens = reasoningOutputTokens;
1463
+ }
1464
+ return merged;
1465
+ }
1466
+ function mergeProviderWorkerObservedTokenUsage(current, observed) {
1467
+ const merged = {
1468
+ input_tokens: observed.input_tokens ?? current.input_tokens,
1469
+ output_tokens: observed.output_tokens ?? current.output_tokens,
1470
+ total_tokens: observed.total_tokens ?? current.total_tokens
1471
+ };
1472
+ const reasoningOutputTokens = observed.reasoning_output_tokens ?? current.reasoning_output_tokens ?? null;
1473
+ if (reasoningOutputTokens !== null) {
1474
+ merged.reasoning_output_tokens = reasoningOutputTokens;
1475
+ }
1476
+ return merged;
1460
1477
  }
1461
1478
  function providerWorkerTokenUsageFallsBehindFloor(current, observed) {
1462
1479
  return (observed !== null &&
@@ -1666,15 +1683,30 @@ function normalizeProviderWorkerTokenUsage(input) {
1666
1683
  'totalTokens',
1667
1684
  'total'
1668
1685
  ]);
1686
+ const reasoningOutputTokens = readTokenCount(input, [
1687
+ 'reasoning_output_tokens',
1688
+ 'reasoningOutputTokens',
1689
+ 'total_reasoning_output_tokens',
1690
+ 'totalReasoningOutputTokens',
1691
+ 'reasoning_tokens',
1692
+ 'reasoningTokens'
1693
+ ]);
1669
1694
  const normalizedTotalTokens = totalTokens ?? (inputTokens !== null && outputTokens !== null ? inputTokens + outputTokens : null);
1670
- if (inputTokens === null && outputTokens === null && normalizedTotalTokens === null) {
1695
+ if (inputTokens === null &&
1696
+ outputTokens === null &&
1697
+ normalizedTotalTokens === null &&
1698
+ reasoningOutputTokens === null) {
1671
1699
  return null;
1672
1700
  }
1673
- return {
1701
+ const usage = {
1674
1702
  input_tokens: inputTokens,
1675
1703
  output_tokens: outputTokens,
1676
1704
  total_tokens: normalizedTotalTokens
1677
1705
  };
1706
+ if (reasoningOutputTokens !== null) {
1707
+ usage.reasoning_output_tokens = reasoningOutputTokens;
1708
+ }
1709
+ return usage;
1678
1710
  }
1679
1711
  function readTokenCount(input, keys) {
1680
1712
  for (const key of keys) {
@@ -2698,6 +2730,9 @@ function formatProviderWorkerTokenUsageSummary(usage) {
2698
2730
  if (typeof usage.total_tokens === 'number' && Number.isFinite(usage.total_tokens)) {
2699
2731
  parts.push(`total ${Math.max(0, Math.trunc(usage.total_tokens))}`);
2700
2732
  }
2733
+ if (typeof usage.reasoning_output_tokens === 'number' && Number.isFinite(usage.reasoning_output_tokens)) {
2734
+ parts.push(`reasoning ${Math.max(0, Math.trunc(usage.reasoning_output_tokens))}`);
2735
+ }
2701
2736
  return parts.length > 0 ? parts.join(' / ') : null;
2702
2737
  }
2703
2738
  function formatProviderWorkerRateLimitSummary(rateLimits) {
@@ -2964,6 +2999,7 @@ function resetProviderWorkerSessionLogTailState(state) {
2964
2999
  state.offsetBytes = 0;
2965
3000
  state.trailingText = '';
2966
3001
  state.bootstrapPending = true;
3002
+ state.idRewindSignature = null;
2967
3003
  }
2968
3004
  function normalizeProviderWorkerSessionLogHydrationState(value) {
2969
3005
  if (!isRecord(value)) {
@@ -2981,36 +3017,46 @@ function normalizeProviderWorkerSessionLogHydrationState(value) {
2981
3017
  offset_bytes: offsetBytes,
2982
3018
  trailing_text: typeof value.trailing_text === 'string' ? value.trailing_text : '',
2983
3019
  bootstrap_pending: typeof value.bootstrap_pending === 'boolean' ? value.bootstrap_pending : true,
2984
- proof_signature: typeof value.proof_signature === 'string' ? value.proof_signature : ''
3020
+ proof_signature: typeof value.proof_signature === 'string' ? value.proof_signature : '',
3021
+ id_rewind_signature: typeof value.id_rewind_signature === 'string' ? value.id_rewind_signature : null
2985
3022
  };
2986
3023
  }
2987
- function buildProviderWorkerSessionLogTailState(path, hydrationState) {
3024
+ function buildProviderWorkerSessionLogTailState(path, hydrationState, currentTurnStartedAt = null) {
3025
+ const normalizedCurrentTurnStartedAt = normalizeOptionalString(currentTurnStartedAt);
2988
3026
  if (!hydrationState || hydrationState.path !== path) {
2989
3027
  return {
2990
3028
  path,
2991
3029
  offsetBytes: 0,
2992
3030
  trailingText: '',
2993
- bootstrapPending: true
3031
+ bootstrapPending: true,
3032
+ currentTurnStartedAt: normalizedCurrentTurnStartedAt,
3033
+ idRewindSignature: null
2994
3034
  };
2995
3035
  }
2996
3036
  return {
2997
3037
  path,
2998
3038
  offsetBytes: hydrationState.offset_bytes,
2999
3039
  trailingText: hydrationState.trailing_text,
3000
- bootstrapPending: hydrationState.bootstrap_pending
3040
+ bootstrapPending: hydrationState.bootstrap_pending,
3041
+ currentTurnStartedAt: normalizedCurrentTurnStartedAt,
3042
+ idRewindSignature: hydrationState.id_rewind_signature ?? null
3001
3043
  };
3002
3044
  }
3003
3045
  function snapshotProviderWorkerSessionLogTailState(state) {
3004
3046
  if (!state.path) {
3005
3047
  return null;
3006
3048
  }
3007
- return {
3049
+ const snapshot = {
3008
3050
  path: state.path,
3009
3051
  offset_bytes: state.offsetBytes,
3010
3052
  trailing_text: state.trailingText,
3011
3053
  bootstrap_pending: state.bootstrapPending,
3012
3054
  proof_signature: ''
3013
3055
  };
3056
+ if (state.idRewindSignature) {
3057
+ snapshot.id_rewind_signature = state.idRewindSignature;
3058
+ }
3059
+ return snapshot;
3014
3060
  }
3015
3061
  function selectProviderLinearWorkerCurrentTurnActivity(proof) {
3016
3062
  const hydrated = proof.current_turn_activity ?? null;
@@ -3048,6 +3094,31 @@ function buildProviderWorkerSessionLogHydrationProofSignature(proof) {
3048
3094
  failure_diagnosis: proof.failure_diagnosis ?? null
3049
3095
  });
3050
3096
  }
3097
+ function providerLinearWorkerProofNeedsSessionLogIdHydration(proof) {
3098
+ const selectedMode = proof.runtime?.selected_mode ?? proof.auth_provenance?.runtime_mode ?? null;
3099
+ if (selectedMode !== 'appserver') {
3100
+ return false;
3101
+ }
3102
+ if (!proof.thread_id || !proof.latest_turn_id || !proof.latest_session_id) {
3103
+ return false;
3104
+ }
3105
+ return (proof.session_log_thread_id !== proof.thread_id ||
3106
+ proof.session_log_turn_id !== proof.latest_turn_id ||
3107
+ proof.session_log_session_id !== proof.latest_session_id);
3108
+ }
3109
+ function buildProviderWorkerSessionLogIdHydrationRewindSignature(proof) {
3110
+ if (!providerLinearWorkerProofNeedsSessionLogIdHydration(proof)) {
3111
+ return null;
3112
+ }
3113
+ return JSON.stringify({
3114
+ thread_id: proof.thread_id ?? null,
3115
+ latest_turn_id: proof.latest_turn_id ?? null,
3116
+ latest_session_id: proof.latest_session_id ?? null,
3117
+ session_log_thread_id: proof.session_log_thread_id ?? null,
3118
+ session_log_turn_id: proof.session_log_turn_id ?? null,
3119
+ session_log_session_id: proof.session_log_session_id ?? null
3120
+ });
3121
+ }
3051
3122
  async function readProviderWorkerSessionLogDelta(state) {
3052
3123
  if (!state.path) {
3053
3124
  return '';
@@ -3060,6 +3131,7 @@ async function readProviderWorkerSessionLogDelta(state) {
3060
3131
  state.offsetBytes = 0;
3061
3132
  state.trailingText = '';
3062
3133
  state.bootstrapPending = true;
3134
+ state.idRewindSignature = null;
3063
3135
  }
3064
3136
  const bytesToRead = fileStat.size - state.offsetBytes;
3065
3137
  if (bytesToRead <= 0) {
@@ -3089,11 +3161,54 @@ function parseProviderWorkerSessionJsonlLine(line) {
3089
3161
  return null;
3090
3162
  }
3091
3163
  }
3164
+ function extractProviderWorkerSessionLogObservedThreadId(parsed) {
3165
+ const payload = isRecord(parsed.payload) ? parsed.payload : null;
3166
+ if (parsed.type === 'session_meta' && payload) {
3167
+ return normalizeOptionalString(payload.id);
3168
+ }
3169
+ if (parsed.type === 'thread.started') {
3170
+ return normalizeOptionalString(parsed.thread_id);
3171
+ }
3172
+ return null;
3173
+ }
3174
+ function extractProviderWorkerSessionLogObservedTurnId(parsed) {
3175
+ const payload = isRecord(parsed.payload) ? parsed.payload : null;
3176
+ if (parsed.type === 'turn_context' && payload) {
3177
+ return normalizeOptionalString(payload.turn_id);
3178
+ }
3179
+ return extractProviderWorkerActivityTurnId(parsed);
3180
+ }
3181
+ function observeProviderWorkerSessionLogLines(lines) {
3182
+ let observed = false;
3183
+ let observedThreadId = null;
3184
+ let observedTurnId = null;
3185
+ for (const line of lines) {
3186
+ const parsed = parseProviderWorkerSessionJsonlLine(line);
3187
+ if (!parsed) {
3188
+ continue;
3189
+ }
3190
+ observed = true;
3191
+ observedThreadId = extractProviderWorkerSessionLogObservedThreadId(parsed) ?? observedThreadId;
3192
+ observedTurnId = extractProviderWorkerSessionLogObservedTurnId(parsed) ?? observedTurnId;
3193
+ }
3194
+ return {
3195
+ observed,
3196
+ observedThreadId,
3197
+ observedTurnId
3198
+ };
3199
+ }
3200
+ function observeProviderWorkerSessionLogAppliedLines(input) {
3201
+ const observationLines = !input.bootstrapPending || input.linesToApply.length === input.lines.length
3202
+ ? input.lines
3203
+ : input.linesToApply;
3204
+ return observeProviderWorkerSessionLogLines(observationLines);
3205
+ }
3092
3206
  function selectProviderWorkerSessionBootstrapLines(lines, options = { requireTurnContext: false }) {
3093
3207
  let latestSessionMetaIndex = -1;
3094
3208
  let latestTurnContextIndex = -1;
3095
3209
  let latestTurnId = null;
3096
3210
  let latestTurnCompleted = false;
3211
+ let latestTurnCompletedIndex = -1;
3097
3212
  for (let index = 0; index < lines.length; index += 1) {
3098
3213
  const parsed = parseProviderWorkerSessionJsonlLine(lines[index] ?? '');
3099
3214
  if (!parsed) {
@@ -3106,12 +3221,14 @@ function selectProviderWorkerSessionBootstrapLines(lines, options = { requireTur
3106
3221
  latestTurnContextIndex = index;
3107
3222
  latestTurnId = normalizeOptionalString(parsed.payload.turn_id);
3108
3223
  latestTurnCompleted = false;
3224
+ latestTurnCompletedIndex = -1;
3109
3225
  }
3110
3226
  if (parsed.type === 'event_msg' && isRecord(parsed.payload) && parsed.payload.type === 'task_complete') {
3111
3227
  const completedTurnId = normalizeOptionalString(parsed.payload.turn_id);
3112
3228
  if (latestTurnContextIndex >= 0 &&
3113
3229
  (!latestTurnId || !completedTurnId || completedTurnId === latestTurnId)) {
3114
3230
  latestTurnCompleted = true;
3231
+ latestTurnCompletedIndex = index;
3115
3232
  }
3116
3233
  }
3117
3234
  }
@@ -3122,14 +3239,66 @@ function selectProviderWorkerSessionBootstrapLines(lines, options = { requireTur
3122
3239
  return lines;
3123
3240
  }
3124
3241
  if (latestTurnCompleted) {
3125
- return latestSessionMetaIndex >= 0 ? [lines[latestSessionMetaIndex] ?? ''] : [];
3242
+ const currentTurnId = normalizeOptionalString(options.currentTurnId);
3243
+ const allowCompletedBootstrapTurn = options.allowCompletedBootstrapTurn ?? true;
3244
+ if (!allowCompletedBootstrapTurn && currentTurnId === null) {
3245
+ return latestSessionMetaIndex >= 0 ? [lines[latestSessionMetaIndex] ?? ''] : [];
3246
+ }
3247
+ if (currentTurnId !== null && latestTurnId !== null && latestTurnId !== currentTurnId) {
3248
+ return latestSessionMetaIndex >= 0 ? [lines[latestSessionMetaIndex] ?? ''] : [];
3249
+ }
3250
+ const currentTurnMatchesCompletedLog = currentTurnId !== null && latestTurnId === currentTurnId;
3251
+ const completedLine = latestTurnCompletedIndex >= 0 ? lines[latestTurnCompletedIndex] ?? '' : '';
3252
+ const completedLineHasTimestamp = providerWorkerSessionJsonlLineTimestamp(completedLine) !== null;
3253
+ const completedFloorLine = completedLine && completedLineHasTimestamp
3254
+ ? completedLine
3255
+ : lines[latestTurnContextIndex] ?? '';
3256
+ if (!currentTurnMatchesCompletedLog &&
3257
+ !isProviderWorkerSessionBootstrapLineAtOrAfter(completedFloorLine, options.currentTurnStartedAt ?? null)) {
3258
+ return latestSessionMetaIndex >= 0 ? [lines[latestSessionMetaIndex] ?? ''] : [];
3259
+ }
3260
+ const bootstrapLines = latestSessionMetaIndex >= 0 && latestSessionMetaIndex < latestTurnContextIndex
3261
+ ? [lines[latestSessionMetaIndex] ?? '']
3262
+ : [];
3263
+ return [...bootstrapLines, ...lines.slice(latestTurnContextIndex)];
3126
3264
  }
3127
3265
  const bootstrapLines = latestSessionMetaIndex >= 0 && latestSessionMetaIndex < latestTurnContextIndex
3128
3266
  ? [lines[latestSessionMetaIndex] ?? '']
3129
3267
  : [];
3130
3268
  return [...bootstrapLines, ...lines.slice(latestTurnContextIndex)];
3131
3269
  }
3132
- function applyProviderWorkerSessionLogDelta(parseState, tailState, chunk, env = process.env) {
3270
+ function providerWorkerSessionJsonlLineTimestamp(line) {
3271
+ const parsed = parseProviderWorkerSessionJsonlLine(line);
3272
+ if (!parsed) {
3273
+ return null;
3274
+ }
3275
+ const lineTimestamp = normalizeOptionalString(parsed.timestamp);
3276
+ if (lineTimestamp) {
3277
+ return lineTimestamp;
3278
+ }
3279
+ const payload = isRecord(parsed.payload) ? parsed.payload : null;
3280
+ return payload
3281
+ ? normalizeOptionalString(payload.timestamp) ??
3282
+ normalizeOptionalString(payload.created_at) ??
3283
+ normalizeOptionalString(payload.at)
3284
+ : null;
3285
+ }
3286
+ function isProviderWorkerSessionBootstrapLineAtOrAfter(line, floorTimestamp) {
3287
+ const normalizedFloor = normalizeOptionalString(floorTimestamp);
3288
+ if (!normalizedFloor) {
3289
+ return false;
3290
+ }
3291
+ const lineTimestamp = providerWorkerSessionJsonlLineTimestamp(line);
3292
+ return lineTimestamp !== null && compareIsoTimestamp(lineTimestamp, normalizedFloor) >= 0;
3293
+ }
3294
+ function shouldAllowCompletedProviderWorkerSessionBootstrapTurn(proof) {
3295
+ if (proof.latest_turn_id !== null) {
3296
+ return true;
3297
+ }
3298
+ const continuityState = proof.resident_session?.continuity_state ?? null;
3299
+ return continuityState !== 'guarded_resume_pending' && continuityState !== 'guarded_resume_active';
3300
+ }
3301
+ function applyProviderWorkerSessionLogDelta(parseState, tailState, chunk, env = process.env, options = {}) {
3133
3302
  const combined = `${tailState.trailingText}${chunk}`;
3134
3303
  const lines = combined.split(/\r?\n/u);
3135
3304
  tailState.trailingText = lines.pop() ?? '';
@@ -3139,49 +3308,111 @@ function applyProviderWorkerSessionLogDelta(parseState, tailState, chunk, env =
3139
3308
  }
3140
3309
  const requireTurnContext = tailState.bootstrapPending && parseState.turnId === null;
3141
3310
  const linesToApply = tailState.bootstrapPending && lines.length > 0
3142
- ? selectProviderWorkerSessionBootstrapLines(lines, { requireTurnContext })
3311
+ ? selectProviderWorkerSessionBootstrapLines(lines, {
3312
+ requireTurnContext,
3313
+ currentTurnStartedAt: tailState.currentTurnStartedAt,
3314
+ currentTurnId: parseState.turnId,
3315
+ allowCompletedBootstrapTurn: options.allowCompletedBootstrapTurn
3316
+ })
3143
3317
  : lines;
3318
+ const observation = observeProviderWorkerSessionLogAppliedLines({
3319
+ lines,
3320
+ linesToApply,
3321
+ bootstrapPending: tailState.bootstrapPending
3322
+ });
3144
3323
  let changed = false;
3145
3324
  for (const line of linesToApply) {
3146
- changed = applyProviderLinearWorkerSessionJsonlLine(parseState, line, env) || changed;
3325
+ const parsed = parseProviderWorkerSessionJsonlLine(line);
3326
+ if (!parsed) {
3327
+ continue;
3328
+ }
3329
+ changed = applyProviderLinearWorkerSessionJsonlRecord(parseState, parsed, env) || changed;
3147
3330
  }
3148
3331
  if (tailState.bootstrapPending && lines.length > 0) {
3149
3332
  tailState.bootstrapPending = requireTurnContext && parseState.turnId === null;
3150
3333
  }
3151
- return changed;
3334
+ return { changed, ...observation };
3152
3335
  }
3153
- function flushProviderWorkerSessionLogTail(parseState, tailState, env = process.env) {
3336
+ function flushProviderWorkerSessionLogTail(parseState, tailState, env = process.env, options = {}) {
3154
3337
  const trailingLine = tailState.trailingText.trim();
3155
3338
  if (!trailingLine) {
3156
3339
  tailState.trailingText = '';
3157
- return false;
3340
+ return { changed: false, observed: false, observedThreadId: null, observedTurnId: null };
3158
3341
  }
3159
3342
  if (!parseProviderWorkerSessionJsonlLine(trailingLine)) {
3160
- return false;
3343
+ return { changed: false, observed: false, observedThreadId: null, observedTurnId: null };
3161
3344
  }
3162
3345
  tailState.trailingText = '';
3163
3346
  const shouldBootstrap = tailState.bootstrapPending;
3164
3347
  const requireTurnContext = shouldBootstrap && parseState.turnId === null;
3165
3348
  const trailingLines = shouldBootstrap
3166
- ? selectProviderWorkerSessionBootstrapLines([trailingLine], { requireTurnContext })
3349
+ ? selectProviderWorkerSessionBootstrapLines([trailingLine], {
3350
+ requireTurnContext,
3351
+ currentTurnStartedAt: tailState.currentTurnStartedAt,
3352
+ currentTurnId: parseState.turnId,
3353
+ allowCompletedBootstrapTurn: options.allowCompletedBootstrapTurn
3354
+ })
3167
3355
  : [trailingLine];
3356
+ const observation = observeProviderWorkerSessionLogAppliedLines({
3357
+ lines: [trailingLine],
3358
+ linesToApply: trailingLines,
3359
+ bootstrapPending: shouldBootstrap
3360
+ });
3168
3361
  let changed = false;
3169
3362
  for (const line of trailingLines) {
3170
- changed = applyProviderLinearWorkerSessionJsonlLine(parseState, line, env) || changed;
3363
+ const parsed = parseProviderWorkerSessionJsonlLine(line);
3364
+ if (!parsed) {
3365
+ continue;
3366
+ }
3367
+ changed = applyProviderLinearWorkerSessionJsonlRecord(parseState, parsed, env) || changed;
3171
3368
  }
3172
3369
  if (shouldBootstrap) {
3173
3370
  tailState.bootstrapPending = requireTurnContext && parseState.turnId === null;
3174
3371
  }
3175
- return changed;
3372
+ return { changed, ...observation };
3176
3373
  }
3177
3374
  function normalizeProviderLinearWorkerProofForUpdatedAtComparison(proof) {
3178
3375
  return {
3179
3376
  ...proof,
3377
+ current_turn_started_at: proof.current_turn_started_at ?? null,
3378
+ session_log_thread_id: proof.session_log_thread_id ?? null,
3379
+ session_log_turn_id: proof.session_log_turn_id ?? null,
3380
+ session_log_session_id: proof.session_log_session_id ?? null,
3381
+ resume_source_thread_id: proof.resume_source_thread_id ?? null,
3382
+ current_turn_activity: proof.current_turn_activity ?? null,
3383
+ runtime: proof.runtime ?? null,
3384
+ appserver_supervision: proof.appserver_supervision
3385
+ ? {
3386
+ ...proof.appserver_supervision,
3387
+ updated_at: null
3388
+ }
3389
+ : proof.appserver_supervision ?? null,
3390
+ auth_provenance: proof.auth_provenance ?? null,
3391
+ failure_diagnosis: proof.failure_diagnosis ?? null,
3392
+ worker_host: proof.worker_host ?? null,
3393
+ source_setup: proof.source_setup ?? null,
3394
+ linear_budget: proof.linear_budget ?? null,
3395
+ tracked_issue_error: proof.tracked_issue_error ?? null,
3396
+ resident_session: proof.resident_session ?? null,
3180
3397
  parallelization: proof.parallelization ?? null,
3181
3398
  progress: null,
3182
3399
  updated_at: null
3183
3400
  };
3184
3401
  }
3402
+ function stableProviderLinearWorkerProofComparisonString(value) {
3403
+ return JSON.stringify(sortProviderLinearWorkerProofComparisonValue(value));
3404
+ }
3405
+ function sortProviderLinearWorkerProofComparisonValue(value) {
3406
+ if (Array.isArray(value)) {
3407
+ return value.map((entry) => sortProviderLinearWorkerProofComparisonValue(entry));
3408
+ }
3409
+ if (!isRecord(value)) {
3410
+ return value;
3411
+ }
3412
+ return Object.fromEntries(Object.keys(value)
3413
+ .sort()
3414
+ .map((key) => [key, sortProviderLinearWorkerProofComparisonValue(value[key])]));
3415
+ }
3185
3416
  function selectProviderLinearWorkerProofTelemetryFields(proof) {
3186
3417
  return {
3187
3418
  attempt_started_at: proof.attempt_started_at ?? null,
@@ -3189,6 +3420,10 @@ function selectProviderLinearWorkerProofTelemetryFields(proof) {
3189
3420
  latest_turn_id: proof.latest_turn_id ?? null,
3190
3421
  latest_session_id: proof.latest_session_id ?? null,
3191
3422
  latest_session_id_source: proof.latest_session_id_source ?? null,
3423
+ session_log_thread_id: proof.session_log_thread_id ?? null,
3424
+ session_log_turn_id: proof.session_log_turn_id ?? null,
3425
+ session_log_session_id: proof.session_log_session_id ?? null,
3426
+ resume_source_thread_id: proof.resume_source_thread_id ?? null,
3192
3427
  turn_count: proof.turn_count,
3193
3428
  last_event: proof.last_event ?? null,
3194
3429
  last_message: proof.last_message ?? null,
@@ -3220,13 +3455,17 @@ function deriveProviderLinearWorkerParallelizationRecord(input) {
3220
3455
  child_lane_count: selectCurrentTurnChildLanes(input.childLanes, boundary).length
3221
3456
  };
3222
3457
  }
3223
- function buildProviderLinearWorkerTurnBootstrapProof(proof, turnCount, updatedAt) {
3458
+ function buildProviderLinearWorkerTurnBootstrapProof(proof, turnCount, updatedAt, resumeSourceThreadId = null) {
3224
3459
  return {
3225
3460
  ...proof,
3226
3461
  current_turn_started_at: updatedAt,
3227
3462
  latest_turn_id: null,
3228
3463
  latest_session_id: null,
3229
3464
  latest_session_id_source: null,
3465
+ session_log_thread_id: null,
3466
+ session_log_turn_id: null,
3467
+ session_log_session_id: null,
3468
+ resume_source_thread_id: resumeSourceThreadId,
3230
3469
  last_event: null,
3231
3470
  last_message: null,
3232
3471
  last_event_at: null,
@@ -3334,8 +3573,60 @@ function shouldAdvanceProviderLinearWorkerProofUpdatedAt(currentProof, nextProof
3334
3573
  return (JSON.stringify(selectProviderLinearWorkerProofTelemetryFields(currentProof)) !==
3335
3574
  JSON.stringify(selectProviderLinearWorkerProofTelemetryFields(nextProof)));
3336
3575
  }
3337
- return (JSON.stringify(normalizeProviderLinearWorkerProofForUpdatedAtComparison(currentProof)) !==
3338
- JSON.stringify(normalizeProviderLinearWorkerProofForUpdatedAtComparison(nextProof)));
3576
+ return (stableProviderLinearWorkerProofComparisonString(normalizeProviderLinearWorkerProofForUpdatedAtComparison(currentProof)) !==
3577
+ stableProviderLinearWorkerProofComparisonString(normalizeProviderLinearWorkerProofForUpdatedAtComparison(nextProof)));
3578
+ }
3579
+ function selectProviderWorkerScopedSessionLogIds(input) {
3580
+ const proofThreadId = input.proof.session_log_thread_id ?? null;
3581
+ const proofTurnId = input.proof.session_log_turn_id ?? null;
3582
+ const proofThreadMatchesLive = proofThreadId !== null &&
3583
+ input.liveThreadId !== null &&
3584
+ proofThreadId === input.liveThreadId;
3585
+ const proofTurnMatchesLive = proofTurnId !== null && input.liveTurnId !== null && proofTurnId === input.liveTurnId;
3586
+ const observedThreadMatchesLive = input.observedThreadId !== null &&
3587
+ input.liveThreadId !== null &&
3588
+ input.observedThreadId === input.liveThreadId;
3589
+ const observedTurnMatchesLive = input.observedTurnId !== null &&
3590
+ input.liveTurnId !== null &&
3591
+ input.observedTurnId === input.liveTurnId;
3592
+ let sessionLogThreadId;
3593
+ let sessionLogTurnId;
3594
+ if (input.sessionLogObserved) {
3595
+ if (observedThreadMatchesLive) {
3596
+ sessionLogThreadId = input.observedThreadId;
3597
+ sessionLogTurnId = observedTurnMatchesLive ? input.observedTurnId : null;
3598
+ }
3599
+ else if (input.observedThreadId === null &&
3600
+ observedTurnMatchesLive &&
3601
+ input.liveThreadId !== null) {
3602
+ sessionLogThreadId = input.liveThreadId;
3603
+ sessionLogTurnId = input.observedTurnId;
3604
+ }
3605
+ else if (proofThreadMatchesLive) {
3606
+ sessionLogThreadId = proofThreadId;
3607
+ sessionLogTurnId = proofTurnMatchesLive ? proofTurnId : null;
3608
+ }
3609
+ else {
3610
+ sessionLogThreadId = null;
3611
+ sessionLogTurnId = null;
3612
+ }
3613
+ }
3614
+ else if (proofThreadMatchesLive) {
3615
+ sessionLogThreadId = proofThreadId;
3616
+ sessionLogTurnId = proofTurnMatchesLive ? proofTurnId : null;
3617
+ }
3618
+ else {
3619
+ sessionLogThreadId = input.proof.session_log_thread_id ?? null;
3620
+ sessionLogTurnId = input.proof.session_log_turn_id ?? null;
3621
+ }
3622
+ return {
3623
+ sessionLogThreadId,
3624
+ sessionLogTurnId,
3625
+ sessionLogSessionId: deriveLatestTurnSessionId({
3626
+ threadId: sessionLogThreadId,
3627
+ turnId: sessionLogTurnId
3628
+ }).sessionId
3629
+ };
3339
3630
  }
3340
3631
  async function hydrateProviderLinearWorkerProofFromSessionLog(proof, env, hydrationState = null) {
3341
3632
  const workspacePath = normalizeOptionalString(proof.workspace_path);
@@ -3395,7 +3686,7 @@ async function hydrateProviderLinearWorkerProofFromSessionLog(proof, env, hydrat
3395
3686
  parseState.currentTurnActivity = proofCurrentTurnActivity;
3396
3687
  parseState.failureDiagnosis = proof.failure_diagnosis ?? null;
3397
3688
  };
3398
- let tailState = buildProviderWorkerSessionLogTailState(sessionLogPath, hydrationState);
3689
+ let tailState = buildProviderWorkerSessionLogTailState(sessionLogPath, hydrationState, proof.current_turn_started_at ?? null);
3399
3690
  let preserveProofTelemetryFloor = false;
3400
3691
  if (hydrationState && hydrationState.path === sessionLogPath) {
3401
3692
  const proofSignature = buildProviderWorkerSessionLogHydrationProofSignature(proof);
@@ -3409,7 +3700,9 @@ async function hydrateProviderLinearWorkerProofFromSessionLog(proof, env, hydrat
3409
3700
  path: sessionLogPath,
3410
3701
  offsetBytes: fileStat.size,
3411
3702
  trailingText: tailState.trailingText,
3412
- bootstrapPending: true
3703
+ bootstrapPending: true,
3704
+ currentTurnStartedAt: tailState.currentTurnStartedAt,
3705
+ idRewindSignature: tailState.idRewindSignature
3413
3706
  };
3414
3707
  }
3415
3708
  else if (fileStat.size < tailState.offsetBytes) {
@@ -3417,7 +3710,9 @@ async function hydrateProviderLinearWorkerProofFromSessionLog(proof, env, hydrat
3417
3710
  path: sessionLogPath,
3418
3711
  offsetBytes: 0,
3419
3712
  trailingText: '',
3420
- bootstrapPending: true
3713
+ bootstrapPending: true,
3714
+ currentTurnStartedAt: tailState.currentTurnStartedAt,
3715
+ idRewindSignature: null
3421
3716
  };
3422
3717
  }
3423
3718
  else {
@@ -3429,12 +3724,44 @@ async function hydrateProviderLinearWorkerProofFromSessionLog(proof, env, hydrat
3429
3724
  }
3430
3725
  }
3431
3726
  }
3727
+ const idHydrationRewindSignature = buildProviderWorkerSessionLogIdHydrationRewindSignature(proof);
3728
+ if (idHydrationRewindSignature === null) {
3729
+ tailState = {
3730
+ ...tailState,
3731
+ idRewindSignature: null
3732
+ };
3733
+ }
3734
+ else if (tailState.offsetBytes > 0 &&
3735
+ tailState.idRewindSignature !== idHydrationRewindSignature) {
3736
+ tailState = {
3737
+ path: sessionLogPath,
3738
+ offsetBytes: 0,
3739
+ trailingText: '',
3740
+ bootstrapPending: true,
3741
+ currentTurnStartedAt: tailState.currentTurnStartedAt,
3742
+ idRewindSignature: idHydrationRewindSignature
3743
+ };
3744
+ }
3745
+ let sessionLogObserved = false;
3746
+ let observedSessionLogThreadId = proof.session_log_thread_id ?? null;
3747
+ let observedSessionLogTurnId = proof.session_log_turn_id ?? null;
3748
+ const allowCompletedBootstrapTurn = shouldAllowCompletedProviderWorkerSessionBootstrapTurn(proof);
3432
3749
  try {
3433
3750
  const delta = await readProviderWorkerSessionLogDelta(tailState);
3434
3751
  if (delta) {
3435
- applyProviderWorkerSessionLogDelta(parseState, tailState, delta, env);
3752
+ const deltaApply = applyProviderWorkerSessionLogDelta(parseState, tailState, delta, env, {
3753
+ allowCompletedBootstrapTurn
3754
+ });
3755
+ sessionLogObserved = deltaApply.observed || sessionLogObserved;
3756
+ observedSessionLogThreadId = deltaApply.observedThreadId ?? observedSessionLogThreadId;
3757
+ observedSessionLogTurnId = deltaApply.observedTurnId ?? observedSessionLogTurnId;
3436
3758
  }
3437
- flushProviderWorkerSessionLogTail(parseState, tailState, env);
3759
+ const tailApply = flushProviderWorkerSessionLogTail(parseState, tailState, env, {
3760
+ allowCompletedBootstrapTurn
3761
+ });
3762
+ sessionLogObserved = tailApply.observed || sessionLogObserved;
3763
+ observedSessionLogThreadId = tailApply.observedThreadId ?? observedSessionLogThreadId;
3764
+ observedSessionLogTurnId = tailApply.observedTurnId ?? observedSessionLogTurnId;
3438
3765
  }
3439
3766
  catch {
3440
3767
  return {
@@ -3471,12 +3798,23 @@ async function hydrateProviderLinearWorkerProofFromSessionLog(proof, env, hydrat
3471
3798
  parseState.rateLimits !== null &&
3472
3799
  providerWorkerTokenUsageFallsBehindFloor(proofTokenFloor, parseState.tokens);
3473
3800
  const persistedTailState = snapshotProviderWorkerSessionLogTailState(tailState);
3801
+ const scopedSessionLogIds = selectProviderWorkerScopedSessionLogIds({
3802
+ sessionLogObserved,
3803
+ observedThreadId: observedSessionLogThreadId,
3804
+ observedTurnId: observedSessionLogTurnId,
3805
+ proof,
3806
+ liveThreadId,
3807
+ liveTurnId
3808
+ });
3474
3809
  const hydratedProof = {
3475
3810
  ...proof,
3476
3811
  thread_id: liveThreadId,
3477
3812
  latest_turn_id: liveTurnId,
3478
3813
  latest_session_id: session.sessionId,
3479
3814
  latest_session_id_source: session.source,
3815
+ session_log_thread_id: scopedSessionLogIds.sessionLogThreadId,
3816
+ session_log_turn_id: scopedSessionLogIds.sessionLogTurnId,
3817
+ session_log_session_id: scopedSessionLogIds.sessionLogSessionId,
3480
3818
  last_event: parseState.lastEvent ?? null,
3481
3819
  last_message: parseState.finalMessage ?? null,
3482
3820
  last_event_at: parseState.lastEventAt ?? null,
@@ -3533,6 +3871,158 @@ export function deriveLatestTurnSessionId(input) {
3533
3871
  source: 'derived_from_thread_and_turn'
3534
3872
  };
3535
3873
  }
3874
+ function selectProviderLinearWorkerSessionLogProofForScope(input) {
3875
+ const sessionLogThreadId = input.proof.session_log_thread_id ?? null;
3876
+ const sessionLogTurnId = input.proof.session_log_turn_id ?? null;
3877
+ const sessionLogSessionId = input.proof.session_log_session_id ?? null;
3878
+ if (!input.scopeChanged) {
3879
+ return { sessionLogThreadId, sessionLogTurnId, sessionLogSessionId };
3880
+ }
3881
+ if (sessionLogThreadId &&
3882
+ sessionLogTurnId &&
3883
+ sessionLogSessionId &&
3884
+ sessionLogThreadId === input.threadId &&
3885
+ sessionLogTurnId === input.turnId &&
3886
+ sessionLogSessionId === input.sessionId) {
3887
+ return { sessionLogThreadId, sessionLogTurnId, sessionLogSessionId };
3888
+ }
3889
+ return { sessionLogThreadId: null, sessionLogTurnId: null, sessionLogSessionId: null };
3890
+ }
3891
+ function buildProviderLinearWorkerRuntimeProof(selection) {
3892
+ return {
3893
+ requested_mode: selection.requested_mode,
3894
+ selected_mode: selection.selected_mode,
3895
+ provider: selection.provider,
3896
+ runtime_session_id: selection.runtime_session_id,
3897
+ fallback: selection.fallback
3898
+ };
3899
+ }
3900
+ function normalizeProviderLinearWorkerRuntimeProof(proof) {
3901
+ const existing = proof.runtime ?? null;
3902
+ const authProvenance = proof.auth_provenance ?? null;
3903
+ return {
3904
+ requested_mode: existing?.requested_mode ?? authProvenance?.runtime_mode ?? null,
3905
+ selected_mode: existing?.selected_mode ?? authProvenance?.runtime_mode ?? null,
3906
+ provider: existing?.provider ?? authProvenance?.runtime_provider ?? null,
3907
+ runtime_session_id: existing?.runtime_session_id ?? null,
3908
+ fallback: existing?.fallback ?? null
3909
+ };
3910
+ }
3911
+ function normalizeProviderLinearWorkerRuntimeProofIfRelevant(proof) {
3912
+ const runtime = normalizeProviderLinearWorkerRuntimeProof(proof);
3913
+ if (runtime.requested_mode ||
3914
+ runtime.selected_mode ||
3915
+ runtime.provider ||
3916
+ runtime.runtime_session_id ||
3917
+ runtime.fallback ||
3918
+ proof.auth_provenance?.runtime_mode ||
3919
+ proof.auth_provenance?.runtime_provider) {
3920
+ return runtime;
3921
+ }
3922
+ return null;
3923
+ }
3924
+ function shouldEmitProviderLinearWorkerAppServerSupervisionProof(proof) {
3925
+ const runtime = normalizeProviderLinearWorkerRuntimeProofIfRelevant(proof);
3926
+ return (runtime?.requested_mode === 'appserver' ||
3927
+ runtime?.selected_mode === 'appserver' ||
3928
+ runtime?.fallback?.from_mode === 'appserver' ||
3929
+ runtime?.fallback?.to_mode === 'appserver' ||
3930
+ proof.auth_provenance?.runtime_mode === 'appserver');
3931
+ }
3932
+ function buildProviderLinearWorkerAppServerSupervisionProofIfRelevant(proof) {
3933
+ return shouldEmitProviderLinearWorkerAppServerSupervisionProof(proof)
3934
+ ? buildProviderLinearWorkerAppServerSupervisionProof(proof)
3935
+ : null;
3936
+ }
3937
+ function buildProviderLinearWorkerAppServerSupervisionProof(proof) {
3938
+ const selectedRuntime = normalizeProviderLinearWorkerRuntimeProof(proof);
3939
+ const selectedMode = selectedRuntime.selected_mode ?? proof.auth_provenance?.runtime_mode ?? null;
3940
+ const appserverSelected = selectedMode === 'appserver';
3941
+ const appserverIntended = appserverSelected ||
3942
+ selectedRuntime.requested_mode === 'appserver' ||
3943
+ selectedRuntime.fallback?.from_mode === 'appserver' ||
3944
+ proof.auth_provenance?.runtime_mode === 'appserver';
3945
+ const stickyEnvironmentId = normalizeOptionalString(proof.auth_provenance?.cloud_env_id) ?? null;
3946
+ const sessionLogThreadId = normalizeOptionalString(proof.session_log_thread_id) ?? null;
3947
+ const sessionLogTurnId = normalizeOptionalString(proof.session_log_turn_id) ?? null;
3948
+ const sessionLogSessionId = normalizeOptionalString(proof.session_log_session_id) ?? null;
3949
+ const hasTurnPersistence = Boolean(proof.thread_id &&
3950
+ proof.latest_turn_id &&
3951
+ proof.latest_session_id &&
3952
+ sessionLogThreadId === proof.thread_id &&
3953
+ sessionLogTurnId === proof.latest_turn_id &&
3954
+ sessionLogSessionId === proof.latest_session_id);
3955
+ const residentResumeSourceThreadId = normalizeOptionalString(proof.resident_session?.source_thread_id) ?? null;
3956
+ const recordedResumeSourceThreadId = normalizeOptionalString(proof.resume_source_thread_id) ?? null;
3957
+ const inRunResumeRequested = appserverIntended && proof.turn_count > 1;
3958
+ const supervisionCommand = residentResumeSourceThreadId || recordedResumeSourceThreadId || proof.turn_count > 1
3959
+ ? 'codex_exec_resume'
3960
+ : 'codex_exec';
3961
+ const resumeSourceThreadId = residentResumeSourceThreadId ?? recordedResumeSourceThreadId;
3962
+ const resumeRequested = Boolean(residentResumeSourceThreadId) || inRunResumeRequested;
3963
+ const resumeThreadMatches = resumeRequested &&
3964
+ proof.thread_id !== null &&
3965
+ resumeSourceThreadId !== null &&
3966
+ proof.thread_id === resumeSourceThreadId;
3967
+ const resumeThreadMismatch = Boolean(resumeSourceThreadId) &&
3968
+ proof.thread_id !== null &&
3969
+ proof.thread_id !== resumeSourceThreadId;
3970
+ const resumePersistedTurnObserved = resumeThreadMatches && hasTurnPersistence;
3971
+ return {
3972
+ selected_runtime: selectedRuntime,
3973
+ supervision_command: supervisionCommand,
3974
+ appserver_session_id: appserverSelected ? selectedRuntime.runtime_session_id : null,
3975
+ thread_id: proof.thread_id,
3976
+ latest_turn_id: proof.latest_turn_id,
3977
+ latest_session_id: proof.latest_session_id,
3978
+ session_log_thread_id: sessionLogThreadId,
3979
+ session_log_turn_id: sessionLogTurnId,
3980
+ session_log_session_id: sessionLogSessionId,
3981
+ sticky_environment_id: stickyEnvironmentId,
3982
+ sticky_environment_status: appserverIntended
3983
+ ? stickyEnvironmentId
3984
+ ? 'proven'
3985
+ : 'blocked'
3986
+ : 'not_applicable',
3987
+ sticky_environment_blocker: appserverIntended && !stickyEnvironmentId
3988
+ ? 'configured_environment_id_missing'
3989
+ : null,
3990
+ turn_persistence_status: appserverIntended
3991
+ ? hasTurnPersistence
3992
+ ? 'proven'
3993
+ : 'blocked'
3994
+ : 'not_applicable',
3995
+ turn_persistence_source: appserverIntended && hasTurnPersistence ? 'session_log_hydration' : null,
3996
+ turn_persistence_blocker: appserverIntended && !hasTurnPersistence
3997
+ ? 'session_log_hydration_missing'
3998
+ : null,
3999
+ pagination_status: appserverIntended ? 'blocked' : 'not_applicable',
4000
+ pagination_blocker: appserverIntended ? 'appserver_pagination_probe_not_implemented' : null,
4001
+ resume_status: appserverIntended
4002
+ ? resumeRequested
4003
+ ? resumePersistedTurnObserved
4004
+ ? 'proven'
4005
+ : 'blocked'
4006
+ : 'not_requested'
4007
+ : 'not_applicable',
4008
+ resume_source_thread_id: resumeSourceThreadId,
4009
+ resume_observed_thread_id: resumeRequested ? proof.thread_id : null,
4010
+ resume_blocker: appserverIntended && resumeRequested && resumeThreadMismatch
4011
+ ? 'guarded_resume_thread_mismatch'
4012
+ : appserverIntended && resumeRequested && !resumeSourceThreadId
4013
+ ? 'resume_source_thread_id_missing'
4014
+ : appserverIntended && resumeRequested && !proof.thread_id
4015
+ ? 'resume_thread_id_missing'
4016
+ : appserverIntended && resumeRequested && !resumePersistedTurnObserved
4017
+ ? 'resume_session_log_hydration_missing'
4018
+ : null,
4019
+ fork_status: appserverIntended ? 'blocked' : 'not_applicable',
4020
+ fork_blocker: appserverIntended ? 'appserver_fork_probe_not_implemented' : null,
4021
+ jsonl_truth_retained: true,
4022
+ session_log_truth_retained: appserverSelected,
4023
+ updated_at: proof.updated_at ?? null
4024
+ };
4025
+ }
3536
4026
  async function resolveProviderLinearWorkerRuntimeContext(env, repoRoot, runId) {
3537
4027
  const requestedMode = parseRuntimeMode(env.CODEX_ORCHESTRATOR_RUNTIME_MODE_ACTIVE ?? env.CODEX_ORCHESTRATOR_RUNTIME_MODE ?? null);
3538
4028
  return await createRuntimeCodexCommandContext({
@@ -3793,7 +4283,10 @@ async function readProviderLinearWorkerChildLanesWithPresence(runDir) {
3793
4283
  ledgerExists: true
3794
4284
  };
3795
4285
  }
3796
- async function hydrateProviderLinearWorkerChildLanesFromActiveManifests(runDir, childLanes, priorProofChildLanes = null) {
4286
+ async function hydrateProviderLinearWorkerChildLanesFromActiveManifests(runDir, childLanes, priorProofChildLanes = null, options = {
4287
+ now: () => new Date().toISOString(),
4288
+ inspectProcess: inspectLocalProviderLinearChildLaneRunnerProcess
4289
+ }) {
3797
4290
  if (childLanes.length === 0) {
3798
4291
  return childLanes;
3799
4292
  }
@@ -3801,9 +4294,12 @@ async function hydrateProviderLinearWorkerChildLanesFromActiveManifests(runDir,
3801
4294
  if (!parent) {
3802
4295
  return childLanes;
3803
4296
  }
3804
- return await Promise.all(childLanes.map(async (childLane) => await hydrateProviderLinearWorkerChildLaneFromActiveManifest(parent, childLane, findMatchingPriorHydratedProviderLinearWorkerChildLane(childLane, priorProofChildLanes))));
4297
+ return await Promise.all(childLanes.map(async (childLane) => await hydrateProviderLinearWorkerChildLaneFromActiveManifest(parent, childLane, findMatchingPriorHydratedProviderLinearWorkerChildLane(childLane, priorProofChildLanes), options)));
3805
4298
  }
3806
- async function readHydratedProviderLinearWorkerChildLanesAndRepairLedger(runDir, priorProofChildLanes = null) {
4299
+ async function readHydratedProviderLinearWorkerChildLanesAndRepairLedger(runDir, priorProofChildLanes = null, options = {
4300
+ now: () => new Date().toISOString(),
4301
+ inspectProcess: inspectLocalProviderLinearChildLaneRunnerProcess
4302
+ }) {
3807
4303
  return await withProviderLinearWorkerChildLanesLock(runDir, async () => {
3808
4304
  const { records: existing, ledgerExists } = await readProviderLinearWorkerChildLanesWithPresence(runDir);
3809
4305
  if (!ledgerExists && existing.length === 0 && Array.isArray(priorProofChildLanes)) {
@@ -3815,7 +4311,7 @@ async function readHydratedProviderLinearWorkerChildLanesAndRepairLedger(runDir,
3815
4311
  }
3816
4312
  return recovered;
3817
4313
  }
3818
- const hydrated = await hydrateProviderLinearWorkerChildLanesFromActiveManifests(runDir, existing, priorProofChildLanes);
4314
+ const hydrated = await hydrateProviderLinearWorkerChildLanesFromActiveManifests(runDir, existing, priorProofChildLanes, options);
3819
4315
  const ledgerRecords = hydrated.map((childLane, index) => preserveProviderLinearWorkerLaunchReservationLedgerIdentity(existing[index] ?? null, childLane));
3820
4316
  if (JSON.stringify(existing) !== JSON.stringify(ledgerRecords)) {
3821
4317
  await writeJsonAtomic(buildChildLanesPath(runDir), ledgerRecords);
@@ -3851,6 +4347,9 @@ function preserveProviderLinearWorkerLaunchReservationLedgerIdentity(existing, h
3851
4347
  existing.task_id !== hydrated.task_id) {
3852
4348
  return hydrated;
3853
4349
  }
4350
+ if (hydrated.stale_invalidation_candidate) {
4351
+ return hydrated;
4352
+ }
3854
4353
  return existing;
3855
4354
  }
3856
4355
  async function readProviderLinearWorkerParentManifestHydrationMetadata(runDir) {
@@ -3875,7 +4374,10 @@ async function readProviderLinearWorkerParentManifestHydrationMetadata(runDir) {
3875
4374
  workspacePath: normalizeOptionalString(parsed.workspace_path) ?? normalizeOptionalString(parsed.workspacePath)
3876
4375
  };
3877
4376
  }
3878
- async function hydrateProviderLinearWorkerChildLaneFromActiveManifest(parent, childLane, priorHydratedChildLane = null) {
4377
+ async function hydrateProviderLinearWorkerChildLaneFromActiveManifest(parent, childLane, priorHydratedChildLane = null, options = {
4378
+ now: () => new Date().toISOString(),
4379
+ inspectProcess: inspectLocalProviderLinearChildLaneRunnerProcess
4380
+ }) {
3879
4381
  if (isProviderLinearWorkerRetiredChildLanePlaceholder(childLane)) {
3880
4382
  return retireProviderLinearWorkerChildLanePlaceholder(childLane);
3881
4383
  }
@@ -3888,8 +4390,8 @@ async function hydrateProviderLinearWorkerChildLaneFromActiveManifest(parent, ch
3888
4390
  }
3889
4391
  const reservationPlaceholder = isProviderLinearWorkerChildLaneReservationPlaceholder(childLane);
3890
4392
  const candidate = reservationPlaceholder
3891
- ? await findMatchingProviderLinearWorkerChildLaneManifest(parent, childLane, childCliDir)
3892
- : await readProviderLinearWorkerChildLaneManifestCandidate(parent, childLane, childCliDir, resolveProviderLinearWorkerChildLanePath(childLane.manifest_path, childLane.workspace_path ?? parent.workspacePath) ?? join(childCliDir, childLane.run_id, 'manifest.json'));
4393
+ ? await findMatchingProviderLinearWorkerChildLaneManifest(parent, childLane, childCliDir, options, priorHydratedChildLane)
4394
+ : await readProviderLinearWorkerChildLaneManifestCandidate(parent, childLane, childCliDir, resolveProviderLinearWorkerChildLanePath(childLane.manifest_path, childLane.workspace_path ?? parent.workspacePath) ?? join(childCliDir, childLane.run_id, 'manifest.json'), options, priorHydratedChildLane);
3893
4395
  if (!candidate) {
3894
4396
  return childLane;
3895
4397
  }
@@ -3923,7 +4425,24 @@ async function hydrateProviderLinearWorkerChildLaneFromActiveManifest(parent, ch
3923
4425
  guardrail_command_count: candidate.guardrailCommandCount,
3924
4426
  lane_workspace_path: candidate.laneWorkspacePath ?? childLane.lane_workspace_path,
3925
4427
  patch_artifact_path: candidate.patchArtifactPath ?? childLane.patch_artifact_path,
3926
- patch_bytes: candidate.patchBytes ?? childLane.patch_bytes
4428
+ patch_bytes: candidate.patchBytes ?? childLane.patch_bytes,
4429
+ runtime_mode: candidate.runtimeMode,
4430
+ runtime_provider: candidate.runtimeProvider,
4431
+ heartbeat_at: candidate.heartbeatAt,
4432
+ heartbeat_stale_after_seconds: candidate.heartbeatStaleAfterSeconds,
4433
+ runner_pid: candidate.runnerPid,
4434
+ runner_started_at: candidate.runnerStartedAt,
4435
+ runner_alive: candidate.runnerAlive,
4436
+ runner_identity_status: candidate.runnerIdentityStatus,
4437
+ runner_identity_reason: candidate.runnerIdentityReason,
4438
+ runner_observed_started_at: candidate.runnerObservedStartedAt,
4439
+ runner_command_line_matches: candidate.runnerCommandLineMatches,
4440
+ runtime_event: candidate.runtimeEvent,
4441
+ runtime_event_at: candidate.runtimeEventAt,
4442
+ appserver_startup_observed: candidate.appserverStartupObserved,
4443
+ appserver_startup_observed_at: candidate.appserverStartupObservedAt,
4444
+ stale_invalidation_candidate: candidate.staleInvalidationCandidate,
4445
+ stale_invalidation_reason: candidate.staleInvalidationReason
3927
4446
  };
3928
4447
  }
3929
4448
  function isProviderLinearWorkerPendingChildLaneRecord(childLane) {
@@ -3938,6 +4457,8 @@ function isProviderLinearWorkerRetiredChildLanePlaceholder(childLane) {
3938
4457
  const summary = normalizeOptionalString(childLane.summary);
3939
4458
  return (childLane.status === 'launching' ||
3940
4459
  isActiveLookingProviderLinearWorkerChildLaneStatus(childLane.status) ||
4460
+ childLane.status === 'stale_invalidation_candidate' ||
4461
+ childLane.stale_invalidation_candidate === true ||
3941
4462
  Boolean(normalizeOptionalString(childLane.in_flight_action)) ||
3942
4463
  Boolean(runId?.startsWith('launching-')) ||
3943
4464
  isActiveLookingProviderLinearWorkerChildLaneSummary(summary));
@@ -4051,7 +4572,7 @@ function resolveProviderLinearWorkerChildLanePath(value, workspacePath) {
4051
4572
  const normalizedWorkspacePath = normalizeOptionalString(workspacePath);
4052
4573
  return normalizedWorkspacePath ? resolve(normalizedWorkspacePath, normalized) : resolve(normalized);
4053
4574
  }
4054
- async function findMatchingProviderLinearWorkerChildLaneManifest(parent, childLane, childCliDir) {
4575
+ async function findMatchingProviderLinearWorkerChildLaneManifest(parent, childLane, childCliDir, options, priorHydratedChildLane = null) {
4055
4576
  let entries;
4056
4577
  try {
4057
4578
  entries = await readdir(childCliDir, { withFileTypes: true });
@@ -4061,7 +4582,7 @@ async function findMatchingProviderLinearWorkerChildLaneManifest(parent, childLa
4061
4582
  }
4062
4583
  const candidates = await Promise.all(entries
4063
4584
  .filter((entry) => entry.isDirectory())
4064
- .map(async (entry) => await readProviderLinearWorkerChildLaneManifestCandidate(parent, childLane, childCliDir, join(childCliDir, entry.name, 'manifest.json'))));
4585
+ .map(async (entry) => await readProviderLinearWorkerChildLaneManifestCandidate(parent, childLane, childCliDir, join(childCliDir, entry.name, 'manifest.json'), options, priorHydratedChildLane)));
4065
4586
  return candidates
4066
4587
  .filter((candidate) => candidate !== null)
4067
4588
  .sort((left, right) => {
@@ -4069,7 +4590,7 @@ async function findMatchingProviderLinearWorkerChildLaneManifest(parent, childLa
4069
4590
  return timestampComparison !== 0 ? timestampComparison : right.runId.localeCompare(left.runId);
4070
4591
  })[0] ?? null;
4071
4592
  }
4072
- async function readProviderLinearWorkerChildLaneManifestCandidate(parent, childLane, childCliDir, manifestPath) {
4593
+ async function readProviderLinearWorkerChildLaneManifestCandidate(parent, childLane, childCliDir, manifestPath, options, priorHydratedChildLane = null) {
4073
4594
  let parsed;
4074
4595
  try {
4075
4596
  parsed = JSON.parse(await readFile(manifestPath, 'utf8'));
@@ -4136,33 +4657,485 @@ async function readProviderLinearWorkerChildLaneManifestCandidate(parent, childL
4136
4657
  return null;
4137
4658
  }
4138
4659
  const proofMetadata = await readProviderLinearWorkerChildLaneProofHydrationMetadata(parent, childLane, runId, manifestArtifactRoot, workspacePath);
4660
+ const runtimeDiagnostics = await readProviderLinearWorkerChildLaneRuntimeDiagnostics(parent, childLane, runId, manifestArtifactRoot);
4661
+ const runtimeMode = normalizeOptionalString(runtimeDiagnostics?.provider_linear_child_lane_runtime_selected_mode) ??
4662
+ normalizeOptionalString(runtimeDiagnostics?.runtime_mode) ??
4663
+ normalizeOptionalString(parsed.runtime_mode);
4664
+ const runtimeProvider = normalizeOptionalString(runtimeDiagnostics?.provider_linear_child_lane_runtime_provider) ??
4665
+ normalizeOptionalString(runtimeDiagnostics?.runtime_provider) ??
4666
+ normalizeOptionalString(parsed.runtime_provider);
4667
+ const heartbeatAt = normalizeOptionalString(parsed.heartbeat_at);
4668
+ const heartbeatStaleAfterSeconds = normalizeOptionalInteger(parsed.heartbeat_stale_after_seconds);
4669
+ const rawRunnerPid = normalizeOptionalInteger(runtimeDiagnostics?.provider_linear_child_lane_runner_pid ?? parsed.provider_linear_child_lane_runner_pid);
4670
+ const runnerPid = rawRunnerPid !== null && rawRunnerPid > 0 ? rawRunnerPid : null;
4671
+ const runnerStartedAt = normalizeOptionalString(runtimeDiagnostics?.provider_linear_child_lane_runner_started_at ??
4672
+ parsed.provider_linear_child_lane_runner_started_at);
4673
+ const runnerIdentity = await inspectProviderLinearWorkerChildLaneRunnerIdentity({
4674
+ runnerPid,
4675
+ runnerStartedAt,
4676
+ options
4677
+ });
4678
+ const runnerAlive = runnerIdentity.alive;
4679
+ const runtimeEvent = normalizeOptionalString(runtimeDiagnostics?.provider_linear_child_lane_runtime_event ?? parsed.provider_linear_child_lane_runtime_event);
4680
+ const runtimeEventAt = normalizeOptionalString(runtimeDiagnostics?.provider_linear_child_lane_runtime_event_at ?? parsed.provider_linear_child_lane_runtime_event_at);
4681
+ const appserverStartupObserved = runtimeEvent === 'appserver_startup_observed' ||
4682
+ runtimeDiagnostics?.provider_linear_child_lane_appserver_startup_observed === true ||
4683
+ parsed.provider_linear_child_lane_appserver_startup_observed === true;
4684
+ const appserverStartupObservedAt = normalizeOptionalString(runtimeDiagnostics?.provider_linear_child_lane_appserver_startup_observed_at ??
4685
+ parsed.provider_linear_child_lane_appserver_startup_observed_at ??
4686
+ (runtimeEvent === 'appserver_startup_observed' ? runtimeEventAt : null));
4139
4687
  const successfulStatus = isSuccessfulProviderLinearWorkerChildLaneStatus(status);
4688
+ const patchArtifactPath = proofMetadata?.patchArtifactPath ?? null;
4140
4689
  const patchBytes = proofMetadata?.patchBytes ?? null;
4141
- const patchReady = Boolean(proofMetadata?.patchArtifactPath && patchBytes !== null && patchBytes > 0);
4142
- const hydratedStatus = successfulStatus && !patchReady ? 'in_progress' : status;
4690
+ const proofOutputReady = Boolean(patchArtifactPath);
4691
+ const patchReady = Boolean(patchArtifactPath && patchBytes !== null && patchBytes > 0);
4692
+ const diagnosticStatus = successfulStatus && !proofOutputReady ? 'in_progress' : status;
4693
+ const staleDiagnostic = resolveProviderLinearWorkerChildLanePostStartupNoOutputDiagnostic({
4694
+ childLane,
4695
+ status: diagnosticStatus,
4696
+ runtimeMode,
4697
+ heartbeatAt,
4698
+ heartbeatStaleAfterSeconds,
4699
+ runnerPid,
4700
+ runnerStartedAt,
4701
+ runnerAlive,
4702
+ runnerIdentityStatus: runnerIdentity.status,
4703
+ runnerIdentityReason: runnerIdentity.reason,
4704
+ runtimeEvent,
4705
+ runtimeEventAt,
4706
+ appserverStartupObserved,
4707
+ appserverStartupObservedAt,
4708
+ proofOutputReady,
4709
+ now: options.now
4710
+ });
4711
+ const hydratedStatus = staleDiagnostic
4712
+ ? 'stale_invalidation_candidate'
4713
+ : diagnosticStatus;
4143
4714
  const manifestTimestamp = latestProviderLinearWorkerChildLaneManifestTimestamp(parsed);
4144
4715
  const summaryRecordedAt = providerLinearWorkerChildLaneSummaryRecordedAt(parsed, proofMetadata?.updatedAt ?? null, startedAt);
4716
+ const summary = staleDiagnostic?.summary ??
4717
+ (successfulStatus && !patchReady
4718
+ ? patchBytes === 0
4719
+ ? 'Child lane completed without patch output; waiting for parent ledger decision.'
4720
+ : 'Child lane completed; waiting for patch proof metadata.'
4721
+ : stripNonApplicableGuardrailSummaryLines(parsed, normalizeOptionalString(parsed.summary)) ??
4722
+ normalizeOptionalString(parsed.status_detail));
4723
+ const priorStaleSummaryRecordedAt = staleDiagnostic &&
4724
+ priorHydratedChildLane?.stale_invalidation_candidate === true &&
4725
+ priorHydratedChildLane.stale_invalidation_reason === staleDiagnostic.reason
4726
+ ? priorHydratedChildLane.summary_recorded_at
4727
+ : null;
4728
+ const currentStaleSummaryRecordedAt = staleDiagnostic &&
4729
+ childLane.stale_invalidation_candidate === true &&
4730
+ childLane.stale_invalidation_reason === staleDiagnostic.reason
4731
+ ? childLane.summary_recorded_at
4732
+ : null;
4733
+ const staleSummaryRecordedAt = staleDiagnostic
4734
+ ? currentStaleSummaryRecordedAt ?? priorStaleSummaryRecordedAt ?? staleDiagnostic.observedAt
4735
+ : null;
4145
4736
  return {
4146
4737
  runId,
4147
4738
  status: hydratedStatus,
4148
4739
  manifestPath,
4149
4740
  artifactRoot: manifestArtifactRoot,
4150
4741
  logPath,
4151
- summary: successfulStatus && !patchReady
4152
- ? patchBytes === 0
4153
- ? 'Child lane completed without patch output; waiting for parent ledger decision.'
4154
- : 'Child lane completed; waiting for patch proof metadata.'
4155
- : stripNonApplicableGuardrailSummaryLines(parsed, normalizeOptionalString(parsed.summary)) ??
4156
- normalizeOptionalString(parsed.status_detail),
4742
+ summary,
4157
4743
  startedAt,
4158
4744
  updatedAt: manifestTimestamp,
4159
4745
  laneWorkspacePath: proofMetadata?.laneWorkspacePath ?? null,
4160
- patchArtifactPath: proofMetadata?.patchArtifactPath ?? null,
4746
+ patchArtifactPath,
4161
4747
  patchBytes: proofMetadata?.patchBytes ?? null,
4162
4748
  guardrailsRequired: resolveGuardrailsRequiredForManifest(parsed),
4163
4749
  guardrailsRequiredSource: resolveGuardrailsRequiredSourceForManifest(parsed),
4164
4750
  guardrailCommandCount: countGuardrailCommands(parsed),
4165
- summaryRecordedAt
4751
+ summaryRecordedAt: staleSummaryRecordedAt ?? summaryRecordedAt,
4752
+ runtimeMode,
4753
+ runtimeProvider,
4754
+ heartbeatAt,
4755
+ heartbeatStaleAfterSeconds,
4756
+ runnerPid,
4757
+ runnerStartedAt,
4758
+ runnerAlive,
4759
+ runnerIdentityStatus: runnerIdentity.status,
4760
+ runnerIdentityReason: runnerIdentity.reason,
4761
+ runnerObservedStartedAt: runnerIdentity.observedStartedAt,
4762
+ runnerCommandLineMatches: runnerIdentity.commandLineMatches,
4763
+ runtimeEvent,
4764
+ runtimeEventAt,
4765
+ appserverStartupObserved,
4766
+ appserverStartupObservedAt,
4767
+ staleInvalidationCandidate: staleDiagnostic ? true : null,
4768
+ staleInvalidationReason: staleDiagnostic?.reason ?? null
4769
+ };
4770
+ }
4771
+ async function readProviderLinearWorkerChildLaneRuntimeDiagnostics(parent, childLane, runId, artifactRoot) {
4772
+ let parsed;
4773
+ try {
4774
+ parsed = JSON.parse(await readFile(join(artifactRoot, PROVIDER_LINEAR_CHILD_LANE_DIAGNOSTICS_FILENAME), 'utf8'));
4775
+ }
4776
+ catch {
4777
+ return null;
4778
+ }
4779
+ if (!isRecord(parsed)) {
4780
+ return null;
4781
+ }
4782
+ if (normalizeOptionalString(parsed.parent_run_id) !== parent.runId ||
4783
+ normalizeOptionalString(parsed.issue_id) !== childLane.issue_id ||
4784
+ normalizeOptionalString(parsed.issue_identifier) !== childLane.issue_identifier ||
4785
+ normalizeOptionalString(parsed.task_id) !== childLane.task_id ||
4786
+ normalizeOptionalString(parsed.run_id) !== runId) {
4787
+ return null;
4788
+ }
4789
+ if (parent.issueId && normalizeOptionalString(parsed.issue_id) !== parent.issueId) {
4790
+ return null;
4791
+ }
4792
+ if (parent.issueIdentifier && normalizeOptionalString(parsed.issue_identifier) !== parent.issueIdentifier) {
4793
+ return null;
4794
+ }
4795
+ const stream = normalizeOptionalString(parsed.stream);
4796
+ if (stream && stream !== childLane.stream) {
4797
+ return null;
4798
+ }
4799
+ return parsed;
4800
+ }
4801
+ async function inspectProviderLinearWorkerChildLaneRunnerIdentity(input) {
4802
+ if (input.runnerPid === null) {
4803
+ return {
4804
+ alive: null,
4805
+ status: 'not_recorded',
4806
+ reason: 'runner_pid_not_recorded',
4807
+ observedStartedAt: null,
4808
+ commandLineMatches: null
4809
+ };
4810
+ }
4811
+ const inspection = await readProviderLinearWorkerChildLaneRunnerProcessInspection(input.runnerPid, input.options);
4812
+ return resolveProviderLinearWorkerChildLaneRunnerIdentity({
4813
+ runnerStartedAt: input.runnerStartedAt,
4814
+ inspection
4815
+ });
4816
+ }
4817
+ async function readProviderLinearWorkerChildLaneRunnerProcessInspection(pid, options) {
4818
+ if (options.inspectProcess) {
4819
+ try {
4820
+ return normalizeProviderLinearWorkerProcessInspection(await options.inspectProcess(pid));
4821
+ }
4822
+ catch (error) {
4823
+ return {
4824
+ alive: null,
4825
+ startedAt: null,
4826
+ commandLine: null,
4827
+ error: providerLinearWorkerErrorMessage(error)
4828
+ };
4829
+ }
4830
+ }
4831
+ if (options.isProcessAlive) {
4832
+ return {
4833
+ alive: options.isProcessAlive(pid),
4834
+ startedAt: null,
4835
+ commandLine: null,
4836
+ error: null
4837
+ };
4838
+ }
4839
+ return await inspectLocalProviderLinearChildLaneRunnerProcess(pid);
4840
+ }
4841
+ function normalizeProviderLinearWorkerProcessInspection(value) {
4842
+ if (!isRecord(value)) {
4843
+ return {
4844
+ alive: null,
4845
+ startedAt: null,
4846
+ commandLine: null,
4847
+ error: 'process_identity_inspection_invalid'
4848
+ };
4849
+ }
4850
+ return {
4851
+ alive: typeof value.alive === 'boolean' ? value.alive : null,
4852
+ startedAt: normalizeOptionalString(value.startedAt),
4853
+ commandLine: normalizeOptionalString(value.commandLine),
4854
+ error: normalizeOptionalString(value.error)
4855
+ };
4856
+ }
4857
+ function resolveProviderLinearWorkerChildLaneRunnerIdentity(input) {
4858
+ const commandLineMatches = resolveProviderLinearChildLaneRunnerCommandLineMatch(input.inspection.commandLine);
4859
+ const recordedStartedMs = input.runnerStartedAt ? Date.parse(input.runnerStartedAt) : Number.NaN;
4860
+ const recordedStartIdentityError = !input.runnerStartedAt
4861
+ ? 'runner_started_at_missing'
4862
+ : Number.isFinite(recordedStartedMs)
4863
+ ? null
4864
+ : 'runner_started_at_unparseable';
4865
+ if (input.inspection.alive === false) {
4866
+ if (recordedStartIdentityError) {
4867
+ return {
4868
+ alive: null,
4869
+ status: 'ambiguous',
4870
+ reason: recordedStartIdentityError,
4871
+ observedStartedAt: input.inspection.startedAt,
4872
+ commandLineMatches
4873
+ };
4874
+ }
4875
+ return {
4876
+ alive: false,
4877
+ status: 'not_live',
4878
+ reason: 'runner_pid_not_live',
4879
+ observedStartedAt: input.inspection.startedAt,
4880
+ commandLineMatches
4881
+ };
4882
+ }
4883
+ if (input.inspection.alive !== true) {
4884
+ const lookupFailureReason = input.inspection.error
4885
+ ? `process_identity_lookup_failed:${truncateProviderLinearWorkerDiagnosticReason(input.inspection.error)}`
4886
+ : 'process_identity_lookup_unknown';
4887
+ return {
4888
+ alive: null,
4889
+ status: 'ambiguous',
4890
+ reason: recordedStartIdentityError ?? lookupFailureReason,
4891
+ observedStartedAt: input.inspection.startedAt,
4892
+ commandLineMatches
4893
+ };
4894
+ }
4895
+ if (commandLineMatches !== true) {
4896
+ const reason = commandLineMatches === false
4897
+ ? 'process_command_line_mismatch'
4898
+ : input.inspection.error
4899
+ ? `process_identity_lookup_failed:${truncateProviderLinearWorkerDiagnosticReason(input.inspection.error)}`
4900
+ : 'process_command_line_unavailable';
4901
+ return {
4902
+ alive: null,
4903
+ status: commandLineMatches === false ? 'pid_reuse_suspected' : 'ambiguous',
4904
+ reason,
4905
+ observedStartedAt: input.inspection.startedAt,
4906
+ commandLineMatches
4907
+ };
4908
+ }
4909
+ if (recordedStartIdentityError) {
4910
+ return {
4911
+ alive: null,
4912
+ status: 'ambiguous',
4913
+ reason: recordedStartIdentityError,
4914
+ observedStartedAt: input.inspection.startedAt,
4915
+ commandLineMatches
4916
+ };
4917
+ }
4918
+ if (!input.inspection.startedAt) {
4919
+ return {
4920
+ alive: null,
4921
+ status: 'ambiguous',
4922
+ reason: input.inspection.error
4923
+ ? `process_start_time_unavailable:${truncateProviderLinearWorkerDiagnosticReason(input.inspection.error)}`
4924
+ : 'process_start_time_unavailable',
4925
+ observedStartedAt: null,
4926
+ commandLineMatches
4927
+ };
4928
+ }
4929
+ const observedStartedMs = Date.parse(input.inspection.startedAt);
4930
+ if (!Number.isFinite(observedStartedMs)) {
4931
+ return {
4932
+ alive: null,
4933
+ status: 'ambiguous',
4934
+ reason: 'process_start_time_unparseable',
4935
+ observedStartedAt: input.inspection.startedAt,
4936
+ commandLineMatches
4937
+ };
4938
+ }
4939
+ if (observedStartedMs > recordedStartedMs) {
4940
+ return {
4941
+ alive: null,
4942
+ status: 'pid_reuse_suspected',
4943
+ reason: 'process_started_after_recorded_runner_start',
4944
+ observedStartedAt: input.inspection.startedAt,
4945
+ commandLineMatches
4946
+ };
4947
+ }
4948
+ if (observedStartedMs < recordedStartedMs - PROVIDER_LINEAR_CHILD_LANE_RUNNER_IDENTITY_START_BEFORE_TOLERANCE_MS) {
4949
+ return {
4950
+ alive: null,
4951
+ status: 'pid_reuse_suspected',
4952
+ reason: 'process_start_time_mismatch',
4953
+ observedStartedAt: input.inspection.startedAt,
4954
+ commandLineMatches
4955
+ };
4956
+ }
4957
+ return {
4958
+ alive: true,
4959
+ status: 'matched',
4960
+ reason: 'process_identity_matched',
4961
+ observedStartedAt: input.inspection.startedAt,
4962
+ commandLineMatches
4963
+ };
4964
+ }
4965
+ async function inspectLocalProviderLinearChildLaneRunnerProcess(pid) {
4966
+ if (!isLocalProcessAlive(pid)) {
4967
+ return {
4968
+ alive: false,
4969
+ startedAt: null,
4970
+ commandLine: null,
4971
+ error: null
4972
+ };
4973
+ }
4974
+ const [startedAtResult, commandLineResult] = await Promise.all([
4975
+ readLocalProcessPsOutput(pid, 'lstart='),
4976
+ readLocalProcessCommandLine(pid)
4977
+ ]);
4978
+ if (startedAtResult.output === null && commandLineResult.output === null && !isLocalProcessAlive(pid)) {
4979
+ return {
4980
+ alive: false,
4981
+ startedAt: null,
4982
+ commandLine: null,
4983
+ error: 'process_exited_before_identity_lookup'
4984
+ };
4985
+ }
4986
+ const startedAt = startedAtResult.output ? parseLocalProcessStartedAt(startedAtResult.output) : null;
4987
+ const startError = startedAtResult.output && !startedAt
4988
+ ? `process_start_time_unparseable:${startedAtResult.output}`
4989
+ : startedAtResult.error;
4990
+ const error = [startError, commandLineResult.error]
4991
+ .map((value) => normalizeOptionalString(value))
4992
+ .filter((value) => Boolean(value))
4993
+ .join('; ');
4994
+ return {
4995
+ alive: true,
4996
+ startedAt,
4997
+ commandLine: commandLineResult.output,
4998
+ error: error || null
4999
+ };
5000
+ }
5001
+ async function readLocalProcessCommandLine(pid) {
5002
+ const commandResult = await readLocalProcessPsOutput(pid, 'command=');
5003
+ if (commandResult.output !== null) {
5004
+ return commandResult;
5005
+ }
5006
+ const argsResult = await readLocalProcessPsOutput(pid, 'args=');
5007
+ if (argsResult.output !== null) {
5008
+ return argsResult;
5009
+ }
5010
+ return {
5011
+ output: null,
5012
+ error: [commandResult.error, argsResult.error]
5013
+ .map((value) => normalizeOptionalString(value))
5014
+ .filter((value) => Boolean(value))
5015
+ .join('; ') || null
5016
+ };
5017
+ }
5018
+ async function readLocalProcessPsOutput(pid, outputColumn) {
5019
+ return await new Promise((resolvePromise) => {
5020
+ let stdout = '';
5021
+ let stderr = '';
5022
+ let completed = false;
5023
+ let timedOut = false;
5024
+ let timer = null;
5025
+ const child = spawn('ps', ['-ww', '-p', String(pid), '-o', outputColumn], {
5026
+ stdio: ['ignore', 'pipe', 'pipe']
5027
+ });
5028
+ const finish = (result) => {
5029
+ if (completed) {
5030
+ return;
5031
+ }
5032
+ completed = true;
5033
+ if (timer) {
5034
+ clearTimeout(timer);
5035
+ }
5036
+ resolvePromise(result);
5037
+ };
5038
+ timer = setTimeout(() => {
5039
+ timedOut = true;
5040
+ child.kill('SIGKILL');
5041
+ }, PROVIDER_LINEAR_CHILD_LANE_RUNNER_PROCESS_LOOKUP_TIMEOUT_MS);
5042
+ child.stdout?.on('data', (chunk) => {
5043
+ stdout += String(chunk);
5044
+ });
5045
+ child.stderr?.on('data', (chunk) => {
5046
+ stderr += String(chunk);
5047
+ });
5048
+ child.on('error', (error) => {
5049
+ finish({
5050
+ output: null,
5051
+ error: providerLinearWorkerErrorMessage(error)
5052
+ });
5053
+ });
5054
+ child.on('close', (code) => {
5055
+ if (timedOut) {
5056
+ finish({
5057
+ output: null,
5058
+ error: 'process_identity_lookup_timeout'
5059
+ });
5060
+ return;
5061
+ }
5062
+ const output = normalizeOptionalString(stdout);
5063
+ if (code === 0 && output) {
5064
+ finish({
5065
+ output,
5066
+ error: null
5067
+ });
5068
+ return;
5069
+ }
5070
+ finish({
5071
+ output: null,
5072
+ error: normalizeOptionalString(stderr) ?? `ps exited with code ${code ?? 'unknown'}`
5073
+ });
5074
+ });
5075
+ });
5076
+ }
5077
+ function parseLocalProcessStartedAt(value) {
5078
+ const normalized = normalizeOptionalString(value);
5079
+ if (!normalized) {
5080
+ return null;
5081
+ }
5082
+ const parsed = Date.parse(normalized);
5083
+ return Number.isFinite(parsed) ? new Date(parsed).toISOString() : null;
5084
+ }
5085
+ function resolveProviderLinearChildLaneRunnerCommandLineMatch(commandLine) {
5086
+ const normalized = normalizeOptionalString(commandLine);
5087
+ if (!normalized) {
5088
+ return null;
5089
+ }
5090
+ return normalized.includes('providerLinearChildLaneRunner');
5091
+ }
5092
+ function truncateProviderLinearWorkerDiagnosticReason(value) {
5093
+ const normalized = normalizeOptionalString(value);
5094
+ if (!normalized) {
5095
+ return 'unknown';
5096
+ }
5097
+ return normalized.length > 160 ? `${normalized.slice(0, 157)}...` : normalized;
5098
+ }
5099
+ function providerLinearWorkerErrorMessage(error) {
5100
+ return normalizeOptionalString(error?.message) ?? String(error);
5101
+ }
5102
+ function resolveProviderLinearWorkerChildLanePostStartupNoOutputDiagnostic(input) {
5103
+ if (!isActiveLookingProviderLinearWorkerChildLaneStatus(input.status) ||
5104
+ input.runtimeMode !== 'appserver' ||
5105
+ input.appserverStartupObserved !== true ||
5106
+ input.proofOutputReady) {
5107
+ return null;
5108
+ }
5109
+ const heartbeatMs = input.heartbeatAt ? Date.parse(input.heartbeatAt) : Number.NaN;
5110
+ const now = input.now();
5111
+ const nowMs = Date.parse(now);
5112
+ if (!Number.isFinite(heartbeatMs) || !Number.isFinite(nowMs)) {
5113
+ return null;
5114
+ }
5115
+ const staleAfterMs = Math.max(PROVIDER_LINEAR_CHILD_LANE_POST_STARTUP_NO_OUTPUT_MIN_STALE_MS, (input.heartbeatStaleAfterSeconds ?? 0) * 1000);
5116
+ if (nowMs - heartbeatMs <= staleAfterMs) {
5117
+ return null;
5118
+ }
5119
+ if (input.runnerAlive !== false || input.runnerIdentityStatus !== 'not_live') {
5120
+ return null;
5121
+ }
5122
+ const stream = input.childLane.stream || input.childLane.task_id || input.childLane.run_id;
5123
+ const runnerState = input.runnerPid !== null
5124
+ ? `providerLinearChildLaneRunner pid ${input.runnerPid} is not live` +
5125
+ (input.runnerStartedAt ? ` for recorded start ${input.runnerStartedAt}` : '')
5126
+ : 'providerLinearChildLaneRunner pid was not recorded';
5127
+ const identityState = input.runnerIdentityReason
5128
+ ? ` Runner identity proof: ${input.runnerIdentityReason}.`
5129
+ : '';
5130
+ const startupAt = input.appserverStartupObservedAt ?? input.runtimeEventAt ?? 'unknown time';
5131
+ const reason = 'post_startup_no_output_heartbeat_stale_runner_dead';
5132
+ return {
5133
+ observedAt: now,
5134
+ reason,
5135
+ summary: `Child lane ${stream} is a stale invalidation candidate: appserver startup was observed at ${startupAt}, ` +
5136
+ `manifest heartbeat stopped at ${input.heartbeatAt}, ${runnerState}, and no proof/patch output is present. ` +
5137
+ identityState +
5138
+ 'Invalidate the lane and rerun parent-owned validation, or relaunch under CLI for scoped diagnosis.'
4166
5139
  };
4167
5140
  }
4168
5141
  async function readProviderLinearWorkerChildLaneProofHydrationMetadata(parent, childLane, runId, artifactRoot, workspacePath) {
@@ -4226,7 +5199,8 @@ function latestProviderLinearWorkerIsoTimestamp(...values) {
4226
5199
  return normalized[normalized.length - 1] ?? null;
4227
5200
  }
4228
5201
  function buildProviderLinearWorkerHydratedChildLaneSummary(childLane, candidate) {
4229
- if (candidate.summary?.startsWith('Child lane completed')) {
5202
+ if (candidate.summary &&
5203
+ (candidate.status === 'stale_invalidation_candidate' || candidate.summary.startsWith('Child lane completed'))) {
4230
5204
  return candidate.summary;
4231
5205
  }
4232
5206
  const label = childLane.stream || childLane.task_id || candidate.runId;
@@ -4454,6 +5428,25 @@ function normalizeProviderLinearWorkerChildLaneRecord(value) {
4454
5428
  lane_workspace_path: normalizeOptionalString(value.lane_workspace_path),
4455
5429
  patch_artifact_path: normalizeOptionalString(value.patch_artifact_path),
4456
5430
  patch_bytes: normalizeOptionalInteger(value.patch_bytes),
5431
+ runtime_mode: normalizeOptionalString(value.runtime_mode),
5432
+ runtime_provider: normalizeOptionalString(value.runtime_provider),
5433
+ heartbeat_at: normalizeOptionalString(value.heartbeat_at),
5434
+ heartbeat_stale_after_seconds: normalizeOptionalInteger(value.heartbeat_stale_after_seconds),
5435
+ runner_pid: normalizeOptionalInteger(value.runner_pid),
5436
+ runner_started_at: normalizeOptionalString(value.runner_started_at),
5437
+ runner_alive: typeof value.runner_alive === 'boolean' ? value.runner_alive : null,
5438
+ runner_identity_status: normalizeProviderLinearWorkerChildLaneRunnerIdentityStatus(value.runner_identity_status),
5439
+ runner_identity_reason: normalizeOptionalString(value.runner_identity_reason),
5440
+ runner_observed_started_at: normalizeOptionalString(value.runner_observed_started_at),
5441
+ runner_command_line_matches: typeof value.runner_command_line_matches === 'boolean' ? value.runner_command_line_matches : null,
5442
+ runtime_event: normalizeOptionalString(value.runtime_event),
5443
+ runtime_event_at: normalizeOptionalString(value.runtime_event_at),
5444
+ appserver_startup_observed: typeof value.appserver_startup_observed === 'boolean' ? value.appserver_startup_observed : null,
5445
+ appserver_startup_observed_at: normalizeOptionalString(value.appserver_startup_observed_at),
5446
+ stale_invalidation_candidate: typeof value.stale_invalidation_candidate === 'boolean'
5447
+ ? value.stale_invalidation_candidate
5448
+ : null,
5449
+ stale_invalidation_reason: normalizeOptionalString(value.stale_invalidation_reason),
4457
5450
  decision,
4458
5451
  in_flight_action: inFlightAction,
4459
5452
  in_flight_started_at: normalizeOptionalString(value.in_flight_started_at),
@@ -4503,6 +5496,24 @@ function normalizeChildLaneInFlightAction(value) {
4503
5496
  ? value
4504
5497
  : null;
4505
5498
  }
5499
+ function normalizeProviderLinearWorkerChildLaneRunnerIdentityStatus(value) {
5500
+ return value === 'not_recorded' ||
5501
+ value === 'not_live' ||
5502
+ value === 'matched' ||
5503
+ value === 'ambiguous' ||
5504
+ value === 'pid_reuse_suspected'
5505
+ ? value
5506
+ : null;
5507
+ }
5508
+ function isLocalProcessAlive(pid) {
5509
+ try {
5510
+ process.kill(pid, 0);
5511
+ return true;
5512
+ }
5513
+ catch (error) {
5514
+ return error?.code === 'EPERM';
5515
+ }
5516
+ }
4506
5517
  async function resolveProviderWorkerRunLocation(currentManifestPath) {
4507
5518
  try {
4508
5519
  const canonicalManifestPath = await realpath(currentManifestPath);
@@ -4926,6 +5937,7 @@ async function writeProofSnapshot(deps, runDir, auditPath, proof, env = process.
4926
5937
  const childLanes = await readHydratedProviderLinearWorkerChildLanesAndRepairLedger(runDir, proof.child_lanes);
4927
5938
  const proofWithHydratedSources = {
4928
5939
  ...proof,
5940
+ runtime: normalizeProviderLinearWorkerRuntimeProofIfRelevant(proof),
4929
5941
  linear_audit: linearAudit,
4930
5942
  child_streams: childStreams,
4931
5943
  child_lanes: childLanes,
@@ -4940,6 +5952,7 @@ async function writeProofSnapshot(deps, runDir, auditPath, proof, env = process.
4940
5952
  };
4941
5953
  const hydratedProof = {
4942
5954
  ...proofWithHydratedSources,
5955
+ appserver_supervision: buildProviderLinearWorkerAppServerSupervisionProofIfRelevant(proofWithHydratedSources),
4943
5956
  progress: deriveProviderLinearWorkerProgressSnapshot({
4944
5957
  proof: proofWithHydratedSources,
4945
5958
  now: deps.now
@@ -4967,9 +5980,14 @@ export async function refreshProviderLinearWorkerProofSnapshot(runDir, auditPath
4967
5980
  const linearBudget = await readSharedLinearBudgetStatus(env).catch(() => null);
4968
5981
  const linearAudit = auditPath ? await summarizeProviderLinearAuditPath(auditPath) : parsed.linear_audit ?? null;
4969
5982
  const childStreams = await readProviderLinearWorkerChildStreams(runDir);
4970
- const childLanes = await readHydratedProviderLinearWorkerChildLanesAndRepairLedger(runDir, parsed.child_lanes);
5983
+ const childLanes = await readHydratedProviderLinearWorkerChildLanesAndRepairLedger(runDir, parsed.child_lanes, {
5984
+ now,
5985
+ isProcessAlive: options.isProcessAlive,
5986
+ inspectProcess: options.inspectProcess
5987
+ });
4971
5988
  const proofWithHydratedSources = {
4972
5989
  ...parsed,
5990
+ runtime: normalizeProviderLinearWorkerRuntimeProofIfRelevant(parsed),
4973
5991
  linear_audit: linearAudit,
4974
5992
  child_streams: childStreams,
4975
5993
  child_lanes: childLanes,
@@ -4992,16 +6010,22 @@ export async function refreshProviderLinearWorkerProofSnapshot(runDir, auditPath
4992
6010
  const proofWithSessionTelemetry = proofWithSessionTelemetryResult.proof;
4993
6011
  const hydratedWithoutUpdatedAt = {
4994
6012
  ...proofWithSessionTelemetry,
6013
+ appserver_supervision: buildProviderLinearWorkerAppServerSupervisionProofIfRelevant(proofWithSessionTelemetry),
4995
6014
  progress: deriveProviderLinearWorkerProgressSnapshot({
4996
6015
  proof: proofWithSessionTelemetry,
4997
6016
  now
4998
6017
  })
4999
6018
  };
5000
- const hydrated = {
6019
+ const nextUpdatedAt = shouldAdvanceProviderLinearWorkerProofUpdatedAt(parsed, hydratedWithoutUpdatedAt, options.updatedAtComparisonScope ?? 'full')
6020
+ ? now()
6021
+ : parsed.updated_at ?? null;
6022
+ const hydratedBase = {
5001
6023
  ...hydratedWithoutUpdatedAt,
5002
- updated_at: shouldAdvanceProviderLinearWorkerProofUpdatedAt(parsed, hydratedWithoutUpdatedAt, options.updatedAtComparisonScope ?? 'full')
5003
- ? now()
5004
- : parsed.updated_at ?? null
6024
+ updated_at: nextUpdatedAt
6025
+ };
6026
+ const hydrated = {
6027
+ ...hydratedBase,
6028
+ appserver_supervision: buildProviderLinearWorkerAppServerSupervisionProofIfRelevant(hydratedBase)
5005
6029
  };
5006
6030
  await writeProof(proofPath, hydrated);
5007
6031
  await writeProviderWorkerSessionLogHydrationState(runDir, proofWithSessionTelemetryResult.hydrationState);
@@ -5088,6 +6112,10 @@ export async function runProviderLinearWorker(env = process.env, dependencyOverr
5088
6112
  latest_turn_id: null,
5089
6113
  latest_session_id: null,
5090
6114
  latest_session_id_source: null,
6115
+ session_log_thread_id: null,
6116
+ session_log_turn_id: null,
6117
+ session_log_session_id: null,
6118
+ resume_source_thread_id: residentSessionSeed?.source_thread_id ?? null,
5091
6119
  turn_count: 0,
5092
6120
  last_event: null,
5093
6121
  last_message: null,
@@ -5095,6 +6123,8 @@ export async function runProviderLinearWorker(env = process.env, dependencyOverr
5095
6123
  current_turn_activity: null,
5096
6124
  tokens: buildEmptyProviderLinearWorkerTokenUsage(),
5097
6125
  rate_limits: null,
6126
+ runtime: buildProviderLinearWorkerRuntimeProof(runtimeContext.runtime),
6127
+ appserver_supervision: null,
5098
6128
  auth_provenance: buildProviderWorkerRuntimeAuthProvenance({
5099
6129
  env: childEnv,
5100
6130
  runtime: runtimeContext.runtime,
@@ -5236,6 +6266,9 @@ export async function runProviderLinearWorker(env = process.env, dependencyOverr
5236
6266
  let liveStdoutBuffer = '';
5237
6267
  let liveProofSignature = null;
5238
6268
  const liveParseState = buildEmptyProviderLinearWorkerJsonlParseResult();
6269
+ let liveSessionLogThreadId = null;
6270
+ let liveSessionLogTurnId = null;
6271
+ let liveSessionLogSessionId = null;
5239
6272
  const scheduleTrailingLiveRefresh = () => {
5240
6273
  if (liveRefreshClosed || !liveRefreshPending || liveRefreshRequest !== null || liveRefreshTimer !== null) {
5241
6274
  return;
@@ -5349,6 +6382,10 @@ export async function runProviderLinearWorker(env = process.env, dependencyOverr
5349
6382
  latest_turn_id: liveTurnId,
5350
6383
  latest_session_id: session.sessionId,
5351
6384
  latest_session_id_source: session.source,
6385
+ session_log_thread_id: liveSessionLogThreadId ?? (liveScopeChanged ? null : finalProof.session_log_thread_id ?? null),
6386
+ session_log_turn_id: liveSessionLogTurnId ?? (liveScopeChanged ? null : finalProof.session_log_turn_id ?? null),
6387
+ session_log_session_id: liveSessionLogSessionId ?? (liveScopeChanged ? null : finalProof.session_log_session_id ?? null),
6388
+ resume_source_thread_id: finalProof.resume_source_thread_id ?? null,
5352
6389
  turn_count: turnNumber,
5353
6390
  last_event: liveParseState.lastEvent ?? (liveScopeChanged ? null : finalProof.last_event),
5354
6391
  last_message: liveParseState.finalMessage ?? (liveScopeChanged ? null : finalProof.last_message),
@@ -5373,6 +6410,10 @@ export async function runProviderLinearWorker(env = process.env, dependencyOverr
5373
6410
  latest_turn_id: nextProof.latest_turn_id,
5374
6411
  latest_session_id: nextProof.latest_session_id,
5375
6412
  latest_session_id_source: nextProof.latest_session_id_source,
6413
+ session_log_thread_id: nextProof.session_log_thread_id ?? null,
6414
+ session_log_turn_id: nextProof.session_log_turn_id ?? null,
6415
+ session_log_session_id: nextProof.session_log_session_id ?? null,
6416
+ resume_source_thread_id: nextProof.resume_source_thread_id ?? null,
5376
6417
  turn_count: nextProof.turn_count,
5377
6418
  last_event: nextProof.last_event,
5378
6419
  last_message: nextProof.last_message,
@@ -5434,6 +6475,11 @@ export async function runProviderLinearWorker(env = process.env, dependencyOverr
5434
6475
  })) ??
5435
6476
  deriveSharedRepoCheckoutPathFallback(context.repoRoot, context.taskId);
5436
6477
  const continueResidentSessionOnBoot = turnNumber === 1 && residentSessionSeed !== null;
6478
+ const resumeSourceThreadIdForTurn = continueResidentSessionOnBoot
6479
+ ? residentSessionSeed?.source_thread_id ?? null
6480
+ : turnNumber > 1
6481
+ ? threadId ?? finalProof.thread_id ?? null
6482
+ : null;
5437
6483
  const prompt = buildProviderWorkerPrompt(issue, turnNumber, context.maxTurns, helperCommand, sharedRepoCheckoutPath, {
5438
6484
  linearAudit: finalProof.linear_audit,
5439
6485
  attemptStartedAt: finalProof.attempt_started_at ?? null,
@@ -5442,10 +6488,10 @@ export async function runProviderLinearWorker(env = process.env, dependencyOverr
5442
6488
  continueResidentSessionOnBoot
5443
6489
  });
5444
6490
  const args = continueResidentSessionOnBoot
5445
- ? ['exec', 'resume', '--json', residentSessionSeed?.source_thread_id ?? '', prompt]
6491
+ ? ['exec', 'resume', '--json', resumeSourceThreadIdForTurn ?? '', prompt]
5446
6492
  : turnNumber === 1
5447
6493
  ? ['exec', '--json', prompt]
5448
- : ['exec', 'resume', '--json', threadId ?? '', prompt];
6494
+ : ['exec', 'resume', '--json', resumeSourceThreadIdForTurn ?? '', prompt];
5449
6495
  const resolved = resolveRuntimeCodexCommand(args, runtimeContext);
5450
6496
  let stopLiveSessionTailResolve = null;
5451
6497
  let liveSessionTailStopped = false;
@@ -5461,7 +6507,7 @@ export async function runProviderLinearWorker(env = process.env, dependencyOverr
5461
6507
  };
5462
6508
  const previousTurnProof = finalProof;
5463
6509
  const turnStartedAt = deps.now();
5464
- finalProof = await writeProofSnapshot(deps, context.runDir, auditPath, buildProviderLinearWorkerTurnBootstrapProof(finalProof, turnNumber, turnStartedAt), childEnv);
6510
+ finalProof = await writeProofSnapshot(deps, context.runDir, auditPath, buildProviderLinearWorkerTurnBootstrapProof(finalProof, turnNumber, turnStartedAt, resumeSourceThreadIdForTurn), childEnv);
5465
6511
  const parallelizationDecisionCountBeforeTurn = readProviderLinearParallelizationSnapshots(finalProof.linear_audit, {
5466
6512
  issueId: finalProof.issue_id
5467
6513
  }).length;
@@ -5471,9 +6517,14 @@ export async function runProviderLinearWorker(env = process.env, dependencyOverr
5471
6517
  path: null,
5472
6518
  offsetBytes: 0,
5473
6519
  trailingText: '',
5474
- bootstrapPending: true
6520
+ bootstrapPending: true,
6521
+ currentTurnStartedAt: turnStartedAt,
6522
+ idRewindSignature: null
5475
6523
  }
5476
6524
  : null;
6525
+ const allowCompletedSessionBootstrapTurn = turnNumber === 1 &&
6526
+ previousTurnProof.latest_turn_id === null &&
6527
+ !continueResidentSessionOnBoot;
5477
6528
  const liveSessionTailPromise = liveSessionTailState === null
5478
6529
  ? Promise.resolve()
5479
6530
  : (async () => {
@@ -5499,7 +6550,22 @@ export async function runProviderLinearWorker(env = process.env, dependencyOverr
5499
6550
  }
5500
6551
  if (liveSessionTailState.path !== null) {
5501
6552
  const delta = await readProviderWorkerSessionLogDelta(liveSessionTailState);
5502
- if (delta && applyProviderWorkerSessionLogDelta(liveParseState, liveSessionTailState, delta, childEnv)) {
6553
+ const deltaApply = delta
6554
+ ? applyProviderWorkerSessionLogDelta(liveParseState, liveSessionTailState, delta, childEnv, { allowCompletedBootstrapTurn: allowCompletedSessionBootstrapTurn })
6555
+ : {
6556
+ changed: false,
6557
+ observed: false,
6558
+ observedThreadId: null,
6559
+ observedTurnId: null
6560
+ };
6561
+ if (deltaApply.observed) {
6562
+ liveSessionLogThreadId =
6563
+ deltaApply.observedThreadId ?? liveSessionLogThreadId;
6564
+ liveSessionLogTurnId = deltaApply.observedTurnId ?? liveSessionLogTurnId;
6565
+ liveSessionLogSessionId = deriveLatestTurnSessionId({
6566
+ threadId: liveSessionLogThreadId,
6567
+ turnId: liveSessionLogTurnId
6568
+ }).sessionId;
5503
6569
  queueLiveProofWrite();
5504
6570
  }
5505
6571
  }
@@ -5511,7 +6577,21 @@ export async function runProviderLinearWorker(env = process.env, dependencyOverr
5511
6577
  stopLiveSessionTailPromise
5512
6578
  ]);
5513
6579
  }
5514
- if (liveSessionTailState.path !== null && flushProviderWorkerSessionLogTail(liveParseState, liveSessionTailState, childEnv)) {
6580
+ const tailApply = liveSessionTailState.path !== null
6581
+ ? flushProviderWorkerSessionLogTail(liveParseState, liveSessionTailState, childEnv, { allowCompletedBootstrapTurn: allowCompletedSessionBootstrapTurn })
6582
+ : {
6583
+ changed: false,
6584
+ observed: false,
6585
+ observedThreadId: null,
6586
+ observedTurnId: null
6587
+ };
6588
+ if (tailApply.observed) {
6589
+ liveSessionLogThreadId = tailApply.observedThreadId ?? liveSessionLogThreadId;
6590
+ liveSessionLogTurnId = tailApply.observedTurnId ?? liveSessionLogTurnId;
6591
+ liveSessionLogSessionId = deriveLatestTurnSessionId({
6592
+ threadId: liveSessionLogThreadId,
6593
+ turnId: liveSessionLogTurnId
6594
+ }).sessionId;
5515
6595
  queueLiveProofWrite();
5516
6596
  }
5517
6597
  })().catch((error) => {
@@ -5541,6 +6621,9 @@ export async function runProviderLinearWorker(env = process.env, dependencyOverr
5541
6621
  latest_turn_id: previousTurnProof.latest_turn_id,
5542
6622
  latest_session_id: previousTurnProof.latest_session_id,
5543
6623
  latest_session_id_source: previousTurnProof.latest_session_id_source,
6624
+ session_log_thread_id: previousTurnProof.session_log_thread_id,
6625
+ session_log_turn_id: previousTurnProof.session_log_turn_id,
6626
+ session_log_session_id: previousTurnProof.session_log_session_id,
5544
6627
  last_event: previousTurnProof.last_event,
5545
6628
  last_message: previousTurnProof.last_message,
5546
6629
  last_event_at: previousTurnProof.last_event_at,
@@ -5600,6 +6683,13 @@ export async function runProviderLinearWorker(env = process.env, dependencyOverr
5600
6683
  const parsedTurnChanged = Boolean(turnId && turnId !== finalProof.latest_turn_id);
5601
6684
  const parsedScopeChanged = parsedThreadChanged || parsedTurnChanged;
5602
6685
  const session = deriveLatestTurnSessionId({ threadId, turnId });
6686
+ const sessionLogProof = selectProviderLinearWorkerSessionLogProofForScope({
6687
+ proof: finalProof,
6688
+ threadId,
6689
+ turnId,
6690
+ sessionId: session.sessionId,
6691
+ scopeChanged: parsedScopeChanged
6692
+ });
5603
6693
  finalProof = {
5604
6694
  issue_id: context.issueId,
5605
6695
  issue_identifier: context.issueIdentifier,
@@ -5610,6 +6700,10 @@ export async function runProviderLinearWorker(env = process.env, dependencyOverr
5610
6700
  latest_turn_id: turnId,
5611
6701
  latest_session_id: session.sessionId,
5612
6702
  latest_session_id_source: session.source,
6703
+ session_log_thread_id: sessionLogProof.sessionLogThreadId,
6704
+ session_log_turn_id: sessionLogProof.sessionLogTurnId,
6705
+ session_log_session_id: sessionLogProof.sessionLogSessionId,
6706
+ resume_source_thread_id: finalProof.resume_source_thread_id ?? null,
5613
6707
  turn_count: turnNumber,
5614
6708
  last_event: parsed.lastEvent ?? (parsedScopeChanged ? null : finalProof.last_event),
5615
6709
  last_message: parsed.finalMessage ?? (parsedScopeChanged ? null : finalProof.last_message),
@@ -5617,6 +6711,8 @@ export async function runProviderLinearWorker(env = process.env, dependencyOverr
5617
6711
  current_turn_activity: synchronizeProviderLinearWorkerCurrentTurnActivity(parsed.currentTurnActivity, threadId, turnId) ?? (parsedScopeChanged ? null : selectProviderLinearWorkerCurrentTurnActivity(finalProof)),
5618
6712
  tokens: hasProviderWorkerTokenUsage(parsed.tokens) ? parsed.tokens : finalProof.tokens,
5619
6713
  rate_limits: parsed.rateLimits ?? finalProof.rate_limits,
6714
+ runtime: finalProof.runtime ?? buildProviderLinearWorkerRuntimeProof(runtimeContext.runtime),
6715
+ appserver_supervision: finalProof.appserver_supervision ?? null,
5620
6716
  auth_provenance: mergeProviderWorkerAuthProvenance(finalProof.auth_provenance ?? null, parsed.authProvenance),
5621
6717
  failure_diagnosis: parsed.failureDiagnosis ??
5622
6718
  stderrFailureDiagnosis ??