oh-my-codex 0.18.6 → 0.18.8
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 +6 -6
- package/Cargo.toml +1 -1
- package/README.md +59 -10
- package/crates/omx-sparkshell/tests/execution.rs +1 -1
- package/dist/agents/__tests__/definitions.test.js +11 -0
- package/dist/agents/__tests__/definitions.test.js.map +1 -1
- package/dist/agents/__tests__/native-config.test.js +56 -6
- package/dist/agents/__tests__/native-config.test.js.map +1 -1
- package/dist/agents/definitions.d.ts +10 -0
- package/dist/agents/definitions.d.ts.map +1 -1
- package/dist/agents/definitions.js +5 -1
- package/dist/agents/definitions.js.map +1 -1
- package/dist/agents/native-config.d.ts +5 -1
- package/dist/agents/native-config.d.ts.map +1 -1
- package/dist/agents/native-config.js +19 -4
- package/dist/agents/native-config.js.map +1 -1
- package/dist/autopilot/__tests__/fsm.test.d.ts +2 -0
- package/dist/autopilot/__tests__/fsm.test.d.ts.map +1 -0
- package/dist/autopilot/__tests__/fsm.test.js +75 -0
- package/dist/autopilot/__tests__/fsm.test.js.map +1 -0
- package/dist/autopilot/__tests__/ralplan-gate.test.d.ts +2 -0
- package/dist/autopilot/__tests__/ralplan-gate.test.d.ts.map +1 -0
- package/dist/autopilot/__tests__/ralplan-gate.test.js +79 -0
- package/dist/autopilot/__tests__/ralplan-gate.test.js.map +1 -0
- package/dist/autopilot/deep-interview-gate.d.ts +18 -0
- package/dist/autopilot/deep-interview-gate.d.ts.map +1 -0
- package/dist/autopilot/deep-interview-gate.js +256 -0
- package/dist/autopilot/deep-interview-gate.js.map +1 -0
- package/dist/autopilot/fsm.d.ts +13 -0
- package/dist/autopilot/fsm.d.ts.map +1 -0
- package/dist/autopilot/fsm.js +70 -0
- package/dist/autopilot/fsm.js.map +1 -0
- package/dist/autopilot/ralplan-gate.d.ts +17 -0
- package/dist/autopilot/ralplan-gate.d.ts.map +1 -0
- package/dist/autopilot/ralplan-gate.js +61 -0
- package/dist/autopilot/ralplan-gate.js.map +1 -0
- package/dist/cli/__tests__/codex-plugin-layout.test.js +512 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js +39 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +83 -7
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/launch-fallback.test.js +175 -6
- package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
- package/dist/cli/__tests__/package-bin-contract.test.js +8 -4
- package/dist/cli/__tests__/package-bin-contract.test.js.map +1 -1
- package/dist/cli/__tests__/question.test.js +100 -0
- package/dist/cli/__tests__/question.test.js.map +1 -1
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +13 -0
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
- package/dist/cli/__tests__/ralph.test.js +14 -0
- package/dist/cli/__tests__/ralph.test.js.map +1 -1
- package/dist/cli/__tests__/setup-install-mode.test.js +89 -0
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
- package/dist/cli/__tests__/setup-refresh.test.js +83 -0
- package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
- package/dist/cli/__tests__/state.test.js +21 -0
- package/dist/cli/__tests__/state.test.js.map +1 -1
- package/dist/cli/__tests__/team.test.js +2 -2
- package/dist/cli/__tests__/team.test.js.map +1 -1
- package/dist/cli/__tests__/update.test.js +110 -2
- package/dist/cli/__tests__/update.test.js.map +1 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +8 -1
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.d.ts +14 -3
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +298 -50
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/plugin-marketplace.d.ts +14 -2
- package/dist/cli/plugin-marketplace.d.ts.map +1 -1
- package/dist/cli/plugin-marketplace.js +62 -15
- package/dist/cli/plugin-marketplace.js.map +1 -1
- package/dist/cli/question.d.ts.map +1 -1
- package/dist/cli/question.js +36 -5
- package/dist/cli/question.js.map +1 -1
- package/dist/cli/ralph.d.ts.map +1 -1
- package/dist/cli/ralph.js +3 -1
- package/dist/cli/ralph.js.map +1 -1
- package/dist/cli/setup-preferences.d.ts +2 -0
- package/dist/cli/setup-preferences.d.ts.map +1 -1
- package/dist/cli/setup-preferences.js +4 -0
- package/dist/cli/setup-preferences.js.map +1 -1
- package/dist/cli/setup.d.ts +3 -0
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +166 -27
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/state.d.ts.map +1 -1
- package/dist/cli/state.js +8 -1
- package/dist/cli/state.js.map +1 -1
- package/dist/cli/tmux-hook.d.ts.map +1 -1
- package/dist/cli/tmux-hook.js +16 -0
- package/dist/cli/tmux-hook.js.map +1 -1
- package/dist/cli/update.d.ts +2 -0
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +47 -3
- package/dist/cli/update.js.map +1 -1
- package/dist/config/__tests__/deep-interview.test.js +7 -6
- package/dist/config/__tests__/deep-interview.test.js.map +1 -1
- package/dist/config/__tests__/generator-notify.test.js +1 -0
- package/dist/config/__tests__/generator-notify.test.js.map +1 -1
- package/dist/config/deep-interview.d.ts.map +1 -1
- package/dist/config/deep-interview.js +14 -4
- package/dist/config/deep-interview.js.map +1 -1
- package/dist/config/generator.d.ts +2 -2
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +2 -2
- package/dist/config/generator.js.map +1 -1
- package/dist/config/team-mode.d.ts +12 -0
- package/dist/config/team-mode.d.ts.map +1 -0
- package/dist/config/team-mode.js +91 -0
- package/dist/config/team-mode.js.map +1 -0
- package/dist/hooks/__tests__/agents-overlay.test.js +88 -0
- package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
- package/dist/hooks/__tests__/autopilot-skill-contract.test.js +8 -0
- package/dist/hooks/__tests__/autopilot-skill-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/code-review-skill-contract.test.js +8 -0
- package/dist/hooks/__tests__/code-review-skill-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/deep-interview-contract.test.js +10 -0
- package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +1072 -14
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js +64 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +189 -0
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +35 -2
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +3 -3
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
- package/dist/hooks/__tests__/session.test.js +25 -0
- package/dist/hooks/__tests__/session.test.js.map +1 -1
- package/dist/hooks/__tests__/skill-guidance-contract.test.js +21 -0
- package/dist/hooks/__tests__/skill-guidance-contract.test.js.map +1 -1
- package/dist/hooks/agents-overlay.d.ts.map +1 -1
- package/dist/hooks/agents-overlay.js +36 -50
- package/dist/hooks/agents-overlay.js.map +1 -1
- package/dist/hooks/deep-interview-config-instruction.js +1 -1
- package/dist/hooks/deep-interview-config-instruction.js.map +1 -1
- package/dist/hooks/extensibility/__tests__/plugin-runner.test.js +31 -0
- package/dist/hooks/extensibility/__tests__/plugin-runner.test.js.map +1 -1
- package/dist/hooks/extensibility/plugin-runner.js +17 -21
- package/dist/hooks/extensibility/plugin-runner.js.map +1 -1
- package/dist/hooks/keyword-detector.d.ts +1 -0
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +428 -32
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/hooks/keyword-registry.d.ts.map +1 -1
- package/dist/hooks/keyword-registry.js +1 -0
- package/dist/hooks/keyword-registry.js.map +1 -1
- package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
- package/dist/hooks/prompt-guidance-contract.js +6 -0
- package/dist/hooks/prompt-guidance-contract.js.map +1 -1
- package/dist/hooks/session.d.ts +3 -0
- package/dist/hooks/session.d.ts.map +1 -1
- package/dist/hooks/session.js +13 -5
- package/dist/hooks/session.js.map +1 -1
- package/dist/hud/__tests__/authority.test.js +469 -31
- package/dist/hud/__tests__/authority.test.js.map +1 -1
- package/dist/hud/__tests__/hud-tmux-injection.test.js +2 -1
- package/dist/hud/__tests__/hud-tmux-injection.test.js.map +1 -1
- package/dist/hud/__tests__/index.test.js +210 -2
- package/dist/hud/__tests__/index.test.js.map +1 -1
- package/dist/hud/__tests__/reconcile.test.js +588 -28
- package/dist/hud/__tests__/reconcile.test.js.map +1 -1
- package/dist/hud/__tests__/render.test.js +61 -0
- package/dist/hud/__tests__/render.test.js.map +1 -1
- package/dist/hud/__tests__/state.test.js +208 -0
- package/dist/hud/__tests__/state.test.js.map +1 -1
- package/dist/hud/__tests__/tmux.test.js +314 -22
- package/dist/hud/__tests__/tmux.test.js.map +1 -1
- package/dist/hud/authority.d.ts +5 -0
- package/dist/hud/authority.d.ts.map +1 -1
- package/dist/hud/authority.js +337 -30
- package/dist/hud/authority.js.map +1 -1
- package/dist/hud/index.d.ts +20 -2
- package/dist/hud/index.d.ts.map +1 -1
- package/dist/hud/index.js +103 -26
- package/dist/hud/index.js.map +1 -1
- package/dist/hud/reconcile.d.ts +3 -3
- package/dist/hud/reconcile.d.ts.map +1 -1
- package/dist/hud/reconcile.js +129 -20
- package/dist/hud/reconcile.js.map +1 -1
- package/dist/hud/render.d.ts.map +1 -1
- package/dist/hud/render.js +35 -0
- package/dist/hud/render.js.map +1 -1
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +64 -50
- package/dist/hud/state.js.map +1 -1
- package/dist/hud/tmux.d.ts +26 -6
- package/dist/hud/tmux.d.ts.map +1 -1
- package/dist/hud/tmux.js +173 -38
- package/dist/hud/tmux.js.map +1 -1
- package/dist/hud/types.d.ts +11 -0
- package/dist/hud/types.d.ts.map +1 -1
- package/dist/hud/types.js.map +1 -1
- package/dist/mcp/__tests__/hermes-bridge.test.js +203 -7
- package/dist/mcp/__tests__/hermes-bridge.test.js.map +1 -1
- package/dist/mcp/__tests__/state-paths.test.js +71 -1
- package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
- package/dist/mcp/__tests__/state-server.test.js +13 -1
- package/dist/mcp/__tests__/state-server.test.js.map +1 -1
- package/dist/mcp/hermes-bridge.d.ts +12 -2
- package/dist/mcp/hermes-bridge.d.ts.map +1 -1
- package/dist/mcp/hermes-bridge.js +83 -9
- package/dist/mcp/hermes-bridge.js.map +1 -1
- package/dist/mcp/state-paths.d.ts +32 -0
- package/dist/mcp/state-paths.d.ts.map +1 -1
- package/dist/mcp/state-paths.js +113 -17
- package/dist/mcp/state-paths.js.map +1 -1
- package/dist/mcp/state-server.d.ts +4 -4
- package/dist/modes/__tests__/base-autoresearch-contract.test.js +7 -1
- package/dist/modes/__tests__/base-autoresearch-contract.test.js.map +1 -1
- package/dist/pipeline/__tests__/stages.test.js +130 -0
- package/dist/pipeline/__tests__/stages.test.js.map +1 -1
- package/dist/pipeline/orchestrator.js +1 -1
- package/dist/pipeline/orchestrator.js.map +1 -1
- package/dist/pipeline/stages/ralplan.d.ts +1 -0
- package/dist/pipeline/stages/ralplan.d.ts.map +1 -1
- package/dist/pipeline/stages/ralplan.js +14 -5
- package/dist/pipeline/stages/ralplan.js.map +1 -1
- package/dist/question/__tests__/deep-interview.test.js +160 -2
- package/dist/question/__tests__/deep-interview.test.js.map +1 -1
- package/dist/question/__tests__/policy.test.js +63 -3
- package/dist/question/__tests__/policy.test.js.map +1 -1
- package/dist/question/__tests__/renderer.test.js +191 -2
- package/dist/question/__tests__/renderer.test.js.map +1 -1
- package/dist/question/__tests__/state.test.js +94 -3
- package/dist/question/__tests__/state.test.js.map +1 -1
- package/dist/question/__tests__/ui.test.js +4 -0
- package/dist/question/__tests__/ui.test.js.map +1 -1
- package/dist/question/autopilot-wait.d.ts +12 -2
- package/dist/question/autopilot-wait.d.ts.map +1 -1
- package/dist/question/autopilot-wait.js +158 -47
- package/dist/question/autopilot-wait.js.map +1 -1
- package/dist/question/deep-interview.d.ts.map +1 -1
- package/dist/question/deep-interview.js +22 -6
- package/dist/question/deep-interview.js.map +1 -1
- package/dist/question/policy.d.ts.map +1 -1
- package/dist/question/policy.js +2 -5
- package/dist/question/policy.js.map +1 -1
- package/dist/question/renderer.d.ts +12 -0
- package/dist/question/renderer.d.ts.map +1 -1
- package/dist/question/renderer.js +87 -3
- package/dist/question/renderer.js.map +1 -1
- package/dist/question/state.d.ts +8 -1
- package/dist/question/state.d.ts.map +1 -1
- package/dist/question/state.js +54 -14
- package/dist/question/state.js.map +1 -1
- package/dist/question/types.d.ts +1 -1
- package/dist/question/types.d.ts.map +1 -1
- package/dist/question/ui.d.ts +1 -0
- package/dist/question/ui.d.ts.map +1 -1
- package/dist/question/ui.js +1 -0
- package/dist/question/ui.js.map +1 -1
- package/dist/ralplan/__tests__/runtime.test.js +191 -0
- package/dist/ralplan/__tests__/runtime.test.js.map +1 -1
- package/dist/ralplan/consensus-gate.d.ts +9 -1
- package/dist/ralplan/consensus-gate.d.ts.map +1 -1
- package/dist/ralplan/consensus-gate.js +84 -2
- package/dist/ralplan/consensus-gate.js.map +1 -1
- package/dist/ralplan/runtime.d.ts +9 -0
- package/dist/ralplan/runtime.d.ts.map +1 -1
- package/dist/ralplan/runtime.js +32 -11
- package/dist/ralplan/runtime.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +2315 -280
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/notify-state-io.test.js +72 -1
- package/dist/scripts/__tests__/notify-state-io.test.js.map +1 -1
- package/dist/scripts/__tests__/notify-tmux-injection.test.d.ts +2 -0
- package/dist/scripts/__tests__/notify-tmux-injection.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/notify-tmux-injection.test.js +57 -0
- package/dist/scripts/__tests__/notify-tmux-injection.test.js.map +1 -0
- package/dist/scripts/__tests__/run-test-files.test.js +74 -0
- package/dist/scripts/__tests__/run-test-files.test.js.map +1 -1
- package/dist/scripts/__tests__/verify-native-agents.test.js +65 -0
- package/dist/scripts/__tests__/verify-native-agents.test.js.map +1 -1
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +431 -56
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
- package/dist/scripts/codex-native-pre-post.js +79 -1
- package/dist/scripts/codex-native-pre-post.js.map +1 -1
- package/dist/scripts/eval/eval-parity-smoke.js +1 -1
- package/dist/scripts/eval/eval-parity-smoke.js.map +1 -1
- package/dist/scripts/hook-payload-guard.d.ts +9 -0
- package/dist/scripts/hook-payload-guard.d.ts.map +1 -0
- package/dist/scripts/hook-payload-guard.js +111 -0
- package/dist/scripts/hook-payload-guard.js.map +1 -0
- package/dist/scripts/notify-fallback-watcher.js +8 -1
- package/dist/scripts/notify-fallback-watcher.js.map +1 -1
- package/dist/scripts/notify-hook/__tests__/payload-guard.test.d.ts +2 -0
- package/dist/scripts/notify-hook/__tests__/payload-guard.test.d.ts.map +1 -0
- package/dist/scripts/notify-hook/__tests__/payload-guard.test.js +39 -0
- package/dist/scripts/notify-hook/__tests__/payload-guard.test.js.map +1 -0
- package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.js +3 -1
- package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/ralph-session-resume.d.ts.map +1 -1
- package/dist/scripts/notify-hook/ralph-session-resume.js +3 -10
- package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -1
- package/dist/scripts/notify-hook/state-io.d.ts.map +1 -1
- package/dist/scripts/notify-hook/state-io.js +62 -38
- package/dist/scripts/notify-hook/state-io.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 +7 -0
- package/dist/scripts/notify-hook/team-leader-nudge.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 +234 -86
- package/dist/scripts/notify-hook/team-worker-stop.js.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.d.ts +7 -0
- package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.js +24 -18
- package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
- package/dist/scripts/notify-hook.js +86 -13
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/scripts/run-test-files.js +193 -22
- package/dist/scripts/run-test-files.js.map +1 -1
- package/dist/scripts/sync-plugin-mirror.d.ts.map +1 -1
- package/dist/scripts/sync-plugin-mirror.js +61 -3
- package/dist/scripts/sync-plugin-mirror.js.map +1 -1
- package/dist/scripts/verify-native-agents.d.ts.map +1 -1
- package/dist/scripts/verify-native-agents.js +58 -1
- package/dist/scripts/verify-native-agents.js.map +1 -1
- package/dist/state/__tests__/operations.test.js +1125 -1
- package/dist/state/__tests__/operations.test.js.map +1 -1
- package/dist/state/__tests__/skill-active.test.js +46 -1
- package/dist/state/__tests__/skill-active.test.js.map +1 -1
- package/dist/state/__tests__/workflow-transition.test.js +98 -7
- package/dist/state/__tests__/workflow-transition.test.js.map +1 -1
- package/dist/state/operations.d.ts.map +1 -1
- package/dist/state/operations.js +159 -2
- package/dist/state/operations.js.map +1 -1
- package/dist/state/skill-active.js +6 -8
- package/dist/state/skill-active.js.map +1 -1
- package/dist/state/workflow-transition-reconcile.d.ts +6 -0
- package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
- package/dist/state/workflow-transition-reconcile.js +38 -15
- package/dist/state/workflow-transition-reconcile.js.map +1 -1
- package/dist/state/workflow-transition.d.ts.map +1 -1
- package/dist/state/workflow-transition.js +10 -3
- package/dist/state/workflow-transition.js.map +1 -1
- package/dist/subagents/__tests__/tracker.test.js +139 -0
- package/dist/subagents/__tests__/tracker.test.js.map +1 -1
- package/dist/subagents/tracker.d.ts +3 -0
- package/dist/subagents/tracker.d.ts.map +1 -1
- package/dist/subagents/tracker.js +41 -4
- package/dist/subagents/tracker.js.map +1 -1
- package/dist/team/__tests__/coordination-protocol.test.d.ts +2 -0
- package/dist/team/__tests__/coordination-protocol.test.d.ts.map +1 -0
- package/dist/team/__tests__/coordination-protocol.test.js +173 -0
- package/dist/team/__tests__/coordination-protocol.test.js.map +1 -0
- package/dist/team/__tests__/runtime.test.js +52 -3
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/scaling.test.js +9 -4
- package/dist/team/__tests__/scaling.test.js.map +1 -1
- package/dist/team/__tests__/state.test.js +83 -0
- package/dist/team/__tests__/state.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +240 -2
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/__tests__/worker-bootstrap.test.js +84 -0
- package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
- package/dist/team/__tests__/worker-runtime-identity.test.js +4 -2
- package/dist/team/__tests__/worker-runtime-identity.test.js.map +1 -1
- package/dist/team/coordination-protocol.d.ts +14 -0
- package/dist/team/coordination-protocol.d.ts.map +1 -0
- package/dist/team/coordination-protocol.js +244 -0
- package/dist/team/coordination-protocol.js.map +1 -0
- package/dist/team/runtime.d.ts +1 -0
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +19 -3
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +3 -2
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/state/tasks.d.ts.map +1 -1
- package/dist/team/state/tasks.js +24 -0
- package/dist/team/state/tasks.js.map +1 -1
- package/dist/team/state/types.d.ts +21 -1
- package/dist/team/state/types.d.ts.map +1 -1
- package/dist/team/state/types.js.map +1 -1
- package/dist/team/state.d.ts +17 -1
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +12 -5
- package/dist/team/state.js.map +1 -1
- package/dist/team/team-ops.d.ts +1 -1
- package/dist/team/team-ops.d.ts.map +1 -1
- package/dist/team/team-ops.js.map +1 -1
- package/dist/team/tmux-session.d.ts +2 -0
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +161 -13
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/worker-bootstrap.d.ts.map +1 -1
- package/dist/team/worker-bootstrap.js +63 -0
- package/dist/team/worker-bootstrap.js.map +1 -1
- package/dist/utils/__tests__/agents-model-table.test.js +4 -2
- package/dist/utils/__tests__/agents-model-table.test.js.map +1 -1
- package/dist/utils/agents-model-table.d.ts.map +1 -1
- package/dist/utils/agents-model-table.js +3 -0
- package/dist/utils/agents-model-table.js.map +1 -1
- package/dist/verification/__tests__/ci-rust-gates.test.js +81 -1
- package/dist/verification/__tests__/ci-rust-gates.test.js.map +1 -1
- package/package.json +8 -8
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +334 -21
- package/plugins/oh-my-codex/hooks/hooks.json +1 -2
- package/plugins/oh-my-codex/skills/autopilot/SKILL.md +13 -6
- package/plugins/oh-my-codex/skills/code-review/SKILL.md +7 -7
- package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +9 -4
- package/plugins/oh-my-codex/skills/ralph/SKILL.md +22 -22
- package/plugins/oh-my-codex/skills/ralplan/SKILL.md +12 -0
- package/plugins/oh-my-codex/skills/team/SKILL.md +16 -0
- package/plugins/oh-my-codex/skills/ultraqa/SKILL.md +9 -0
- package/plugins/oh-my-codex/skills/worker/SKILL.md +14 -0
- package/skills/autopilot/SKILL.md +13 -6
- package/skills/code-review/SKILL.md +7 -7
- package/skills/deep-interview/SKILL.md +9 -4
- package/skills/ralph/SKILL.md +22 -22
- package/skills/ralplan/SKILL.md +12 -0
- package/skills/team/SKILL.md +16 -0
- package/skills/ultraqa/SKILL.md +9 -0
- package/skills/worker/SKILL.md +14 -0
- package/src/scripts/__tests__/codex-native-hook.test.ts +4435 -2083
- package/src/scripts/__tests__/notify-state-io.test.ts +95 -0
- package/src/scripts/__tests__/notify-tmux-injection.test.ts +82 -0
- package/src/scripts/__tests__/run-test-files.test.ts +102 -0
- package/src/scripts/__tests__/verify-native-agents.test.ts +75 -0
- package/src/scripts/codex-native-hook.ts +536 -51
- package/src/scripts/codex-native-pre-post.ts +80 -0
- package/src/scripts/demo-team-e2e.sh +10 -7
- package/src/scripts/eval/eval-parity-smoke.ts +1 -1
- package/src/scripts/hook-payload-guard.ts +113 -0
- package/src/scripts/notify-fallback-watcher.ts +8 -1
- package/src/scripts/notify-hook/__tests__/payload-guard.test.ts +41 -0
- package/src/scripts/notify-hook/auto-nudge.ts +3 -1
- package/src/scripts/notify-hook/ralph-session-resume.ts +2 -8
- package/src/scripts/notify-hook/state-io.ts +75 -37
- package/src/scripts/notify-hook/team-leader-nudge.ts +7 -0
- package/src/scripts/notify-hook/team-worker-stop.ts +193 -52
- package/src/scripts/notify-hook/tmux-injection.ts +35 -19
- package/src/scripts/notify-hook.ts +105 -6
- package/src/scripts/run-test-files.ts +192 -22
- package/src/scripts/sync-plugin-mirror.ts +98 -9
- package/src/scripts/verify-native-agents.ts +65 -1
|
@@ -84,6 +84,139 @@ describe('reconcileHudForPromptSubmit', () => {
|
|
|
84
84
|
assert.equal(resized.length, 1);
|
|
85
85
|
assert.equal(resized[0]?.heightLines, HUD_TMUX_HEIGHT_LINES);
|
|
86
86
|
});
|
|
87
|
+
it('reaps orphaned same-session HUD panes whose leader pane was destroyed, then recreates a single HUD', async () => {
|
|
88
|
+
// Regression for the "team mode leaves only stacked HUD strips" bug: the leader
|
|
89
|
+
// pane (%21) was destroyed but its owner-tagged HUD panes remained, all pointing
|
|
90
|
+
// at the dead leader id. They match neither findHudWatchPaneIds (leader mismatch)
|
|
91
|
+
// nor findLegacyFocusedHudWatchPaneIds (they carry owner metadata), so each prompt
|
|
92
|
+
// submit previously appended a fresh HUD instead of reclaiming the orphans.
|
|
93
|
+
const killed = [];
|
|
94
|
+
const created = [];
|
|
95
|
+
const orphan = (paneId) => ({
|
|
96
|
+
paneId,
|
|
97
|
+
currentCommand: 'node',
|
|
98
|
+
startCommand: `exec env OMX_SESSION_ID='sess-a' OMX_TMUX_HUD_OWNER='1' ${OMX_TMUX_HUD_LEADER_PANE_ENV}='%21' node omx hud --watch --preset=focused`,
|
|
99
|
+
});
|
|
100
|
+
const result = await reconcileHudForPromptSubmit('/repo', {
|
|
101
|
+
env: { TMUX: '1', TMUX_PANE: '%33', OMX_SESSION_ID: 'sess-a', [OMX_TMUX_HUD_OWNER_ENV]: '1' },
|
|
102
|
+
listCurrentWindowPanes: () => [
|
|
103
|
+
// %33 is the current (live) leader pane; %21 is gone from the window.
|
|
104
|
+
{ paneId: '%33', currentCommand: 'codex', startCommand: 'codex' },
|
|
105
|
+
orphan('%34'),
|
|
106
|
+
orphan('%42'),
|
|
107
|
+
orphan('%47'),
|
|
108
|
+
],
|
|
109
|
+
killTmuxPane: (paneId) => {
|
|
110
|
+
killed.push(paneId);
|
|
111
|
+
return true;
|
|
112
|
+
},
|
|
113
|
+
resizeTmuxPane: () => true,
|
|
114
|
+
createHudWatchPane: (_cwd, cmd, options) => {
|
|
115
|
+
created.push({ cmd, options });
|
|
116
|
+
return '%50';
|
|
117
|
+
},
|
|
118
|
+
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
119
|
+
});
|
|
120
|
+
// All three dead-leader orphans are reaped, then exactly one fresh HUD is created.
|
|
121
|
+
assert.deepEqual(killed.sort(), ['%34', '%42', '%47']);
|
|
122
|
+
assert.equal(result.status, 'recreated');
|
|
123
|
+
assert.equal(result.paneId, '%50');
|
|
124
|
+
assert.equal(created.length, 1);
|
|
125
|
+
assert.equal(created[0]?.options?.targetPaneId, '%33');
|
|
126
|
+
assert.match(created[0]?.cmd || '', new RegExp(`${OMX_TMUX_HUD_LEADER_PANE_ENV}='%33'`));
|
|
127
|
+
});
|
|
128
|
+
it('reaps orphaned HUD panes tagged with an equivalent native session id', async () => {
|
|
129
|
+
// #2684 lets HUD dedupe treat the OMX owner id and Codex native session id as
|
|
130
|
+
// equivalent. Orphan reaping must use the same identity set so a canonical
|
|
131
|
+
// owner reconcile still reclaims dead-leader HUDs tagged with the native id.
|
|
132
|
+
const killed = [];
|
|
133
|
+
const result = await reconcileHudForPromptSubmit('/repo', {
|
|
134
|
+
env: { TMUX: '1', TMUX_PANE: '%1', OMX_SESSION_ID: 'codex-native-uuid', [OMX_TMUX_HUD_OWNER_ENV]: '1' },
|
|
135
|
+
sessionId: 'omx-owner-abc',
|
|
136
|
+
sessionIds: ['omx-owner-abc', 'codex-native-uuid'],
|
|
137
|
+
listCurrentWindowPanes: () => [
|
|
138
|
+
{ paneId: '%1', currentCommand: 'codex', startCommand: 'codex' },
|
|
139
|
+
{
|
|
140
|
+
paneId: '%2',
|
|
141
|
+
currentCommand: 'node',
|
|
142
|
+
startCommand: `env OMX_SESSION_ID='codex-native-uuid' OMX_TMUX_HUD_OWNER='1' ${OMX_TMUX_HUD_LEADER_PANE_ENV}='%21' node omx hud --watch`,
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
killTmuxPane: (paneId) => {
|
|
146
|
+
killed.push(paneId);
|
|
147
|
+
return true;
|
|
148
|
+
},
|
|
149
|
+
resizeTmuxPane: () => true,
|
|
150
|
+
createHudWatchPane: () => '%9',
|
|
151
|
+
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
152
|
+
});
|
|
153
|
+
assert.deepEqual(killed, ['%2']);
|
|
154
|
+
assert.equal(result.status, 'recreated');
|
|
155
|
+
assert.equal(result.paneId, '%9');
|
|
156
|
+
});
|
|
157
|
+
it('does not reap an orphaned HUD pane that belongs to a different session', async () => {
|
|
158
|
+
// A HUD owned by another session's leader (which may live in a different tmux
|
|
159
|
+
// window we cannot see here) must survive even when that leader is absent.
|
|
160
|
+
const killed = [];
|
|
161
|
+
const result = await reconcileHudForPromptSubmit('/repo', {
|
|
162
|
+
env: { TMUX: '1', TMUX_PANE: '%1', OMX_SESSION_ID: 'sess-a', [OMX_TMUX_HUD_OWNER_ENV]: '1' },
|
|
163
|
+
listCurrentWindowPanes: () => [
|
|
164
|
+
{ paneId: '%1', currentCommand: 'codex', startCommand: 'codex' },
|
|
165
|
+
{
|
|
166
|
+
paneId: '%4',
|
|
167
|
+
currentCommand: 'node',
|
|
168
|
+
startCommand: `env OMX_SESSION_ID='sess-b' OMX_TMUX_HUD_OWNER='1' ${OMX_TMUX_HUD_LEADER_PANE_ENV}='%5' node omx hud --watch`,
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
killTmuxPane: (paneId) => {
|
|
172
|
+
killed.push(paneId);
|
|
173
|
+
return true;
|
|
174
|
+
},
|
|
175
|
+
resizeTmuxPane: () => true,
|
|
176
|
+
createHudWatchPane: () => '%9',
|
|
177
|
+
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
178
|
+
});
|
|
179
|
+
// sess-b orphan is left untouched; this session simply creates its own HUD.
|
|
180
|
+
assert.deepEqual(killed, []);
|
|
181
|
+
assert.equal(result.status, 'recreated');
|
|
182
|
+
assert.equal(result.paneId, '%9');
|
|
183
|
+
});
|
|
184
|
+
it('reaps a same-session orphan whose recorded leader is itself another HUD pane', async () => {
|
|
185
|
+
// Review follow-up (#2682): when a HUD pane was mistakenly used as a leader, an
|
|
186
|
+
// orphan can name another HUD pane as its leader. That referenced HUD must not
|
|
187
|
+
// count as a live leader, or the orphan survives while the referenced HUD is
|
|
188
|
+
// reaped — leaving a dangling strip that still never matches the real pane.
|
|
189
|
+
const killed = [];
|
|
190
|
+
const result = await reconcileHudForPromptSubmit('/repo', {
|
|
191
|
+
env: { TMUX: '1', TMUX_PANE: '%1', OMX_SESSION_ID: 'sess-a', [OMX_TMUX_HUD_OWNER_ENV]: '1' },
|
|
192
|
+
listCurrentWindowPanes: () => [
|
|
193
|
+
{ paneId: '%1', currentCommand: 'codex', startCommand: 'codex' },
|
|
194
|
+
{
|
|
195
|
+
// orphan whose recorded leader (%3) is itself another HUD pane
|
|
196
|
+
paneId: '%2',
|
|
197
|
+
currentCommand: 'node',
|
|
198
|
+
startCommand: `exec env OMX_SESSION_ID='sess-a' OMX_TMUX_HUD_OWNER='1' ${OMX_TMUX_HUD_LEADER_PANE_ENV}='%3' node omx hud --watch --preset=focused`,
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
// the referenced HUD %3, itself orphaned (its leader %21 is gone)
|
|
202
|
+
paneId: '%3',
|
|
203
|
+
currentCommand: 'node',
|
|
204
|
+
startCommand: `exec env OMX_SESSION_ID='sess-a' OMX_TMUX_HUD_OWNER='1' ${OMX_TMUX_HUD_LEADER_PANE_ENV}='%21' node omx hud --watch --preset=focused`,
|
|
205
|
+
},
|
|
206
|
+
],
|
|
207
|
+
killTmuxPane: (paneId) => {
|
|
208
|
+
killed.push(paneId);
|
|
209
|
+
return true;
|
|
210
|
+
},
|
|
211
|
+
resizeTmuxPane: () => true,
|
|
212
|
+
createHudWatchPane: () => '%9',
|
|
213
|
+
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
214
|
+
});
|
|
215
|
+
// Both HUD-led and dead-leader orphans are reaped; a single fresh HUD is created.
|
|
216
|
+
assert.deepEqual(killed.sort(), ['%2', '%3']);
|
|
217
|
+
assert.equal(result.status, 'recreated');
|
|
218
|
+
assert.equal(result.paneId, '%9');
|
|
219
|
+
});
|
|
87
220
|
it('prefers an explicit session override when recreating HUD', async () => {
|
|
88
221
|
const created = [];
|
|
89
222
|
const result = await reconcileHudForPromptSubmit('/repo', {
|
|
@@ -128,6 +261,87 @@ describe('reconcileHudForPromptSubmit', () => {
|
|
|
128
261
|
assert.equal(created.length, 1);
|
|
129
262
|
assert.match(created[0]?.cmd || '', /^exec env OMX_SESSION_ID='sess boxed' OMX_TMUX_HUD_OWNER='1' OMX_TMUX_HUD_LEADER_PANE='%1' OMX_ROOT='\/tmp\/boxed root\/it'\\''s\/\$\(literal\)' '.*' '.*omx\.js' hud --watch/);
|
|
130
263
|
});
|
|
264
|
+
it('forwards OMX_STATE_ROOT when recreating HUD with shell-safe quoting', async () => {
|
|
265
|
+
const created = [];
|
|
266
|
+
const result = await reconcileHudForPromptSubmit('/repo', {
|
|
267
|
+
env: {
|
|
268
|
+
TMUX: '1',
|
|
269
|
+
TMUX_PANE: '%1',
|
|
270
|
+
OMX_SESSION_ID: 'sess-a',
|
|
271
|
+
OMX_STATE_ROOT: '/boxed state/root',
|
|
272
|
+
[OMX_TMUX_HUD_OWNER_ENV]: '1',
|
|
273
|
+
},
|
|
274
|
+
listCurrentWindowPanes: () => [{ paneId: '%1', currentCommand: 'codex', startCommand: 'codex' }],
|
|
275
|
+
createHudWatchPane: (_cwd, hudCmd) => {
|
|
276
|
+
created.push(hudCmd);
|
|
277
|
+
return '%9';
|
|
278
|
+
},
|
|
279
|
+
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
280
|
+
resizeTmuxPane: () => true,
|
|
281
|
+
readHudConfig: async () => ({ preset: 'focused', git: { display: 'branch' }, statusLine: { preset: 'focused' } }),
|
|
282
|
+
readAllState: async () => ({
|
|
283
|
+
version: null,
|
|
284
|
+
gitBranch: null,
|
|
285
|
+
ralph: null,
|
|
286
|
+
ultragoal: null,
|
|
287
|
+
ultrawork: null,
|
|
288
|
+
autopilot: null,
|
|
289
|
+
ralplan: null,
|
|
290
|
+
deepInterview: null,
|
|
291
|
+
autoresearch: null,
|
|
292
|
+
ultraqa: null,
|
|
293
|
+
team: null,
|
|
294
|
+
metrics: null,
|
|
295
|
+
hudNotify: null,
|
|
296
|
+
session: null,
|
|
297
|
+
}),
|
|
298
|
+
});
|
|
299
|
+
assert.equal(result.status, 'recreated');
|
|
300
|
+
assert.match(created[0] ?? '', /OMX_STATE_ROOT='\/boxed state\/root'/);
|
|
301
|
+
assert.doesNotMatch(created[0] ?? '', /OMX_ROOT=/);
|
|
302
|
+
});
|
|
303
|
+
it('forwards OMX_TEAM_STATE_ROOT before boxed roots when recreating HUD', async () => {
|
|
304
|
+
const created = [];
|
|
305
|
+
const result = await reconcileHudForPromptSubmit('/repo', {
|
|
306
|
+
env: {
|
|
307
|
+
TMUX: '1',
|
|
308
|
+
TMUX_PANE: '%1',
|
|
309
|
+
OMX_SESSION_ID: 'sess-a',
|
|
310
|
+
OMX_ROOT: '/boxed-root',
|
|
311
|
+
OMX_STATE_ROOT: '/boxed-state-root',
|
|
312
|
+
OMX_TEAM_STATE_ROOT: '/team-state-root',
|
|
313
|
+
[OMX_TMUX_HUD_OWNER_ENV]: '1',
|
|
314
|
+
},
|
|
315
|
+
listCurrentWindowPanes: () => [{ paneId: '%1', currentCommand: 'codex', startCommand: 'codex' }],
|
|
316
|
+
createHudWatchPane: (_cwd, hudCmd) => {
|
|
317
|
+
created.push(hudCmd);
|
|
318
|
+
return '%9';
|
|
319
|
+
},
|
|
320
|
+
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
321
|
+
resizeTmuxPane: () => true,
|
|
322
|
+
readHudConfig: async () => ({ preset: 'focused', git: { display: 'branch' }, statusLine: { preset: 'focused' } }),
|
|
323
|
+
readAllState: async () => ({
|
|
324
|
+
version: null,
|
|
325
|
+
gitBranch: null,
|
|
326
|
+
ralph: null,
|
|
327
|
+
ultragoal: null,
|
|
328
|
+
ultrawork: null,
|
|
329
|
+
autopilot: null,
|
|
330
|
+
ralplan: null,
|
|
331
|
+
deepInterview: null,
|
|
332
|
+
autoresearch: null,
|
|
333
|
+
ultraqa: null,
|
|
334
|
+
team: null,
|
|
335
|
+
metrics: null,
|
|
336
|
+
hudNotify: null,
|
|
337
|
+
session: null,
|
|
338
|
+
}),
|
|
339
|
+
});
|
|
340
|
+
assert.equal(result.status, 'recreated');
|
|
341
|
+
assert.match(created[0] ?? '', /OMX_TEAM_STATE_ROOT='\/team-state-root'/);
|
|
342
|
+
assert.doesNotMatch(created[0] ?? '', /OMX_ROOT=/);
|
|
343
|
+
assert.doesNotMatch(created[0] ?? '', /OMX_STATE_ROOT=/);
|
|
344
|
+
});
|
|
131
345
|
it('targets the emitting pane window when listing and creating HUD panes', async () => {
|
|
132
346
|
const listArgs = [];
|
|
133
347
|
const created = [];
|
|
@@ -147,11 +361,141 @@ describe('reconcileHudForPromptSubmit', () => {
|
|
|
147
361
|
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
148
362
|
});
|
|
149
363
|
assert.equal(result.status, 'recreated');
|
|
150
|
-
assert.deepEqual(listArgs, ['%leader']);
|
|
364
|
+
assert.deepEqual(listArgs, ['%leader', '%leader']);
|
|
151
365
|
assert.equal(created[0]?.options?.targetPaneId, '%leader');
|
|
152
366
|
});
|
|
153
|
-
it('
|
|
367
|
+
it('keeps prompt-submit HUD recreation scoped to the emitting pane in multi-pane windows', async () => {
|
|
368
|
+
const created = [];
|
|
369
|
+
const result = await reconcileHudForPromptSubmit('/repo', {
|
|
370
|
+
env: { TMUX: '1', TMUX_PANE: '%right', OMX_SESSION_ID: 'sess-right', [OMX_TMUX_HUD_OWNER_ENV]: '1' },
|
|
371
|
+
listCurrentWindowPanes: () => [
|
|
372
|
+
{ paneId: '%left', currentCommand: 'codex', startCommand: 'codex' },
|
|
373
|
+
{ paneId: '%right', currentCommand: 'codex', startCommand: 'codex' },
|
|
374
|
+
],
|
|
375
|
+
createHudWatchPane: (_cwd, _cmd, options) => {
|
|
376
|
+
created.push({ options });
|
|
377
|
+
return '%hud-right';
|
|
378
|
+
},
|
|
379
|
+
resizeTmuxPane: () => true,
|
|
380
|
+
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
381
|
+
});
|
|
382
|
+
assert.equal(result.status, 'recreated');
|
|
383
|
+
assert.equal(created[0]?.options?.targetPaneId, '%right');
|
|
384
|
+
assert.equal(Object.hasOwn(created[0]?.options ?? {}, 'fullWidth'), false);
|
|
385
|
+
});
|
|
386
|
+
it('collapses same-owner HUD panes that appear during the create race window', async () => {
|
|
387
|
+
const killed = [];
|
|
388
|
+
const resized = [];
|
|
389
|
+
let listCount = 0;
|
|
390
|
+
const result = await reconcileHudForPromptSubmit('/repo', {
|
|
391
|
+
env: { TMUX: '1', TMUX_PANE: '%1', OMX_SESSION_ID: 'sess-race', [OMX_TMUX_HUD_OWNER_ENV]: '1' },
|
|
392
|
+
listCurrentWindowPanes: () => {
|
|
393
|
+
listCount += 1;
|
|
394
|
+
if (listCount === 1) {
|
|
395
|
+
return [
|
|
396
|
+
{ paneId: '%1', currentCommand: 'codex', startCommand: 'codex' },
|
|
397
|
+
];
|
|
398
|
+
}
|
|
399
|
+
return [
|
|
400
|
+
{ paneId: '%1', currentCommand: 'codex', startCommand: 'codex' },
|
|
401
|
+
{
|
|
402
|
+
paneId: '%8',
|
|
403
|
+
currentCommand: 'node',
|
|
404
|
+
startCommand: `exec env OMX_SESSION_ID='sess-race' ${OMX_TMUX_HUD_LEADER_PANE_ENV}='%1' /node /omx.js hud --watch`,
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
paneId: '%9',
|
|
408
|
+
currentCommand: 'node',
|
|
409
|
+
startCommand: `exec env OMX_SESSION_ID='sess-race' ${OMX_TMUX_HUD_LEADER_PANE_ENV}='%1' /node /omx.js hud --watch --preset=focused`,
|
|
410
|
+
},
|
|
411
|
+
];
|
|
412
|
+
},
|
|
413
|
+
createHudWatchPane: () => '%9',
|
|
414
|
+
killTmuxPane: (paneId) => {
|
|
415
|
+
killed.push(paneId);
|
|
416
|
+
return true;
|
|
417
|
+
},
|
|
418
|
+
resizeTmuxPane: (paneId, heightLines) => {
|
|
419
|
+
resized.push({ paneId, heightLines });
|
|
420
|
+
return true;
|
|
421
|
+
},
|
|
422
|
+
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
423
|
+
});
|
|
424
|
+
assert.equal(result.status, 'replaced_duplicates');
|
|
425
|
+
assert.equal(result.paneId, '%9');
|
|
426
|
+
assert.equal(result.duplicateCount, 1);
|
|
427
|
+
assert.deepEqual(killed, ['%8']);
|
|
428
|
+
assert.deepEqual(resized, [{ paneId: '%9', heightLines: HUD_TMUX_HEIGHT_LINES }]);
|
|
429
|
+
});
|
|
430
|
+
it('keeps an observed same-owner HUD when the returned create pane is absent from the post-create scan', async () => {
|
|
154
431
|
const killed = [];
|
|
432
|
+
const resized = [];
|
|
433
|
+
let listCount = 0;
|
|
434
|
+
const result = await reconcileHudForPromptSubmit('/repo', {
|
|
435
|
+
env: { TMUX: '1', TMUX_PANE: '%1', OMX_SESSION_ID: 'sess-race', [OMX_TMUX_HUD_OWNER_ENV]: '1' },
|
|
436
|
+
listCurrentWindowPanes: () => {
|
|
437
|
+
listCount += 1;
|
|
438
|
+
if (listCount === 1)
|
|
439
|
+
return [{ paneId: '%1', currentCommand: 'codex', startCommand: 'codex' }];
|
|
440
|
+
return [
|
|
441
|
+
{ paneId: '%1', currentCommand: 'codex', startCommand: 'codex' },
|
|
442
|
+
{
|
|
443
|
+
paneId: '%8',
|
|
444
|
+
currentCommand: 'node',
|
|
445
|
+
startCommand: `exec env OMX_SESSION_ID='sess-race' ${OMX_TMUX_HUD_LEADER_PANE_ENV}='%1' /node /omx.js hud --watch`,
|
|
446
|
+
},
|
|
447
|
+
];
|
|
448
|
+
},
|
|
449
|
+
createHudWatchPane: () => '%9',
|
|
450
|
+
killTmuxPane: (paneId) => { killed.push(paneId); return true; },
|
|
451
|
+
resizeTmuxPane: (paneId, heightLines) => { resized.push({ paneId, heightLines }); return true; },
|
|
452
|
+
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
453
|
+
});
|
|
454
|
+
assert.equal(result.status, 'recreated');
|
|
455
|
+
assert.equal(result.paneId, '%8');
|
|
456
|
+
assert.equal(result.duplicateCount, 0);
|
|
457
|
+
assert.deepEqual(killed, []);
|
|
458
|
+
assert.deepEqual(resized, [{ paneId: '%8', heightLines: HUD_TMUX_HEIGHT_LINES }]);
|
|
459
|
+
});
|
|
460
|
+
it('kills post-create duplicate HUD panes even when the keeper cannot be resized', async () => {
|
|
461
|
+
const killed = [];
|
|
462
|
+
const registered = [];
|
|
463
|
+
let listCount = 0;
|
|
464
|
+
const result = await reconcileHudForPromptSubmit('/repo', {
|
|
465
|
+
env: { TMUX: '1', TMUX_PANE: '%1', OMX_SESSION_ID: 'sess-race', [OMX_TMUX_HUD_OWNER_ENV]: '1' },
|
|
466
|
+
listCurrentWindowPanes: () => {
|
|
467
|
+
listCount += 1;
|
|
468
|
+
if (listCount === 1)
|
|
469
|
+
return [{ paneId: '%1', currentCommand: 'codex', startCommand: 'codex' }];
|
|
470
|
+
return [
|
|
471
|
+
{ paneId: '%1', currentCommand: 'codex', startCommand: 'codex' },
|
|
472
|
+
{
|
|
473
|
+
paneId: '%8',
|
|
474
|
+
currentCommand: 'node',
|
|
475
|
+
startCommand: `exec env OMX_SESSION_ID='sess-race' ${OMX_TMUX_HUD_LEADER_PANE_ENV}='%1' /node /omx.js hud --watch`,
|
|
476
|
+
},
|
|
477
|
+
{
|
|
478
|
+
paneId: '%9',
|
|
479
|
+
currentCommand: 'node',
|
|
480
|
+
startCommand: `exec env OMX_SESSION_ID='sess-race' ${OMX_TMUX_HUD_LEADER_PANE_ENV}='%1' /node /omx.js hud --watch`,
|
|
481
|
+
},
|
|
482
|
+
];
|
|
483
|
+
},
|
|
484
|
+
createHudWatchPane: () => '%9',
|
|
485
|
+
killTmuxPane: (paneId) => { killed.push(paneId); return true; },
|
|
486
|
+
resizeTmuxPane: () => false,
|
|
487
|
+
registerHudResizeHook: (paneId) => { registered.push(paneId); return true; },
|
|
488
|
+
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
489
|
+
});
|
|
490
|
+
assert.equal(result.status, 'failed');
|
|
491
|
+
assert.equal(result.paneId, '%9');
|
|
492
|
+
assert.equal(result.duplicateCount, 1);
|
|
493
|
+
assert.deepEqual(killed, ['%8']);
|
|
494
|
+
assert.deepEqual(registered, []);
|
|
495
|
+
});
|
|
496
|
+
it('kills duplicate HUD panes and reuses one existing pane', async () => {
|
|
497
|
+
const killed = [];
|
|
498
|
+
const resized = [];
|
|
155
499
|
const created = [];
|
|
156
500
|
const result = await reconcileHudForPromptSubmit('/repo', {
|
|
157
501
|
env: { TMUX: '1', TMUX_PANE: '%1', OMX_SESSION_ID: 'sess-a', [OMX_TMUX_HUD_OWNER_ENV]: '1' },
|
|
@@ -173,19 +517,179 @@ describe('reconcileHudForPromptSubmit', () => {
|
|
|
173
517
|
killed.push(paneId);
|
|
174
518
|
return true;
|
|
175
519
|
},
|
|
176
|
-
createHudWatchPane: (_cwd, cmd
|
|
520
|
+
createHudWatchPane: (_cwd, cmd) => {
|
|
177
521
|
created.push({ cmd });
|
|
178
|
-
assert.equal(options?.fullWidth, true);
|
|
179
|
-
assert.equal(options?.heightLines, HUD_TMUX_HEIGHT_LINES);
|
|
180
522
|
return '%9';
|
|
181
523
|
},
|
|
182
|
-
resizeTmuxPane: () =>
|
|
524
|
+
resizeTmuxPane: (paneId, heightLines) => {
|
|
525
|
+
resized.push({ paneId, heightLines });
|
|
526
|
+
return true;
|
|
527
|
+
},
|
|
183
528
|
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
184
529
|
});
|
|
185
530
|
assert.equal(result.status, 'replaced_duplicates');
|
|
186
|
-
assert.
|
|
187
|
-
assert.
|
|
188
|
-
assert.
|
|
531
|
+
assert.equal(result.paneId, '%2');
|
|
532
|
+
assert.deepEqual(killed, ['%3']);
|
|
533
|
+
assert.deepEqual(resized, [{ paneId: '%2', heightLines: HUD_TMUX_HEIGHT_LINES }]);
|
|
534
|
+
assert.deepEqual(created, []);
|
|
535
|
+
});
|
|
536
|
+
it('deduplicates same-leader HUD panes tagged with equivalent owner and canonical session ids', async () => {
|
|
537
|
+
const killed = [];
|
|
538
|
+
const resized = [];
|
|
539
|
+
const created = [];
|
|
540
|
+
const result = await reconcileHudForPromptSubmit('/repo', {
|
|
541
|
+
env: { TMUX: '1', TMUX_PANE: '%1', OMX_SESSION_ID: 'codex-native-uuid', [OMX_TMUX_HUD_OWNER_ENV]: '1' },
|
|
542
|
+
sessionId: 'omx-owner-abc',
|
|
543
|
+
sessionIds: ['omx-owner-abc', 'codex-native-uuid'],
|
|
544
|
+
listCurrentWindowPanes: () => [
|
|
545
|
+
{ paneId: '%1', currentCommand: 'codex', startCommand: 'codex' },
|
|
546
|
+
{
|
|
547
|
+
paneId: '%2',
|
|
548
|
+
currentCommand: 'node',
|
|
549
|
+
startCommand: `env OMX_SESSION_ID='omx-owner-abc' ${OMX_TMUX_HUD_LEADER_PANE_ENV}='%1' node omx hud --watch`,
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
paneId: '%3',
|
|
553
|
+
currentCommand: 'node',
|
|
554
|
+
startCommand: `env OMX_SESSION_ID='codex-native-uuid' ${OMX_TMUX_HUD_LEADER_PANE_ENV}='%1' node omx hud --watch`,
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
// Same equivalent session, but its recorded leader is itself a HUD pane;
|
|
558
|
+
// the orphan reaper should remove it before normal same-leader dedupe.
|
|
559
|
+
paneId: '%4',
|
|
560
|
+
currentCommand: 'node',
|
|
561
|
+
startCommand: `env OMX_SESSION_ID='codex-native-uuid' ${OMX_TMUX_HUD_LEADER_PANE_ENV}='%4' node omx hud --watch`,
|
|
562
|
+
},
|
|
563
|
+
],
|
|
564
|
+
killTmuxPane: (paneId) => {
|
|
565
|
+
killed.push(paneId);
|
|
566
|
+
return true;
|
|
567
|
+
},
|
|
568
|
+
createHudWatchPane: (_cwd, cmd) => {
|
|
569
|
+
created.push({ cmd });
|
|
570
|
+
return '%9';
|
|
571
|
+
},
|
|
572
|
+
resizeTmuxPane: (paneId, heightLines) => {
|
|
573
|
+
resized.push({ paneId, heightLines });
|
|
574
|
+
return true;
|
|
575
|
+
},
|
|
576
|
+
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
577
|
+
});
|
|
578
|
+
assert.equal(result.status, 'replaced_duplicates');
|
|
579
|
+
assert.equal(result.paneId, '%2');
|
|
580
|
+
assert.equal(result.duplicateCount, 1);
|
|
581
|
+
assert.deepEqual(killed, ['%4', '%3']);
|
|
582
|
+
assert.deepEqual(resized, [{ paneId: '%2', heightLines: HUD_TMUX_HEIGHT_LINES }]);
|
|
583
|
+
assert.deepEqual(created, []);
|
|
584
|
+
});
|
|
585
|
+
it('reuses and deduplicates legacy unowned focused HUD watch panes before recreating', async () => {
|
|
586
|
+
const killed = [];
|
|
587
|
+
const resized = [];
|
|
588
|
+
const created = [];
|
|
589
|
+
const result = await reconcileHudForPromptSubmit('/repo', {
|
|
590
|
+
env: { TMUX: '1', TMUX_PANE: '%1', OMX_SESSION_ID: 'sess-a', [OMX_TMUX_HUD_OWNER_ENV]: '1' },
|
|
591
|
+
listCurrentWindowPanes: () => [
|
|
592
|
+
{ paneId: '%1', currentCommand: 'codex', startCommand: 'codex' },
|
|
593
|
+
{ paneId: '%2', currentCommand: 'node', startCommand: 'node /tmp/bin/omx.js hud --watch --preset=focused' },
|
|
594
|
+
{ paneId: '%3', currentCommand: 'node', startCommand: 'node /tmp/bin/omx.js hud --watch --preset=focused' },
|
|
595
|
+
{ paneId: '%4', currentCommand: 'node', startCommand: 'node /tmp/bin/omx.js hud --watch --preset=minimal' },
|
|
596
|
+
{ paneId: '%5', currentCommand: 'node', startCommand: 'node /tmp/bin/omx.js hud --tmux --preset=focused' },
|
|
597
|
+
],
|
|
598
|
+
killTmuxPane: (paneId) => { killed.push(paneId); return true; },
|
|
599
|
+
createHudWatchPane: () => { created.push('create'); return '%9'; },
|
|
600
|
+
resizeTmuxPane: (paneId, heightLines) => { resized.push({ paneId, heightLines }); return true; },
|
|
601
|
+
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
602
|
+
});
|
|
603
|
+
assert.equal(result.status, 'replaced_duplicates');
|
|
604
|
+
assert.equal(result.paneId, '%2');
|
|
605
|
+
assert.equal(result.duplicateCount, 1);
|
|
606
|
+
assert.deepEqual(killed, ['%3']);
|
|
607
|
+
assert.deepEqual(resized, [{ paneId: '%2', heightLines: HUD_TMUX_HEIGHT_LINES }]);
|
|
608
|
+
assert.deepEqual(created, []);
|
|
609
|
+
});
|
|
610
|
+
it('treats an extra legacy focused pane as stale when an owned HUD already exists', async () => {
|
|
611
|
+
const killed = [];
|
|
612
|
+
const resized = [];
|
|
613
|
+
const result = await reconcileHudForPromptSubmit('/repo', {
|
|
614
|
+
env: { TMUX: '1', TMUX_PANE: '%1', OMX_SESSION_ID: 'sess-a', [OMX_TMUX_HUD_OWNER_ENV]: '1' },
|
|
615
|
+
listCurrentWindowPanes: () => [
|
|
616
|
+
{ paneId: '%1', currentCommand: 'codex', startCommand: 'codex' },
|
|
617
|
+
{
|
|
618
|
+
paneId: '%2',
|
|
619
|
+
currentCommand: 'node',
|
|
620
|
+
startCommand: `env OMX_SESSION_ID='sess-a' ${OMX_TMUX_HUD_LEADER_PANE_ENV}='%1' node omx hud --watch --preset=focused`,
|
|
621
|
+
},
|
|
622
|
+
{ paneId: '%3', currentCommand: 'node', startCommand: 'node /tmp/bin/omx.js hud --watch --preset=focused' },
|
|
623
|
+
],
|
|
624
|
+
killTmuxPane: (paneId) => { killed.push(paneId); return true; },
|
|
625
|
+
resizeTmuxPane: (paneId, heightLines) => { resized.push({ paneId, heightLines }); return true; },
|
|
626
|
+
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
627
|
+
});
|
|
628
|
+
assert.equal(result.status, 'replaced_duplicates');
|
|
629
|
+
assert.equal(result.paneId, '%2');
|
|
630
|
+
assert.equal(result.duplicateCount, 1);
|
|
631
|
+
assert.deepEqual(killed, ['%3']);
|
|
632
|
+
assert.deepEqual(resized, [{ paneId: '%2', heightLines: HUD_TMUX_HEIGHT_LINES }]);
|
|
633
|
+
});
|
|
634
|
+
it('deduplicates legacy focused panes that appear during the prompt-submit create race', async () => {
|
|
635
|
+
const killed = [];
|
|
636
|
+
const resized = [];
|
|
637
|
+
let listCount = 0;
|
|
638
|
+
const result = await reconcileHudForPromptSubmit('/repo', {
|
|
639
|
+
env: { TMUX: '1', TMUX_PANE: '%1', OMX_SESSION_ID: 'sess-race', [OMX_TMUX_HUD_OWNER_ENV]: '1' },
|
|
640
|
+
listCurrentWindowPanes: () => {
|
|
641
|
+
listCount += 1;
|
|
642
|
+
if (listCount === 1)
|
|
643
|
+
return [{ paneId: '%1', currentCommand: 'codex', startCommand: 'codex' }];
|
|
644
|
+
return [
|
|
645
|
+
{ paneId: '%1', currentCommand: 'codex', startCommand: 'codex' },
|
|
646
|
+
{ paneId: '%8', currentCommand: 'node', startCommand: 'node /tmp/bin/omx.js hud --watch --preset=focused' },
|
|
647
|
+
{
|
|
648
|
+
paneId: '%9',
|
|
649
|
+
currentCommand: 'node',
|
|
650
|
+
startCommand: `exec env OMX_SESSION_ID='sess-race' ${OMX_TMUX_HUD_LEADER_PANE_ENV}='%1' /node /omx.js hud --watch --preset=focused`,
|
|
651
|
+
},
|
|
652
|
+
];
|
|
653
|
+
},
|
|
654
|
+
createHudWatchPane: () => '%9',
|
|
655
|
+
killTmuxPane: (paneId) => { killed.push(paneId); return true; },
|
|
656
|
+
resizeTmuxPane: (paneId, heightLines) => { resized.push({ paneId, heightLines }); return true; },
|
|
657
|
+
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
658
|
+
});
|
|
659
|
+
assert.equal(result.status, 'replaced_duplicates');
|
|
660
|
+
assert.equal(result.paneId, '%9');
|
|
661
|
+
assert.equal(result.duplicateCount, 1);
|
|
662
|
+
assert.deepEqual(killed, ['%8']);
|
|
663
|
+
assert.deepEqual(resized, [{ paneId: '%9', heightLines: HUD_TMUX_HEIGHT_LINES }]);
|
|
664
|
+
});
|
|
665
|
+
it('kills existing duplicate HUD panes even when the keeper cannot be resized', async () => {
|
|
666
|
+
const killed = [];
|
|
667
|
+
const registered = [];
|
|
668
|
+
const result = await reconcileHudForPromptSubmit('/repo', {
|
|
669
|
+
env: { TMUX: '1', TMUX_PANE: '%1', OMX_SESSION_ID: 'sess-a', [OMX_TMUX_HUD_OWNER_ENV]: '1' },
|
|
670
|
+
listCurrentWindowPanes: () => [
|
|
671
|
+
{ paneId: '%1', currentCommand: 'codex', startCommand: 'codex' },
|
|
672
|
+
{
|
|
673
|
+
paneId: '%8',
|
|
674
|
+
currentCommand: 'node',
|
|
675
|
+
startCommand: `env OMX_SESSION_ID='sess-a' ${OMX_TMUX_HUD_LEADER_PANE_ENV}='%1' node omx hud --watch`,
|
|
676
|
+
},
|
|
677
|
+
{
|
|
678
|
+
paneId: '%9',
|
|
679
|
+
currentCommand: 'node',
|
|
680
|
+
startCommand: `env OMX_SESSION_ID='sess-a' ${OMX_TMUX_HUD_LEADER_PANE_ENV}='%1' node omx hud --watch`,
|
|
681
|
+
},
|
|
682
|
+
],
|
|
683
|
+
killTmuxPane: (paneId) => { killed.push(paneId); return true; },
|
|
684
|
+
resizeTmuxPane: () => false,
|
|
685
|
+
registerHudResizeHook: (paneId) => { registered.push(paneId); return true; },
|
|
686
|
+
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
687
|
+
});
|
|
688
|
+
assert.equal(result.status, 'failed');
|
|
689
|
+
assert.equal(result.paneId, '%8');
|
|
690
|
+
assert.equal(result.duplicateCount, 1);
|
|
691
|
+
assert.deepEqual(killed, ['%9']);
|
|
692
|
+
assert.deepEqual(registered, []);
|
|
189
693
|
});
|
|
190
694
|
it('does not resize, kill, or reuse another active leader session HUD in the same tmux window', async () => {
|
|
191
695
|
const killed = [];
|
|
@@ -243,6 +747,11 @@ describe('reconcileHudForPromptSubmit', () => {
|
|
|
243
747
|
{
|
|
244
748
|
paneId: '%4',
|
|
245
749
|
currentCommand: 'node',
|
|
750
|
+
startCommand: `env OMX_SESSION_ID='sess-b' ${OMX_TMUX_HUD_LEADER_PANE_ENV}='%1' node omx hud --watch`,
|
|
751
|
+
},
|
|
752
|
+
{
|
|
753
|
+
paneId: '%5',
|
|
754
|
+
currentCommand: 'node',
|
|
246
755
|
startCommand: `env OMX_SESSION_ID='sess-b' ${OMX_TMUX_HUD_LEADER_PANE_ENV}='%5' node omx hud --watch`,
|
|
247
756
|
},
|
|
248
757
|
],
|
|
@@ -255,7 +764,59 @@ describe('reconcileHudForPromptSubmit', () => {
|
|
|
255
764
|
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
256
765
|
});
|
|
257
766
|
assert.equal(result.status, 'replaced_duplicates');
|
|
258
|
-
assert.
|
|
767
|
+
assert.equal(result.paneId, '%2');
|
|
768
|
+
assert.deepEqual(killed, ['%3']);
|
|
769
|
+
});
|
|
770
|
+
it('deduplicates same-leader node HUD panes while preserving active ultragoal height despite empty mode state', async () => {
|
|
771
|
+
const killed = [];
|
|
772
|
+
const resized = [];
|
|
773
|
+
const created = [];
|
|
774
|
+
const result = await reconcileHudForPromptSubmit('/repo', {
|
|
775
|
+
env: { TMUX: '1', TMUX_PANE: '%1', OMX_SESSION_ID: 'sess-a', [OMX_TMUX_HUD_OWNER_ENV]: '1' },
|
|
776
|
+
listCurrentWindowPanes: () => [
|
|
777
|
+
{ paneId: '%1', currentCommand: 'zsh', startCommand: 'zsh' },
|
|
778
|
+
{ paneId: '%2', currentCommand: 'node', startCommand: `exec env OMX_SESSION_ID='sess-a' ${OMX_TMUX_HUD_LEADER_PANE_ENV}='%1' /node /omx.js hud --watch` },
|
|
779
|
+
{ paneId: '%3', currentCommand: 'node', startCommand: `exec env OMX_SESSION_ID='sess-a' ${OMX_TMUX_HUD_LEADER_PANE_ENV}='%1' /node /omx.js hud --watch` },
|
|
780
|
+
],
|
|
781
|
+
readHudConfig: async () => ({ preset: 'focused', git: { display: 'branch' }, statusLine: { preset: 'focused' } }),
|
|
782
|
+
readAllState: async () => ({
|
|
783
|
+
version: null,
|
|
784
|
+
gitBranch: null,
|
|
785
|
+
ralph: null,
|
|
786
|
+
ultragoal: {
|
|
787
|
+
active: true,
|
|
788
|
+
status: 'in_progress',
|
|
789
|
+
total: 1,
|
|
790
|
+
complete: 0,
|
|
791
|
+
pending: 0,
|
|
792
|
+
inProgress: 1,
|
|
793
|
+
failed: 0,
|
|
794
|
+
reviewBlocked: 0,
|
|
795
|
+
needsUserDecision: 0,
|
|
796
|
+
progressTotal: 1,
|
|
797
|
+
},
|
|
798
|
+
ultrawork: null,
|
|
799
|
+
autopilot: null,
|
|
800
|
+
ralplan: null,
|
|
801
|
+
deepInterview: null,
|
|
802
|
+
autoresearch: null,
|
|
803
|
+
ultraqa: null,
|
|
804
|
+
team: null,
|
|
805
|
+
metrics: null,
|
|
806
|
+
hudNotify: null,
|
|
807
|
+
session: null,
|
|
808
|
+
}),
|
|
809
|
+
killTmuxPane: (paneId) => { killed.push(paneId); return true; },
|
|
810
|
+
resizeTmuxPane: (paneId, heightLines) => { resized.push({ paneId, heightLines }); return true; },
|
|
811
|
+
createHudWatchPane: () => { created.push('create'); return '%9'; },
|
|
812
|
+
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
813
|
+
});
|
|
814
|
+
assert.equal(result.status, 'replaced_duplicates');
|
|
815
|
+
assert.equal(result.paneId, '%2');
|
|
816
|
+
assert.equal(result.duplicateCount, 1);
|
|
817
|
+
assert.deepEqual(killed, ['%3']);
|
|
818
|
+
assert.deepEqual(resized, [{ paneId: '%2', heightLines: HUD_TMUX_ULTRAGOAL_HEIGHT_LINES }]);
|
|
819
|
+
assert.deepEqual(created, []);
|
|
259
820
|
});
|
|
260
821
|
it('resizes an existing single HUD pane instead of recreating it', async () => {
|
|
261
822
|
const resized = [];
|
|
@@ -329,7 +890,7 @@ describe('reconcileHudForPromptSubmit', () => {
|
|
|
329
890
|
assert.equal(result.status, 'resized');
|
|
330
891
|
assert.deepEqual(resized, [{ paneId: '%2', heightLines: HUD_TMUX_ULTRAGOAL_HEIGHT_LINES }]);
|
|
331
892
|
});
|
|
332
|
-
it('
|
|
893
|
+
it('recreates instead of reusing a leader-only HUD pane when reviving with a canonical session id', async () => {
|
|
333
894
|
const resized = [];
|
|
334
895
|
const created = [];
|
|
335
896
|
const result = await reconcileHudForPromptSubmit('/repo', {
|
|
@@ -352,10 +913,10 @@ describe('reconcileHudForPromptSubmit', () => {
|
|
|
352
913
|
},
|
|
353
914
|
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
354
915
|
});
|
|
355
|
-
assert.equal(result.status, '
|
|
356
|
-
assert.equal(result.paneId, '%
|
|
357
|
-
assert.deepEqual(created, []);
|
|
358
|
-
assert.deepEqual(resized, [{ paneId: '%
|
|
916
|
+
assert.equal(result.status, 'recreated');
|
|
917
|
+
assert.equal(result.paneId, '%9');
|
|
918
|
+
assert.deepEqual(created, ['create']);
|
|
919
|
+
assert.deepEqual(resized, [{ paneId: '%9', heightLines: HUD_TMUX_HEIGHT_LINES }]);
|
|
359
920
|
});
|
|
360
921
|
it('deduplicates same-leader HUD panes without creating a new pane when session id is unavailable', async () => {
|
|
361
922
|
const killed = [];
|
|
@@ -421,15 +982,15 @@ describe('reconcileHudForPromptSubmit', () => {
|
|
|
421
982
|
},
|
|
422
983
|
],
|
|
423
984
|
resizeTmuxPane: () => true,
|
|
424
|
-
registerHudResizeHook: (hudPaneId,
|
|
425
|
-
registered.push({ hudPaneId,
|
|
985
|
+
registerHudResizeHook: (hudPaneId, leaderPaneId, heightLines) => {
|
|
986
|
+
registered.push({ hudPaneId, leaderPaneId, heightLines });
|
|
426
987
|
return true;
|
|
427
988
|
},
|
|
428
989
|
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
429
990
|
});
|
|
430
991
|
assert.equal(registered.length, 1);
|
|
431
992
|
assert.equal(registered[0]?.hudPaneId, '%2');
|
|
432
|
-
assert.equal(registered[0]?.
|
|
993
|
+
assert.equal(registered[0]?.leaderPaneId, '%1');
|
|
433
994
|
assert.equal(registered[0]?.heightLines, HUD_TMUX_HEIGHT_LINES);
|
|
434
995
|
});
|
|
435
996
|
it('registers client-resized hook scoped from the emitting pane after creating a new HUD pane', async () => {
|
|
@@ -441,18 +1002,18 @@ describe('reconcileHudForPromptSubmit', () => {
|
|
|
441
1002
|
],
|
|
442
1003
|
createHudWatchPane: () => '%9',
|
|
443
1004
|
resizeTmuxPane: () => true,
|
|
444
|
-
registerHudResizeHook: (hudPaneId,
|
|
445
|
-
registered.push({ hudPaneId,
|
|
1005
|
+
registerHudResizeHook: (hudPaneId, leaderPaneId, heightLines) => {
|
|
1006
|
+
registered.push({ hudPaneId, leaderPaneId, heightLines });
|
|
446
1007
|
return true;
|
|
447
1008
|
},
|
|
448
1009
|
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
449
1010
|
});
|
|
450
1011
|
assert.equal(registered.length, 1);
|
|
451
1012
|
assert.equal(registered[0]?.hudPaneId, '%9');
|
|
452
|
-
assert.equal(registered[0]?.
|
|
1013
|
+
assert.equal(registered[0]?.leaderPaneId, '%1');
|
|
453
1014
|
assert.equal(registered[0]?.heightLines, HUD_TMUX_HEIGHT_LINES);
|
|
454
1015
|
});
|
|
455
|
-
it('
|
|
1016
|
+
it('keeps the resize hook on the reused duplicate keeper pane', async () => {
|
|
456
1017
|
const unregistered = [];
|
|
457
1018
|
const registered = [];
|
|
458
1019
|
await reconcileHudForPromptSubmit('/repo', {
|
|
@@ -465,15 +1026,14 @@ describe('reconcileHudForPromptSubmit', () => {
|
|
|
465
1026
|
killTmuxPane: () => true,
|
|
466
1027
|
createHudWatchPane: () => '%9',
|
|
467
1028
|
resizeTmuxPane: () => true,
|
|
468
|
-
unregisterHudResizeHook: (
|
|
469
|
-
registerHudResizeHook: (hudPaneId,
|
|
1029
|
+
unregisterHudResizeHook: (leaderPaneId) => { unregistered.push(leaderPaneId); return true; },
|
|
1030
|
+
registerHudResizeHook: (hudPaneId, leaderPaneId) => { registered.push({ hudPaneId, leaderPaneId }); return true; },
|
|
470
1031
|
resolveOmxCliEntryPath: () => '/repo/dist/cli/omx.js',
|
|
471
1032
|
});
|
|
472
|
-
assert.
|
|
473
|
-
assert.equal(unregistered[0], '%1');
|
|
1033
|
+
assert.deepEqual(unregistered, []);
|
|
474
1034
|
assert.equal(registered.length, 1);
|
|
475
|
-
assert.equal(registered[0]?.hudPaneId, '%
|
|
476
|
-
assert.equal(registered[0]?.
|
|
1035
|
+
assert.equal(registered[0]?.hudPaneId, '%2');
|
|
1036
|
+
assert.equal(registered[0]?.leaderPaneId, '%1');
|
|
477
1037
|
});
|
|
478
1038
|
});
|
|
479
1039
|
//# sourceMappingURL=reconcile.test.js.map
|