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
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { describe, it } from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
|
-
import { cp, mkdir, mkdtemp, readFile, rm, symlink, writeFile, } from "node:fs/promises";
|
|
4
|
-
import { existsSync } from "node:fs";
|
|
3
|
+
import { cp, link, mkdir, mkdtemp, realpath, readFile, rename, rm, symlink, writeFile, } from "node:fs/promises";
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { join, dirname } from "node:path";
|
|
6
6
|
import { tmpdir } from "node:os";
|
|
7
7
|
import { spawnSync } from "node:child_process";
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
9
9
|
import { withPackagedExploreHarnessHidden, withPackagedExploreHarnessLock, } from "./packaged-explore-harness-lock.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
10
|
+
import { buildPostCompactSmokeSpawnInvocation, checkExternalCodexProcessGuards, checkExploreHarness, checkLegacyMultiAgentCompatibility, checkNativeHookDistSmoke, checkNativePostCompactHookRuntime, checkNativeHooks, classifyPostCompactHookStdout, doctor, setDoctorClaimJournalDurabilityForTest, } from "../doctor.js";
|
|
11
|
+
import { createNativeHookClaimJournalDurability, persistNativeHookClaimJournal, } from "../native-hook-claim-journal.js";
|
|
12
|
+
import { syncRegularFile } from "../../utils/file-durability.js";
|
|
13
|
+
import { buildManagedCodexNativeHookCommand, buildManagedCodexNativeHookWindowsShimContent, } from "../../config/codex-hooks.js";
|
|
12
14
|
const MANAGED_HOOK_EVENTS = [
|
|
13
15
|
"SessionStart",
|
|
14
16
|
"PreToolUse",
|
|
@@ -54,6 +56,13 @@ function currentNativeHookCommand(codexHomeDir) {
|
|
|
54
56
|
codexHomeDir,
|
|
55
57
|
});
|
|
56
58
|
}
|
|
59
|
+
function buildWindowsShimCommand(shimPath) {
|
|
60
|
+
return `& 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe' -NoProfile -ExecutionPolicy Bypass -File '${shimPath.replace(/'/g, "''")}'`;
|
|
61
|
+
}
|
|
62
|
+
function buildWindowsShimHooksJson(shimPath, codexHomeDir) {
|
|
63
|
+
const command = buildWindowsShimCommand(shimPath);
|
|
64
|
+
return buildHooksJsonWithPostCompactCommand(command, codexHomeDir, command);
|
|
65
|
+
}
|
|
57
66
|
async function installPluginCacheFixture(codexDir) {
|
|
58
67
|
const root = repoRoot();
|
|
59
68
|
const sourcePluginDir = join(root, "plugins", "oh-my-codex");
|
|
@@ -77,8 +86,7 @@ async function packagedPluginVersion() {
|
|
|
77
86
|
}
|
|
78
87
|
return manifest.version;
|
|
79
88
|
}
|
|
80
|
-
function buildHooksJsonWithPostCompactCommand(postCompactCommand, codexHomeDir) {
|
|
81
|
-
const expectedCommand = currentNativeHookCommand(codexHomeDir);
|
|
89
|
+
function buildHooksJsonWithPostCompactCommand(postCompactCommand, codexHomeDir, expectedCommand = currentNativeHookCommand(codexHomeDir)) {
|
|
82
90
|
return `${JSON.stringify({
|
|
83
91
|
hooks: Object.fromEntries(MANAGED_HOOK_EVENTS.map((eventName) => [
|
|
84
92
|
eventName,
|
|
@@ -97,6 +105,40 @@ function buildHooksJsonWithPostCompactCommand(postCompactCommand, codexHomeDir)
|
|
|
97
105
|
])),
|
|
98
106
|
}, null, 2)}\n`;
|
|
99
107
|
}
|
|
108
|
+
async function withRecoverableDoctorClaimJournal(run) {
|
|
109
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-doctor-claim-recovery-"));
|
|
110
|
+
const codexHomeDir = join(wd, ".codex");
|
|
111
|
+
const hooksPath = join(codexHomeDir, "hooks.json");
|
|
112
|
+
const claimPath = join(codexHomeDir, ".hooks.json.omx-claim-test.tmp");
|
|
113
|
+
const previousCwd = process.cwd();
|
|
114
|
+
const previousCodexHome = process.env.CODEX_HOME;
|
|
115
|
+
try {
|
|
116
|
+
await mkdir(codexHomeDir, { recursive: true });
|
|
117
|
+
await writeFile(hooksPath, "{\"hooks\":{}}\n");
|
|
118
|
+
await persistNativeHookClaimJournal(codexHomeDir, {
|
|
119
|
+
canonicalPath: hooksPath,
|
|
120
|
+
claimPath,
|
|
121
|
+
before: Buffer.from("{\"hooks\":{}}\n"),
|
|
122
|
+
after: null,
|
|
123
|
+
}, createNativeHookClaimJournalDurability());
|
|
124
|
+
await rename(hooksPath, claimPath);
|
|
125
|
+
const journalPath = join(codexHomeDir, ".omx", "native-hook-claim-journal.json");
|
|
126
|
+
const journal = JSON.parse(await readFile(journalPath, "utf-8"));
|
|
127
|
+
journal.ownerPid = 2_147_483_647;
|
|
128
|
+
await writeFile(journalPath, `${JSON.stringify(journal, null, 2)}\n`, "utf-8");
|
|
129
|
+
process.env.CODEX_HOME = codexHomeDir;
|
|
130
|
+
process.chdir(wd);
|
|
131
|
+
return await run(codexHomeDir);
|
|
132
|
+
}
|
|
133
|
+
finally {
|
|
134
|
+
process.chdir(previousCwd);
|
|
135
|
+
if (previousCodexHome === undefined)
|
|
136
|
+
delete process.env.CODEX_HOME;
|
|
137
|
+
else
|
|
138
|
+
process.env.CODEX_HOME = previousCodexHome;
|
|
139
|
+
await rm(wd, { recursive: true, force: true });
|
|
140
|
+
}
|
|
141
|
+
}
|
|
100
142
|
describe("omx doctor onboarding warning copy", () => {
|
|
101
143
|
it("warns about external LaunchAgents that kill Codex app-server MCP children", async () => {
|
|
102
144
|
const wd = await mkdtemp(join(tmpdir(), "omx-doctor-external-guard-"));
|
|
@@ -891,7 +933,7 @@ OMX_LORE_COMMIT_GUARD = "truee"
|
|
|
891
933
|
return;
|
|
892
934
|
assert.equal(res.status, 0, res.stderr || res.stdout);
|
|
893
935
|
assert.doesNotMatch(res.stdout, /Resolved setup install mode: plugin \(inferred from Codex plugin config\)/);
|
|
894
|
-
assert.match(res.stdout, /Native hooks: expected setup-owned hooks\.json is missing at .*\.codex[\\/]+hooks\.json even though config\.toml has OMX entries; run "omx setup
|
|
936
|
+
assert.match(res.stdout, /Native hooks: expected setup-owned hooks\.json is missing at .*\.codex[\\/]+hooks\.json even though config\.toml has OMX entries; run "omx setup" to restore native hook coverage/);
|
|
895
937
|
assert.match(res.stdout, /Prompts: prompts directory not found/);
|
|
896
938
|
}
|
|
897
939
|
finally {
|
|
@@ -1144,7 +1186,7 @@ OMX_LORE_COMMIT_GUARD = "truee"
|
|
|
1144
1186
|
if (shouldSkipForSpawnPermissions(res.error))
|
|
1145
1187
|
return;
|
|
1146
1188
|
assert.equal(res.status, 0, res.stderr || res.stdout);
|
|
1147
|
-
assert.match(res.stdout, new RegExp(`\\[!!\\] Native hooks: plugin-scoped hooks are enabled, but cached plugin hook files or pinned hook launcher in ${cacheDir.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")} do not match the packaged plugin; setup-owned hooks\\.json is intentionally absent at .*\\.codex[\\/]+hooks\\.json; run "omx setup --plugin
|
|
1189
|
+
assert.match(res.stdout, new RegExp(`\\[!!\\] Native hooks: plugin-scoped hooks are enabled, but cached plugin hook files or pinned hook launcher in ${cacheDir.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")} do not match the packaged plugin; setup-owned hooks\\.json is intentionally absent at .*\\.codex[\\/]+hooks\\.json; run "omx setup --plugin" to refresh the plugin cache`));
|
|
1148
1190
|
assert.doesNotMatch(res.stdout, /plugin cache native hook coverage smoke passed/);
|
|
1149
1191
|
}
|
|
1150
1192
|
finally {
|
|
@@ -1194,7 +1236,7 @@ OMX_LORE_COMMIT_GUARD = "truee"
|
|
|
1194
1236
|
if (shouldSkipForSpawnPermissions(res.error))
|
|
1195
1237
|
return;
|
|
1196
1238
|
assert.equal(res.status, 0, res.stderr || res.stdout);
|
|
1197
|
-
assert.match(res.stdout, new RegExp(`\\[OK\\] Native hooks: plugin-scoped hooks are enabled; existing hooks\\.json at .*\\.codex[\\/]+hooks\\.json is
|
|
1239
|
+
assert.match(res.stdout, new RegExp(`\\[OK\\] Native hooks: plugin-scoped hooks are enabled; existing hooks\\.json at .*\\.codex[\\/]+hooks\\.json is retained read-only and validated separately because plugin-scoped hooks are enabled, and plugin cache native hook coverage smoke passed via ${join(cacheDir, "hooks", "hooks.json").replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`));
|
|
1198
1240
|
assert.doesNotMatch(res.stdout, /hooks\.json is missing OMX-managed coverage/);
|
|
1199
1241
|
assert.doesNotMatch(res.stdout, /run "omx setup --force" to restore native hooks/);
|
|
1200
1242
|
}
|
|
@@ -1229,7 +1271,7 @@ OMX_LORE_COMMIT_GUARD = "truee"
|
|
|
1229
1271
|
if (shouldSkipForSpawnPermissions(res.error))
|
|
1230
1272
|
return;
|
|
1231
1273
|
assert.equal(res.status, 0, res.stderr || res.stdout);
|
|
1232
|
-
assert.match(res.stdout, /Native hooks: hooks\.json is missing OMX-managed coverage for PreToolUse, PostToolUse, UserPromptSubmit, PreCompact, PostCompact, Stop; run "omx setup
|
|
1274
|
+
assert.match(res.stdout, /Native hooks: hooks\.json is missing OMX-managed coverage for PreToolUse, PostToolUse, UserPromptSubmit, PreCompact, PostCompact, Stop; run "omx setup" to restore native hooks/);
|
|
1233
1275
|
}
|
|
1234
1276
|
finally {
|
|
1235
1277
|
await rm(wd, { recursive: true, force: true });
|
|
@@ -1289,7 +1331,7 @@ command = "node"
|
|
|
1289
1331
|
if (shouldSkipForSpawnPermissions(res.error))
|
|
1290
1332
|
return;
|
|
1291
1333
|
assert.equal(res.status, 0, res.stderr || res.stdout);
|
|
1292
|
-
assert.match(res.stdout, /Native hooks: expected setup-owned hooks\.json is missing at .*\.codex[\/]+hooks\.json even though config\.toml has OMX entries; run "omx setup
|
|
1334
|
+
assert.match(res.stdout, /Native hooks: expected setup-owned hooks\.json is missing at .*\.codex[\/]+hooks\.json even though config\.toml has OMX entries; run "omx setup" to restore native hook coverage/);
|
|
1293
1335
|
}
|
|
1294
1336
|
finally {
|
|
1295
1337
|
await rm(wd, { recursive: true, force: true });
|
|
@@ -1309,7 +1351,508 @@ command = "node"
|
|
|
1309
1351
|
if (shouldSkipForSpawnPermissions(res.error))
|
|
1310
1352
|
return;
|
|
1311
1353
|
assert.equal(res.status, 0, res.stderr || res.stdout);
|
|
1312
|
-
assert.match(res.stdout, /\[XX\] Native hooks:
|
|
1354
|
+
assert.match(res.stdout, /\[XX\] Native hooks: hooks\.json failed strict load validation \(invalid_document\): hooks\.json must contain a JSON object; inspect the file manually because doctor will not modify it/);
|
|
1355
|
+
}
|
|
1356
|
+
finally {
|
|
1357
|
+
await rm(wd, { recursive: true, force: true });
|
|
1358
|
+
}
|
|
1359
|
+
});
|
|
1360
|
+
it("reports matcher-aware discovery warnings without touching hooks.json", async () => {
|
|
1361
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-doctor-hooks-matcher-warning-"));
|
|
1362
|
+
try {
|
|
1363
|
+
const home = join(wd, "home");
|
|
1364
|
+
const codexDir = join(home, ".codex");
|
|
1365
|
+
await mkdir(codexDir, { recursive: true });
|
|
1366
|
+
await writeFile(join(codexDir, "hooks.json"), JSON.stringify({
|
|
1367
|
+
hooks: {
|
|
1368
|
+
SessionStart: [{
|
|
1369
|
+
matcher: "[",
|
|
1370
|
+
hooks: [{ type: "command", command: "echo user-owned" }],
|
|
1371
|
+
}],
|
|
1372
|
+
},
|
|
1373
|
+
}, null, 2) + "\n");
|
|
1374
|
+
const res = runOmx(wd, ["doctor"], { HOME: home, CODEX_HOME: codexDir });
|
|
1375
|
+
if (shouldSkipForSpawnPermissions(res.error))
|
|
1376
|
+
return;
|
|
1377
|
+
assert.equal(res.status, 0, res.stderr || res.stdout);
|
|
1378
|
+
assert.match(res.stdout, /Native hooks: hooks\.json discovery warnings: SessionStart\[0\]: Codex skips groups whose matcher is not a valid regular expression; Codex may ignore the listed entries, and doctor will not modify them/);
|
|
1379
|
+
assert.doesNotMatch(res.stdout, /Native hooks:.*--force/);
|
|
1380
|
+
}
|
|
1381
|
+
finally {
|
|
1382
|
+
await rm(wd, { recursive: true, force: true });
|
|
1383
|
+
}
|
|
1384
|
+
});
|
|
1385
|
+
it("treats UserPromptSubmit and Stop matcher groups as valid foreign survivors", async () => {
|
|
1386
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-doctor-hooks-foreign-survivors-"));
|
|
1387
|
+
try {
|
|
1388
|
+
const home = join(wd, "home");
|
|
1389
|
+
const codexDir = join(home, ".codex");
|
|
1390
|
+
await mkdir(codexDir, { recursive: true });
|
|
1391
|
+
await writeFile(join(codexDir, "hooks.json"), JSON.stringify({
|
|
1392
|
+
hooks: {
|
|
1393
|
+
UserPromptSubmit: [{ matcher: "[", hooks: [{ type: "command", command: "echo prompt" }] }],
|
|
1394
|
+
Stop: [{ matcher: "[", hooks: [{ type: "command", command: "echo stop" }] }],
|
|
1395
|
+
},
|
|
1396
|
+
}, null, 2) + "\n");
|
|
1397
|
+
const res = runOmx(wd, ["doctor"], { HOME: home, CODEX_HOME: codexDir });
|
|
1398
|
+
if (shouldSkipForSpawnPermissions(res.error))
|
|
1399
|
+
return;
|
|
1400
|
+
assert.equal(res.status, 0, res.stderr || res.stdout);
|
|
1401
|
+
assert.match(res.stdout, /\[OK\] Native hooks: hooks\.json contains valid foreign hook entries and no OMX-managed wrappers; doctor will preserve the user-owned configuration/);
|
|
1402
|
+
assert.doesNotMatch(res.stdout, /hooks\.json discovery warnings/);
|
|
1403
|
+
assert.doesNotMatch(res.stdout, /Native hooks:.*--force/);
|
|
1404
|
+
}
|
|
1405
|
+
finally {
|
|
1406
|
+
await rm(wd, { recursive: true, force: true });
|
|
1407
|
+
}
|
|
1408
|
+
});
|
|
1409
|
+
it("reports unsafe managed removal without recommending destructive repair", async () => {
|
|
1410
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-doctor-hooks-unsafe-removal-"));
|
|
1411
|
+
try {
|
|
1412
|
+
const home = join(wd, "home");
|
|
1413
|
+
const codexDir = join(home, ".codex");
|
|
1414
|
+
await mkdir(codexDir, { recursive: true });
|
|
1415
|
+
await writeFile(join(codexDir, "hooks.json"), JSON.stringify({
|
|
1416
|
+
hooks: {
|
|
1417
|
+
SessionStart: [{
|
|
1418
|
+
matcher: "startup|resume|clear",
|
|
1419
|
+
hooks: [
|
|
1420
|
+
{ type: "command", command: 'node "/repo/dist/scripts/codex-native-hook.js"' },
|
|
1421
|
+
{ type: "command", command: "echo user-owned" },
|
|
1422
|
+
],
|
|
1423
|
+
}],
|
|
1424
|
+
},
|
|
1425
|
+
}, null, 2) + "\n");
|
|
1426
|
+
const res = runOmx(wd, ["doctor"], { HOME: home, CODEX_HOME: codexDir });
|
|
1427
|
+
if (shouldSkipForSpawnPermissions(res.error))
|
|
1428
|
+
return;
|
|
1429
|
+
assert.equal(res.status, 0, res.stderr || res.stdout);
|
|
1430
|
+
assert.match(res.stdout, /\[!!\] Native hooks: hooks\.json has OMX entries that cannot be safely removed \(unsafe_managed_removal\): Removing OMX hooks would shift a foreign coordinate or discard opaque metadata; manual cleanup is required because doctor will not overwrite or remove it/);
|
|
1431
|
+
assert.doesNotMatch(res.stdout, /Native hooks:.*--force/);
|
|
1432
|
+
}
|
|
1433
|
+
finally {
|
|
1434
|
+
await rm(wd, { recursive: true, force: true });
|
|
1435
|
+
}
|
|
1436
|
+
});
|
|
1437
|
+
it("fails closed when a Windows native hook references a missing shim", async () => {
|
|
1438
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-doctor-windows-shim-missing-"));
|
|
1439
|
+
try {
|
|
1440
|
+
const codexDir = join(wd, ".codex");
|
|
1441
|
+
const hooksPath = join(codexDir, "hooks.json");
|
|
1442
|
+
const shimPath = join(codexDir, "hooks", "omx-native-hook-windows-shim.ps1");
|
|
1443
|
+
await mkdir(codexDir, { recursive: true });
|
|
1444
|
+
const original = buildWindowsShimHooksJson(shimPath, codexDir);
|
|
1445
|
+
await writeFile(hooksPath, original);
|
|
1446
|
+
const check = await checkNativeHooks(hooksPath, join(codexDir, "config.toml"), {
|
|
1447
|
+
codexHomeDir: codexDir,
|
|
1448
|
+
platform: "win32",
|
|
1449
|
+
});
|
|
1450
|
+
assert.equal(check.status, "fail");
|
|
1451
|
+
assert.match(check.message, /referenced Windows native hook shim is missing at/);
|
|
1452
|
+
assert.match(check.message, /manually reinstall the matching oh-my-codex version/);
|
|
1453
|
+
assert.doesNotMatch(check.message, /omx setup|--force/);
|
|
1454
|
+
assert.equal(existsSync(shimPath), false);
|
|
1455
|
+
assert.equal(await readFile(hooksPath, "utf-8"), original);
|
|
1456
|
+
}
|
|
1457
|
+
finally {
|
|
1458
|
+
await rm(wd, { recursive: true, force: true });
|
|
1459
|
+
}
|
|
1460
|
+
});
|
|
1461
|
+
it("fails closed when a referenced Windows native hook shim is tampered", async () => {
|
|
1462
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-doctor-windows-shim-tampered-"));
|
|
1463
|
+
try {
|
|
1464
|
+
const codexDir = join(wd, ".codex");
|
|
1465
|
+
const hooksPath = join(codexDir, "hooks.json");
|
|
1466
|
+
const shimPath = join(codexDir, "hooks", "omx-native-hook-windows-shim.ps1");
|
|
1467
|
+
await mkdir(dirname(shimPath), { recursive: true });
|
|
1468
|
+
const original = buildWindowsShimHooksJson(shimPath, codexDir);
|
|
1469
|
+
const tamperedShim = `${buildManagedCodexNativeHookWindowsShimContent(repoRoot())}# user change\n`;
|
|
1470
|
+
await writeFile(hooksPath, original);
|
|
1471
|
+
await writeFile(shimPath, tamperedShim, "utf-8");
|
|
1472
|
+
const check = await checkNativeHooks(hooksPath, join(codexDir, "config.toml"), {
|
|
1473
|
+
codexHomeDir: codexDir,
|
|
1474
|
+
platform: "win32",
|
|
1475
|
+
});
|
|
1476
|
+
assert.equal(check.status, "fail");
|
|
1477
|
+
assert.match(check.message, /not an exact current or complete historical generated shim/);
|
|
1478
|
+
assert.match(check.message, /modified, truncated, have extra content, or use ambiguous encoding/);
|
|
1479
|
+
assert.doesNotMatch(check.message, /omx setup|--force/);
|
|
1480
|
+
assert.equal(await readFile(hooksPath, "utf-8"), original);
|
|
1481
|
+
assert.equal(await readFile(shimPath, "utf-8"), tamperedShim);
|
|
1482
|
+
}
|
|
1483
|
+
finally {
|
|
1484
|
+
await rm(wd, { recursive: true, force: true });
|
|
1485
|
+
}
|
|
1486
|
+
});
|
|
1487
|
+
it("accepts a complete historical Windows native hook shim without modifying it", async () => {
|
|
1488
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-doctor-windows-shim-historical-"));
|
|
1489
|
+
try {
|
|
1490
|
+
const codexDir = join(wd, ".codex");
|
|
1491
|
+
const hooksPath = join(codexDir, "hooks.json");
|
|
1492
|
+
const shimPath = join(codexDir, "hooks", "omx-native-hook-windows-shim.ps1");
|
|
1493
|
+
await mkdir(dirname(shimPath), { recursive: true });
|
|
1494
|
+
const original = buildWindowsShimHooksJson(shimPath, codexDir);
|
|
1495
|
+
const historicalShim = buildManagedCodexNativeHookWindowsShimContent("", {
|
|
1496
|
+
nodePath: "C:\\Historical Node\\node.exe",
|
|
1497
|
+
hookScriptPath: "C:\\Historical Install\\oh-my-codex\\dist\\scripts\\codex-native-hook.js",
|
|
1498
|
+
});
|
|
1499
|
+
await writeFile(hooksPath, original);
|
|
1500
|
+
await writeFile(shimPath, historicalShim, "utf-8");
|
|
1501
|
+
const check = await checkNativeHooks(hooksPath, join(codexDir, "config.toml"), {
|
|
1502
|
+
codexHomeDir: codexDir,
|
|
1503
|
+
platform: "win32",
|
|
1504
|
+
});
|
|
1505
|
+
assert.equal(check.status, "pass");
|
|
1506
|
+
assert.match(check.message, /includes OMX-managed coverage for all native hook events/);
|
|
1507
|
+
assert.equal(await readFile(hooksPath, "utf-8"), original);
|
|
1508
|
+
assert.equal(await readFile(shimPath, "utf-8"), historicalShim);
|
|
1509
|
+
}
|
|
1510
|
+
finally {
|
|
1511
|
+
await rm(wd, { recursive: true, force: true });
|
|
1512
|
+
}
|
|
1513
|
+
});
|
|
1514
|
+
it("reports Windows shim integrity before an unsafe managed/foreign group coordinate warning", async () => {
|
|
1515
|
+
for (const fixture of [
|
|
1516
|
+
{
|
|
1517
|
+
name: "missing",
|
|
1518
|
+
shimContent: null,
|
|
1519
|
+
integrity: /referenced Windows native hook shim is missing at/,
|
|
1520
|
+
},
|
|
1521
|
+
{
|
|
1522
|
+
name: "tampered",
|
|
1523
|
+
shimContent: `${buildManagedCodexNativeHookWindowsShimContent(repoRoot())}# mixed-group sentinel\n`,
|
|
1524
|
+
integrity: /not an exact current or complete historical generated shim/,
|
|
1525
|
+
},
|
|
1526
|
+
]) {
|
|
1527
|
+
const wd = await mkdtemp(join(tmpdir(), `omx-doctor-windows-shim-${fixture.name}-unsafe-`));
|
|
1528
|
+
try {
|
|
1529
|
+
const codexDir = join(wd, ".codex");
|
|
1530
|
+
const hooksPath = join(codexDir, "hooks.json");
|
|
1531
|
+
const shimPath = join(codexDir, "hooks", "omx-native-hook-windows-shim.ps1");
|
|
1532
|
+
const parsed = JSON.parse(buildWindowsShimHooksJson(shimPath, codexDir));
|
|
1533
|
+
parsed.hooks.PreToolUse[0].hooks.push({
|
|
1534
|
+
type: "command",
|
|
1535
|
+
command: "echo foreign-handler",
|
|
1536
|
+
});
|
|
1537
|
+
await mkdir(codexDir, { recursive: true });
|
|
1538
|
+
await writeFile(hooksPath, `${JSON.stringify(parsed, null, 2)}\n`);
|
|
1539
|
+
if (fixture.shimContent !== null) {
|
|
1540
|
+
await mkdir(dirname(shimPath), { recursive: true });
|
|
1541
|
+
await writeFile(shimPath, fixture.shimContent, "utf-8");
|
|
1542
|
+
}
|
|
1543
|
+
const check = await checkNativeHooks(hooksPath, join(codexDir, "config.toml"), {
|
|
1544
|
+
codexHomeDir: codexDir,
|
|
1545
|
+
platform: "win32",
|
|
1546
|
+
});
|
|
1547
|
+
assert.equal(check.status, "fail", fixture.name);
|
|
1548
|
+
assert.match(check.message, fixture.integrity, fixture.name);
|
|
1549
|
+
assert.match(check.message, /unsafe_managed_removal/, fixture.name);
|
|
1550
|
+
assert.ok(check.message.search(fixture.integrity) < check.message.indexOf("unsafe_managed_removal"), `${fixture.name} shim integrity must take precedence over the coordinate warning`);
|
|
1551
|
+
}
|
|
1552
|
+
finally {
|
|
1553
|
+
await rm(wd, { recursive: true, force: true });
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
});
|
|
1557
|
+
it("never executes missing, tampered, historical, hard-linked, or symlinked Windows shim sentinels during verbose validation", async () => {
|
|
1558
|
+
for (const fixture of [
|
|
1559
|
+
{
|
|
1560
|
+
name: "missing",
|
|
1561
|
+
shimContent: null,
|
|
1562
|
+
hardLink: false,
|
|
1563
|
+
symlinkTarget: null,
|
|
1564
|
+
expected: /referenced Windows native hook shim is missing at/,
|
|
1565
|
+
},
|
|
1566
|
+
{
|
|
1567
|
+
name: "tampered",
|
|
1568
|
+
shimContent: `${buildManagedCodexNativeHookWindowsShimContent(repoRoot())}# verbose-execution sentinel\n`,
|
|
1569
|
+
hardLink: false,
|
|
1570
|
+
symlinkTarget: null,
|
|
1571
|
+
expected: /not an exact current or complete historical generated shim/,
|
|
1572
|
+
},
|
|
1573
|
+
{
|
|
1574
|
+
name: "historical",
|
|
1575
|
+
shimContent: buildManagedCodexNativeHookWindowsShimContent("", {
|
|
1576
|
+
nodePath: "C:\\Historical Node\\node.exe",
|
|
1577
|
+
hookScriptPath: "C:\\Historical Install\\oh-my-codex\\dist\\scripts\\codex-native-hook.js",
|
|
1578
|
+
}),
|
|
1579
|
+
hardLink: false,
|
|
1580
|
+
symlinkTarget: null,
|
|
1581
|
+
expected: /complete historical generated shim.*run "omx setup" to migrate/,
|
|
1582
|
+
},
|
|
1583
|
+
{
|
|
1584
|
+
name: "hard-linked",
|
|
1585
|
+
shimContent: buildManagedCodexNativeHookWindowsShimContent(repoRoot()),
|
|
1586
|
+
hardLink: true,
|
|
1587
|
+
symlinkTarget: null,
|
|
1588
|
+
expected: /is hard-linked; doctor will not execute or modify it/,
|
|
1589
|
+
},
|
|
1590
|
+
{
|
|
1591
|
+
name: "symlinked",
|
|
1592
|
+
shimContent: null,
|
|
1593
|
+
hardLink: false,
|
|
1594
|
+
symlinkTarget: buildManagedCodexNativeHookWindowsShimContent(repoRoot()),
|
|
1595
|
+
expected: /is not a regular file; doctor will not follow or modify it/,
|
|
1596
|
+
},
|
|
1597
|
+
]) {
|
|
1598
|
+
const wd = await mkdtemp(join(tmpdir(), `omx-doctor-verbose-windows-shim-${fixture.name}-`));
|
|
1599
|
+
try {
|
|
1600
|
+
const codexDir = join(wd, ".codex");
|
|
1601
|
+
const hooksPath = join(codexDir, "hooks.json");
|
|
1602
|
+
const shimPath = join(codexDir, "hooks", "omx-native-hook-windows-shim.ps1");
|
|
1603
|
+
const command = buildWindowsShimCommand(shimPath);
|
|
1604
|
+
await mkdir(codexDir, { recursive: true });
|
|
1605
|
+
await writeFile(hooksPath, buildWindowsShimHooksJson(shimPath, codexDir));
|
|
1606
|
+
if (fixture.symlinkTarget !== null) {
|
|
1607
|
+
const symlinkTargetPath = join(wd, "symlink-target.ps1");
|
|
1608
|
+
await mkdir(dirname(shimPath), { recursive: true });
|
|
1609
|
+
await writeFile(symlinkTargetPath, fixture.symlinkTarget, "utf-8");
|
|
1610
|
+
await symlink(symlinkTargetPath, shimPath);
|
|
1611
|
+
}
|
|
1612
|
+
else if (fixture.shimContent !== null) {
|
|
1613
|
+
await mkdir(dirname(shimPath), { recursive: true });
|
|
1614
|
+
await writeFile(shimPath, fixture.shimContent, "utf-8");
|
|
1615
|
+
if (fixture.hardLink) {
|
|
1616
|
+
await link(shimPath, join(wd, "canonical-shim-hardlink.ps1"));
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
let spawned = false;
|
|
1620
|
+
const check = await checkNativePostCompactHookRuntime(hooksPath, wd, codexDir, {
|
|
1621
|
+
platform: "win32",
|
|
1622
|
+
expectedCommand: command,
|
|
1623
|
+
runner: (() => {
|
|
1624
|
+
spawned = true;
|
|
1625
|
+
throw new Error("unverified Windows shim execution");
|
|
1626
|
+
}),
|
|
1627
|
+
});
|
|
1628
|
+
assert.equal(spawned, false, `${fixture.name} shim executed`);
|
|
1629
|
+
assert.ok(check, `${fixture.name} shim must produce a safety diagnostic`);
|
|
1630
|
+
assert.notEqual(check.status, "pass", fixture.name);
|
|
1631
|
+
assert.match(check.message, fixture.expected, fixture.name);
|
|
1632
|
+
}
|
|
1633
|
+
finally {
|
|
1634
|
+
await rm(wd, { recursive: true, force: true });
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
});
|
|
1638
|
+
it("runs exact current Windows shim bytes in memory after canonical replacement, hard-linking, and ancestor retargeting", async () => {
|
|
1639
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-doctor-verbose-windows-shim-in-memory-"));
|
|
1640
|
+
try {
|
|
1641
|
+
const codexDir = join(wd, ".codex");
|
|
1642
|
+
const hooksPath = join(codexDir, "hooks.json");
|
|
1643
|
+
const hooksDir = join(codexDir, "hooks");
|
|
1644
|
+
const shimPath = join(hooksDir, "omx-native-hook-windows-shim.ps1");
|
|
1645
|
+
const command = buildWindowsShimCommand(shimPath);
|
|
1646
|
+
const currentShim = buildManagedCodexNativeHookWindowsShimContent(repoRoot());
|
|
1647
|
+
const sentinel = "# foreign canonical shim sentinel\n";
|
|
1648
|
+
const foreignHooksDir = join(codexDir, "foreign-hooks");
|
|
1649
|
+
const foreignShimPath = join(foreignHooksDir, "omx-native-hook-windows-shim.ps1");
|
|
1650
|
+
const foreignHardLinkPath = join(foreignHooksDir, "foreign-shim-hard-link.ps1");
|
|
1651
|
+
await mkdir(hooksDir, { recursive: true });
|
|
1652
|
+
await writeFile(hooksPath, buildWindowsShimHooksJson(shimPath, codexDir));
|
|
1653
|
+
await writeFile(shimPath, currentShim, "utf-8");
|
|
1654
|
+
const check = await checkNativePostCompactHookRuntime(hooksPath, wd, codexDir, {
|
|
1655
|
+
platform: "win32",
|
|
1656
|
+
expectedCommand: command,
|
|
1657
|
+
beforeWindowsShimSmoke: async () => {
|
|
1658
|
+
const parkedHooksDir = join(codexDir, "validated-hooks");
|
|
1659
|
+
await rename(hooksDir, parkedHooksDir);
|
|
1660
|
+
await mkdir(foreignHooksDir, { recursive: true });
|
|
1661
|
+
await writeFile(foreignShimPath, sentinel);
|
|
1662
|
+
await link(foreignShimPath, foreignHardLinkPath);
|
|
1663
|
+
await symlink(foreignHooksDir, hooksDir, "dir");
|
|
1664
|
+
},
|
|
1665
|
+
runner: ((_command, args) => {
|
|
1666
|
+
const encodedCommand = args[args.indexOf("-EncodedCommand") + 1];
|
|
1667
|
+
if (typeof encodedCommand !== "string") {
|
|
1668
|
+
throw new Error("PowerShell smoke must receive an encoded in-memory command");
|
|
1669
|
+
}
|
|
1670
|
+
assert.doesNotMatch(args.join("\u0000"), /(?:^|\u0000)-File(?:\u0000|$)/);
|
|
1671
|
+
const smokeCommand = Buffer.from(encodedCommand, "base64").toString("utf16le");
|
|
1672
|
+
assert.doesNotMatch(smokeCommand, /(?:^|\s)-File(?:\s|$)/);
|
|
1673
|
+
assert.equal(smokeCommand.includes(shimPath), false);
|
|
1674
|
+
assert.match(smokeCommand, /\[ScriptBlock\]::Create\(\$omxShimSource\)/);
|
|
1675
|
+
const encodedShimBytes = /FromBase64String\('([A-Za-z0-9+/=]+)'\)/.exec(smokeCommand)?.[1];
|
|
1676
|
+
if (encodedShimBytes === undefined) {
|
|
1677
|
+
throw new Error("encoded PowerShell smoke command omitted validated shim bytes");
|
|
1678
|
+
}
|
|
1679
|
+
assert.deepEqual(Buffer.from(encodedShimBytes, "base64"), Buffer.from(currentShim, "utf-8"));
|
|
1680
|
+
assert.equal(readFileSync(shimPath, "utf-8"), sentinel);
|
|
1681
|
+
assert.equal(readFileSync(foreignHardLinkPath, "utf-8"), sentinel);
|
|
1682
|
+
return { status: 0, stdout: "", stderr: "" };
|
|
1683
|
+
}),
|
|
1684
|
+
});
|
|
1685
|
+
assert.equal(check?.status, "pass");
|
|
1686
|
+
}
|
|
1687
|
+
finally {
|
|
1688
|
+
await rm(wd, { recursive: true, force: true });
|
|
1689
|
+
}
|
|
1690
|
+
});
|
|
1691
|
+
it("preserves a swapped Windows PostCompact smoke root instead of recursively deleting it", async () => {
|
|
1692
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-doctor-verbose-windows-smoke-root-"));
|
|
1693
|
+
let foreignSmokeCwd = null;
|
|
1694
|
+
let parkedSmokeCwd = null;
|
|
1695
|
+
try {
|
|
1696
|
+
const codexDir = join(wd, ".codex");
|
|
1697
|
+
const hooksPath = join(codexDir, "hooks.json");
|
|
1698
|
+
const hooksDir = join(codexDir, "hooks");
|
|
1699
|
+
const shimPath = join(hooksDir, "omx-native-hook-windows-shim.ps1");
|
|
1700
|
+
const command = buildWindowsShimCommand(shimPath);
|
|
1701
|
+
await mkdir(hooksDir, { recursive: true });
|
|
1702
|
+
await writeFile(hooksPath, buildWindowsShimHooksJson(shimPath, codexDir));
|
|
1703
|
+
await writeFile(shimPath, buildManagedCodexNativeHookWindowsShimContent(repoRoot()), "utf-8");
|
|
1704
|
+
const check = await checkNativePostCompactHookRuntime(hooksPath, wd, codexDir, {
|
|
1705
|
+
platform: "win32",
|
|
1706
|
+
expectedCommand: command,
|
|
1707
|
+
beforeWindowsShimSmoke: ({ smokeCwd }) => {
|
|
1708
|
+
foreignSmokeCwd = smokeCwd;
|
|
1709
|
+
},
|
|
1710
|
+
runner: (() => {
|
|
1711
|
+
const currentSmokeCwd = foreignSmokeCwd;
|
|
1712
|
+
if (currentSmokeCwd === null) {
|
|
1713
|
+
throw new Error("Windows smoke root was not captured before execution");
|
|
1714
|
+
}
|
|
1715
|
+
parkedSmokeCwd = `${currentSmokeCwd}-parked`;
|
|
1716
|
+
renameSync(currentSmokeCwd, parkedSmokeCwd);
|
|
1717
|
+
mkdirSync(currentSmokeCwd, { mode: 0o700 });
|
|
1718
|
+
writeFileSync(join(currentSmokeCwd, "foreign-sentinel.txt"), "foreign smoke root\n");
|
|
1719
|
+
return { status: 0, stdout: "", stderr: "" };
|
|
1720
|
+
}),
|
|
1721
|
+
});
|
|
1722
|
+
assert.equal(check?.status, "warn");
|
|
1723
|
+
assert.match(check?.message ?? "", /temporary PostCompact smoke directory changed during validation/);
|
|
1724
|
+
if (foreignSmokeCwd === null)
|
|
1725
|
+
assert.fail("Windows smoke root was not captured");
|
|
1726
|
+
assert.equal(readFileSync(join(foreignSmokeCwd, "foreign-sentinel.txt"), "utf-8"), "foreign smoke root\n");
|
|
1727
|
+
}
|
|
1728
|
+
finally {
|
|
1729
|
+
if (foreignSmokeCwd !== null)
|
|
1730
|
+
await rm(foreignSmokeCwd, { recursive: true, force: true });
|
|
1731
|
+
if (parkedSmokeCwd !== null)
|
|
1732
|
+
await rm(parkedSmokeCwd, { recursive: true, force: true });
|
|
1733
|
+
await rm(wd, { recursive: true, force: true });
|
|
1734
|
+
}
|
|
1735
|
+
});
|
|
1736
|
+
it("preserves a failed PostCompact smoke result when cleanup retains the smoke directory", async () => {
|
|
1737
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-doctor-postcompact-smoke-cleanup-failure-"));
|
|
1738
|
+
let smokeCwd = null;
|
|
1739
|
+
try {
|
|
1740
|
+
const codexDir = join(wd, ".codex");
|
|
1741
|
+
const hooksPath = join(codexDir, "hooks.json");
|
|
1742
|
+
const hooksDir = join(codexDir, "hooks");
|
|
1743
|
+
const shimPath = join(hooksDir, "omx-native-hook-windows-shim.ps1");
|
|
1744
|
+
const command = buildWindowsShimCommand(shimPath);
|
|
1745
|
+
await mkdir(hooksDir, { recursive: true });
|
|
1746
|
+
await writeFile(hooksPath, buildWindowsShimHooksJson(shimPath, codexDir));
|
|
1747
|
+
await writeFile(shimPath, buildManagedCodexNativeHookWindowsShimContent(repoRoot()), "utf-8");
|
|
1748
|
+
const check = await checkNativePostCompactHookRuntime(hooksPath, wd, codexDir, {
|
|
1749
|
+
platform: "win32",
|
|
1750
|
+
expectedCommand: command,
|
|
1751
|
+
beforeWindowsShimSmoke: ({ smokeCwd: currentSmokeCwd }) => {
|
|
1752
|
+
smokeCwd = currentSmokeCwd;
|
|
1753
|
+
},
|
|
1754
|
+
runner: (() => {
|
|
1755
|
+
if (smokeCwd === null) {
|
|
1756
|
+
throw new Error("Windows smoke root was not captured before execution");
|
|
1757
|
+
}
|
|
1758
|
+
writeFileSync(join(smokeCwd, "retained-sentinel.txt"), "retained smoke root\n");
|
|
1759
|
+
return { status: 1, stdout: "", stderr: "hook failure" };
|
|
1760
|
+
}),
|
|
1761
|
+
});
|
|
1762
|
+
assert.equal(check?.status, "fail");
|
|
1763
|
+
assert.match(check?.message ?? "", /PostCompact hook smoke validation exited 1: hook failure/);
|
|
1764
|
+
assert.match(check?.message ?? "", /temporary PostCompact smoke directory could not be removed without recursive deletion/);
|
|
1765
|
+
if (smokeCwd === null)
|
|
1766
|
+
assert.fail("Windows smoke root was not captured");
|
|
1767
|
+
assert.equal(readFileSync(join(smokeCwd, "retained-sentinel.txt"), "utf-8"), "retained smoke root\n");
|
|
1768
|
+
}
|
|
1769
|
+
finally {
|
|
1770
|
+
if (smokeCwd !== null)
|
|
1771
|
+
await rm(smokeCwd, { recursive: true, force: true });
|
|
1772
|
+
await rm(wd, { recursive: true, force: true });
|
|
1773
|
+
}
|
|
1774
|
+
});
|
|
1775
|
+
it("preserves a thrown PostCompact smoke error when cleanup also fails", async () => {
|
|
1776
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-doctor-postcompact-smoke-thrown-cleanup-"));
|
|
1777
|
+
let smokeCwd = null;
|
|
1778
|
+
try {
|
|
1779
|
+
const codexDir = join(wd, ".codex");
|
|
1780
|
+
const hooksPath = join(codexDir, "hooks.json");
|
|
1781
|
+
const hooksDir = join(codexDir, "hooks");
|
|
1782
|
+
const shimPath = join(hooksDir, "omx-native-hook-windows-shim.ps1");
|
|
1783
|
+
const command = buildWindowsShimCommand(shimPath);
|
|
1784
|
+
await mkdir(hooksDir, { recursive: true });
|
|
1785
|
+
await writeFile(hooksPath, buildWindowsShimHooksJson(shimPath, codexDir));
|
|
1786
|
+
await writeFile(shimPath, buildManagedCodexNativeHookWindowsShimContent(repoRoot()), "utf-8");
|
|
1787
|
+
await assert.rejects(checkNativePostCompactHookRuntime(hooksPath, wd, codexDir, {
|
|
1788
|
+
platform: "win32",
|
|
1789
|
+
expectedCommand: command,
|
|
1790
|
+
beforeWindowsShimSmoke: ({ smokeCwd: currentSmokeCwd }) => {
|
|
1791
|
+
smokeCwd = currentSmokeCwd;
|
|
1792
|
+
},
|
|
1793
|
+
runner: (() => {
|
|
1794
|
+
if (smokeCwd === null)
|
|
1795
|
+
throw new Error("Windows smoke root was not captured before execution");
|
|
1796
|
+
writeFileSync(join(smokeCwd, "retained-sentinel.txt"), "retained smoke root\n");
|
|
1797
|
+
throw new Error("primary spawn failure");
|
|
1798
|
+
}),
|
|
1799
|
+
}), /primary spawn failure; temporary PostCompact smoke directory could not be removed without recursive deletion/);
|
|
1800
|
+
}
|
|
1801
|
+
finally {
|
|
1802
|
+
if (smokeCwd !== null)
|
|
1803
|
+
await rm(smokeCwd, { recursive: true, force: true });
|
|
1804
|
+
await rm(wd, { recursive: true, force: true });
|
|
1805
|
+
}
|
|
1806
|
+
});
|
|
1807
|
+
it("reports exact nested legacy hook trust state as migration-required without modifying hooks.json", async () => {
|
|
1808
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-doctor-hooks-legacy-trust-"));
|
|
1809
|
+
try {
|
|
1810
|
+
const home = join(wd, "home");
|
|
1811
|
+
const codexDir = join(home, ".codex");
|
|
1812
|
+
await mkdir(codexDir, { recursive: true });
|
|
1813
|
+
const parsed = JSON.parse(buildHooksJsonWithPostCompactCommand(currentNativeHookCommand(codexDir), codexDir));
|
|
1814
|
+
parsed.hooks.state = {
|
|
1815
|
+
"custom:/hooks.json:stop:0:0": {
|
|
1816
|
+
trusted_hash: "sha256:legacy",
|
|
1817
|
+
enabled: false,
|
|
1818
|
+
},
|
|
1819
|
+
};
|
|
1820
|
+
const hooksPath = join(codexDir, "hooks.json");
|
|
1821
|
+
const original = `${JSON.stringify(parsed, null, 2)}\n`;
|
|
1822
|
+
await writeFile(hooksPath, original);
|
|
1823
|
+
const res = runOmx(wd, ["doctor"], { HOME: home, CODEX_HOME: codexDir });
|
|
1824
|
+
if (shouldSkipForSpawnPermissions(res.error))
|
|
1825
|
+
return;
|
|
1826
|
+
assert.equal(res.status, 0, res.stderr || res.stdout);
|
|
1827
|
+
assert.match(res.stdout, /\[!!\] Native hooks: hooks\.json contains 1 exact historical OMX hook trust-state entry that requires migration; run "omx setup" to migrate it after reviewing the configuration/);
|
|
1828
|
+
assert.doesNotMatch(res.stdout, /Native hooks: hooks\.json includes OMX-managed coverage/);
|
|
1829
|
+
assert.doesNotMatch(res.stdout, /Native hooks:.*--force/);
|
|
1830
|
+
assert.equal(await readFile(hooksPath, "utf-8"), original);
|
|
1831
|
+
}
|
|
1832
|
+
finally {
|
|
1833
|
+
await rm(wd, { recursive: true, force: true });
|
|
1834
|
+
}
|
|
1835
|
+
});
|
|
1836
|
+
it("preserves nonmatching nested hooks.state without reporting a migration", async () => {
|
|
1837
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-doctor-hooks-nonlegacy-state-"));
|
|
1838
|
+
try {
|
|
1839
|
+
const home = join(wd, "home");
|
|
1840
|
+
const codexDir = join(home, ".codex");
|
|
1841
|
+
await mkdir(codexDir, { recursive: true });
|
|
1842
|
+
const parsed = JSON.parse(buildHooksJsonWithPostCompactCommand(currentNativeHookCommand(codexDir), codexDir));
|
|
1843
|
+
parsed.hooks.state = {
|
|
1844
|
+
retained: { custom: true, trusted_hash: "sha256:not-omx" },
|
|
1845
|
+
};
|
|
1846
|
+
const hooksPath = join(codexDir, "hooks.json");
|
|
1847
|
+
const original = `${JSON.stringify(parsed, null, 2)}\n`;
|
|
1848
|
+
await writeFile(hooksPath, original);
|
|
1849
|
+
const res = runOmx(wd, ["doctor"], { HOME: home, CODEX_HOME: codexDir });
|
|
1850
|
+
if (shouldSkipForSpawnPermissions(res.error))
|
|
1851
|
+
return;
|
|
1852
|
+
assert.equal(res.status, 0, res.stderr || res.stdout);
|
|
1853
|
+
assert.match(res.stdout, /\[OK\] Native hooks: hooks\.json includes OMX-managed coverage for all native hook events/);
|
|
1854
|
+
assert.doesNotMatch(res.stdout, /Native hooks:.*legacy OMX hook trust-state/);
|
|
1855
|
+
assert.equal(await readFile(hooksPath, "utf-8"), original);
|
|
1313
1856
|
}
|
|
1314
1857
|
finally {
|
|
1315
1858
|
await rm(wd, { recursive: true, force: true });
|
|
@@ -1407,8 +1950,9 @@ command = "node"
|
|
|
1407
1950
|
assert.equal(check.name, "Native hook dist smoke");
|
|
1408
1951
|
assert.equal(check.status, "fail");
|
|
1409
1952
|
assert.match(check.message, /minimal UserPromptSubmit smoke/);
|
|
1410
|
-
assert.match(check.message, /
|
|
1411
|
-
assert.
|
|
1953
|
+
assert.match(check.message, /reinstall the matching oh-my-codex version/);
|
|
1954
|
+
assert.doesNotMatch(check.message, /--force/);
|
|
1955
|
+
assert.match(check.message, /run "omx setup"/);
|
|
1412
1956
|
}
|
|
1413
1957
|
finally {
|
|
1414
1958
|
await rm(wd, { recursive: true, force: true });
|
|
@@ -1489,7 +2033,7 @@ command = "node"
|
|
|
1489
2033
|
assert.equal(res.status, 0, res.stderr || res.stdout);
|
|
1490
2034
|
assert.match(res.stdout, /Resolved setup scope: project \(from \.omx\/setup-scope\.json\)/);
|
|
1491
2035
|
assert.equal(res.stdout.match(/\[!!\] GPT-5\.6 multi-agent compatibility:/g)?.length, 1);
|
|
1492
|
-
assert.match(res.stdout, new RegExp(`project scope config at ${
|
|
2036
|
+
assert.match(res.stdout, new RegExp(`project scope config at ${join(await realpath(wd), ".codex", "config.toml")}`));
|
|
1493
2037
|
assert.match(res.stdout, /features\.multi_agent \(custom; custom-value\)/);
|
|
1494
2038
|
assert.match(res.stdout, /agents\.max_threads \(custom; custom-value\)/);
|
|
1495
2039
|
assert.match(res.stdout, /agents\.max_depth \(custom; custom-value\)/);
|
|
@@ -1526,5 +2070,198 @@ command = "node"
|
|
|
1526
2070
|
await rm(wd, { recursive: true, force: true });
|
|
1527
2071
|
}
|
|
1528
2072
|
});
|
|
2073
|
+
it("validates an existing global hooks.json before reporting plugin-cache status", async () => {
|
|
2074
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-doctor-plugin-global-invalid-"));
|
|
2075
|
+
try {
|
|
2076
|
+
const codexDir = join(wd, ".codex");
|
|
2077
|
+
const configPath = join(codexDir, "config.toml");
|
|
2078
|
+
const hooksPath = join(codexDir, "hooks.json");
|
|
2079
|
+
await mkdir(codexDir, { recursive: true });
|
|
2080
|
+
await writeFile(configPath, "plugin_hooks = true\n");
|
|
2081
|
+
await writeFile(hooksPath, '{"state":{}}\n');
|
|
2082
|
+
const check = await checkNativeHooks(hooksPath, configPath, {
|
|
2083
|
+
codexHomeDir: codexDir,
|
|
2084
|
+
installMode: "plugin",
|
|
2085
|
+
});
|
|
2086
|
+
assert.equal(check.status, "fail");
|
|
2087
|
+
assert.match(check.message, /plugin-scoped hooks are enabled/);
|
|
2088
|
+
assert.match(check.message, /existing global hooks\.json: hooks\.json failed strict load validation/);
|
|
2089
|
+
assert.match(check.message, /unknown root field state/);
|
|
2090
|
+
}
|
|
2091
|
+
finally {
|
|
2092
|
+
await rm(wd, { recursive: true, force: true });
|
|
2093
|
+
}
|
|
2094
|
+
});
|
|
2095
|
+
it("fails plugin mode when an existing global Windows shim is tampered", async () => {
|
|
2096
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-doctor-plugin-global-shim-"));
|
|
2097
|
+
try {
|
|
2098
|
+
const codexDir = join(wd, ".codex");
|
|
2099
|
+
const configPath = join(codexDir, "config.toml");
|
|
2100
|
+
const hooksPath = join(codexDir, "hooks.json");
|
|
2101
|
+
const shimPath = join(codexDir, "hooks", "omx-native-hook-windows-shim.ps1");
|
|
2102
|
+
await mkdir(dirname(shimPath), { recursive: true });
|
|
2103
|
+
await writeFile(configPath, "plugin_hooks = true\n");
|
|
2104
|
+
await writeFile(hooksPath, `${JSON.stringify({
|
|
2105
|
+
hooks: {
|
|
2106
|
+
PostCompact: [{ hooks: [{ type: "command", command: buildWindowsShimCommand(shimPath) }] }],
|
|
2107
|
+
},
|
|
2108
|
+
})}\n`);
|
|
2109
|
+
await writeFile(shimPath, "# modified\n");
|
|
2110
|
+
const check = await checkNativeHooks(hooksPath, configPath, {
|
|
2111
|
+
codexHomeDir: codexDir,
|
|
2112
|
+
installMode: "plugin",
|
|
2113
|
+
platform: "win32",
|
|
2114
|
+
});
|
|
2115
|
+
assert.equal(check.status, "fail");
|
|
2116
|
+
assert.match(check.message, /not an exact current or complete historical generated shim/);
|
|
2117
|
+
assert.match(check.message, /plugin-scoped hooks are enabled/);
|
|
2118
|
+
}
|
|
2119
|
+
finally {
|
|
2120
|
+
await rm(wd, { recursive: true, force: true });
|
|
2121
|
+
}
|
|
2122
|
+
});
|
|
2123
|
+
it("fails ambiguous managed handler ownership instead of downgrading it to a warning", async () => {
|
|
2124
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-doctor-ambiguous-managed-handler-"));
|
|
2125
|
+
try {
|
|
2126
|
+
const codexDir = join(wd, ".codex");
|
|
2127
|
+
const hooksPath = join(codexDir, "hooks.json");
|
|
2128
|
+
await mkdir(codexDir, { recursive: true });
|
|
2129
|
+
await writeFile(hooksPath, `${JSON.stringify({
|
|
2130
|
+
hooks: {
|
|
2131
|
+
SessionStart: [{
|
|
2132
|
+
matcher: "startup|resume|clear",
|
|
2133
|
+
hooks: [{ type: "command", command: "node /repo/dist/scripts/codex-native-hook.js --unexpected" }],
|
|
2134
|
+
}],
|
|
2135
|
+
},
|
|
2136
|
+
})}\n`);
|
|
2137
|
+
const check = await checkNativeHooks(hooksPath, join(codexDir, "config.toml"), {
|
|
2138
|
+
codexHomeDir: codexDir,
|
|
2139
|
+
});
|
|
2140
|
+
assert.equal(check.status, "fail");
|
|
2141
|
+
assert.match(check.message, /ambiguous_managed_handler/);
|
|
2142
|
+
assert.match(check.message, /ambiguous or untrusted OMX ownership/);
|
|
2143
|
+
}
|
|
2144
|
+
finally {
|
|
2145
|
+
await rm(wd, { recursive: true, force: true });
|
|
2146
|
+
}
|
|
2147
|
+
});
|
|
2148
|
+
it("fails closed instead of recognizing a shell-expanding foreign command as an OMX hook", async () => {
|
|
2149
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-doctor-shell-expanding-handler-"));
|
|
2150
|
+
try {
|
|
2151
|
+
const codexDir = join(wd, ".codex");
|
|
2152
|
+
const hooksPath = join(codexDir, "hooks.json");
|
|
2153
|
+
await mkdir(codexDir, { recursive: true });
|
|
2154
|
+
await writeFile(hooksPath, `${JSON.stringify({
|
|
2155
|
+
hooks: {
|
|
2156
|
+
SessionStart: [{
|
|
2157
|
+
matcher: "startup|resume|clear",
|
|
2158
|
+
hooks: [{ type: "command", command: 'node "$HOME/repo/dist/scripts/codex-native-hook.js"' }],
|
|
2159
|
+
}],
|
|
2160
|
+
},
|
|
2161
|
+
})}\n`);
|
|
2162
|
+
const check = await checkNativeHooks(hooksPath, join(codexDir, "config.toml"), {
|
|
2163
|
+
codexHomeDir: codexDir,
|
|
2164
|
+
});
|
|
2165
|
+
assert.equal(check.status, "fail");
|
|
2166
|
+
assert.match(check.message, /ambiguous_managed_handler|does not match the managed command grammar/i);
|
|
2167
|
+
}
|
|
2168
|
+
finally {
|
|
2169
|
+
await rm(wd, { recursive: true, force: true });
|
|
2170
|
+
}
|
|
2171
|
+
});
|
|
2172
|
+
it("ignores prompt, agent, and future-event metadata while scanning Windows shim references", async () => {
|
|
2173
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-doctor-inert-shim-metadata-"));
|
|
2174
|
+
try {
|
|
2175
|
+
const codexDir = join(wd, ".codex");
|
|
2176
|
+
const hooksPath = join(codexDir, "hooks.json");
|
|
2177
|
+
const missingShimPath = join(codexDir, "hooks", "omx-native-hook-windows-shim.ps1");
|
|
2178
|
+
await mkdir(codexDir, { recursive: true });
|
|
2179
|
+
await writeFile(hooksPath, `${JSON.stringify({
|
|
2180
|
+
hooks: {
|
|
2181
|
+
PostCompact: [{ hooks: [
|
|
2182
|
+
{ type: "prompt", command: buildWindowsShimCommand(missingShimPath) },
|
|
2183
|
+
{ type: "agent", commandWindows: buildWindowsShimCommand(missingShimPath) },
|
|
2184
|
+
] }],
|
|
2185
|
+
FutureSerdeEvent: [{ hooks: [{ type: "command", command: buildWindowsShimCommand(missingShimPath) }] }],
|
|
2186
|
+
},
|
|
2187
|
+
})}\n`);
|
|
2188
|
+
const check = await checkNativeHooks(hooksPath, join(codexDir, "config.toml"), {
|
|
2189
|
+
codexHomeDir: codexDir,
|
|
2190
|
+
platform: "win32",
|
|
2191
|
+
});
|
|
2192
|
+
assert.equal(check.status, "warn");
|
|
2193
|
+
assert.match(check.message, /hooks\.json discovery warnings/);
|
|
2194
|
+
assert.doesNotMatch(check.message, /referenced Windows native hook shim/);
|
|
2195
|
+
}
|
|
2196
|
+
finally {
|
|
2197
|
+
await rm(wd, { recursive: true, force: true });
|
|
2198
|
+
}
|
|
2199
|
+
});
|
|
2200
|
+
it("recovers a claim journal after Windows regular-file EPERM with one degraded-durability warning", async () => {
|
|
2201
|
+
const originalStderrWrite = process.stderr.write;
|
|
2202
|
+
const stderr = [];
|
|
2203
|
+
try {
|
|
2204
|
+
await withRecoverableDoctorClaimJournal(async (codexHomeDir) => {
|
|
2205
|
+
const restoreDurability = setDoctorClaimJournalDurabilityForTest({
|
|
2206
|
+
platform: "win32",
|
|
2207
|
+
syncRegularFile: async () => syncRegularFile({
|
|
2208
|
+
sync: async () => {
|
|
2209
|
+
throw Object.assign(new Error("injected Windows EPERM"), { code: "EPERM" });
|
|
2210
|
+
},
|
|
2211
|
+
}, "win32"),
|
|
2212
|
+
syncDirectory: async () => undefined,
|
|
2213
|
+
});
|
|
2214
|
+
process.stderr.write = ((chunk) => {
|
|
2215
|
+
stderr.push(String(chunk));
|
|
2216
|
+
return true;
|
|
2217
|
+
});
|
|
2218
|
+
try {
|
|
2219
|
+
await doctor();
|
|
2220
|
+
assert.equal(await readFile(join(codexHomeDir, "hooks.json"), "utf-8"), "{\"hooks\":{}}\n");
|
|
2221
|
+
await assert.rejects(readFile(join(codexHomeDir, ".omx", "native-hook-claim-journal.json")), /ENOENT/);
|
|
2222
|
+
}
|
|
2223
|
+
finally {
|
|
2224
|
+
restoreDurability();
|
|
2225
|
+
}
|
|
2226
|
+
});
|
|
2227
|
+
assert.equal(stderr.length, 1);
|
|
2228
|
+
assert.match(stderr[0], /Windows EPERM/);
|
|
2229
|
+
assert.match(stderr[0], /native-hook claim-journal recovery/);
|
|
2230
|
+
assert.match(stderr[0], /degraded durability/);
|
|
2231
|
+
}
|
|
2232
|
+
finally {
|
|
2233
|
+
process.stderr.write = originalStderrWrite;
|
|
2234
|
+
}
|
|
2235
|
+
});
|
|
2236
|
+
it("keeps non-EPERM regular-file and directory claim-journal sync failures fatal", async () => {
|
|
2237
|
+
const regularError = Object.assign(new Error("injected regular-file EIO"), { code: "EIO" });
|
|
2238
|
+
await withRecoverableDoctorClaimJournal(async () => {
|
|
2239
|
+
const restoreDurability = setDoctorClaimJournalDurabilityForTest({
|
|
2240
|
+
platform: "win32",
|
|
2241
|
+
syncRegularFile: async () => { throw regularError; },
|
|
2242
|
+
syncDirectory: async () => undefined,
|
|
2243
|
+
});
|
|
2244
|
+
try {
|
|
2245
|
+
await assert.rejects(doctor(), (error) => error === regularError);
|
|
2246
|
+
}
|
|
2247
|
+
finally {
|
|
2248
|
+
restoreDurability();
|
|
2249
|
+
}
|
|
2250
|
+
});
|
|
2251
|
+
const directoryError = Object.assign(new Error("injected directory EPERM"), { code: "EPERM" });
|
|
2252
|
+
await withRecoverableDoctorClaimJournal(async () => {
|
|
2253
|
+
const restoreDurability = setDoctorClaimJournalDurabilityForTest({
|
|
2254
|
+
platform: "win32",
|
|
2255
|
+
syncRegularFile: async () => "synced",
|
|
2256
|
+
syncDirectory: async () => { throw directoryError; },
|
|
2257
|
+
});
|
|
2258
|
+
try {
|
|
2259
|
+
await assert.rejects(doctor(), (error) => error === directoryError);
|
|
2260
|
+
}
|
|
2261
|
+
finally {
|
|
2262
|
+
restoreDurability();
|
|
2263
|
+
}
|
|
2264
|
+
});
|
|
2265
|
+
});
|
|
1529
2266
|
});
|
|
1530
2267
|
//# sourceMappingURL=doctor-warning-copy.test.js.map
|