oh-my-codex 0.11.13 → 0.12.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 +34 -17
- package/crates/omx-runtime/src/main.rs +6 -2
- package/dist/agents/native-config.js +1 -1
- package/dist/agents/native-config.js.map +1 -1
- package/dist/cli/__tests__/autoresearch-guided.test.js +74 -2
- package/dist/cli/__tests__/autoresearch-guided.test.js.map +1 -1
- package/dist/cli/__tests__/cleanup.test.js +37 -30
- package/dist/cli/__tests__/cleanup.test.js.map +1 -1
- package/dist/cli/__tests__/error-handling-warnings.test.js +3 -1
- package/dist/cli/__tests__/error-handling-warnings.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +276 -5
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/launch-fallback.test.js +95 -1
- package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
- package/dist/cli/__tests__/setup-refresh.test.js +49 -9
- package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
- package/dist/cli/__tests__/setup-scope.test.js +9 -0
- package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
- package/dist/cli/__tests__/team.test.js +136 -11
- package/dist/cli/__tests__/team.test.js.map +1 -1
- package/dist/cli/__tests__/uninstall.test.js +10 -0
- package/dist/cli/__tests__/uninstall.test.js.map +1 -1
- package/dist/cli/__tests__/windows-popup-loop-contract.test.js +1 -0
- package/dist/cli/__tests__/windows-popup-loop-contract.test.js.map +1 -1
- package/dist/cli/autoresearch-guided.d.ts.map +1 -1
- package/dist/cli/autoresearch-guided.js +2 -1
- package/dist/cli/autoresearch-guided.js.map +1 -1
- package/dist/cli/autoresearch.d.ts.map +1 -1
- package/dist/cli/autoresearch.js +2 -1
- package/dist/cli/autoresearch.js.map +1 -1
- package/dist/cli/cleanup.d.ts.map +1 -1
- package/dist/cli/cleanup.js +10 -5
- package/dist/cli/cleanup.js.map +1 -1
- package/dist/cli/index.d.ts +21 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +298 -36
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/omx.js +2 -0
- package/dist/cli/omx.js.map +1 -1
- package/dist/cli/setup.d.ts +1 -0
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +41 -7
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/team.d.ts.map +1 -1
- package/dist/cli/team.js +16 -557
- package/dist/cli/team.js.map +1 -1
- package/dist/cli/uninstall.d.ts.map +1 -1
- package/dist/cli/uninstall.js +34 -9
- package/dist/cli/uninstall.js.map +1 -1
- package/dist/config/__tests__/generator-idempotent.test.js +79 -2
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
- package/dist/config/__tests__/generator-notify.test.js +2 -0
- package/dist/config/__tests__/generator-notify.test.js.map +1 -1
- package/dist/config/codex-hooks.d.ts +11 -0
- package/dist/config/codex-hooks.d.ts.map +1 -0
- package/dist/config/codex-hooks.js +50 -0
- package/dist/config/codex-hooks.js.map +1 -0
- package/dist/config/generator.d.ts +5 -3
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +24 -14
- package/dist/config/generator.js.map +1 -1
- package/dist/hooks/__tests__/debugger-log-recency-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/debugger-log-recency-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/debugger-log-recency-contract.test.js +20 -0
- package/dist/hooks/__tests__/debugger-log-recency-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/keyword-detector.test.js +132 -0
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js +292 -4
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +86 -0
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +40 -0
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.d.ts +2 -0
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js +54 -0
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-modules.test.js +31 -0
- package/dist/hooks/__tests__/notify-hook-modules.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js +51 -0
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.d.ts +2 -0
- package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js +136 -0
- package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +120 -0
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +145 -20
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +116 -0
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +86 -0
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
- package/dist/hooks/__tests__/pre-context-gate-skills.test.js +1 -0
- package/dist/hooks/__tests__/pre-context-gate-skills.test.js.map +1 -1
- package/dist/hooks/extensibility/__tests__/runtime.test.js +49 -0
- package/dist/hooks/extensibility/__tests__/runtime.test.js.map +1 -1
- package/dist/hooks/extensibility/runtime.d.ts.map +1 -1
- package/dist/hooks/extensibility/runtime.js +10 -0
- package/dist/hooks/extensibility/runtime.js.map +1 -1
- package/dist/hooks/extensibility/types.d.ts +1 -1
- package/dist/hooks/extensibility/types.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.d.ts +2 -0
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +76 -4
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
- package/dist/hooks/prompt-guidance-contract.js +12 -8
- package/dist/hooks/prompt-guidance-contract.js.map +1 -1
- package/dist/hooks/session.d.ts +5 -1
- package/dist/hooks/session.d.ts.map +1 -1
- package/dist/hooks/session.js +10 -6
- package/dist/hooks/session.js.map +1 -1
- package/dist/hud/index.d.ts.map +1 -1
- package/dist/hud/index.js +6 -1
- package/dist/hud/index.js.map +1 -1
- package/dist/mcp/__tests__/bootstrap.test.js +0 -3
- package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
- package/dist/mcp/__tests__/code-intel-server.test.js +27 -1
- package/dist/mcp/__tests__/code-intel-server.test.js.map +1 -1
- package/dist/mcp/__tests__/server-lifecycle.test.js +0 -5
- package/dist/mcp/__tests__/server-lifecycle.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 +0 -1
- package/dist/mcp/bootstrap.js.map +1 -1
- package/dist/mcp/code-intel-server.d.ts +20 -0
- package/dist/mcp/code-intel-server.d.ts.map +1 -1
- package/dist/mcp/code-intel-server.js +6 -5
- package/dist/mcp/code-intel-server.js.map +1 -1
- package/dist/notifications/__tests__/idle-cooldown.test.js +24 -1
- package/dist/notifications/__tests__/idle-cooldown.test.js.map +1 -1
- package/dist/notifications/__tests__/reply-listener.test.js +20 -1
- package/dist/notifications/__tests__/reply-listener.test.js.map +1 -1
- package/dist/notifications/__tests__/tmux.test.js +41 -0
- package/dist/notifications/__tests__/tmux.test.js.map +1 -1
- package/dist/notifications/idle-cooldown.d.ts +13 -0
- package/dist/notifications/idle-cooldown.d.ts.map +1 -1
- package/dist/notifications/idle-cooldown.js +50 -16
- package/dist/notifications/idle-cooldown.js.map +1 -1
- package/dist/notifications/reply-listener.d.ts.map +1 -1
- package/dist/notifications/reply-listener.js +2 -0
- package/dist/notifications/reply-listener.js.map +1 -1
- package/dist/notifications/tmux.d.ts.map +1 -1
- package/dist/notifications/tmux.js +4 -0
- package/dist/notifications/tmux.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.d.ts +2 -0
- package/dist/scripts/__tests__/codex-native-hook.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/codex-native-hook.test.js +1050 -0
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -0
- package/dist/scripts/codex-native-hook.d.ts +22 -0
- package/dist/scripts/codex-native-hook.d.ts.map +1 -0
- package/dist/scripts/codex-native-hook.js +792 -0
- package/dist/scripts/codex-native-hook.js.map +1 -0
- package/dist/scripts/codex-native-pre-post.d.ts +26 -0
- package/dist/scripts/codex-native-pre-post.d.ts.map +1 -0
- package/dist/scripts/codex-native-pre-post.js +118 -0
- package/dist/scripts/codex-native-pre-post.js.map +1 -0
- package/dist/scripts/notify-fallback-watcher.js +322 -21
- package/dist/scripts/notify-fallback-watcher.js.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.js +5 -6
- package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/log.d.ts +2 -2
- package/dist/scripts/notify-hook/log.d.ts.map +1 -1
- package/dist/scripts/notify-hook/log.js +10 -2
- package/dist/scripts/notify-hook/log.js.map +1 -1
- package/dist/scripts/notify-hook/managed-tmux.d.ts.map +1 -1
- package/dist/scripts/notify-hook/managed-tmux.js +2 -0
- package/dist/scripts/notify-hook/managed-tmux.js.map +1 -1
- package/dist/scripts/notify-hook/orchestration-intent.d.ts +18 -0
- package/dist/scripts/notify-hook/orchestration-intent.d.ts.map +1 -0
- package/dist/scripts/notify-hook/orchestration-intent.js +72 -0
- package/dist/scripts/notify-hook/orchestration-intent.js.map +1 -0
- package/dist/scripts/notify-hook/process-runner.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 +7 -0
- package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -1
- package/dist/scripts/notify-hook/team-dispatch.d.ts +15 -6
- package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-dispatch.js +125 -6
- package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.d.ts +3 -2
- package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.js +165 -37
- package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.d.ts +4 -1
- package/dist/scripts/notify-hook/team-tmux-guard.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.js +33 -44
- package/dist/scripts/notify-hook/team-tmux-guard.js.map +1 -1
- package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-worker.js +68 -5
- package/dist/scripts/notify-hook/team-worker.js.map +1 -1
- package/dist/scripts/notify-hook/utils.d.ts +1 -1
- package/dist/scripts/notify-hook/utils.d.ts.map +1 -1
- package/dist/scripts/notify-hook/utils.js.map +1 -1
- package/dist/scripts/notify-hook.js +55 -32
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/team/__tests__/api-interop.test.js +344 -18
- package/dist/team/__tests__/api-interop.test.js.map +1 -1
- package/dist/team/__tests__/delivery-e2e-smoke.test.d.ts +2 -0
- package/dist/team/__tests__/delivery-e2e-smoke.test.d.ts.map +1 -0
- package/dist/team/__tests__/delivery-e2e-smoke.test.js +671 -0
- package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +1 -0
- package/dist/team/__tests__/mcp-comm.test.js +5 -0
- package/dist/team/__tests__/mcp-comm.test.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +543 -15
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/state.test.js +133 -8
- package/dist/team/__tests__/state.test.js.map +1 -1
- package/dist/team/__tests__/team-ops-contract.test.js +4 -0
- package/dist/team/__tests__/team-ops-contract.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +160 -0
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/__tests__/worker-bootstrap.test.js +19 -1
- package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
- package/dist/team/api-interop.d.ts.map +1 -1
- package/dist/team/api-interop.js +95 -23
- package/dist/team/api-interop.js.map +1 -1
- package/dist/team/contracts.d.ts +11 -1
- package/dist/team/contracts.d.ts.map +1 -1
- package/dist/team/contracts.js +29 -0
- package/dist/team/contracts.js.map +1 -1
- package/dist/team/delivery-log.d.ts +14 -0
- package/dist/team/delivery-log.d.ts.map +1 -0
- package/dist/team/delivery-log.js +35 -0
- package/dist/team/delivery-log.js.map +1 -0
- package/dist/team/idle-nudge.d.ts +2 -2
- package/dist/team/idle-nudge.js +2 -2
- package/dist/team/mcp-comm.d.ts +4 -0
- package/dist/team/mcp-comm.d.ts.map +1 -1
- package/dist/team/mcp-comm.js +84 -1
- package/dist/team/mcp-comm.js.map +1 -1
- package/dist/team/pane-status.d.ts +149 -0
- package/dist/team/pane-status.d.ts.map +1 -0
- package/dist/team/pane-status.js +558 -0
- package/dist/team/pane-status.js.map +1 -0
- package/dist/team/reminder-intents.d.ts +11 -0
- package/dist/team/reminder-intents.d.ts.map +1 -0
- package/dist/team/reminder-intents.js +40 -0
- package/dist/team/reminder-intents.js.map +1 -0
- package/dist/team/runtime-cli.d.ts +1 -1
- package/dist/team/runtime-cli.js +2 -2
- package/dist/team/runtime-cli.js.map +1 -1
- package/dist/team/runtime.d.ts +2 -1
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +409 -191
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +6 -5
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/state/dispatch.d.ts +4 -1
- package/dist/team/state/dispatch.d.ts.map +1 -1
- package/dist/team/state/dispatch.js +59 -18
- package/dist/team/state/dispatch.js.map +1 -1
- package/dist/team/state/mailbox.d.ts.map +1 -1
- package/dist/team/state/mailbox.js +45 -2
- package/dist/team/state/mailbox.js.map +1 -1
- package/dist/team/state/monitor.d.ts +2 -1
- package/dist/team/state/monitor.d.ts.map +1 -1
- package/dist/team/state/monitor.js +30 -1
- package/dist/team/state/monitor.js.map +1 -1
- package/dist/team/state/types.d.ts +5 -2
- 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 +30 -3
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +170 -2
- package/dist/team/state.js.map +1 -1
- package/dist/team/team-ops.d.ts +5 -1
- package/dist/team/team-ops.d.ts.map +1 -1
- package/dist/team/team-ops.js +4 -0
- package/dist/team/team-ops.js.map +1 -1
- package/dist/team/tmux-session.d.ts +2 -0
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +19 -3
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/worker-bootstrap.d.ts +4 -0
- package/dist/team/worker-bootstrap.d.ts.map +1 -1
- package/dist/team/worker-bootstrap.js +33 -6
- package/dist/team/worker-bootstrap.js.map +1 -1
- package/dist/utils/__tests__/paths.test.js +63 -1
- package/dist/utils/__tests__/paths.test.js.map +1 -1
- package/dist/utils/__tests__/platform-command.test.js +50 -4
- package/dist/utils/__tests__/platform-command.test.js.map +1 -1
- package/dist/utils/paths.d.ts +12 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +44 -2
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/platform-command.d.ts.map +1 -1
- package/dist/utils/platform-command.js +13 -5
- package/dist/utils/platform-command.js.map +1 -1
- package/dist/utils/sleep.d.ts.map +1 -1
- package/dist/utils/sleep.js +10 -1
- package/dist/utils/sleep.js.map +1 -1
- package/package.json +1 -1
- package/prompts/analyst.md +2 -2
- package/prompts/api-reviewer.md +2 -2
- package/prompts/architect.md +2 -2
- package/prompts/build-fixer.md +2 -2
- package/prompts/code-reviewer.md +2 -2
- package/prompts/code-simplifier.md +1 -1
- package/prompts/critic.md +2 -2
- package/prompts/debugger.md +3 -2
- package/prompts/dependency-expert.md +2 -2
- package/prompts/designer.md +2 -2
- package/prompts/executor.md +3 -2
- package/prompts/explore.md +2 -2
- package/prompts/git-master.md +2 -2
- package/prompts/information-architect.md +15 -102
- package/prompts/performance-reviewer.md +2 -2
- package/prompts/planner.md +3 -2
- package/prompts/product-analyst.md +2 -2
- package/prompts/product-manager.md +2 -2
- package/prompts/qa-tester.md +2 -2
- package/prompts/quality-reviewer.md +2 -2
- package/prompts/quality-strategist.md +2 -2
- package/prompts/researcher.md +2 -2
- package/prompts/security-reviewer.md +2 -2
- package/prompts/sisyphus-lite.md +2 -2
- package/prompts/style-reviewer.md +2 -2
- package/prompts/team-executor.md +2 -2
- package/prompts/test-engineer.md +2 -2
- package/prompts/ux-researcher.md +2 -2
- package/prompts/verifier.md +3 -2
- package/prompts/vision.md +2 -2
- package/prompts/writer.md +2 -2
- package/skills/team/SKILL.md +18 -33
- package/src/scripts/__tests__/codex-native-hook.test.ts +1346 -0
- package/src/scripts/codex-native-hook.ts +983 -0
- package/src/scripts/codex-native-pre-post.ts +161 -0
- package/src/scripts/notify-fallback-watcher.ts +378 -29
- package/src/scripts/notify-hook/auto-nudge.ts +5 -10
- package/src/scripts/notify-hook/log.ts +18 -4
- package/src/scripts/notify-hook/managed-tmux.ts +1 -0
- package/src/scripts/notify-hook/orchestration-intent.ts +82 -0
- package/src/scripts/notify-hook/process-runner.ts +4 -4
- package/src/scripts/notify-hook/ralph-session-resume.ts +9 -0
- package/src/scripts/notify-hook/team-dispatch.ts +134 -6
- package/src/scripts/notify-hook/team-leader-nudge.ts +183 -37
- package/src/scripts/notify-hook/team-tmux-guard.ts +35 -43
- package/src/scripts/notify-hook/team-worker.ts +73 -4
- package/src/scripts/notify-hook/utils.ts +1 -1
- package/src/scripts/notify-hook.ts +64 -32
- package/templates/AGENTS.md +21 -11
- package/README.de.md +0 -263
- package/README.el.md +0 -223
- package/README.es.md +0 -263
- package/README.fr.md +0 -263
- package/README.it.md +0 -263
- package/README.ja.md +0 -264
- package/README.ko.md +0 -264
- package/README.pl.md +0 -216
- package/README.pt.md +0 -263
- package/README.ru.md +0 -263
- package/README.tr.md +0 -263
- package/README.vi.md +0 -223
- package/README.zh-TW.md +0 -293
- package/README.zh.md +0 -264
- package/dist/mcp/__tests__/team-server-cleanup.test.d.ts +0 -2
- package/dist/mcp/__tests__/team-server-cleanup.test.d.ts.map +0 -1
- package/dist/mcp/__tests__/team-server-cleanup.test.js +0 -219
- package/dist/mcp/__tests__/team-server-cleanup.test.js.map +0 -1
- package/dist/mcp/__tests__/team-server-runtime-deps.test.d.ts +0 -2
- package/dist/mcp/__tests__/team-server-runtime-deps.test.d.ts.map +0 -1
- package/dist/mcp/__tests__/team-server-runtime-deps.test.js +0 -13
- package/dist/mcp/__tests__/team-server-runtime-deps.test.js.map +0 -1
- package/dist/mcp/__tests__/team-server-wait.test.d.ts +0 -2
- package/dist/mcp/__tests__/team-server-wait.test.d.ts.map +0 -1
- package/dist/mcp/__tests__/team-server-wait.test.js +0 -155
- package/dist/mcp/__tests__/team-server-wait.test.js.map +0 -1
- package/dist/mcp/team-server.d.ts +0 -24
- package/dist/mcp/team-server.d.ts.map +0 -1
- package/dist/mcp/team-server.js +0 -482
- package/dist/mcp/team-server.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { existsSync } from 'fs';
|
|
3
|
-
import { appendFile, mkdir, open, readFile, readdir, rename, stat, unlink, writeFile } from 'fs/promises';
|
|
3
|
+
import { appendFile, mkdir, open, readFile, readdir, rename, rm, stat, unlink, writeFile } from 'fs/promises';
|
|
4
4
|
import { spawnSync } from 'child_process';
|
|
5
5
|
import { dirname, join, resolve } from 'path';
|
|
6
6
|
import { homedir } from 'os';
|
|
@@ -12,6 +12,7 @@ import { checkWorkerPanesAlive, isLeaderStale, maybeNudgeTeamLeader, resolveLead
|
|
|
12
12
|
import { DEFAULT_MARKER } from './tmux-hook-engine.js';
|
|
13
13
|
import { isTerminalPhase } from './notify-hook/utils.js';
|
|
14
14
|
import { isSessionStale, readSessionState } from '../hooks/session.js';
|
|
15
|
+
import { DEFAULT_SUBAGENT_ACTIVE_WINDOW_MS, readSubagentSessionSummary, } from '../subagents/tracker.js';
|
|
15
16
|
function argValue(name, fallback = '') {
|
|
16
17
|
const idx = process.argv.indexOf(name);
|
|
17
18
|
if (idx < 0 || idx + 1 >= process.argv.length)
|
|
@@ -64,6 +65,7 @@ const authorityOnly = process.argv.includes('--authority-only');
|
|
|
64
65
|
// ack budget so leaderless team dispatch + stale-alert recovery do not feel
|
|
65
66
|
// laggy between native notify-hook turns.
|
|
66
67
|
const pollMs = Math.max(50, asNumber(argValue('--poll-ms', '250'), 250));
|
|
68
|
+
const idleMaxPollMs = Math.max(pollMs, asNumber(argValue('--idle-max-poll-ms', process.env.OMX_NOTIFY_FALLBACK_IDLE_MAX_POLL_MS || '1000'), 1000));
|
|
67
69
|
const parentPid = Math.trunc(asNumber(argValue('--parent-pid', String(process.ppid || 0)), process.ppid || 0));
|
|
68
70
|
const startedAt = Date.now();
|
|
69
71
|
const fileWindowMs = runOnce ? 15000 : 30000;
|
|
@@ -77,6 +79,10 @@ const stateDir = join(omxDir, 'state');
|
|
|
77
79
|
const statePath = join(stateDir, 'notify-fallback-state.json');
|
|
78
80
|
const pidFilePath = resolve(argValue('--pid-file', join(stateDir, 'notify-fallback.pid')));
|
|
79
81
|
const logPath = join(logsDir, `notify-fallback-${new Date().toISOString().split('T')[0]}.jsonl`);
|
|
82
|
+
const logRotatePath = `${logPath}.1`;
|
|
83
|
+
const logLockPath = `${logPath}.lock`;
|
|
84
|
+
const defaultMaxLogBytes = 10 * 1024 * 1024;
|
|
85
|
+
const maxLogBytes = Math.max(0, asNumber(argValue('--log-max-bytes', process.env.OMX_NOTIFY_FALLBACK_LOG_MAX_BYTES || String(defaultMaxLogBytes)), defaultMaxLogBytes));
|
|
80
86
|
const ralphSteerTimestampPath = join(stateDir, 'ralph-last-steer-at');
|
|
81
87
|
const ralphSteerLockPath = join(stateDir, 'ralph-continue-steer.lock');
|
|
82
88
|
const watcherOwnerToken = `${process.pid}-${startedAt}-${Math.random().toString(36).slice(2, 10)}`;
|
|
@@ -84,6 +90,7 @@ const RALPH_CONTINUE_TEXT = 'Ralph loop active continue';
|
|
|
84
90
|
const RALPH_CONTINUE_CADENCE_MS = 60_000;
|
|
85
91
|
const RALPH_STEER_LOCK_STALE_MS = 30_000;
|
|
86
92
|
const RALPH_TERMINAL_PHASES = new Set(['complete', 'failed', 'cancelled']);
|
|
93
|
+
const QUIET_ONCE_EVENT_TYPES = new Set(['watcher_start', 'watcher_once_complete']);
|
|
87
94
|
const fileState = new Map();
|
|
88
95
|
const seenTurnKeys = new Set();
|
|
89
96
|
let stopping = false;
|
|
@@ -119,6 +126,8 @@ let lastRalphContinueSteer = {
|
|
|
119
126
|
pane_id: '',
|
|
120
127
|
pane_current_command: '',
|
|
121
128
|
current_phase: '',
|
|
129
|
+
subagent_session_id: '',
|
|
130
|
+
active_subagent_thread_ids: [],
|
|
122
131
|
shared_timestamp_path: ralphSteerTimestampPath,
|
|
123
132
|
shared_last_sent_at: '',
|
|
124
133
|
singleton_lock_path: ralphSteerLockPath,
|
|
@@ -128,6 +137,14 @@ let lastParentGuard = {
|
|
|
128
137
|
state_path: '',
|
|
129
138
|
current_phase: '',
|
|
130
139
|
};
|
|
140
|
+
let lastAuthorityBackoff = {
|
|
141
|
+
active: false,
|
|
142
|
+
reason: '',
|
|
143
|
+
primary_pid: null,
|
|
144
|
+
primary_last_tick_at: '',
|
|
145
|
+
freshness_ms: null,
|
|
146
|
+
threshold_ms: null,
|
|
147
|
+
};
|
|
131
148
|
const AUTO_NUDGE_STALL_MS = Math.max(pollMs, asNumber(process.env.OMX_NOTIFY_FALLBACK_AUTO_NUDGE_STALL_MS || '5000', 5000));
|
|
132
149
|
let lastFallbackAutoNudge = {
|
|
133
150
|
enabled: true,
|
|
@@ -141,12 +158,106 @@ let lastFallbackAutoNudge = {
|
|
|
141
158
|
last_nudged_signature: '',
|
|
142
159
|
last_nudged_at: '',
|
|
143
160
|
};
|
|
144
|
-
|
|
145
|
-
|
|
161
|
+
let adaptivePollState = {
|
|
162
|
+
enabled: true,
|
|
163
|
+
base_ms: pollMs,
|
|
164
|
+
max_ms: idleMaxPollMs,
|
|
165
|
+
current_ms: pollMs,
|
|
166
|
+
idle_streak: 0,
|
|
167
|
+
last_tick_at: null,
|
|
168
|
+
last_activity_at: null,
|
|
169
|
+
last_activity_reason: 'init',
|
|
170
|
+
};
|
|
171
|
+
function shouldSuppressEventLog(event) {
|
|
172
|
+
const eventType = safeString(event.type).trim();
|
|
173
|
+
return runOnce && QUIET_ONCE_EVENT_TYPES.has(eventType);
|
|
174
|
+
}
|
|
175
|
+
async function acquireLogLock(timeoutMs = 1000) {
|
|
176
|
+
const deadline = Date.now() + timeoutMs;
|
|
177
|
+
while (Date.now() < deadline) {
|
|
178
|
+
try {
|
|
179
|
+
await mkdir(logLockPath, { recursive: false });
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
if (error?.code !== 'EEXIST')
|
|
184
|
+
return false;
|
|
185
|
+
const lockStat = await stat(logLockPath).catch(() => null);
|
|
186
|
+
if (lockStat && Date.now() - lockStat.mtimeMs > 5000) {
|
|
187
|
+
await rm(logLockPath, { recursive: true, force: true }).catch(() => { });
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
await sleep(10);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
async function releaseLogLock() {
|
|
196
|
+
await rm(logLockPath, { recursive: true, force: true }).catch(() => { });
|
|
197
|
+
}
|
|
198
|
+
async function rotateLogIfNeeded(nextEntryBytes) {
|
|
199
|
+
if (maxLogBytes <= 0)
|
|
200
|
+
return;
|
|
201
|
+
const currentStat = await stat(logPath).catch(() => null);
|
|
202
|
+
if (!currentStat || currentStat.size + nextEntryBytes <= maxLogBytes)
|
|
203
|
+
return;
|
|
204
|
+
await unlink(logRotatePath).catch(() => { });
|
|
205
|
+
await rename(logPath, logRotatePath).catch(() => { });
|
|
206
|
+
}
|
|
207
|
+
async function eventLog(event) {
|
|
208
|
+
if (shouldSuppressEventLog(event))
|
|
209
|
+
return;
|
|
210
|
+
const line = `${JSON.stringify({ timestamp: new Date().toISOString(), ...event })}\n`;
|
|
211
|
+
await mkdir(dirname(logPath), { recursive: true }).catch(() => { });
|
|
212
|
+
const locked = await acquireLogLock();
|
|
213
|
+
if (!locked)
|
|
214
|
+
return;
|
|
215
|
+
try {
|
|
216
|
+
await rotateLogIfNeeded(Buffer.byteLength(line));
|
|
217
|
+
await appendFile(logPath, line);
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
// best effort only
|
|
221
|
+
}
|
|
222
|
+
finally {
|
|
223
|
+
await releaseLogLock();
|
|
224
|
+
}
|
|
146
225
|
}
|
|
147
226
|
function shouldLogLeaderNudgeTick(reason) {
|
|
148
227
|
return reason === 'leader_nudge_checked' || reason === 'leader_nudge_failed';
|
|
149
228
|
}
|
|
229
|
+
function nextIdlePollMs(currentMs) {
|
|
230
|
+
return Math.min(idleMaxPollMs, Math.max(pollMs, currentMs * 2));
|
|
231
|
+
}
|
|
232
|
+
function updateAdaptivePollState(summary) {
|
|
233
|
+
const nowIso = new Date().toISOString();
|
|
234
|
+
if (summary.active) {
|
|
235
|
+
adaptivePollState = {
|
|
236
|
+
...adaptivePollState,
|
|
237
|
+
enabled: true,
|
|
238
|
+
base_ms: pollMs,
|
|
239
|
+
max_ms: idleMaxPollMs,
|
|
240
|
+
current_ms: pollMs,
|
|
241
|
+
idle_streak: 0,
|
|
242
|
+
last_tick_at: nowIso,
|
|
243
|
+
last_activity_at: nowIso,
|
|
244
|
+
last_activity_reason: summary.reason,
|
|
245
|
+
};
|
|
246
|
+
return adaptivePollState.current_ms;
|
|
247
|
+
}
|
|
248
|
+
const nextMs = nextIdlePollMs(adaptivePollState.current_ms);
|
|
249
|
+
adaptivePollState = {
|
|
250
|
+
...adaptivePollState,
|
|
251
|
+
enabled: true,
|
|
252
|
+
base_ms: pollMs,
|
|
253
|
+
max_ms: idleMaxPollMs,
|
|
254
|
+
current_ms: nextMs,
|
|
255
|
+
idle_streak: adaptivePollState.idle_streak + 1,
|
|
256
|
+
last_tick_at: nowIso,
|
|
257
|
+
last_activity_reason: summary.reason,
|
|
258
|
+
};
|
|
259
|
+
return adaptivePollState.current_ms;
|
|
260
|
+
}
|
|
150
261
|
function shouldLogDispatchDrainTick(result) {
|
|
151
262
|
if (!result || typeof result !== 'object')
|
|
152
263
|
return false;
|
|
@@ -176,6 +287,10 @@ function normalizeRalphContinueSteerState(raw) {
|
|
|
176
287
|
pane_id: safeString(raw.pane_id),
|
|
177
288
|
pane_current_command: safeString(raw.pane_current_command),
|
|
178
289
|
current_phase: safeString(raw.current_phase),
|
|
290
|
+
subagent_session_id: safeString(raw.subagent_session_id),
|
|
291
|
+
active_subagent_thread_ids: Array.isArray(raw.active_subagent_thread_ids)
|
|
292
|
+
? raw.active_subagent_thread_ids.map((value) => safeString(value).trim()).filter(Boolean)
|
|
293
|
+
: [],
|
|
179
294
|
shared_timestamp_path: safeString(raw.shared_timestamp_path) || ralphSteerTimestampPath,
|
|
180
295
|
shared_last_sent_at: safeString(raw.shared_last_sent_at),
|
|
181
296
|
singleton_lock_path: safeString(raw.singleton_lock_path) || ralphSteerLockPath,
|
|
@@ -215,6 +330,19 @@ async function loadPersistedWatcherState() {
|
|
|
215
330
|
last_nudged_at: safeString(persistedAutoNudge.last_nudged_at),
|
|
216
331
|
};
|
|
217
332
|
}
|
|
333
|
+
const persistedAdaptivePoll = persisted?.adaptive_poll;
|
|
334
|
+
if (persistedAdaptivePoll && typeof persistedAdaptivePoll === 'object') {
|
|
335
|
+
adaptivePollState = {
|
|
336
|
+
enabled: persistedAdaptivePoll.enabled !== false,
|
|
337
|
+
base_ms: pollMs,
|
|
338
|
+
max_ms: idleMaxPollMs,
|
|
339
|
+
current_ms: Math.min(idleMaxPollMs, Math.max(pollMs, asNumber(persistedAdaptivePoll.current_ms, pollMs))),
|
|
340
|
+
idle_streak: Math.max(0, Math.trunc(asNumber(persistedAdaptivePoll.idle_streak, 0))),
|
|
341
|
+
last_tick_at: safeString(persistedAdaptivePoll.last_tick_at) || null,
|
|
342
|
+
last_activity_at: safeString(persistedAdaptivePoll.last_activity_at) || null,
|
|
343
|
+
last_activity_reason: safeString(persistedAdaptivePoll.last_activity_reason) || 'init',
|
|
344
|
+
};
|
|
345
|
+
}
|
|
218
346
|
}
|
|
219
347
|
async function resolveActiveModeState(mode) {
|
|
220
348
|
const candidateDirs = [];
|
|
@@ -416,7 +544,8 @@ async function withRalphSteerLock(task) {
|
|
|
416
544
|
throw error;
|
|
417
545
|
const existing = await readRalphSteerLock(ralphSteerLockPath);
|
|
418
546
|
const lockAgeMs = parseIsoMillis(existing?.acquired_at) ?? 0;
|
|
419
|
-
const stale =
|
|
547
|
+
const stale = existing !== null
|
|
548
|
+
&& (!isPidAlive(existing.pid) || (lockAgeMs > 0 && Date.now() - lockAgeMs > RALPH_STEER_LOCK_STALE_MS));
|
|
420
549
|
if (stale) {
|
|
421
550
|
await unlink(ralphSteerLockPath).catch(() => { });
|
|
422
551
|
continue;
|
|
@@ -438,23 +567,39 @@ async function withRalphSteerLock(task) {
|
|
|
438
567
|
}
|
|
439
568
|
}
|
|
440
569
|
}
|
|
441
|
-
async function readRalphProgressGate(now) {
|
|
570
|
+
async function readRalphProgressGate(activeRalphState, now) {
|
|
571
|
+
const subagentSessionId = safeString(activeRalphState?.owner_codex_session_id).trim();
|
|
572
|
+
if (subagentSessionId) {
|
|
573
|
+
const summary = await readSubagentSessionSummary(cwd, subagentSessionId, {
|
|
574
|
+
now: new Date(now),
|
|
575
|
+
activeWindowMs: DEFAULT_SUBAGENT_ACTIVE_WINDOW_MS,
|
|
576
|
+
});
|
|
577
|
+
if ((summary?.activeSubagentThreadIds.length ?? 0) > 0) {
|
|
578
|
+
return {
|
|
579
|
+
allow: false,
|
|
580
|
+
reason: 'subagents_active',
|
|
581
|
+
progress_at: '',
|
|
582
|
+
subagent_session_id: subagentSessionId,
|
|
583
|
+
active_subagent_thread_ids: summary?.activeSubagentThreadIds ?? [],
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
}
|
|
442
587
|
const hudState = await readJsonObject(join(stateDir, 'hud-state.json'));
|
|
443
588
|
if (!hudState || typeof hudState !== 'object') {
|
|
444
|
-
return { allow: false, reason: 'progress_missing', progress_at: '' };
|
|
589
|
+
return { allow: false, reason: 'progress_missing', progress_at: '', subagent_session_id: subagentSessionId };
|
|
445
590
|
}
|
|
446
591
|
const progressAt = safeString(hudState.last_progress_at).trim();
|
|
447
592
|
if (!progressAt) {
|
|
448
|
-
return { allow: false, reason: 'progress_missing', progress_at: '' };
|
|
593
|
+
return { allow: false, reason: 'progress_missing', progress_at: '', subagent_session_id: subagentSessionId };
|
|
449
594
|
}
|
|
450
595
|
const progressMs = parseIsoMillis(progressAt);
|
|
451
596
|
if (progressMs === null) {
|
|
452
|
-
return { allow: false, reason: 'progress_invalid', progress_at: progressAt };
|
|
597
|
+
return { allow: false, reason: 'progress_invalid', progress_at: progressAt, subagent_session_id: subagentSessionId };
|
|
453
598
|
}
|
|
454
599
|
if (now - progressMs < RALPH_CONTINUE_CADENCE_MS) {
|
|
455
|
-
return { allow: false, reason: 'progress_fresh', progress_at: progressAt };
|
|
600
|
+
return { allow: false, reason: 'progress_fresh', progress_at: progressAt, subagent_session_id: subagentSessionId };
|
|
456
601
|
}
|
|
457
|
-
return { allow: true, reason: 'progress_stale', progress_at: progressAt };
|
|
602
|
+
return { allow: true, reason: 'progress_stale', progress_at: progressAt, subagent_session_id: subagentSessionId };
|
|
458
603
|
}
|
|
459
604
|
function shouldSkipRalphContinue(now, candidateIso, startupIso) {
|
|
460
605
|
const sharedMs = parseIsoMillis(candidateIso);
|
|
@@ -497,6 +642,100 @@ async function readPidFileRecord(path) {
|
|
|
497
642
|
return pid === null ? null : { pid };
|
|
498
643
|
}
|
|
499
644
|
}
|
|
645
|
+
function createAuthorityBackoffState(reason, overrides = {}) {
|
|
646
|
+
return {
|
|
647
|
+
active: false,
|
|
648
|
+
reason,
|
|
649
|
+
primary_pid: null,
|
|
650
|
+
primary_last_tick_at: '',
|
|
651
|
+
freshness_ms: null,
|
|
652
|
+
threshold_ms: null,
|
|
653
|
+
...overrides,
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
function latestWatcherTickIso(state) {
|
|
657
|
+
if (!state || typeof state !== 'object')
|
|
658
|
+
return '';
|
|
659
|
+
const candidates = [
|
|
660
|
+
safeString(state.dispatch_drain?.last_tick_at),
|
|
661
|
+
safeString(state.leader_nudge?.last_tick_at),
|
|
662
|
+
safeString(state.fallback_auto_nudge?.last_tick_at),
|
|
663
|
+
safeString(state.ralph_continue_steer?.last_state_check_at),
|
|
664
|
+
]
|
|
665
|
+
.map((value) => value.trim())
|
|
666
|
+
.filter(Boolean);
|
|
667
|
+
let latestIso = '';
|
|
668
|
+
let latestMs = -1;
|
|
669
|
+
for (const candidate of candidates) {
|
|
670
|
+
const parsed = parseIsoMillis(candidate);
|
|
671
|
+
if (parsed === null || parsed <= latestMs)
|
|
672
|
+
continue;
|
|
673
|
+
latestMs = parsed;
|
|
674
|
+
latestIso = candidate;
|
|
675
|
+
}
|
|
676
|
+
return latestIso;
|
|
677
|
+
}
|
|
678
|
+
async function resolveAuthorityPrimaryWatcherHealth(now = Date.now()) {
|
|
679
|
+
if (!authorityOnly)
|
|
680
|
+
return createAuthorityBackoffState('not_authority');
|
|
681
|
+
const existingRecord = await readPidFileRecord(pidFilePath).catch(() => null);
|
|
682
|
+
if (!existingRecord)
|
|
683
|
+
return createAuthorityBackoffState('pid_missing');
|
|
684
|
+
if (existingRecord.cwd && resolve(existingRecord.cwd) !== cwd)
|
|
685
|
+
return createAuthorityBackoffState('cwd_mismatch');
|
|
686
|
+
if (!isPidAlive(existingRecord.pid)) {
|
|
687
|
+
return createAuthorityBackoffState('pid_stale', {
|
|
688
|
+
primary_pid: existingRecord.pid,
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
const persistedState = await readJsonObject(statePath);
|
|
692
|
+
if (!persistedState) {
|
|
693
|
+
return createAuthorityBackoffState('state_missing', {
|
|
694
|
+
primary_pid: existingRecord.pid,
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
const persistedPid = Math.trunc(asNumber(persistedState.pid, 0));
|
|
698
|
+
if (persistedPid > 0 && persistedPid !== existingRecord.pid) {
|
|
699
|
+
return createAuthorityBackoffState('state_pid_mismatch', {
|
|
700
|
+
primary_pid: existingRecord.pid,
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
const lastTickAt = latestWatcherTickIso(persistedState);
|
|
704
|
+
if (!lastTickAt) {
|
|
705
|
+
return createAuthorityBackoffState('tick_missing', {
|
|
706
|
+
primary_pid: existingRecord.pid,
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
const lastTickMs = parseIsoMillis(lastTickAt);
|
|
710
|
+
const primaryPollMs = Math.max(50, asNumber(persistedState.poll_ms, 250));
|
|
711
|
+
const thresholdMs = Math.max(1_000, primaryPollMs * 4);
|
|
712
|
+
if (lastTickMs === null) {
|
|
713
|
+
return createAuthorityBackoffState('tick_invalid', {
|
|
714
|
+
primary_pid: existingRecord.pid,
|
|
715
|
+
primary_last_tick_at: lastTickAt,
|
|
716
|
+
threshold_ms: thresholdMs,
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
const freshnessMs = now - lastTickMs;
|
|
720
|
+
if (freshnessMs > thresholdMs) {
|
|
721
|
+
return {
|
|
722
|
+
active: false,
|
|
723
|
+
reason: 'tick_stale',
|
|
724
|
+
primary_pid: existingRecord.pid,
|
|
725
|
+
primary_last_tick_at: lastTickAt,
|
|
726
|
+
freshness_ms: freshnessMs,
|
|
727
|
+
threshold_ms: thresholdMs,
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
return {
|
|
731
|
+
active: true,
|
|
732
|
+
reason: 'primary_watcher_healthy',
|
|
733
|
+
primary_pid: existingRecord.pid,
|
|
734
|
+
primary_last_tick_at: lastTickAt,
|
|
735
|
+
freshness_ms: freshnessMs,
|
|
736
|
+
threshold_ms: thresholdMs,
|
|
737
|
+
};
|
|
738
|
+
}
|
|
500
739
|
async function writePidFileRecord() {
|
|
501
740
|
const nextRecord = {
|
|
502
741
|
pid: process.pid,
|
|
@@ -524,6 +763,8 @@ async function runRalphContinueSteerTick() {
|
|
|
524
763
|
state_path: activeRalph.path,
|
|
525
764
|
pane_id: activePaneId,
|
|
526
765
|
pane_current_command: '',
|
|
766
|
+
subagent_session_id: safeString(activeRalph.state?.owner_codex_session_id).trim(),
|
|
767
|
+
active_subagent_thread_ids: [],
|
|
527
768
|
shared_timestamp_path: ralphSteerTimestampPath,
|
|
528
769
|
singleton_lock_path: ralphSteerLockPath,
|
|
529
770
|
};
|
|
@@ -553,9 +794,11 @@ async function runRalphContinueSteerTick() {
|
|
|
553
794
|
}
|
|
554
795
|
return { sent: false, skipped: true };
|
|
555
796
|
}
|
|
556
|
-
const progressGate = await readRalphProgressGate(Date.now());
|
|
797
|
+
const progressGate = await readRalphProgressGate(activeRalph.state, Date.now());
|
|
557
798
|
if (!progressGate.allow) {
|
|
558
799
|
lastRalphContinueSteer.last_reason = progressGate.reason;
|
|
800
|
+
lastRalphContinueSteer.subagent_session_id = progressGate.subagent_session_id ?? lastRalphContinueSteer.subagent_session_id;
|
|
801
|
+
lastRalphContinueSteer.active_subagent_thread_ids = progressGate.active_subagent_thread_ids ?? [];
|
|
559
802
|
return { sent: false, skipped: true };
|
|
560
803
|
}
|
|
561
804
|
const paneId = safeString(activeRalph.state?.tmux_pane_id).trim();
|
|
@@ -675,6 +918,8 @@ async function writeState(extra = {}) {
|
|
|
675
918
|
notify_script: notifyScript,
|
|
676
919
|
authority_only: authorityOnly,
|
|
677
920
|
poll_ms: pollMs,
|
|
921
|
+
effective_poll_ms: adaptivePollState.current_ms,
|
|
922
|
+
idle_max_poll_ms: idleMaxPollMs,
|
|
678
923
|
pid_file: runOnce ? null : pidFilePath,
|
|
679
924
|
max_lifetime_ms: maxLifetimeMs,
|
|
680
925
|
tracked_files: fileState.size,
|
|
@@ -701,10 +946,25 @@ async function writeState(extra = {}) {
|
|
|
701
946
|
enabled: true,
|
|
702
947
|
stall_ms: AUTO_NUDGE_STALL_MS,
|
|
703
948
|
},
|
|
949
|
+
authority_backoff: lastAuthorityBackoff,
|
|
950
|
+
adaptive_poll: {
|
|
951
|
+
...adaptivePollState,
|
|
952
|
+
enabled: true,
|
|
953
|
+
base_ms: pollMs,
|
|
954
|
+
max_ms: idleMaxPollMs,
|
|
955
|
+
},
|
|
704
956
|
...extra,
|
|
705
957
|
};
|
|
706
958
|
await writeFile(statePath, JSON.stringify(state, null, 2)).catch(() => { });
|
|
707
959
|
}
|
|
960
|
+
async function writeAuthorityBackoffState() {
|
|
961
|
+
await mkdir(stateDir, { recursive: true }).catch(() => { });
|
|
962
|
+
const existing = await readJsonObject(statePath);
|
|
963
|
+
const state = existing && typeof existing === 'object'
|
|
964
|
+
? { ...existing, authority_backoff: lastAuthorityBackoff }
|
|
965
|
+
: { authority_backoff: lastAuthorityBackoff };
|
|
966
|
+
await writeFile(statePath, JSON.stringify(state, null, 2)).catch(() => { });
|
|
967
|
+
}
|
|
708
968
|
async function readJsonObject(path) {
|
|
709
969
|
return readFile(path, 'utf-8')
|
|
710
970
|
.then((content) => JSON.parse(content))
|
|
@@ -1020,6 +1280,7 @@ function splitBufferedLines(partial, delta) {
|
|
|
1020
1280
|
};
|
|
1021
1281
|
}
|
|
1022
1282
|
async function pollFiles() {
|
|
1283
|
+
let processedCount = 0;
|
|
1023
1284
|
for (const [path, meta] of fileState.entries()) {
|
|
1024
1285
|
const currentSize = (await stat(path).catch(() => ({ size: 0 }))).size || 0;
|
|
1025
1286
|
if (currentSize <= meta.offset)
|
|
@@ -1036,8 +1297,10 @@ async function pollFiles() {
|
|
|
1036
1297
|
if (!line.trim())
|
|
1037
1298
|
continue;
|
|
1038
1299
|
await processLine(meta, line, path);
|
|
1300
|
+
processedCount += 1;
|
|
1039
1301
|
}
|
|
1040
1302
|
}
|
|
1303
|
+
return processedCount;
|
|
1041
1304
|
}
|
|
1042
1305
|
async function runLeaderNudgeTick() {
|
|
1043
1306
|
const startedIso = new Date().toISOString();
|
|
@@ -1053,7 +1316,7 @@ async function runLeaderNudgeTick() {
|
|
|
1053
1316
|
last_tick_at: startedIso,
|
|
1054
1317
|
last_error: 'worker_context',
|
|
1055
1318
|
};
|
|
1056
|
-
return;
|
|
1319
|
+
return false;
|
|
1057
1320
|
}
|
|
1058
1321
|
try {
|
|
1059
1322
|
const preComputedLeaderStale = await isLeaderStale(stateDir, staleThresholdMs, Date.now());
|
|
@@ -1063,6 +1326,7 @@ async function runLeaderNudgeTick() {
|
|
|
1063
1326
|
logsDir,
|
|
1064
1327
|
preComputedLeaderStale,
|
|
1065
1328
|
allowFreshMailboxNudges: false,
|
|
1329
|
+
source: 'notify_fallback_watcher',
|
|
1066
1330
|
});
|
|
1067
1331
|
leaderNudgeRuns += 1;
|
|
1068
1332
|
lastLeaderNudge = {
|
|
@@ -1084,6 +1348,7 @@ async function runLeaderNudgeTick() {
|
|
|
1084
1348
|
reason,
|
|
1085
1349
|
});
|
|
1086
1350
|
}
|
|
1351
|
+
return preComputedLeaderStale;
|
|
1087
1352
|
}
|
|
1088
1353
|
catch (err) {
|
|
1089
1354
|
leaderNudgeRuns += 1;
|
|
@@ -1103,6 +1368,7 @@ async function runLeaderNudgeTick() {
|
|
|
1103
1368
|
reason: 'leader_nudge_failed',
|
|
1104
1369
|
error: lastLeaderNudge.last_error,
|
|
1105
1370
|
});
|
|
1371
|
+
return true;
|
|
1106
1372
|
}
|
|
1107
1373
|
}
|
|
1108
1374
|
async function runDispatchDrainTick() {
|
|
@@ -1125,6 +1391,7 @@ async function runDispatchDrainTick() {
|
|
|
1125
1391
|
...(result && typeof result === 'object' ? result : {}),
|
|
1126
1392
|
});
|
|
1127
1393
|
}
|
|
1394
|
+
return shouldLogDispatchDrainTick(result);
|
|
1128
1395
|
}
|
|
1129
1396
|
catch (err) {
|
|
1130
1397
|
dispatchDrainRuns += 1;
|
|
@@ -1142,6 +1409,7 @@ async function runDispatchDrainTick() {
|
|
|
1142
1409
|
reason: 'dispatch_drain_failed',
|
|
1143
1410
|
error: lastDispatchDrain.last_error,
|
|
1144
1411
|
});
|
|
1412
|
+
return true;
|
|
1145
1413
|
}
|
|
1146
1414
|
}
|
|
1147
1415
|
async function shouldSuppressInteractiveFallbackTicks() {
|
|
@@ -1152,34 +1420,65 @@ async function shouldSuppressInteractiveFallbackTicks() {
|
|
|
1152
1420
|
return deepInterviewStateActive || deepInterviewInputLockActive;
|
|
1153
1421
|
}
|
|
1154
1422
|
async function pumpTeamControlPlaneTick() {
|
|
1155
|
-
await runDispatchDrainTick();
|
|
1156
|
-
if (await shouldSuppressInteractiveFallbackTicks())
|
|
1157
|
-
return;
|
|
1158
|
-
|
|
1423
|
+
const dispatchActive = await runDispatchDrainTick();
|
|
1424
|
+
if (await shouldSuppressInteractiveFallbackTicks()) {
|
|
1425
|
+
return { active: dispatchActive, reason: dispatchActive ? 'dispatch_drain' : 'deep_interview_locked' };
|
|
1426
|
+
}
|
|
1427
|
+
const leaderActive = await runLeaderNudgeTick();
|
|
1159
1428
|
await runFallbackAutoNudgeTick();
|
|
1429
|
+
const autoNudgeActive = lastFallbackAutoNudge.last_reason === 'sent';
|
|
1430
|
+
if (dispatchActive)
|
|
1431
|
+
return { active: true, reason: 'dispatch_drain' };
|
|
1432
|
+
if (leaderActive)
|
|
1433
|
+
return { active: true, reason: 'leader_nudge' };
|
|
1434
|
+
if (autoNudgeActive)
|
|
1435
|
+
return { active: true, reason: 'fallback_auto_nudge' };
|
|
1436
|
+
return { active: false, reason: lastFallbackAutoNudge.last_reason || 'control_plane_idle' };
|
|
1160
1437
|
}
|
|
1161
1438
|
async function runWatcherCycle() {
|
|
1439
|
+
let processedRolloutCount = 0;
|
|
1440
|
+
if (authorityOnly) {
|
|
1441
|
+
const authorityBackoff = await resolveAuthorityPrimaryWatcherHealth();
|
|
1442
|
+
lastAuthorityBackoff = authorityBackoff;
|
|
1443
|
+
if (authorityBackoff.active) {
|
|
1444
|
+
await writeAuthorityBackoffState();
|
|
1445
|
+
return processedRolloutCount;
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
else {
|
|
1449
|
+
lastAuthorityBackoff = createAuthorityBackoffState('');
|
|
1450
|
+
}
|
|
1162
1451
|
if (!authorityOnly) {
|
|
1163
1452
|
await ensureTrackedFiles();
|
|
1164
|
-
await pollFiles();
|
|
1453
|
+
processedRolloutCount = await pollFiles();
|
|
1165
1454
|
}
|
|
1166
|
-
await pumpTeamControlPlaneTick();
|
|
1455
|
+
const controlPlaneSummary = await pumpTeamControlPlaneTick();
|
|
1167
1456
|
if (!authorityOnly && !(await shouldSuppressInteractiveFallbackTicks())) {
|
|
1168
1457
|
await runRalphWatcherBehaviorTick();
|
|
1169
1458
|
}
|
|
1170
|
-
|
|
1459
|
+
const ralphActive = lastRalphContinueSteer.last_reason === 'sent';
|
|
1460
|
+
const summary = processedRolloutCount > 0
|
|
1461
|
+
? { active: true, reason: 'rollout_event' }
|
|
1462
|
+
: controlPlaneSummary.active
|
|
1463
|
+
? controlPlaneSummary
|
|
1464
|
+
: ralphActive
|
|
1465
|
+
? { active: true, reason: 'ralph_continue_steer' }
|
|
1466
|
+
: { active: false, reason: controlPlaneSummary.reason || lastRalphContinueSteer.last_reason || 'idle' };
|
|
1467
|
+
const nextDelayMs = updateAdaptivePollState(summary);
|
|
1468
|
+
await writeState({ last_cycle_activity: summary.reason });
|
|
1469
|
+
return nextDelayMs;
|
|
1171
1470
|
}
|
|
1172
1471
|
async function tick() {
|
|
1173
1472
|
if (stopping)
|
|
1174
1473
|
return;
|
|
1175
1474
|
if (await enforceLifecycleGuards())
|
|
1176
1475
|
return;
|
|
1177
|
-
await runWatcherCycle();
|
|
1476
|
+
const nextDelayMs = await runWatcherCycle();
|
|
1178
1477
|
if (await enforceLifecycleGuards())
|
|
1179
1478
|
return;
|
|
1180
1479
|
setTimeout(() => {
|
|
1181
1480
|
void tick();
|
|
1182
|
-
},
|
|
1481
|
+
}, nextDelayMs);
|
|
1183
1482
|
}
|
|
1184
1483
|
function shutdown(signal) {
|
|
1185
1484
|
void requestShutdown('signal', signal);
|
|
@@ -1200,6 +1499,8 @@ async function main() {
|
|
|
1200
1499
|
notify_script: notifyScript,
|
|
1201
1500
|
authority_only: authorityOnly,
|
|
1202
1501
|
poll_ms: pollMs,
|
|
1502
|
+
effective_poll_ms: adaptivePollState.current_ms,
|
|
1503
|
+
idle_max_poll_ms: idleMaxPollMs,
|
|
1203
1504
|
once: runOnce,
|
|
1204
1505
|
parent_pid: parentPid,
|
|
1205
1506
|
pid_file: runOnce ? null : pidFilePath,
|