sneakoscope 6.1.0 → 6.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. package/README.md +35 -11
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/dist/bin/fast-inline.js +18 -9
  5. package/dist/bin/sks-dispatch.js +2 -2
  6. package/dist/cli/args.js +2 -0
  7. package/dist/cli/command-manifest-lite.js +2 -3
  8. package/dist/cli/command-registry.js +3 -4
  9. package/dist/cli/help-fast.js +1 -1
  10. package/dist/cli/install-helpers.js +116 -306
  11. package/dist/cli/install-tool-helpers.js +287 -0
  12. package/dist/cli/router.js +40 -4
  13. package/dist/commands/codex-lb.js +51 -20
  14. package/dist/commands/codex.js +39 -1
  15. package/dist/commands/doctor.js +242 -20
  16. package/dist/commands/tmux.js +5 -1
  17. package/dist/commands/zellij-monitor-pane.js +2 -0
  18. package/dist/commands/zellij-viewport-pane.js +3 -1
  19. package/dist/commands/zellij.js +1 -1
  20. package/dist/config/skills-manifest.json +59 -59
  21. package/dist/core/agent-bridge/agent-manifest.js +48 -0
  22. package/dist/core/agents/agent-command-surface.js +2 -1
  23. package/dist/core/agents/agent-effort-policy.js +38 -35
  24. package/dist/core/agents/agent-plan.js +100 -21
  25. package/dist/core/agents/agent-role-config.js +43 -46
  26. package/dist/core/agents/agent-runner-codex-exec.js +16 -3
  27. package/dist/core/agents/agent-schema.js +3 -2
  28. package/dist/core/agents/native-cli-session-swarm.js +1 -1
  29. package/dist/core/agents/zellij-right-lane-cockpit.js +2 -2
  30. package/dist/core/codex/agent-config-file-repair.js +94 -193
  31. package/dist/core/codex/codex-cli-update.js +723 -0
  32. package/dist/core/codex/codex-config-guard.js +185 -9
  33. package/dist/core/codex/codex-config-readability.js +21 -8
  34. package/dist/core/codex/codex-config-toml.js +14 -11
  35. package/dist/core/codex/codex-project-config-policy.js +3 -6
  36. package/dist/core/codex/codex-startup-config-postcheck.js +52 -42
  37. package/dist/core/codex-adapter.js +35 -22
  38. package/dist/core/codex-app/codex-agent-role-sync.js +13 -54
  39. package/dist/core/codex-app/codex-app-launcher.js +48 -17
  40. package/dist/core/codex-app/codex-app-restart.js +23 -2
  41. package/dist/core/codex-app/mcp-manager.js +679 -0
  42. package/dist/core/codex-app/sks-menubar.js +533 -8
  43. package/dist/core/codex-control/codex-0139-image-path-real-probe.js +15 -4
  44. package/dist/core/codex-control/codex-0139-web-search-probe.js +17 -6
  45. package/dist/core/codex-control/codex-lb-launch-recovery.js +293 -0
  46. package/dist/core/codex-control/codex-reliability-shield.js +89 -29
  47. package/dist/core/codex-control/codex-sdk-adapter.js +44 -8
  48. package/dist/core/codex-control/codex-task-runner.js +62 -9
  49. package/dist/core/codex-control/python-codex-sdk-adapter.js +30 -3
  50. package/dist/core/codex-exec-output-schema.js +35 -6
  51. package/dist/core/codex-lb/codex-lb-env.js +1 -1
  52. package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +291 -0
  53. package/dist/core/codex-native/codex-native-feature-broker.js +9 -16
  54. package/dist/core/codex-native/codex-native-repair-transaction.js +1 -1
  55. package/dist/core/codex-native/core-skill-manifest.js +8 -4
  56. package/dist/core/codex-runtime/codex-desktop-config-policy.js +2 -3
  57. package/dist/core/commands/agent-bridge-command.js +23 -2
  58. package/dist/core/commands/agent-command.js +19 -5
  59. package/dist/core/commands/basic-cli.js +47 -6
  60. package/dist/core/commands/command-utils.js +1 -1
  61. package/dist/core/commands/mad-sks-command.js +76 -10
  62. package/dist/core/commands/menubar-command.js +94 -0
  63. package/dist/core/commands/naruto-command.js +645 -1156
  64. package/dist/core/commands/research-command.js +293 -231
  65. package/dist/core/commands/run-command.js +100 -23
  66. package/dist/core/commands/team-command.js +2 -3
  67. package/dist/core/commands/team-legacy-observe-command.js +94 -359
  68. package/dist/core/commands/wiki-command.js +11 -5
  69. package/dist/core/db-safety.js +2 -2
  70. package/dist/core/decision-lattice.js +6 -6
  71. package/dist/core/doctor/codex-startup-config-repair.js +8 -3
  72. package/dist/core/doctor/doctor-codex-startup-repair.js +6 -141
  73. package/dist/core/feature-fixture-executor.js +71 -7
  74. package/dist/core/feature-fixture-runner.js +53 -12
  75. package/dist/core/feature-fixtures.js +47 -14
  76. package/dist/core/feature-registry.js +28 -27
  77. package/dist/core/fsx.js +1 -0
  78. package/dist/core/harness-conflicts.js +18 -9
  79. package/dist/core/hooks-runtime/code-pack-freshness-preflight.js +14 -8
  80. package/dist/core/hooks-runtime/hook-io.js +8 -4
  81. package/dist/core/hooks-runtime/light-turn.js +70 -0
  82. package/dist/core/hooks-runtime/naruto-decision-gate.js +184 -0
  83. package/dist/core/hooks-runtime/payload-signals.js +270 -0
  84. package/dist/core/hooks-runtime/stop-repeat-guard.js +89 -0
  85. package/dist/core/hooks-runtime/team-digest.js +0 -1
  86. package/dist/core/hooks-runtime/tool-output-quarantine.js +93 -0
  87. package/dist/core/hooks-runtime.js +438 -354
  88. package/dist/core/init/skills.js +16 -30
  89. package/dist/core/init.js +144 -36
  90. package/dist/core/managed-assets/managed-assets-manifest.js +566 -10
  91. package/dist/core/mission.js +24 -1
  92. package/dist/core/pipeline-internals/runtime-core.js +570 -177
  93. package/dist/core/pipeline-internals/runtime-gates.js +174 -48
  94. package/dist/core/preflight/parallel-preflight-engine.js +66 -4
  95. package/dist/core/proof/route-adapter.js +1 -1
  96. package/dist/core/proof/route-proof-gate.js +7 -2
  97. package/dist/core/proof/selftest-proof-fixtures.js +3 -5
  98. package/dist/core/proof-field.js +1 -1
  99. package/dist/core/provider/model-router.js +42 -31
  100. package/dist/core/recallpulse/policy.js +12 -28
  101. package/dist/core/recallpulse.js +11 -6
  102. package/dist/core/release/npm-pack-proof.js +247 -0
  103. package/dist/core/release/package-dist-snapshot.js +151 -0
  104. package/dist/core/release/package-size-budget.js +4 -1
  105. package/dist/core/release/release-authorization-snapshot.js +115 -0
  106. package/dist/core/release/release-gate-affected-selector.js +14 -2
  107. package/dist/core/release/release-gate-cache-v2.js +30 -0
  108. package/dist/core/release/release-gate-contract.js +161 -0
  109. package/dist/core/release/release-gate-dag.js +1 -0
  110. package/dist/core/release/release-real-contract.js +90 -10
  111. package/dist/core/release-parallel-full-coverage.js +31 -143
  112. package/dist/core/research/claim-evidence-matrix.js +41 -6
  113. package/dist/core/research/experiment-plan.js +14 -10
  114. package/dist/core/research/falsification.js +9 -2
  115. package/dist/core/research/implementation-blueprint-densifier.js +82 -60
  116. package/dist/core/research/implementation-blueprint.js +32 -26
  117. package/dist/core/research/mock-result.js +122 -11
  118. package/dist/core/research/replication-pack.js +15 -8
  119. package/dist/core/research/research-adversarial-review.js +1068 -0
  120. package/dist/core/research/research-claim-builder.js +69 -17
  121. package/dist/core/research/research-claim-synthesizer.js +343 -0
  122. package/dist/core/research/research-cycle-runner.js +53 -3
  123. package/dist/core/research/research-falsification-runner.js +176 -0
  124. package/dist/core/research/research-final-reviewer.js +44 -125
  125. package/dist/core/research/research-plan-markdown.js +123 -0
  126. package/dist/core/research/research-realistic-report.js +14 -6
  127. package/dist/core/research/research-review-artifact-digest.js +66 -0
  128. package/dist/core/research/research-source-evidence.js +144 -0
  129. package/dist/core/research/research-source-layer-catalog.js +68 -0
  130. package/dist/core/research/research-source-ledger-merge.js +250 -12
  131. package/dist/core/research/research-source-shards.js +26 -70
  132. package/dist/core/research/research-stage-runner.js +237 -247
  133. package/dist/core/research/research-super-search.js +188 -0
  134. package/dist/core/research/research-synthesis-prompt.js +20 -1
  135. package/dist/core/research/research-synthesis-writer.js +86 -5
  136. package/dist/core/research/research-work-graph.js +25 -18
  137. package/dist/core/research/source-quality-report.js +21 -0
  138. package/dist/core/research.js +424 -390
  139. package/dist/core/retention.js +70 -2
  140. package/dist/core/routes/constants.js +1 -1
  141. package/dist/core/routes/dollar-manifest-lite.js +11 -11
  142. package/dist/core/routes.js +149 -69
  143. package/dist/core/runtime/task-profile.js +66 -0
  144. package/dist/core/runtime/verification-budget.js +12 -0
  145. package/dist/core/security/high-risk-contracts.js +6 -6
  146. package/dist/core/stop-gate/stop-gate-check.js +49 -12
  147. package/dist/core/subagents/agent-catalog.js +287 -0
  148. package/dist/core/subagents/model-policy.js +259 -0
  149. package/dist/core/subagents/naruto-help-contract.js +47 -0
  150. package/dist/core/subagents/official-subagent-config.js +488 -0
  151. package/dist/core/subagents/official-subagent-preparation.js +297 -0
  152. package/dist/core/subagents/official-subagent-prompt.js +159 -0
  153. package/dist/core/subagents/official-subagent-runner.js +129 -0
  154. package/dist/core/subagents/subagent-evidence.js +663 -0
  155. package/dist/core/subagents/terminology.js +16 -0
  156. package/dist/core/subagents/thread-budget.js +21 -0
  157. package/dist/core/subagents/triwiki-attention.js +168 -0
  158. package/dist/core/super-search/runtime-helpers.js +173 -19
  159. package/dist/core/super-search/runtime.js +140 -15
  160. package/dist/core/super-search/source-records.js +49 -8
  161. package/dist/core/team-review-policy.js +15 -0
  162. package/dist/core/triwiki/code-pack-head-freshness.js +291 -0
  163. package/dist/core/triwiki/triwiki-module-card.js +1 -1
  164. package/dist/core/triwiki-wrongness/wrongness-ledger.js +9 -2
  165. package/dist/core/version-manager.js +51 -1
  166. package/dist/core/version.js +1 -1
  167. package/dist/core/work-order-ledger.js +40 -1
  168. package/dist/core/zellij/zellij-fake-adapter.js +3 -1
  169. package/dist/core/zellij/zellij-launcher.js +49 -10
  170. package/dist/core/zellij/zellij-layout-builder.js +14 -5
  171. package/dist/core/zellij/zellij-official-subagent-activity.js +477 -0
  172. package/dist/core/zellij/zellij-official-subagent-telemetry.js +264 -0
  173. package/dist/core/zellij/zellij-pane-proof.js +9 -1
  174. package/dist/core/zellij/zellij-slot-pane-renderer.js +17 -5
  175. package/dist/core/zellij/zellij-slot-telemetry.js +15 -3
  176. package/dist/core/zellij/zellij-ui-mode.js +1 -1
  177. package/dist/core/zellij/zellij-update.js +14 -1
  178. package/dist/core/zellij/zellij-viewport-binder.js +3 -0
  179. package/dist/scripts/agent-role-config-repair-check.js +14 -16
  180. package/dist/scripts/architecture-guard-check.js +8 -1
  181. package/dist/scripts/canonical-test-runner.js +7 -1
  182. package/dist/scripts/check-route-modularity.js +0 -1
  183. package/dist/scripts/check-ts-contracts.js +1 -1
  184. package/dist/scripts/codex-control-all-pipelines-check.js +7 -3
  185. package/dist/scripts/codex-control-tool-output-continuity-audit-check.js +27 -0
  186. package/dist/scripts/codex-lb-fast-mode-truth-check.js +11 -1
  187. package/dist/scripts/codex-lb-fast-ui-preservation-check.js +9 -2
  188. package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +13 -2
  189. package/dist/scripts/codex-native-agent-role-content-check.js +27 -7
  190. package/dist/scripts/codex-native-repair-transaction-check.js +3 -1
  191. package/dist/scripts/codex-sdk-all-pipelines-check.js +7 -4
  192. package/dist/scripts/codex-sdk-backend-router-check.js +2 -0
  193. package/dist/scripts/codex-sdk-research-pipeline-check.js +30 -8
  194. package/dist/scripts/db-route-materialization-check.js +33 -0
  195. package/dist/scripts/docs-truthfulness-check.js +3 -1
  196. package/dist/scripts/doctor-codex-startup-repair-check.js +12 -15
  197. package/dist/scripts/doctor-fix-production-blackbox.js +12 -2
  198. package/dist/scripts/doctor-startup-config-repair-blackbox.js +8 -2
  199. package/dist/scripts/doctor-startup-config-repair-check.js +12 -2
  200. package/dist/scripts/install-update-preserves-config-check.js +6 -1
  201. package/dist/scripts/lib/codex-sdk-gate-lib.js +4 -0
  202. package/dist/scripts/mad-sks-app-ui-no-mutation-check.js +0 -1
  203. package/dist/scripts/managed-role-manifest-parity-check.js +5 -4
  204. package/dist/scripts/naruto-codex-e2e-check.js +14 -7
  205. package/dist/scripts/naruto-shadow-clone-swarm-check.js +4 -201
  206. package/dist/scripts/npm-publish-performance-check.js +20 -12
  207. package/dist/scripts/official-subagent-workflow-check.js +145 -0
  208. package/dist/scripts/package-published-contract-check.js +6 -29
  209. package/dist/scripts/packlist-performance-check.js +18 -21
  210. package/dist/scripts/parallel-verification-engine-check.js +2 -2
  211. package/dist/scripts/prepublish-release-check-or-fast.js +23 -86
  212. package/dist/scripts/python-codex-sdk-all-pipelines-check.js +8 -0
  213. package/dist/scripts/release-affected-selector-check.js +74 -1
  214. package/dist/scripts/release-check-stamp.js +153 -248
  215. package/dist/scripts/release-dag-full-coverage-check.js +7 -15
  216. package/dist/scripts/release-dynamic-presets-check.js +2 -1
  217. package/dist/scripts/release-gate-dag-runner-check.js +0 -1
  218. package/dist/scripts/release-gate-dag-runner.js +12 -1
  219. package/dist/scripts/release-gate-existence-audit.js +1 -2
  220. package/dist/scripts/release-parallel-full-coverage-check.js +12 -6
  221. package/dist/scripts/release-parallel-speed-budget-check.js +18 -2
  222. package/dist/scripts/release-real-check.js +26 -4
  223. package/dist/scripts/release-registry-check.js +61 -16
  224. package/dist/scripts/research-blueprint-densifier-check.js +2 -2
  225. package/dist/scripts/research-real-cycle-no-legacy-final-md-check.js +11 -7
  226. package/dist/scripts/sizecheck.js +2 -2
  227. package/dist/scripts/sks-3-1-4-directive-check-lib.js +8 -2
  228. package/dist/scripts/sks-3-1-5-directive-check-lib.js +3 -2
  229. package/dist/scripts/sks-3-1-6-directive-check-lib.js +5 -3
  230. package/dist/scripts/sks-menubar-install-check.js +14 -1
  231. package/dist/scripts/super-search-provider-interface-check.js +31 -18
  232. package/dist/scripts/trust-fixture-check.js +32 -10
  233. package/dist/scripts/wrongness-fixture-check.js +1 -1
  234. package/dist/scripts/zellij-layout-valid-check.js +5 -5
  235. package/dist/scripts/zellij-spawn-on-demand-layout-check.js +3 -3
  236. package/docs/demo.tape +1 -1
  237. package/infra-harness-gates.json +1486 -0
  238. package/package.json +15 -10
  239. package/release-gates.v2.json +4060 -0
  240. package/runtime-required-scripts.json +9 -0
  241. package/dist/commands/db.js +0 -6
  242. package/dist/core/commands/db-command.js +0 -146
  243. package/dist/core/research/prompt.js +0 -15
  244. package/dist/scripts/codex-0139-feature-probes-check.js +0 -30
  245. package/dist/scripts/codex-0139-marketplace-source-check.js +0 -13
  246. package/dist/scripts/codex-control-tool-call-sequence-repair-check.js +0 -14
@@ -1,4 +1,6 @@
1
1
  import path from 'node:path';
2
+ import fsp from 'node:fs/promises';
3
+ import { randomBytes } from 'node:crypto';
2
4
  import { appendJsonl, ensureDir, nowIso, readText, sha256, writeTextAtomic } from '../fsx.js';
3
5
  import { diffCodexAppUiSnapshots, snapshotCodexAppUiState } from '../codex-app/codex-app-ui-state-snapshot.js';
4
6
  import { cleanupCodexConfigBackups, validateCodexConfigRoundTrip } from './codex-config-toml.js';
@@ -9,7 +11,7 @@ export async function writeCodexConfigGuarded(input) {
9
11
  const root = path.resolve(input.root || process.cwd());
10
12
  const cause = input.cause || 'codex-config';
11
13
  const before = input.before === undefined ? String(await readText(configPath, '')) : String(input.before || '');
12
- if (isUnmanagedProjectCodexConfig(root, configPath, before)) {
14
+ if (isUnmanagedProjectCodexConfig(root, configPath, before) && input.ownershipVerified !== true) {
13
15
  const result = { ok: false, status: 'blocked_unmanaged_project_config', config_path: configPath, backup_path: null, changed: false };
14
16
  await recordCodexConfigGuard(root, input.reportPath, {
15
17
  cause,
@@ -38,10 +40,13 @@ export async function writeCodexConfigGuarded(input) {
38
40
  return result;
39
41
  }
40
42
  const beforeSnapshot = await snapshotForConfig(root, configPath).catch(() => null);
41
- let next = ensureTrailingNewline(await input.mutate(before));
43
+ const normalizeText = input.preserveTextFormatting === true
44
+ ? (value) => String(value || '')
45
+ : ensureTrailingNewline;
46
+ let next = normalizeText(await input.mutate(before));
42
47
  if (input.removeTopLevelModeLocks === true)
43
48
  next = removeLegacyTopLevelCodexModeLocks(next);
44
- const preserved = input.preserveFastUiKeys === false ? { text: ensureTrailingNewline(next), keys: [] } : mergeLostFastUiKeys(before, next);
49
+ const preserved = input.preserveFastUiKeys === false ? { text: normalizeText(next), keys: [] } : mergeLostFastUiKeys(before, next);
45
50
  next = preserved.text;
46
51
  if (input.removeTopLevelModeLocks === true)
47
52
  next = removeLegacyTopLevelCodexModeLocks(next);
@@ -63,8 +68,29 @@ export async function writeCodexConfigGuarded(input) {
63
68
  });
64
69
  return result;
65
70
  }
66
- if (next === ensureTrailingNewline(before)) {
67
- await writeTextAtomic(configPath, next, { mode: 0o600 });
71
+ const expectedBefore = normalizeText(before);
72
+ if (next === expectedBefore) {
73
+ if (input.verifyUnchangedBeforeWrite === true) {
74
+ const observed = await readConfigCommitSnapshot(configPath);
75
+ const expectedExists = input.expectedBeforeExists ?? true;
76
+ if (!configCommitSnapshotMatches(observed, expectedExists, before)) {
77
+ return recordConcurrentConfigChange({
78
+ root,
79
+ reportPath: input.reportPath,
80
+ cause,
81
+ configPath,
82
+ before,
83
+ expectedExists,
84
+ observed,
85
+ backupPath: null,
86
+ repairedKeys: preserved.keys,
87
+ forbiddenTopLevel
88
+ });
89
+ }
90
+ }
91
+ else {
92
+ await writeTextAtomic(configPath, next, { mode: 0o600 });
93
+ }
68
94
  const result = { ok: true, status: 'present', config_path: configPath, backup_path: null, changed: false, repaired_keys: preserved.keys, forbidden_top_level: forbiddenTopLevel };
69
95
  if (preserved.keys.length || forbiddenTopLevel.length) {
70
96
  await recordCodexConfigGuard(root, input.reportPath, {
@@ -79,9 +105,37 @@ export async function writeCodexConfigGuarded(input) {
79
105
  }
80
106
  return result;
81
107
  }
82
- const backupPath = before.trim() ? await backupCodexConfig(configPath, before, input.backupTag || cause) : null;
83
- await ensureDir(path.dirname(configPath));
84
- await writeTextAtomic(configPath, next, { mode: 0o600 });
108
+ let backupPath = null;
109
+ if (input.verifyUnchangedBeforeWrite === true) {
110
+ const expectedExists = input.expectedBeforeExists ?? true;
111
+ const commit = await commitCodexConfigIfUnchanged({
112
+ configPath,
113
+ before,
114
+ next,
115
+ expectedExists,
116
+ backupTag: input.backupTag || cause
117
+ });
118
+ if (!commit.ok) {
119
+ return recordConcurrentConfigChange({
120
+ root,
121
+ reportPath: input.reportPath,
122
+ cause,
123
+ configPath,
124
+ before,
125
+ expectedExists,
126
+ observed: commit.observed,
127
+ backupPath: commit.backupPath,
128
+ repairedKeys: preserved.keys,
129
+ forbiddenTopLevel
130
+ });
131
+ }
132
+ backupPath = commit.backupPath;
133
+ }
134
+ else {
135
+ backupPath = before.trim() ? await backupCodexConfig(configPath, before, input.backupTag || cause) : null;
136
+ await ensureDir(path.dirname(configPath));
137
+ await writeTextAtomic(configPath, next, { mode: 0o600 });
138
+ }
85
139
  const afterSnapshot = await snapshotForConfig(root, configPath).catch(() => null);
86
140
  const diff = beforeSnapshot && afterSnapshot ? diffCodexAppUiSnapshots(beforeSnapshot, afterSnapshot) : null;
87
141
  const result = {
@@ -115,6 +169,123 @@ export async function writeCodexConfigGuarded(input) {
115
169
  });
116
170
  return { ...result, report_path: reportPath };
117
171
  }
172
+ function configCommitSnapshotMatches(observed, expectedExists, expectedText) {
173
+ return observed.ok
174
+ && observed.exists === expectedExists
175
+ && sha256(observed.text) === sha256(expectedText);
176
+ }
177
+ async function recordConcurrentConfigChange(input) {
178
+ const result = {
179
+ ok: false,
180
+ status: 'concurrent_change_detected',
181
+ config_path: input.configPath,
182
+ backup_path: input.backupPath,
183
+ changed: false,
184
+ repaired_keys: input.repairedKeys,
185
+ forbidden_top_level: input.forbiddenTopLevel
186
+ };
187
+ await recordCodexConfigGuard(input.root, input.reportPath, {
188
+ cause: input.cause,
189
+ config_path: input.configPath,
190
+ ok: false,
191
+ status: result.status,
192
+ expected_exists: input.expectedExists,
193
+ observed_exists: input.observed.exists,
194
+ expected_sha256: sha256(input.before),
195
+ observed_sha256: input.observed.ok ? sha256(input.observed.text) : null,
196
+ observed_status: input.observed.status,
197
+ backup_path: input.backupPath,
198
+ changed: false
199
+ });
200
+ return result;
201
+ }
202
+ async function commitCodexConfigIfUnchanged(input) {
203
+ await ensureDir(path.dirname(input.configPath));
204
+ const token = `${Date.now().toString(36)}-${process.pid}-${randomBytes(6).toString('hex')}`;
205
+ const candidatePath = `${input.configPath}.sks-commit-${token}.tmp`;
206
+ let backupPath = null;
207
+ try {
208
+ await writeTextAtomic(candidatePath, input.next, { mode: 0o600 });
209
+ const observed = await readConfigCommitSnapshot(input.configPath);
210
+ if (!configCommitSnapshotMatches(observed, input.expectedExists, input.before)) {
211
+ return { ok: false, backupPath, observed };
212
+ }
213
+ if (input.expectedExists) {
214
+ backupPath = `${input.configPath}.sks-${safeBackupTag(input.backupTag)}-${token}.bak`;
215
+ try {
216
+ await fsp.rename(input.configPath, backupPath);
217
+ }
218
+ catch {
219
+ return { ok: false, backupPath: null, observed: await readConfigCommitSnapshot(input.configPath) };
220
+ }
221
+ const claimed = await readConfigCommitSnapshot(backupPath);
222
+ if (!configCommitSnapshotMatches(claimed, true, input.before)) {
223
+ await restoreClaimedConfigIfAbsent(backupPath, input.configPath, claimed);
224
+ return { ok: false, backupPath, observed: claimed };
225
+ }
226
+ try {
227
+ await fsp.chmod(backupPath, 0o600);
228
+ const now = new Date();
229
+ await fsp.utimes(backupPath, now, now);
230
+ }
231
+ catch {
232
+ await restoreClaimedConfigIfAbsent(backupPath, input.configPath, claimed);
233
+ return { ok: false, backupPath, observed: await readConfigCommitSnapshot(input.configPath) };
234
+ }
235
+ const afterClaim = await readConfigCommitSnapshot(input.configPath);
236
+ if (!afterClaim.ok || afterClaim.exists) {
237
+ if (!afterClaim.exists)
238
+ await restoreClaimedConfigIfAbsent(backupPath, input.configPath, claimed);
239
+ return { ok: false, backupPath, observed: await readConfigCommitSnapshot(input.configPath) };
240
+ }
241
+ }
242
+ try {
243
+ await fsp.link(candidatePath, input.configPath);
244
+ }
245
+ catch {
246
+ if (backupPath) {
247
+ const claimed = await readConfigCommitSnapshot(backupPath);
248
+ await restoreClaimedConfigIfAbsent(backupPath, input.configPath, claimed);
249
+ }
250
+ return { ok: false, backupPath, observed: await readConfigCommitSnapshot(input.configPath) };
251
+ }
252
+ await fsp.chmod(input.configPath, 0o600).catch(() => undefined);
253
+ await cleanupCodexConfigBackups(input.configPath, { keepPerTag: 3, maxAgeMs: 30 * 24 * 60 * 60 * 1000 }).catch(() => undefined);
254
+ return { ok: true, backupPath };
255
+ }
256
+ finally {
257
+ await fsp.rm(candidatePath, { force: true }).catch(() => undefined);
258
+ }
259
+ }
260
+ async function restoreClaimedConfigIfAbsent(backupPath, configPath, claimed) {
261
+ if (!claimed.ok || !claimed.exists || claimed.status !== 'regular')
262
+ return;
263
+ await fsp.link(backupPath, configPath).catch(() => undefined);
264
+ }
265
+ function safeBackupTag(value) {
266
+ return String(value || 'codex-config').replace(/[^A-Za-z0-9_.-]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 96) || 'codex-config';
267
+ }
268
+ async function readConfigCommitSnapshot(configPath) {
269
+ let stat;
270
+ try {
271
+ stat = await fsp.lstat(configPath);
272
+ }
273
+ catch (error) {
274
+ if (error?.code === 'ENOENT')
275
+ return { ok: true, exists: false, text: '', status: 'missing' };
276
+ return { ok: false, exists: false, text: '', status: 'read_failed' };
277
+ }
278
+ if (stat.isSymbolicLink())
279
+ return { ok: false, exists: true, text: '', status: 'symlink' };
280
+ if (!stat.isFile())
281
+ return { ok: false, exists: true, text: '', status: 'non_regular' };
282
+ try {
283
+ return { ok: true, exists: true, text: await fsp.readFile(configPath, 'utf8'), status: 'regular' };
284
+ }
285
+ catch {
286
+ return { ok: false, exists: true, text: '', status: 'read_failed' };
287
+ }
288
+ }
118
289
  export function extractTomlTable(text, tableName) {
119
290
  const source = String(text || '');
120
291
  const header = `[${tableName}]`;
@@ -146,7 +317,12 @@ export function isProjectCodexConfig(root, configPath) {
146
317
  return path.resolve(configPath) === path.resolve(root, '.codex', 'config.toml');
147
318
  }
148
319
  export function hasSksManagedCodexConfigMarker(text) {
149
- return /(?:SKS managed|Sneakoscope|sneakoscope|sks_|agents\.native_agent|agents\.implementation_worker|multi_agent)/i.test(String(text || ''));
320
+ const source = String(text || '');
321
+ return /^\s*#\s*SKS-MANAGED-CODEX-CONFIG\b/im.test(source)
322
+ || /(?:SKS managed|Sneakoscope|sneakoscope|sks_|agents\.native_agent|agents\.implementation_worker|multi_agent)/i.test(source)
323
+ || /^\s*model_provider\s*=\s*["']codex-lb["']\s*(?:#.*)?$/mi.test(source)
324
+ || /^\s*default_profile\s*=\s*["']sks-fast-high["']\s*(?:#.*)?$/mi.test(source)
325
+ || /^\s*\[(?:user\.fast_mode|model_providers\.(?:"codex-lb"|codex-lb)|profiles\.(?:"sks-fast-high"|sks-fast-high))\]\s*(?:#.*)?$/mi.test(source);
150
326
  }
151
327
  export function isUnmanagedProjectCodexConfig(root, configPath, text) {
152
328
  return isProjectCodexConfig(root, configPath)
@@ -50,16 +50,29 @@ export async function inspectCodexConfigReadability(rootInput = process.cwd(), o
50
50
  }
51
51
  add({ name: 'config_symlink', ok: !isSymlink || symlinkDetail.allowed === true, detail: symlinkDetail });
52
52
  }
53
- if (process.platform === 'darwin') {
54
- add(await commandCheck('macos_acl_ls_le', 'ls', ['-le', configPath], root));
55
- const acl = checks.find((check) => check.name === 'macos_acl_ls_le');
53
+ const readChecksPromise = Promise.all([
54
+ nodeReadCheck(configPath),
55
+ childReadCheck(configPath, root),
56
+ codexCliConfigLoadCheck(root, configPath, opts)
57
+ ]);
58
+ // These are independent read-only metadata probes. Running them serially
59
+ // multiplied a single TCC/ACL timeout by three on the MAD launch path.
60
+ const macChecksPromise = process.platform === 'darwin'
61
+ ? Promise.all([
62
+ commandCheck('macos_acl_ls_le', 'ls', ['-le', configPath], root),
63
+ commandCheck('macos_flags_ls_lO', 'ls', ['-lO', configPath], root),
64
+ commandCheck('macos_xattr', 'xattr', ['-l', configPath], root, { allowExitCodes: [0, 1] })
65
+ ])
66
+ : Promise.resolve(null);
67
+ const [[nodeRead, childRead, codexLoad], macChecks] = await Promise.all([readChecksPromise, macChecksPromise]);
68
+ if (macChecks) {
69
+ const [acl, flags, xattrs] = macChecks;
70
+ add(acl);
56
71
  if (/\bdeny\b.*\b(read|readattr|readextattr|readsecurity|search)\b/i.test(String(acl?.detail?.stdout || '')))
57
72
  blockers.add('acl_denied');
58
- const flags = await commandCheck('macos_flags_ls_lO', 'ls', ['-lO', configPath], root);
59
73
  add(flags);
60
74
  if (/\b(uchg|schg|restricted)\b/.test(String(flags.detail?.stdout || '')))
61
75
  blockers.add('flags_locked');
62
- const xattrs = await commandCheck('macos_xattr', 'xattr', ['-l', configPath], root, { allowExitCodes: [0, 1] });
63
76
  add(xattrs);
64
77
  add({ name: 'macos_quarantine_xattr', ok: !/com\.apple\.quarantine/.test(String(xattrs.detail?.stdout || '')), detail: { present: /com\.apple\.quarantine/.test(String(xattrs.detail?.stdout || '')) } });
65
78
  if (/com\.apple\.quarantine/.test(String(xattrs.detail?.stdout || '')))
@@ -68,9 +81,9 @@ export async function inspectCodexConfigReadability(rootInput = process.cwd(), o
68
81
  else {
69
82
  add({ name: 'macos_metadata', ok: true, status: 'skipped_non_macos' });
70
83
  }
71
- add(await nodeReadCheck(configPath));
72
- add(await childReadCheck(configPath, root));
73
- add(await codexCliConfigLoadCheck(root, configPath, opts));
84
+ add(nodeRead);
85
+ add(childRead);
86
+ add(codexLoad);
74
87
  }
75
88
  else {
76
89
  add({ name: 'config_file_checks', ok: true, status: 'skipped_config_missing', detail: { config_path: configPath } });
@@ -52,9 +52,8 @@ export async function cleanupCodexConfigBackups(configPath, opts = {}) {
52
52
  const now = Date.now();
53
53
  const groups = new Map();
54
54
  for (const file of entries) {
55
- if (!file.startsWith(`${base}.`))
56
- continue;
57
- if (!/(?:^|[.-])(?:sks-|bak-|struct-bak-)|\.bak$/.test(file))
55
+ const tag = ownedBackupTag(base, file);
56
+ if (!tag)
58
57
  continue;
59
58
  const abs = path.join(dir, file);
60
59
  let stat;
@@ -66,7 +65,6 @@ export async function cleanupCodexConfigBackups(configPath, opts = {}) {
66
65
  }
67
66
  if (!stat.isFile())
68
67
  continue;
69
- const tag = backupTag(base, file);
70
68
  const group = groups.get(tag) || [];
71
69
  group.push({ file, abs, mtimeMs: stat.mtimeMs });
72
70
  groups.set(tag, group);
@@ -87,16 +85,21 @@ export async function cleanupCodexConfigBackups(configPath, opts = {}) {
87
85
  }
88
86
  return { cleaned: removed.length, files: removed };
89
87
  }
90
- function backupTag(base, file) {
88
+ function ownedBackupTag(base, file) {
89
+ if (!file.startsWith(`${base}.`))
90
+ return null;
91
91
  const suffix = file.slice(`${base}.`.length);
92
- const sks = suffix.match(/^sks-([^-]+)-/);
93
- if (sks?.[1])
94
- return `sks-${sks[1]}`;
95
- if (suffix.startsWith('struct-bak-'))
92
+ if (/^sks-[A-Za-z0-9_.-]+\.bak$/.test(suffix)) {
93
+ const group = suffix.match(/^sks-([^-]+)-/)?.[1] || suffix.slice('sks-'.length, -'.bak'.length);
94
+ return `sks-${group}`;
95
+ }
96
+ if (/^struct-bak-[A-Za-z0-9_.-]+$/.test(suffix))
96
97
  return 'struct-bak';
97
- if (suffix.startsWith('bak-'))
98
+ if (/^bak-[A-Za-z0-9_.-]+$/.test(suffix))
98
99
  return 'bak';
99
- return 'misc';
100
+ if (/^codex-app-ui-repair-[A-Za-z0-9_.-]+\.bak$/.test(suffix))
101
+ return 'codex-app-ui-repair';
102
+ return null;
100
103
  }
101
104
  function messageOf(err) {
102
105
  return err instanceof Error ? err.message : String(err);
@@ -2,7 +2,7 @@ import fsp from 'node:fs/promises';
2
2
  import os from 'node:os';
3
3
  import path from 'node:path';
4
4
  import { ensureDir, nowIso, readText, writeJsonAtomic } from '../fsx.js';
5
- import { writeCodexConfigGuarded } from './codex-config-guard.js';
5
+ import { hasSksManagedCodexConfigMarker, writeCodexConfigGuarded } from './codex-config-guard.js';
6
6
  import { cleanupCodexConfigBackups } from './codex-config-toml.js';
7
7
  export const CODEX_PROJECT_CONFIG_POLICY_SCHEMA = 'sks.codex-project-config-policy.v1';
8
8
  const MACHINE_LOCAL_TOP_LEVEL_KEYS = new Set([
@@ -95,7 +95,7 @@ export async function splitCodexProjectConfigPolicy(rootInput = process.cwd(), o
95
95
  await writeJsonAtomic(reportPath, { ...report, report_path: reportPath });
96
96
  return report;
97
97
  }
98
- if (opts.apply && isCodexConfigToml(configPath) && !hasSksManagedCodexMarker(String(original))) {
98
+ if (opts.apply && isCodexConfigToml(configPath) && !hasSksManagedCodexConfigMarker(String(original))) {
99
99
  const report = {
100
100
  schema: CODEX_PROJECT_CONFIG_POLICY_SCHEMA,
101
101
  generated_at: nowIso(),
@@ -208,7 +208,7 @@ export async function repairCodexConfigStructure(configPathInput, opts = {}) {
208
208
  if (original === null) {
209
209
  return { config_path: configPath, ok: true, status: 'config_missing', changed: false, applied: false, hoisted_keys: [], backup_path: null };
210
210
  }
211
- if (opts.apply && isCodexConfigToml(configPath) && !hasSksManagedCodexMarker(String(original))) {
211
+ if (opts.apply && isCodexConfigToml(configPath) && !hasSksManagedCodexConfigMarker(String(original))) {
212
212
  return {
213
213
  config_path: configPath,
214
214
  ok: false,
@@ -249,9 +249,6 @@ export async function repairCodexConfigStructure(configPathInput, opts = {}) {
249
249
  function isCodexConfigToml(file) {
250
250
  return path.basename(file) === 'config.toml' && path.basename(path.dirname(file)) === '.codex';
251
251
  }
252
- function hasSksManagedCodexMarker(text) {
253
- return /(?:SKS managed|Sneakoscope|sneakoscope|sks_|agents\.native_agent|agents\.implementation_worker|multi_agent)/i.test(text);
254
- }
255
252
  function hoistMisplacedMachineLocalKeys(text) {
256
253
  const blocks = tomlBlocks(text);
257
254
  const preamble = [];
@@ -1,64 +1,64 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import { nowIso, writeJsonAtomic } from '../fsx.js';
4
- import { missingAgentConfigFiles } from './agent-config-file-repair.js';
5
- import { managedAgentRoleConfigForFile, managedAgentRoleConfigForRole } from '../agents/agent-role-config.js';
4
+ import { inspectOfficialSubagentToml, installOfficialSubagentAgentConfigs, readOfficialSubagentConfig } from '../subagents/official-subagent-config.js';
6
5
  export async function postcheckCodexStartupConfig(input) {
7
6
  const root = path.resolve(input.root);
8
7
  const configPath = path.join(root, '.codex', 'config.toml');
9
8
  const text = await fs.readFile(configPath, 'utf8').catch(() => '');
10
- const missing = await missingAgentConfigFiles(text);
11
- const managedBlocks = managedAgentBlocks(text);
12
- const unsupportedRoleFields = managedBlocks.some((block) => /^\s*message_role_prefix\s*=/m.test(block.text));
13
- const relativePaths = managedBlocks
14
- .map((block) => block.text.match(/^\s*config_file\s*=\s*"([^"]+)"/m)?.[1])
15
- .filter((file) => Boolean(file && !path.isAbsolute(file)));
9
+ const configPresent = Boolean(text.trim());
10
+ const tomlValidation = inspectOfficialSubagentToml(text);
11
+ const officialConfig = await readOfficialSubagentConfig(root, {
12
+ ...(input.home ? { home: input.home } : {}),
13
+ ...(input.codexHome ? { codexHome: input.codexHome } : {}),
14
+ projectConfigPath: configPath
15
+ });
16
+ const rolePlan = await installOfficialSubagentAgentConfigs(root, { apply: false });
16
17
  const tomlSmoke = tomlSyntaxSmoke(text);
17
18
  const orphanChildTables = orphanMcpChildTables(text);
19
+ const blockers = [
20
+ ...(!configPresent ? ['project_official_subagent_config_missing'] : []),
21
+ ...(!tomlValidation.ok ? ['project_official_subagent_config_toml_parse_failed'] : []),
22
+ ...officialConfig.blockers.map((item) => `official_subagent_config:${item}`),
23
+ ...rolePlan.missing.map((file) => `missing_official_subagent_agent:${file}`),
24
+ ...rolePlan.stale.map((file) => `stale_official_subagent_agent:${file}`),
25
+ ...rolePlan.manual_blockers,
26
+ ...tomlSmoke.blockers,
27
+ ...orphanChildTables.map((table) => `orphan_mcp_child_table:${table}`)
28
+ ];
18
29
  const report = {
19
30
  schema: 'sks.codex-startup-config-postcheck.v1',
20
31
  generated_at: nowIso(),
21
- ok: missing.length === 0 && relativePaths.length === 0 && !unsupportedRoleFields && tomlSmoke.ok && orphanChildTables.length === 0,
32
+ ok: blockers.length === 0,
22
33
  config_path: configPath,
23
- missing_config_files: missing,
24
- relative_config_files: relativePaths,
25
- unsupported_managed_role_fields: unsupportedRoleFields,
34
+ missing_config_files: [],
35
+ relative_config_files: [],
36
+ unsupported_managed_role_fields: false,
37
+ official_subagent_config: {
38
+ max_threads: officialConfig.maxThreads,
39
+ max_depth: officialConfig.maxDepth,
40
+ job_max_runtime_seconds: officialConfig.jobMaxRuntimeSeconds,
41
+ interrupt_message: officialConfig.interruptMessage,
42
+ sources: officialConfig.sources,
43
+ warnings: officialConfig.warnings
44
+ },
45
+ official_subagent_agents: {
46
+ missing: rolePlan.missing,
47
+ stale: rolePlan.stale,
48
+ existing: rolePlan.existing,
49
+ preserved: rolePlan.preserved,
50
+ manual_blockers: rolePlan.manual_blockers
51
+ },
52
+ legacy_agent_tables_preserved: true,
26
53
  toml_syntax_smoke_ok: tomlSmoke.ok,
27
54
  orphan_mcp_child_tables: orphanChildTables,
28
- blockers: [
29
- ...missing.map((file) => `missing_agent_config_file:${file}`),
30
- ...relativePaths.map((file) => `relative_agent_config_file:${file}`),
31
- ...(unsupportedRoleFields ? ['unsupported_message_role_prefix_field'] : []),
32
- ...tomlSmoke.blockers,
33
- ...orphanChildTables.map((table) => `orphan_mcp_child_table:${table}`)
34
- ]
55
+ blockers
35
56
  };
36
- if (input.reportPath !== null)
57
+ if (input.reportPath !== null) {
37
58
  await writeJsonAtomic(input.reportPath || path.join(root, '.sneakoscope', 'reports', 'codex-startup-config-postcheck.json'), report).catch(() => undefined);
59
+ }
38
60
  return report;
39
61
  }
40
- function managedAgentBlocks(text) {
41
- const blocks = tomlBlocks(text);
42
- return blocks.filter((block) => {
43
- if (!block.header.startsWith('agents.'))
44
- return false;
45
- const role = block.header.slice('agents.'.length);
46
- if (managedAgentRoleConfigForRole(role))
47
- return true;
48
- const configFile = block.text.match(/^\s*config_file\s*=\s*"([^"]+)"/m)?.[1] || '';
49
- return Boolean(configFile && managedAgentRoleConfigForFile(configFile));
50
- });
51
- }
52
- function tomlBlocks(text) {
53
- const source = String(text || '');
54
- const matches = [...source.matchAll(/(^|\n)\s*\[([^\]]+)\]\s*(?:#.*)?(?:\n|$)/g)];
55
- return matches.map((match, index) => {
56
- const start = Number(match.index || 0) + (match[1] ? 1 : 0);
57
- const next = matches[index + 1];
58
- const end = next ? Number(next.index || 0) + (next[1] ? 1 : 0) : source.length;
59
- return { header: String(match[2] || '').trim(), text: source.slice(start, end) };
60
- });
61
- }
62
62
  function tomlSyntaxSmoke(text) {
63
63
  const blockers = [];
64
64
  for (const [index, line] of String(text || '').split(/\r?\n/).entries()) {
@@ -80,4 +80,14 @@ function orphanMcpChildTables(text) {
80
80
  return Boolean(match && !headers.has(`mcp_servers.${match[1]}`));
81
81
  });
82
82
  }
83
+ function tomlBlocks(text) {
84
+ const source = String(text || '');
85
+ const matches = [...source.matchAll(/(^|\n)\s*\[([^\]]+)\]\s*(?:#.*)?(?:\n|$)/g)];
86
+ return matches.map((match, index) => {
87
+ const start = Number(match.index || 0) + (match[1] ? 1 : 0);
88
+ const next = matches[index + 1];
89
+ const end = next ? Number(next.index || 0) + (next[1] ? 1 : 0) : source.length;
90
+ return { header: String(match[2] || '').trim(), text: source.slice(start, end) };
91
+ });
92
+ }
83
93
  //# sourceMappingURL=codex-startup-config-postcheck.js.map
@@ -3,6 +3,7 @@ import { runProcess } from './fsx.js';
3
3
  import { preserveCodexModelArgs } from './codex-model-guard.js';
4
4
  import { managedProxyEnvForChild } from './codex/managed-proxy-env.js';
5
5
  import { resolveCodexRuntime } from './codex-runtime/resolve-codex-runtime.js';
6
+ import { codexLbRecoveryBlockedProcessResult, withCodexLbCliLaunchRecovery } from './codex-control/codex-lb-launch-recovery.js';
6
7
  export async function findCodexBinary() {
7
8
  const resolved = await resolveCodexRuntime({
8
9
  explicitPath: process.env.DCODEX_CODEX_BIN || null,
@@ -39,30 +40,42 @@ export function buildCodexExecArgs({ root, prompt, outputFile, json = true, prof
39
40
  args.push(prompt);
40
41
  return args;
41
42
  }
42
- export async function runCodexExec({ root, prompt, outputFile, json = true, profile = null, extraArgs = [], onStdout, onStderr, logDir = null, stdoutFile = null, stderrFile = null, maxBufferBytes = 256 * 1024, timeoutMs = null }) {
43
- const bin = await findCodexBinary();
44
- if (!bin) {
45
- return {
46
- code: 127,
47
- stdout: '',
48
- stderr: 'Codex CLI not found. Install @openai/codex or set SKS_CODEX_BIN.',
49
- stdoutBytes: 0,
50
- stderrBytes: 0,
51
- truncated: false,
52
- timedOut: false
53
- };
54
- }
43
+ export async function runCodexExec({ root, recoveryRoot = root, prompt, outputFile, json = true, profile = null, extraArgs = [], onStdout, onStderr, logDir = null, stdoutFile = null, stderrFile = null, maxBufferBytes = 256 * 1024, timeoutMs = null, env = process.env, codexBin = null, findCodexBinaryImpl = findCodexBinary, runProcessImpl = runProcess, recoveryFetch = undefined, recoveryTimeoutMs = undefined }) {
55
44
  const args = buildCodexExecArgs({ root, prompt, outputFile, json, profile, extraArgs });
56
45
  const effectiveTimeoutMs = Number(timeoutMs || process.env.SKS_CODEX_TIMEOUT_MS || process.env.DCODEX_CODEX_TIMEOUT_MS || 30 * 60 * 1000);
57
- return runProcess(bin, args, {
58
- cwd: root,
59
- env: managedProxyEnvForChild(process.env),
60
- onStdout,
61
- onStderr,
62
- timeoutMs: effectiveTimeoutMs,
63
- maxOutputBytes: maxBufferBytes,
64
- stdoutFile: stdoutFile || (logDir ? path.join(logDir, 'codex.stdout.log') : undefined),
65
- stderrFile: stderrFile || (logDir ? path.join(logDir, 'codex.stderr.log') : undefined)
46
+ const recoveryArgs = args.slice(1, -1);
47
+ const guarded = await withCodexLbCliLaunchRecovery({
48
+ root: recoveryRoot,
49
+ env,
50
+ cliArgs: recoveryArgs,
51
+ ...(typeof recoveryFetch === 'function' ? { fetchImpl: recoveryFetch } : {}),
52
+ ...(recoveryTimeoutMs === undefined ? {} : { timeoutMs: recoveryTimeoutMs })
53
+ }, async () => {
54
+ const bin = codexBin || await findCodexBinaryImpl();
55
+ if (!bin) {
56
+ return {
57
+ code: 127,
58
+ stdout: '',
59
+ stderr: 'Codex CLI not found. Install @openai/codex or set SKS_CODEX_BIN.',
60
+ stdoutBytes: 0,
61
+ stderrBytes: 0,
62
+ truncated: false,
63
+ timedOut: false
64
+ };
65
+ }
66
+ return runProcessImpl(bin, args, {
67
+ cwd: root,
68
+ env: { ...env, ...managedProxyEnvForChild(env) },
69
+ onStdout,
70
+ onStderr,
71
+ timeoutMs: effectiveTimeoutMs,
72
+ maxOutputBytes: maxBufferBytes,
73
+ stdoutFile: stdoutFile || (logDir ? path.join(logDir, 'codex.stdout.log') : undefined),
74
+ stderrFile: stderrFile || (logDir ? path.join(logDir, 'codex.stderr.log') : undefined)
75
+ });
66
76
  });
77
+ return guarded.launched
78
+ ? guarded.value
79
+ : codexLbRecoveryBlockedProcessResult(guarded.toolOutputRecovery);
67
80
  }
68
81
  //# sourceMappingURL=codex-adapter.js.map