oh-my-codex 0.20.1 → 0.20.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +7 -6
- package/Cargo.toml +1 -1
- package/README.md +36 -1
- package/crates/omx-runtime/Cargo.toml +1 -0
- package/crates/omx-runtime/src/main.rs +25 -2
- package/crates/omx-runtime/tests/execution.rs +219 -0
- package/crates/omx-runtime-core/src/dispatch.rs +96 -10
- package/crates/omx-runtime-core/src/engine.rs +839 -29
- package/crates/omx-runtime-core/src/lib.rs +8 -0
- package/dist/adapt/__tests__/hermes.test.js.map +1 -1
- package/dist/adapt/contracts.d.ts.map +1 -1
- package/dist/agents/__tests__/definitions.test.js +81 -0
- package/dist/agents/__tests__/definitions.test.js.map +1 -1
- package/dist/agents/__tests__/native-config.test.js +25 -0
- package/dist/agents/__tests__/native-config.test.js.map +1 -1
- package/dist/agents/native-config.d.ts +2 -1
- package/dist/agents/native-config.d.ts.map +1 -1
- package/dist/agents/native-config.js.map +1 -1
- package/dist/auth/__tests__/hotswap.test.d.ts +2 -0
- package/dist/auth/__tests__/hotswap.test.d.ts.map +1 -0
- package/dist/auth/__tests__/hotswap.test.js +183 -0
- package/dist/auth/__tests__/hotswap.test.js.map +1 -0
- package/dist/auth/hotswap.d.ts +6 -0
- package/dist/auth/hotswap.d.ts.map +1 -1
- package/dist/auth/hotswap.js +102 -19
- package/dist/auth/hotswap.js.map +1 -1
- package/dist/auth/paths.js.map +1 -1
- package/dist/auth/storage.js.map +1 -1
- package/dist/autopilot/__tests__/ralplan-gate.test.js +5 -5
- package/dist/autopilot/__tests__/ralplan-gate.test.js.map +1 -1
- package/dist/autopilot/completion-gate.js.map +1 -1
- package/dist/autopilot/fsm.d.ts +1 -1
- package/dist/autopilot/fsm.d.ts.map +1 -1
- package/dist/autoresearch/goal.js.map +1 -1
- package/dist/autoresearch/runtime.js.map +1 -1
- package/dist/capabilities/lockfile.js.map +1 -1
- package/dist/catalog/reader.js.map +1 -1
- package/dist/catalog/skill-mirror.js.map +1 -1
- package/dist/cli/__tests__/adapt-help.test.js.map +1 -1
- package/dist/cli/__tests__/agents-init.test.js.map +1 -1
- package/dist/cli/__tests__/agents.test.js.map +1 -1
- package/dist/cli/__tests__/api.test.js.map +1 -1
- package/dist/cli/__tests__/ask.test.js.map +1 -1
- package/dist/cli/__tests__/auth.test.js +60 -6
- package/dist/cli/__tests__/auth.test.js.map +1 -1
- package/dist/cli/__tests__/autoresearch-guided.test.js.map +1 -1
- package/dist/cli/__tests__/autoresearch.test.js.map +1 -1
- package/dist/cli/__tests__/capabilities.test.js.map +1 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js +80 -0
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-context-window-warning.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-invalid-config.test.js +47 -4
- package/dist/cli/__tests__/doctor-invalid-config.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-team.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js +752 -15
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/exec.test.js +136 -0
- package/dist/cli/__tests__/exec.test.js.map +1 -1
- package/dist/cli/__tests__/imagegen-continuation.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +473 -14
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/launch-fallback.test.js +336 -4
- package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
- package/dist/cli/__tests__/mcp-parity.test.js +87 -12
- package/dist/cli/__tests__/mcp-parity.test.js.map +1 -1
- package/dist/cli/__tests__/native-hook-claim-journal.test.d.ts +2 -0
- package/dist/cli/__tests__/native-hook-claim-journal.test.d.ts.map +1 -0
- package/dist/cli/__tests__/native-hook-claim-journal.test.js +206 -0
- package/dist/cli/__tests__/native-hook-claim-journal.test.js.map +1 -0
- package/dist/cli/__tests__/nested-help-routing.test.js.map +1 -1
- package/dist/cli/__tests__/question.test.js.map +1 -1
- package/dist/cli/__tests__/ralph-deslop-contract.test.js.map +1 -1
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +6 -0
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
- package/dist/cli/__tests__/ralph-prd-deep-interview.test.js.map +1 -1
- package/dist/cli/__tests__/ralph-prd-smoke.test.js.map +1 -1
- package/dist/cli/__tests__/ralph.test.js +8 -3
- package/dist/cli/__tests__/ralph.test.js.map +1 -1
- package/dist/cli/__tests__/ralplan-bootstrap-3181.test.d.ts +2 -0
- package/dist/cli/__tests__/ralplan-bootstrap-3181.test.d.ts.map +1 -0
- package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js +72 -0
- package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js.map +1 -0
- package/dist/cli/__tests__/ralplan.test.d.ts +2 -0
- package/dist/cli/__tests__/ralplan.test.d.ts.map +1 -0
- package/dist/cli/__tests__/ralplan.test.js +55 -0
- package/dist/cli/__tests__/ralplan.test.js.map +1 -0
- package/dist/cli/__tests__/resume.test.js +17 -11
- package/dist/cli/__tests__/resume.test.js.map +1 -1
- package/dist/cli/__tests__/session-scoped-runtime.test.js +25 -0
- package/dist/cli/__tests__/session-scoped-runtime.test.js.map +1 -1
- package/dist/cli/__tests__/session-search-help.test.js +25 -1
- package/dist/cli/__tests__/session-search-help.test.js.map +1 -1
- package/dist/cli/__tests__/session-search.test.js.map +1 -1
- package/dist/cli/__tests__/setup-agents-overwrite.test.js +79 -0
- package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
- package/dist/cli/__tests__/setup-gh-star.test.js.map +1 -1
- package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js +77 -3
- package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js.map +1 -1
- package/dist/cli/__tests__/setup-hooks-trust-e2e.test.d.ts +2 -0
- package/dist/cli/__tests__/setup-hooks-trust-e2e.test.d.ts.map +1 -0
- package/dist/cli/__tests__/setup-hooks-trust-e2e.test.js +285 -0
- package/dist/cli/__tests__/setup-hooks-trust-e2e.test.js.map +1 -0
- package/dist/cli/__tests__/setup-install-mode.test.js +2579 -294
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
- package/dist/cli/__tests__/setup-preferences.test.d.ts +2 -0
- package/dist/cli/__tests__/setup-preferences.test.d.ts.map +1 -0
- package/dist/cli/__tests__/setup-preferences.test.js +79 -0
- package/dist/cli/__tests__/setup-preferences.test.js.map +1 -0
- package/dist/cli/__tests__/setup-refresh.test.js +33 -2
- package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
- package/dist/cli/__tests__/setup-scope.test.js +46 -3
- package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
- package/dist/cli/__tests__/sparkshell-cli.test.js.map +1 -1
- package/dist/cli/__tests__/state.test.js +37 -0
- package/dist/cli/__tests__/state.test.js.map +1 -1
- package/dist/cli/__tests__/team.test.js +105 -7
- package/dist/cli/__tests__/team.test.js.map +1 -1
- package/dist/cli/__tests__/ultragoal.test.js +61 -1
- package/dist/cli/__tests__/ultragoal.test.js.map +1 -1
- package/dist/cli/__tests__/uninstall.test.js +1817 -24
- package/dist/cli/__tests__/uninstall.test.js.map +1 -1
- package/dist/cli/__tests__/update.test.js +58 -0
- package/dist/cli/__tests__/update.test.js.map +1 -1
- package/dist/cli/__tests__/url.test.js.map +1 -1
- package/dist/cli/__tests__/windows-popup-loop-contract.test.js +2 -1
- package/dist/cli/__tests__/windows-popup-loop-contract.test.js.map +1 -1
- package/dist/cli/adapt.js.map +1 -1
- package/dist/cli/agents-init.js.map +1 -1
- package/dist/cli/agents.js.map +1 -1
- package/dist/cli/api.js.map +1 -1
- package/dist/cli/ask.d.ts +1 -1
- package/dist/cli/ask.d.ts.map +1 -1
- package/dist/cli/ask.js.map +1 -1
- package/dist/cli/auth.js.map +1 -1
- package/dist/cli/autoresearch-guided.js.map +1 -1
- package/dist/cli/autoresearch-intake.js.map +1 -1
- package/dist/cli/capabilities.js.map +1 -1
- package/dist/cli/cleanup.js.map +1 -1
- package/dist/cli/codex-feature-probe.js.map +1 -1
- package/dist/cli/codex-home.js.map +1 -1
- package/dist/cli/doctor.d.ts +21 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +607 -130
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/explore.js.map +1 -1
- package/dist/cli/index.d.ts +14 -3
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +245 -57
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-parity.js +2 -2
- package/dist/cli/mcp-parity.js.map +1 -1
- package/dist/cli/mcp-serve.js.map +1 -1
- package/dist/cli/mission.js.map +1 -1
- package/dist/cli/native-assets.js.map +1 -1
- package/dist/cli/native-hook-claim-journal.d.ts +29 -0
- package/dist/cli/native-hook-claim-journal.d.ts.map +1 -0
- package/dist/cli/native-hook-claim-journal.js +252 -0
- package/dist/cli/native-hook-claim-journal.js.map +1 -0
- package/dist/cli/omx.js.map +1 -1
- package/dist/cli/plugin-marketplace.js.map +1 -1
- package/dist/cli/project-runtime-codex-homes.js.map +1 -1
- package/dist/cli/question.js.map +1 -1
- package/dist/cli/ralph.d.ts.map +1 -1
- package/dist/cli/ralph.js +3 -2
- package/dist/cli/ralph.js.map +1 -1
- package/dist/cli/ralplan.d.ts +10 -0
- package/dist/cli/ralplan.d.ts.map +1 -0
- package/dist/cli/ralplan.js +110 -0
- package/dist/cli/ralplan.js.map +1 -0
- package/dist/cli/session-search.d.ts +5 -0
- package/dist/cli/session-search.d.ts.map +1 -1
- package/dist/cli/session-search.js +87 -0
- package/dist/cli/session-search.js.map +1 -1
- package/dist/cli/setup-preferences.d.ts +11 -0
- package/dist/cli/setup-preferences.d.ts.map +1 -1
- package/dist/cli/setup-preferences.js +32 -0
- package/dist/cli/setup-preferences.js.map +1 -1
- package/dist/cli/setup.d.ts +58 -0
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +1450 -398
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/sparkshell.js.map +1 -1
- package/dist/cli/star-prompt.js.map +1 -1
- package/dist/cli/state.d.ts.map +1 -1
- package/dist/cli/state.js +2 -1
- package/dist/cli/state.js.map +1 -1
- package/dist/cli/team.js.map +1 -1
- package/dist/cli/ultragoal.d.ts +5 -1
- package/dist/cli/ultragoal.d.ts.map +1 -1
- package/dist/cli/ultragoal.js +34 -2
- package/dist/cli/ultragoal.js.map +1 -1
- package/dist/cli/uninstall.d.ts +17 -0
- package/dist/cli/uninstall.d.ts.map +1 -1
- package/dist/cli/uninstall.js +986 -95
- package/dist/cli/uninstall.js.map +1 -1
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +8 -1
- package/dist/cli/update.js.map +1 -1
- package/dist/cli/url.js.map +1 -1
- package/dist/compat/__tests__/doctor-contract.test.js +5 -1
- package/dist/compat/__tests__/doctor-contract.test.js.map +1 -1
- package/dist/compat/__tests__/rust-runtime-compat.test.js +1 -1
- package/dist/compat/__tests__/rust-runtime-compat.test.js.map +1 -1
- package/dist/config/__tests__/codex-hooks.test.js +1287 -11
- package/dist/config/__tests__/codex-hooks.test.js.map +1 -1
- package/dist/config/__tests__/generator-idempotent.test.js +1179 -32
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
- package/dist/config/__tests__/generator-notify.test.js +6 -1
- package/dist/config/__tests__/generator-notify.test.js.map +1 -1
- package/dist/config/__tests__/models.test.js +67 -3
- package/dist/config/__tests__/models.test.js.map +1 -1
- package/dist/config/codex-feature-flags.d.ts.map +1 -1
- package/dist/config/codex-feature-flags.js.map +1 -1
- package/dist/config/codex-hooks.d.ts +124 -1
- package/dist/config/codex-hooks.d.ts.map +1 -1
- package/dist/config/codex-hooks.js +2142 -265
- package/dist/config/codex-hooks.js.map +1 -1
- package/dist/config/commit-lore-guard.js.map +1 -1
- package/dist/config/generator.d.ts +23 -34
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +1480 -246
- package/dist/config/generator.js.map +1 -1
- package/dist/config/mcp-registry.js.map +1 -1
- package/dist/config/models.d.ts +14 -4
- package/dist/config/models.d.ts.map +1 -1
- package/dist/config/models.js +15 -1
- package/dist/config/models.js.map +1 -1
- package/dist/config/omx-first-party-mcp.js.map +1 -1
- package/dist/config/team-mode.d.ts.map +1 -1
- package/dist/document-refresh/__tests__/enforcer.test.js.map +1 -1
- package/dist/document-refresh/enforcer.js.map +1 -1
- package/dist/exec/followup.js.map +1 -1
- package/dist/goal-workflows/artifacts.js.map +1 -1
- package/dist/hooks/__tests__/agents-overlay.test.js +7 -4
- package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
- package/dist/hooks/__tests__/analyze-routing-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/analyze-skill-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/anti-slop-workflow.test.js.map +1 -1
- package/dist/hooks/__tests__/autopilot-skill-contract.test.js +9 -3
- package/dist/hooks/__tests__/autopilot-skill-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/code-review-skill-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/consensus-execution-handoff.test.js.map +1 -1
- package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/design-skill.test.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +1376 -6
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js +252 -543
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +38 -4
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +765 -10
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js +2 -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 +142 -1
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-modules.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.js +48 -2
- package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js +61 -44
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-regression-205.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js +3 -2
- package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js +243 -4
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +531 -12
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +163 -24
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +482 -32
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +68 -1
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js +7 -1
- package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-visual-verdict.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +43 -4
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
- package/dist/hooks/__tests__/openclaw-setup-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/pre-context-gate-skills.test.js.map +1 -1
- package/dist/hooks/__tests__/prometheus-strict-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-guidance-fragments.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-guidance-test-helpers.js.map +1 -1
- package/dist/hooks/__tests__/prompt-session-provenance.test.d.ts +2 -0
- package/dist/hooks/__tests__/prompt-session-provenance.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/prompt-session-provenance.test.js +82 -0
- package/dist/hooks/__tests__/prompt-session-provenance.test.js.map +1 -0
- package/dist/hooks/__tests__/session.test.js +878 -11
- package/dist/hooks/__tests__/session.test.js.map +1 -1
- package/dist/hooks/__tests__/skill-catalog-hygiene.test.js.map +1 -1
- package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/visual-ralph-skill.test.js.map +1 -1
- package/dist/hooks/__tests__/visual-verdict-loop.test.js.map +1 -1
- package/dist/hooks/agents-overlay.js +5 -5
- package/dist/hooks/agents-overlay.js.map +1 -1
- package/dist/hooks/code-simplifier/index.js.map +1 -1
- package/dist/hooks/explore-routing.js.map +1 -1
- package/dist/hooks/extensibility/dispatcher.js.map +1 -1
- package/dist/hooks/extensibility/events.js.map +1 -1
- package/dist/hooks/extensibility/loader.js.map +1 -1
- package/dist/hooks/extensibility/plugin-runner-stdin.js.map +1 -1
- package/dist/hooks/extensibility/sdk/logging.js.map +1 -1
- package/dist/hooks/keyword-detector.d.ts +33 -7
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +2228 -119
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/hooks/keyword-registry.d.ts +12 -0
- package/dist/hooks/keyword-registry.d.ts.map +1 -1
- package/dist/hooks/keyword-registry.js +41 -0
- package/dist/hooks/keyword-registry.js.map +1 -1
- package/dist/hooks/prompt-session-provenance.d.ts +87 -0
- package/dist/hooks/prompt-session-provenance.d.ts.map +1 -0
- package/dist/hooks/prompt-session-provenance.js +180 -0
- package/dist/hooks/prompt-session-provenance.js.map +1 -0
- package/dist/hooks/session.d.ts +163 -34
- package/dist/hooks/session.d.ts.map +1 -1
- package/dist/hooks/session.js +1395 -317
- package/dist/hooks/session.js.map +1 -1
- package/dist/hooks/task-size-detector.js.map +1 -1
- package/dist/hud/__tests__/state.test.js.map +1 -1
- package/dist/hud/authority.js.map +1 -1
- package/dist/hud/constants.js.map +1 -1
- package/dist/hud/index.js.map +1 -1
- package/dist/hud/reconcile.js.map +1 -1
- package/dist/hud/render.js.map +1 -1
- package/dist/hud/state.js.map +1 -1
- package/dist/hud/tmux.js.map +1 -1
- package/dist/leader/__tests__/contract.test.js +153 -1
- package/dist/leader/__tests__/contract.test.js.map +1 -1
- package/dist/leader/contract.d.ts +42 -5
- package/dist/leader/contract.d.ts.map +1 -1
- package/dist/leader/contract.js +184 -3
- package/dist/leader/contract.js.map +1 -1
- package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
- package/dist/mcp/__tests__/code-intel-server.test.js +31 -3
- package/dist/mcp/__tests__/code-intel-server.test.js.map +1 -1
- package/dist/mcp/__tests__/server-lifecycle.test.js +15 -2
- package/dist/mcp/__tests__/server-lifecycle.test.js.map +1 -1
- package/dist/mcp/__tests__/state-paths.test.js +98 -1
- package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
- package/dist/mcp/__tests__/wiki-server.test.js +18 -0
- package/dist/mcp/__tests__/wiki-server.test.js.map +1 -1
- package/dist/mcp/bootstrap.js.map +1 -1
- package/dist/mcp/code-intel-server.d.ts +58 -58
- package/dist/mcp/code-intel-server.d.ts.map +1 -1
- package/dist/mcp/code-intel-server.js +13 -3
- package/dist/mcp/code-intel-server.js.map +1 -1
- package/dist/mcp/hermes-bridge.js.map +1 -1
- package/dist/mcp/hermes-server.d.ts +70 -70
- package/dist/mcp/hermes-server.d.ts.map +1 -1
- package/dist/mcp/lifecycle-telemetry.js.map +1 -1
- package/dist/mcp/memory-server.d.ts +34 -34
- package/dist/mcp/memory-server.d.ts.map +1 -1
- package/dist/mcp/memory-server.js.map +1 -1
- package/dist/mcp/state-paths.d.ts +14 -0
- package/dist/mcp/state-paths.d.ts.map +1 -1
- package/dist/mcp/state-paths.js +96 -20
- package/dist/mcp/state-paths.js.map +1 -1
- package/dist/mcp/state-server.d.ts +47 -47
- package/dist/mcp/state-server.d.ts.map +1 -1
- package/dist/mcp/trace-server.d.ts +4 -4
- package/dist/mcp/trace-server.d.ts.map +1 -1
- package/dist/mcp/trace-server.js.map +1 -1
- package/dist/mcp/wiki-server.d.ts +34 -23
- package/dist/mcp/wiki-server.d.ts.map +1 -1
- package/dist/mcp/wiki-server.js +9 -2
- package/dist/mcp/wiki-server.js.map +1 -1
- package/dist/modes/__tests__/base-session-scope.test.js +53 -1
- package/dist/modes/__tests__/base-session-scope.test.js.map +1 -1
- package/dist/modes/__tests__/base-tmux-pane.test.js +4 -4
- package/dist/modes/__tests__/base-tmux-pane.test.js.map +1 -1
- package/dist/modes/base.d.ts.map +1 -1
- package/dist/modes/base.js +5 -5
- package/dist/modes/base.js.map +1 -1
- package/dist/notifications/__tests__/lifecycle-dedupe.test.js.map +1 -1
- package/dist/notifications/__tests__/reply-listener.test.js.map +1 -1
- package/dist/notifications/__tests__/session-idle-tail-dedupe.test.js +177 -85
- package/dist/notifications/__tests__/session-idle-tail-dedupe.test.js.map +1 -1
- package/dist/notifications/__tests__/session-registry.test.js.map +1 -1
- package/dist/notifications/__tests__/template-engine.test.js.map +1 -1
- package/dist/notifications/__tests__/verbosity.test.js.map +1 -1
- package/dist/notifications/http-client.js.map +1 -1
- package/dist/notifications/index.d.ts +4 -1
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +3 -9
- package/dist/notifications/index.js.map +1 -1
- package/dist/notifications/lifecycle-dedupe.js.map +1 -1
- package/dist/notifications/reply-listener.d.ts.map +1 -1
- package/dist/notifications/reply-listener.js.map +1 -1
- package/dist/notifications/session-registry.js.map +1 -1
- package/dist/notifications/session-status.js.map +1 -1
- package/dist/notifications/temp-contract.d.ts.map +1 -1
- package/dist/notifications/temp-contract.js +4 -0
- package/dist/notifications/temp-contract.js.map +1 -1
- package/dist/notifications/tmux-detector.js.map +1 -1
- package/dist/notifications/tmux.js.map +1 -1
- package/dist/openclaw/config.js.map +1 -1
- package/dist/openclaw/dispatcher.js.map +1 -1
- package/dist/pipeline/__tests__/orchestrator.test.js +4 -4
- package/dist/pipeline/__tests__/orchestrator.test.js.map +1 -1
- package/dist/pipeline/__tests__/stages.test.js +16 -13
- package/dist/pipeline/__tests__/stages.test.js.map +1 -1
- package/dist/pipeline/stages/code-review.js.map +1 -1
- package/dist/pipeline/stages/ralph-verify.js.map +1 -1
- package/dist/pipeline/stages/ralplan.js.map +1 -1
- package/dist/pipeline/stages/team-exec.js.map +1 -1
- package/dist/pipeline/stages/ultragoal.js.map +1 -1
- package/dist/pipeline/stages/ultraqa.js.map +1 -1
- package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.js.map +1 -1
- package/dist/planning/artifact-names.js.map +1 -1
- package/dist/planning/artifacts.js.map +1 -1
- package/dist/question/__tests__/state.test.js.map +1 -1
- package/dist/question/__tests__/ui.test.js.map +1 -1
- package/dist/question/autopilot-wait.js.map +1 -1
- package/dist/question/client.d.ts.map +1 -1
- package/dist/question/client.js.map +1 -1
- package/dist/question/deep-interview.js.map +1 -1
- package/dist/question/events.js.map +1 -1
- package/dist/question/renderer.js.map +1 -1
- package/dist/question/state.d.ts.map +1 -1
- package/dist/question/state.js.map +1 -1
- package/dist/question/ui.js.map +1 -1
- package/dist/ralph/contract.d.ts +1 -1
- package/dist/ralph/contract.d.ts.map +1 -1
- package/dist/ralplan/__tests__/consensus-gate.test.js +527 -8
- package/dist/ralplan/__tests__/consensus-gate.test.js.map +1 -1
- package/dist/ralplan/__tests__/documented-leader-preflight.test.d.ts +2 -0
- package/dist/ralplan/__tests__/documented-leader-preflight.test.d.ts.map +1 -0
- package/dist/ralplan/__tests__/documented-leader-preflight.test.js +46 -0
- package/dist/ralplan/__tests__/documented-leader-preflight.test.js.map +1 -0
- package/dist/ralplan/__tests__/runtime.test.js +116 -14
- package/dist/ralplan/__tests__/runtime.test.js.map +1 -1
- package/dist/ralplan/consensus-gate.d.ts +3 -3
- package/dist/ralplan/consensus-gate.d.ts.map +1 -1
- package/dist/ralplan/consensus-gate.js +173 -70
- package/dist/ralplan/consensus-gate.js.map +1 -1
- package/dist/ralplan/documented-leader-preflight.d.ts +34 -0
- package/dist/ralplan/documented-leader-preflight.d.ts.map +1 -0
- package/dist/ralplan/documented-leader-preflight.js +58 -0
- package/dist/ralplan/documented-leader-preflight.js.map +1 -0
- package/dist/ralplan/runtime.d.ts +3 -2
- package/dist/ralplan/runtime.d.ts.map +1 -1
- package/dist/ralplan/runtime.js +12 -9
- package/dist/ralplan/runtime.js.map +1 -1
- package/dist/runtime/__tests__/bridge.test.js +42 -1
- package/dist/runtime/__tests__/bridge.test.js.map +1 -1
- package/dist/runtime/bridge.d.ts +12 -0
- package/dist/runtime/bridge.d.ts.map +1 -1
- package/dist/runtime/bridge.js +52 -1
- package/dist/runtime/bridge.js.map +1 -1
- package/dist/runtime/process-tree.js.map +1 -1
- package/dist/runtime/run-loop.js.map +1 -1
- package/dist/runtime/run-outcome.d.ts +3 -3
- package/dist/runtime/run-outcome.d.ts.map +1 -1
- package/dist/runtime/run-outcome.js.map +1 -1
- package/dist/runtime/run-state.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +6657 -995
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/fixtures/issue-3138-installed-smoke.d.ts +2 -0
- package/dist/scripts/__tests__/fixtures/issue-3138-installed-smoke.d.ts.map +1 -0
- package/dist/scripts/__tests__/fixtures/issue-3138-installed-smoke.js +634 -0
- package/dist/scripts/__tests__/fixtures/issue-3138-installed-smoke.js.map +1 -0
- package/dist/scripts/__tests__/generate-release-body.test.js.map +1 -1
- package/dist/scripts/__tests__/hook-derived-watcher.test.js.map +1 -1
- package/dist/scripts/__tests__/notify-dispatcher.test.js.map +1 -1
- package/dist/scripts/__tests__/notify-fallback-delivery.test.d.ts +2 -0
- package/dist/scripts/__tests__/notify-fallback-delivery.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/notify-fallback-delivery.test.js +174 -0
- package/dist/scripts/__tests__/notify-fallback-delivery.test.js.map +1 -0
- package/dist/scripts/__tests__/notify-state-io.test.js +57 -1
- package/dist/scripts/__tests__/notify-state-io.test.js.map +1 -1
- package/dist/scripts/__tests__/reasoning-artifact-contract.test.d.ts +2 -0
- package/dist/scripts/__tests__/reasoning-artifact-contract.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/reasoning-artifact-contract.test.js +108 -0
- package/dist/scripts/__tests__/reasoning-artifact-contract.test.js.map +1 -0
- package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.d.ts +2 -0
- package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js +78 -0
- package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js.map +1 -0
- package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.d.ts +2 -0
- package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js +55 -0
- package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js.map +1 -0
- package/dist/scripts/__tests__/run-test-files.test.js.map +1 -1
- package/dist/scripts/__tests__/smoke-packed-install.test.js +1100 -4
- package/dist/scripts/__tests__/smoke-packed-install.test.js.map +1 -1
- package/dist/scripts/__tests__/test-reply-listener-live.test.js.map +1 -1
- package/dist/scripts/build-api.js.map +1 -1
- package/dist/scripts/build-explore-harness.js.map +1 -1
- package/dist/scripts/build-sparkshell.js.map +1 -1
- package/dist/scripts/cleanup-explore-harness.js.map +1 -1
- package/dist/scripts/codex-execution-surface.js.map +1 -1
- package/dist/scripts/codex-native-hook.d.ts +4 -1
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +11577 -1184
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/generate-native-release-manifest.js.map +1 -1
- package/dist/scripts/generate-release-body.js.map +1 -1
- package/dist/scripts/hook-payload-guard.d.ts.map +1 -1
- package/dist/scripts/hook-payload-guard.js.map +1 -1
- package/dist/scripts/notify-fallback-delivery.d.ts +48 -0
- package/dist/scripts/notify-fallback-delivery.d.ts.map +1 -0
- package/dist/scripts/notify-fallback-delivery.js +419 -0
- package/dist/scripts/notify-fallback-delivery.js.map +1 -0
- package/dist/scripts/notify-fallback-watcher.js +218 -138
- package/dist/scripts/notify-fallback-watcher.js.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.d.ts +18 -9
- package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.js +112 -15
- package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/managed-tmux.d.ts +23 -0
- package/dist/scripts/notify-hook/managed-tmux.d.ts.map +1 -1
- package/dist/scripts/notify-hook/managed-tmux.js +122 -12
- package/dist/scripts/notify-hook/managed-tmux.js.map +1 -1
- package/dist/scripts/notify-hook/orchestration-intent.d.ts +7 -7
- package/dist/scripts/notify-hook/orchestration-intent.d.ts.map +1 -1
- package/dist/scripts/notify-hook/ralph-session-resume.d.ts +5 -2
- package/dist/scripts/notify-hook/ralph-session-resume.d.ts.map +1 -1
- package/dist/scripts/notify-hook/ralph-session-resume.js +33 -37
- package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -1
- package/dist/scripts/notify-hook/state-io.d.ts +17 -0
- package/dist/scripts/notify-hook/state-io.d.ts.map +1 -1
- package/dist/scripts/notify-hook/state-io.js +73 -11
- package/dist/scripts/notify-hook/state-io.js.map +1 -1
- package/dist/scripts/notify-hook/team-dispatch.d.ts +10 -1
- package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-dispatch.js +234 -79
- package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.d.ts +2 -2
- package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.js +39 -13
- package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.d.ts +16 -8
- package/dist/scripts/notify-hook/team-tmux-guard.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.js +365 -44
- package/dist/scripts/notify-hook/team-tmux-guard.js.map +1 -1
- package/dist/scripts/notify-hook/team-worker-posttooluse.js.map +1 -1
- package/dist/scripts/notify-hook/team-worker-stop.d.ts +1 -1
- package/dist/scripts/notify-hook/team-worker-stop.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-worker-stop.js +19 -18
- package/dist/scripts/notify-hook/team-worker-stop.js.map +1 -1
- package/dist/scripts/notify-hook/team-worker.d.ts +5 -2
- package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-worker.js +37 -28
- package/dist/scripts/notify-hook/team-worker.js.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.d.ts +8 -1
- package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.js +53 -18
- package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
- package/dist/scripts/notify-hook/visual-verdict.d.ts +1 -1
- package/dist/scripts/notify-hook/visual-verdict.d.ts.map +1 -1
- package/dist/scripts/notify-hook/visual-verdict.js +15 -13
- package/dist/scripts/notify-hook/visual-verdict.js.map +1 -1
- package/dist/scripts/notify-hook.d.ts +24 -1
- package/dist/scripts/notify-hook.d.ts.map +1 -1
- package/dist/scripts/notify-hook.js +267 -90
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/scripts/postinstall.js.map +1 -1
- package/dist/scripts/prompt-inventory.js.map +1 -1
- package/dist/scripts/smoke-packed-install.d.ts +927 -5
- package/dist/scripts/smoke-packed-install.d.ts.map +1 -1
- package/dist/scripts/smoke-packed-install.js +4317 -13
- package/dist/scripts/smoke-packed-install.js.map +1 -1
- package/dist/scripts/sync-plugin-mirror.js.map +1 -1
- package/dist/scripts/test-reply-listener-live.js.map +1 -1
- package/dist/scripts/test-sparkshell.js.map +1 -1
- package/dist/scripts/verify-native-agents.js.map +1 -1
- package/dist/session-history/friction.js.map +1 -1
- package/dist/session-history/search.js.map +1 -1
- package/dist/sidecar/__tests__/boundary.test.js.map +1 -1
- package/dist/sidecar/collector.js.map +1 -1
- package/dist/sidecar/index.js.map +1 -1
- package/dist/sidecar/render.js.map +1 -1
- package/dist/sidecar/tmux.js.map +1 -1
- package/dist/state/__tests__/mode-state-context.test.js +54 -0
- package/dist/state/__tests__/mode-state-context.test.js.map +1 -1
- package/dist/state/__tests__/operations.test.js +66 -15
- package/dist/state/__tests__/operations.test.js.map +1 -1
- package/dist/state/__tests__/skill-active.test.js +19 -1
- package/dist/state/__tests__/skill-active.test.js.map +1 -1
- package/dist/state/__tests__/workflow-transition.test.js +61 -0
- package/dist/state/__tests__/workflow-transition.test.js.map +1 -1
- package/dist/state/mode-state-context.d.ts +5 -0
- package/dist/state/mode-state-context.d.ts.map +1 -1
- package/dist/state/mode-state-context.js +59 -0
- package/dist/state/mode-state-context.js.map +1 -1
- package/dist/state/operations.d.ts +1 -1
- package/dist/state/operations.d.ts.map +1 -1
- package/dist/state/operations.js +49 -55
- package/dist/state/operations.js.map +1 -1
- package/dist/state/paths.d.ts +1 -1
- package/dist/state/paths.d.ts.map +1 -1
- package/dist/state/paths.js +1 -1
- package/dist/state/paths.js.map +1 -1
- package/dist/state/skill-active.d.ts +13 -1
- package/dist/state/skill-active.d.ts.map +1 -1
- package/dist/state/skill-active.js +43 -4
- package/dist/state/skill-active.js.map +1 -1
- package/dist/state/terminal-normalization.js.map +1 -1
- package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
- package/dist/state/workflow-transition-reconcile.js +20 -4
- package/dist/state/workflow-transition-reconcile.js.map +1 -1
- package/dist/state/workflow-transition.d.ts +1 -1
- package/dist/state/workflow-transition.d.ts.map +1 -1
- package/dist/state/workflow-transition.js.map +1 -1
- package/dist/subagents/__tests__/leader-bootstrap-3181.test.d.ts +2 -0
- package/dist/subagents/__tests__/leader-bootstrap-3181.test.d.ts.map +1 -0
- package/dist/subagents/__tests__/leader-bootstrap-3181.test.js +52 -0
- package/dist/subagents/__tests__/leader-bootstrap-3181.test.js.map +1 -0
- package/dist/subagents/__tests__/tracker.test.js +1550 -10
- package/dist/subagents/__tests__/tracker.test.js.map +1 -1
- package/dist/subagents/role-routing-marker.d.ts +10 -0
- package/dist/subagents/role-routing-marker.d.ts.map +1 -0
- package/dist/subagents/role-routing-marker.js +136 -0
- package/dist/subagents/role-routing-marker.js.map +1 -0
- package/dist/subagents/tracker.d.ts +91 -0
- package/dist/subagents/tracker.d.ts.map +1 -1
- package/dist/subagents/tracker.js +806 -62
- package/dist/subagents/tracker.js.map +1 -1
- package/dist/team/__tests__/api-interop.test.js +91 -1
- package/dist/team/__tests__/api-interop.test.js.map +1 -1
- package/dist/team/__tests__/approved-execution.test.js.map +1 -1
- package/dist/team/__tests__/delivery-e2e-smoke.test.js +52 -10
- package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +1 -1
- package/dist/team/__tests__/idle-nudge.test.js +45 -15
- package/dist/team/__tests__/idle-nudge.test.js.map +1 -1
- package/dist/team/__tests__/mcp-comm.test.js +93 -27
- package/dist/team/__tests__/mcp-comm.test.js.map +1 -1
- package/dist/team/__tests__/model-contract.test.js +341 -4
- package/dist/team/__tests__/model-contract.test.js.map +1 -1
- package/dist/team/__tests__/role-router.test.js.map +1 -1
- package/dist/team/__tests__/runtime-cli.test.js +9 -0
- package/dist/team/__tests__/runtime-cli.test.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +3624 -355
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/scaling.test.js +2516 -118
- package/dist/team/__tests__/scaling.test.js.map +1 -1
- package/dist/team/__tests__/state-root.test.js.map +1 -1
- package/dist/team/__tests__/state.test.js +804 -36
- package/dist/team/__tests__/state.test.js.map +1 -1
- package/dist/team/__tests__/team-ops-contract.test.js +6 -0
- package/dist/team/__tests__/team-ops-contract.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +3664 -969
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/__tests__/tmux-test-fixture.js.map +1 -1
- package/dist/team/__tests__/worker-runtime-identity.test.js +38 -2
- package/dist/team/__tests__/worker-runtime-identity.test.js.map +1 -1
- package/dist/team/__tests__/worktree.test.js +6 -0
- package/dist/team/__tests__/worktree.test.js.map +1 -1
- package/dist/team/api-interop.d.ts +2 -2
- package/dist/team/api-interop.d.ts.map +1 -1
- package/dist/team/api-interop.js +15 -9
- package/dist/team/api-interop.js.map +1 -1
- package/dist/team/commit-hygiene.js.map +1 -1
- package/dist/team/contracts.d.ts +5 -5
- package/dist/team/contracts.d.ts.map +1 -1
- package/dist/team/delivery-log.js.map +1 -1
- package/dist/team/exact-pane.d.ts +23 -0
- package/dist/team/exact-pane.d.ts.map +1 -0
- package/dist/team/exact-pane.js +133 -0
- package/dist/team/exact-pane.js.map +1 -0
- package/dist/team/followup-planner.js.map +1 -1
- package/dist/team/goal-workflow.js.map +1 -1
- package/dist/team/idle-nudge.d.ts +12 -1
- package/dist/team/idle-nudge.d.ts.map +1 -1
- package/dist/team/idle-nudge.js +41 -14
- package/dist/team/idle-nudge.js.map +1 -1
- package/dist/team/model-contract.d.ts +18 -2
- package/dist/team/model-contract.d.ts.map +1 -1
- package/dist/team/model-contract.js +314 -35
- package/dist/team/model-contract.js.map +1 -1
- package/dist/team/orchestrator.js.map +1 -1
- package/dist/team/pane-status.js.map +1 -1
- package/dist/team/phase-controller.js.map +1 -1
- package/dist/team/reminder-intents.d.ts +1 -1
- package/dist/team/reminder-intents.d.ts.map +1 -1
- package/dist/team/reminder-intents.js.map +1 -1
- package/dist/team/runtime-cli.js.map +1 -1
- package/dist/team/runtime.d.ts +1 -0
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +1326 -231
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/scaling.d.ts +22 -8
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +1463 -376
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/state/dispatch-lock.js.map +1 -1
- package/dist/team/state/dispatch.d.ts.map +1 -1
- package/dist/team/state/dispatch.js +26 -8
- package/dist/team/state/dispatch.js.map +1 -1
- package/dist/team/state/events.js.map +1 -1
- package/dist/team/state/locks.d.ts.map +1 -1
- package/dist/team/state/locks.js +61 -13
- package/dist/team/state/locks.js.map +1 -1
- package/dist/team/state/tasks.d.ts.map +1 -1
- package/dist/team/state/tasks.js +4 -3
- package/dist/team/state/tasks.js.map +1 -1
- package/dist/team/state-root.js.map +1 -1
- package/dist/team/state.d.ts +67 -1
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +636 -129
- package/dist/team/state.js.map +1 -1
- package/dist/team/team-identity.d.ts.map +1 -1
- package/dist/team/team-identity.js.map +1 -1
- package/dist/team/team-ops.d.ts +5 -0
- package/dist/team/team-ops.d.ts.map +1 -1
- package/dist/team/team-ops.js +4 -0
- package/dist/team/team-ops.js.map +1 -1
- package/dist/team/tmux-session.d.ts +125 -23
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +1340 -333
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/worker-bootstrap.js.map +1 -1
- package/dist/team/worktree.d.ts.map +1 -1
- package/dist/team/worktree.js +4 -0
- package/dist/team/worktree.js.map +1 -1
- package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
- package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -1
- package/dist/ultragoal/artifacts.d.ts.map +1 -1
- package/dist/ultragoal/artifacts.js +4 -1
- package/dist/ultragoal/artifacts.js.map +1 -1
- package/dist/url-reader/index.js.map +1 -1
- package/dist/utils/__tests__/file-durability.test.d.ts +2 -0
- package/dist/utils/__tests__/file-durability.test.d.ts.map +1 -0
- package/dist/utils/__tests__/file-durability.test.js +57 -0
- package/dist/utils/__tests__/file-durability.test.js.map +1 -0
- package/dist/utils/agents-model-table.js.map +1 -1
- package/dist/utils/file-durability.d.ts +15 -0
- package/dist/utils/file-durability.d.ts.map +1 -0
- package/dist/utils/file-durability.js +37 -0
- package/dist/utils/file-durability.js.map +1 -0
- package/dist/utils/package.js.map +1 -1
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/platform-command.js.map +1 -1
- package/dist/utils/repo-deps.js.map +1 -1
- package/dist/utils/version.js.map +1 -1
- package/dist/verification/__tests__/ci-rust-gates.test.js +1 -1
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js +3 -0
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js.map +1 -1
- package/dist/verification/verifier.js.map +1 -1
- package/dist/visual/constants.d.ts +1 -1
- package/dist/visual/constants.d.ts.map +1 -1
- package/dist/vscode/__tests__/index.test.js.map +1 -1
- package/dist/vscode/index.js.map +1 -1
- package/dist/wiki/__tests__/cjk-tokenize.test.js.map +1 -1
- package/dist/wiki/__tests__/lint.test.js.map +1 -1
- package/dist/wiki/__tests__/query.test.js.map +1 -1
- package/dist/wiki/__tests__/storage.test.js.map +1 -1
- package/dist/wiki/__tests__/test-helpers.d.ts.map +1 -1
- package/dist/wiki/lint.d.ts +4 -1
- package/dist/wiki/lint.d.ts.map +1 -1
- package/dist/wiki/lint.js +3 -2
- package/dist/wiki/lint.js.map +1 -1
- package/dist/wiki/query.js.map +1 -1
- package/dist/wiki/storage.js.map +1 -1
- package/package.json +2 -2
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +24 -0
- package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +10 -5
- package/plugins/oh-my-codex/skills/ralph/SKILL.md +6 -2
- package/plugins/oh-my-codex/skills/ralplan/SKILL.md +6 -2
- package/plugins/oh-my-codex/skills/team/SKILL.md +13 -9
- package/skills/omx-setup/SKILL.md +10 -5
- package/skills/ralph/SKILL.md +6 -2
- package/skills/ralplan/SKILL.md +6 -2
- package/skills/team/SKILL.md +13 -9
- package/src/scripts/__tests__/codex-native-hook.test.ts +20048 -10827
- package/src/scripts/__tests__/fixtures/issue-3138-installed-smoke.ts +734 -0
- package/src/scripts/__tests__/notify-fallback-delivery.test.ts +177 -0
- package/src/scripts/__tests__/notify-state-io.test.ts +73 -0
- package/src/scripts/__tests__/reasoning-artifact-contract.test.ts +129 -0
- package/src/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.ts +78 -0
- package/src/scripts/__tests__/role-intent-durable-recovery-3181.test.ts +60 -0
- package/src/scripts/__tests__/smoke-packed-install.test.ts +1309 -4
- package/src/scripts/codex-native-hook.ts +11429 -1163
- package/src/scripts/notify-fallback-delivery.ts +416 -0
- package/src/scripts/notify-fallback-watcher.ts +216 -155
- package/src/scripts/notify-hook/auto-nudge.ts +113 -14
- package/src/scripts/notify-hook/managed-tmux.ts +149 -12
- package/src/scripts/notify-hook/ralph-session-resume.ts +37 -36
- package/src/scripts/notify-hook/state-io.ts +100 -13
- package/src/scripts/notify-hook/team-dispatch.ts +242 -75
- package/src/scripts/notify-hook/team-leader-nudge.ts +40 -18
- package/src/scripts/notify-hook/team-tmux-guard.ts +366 -39
- package/src/scripts/notify-hook/team-worker-stop.ts +20 -16
- package/src/scripts/notify-hook/team-worker.ts +39 -26
- package/src/scripts/notify-hook/tmux-injection.ts +66 -23
- package/src/scripts/notify-hook/visual-verdict.ts +22 -12
- package/src/scripts/notify-hook.ts +336 -90
- package/src/scripts/smoke-packed-install.ts +5154 -149
|
@@ -6,6 +6,9 @@ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
|
6
6
|
import { tmpdir } from 'node:os';
|
|
7
7
|
import { join } from 'node:path';
|
|
8
8
|
import { buildTmuxSessionName } from '../../cli/index.js';
|
|
9
|
+
import { classifyKeywordInput, recordSkillActivation } from '../keyword-detector.js';
|
|
10
|
+
import { recordNotifySkillActivation, recordNotifySkillActivationNonFatal } from '../../scripts/notify-hook.js';
|
|
11
|
+
import { normalizeSkillActiveState } from '../../scripts/notify-hook/auto-nudge.js';
|
|
9
12
|
const NOTIFY_HOOK_SCRIPT = new URL('../../../dist/scripts/notify-hook.js', import.meta.url);
|
|
10
13
|
const DEEP_INTERVIEW_BLOCKED_APPROVAL_INPUTS = ['yes', 'y', 'proceed', 'continue', 'ok', 'sure', 'go ahead', 'next i should'];
|
|
11
14
|
const NEXT_I_SHOULD_RESPONSE = 'Next I should update the focused tests.';
|
|
@@ -18,6 +21,17 @@ const INHERITED_OMX_ENV_KEYS = [
|
|
|
18
21
|
'OMX_STARTUP_CWD',
|
|
19
22
|
'OMX_ENTRY_PATH',
|
|
20
23
|
];
|
|
24
|
+
describe('notify lifecycle owner normalization', () => {
|
|
25
|
+
it('preserves the stored Codex owner for lifecycle authorization checks', () => {
|
|
26
|
+
const state = normalizeSkillActiveState({
|
|
27
|
+
skill: 'ralph',
|
|
28
|
+
active: true,
|
|
29
|
+
phase: 'executing',
|
|
30
|
+
owner_codex_session_id: 'codex-owner-a',
|
|
31
|
+
});
|
|
32
|
+
assert.equal(state?.owner_codex_session_id, 'codex-owner-a');
|
|
33
|
+
});
|
|
34
|
+
});
|
|
21
35
|
async function withTempWorkingDir(run) {
|
|
22
36
|
const cwd = await mkdtemp(join(tmpdir(), 'omx-auto-nudge-'));
|
|
23
37
|
try {
|
|
@@ -79,6 +93,12 @@ async function writeWorkerIdentityFixture(stateRoot, cwd, teamName, workerName)
|
|
|
79
93
|
worktree_path: cwd,
|
|
80
94
|
team_state_root: stateRoot,
|
|
81
95
|
});
|
|
96
|
+
await writeJson(join(stateRoot, 'team', teamName, 'config.json'), {
|
|
97
|
+
name: teamName,
|
|
98
|
+
tmux_pane_owner_id: `team:${teamName}`,
|
|
99
|
+
hud_pane_id: null,
|
|
100
|
+
workers: [{ name: workerName, pane_id: '%99', pid: 9999 }],
|
|
101
|
+
});
|
|
82
102
|
}
|
|
83
103
|
function escapeRegex(value) {
|
|
84
104
|
return value.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
|
|
@@ -130,6 +150,15 @@ fi
|
|
|
130
150
|
if [[ "\$cmd" == "send-keys" ]]; then
|
|
131
151
|
exit 0
|
|
132
152
|
fi
|
|
153
|
+
if [[ "$cmd" == "show-option" ]]; then
|
|
154
|
+
option="\${@: -1}"
|
|
155
|
+
case "$option" in
|
|
156
|
+
@omx_team_pane_owner_id) echo "\${OMX_TEST_TMUX_OWNER:-team:auto-nudge}" ;;
|
|
157
|
+
@omx_pane_instance_id) echo "\${OMX_TEST_TMUX_PANE_INSTANCE_ID:-}" ;;
|
|
158
|
+
@omx_instance_id) echo "\${OMX_TEST_TMUX_INSTANCE_ID:-}" ;;
|
|
159
|
+
esac
|
|
160
|
+
exit 0
|
|
161
|
+
fi
|
|
133
162
|
if [[ "\$cmd" == "display-message" ]]; then
|
|
134
163
|
target=""
|
|
135
164
|
format=""
|
|
@@ -170,7 +199,7 @@ if [[ "\$cmd" == "list-panes" ]]; then
|
|
|
170
199
|
printf '%%99\t1\tnode\tcodex --model gpt-5\n'
|
|
171
200
|
exit 0
|
|
172
201
|
fi
|
|
173
|
-
|
|
202
|
+
printf '%%99\t0\t%s\n%%100\t0\t10000\n' "\${OMX_TEST_TMUX_PANE_PID:-9999}"
|
|
174
203
|
exit 0
|
|
175
204
|
fi
|
|
176
205
|
exit 0
|
|
@@ -623,7 +652,7 @@ if [[ "$cmd" == "list-panes" ]]; then
|
|
|
623
652
|
printf "%%99\t0\tsh\tbash\n%%100\t1\tnode\tcodex --model gpt-5\n"
|
|
624
653
|
exit 0
|
|
625
654
|
fi
|
|
626
|
-
|
|
655
|
+
printf '%%99\t0\t9999\n%%100\t0\t10000\n'
|
|
627
656
|
exit 0
|
|
628
657
|
fi
|
|
629
658
|
if [[ "$cmd" == "capture-pane" ]]; then
|
|
@@ -740,7 +769,7 @@ if [[ "$cmd" == "list-panes" ]]; then
|
|
|
740
769
|
printf "%%99\t0\tcodex\tcodex\\n%%100\t1\tcodex\tcodex\\n"
|
|
741
770
|
exit 0
|
|
742
771
|
fi
|
|
743
|
-
|
|
772
|
+
printf '%%99\t0\t9999\n%%100\t0\t10000\n'
|
|
744
773
|
exit 0
|
|
745
774
|
fi
|
|
746
775
|
if [[ "$cmd" == "capture-pane" ]]; then
|
|
@@ -858,7 +887,7 @@ if [[ "$cmd" == "list-panes" ]]; then
|
|
|
858
887
|
printf "%%99\t0\tnode\tbash\\n%%100\t1\tnode\tcodex --model gpt-5\\n"
|
|
859
888
|
exit 0
|
|
860
889
|
fi
|
|
861
|
-
|
|
890
|
+
printf '%%99\t0\t9999\n%%100\t0\t10000\n'
|
|
862
891
|
exit 0
|
|
863
892
|
fi
|
|
864
893
|
if [[ "$cmd" == "capture-pane" ]]; then
|
|
@@ -976,7 +1005,7 @@ if [[ "$cmd" == "list-panes" ]]; then
|
|
|
976
1005
|
printf "%%99\t1\tbash\tcodex --model gpt-5\\n%%100\t0\tnode\tcodex --model gpt-5\\n"
|
|
977
1006
|
exit 0
|
|
978
1007
|
fi
|
|
979
|
-
|
|
1008
|
+
printf '%%99\t0\t9999\n%%100\t0\t10000\n'
|
|
980
1009
|
exit 0
|
|
981
1010
|
fi
|
|
982
1011
|
if [[ "$cmd" == "capture-pane" ]]; then
|
|
@@ -1090,7 +1119,7 @@ if [[ "$cmd" == "list-panes" ]]; then
|
|
|
1090
1119
|
printf "%%99\t1\tbash\tcodex --model gpt-5\\n%%100\t0\tbash\tbash\\n"
|
|
1091
1120
|
exit 0
|
|
1092
1121
|
fi
|
|
1093
|
-
|
|
1122
|
+
printf '%%99\t0\t9999\n%%100\t0\t10000\n'
|
|
1094
1123
|
exit 0
|
|
1095
1124
|
fi
|
|
1096
1125
|
if [[ "$cmd" == "capture-pane" ]]; then
|
|
@@ -1171,6 +1200,74 @@ exit 0
|
|
|
1171
1200
|
assert.ok(existsSync(nudgeStatePath), 'worker state root should receive auto-nudge state');
|
|
1172
1201
|
});
|
|
1173
1202
|
});
|
|
1203
|
+
it('does not capture or send in team-worker context without a persisted string owner token', async () => {
|
|
1204
|
+
for (const owner of [undefined, 17]) {
|
|
1205
|
+
await withTempWorkingDir(async (cwd) => {
|
|
1206
|
+
const workerStateRoot = join(cwd, 'leader-state-root');
|
|
1207
|
+
const codexHome = join(cwd, 'codex-home');
|
|
1208
|
+
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1209
|
+
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1210
|
+
await mkdir(workerStateRoot, { recursive: true });
|
|
1211
|
+
await mkdir(codexHome, { recursive: true });
|
|
1212
|
+
await mkdir(fakeBinDir, { recursive: true });
|
|
1213
|
+
await writeWorkerIdentityFixture(workerStateRoot, cwd, 'auto-nudge', 'worker-1');
|
|
1214
|
+
const configPath = join(workerStateRoot, 'team', 'auto-nudge', 'config.json');
|
|
1215
|
+
const config = JSON.parse(await readFile(configPath, 'utf-8'));
|
|
1216
|
+
if (owner === undefined)
|
|
1217
|
+
delete config.tmux_pane_owner_id;
|
|
1218
|
+
else
|
|
1219
|
+
config.tmux_pane_owner_id = owner;
|
|
1220
|
+
await writeJson(configPath, config);
|
|
1221
|
+
await writeJson(join(codexHome, '.omx-config.json'), { autoNudge: { enabled: true, delaySec: 0, stallMs: 0 } });
|
|
1222
|
+
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
1223
|
+
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1224
|
+
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1225
|
+
'last-assistant-message': 'I can continue with the worker follow-up from here.',
|
|
1226
|
+
}, {
|
|
1227
|
+
OMX_TEAM_WORKER: 'auto-nudge/worker-1',
|
|
1228
|
+
OMX_TEAM_STATE_ROOT: workerStateRoot,
|
|
1229
|
+
});
|
|
1230
|
+
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
1231
|
+
const tmuxLog = await readFile(tmuxLogPath, 'utf-8').catch(() => '');
|
|
1232
|
+
assert.doesNotMatch(tmuxLog, /capture-pane|send-keys/, 'missing or malformed persisted owner must not capture or send tmux input');
|
|
1233
|
+
});
|
|
1234
|
+
}
|
|
1235
|
+
});
|
|
1236
|
+
it('fails closed for Team-worker owner takeover, recycled panes, and HUD targets', async () => {
|
|
1237
|
+
for (const scenario of [
|
|
1238
|
+
{ name: 'owner takeover', env: { OMX_TEST_TMUX_OWNER: 'team:foreign' }, hudPaneId: null },
|
|
1239
|
+
{ name: 'recycled pane', env: { OMX_TEST_TMUX_PANE_PID: '10001' }, hudPaneId: null },
|
|
1240
|
+
{ name: 'HUD target', env: {}, hudPaneId: '%99' },
|
|
1241
|
+
]) {
|
|
1242
|
+
await withTempWorkingDir(async (cwd) => {
|
|
1243
|
+
const workerStateRoot = join(cwd, 'leader-state-root');
|
|
1244
|
+
const codexHome = join(cwd, 'codex-home');
|
|
1245
|
+
const fakeBinDir = join(cwd, 'fake-bin');
|
|
1246
|
+
const tmuxLogPath = join(cwd, 'tmux.log');
|
|
1247
|
+
await mkdir(workerStateRoot, { recursive: true });
|
|
1248
|
+
await mkdir(codexHome, { recursive: true });
|
|
1249
|
+
await mkdir(fakeBinDir, { recursive: true });
|
|
1250
|
+
await writeWorkerIdentityFixture(workerStateRoot, cwd, 'auto-nudge', 'worker-1');
|
|
1251
|
+
const configPath = join(workerStateRoot, 'team', 'auto-nudge', 'config.json');
|
|
1252
|
+
const config = JSON.parse(await readFile(configPath, 'utf-8'));
|
|
1253
|
+
config.hud_pane_id = scenario.hudPaneId;
|
|
1254
|
+
await writeJson(configPath, config);
|
|
1255
|
+
await writeJson(join(codexHome, '.omx-config.json'), { autoNudge: { enabled: true, delaySec: 0, stallMs: 0 } });
|
|
1256
|
+
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(tmuxLogPath));
|
|
1257
|
+
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
1258
|
+
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
1259
|
+
'last-assistant-message': 'I can continue with the worker follow-up from here.',
|
|
1260
|
+
}, {
|
|
1261
|
+
OMX_TEAM_WORKER: 'auto-nudge/worker-1',
|
|
1262
|
+
OMX_TEAM_STATE_ROOT: workerStateRoot,
|
|
1263
|
+
...scenario.env,
|
|
1264
|
+
});
|
|
1265
|
+
assert.equal(result.status, 0, `${scenario.name}: hook failed: ${result.stderr || result.stdout}`);
|
|
1266
|
+
const tmuxLog = await readFile(tmuxLogPath, 'utf-8');
|
|
1267
|
+
assert.doesNotMatch(tmuxLog, defaultAutoNudgePattern('%99'), `${scenario.name} must not inject Team input`);
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1270
|
+
});
|
|
1174
1271
|
it('fails closed in team-worker context when the worker state root lacks a valid identity', async () => {
|
|
1175
1272
|
await withTempWorkingDir(async (cwd) => {
|
|
1176
1273
|
const localStateRoot = join(cwd, '.omx', 'state');
|
|
@@ -1280,8 +1377,12 @@ fi
|
|
|
1280
1377
|
if [[ "$cmd" == "send-keys" ]]; then
|
|
1281
1378
|
exit 0
|
|
1282
1379
|
fi
|
|
1380
|
+
if [[ "$cmd" == "show-option" ]]; then
|
|
1381
|
+
echo "team:auto-nudge"
|
|
1382
|
+
exit 0
|
|
1383
|
+
fi
|
|
1283
1384
|
if [[ "$cmd" == "list-panes" ]]; then
|
|
1284
|
-
|
|
1385
|
+
printf '%%99\t0\t9999\n%%100\t0\t10000\n'
|
|
1285
1386
|
exit 0
|
|
1286
1387
|
fi
|
|
1287
1388
|
exit 0
|
|
@@ -1400,7 +1501,7 @@ if [[ "$cmd" == "send-keys" ]]; then
|
|
|
1400
1501
|
exit 0
|
|
1401
1502
|
fi
|
|
1402
1503
|
if [[ "$cmd" == "list-panes" ]]; then
|
|
1403
|
-
|
|
1504
|
+
printf '%%99\t0\t9999\n%%100\t0\t10000\n'
|
|
1404
1505
|
exit 0
|
|
1405
1506
|
fi
|
|
1406
1507
|
exit 0
|
|
@@ -1517,7 +1618,7 @@ if [[ "$cmd" == "list-panes" ]]; then
|
|
|
1517
1618
|
printf "%%99\t1\tsh\tbash\\n%%100\t0\tnode\tcodex --model gpt-5\\n"
|
|
1518
1619
|
exit 0
|
|
1519
1620
|
fi
|
|
1520
|
-
|
|
1621
|
+
printf '%%99\t0\t9999\n%%100\t0\t10000\n'
|
|
1521
1622
|
exit 0
|
|
1522
1623
|
fi
|
|
1523
1624
|
exit 0
|
|
@@ -2048,6 +2149,656 @@ exit 0
|
|
|
2048
2149
|
assert.equal(autopilotState.turn_id, 'turn-later-autopilot-start');
|
|
2049
2150
|
});
|
|
2050
2151
|
});
|
|
2152
|
+
it('shares immutable classification across the terminal replay activation matrix', async () => {
|
|
2153
|
+
await withTempWorkingDir(async (cwd) => {
|
|
2154
|
+
const stateDir = join(cwd, '.omx', 'state');
|
|
2155
|
+
const sessionId = 'sess-notify-replay-matrix';
|
|
2156
|
+
const sessionStateDir = join(stateDir, 'sessions', sessionId);
|
|
2157
|
+
const terminalThreadId = 'thread-autopilot-complete';
|
|
2158
|
+
const terminalTurnId = 'turn-autopilot-complete';
|
|
2159
|
+
const terminalPayload = {
|
|
2160
|
+
type: 'agent-turn-complete',
|
|
2161
|
+
'thread-id': terminalThreadId,
|
|
2162
|
+
'turn-id': terminalTurnId,
|
|
2163
|
+
'last-assistant-message': 'Autopilot complete.',
|
|
2164
|
+
};
|
|
2165
|
+
await mkdir(sessionStateDir, { recursive: true });
|
|
2166
|
+
await writeJson(join(sessionStateDir, 'autopilot-state.json'), {
|
|
2167
|
+
mode: 'autopilot',
|
|
2168
|
+
active: false,
|
|
2169
|
+
current_phase: 'complete',
|
|
2170
|
+
completed_at: '2026-05-31T20:24:39.005Z',
|
|
2171
|
+
session_id: sessionId,
|
|
2172
|
+
thread_id: terminalThreadId,
|
|
2173
|
+
turn_id: terminalTurnId,
|
|
2174
|
+
});
|
|
2175
|
+
const terminalAutopilotStatePath = join(sessionStateDir, 'autopilot-state.json');
|
|
2176
|
+
const terminalSessionSkillStatePath = join(sessionStateDir, 'skill-active-state.json');
|
|
2177
|
+
const terminalRootSkillStatePath = join(stateDir, 'skill-active-state.json');
|
|
2178
|
+
for (const text of ['$autopilot replay task café\r\n', 'autopilot mode — replay café']) {
|
|
2179
|
+
const bytesBefore = Buffer.from(text, 'utf8');
|
|
2180
|
+
const terminalStateBefore = await readFile(terminalAutopilotStatePath);
|
|
2181
|
+
let classifierCalls = 0;
|
|
2182
|
+
let classifierText = '';
|
|
2183
|
+
let writerCalls = 0;
|
|
2184
|
+
const result = await recordNotifySkillActivation({
|
|
2185
|
+
stateDir,
|
|
2186
|
+
sourceCwd: cwd,
|
|
2187
|
+
text,
|
|
2188
|
+
sessionId,
|
|
2189
|
+
threadId: terminalThreadId,
|
|
2190
|
+
turnId: terminalTurnId,
|
|
2191
|
+
payload: terminalPayload,
|
|
2192
|
+
}, {
|
|
2193
|
+
classifyKeywordInput: (input) => {
|
|
2194
|
+
classifierCalls += 1;
|
|
2195
|
+
classifierText = input;
|
|
2196
|
+
return classifyKeywordInput(input);
|
|
2197
|
+
},
|
|
2198
|
+
recordSkillActivation: async () => {
|
|
2199
|
+
writerCalls += 1;
|
|
2200
|
+
return null;
|
|
2201
|
+
},
|
|
2202
|
+
});
|
|
2203
|
+
assert.equal(classifierCalls, 1, 'notify should classify each latest input once');
|
|
2204
|
+
assert.equal(writerCalls, 0, 'same-turn terminal replay must not reach the writer');
|
|
2205
|
+
assert.equal(result, null);
|
|
2206
|
+
assert.deepEqual(Buffer.from(classifierText, 'utf8'), bytesBefore, 'classifier must receive the original input bytes');
|
|
2207
|
+
assert.deepEqual(await readFile(terminalAutopilotStatePath), terminalStateBefore, 'same-turn replay must preserve terminal detail bytes');
|
|
2208
|
+
assert.equal(existsSync(terminalSessionSkillStatePath), false, 'same-turn replay must not create session canonical state');
|
|
2209
|
+
assert.equal(existsSync(terminalRootSkillStatePath), false, 'same-turn replay must not create root canonical state');
|
|
2210
|
+
}
|
|
2211
|
+
const markedSessionId = 'sess-notify-terminal-marked-answer';
|
|
2212
|
+
const markedThreadId = 'thread-notify-terminal-marked-answer';
|
|
2213
|
+
const markedTurnId = 'turn-notify-terminal-marked-answer';
|
|
2214
|
+
const markedSessionDir = join(stateDir, 'sessions', markedSessionId);
|
|
2215
|
+
const markedSkillPath = join(markedSessionDir, 'skill-active-state.json');
|
|
2216
|
+
const markedDetailPath = join(markedSessionDir, 'autopilot-state.json');
|
|
2217
|
+
await mkdir(markedSessionDir, { recursive: true });
|
|
2218
|
+
await writeJson(markedSkillPath, {
|
|
2219
|
+
version: 1,
|
|
2220
|
+
active: true,
|
|
2221
|
+
skill: 'autopilot',
|
|
2222
|
+
keyword: '$autopilot',
|
|
2223
|
+
phase: 'completing',
|
|
2224
|
+
activated_at: '2026-05-31T20:24:39.005Z',
|
|
2225
|
+
updated_at: '2026-05-31T20:24:39.005Z',
|
|
2226
|
+
session_id: markedSessionId,
|
|
2227
|
+
active_skills: [{ skill: 'autopilot', phase: 'completing', active: true, session_id: markedSessionId }],
|
|
2228
|
+
});
|
|
2229
|
+
await writeJson(markedDetailPath, {
|
|
2230
|
+
mode: 'autopilot',
|
|
2231
|
+
active: false,
|
|
2232
|
+
current_phase: 'complete',
|
|
2233
|
+
completed_at: '2026-05-31T20:24:39.005Z',
|
|
2234
|
+
session_id: markedSessionId,
|
|
2235
|
+
});
|
|
2236
|
+
const markedSkillBefore = await readFile(markedSkillPath);
|
|
2237
|
+
const markedDetailBefore = await readFile(markedDetailPath);
|
|
2238
|
+
let markedWriterCalls = 0;
|
|
2239
|
+
const markedResult = await recordNotifySkillActivation({
|
|
2240
|
+
stateDir,
|
|
2241
|
+
sourceCwd: cwd,
|
|
2242
|
+
text: '[omx question answered] yes',
|
|
2243
|
+
sessionId: markedSessionId,
|
|
2244
|
+
threadId: markedThreadId,
|
|
2245
|
+
turnId: markedTurnId,
|
|
2246
|
+
payload: {
|
|
2247
|
+
type: 'agent-turn-complete',
|
|
2248
|
+
'thread-id': markedThreadId,
|
|
2249
|
+
'turn-id': markedTurnId,
|
|
2250
|
+
'last-assistant-message': 'Autopilot complete.',
|
|
2251
|
+
},
|
|
2252
|
+
}, {
|
|
2253
|
+
recordSkillActivation: async (input) => {
|
|
2254
|
+
markedWriterCalls += 1;
|
|
2255
|
+
return recordSkillActivation(input);
|
|
2256
|
+
},
|
|
2257
|
+
});
|
|
2258
|
+
assert.equal(markedWriterCalls, 1);
|
|
2259
|
+
assert.equal(markedResult, null);
|
|
2260
|
+
assert.deepEqual(await readFile(markedSkillPath), markedSkillBefore);
|
|
2261
|
+
assert.deepEqual(await readFile(markedDetailPath), markedDetailBefore);
|
|
2262
|
+
for (const orderedCase of [
|
|
2263
|
+
{ text: '$ralplan $autopilot plan this change', skill: 'ralplan' },
|
|
2264
|
+
{ text: '$ralph $autopilot ship this change', skill: 'ralph' },
|
|
2265
|
+
]) {
|
|
2266
|
+
const orderedSessionId = `sess-notify-primary-${orderedCase.skill}`;
|
|
2267
|
+
const orderedThreadId = `thread-notify-primary-${orderedCase.skill}`;
|
|
2268
|
+
const orderedTurnId = `turn-notify-primary-${orderedCase.skill}`;
|
|
2269
|
+
const orderedSessionDir = join(stateDir, 'sessions', orderedSessionId);
|
|
2270
|
+
await mkdir(orderedSessionDir, { recursive: true });
|
|
2271
|
+
await writeJson(join(orderedSessionDir, 'autopilot-state.json'), {
|
|
2272
|
+
mode: 'autopilot',
|
|
2273
|
+
active: false,
|
|
2274
|
+
current_phase: 'complete',
|
|
2275
|
+
completed_at: '2026-05-31T20:24:39.005Z',
|
|
2276
|
+
session_id: orderedSessionId,
|
|
2277
|
+
thread_id: orderedThreadId,
|
|
2278
|
+
turn_id: orderedTurnId,
|
|
2279
|
+
});
|
|
2280
|
+
const orderedAutopilotPath = join(orderedSessionDir, 'autopilot-state.json');
|
|
2281
|
+
const orderedAutopilotBefore = await readFile(orderedAutopilotPath);
|
|
2282
|
+
await writeJson(join(orderedSessionDir, 'skill-active-state.json'), {
|
|
2283
|
+
version: 1,
|
|
2284
|
+
active: true,
|
|
2285
|
+
skill: 'autopilot',
|
|
2286
|
+
keyword: '$autopilot',
|
|
2287
|
+
phase: 'completing',
|
|
2288
|
+
activated_at: '2026-05-31T20:24:39.005Z',
|
|
2289
|
+
updated_at: '2026-05-31T20:24:39.005Z',
|
|
2290
|
+
session_id: orderedSessionId,
|
|
2291
|
+
thread_id: orderedThreadId,
|
|
2292
|
+
turn_id: orderedTurnId,
|
|
2293
|
+
active_skills: [{
|
|
2294
|
+
skill: 'autopilot',
|
|
2295
|
+
phase: 'completing',
|
|
2296
|
+
active: true,
|
|
2297
|
+
session_id: orderedSessionId,
|
|
2298
|
+
thread_id: orderedThreadId,
|
|
2299
|
+
turn_id: orderedTurnId,
|
|
2300
|
+
}],
|
|
2301
|
+
});
|
|
2302
|
+
let orderedWriterCalls = 0;
|
|
2303
|
+
const orderedResult = await recordNotifySkillActivation({
|
|
2304
|
+
stateDir,
|
|
2305
|
+
sourceCwd: cwd,
|
|
2306
|
+
text: orderedCase.text,
|
|
2307
|
+
sessionId: orderedSessionId,
|
|
2308
|
+
threadId: orderedThreadId,
|
|
2309
|
+
turnId: orderedTurnId,
|
|
2310
|
+
payload: {
|
|
2311
|
+
type: 'agent-turn-complete',
|
|
2312
|
+
'thread-id': orderedThreadId,
|
|
2313
|
+
'turn-id': orderedTurnId,
|
|
2314
|
+
'last-assistant-message': 'Autopilot complete.',
|
|
2315
|
+
},
|
|
2316
|
+
}, {
|
|
2317
|
+
recordSkillActivation: async (input) => {
|
|
2318
|
+
orderedWriterCalls += 1;
|
|
2319
|
+
return recordSkillActivation(input);
|
|
2320
|
+
},
|
|
2321
|
+
});
|
|
2322
|
+
assert.equal(orderedWriterCalls, 1, `leading ${orderedCase.skill} must reach the writer`);
|
|
2323
|
+
assert.equal(orderedResult?.skill, orderedCase.skill, orderedCase.text);
|
|
2324
|
+
assert.equal(orderedResult?.active, true, orderedCase.text);
|
|
2325
|
+
assert.equal(existsSync(join(orderedSessionDir, 'skill-active-state.json')), true, orderedCase.text);
|
|
2326
|
+
assert.equal(orderedResult?.active_skills?.some((entry) => entry.skill === 'autopilot'), false, orderedCase.text);
|
|
2327
|
+
assert.deepEqual(await readFile(orderedAutopilotPath), orderedAutopilotBefore, orderedCase.text);
|
|
2328
|
+
}
|
|
2329
|
+
const filteredSessionId = 'sess-notify-disabled-team-terminal-autopilot';
|
|
2330
|
+
const filteredThreadId = 'thread-notify-disabled-team-terminal-autopilot';
|
|
2331
|
+
const filteredTurnId = 'turn-notify-disabled-team-terminal-autopilot';
|
|
2332
|
+
const filteredSessionDir = join(stateDir, 'sessions', filteredSessionId);
|
|
2333
|
+
const filteredAutopilotPath = join(filteredSessionDir, 'autopilot-state.json');
|
|
2334
|
+
await mkdir(filteredSessionDir, { recursive: true });
|
|
2335
|
+
await writeJson(filteredAutopilotPath, {
|
|
2336
|
+
mode: 'autopilot',
|
|
2337
|
+
active: false,
|
|
2338
|
+
current_phase: 'complete',
|
|
2339
|
+
completed_at: '2026-05-31T20:24:39.005Z',
|
|
2340
|
+
session_id: filteredSessionId,
|
|
2341
|
+
thread_id: filteredThreadId,
|
|
2342
|
+
turn_id: filteredTurnId,
|
|
2343
|
+
});
|
|
2344
|
+
const filteredAutopilotBefore = await readFile(filteredAutopilotPath);
|
|
2345
|
+
const previousTeamMode = process.env.OMX_TEAM_MODE;
|
|
2346
|
+
process.env.OMX_TEAM_MODE = 'disabled';
|
|
2347
|
+
try {
|
|
2348
|
+
const filteredResult = await recordNotifySkillActivation({
|
|
2349
|
+
stateDir,
|
|
2350
|
+
sourceCwd: cwd,
|
|
2351
|
+
text: '$team $autopilot retry',
|
|
2352
|
+
sessionId: filteredSessionId,
|
|
2353
|
+
threadId: filteredThreadId,
|
|
2354
|
+
turnId: filteredTurnId,
|
|
2355
|
+
payload: {
|
|
2356
|
+
type: 'agent-turn-complete',
|
|
2357
|
+
'thread-id': filteredThreadId,
|
|
2358
|
+
'turn-id': filteredTurnId,
|
|
2359
|
+
'last-assistant-message': 'Autopilot complete.',
|
|
2360
|
+
},
|
|
2361
|
+
});
|
|
2362
|
+
assert.equal(filteredResult, null);
|
|
2363
|
+
assert.deepEqual(await readFile(filteredAutopilotPath), filteredAutopilotBefore);
|
|
2364
|
+
assert.equal(existsSync(join(filteredSessionDir, 'skill-active-state.json')), false);
|
|
2365
|
+
assert.equal(existsSync(join(stateDir, 'skill-active-state.json')), false);
|
|
2366
|
+
}
|
|
2367
|
+
finally {
|
|
2368
|
+
if (previousTeamMode === undefined)
|
|
2369
|
+
delete process.env.OMX_TEAM_MODE;
|
|
2370
|
+
else
|
|
2371
|
+
process.env.OMX_TEAM_MODE = previousTeamMode;
|
|
2372
|
+
}
|
|
2373
|
+
const restartText = '$autopilot new task — café';
|
|
2374
|
+
const restartBytes = Buffer.from(restartText, 'utf8');
|
|
2375
|
+
let restartClassification;
|
|
2376
|
+
let writerClassification;
|
|
2377
|
+
let writerResult;
|
|
2378
|
+
let writerCalls = 0;
|
|
2379
|
+
let writerText = '';
|
|
2380
|
+
const restartResult = await recordNotifySkillActivation({
|
|
2381
|
+
stateDir,
|
|
2382
|
+
sourceCwd: cwd,
|
|
2383
|
+
text: restartText,
|
|
2384
|
+
sessionId,
|
|
2385
|
+
threadId: terminalThreadId,
|
|
2386
|
+
turnId: 'turn-autopilot-restart',
|
|
2387
|
+
payload: {
|
|
2388
|
+
...terminalPayload,
|
|
2389
|
+
'turn-id': 'turn-autopilot-restart',
|
|
2390
|
+
'last-assistant-message': 'Autopilot complete text from a prior turn.',
|
|
2391
|
+
},
|
|
2392
|
+
}, {
|
|
2393
|
+
classifyKeywordInput: (input) => {
|
|
2394
|
+
restartClassification = classifyKeywordInput(input);
|
|
2395
|
+
return restartClassification;
|
|
2396
|
+
},
|
|
2397
|
+
recordSkillActivation: async (input) => {
|
|
2398
|
+
writerCalls += 1;
|
|
2399
|
+
writerText = input.text;
|
|
2400
|
+
writerClassification = input.classification;
|
|
2401
|
+
writerResult = await recordSkillActivation(input);
|
|
2402
|
+
return writerResult;
|
|
2403
|
+
},
|
|
2404
|
+
});
|
|
2405
|
+
assert.equal(writerCalls, 1, 'a different turn must reach the writer');
|
|
2406
|
+
assert.strictEqual(writerClassification, restartClassification, 'writer must receive the classifier object by identity');
|
|
2407
|
+
assert.strictEqual(restartResult, writerResult, 'notify must return the writer result unchanged');
|
|
2408
|
+
assert.deepEqual(Buffer.from(writerText, 'utf8'), restartBytes, 'writer must receive the original input bytes');
|
|
2409
|
+
const reactivatedAutopilot = JSON.parse(await readFile(join(sessionStateDir, 'autopilot-state.json'), 'utf-8'));
|
|
2410
|
+
assert.equal(reactivatedAutopilot.active, true);
|
|
2411
|
+
assert.equal(reactivatedAutopilot.current_phase, 'deep-interview');
|
|
2412
|
+
assert.equal(reactivatedAutopilot.turn_id, 'turn-autopilot-restart');
|
|
2413
|
+
const sessionSkillStatePath = join(sessionStateDir, 'skill-active-state.json');
|
|
2414
|
+
const autopilotStatePath = join(sessionStateDir, 'autopilot-state.json');
|
|
2415
|
+
const rootSkillStatePath = join(stateDir, 'skill-active-state.json');
|
|
2416
|
+
for (const [index, text] of ['do not start $autopilot — café', '"$autopilot" — quoted only'].entries()) {
|
|
2417
|
+
const bytesBefore = Buffer.from(text, 'utf8');
|
|
2418
|
+
const skillStateBefore = await readFile(sessionSkillStatePath);
|
|
2419
|
+
const autopilotStateBefore = await readFile(autopilotStatePath);
|
|
2420
|
+
let rejectedClassification;
|
|
2421
|
+
let rejectedWriterClassification;
|
|
2422
|
+
let rejectedWriterResult;
|
|
2423
|
+
let rejectedWriterCalls = 0;
|
|
2424
|
+
let rejectedWriterText = '';
|
|
2425
|
+
const rejectedResult = await recordNotifySkillActivation({
|
|
2426
|
+
stateDir,
|
|
2427
|
+
sourceCwd: cwd,
|
|
2428
|
+
text,
|
|
2429
|
+
sessionId,
|
|
2430
|
+
threadId: terminalThreadId,
|
|
2431
|
+
turnId: `turn-rejected-${index}`,
|
|
2432
|
+
payload: {
|
|
2433
|
+
type: 'agent-turn-complete',
|
|
2434
|
+
'thread-id': terminalThreadId,
|
|
2435
|
+
'turn-id': `turn-rejected-${index}`,
|
|
2436
|
+
'last-assistant-message': 'Normal nonterminal reply.',
|
|
2437
|
+
},
|
|
2438
|
+
}, {
|
|
2439
|
+
classifyKeywordInput: (input) => {
|
|
2440
|
+
rejectedClassification = classifyKeywordInput(input);
|
|
2441
|
+
return rejectedClassification;
|
|
2442
|
+
},
|
|
2443
|
+
recordSkillActivation: async (input) => {
|
|
2444
|
+
rejectedWriterCalls += 1;
|
|
2445
|
+
rejectedWriterText = input.text;
|
|
2446
|
+
rejectedWriterClassification = input.classification;
|
|
2447
|
+
rejectedWriterResult = await recordSkillActivation(input);
|
|
2448
|
+
return rejectedWriterResult;
|
|
2449
|
+
},
|
|
2450
|
+
});
|
|
2451
|
+
assert.equal(rejectedWriterCalls, 1, 'rejected nonterminal text must still reach the real writer once');
|
|
2452
|
+
assert.strictEqual(rejectedResult, rejectedWriterResult, 'notify must return the real writer result unchanged');
|
|
2453
|
+
assert.equal(rejectedResult, null);
|
|
2454
|
+
assert.strictEqual(rejectedWriterClassification, rejectedClassification, 'rejected input must retain classification identity');
|
|
2455
|
+
assert.deepEqual(rejectedClassification?.matches, [], 'negated and quoted text must not activate a workflow');
|
|
2456
|
+
assert.deepEqual(Buffer.from(rejectedWriterText, 'utf8'), bytesBefore, 'writer must receive rejected input bytes unchanged');
|
|
2457
|
+
assert.deepEqual(await readFile(sessionSkillStatePath), skillStateBefore, 'rejected input must preserve canonical state bytes');
|
|
2458
|
+
assert.deepEqual(await readFile(autopilotStatePath), autopilotStateBefore, 'rejected input must preserve detail state bytes');
|
|
2459
|
+
assert.equal(existsSync(rootSkillStatePath), false, 'rejected session input must not create root canonical state');
|
|
2460
|
+
}
|
|
2461
|
+
});
|
|
2462
|
+
});
|
|
2463
|
+
it('G1a-N preserves ordered multi-skill classification and seeds only the ralplan primary when Team is enabled', async () => {
|
|
2464
|
+
await withTempWorkingDir(async (cwd) => {
|
|
2465
|
+
const stateDir = join(cwd, '.omx', 'state');
|
|
2466
|
+
const sessionId = 'sess-g1a-notify-ordered';
|
|
2467
|
+
const threadId = 'thread-g1a-notify-ordered';
|
|
2468
|
+
const turnId = 'turn-g1a-notify-ordered';
|
|
2469
|
+
const sessionDir = join(stateDir, 'sessions', sessionId);
|
|
2470
|
+
const text = '$ralplan, $autopilot; $team';
|
|
2471
|
+
let classification;
|
|
2472
|
+
let writerClassification;
|
|
2473
|
+
let writerCalls = 0;
|
|
2474
|
+
const previousTeamMode = process.env.OMX_TEAM_MODE;
|
|
2475
|
+
process.env.OMX_TEAM_MODE = 'enabled';
|
|
2476
|
+
try {
|
|
2477
|
+
const result = await recordNotifySkillActivation({
|
|
2478
|
+
stateDir,
|
|
2479
|
+
sourceCwd: cwd,
|
|
2480
|
+
text,
|
|
2481
|
+
sessionId,
|
|
2482
|
+
threadId,
|
|
2483
|
+
turnId,
|
|
2484
|
+
payload: { type: 'agent-turn-complete', 'thread-id': threadId, 'turn-id': turnId },
|
|
2485
|
+
}, {
|
|
2486
|
+
classifyKeywordInput: (input) => {
|
|
2487
|
+
classification = classifyKeywordInput(input);
|
|
2488
|
+
return classification;
|
|
2489
|
+
},
|
|
2490
|
+
recordSkillActivation: async (input) => {
|
|
2491
|
+
writerCalls += 1;
|
|
2492
|
+
writerClassification = input.classification;
|
|
2493
|
+
return recordSkillActivation(input);
|
|
2494
|
+
},
|
|
2495
|
+
});
|
|
2496
|
+
assert.equal(writerCalls, 1);
|
|
2497
|
+
assert.strictEqual(writerClassification, classification, 'notify must pass the ordered classifier output to the writer');
|
|
2498
|
+
assert.deepEqual(classification?.matches.map((match) => match.skill), ['ralplan', 'autopilot', 'team']);
|
|
2499
|
+
assert.equal(result?.skill, 'ralplan');
|
|
2500
|
+
assert.deepEqual(result?.deferred_skills, ['autopilot', 'team']);
|
|
2501
|
+
assert.deepEqual(result?.active_skills?.map((entry) => entry.skill), ['ralplan']);
|
|
2502
|
+
assert.equal(existsSync(join(sessionDir, 'ralplan-state.json')), true);
|
|
2503
|
+
assert.equal(existsSync(join(sessionDir, 'autopilot-state.json')), false);
|
|
2504
|
+
assert.equal(existsSync(join(stateDir, 'team-state.json')), false);
|
|
2505
|
+
}
|
|
2506
|
+
finally {
|
|
2507
|
+
if (previousTeamMode === undefined)
|
|
2508
|
+
delete process.env.OMX_TEAM_MODE;
|
|
2509
|
+
else
|
|
2510
|
+
process.env.OMX_TEAM_MODE = previousTeamMode;
|
|
2511
|
+
}
|
|
2512
|
+
});
|
|
2513
|
+
});
|
|
2514
|
+
it('G1c-N deduplicates exact canonical and alias Autopilot invocations across classifier, writer, canonical state, and detail state', async () => {
|
|
2515
|
+
await withTempWorkingDir(async (cwd) => {
|
|
2516
|
+
const stateDir = join(cwd, '.omx', 'state');
|
|
2517
|
+
const sessionId = 'sess-g1c-notify-duplicate';
|
|
2518
|
+
const threadId = 'thread-g1c-notify-duplicate';
|
|
2519
|
+
const turnId = 'turn-g1c-notify-duplicate';
|
|
2520
|
+
const sessionDir = join(stateDir, 'sessions', sessionId);
|
|
2521
|
+
const text = '$autopilot $oh-my-codex:autopilot build it';
|
|
2522
|
+
let classification;
|
|
2523
|
+
let writerClassification;
|
|
2524
|
+
let writerCalls = 0;
|
|
2525
|
+
const result = await recordNotifySkillActivation({
|
|
2526
|
+
stateDir,
|
|
2527
|
+
sourceCwd: cwd,
|
|
2528
|
+
text,
|
|
2529
|
+
sessionId,
|
|
2530
|
+
threadId,
|
|
2531
|
+
turnId,
|
|
2532
|
+
payload: { type: 'agent-turn-complete', 'thread-id': threadId, 'turn-id': turnId },
|
|
2533
|
+
}, {
|
|
2534
|
+
classifyKeywordInput: (input) => {
|
|
2535
|
+
classification = classifyKeywordInput(input);
|
|
2536
|
+
return classification;
|
|
2537
|
+
},
|
|
2538
|
+
recordSkillActivation: async (input) => {
|
|
2539
|
+
writerCalls += 1;
|
|
2540
|
+
writerClassification = input.classification;
|
|
2541
|
+
return recordSkillActivation(input);
|
|
2542
|
+
},
|
|
2543
|
+
});
|
|
2544
|
+
assert.equal(writerCalls, 1);
|
|
2545
|
+
assert.strictEqual(writerClassification, classification, 'writer must receive the deduplicated classifier output');
|
|
2546
|
+
assert.deepEqual(classification?.matches.map((match) => match.skill), ['autopilot']);
|
|
2547
|
+
assert.equal(result?.skill, 'autopilot');
|
|
2548
|
+
assert.deepEqual(result?.deferred_skills ?? [], []);
|
|
2549
|
+
assert.deepEqual(result?.active_skills?.map((entry) => entry.skill), ['autopilot']);
|
|
2550
|
+
const canonical = JSON.parse(await readFile(join(sessionDir, 'skill-active-state.json'), 'utf8'));
|
|
2551
|
+
assert.deepEqual(canonical.active_skills?.map((entry) => entry.skill), ['autopilot']);
|
|
2552
|
+
assert.equal(existsSync(join(sessionDir, 'autopilot-state.json')), true);
|
|
2553
|
+
});
|
|
2554
|
+
});
|
|
2555
|
+
// Notify Stop is N/A: it has no user-prompt activation transport to replay.
|
|
2556
|
+
it('G1b-N filters disabled Team before suppressing an exact same-turn terminal Autopilot replay without changing state bytes', async () => {
|
|
2557
|
+
await withTempWorkingDir(async (cwd) => {
|
|
2558
|
+
const stateDir = join(cwd, '.omx', 'state');
|
|
2559
|
+
const sessionId = 'sess-g1b-notify-terminal';
|
|
2560
|
+
const threadId = 'thread-g1b-notify-terminal';
|
|
2561
|
+
const turnId = 'turn-g1b-notify-terminal';
|
|
2562
|
+
const sessionDir = join(stateDir, 'sessions', sessionId);
|
|
2563
|
+
const sessionSkillPath = join(sessionDir, 'skill-active-state.json');
|
|
2564
|
+
const sessionAutopilotPath = join(sessionDir, 'autopilot-state.json');
|
|
2565
|
+
const rootSkillPath = join(stateDir, 'skill-active-state.json');
|
|
2566
|
+
const rootAutopilotPath = join(stateDir, 'autopilot-state.json');
|
|
2567
|
+
const seededPaths = [sessionSkillPath, sessionAutopilotPath, rootSkillPath, rootAutopilotPath];
|
|
2568
|
+
await mkdir(sessionDir, { recursive: true });
|
|
2569
|
+
await writeJson(sessionSkillPath, {
|
|
2570
|
+
version: 1,
|
|
2571
|
+
active: true,
|
|
2572
|
+
skill: 'autopilot',
|
|
2573
|
+
keyword: '$autopilot',
|
|
2574
|
+
phase: 'completing',
|
|
2575
|
+
session_id: sessionId,
|
|
2576
|
+
thread_id: threadId,
|
|
2577
|
+
turn_id: turnId,
|
|
2578
|
+
active_skills: [{ skill: 'autopilot', phase: 'completing', active: true, session_id: sessionId, thread_id: threadId, turn_id: turnId }],
|
|
2579
|
+
});
|
|
2580
|
+
await writeJson(sessionAutopilotPath, {
|
|
2581
|
+
mode: 'autopilot',
|
|
2582
|
+
active: false,
|
|
2583
|
+
current_phase: 'complete',
|
|
2584
|
+
completed_at: '2026-05-31T20:24:39.005Z',
|
|
2585
|
+
session_id: sessionId,
|
|
2586
|
+
thread_id: threadId,
|
|
2587
|
+
turn_id: turnId,
|
|
2588
|
+
});
|
|
2589
|
+
await writeJson(rootSkillPath, {
|
|
2590
|
+
version: 1,
|
|
2591
|
+
active: true,
|
|
2592
|
+
skill: 'autopilot',
|
|
2593
|
+
keyword: '$autopilot',
|
|
2594
|
+
phase: 'completing',
|
|
2595
|
+
scope: 'root-copy',
|
|
2596
|
+
session_id: sessionId,
|
|
2597
|
+
thread_id: threadId,
|
|
2598
|
+
turn_id: turnId,
|
|
2599
|
+
});
|
|
2600
|
+
await writeJson(rootAutopilotPath, {
|
|
2601
|
+
mode: 'autopilot',
|
|
2602
|
+
active: false,
|
|
2603
|
+
current_phase: 'complete',
|
|
2604
|
+
completed_at: '2026-05-31T20:24:39.005Z',
|
|
2605
|
+
scope: 'root-copy',
|
|
2606
|
+
session_id: sessionId,
|
|
2607
|
+
thread_id: threadId,
|
|
2608
|
+
turn_id: turnId,
|
|
2609
|
+
});
|
|
2610
|
+
const bytesBefore = new Map(await Promise.all(seededPaths.map(async (path) => [path, await readFile(path)])));
|
|
2611
|
+
const previousTeamMode = process.env.OMX_TEAM_MODE;
|
|
2612
|
+
process.env.OMX_TEAM_MODE = 'disabled';
|
|
2613
|
+
try {
|
|
2614
|
+
let classification;
|
|
2615
|
+
let writerCalls = 0;
|
|
2616
|
+
const result = await recordNotifySkillActivation({
|
|
2617
|
+
stateDir,
|
|
2618
|
+
sourceCwd: cwd,
|
|
2619
|
+
text: '$team $autopilot retry',
|
|
2620
|
+
sessionId,
|
|
2621
|
+
threadId,
|
|
2622
|
+
turnId,
|
|
2623
|
+
payload: {
|
|
2624
|
+
type: 'agent-turn-complete',
|
|
2625
|
+
'thread-id': threadId,
|
|
2626
|
+
'turn-id': turnId,
|
|
2627
|
+
'last-assistant-message': 'Autopilot complete.',
|
|
2628
|
+
},
|
|
2629
|
+
}, {
|
|
2630
|
+
classifyKeywordInput: (text) => {
|
|
2631
|
+
classification = classifyKeywordInput(text);
|
|
2632
|
+
return classification;
|
|
2633
|
+
},
|
|
2634
|
+
recordSkillActivation: async () => {
|
|
2635
|
+
writerCalls += 1;
|
|
2636
|
+
return null;
|
|
2637
|
+
},
|
|
2638
|
+
});
|
|
2639
|
+
assert.deepEqual(classification?.matches.map((match) => match.skill), ['team', 'autopilot'], 'the source classification must retain Team before runtime filtering');
|
|
2640
|
+
assert.equal(writerCalls, 0, 'disabled Team filtering must expose the same-turn terminal Autopilot replay for suppression');
|
|
2641
|
+
assert.equal(result, null);
|
|
2642
|
+
for (const path of seededPaths) {
|
|
2643
|
+
assert.deepEqual(await readFile(path), bytesBefore.get(path), `same-turn notify replay must preserve ${path} byte-for-byte`);
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
2646
|
+
finally {
|
|
2647
|
+
if (previousTeamMode === undefined)
|
|
2648
|
+
delete process.env.OMX_TEAM_MODE;
|
|
2649
|
+
else
|
|
2650
|
+
process.env.OMX_TEAM_MODE = previousTeamMode;
|
|
2651
|
+
}
|
|
2652
|
+
});
|
|
2653
|
+
});
|
|
2654
|
+
it('G2a sends the exact stale predecessor prompt through the shared classification and writer boundary without state', async () => {
|
|
2655
|
+
await withTempWorkingDir(async (cwd) => {
|
|
2656
|
+
const stateDir = join(cwd, 'isolated-g2a-state-root');
|
|
2657
|
+
const sessionId = 'sess-g2a-stale-predecessor';
|
|
2658
|
+
const sessionDir = join(stateDir, 'sessions', sessionId);
|
|
2659
|
+
const rootSkillPath = join(stateDir, 'skill-active-state.json');
|
|
2660
|
+
const sessionSkillPath = join(sessionDir, 'skill-active-state.json');
|
|
2661
|
+
const rootRalplanPath = join(stateDir, 'ralplan-state.json');
|
|
2662
|
+
const sessionRalplanPath = join(sessionDir, 'ralplan-state.json');
|
|
2663
|
+
const text = 'use $ralplan is the consensus-planning command';
|
|
2664
|
+
const textBytes = Buffer.from(text, 'utf8');
|
|
2665
|
+
let classification;
|
|
2666
|
+
let writerClassification;
|
|
2667
|
+
let writerText = '';
|
|
2668
|
+
let writerCalls = 0;
|
|
2669
|
+
const result = await recordNotifySkillActivation({
|
|
2670
|
+
stateDir,
|
|
2671
|
+
sourceCwd: cwd,
|
|
2672
|
+
text,
|
|
2673
|
+
sessionId,
|
|
2674
|
+
threadId: 'thread-g2a-stale-predecessor',
|
|
2675
|
+
turnId: 'turn-g2a-stale-predecessor',
|
|
2676
|
+
payload: { type: 'agent-turn-complete' },
|
|
2677
|
+
}, {
|
|
2678
|
+
classifyKeywordInput: (input) => {
|
|
2679
|
+
classification = classifyKeywordInput(input);
|
|
2680
|
+
return classification;
|
|
2681
|
+
},
|
|
2682
|
+
recordSkillActivation: async (input) => {
|
|
2683
|
+
writerCalls += 1;
|
|
2684
|
+
writerText = input.text;
|
|
2685
|
+
writerClassification = input.classification;
|
|
2686
|
+
return recordSkillActivation(input);
|
|
2687
|
+
},
|
|
2688
|
+
});
|
|
2689
|
+
assert.equal(writerCalls, 1, 'notify must invoke the shared writer boundary once');
|
|
2690
|
+
assert.strictEqual(writerClassification, classification, 'notify must pass the original classification object to the writer');
|
|
2691
|
+
assert.deepEqual(Buffer.from(writerText, 'utf8'), textBytes, 'notify must pass the stale predecessor bytes unchanged');
|
|
2692
|
+
assert.deepEqual(classification?.matches, [], 'the stale predecessor wording must not activate ralplan');
|
|
2693
|
+
assert.equal(result, null);
|
|
2694
|
+
assert.equal(existsSync(stateDir), false, 'the stale predecessor wording must not create isolated state');
|
|
2695
|
+
assert.equal(existsSync(rootSkillPath), false, 'the stale predecessor wording must not create root canonical state');
|
|
2696
|
+
assert.equal(existsSync(sessionSkillPath), false, 'the stale predecessor wording must not create session canonical state');
|
|
2697
|
+
assert.equal(existsSync(rootRalplanPath), false, 'the stale predecessor wording must not create root ralplan detail state');
|
|
2698
|
+
assert.equal(existsSync(sessionRalplanPath), false, 'the stale predecessor wording must not create session ralplan detail state');
|
|
2699
|
+
});
|
|
2700
|
+
});
|
|
2701
|
+
it('G2b-N preserves five distinct terminal state files for the exact negated notify prompt without a fabricated Stop signal', async () => {
|
|
2702
|
+
await withTempWorkingDir(async (cwd) => {
|
|
2703
|
+
const stateDir = join(cwd, '.omx', 'state');
|
|
2704
|
+
const sessionId = 'sess-g2b-negated-terminal';
|
|
2705
|
+
const threadId = 'thread-g2b-negated-terminal';
|
|
2706
|
+
const turnId = 'turn-g2b-negated-terminal';
|
|
2707
|
+
const sessionDir = join(stateDir, 'sessions', sessionId);
|
|
2708
|
+
const sessionJsonPath = join(stateDir, 'session.json');
|
|
2709
|
+
const rootSkillPath = join(stateDir, 'skill-active-state.json');
|
|
2710
|
+
const rootAutopilotPath = join(stateDir, 'autopilot-state.json');
|
|
2711
|
+
const sessionSkillPath = join(sessionDir, 'skill-active-state.json');
|
|
2712
|
+
const sessionAutopilotPath = join(sessionDir, 'autopilot-state.json');
|
|
2713
|
+
const seededPaths = [sessionJsonPath, rootSkillPath, rootAutopilotPath, sessionSkillPath, sessionAutopilotPath];
|
|
2714
|
+
const terminalBytes = [
|
|
2715
|
+
Buffer.from(`{\n "session_id": "${sessionId}",\n "started_at": "2026-06-01T00:00:01.001Z",\n "turn_id": "turn-g2b-session-pointer"\n}\n`),
|
|
2716
|
+
Buffer.from(`{\n "version": 1,\n "active": true,\n "skill": "autopilot",\n "phase": "completing",\n "updated_at": "2026-06-01T00:00:02.002Z",\n "turn_id": "turn-g2b-root-skill"\n}\n`),
|
|
2717
|
+
Buffer.from(`{\n "mode": "autopilot",\n "active": false,\n "current_phase": "complete",\n "completed_at": "2026-06-01T00:00:03.003Z",\n "turn_id": "turn-g2b-root-detail"\n}\n`),
|
|
2718
|
+
Buffer.from(`{\n "version": 1,\n "active": true,\n "skill": "autopilot",\n "phase": "completing",\n "updated_at": "2026-06-01T00:00:04.004Z",\n "turn_id": "turn-g2b-session-skill"\n}\n`),
|
|
2719
|
+
Buffer.from(`{\n "mode": "autopilot",\n "active": false,\n "current_phase": "complete",\n "completed_at": "2026-06-01T00:00:05.005Z",\n "turn_id": "turn-g2b-session-detail"\n}\n`),
|
|
2720
|
+
];
|
|
2721
|
+
await mkdir(sessionDir, { recursive: true });
|
|
2722
|
+
await Promise.all(seededPaths.map((path, index) => writeFile(path, terminalBytes[index])));
|
|
2723
|
+
const text = 'do not start $autopilot — café';
|
|
2724
|
+
const textBytes = Buffer.from(text, 'utf8');
|
|
2725
|
+
let classification;
|
|
2726
|
+
let writerClassification;
|
|
2727
|
+
let writerText = '';
|
|
2728
|
+
let writerCalls = 0;
|
|
2729
|
+
const result = await recordNotifySkillActivation({
|
|
2730
|
+
stateDir,
|
|
2731
|
+
sourceCwd: cwd,
|
|
2732
|
+
text,
|
|
2733
|
+
sessionId,
|
|
2734
|
+
threadId,
|
|
2735
|
+
turnId,
|
|
2736
|
+
payload: {
|
|
2737
|
+
type: 'agent-turn-complete',
|
|
2738
|
+
'thread-id': threadId,
|
|
2739
|
+
'turn-id': turnId,
|
|
2740
|
+
},
|
|
2741
|
+
}, {
|
|
2742
|
+
classifyKeywordInput: (input) => {
|
|
2743
|
+
classification = classifyKeywordInput(input);
|
|
2744
|
+
return classification;
|
|
2745
|
+
},
|
|
2746
|
+
recordSkillActivation: async (input) => {
|
|
2747
|
+
writerCalls += 1;
|
|
2748
|
+
writerText = input.text;
|
|
2749
|
+
writerClassification = input.classification;
|
|
2750
|
+
return recordSkillActivation(input);
|
|
2751
|
+
},
|
|
2752
|
+
});
|
|
2753
|
+
assert.equal(writerCalls, 1, 'the negated notify input must reach the shared writer boundary once');
|
|
2754
|
+
assert.strictEqual(writerClassification, classification, 'notify must retain classification identity for negated input');
|
|
2755
|
+
assert.deepEqual(Buffer.from(writerText, 'utf8'), textBytes, 'notify must retain the exact negated input bytes');
|
|
2756
|
+
assert.deepEqual(classification?.matches, [], 'the exact negated input must not restart Autopilot');
|
|
2757
|
+
assert.equal(result, null);
|
|
2758
|
+
for (const [index, path] of seededPaths.entries()) {
|
|
2759
|
+
assert.deepEqual(await readFile(path), terminalBytes[index], `negated notify input must preserve ${path} byte-for-byte`);
|
|
2760
|
+
}
|
|
2761
|
+
});
|
|
2762
|
+
});
|
|
2763
|
+
it('logs injected skill activation writer failures without failing the notify hook boundary', async () => {
|
|
2764
|
+
await withTempWorkingDir(async (cwd) => {
|
|
2765
|
+
const stateDir = join(cwd, '.omx', 'state');
|
|
2766
|
+
const logsDir = join(cwd, '.omx', 'logs');
|
|
2767
|
+
const sessionId = 'sess-notify-writer-failure';
|
|
2768
|
+
const threadId = 'thread-notify-writer-failure';
|
|
2769
|
+
const turnId = 'turn-notify-writer-failure';
|
|
2770
|
+
let writerCalls = 0;
|
|
2771
|
+
await mkdir(logsDir, { recursive: true });
|
|
2772
|
+
const result = await recordNotifySkillActivationNonFatal({
|
|
2773
|
+
stateDir,
|
|
2774
|
+
sourceCwd: cwd,
|
|
2775
|
+
text: '$ralplan plan this change',
|
|
2776
|
+
sessionId,
|
|
2777
|
+
threadId,
|
|
2778
|
+
turnId,
|
|
2779
|
+
payload: { type: 'agent-turn-complete' },
|
|
2780
|
+
}, logsDir, {
|
|
2781
|
+
recordSkillActivation: async () => {
|
|
2782
|
+
writerCalls += 1;
|
|
2783
|
+
throw new Error(`injected writer failure ${'x'.repeat(1_000)}`);
|
|
2784
|
+
},
|
|
2785
|
+
});
|
|
2786
|
+
assert.equal(result, null);
|
|
2787
|
+
assert.equal(writerCalls, 1);
|
|
2788
|
+
const logPath = join(logsDir, `notify-hook-${new Date().toISOString().split('T')[0]}.jsonl`);
|
|
2789
|
+
const events = (await readFile(logPath, 'utf8')).trim().split('\n')
|
|
2790
|
+
.map((line) => JSON.parse(line));
|
|
2791
|
+
const failure = events.find((event) => event.type === 'notify_skill_activation_failure');
|
|
2792
|
+
assert.ok(failure);
|
|
2793
|
+
assert.equal(failure.level, 'warn');
|
|
2794
|
+
assert.equal(failure.session_id, sessionId);
|
|
2795
|
+
assert.equal(failure.thread_id, threadId);
|
|
2796
|
+
assert.equal(failure.turn_id, turnId);
|
|
2797
|
+
assert.match(String(failure.error), /^injected writer failure /);
|
|
2798
|
+
assert.ok(String(failure.error).length <= 512);
|
|
2799
|
+
assert.equal(Number.isNaN(Date.parse(String(failure.timestamp))), false);
|
|
2800
|
+
});
|
|
2801
|
+
});
|
|
2051
2802
|
it('writes skill-active-state.json when keyword activation is detected', async () => {
|
|
2052
2803
|
await withTempWorkingDir(async (cwd) => {
|
|
2053
2804
|
const omxDir = join(cwd, '.omx');
|
|
@@ -2067,7 +2818,7 @@ exit 0
|
|
|
2067
2818
|
await writeFile(join(fakeBinDir, 'tmux'), buildFakeTmux(join(cwd, 'tmux.log')));
|
|
2068
2819
|
await chmod(join(fakeBinDir, 'tmux'), 0o755);
|
|
2069
2820
|
const result = runNotifyHook(cwd, fakeBinDir, codexHome, {
|
|
2070
|
-
'input-messages': ['
|
|
2821
|
+
'input-messages': ['$autopilot handle this task'],
|
|
2071
2822
|
'last-assistant-message': 'Here is the plan I will follow.',
|
|
2072
2823
|
});
|
|
2073
2824
|
assert.equal(result.status, 0, `hook failed: ${result.stderr || result.stdout}`);
|
|
@@ -2439,12 +3190,14 @@ exit 0
|
|
|
2439
3190
|
phase: 'executing',
|
|
2440
3191
|
source: 'keyword-detector',
|
|
2441
3192
|
session_id: 'sess-managed',
|
|
3193
|
+
owner_codex_session_id: 'sess-managed',
|
|
2442
3194
|
});
|
|
2443
3195
|
await writeJson(join(sessionStateDir, 'autoresearch-state.json'), {
|
|
2444
3196
|
active: true,
|
|
2445
3197
|
mode: 'autoresearch',
|
|
2446
3198
|
current_phase: 'executing',
|
|
2447
3199
|
session_id: 'sess-managed',
|
|
3200
|
+
owner_codex_session_id: 'sess-managed',
|
|
2448
3201
|
validation_mode: 'mission-validator-script',
|
|
2449
3202
|
mission_validator_command: 'node scripts/validate.js',
|
|
2450
3203
|
completion_artifact_path: '.omx/specs/autoresearch-demo/completion.json',
|
|
@@ -2488,12 +3241,14 @@ exit 0
|
|
|
2488
3241
|
phase: 'reviewing',
|
|
2489
3242
|
source: 'keyword-detector',
|
|
2490
3243
|
session_id: 'sess-managed',
|
|
3244
|
+
owner_codex_session_id: 'sess-managed',
|
|
2491
3245
|
});
|
|
2492
3246
|
await writeJson(join(sessionStateDir, 'autoresearch-state.json'), {
|
|
2493
3247
|
active: true,
|
|
2494
3248
|
mode: 'autoresearch',
|
|
2495
3249
|
current_phase: 'reviewing',
|
|
2496
3250
|
session_id: 'sess-managed',
|
|
3251
|
+
owner_codex_session_id: 'sess-managed',
|
|
2497
3252
|
validation_mode: 'mission-validator-script',
|
|
2498
3253
|
mission_validator_command: 'node scripts/validate.js',
|
|
2499
3254
|
completion_artifact_path: '.omx/specs/autoresearch-demo/completion.json',
|