@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.
- package/README.md +43 -83
- package/dist/bin/codex-orchestrator.js +2 -0
- package/dist/orchestrator/src/cli/adapters/CommandBuilder.js +50 -0
- package/dist/orchestrator/src/cli/adapters/cloudFailureDiagnostics.js +117 -5
- package/dist/orchestrator/src/cli/coStatusAttachCliShell.js +2 -2
- package/dist/orchestrator/src/cli/coStatusCliShell.js +28 -6
- package/dist/orchestrator/src/cli/codexCliShell.js +48 -1
- package/dist/orchestrator/src/cli/codexDefaultsSetup.js +217 -26
- package/dist/orchestrator/src/cli/control/controlHostSupervision.js +28 -6
- package/dist/orchestrator/src/cli/control/controlRuntime.js +17 -6
- package/dist/orchestrator/src/cli/control/controlStatusDashboard.js +6 -1
- package/dist/orchestrator/src/cli/control/selectedRunProjection.js +49 -2
- package/dist/orchestrator/src/cli/doctor.js +142 -48
- package/dist/orchestrator/src/cli/init.js +94 -1
- package/dist/orchestrator/src/cli/providerLinearChildLaneRunner.js +64 -1
- package/dist/orchestrator/src/cli/providerLinearWorkerRunner.js +1165 -69
- package/dist/orchestrator/src/cli/rlm/alignment.js +3 -3
- package/dist/orchestrator/src/cli/services/commandRunner.js +31 -0
- package/dist/orchestrator/src/cli/utils/cloudPreflight.js +202 -6
- package/dist/orchestrator/src/cli/utils/codexFeatures.js +60 -0
- package/dist/orchestrator/src/manager.js +74 -4
- package/dist/scripts/lib/docs-catalog.js +35 -1
- package/docs/README.md +333 -0
- package/docs/book/README.md +19 -0
- package/docs/book/codex-cli-0124-adoption.md +68 -0
- package/docs/book/local-hook-impact.md +73 -0
- package/docs/book/operations.md +60 -0
- package/docs/book/public-posture.md +34 -0
- package/docs/book/setup.md +91 -0
- package/docs/book/skills.md +11 -0
- package/docs/guides/codex-version-policy.md +104 -0
- package/docs/public/downstream-setup.md +25 -18
- package/package.json +4 -1
- package/plugins/codex-orchestrator/.codex-plugin/plugin.json +1 -1
- package/plugins/codex-orchestrator/launcher.mjs +6 -4
- package/schemas/manifest.json +17 -0
- package/skills/README.md +26 -0
- package/skills/collab-subagents-first/SKILL.md +1 -1
- package/skills/delegation-usage/DELEGATION_GUIDE.md +12 -7
- package/skills/delegation-usage/SKILL.md +13 -8
- 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 ||
|
|
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
|
-
|
|
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 &&
|
|
1695
|
+
if (inputTokens === null &&
|
|
1696
|
+
outputTokens === null &&
|
|
1697
|
+
normalizedTotalTokens === null &&
|
|
1698
|
+
reasoningOutputTokens === null) {
|
|
1671
1699
|
return null;
|
|
1672
1700
|
}
|
|
1673
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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, {
|
|
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
|
-
|
|
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], {
|
|
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
|
-
|
|
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 (
|
|
3338
|
-
|
|
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
|
|
4142
|
-
const
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
5003
|
-
|
|
5004
|
-
|
|
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',
|
|
6491
|
+
? ['exec', 'resume', '--json', resumeSourceThreadIdForTurn ?? '', prompt]
|
|
5446
6492
|
: turnNumber === 1
|
|
5447
6493
|
? ['exec', '--json', prompt]
|
|
5448
|
-
: ['exec', 'resume', '--json',
|
|
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
|
-
|
|
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
|
-
|
|
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 ??
|