oh-my-codex 0.13.2 → 0.14.1
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 +5 -5
- package/Cargo.toml +1 -1
- package/README.md +14 -8
- package/crates/omx-explore/src/main.rs +94 -1
- package/crates/omx-sparkshell/src/codex_bridge.rs +59 -12
- package/crates/omx-sparkshell/tests/execution.rs +48 -0
- package/dist/autoresearch/__tests__/skill-validation.test.d.ts +2 -0
- package/dist/autoresearch/__tests__/skill-validation.test.d.ts.map +1 -0
- package/dist/autoresearch/__tests__/skill-validation.test.js +91 -0
- package/dist/autoresearch/__tests__/skill-validation.test.js.map +1 -0
- package/dist/autoresearch/skill-validation.d.ts +13 -0
- package/dist/autoresearch/skill-validation.d.ts.map +1 -0
- package/dist/autoresearch/skill-validation.js +165 -0
- package/dist/autoresearch/skill-validation.js.map +1 -0
- package/dist/catalog/__tests__/schema.test.js +6 -0
- package/dist/catalog/__tests__/schema.test.js.map +1 -1
- package/dist/cli/__tests__/autoresearch-guided.test.js +236 -273
- package/dist/cli/__tests__/autoresearch-guided.test.js.map +1 -1
- package/dist/cli/__tests__/autoresearch.test.js +64 -653
- package/dist/cli/__tests__/autoresearch.test.js.map +1 -1
- package/dist/cli/__tests__/explore.test.js +33 -1
- package/dist/cli/__tests__/explore.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +18 -2
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/nested-help-routing.test.js +2 -1
- package/dist/cli/__tests__/nested-help-routing.test.js.map +1 -1
- package/dist/cli/__tests__/package-bin-contract.test.js +5 -0
- package/dist/cli/__tests__/package-bin-contract.test.js.map +1 -1
- package/dist/cli/__tests__/question.test.d.ts +2 -0
- package/dist/cli/__tests__/question.test.d.ts.map +1 -0
- package/dist/cli/__tests__/question.test.js +166 -0
- package/dist/cli/__tests__/question.test.js.map +1 -0
- package/dist/cli/__tests__/session-search-help.test.js +1 -1
- package/dist/cli/__tests__/session-search-help.test.js.map +1 -1
- package/dist/cli/__tests__/setup-agents-overwrite.test.js +32 -7
- package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
- package/dist/cli/__tests__/setup-refresh.test.js +8 -6
- package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
- package/dist/cli/__tests__/setup-skills-overwrite.test.js +2 -0
- package/dist/cli/__tests__/setup-skills-overwrite.test.js.map +1 -1
- package/dist/cli/__tests__/sparkshell-cli.test.js +23 -0
- package/dist/cli/__tests__/sparkshell-cli.test.js.map +1 -1
- package/dist/cli/__tests__/uninstall.test.js +65 -5
- package/dist/cli/__tests__/uninstall.test.js.map +1 -1
- package/dist/cli/__tests__/update.test.js +360 -26
- package/dist/cli/__tests__/update.test.js.map +1 -1
- package/dist/cli/autoresearch-guided.d.ts +24 -7
- package/dist/cli/autoresearch-guided.d.ts.map +1 -1
- package/dist/cli/autoresearch-guided.js +189 -130
- package/dist/cli/autoresearch-guided.js.map +1 -1
- package/dist/cli/autoresearch.d.ts +3 -2
- package/dist/cli/autoresearch.d.ts.map +1 -1
- package/dist/cli/autoresearch.js +29 -305
- package/dist/cli/autoresearch.js.map +1 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +43 -0
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/explore.d.ts.map +1 -1
- package/dist/cli/explore.js +18 -3
- package/dist/cli/explore.js.map +1 -1
- package/dist/cli/index.d.ts +2 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +15 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/question.d.ts +3 -0
- package/dist/cli/question.d.ts.map +1 -0
- package/dist/cli/question.js +182 -0
- package/dist/cli/question.js.map +1 -0
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +25 -3
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/sparkshell.d.ts.map +1 -1
- package/dist/cli/sparkshell.js +11 -1
- package/dist/cli/sparkshell.js.map +1 -1
- package/dist/cli/team.d.ts.map +1 -1
- package/dist/cli/team.js +159 -394
- package/dist/cli/team.js.map +1 -1
- package/dist/cli/uninstall.d.ts.map +1 -1
- package/dist/cli/uninstall.js +3 -1
- package/dist/cli/uninstall.js.map +1 -1
- package/dist/cli/update.d.ts +37 -9
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +204 -26
- package/dist/cli/update.js.map +1 -1
- package/dist/config/__tests__/generator-idempotent.test.js +51 -14
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
- package/dist/config/__tests__/generator-notify.test.js +35 -10
- package/dist/config/__tests__/generator-notify.test.js.map +1 -1
- package/dist/config/generator.d.ts +1 -0
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +61 -7
- package/dist/config/generator.js.map +1 -1
- package/dist/hooks/__tests__/analyze-routing-contract.test.js +22 -13
- package/dist/hooks/__tests__/analyze-routing-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/anti-slop-workflow.test.js +3 -3
- package/dist/hooks/__tests__/anti-slop-workflow.test.js.map +1 -1
- package/dist/hooks/__tests__/code-review-skill-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/code-review-skill-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/code-review-skill-contract.test.js +56 -0
- package/dist/hooks/__tests__/code-review-skill-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/debugger-log-recency-contract.test.js +2 -2
- package/dist/hooks/__tests__/debugger-log-recency-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/deep-interview-contract.test.js +51 -5
- package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/explicit-terminal-stop-docs-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-docs-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-docs-contract.test.js +43 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-docs-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-model-docs-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-model-docs-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-model-docs-contract.test.js +38 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-model-docs-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/explore-sparkshell-guidance-contract.test.js +2 -2
- package/dist/hooks/__tests__/explore-sparkshell-guidance-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +308 -17
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js +570 -2
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +717 -16
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js +25 -0
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js +894 -1
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js +34 -0
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +132 -0
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-guidance-contract.test.js +22 -4
- package/dist/hooks/__tests__/prompt-guidance-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-guidance-fragments.test.js +4 -2
- package/dist/hooks/__tests__/prompt-guidance-fragments.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-guidance-test-helpers.d.ts +1 -0
- package/dist/hooks/__tests__/prompt-guidance-test-helpers.d.ts.map +1 -1
- package/dist/hooks/__tests__/prompt-guidance-test-helpers.js +19 -1
- package/dist/hooks/__tests__/prompt-guidance-test-helpers.js.map +1 -1
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js +28 -0
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-orchestration-boundary.test.js +5 -4
- package/dist/hooks/__tests__/prompt-orchestration-boundary.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-team-routing.test.js +2 -2
- package/dist/hooks/__tests__/prompt-team-routing.test.js.map +1 -1
- package/dist/hooks/__tests__/triage-config.test.d.ts +2 -0
- package/dist/hooks/__tests__/triage-config.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/triage-config.test.js +211 -0
- package/dist/hooks/__tests__/triage-config.test.js.map +1 -0
- package/dist/hooks/__tests__/triage-heuristic.test.d.ts +2 -0
- package/dist/hooks/__tests__/triage-heuristic.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/triage-heuristic.test.js +230 -0
- package/dist/hooks/__tests__/triage-heuristic.test.js.map +1 -0
- package/dist/hooks/__tests__/triage-state.test.d.ts +2 -0
- package/dist/hooks/__tests__/triage-state.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/triage-state.test.js +426 -0
- package/dist/hooks/__tests__/triage-state.test.js.map +1 -0
- package/dist/hooks/keyword-detector.d.ts +26 -7
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +97 -26
- 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 +16 -9
- 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 +28 -1
- package/dist/hooks/prompt-guidance-contract.js.map +1 -1
- package/dist/hooks/triage-config.d.ts +33 -0
- package/dist/hooks/triage-config.d.ts.map +1 -0
- package/dist/hooks/triage-config.js +87 -0
- package/dist/hooks/triage-config.js.map +1 -0
- package/dist/hooks/triage-heuristic.d.ts +20 -0
- package/dist/hooks/triage-heuristic.d.ts.map +1 -0
- package/dist/hooks/triage-heuristic.js +210 -0
- package/dist/hooks/triage-heuristic.js.map +1 -0
- package/dist/hooks/triage-state.d.ts +63 -0
- package/dist/hooks/triage-state.d.ts.map +1 -0
- package/dist/hooks/triage-state.js +138 -0
- package/dist/hooks/triage-state.js.map +1 -0
- package/dist/hud/__tests__/reconcile.test.js +20 -0
- package/dist/hud/__tests__/reconcile.test.js.map +1 -1
- package/dist/hud/reconcile.d.ts +1 -0
- package/dist/hud/reconcile.d.ts.map +1 -1
- package/dist/hud/reconcile.js +2 -1
- package/dist/hud/reconcile.js.map +1 -1
- package/dist/mcp/__tests__/bootstrap.test.js +5 -24
- package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
- package/dist/mcp/__tests__/state-server.test.js +127 -0
- package/dist/mcp/__tests__/state-server.test.js.map +1 -1
- package/dist/mcp/bootstrap.d.ts +1 -1
- package/dist/mcp/bootstrap.d.ts.map +1 -1
- package/dist/mcp/bootstrap.js +3 -11
- package/dist/mcp/bootstrap.js.map +1 -1
- package/dist/mcp/state-server.d.ts +25 -0
- package/dist/mcp/state-server.d.ts.map +1 -1
- package/dist/mcp/state-server.js +41 -0
- package/dist/mcp/state-server.js.map +1 -1
- package/dist/modes/__tests__/base-ralph-contract.test.js +15 -0
- package/dist/modes/__tests__/base-ralph-contract.test.js.map +1 -1
- package/dist/modes/base.d.ts +1 -0
- package/dist/modes/base.d.ts.map +1 -1
- package/dist/modes/base.js +22 -6
- package/dist/modes/base.js.map +1 -1
- package/dist/notifications/__tests__/index.test.js +75 -0
- package/dist/notifications/__tests__/index.test.js.map +1 -1
- package/dist/notifications/__tests__/session-status.test.js +90 -0
- package/dist/notifications/__tests__/session-status.test.js.map +1 -1
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +39 -22
- package/dist/notifications/index.js.map +1 -1
- package/dist/notifications/session-status.d.ts +2 -0
- package/dist/notifications/session-status.d.ts.map +1 -1
- package/dist/notifications/session-status.js +19 -4
- package/dist/notifications/session-status.js.map +1 -1
- package/dist/openclaw/index.d.ts +5 -3
- package/dist/openclaw/index.d.ts.map +1 -1
- package/dist/openclaw/index.js +5 -3
- package/dist/openclaw/index.js.map +1 -1
- package/dist/question/__tests__/client.test.d.ts +2 -0
- package/dist/question/__tests__/client.test.d.ts.map +1 -0
- package/dist/question/__tests__/client.test.js +70 -0
- package/dist/question/__tests__/client.test.js.map +1 -0
- package/dist/question/__tests__/deep-interview.test.d.ts +2 -0
- package/dist/question/__tests__/deep-interview.test.d.ts.map +1 -0
- package/dist/question/__tests__/deep-interview.test.js +118 -0
- package/dist/question/__tests__/deep-interview.test.js.map +1 -0
- package/dist/question/__tests__/policy.test.d.ts +2 -0
- package/dist/question/__tests__/policy.test.d.ts.map +1 -0
- package/dist/question/__tests__/policy.test.js +107 -0
- package/dist/question/__tests__/policy.test.js.map +1 -0
- package/dist/question/__tests__/renderer.test.d.ts +2 -0
- package/dist/question/__tests__/renderer.test.d.ts.map +1 -0
- package/dist/question/__tests__/renderer.test.js +238 -0
- package/dist/question/__tests__/renderer.test.js.map +1 -0
- package/dist/question/__tests__/state.test.d.ts +2 -0
- package/dist/question/__tests__/state.test.d.ts.map +1 -0
- package/dist/question/__tests__/state.test.js +75 -0
- package/dist/question/__tests__/state.test.js.map +1 -0
- package/dist/question/__tests__/types.test.d.ts +2 -0
- package/dist/question/__tests__/types.test.d.ts.map +1 -0
- package/dist/question/__tests__/types.test.js +44 -0
- package/dist/question/__tests__/types.test.js.map +1 -0
- package/dist/question/__tests__/ui.test.d.ts +2 -0
- package/dist/question/__tests__/ui.test.d.ts.map +1 -0
- package/dist/question/__tests__/ui.test.js +169 -0
- package/dist/question/__tests__/ui.test.js.map +1 -0
- package/dist/question/client.d.ts +54 -0
- package/dist/question/client.d.ts.map +1 -0
- package/dist/question/client.js +77 -0
- package/dist/question/client.js.map +1 -0
- package/dist/question/deep-interview.d.ts +30 -0
- package/dist/question/deep-interview.d.ts.map +1 -0
- package/dist/question/deep-interview.js +118 -0
- package/dist/question/deep-interview.js.map +1 -0
- package/dist/question/policy.d.ts +18 -0
- package/dist/question/policy.d.ts.map +1 -0
- package/dist/question/policy.js +77 -0
- package/dist/question/policy.js.map +1 -0
- package/dist/question/renderer.d.ts +20 -0
- package/dist/question/renderer.d.ts.map +1 -0
- package/dist/question/renderer.js +190 -0
- package/dist/question/renderer.js.map +1 -0
- package/dist/question/state.d.ts +19 -0
- package/dist/question/state.d.ts.map +1 -0
- package/dist/question/state.js +108 -0
- package/dist/question/state.js.map +1 -0
- package/dist/question/types.d.ts +66 -0
- package/dist/question/types.d.ts.map +1 -0
- package/dist/question/types.js +82 -0
- package/dist/question/types.js.map +1 -0
- package/dist/question/ui.d.ts +38 -0
- package/dist/question/ui.d.ts.map +1 -0
- package/dist/question/ui.js +321 -0
- package/dist/question/ui.js.map +1 -0
- package/dist/ralph/contract.d.ts +1 -1
- package/dist/ralph/contract.d.ts.map +1 -1
- package/dist/ralph/contract.js +4 -1
- package/dist/ralph/contract.js.map +1 -1
- package/dist/ralplan/runtime.js +1 -1
- package/dist/ralplan/runtime.js.map +1 -1
- package/dist/runtime/__tests__/run-loop.test.d.ts +2 -0
- package/dist/runtime/__tests__/run-loop.test.d.ts.map +1 -0
- package/dist/runtime/__tests__/run-loop.test.js +35 -0
- package/dist/runtime/__tests__/run-loop.test.js.map +1 -0
- package/dist/runtime/__tests__/run-outcome.test.d.ts +2 -0
- package/dist/runtime/__tests__/run-outcome.test.d.ts.map +1 -0
- package/dist/runtime/__tests__/run-outcome.test.js +102 -0
- package/dist/runtime/__tests__/run-outcome.test.js.map +1 -0
- package/dist/runtime/__tests__/run-state.test.d.ts +2 -0
- package/dist/runtime/__tests__/run-state.test.d.ts.map +1 -0
- package/dist/runtime/__tests__/run-state.test.js +37 -0
- package/dist/runtime/__tests__/run-state.test.js.map +1 -0
- package/dist/runtime/run-loop.d.ts +45 -0
- package/dist/runtime/run-loop.d.ts.map +1 -0
- package/dist/runtime/run-loop.js +51 -0
- package/dist/runtime/run-loop.js.map +1 -0
- package/dist/runtime/run-outcome.d.ts +46 -0
- package/dist/runtime/run-outcome.d.ts.map +1 -0
- package/dist/runtime/run-outcome.js +285 -0
- package/dist/runtime/run-outcome.js.map +1 -0
- package/dist/runtime/run-state.d.ts +40 -0
- package/dist/runtime/run-state.d.ts.map +1 -0
- package/dist/runtime/run-state.js +120 -0
- package/dist/runtime/run-state.js.map +1 -0
- package/dist/runtime/terminal-lifecycle.d.ts +11 -0
- package/dist/runtime/terminal-lifecycle.d.ts.map +1 -0
- package/dist/runtime/terminal-lifecycle.js +52 -0
- package/dist/runtime/terminal-lifecycle.js.map +1 -0
- package/dist/scripts/__tests__/codex-native-hook.test.js +1459 -126
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/postinstall.test.d.ts +2 -0
- package/dist/scripts/__tests__/postinstall.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/postinstall.test.js +178 -0
- package/dist/scripts/__tests__/postinstall.test.js.map +1 -0
- package/dist/scripts/codex-native-hook.d.ts +3 -0
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +308 -61
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/notify-fallback-watcher.js +81 -2
- package/dist/scripts/notify-fallback-watcher.js.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.d.ts +27 -0
- package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.js +83 -20
- package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/managed-tmux.d.ts.map +1 -1
- package/dist/scripts/notify-hook/managed-tmux.js +64 -38
- package/dist/scripts/notify-hook/managed-tmux.js.map +1 -1
- package/dist/scripts/notify-hook/ralph-session-resume.js +1 -1
- package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -1
- package/dist/scripts/notify-hook.js +15 -5
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/scripts/postinstall.d.ts +22 -0
- package/dist/scripts/postinstall.d.ts.map +1 -0
- package/dist/scripts/postinstall.js +105 -0
- package/dist/scripts/postinstall.js.map +1 -0
- package/dist/scripts/sync-prompt-guidance-fragments.js +5 -0
- package/dist/scripts/sync-prompt-guidance-fragments.js.map +1 -1
- package/dist/state/__tests__/operations-ralph-phase.test.js +21 -0
- package/dist/state/__tests__/operations-ralph-phase.test.js.map +1 -1
- package/dist/state/__tests__/operations.test.js +18 -0
- package/dist/state/__tests__/operations.test.js.map +1 -1
- package/dist/state/__tests__/workflow-transition.test.js +11 -0
- 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 +15 -0
- package/dist/state/operations.js.map +1 -1
- package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
- package/dist/state/workflow-transition-reconcile.js +14 -1
- 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 +3 -1
- package/dist/state/workflow-transition.js.map +1 -1
- package/dist/team/__tests__/followup-planner.test.js +15 -0
- package/dist/team/__tests__/followup-planner.test.js.map +1 -1
- package/dist/team/__tests__/role-router.test.js +47 -0
- package/dist/team/__tests__/role-router.test.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +108 -2
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/followup-planner.d.ts.map +1 -1
- package/dist/team/followup-planner.js +31 -9
- package/dist/team/followup-planner.js.map +1 -1
- package/dist/team/role-router.d.ts.map +1 -1
- package/dist/team/role-router.js +73 -0
- package/dist/team/role-router.js.map +1 -1
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +18 -4
- package/dist/team/runtime.js.map +1 -1
- package/dist/utils/__tests__/dep-versions.test.js +25 -8
- package/dist/utils/__tests__/dep-versions.test.js.map +1 -1
- package/dist/utils/__tests__/paths.test.js +45 -0
- package/dist/utils/__tests__/paths.test.js.map +1 -1
- package/dist/utils/paths.d.ts +2 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +22 -7
- package/dist/utils/paths.js.map +1 -1
- package/dist/verification/__tests__/ci-rust-gates.test.js +1 -1
- package/dist/verification/__tests__/ci-rust-gates.test.js.map +1 -1
- package/package.json +4 -2
- package/prompts/architect.md +4 -0
- package/prompts/code-reviewer.md +3 -0
- package/prompts/dependency-expert.md +3 -0
- package/prompts/executor.md +5 -0
- package/prompts/explore.md +2 -0
- package/prompts/planner.md +5 -0
- package/prompts/product-analyst.md +8 -8
- package/prompts/researcher.md +78 -30
- package/prompts/verifier.md +4 -0
- package/skills/autoresearch/SKILL.md +68 -0
- package/skills/code-review/SKILL.md +94 -28
- package/skills/deep-interview/SKILL.md +100 -9
- package/skills/help/SKILL.md +3 -1
- package/skills/ralplan/SKILL.md +1 -0
- package/skills/team/SKILL.md +1 -0
- package/skills/ultrawork/SKILL.md +1 -0
- package/src/scripts/__tests__/codex-native-hook.test.ts +2373 -692
- package/src/scripts/__tests__/postinstall.test.ts +210 -0
- package/src/scripts/codex-native-hook.ts +365 -66
- package/src/scripts/notify-fallback-watcher.ts +92 -2
- package/src/scripts/notify-hook/auto-nudge.ts +89 -20
- package/src/scripts/notify-hook/managed-tmux.ts +70 -31
- package/src/scripts/notify-hook/ralph-session-resume.ts +1 -1
- package/src/scripts/notify-hook.ts +23 -5
- package/src/scripts/postinstall-bootstrap.js +23 -0
- package/src/scripts/postinstall.ts +161 -0
- package/src/scripts/sync-prompt-guidance-fragments.ts +4 -0
- package/templates/AGENTS.md +48 -37
- package/templates/catalog-manifest.json +7 -0
- package/templates/model-instructions/explore-lightweight-AGENTS.md +11 -0
- package/templates/model-instructions/sparkshell-lightweight-AGENTS.md +10 -0
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
maybeNudgeTeamLeader,
|
|
26
26
|
resolveLeaderStalenessThresholdMs,
|
|
27
27
|
} from './notify-hook/team-leader-nudge.js';
|
|
28
|
+
import { resolveManagedPaneFromAnchor, resolveManagedSessionPane } from './notify-hook/managed-tmux.js';
|
|
28
29
|
import { DEFAULT_MARKER } from './tmux-hook-engine.js';
|
|
29
30
|
import { isTerminalPhase } from './notify-hook/utils.js';
|
|
30
31
|
import { isSessionStale, isSessionStateAuthoritativeForCwd, readSessionState } from '../hooks/session.js';
|
|
@@ -36,6 +37,7 @@ import { listNotifyCanonicalActiveTeams } from './notify-hook/active-team.js';
|
|
|
36
37
|
import { sameFilePath } from '../utils/paths.js';
|
|
37
38
|
import { validateSessionId } from '../mcp/state-paths.js';
|
|
38
39
|
import { TEAM_NAME_SAFE_PATTERN } from '../team/contracts.js';
|
|
40
|
+
import { shouldContinueRun } from '../runtime/run-loop.js';
|
|
39
41
|
|
|
40
42
|
function argValue(name: string, fallback = ''): string {
|
|
41
43
|
const idx = process.argv.indexOf(name);
|
|
@@ -145,7 +147,7 @@ const watcherOwnerToken = `${process.pid}-${startedAt}-${Math.random().toString(
|
|
|
145
147
|
const RALPH_CONTINUE_TEXT = 'Ralph loop active continue';
|
|
146
148
|
const RALPH_CONTINUE_CADENCE_MS = 60_000;
|
|
147
149
|
const RALPH_STEER_LOCK_STALE_MS = 30_000;
|
|
148
|
-
const RALPH_TERMINAL_PHASES = new Set(['complete', 'failed', 'cancelled']);
|
|
150
|
+
const RALPH_TERMINAL_PHASES = new Set(['blocked_on_user', 'complete', 'failed', 'cancelled']);
|
|
149
151
|
const RALPH_STARTING_PHASE_TIMEOUT_MS = RALPH_CONTINUE_CADENCE_MS * 2;
|
|
150
152
|
const QUIET_ONCE_EVENT_TYPES = new Set(['watcher_start', 'watcher_once_complete']);
|
|
151
153
|
|
|
@@ -474,6 +476,7 @@ function normalizeRalphContinueSteerState(raw: Record<string, unknown> | null |
|
|
|
474
476
|
function hasRalphTerminalState(raw: Record<string, unknown> | null | undefined): boolean {
|
|
475
477
|
if (!raw || typeof raw !== 'object') return true;
|
|
476
478
|
if (raw.active !== true) return true;
|
|
479
|
+
if (!shouldContinueRun(raw)) return true;
|
|
477
480
|
const phase = safeString(raw.current_phase).trim().toLowerCase();
|
|
478
481
|
if (phase && RALPH_TERMINAL_PHASES.has(phase)) return true;
|
|
479
482
|
if (isStaleRalphStartingPhase(raw)) return true;
|
|
@@ -1029,6 +1032,90 @@ async function writePidFileRecord(): Promise<void> {
|
|
|
1029
1032
|
await writeFile(pidFilePath, JSON.stringify(nextRecord, null, 2)).catch(() => {});
|
|
1030
1033
|
}
|
|
1031
1034
|
|
|
1035
|
+
async function buildWatcherManagedPayload(): Promise<Record<string, string> | null> {
|
|
1036
|
+
const session = await readSessionState(cwd).catch(() => null);
|
|
1037
|
+
const sessionId = safeString(session?.session_id).trim();
|
|
1038
|
+
if (!sessionId || !session || isSessionStale(session)) return null;
|
|
1039
|
+
return { session_id: sessionId };
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
async function persistReboundRalphPaneState(
|
|
1043
|
+
statePath: string,
|
|
1044
|
+
state: Record<string, unknown> | null,
|
|
1045
|
+
paneId: string,
|
|
1046
|
+
nowIso: string,
|
|
1047
|
+
): Promise<Record<string, unknown>> {
|
|
1048
|
+
const latestState = await readFile(statePath, 'utf-8')
|
|
1049
|
+
.then((content) => JSON.parse(content) as Record<string, unknown>)
|
|
1050
|
+
.catch(() => null);
|
|
1051
|
+
const nextState = {
|
|
1052
|
+
...((latestState && typeof latestState === 'object') ? latestState : (state || {})),
|
|
1053
|
+
tmux_pane_id: paneId,
|
|
1054
|
+
tmux_pane_set_at: nowIso,
|
|
1055
|
+
};
|
|
1056
|
+
const tmpPath = `${statePath}.tmp.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}`;
|
|
1057
|
+
await writeFile(tmpPath, JSON.stringify(nextState, null, 2));
|
|
1058
|
+
try {
|
|
1059
|
+
await rename(tmpPath, statePath);
|
|
1060
|
+
} catch (error) {
|
|
1061
|
+
await unlink(tmpPath).catch(() => {});
|
|
1062
|
+
throw error;
|
|
1063
|
+
}
|
|
1064
|
+
return nextState;
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
async function resolveRalphContinuePaneTarget(
|
|
1068
|
+
activeRalph: ActiveModeResult,
|
|
1069
|
+
nowIso: string,
|
|
1070
|
+
): Promise<{ paneId: string; state: Record<string, unknown> | null; reboundFrom: string }> {
|
|
1071
|
+
const currentState = activeRalph.state && typeof activeRalph.state === 'object'
|
|
1072
|
+
? activeRalph.state as Record<string, unknown>
|
|
1073
|
+
: null;
|
|
1074
|
+
const anchorPaneId = safeString(currentState?.tmux_pane_id).trim();
|
|
1075
|
+
if (!anchorPaneId) {
|
|
1076
|
+
return {
|
|
1077
|
+
paneId: '',
|
|
1078
|
+
state: currentState,
|
|
1079
|
+
reboundFrom: '',
|
|
1080
|
+
};
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
const managedPayload = await buildWatcherManagedPayload();
|
|
1084
|
+
if (!managedPayload) {
|
|
1085
|
+
return {
|
|
1086
|
+
paneId: anchorPaneId,
|
|
1087
|
+
state: currentState,
|
|
1088
|
+
reboundFrom: '',
|
|
1089
|
+
};
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
let resolvedPaneId = await resolveManagedPaneFromAnchor(anchorPaneId, cwd, managedPayload, { allowTeamWorker: false });
|
|
1093
|
+
if (!resolvedPaneId) {
|
|
1094
|
+
resolvedPaneId = await resolveManagedSessionPane(cwd, managedPayload);
|
|
1095
|
+
}
|
|
1096
|
+
if (!resolvedPaneId) {
|
|
1097
|
+
return {
|
|
1098
|
+
paneId: '',
|
|
1099
|
+
state: currentState,
|
|
1100
|
+
reboundFrom: '',
|
|
1101
|
+
};
|
|
1102
|
+
}
|
|
1103
|
+
if (resolvedPaneId === anchorPaneId) {
|
|
1104
|
+
return {
|
|
1105
|
+
paneId: resolvedPaneId,
|
|
1106
|
+
state: currentState,
|
|
1107
|
+
reboundFrom: '',
|
|
1108
|
+
};
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
const updatedState = await persistReboundRalphPaneState(activeRalph.path, currentState, resolvedPaneId, nowIso);
|
|
1112
|
+
return {
|
|
1113
|
+
paneId: resolvedPaneId,
|
|
1114
|
+
state: updatedState,
|
|
1115
|
+
reboundFrom: anchorPaneId,
|
|
1116
|
+
};
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1032
1119
|
async function runRalphContinueSteerTick(): Promise<void> {
|
|
1033
1120
|
const now = Date.now();
|
|
1034
1121
|
const nowIso = new Date(now).toISOString();
|
|
@@ -1088,7 +1175,9 @@ async function runRalphContinueSteerTick(): Promise<void> {
|
|
|
1088
1175
|
return { sent: false, skipped: true };
|
|
1089
1176
|
}
|
|
1090
1177
|
|
|
1091
|
-
const
|
|
1178
|
+
const resolvedPane = await resolveRalphContinuePaneTarget(activeRalph, nowIso);
|
|
1179
|
+
activeRalph.state = resolvedPane.state;
|
|
1180
|
+
const paneId = resolvedPane.paneId;
|
|
1092
1181
|
if (!paneId) {
|
|
1093
1182
|
lastRalphContinueSteer.last_reason = 'pane_missing';
|
|
1094
1183
|
lastRalphContinueSteer.pane_id = '';
|
|
@@ -1113,6 +1202,7 @@ async function runRalphContinueSteerTick(): Promise<void> {
|
|
|
1113
1202
|
type: 'ralph_continue_steer',
|
|
1114
1203
|
reason: 'sent',
|
|
1115
1204
|
pane_id: paneId,
|
|
1205
|
+
rebound_from: resolvedPane.reboundFrom || null,
|
|
1116
1206
|
state_path: activeRalph.path,
|
|
1117
1207
|
current_phase: safeString(activeRalph.state?.current_phase) || null,
|
|
1118
1208
|
cadence_ms: RALPH_CONTINUE_CADENCE_MS,
|
|
@@ -21,6 +21,8 @@ import { logTmuxHookEvent } from './log.js';
|
|
|
21
21
|
import { evaluatePaneInjectionReadiness, mapPaneInjectionReadinessReason, sendPaneInput } from './team-tmux-guard.js';
|
|
22
22
|
import { stripOrchestrationIntentTags } from './orchestration-intent.js';
|
|
23
23
|
import { buildCapturePaneArgv, DEFAULT_MARKER, tmuxHookExplicitlyDisablesInjection } from '../tmux-hook-engine.js';
|
|
24
|
+
import { readAutoresearchCompletionStatus } from '../../autoresearch/skill-validation.js';
|
|
25
|
+
import { persistDeepInterviewModeState } from '../../hooks/keyword-detector.js';
|
|
24
26
|
import {
|
|
25
27
|
isManagedOmxSession,
|
|
26
28
|
resolveManagedCurrentPane,
|
|
@@ -36,6 +38,7 @@ export const DEEP_INTERVIEW_INPUT_LOCK_MESSAGE = 'Deep interview is active; auto
|
|
|
36
38
|
export const DEFAULT_AUTO_NUDGE_RESPONSE = 'continue with the current task only if it is already authorized';
|
|
37
39
|
const DEEP_INTERVIEW_ERROR_PATTERNS = [' error', ' failed', ' failure', ' exception', 'unable to continue', 'cannot continue', 'could not continue'];
|
|
38
40
|
const DEEP_INTERVIEW_ABORT_PATTERNS = ['aborted', 'cancelled', 'canceled'];
|
|
41
|
+
const DEEP_INTERVIEW_SUCCESS_PATTERNS = ['interview completed', 'interview complete', 'interview finished', 'final summary ready'];
|
|
39
42
|
const DEEP_INTERVIEW_ABORT_INPUTS = new Set(['abort', 'cancel', 'stop']);
|
|
40
43
|
const DEEP_INTERVIEW_BLOCKED_APPROVAL_PREFIXES = new Set(['next i should']);
|
|
41
44
|
const SKILL_PHASES = new Set(['planning', 'executing', 'reviewing', 'completing']);
|
|
@@ -99,6 +102,10 @@ function hasAnySubstring(text, patterns) {
|
|
|
99
102
|
return patterns.some((pattern) => lower.includes(pattern));
|
|
100
103
|
}
|
|
101
104
|
|
|
105
|
+
function looksLikeDeepInterviewSuccess(text) {
|
|
106
|
+
return hasAnySubstring(text, DEEP_INTERVIEW_SUCCESS_PATTERNS);
|
|
107
|
+
}
|
|
108
|
+
|
|
102
109
|
export function isDeepInterviewAutoApprovalLocked(skillState) {
|
|
103
110
|
return Boolean(
|
|
104
111
|
skillState
|
|
@@ -188,6 +195,78 @@ async function persistSkillActiveState(stateDir, sessionId, state) {
|
|
|
188
195
|
await writeScopedJson(stateDir, SKILL_ACTIVE_STATE_FILE, sessionId, state).catch(() => {});
|
|
189
196
|
}
|
|
190
197
|
|
|
198
|
+
function cloneSkillActiveState(state) {
|
|
199
|
+
if (!state || typeof state !== 'object') return null;
|
|
200
|
+
return {
|
|
201
|
+
...state,
|
|
202
|
+
input_lock: state.input_lock
|
|
203
|
+
? {
|
|
204
|
+
...state.input_lock,
|
|
205
|
+
blocked_inputs: Array.isArray(state.input_lock.blocked_inputs)
|
|
206
|
+
? [...state.input_lock.blocked_inputs]
|
|
207
|
+
: state.input_lock.blocked_inputs,
|
|
208
|
+
}
|
|
209
|
+
: state.input_lock,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export async function syncSkillStateFromTurn(stateDir, payload) {
|
|
214
|
+
const lastMessage = safeString(payload['last-assistant-message'] || payload.last_assistant_message || '');
|
|
215
|
+
const latestUserInput = latestUserInputFromPayload(payload);
|
|
216
|
+
const invocationSessionId = resolveInvocationSessionId(payload);
|
|
217
|
+
let skillState = await loadSkillActiveState(stateDir, invocationSessionId);
|
|
218
|
+
let releaseReason = null;
|
|
219
|
+
|
|
220
|
+
if (!skillState) {
|
|
221
|
+
return { invocationSessionId, skillState: null, releaseReason };
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const previousSkillState = cloneSkillActiveState(skillState);
|
|
225
|
+
const previousPhase = normalizeSkillPhase(skillState.phase);
|
|
226
|
+
const inferredPhase = inferSkillPhaseFromText(lastMessage, previousPhase);
|
|
227
|
+
const explicitDeepInterviewSuccess = skillState.skill === 'deep-interview' && looksLikeDeepInterviewSuccess(lastMessage);
|
|
228
|
+
const nextPhase = skillState.skill === 'deep-interview'
|
|
229
|
+
&& inferredPhase === 'completing'
|
|
230
|
+
&& previousPhase !== 'completing'
|
|
231
|
+
&& !explicitDeepInterviewSuccess
|
|
232
|
+
? previousPhase
|
|
233
|
+
: inferredPhase;
|
|
234
|
+
skillState.phase = nextPhase;
|
|
235
|
+
skillState.active = nextPhase !== 'completing';
|
|
236
|
+
|
|
237
|
+
if (skillState.skill === 'autoresearch') {
|
|
238
|
+
const completion = await readAutoresearchCompletionStatus(payload.cwd || process.cwd(), invocationSessionId);
|
|
239
|
+
skillState.validation_mode = completion.validationMode;
|
|
240
|
+
skillState.autoresearch_completion_reason = completion.reason;
|
|
241
|
+
skillState.completion_artifact_path = completion.artifactPath;
|
|
242
|
+
if (completion.complete) {
|
|
243
|
+
skillState.phase = 'completing';
|
|
244
|
+
skillState.active = false;
|
|
245
|
+
} else if (inferredPhase === 'completing') {
|
|
246
|
+
skillState.phase = previousPhase === 'completing' ? 'reviewing' : previousPhase;
|
|
247
|
+
skillState.active = true;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const nowIso = new Date().toISOString();
|
|
252
|
+
skillState.updated_at = nowIso;
|
|
253
|
+
releaseReason = inferDeepInterviewReleaseReason({ skillState, latestUserInput, lastMessage });
|
|
254
|
+
if (releaseReason && isDeepInterviewAutoApprovalLocked(skillState)) {
|
|
255
|
+
releaseDeepInterviewInputLock(skillState, releaseReason, nowIso);
|
|
256
|
+
}
|
|
257
|
+
await persistSkillActiveState(stateDir, invocationSessionId, skillState);
|
|
258
|
+
|
|
259
|
+
if (skillState.skill === 'deep-interview' || previousSkillState?.skill === 'deep-interview') {
|
|
260
|
+
await persistDeepInterviewModeState(stateDir, skillState, nowIso, previousSkillState, {
|
|
261
|
+
sessionId: invocationSessionId,
|
|
262
|
+
threadId: safeString(payload?.['thread-id'] || payload?.thread_id || ''),
|
|
263
|
+
turnId: safeString(payload?.['turn-id'] || payload?.turn_id || ''),
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return { invocationSessionId, skillState, releaseReason };
|
|
268
|
+
}
|
|
269
|
+
|
|
191
270
|
|
|
192
271
|
export async function isDeepInterviewStateActive(stateDir, sessionId) {
|
|
193
272
|
const modeState = await readScopedJsonIfExists(stateDir, 'deep-interview-state.json', sessionId, null);
|
|
@@ -479,8 +558,10 @@ export async function resolveNudgePaneTarget(stateDir: any, cwd = '', payload: a
|
|
|
479
558
|
if (!anchoredPane) continue;
|
|
480
559
|
const managedPane = await resolveManagedPaneFromAnchor(anchoredPane, cwd, payload, { allowTeamWorker });
|
|
481
560
|
if (managedPane) return managedPane;
|
|
482
|
-
|
|
483
|
-
|
|
561
|
+
if (allowTeamWorker) {
|
|
562
|
+
const verdict = await verifyManagedPaneTarget(anchoredPane, cwd, payload, { allowTeamWorker });
|
|
563
|
+
if (verdict.ok) return anchoredPane;
|
|
564
|
+
}
|
|
484
565
|
} catch {
|
|
485
566
|
// skip malformed state
|
|
486
567
|
}
|
|
@@ -516,21 +597,9 @@ export async function maybeAutoNudge({ cwd, stateDir, logsDir, payload }) {
|
|
|
516
597
|
}
|
|
517
598
|
|
|
518
599
|
const lastMessage = safeString(payload['last-assistant-message'] || payload.last_assistant_message || '');
|
|
519
|
-
const
|
|
520
|
-
const invocationSessionId = resolveInvocationSessionId(payload);
|
|
521
|
-
let skillState = await loadSkillActiveState(stateDir, invocationSessionId);
|
|
522
|
-
let releaseReason = null;
|
|
600
|
+
const { invocationSessionId, skillState, releaseReason } = await syncSkillStateFromTurn(stateDir, payload);
|
|
523
601
|
|
|
524
602
|
try {
|
|
525
|
-
if (skillState) {
|
|
526
|
-
const inferredPhase = inferSkillPhaseFromText(lastMessage, skillState.phase);
|
|
527
|
-
skillState.phase = inferredPhase;
|
|
528
|
-
skillState.active = inferredPhase !== 'completing';
|
|
529
|
-
skillState.updated_at = new Date().toISOString();
|
|
530
|
-
releaseReason = inferDeepInterviewReleaseReason({ skillState, latestUserInput, lastMessage });
|
|
531
|
-
await persistSkillActiveState(stateDir, invocationSessionId, skillState);
|
|
532
|
-
}
|
|
533
|
-
|
|
534
603
|
const nudgeStatePath = await getScopedStatePath(stateDir, 'auto-nudge-state.json', invocationSessionId);
|
|
535
604
|
let nudgeState = await readScopedJsonIfExists(stateDir, 'auto-nudge-state.json', invocationSessionId, null);
|
|
536
605
|
if (!nudgeState || typeof nudgeState !== 'object') {
|
|
@@ -618,8 +687,10 @@ export async function maybeAutoNudge({ cwd, stateDir, logsDir, payload }) {
|
|
|
618
687
|
return;
|
|
619
688
|
}
|
|
620
689
|
|
|
621
|
-
const
|
|
622
|
-
|
|
690
|
+
const blockedAutoApproval = isDeepInterviewAutoApprovalLocked(skillState)
|
|
691
|
+
&& !releaseReason
|
|
692
|
+
&& isBlockedAutoApprovalInput(effectiveResponse, skillState.input_lock?.blocked_inputs);
|
|
693
|
+
if (blockedAutoApproval) {
|
|
623
694
|
const blockedMessage = skillState.input_lock?.message || DEEP_INTERVIEW_INPUT_LOCK_MESSAGE;
|
|
624
695
|
await logTmuxHookEvent(logsDir, {
|
|
625
696
|
timestamp: new Date().toISOString(),
|
|
@@ -628,9 +699,7 @@ export async function maybeAutoNudge({ cwd, stateDir, logsDir, payload }) {
|
|
|
628
699
|
response: effectiveResponse,
|
|
629
700
|
source,
|
|
630
701
|
blocked_by: 'deep-interview-lock',
|
|
631
|
-
block_kind:
|
|
632
|
-
? 'blocked-auto-approval'
|
|
633
|
-
: 'input-lock-active',
|
|
702
|
+
block_kind: 'blocked-auto-approval',
|
|
634
703
|
message: blockedMessage,
|
|
635
704
|
suppressed: true,
|
|
636
705
|
}).catch(() => {});
|
|
@@ -248,7 +248,7 @@ export async function verifyManagedPaneTarget(paneId: string, cwd: string, paylo
|
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
|
|
251
|
-
async function readManagedPaneCommandState(paneTarget: string): Promise<{ currentCommand: string; startCommand: string }> {
|
|
251
|
+
async function readManagedPaneCommandState(paneTarget: string): Promise<{ currentCommand: string; startCommand: string; lookupFailed: boolean }> {
|
|
252
252
|
try {
|
|
253
253
|
const [currentResult, startResult] = await Promise.all([
|
|
254
254
|
runProcess('tmux', ['display-message', '-p', '-t', paneTarget, '#{pane_current_command}'], 2000),
|
|
@@ -257,9 +257,10 @@ async function readManagedPaneCommandState(paneTarget: string): Promise<{ curren
|
|
|
257
257
|
return {
|
|
258
258
|
currentCommand: safeString(currentResult.stdout).trim().toLowerCase(),
|
|
259
259
|
startCommand: safeString(startResult.stdout).trim().toLowerCase(),
|
|
260
|
+
lookupFailed: false,
|
|
260
261
|
};
|
|
261
262
|
} catch {
|
|
262
|
-
return { currentCommand: '', startCommand: '' };
|
|
263
|
+
return { currentCommand: '', startCommand: '', lookupFailed: true };
|
|
263
264
|
}
|
|
264
265
|
}
|
|
265
266
|
|
|
@@ -268,6 +269,59 @@ function paneLooksLikeManagedAgent({ currentCommand, startCommand }: { currentCo
|
|
|
268
269
|
if (startCommand.includes('codex')) return true;
|
|
269
270
|
return currentCommand === 'codex' || currentCommand === 'node' || currentCommand === 'npx';
|
|
270
271
|
}
|
|
272
|
+
|
|
273
|
+
function paneLooksLikeRetainableManagedAnchor({ currentCommand, startCommand }: { currentCommand: string; startCommand: string }): boolean {
|
|
274
|
+
if (/\bomx\b.*\bhud\b.*--watch/i.test(startCommand)) return false;
|
|
275
|
+
if (currentCommand === 'codex') return true;
|
|
276
|
+
if ((currentCommand === 'node' || currentCommand === 'npx') && startCommand.includes('codex')) return true;
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function paneLooksLikeDetachedManagedWrapperFallback({ currentCommand, startCommand }: { currentCommand: string; startCommand: string }): boolean {
|
|
281
|
+
if (/\bomx\b.*\bhud\b.*--watch/i.test(startCommand)) return false;
|
|
282
|
+
return currentCommand === 'node' || currentCommand === 'npx';
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
interface ManagedSessionPaneRow {
|
|
286
|
+
paneId: string;
|
|
287
|
+
active: boolean;
|
|
288
|
+
currentCommand: string;
|
|
289
|
+
startCommand: string;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function parseManagedSessionPaneRows(stdout: string): ManagedSessionPaneRow[] {
|
|
293
|
+
return safeString(stdout)
|
|
294
|
+
.trim()
|
|
295
|
+
.split('\n')
|
|
296
|
+
.filter(Boolean)
|
|
297
|
+
.map((line) => {
|
|
298
|
+
const [paneId = '', activeRaw = '0', rawCurrentCommand = '', rawStartCommand = ''] = line.split('\t');
|
|
299
|
+
return {
|
|
300
|
+
paneId: safeString(paneId).trim(),
|
|
301
|
+
active: safeString(activeRaw).trim() === '1',
|
|
302
|
+
currentCommand: safeString(rawCurrentCommand).trim().toLowerCase(),
|
|
303
|
+
startCommand: safeString(rawStartCommand).trim().toLowerCase(),
|
|
304
|
+
};
|
|
305
|
+
})
|
|
306
|
+
.filter((row) => row.paneId !== '');
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function selectManagedSessionPane(
|
|
310
|
+
rows: ManagedSessionPaneRow[],
|
|
311
|
+
{ allowWrapperFallback = false }: { allowWrapperFallback?: boolean } = {},
|
|
312
|
+
): string {
|
|
313
|
+
const nonHudRows = rows.filter((row) => !/\bomx\b.*\bhud\b.*--watch/i.test(row.startCommand));
|
|
314
|
+
const canonicalRows = nonHudRows.filter((row) => paneLooksLikeRetainableManagedAnchor(row));
|
|
315
|
+
const activeCanonical = canonicalRows.find((row) => row.active);
|
|
316
|
+
if (activeCanonical) return activeCanonical.paneId;
|
|
317
|
+
if (canonicalRows[0]?.paneId) return canonicalRows[0].paneId;
|
|
318
|
+
if (!allowWrapperFallback) return '';
|
|
319
|
+
|
|
320
|
+
const wrapperFallbackRows = nonHudRows.filter((row) => paneLooksLikeDetachedManagedWrapperFallback(row));
|
|
321
|
+
const activeWrapperFallback = wrapperFallbackRows.find((row) => row.active);
|
|
322
|
+
if (activeWrapperFallback) return activeWrapperFallback.paneId;
|
|
323
|
+
return wrapperFallbackRows[0]?.paneId || '';
|
|
324
|
+
}
|
|
271
325
|
export async function resolveManagedCurrentPane(cwd: string, payload: any, { allowTeamWorker = false } = {}): Promise<string> {
|
|
272
326
|
const paneTarget = safeString(process.env.TMUX_PANE || '').trim();
|
|
273
327
|
if (!paneTarget) return '';
|
|
@@ -286,22 +340,10 @@ export async function resolveManagedSessionPane(cwd: string, payload: any): Prom
|
|
|
286
340
|
try {
|
|
287
341
|
const panesResult = await runProcess(
|
|
288
342
|
'tmux',
|
|
289
|
-
['list-panes', '-s', '-t', expectedSession, '-F', '#{pane_id}\t#{pane_current_command}\t#{pane_start_command}'],
|
|
343
|
+
['list-panes', '-s', '-t', expectedSession, '-F', '#{pane_id}\t#{pane_active}\t#{pane_current_command}\t#{pane_start_command}'],
|
|
290
344
|
2000,
|
|
291
345
|
);
|
|
292
|
-
|
|
293
|
-
.trim()
|
|
294
|
-
.split('\n')
|
|
295
|
-
.filter(Boolean);
|
|
296
|
-
for (const line of panes) {
|
|
297
|
-
const [candidatePaneId, rawCurrentCommand = '', rawStartCommand = ''] = line.split('\t');
|
|
298
|
-
const startCommand = safeString(rawStartCommand).toLowerCase();
|
|
299
|
-
const currentCommand = safeString(rawCurrentCommand).trim().toLowerCase();
|
|
300
|
-
if (!candidatePaneId) continue;
|
|
301
|
-
if (/\bomx\b.*\bhud\b.*--watch/i.test(startCommand)) continue;
|
|
302
|
-
if (startCommand.includes('codex')) return candidatePaneId;
|
|
303
|
-
if (currentCommand === 'codex') return candidatePaneId;
|
|
304
|
-
}
|
|
346
|
+
return selectManagedSessionPane(parseManagedSessionPaneRows(panesResult.stdout));
|
|
305
347
|
} catch {
|
|
306
348
|
// best effort only
|
|
307
349
|
}
|
|
@@ -315,29 +357,26 @@ export async function resolveManagedPaneFromAnchor(anchorPane: string, cwd: stri
|
|
|
315
357
|
const verdict = await verifyManagedPaneTarget(paneTarget, cwd, payload, { allowTeamWorker });
|
|
316
358
|
if (!verdict.ok) return '';
|
|
317
359
|
|
|
360
|
+
const commandState = await readManagedPaneCommandState(paneTarget);
|
|
361
|
+
if (commandState.lookupFailed) return paneTarget;
|
|
362
|
+
if (paneLooksLikeRetainableManagedAnchor(commandState)) return paneTarget;
|
|
363
|
+
|
|
318
364
|
try {
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
if (!sessionName) return paneTarget;
|
|
365
|
+
const sessionName = safeString(verdict.paneSessionName || verdict.managedContext?.expectedTmuxSessionName).trim();
|
|
366
|
+
if (!sessionName) return '';
|
|
322
367
|
|
|
323
368
|
const panesResult = await runProcess(
|
|
324
369
|
'tmux',
|
|
325
|
-
['list-panes', '-s', '-t', sessionName, '-F', '#{pane_id}\t#{pane_current_command}\t#{pane_start_command}'],
|
|
370
|
+
['list-panes', '-s', '-t', sessionName, '-F', '#{pane_id}\t#{pane_active}\t#{pane_current_command}\t#{pane_start_command}'],
|
|
326
371
|
2000,
|
|
327
372
|
);
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
const currentCommand = safeString(rawCurrentCommand).trim().toLowerCase();
|
|
333
|
-
if (!candidatePaneId) continue;
|
|
334
|
-
if (/\bomx\b.*\bhud\b.*--watch/i.test(startCommand)) continue;
|
|
335
|
-
if (startCommand.includes('codex')) return candidatePaneId;
|
|
336
|
-
if (currentCommand === 'codex') return candidatePaneId;
|
|
337
|
-
}
|
|
373
|
+
const selectedPane = selectManagedSessionPane(parseManagedSessionPaneRows(panesResult.stdout), {
|
|
374
|
+
allowWrapperFallback: paneLooksLikeDetachedManagedWrapperFallback(commandState),
|
|
375
|
+
});
|
|
376
|
+
if (selectedPane) return selectedPane;
|
|
338
377
|
} catch {
|
|
339
378
|
// best effort only
|
|
340
379
|
}
|
|
341
380
|
|
|
342
|
-
return
|
|
381
|
+
return '';
|
|
343
382
|
}
|
|
@@ -7,7 +7,7 @@ import { resolveCodexPane } from '../tmux-hook-engine.js';
|
|
|
7
7
|
import { safeString } from './utils.js';
|
|
8
8
|
|
|
9
9
|
const SESSION_ID_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
|
|
10
|
-
const RALPH_TERMINAL_PHASES = new Set(['complete', 'failed', 'cancelled']);
|
|
10
|
+
const RALPH_TERMINAL_PHASES = new Set(['blocked_on_user', 'complete', 'failed', 'cancelled']);
|
|
11
11
|
const RALPH_RESUME_LOCK_STALE_MS = 10_000;
|
|
12
12
|
const RALPH_RESUME_LOCK_TIMEOUT_MS = 5_000;
|
|
13
13
|
const RALPH_RESUME_LOCK_RETRY_MS = 25;
|
|
@@ -40,7 +40,13 @@ import {
|
|
|
40
40
|
import { isLeaderStale, resolveLeaderStalenessThresholdMs, maybeNudgeTeamLeader } from './notify-hook/team-leader-nudge.js';
|
|
41
41
|
import { drainPendingTeamDispatch } from './notify-hook/team-dispatch.js';
|
|
42
42
|
import { handleTmuxInjection } from './notify-hook/tmux-injection.js';
|
|
43
|
-
import {
|
|
43
|
+
import {
|
|
44
|
+
maybeAutoNudge,
|
|
45
|
+
resolveNudgePaneTarget,
|
|
46
|
+
isDeepInterviewStateActive,
|
|
47
|
+
isDeepInterviewInputLockActive,
|
|
48
|
+
syncSkillStateFromTurn,
|
|
49
|
+
} from './notify-hook/auto-nudge.js';
|
|
44
50
|
import { isManagedOmxSession } from './notify-hook/managed-tmux.js';
|
|
45
51
|
import { logNotifyHookEvent } from './notify-hook/log.js';
|
|
46
52
|
import { reconcileRalphSessionResume } from './notify-hook/ralph-session-resume.js';
|
|
@@ -238,14 +244,19 @@ async function main() {
|
|
|
238
244
|
}
|
|
239
245
|
|
|
240
246
|
// 1. Log the turn
|
|
247
|
+
const normalizedInputMessages = normalizeInputMessages(payload);
|
|
248
|
+
const latestInputPreview = safeString(
|
|
249
|
+
normalizedInputMessages.length > 0
|
|
250
|
+
? normalizedInputMessages[normalizedInputMessages.length - 1]
|
|
251
|
+
: '',
|
|
252
|
+
).slice(0, 200);
|
|
241
253
|
const logEntry = {
|
|
242
254
|
timestamp: new Date().toISOString(),
|
|
243
255
|
type: payload.type || 'agent-turn-complete',
|
|
244
256
|
thread_id: payload['thread-id'] || payload.thread_id,
|
|
245
257
|
turn_id: payload['turn-id'] || payload.turn_id,
|
|
246
|
-
input_preview:
|
|
247
|
-
|
|
248
|
-
.join('; '),
|
|
258
|
+
input_preview: latestInputPreview,
|
|
259
|
+
input_message_count: normalizedInputMessages.length,
|
|
249
260
|
output_preview: (payload['last-assistant-message'] || payload.last_assistant_message || '')
|
|
250
261
|
.slice(0, 200),
|
|
251
262
|
};
|
|
@@ -473,7 +484,14 @@ async function main() {
|
|
|
473
484
|
// Non-fatal: keyword detector module may not be built yet
|
|
474
485
|
}
|
|
475
486
|
|
|
487
|
+
try {
|
|
488
|
+
await syncSkillStateFromTurn(stateDir, payload);
|
|
489
|
+
} catch {
|
|
490
|
+
// Non-fatal: lifecycle sync should not block the hook
|
|
491
|
+
}
|
|
492
|
+
|
|
476
493
|
const deepInterviewStateActive = await isDeepInterviewStateActive(stateDir, getEffectiveSessionId());
|
|
494
|
+
const deepInterviewInputLockActive = await isDeepInterviewInputLockActive(stateDir, getEffectiveSessionId());
|
|
477
495
|
|
|
478
496
|
// 4.55. Notify leader when individual worker transitions to idle (worker session only)
|
|
479
497
|
if (isTeamWorker && parsedTeamWorker && !deepInterviewStateActive) {
|
|
@@ -642,7 +660,7 @@ async function main() {
|
|
|
642
660
|
|
|
643
661
|
// 9. Auto-nudge: detect Codex stall patterns and automatically send a continuation prompt.
|
|
644
662
|
// Works for both leader and worker contexts.
|
|
645
|
-
if (!deepInterviewStateActive) {
|
|
663
|
+
if (!deepInterviewStateActive || deepInterviewInputLockActive) {
|
|
646
664
|
try {
|
|
647
665
|
await maybeAutoNudge({ cwd, stateDir, logsDir, payload });
|
|
648
666
|
} catch {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
4
|
+
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = dirname(__filename);
|
|
7
|
+
const distScriptPath = join(__dirname, "..", "..", "dist", "scripts", "postinstall.js");
|
|
8
|
+
|
|
9
|
+
if (!existsSync(distScriptPath)) {
|
|
10
|
+
process.exit(0);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const moduleUrl = pathToFileURL(distScriptPath).href;
|
|
14
|
+
try {
|
|
15
|
+
const postinstallModule = await import(moduleUrl);
|
|
16
|
+
if (typeof postinstallModule.main === "function") {
|
|
17
|
+
await postinstallModule.main();
|
|
18
|
+
}
|
|
19
|
+
} catch (error) {
|
|
20
|
+
console.warn(
|
|
21
|
+
`[omx] Postinstall bootstrap skipped after a non-fatal error: ${error instanceof Error ? error.message : String(error)}`,
|
|
22
|
+
);
|
|
23
|
+
}
|