oh-my-codex 0.20.2 → 0.20.3
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/Cargo.lock +7 -6
- package/Cargo.toml +1 -1
- package/README.md +26 -0
- package/crates/omx-runtime/Cargo.toml +1 -0
- package/crates/omx-runtime/src/main.rs +25 -2
- package/crates/omx-runtime/tests/execution.rs +219 -0
- package/crates/omx-runtime-core/src/dispatch.rs +96 -10
- package/crates/omx-runtime-core/src/engine.rs +839 -29
- package/crates/omx-runtime-core/src/lib.rs +8 -0
- package/dist/agents/__tests__/definitions.test.js +81 -0
- package/dist/agents/__tests__/definitions.test.js.map +1 -1
- package/dist/agents/__tests__/native-config.test.js +25 -0
- package/dist/agents/__tests__/native-config.test.js.map +1 -1
- package/dist/agents/native-config.d.ts +2 -1
- package/dist/agents/native-config.d.ts.map +1 -1
- package/dist/agents/native-config.js.map +1 -1
- package/dist/auth/hotswap.d.ts +6 -0
- package/dist/auth/hotswap.d.ts.map +1 -1
- package/dist/auth/hotswap.js +85 -15
- package/dist/auth/hotswap.js.map +1 -1
- package/dist/autopilot/__tests__/ralplan-gate.test.js +1 -1
- package/dist/autopilot/__tests__/ralplan-gate.test.js.map +1 -1
- package/dist/cli/__tests__/auth.test.js +60 -6
- package/dist/cli/__tests__/auth.test.js.map +1 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js +80 -0
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js +103 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/exec.test.js +136 -0
- package/dist/cli/__tests__/exec.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +258 -4
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/launch-fallback.test.js +287 -1
- package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
- package/dist/cli/__tests__/mcp-parity.test.js +4 -1
- package/dist/cli/__tests__/mcp-parity.test.js.map +1 -1
- package/dist/cli/__tests__/native-hook-claim-journal.test.js +84 -6
- package/dist/cli/__tests__/native-hook-claim-journal.test.js.map +1 -1
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +3 -3
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
- package/dist/cli/__tests__/ralph.test.js +3 -3
- package/dist/cli/__tests__/ralph.test.js.map +1 -1
- package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js +56 -171
- package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js.map +1 -1
- package/dist/cli/__tests__/ralplan.test.js +37 -111
- package/dist/cli/__tests__/ralplan.test.js.map +1 -1
- package/dist/cli/__tests__/resume.test.js +11 -10
- package/dist/cli/__tests__/resume.test.js.map +1 -1
- package/dist/cli/__tests__/session-search-help.test.js +25 -1
- package/dist/cli/__tests__/session-search-help.test.js.map +1 -1
- package/dist/cli/__tests__/setup-install-mode.test.js +42 -4
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
- package/dist/cli/__tests__/team.test.js +105 -7
- package/dist/cli/__tests__/team.test.js.map +1 -1
- package/dist/cli/__tests__/uninstall.test.js +46 -0
- package/dist/cli/__tests__/uninstall.test.js.map +1 -1
- package/dist/cli/__tests__/windows-popup-loop-contract.test.js +2 -1
- package/dist/cli/__tests__/windows-popup-loop-contract.test.js.map +1 -1
- package/dist/cli/doctor.d.ts +3 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +15 -2
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.d.ts +4 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +138 -38
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-parity.js +2 -2
- package/dist/cli/mcp-parity.js.map +1 -1
- package/dist/cli/native-hook-claim-journal.d.ts +16 -5
- package/dist/cli/native-hook-claim-journal.d.ts.map +1 -1
- package/dist/cli/native-hook-claim-journal.js +42 -29
- package/dist/cli/native-hook-claim-journal.js.map +1 -1
- package/dist/cli/ralph.js +2 -2
- package/dist/cli/ralph.js.map +1 -1
- package/dist/cli/ralplan.d.ts +4 -8
- package/dist/cli/ralplan.d.ts.map +1 -1
- package/dist/cli/ralplan.js +19 -112
- package/dist/cli/ralplan.js.map +1 -1
- package/dist/cli/session-search.d.ts +5 -0
- package/dist/cli/session-search.d.ts.map +1 -1
- package/dist/cli/session-search.js +87 -0
- package/dist/cli/session-search.js.map +1 -1
- package/dist/cli/setup.d.ts +5 -0
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +80 -31
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/uninstall.d.ts +9 -0
- package/dist/cli/uninstall.d.ts.map +1 -1
- package/dist/cli/uninstall.js +61 -19
- package/dist/cli/uninstall.js.map +1 -1
- package/dist/compat/__tests__/rust-runtime-compat.test.js +1 -1
- package/dist/config/__tests__/generator-idempotent.test.js +330 -1
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
- package/dist/config/__tests__/generator-notify.test.js +2 -2
- package/dist/config/__tests__/generator-notify.test.js.map +1 -1
- package/dist/config/__tests__/models.test.js +67 -3
- package/dist/config/__tests__/models.test.js.map +1 -1
- package/dist/config/generator.d.ts +4 -20
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +499 -119
- package/dist/config/generator.js.map +1 -1
- package/dist/config/models.d.ts +12 -2
- package/dist/config/models.d.ts.map +1 -1
- package/dist/config/models.js +15 -1
- package/dist/config/models.js.map +1 -1
- package/dist/hooks/__tests__/agents-overlay.test.js +2 -2
- package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +4 -4
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js +238 -543
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +38 -4
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +96 -9
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +531 -12
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +155 -23
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +482 -32
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +68 -1
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js +7 -1
- package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +43 -4
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
- package/dist/hooks/__tests__/session.test.js +348 -2
- package/dist/hooks/__tests__/session.test.js.map +1 -1
- package/dist/hooks/agents-overlay.js +1 -1
- package/dist/hooks/session.d.ts +26 -2
- package/dist/hooks/session.d.ts.map +1 -1
- package/dist/hooks/session.js +169 -13
- package/dist/hooks/session.js.map +1 -1
- package/dist/leader/__tests__/contract.test.js +57 -7
- package/dist/leader/__tests__/contract.test.js.map +1 -1
- package/dist/leader/contract.d.ts +16 -0
- package/dist/leader/contract.d.ts.map +1 -1
- package/dist/leader/contract.js +79 -4
- package/dist/leader/contract.js.map +1 -1
- package/dist/mcp/__tests__/code-intel-server.test.js +31 -3
- package/dist/mcp/__tests__/code-intel-server.test.js.map +1 -1
- package/dist/mcp/__tests__/wiki-server.test.js +18 -0
- package/dist/mcp/__tests__/wiki-server.test.js.map +1 -1
- package/dist/mcp/code-intel-server.d.ts.map +1 -1
- package/dist/mcp/code-intel-server.js +13 -3
- package/dist/mcp/code-intel-server.js.map +1 -1
- package/dist/mcp/wiki-server.d.ts +11 -0
- package/dist/mcp/wiki-server.d.ts.map +1 -1
- package/dist/mcp/wiki-server.js +9 -2
- package/dist/mcp/wiki-server.js.map +1 -1
- package/dist/modes/__tests__/base-tmux-pane.test.js +4 -4
- package/dist/modes/__tests__/base-tmux-pane.test.js.map +1 -1
- package/dist/notifications/temp-contract.d.ts.map +1 -1
- package/dist/notifications/temp-contract.js +4 -0
- package/dist/notifications/temp-contract.js.map +1 -1
- package/dist/pipeline/__tests__/orchestrator.test.js +4 -4
- package/dist/pipeline/__tests__/orchestrator.test.js.map +1 -1
- package/dist/pipeline/__tests__/stages.test.js +8 -8
- package/dist/pipeline/__tests__/stages.test.js.map +1 -1
- package/dist/ralplan/__tests__/consensus-gate.test.js +134 -10
- package/dist/ralplan/__tests__/consensus-gate.test.js.map +1 -1
- package/dist/ralplan/__tests__/documented-leader-preflight.test.d.ts +2 -0
- package/dist/ralplan/__tests__/documented-leader-preflight.test.d.ts.map +1 -0
- package/dist/ralplan/__tests__/documented-leader-preflight.test.js +46 -0
- package/dist/ralplan/__tests__/documented-leader-preflight.test.js.map +1 -0
- package/dist/ralplan/__tests__/runtime.test.js +8 -4
- package/dist/ralplan/__tests__/runtime.test.js.map +1 -1
- package/dist/ralplan/consensus-gate.d.ts.map +1 -1
- package/dist/ralplan/consensus-gate.js +58 -50
- package/dist/ralplan/consensus-gate.js.map +1 -1
- package/dist/ralplan/documented-leader-preflight.d.ts +34 -0
- package/dist/ralplan/documented-leader-preflight.d.ts.map +1 -0
- package/dist/ralplan/documented-leader-preflight.js +58 -0
- package/dist/ralplan/documented-leader-preflight.js.map +1 -0
- package/dist/ralplan/runtime.d.ts +1 -0
- package/dist/ralplan/runtime.d.ts.map +1 -1
- package/dist/ralplan/runtime.js +11 -7
- package/dist/ralplan/runtime.js.map +1 -1
- package/dist/runtime/__tests__/bridge.test.js +42 -1
- package/dist/runtime/__tests__/bridge.test.js.map +1 -1
- package/dist/runtime/bridge.d.ts +12 -0
- package/dist/runtime/bridge.d.ts.map +1 -1
- package/dist/runtime/bridge.js +52 -1
- package/dist/runtime/bridge.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +2620 -487
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/reasoning-artifact-contract.test.d.ts +2 -0
- package/dist/scripts/__tests__/reasoning-artifact-contract.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/reasoning-artifact-contract.test.js +108 -0
- package/dist/scripts/__tests__/reasoning-artifact-contract.test.js.map +1 -0
- package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js +46 -173
- package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js.map +1 -1
- package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js +39 -159
- package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js.map +1 -1
- package/dist/scripts/__tests__/smoke-packed-install.test.js +254 -2
- package/dist/scripts/__tests__/smoke-packed-install.test.js.map +1 -1
- package/dist/scripts/codex-native-hook.d.ts +4 -1
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +11013 -1153
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/notify-fallback-watcher.js +82 -108
- package/dist/scripts/notify-fallback-watcher.js.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.js +74 -3
- package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/team-dispatch.d.ts +9 -0
- package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-dispatch.js +234 -79
- package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.js +39 -13
- package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.d.ts +12 -4
- package/dist/scripts/notify-hook/team-tmux-guard.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.js +365 -44
- package/dist/scripts/notify-hook/team-tmux-guard.js.map +1 -1
- package/dist/scripts/notify-hook/team-worker-stop.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-worker-stop.js +19 -18
- package/dist/scripts/notify-hook/team-worker-stop.js.map +1 -1
- package/dist/scripts/notify-hook/team-worker.d.ts +3 -0
- package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-worker.js +37 -28
- package/dist/scripts/notify-hook/team-worker.js.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.js +28 -2
- package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
- package/dist/scripts/notify-hook.js +1 -0
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/scripts/smoke-packed-install.d.ts +48 -3
- package/dist/scripts/smoke-packed-install.d.ts.map +1 -1
- package/dist/scripts/smoke-packed-install.js +2796 -13
- package/dist/scripts/smoke-packed-install.js.map +1 -1
- package/dist/state/__tests__/mode-state-context.test.js +54 -0
- package/dist/state/__tests__/mode-state-context.test.js.map +1 -1
- package/dist/state/__tests__/operations.test.js +2 -0
- package/dist/state/__tests__/operations.test.js.map +1 -1
- package/dist/state/mode-state-context.d.ts +5 -0
- package/dist/state/mode-state-context.d.ts.map +1 -1
- package/dist/state/mode-state-context.js +59 -0
- package/dist/state/mode-state-context.js.map +1 -1
- package/dist/subagents/__tests__/leader-bootstrap-3181.test.js +24 -245
- package/dist/subagents/__tests__/leader-bootstrap-3181.test.js.map +1 -1
- package/dist/subagents/tracker.d.ts +1 -82
- package/dist/subagents/tracker.d.ts.map +1 -1
- package/dist/subagents/tracker.js +3 -275
- package/dist/subagents/tracker.js.map +1 -1
- package/dist/team/__tests__/api-interop.test.js +91 -1
- package/dist/team/__tests__/api-interop.test.js.map +1 -1
- package/dist/team/__tests__/delivery-e2e-smoke.test.js +52 -10
- package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +1 -1
- package/dist/team/__tests__/idle-nudge.test.js +45 -15
- package/dist/team/__tests__/idle-nudge.test.js.map +1 -1
- package/dist/team/__tests__/mcp-comm.test.js +93 -27
- package/dist/team/__tests__/mcp-comm.test.js.map +1 -1
- package/dist/team/__tests__/model-contract.test.js +110 -3
- package/dist/team/__tests__/model-contract.test.js.map +1 -1
- package/dist/team/__tests__/runtime-cli.test.js +9 -0
- package/dist/team/__tests__/runtime-cli.test.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +3204 -335
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/scaling.test.js +2359 -142
- package/dist/team/__tests__/scaling.test.js.map +1 -1
- package/dist/team/__tests__/state.test.js +804 -36
- package/dist/team/__tests__/state.test.js.map +1 -1
- package/dist/team/__tests__/team-ops-contract.test.js +6 -0
- package/dist/team/__tests__/team-ops-contract.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +3049 -784
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/__tests__/worker-runtime-identity.test.js +38 -2
- package/dist/team/__tests__/worker-runtime-identity.test.js.map +1 -1
- package/dist/team/__tests__/worktree.test.js +6 -0
- package/dist/team/__tests__/worktree.test.js.map +1 -1
- package/dist/team/api-interop.d.ts.map +1 -1
- package/dist/team/api-interop.js +15 -9
- package/dist/team/api-interop.js.map +1 -1
- package/dist/team/exact-pane.d.ts +23 -0
- package/dist/team/exact-pane.d.ts.map +1 -0
- package/dist/team/exact-pane.js +133 -0
- package/dist/team/exact-pane.js.map +1 -0
- package/dist/team/idle-nudge.d.ts +12 -1
- package/dist/team/idle-nudge.d.ts.map +1 -1
- package/dist/team/idle-nudge.js +41 -14
- package/dist/team/idle-nudge.js.map +1 -1
- package/dist/team/model-contract.d.ts +2 -5
- package/dist/team/model-contract.d.ts.map +1 -1
- package/dist/team/model-contract.js +59 -17
- package/dist/team/model-contract.js.map +1 -1
- package/dist/team/runtime.d.ts +1 -0
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +1244 -180
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/scaling.d.ts +13 -1
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +1430 -384
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/state/dispatch.d.ts.map +1 -1
- package/dist/team/state/dispatch.js +26 -8
- package/dist/team/state/dispatch.js.map +1 -1
- package/dist/team/state/locks.d.ts.map +1 -1
- package/dist/team/state/locks.js +61 -13
- package/dist/team/state/locks.js.map +1 -1
- package/dist/team/state/tasks.d.ts.map +1 -1
- package/dist/team/state/tasks.js +4 -3
- package/dist/team/state/tasks.js.map +1 -1
- package/dist/team/state.d.ts +67 -1
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +636 -129
- package/dist/team/state.js.map +1 -1
- package/dist/team/team-ops.d.ts +5 -0
- package/dist/team/team-ops.d.ts.map +1 -1
- package/dist/team/team-ops.js +4 -0
- package/dist/team/team-ops.js.map +1 -1
- package/dist/team/tmux-session.d.ts +123 -23
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +1250 -291
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/worktree.d.ts.map +1 -1
- package/dist/team/worktree.js +4 -0
- package/dist/team/worktree.js.map +1 -1
- package/dist/utils/__tests__/file-durability.test.d.ts +2 -0
- package/dist/utils/__tests__/file-durability.test.d.ts.map +1 -0
- package/dist/utils/__tests__/file-durability.test.js +57 -0
- package/dist/utils/__tests__/file-durability.test.js.map +1 -0
- package/dist/utils/file-durability.d.ts +15 -0
- package/dist/utils/file-durability.d.ts.map +1 -0
- package/dist/utils/file-durability.js +37 -0
- package/dist/utils/file-durability.js.map +1 -0
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js +3 -0
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js.map +1 -1
- package/dist/wiki/lint.d.ts +4 -1
- package/dist/wiki/lint.d.ts.map +1 -1
- package/dist/wiki/lint.js +3 -2
- package/dist/wiki/lint.js.map +1 -1
- package/package.json +1 -1
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +24 -0
- package/plugins/oh-my-codex/skills/ralph/SKILL.md +6 -4
- package/plugins/oh-my-codex/skills/ralplan/SKILL.md +3 -2
- package/plugins/oh-my-codex/skills/team/SKILL.md +13 -9
- package/skills/ralph/SKILL.md +6 -4
- package/skills/ralplan/SKILL.md +3 -2
- package/skills/team/SKILL.md +13 -9
- package/src/scripts/__tests__/codex-native-hook.test.ts +2826 -497
- package/src/scripts/__tests__/reasoning-artifact-contract.test.ts +129 -0
- package/src/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.ts +48 -185
- package/src/scripts/__tests__/role-intent-durable-recovery-3181.test.ts +44 -177
- package/src/scripts/__tests__/smoke-packed-install.test.ts +320 -2
- package/src/scripts/codex-native-hook.ts +10715 -1069
- package/src/scripts/notify-fallback-watcher.ts +84 -115
- package/src/scripts/notify-hook/auto-nudge.ts +71 -3
- package/src/scripts/notify-hook/team-dispatch.ts +242 -75
- package/src/scripts/notify-hook/team-leader-nudge.ts +40 -18
- package/src/scripts/notify-hook/team-tmux-guard.ts +366 -39
- package/src/scripts/notify-hook/team-worker-stop.ts +20 -16
- package/src/scripts/notify-hook/team-worker.ts +39 -26
- package/src/scripts/notify-hook/tmux-injection.ts +28 -2
- package/src/scripts/notify-hook.ts +1 -0
- package/src/scripts/smoke-packed-install.ts +3196 -14
- package/dist/subagents/__tests__/adapted-role-binding.test.d.ts +0 -2
- package/dist/subagents/__tests__/adapted-role-binding.test.d.ts.map +0 -1
- package/dist/subagents/__tests__/adapted-role-binding.test.js +0 -988
- package/dist/subagents/__tests__/adapted-role-binding.test.js.map +0 -1
- package/dist/subagents/adapted-role-binding.d.ts +0 -17
- package/dist/subagents/adapted-role-binding.d.ts.map +0 -1
- package/dist/subagents/adapted-role-binding.js +0 -75
- package/dist/subagents/adapted-role-binding.js.map +0 -1
|
@@ -11,7 +11,7 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
11
11
|
const __dirname = dirname(__filename);
|
|
12
12
|
import { runProcess } from './process-runner.js';
|
|
13
13
|
import { resolvePaneTarget, resolveSessionToPane } from './tmux-injection.js';
|
|
14
|
-
import { evaluatePaneInjectionReadiness, sendPaneInput } from './team-tmux-guard.js';
|
|
14
|
+
import { EXACT_PANE_UNAVAILABLE_REASON, evaluatePaneInjectionReadiness, normalizeExactPaneId, sendPaneInput, verifyExactPaneLive, verifyExactPaneOwnerLive, } from './team-tmux-guard.js';
|
|
15
15
|
import { normalizeTmuxCapture, paneHasActiveTask, paneLooksReady, } from '../tmux-hook-engine.js';
|
|
16
16
|
/**
|
|
17
17
|
* Route dispatch state transitions through the Rust runtime binary.
|
|
@@ -419,26 +419,79 @@ async function writeBridgeDispatchCompat(stateDir, teamName, requests) {
|
|
|
419
419
|
const records = [...otherTeams, ...requests.map(serializeDispatchRequestRecord)];
|
|
420
420
|
await writeJsonAtomic(compatPath, { records });
|
|
421
421
|
}
|
|
422
|
-
function
|
|
422
|
+
function explicitPaneIdentity(value) {
|
|
423
|
+
const rawPaneId = safeString(value).trim();
|
|
424
|
+
return { provided: rawPaneId !== '', paneId: normalizeExactPaneId(rawPaneId), rawPaneId };
|
|
425
|
+
}
|
|
426
|
+
function positivePanePid(value) {
|
|
427
|
+
return Number.isInteger(value) && Number(value) > 0 ? Number(value) : undefined;
|
|
428
|
+
}
|
|
429
|
+
function resolveAddressedWorker(request, config) {
|
|
430
|
+
const workers = Array.isArray(config?.workers) ? config.workers : [];
|
|
431
|
+
if (Number.isFinite(request?.worker_index)) {
|
|
432
|
+
const worker = workers.find((candidate) => Number(candidate?.index) === Number(request.worker_index));
|
|
433
|
+
if (worker)
|
|
434
|
+
return worker;
|
|
435
|
+
}
|
|
436
|
+
const recipient = safeString(request?.to_worker).trim();
|
|
437
|
+
return workers.find((candidate) => safeString(candidate?.name).trim() === recipient) || null;
|
|
438
|
+
}
|
|
439
|
+
function resolveConfiguredPaneIdentity(request, config) {
|
|
423
440
|
if (request.to_worker === 'leader-fixed') {
|
|
424
|
-
|
|
425
|
-
if (leaderPaneId)
|
|
426
|
-
return { type: 'pane', value: leaderPaneId };
|
|
427
|
-
return null;
|
|
441
|
+
return { source: 'leader_pane_id', expectedPanePid: positivePanePid(config?.leader_pane_pid), expectedPaneOwnerId: safeString(config?.tmux_pane_owner_id).trim(), ...explicitPaneIdentity(config?.leader_pane_id) };
|
|
428
442
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
443
|
+
const worker = resolveAddressedWorker(request, config);
|
|
444
|
+
const expectedPanePid = positivePanePid(worker?.pid);
|
|
445
|
+
return { source: 'worker_pane_id', expectedPanePid, expectedPaneOwnerId: safeString(config?.tmux_pane_owner_id).trim(), ...explicitPaneIdentity(worker?.pane_id) };
|
|
446
|
+
}
|
|
447
|
+
function resolveDispatchTarget(request, config) {
|
|
448
|
+
const requestPane = explicitPaneIdentity(request?.pane_id);
|
|
449
|
+
const configuredPane = resolveConfiguredPaneIdentity(request, config);
|
|
450
|
+
const hudPaneId = explicitPaneIdentity(config?.hud_pane_id).paneId;
|
|
451
|
+
if (requestPane.provided) {
|
|
452
|
+
if (!requestPane.paneId) {
|
|
453
|
+
return { failure: 'invalid_explicit_pane', paneId: requestPane.paneId, paneSource: 'request_pane_id', rawPaneId: requestPane.rawPaneId };
|
|
454
|
+
}
|
|
455
|
+
if (requestPane.paneId === hudPaneId) {
|
|
456
|
+
return { failure: 'hud_pane_target', paneId: requestPane.paneId, paneSource: 'request_pane_id' };
|
|
457
|
+
}
|
|
458
|
+
if (configuredPane.provided) {
|
|
459
|
+
if (!configuredPane.paneId) {
|
|
460
|
+
return { failure: 'invalid_explicit_pane', paneId: configuredPane.paneId, paneSource: configuredPane.source, rawPaneId: configuredPane.rawPaneId };
|
|
461
|
+
}
|
|
462
|
+
if (requestPane.paneId !== configuredPane.paneId) {
|
|
463
|
+
return {
|
|
464
|
+
failure: 'exact_pane_mismatch',
|
|
465
|
+
paneId: requestPane.paneId,
|
|
466
|
+
paneSource: 'request_pane_id',
|
|
467
|
+
configuredPaneId: configuredPane.paneId,
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
if (!positivePanePid(configuredPane.expectedPanePid)) {
|
|
472
|
+
return { failure: 'missing_exact_pane_pid', paneId: requestPane.paneId, paneSource: configuredPane.source };
|
|
473
|
+
}
|
|
474
|
+
if (!configuredPane.expectedPaneOwnerId) {
|
|
475
|
+
return { failure: 'missing_expected_pane_owner', paneId: requestPane.paneId, paneSource: configuredPane.source };
|
|
476
|
+
}
|
|
477
|
+
return { target: { type: 'pane', value: requestPane.paneId }, exactPaneId: requestPane.paneId, expectedPanePid: configuredPane.expectedPanePid, expectedPaneOwnerId: configuredPane.expectedPaneOwnerId, expectedHudPaneId: hudPaneId, source: 'request_pane_id', reason: 'explicit_request_pane_id' };
|
|
435
478
|
}
|
|
436
|
-
if (
|
|
437
|
-
|
|
479
|
+
if (configuredPane.provided) {
|
|
480
|
+
if (!configuredPane.paneId) {
|
|
481
|
+
return { failure: 'invalid_explicit_pane', paneId: configuredPane.paneId, paneSource: configuredPane.source, rawPaneId: configuredPane.rawPaneId };
|
|
482
|
+
}
|
|
483
|
+
if (configuredPane.paneId === hudPaneId) {
|
|
484
|
+
return { failure: 'hud_pane_target', paneId: configuredPane.paneId, paneSource: configuredPane.source };
|
|
485
|
+
}
|
|
486
|
+
if (!positivePanePid(configuredPane.expectedPanePid)) {
|
|
487
|
+
return { failure: 'missing_exact_pane_pid', paneId: configuredPane.paneId, paneSource: configuredPane.source };
|
|
488
|
+
}
|
|
489
|
+
if (!configuredPane.expectedPaneOwnerId) {
|
|
490
|
+
return { failure: 'missing_expected_pane_owner', paneId: configuredPane.paneId, paneSource: configuredPane.source };
|
|
491
|
+
}
|
|
492
|
+
return { target: { type: 'pane', value: configuredPane.paneId }, exactPaneId: configuredPane.paneId, expectedPanePid: configuredPane.expectedPanePid, expectedPaneOwnerId: configuredPane.expectedPaneOwnerId, expectedHudPaneId: hudPaneId, source: configuredPane.source, reason: configuredPane.source };
|
|
438
493
|
}
|
|
439
|
-
|
|
440
|
-
return { type: 'session', value: config.tmux_session };
|
|
441
|
-
return null;
|
|
494
|
+
return { target: null };
|
|
442
495
|
}
|
|
443
496
|
async function appendLeaderNotificationDeferredEvent({ stateDir, teamName, request, reason, nowIso, tmuxSession = '', leaderPaneId = '', sourceType = 'team_dispatch', }) {
|
|
444
497
|
const eventsDir = join(stateDir, 'team', teamName, 'events');
|
|
@@ -695,13 +748,52 @@ function buildJoinedCapturePaneArgv(paneTarget, tailLines = 80) {
|
|
|
695
748
|
const INJECT_VERIFY_DELAY_MS = 250;
|
|
696
749
|
const INJECT_VERIFY_ROUNDS = 3;
|
|
697
750
|
async function injectDispatchRequest(request, config, cwd, stateDir) {
|
|
698
|
-
const
|
|
751
|
+
const dispatchTarget = resolveDispatchTarget(request, config);
|
|
752
|
+
if (dispatchTarget.failure) {
|
|
753
|
+
if (dispatchTarget.failure !== 'exact_pane_mismatch' && dispatchTarget.failure !== 'invalid_explicit_pane') {
|
|
754
|
+
return {
|
|
755
|
+
ok: false,
|
|
756
|
+
reason: dispatchTarget.failure,
|
|
757
|
+
pane: dispatchTarget.paneId || null,
|
|
758
|
+
pane_source: dispatchTarget.paneSource || null,
|
|
759
|
+
exact_pane_proof: null,
|
|
760
|
+
tmux_injection_attempted: false,
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
const paneProof = dispatchTarget.failure === 'exact_pane_mismatch'
|
|
764
|
+
? {
|
|
765
|
+
reason: 'exact_pane_mismatch',
|
|
766
|
+
proof: {
|
|
767
|
+
status: 'unavailable',
|
|
768
|
+
paneId: dispatchTarget.paneId,
|
|
769
|
+
reason: 'pane_mismatch',
|
|
770
|
+
detail: `configured pane is ${dispatchTarget.configuredPaneId}`,
|
|
771
|
+
},
|
|
772
|
+
}
|
|
773
|
+
: await verifyExactPaneLive(dispatchTarget.rawPaneId);
|
|
774
|
+
return {
|
|
775
|
+
ok: false,
|
|
776
|
+
reason: paneProof.reason,
|
|
777
|
+
pane: dispatchTarget.paneId || null,
|
|
778
|
+
pane_source: dispatchTarget.paneSource || null,
|
|
779
|
+
exact_pane_proof: paneProof.proof || null,
|
|
780
|
+
tmux_injection_attempted: false,
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
const target = dispatchTarget.target;
|
|
699
784
|
if (!target) {
|
|
700
785
|
return { ok: false, reason: 'missing_tmux_target' };
|
|
701
786
|
}
|
|
702
787
|
const leaderTargeted = request.to_worker === 'leader-fixed';
|
|
703
788
|
let resolution;
|
|
704
|
-
if (
|
|
789
|
+
if (dispatchTarget.exactPaneId) {
|
|
790
|
+
resolution = {
|
|
791
|
+
paneTarget: dispatchTarget.exactPaneId,
|
|
792
|
+
reason: dispatchTarget.reason,
|
|
793
|
+
source: dispatchTarget.source,
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
else if (target.type === 'session') {
|
|
705
797
|
const paneId = await resolveSessionToPane(target.value).catch(() => null);
|
|
706
798
|
resolution = paneId
|
|
707
799
|
? { paneTarget: paneId, reason: 'session_target_resolved' }
|
|
@@ -713,13 +805,25 @@ async function injectDispatchRequest(request, config, cwd, stateDir) {
|
|
|
713
805
|
if (!resolution.paneTarget) {
|
|
714
806
|
return { ok: false, reason: `target_resolution_failed:${resolution.reason}` };
|
|
715
807
|
}
|
|
716
|
-
const
|
|
808
|
+
const exactPaneId = dispatchTarget.exactPaneId || normalizeExactPaneId(resolution.paneTarget);
|
|
809
|
+
const exactPaneFailure = (paneProof, tmuxInjectionAttempted) => ({
|
|
810
|
+
ok: false,
|
|
811
|
+
reason: paneProof.reason,
|
|
812
|
+
pane: resolution.paneTarget,
|
|
813
|
+
pane_source: resolution.source || null,
|
|
814
|
+
exact_pane_proof: paneProof.proof || null,
|
|
815
|
+
tmux_injection_attempted: tmuxInjectionAttempted,
|
|
816
|
+
});
|
|
717
817
|
const paneGuard = await evaluatePaneInjectionReadiness(resolution.paneTarget, {
|
|
718
818
|
skipIfScrolling: true,
|
|
719
819
|
requireRunningAgent: leaderTargeted,
|
|
720
820
|
requireReady: false,
|
|
721
821
|
requireIdle: false,
|
|
722
822
|
requireObservableState: leaderTargeted,
|
|
823
|
+
exactPaneId,
|
|
824
|
+
expectedPanePid: dispatchTarget.expectedPanePid,
|
|
825
|
+
expectedPaneOwnerId: dispatchTarget.expectedPaneOwnerId,
|
|
826
|
+
expectedHudPaneId: dispatchTarget.expectedHudPaneId,
|
|
723
827
|
});
|
|
724
828
|
if (!paneGuard.ok) {
|
|
725
829
|
return {
|
|
@@ -729,15 +833,25 @@ async function injectDispatchRequest(request, config, cwd, stateDir) {
|
|
|
729
833
|
pane_source: resolution.source || null,
|
|
730
834
|
readiness_evidence: paneGuard.readinessEvidence || null,
|
|
731
835
|
pane_current_command: paneGuard.paneCurrentCommand || null,
|
|
836
|
+
exact_pane_proof: paneGuard.exactPaneProof || null,
|
|
732
837
|
tmux_injection_attempted: false,
|
|
733
838
|
};
|
|
734
839
|
}
|
|
840
|
+
let exactPaneProof = paneGuard.exactPaneProof || null;
|
|
841
|
+
const verifyExplicitPane = async () => {
|
|
842
|
+
const paneProof = await verifyExactPaneOwnerLive(exactPaneId, dispatchTarget.expectedPanePid, dispatchTarget.expectedPaneOwnerId);
|
|
843
|
+
exactPaneProof = paneProof.proof || null;
|
|
844
|
+
return paneProof;
|
|
845
|
+
};
|
|
735
846
|
const attemptCountAtStart = Number.isFinite(request.attempt_count)
|
|
736
847
|
? Math.max(0, Math.floor(request.attempt_count))
|
|
737
848
|
: 0;
|
|
738
849
|
const submitKeyPresses = resolveWorkerCliForRequest(request, config) === 'claude' ? 1 : 2;
|
|
739
850
|
let preCaptureHasTrigger = false;
|
|
740
851
|
if (attemptCountAtStart >= 1) {
|
|
852
|
+
const preCaptureProof = await verifyExplicitPane();
|
|
853
|
+
if (!preCaptureProof.ok)
|
|
854
|
+
return exactPaneFailure(preCaptureProof, false);
|
|
741
855
|
try {
|
|
742
856
|
// Narrow capture (8 lines) to scope check to input area, not scrollback output
|
|
743
857
|
const preCapture = await runProcess('tmux', buildJoinedCapturePaneArgv(resolution.paneTarget, 8), 2000);
|
|
@@ -750,15 +864,20 @@ async function injectDispatchRequest(request, config, cwd, stateDir) {
|
|
|
750
864
|
// Retype whenever trigger text is NOT in the narrow input area, regardless of attempt count.
|
|
751
865
|
// Pre-0.7.4 bug: 80-line capture matched trigger in scrollback output, falsely skipping retype.
|
|
752
866
|
const shouldTypePrompt = attemptCountAtStart === 0 || !preCaptureHasTrigger;
|
|
753
|
-
if (shouldTypePrompt) {
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
}
|
|
867
|
+
if (shouldTypePrompt && attemptCountAtStart >= 1) {
|
|
868
|
+
// Clear stale text in input buffer before retyping (mirrors sync path tmux-session.ts:1270)
|
|
869
|
+
const clearProof = await verifyExplicitPane();
|
|
870
|
+
if (!clearProof.ok)
|
|
871
|
+
return exactPaneFailure(clearProof, false);
|
|
872
|
+
await runProcess('tmux', ['send-keys', '-t', resolution.paneTarget, 'C-u'], 1000).catch(() => { });
|
|
873
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
759
874
|
}
|
|
760
875
|
const sendResult = await sendPaneInput({
|
|
761
876
|
paneTarget: resolution.paneTarget,
|
|
877
|
+
exactPaneId,
|
|
878
|
+
expectedPanePid: dispatchTarget.expectedPanePid,
|
|
879
|
+
expectedPaneOwnerId: dispatchTarget.expectedPaneOwnerId,
|
|
880
|
+
expectedHudPaneId: dispatchTarget.expectedHudPaneId,
|
|
762
881
|
prompt: request.trigger_message,
|
|
763
882
|
submitKeyPresses,
|
|
764
883
|
typePrompt: shouldTypePrompt,
|
|
@@ -772,9 +891,11 @@ async function injectDispatchRequest(request, config, cwd, stateDir) {
|
|
|
772
891
|
pane_source: resolution.source || null,
|
|
773
892
|
readiness_evidence: paneGuard.readinessEvidence || null,
|
|
774
893
|
pane_current_command: paneGuard.paneCurrentCommand || null,
|
|
894
|
+
exact_pane_proof: sendResult.exactPaneProof || null,
|
|
775
895
|
tmux_injection_attempted: true,
|
|
776
896
|
};
|
|
777
897
|
}
|
|
898
|
+
exactPaneProof = sendResult.exactPaneProof || exactPaneProof;
|
|
778
899
|
// Post-injection verification: confirm the trigger text was consumed.
|
|
779
900
|
// Fixes #391: without this, dispatch marks 'notified' even when the worker
|
|
780
901
|
// pane is sitting on an unsent draft (C-m was not effectively applied).
|
|
@@ -782,73 +903,105 @@ async function injectDispatchRequest(request, config, cwd, stateDir) {
|
|
|
782
903
|
const verifyWideArgv = buildJoinedCapturePaneArgv(resolution.paneTarget);
|
|
783
904
|
for (let round = 0; round < INJECT_VERIFY_ROUNDS; round++) {
|
|
784
905
|
await new Promise((r) => setTimeout(r, INJECT_VERIFY_DELAY_MS));
|
|
906
|
+
const narrowProof = await verifyExplicitPane();
|
|
907
|
+
if (!narrowProof.ok)
|
|
908
|
+
return exactPaneFailure(narrowProof, true);
|
|
909
|
+
let narrowCap;
|
|
785
910
|
try {
|
|
786
911
|
// Primary: trigger text no longer in narrow input area.
|
|
787
912
|
// Secondary guard: also inspect the recent non-empty tail of wide capture.
|
|
788
913
|
// This avoids false confirmations when Codex leaves the unsent draft just
|
|
789
914
|
// above a large blank area (narrow capture misses it) while still avoiding
|
|
790
915
|
// full-scrollback false positives.
|
|
791
|
-
|
|
792
|
-
const wideCap = await runProcess('tmux', verifyWideArgv, 2000);
|
|
793
|
-
const triggerInNarrow = capturedPaneContainsTrigger(narrowCap.stdout, request.trigger_message);
|
|
794
|
-
const triggerNearTail = capturedPaneContainsTriggerNearTail(wideCap.stdout, request.trigger_message);
|
|
795
|
-
if (triggerInNarrow || triggerNearTail) {
|
|
796
|
-
// Draft is still visible, so C-m has not actually submitted it yet.
|
|
797
|
-
// Do not let transient spinner/active-task text mask an unsent draft.
|
|
798
|
-
await sendPaneInput({
|
|
799
|
-
paneTarget: resolution.paneTarget,
|
|
800
|
-
prompt: request.trigger_message,
|
|
801
|
-
submitKeyPresses,
|
|
802
|
-
typePrompt: false,
|
|
803
|
-
}).catch(() => { });
|
|
804
|
-
continue;
|
|
805
|
-
}
|
|
806
|
-
// Worker is actively processing (mirrors sync path tmux-session.ts:1292-1294)
|
|
807
|
-
if (paneHasActiveTask(wideCap.stdout)) {
|
|
808
|
-
runtimeExec({ command: 'MarkDelivered', request_id: request.request_id }, stateDir, request.team_name);
|
|
809
|
-
return {
|
|
810
|
-
ok: true,
|
|
811
|
-
reason: 'tmux_send_keys_confirmed_active_task',
|
|
812
|
-
pane: resolution.paneTarget,
|
|
813
|
-
pane_source: resolution.source || null,
|
|
814
|
-
readiness_evidence: paneGuard.readinessEvidence || null,
|
|
815
|
-
pane_current_command: paneGuard.paneCurrentCommand || null,
|
|
816
|
-
tmux_injection_attempted: true,
|
|
817
|
-
};
|
|
818
|
-
}
|
|
819
|
-
// Do not declare success while a pane is not input-ready. Otherwise a
|
|
820
|
-
// pre-ready send can be marked "confirmed" and later appear as a stuck
|
|
821
|
-
// unsent draft once the UI finishes loading. This includes leader-fixed:
|
|
822
|
-
// its Codex UI can show "tab to queue message" while busy, and marking
|
|
823
|
-
// delivered before queue/consumption confirmation loses the orchestration
|
|
824
|
-
// nudge until a human presses Tab manually.
|
|
825
|
-
if (!paneLooksReady(wideCap.stdout)) {
|
|
826
|
-
continue;
|
|
827
|
-
}
|
|
828
|
-
if (!triggerInNarrow && !triggerNearTail) {
|
|
829
|
-
runtimeExec({ command: 'MarkDelivered', request_id: request.request_id }, stateDir, request.team_name);
|
|
830
|
-
return {
|
|
831
|
-
ok: true,
|
|
832
|
-
reason: 'tmux_send_keys_confirmed',
|
|
833
|
-
pane: resolution.paneTarget,
|
|
834
|
-
pane_source: resolution.source || null,
|
|
835
|
-
readiness_evidence: paneGuard.readinessEvidence || null,
|
|
836
|
-
pane_current_command: paneGuard.paneCurrentCommand || null,
|
|
837
|
-
tmux_injection_attempted: true,
|
|
838
|
-
};
|
|
839
|
-
}
|
|
916
|
+
narrowCap = await runProcess('tmux', verifyNarrowArgv, 2000);
|
|
840
917
|
}
|
|
841
918
|
catch {
|
|
842
|
-
//
|
|
919
|
+
// Capture failed; fall through to retry C-m.
|
|
920
|
+
}
|
|
921
|
+
if (narrowCap) {
|
|
922
|
+
const wideProof = await verifyExplicitPane();
|
|
923
|
+
if (!wideProof.ok)
|
|
924
|
+
return exactPaneFailure(wideProof, true);
|
|
925
|
+
try {
|
|
926
|
+
const wideCap = await runProcess('tmux', verifyWideArgv, 2000);
|
|
927
|
+
const triggerInNarrow = capturedPaneContainsTrigger(narrowCap.stdout, request.trigger_message);
|
|
928
|
+
const triggerNearTail = capturedPaneContainsTriggerNearTail(wideCap.stdout, request.trigger_message);
|
|
929
|
+
if (triggerInNarrow || triggerNearTail) {
|
|
930
|
+
// Draft is still visible, so C-m has not actually submitted it yet.
|
|
931
|
+
// Do not let transient spinner/active-task text mask an unsent draft.
|
|
932
|
+
const retrySend = await sendPaneInput({
|
|
933
|
+
paneTarget: resolution.paneTarget,
|
|
934
|
+
exactPaneId,
|
|
935
|
+
expectedPanePid: dispatchTarget.expectedPanePid,
|
|
936
|
+
expectedPaneOwnerId: dispatchTarget.expectedPaneOwnerId,
|
|
937
|
+
expectedHudPaneId: dispatchTarget.expectedHudPaneId,
|
|
938
|
+
prompt: request.trigger_message,
|
|
939
|
+
submitKeyPresses,
|
|
940
|
+
typePrompt: false,
|
|
941
|
+
});
|
|
942
|
+
if (!retrySend.ok && retrySend.reason === EXACT_PANE_UNAVAILABLE_REASON) {
|
|
943
|
+
return exactPaneFailure({ reason: retrySend.reason, proof: retrySend.exactPaneProof }, true);
|
|
944
|
+
}
|
|
945
|
+
exactPaneProof = retrySend.exactPaneProof || exactPaneProof;
|
|
946
|
+
continue;
|
|
947
|
+
}
|
|
948
|
+
// Worker is actively processing (mirrors sync path tmux-session.ts:1292-1294)
|
|
949
|
+
if (paneHasActiveTask(wideCap.stdout)) {
|
|
950
|
+
runtimeExec({ command: 'MarkDelivered', request_id: request.request_id }, stateDir, request.team_name);
|
|
951
|
+
return {
|
|
952
|
+
ok: true,
|
|
953
|
+
reason: 'tmux_send_keys_confirmed_active_task',
|
|
954
|
+
pane: resolution.paneTarget,
|
|
955
|
+
pane_source: resolution.source || null,
|
|
956
|
+
readiness_evidence: paneGuard.readinessEvidence || null,
|
|
957
|
+
pane_current_command: paneGuard.paneCurrentCommand || null,
|
|
958
|
+
exact_pane_proof: exactPaneProof,
|
|
959
|
+
tmux_injection_attempted: true,
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
// Do not declare success while a pane is not input-ready. Otherwise a
|
|
963
|
+
// pre-ready send can be marked "confirmed" and later appear as a stuck
|
|
964
|
+
// unsent draft once the UI finishes loading. This includes leader-fixed:
|
|
965
|
+
// its Codex UI can show "tab to queue message" while busy, and marking
|
|
966
|
+
// delivered before queue/consumption confirmation loses the orchestration
|
|
967
|
+
// nudge until a human presses Tab manually.
|
|
968
|
+
if (!paneLooksReady(wideCap.stdout)) {
|
|
969
|
+
continue;
|
|
970
|
+
}
|
|
971
|
+
if (!triggerInNarrow && !triggerNearTail) {
|
|
972
|
+
runtimeExec({ command: 'MarkDelivered', request_id: request.request_id }, stateDir, request.team_name);
|
|
973
|
+
return {
|
|
974
|
+
ok: true,
|
|
975
|
+
reason: 'tmux_send_keys_confirmed',
|
|
976
|
+
pane: resolution.paneTarget,
|
|
977
|
+
pane_source: resolution.source || null,
|
|
978
|
+
readiness_evidence: paneGuard.readinessEvidence || null,
|
|
979
|
+
pane_current_command: paneGuard.paneCurrentCommand || null,
|
|
980
|
+
exact_pane_proof: exactPaneProof,
|
|
981
|
+
tmux_injection_attempted: true,
|
|
982
|
+
};
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
catch {
|
|
986
|
+
// Capture failed; fall through to retry C-m.
|
|
987
|
+
}
|
|
843
988
|
}
|
|
844
989
|
// Draft still visible and no active task — retry C-m
|
|
845
|
-
await sendPaneInput({
|
|
990
|
+
const retrySend = await sendPaneInput({
|
|
846
991
|
paneTarget: resolution.paneTarget,
|
|
992
|
+
exactPaneId,
|
|
993
|
+
expectedPanePid: dispatchTarget.expectedPanePid,
|
|
994
|
+
expectedPaneOwnerId: dispatchTarget.expectedPaneOwnerId,
|
|
995
|
+
expectedHudPaneId: dispatchTarget.expectedHudPaneId,
|
|
847
996
|
prompt: request.trigger_message,
|
|
848
997
|
submitKeyPresses,
|
|
849
998
|
typePrompt: false,
|
|
850
999
|
queueFirstSubmit: leaderTargeted,
|
|
851
|
-
})
|
|
1000
|
+
});
|
|
1001
|
+
if (!retrySend.ok && retrySend.reason === EXACT_PANE_UNAVAILABLE_REASON) {
|
|
1002
|
+
return exactPaneFailure({ reason: retrySend.reason, proof: retrySend.exactPaneProof }, true);
|
|
1003
|
+
}
|
|
1004
|
+
exactPaneProof = retrySend.exactPaneProof || exactPaneProof;
|
|
852
1005
|
}
|
|
853
1006
|
// Trigger text is still visible after all retry rounds.
|
|
854
1007
|
return {
|
|
@@ -858,6 +1011,7 @@ async function injectDispatchRequest(request, config, cwd, stateDir) {
|
|
|
858
1011
|
pane_source: resolution.source || null,
|
|
859
1012
|
readiness_evidence: paneGuard.readinessEvidence || null,
|
|
860
1013
|
pane_current_command: paneGuard.paneCurrentCommand || null,
|
|
1014
|
+
exact_pane_proof: exactPaneProof,
|
|
861
1015
|
tmux_injection_attempted: true,
|
|
862
1016
|
};
|
|
863
1017
|
}
|
|
@@ -900,6 +1054,7 @@ function buildDispatchAttemptEvidence(result, fallback = {}) {
|
|
|
900
1054
|
pane_source: safeString(result?.pane_source || fallback.pane_source || '').trim() || null,
|
|
901
1055
|
readiness_evidence: safeString(result?.readiness_evidence || fallback.readiness_evidence || '').trim() || null,
|
|
902
1056
|
pane_current_command: safeString(result?.pane_current_command || fallback.pane_current_command || '').trim() || null,
|
|
1057
|
+
exact_pane_proof: result?.exact_pane_proof ?? fallback.exact_pane_proof ?? null,
|
|
903
1058
|
tmux_injection_attempted: typeof result?.tmux_injection_attempted === 'boolean'
|
|
904
1059
|
? result.tmux_injection_attempted
|
|
905
1060
|
: (typeof fallback.tmux_injection_attempted === 'boolean' ? fallback.tmux_injection_attempted : null),
|
|
@@ -948,7 +1103,7 @@ export async function drainPendingTeamDispatch({ cwd, stateDir = resolveBridgeSt
|
|
|
948
1103
|
skipped += 1;
|
|
949
1104
|
continue;
|
|
950
1105
|
}
|
|
951
|
-
if (request.to_worker === 'leader-fixed' && !resolveLeaderPaneId(config)) {
|
|
1106
|
+
if (request.to_worker === 'leader-fixed' && !resolveLeaderPaneId(config) && !explicitPaneIdentity(request.pane_id).provided) {
|
|
952
1107
|
const nowIso = new Date().toISOString();
|
|
953
1108
|
const alreadyDeferred = safeString(request.last_reason).trim() === LEADER_PANE_MISSING_DEFERRED_REASON;
|
|
954
1109
|
request.updated_at = nowIso;
|