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
|
@@ -9,6 +9,158 @@ import {
|
|
|
9
9
|
paneHasActiveTask,
|
|
10
10
|
paneLooksReady,
|
|
11
11
|
} from '../tmux-hook-engine.js';
|
|
12
|
+
import { readExactPaneProof } from '../../team/exact-pane.js';
|
|
13
|
+
|
|
14
|
+
export const EXACT_PANE_UNAVAILABLE_REASON = 'exact_pane_unavailable';
|
|
15
|
+
const EXACT_PANE_ID_RE = /^%\d+$/;
|
|
16
|
+
|
|
17
|
+
function explicitPaneIdentity(value: any): { provided: boolean; paneId: string } {
|
|
18
|
+
const paneId = safeString(value).trim();
|
|
19
|
+
return { provided: paneId !== '', paneId: EXACT_PANE_ID_RE.test(paneId) ? paneId : '' };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function normalizeExactPaneId(value: any): string {
|
|
23
|
+
return explicitPaneIdentity(value).paneId;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function exactPaneBindingFailure(target: string, exactPaneId: any): any | null {
|
|
27
|
+
const identity = explicitPaneIdentity(exactPaneId);
|
|
28
|
+
const targetIsExactPane = EXACT_PANE_ID_RE.test(target);
|
|
29
|
+
if (targetIsExactPane && !identity.provided) {
|
|
30
|
+
return {
|
|
31
|
+
ok: false,
|
|
32
|
+
reason: EXACT_PANE_UNAVAILABLE_REASON,
|
|
33
|
+
paneId: target,
|
|
34
|
+
proof: { status: 'unavailable', paneId: target, reason: 'missing_exact_pane_id' },
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (identity.provided && !identity.paneId) {
|
|
38
|
+
return {
|
|
39
|
+
ok: false,
|
|
40
|
+
reason: EXACT_PANE_UNAVAILABLE_REASON,
|
|
41
|
+
paneId: '',
|
|
42
|
+
proof: { status: 'unavailable', paneId: safeString(exactPaneId).trim(), reason: 'invalid_pane_id' },
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (identity.paneId && identity.paneId !== target) {
|
|
46
|
+
return {
|
|
47
|
+
ok: false,
|
|
48
|
+
reason: EXACT_PANE_UNAVAILABLE_REASON,
|
|
49
|
+
paneId: identity.paneId,
|
|
50
|
+
proof: { status: 'unavailable', paneId: identity.paneId, reason: 'pane_target_mismatch' },
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export async function verifyExactPaneLive(exactPaneId: any, expectedPanePid?: number): Promise<any> {
|
|
57
|
+
const identity = explicitPaneIdentity(exactPaneId);
|
|
58
|
+
if (!identity.provided) return { ok: true, paneId: '', proof: null };
|
|
59
|
+
if (!identity.paneId) {
|
|
60
|
+
return {
|
|
61
|
+
ok: false,
|
|
62
|
+
reason: EXACT_PANE_UNAVAILABLE_REASON,
|
|
63
|
+
paneId: '',
|
|
64
|
+
proof: {
|
|
65
|
+
status: 'unavailable',
|
|
66
|
+
paneId: safeString(exactPaneId).trim(),
|
|
67
|
+
reason: 'invalid_pane_id',
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
const proof = await readExactPaneProof(identity.paneId);
|
|
74
|
+
if (proof.status === 'live' && proof.paneId === identity.paneId) {
|
|
75
|
+
if (typeof expectedPanePid === 'number' && proof.pid !== expectedPanePid) {
|
|
76
|
+
return {
|
|
77
|
+
ok: false,
|
|
78
|
+
reason: EXACT_PANE_UNAVAILABLE_REASON,
|
|
79
|
+
paneId: identity.paneId,
|
|
80
|
+
proof: { ...proof, status: 'unavailable', reason: 'pane_pid_changed', expectedPid: expectedPanePid },
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return { ok: true, paneId: identity.paneId, proof };
|
|
84
|
+
}
|
|
85
|
+
return { ok: false, reason: EXACT_PANE_UNAVAILABLE_REASON, paneId: identity.paneId, proof };
|
|
86
|
+
} catch (error) {
|
|
87
|
+
return {
|
|
88
|
+
ok: false,
|
|
89
|
+
reason: EXACT_PANE_UNAVAILABLE_REASON,
|
|
90
|
+
paneId: identity.paneId,
|
|
91
|
+
proof: {
|
|
92
|
+
status: 'unavailable',
|
|
93
|
+
paneId: identity.paneId,
|
|
94
|
+
reason: 'query_failed',
|
|
95
|
+
detail: error instanceof Error ? error.message : safeString(error),
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export async function verifyExactPaneOwnerLive(exactPaneId: any, expectedPanePid: number | undefined, expectedPaneOwnerId: any): Promise<any> {
|
|
102
|
+
const expectedOwner = safeString(expectedPaneOwnerId).trim();
|
|
103
|
+
if (!expectedOwner || !Number.isInteger(expectedPanePid) || Number(expectedPanePid) <= 0) {
|
|
104
|
+
return {
|
|
105
|
+
ok: false,
|
|
106
|
+
reason: EXACT_PANE_UNAVAILABLE_REASON,
|
|
107
|
+
paneId: normalizeExactPaneId(exactPaneId),
|
|
108
|
+
proof: {
|
|
109
|
+
status: 'unavailable',
|
|
110
|
+
paneId: normalizeExactPaneId(exactPaneId),
|
|
111
|
+
reason: !expectedOwner ? 'missing_expected_pane_owner' : 'missing_expected_pane_pid',
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
const beforeOwner = await verifyExactPaneLive(exactPaneId, expectedPanePid);
|
|
116
|
+
if (!beforeOwner.ok) return beforeOwner;
|
|
117
|
+
try {
|
|
118
|
+
const ownerResult = await runProcess(
|
|
119
|
+
'tmux',
|
|
120
|
+
['show-option', '-qv', '-p', '-t', beforeOwner.paneId, '@omx_team_pane_owner_id'],
|
|
121
|
+
3000,
|
|
122
|
+
);
|
|
123
|
+
const actualOwner = safeString(ownerResult.stdout).trim();
|
|
124
|
+
if (actualOwner !== expectedOwner) {
|
|
125
|
+
return {
|
|
126
|
+
ok: false,
|
|
127
|
+
reason: EXACT_PANE_UNAVAILABLE_REASON,
|
|
128
|
+
paneId: beforeOwner.paneId,
|
|
129
|
+
proof: {
|
|
130
|
+
status: 'unavailable',
|
|
131
|
+
paneId: beforeOwner.paneId,
|
|
132
|
+
reason: actualOwner ? 'pane_owner_changed' : 'pane_owner_unavailable',
|
|
133
|
+
expectedOwner,
|
|
134
|
+
actualOwner: actualOwner || undefined,
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
} catch (error) {
|
|
139
|
+
return {
|
|
140
|
+
ok: false,
|
|
141
|
+
reason: EXACT_PANE_UNAVAILABLE_REASON,
|
|
142
|
+
paneId: beforeOwner.paneId,
|
|
143
|
+
proof: {
|
|
144
|
+
status: 'unavailable',
|
|
145
|
+
paneId: beforeOwner.paneId,
|
|
146
|
+
reason: 'pane_owner_unavailable',
|
|
147
|
+
detail: error instanceof Error ? error.message : safeString(error),
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return verifyExactPaneLive(exactPaneId, expectedPanePid);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function exactPaneUnavailableResult(target: string, paneProof: any, extra: any = {}): any {
|
|
155
|
+
return {
|
|
156
|
+
ok: false,
|
|
157
|
+
sent: false,
|
|
158
|
+
reason: EXACT_PANE_UNAVAILABLE_REASON,
|
|
159
|
+
paneTarget: target,
|
|
160
|
+
exactPaneProof: paneProof.proof || null,
|
|
161
|
+
...extra,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
12
164
|
|
|
13
165
|
export const PANE_READINESS_UNVERIFIED_REASON = 'pane_readiness_unverified';
|
|
14
166
|
let nextTmuxBufferId = 0;
|
|
@@ -46,6 +198,10 @@ export async function evaluatePaneInjectionReadiness(paneTarget: any, {
|
|
|
46
198
|
requireIdle = true,
|
|
47
199
|
requireObservableState = false,
|
|
48
200
|
requireCaptureEvidence = undefined,
|
|
201
|
+
exactPaneId = undefined,
|
|
202
|
+
expectedPanePid = undefined,
|
|
203
|
+
expectedPaneOwnerId = undefined,
|
|
204
|
+
expectedHudPaneId = undefined,
|
|
49
205
|
} = {}): Promise<any> {
|
|
50
206
|
const normalizedRequireObservableState = typeof requireCaptureEvidence === 'boolean' ? requireCaptureEvidence : requireObservableState;
|
|
51
207
|
const target = safeString(paneTarget).trim();
|
|
@@ -59,24 +215,26 @@ export async function evaluatePaneInjectionReadiness(paneTarget: any, {
|
|
|
59
215
|
paneCapture: '',
|
|
60
216
|
};
|
|
61
217
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const modeResult = await runProcess('tmux', buildPaneInModeArgv(target), 3000);
|
|
65
|
-
if (safeString(modeResult.stdout).trim() === '1') {
|
|
66
|
-
return {
|
|
67
|
-
ok: false,
|
|
68
|
-
sent: false,
|
|
69
|
-
reason: 'scroll_active',
|
|
70
|
-
paneTarget: target,
|
|
71
|
-
paneCurrentCommand: '',
|
|
72
|
-
paneCapture: '',
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
} catch {
|
|
76
|
-
// Non-fatal: continue with remaining preflight checks.
|
|
77
|
-
}
|
|
78
|
-
}
|
|
218
|
+
const bindingFailure = exactPaneBindingFailure(target, exactPaneId);
|
|
219
|
+
if (bindingFailure) return exactPaneUnavailableResult(target, bindingFailure);
|
|
79
220
|
|
|
221
|
+
const exactPaneIdentity = safeString(exactPaneId).trim();
|
|
222
|
+
const exactPaneIdentityProvided = explicitPaneIdentity(exactPaneId).provided;
|
|
223
|
+
const expectedOwner = safeString(expectedPaneOwnerId).trim();
|
|
224
|
+
const expectedHudPane = normalizeExactPaneId(expectedHudPaneId);
|
|
225
|
+
const requiresTeamReadAuthority = exactPaneIdentityProvided && (
|
|
226
|
+
expectedPanePid !== undefined || expectedOwner || expectedHudPane
|
|
227
|
+
);
|
|
228
|
+
let exactPaneProof: any = null;
|
|
229
|
+
let pinnedPanePid = typeof expectedPanePid === 'number' ? expectedPanePid : undefined;
|
|
230
|
+
const verifyExplicitPane = async () => {
|
|
231
|
+
const paneProof = requiresTeamReadAuthority
|
|
232
|
+
? await verifyExactPaneOwnerLive(exactPaneIdentity, pinnedPanePid, expectedOwner)
|
|
233
|
+
: await verifyExactPaneLive(exactPaneIdentity, pinnedPanePid);
|
|
234
|
+
exactPaneProof = paneProof.proof || null;
|
|
235
|
+
if (paneProof.ok && typeof paneProof.proof?.pid === 'number') pinnedPanePid ??= paneProof.proof.pid;
|
|
236
|
+
return paneProof;
|
|
237
|
+
};
|
|
80
238
|
let paneCurrentCommand = '';
|
|
81
239
|
let paneRunningShell = false;
|
|
82
240
|
const buildReadinessResult = (ok: boolean, reason: string, paneCapture: string, readinessEvidence: string) => ({
|
|
@@ -87,18 +245,91 @@ export async function evaluatePaneInjectionReadiness(paneTarget: any, {
|
|
|
87
245
|
paneCurrentCommand,
|
|
88
246
|
paneCapture,
|
|
89
247
|
readinessEvidence,
|
|
248
|
+
exactPaneProof,
|
|
90
249
|
});
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
|
|
250
|
+
const exactPaneFailure = (paneProof: any, paneCapture = '') => exactPaneUnavailableResult(target, paneProof, {
|
|
251
|
+
paneCurrentCommand,
|
|
252
|
+
paneCapture,
|
|
253
|
+
readinessEvidence: 'exact_pane_unavailable',
|
|
254
|
+
});
|
|
255
|
+
if (expectedHudPane && expectedHudPane === exactPaneIdentity) {
|
|
256
|
+
return buildReadinessResult(false, 'hud_pane_target', '', 'hud_pane_rejected');
|
|
97
257
|
}
|
|
98
258
|
|
|
99
|
-
|
|
100
|
-
const
|
|
101
|
-
|
|
259
|
+
const readExplicitPane = async (argv: string[]) => {
|
|
260
|
+
const beforeRead = await verifyExplicitPane();
|
|
261
|
+
if (!beforeRead.ok) return { ok: false, paneProof: beforeRead, result: null };
|
|
262
|
+
try {
|
|
263
|
+
const result = await runProcess('tmux', argv, 3000);
|
|
264
|
+
if (requiresTeamReadAuthority) {
|
|
265
|
+
const afterRead = await verifyExplicitPane();
|
|
266
|
+
if (!afterRead.ok) return { ok: false, paneProof: afterRead, result: null };
|
|
267
|
+
}
|
|
268
|
+
return { ok: true, paneProof: beforeRead, result };
|
|
269
|
+
} catch (error) {
|
|
270
|
+
return { ok: false, paneProof: null, result: null, error };
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
if (skipIfScrolling) {
|
|
275
|
+
const read = await readExplicitPane(buildPaneInModeArgv(target));
|
|
276
|
+
if (!read.ok) {
|
|
277
|
+
if (read.paneProof) return exactPaneFailure(read.paneProof);
|
|
278
|
+
// Non-fatal: continue with remaining preflight checks.
|
|
279
|
+
} else if (safeString(read.result?.stdout).trim() === '1') {
|
|
280
|
+
return {
|
|
281
|
+
ok: false,
|
|
282
|
+
sent: false,
|
|
283
|
+
reason: 'scroll_active',
|
|
284
|
+
paneTarget: target,
|
|
285
|
+
paneCurrentCommand: '',
|
|
286
|
+
paneCapture: '',
|
|
287
|
+
exactPaneProof,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (exactPaneIdentityProvided) {
|
|
293
|
+
const read = await readExplicitPane(['display-message', '-p', '-t', target, '#{pane_start_command}']);
|
|
294
|
+
if (!read.ok) {
|
|
295
|
+
if (read.paneProof) return exactPaneFailure(read.paneProof);
|
|
296
|
+
return buildReadinessResult(false, PANE_READINESS_UNVERIFIED_REASON, '', 'start_command_failed');
|
|
297
|
+
}
|
|
298
|
+
if (/\bomx\b.*\bhud\b.*--watch/i.test(safeString(read.result?.stdout))) {
|
|
299
|
+
return buildReadinessResult(false, 'hud_pane_target', '', 'hud_pane_rejected');
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
{
|
|
304
|
+
const read = await readExplicitPane(buildPaneCurrentCommandArgv(target));
|
|
305
|
+
if (!read.ok) {
|
|
306
|
+
if (read.paneProof) return exactPaneFailure(read.paneProof);
|
|
307
|
+
if (exactPaneIdentityProvided) {
|
|
308
|
+
return buildReadinessResult(false, PANE_READINESS_UNVERIFIED_REASON, '', 'command_failed');
|
|
309
|
+
}
|
|
310
|
+
paneCurrentCommand = '';
|
|
311
|
+
} else {
|
|
312
|
+
paneCurrentCommand = safeString(read.result?.stdout).trim();
|
|
313
|
+
paneRunningShell = requireRunningAgent && isPaneRunningShell(paneCurrentCommand);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
{
|
|
318
|
+
const read = await readExplicitPane(buildCapturePaneArgv(target, captureLines));
|
|
319
|
+
if (!read.ok) {
|
|
320
|
+
if (read.paneProof) return exactPaneFailure(read.paneProof);
|
|
321
|
+
if (exactPaneIdentityProvided) {
|
|
322
|
+
return buildReadinessResult(false, PANE_READINESS_UNVERIFIED_REASON, '', 'capture_failed');
|
|
323
|
+
}
|
|
324
|
+
if (paneRunningShell) {
|
|
325
|
+
return buildReadinessResult(false, 'pane_running_shell', '', 'capture_failed');
|
|
326
|
+
}
|
|
327
|
+
if (normalizedRequireObservableState) {
|
|
328
|
+
return buildReadinessResult(false, PANE_READINESS_UNVERIFIED_REASON, '', 'capture_failed');
|
|
329
|
+
}
|
|
330
|
+
return buildReadinessResult(true, 'ok', '', paneCurrentCommand ? 'command_only' : 'none');
|
|
331
|
+
}
|
|
332
|
+
const paneCapture = safeString(read.result?.stdout);
|
|
102
333
|
const hasCaptureEvidence = paneCapture.trim() !== '';
|
|
103
334
|
if (hasCaptureEvidence) {
|
|
104
335
|
const paneShowsLiveAgent = paneLooksReady(paneCapture) || paneHasActiveTask(paneCapture);
|
|
@@ -122,6 +353,7 @@ export async function evaluatePaneInjectionReadiness(paneTarget: any, {
|
|
|
122
353
|
paneTarget: target,
|
|
123
354
|
paneCurrentCommand,
|
|
124
355
|
paneCapture,
|
|
356
|
+
exactPaneProof,
|
|
125
357
|
};
|
|
126
358
|
}
|
|
127
359
|
}
|
|
@@ -133,20 +365,13 @@ export async function evaluatePaneInjectionReadiness(paneTarget: any, {
|
|
|
133
365
|
paneTarget: target,
|
|
134
366
|
paneCurrentCommand,
|
|
135
367
|
paneCapture,
|
|
368
|
+
exactPaneProof,
|
|
136
369
|
};
|
|
137
370
|
}
|
|
138
371
|
if (normalizedRequireObservableState && !hasCaptureEvidence && !paneCurrentCommand) {
|
|
139
372
|
return buildReadinessResult(false, PANE_READINESS_UNVERIFIED_REASON, paneCapture, 'capture_empty');
|
|
140
373
|
}
|
|
141
374
|
return buildReadinessResult(true, 'ok', paneCapture, hasCaptureEvidence ? 'captured' : (paneCurrentCommand ? 'command_only' : 'none'));
|
|
142
|
-
} catch {
|
|
143
|
-
if (paneRunningShell) {
|
|
144
|
-
return buildReadinessResult(false, 'pane_running_shell', '', 'capture_failed');
|
|
145
|
-
}
|
|
146
|
-
if (normalizedRequireObservableState) {
|
|
147
|
-
return buildReadinessResult(false, PANE_READINESS_UNVERIFIED_REASON, '', 'capture_failed');
|
|
148
|
-
}
|
|
149
|
-
return buildReadinessResult(true, 'ok', '', paneCurrentCommand ? 'command_only' : 'none');
|
|
150
375
|
}
|
|
151
376
|
}
|
|
152
377
|
|
|
@@ -157,11 +382,59 @@ export async function sendPaneInput({
|
|
|
157
382
|
submitDelayMs = 0,
|
|
158
383
|
typePrompt = true,
|
|
159
384
|
queueFirstSubmit = false,
|
|
385
|
+
exactPaneId = undefined,
|
|
386
|
+
expectedPanePid = undefined,
|
|
387
|
+
expectedPaneOwnerId = undefined,
|
|
388
|
+
expectedHudPaneId = undefined,
|
|
160
389
|
}: any): Promise<any> {
|
|
161
390
|
const target = safeString(paneTarget).trim();
|
|
162
391
|
if (!target) {
|
|
163
392
|
return { ok: false, sent: false, reason: 'missing_pane_target', paneTarget: '' };
|
|
164
393
|
}
|
|
394
|
+
const bindingFailure = exactPaneBindingFailure(target, exactPaneId);
|
|
395
|
+
if (bindingFailure) return exactPaneUnavailableResult(target, bindingFailure);
|
|
396
|
+
|
|
397
|
+
const exactPaneIdentity = safeString(exactPaneId).trim();
|
|
398
|
+
let exactPaneProof: any = null;
|
|
399
|
+
let pinnedPanePid = typeof expectedPanePid === 'number' ? expectedPanePid : undefined;
|
|
400
|
+
const verifyExplicitPane = async () => {
|
|
401
|
+
const paneProof = await verifyExactPaneLive(exactPaneIdentity, pinnedPanePid);
|
|
402
|
+
exactPaneProof = paneProof.proof || null;
|
|
403
|
+
if (paneProof.ok && typeof paneProof.proof?.pid === 'number') pinnedPanePid ??= paneProof.proof.pid;
|
|
404
|
+
return paneProof;
|
|
405
|
+
};
|
|
406
|
+
const expectedOwner = safeString(expectedPaneOwnerId).trim();
|
|
407
|
+
const expectedHudPane = normalizeExactPaneId(expectedHudPaneId);
|
|
408
|
+
if (expectedHudPane && expectedHudPane === exactPaneIdentity) {
|
|
409
|
+
return { ok: false, sent: false, reason: 'hud_pane_target', paneTarget: target };
|
|
410
|
+
}
|
|
411
|
+
const verifyForEffect = async () => {
|
|
412
|
+
if (expectedOwner) {
|
|
413
|
+
const paneProof = await verifyExactPaneOwnerLive(exactPaneIdentity, pinnedPanePid, expectedOwner);
|
|
414
|
+
exactPaneProof = paneProof.proof || null;
|
|
415
|
+
return paneProof;
|
|
416
|
+
}
|
|
417
|
+
return verifyExplicitPane();
|
|
418
|
+
};
|
|
419
|
+
const initialProof = await verifyForEffect();
|
|
420
|
+
if (!initialProof.ok) return exactPaneUnavailableResult(target, initialProof);
|
|
421
|
+
try {
|
|
422
|
+
const startCommandResult = await runProcess('tmux', ['display-message', '-p', '-t', target, '#{pane_start_command}'], 3000);
|
|
423
|
+
if (/\bomx\b.*\bhud\b.*--watch/i.test(safeString(startCommandResult.stdout))) {
|
|
424
|
+
return { ok: false, sent: false, reason: 'hud_pane_target', paneTarget: target, exactPaneProof };
|
|
425
|
+
}
|
|
426
|
+
} catch {
|
|
427
|
+
return {
|
|
428
|
+
ok: false,
|
|
429
|
+
sent: false,
|
|
430
|
+
reason: PANE_READINESS_UNVERIFIED_REASON,
|
|
431
|
+
paneTarget: target,
|
|
432
|
+
exactPaneProof,
|
|
433
|
+
readinessEvidence: 'start_command_failed',
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
const postHudProof = await verifyForEffect();
|
|
437
|
+
if (!postHudProof.ok) return exactPaneUnavailableResult(target, postHudProof);
|
|
165
438
|
|
|
166
439
|
const normalizedSubmitKeyPresses = Number.isFinite(submitKeyPresses)
|
|
167
440
|
? Math.max(0, Math.floor(submitKeyPresses))
|
|
@@ -176,7 +449,7 @@ export async function sendPaneInput({
|
|
|
176
449
|
submitKeyPresses: normalizedSubmitKeyPresses,
|
|
177
450
|
})?.submitArgv;
|
|
178
451
|
if (!submitArgv) {
|
|
179
|
-
return { ok: false, sent: false, reason: 'send_failed', paneTarget: target };
|
|
452
|
+
return { ok: false, sent: false, reason: 'send_failed', paneTarget: target, exactPaneProof };
|
|
180
453
|
}
|
|
181
454
|
const pasteArgv = buildSafePasteArgv(target, literalPrompt);
|
|
182
455
|
const argv = {
|
|
@@ -203,6 +476,7 @@ export async function sendPaneInput({
|
|
|
203
476
|
reason: 'buffer_set_failed',
|
|
204
477
|
paneTarget: target,
|
|
205
478
|
argv,
|
|
479
|
+
exactPaneProof,
|
|
206
480
|
error: error instanceof Error ? error.message : safeString(error),
|
|
207
481
|
};
|
|
208
482
|
}
|
|
@@ -216,6 +490,7 @@ export async function sendPaneInput({
|
|
|
216
490
|
reason: 'buffer_show_failed',
|
|
217
491
|
paneTarget: target,
|
|
218
492
|
argv,
|
|
493
|
+
exactPaneProof,
|
|
219
494
|
error: error instanceof Error ? error.message : safeString(error),
|
|
220
495
|
};
|
|
221
496
|
}
|
|
@@ -226,12 +501,31 @@ export async function sendPaneInput({
|
|
|
226
501
|
reason: 'buffer_verify_failed',
|
|
227
502
|
paneTarget: target,
|
|
228
503
|
argv,
|
|
504
|
+
exactPaneProof,
|
|
229
505
|
expectedBytes: literalPrompt.length,
|
|
230
506
|
actualBytes: verifiedBuffer.stdout.length,
|
|
231
507
|
};
|
|
232
508
|
}
|
|
509
|
+
|
|
510
|
+
const clearProof = await verifyForEffect();
|
|
511
|
+
if (!clearProof.ok) return exactPaneUnavailableResult(target, clearProof, { argv });
|
|
233
512
|
try {
|
|
234
513
|
await runProcess('tmux', pasteArgv.clearComposerArgv, 3000);
|
|
514
|
+
} catch (error) {
|
|
515
|
+
return {
|
|
516
|
+
ok: false,
|
|
517
|
+
sent: false,
|
|
518
|
+
reason: 'buffer_paste_failed',
|
|
519
|
+
paneTarget: target,
|
|
520
|
+
argv,
|
|
521
|
+
exactPaneProof,
|
|
522
|
+
error: error instanceof Error ? error.message : safeString(error),
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
const pasteProof = await verifyForEffect();
|
|
527
|
+
if (!pasteProof.ok) return exactPaneUnavailableResult(target, pasteProof, { argv });
|
|
528
|
+
try {
|
|
235
529
|
await runProcess('tmux', pasteArgv.pasteBufferArgv, 3000);
|
|
236
530
|
} catch (error) {
|
|
237
531
|
return {
|
|
@@ -240,11 +534,14 @@ export async function sendPaneInput({
|
|
|
240
534
|
reason: 'buffer_paste_failed',
|
|
241
535
|
paneTarget: target,
|
|
242
536
|
argv,
|
|
537
|
+
exactPaneProof,
|
|
243
538
|
error: error instanceof Error ? error.message : safeString(error),
|
|
244
539
|
};
|
|
245
540
|
}
|
|
246
541
|
}
|
|
247
542
|
if (queueFirstSubmit && argv.submitArgv.length > 0) {
|
|
543
|
+
const queueProof = await verifyForEffect();
|
|
544
|
+
if (!queueProof.ok) return exactPaneUnavailableResult(target, queueProof, { argv });
|
|
248
545
|
await runProcess('tmux', ['send-keys', '-t', target, 'Tab'], 3000);
|
|
249
546
|
if (submitDelayMs > 0) {
|
|
250
547
|
await new Promise((resolve) => setTimeout(resolve, submitDelayMs));
|
|
@@ -254,9 +551,11 @@ export async function sendPaneInput({
|
|
|
254
551
|
if (submitDelayMs > 0) {
|
|
255
552
|
await new Promise((resolve) => setTimeout(resolve, submitDelayMs));
|
|
256
553
|
}
|
|
554
|
+
const submitProof = await verifyForEffect();
|
|
555
|
+
if (!submitProof.ok) return exactPaneUnavailableResult(target, submitProof, { argv });
|
|
257
556
|
await runProcess('tmux', submit, 3000);
|
|
258
557
|
}
|
|
259
|
-
return { ok: true, sent: true, reason: 'sent', paneTarget: target, argv };
|
|
558
|
+
return { ok: true, sent: true, reason: 'sent', paneTarget: target, argv, exactPaneProof };
|
|
260
559
|
} catch (error) {
|
|
261
560
|
return {
|
|
262
561
|
ok: false,
|
|
@@ -264,6 +563,7 @@ export async function sendPaneInput({
|
|
|
264
563
|
reason: 'send_failed',
|
|
265
564
|
paneTarget: target,
|
|
266
565
|
argv,
|
|
566
|
+
exactPaneProof,
|
|
267
567
|
error: error instanceof Error ? error.message : safeString(error),
|
|
268
568
|
};
|
|
269
569
|
} finally {
|
|
@@ -277,24 +577,49 @@ export async function queuePaneInput({
|
|
|
277
577
|
paneTarget,
|
|
278
578
|
prompt,
|
|
279
579
|
submitDelayMs = 80,
|
|
580
|
+
exactPaneId = undefined,
|
|
280
581
|
}: any): Promise<any> {
|
|
582
|
+
const target = safeString(paneTarget).trim();
|
|
583
|
+
const exactPaneIdentity = safeString(exactPaneId).trim();
|
|
584
|
+
const bindingFailure = exactPaneBindingFailure(target, exactPaneId);
|
|
585
|
+
if (bindingFailure) return exactPaneUnavailableResult(target, bindingFailure);
|
|
281
586
|
const sendResult = await sendPaneInput({
|
|
282
587
|
paneTarget,
|
|
283
588
|
prompt,
|
|
284
589
|
submitKeyPresses: 0,
|
|
590
|
+
exactPaneId: exactPaneIdentity,
|
|
285
591
|
});
|
|
286
592
|
if (!sendResult.ok) return sendResult;
|
|
287
593
|
|
|
288
|
-
|
|
594
|
+
let exactPaneProof = sendResult.exactPaneProof || null;
|
|
595
|
+
let expectedPanePid = typeof sendResult.exactPaneProof?.pid === 'number' ? sendResult.exactPaneProof.pid : undefined;
|
|
596
|
+
const verifyExplicitPane = async () => {
|
|
597
|
+
const paneProof = await verifyExactPaneLive(exactPaneIdentity, expectedPanePid);
|
|
598
|
+
exactPaneProof = paneProof.proof || null;
|
|
599
|
+
if (paneProof.ok && typeof paneProof.proof?.pid === 'number') expectedPanePid ??= paneProof.proof.pid;
|
|
600
|
+
return paneProof;
|
|
601
|
+
};
|
|
289
602
|
const submitArgv = [
|
|
290
603
|
['send-keys', '-t', target, 'Tab'],
|
|
291
604
|
['send-keys', '-t', target, 'C-m'],
|
|
292
605
|
];
|
|
606
|
+
const firstSubmitProof = await verifyExplicitPane();
|
|
607
|
+
if (!firstSubmitProof.ok) {
|
|
608
|
+
return exactPaneUnavailableResult(target, firstSubmitProof, {
|
|
609
|
+
argv: { typeArgv: sendResult.argv?.typeArgv || null, submitArgv },
|
|
610
|
+
});
|
|
611
|
+
}
|
|
293
612
|
try {
|
|
294
613
|
await runProcess('tmux', submitArgv[0], 3000);
|
|
295
614
|
if (submitDelayMs > 0) {
|
|
296
615
|
await new Promise((resolve) => setTimeout(resolve, submitDelayMs));
|
|
297
616
|
}
|
|
617
|
+
const secondSubmitProof = await verifyExplicitPane();
|
|
618
|
+
if (!secondSubmitProof.ok) {
|
|
619
|
+
return exactPaneUnavailableResult(target, secondSubmitProof, {
|
|
620
|
+
argv: { typeArgv: sendResult.argv?.typeArgv || null, submitArgv },
|
|
621
|
+
});
|
|
622
|
+
}
|
|
298
623
|
await runProcess('tmux', submitArgv[1], 3000);
|
|
299
624
|
return {
|
|
300
625
|
ok: true,
|
|
@@ -302,6 +627,7 @@ export async function queuePaneInput({
|
|
|
302
627
|
reason: 'queued',
|
|
303
628
|
paneTarget: target,
|
|
304
629
|
argv: { typeArgv: sendResult.argv?.typeArgv || null, submitArgv },
|
|
630
|
+
exactPaneProof,
|
|
305
631
|
};
|
|
306
632
|
} catch (error) {
|
|
307
633
|
return {
|
|
@@ -310,11 +636,12 @@ export async function queuePaneInput({
|
|
|
310
636
|
reason: 'queue_failed',
|
|
311
637
|
paneTarget: target,
|
|
312
638
|
argv: { typeArgv: sendResult.argv?.typeArgv || null, submitArgv },
|
|
639
|
+
exactPaneProof,
|
|
313
640
|
error: error instanceof Error ? error.message : safeString(error),
|
|
314
641
|
};
|
|
315
642
|
}
|
|
316
643
|
}
|
|
317
644
|
|
|
318
|
-
export async function checkPaneReadyForTeamSendKeys(paneTarget: any): Promise<any> {
|
|
319
|
-
return evaluatePaneInjectionReadiness(paneTarget);
|
|
645
|
+
export async function checkPaneReadyForTeamSendKeys(paneTarget: any, exactPaneId: any): Promise<any> {
|
|
646
|
+
return evaluatePaneInjectionReadiness(paneTarget, { exactPaneId });
|
|
320
647
|
}
|
|
@@ -14,8 +14,7 @@ import { appendTeamDeliveryLog } from '../../team/delivery-log.js';
|
|
|
14
14
|
import { safeString, asNumber, isTerminalPhase } from './utils.js';
|
|
15
15
|
import { readJsonIfExists } from './state-io.js';
|
|
16
16
|
import { logTmuxHookEvent } from './log.js';
|
|
17
|
-
import { evaluatePaneInjectionReadiness, sendPaneInput } from './team-tmux-guard.js';
|
|
18
|
-
import { resolvePaneTarget } from './tmux-injection.js';
|
|
17
|
+
import { evaluatePaneInjectionReadiness, normalizeExactPaneId, sendPaneInput } from './team-tmux-guard.js';
|
|
19
18
|
import { readTeamWorkersForIdleCheck } from './team-worker.js';
|
|
20
19
|
|
|
21
20
|
const STOP_NUDGE_COOLDOWN_MS = 30_000;
|
|
@@ -134,17 +133,8 @@ function resolveWorkerStopCooldownMs() {
|
|
|
134
133
|
return STOP_NUDGE_COOLDOWN_MS;
|
|
135
134
|
}
|
|
136
135
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
if (!normalizedLeaderPaneId) return '';
|
|
140
|
-
try {
|
|
141
|
-
const resolved = await resolvePaneTarget({ type: 'pane', value: normalizedLeaderPaneId }, '', '', '', {});
|
|
142
|
-
const paneTarget = safeString(resolved?.paneTarget).trim();
|
|
143
|
-
if (paneTarget) return paneTarget;
|
|
144
|
-
} catch {
|
|
145
|
-
// Fall back to the recorded pane id; readiness guard remains authoritative.
|
|
146
|
-
}
|
|
147
|
-
return normalizedLeaderPaneId;
|
|
136
|
+
function resolveCanonicalLeaderPaneId(leaderPaneId) {
|
|
137
|
+
return normalizeExactPaneId(leaderPaneId);
|
|
148
138
|
}
|
|
149
139
|
|
|
150
140
|
async function recordSuppressedWorkerStopNudge({
|
|
@@ -304,9 +294,16 @@ export async function maybeNudgeLeaderForAllowedWorkerStop({
|
|
|
304
294
|
const teamInfo = await readTeamWorkersForIdleCheck(stateDir, teamName);
|
|
305
295
|
if (!teamInfo) return { ok: false, result: 'unresolved' };
|
|
306
296
|
({ tmuxSession, leaderPaneId } = teamInfo);
|
|
307
|
-
const
|
|
308
|
-
|
|
309
|
-
|
|
297
|
+
const leaderPanePid = Number.isInteger(teamInfo.leaderPanePid) && Number(teamInfo.leaderPanePid) > 0
|
|
298
|
+
? Number(teamInfo.leaderPanePid)
|
|
299
|
+
: undefined;
|
|
300
|
+
const leaderPaneOwnerId = safeString(teamInfo.tmuxPaneOwnerId).trim();
|
|
301
|
+
const resolvedLeaderPaneId = await resolveCanonicalLeaderPaneId(leaderPaneId);
|
|
302
|
+
const tmuxTarget = resolvedLeaderPaneId && resolvedLeaderPaneId !== normalizeExactPaneId(teamInfo.hudPaneId)
|
|
303
|
+
? resolvedLeaderPaneId
|
|
304
|
+
: '';
|
|
305
|
+
|
|
306
|
+
if (!tmuxTarget || !leaderPanePid || !leaderPaneOwnerId) {
|
|
310
307
|
if (!(await teamStateAllowsWorkerStopNudge(stateDir, teamName))) {
|
|
311
308
|
await recordShutdownSuppressionOnce();
|
|
312
309
|
return { ok: true, result: TEAM_SHUTDOWN_NO_INJECTION_REASON };
|
|
@@ -330,6 +327,9 @@ export async function maybeNudgeLeaderForAllowedWorkerStop({
|
|
|
330
327
|
requireRunningAgent: true,
|
|
331
328
|
requireReady: false,
|
|
332
329
|
requireIdle: false,
|
|
330
|
+
exactPaneId: tmuxTarget,
|
|
331
|
+
expectedPanePid: leaderPanePid,
|
|
332
|
+
expectedPaneOwnerId: leaderPaneOwnerId,
|
|
333
333
|
});
|
|
334
334
|
if (!paneGuard.ok) {
|
|
335
335
|
if (!(await teamStateAllowsWorkerStopNudge(stateDir, teamName))) {
|
|
@@ -367,6 +367,10 @@ export async function maybeNudgeLeaderForAllowedWorkerStop({
|
|
|
367
367
|
prompt,
|
|
368
368
|
submitKeyPresses: 2,
|
|
369
369
|
submitDelayMs: 100,
|
|
370
|
+
exactPaneId: tmuxTarget,
|
|
371
|
+
expectedPanePid: leaderPanePid,
|
|
372
|
+
expectedPaneOwnerId: leaderPaneOwnerId,
|
|
373
|
+
expectedHudPaneId: teamInfo.hudPaneId,
|
|
370
374
|
});
|
|
371
375
|
if (!sendResult.ok) throw new Error(sendResult.error || sendResult.reason || 'send_failed');
|
|
372
376
|
const deliveryMode = leaderHasActiveTask ? 'steered' : 'sent';
|