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,10 +1,10 @@
|
|
|
1
1
|
import { describe, it } from 'node:test';
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
|
-
import { mkdtemp, rm, mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { chmod, mkdtemp, rm, mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { tmpdir } from 'node:os';
|
|
6
6
|
import { resolveTeamApiOperation, buildLegacyTeamDeprecationHint, executeTeamApiOperation, LEGACY_TEAM_MCP_TOOLS, TEAM_API_OPERATIONS, } from '../api-interop.js';
|
|
7
|
-
import { initTeamState, createTask, readTask, sendDirectMessage, enqueueDispatchRequest, readDispatchRequest, listDispatchRequests, appendTeamEvent, updateWorkerHeartbeat, writeMonitorSnapshot, writeWorkerStatus, } from '../state.js';
|
|
7
|
+
import { initTeamState, createTask, readTeamLeaderAttention, readTeamManifestV2, readTask, writeTeamLeaderAttention, writeTeamManifestV2, writeTeamPhase, sendDirectMessage, enqueueDispatchRequest, readDispatchRequest, listDispatchRequests, appendTeamEvent, markOwnedTeamsLeaderStopObserved, markOwnedTeamsLeaderSessionStopped, updateWorkerHeartbeat, writeMonitorSnapshot, writeWorkerStatus, } from '../state.js';
|
|
8
8
|
async function setupTeam(name) {
|
|
9
9
|
const cwd = await mkdtemp(join(tmpdir(), `omx-interop-${name}-`));
|
|
10
10
|
const previousTeamStateRoot = process.env.OMX_TEAM_STATE_ROOT;
|
|
@@ -21,6 +21,76 @@ async function setupTeam(name) {
|
|
|
21
21
|
},
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
+
async function withMailboxCompatHoleRuntime(cwd, fn) {
|
|
25
|
+
const fakeBin = join(cwd, 'runtime-bin');
|
|
26
|
+
const runtimePath = join(fakeBin, 'omx-runtime');
|
|
27
|
+
const previousPath = process.env.PATH;
|
|
28
|
+
const previousBinary = process.env.OMX_RUNTIME_BINARY;
|
|
29
|
+
const previousBridge = process.env.OMX_RUNTIME_BRIDGE;
|
|
30
|
+
await mkdir(fakeBin, { recursive: true });
|
|
31
|
+
await writeFile(runtimePath, `#!/usr/bin/env node
|
|
32
|
+
const fs = require('fs');
|
|
33
|
+
const path = require('path');
|
|
34
|
+
const argv = process.argv.slice(2);
|
|
35
|
+
function argValue(prefix) {
|
|
36
|
+
const entry = argv.find((value) => value.startsWith(prefix));
|
|
37
|
+
return entry ? entry.slice(prefix.length) : null;
|
|
38
|
+
}
|
|
39
|
+
function stateDir() {
|
|
40
|
+
return argValue('--state-dir=') || process.cwd();
|
|
41
|
+
}
|
|
42
|
+
function readJson(file, fallback) {
|
|
43
|
+
try { return JSON.parse(fs.readFileSync(file, 'utf8')); } catch { return fallback; }
|
|
44
|
+
}
|
|
45
|
+
function writeJson(file, value) {
|
|
46
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
47
|
+
fs.writeFileSync(file, JSON.stringify(value, null, 2) + '\\n');
|
|
48
|
+
}
|
|
49
|
+
if (argv[0] === 'schema') {
|
|
50
|
+
process.stdout.write(JSON.stringify({ schema_version: 1, commands: [], events: [], transport: 'tmux' }) + '\\n');
|
|
51
|
+
process.exit(0);
|
|
52
|
+
}
|
|
53
|
+
if (argv[0] !== 'exec') process.exit(1);
|
|
54
|
+
const command = JSON.parse(argv[1] || '{}');
|
|
55
|
+
const dir = stateDir();
|
|
56
|
+
if (command.command === 'CreateMailboxMessage') {
|
|
57
|
+
writeJson(path.join(dir, 'mailbox.json'), readJson(path.join(dir, 'mailbox.json'), { records: [] }));
|
|
58
|
+
process.stdout.write(JSON.stringify({ event: 'MailboxMessageCreated', message_id: command.message_id, from_worker: command.from_worker, to_worker: command.to_worker }) + '\\n');
|
|
59
|
+
process.exit(0);
|
|
60
|
+
}
|
|
61
|
+
process.stdout.write(JSON.stringify({ event: 'ok' }) + '\\n');
|
|
62
|
+
`, 'utf8');
|
|
63
|
+
await chmod(runtimePath, 0o755);
|
|
64
|
+
process.env.PATH = `${fakeBin}:${previousPath || ''}`;
|
|
65
|
+
process.env.OMX_RUNTIME_BINARY = runtimePath;
|
|
66
|
+
process.env.OMX_RUNTIME_BRIDGE = '1';
|
|
67
|
+
try {
|
|
68
|
+
return await fn();
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
71
|
+
if (typeof previousPath === 'string')
|
|
72
|
+
process.env.PATH = previousPath;
|
|
73
|
+
else
|
|
74
|
+
delete process.env.PATH;
|
|
75
|
+
if (typeof previousBinary === 'string')
|
|
76
|
+
process.env.OMX_RUNTIME_BINARY = previousBinary;
|
|
77
|
+
else
|
|
78
|
+
delete process.env.OMX_RUNTIME_BINARY;
|
|
79
|
+
if (typeof previousBridge === 'string')
|
|
80
|
+
process.env.OMX_RUNTIME_BRIDGE = previousBridge;
|
|
81
|
+
else
|
|
82
|
+
delete process.env.OMX_RUNTIME_BRIDGE;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async function readTeamDeliveryLog(cwd) {
|
|
86
|
+
const path = join(cwd, '.omx', 'logs', `team-delivery-${new Date().toISOString().slice(0, 10)}.jsonl`);
|
|
87
|
+
const raw = await readFile(path, 'utf-8').catch(() => '');
|
|
88
|
+
return raw
|
|
89
|
+
.split('\n')
|
|
90
|
+
.map((line) => line.trim())
|
|
91
|
+
.filter(Boolean)
|
|
92
|
+
.map((line) => JSON.parse(line));
|
|
93
|
+
}
|
|
24
94
|
// ─── resolveTeamApiOperation ──────────────────────────────────────────────
|
|
25
95
|
describe('resolveTeamApiOperation', () => {
|
|
26
96
|
it('resolves a valid kebab-case operation', () => {
|
|
@@ -149,6 +219,15 @@ describe('executeTeamApiOperation: send-message', () => {
|
|
|
149
219
|
const mailboxRequest = parsedRequests.find((request) => request.message_id === messageId);
|
|
150
220
|
assert.ok(mailboxRequest, 'send-message should enqueue a mailbox dispatch request');
|
|
151
221
|
assert.equal(mailboxRequest?.to_worker, 'worker-2');
|
|
222
|
+
const deliveryLog = await readTeamDeliveryLog(cwd);
|
|
223
|
+
assert.ok(deliveryLog.some((entry) => entry.event === 'mailbox_created'
|
|
224
|
+
&& entry.message_id === messageId
|
|
225
|
+
&& entry.from_worker === 'worker-1'
|
|
226
|
+
&& entry.to_worker === 'worker-2'));
|
|
227
|
+
assert.ok(deliveryLog.some((entry) => entry.event === 'dispatch_attempted'
|
|
228
|
+
&& entry.request_id === mailboxRequest?.request_id
|
|
229
|
+
&& entry.message_id === messageId
|
|
230
|
+
&& entry.to_worker === 'worker-2'));
|
|
152
231
|
}
|
|
153
232
|
finally {
|
|
154
233
|
await cleanup();
|
|
@@ -197,6 +276,15 @@ describe('executeTeamApiOperation: send-message', () => {
|
|
|
197
276
|
const mailbox = JSON.parse(await readFile(join(repoCwd, '.omx', 'state', 'team', teamName, 'mailbox', 'leader-fixed.json'), 'utf-8'));
|
|
198
277
|
const workerMessages = (mailbox.messages ?? []).filter((message) => message.from_worker === 'worker-1' && message.to_worker === 'leader-fixed');
|
|
199
278
|
assert.equal(workerMessages.length, 1, 'deduped leader sends should not append duplicate worker mailbox rows');
|
|
279
|
+
const deliveryLog = [
|
|
280
|
+
...(await readTeamDeliveryLog(repoCwd)),
|
|
281
|
+
...(await readTeamDeliveryLog(workerCwd)),
|
|
282
|
+
];
|
|
283
|
+
const createdEvents = deliveryLog.filter((entry) => entry.event === 'mailbox_created'
|
|
284
|
+
&& entry.from_worker === 'worker-1'
|
|
285
|
+
&& entry.to_worker === 'leader-fixed'
|
|
286
|
+
&& entry.message_id === firstMessage.message_id);
|
|
287
|
+
assert.equal(createdEvents.length, 1, 'deduped leader sends should only emit one mailbox_created event');
|
|
200
288
|
}
|
|
201
289
|
finally {
|
|
202
290
|
if (typeof prevTeamStateRoot === 'string')
|
|
@@ -207,6 +295,43 @@ describe('executeTeamApiOperation: send-message', () => {
|
|
|
207
295
|
await rm(workerCwd, { recursive: true, force: true });
|
|
208
296
|
}
|
|
209
297
|
});
|
|
298
|
+
it('returns the persisted mailbox message when bridge compat omits the mailbox row under an explicit shared state root', async () => {
|
|
299
|
+
const teamName = 'msg-team-shared-root';
|
|
300
|
+
const root = await mkdtemp(join(tmpdir(), 'omx-interop-shared-root-'));
|
|
301
|
+
const leaderCwd = join(root, 'leader');
|
|
302
|
+
const workerCwd = join(root, 'worker-worktree');
|
|
303
|
+
const sharedStateRoot = join(root, 'shared-state');
|
|
304
|
+
const prevTeamStateRoot = process.env.OMX_TEAM_STATE_ROOT;
|
|
305
|
+
try {
|
|
306
|
+
await mkdir(leaderCwd, { recursive: true });
|
|
307
|
+
await mkdir(workerCwd, { recursive: true });
|
|
308
|
+
process.env.OMX_TEAM_STATE_ROOT = sharedStateRoot;
|
|
309
|
+
await initTeamState(teamName, 'shared state root mailbox fallback', 'executor', 2, leaderCwd);
|
|
310
|
+
await withMailboxCompatHoleRuntime(root, async () => {
|
|
311
|
+
const result = await executeTeamApiOperation('send-message', {
|
|
312
|
+
team_name: teamName,
|
|
313
|
+
from_worker: 'worker-1',
|
|
314
|
+
to_worker: 'leader-fixed',
|
|
315
|
+
body: 'shared-root hello',
|
|
316
|
+
}, workerCwd);
|
|
317
|
+
assert.equal(result.ok, true);
|
|
318
|
+
if (!result.ok)
|
|
319
|
+
throw new Error('expected send-message call to succeed');
|
|
320
|
+
const message = result.data.message;
|
|
321
|
+
assert.equal(message.body, 'shared-root hello');
|
|
322
|
+
assert.equal(message.to_worker, 'leader-fixed');
|
|
323
|
+
const mailbox = JSON.parse(await readFile(join(sharedStateRoot, 'team', teamName, 'mailbox', 'leader-fixed.json'), 'utf8'));
|
|
324
|
+
assert.equal(mailbox.messages?.length, 1);
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
finally {
|
|
328
|
+
if (typeof prevTeamStateRoot === 'string')
|
|
329
|
+
process.env.OMX_TEAM_STATE_ROOT = prevTeamStateRoot;
|
|
330
|
+
else
|
|
331
|
+
delete process.env.OMX_TEAM_STATE_ROOT;
|
|
332
|
+
await rm(root, { recursive: true, force: true });
|
|
333
|
+
}
|
|
334
|
+
});
|
|
210
335
|
it('returns error when from_worker missing', async () => {
|
|
211
336
|
const result = await executeTeamApiOperation('send-message', {
|
|
212
337
|
team_name: 'any', to_worker: 'w2', body: 'hi',
|
|
@@ -318,11 +443,70 @@ describe('executeTeamApiOperation: mailbox-mark-delivered', () => {
|
|
|
318
443
|
assert.equal(result.data.dispatch_updated, true);
|
|
319
444
|
const updatedDispatch = await readDispatchRequest('mark-dlv', dispatch.request.request_id, cwd);
|
|
320
445
|
assert.equal(updatedDispatch?.status, 'delivered');
|
|
446
|
+
const deliveryLog = await readTeamDeliveryLog(cwd);
|
|
447
|
+
assert.ok(deliveryLog.some((entry) => entry.event === 'delivered'
|
|
448
|
+
&& entry.message_id === msgId
|
|
449
|
+
&& entry.to_worker === 'worker-2'));
|
|
450
|
+
assert.ok(deliveryLog.some((entry) => entry.event === 'mark_delivered'
|
|
451
|
+
&& entry.message_id === msgId
|
|
452
|
+
&& entry.request_id === dispatch.request.request_id
|
|
453
|
+
&& entry.dispatch_updated === true));
|
|
321
454
|
}
|
|
322
455
|
finally {
|
|
323
456
|
await cleanup();
|
|
324
457
|
}
|
|
325
458
|
});
|
|
459
|
+
it('marks leader-fixed mailbox delivery from a worker worktree and resolves the matching dispatch receipt', async () => {
|
|
460
|
+
const teamName = 'mark-dlv-leader-worktree';
|
|
461
|
+
const repoCwd = await mkdtemp(join(tmpdir(), 'omx-interop-mark-dlv-root-'));
|
|
462
|
+
const workerCwd = await mkdtemp(join(tmpdir(), 'omx-interop-mark-dlv-worktree-'));
|
|
463
|
+
const prevTeamStateRoot = process.env.OMX_TEAM_STATE_ROOT;
|
|
464
|
+
delete process.env.OMX_TEAM_STATE_ROOT;
|
|
465
|
+
try {
|
|
466
|
+
await initTeamState(teamName, 'leader mailbox delivery receipt', 'executor', 2, repoCwd);
|
|
467
|
+
process.env.OMX_TEAM_STATE_ROOT = join(repoCwd, '.omx', 'state');
|
|
468
|
+
const sendResult = await executeTeamApiOperation('send-message', {
|
|
469
|
+
team_name: teamName,
|
|
470
|
+
from_worker: 'worker-1',
|
|
471
|
+
to_worker: 'leader-fixed',
|
|
472
|
+
body: 'DONE: worker-1 finished a mailbox integrity probe',
|
|
473
|
+
}, workerCwd);
|
|
474
|
+
assert.equal(sendResult.ok, true);
|
|
475
|
+
if (!sendResult.ok)
|
|
476
|
+
throw new Error('expected successful leader send-message result');
|
|
477
|
+
const message = sendResult.data.message;
|
|
478
|
+
const messageId = String(message.message_id ?? '');
|
|
479
|
+
assert.ok(messageId, 'leader mailbox message should include a message_id');
|
|
480
|
+
const pendingRequests = await listDispatchRequests(teamName, repoCwd, { kind: 'mailbox', to_worker: 'leader-fixed' });
|
|
481
|
+
const pendingDispatch = pendingRequests.find((request) => request.message_id === messageId);
|
|
482
|
+
assert.ok(pendingDispatch, 'leader mailbox send should enqueue a matching dispatch request');
|
|
483
|
+
const result = await executeTeamApiOperation('mailbox-mark-delivered', {
|
|
484
|
+
team_name: teamName,
|
|
485
|
+
worker: 'leader-fixed',
|
|
486
|
+
message_id: messageId,
|
|
487
|
+
}, workerCwd);
|
|
488
|
+
assert.equal(result.ok, true);
|
|
489
|
+
if (!result.ok)
|
|
490
|
+
throw new Error('expected successful leader mailbox-mark-delivered result');
|
|
491
|
+
assert.equal(result.data.updated, true);
|
|
492
|
+
assert.equal(result.data.dispatch_request_id, pendingDispatch?.request_id);
|
|
493
|
+
assert.equal(result.data.dispatch_updated, true);
|
|
494
|
+
const updatedDispatch = await readDispatchRequest(teamName, pendingDispatch.request_id, repoCwd);
|
|
495
|
+
assert.equal(updatedDispatch?.status, 'delivered');
|
|
496
|
+
assert.ok(updatedDispatch?.delivered_at, 'leader dispatch receipt should record delivered_at');
|
|
497
|
+
const leaderMailbox = JSON.parse(await readFile(join(repoCwd, '.omx', 'state', 'team', teamName, 'mailbox', 'leader-fixed.json'), 'utf-8'));
|
|
498
|
+
const deliveredMessage = (leaderMailbox.messages ?? []).find((entry) => entry.message_id === messageId);
|
|
499
|
+
assert.equal(typeof deliveredMessage?.delivered_at, 'string');
|
|
500
|
+
}
|
|
501
|
+
finally {
|
|
502
|
+
if (typeof prevTeamStateRoot === 'string')
|
|
503
|
+
process.env.OMX_TEAM_STATE_ROOT = prevTeamStateRoot;
|
|
504
|
+
else
|
|
505
|
+
delete process.env.OMX_TEAM_STATE_ROOT;
|
|
506
|
+
await rm(repoCwd, { recursive: true, force: true });
|
|
507
|
+
await rm(workerCwd, { recursive: true, force: true });
|
|
508
|
+
}
|
|
509
|
+
});
|
|
326
510
|
it('reports when no matching mailbox dispatch request exists', async () => {
|
|
327
511
|
const { cwd, cleanup } = await setupTeam('mark-dlv-no-dispatch');
|
|
328
512
|
try {
|
|
@@ -1208,7 +1392,7 @@ describe('executeTeamApiOperation: read-idle-state', () => {
|
|
|
1208
1392
|
});
|
|
1209
1393
|
// ─── read-stall-state ───────────────────────────────────────────────────────
|
|
1210
1394
|
describe('executeTeamApiOperation: read-stall-state', () => {
|
|
1211
|
-
it('returns structured stall state from
|
|
1395
|
+
it('returns structured stall state from authoritative leader attention state', async () => {
|
|
1212
1396
|
const { cwd, cleanup } = await setupTeam('stall-state-team');
|
|
1213
1397
|
try {
|
|
1214
1398
|
const task = await createTask('stall-state-team', {
|
|
@@ -1256,15 +1440,21 @@ describe('executeTeamApiOperation: read-stall-state', () => {
|
|
|
1256
1440
|
mailboxNotifiedByMessageId: {},
|
|
1257
1441
|
completedEventTaskIds: {},
|
|
1258
1442
|
}, cwd);
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1443
|
+
await writeTeamLeaderAttention('stall-state-team', {
|
|
1444
|
+
team_name: 'stall-state-team',
|
|
1445
|
+
updated_at: '2026-03-10T10:05:00.000Z',
|
|
1446
|
+
source: 'native_stop',
|
|
1447
|
+
leader_decision_state: 'still_actionable',
|
|
1448
|
+
leader_attention_pending: true,
|
|
1449
|
+
leader_attention_reason: 'leader_session_stopped',
|
|
1450
|
+
attention_reasons: ['leader_session_stopped'],
|
|
1451
|
+
leader_stale: false,
|
|
1452
|
+
leader_session_active: false,
|
|
1453
|
+
leader_session_id: 'leader-session-1',
|
|
1454
|
+
leader_session_stopped_at: '2026-03-10T10:05:00.000Z',
|
|
1455
|
+
unread_leader_message_count: 1,
|
|
1456
|
+
work_remaining: true,
|
|
1457
|
+
stalled_for_ms: null,
|
|
1268
1458
|
}, cwd);
|
|
1269
1459
|
const result = await executeTeamApiOperation('read-stall-state', {
|
|
1270
1460
|
team_name: 'stall-state-team',
|
|
@@ -1279,18 +1469,154 @@ describe('executeTeamApiOperation: read-stall-state', () => {
|
|
|
1279
1469
|
assert.equal(result.data.pending_task_count, 1);
|
|
1280
1470
|
assert.equal(result.data.all_workers_idle, true);
|
|
1281
1471
|
assert.match(result.data.reasons.join(' '), /workers_non_reporting:worker-1/);
|
|
1282
|
-
assert.match(result.data.reasons.join(' '), /leader_attention_pending:
|
|
1283
|
-
const
|
|
1284
|
-
|
|
1285
|
-
assert.equal(
|
|
1286
|
-
|
|
1287
|
-
|
|
1472
|
+
assert.match(result.data.reasons.join(' '), /leader_attention_pending:leader_session_stopped/);
|
|
1473
|
+
const attention = result.data.leader_attention_state;
|
|
1474
|
+
assert.equal(attention?.leader_session_active, false);
|
|
1475
|
+
assert.equal(attention?.source, 'native_stop');
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
finally {
|
|
1479
|
+
await cleanup();
|
|
1480
|
+
}
|
|
1481
|
+
});
|
|
1482
|
+
it('uses unread leader mailbox state even without recent nudge events', async () => {
|
|
1483
|
+
const { cwd, cleanup } = await setupTeam('stall-state-mailbox');
|
|
1484
|
+
try {
|
|
1485
|
+
await sendDirectMessage('stall-state-mailbox', 'worker-1', 'leader-fixed', 'please review', cwd);
|
|
1486
|
+
const result = await executeTeamApiOperation('read-stall-state', {
|
|
1487
|
+
team_name: 'stall-state-mailbox',
|
|
1488
|
+
}, cwd);
|
|
1489
|
+
assert.equal(result.ok, true);
|
|
1490
|
+
if (result.ok) {
|
|
1491
|
+
assert.equal(result.data.leader_attention_pending, true);
|
|
1492
|
+
assert.equal(result.data.leader_stale, false);
|
|
1493
|
+
assert.equal(result.data.unread_leader_message_count, 1);
|
|
1494
|
+
assert.match(result.data.reasons.join(' '), /leader_attention_pending:unread_leader_mailbox/);
|
|
1288
1495
|
}
|
|
1289
1496
|
}
|
|
1290
1497
|
finally {
|
|
1291
1498
|
await cleanup();
|
|
1292
1499
|
}
|
|
1293
1500
|
});
|
|
1501
|
+
it('suppresses stale native-stop attention after newer leader activity', async () => {
|
|
1502
|
+
const { cwd, cleanup } = await setupTeam('stall-state-resume');
|
|
1503
|
+
try {
|
|
1504
|
+
await writeTeamLeaderAttention('stall-state-resume', {
|
|
1505
|
+
team_name: 'stall-state-resume',
|
|
1506
|
+
updated_at: '2026-03-10T10:05:00.000Z',
|
|
1507
|
+
source: 'native_stop',
|
|
1508
|
+
leader_decision_state: 'still_actionable',
|
|
1509
|
+
leader_attention_pending: true,
|
|
1510
|
+
leader_attention_reason: 'leader_session_stopped',
|
|
1511
|
+
attention_reasons: ['leader_session_stopped'],
|
|
1512
|
+
leader_stale: false,
|
|
1513
|
+
leader_session_active: false,
|
|
1514
|
+
leader_session_id: 'leader-session-1',
|
|
1515
|
+
leader_session_stopped_at: '2026-03-10T10:05:00.000Z',
|
|
1516
|
+
unread_leader_message_count: 0,
|
|
1517
|
+
work_remaining: false,
|
|
1518
|
+
stalled_for_ms: null,
|
|
1519
|
+
}, cwd);
|
|
1520
|
+
await writeFile(join(cwd, '.omx', 'state', 'leader-runtime-activity.json'), JSON.stringify({
|
|
1521
|
+
last_activity_at: '2026-03-10T10:06:00.000Z',
|
|
1522
|
+
last_source: 'team_status',
|
|
1523
|
+
last_team_name: 'stall-state-resume',
|
|
1524
|
+
}, null, 2));
|
|
1525
|
+
const result = await executeTeamApiOperation('read-stall-state', {
|
|
1526
|
+
team_name: 'stall-state-resume',
|
|
1527
|
+
}, cwd);
|
|
1528
|
+
assert.equal(result.ok, true);
|
|
1529
|
+
if (result.ok) {
|
|
1530
|
+
assert.equal(result.data.leader_attention_pending, false);
|
|
1531
|
+
assert.equal(result.data.leader_stale, false);
|
|
1532
|
+
assert.doesNotMatch(result.data.reasons.join(' '), /leader_attention_pending:leader_session_stopped/);
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
finally {
|
|
1536
|
+
await cleanup();
|
|
1537
|
+
}
|
|
1538
|
+
});
|
|
1539
|
+
it('marks only active leader-owned teams as stopped on session end', async () => {
|
|
1540
|
+
const { cwd, cleanup } = await setupTeam('owned-team');
|
|
1541
|
+
try {
|
|
1542
|
+
await initTeamState('other-team', 'Other', 'executor', 1, cwd);
|
|
1543
|
+
const ownedManifest = await readTeamManifestV2('owned-team', cwd);
|
|
1544
|
+
const otherManifest = await readTeamManifestV2('other-team', cwd);
|
|
1545
|
+
assert.ok(ownedManifest);
|
|
1546
|
+
assert.ok(otherManifest);
|
|
1547
|
+
await writeTeamManifestV2({
|
|
1548
|
+
...ownedManifest,
|
|
1549
|
+
leader: {
|
|
1550
|
+
...ownedManifest.leader,
|
|
1551
|
+
session_id: 'leader-session-1',
|
|
1552
|
+
},
|
|
1553
|
+
}, cwd);
|
|
1554
|
+
await writeTeamManifestV2({
|
|
1555
|
+
...otherManifest,
|
|
1556
|
+
leader: {
|
|
1557
|
+
...otherManifest.leader,
|
|
1558
|
+
session_id: 'leader-session-2',
|
|
1559
|
+
},
|
|
1560
|
+
}, cwd);
|
|
1561
|
+
await writeTeamLeaderAttention('owned-team', {
|
|
1562
|
+
team_name: 'owned-team',
|
|
1563
|
+
updated_at: '2026-03-10T10:12:00.000Z',
|
|
1564
|
+
source: 'notify_hook',
|
|
1565
|
+
leader_decision_state: 'still_actionable',
|
|
1566
|
+
leader_attention_pending: true,
|
|
1567
|
+
leader_attention_reason: 'stale_leader_with_messages',
|
|
1568
|
+
attention_reasons: ['stale_leader_with_messages'],
|
|
1569
|
+
leader_stale: true,
|
|
1570
|
+
leader_session_active: true,
|
|
1571
|
+
leader_session_id: 'leader-session-1',
|
|
1572
|
+
leader_session_stopped_at: null,
|
|
1573
|
+
unread_leader_message_count: 1,
|
|
1574
|
+
work_remaining: true,
|
|
1575
|
+
stalled_for_ms: null,
|
|
1576
|
+
}, cwd);
|
|
1577
|
+
await writeTeamPhase('other-team', {
|
|
1578
|
+
current_phase: 'complete',
|
|
1579
|
+
max_fix_attempts: 3,
|
|
1580
|
+
current_fix_attempt: 0,
|
|
1581
|
+
transitions: [],
|
|
1582
|
+
updated_at: '2026-03-10T10:10:00.000Z',
|
|
1583
|
+
}, cwd);
|
|
1584
|
+
const updatedTeams = await markOwnedTeamsLeaderSessionStopped(cwd, 'leader-session-1', '2026-03-10T10:15:00.000Z');
|
|
1585
|
+
assert.deepEqual(updatedTeams, ['owned-team']);
|
|
1586
|
+
const ownedAttention = await readTeamLeaderAttention('owned-team', cwd);
|
|
1587
|
+
const otherAttention = await readTeamLeaderAttention('other-team', cwd);
|
|
1588
|
+
assert.equal(ownedAttention?.leader_session_active, false);
|
|
1589
|
+
assert.equal(ownedAttention?.leader_attention_pending, true);
|
|
1590
|
+
assert.equal(ownedAttention?.leader_attention_reason, 'stale_leader_with_messages');
|
|
1591
|
+
assert.deepEqual(ownedAttention?.attention_reasons, ['stale_leader_with_messages', 'leader_session_stopped']);
|
|
1592
|
+
assert.equal(otherAttention, null);
|
|
1593
|
+
}
|
|
1594
|
+
finally {
|
|
1595
|
+
await cleanup();
|
|
1596
|
+
}
|
|
1597
|
+
});
|
|
1598
|
+
it('marks only active leader-owned teams from the native stop hook', async () => {
|
|
1599
|
+
const { cwd, cleanup } = await setupTeam('owned-stop-team');
|
|
1600
|
+
try {
|
|
1601
|
+
const ownedManifest = await readTeamManifestV2('owned-stop-team', cwd);
|
|
1602
|
+
assert.ok(ownedManifest);
|
|
1603
|
+
await writeTeamManifestV2({
|
|
1604
|
+
...ownedManifest,
|
|
1605
|
+
leader: {
|
|
1606
|
+
...ownedManifest.leader,
|
|
1607
|
+
session_id: 'leader-session-stop',
|
|
1608
|
+
},
|
|
1609
|
+
}, cwd);
|
|
1610
|
+
const updatedTeams = await markOwnedTeamsLeaderStopObserved(cwd, 'leader-session-stop', '2026-03-10T10:15:00.000Z');
|
|
1611
|
+
assert.deepEqual(updatedTeams, ['owned-stop-team']);
|
|
1612
|
+
const ownedAttention = await readTeamLeaderAttention('owned-stop-team', cwd);
|
|
1613
|
+
assert.equal(ownedAttention?.source, 'native_stop');
|
|
1614
|
+
assert.equal(ownedAttention?.leader_session_active, false);
|
|
1615
|
+
}
|
|
1616
|
+
finally {
|
|
1617
|
+
await cleanup();
|
|
1618
|
+
}
|
|
1619
|
+
});
|
|
1294
1620
|
});
|
|
1295
1621
|
// ─── get-summary ──────────────────────────────────────────────────────────
|
|
1296
1622
|
describe('executeTeamApiOperation: get-summary', () => {
|