botmux 3.9.0 → 3.9.2

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 (112) hide show
  1. package/dist/.runtime-build-id +1 -1
  2. package/dist/adapters/backend/tmux-pipe-backend.d.ts +7 -0
  3. package/dist/adapters/backend/tmux-pipe-backend.d.ts.map +1 -1
  4. package/dist/adapters/backend/tmux-pipe-backend.js +20 -0
  5. package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -1
  6. package/dist/adapters/backend/types.d.ts +12 -0
  7. package/dist/adapters/backend/types.d.ts.map +1 -1
  8. package/dist/adapters/backend/types.js.map +1 -1
  9. package/dist/adapters/cli/codex.d.ts.map +1 -1
  10. package/dist/adapters/cli/codex.js +40 -7
  11. package/dist/adapters/cli/codex.js.map +1 -1
  12. package/dist/adapters/cli/traex.d.ts.map +1 -1
  13. package/dist/adapters/cli/traex.js +87 -87
  14. package/dist/adapters/cli/traex.js.map +1 -1
  15. package/dist/cli/deferred-topic-send.d.ts +11 -0
  16. package/dist/cli/deferred-topic-send.d.ts.map +1 -1
  17. package/dist/cli/deferred-topic-send.js +21 -4
  18. package/dist/cli/deferred-topic-send.js.map +1 -1
  19. package/dist/cli.d.ts.map +1 -1
  20. package/dist/cli.js +177 -38
  21. package/dist/cli.js.map +1 -1
  22. package/dist/core/command-handler.d.ts.map +1 -1
  23. package/dist/core/command-handler.js +40 -1
  24. package/dist/core/command-handler.js.map +1 -1
  25. package/dist/core/dispatch.d.ts +43 -5
  26. package/dist/core/dispatch.d.ts.map +1 -1
  27. package/dist/core/dispatch.js +104 -6
  28. package/dist/core/dispatch.js.map +1 -1
  29. package/dist/core/passthrough-commands.d.ts.map +1 -1
  30. package/dist/core/passthrough-commands.js +1 -1
  31. package/dist/core/passthrough-commands.js.map +1 -1
  32. package/dist/daemon.d.ts +11 -1
  33. package/dist/daemon.d.ts.map +1 -1
  34. package/dist/daemon.js +32 -3
  35. package/dist/daemon.js.map +1 -1
  36. package/dist/i18n/en.d.ts.map +1 -1
  37. package/dist/i18n/en.js +2 -0
  38. package/dist/i18n/en.js.map +1 -1
  39. package/dist/i18n/zh.d.ts.map +1 -1
  40. package/dist/i18n/zh.js +2 -0
  41. package/dist/i18n/zh.js.map +1 -1
  42. package/dist/im/lark/card-handler.d.ts.map +1 -1
  43. package/dist/im/lark/card-handler.js +9 -0
  44. package/dist/im/lark/card-handler.js.map +1 -1
  45. package/dist/im/lark/issue-card.d.ts +223 -0
  46. package/dist/im/lark/issue-card.d.ts.map +1 -0
  47. package/dist/im/lark/issue-card.js +542 -0
  48. package/dist/im/lark/issue-card.js.map +1 -0
  49. package/dist/im/lark/issue-command-deps.d.ts +41 -0
  50. package/dist/im/lark/issue-command-deps.d.ts.map +1 -0
  51. package/dist/im/lark/issue-command-deps.js +195 -0
  52. package/dist/im/lark/issue-command-deps.js.map +1 -0
  53. package/dist/im/lark/issue-command.d.ts +137 -0
  54. package/dist/im/lark/issue-command.d.ts.map +1 -0
  55. package/dist/im/lark/issue-command.js +335 -0
  56. package/dist/im/lark/issue-command.js.map +1 -0
  57. package/dist/platform/issue-client.d.ts +201 -0
  58. package/dist/platform/issue-client.d.ts.map +1 -0
  59. package/dist/platform/issue-client.js +142 -0
  60. package/dist/platform/issue-client.js.map +1 -0
  61. package/dist/platform/platform-http.d.ts +4 -0
  62. package/dist/platform/platform-http.d.ts.map +1 -1
  63. package/dist/platform/platform-http.js +38 -2
  64. package/dist/platform/platform-http.js.map +1 -1
  65. package/dist/services/codex-composer-state.d.ts +27 -0
  66. package/dist/services/codex-composer-state.d.ts.map +1 -0
  67. package/dist/services/codex-composer-state.js +53 -0
  68. package/dist/services/codex-composer-state.js.map +1 -0
  69. package/dist/services/codex-transcript.d.ts +33 -12
  70. package/dist/services/codex-transcript.d.ts.map +1 -1
  71. package/dist/services/codex-transcript.js +82 -20
  72. package/dist/services/codex-transcript.js.map +1 -1
  73. package/dist/services/issue-board-store.d.ts +214 -0
  74. package/dist/services/issue-board-store.d.ts.map +1 -0
  75. package/dist/services/issue-board-store.js +472 -0
  76. package/dist/services/issue-board-store.js.map +1 -0
  77. package/dist/services/issue-claim-flow.d.ts +160 -0
  78. package/dist/services/issue-claim-flow.d.ts.map +1 -0
  79. package/dist/services/issue-claim-flow.js +222 -0
  80. package/dist/services/issue-claim-flow.js.map +1 -0
  81. package/dist/services/issue-outbox-pump.d.ts +25 -0
  82. package/dist/services/issue-outbox-pump.d.ts.map +1 -0
  83. package/dist/services/issue-outbox-pump.js +102 -0
  84. package/dist/services/issue-outbox-pump.js.map +1 -0
  85. package/dist/services/issue-release.d.ts +78 -0
  86. package/dist/services/issue-release.d.ts.map +1 -0
  87. package/dist/services/issue-release.js +89 -0
  88. package/dist/services/issue-release.js.map +1 -0
  89. package/dist/services/issue-report.d.ts +72 -0
  90. package/dist/services/issue-report.d.ts.map +1 -0
  91. package/dist/services/issue-report.js +84 -0
  92. package/dist/services/issue-report.js.map +1 -0
  93. package/dist/services/issue-status-view.d.ts +52 -0
  94. package/dist/services/issue-status-view.d.ts.map +1 -0
  95. package/dist/services/issue-status-view.js +42 -0
  96. package/dist/services/issue-status-view.js.map +1 -0
  97. package/dist/services/issue-status-writer.d.ts +98 -0
  98. package/dist/services/issue-status-writer.d.ts.map +1 -0
  99. package/dist/services/issue-status-writer.js +123 -0
  100. package/dist/services/issue-status-writer.js.map +1 -0
  101. package/dist/services/traex-paths.d.ts +14 -2
  102. package/dist/services/traex-paths.d.ts.map +1 -1
  103. package/dist/services/traex-paths.js +16 -2
  104. package/dist/services/traex-paths.js.map +1 -1
  105. package/dist/services/traex-transcript.d.ts +33 -0
  106. package/dist/services/traex-transcript.d.ts.map +1 -1
  107. package/dist/services/traex-transcript.js +135 -28
  108. package/dist/services/traex-transcript.js.map +1 -1
  109. package/dist/setup/lark-scopes.json +0 -2
  110. package/dist/worker.js +269 -7
  111. package/dist/worker.js.map +1 -1
  112. package/package.json +1 -1
@@ -155,6 +155,76 @@ export function traexRolloutHasUserInputSince(path, fromOffset, expectedText) {
155
155
  const expected = normaliseInputText(expectedText);
156
156
  return drainTraexRollout(path, fromOffset).events.some(event => event.kind === 'user' && normaliseInputText(event.text) === expected);
157
157
  }
158
+ function readTraexHistorySid(parsed) {
159
+ return parsed && typeof parsed === 'object' && typeof parsed.session_id === 'string'
160
+ ? parsed.session_id
161
+ : undefined;
162
+ }
163
+ /** Scan the byte delta appended to history.jsonl since `fromByte` for a line
164
+ * whose decoded `text` exactly matches `expectedText` (newline-normalised).
165
+ * Never parses a non-newline-terminated tail, so a half-written line can't
166
+ * manufacture a false match — a later poll sees the completed entry. */
167
+ export function traexHistoryMatchDelta(path, fromByte, expectedText, acceptSid) {
168
+ if (!existsSync(path))
169
+ return { found: false };
170
+ let size;
171
+ try {
172
+ size = statSync(path).size;
173
+ }
174
+ catch {
175
+ return { found: false };
176
+ }
177
+ if (size <= fromByte)
178
+ return { found: false };
179
+ const len = size - fromByte;
180
+ const buf = Buffer.alloc(len);
181
+ const fd = openSync(path, 'r');
182
+ try {
183
+ readSync(fd, buf, 0, len, fromByte);
184
+ }
185
+ finally {
186
+ closeSync(fd);
187
+ }
188
+ const delta = buf.toString('utf8');
189
+ // Drop a trailing partial line (no newline yet) — it may still be mid-write.
190
+ const lines = delta.endsWith('\n') ? delta.split('\n') : delta.split('\n').slice(0, -1);
191
+ const expected = normaliseInputText(expectedText);
192
+ for (const line of lines) {
193
+ if (line.length === 0)
194
+ continue;
195
+ let parsed;
196
+ try {
197
+ parsed = JSON.parse(line);
198
+ }
199
+ catch {
200
+ continue;
201
+ }
202
+ if (typeof parsed?.text !== 'string')
203
+ continue;
204
+ if (normaliseInputText(parsed.text) !== expected)
205
+ continue;
206
+ const cliSessionId = readTraexHistorySid(parsed);
207
+ // Skip a same-text line owned by a DIFFERENT pane (shared-TRAE_HOME
208
+ // collision). Keep scanning — the owned line may be later in this delta
209
+ // or arrive on a later poll.
210
+ if (acceptSid && !acceptSid(cliSessionId))
211
+ continue;
212
+ return { found: true, cliSessionId };
213
+ }
214
+ return { found: false };
215
+ }
216
+ /** Current byte size of history.jsonl (0 when absent), captured before a paste
217
+ * so the confirmation scan only considers lines this submit appends. */
218
+ export function traexHistorySize(path) {
219
+ if (!path || !existsSync(path))
220
+ return 0;
221
+ try {
222
+ return statSync(path).size;
223
+ }
224
+ catch {
225
+ return 0;
226
+ }
227
+ }
158
228
  function matchTraexRolloutPath(target) {
159
229
  if (!target.endsWith('.jsonl'))
160
230
  return undefined;
@@ -172,57 +242,94 @@ function matchTraexRolloutPath(target) {
172
242
  return undefined;
173
243
  return { path: target, cliSessionId: sid };
174
244
  }
175
- /** Find the rollout file an externally-running TRAE process has open.
176
- * Same /proc/<pid>/fd strategy as findCodexRolloutByPid, but with a
177
- * TRAE-specific path matcher so we never bind to a sibling Codex pane. */
178
- export function findTraexRolloutByPid(pid) {
245
+ /** Enumerate the file paths a pid holds open (Linux /proc, else lsof). Shared
246
+ * by findTraexRolloutByPid (single) and findTraexRolloutSetByPid (ownership
247
+ * set) so both derive from one source. Returns undefined when enumeration is
248
+ * unavailable callers treat that as "cannot prove ownership". */
249
+ function traexProcessOpenTargets(pid) {
179
250
  if (!Number.isInteger(pid) || pid <= 0)
180
251
  return undefined;
181
252
  if (IS_LINUX) {
182
253
  const fdDir = `/proc/${pid}/fd`;
183
- if (existsSync(fdDir)) {
184
- let entries;
254
+ if (!existsSync(fdDir))
255
+ return undefined;
256
+ let entries;
257
+ try {
258
+ entries = readdirSync(fdDir);
259
+ }
260
+ catch {
261
+ return undefined;
262
+ }
263
+ const targets = [];
264
+ for (const fd of entries) {
185
265
  try {
186
- entries = readdirSync(fdDir);
266
+ targets.push(readlinkSync(join(fdDir, fd)));
187
267
  }
188
268
  catch {
189
- return undefined;
190
- }
191
- for (const fd of entries) {
192
- let target;
193
- try {
194
- target = readlinkSync(join(fdDir, fd));
195
- }
196
- catch {
197
- continue;
198
- }
199
- const hit = matchTraexRolloutPath(target);
200
- if (hit)
201
- return hit;
269
+ continue;
202
270
  }
203
- return undefined;
204
271
  }
272
+ return targets;
205
273
  }
206
274
  let out;
207
275
  try {
208
- out = execSync(`lsof -p ${pid} -Fn`, {
209
- encoding: 'utf-8',
210
- stdio: ['pipe', 'pipe', 'pipe'],
211
- });
276
+ out = execSync(`lsof -p ${pid} -Fn`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
212
277
  }
213
278
  catch {
214
279
  return undefined;
215
280
  }
281
+ const targets = [];
216
282
  for (const line of out.split('\n')) {
217
- if (!line.startsWith('n/'))
218
- continue;
219
- const target = line.slice(1);
283
+ if (line.startsWith('n/'))
284
+ targets.push(line.slice(1));
285
+ }
286
+ return targets;
287
+ }
288
+ /** Find the rollout file an externally-running TRAE process has open.
289
+ * Same /proc/<pid>/fd strategy as findCodexRolloutByPid, but with a
290
+ * TRAE-specific path matcher so we never bind to a sibling Codex pane. */
291
+ export function findTraexRolloutByPid(pid) {
292
+ const targets = traexProcessOpenTargets(pid);
293
+ if (!targets)
294
+ return undefined;
295
+ for (const target of targets) {
220
296
  const hit = matchTraexRolloutPath(target);
221
297
  if (hit)
222
298
  return hit;
223
299
  }
224
300
  return undefined;
225
301
  }
302
+ /** Lowercased set of TRAE session ids whose rollout the pid holds open. The
303
+ * ownership gate for a shared-history.jsonl submit match: only a sid this pid
304
+ * actually owns is safe to accept, so a concurrent sibling pane's identical
305
+ * text can't hand back a foreign session id. Empty Set = pid holds no TRAE
306
+ * rollout; undefined = fd enumeration unavailable (callers must treat undefined
307
+ * as "cannot prove ownership" — fail closed, do not bind). Mirrors
308
+ * findCodexRolloutSetByPid. */
309
+ export function findTraexRolloutSetByPid(pid) {
310
+ const targets = traexProcessOpenTargets(pid);
311
+ if (!targets)
312
+ return undefined;
313
+ const set = new Set();
314
+ for (const target of targets) {
315
+ const hit = matchTraexRolloutPath(target);
316
+ if (hit)
317
+ set.add(hit.cliSessionId.toLowerCase());
318
+ }
319
+ return set;
320
+ }
321
+ /** Pure ownership decision: is `cliSessionId` one of the rollouts the observed
322
+ * pid holds open? `ownedRollouts` is the lowercased sid set from
323
+ * findTraexRolloutSetByPid (undefined when fd enumeration was unavailable).
324
+ * FAIL CLOSED — a missing set or a non-member id returns false so the caller
325
+ * never binds the bridge (or persists a resume id) it can't prove the pid owns.
326
+ * Extracted so the exact predicate the worker's persist/attach gates use is
327
+ * unit-testable without a live pid. Mirrors codexHistorySidIsOwned. */
328
+ export function traexHistorySidIsOwned(cliSessionId, ownedRollouts) {
329
+ if (!ownedRollouts)
330
+ return false;
331
+ return ownedRollouts.has(cliSessionId.toLowerCase());
332
+ }
226
333
  /** Locate the rollout file for a given TRAE session UUID. Filename shape is
227
334
  * identical to Codex: `rollout-<ts>-<sid>.jsonl`, so a suffix match over the
228
335
  * TRAE sessions tree is unambiguous. */
@@ -1 +1 @@
1
- {"version":3,"file":"traex-transcript.js","sourceRoot":"","sources":["../../src/services/traex-transcript.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"traex-transcript.js","sourceRoot":"","sources":["../../src/services/traex-transcript.ts"],"names":[],"mappings":"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"}
@@ -255,8 +255,6 @@
255
255
  "im:chat:read",
256
256
  "im:chat:update",
257
257
  "im:message",
258
- "im:message.group_msg:get_as_user",
259
- "im:message.p2p_msg:get_as_user",
260
258
  "im:message.pins:read",
261
259
  "im:message.pins:write_only",
262
260
  "im:message.reactions:read",
package/dist/worker.js CHANGED
@@ -54,11 +54,12 @@ import { loadDashboardSecret, loadPersistedToken } from './dashboard/auth.js';
54
54
  import { InflightInputTracker } from './core/inflight-input-tracker.js';
55
55
  import { shouldRunQuietRotation, evaluatePidResolverPullback, decideFingerprintSwitch, shouldHealAbsentBaseline, sessionIdFromJsonlPath, SESSION_ID_FILENAME_RE, } from './services/bridge-rotation-policy.js';
56
56
  import { CodexBridgeQueue } from './services/codex-bridge-queue.js';
57
+ import { detectCodexComposerState } from './services/codex-composer-state.js';
57
58
  import { generateCodexAppThreadTitle, readCodexAppThreadMetadata, setCodexAppThreadName, } from './services/codex-app-threads.js';
58
59
  import { buildBotmuxLarkNativeSessionTitle } from './core/session-title.js';
59
- import { drainCodexRollout, findCodexRolloutBySessionId, findCodexRolloutByPid, splitCodexEventsByCutoff, extractLastCodexTurn, codexSessionIdFromRolloutPath, scanCodexThreadSettings } from './services/codex-transcript.js';
60
+ import { drainCodexRollout, findCodexRolloutBySessionId, findCodexRolloutByPid, findCodexRolloutSetByPid, codexHistorySidIsOwned, splitCodexEventsByCutoff, extractLastCodexTurn, codexSessionIdFromRolloutPath, scanCodexThreadSettings } from './services/codex-transcript.js';
60
61
  import { CodexServiceTierTracker, resolveCodexServiceTierSnapshot } from './services/codex-service-tier.js';
61
- import { drainTraexRollout, findTraexRolloutBySessionId, findTraexRolloutByPid } from './services/traex-transcript.js';
62
+ import { drainTraexRollout, findTraexRolloutBySessionId, findTraexRolloutByPid, findTraexRolloutSetByPid, traexHistorySidIsOwned } from './services/traex-transcript.js';
62
63
  import { parseTraexUserInputQuestions } from './services/traex-user-input.js';
63
64
  import { cocoEventsPathForSession, drainCocoEvents, findCocoSessionByPid } from './services/coco-transcript.js';
64
65
  import { currentHermesStateOffset, drainHermesStateDb, resolveHermesStateDbPath } from './services/hermes-transcript.js';
@@ -978,6 +979,18 @@ function seedAndTrustClaudeState(statePath, workingDir, log) {
978
979
  }
979
980
  if (!data.projects || typeof data.projects !== 'object')
980
981
  data.projects = {};
982
+ // Onboarding gate: Claude Code holds the FIRST launch on a one-time
983
+ // theme/onboarding selection until `hasCompletedOnboarding:true` is on the
984
+ // top level of .claude.json. The seed above copies it from the host's
985
+ // global ~/.claude.json — but a CLEAN environment (fresh sandbox, e.g.
986
+ // core-only in riff, or any box that never ran Claude globally) has no
987
+ // global file to copy it from, so the redirected CLAUDE_CONFIG_DIR session
988
+ // would stick on that first-frame selection until a human clears it once.
989
+ // Force it here (idempotent, top-level) so a headless/programmatic first
990
+ // launch never blocks on interactive onboarding — same intent as the
991
+ // per-cwd trust-dialog acceptance below. If the seed/global already set it,
992
+ // this is a no-op.
993
+ data.hasCompletedOnboarding = true;
981
994
  let canonical = workingDir;
982
995
  try {
983
996
  canonical = realpathSync(workingDir);
@@ -1014,6 +1027,11 @@ let lastSpawnEffectiveCliSessionId;
1014
1027
  let lastSpawnDeferInitialPrompt = false;
1015
1028
  let lastSpawnQueuedInitialPrompt;
1016
1029
  let lastSpawnQueuedInitialPromptLogicalContent;
1030
+ // True when this session runs under an outer bwrap supervisor (file sandbox OR
1031
+ // Linux credential-only bwrap) — both make getChildPid() the supervisor, not the
1032
+ // CLI leaf. credentialOnlyBwrap needs host probes so it can't be recomputed from
1033
+ // cfg at gate-check time; capture the spawn-time verdict for currentTraexObservedPid.
1034
+ let lastSpawnOuterBwrapActive = false;
1017
1035
  /**
1018
1036
  * True only when {@link shouldArmSpawnArgvInitialPromptBusy} says so: argv-
1019
1037
  * baked first prompt + SessionStart ready (Grok-class). First markPromptReady
@@ -3502,7 +3520,22 @@ function codexBridgeStartTimer() {
3502
3520
  cwd: lastInitConfig?.workingDir,
3503
3521
  pid: codexAdoptPendingPid,
3504
3522
  });
3505
- if (path) {
3523
+ // Codex/TRAE defense-in-depth: resolveFileBridgePath resolves
3524
+ // sessionId-first, so a pending sid that is actually a shared-home
3525
+ // sibling's (CODEX_HOME / TRAE_HOME) would resolve to that foreign
3526
+ // rollout. Only attach when the resolved rollout's sid is one the
3527
+ // observed pid actually holds open. This poller re-runs every 1s, so a
3528
+ // lazily-opened owned fd is picked up on a later tick. Skip the gate
3529
+ // only when we have no pid to prove ownership with (keeps the sid/pid
3530
+ // resolution working for non-adopt / pid-less flows).
3531
+ const codexAttachGated = structuredBridgeIsCodex() && lastInitConfig?.adoptMode && path && currentCodexObservedPid();
3532
+ const traexAttachGated = structuredBridgeIsTraex() && lastInitConfig?.adoptMode && path && currentTraexObservedPid();
3533
+ const attachOk = codexAttachGated
3534
+ ? (() => { const sid = codexSessionIdFromRolloutPath(path); return !!sid && codexHistorySidOwnedByCurrentPid(sid); })()
3535
+ : traexAttachGated
3536
+ ? (() => { const sid = codexSessionIdFromRolloutPath(path); return !!sid && traexHistorySidOwnedByCurrentPid(sid); })()
3537
+ : true;
3538
+ if (path && attachOk) {
3506
3539
  if (codexAdoptPendingPid && (lastInitConfig?.cliId === 'codex' || lastInitConfig?.cliId === 'traex')) {
3507
3540
  const discoveredSessionId = codexSessionIdFromRolloutPath(path);
3508
3541
  if (discoveredSessionId)
@@ -3747,6 +3780,86 @@ function codexBridgeDetachFile() {
3747
3780
  codexBridgePendingTail = '';
3748
3781
  codexBridgeBaselineDone = false;
3749
3782
  }
3783
+ /** Resolve the pid of the Codex process this worker observes (spawned child or
3784
+ * adopted pane), mirroring the grok/traex pid-follow resolution order. */
3785
+ function currentCodexObservedPid() {
3786
+ return backend?.cliPid
3787
+ ?? backend?.getChildPid?.()
3788
+ ?? codexAdoptPendingPid;
3789
+ }
3790
+ /** Ownership gate for binding a Codex bridge to a session id that came from the
3791
+ * GLOBAL history.jsonl. That file is shared by every Codex pane under one
3792
+ * CODEX_HOME, so a concurrent sibling pane submitting identical text can make
3793
+ * writeInput's history match return a FOREIGN session id. Before attaching (or
3794
+ * re-attaching) to such an id we require it to be one THIS pid actually holds
3795
+ * open. findCodexRolloutSetByPid returns every open rollout (it does NOT
3796
+ * collapse the legitimate parent+sibling multi-rollout case to undefined the
3797
+ * way findCodexRolloutByPid does), so membership admits the authoritative id
3798
+ * and rejects a foreign one. FAIL CLOSED: an unavailable fd enumeration
3799
+ * (undefined) or a non-member id returns false → caller must not bind.
3800
+ *
3801
+ * The pure decision (sid ∈ owned set) lives in codexHistorySidIsOwned so it can
3802
+ * be unit-tested without spawning a worker; this wrapper only supplies the live
3803
+ * pid + fd-set. BOTH production attach entry points (the notify re-attach branch
3804
+ * AND the initial-attach guard) call this one wrapper — there is no parallel
3805
+ * decision copy that could drift. */
3806
+ function codexHistorySidOwnedByCurrentPid(cliSessionId) {
3807
+ const pid = currentCodexObservedPid();
3808
+ const ownedRollouts = pid ? findCodexRolloutSetByPid(pid) : undefined;
3809
+ const owned = codexHistorySidIsOwned(cliSessionId, ownedRollouts);
3810
+ if (!owned) {
3811
+ log(`Codex session id ${cliSessionId} not owned by pid ${pid ?? '?'} (open rollouts: ${ownedRollouts ? [...ownedRollouts].join(',') || 'none' : 'unknown'})`);
3812
+ }
3813
+ return owned;
3814
+ }
3815
+ /** Resolve the pid that actually holds a TRAE rollout open, given a candidate
3816
+ * that may be a bwrap supervisor. Under the file sandbox, botmux launches
3817
+ * `bwrap --unshare-pid -- traex`, so the tmux pane leaf / getChildPid() is the
3818
+ * bwrap process — its /proc/<pid>/fd holds no rollout, and the ownership gate
3819
+ * would always fail. The real traex leaf is host-visible across the pid ns
3820
+ * (ps -A ppid links), so a comm-based BFS descends to it. Outside the sandbox
3821
+ * (or if traex hasn't been forked yet) the candidate already is the leaf, so
3822
+ * we return it unchanged — fail closed to the launcher pid rather than guess. */
3823
+ function resolveTraexOwnershipPid(candidatePid, sandbox) {
3824
+ if (!sandbox || !candidatePid)
3825
+ return candidatePid;
3826
+ return findLaunchedCliPid(candidatePid, 'traex') ?? candidatePid;
3827
+ }
3828
+ /** TRAE counterpart of currentCodexObservedPid: the pid of the TRAE process
3829
+ * this worker observes (spawned child or adopted pane). Same resolution order
3830
+ * — the wired backend.cliPid first, then the live pane child pid, then the
3831
+ * adopt-pending pid (which is populated for TRAE too, see the codex/traex
3832
+ * branch around line 3674). backend.cliPid is already sandbox-resolved at wire
3833
+ * time; the getChildPid() fallback is not, so descend it here too (no-op
3834
+ * outside the sandbox / when already a leaf). */
3835
+ function currentTraexObservedPid() {
3836
+ const wired = backend?.cliPid;
3837
+ if (wired)
3838
+ return wired;
3839
+ const child = backend?.getChildPid?.();
3840
+ if (child)
3841
+ return resolveTraexOwnershipPid(child, lastSpawnOuterBwrapActive);
3842
+ return codexAdoptPendingPid;
3843
+ }
3844
+ /** Ownership gate for binding a TRAE session id that came from the GLOBAL
3845
+ * history.jsonl (shared by every TRAE pane under one TRAE_HOME). A concurrent
3846
+ * sibling pane submitting identical text — e.g. a bare "继续" in adopt mode,
3847
+ * which carries no unique <session_id> — can make writeInput's history match
3848
+ * surface a FOREIGN session id. Before persisting it (resume target) or
3849
+ * (re-)attaching the transcript bridge, require the id to be one THIS pid
3850
+ * actually holds open. FAIL CLOSED: unavailable fd enumeration (undefined set)
3851
+ * or a non-member id → false, so the caller keeps its current binding. Mirrors
3852
+ * codexHistorySidOwnedByCurrentPid; the pure decision lives in
3853
+ * traexHistorySidIsOwned for unit testing without a live pid. */
3854
+ function traexHistorySidOwnedByCurrentPid(cliSessionId) {
3855
+ const pid = currentTraexObservedPid();
3856
+ const ownedRollouts = pid ? findTraexRolloutSetByPid(pid) : undefined;
3857
+ const owned = traexHistorySidIsOwned(cliSessionId, ownedRollouts);
3858
+ if (!owned) {
3859
+ log(`TRAE session id ${cliSessionId} not owned by pid ${pid ?? '?'} (open rollouts: ${ownedRollouts ? [...ownedRollouts].join(',') || 'none' : 'unknown'})`);
3860
+ }
3861
+ return owned;
3862
+ }
3750
3863
  /** Called from flushPending after writeInput first returns a cliSessionId.
3751
3864
  * Tries to locate the rollout file immediately; if it's not on disk yet,
3752
3865
  * remembers the sid so the 1s poller can keep retrying. */
@@ -3754,12 +3867,67 @@ function codexBridgeNotifyCliSessionId(cliSessionId) {
3754
3867
  if (!codexBridgeFallbackActive())
3755
3868
  return;
3756
3869
  if (codexBridgeRolloutPath) {
3870
+ // A Codex process can keep its parent and sibling-agent rollouts open at
3871
+ // the same time. Pre-submit pid discovery therefore may have attached an
3872
+ // adopted pane to an unverified sibling transcript. writeInput returns a
3873
+ // visible-session id, but that id comes from the GLOBAL history.jsonl
3874
+ // (one file shared by every Codex pane under a CODEX_HOME): a concurrent
3875
+ // sibling pane submitting identical text can make writeInput return the
3876
+ // WRONG (foreign) session id. So the reported id is only a CANDIDATE —
3877
+ // gate the re-attach on pid fd ownership below.
3878
+ //
3879
+ // Not draining the retired rollout before detach is safe here (NOT because
3880
+ // "the old path is proven foreign" — Codex /new · /clear · /resume are
3881
+ // legitimate same-process rotations): prepareAdoptWrite() ran
3882
+ // codexBridgeIngest() before this turn's mark+write, codexBridgeDetachFile()
3883
+ // preserves codexBridgeQueue (already-ingested terminals survive the
3884
+ // re-attach), and a rotated-away rollout is quiescent before the next prompt
3885
+ // is submitted — so there is no post-ingest window in which a legitimate
3886
+ // terminal is appended to the old path and lost.
3887
+ if (structuredBridgeIsCodex()) {
3888
+ const currentSid = codexSessionIdFromRolloutPath(codexBridgeRolloutPath);
3889
+ if (currentSid?.toLowerCase() === cliSessionId.toLowerCase())
3890
+ return;
3891
+ // Ownership gate: only re-attach to a session id THIS pid actually holds
3892
+ // open (admits the real parent+sibling multi-rollout case, rejects a
3893
+ // foreign id from another pane's identical-text history line). Fail
3894
+ // closed: keep the current binding when unowned/unknown.
3895
+ if (!codexHistorySidOwnedByCurrentPid(cliSessionId)) {
3896
+ log(`Keeping current Codex bridge ${currentSid ?? '?'} — refusing history-only re-attach to ${cliSessionId}`);
3897
+ return;
3898
+ }
3899
+ const pid = currentCodexObservedPid();
3900
+ const next = resolveFileBridgePath('codex', { sessionId: cliSessionId });
3901
+ if (next && next !== codexBridgeRolloutPath) {
3902
+ const attachMode = lastInitConfig?.adoptMode ? 'split-live' : 'fresh-empty';
3903
+ log(`Codex session binding corrected ${currentSid ?? '?'} → ${cliSessionId} (pid ${pid} owns it); re-attaching bridge to ${next}`);
3904
+ codexBridgeDetachFile();
3905
+ codexBridgePendingSessionId = undefined;
3906
+ codexBridgeAttach(next, attachMode);
3907
+ }
3908
+ else if (!next) {
3909
+ log(`Codex session binding corrected ${currentSid ?? '?'} → ${cliSessionId} (pid ${pid} owns it); waiting for rollout`);
3910
+ codexBridgeDetachFile();
3911
+ codexBridgePendingSessionId = cliSessionId;
3912
+ codexBridgeStartTimer();
3913
+ }
3914
+ return;
3915
+ }
3757
3916
  // Already attached — first-attach-wins for most CLIs. Exceptions: TRAE
3758
3917
  // and Grok can rotate their native session in the same process.
3759
3918
  if (structuredBridgeIsTraex()) {
3760
3919
  const currentSid = codexSessionIdFromRolloutPath(codexBridgeRolloutPath);
3761
3920
  if (currentSid && currentSid.toLowerCase() === cliSessionId.toLowerCase())
3762
3921
  return;
3922
+ // Ownership gate: the reported id came from the GLOBAL history.jsonl, so a
3923
+ // sibling pane's identical text (e.g. a bare adopt-mode reply with no
3924
+ // unique <session_id>) could surface a foreign id. Only rotate the bridge
3925
+ // to a rollout THIS pid holds open; otherwise keep the current binding
3926
+ // (fail closed on unknown/unowned). Mirrors the codex branch above.
3927
+ if (!traexHistorySidOwnedByCurrentPid(cliSessionId)) {
3928
+ log(`Keeping current TRAE bridge ${currentSid ?? '?'} — refusing history-only re-attach to ${cliSessionId}`);
3929
+ return;
3930
+ }
3763
3931
  const next = resolveFileBridgePath('traex', { sessionId: cliSessionId });
3764
3932
  // Close any terminal already committed to the retired rollout before
3765
3933
  // switching. A durable turn is a worker HOL barrier, so a legitimate
@@ -3860,6 +4028,38 @@ function codexBridgeNotifyCliSessionId(cliSessionId) {
3860
4028
  }
3861
4029
  return;
3862
4030
  }
4031
+ // Codex INITIAL attach (no prior rollout bound). The multi-fd adopt case
4032
+ // reaches here with codexBridgeRolloutPath still unset: findCodexRolloutByPid
4033
+ // returned undefined (ambiguous parent+sibling), so the adopt block armed the
4034
+ // poller instead of attaching. The cliSessionId is normally already
4035
+ // source-filtered by the codex adapter (writeInput only returns an owned sid),
4036
+ // but keep a defense-in-depth ownership gate here too so a sid from any other
4037
+ // path can't first-attach the shared-history foreign session. Fail closed:
4038
+ // when the sid isn't provably owned, DON'T pin it as pending (that would wedge
4039
+ // the bridge — the poller's pid fallback stays ambiguous→undefined forever and
4040
+ // the owned line never re-triggers this callback). Keep the adopt pid pending
4041
+ // so the poller can bind once a uniquely-owned rollout appears.
4042
+ if (structuredBridgeIsCodex() && lastInitConfig?.adoptMode && currentCodexObservedPid()) {
4043
+ if (!codexHistorySidOwnedByCurrentPid(cliSessionId)) {
4044
+ log(`Codex initial-attach refused for unverified session ${cliSessionId}; keeping poller armed on pid ${currentCodexObservedPid()}`);
4045
+ codexBridgePendingSessionId = undefined;
4046
+ codexBridgeStartTimer();
4047
+ return;
4048
+ }
4049
+ }
4050
+ // TRAE INITIAL attach: same shared-history.jsonl hazard as codex above. The
4051
+ // TRAE adapter only returns an owned sid, but keep a defense-in-depth gate so
4052
+ // a foreign sid from any other path can't first-attach the bridge in adopt
4053
+ // mode. Fail closed identically: keep the poller armed on the adopt pid rather
4054
+ // than pinning an unverified sid (which would wedge the bridge).
4055
+ if (structuredBridgeIsTraex() && lastInitConfig?.adoptMode && currentTraexObservedPid()) {
4056
+ if (!traexHistorySidOwnedByCurrentPid(cliSessionId)) {
4057
+ log(`TRAE initial-attach refused for unverified session ${cliSessionId}; keeping poller armed on pid ${currentTraexObservedPid()}`);
4058
+ codexBridgePendingSessionId = undefined;
4059
+ codexBridgeStartTimer();
4060
+ return;
4061
+ }
4062
+ }
3863
4063
  const path = resolveFileBridgePath(lastInitConfig?.cliId, {
3864
4064
  sessionId: cliSessionId,
3865
4065
  cwd: lastInitConfig?.workingDir,
@@ -5461,6 +5661,14 @@ function adapterInputHandle(target) {
5461
5661
  ? strictInputHandle(target)
5462
5662
  : target;
5463
5663
  }
5664
+ function codexAdoptComposerConflict(target) {
5665
+ if (lastInitConfig?.cliId !== 'codex' || !lastInitConfig.adoptMode)
5666
+ return undefined;
5667
+ const state = detectCodexComposerState(target.captureInputState?.());
5668
+ if (state !== 'draft')
5669
+ return undefined;
5670
+ return t('worker.codex_composer_conflict');
5671
+ }
5464
5672
  let ambiguousSubmissionWriteTail = Promise.resolve();
5465
5673
  /** A logical input that was definitely not written because this exact backend
5466
5674
  * already carried older composer-recovery debt. Keep it queued, but freeze all
@@ -9230,17 +9438,62 @@ async function spawnCli(cfg, opts = {}) {
9230
9438
  startWrapperRealPidResolve(cliPid);
9231
9439
  if (cliPid)
9232
9440
  observeCursorCliSessionId(cliPid);
9441
+ // File sandbox / Linux credential-only bwrap launches `bwrap --unshare-pid --
9442
+ // traex`, so the pane leaf (getChildPid) is the bwrap SUPERVISOR — its
9443
+ // /proc/<pid>/fd holds no rollout and the TRAE ownership gate can never admit
9444
+ // a session id (fresh sandbox TRAE then never captures its SID, the bridge
9445
+ // never attaches, and because reliableTurnTerminal disables screen-idle the
9446
+ // durable turn can wedge — it does NOT self-heal). The real traex leaf is
9447
+ // host-visible across the pid ns (ps -A ppid links), so BFS-descend to it and
9448
+ // rewire backend.cliPid. Bounded retry (not one-shot): bwrap may not have
9449
+ // forked traex yet at spawn. Reuses scheduleWrapperRealCliPid's stale-backend
9450
+ // guard so a mid-retry worker restart can't rewire the new session. Gated on
9451
+ // outerBwrapActive — sandboxRequested OR the Linux credential-only bwrap path,
9452
+ // both of which produce an outer supervisor pid. */
9453
+ const outerBwrapActive = sandboxRequested || credentialOnlyBwrap;
9454
+ lastSpawnOuterBwrapActive = outerBwrapActive;
9455
+ const startTraexSandboxPidResolve = (launcherPid) => {
9456
+ if (cfg.cliId !== 'traex' || !outerBwrapActive)
9457
+ return;
9458
+ scheduleWrapperRealCliPid(launcherPid, {
9459
+ findRealPid: (lp) => findLaunchedCliPid(lp, 'traex'),
9460
+ getBackend: () => backend,
9461
+ getChildPid: () => backend?.getChildPid?.(),
9462
+ applyRealPid: (realPid) => {
9463
+ log(`TRAE sandbox: resolved real traex leaf pid ${realPid} under bwrap supervisor ${launcherPid}; rewiring ownership pid`);
9464
+ backend.cliPid = realPid;
9465
+ backend.cliCwd = cfg.workingDir;
9466
+ publishLocalProcessAttestation(realPid);
9467
+ },
9468
+ schedule: (fn, ms) => { setTimeout(fn, ms); },
9469
+ });
9470
+ };
9233
9471
  // Wire pid + cwd so adapters' writeInput can bind submits to this process:
9234
9472
  // - claude-code: ~/.claude/sessions/<pid>.json
9235
9473
  // - grok: findGrokSessionByPid → preferSessionId against shared
9236
9474
  // prompt_history (concurrent same-cwd workers must not cross-claim)
9475
+ // - traex: findTraexRolloutSetByPid → ownership gate for the shared global
9476
+ // history.jsonl (concurrent same-TRAE_HOME panes must not cross-claim a
9477
+ // sibling's session id from an identical-text submit). getChildPid() is
9478
+ // normally the traex process itself, EXCEPT under the file sandbox: bwrap
9479
+ // runs `--unshare-pid -- traex`, so the pane leaf is the bwrap supervisor
9480
+ // and /proc/<bwrap>/fd holds no rollout. resolveTraexOwnershipPid() BFS-
9481
+ // descends to the real traex leaf (host-visible across the pid ns via
9482
+ // `ps -A` ppid links) so the ownership gate can actually admit the id;
9483
+ // it fails closed to the launcher pid when no leaf is found yet (the async
9484
+ // retry below re-resolves once bwrap has forked traex).
9237
9485
  // Claude's sessionId is set ONCE at process start (2.1.123); a `--resume`
9238
9486
  // lookup will surface here, but in-pane `/clear` won't. The pinned
9239
9487
  // claudeJsonlPath above is still the initial guess; the resolver corrects
9240
9488
  // it on first write when Claude was started with `--resume`.
9241
- if (cliPid && (claudeDataDir || cfg.cliId === 'grok')) {
9242
- backend.cliPid = cliPid;
9489
+ if (cliPid && (claudeDataDir || cfg.cliId === 'grok' || cfg.cliId === 'traex')) {
9490
+ // TRAE under outer bwrap: best-effort immediate resolve (leaf may already be
9491
+ // forked), then a bounded retry below covers the not-yet-forked case.
9492
+ const wiredPid = cfg.cliId === 'traex' ? resolveTraexOwnershipPid(cliPid, outerBwrapActive) : cliPid;
9493
+ backend.cliPid = wiredPid;
9243
9494
  backend.cliCwd = cfg.workingDir;
9495
+ if (cfg.cliId === 'traex' && outerBwrapActive)
9496
+ startTraexSandboxPidResolve(cliPid);
9244
9497
  }
9245
9498
  // Async pid fallback: tmux/pty resolve the CLI pid synchronously above, but
9246
9499
  // zellij's CLI subprocess starts AFTER spawn() returns (the zellij server
@@ -9269,9 +9522,12 @@ async function spawnCli(cfg, opts = {}) {
9269
9522
  log(`Failed to write CLI PID marker (async): ${err.message}`);
9270
9523
  }
9271
9524
  }
9272
- if (claudeDataDir || cfg.cliId === 'grok') {
9273
- backend.cliPid = pid;
9525
+ if (claudeDataDir || cfg.cliId === 'grok' || cfg.cliId === 'traex') {
9526
+ const wiredPid = cfg.cliId === 'traex' ? resolveTraexOwnershipPid(pid, outerBwrapActive) : pid;
9527
+ backend.cliPid = wiredPid;
9274
9528
  backend.cliCwd = cfg.workingDir;
9529
+ if (cfg.cliId === 'traex' && outerBwrapActive)
9530
+ startTraexSandboxPidResolve(pid);
9275
9531
  }
9276
9532
  // wrapperCli under a late-pid backend (zellij): `pid` here is still the
9277
9533
  // LAUNCHER. Kick the descendant resolver so the bridge gets the real CLI
@@ -11684,6 +11940,12 @@ process.on('message', async (raw) => {
11684
11940
  const submissionBackend = backend;
11685
11941
  const submissionAdapter = cliAdapter;
11686
11942
  let recoveryFailureReason;
11943
+ const composerConflict = codexAdoptComposerConflict(submissionBackend);
11944
+ if (composerConflict) {
11945
+ log('Refused Codex adopt input because the local composer contains an unsubmitted draft');
11946
+ scheduleSubmitFailureNotify(content, undefined, 'submit history', undefined, composerConflict, turnSeq, msg, 'failed');
11947
+ return;
11948
+ }
11687
11949
  try {
11688
11950
  const transaction = await runAmbiguousSubmissionTransaction(submissionBackend, () => submissionAdapter.writeInput(adapterInputHandle(submissionBackend), content), settleVerifiableSubmissionForJournal, prepareAdoptWrite);
11689
11951
  const result = transaction.result;