oh-my-codex-pennix 0.18.13
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/.agents/plugins/marketplace.json +20 -0
- package/Cargo.lock +185 -0
- package/Cargo.toml +24 -0
- package/README.md +445 -0
- package/crates/omx-api/Cargo.toml +19 -0
- package/crates/omx-api/src/lib.rs +2997 -0
- package/crates/omx-api/src/main.rs +10 -0
- package/crates/omx-api/tests/cli.rs +558 -0
- package/crates/omx-explore/Cargo.toml +14 -0
- package/crates/omx-explore/src/main.rs +2972 -0
- package/crates/omx-mux/Cargo.toml +11 -0
- package/crates/omx-mux/src/lib.rs +91 -0
- package/crates/omx-mux/src/tmux.rs +282 -0
- package/crates/omx-mux/src/types.rs +306 -0
- package/crates/omx-runtime/Cargo.toml +13 -0
- package/crates/omx-runtime/src/main.rs +125 -0
- package/crates/omx-runtime/tests/execution.rs +212 -0
- package/crates/omx-runtime-core/Cargo.toml +13 -0
- package/crates/omx-runtime-core/src/authority.rs +239 -0
- package/crates/omx-runtime-core/src/dispatch.rs +330 -0
- package/crates/omx-runtime-core/src/engine.rs +853 -0
- package/crates/omx-runtime-core/src/lib.rs +653 -0
- package/crates/omx-runtime-core/src/mailbox.rs +261 -0
- package/crates/omx-runtime-core/src/replay.rs +104 -0
- package/crates/omx-sparkshell/Cargo.lock +7 -0
- package/crates/omx-sparkshell/Cargo.toml +14 -0
- package/crates/omx-sparkshell/src/codex_bridge.rs +768 -0
- package/crates/omx-sparkshell/src/error.rs +45 -0
- package/crates/omx-sparkshell/src/exec.rs +241 -0
- package/crates/omx-sparkshell/src/main.rs +1133 -0
- package/crates/omx-sparkshell/src/prompt.rs +364 -0
- package/crates/omx-sparkshell/src/redaction.rs +241 -0
- package/crates/omx-sparkshell/src/registry/c_cpp.rs +9 -0
- package/crates/omx-sparkshell/src/registry/csharp.rs +10 -0
- package/crates/omx-sparkshell/src/registry/generic_shell.rs +11 -0
- package/crates/omx-sparkshell/src/registry/git.rs +10 -0
- package/crates/omx-sparkshell/src/registry/go.rs +9 -0
- package/crates/omx-sparkshell/src/registry/java_kotlin.rs +9 -0
- package/crates/omx-sparkshell/src/registry/mod.rs +85 -0
- package/crates/omx-sparkshell/src/registry/node_js.rs +9 -0
- package/crates/omx-sparkshell/src/registry/python.rs +9 -0
- package/crates/omx-sparkshell/src/registry/ruby.rs +9 -0
- package/crates/omx-sparkshell/src/registry/rust.rs +9 -0
- package/crates/omx-sparkshell/src/registry/swift.rs +10 -0
- package/crates/omx-sparkshell/src/test_support.rs +10 -0
- package/crates/omx-sparkshell/src/threshold.rs +75 -0
- package/crates/omx-sparkshell/tests/execution.rs +986 -0
- package/crates/omx-sparkshell/tests/registry.rs +99 -0
- package/dist/adapt/__tests__/foundation.test.d.ts +2 -0
- package/dist/adapt/__tests__/foundation.test.d.ts.map +1 -0
- package/dist/adapt/__tests__/foundation.test.js +171 -0
- package/dist/adapt/__tests__/foundation.test.js.map +1 -0
- package/dist/adapt/__tests__/hermes.test.d.ts +2 -0
- package/dist/adapt/__tests__/hermes.test.d.ts.map +1 -0
- package/dist/adapt/__tests__/hermes.test.js +137 -0
- package/dist/adapt/__tests__/hermes.test.js.map +1 -0
- package/dist/adapt/contracts.d.ts +157 -0
- package/dist/adapt/contracts.d.ts.map +1 -0
- package/dist/adapt/contracts.js +10 -0
- package/dist/adapt/contracts.js.map +1 -0
- package/dist/adapt/hermes.d.ts +83 -0
- package/dist/adapt/hermes.d.ts.map +1 -0
- package/dist/adapt/hermes.js +371 -0
- package/dist/adapt/hermes.js.map +1 -0
- package/dist/adapt/index.d.ts +14 -0
- package/dist/adapt/index.d.ts.map +1 -0
- package/dist/adapt/index.js +293 -0
- package/dist/adapt/index.js.map +1 -0
- package/dist/adapt/openclaw.d.ts +7 -0
- package/dist/adapt/openclaw.d.ts.map +1 -0
- package/dist/adapt/openclaw.js +299 -0
- package/dist/adapt/openclaw.js.map +1 -0
- package/dist/adapt/paths.d.ts +3 -0
- package/dist/adapt/paths.d.ts.map +1 -0
- package/dist/adapt/paths.js +15 -0
- package/dist/adapt/paths.js.map +1 -0
- package/dist/adapt/registry.d.ts +4 -0
- package/dist/adapt/registry.d.ts.map +1 -0
- package/dist/adapt/registry.js +48 -0
- package/dist/adapt/registry.js.map +1 -0
- package/dist/agents/__tests__/definitions.test.d.ts +2 -0
- package/dist/agents/__tests__/definitions.test.d.ts.map +1 -0
- package/dist/agents/__tests__/definitions.test.js +96 -0
- package/dist/agents/__tests__/definitions.test.js.map +1 -0
- package/dist/agents/__tests__/native-config.test.d.ts +2 -0
- package/dist/agents/__tests__/native-config.test.d.ts.map +1 -0
- package/dist/agents/__tests__/native-config.test.js +398 -0
- package/dist/agents/__tests__/native-config.test.js.map +1 -0
- package/dist/agents/definitions.d.ts +35 -0
- package/dist/agents/definitions.d.ts.map +1 -0
- package/dist/agents/definitions.js +371 -0
- package/dist/agents/definitions.js.map +1 -0
- package/dist/agents/native-config.d.ts +56 -0
- package/dist/agents/native-config.d.ts.map +1 -0
- package/dist/agents/native-config.js +285 -0
- package/dist/agents/native-config.js.map +1 -0
- package/dist/agents/policy.d.ts +10 -0
- package/dist/agents/policy.d.ts.map +1 -0
- package/dist/agents/policy.js +61 -0
- package/dist/agents/policy.js.map +1 -0
- package/dist/auth/__tests__/config-sessions.test.d.ts +2 -0
- package/dist/auth/__tests__/config-sessions.test.d.ts.map +1 -0
- package/dist/auth/__tests__/config-sessions.test.js +48 -0
- package/dist/auth/__tests__/config-sessions.test.js.map +1 -0
- package/dist/auth/__tests__/quota-rotation.test.d.ts +2 -0
- package/dist/auth/__tests__/quota-rotation.test.d.ts.map +1 -0
- package/dist/auth/__tests__/quota-rotation.test.js +33 -0
- package/dist/auth/__tests__/quota-rotation.test.js.map +1 -0
- package/dist/auth/__tests__/redact.test.d.ts +2 -0
- package/dist/auth/__tests__/redact.test.d.ts.map +1 -0
- package/dist/auth/__tests__/redact.test.js +20 -0
- package/dist/auth/__tests__/redact.test.js.map +1 -0
- package/dist/auth/__tests__/storage.test.d.ts +2 -0
- package/dist/auth/__tests__/storage.test.d.ts.map +1 -0
- package/dist/auth/__tests__/storage.test.js +108 -0
- package/dist/auth/__tests__/storage.test.js.map +1 -0
- package/dist/auth/config.d.ts +9 -0
- package/dist/auth/config.d.ts.map +1 -0
- package/dist/auth/config.js +77 -0
- package/dist/auth/config.js.map +1 -0
- package/dist/auth/hotswap.d.ts +36 -0
- package/dist/auth/hotswap.d.ts.map +1 -0
- package/dist/auth/hotswap.js +159 -0
- package/dist/auth/hotswap.js.map +1 -0
- package/dist/auth/index.d.ts +8 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +8 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/paths.d.ts +12 -0
- package/dist/auth/paths.d.ts.map +1 -0
- package/dist/auth/paths.js +78 -0
- package/dist/auth/paths.js.map +1 -0
- package/dist/auth/quota-detector.d.ts +10 -0
- package/dist/auth/quota-detector.d.ts.map +1 -0
- package/dist/auth/quota-detector.js +40 -0
- package/dist/auth/quota-detector.js.map +1 -0
- package/dist/auth/redact.d.ts +2 -0
- package/dist/auth/redact.d.ts.map +1 -0
- package/dist/auth/redact.js +26 -0
- package/dist/auth/redact.js.map +1 -0
- package/dist/auth/rotation.d.ts +9 -0
- package/dist/auth/rotation.d.ts.map +1 -0
- package/dist/auth/rotation.js +26 -0
- package/dist/auth/rotation.js.map +1 -0
- package/dist/auth/sessions.d.ts +15 -0
- package/dist/auth/sessions.d.ts.map +1 -0
- package/dist/auth/sessions.js +62 -0
- package/dist/auth/sessions.js.map +1 -0
- package/dist/auth/storage.d.ts +27 -0
- package/dist/auth/storage.d.ts.map +1 -0
- package/dist/auth/storage.js +111 -0
- package/dist/auth/storage.js.map +1 -0
- package/dist/autopilot/__tests__/deep-interview-gate.test.d.ts +2 -0
- package/dist/autopilot/__tests__/deep-interview-gate.test.d.ts.map +1 -0
- package/dist/autopilot/__tests__/deep-interview-gate.test.js +215 -0
- package/dist/autopilot/__tests__/deep-interview-gate.test.js.map +1 -0
- package/dist/autopilot/__tests__/fsm.test.d.ts +2 -0
- package/dist/autopilot/__tests__/fsm.test.d.ts.map +1 -0
- package/dist/autopilot/__tests__/fsm.test.js +78 -0
- package/dist/autopilot/__tests__/fsm.test.js.map +1 -0
- package/dist/autopilot/__tests__/ralplan-gate.test.d.ts +2 -0
- package/dist/autopilot/__tests__/ralplan-gate.test.d.ts.map +1 -0
- package/dist/autopilot/__tests__/ralplan-gate.test.js +274 -0
- package/dist/autopilot/__tests__/ralplan-gate.test.js.map +1 -0
- package/dist/autopilot/completion-gate.d.ts +10 -0
- package/dist/autopilot/completion-gate.d.ts.map +1 -0
- package/dist/autopilot/completion-gate.js +154 -0
- package/dist/autopilot/completion-gate.js.map +1 -0
- package/dist/autopilot/deep-interview-gate.d.ts +18 -0
- package/dist/autopilot/deep-interview-gate.d.ts.map +1 -0
- package/dist/autopilot/deep-interview-gate.js +396 -0
- package/dist/autopilot/deep-interview-gate.js.map +1 -0
- package/dist/autopilot/fsm.d.ts +13 -0
- package/dist/autopilot/fsm.d.ts.map +1 -0
- package/dist/autopilot/fsm.js +70 -0
- package/dist/autopilot/fsm.js.map +1 -0
- package/dist/autopilot/ralplan-gate.d.ts +17 -0
- package/dist/autopilot/ralplan-gate.d.ts.map +1 -0
- package/dist/autopilot/ralplan-gate.js +68 -0
- package/dist/autopilot/ralplan-gate.js.map +1 -0
- package/dist/autoresearch/__tests__/contracts.test.d.ts +2 -0
- package/dist/autoresearch/__tests__/contracts.test.d.ts.map +1 -0
- package/dist/autoresearch/__tests__/contracts.test.js +127 -0
- package/dist/autoresearch/__tests__/contracts.test.js.map +1 -0
- package/dist/autoresearch/__tests__/runtime-parity-extra.test.d.ts +2 -0
- package/dist/autoresearch/__tests__/runtime-parity-extra.test.d.ts.map +1 -0
- package/dist/autoresearch/__tests__/runtime-parity-extra.test.js +349 -0
- package/dist/autoresearch/__tests__/runtime-parity-extra.test.js.map +1 -0
- package/dist/autoresearch/__tests__/runtime.test.d.ts +2 -0
- package/dist/autoresearch/__tests__/runtime.test.d.ts.map +1 -0
- package/dist/autoresearch/__tests__/runtime.test.js +211 -0
- package/dist/autoresearch/__tests__/runtime.test.js.map +1 -0
- package/dist/autoresearch/__tests__/skill-validation.test.d.ts +2 -0
- package/dist/autoresearch/__tests__/skill-validation.test.d.ts.map +1 -0
- package/dist/autoresearch/__tests__/skill-validation.test.js +91 -0
- package/dist/autoresearch/__tests__/skill-validation.test.js.map +1 -0
- package/dist/autoresearch/contracts.d.ts +31 -0
- package/dist/autoresearch/contracts.d.ts.map +1 -0
- package/dist/autoresearch/contracts.js +197 -0
- package/dist/autoresearch/contracts.js.map +1 -0
- package/dist/autoresearch/goal.d.ts +90 -0
- package/dist/autoresearch/goal.d.ts.map +1 -0
- package/dist/autoresearch/goal.js +237 -0
- package/dist/autoresearch/goal.js.map +1 -0
- package/dist/autoresearch/runtime.d.ts +132 -0
- package/dist/autoresearch/runtime.d.ts.map +1 -0
- package/dist/autoresearch/runtime.js +1022 -0
- package/dist/autoresearch/runtime.js.map +1 -0
- package/dist/autoresearch/skill-validation.d.ts +14 -0
- package/dist/autoresearch/skill-validation.d.ts.map +1 -0
- package/dist/autoresearch/skill-validation.js +172 -0
- package/dist/autoresearch/skill-validation.js.map +1 -0
- package/dist/catalog/__tests__/generator.test.d.ts +2 -0
- package/dist/catalog/__tests__/generator.test.d.ts.map +1 -0
- package/dist/catalog/__tests__/generator.test.js +60 -0
- package/dist/catalog/__tests__/generator.test.js.map +1 -0
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.d.ts +2 -0
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.d.ts.map +1 -0
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.js +108 -0
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.js.map +1 -0
- package/dist/catalog/__tests__/schema.test.d.ts +2 -0
- package/dist/catalog/__tests__/schema.test.d.ts.map +1 -0
- package/dist/catalog/__tests__/schema.test.js +84 -0
- package/dist/catalog/__tests__/schema.test.js.map +1 -0
- package/dist/catalog/installable.d.ts +5 -0
- package/dist/catalog/installable.d.ts.map +1 -0
- package/dist/catalog/installable.js +13 -0
- package/dist/catalog/installable.js.map +1 -0
- package/dist/catalog/reader.d.ts +19 -0
- package/dist/catalog/reader.d.ts.map +1 -0
- package/dist/catalog/reader.js +63 -0
- package/dist/catalog/reader.js.map +1 -0
- package/dist/catalog/schema.d.ts +32 -0
- package/dist/catalog/schema.d.ts.map +1 -0
- package/dist/catalog/schema.js +107 -0
- package/dist/catalog/schema.js.map +1 -0
- package/dist/catalog/skill-mirror.d.ts +20 -0
- package/dist/catalog/skill-mirror.d.ts.map +1 -0
- package/dist/catalog/skill-mirror.js +104 -0
- package/dist/catalog/skill-mirror.js.map +1 -0
- package/dist/cli/__tests__/adapt-help.test.d.ts +2 -0
- package/dist/cli/__tests__/adapt-help.test.d.ts.map +1 -0
- package/dist/cli/__tests__/adapt-help.test.js +39 -0
- package/dist/cli/__tests__/adapt-help.test.js.map +1 -0
- package/dist/cli/__tests__/adapt.test.d.ts +2 -0
- package/dist/cli/__tests__/adapt.test.d.ts.map +1 -0
- package/dist/cli/__tests__/adapt.test.js +62 -0
- package/dist/cli/__tests__/adapt.test.js.map +1 -0
- package/dist/cli/__tests__/agents-init.test.d.ts +2 -0
- package/dist/cli/__tests__/agents-init.test.d.ts.map +1 -0
- package/dist/cli/__tests__/agents-init.test.js +184 -0
- package/dist/cli/__tests__/agents-init.test.js.map +1 -0
- package/dist/cli/__tests__/agents.test.d.ts +2 -0
- package/dist/cli/__tests__/agents.test.d.ts.map +1 -0
- package/dist/cli/__tests__/agents.test.js +137 -0
- package/dist/cli/__tests__/agents.test.js.map +1 -0
- package/dist/cli/__tests__/api.test.d.ts +2 -0
- package/dist/cli/__tests__/api.test.d.ts.map +1 -0
- package/dist/cli/__tests__/api.test.js +175 -0
- package/dist/cli/__tests__/api.test.js.map +1 -0
- package/dist/cli/__tests__/ask.test.d.ts +2 -0
- package/dist/cli/__tests__/ask.test.d.ts.map +1 -0
- package/dist/cli/__tests__/ask.test.js +332 -0
- package/dist/cli/__tests__/ask.test.js.map +1 -0
- package/dist/cli/__tests__/auth.test.d.ts +2 -0
- package/dist/cli/__tests__/auth.test.d.ts.map +1 -0
- package/dist/cli/__tests__/auth.test.js +203 -0
- package/dist/cli/__tests__/auth.test.js.map +1 -0
- package/dist/cli/__tests__/autoresearch-goal.test.d.ts +2 -0
- package/dist/cli/__tests__/autoresearch-goal.test.d.ts.map +1 -0
- package/dist/cli/__tests__/autoresearch-goal.test.js +207 -0
- package/dist/cli/__tests__/autoresearch-goal.test.js.map +1 -0
- package/dist/cli/__tests__/autoresearch-guided.test.d.ts +2 -0
- package/dist/cli/__tests__/autoresearch-guided.test.d.ts.map +1 -0
- package/dist/cli/__tests__/autoresearch-guided.test.js +365 -0
- package/dist/cli/__tests__/autoresearch-guided.test.js.map +1 -0
- package/dist/cli/__tests__/autoresearch.test.d.ts +2 -0
- package/dist/cli/__tests__/autoresearch.test.d.ts.map +1 -0
- package/dist/cli/__tests__/autoresearch.test.js +155 -0
- package/dist/cli/__tests__/autoresearch.test.js.map +1 -0
- package/dist/cli/__tests__/catalog-contract.test.d.ts +2 -0
- package/dist/cli/__tests__/catalog-contract.test.d.ts.map +1 -0
- package/dist/cli/__tests__/catalog-contract.test.js +18 -0
- package/dist/cli/__tests__/catalog-contract.test.js.map +1 -0
- package/dist/cli/__tests__/cleanup.test.d.ts +2 -0
- package/dist/cli/__tests__/cleanup.test.d.ts.map +1 -0
- package/dist/cli/__tests__/cleanup.test.js +527 -0
- package/dist/cli/__tests__/cleanup.test.js.map +1 -0
- package/dist/cli/__tests__/codex-feature-probe.test.d.ts +2 -0
- package/dist/cli/__tests__/codex-feature-probe.test.d.ts.map +1 -0
- package/dist/cli/__tests__/codex-feature-probe.test.js +46 -0
- package/dist/cli/__tests__/codex-feature-probe.test.js.map +1 -0
- package/dist/cli/__tests__/codex-plugin-layout.test.d.ts +2 -0
- package/dist/cli/__tests__/codex-plugin-layout.test.d.ts.map +1 -0
- package/dist/cli/__tests__/codex-plugin-layout.test.js +778 -0
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -0
- package/dist/cli/__tests__/doctor-context-window-warning.test.d.ts +2 -0
- package/dist/cli/__tests__/doctor-context-window-warning.test.d.ts.map +1 -0
- package/dist/cli/__tests__/doctor-context-window-warning.test.js +122 -0
- package/dist/cli/__tests__/doctor-context-window-warning.test.js.map +1 -0
- package/dist/cli/__tests__/doctor-invalid-config.test.d.ts +2 -0
- package/dist/cli/__tests__/doctor-invalid-config.test.d.ts.map +1 -0
- package/dist/cli/__tests__/doctor-invalid-config.test.js +52 -0
- package/dist/cli/__tests__/doctor-invalid-config.test.js.map +1 -0
- package/dist/cli/__tests__/doctor-spark-routing.test.d.ts +2 -0
- package/dist/cli/__tests__/doctor-spark-routing.test.d.ts.map +1 -0
- package/dist/cli/__tests__/doctor-spark-routing.test.js +79 -0
- package/dist/cli/__tests__/doctor-spark-routing.test.js.map +1 -0
- package/dist/cli/__tests__/doctor-team.test.d.ts +2 -0
- package/dist/cli/__tests__/doctor-team.test.d.ts.map +1 -0
- package/dist/cli/__tests__/doctor-team.test.js +299 -0
- package/dist/cli/__tests__/doctor-team.test.js.map +1 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.d.ts +2 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.d.ts.map +1 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.js +1312 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -0
- package/dist/cli/__tests__/error-handling-warnings.test.d.ts +2 -0
- package/dist/cli/__tests__/error-handling-warnings.test.d.ts.map +1 -0
- package/dist/cli/__tests__/error-handling-warnings.test.js +52 -0
- package/dist/cli/__tests__/error-handling-warnings.test.js.map +1 -0
- package/dist/cli/__tests__/exec.test.d.ts +2 -0
- package/dist/cli/__tests__/exec.test.d.ts.map +1 -0
- package/dist/cli/__tests__/exec.test.js +213 -0
- package/dist/cli/__tests__/exec.test.js.map +1 -0
- package/dist/cli/__tests__/explore-windows-diagnostics.test.d.ts +2 -0
- package/dist/cli/__tests__/explore-windows-diagnostics.test.d.ts.map +1 -0
- package/dist/cli/__tests__/explore-windows-diagnostics.test.js +17 -0
- package/dist/cli/__tests__/explore-windows-diagnostics.test.js.map +1 -0
- package/dist/cli/__tests__/explore.test.d.ts +2 -0
- package/dist/cli/__tests__/explore.test.d.ts.map +1 -0
- package/dist/cli/__tests__/explore.test.js +104 -0
- package/dist/cli/__tests__/explore.test.js.map +1 -0
- package/dist/cli/__tests__/hooks.test.d.ts +2 -0
- package/dist/cli/__tests__/hooks.test.d.ts.map +1 -0
- package/dist/cli/__tests__/hooks.test.js +55 -0
- package/dist/cli/__tests__/hooks.test.js.map +1 -0
- package/dist/cli/__tests__/imagegen-continuation.test.d.ts +2 -0
- package/dist/cli/__tests__/imagegen-continuation.test.d.ts.map +1 -0
- package/dist/cli/__tests__/imagegen-continuation.test.js +135 -0
- package/dist/cli/__tests__/imagegen-continuation.test.js.map +1 -0
- package/dist/cli/__tests__/index.test.d.ts +2 -0
- package/dist/cli/__tests__/index.test.d.ts.map +1 -0
- package/dist/cli/__tests__/index.test.js +3619 -0
- package/dist/cli/__tests__/index.test.js.map +1 -0
- package/dist/cli/__tests__/install-docs-contract.test.d.ts +2 -0
- package/dist/cli/__tests__/install-docs-contract.test.d.ts.map +1 -0
- package/dist/cli/__tests__/install-docs-contract.test.js +55 -0
- package/dist/cli/__tests__/install-docs-contract.test.js.map +1 -0
- package/dist/cli/__tests__/launch-fallback.test.d.ts +2 -0
- package/dist/cli/__tests__/launch-fallback.test.d.ts.map +1 -0
- package/dist/cli/__tests__/launch-fallback.test.js +1285 -0
- package/dist/cli/__tests__/launch-fallback.test.js.map +1 -0
- package/dist/cli/__tests__/lifecycle-notifications.test.d.ts +2 -0
- package/dist/cli/__tests__/lifecycle-notifications.test.d.ts.map +1 -0
- package/dist/cli/__tests__/lifecycle-notifications.test.js +48 -0
- package/dist/cli/__tests__/lifecycle-notifications.test.js.map +1 -0
- package/dist/cli/__tests__/list.test.d.ts +2 -0
- package/dist/cli/__tests__/list.test.d.ts.map +1 -0
- package/dist/cli/__tests__/list.test.js +38 -0
- package/dist/cli/__tests__/list.test.js.map +1 -0
- package/dist/cli/__tests__/mcp-parity.test.d.ts +2 -0
- package/dist/cli/__tests__/mcp-parity.test.d.ts.map +1 -0
- package/dist/cli/__tests__/mcp-parity.test.js +228 -0
- package/dist/cli/__tests__/mcp-parity.test.js.map +1 -0
- package/dist/cli/__tests__/mcp-serve.test.d.ts +2 -0
- package/dist/cli/__tests__/mcp-serve.test.d.ts.map +1 -0
- package/dist/cli/__tests__/mcp-serve.test.js +68 -0
- package/dist/cli/__tests__/mcp-serve.test.js.map +1 -0
- package/dist/cli/__tests__/native-assets.test.d.ts +2 -0
- package/dist/cli/__tests__/native-assets.test.d.ts.map +1 -0
- package/dist/cli/__tests__/native-assets.test.js +296 -0
- package/dist/cli/__tests__/native-assets.test.js.map +1 -0
- package/dist/cli/__tests__/native-hook-dispatch-contract.test.d.ts +2 -0
- package/dist/cli/__tests__/native-hook-dispatch-contract.test.d.ts.map +1 -0
- package/dist/cli/__tests__/native-hook-dispatch-contract.test.js +11 -0
- package/dist/cli/__tests__/native-hook-dispatch-contract.test.js.map +1 -0
- package/dist/cli/__tests__/nested-help-routing.test.d.ts +2 -0
- package/dist/cli/__tests__/nested-help-routing.test.d.ts.map +1 -0
- package/dist/cli/__tests__/nested-help-routing.test.js +63 -0
- package/dist/cli/__tests__/nested-help-routing.test.js.map +1 -0
- package/dist/cli/__tests__/package-bin-contract.test.d.ts +2 -0
- package/dist/cli/__tests__/package-bin-contract.test.d.ts.map +1 -0
- package/dist/cli/__tests__/package-bin-contract.test.js +190 -0
- package/dist/cli/__tests__/package-bin-contract.test.js.map +1 -0
- package/dist/cli/__tests__/packaged-explore-harness-lock.d.ts +3 -0
- package/dist/cli/__tests__/packaged-explore-harness-lock.d.ts.map +1 -0
- package/dist/cli/__tests__/packaged-explore-harness-lock.js +67 -0
- package/dist/cli/__tests__/packaged-explore-harness-lock.js.map +1 -0
- package/dist/cli/__tests__/packaged-script-resolution.test.d.ts +2 -0
- package/dist/cli/__tests__/packaged-script-resolution.test.d.ts.map +1 -0
- package/dist/cli/__tests__/packaged-script-resolution.test.js +19 -0
- package/dist/cli/__tests__/packaged-script-resolution.test.js.map +1 -0
- package/dist/cli/__tests__/performance-goal.test.d.ts +2 -0
- package/dist/cli/__tests__/performance-goal.test.d.ts.map +1 -0
- package/dist/cli/__tests__/performance-goal.test.js +144 -0
- package/dist/cli/__tests__/performance-goal.test.js.map +1 -0
- package/dist/cli/__tests__/prompt-skill-sanitization.test.d.ts +2 -0
- package/dist/cli/__tests__/prompt-skill-sanitization.test.d.ts.map +1 -0
- package/dist/cli/__tests__/prompt-skill-sanitization.test.js +48 -0
- package/dist/cli/__tests__/prompt-skill-sanitization.test.js.map +1 -0
- package/dist/cli/__tests__/question.test.d.ts +2 -0
- package/dist/cli/__tests__/question.test.d.ts.map +1 -0
- package/dist/cli/__tests__/question.test.js +850 -0
- package/dist/cli/__tests__/question.test.js.map +1 -0
- package/dist/cli/__tests__/ralph-deslop-contract.test.d.ts +2 -0
- package/dist/cli/__tests__/ralph-deslop-contract.test.d.ts.map +1 -0
- package/dist/cli/__tests__/ralph-deslop-contract.test.js +28 -0
- package/dist/cli/__tests__/ralph-deslop-contract.test.js.map +1 -0
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.d.ts +2 -0
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.d.ts.map +1 -0
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +49 -0
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -0
- package/dist/cli/__tests__/ralph-prd-deep-interview.test.d.ts +2 -0
- package/dist/cli/__tests__/ralph-prd-deep-interview.test.d.ts.map +1 -0
- package/dist/cli/__tests__/ralph-prd-deep-interview.test.js +25 -0
- package/dist/cli/__tests__/ralph-prd-deep-interview.test.js.map +1 -0
- package/dist/cli/__tests__/ralph-prd-smoke.test.d.ts +2 -0
- package/dist/cli/__tests__/ralph-prd-smoke.test.d.ts.map +1 -0
- package/dist/cli/__tests__/ralph-prd-smoke.test.js +174 -0
- package/dist/cli/__tests__/ralph-prd-smoke.test.js.map +1 -0
- package/dist/cli/__tests__/ralph.test.d.ts +2 -0
- package/dist/cli/__tests__/ralph.test.d.ts.map +1 -0
- package/dist/cli/__tests__/ralph.test.js +256 -0
- package/dist/cli/__tests__/ralph.test.js.map +1 -0
- package/dist/cli/__tests__/resume.test.d.ts +2 -0
- package/dist/cli/__tests__/resume.test.d.ts.map +1 -0
- package/dist/cli/__tests__/resume.test.js +133 -0
- package/dist/cli/__tests__/resume.test.js.map +1 -0
- package/dist/cli/__tests__/session-scoped-runtime.test.d.ts +2 -0
- package/dist/cli/__tests__/session-scoped-runtime.test.d.ts.map +1 -0
- package/dist/cli/__tests__/session-scoped-runtime.test.js +247 -0
- package/dist/cli/__tests__/session-scoped-runtime.test.js.map +1 -0
- package/dist/cli/__tests__/session-search-help.test.d.ts +2 -0
- package/dist/cli/__tests__/session-search-help.test.d.ts.map +1 -0
- package/dist/cli/__tests__/session-search-help.test.js +37 -0
- package/dist/cli/__tests__/session-search-help.test.js.map +1 -0
- package/dist/cli/__tests__/session-search.test.d.ts +2 -0
- package/dist/cli/__tests__/session-search.test.d.ts.map +1 -0
- package/dist/cli/__tests__/session-search.test.js +77 -0
- package/dist/cli/__tests__/session-search.test.js.map +1 -0
- package/dist/cli/__tests__/setup-agents-overwrite.test.d.ts +2 -0
- package/dist/cli/__tests__/setup-agents-overwrite.test.d.ts.map +1 -0
- package/dist/cli/__tests__/setup-agents-overwrite.test.js +776 -0
- package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -0
- package/dist/cli/__tests__/setup-gh-star.test.d.ts +2 -0
- package/dist/cli/__tests__/setup-gh-star.test.d.ts.map +1 -0
- package/dist/cli/__tests__/setup-gh-star.test.js +67 -0
- package/dist/cli/__tests__/setup-gh-star.test.js.map +1 -0
- package/dist/cli/__tests__/setup-hooks-shared-ownership.test.d.ts +2 -0
- package/dist/cli/__tests__/setup-hooks-shared-ownership.test.d.ts.map +1 -0
- package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js +202 -0
- package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js.map +1 -0
- package/dist/cli/__tests__/setup-install-mode.test.d.ts +2 -0
- package/dist/cli/__tests__/setup-install-mode.test.d.ts.map +1 -0
- package/dist/cli/__tests__/setup-install-mode.test.js +2103 -0
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -0
- package/dist/cli/__tests__/setup-prompts-overwrite.test.d.ts +2 -0
- package/dist/cli/__tests__/setup-prompts-overwrite.test.d.ts.map +1 -0
- package/dist/cli/__tests__/setup-prompts-overwrite.test.js +191 -0
- package/dist/cli/__tests__/setup-prompts-overwrite.test.js.map +1 -0
- package/dist/cli/__tests__/setup-refresh.test.d.ts +2 -0
- package/dist/cli/__tests__/setup-refresh.test.d.ts.map +1 -0
- package/dist/cli/__tests__/setup-refresh.test.js +779 -0
- package/dist/cli/__tests__/setup-refresh.test.js.map +1 -0
- package/dist/cli/__tests__/setup-scope.test.d.ts +2 -0
- package/dist/cli/__tests__/setup-scope.test.d.ts.map +1 -0
- package/dist/cli/__tests__/setup-scope.test.js +367 -0
- package/dist/cli/__tests__/setup-scope.test.js.map +1 -0
- package/dist/cli/__tests__/setup-skill-validation.test.d.ts +2 -0
- package/dist/cli/__tests__/setup-skill-validation.test.d.ts.map +1 -0
- package/dist/cli/__tests__/setup-skill-validation.test.js +44 -0
- package/dist/cli/__tests__/setup-skill-validation.test.js.map +1 -0
- package/dist/cli/__tests__/setup-skills-overwrite.test.d.ts +2 -0
- package/dist/cli/__tests__/setup-skills-overwrite.test.d.ts.map +1 -0
- package/dist/cli/__tests__/setup-skills-overwrite.test.js +292 -0
- package/dist/cli/__tests__/setup-skills-overwrite.test.js.map +1 -0
- package/dist/cli/__tests__/sidecar.test.d.ts +2 -0
- package/dist/cli/__tests__/sidecar.test.d.ts.map +1 -0
- package/dist/cli/__tests__/sidecar.test.js +24 -0
- package/dist/cli/__tests__/sidecar.test.js.map +1 -0
- package/dist/cli/__tests__/sparkshell-cli.test.d.ts +2 -0
- package/dist/cli/__tests__/sparkshell-cli.test.d.ts.map +1 -0
- package/dist/cli/__tests__/sparkshell-cli.test.js +471 -0
- package/dist/cli/__tests__/sparkshell-cli.test.js.map +1 -0
- package/dist/cli/__tests__/sparkshell-packaging.test.d.ts +2 -0
- package/dist/cli/__tests__/sparkshell-packaging.test.d.ts.map +1 -0
- package/dist/cli/__tests__/sparkshell-packaging.test.js +105 -0
- package/dist/cli/__tests__/sparkshell-packaging.test.js.map +1 -0
- package/dist/cli/__tests__/star-prompt.test.d.ts +2 -0
- package/dist/cli/__tests__/star-prompt.test.d.ts.map +1 -0
- package/dist/cli/__tests__/star-prompt.test.js +172 -0
- package/dist/cli/__tests__/star-prompt.test.js.map +1 -0
- package/dist/cli/__tests__/state.test.d.ts +2 -0
- package/dist/cli/__tests__/state.test.d.ts.map +1 -0
- package/dist/cli/__tests__/state.test.js +160 -0
- package/dist/cli/__tests__/state.test.js.map +1 -0
- package/dist/cli/__tests__/team-decompose.test.d.ts +2 -0
- package/dist/cli/__tests__/team-decompose.test.d.ts.map +1 -0
- package/dist/cli/__tests__/team-decompose.test.js +138 -0
- package/dist/cli/__tests__/team-decompose.test.js.map +1 -0
- package/dist/cli/__tests__/team.test.d.ts +2 -0
- package/dist/cli/__tests__/team.test.d.ts.map +1 -0
- package/dist/cli/__tests__/team.test.js +2897 -0
- package/dist/cli/__tests__/team.test.js.map +1 -0
- package/dist/cli/__tests__/ultragoal.test.d.ts +2 -0
- package/dist/cli/__tests__/ultragoal.test.d.ts.map +1 -0
- package/dist/cli/__tests__/ultragoal.test.js +599 -0
- package/dist/cli/__tests__/ultragoal.test.js.map +1 -0
- package/dist/cli/__tests__/uninstall.test.d.ts +2 -0
- package/dist/cli/__tests__/uninstall.test.d.ts.map +1 -0
- package/dist/cli/__tests__/uninstall.test.js +865 -0
- package/dist/cli/__tests__/uninstall.test.js.map +1 -0
- package/dist/cli/__tests__/update.test.d.ts +2 -0
- package/dist/cli/__tests__/update.test.d.ts.map +1 -0
- package/dist/cli/__tests__/update.test.js +1182 -0
- package/dist/cli/__tests__/update.test.js.map +1 -0
- package/dist/cli/__tests__/version-sync-contract.test.d.ts +2 -0
- package/dist/cli/__tests__/version-sync-contract.test.d.ts.map +1 -0
- package/dist/cli/__tests__/version-sync-contract.test.js +47 -0
- package/dist/cli/__tests__/version-sync-contract.test.js.map +1 -0
- package/dist/cli/__tests__/version.test.d.ts +2 -0
- package/dist/cli/__tests__/version.test.d.ts.map +1 -0
- package/dist/cli/__tests__/version.test.js +21 -0
- package/dist/cli/__tests__/version.test.js.map +1 -0
- package/dist/cli/__tests__/windows-popup-loop-contract.test.d.ts +2 -0
- package/dist/cli/__tests__/windows-popup-loop-contract.test.d.ts.map +1 -0
- package/dist/cli/__tests__/windows-popup-loop-contract.test.js +31 -0
- package/dist/cli/__tests__/windows-popup-loop-contract.test.js.map +1 -0
- package/dist/cli/adapt.d.ts +6 -0
- package/dist/cli/adapt.d.ts.map +1 -0
- package/dist/cli/adapt.js +135 -0
- package/dist/cli/adapt.js.map +1 -0
- package/dist/cli/agents-init.d.ts +14 -0
- package/dist/cli/agents-init.d.ts.map +1 -0
- package/dist/cli/agents-init.js +274 -0
- package/dist/cli/agents-init.js.map +1 -0
- package/dist/cli/agents.d.ts +14 -0
- package/dist/cli/agents.d.ts.map +1 -0
- package/dist/cli/agents.js +267 -0
- package/dist/cli/agents.js.map +1 -0
- package/dist/cli/api.d.ts +26 -0
- package/dist/cli/api.d.ts.map +1 -0
- package/dist/cli/api.js +153 -0
- package/dist/cli/api.js.map +1 -0
- package/dist/cli/ask.d.ts +13 -0
- package/dist/cli/ask.d.ts.map +1 -0
- package/dist/cli/ask.js +178 -0
- package/dist/cli/ask.js.map +1 -0
- package/dist/cli/auth.d.ts +4 -0
- package/dist/cli/auth.d.ts.map +1 -0
- package/dist/cli/auth.js +113 -0
- package/dist/cli/auth.js.map +1 -0
- package/dist/cli/autoresearch-goal.d.ts +3 -0
- package/dist/cli/autoresearch-goal.d.ts.map +1 -0
- package/dist/cli/autoresearch-goal.js +175 -0
- package/dist/cli/autoresearch-goal.js.map +1 -0
- package/dist/cli/autoresearch-guided.d.ts +43 -0
- package/dist/cli/autoresearch-guided.d.ts.map +1 -0
- package/dist/cli/autoresearch-guided.js +282 -0
- package/dist/cli/autoresearch-guided.js.map +1 -0
- package/dist/cli/autoresearch-intake.d.ts +62 -0
- package/dist/cli/autoresearch-intake.d.ts.map +1 -0
- package/dist/cli/autoresearch-intake.js +336 -0
- package/dist/cli/autoresearch-intake.js.map +1 -0
- package/dist/cli/autoresearch.d.ts +16 -0
- package/dist/cli/autoresearch.d.ts.map +1 -0
- package/dist/cli/autoresearch.js +91 -0
- package/dist/cli/autoresearch.js.map +1 -0
- package/dist/cli/catalog-contract.d.ts +10 -0
- package/dist/cli/catalog-contract.d.ts.map +1 -0
- package/dist/cli/catalog-contract.js +34 -0
- package/dist/cli/catalog-contract.js.map +1 -0
- package/dist/cli/cleanup.d.ts +58 -0
- package/dist/cli/cleanup.d.ts.map +1 -0
- package/dist/cli/cleanup.js +444 -0
- package/dist/cli/cleanup.js.map +1 -0
- package/dist/cli/codex-feature-probe.d.ts +17 -0
- package/dist/cli/codex-feature-probe.d.ts.map +1 -0
- package/dist/cli/codex-feature-probe.js +50 -0
- package/dist/cli/codex-feature-probe.js.map +1 -0
- package/dist/cli/codex-home.d.ts +7 -0
- package/dist/cli/codex-home.d.ts.map +1 -0
- package/dist/cli/codex-home.js +26 -0
- package/dist/cli/codex-home.js.map +1 -0
- package/dist/cli/constants.d.ts +11 -0
- package/dist/cli/constants.d.ts.map +1 -0
- package/dist/cli/constants.js +11 -0
- package/dist/cli/constants.js.map +1 -0
- package/dist/cli/doctor.d.ts +43 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +1956 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/explore.d.ts +14 -0
- package/dist/cli/explore.d.ts.map +1 -0
- package/dist/cli/explore.js +72 -0
- package/dist/cli/explore.js.map +1 -0
- package/dist/cli/hooks.d.ts +4 -0
- package/dist/cli/hooks.d.ts.map +1 -0
- package/dist/cli/hooks.js +201 -0
- package/dist/cli/hooks.js.map +1 -0
- package/dist/cli/index.d.ts +247 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +4590 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/list.d.ts +2 -0
- package/dist/cli/list.d.ts.map +1 -0
- package/dist/cli/list.js +40 -0
- package/dist/cli/list.js.map +1 -0
- package/dist/cli/mcp-parity.d.ts +22 -0
- package/dist/cli/mcp-parity.d.ts.map +1 -0
- package/dist/cli/mcp-parity.js +251 -0
- package/dist/cli/mcp-parity.js.map +1 -0
- package/dist/cli/mcp-serve.d.ts +13 -0
- package/dist/cli/mcp-serve.d.ts.map +1 -0
- package/dist/cli/mcp-serve.js +75 -0
- package/dist/cli/mcp-serve.js.map +1 -0
- package/dist/cli/native-assets.d.ts +52 -0
- package/dist/cli/native-assets.d.ts.map +1 -0
- package/dist/cli/native-assets.js +302 -0
- package/dist/cli/native-assets.js.map +1 -0
- package/dist/cli/omx.d.ts +3 -0
- package/dist/cli/omx.d.ts.map +1 -0
- package/dist/cli/omx.js +25 -0
- package/dist/cli/omx.js.map +1 -0
- package/dist/cli/performance-goal.d.ts +3 -0
- package/dist/cli/performance-goal.d.ts.map +1 -0
- package/dist/cli/performance-goal.js +186 -0
- package/dist/cli/performance-goal.js.map +1 -0
- package/dist/cli/plugin-marketplace.d.ts +54 -0
- package/dist/cli/plugin-marketplace.d.ts.map +1 -0
- package/dist/cli/plugin-marketplace.js +369 -0
- package/dist/cli/plugin-marketplace.js.map +1 -0
- package/dist/cli/question.d.ts +3 -0
- package/dist/cli/question.d.ts.map +1 -0
- package/dist/cli/question.js +376 -0
- package/dist/cli/question.js.map +1 -0
- package/dist/cli/ralph.d.ts +17 -0
- package/dist/cli/ralph.d.ts.map +1 -0
- package/dist/cli/ralph.js +330 -0
- package/dist/cli/ralph.js.map +1 -0
- package/dist/cli/session-search.d.ts +8 -0
- package/dist/cli/session-search.d.ts.map +1 -0
- package/dist/cli/session-search.js +133 -0
- package/dist/cli/session-search.js.map +1 -0
- package/dist/cli/setup-preferences.d.ts +26 -0
- package/dist/cli/setup-preferences.d.ts.map +1 -0
- package/dist/cli/setup-preferences.js +82 -0
- package/dist/cli/setup-preferences.js.map +1 -0
- package/dist/cli/setup.d.ts +60 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js +2748 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli/sparkshell.d.ts +39 -0
- package/dist/cli/sparkshell.d.ts.map +1 -0
- package/dist/cli/sparkshell.js +299 -0
- package/dist/cli/sparkshell.js.map +1 -0
- package/dist/cli/star-prompt.d.ts +31 -0
- package/dist/cli/star-prompt.d.ts.map +1 -0
- package/dist/cli/star-prompt.js +97 -0
- package/dist/cli/star-prompt.js.map +1 -0
- package/dist/cli/state.d.ts +8 -0
- package/dist/cli/state.d.ts.map +1 -0
- package/dist/cli/state.js +149 -0
- package/dist/cli/state.js.map +1 -0
- package/dist/cli/team.d.ts +49 -0
- package/dist/cli/team.d.ts.map +1 -0
- package/dist/cli/team.js +1453 -0
- package/dist/cli/team.js.map +1 -0
- package/dist/cli/tmux-hook.d.ts +3 -0
- package/dist/cli/tmux-hook.d.ts.map +1 -0
- package/dist/cli/tmux-hook.js +403 -0
- package/dist/cli/tmux-hook.js.map +1 -0
- package/dist/cli/ultragoal.d.ts +3 -0
- package/dist/cli/ultragoal.d.ts.map +1 -0
- package/dist/cli/ultragoal.js +494 -0
- package/dist/cli/ultragoal.js.map +1 -0
- package/dist/cli/uninstall.d.ts +15 -0
- package/dist/cli/uninstall.d.ts.map +1 -0
- package/dist/cli/uninstall.js +476 -0
- package/dist/cli/uninstall.js.map +1 -0
- package/dist/cli/update.d.ts +86 -0
- package/dist/cli/update.d.ts.map +1 -0
- package/dist/cli/update.js +754 -0
- package/dist/cli/update.js.map +1 -0
- package/dist/cli/version.d.ts +2 -0
- package/dist/cli/version.d.ts.map +1 -0
- package/dist/cli/version.js +13 -0
- package/dist/cli/version.js.map +1 -0
- package/dist/compat/__tests__/doctor-contract.test.d.ts +2 -0
- package/dist/compat/__tests__/doctor-contract.test.d.ts.map +1 -0
- package/dist/compat/__tests__/doctor-contract.test.js +122 -0
- package/dist/compat/__tests__/doctor-contract.test.js.map +1 -0
- package/dist/compat/__tests__/rust-runtime-compat.test.d.ts +2 -0
- package/dist/compat/__tests__/rust-runtime-compat.test.d.ts.map +1 -0
- package/dist/compat/__tests__/rust-runtime-compat.test.js +218 -0
- package/dist/compat/__tests__/rust-runtime-compat.test.js.map +1 -0
- package/dist/config/__tests__/codex-feature-flags.test.d.ts +2 -0
- package/dist/config/__tests__/codex-feature-flags.test.d.ts.map +1 -0
- package/dist/config/__tests__/codex-feature-flags.test.js +45 -0
- package/dist/config/__tests__/codex-feature-flags.test.js.map +1 -0
- package/dist/config/__tests__/codex-hooks.test.d.ts +2 -0
- package/dist/config/__tests__/codex-hooks.test.d.ts.map +1 -0
- package/dist/config/__tests__/codex-hooks.test.js +524 -0
- package/dist/config/__tests__/codex-hooks.test.js.map +1 -0
- package/dist/config/__tests__/commit-lore-guard.test.d.ts +2 -0
- package/dist/config/__tests__/commit-lore-guard.test.d.ts.map +1 -0
- package/dist/config/__tests__/commit-lore-guard.test.js +20 -0
- package/dist/config/__tests__/commit-lore-guard.test.js.map +1 -0
- package/dist/config/__tests__/deep-interview.test.d.ts +2 -0
- package/dist/config/__tests__/deep-interview.test.d.ts.map +1 -0
- package/dist/config/__tests__/deep-interview.test.js +240 -0
- package/dist/config/__tests__/deep-interview.test.js.map +1 -0
- package/dist/config/__tests__/generator-idempotent.test.d.ts +2 -0
- package/dist/config/__tests__/generator-idempotent.test.d.ts.map +1 -0
- package/dist/config/__tests__/generator-idempotent.test.js +1150 -0
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -0
- package/dist/config/__tests__/generator-notify.test.d.ts +2 -0
- package/dist/config/__tests__/generator-notify.test.d.ts.map +1 -0
- package/dist/config/__tests__/generator-notify.test.js +512 -0
- package/dist/config/__tests__/generator-notify.test.js.map +1 -0
- package/dist/config/__tests__/generator-status-line-presets.test.d.ts +2 -0
- package/dist/config/__tests__/generator-status-line-presets.test.d.ts.map +1 -0
- package/dist/config/__tests__/generator-status-line-presets.test.js +203 -0
- package/dist/config/__tests__/generator-status-line-presets.test.js.map +1 -0
- package/dist/config/__tests__/mcp-registry.test.d.ts +2 -0
- package/dist/config/__tests__/mcp-registry.test.d.ts.map +1 -0
- package/dist/config/__tests__/mcp-registry.test.js +190 -0
- package/dist/config/__tests__/mcp-registry.test.js.map +1 -0
- package/dist/config/__tests__/models.test.d.ts +2 -0
- package/dist/config/__tests__/models.test.d.ts.map +1 -0
- package/dist/config/__tests__/models.test.js +241 -0
- package/dist/config/__tests__/models.test.js.map +1 -0
- package/dist/config/__tests__/wiki-config-contract.test.d.ts +2 -0
- package/dist/config/__tests__/wiki-config-contract.test.d.ts.map +1 -0
- package/dist/config/__tests__/wiki-config-contract.test.js +23 -0
- package/dist/config/__tests__/wiki-config-contract.test.js.map +1 -0
- package/dist/config/codex-feature-flags.d.ts +25 -0
- package/dist/config/codex-feature-flags.d.ts.map +1 -0
- package/dist/config/codex-feature-flags.js +60 -0
- package/dist/config/codex-feature-flags.js.map +1 -0
- package/dist/config/codex-hooks.d.ts +79 -0
- package/dist/config/codex-hooks.d.ts.map +1 -0
- package/dist/config/codex-hooks.js +578 -0
- package/dist/config/codex-hooks.js.map +1 -0
- package/dist/config/commit-lore-guard.d.ts +4 -0
- package/dist/config/commit-lore-guard.d.ts.map +1 -0
- package/dist/config/commit-lore-guard.js +35 -0
- package/dist/config/commit-lore-guard.js.map +1 -0
- package/dist/config/deep-interview.d.ts +22 -0
- package/dist/config/deep-interview.d.ts.map +1 -0
- package/dist/config/deep-interview.js +161 -0
- package/dist/config/deep-interview.js.map +1 -0
- package/dist/config/generator.d.ts +141 -0
- package/dist/config/generator.d.ts.map +1 -0
- package/dist/config/generator.js +1845 -0
- package/dist/config/generator.js.map +1 -0
- package/dist/config/mcp-registry.d.ts +35 -0
- package/dist/config/mcp-registry.d.ts.map +1 -0
- package/dist/config/mcp-registry.js +159 -0
- package/dist/config/mcp-registry.js.map +1 -0
- package/dist/config/models.d.ts +80 -0
- package/dist/config/models.d.ts.map +1 -0
- package/dist/config/models.js +251 -0
- package/dist/config/models.js.map +1 -0
- package/dist/config/omx-first-party-mcp.d.ts +21 -0
- package/dist/config/omx-first-party-mcp.d.ts.map +1 -0
- package/dist/config/omx-first-party-mcp.js +86 -0
- package/dist/config/omx-first-party-mcp.js.map +1 -0
- package/dist/config/team-mode.d.ts +12 -0
- package/dist/config/team-mode.d.ts.map +1 -0
- package/dist/config/team-mode.js +91 -0
- package/dist/config/team-mode.js.map +1 -0
- package/dist/document-refresh/__tests__/enforcer.test.d.ts +2 -0
- package/dist/document-refresh/__tests__/enforcer.test.d.ts.map +1 -0
- package/dist/document-refresh/__tests__/enforcer.test.js +128 -0
- package/dist/document-refresh/__tests__/enforcer.test.js.map +1 -0
- package/dist/document-refresh/config.d.ts +9 -0
- package/dist/document-refresh/config.d.ts.map +1 -0
- package/dist/document-refresh/config.js +70 -0
- package/dist/document-refresh/config.js.map +1 -0
- package/dist/document-refresh/enforcer.d.ts +43 -0
- package/dist/document-refresh/enforcer.d.ts.map +1 -0
- package/dist/document-refresh/enforcer.js +329 -0
- package/dist/document-refresh/enforcer.js.map +1 -0
- package/dist/exec/followup.d.ts +45 -0
- package/dist/exec/followup.d.ts.map +1 -0
- package/dist/exec/followup.js +355 -0
- package/dist/exec/followup.js.map +1 -0
- package/dist/goal-workflows/__tests__/artifacts.test.d.ts +2 -0
- package/dist/goal-workflows/__tests__/artifacts.test.d.ts.map +1 -0
- package/dist/goal-workflows/__tests__/artifacts.test.js +96 -0
- package/dist/goal-workflows/__tests__/artifacts.test.js.map +1 -0
- package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.d.ts +2 -0
- package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.d.ts.map +1 -0
- package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js +75 -0
- package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js.map +1 -0
- package/dist/goal-workflows/artifacts.d.ts +62 -0
- package/dist/goal-workflows/artifacts.d.ts.map +1 -0
- package/dist/goal-workflows/artifacts.js +132 -0
- package/dist/goal-workflows/artifacts.js.map +1 -0
- package/dist/goal-workflows/codex-goal-snapshot.d.ts +32 -0
- package/dist/goal-workflows/codex-goal-snapshot.d.ts.map +1 -0
- package/dist/goal-workflows/codex-goal-snapshot.js +157 -0
- package/dist/goal-workflows/codex-goal-snapshot.js.map +1 -0
- package/dist/goal-workflows/handoff.d.ts +10 -0
- package/dist/goal-workflows/handoff.d.ts.map +1 -0
- package/dist/goal-workflows/handoff.js +31 -0
- package/dist/goal-workflows/handoff.js.map +1 -0
- package/dist/goal-workflows/validation.d.ts +13 -0
- package/dist/goal-workflows/validation.d.ts.map +1 -0
- package/dist/goal-workflows/validation.js +36 -0
- package/dist/goal-workflows/validation.js.map +1 -0
- package/dist/hooks/__tests__/agents-overlay.test.d.ts +8 -0
- package/dist/hooks/__tests__/agents-overlay.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/agents-overlay.test.js +761 -0
- package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -0
- package/dist/hooks/__tests__/analyze-routing-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/analyze-routing-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/analyze-routing-contract.test.js +45 -0
- package/dist/hooks/__tests__/analyze-routing-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/analyze-skill-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/analyze-skill-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/analyze-skill-contract.test.js +48 -0
- package/dist/hooks/__tests__/analyze-skill-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/anti-slop-workflow.test.d.ts +2 -0
- package/dist/hooks/__tests__/anti-slop-workflow.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/anti-slop-workflow.test.js +165 -0
- package/dist/hooks/__tests__/anti-slop-workflow.test.js.map +1 -0
- package/dist/hooks/__tests__/autopilot-skill-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/autopilot-skill-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/autopilot-skill-contract.test.js +90 -0
- package/dist/hooks/__tests__/autopilot-skill-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/best-practice-research-skill.test.d.ts +2 -0
- package/dist/hooks/__tests__/best-practice-research-skill.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/best-practice-research-skill.test.js +39 -0
- package/dist/hooks/__tests__/best-practice-research-skill.test.js.map +1 -0
- package/dist/hooks/__tests__/clawhip-event-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/clawhip-event-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/clawhip-event-contract.test.js +37 -0
- package/dist/hooks/__tests__/clawhip-event-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/code-review-skill-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/code-review-skill-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/code-review-skill-contract.test.js +77 -0
- package/dist/hooks/__tests__/code-review-skill-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/codebase-map.test.d.ts +8 -0
- package/dist/hooks/__tests__/codebase-map.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/codebase-map.test.js +218 -0
- package/dist/hooks/__tests__/codebase-map.test.js.map +1 -0
- package/dist/hooks/__tests__/consensus-execution-handoff.test.d.ts +18 -0
- package/dist/hooks/__tests__/consensus-execution-handoff.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/consensus-execution-handoff.test.js +266 -0
- package/dist/hooks/__tests__/consensus-execution-handoff.test.js.map +1 -0
- package/dist/hooks/__tests__/debugger-log-recency-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/debugger-log-recency-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/debugger-log-recency-contract.test.js +20 -0
- package/dist/hooks/__tests__/debugger-log-recency-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/deep-interview-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/deep-interview-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/deep-interview-contract.test.js +309 -0
- package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/design-skill.test.d.ts +2 -0
- package/dist/hooks/__tests__/design-skill.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/design-skill.test.js +55 -0
- package/dist/hooks/__tests__/design-skill.test.js.map +1 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-docs-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-docs-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-docs-contract.test.js +43 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-docs-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-model-docs-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-model-docs-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-model-docs-contract.test.js +38 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-model-docs-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/explore-routing.test.d.ts +2 -0
- package/dist/hooks/__tests__/explore-routing.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/explore-routing.test.js +38 -0
- package/dist/hooks/__tests__/explore-routing.test.js.map +1 -0
- package/dist/hooks/__tests__/explore-sparkshell-guidance-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/explore-sparkshell-guidance-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/explore-sparkshell-guidance-contract.test.js +67 -0
- package/dist/hooks/__tests__/explore-sparkshell-guidance-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/foreground-isolation-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/foreground-isolation-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/foreground-isolation-contract.test.js +28 -0
- package/dist/hooks/__tests__/foreground-isolation-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/keyword-detector.test.d.ts +2 -0
- package/dist/hooks/__tests__/keyword-detector.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/keyword-detector.test.js +3323 -0
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-fallback-watcher.test.d.ts +2 -0
- package/dist/hooks/__tests__/notify-fallback-watcher.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js +3956 -0
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.d.ts +2 -0
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +786 -0
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.d.ts +2 -0
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +2602 -0
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.d.ts +2 -0
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js +161 -0
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.d.ts +2 -0
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js +1178 -0
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-modules.test.d.ts +9 -0
- package/dist/hooks/__tests__/notify-hook-modules.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-modules.test.js +529 -0
- package/dist/hooks/__tests__/notify-hook-modules.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-native-dispatch-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/notify-hook-native-dispatch-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-native-dispatch-contract.test.js +14 -0
- package/dist/hooks/__tests__/notify-hook-native-dispatch-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.d.ts +2 -0
- package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.js +176 -0
- package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.d.ts +2 -0
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js +890 -0
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-regression-205.test.d.ts +9 -0
- package/dist/hooks/__tests__/notify-hook-regression-205.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-regression-205.test.js +255 -0
- package/dist/hooks/__tests__/notify-hook-regression-205.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.d.ts +2 -0
- package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js +162 -0
- package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-session-scope.test.d.ts +2 -0
- package/dist/hooks/__tests__/notify-hook-session-scope.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js +304 -0
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.d.ts +2 -0
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +1511 -0
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.d.ts +2 -0
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +2911 -0
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.d.ts +2 -0
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +261 -0
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.d.ts +2 -0
- package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js +35 -0
- package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.d.ts +2 -0
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +1854 -0
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.d.ts +10 -0
- package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js +0 -0
- package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-visual-verdict.test.d.ts +11 -0
- package/dist/hooks/__tests__/notify-hook-visual-verdict.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-visual-verdict.test.js +266 -0
- package/dist/hooks/__tests__/notify-hook-visual-verdict.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.d.ts +2 -0
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +895 -0
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -0
- package/dist/hooks/__tests__/openclaw-setup-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/openclaw-setup-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/openclaw-setup-contract.test.js +61 -0
- package/dist/hooks/__tests__/openclaw-setup-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/pre-context-gate-skills.test.d.ts +2 -0
- package/dist/hooks/__tests__/pre-context-gate-skills.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/pre-context-gate-skills.test.js +40 -0
- package/dist/hooks/__tests__/pre-context-gate-skills.test.js.map +1 -0
- package/dist/hooks/__tests__/prometheus-strict-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/prometheus-strict-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/prometheus-strict-contract.test.js +320 -0
- package/dist/hooks/__tests__/prometheus-strict-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/prompt-guidance-catalog.test.d.ts +2 -0
- package/dist/hooks/__tests__/prompt-guidance-catalog.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/prompt-guidance-catalog.test.js +11 -0
- package/dist/hooks/__tests__/prompt-guidance-catalog.test.js.map +1 -0
- package/dist/hooks/__tests__/prompt-guidance-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/prompt-guidance-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/prompt-guidance-contract.test.js +38 -0
- package/dist/hooks/__tests__/prompt-guidance-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/prompt-guidance-fragments.test.d.ts +2 -0
- package/dist/hooks/__tests__/prompt-guidance-fragments.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/prompt-guidance-fragments.test.js +48 -0
- package/dist/hooks/__tests__/prompt-guidance-fragments.test.js.map +1 -0
- package/dist/hooks/__tests__/prompt-guidance-scenarios.test.d.ts +2 -0
- package/dist/hooks/__tests__/prompt-guidance-scenarios.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/prompt-guidance-scenarios.test.js +11 -0
- package/dist/hooks/__tests__/prompt-guidance-scenarios.test.js.map +1 -0
- package/dist/hooks/__tests__/prompt-guidance-test-helpers.d.ts +5 -0
- package/dist/hooks/__tests__/prompt-guidance-test-helpers.d.ts.map +1 -0
- package/dist/hooks/__tests__/prompt-guidance-test-helpers.js +34 -0
- package/dist/hooks/__tests__/prompt-guidance-test-helpers.js.map +1 -0
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.d.ts +2 -0
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js +81 -0
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js.map +1 -0
- package/dist/hooks/__tests__/prompt-orchestration-boundary.test.d.ts +2 -0
- package/dist/hooks/__tests__/prompt-orchestration-boundary.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/prompt-orchestration-boundary.test.js +38 -0
- package/dist/hooks/__tests__/prompt-orchestration-boundary.test.js.map +1 -0
- package/dist/hooks/__tests__/prompt-refactor-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/prompt-refactor-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/prompt-refactor-contract.test.js +22 -0
- package/dist/hooks/__tests__/prompt-refactor-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/prompt-team-routing.test.d.ts +2 -0
- package/dist/hooks/__tests__/prompt-team-routing.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/prompt-team-routing.test.js +49 -0
- package/dist/hooks/__tests__/prompt-team-routing.test.js.map +1 -0
- package/dist/hooks/__tests__/research-workflow-boundaries.test.d.ts +2 -0
- package/dist/hooks/__tests__/research-workflow-boundaries.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/research-workflow-boundaries.test.js +35 -0
- package/dist/hooks/__tests__/research-workflow-boundaries.test.js.map +1 -0
- package/dist/hooks/__tests__/session.test.d.ts +2 -0
- package/dist/hooks/__tests__/session.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/session.test.js +504 -0
- package/dist/hooks/__tests__/session.test.js.map +1 -0
- package/dist/hooks/__tests__/skill-catalog-hygiene.test.d.ts +2 -0
- package/dist/hooks/__tests__/skill-catalog-hygiene.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/skill-catalog-hygiene.test.js +84 -0
- package/dist/hooks/__tests__/skill-catalog-hygiene.test.js.map +1 -0
- package/dist/hooks/__tests__/skill-guidance-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/skill-guidance-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/skill-guidance-contract.test.js +89 -0
- package/dist/hooks/__tests__/skill-guidance-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/task-size-detector.test.d.ts +2 -0
- package/dist/hooks/__tests__/task-size-detector.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/task-size-detector.test.js +330 -0
- package/dist/hooks/__tests__/task-size-detector.test.js.map +1 -0
- package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.js +28 -0
- package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/tmux-hook-engine-types-sync.test.d.ts +2 -0
- package/dist/hooks/__tests__/tmux-hook-engine-types-sync.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/tmux-hook-engine-types-sync.test.js +24 -0
- package/dist/hooks/__tests__/tmux-hook-engine-types-sync.test.js.map +1 -0
- package/dist/hooks/__tests__/tmux-hook-engine.test.d.ts +2 -0
- package/dist/hooks/__tests__/tmux-hook-engine.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/tmux-hook-engine.test.js +403 -0
- package/dist/hooks/__tests__/tmux-hook-engine.test.js.map +1 -0
- package/dist/hooks/__tests__/triage-config.test.d.ts +2 -0
- package/dist/hooks/__tests__/triage-config.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/triage-config.test.js +211 -0
- package/dist/hooks/__tests__/triage-config.test.js.map +1 -0
- package/dist/hooks/__tests__/triage-heuristic.test.d.ts +2 -0
- package/dist/hooks/__tests__/triage-heuristic.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/triage-heuristic.test.js +285 -0
- package/dist/hooks/__tests__/triage-heuristic.test.js.map +1 -0
- package/dist/hooks/__tests__/triage-state.test.d.ts +2 -0
- package/dist/hooks/__tests__/triage-state.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/triage-state.test.js +426 -0
- package/dist/hooks/__tests__/triage-state.test.js.map +1 -0
- package/dist/hooks/__tests__/visual-ralph-skill.test.d.ts +2 -0
- package/dist/hooks/__tests__/visual-ralph-skill.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/visual-ralph-skill.test.js +44 -0
- package/dist/hooks/__tests__/visual-ralph-skill.test.js.map +1 -0
- package/dist/hooks/__tests__/visual-verdict-loop.test.d.ts +2 -0
- package/dist/hooks/__tests__/visual-verdict-loop.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/visual-verdict-loop.test.js +31 -0
- package/dist/hooks/__tests__/visual-verdict-loop.test.js.map +1 -0
- package/dist/hooks/__tests__/wiki-docs-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/wiki-docs-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/wiki-docs-contract.test.js +35 -0
- package/dist/hooks/__tests__/wiki-docs-contract.test.js.map +1 -0
- package/dist/hooks/agents-overlay.d.ts +51 -0
- package/dist/hooks/agents-overlay.d.ts.map +1 -0
- package/dist/hooks/agents-overlay.js +547 -0
- package/dist/hooks/agents-overlay.js.map +1 -0
- package/dist/hooks/code-simplifier/__tests__/index.test.d.ts +2 -0
- package/dist/hooks/code-simplifier/__tests__/index.test.d.ts.map +1 -0
- package/dist/hooks/code-simplifier/__tests__/index.test.js +187 -0
- package/dist/hooks/code-simplifier/__tests__/index.test.js.map +1 -0
- package/dist/hooks/code-simplifier/index.d.ts +80 -0
- package/dist/hooks/code-simplifier/index.d.ts.map +1 -0
- package/dist/hooks/code-simplifier/index.js +172 -0
- package/dist/hooks/code-simplifier/index.js.map +1 -0
- package/dist/hooks/codebase-map.d.ts +23 -0
- package/dist/hooks/codebase-map.d.ts.map +1 -0
- package/dist/hooks/codebase-map.js +234 -0
- package/dist/hooks/codebase-map.js.map +1 -0
- package/dist/hooks/deep-interview-config-instruction.d.ts +3 -0
- package/dist/hooks/deep-interview-config-instruction.d.ts.map +1 -0
- package/dist/hooks/deep-interview-config-instruction.js +47 -0
- package/dist/hooks/deep-interview-config-instruction.js.map +1 -0
- package/dist/hooks/explore-routing.d.ts +5 -0
- package/dist/hooks/explore-routing.d.ts.map +1 -0
- package/dist/hooks/explore-routing.js +37 -0
- package/dist/hooks/explore-routing.js.map +1 -0
- package/dist/hooks/extensibility/__tests__/dispatcher.test.d.ts +2 -0
- package/dist/hooks/extensibility/__tests__/dispatcher.test.d.ts.map +1 -0
- package/dist/hooks/extensibility/__tests__/dispatcher.test.js +265 -0
- package/dist/hooks/extensibility/__tests__/dispatcher.test.js.map +1 -0
- package/dist/hooks/extensibility/__tests__/events.test.d.ts +2 -0
- package/dist/hooks/extensibility/__tests__/events.test.d.ts.map +1 -0
- package/dist/hooks/extensibility/__tests__/events.test.js +125 -0
- package/dist/hooks/extensibility/__tests__/events.test.js.map +1 -0
- package/dist/hooks/extensibility/__tests__/example-hook-plugins.test.d.ts +2 -0
- package/dist/hooks/extensibility/__tests__/example-hook-plugins.test.d.ts.map +1 -0
- package/dist/hooks/extensibility/__tests__/example-hook-plugins.test.js +153 -0
- package/dist/hooks/extensibility/__tests__/example-hook-plugins.test.js.map +1 -0
- package/dist/hooks/extensibility/__tests__/loader.test.d.ts +2 -0
- package/dist/hooks/extensibility/__tests__/loader.test.d.ts.map +1 -0
- package/dist/hooks/extensibility/__tests__/loader.test.js +254 -0
- package/dist/hooks/extensibility/__tests__/loader.test.js.map +1 -0
- package/dist/hooks/extensibility/__tests__/logging.test.d.ts +2 -0
- package/dist/hooks/extensibility/__tests__/logging.test.d.ts.map +1 -0
- package/dist/hooks/extensibility/__tests__/logging.test.js +74 -0
- package/dist/hooks/extensibility/__tests__/logging.test.js.map +1 -0
- package/dist/hooks/extensibility/__tests__/plugin-runner.test.d.ts +2 -0
- package/dist/hooks/extensibility/__tests__/plugin-runner.test.d.ts.map +1 -0
- package/dist/hooks/extensibility/__tests__/plugin-runner.test.js +344 -0
- package/dist/hooks/extensibility/__tests__/plugin-runner.test.js.map +1 -0
- package/dist/hooks/extensibility/__tests__/runtime.test.d.ts +2 -0
- package/dist/hooks/extensibility/__tests__/runtime.test.d.ts.map +1 -0
- package/dist/hooks/extensibility/__tests__/runtime.test.js +198 -0
- package/dist/hooks/extensibility/__tests__/runtime.test.js.map +1 -0
- package/dist/hooks/extensibility/__tests__/sdk-public-surface.test.d.ts +2 -0
- package/dist/hooks/extensibility/__tests__/sdk-public-surface.test.d.ts.map +1 -0
- package/dist/hooks/extensibility/__tests__/sdk-public-surface.test.js +32 -0
- package/dist/hooks/extensibility/__tests__/sdk-public-surface.test.js.map +1 -0
- package/dist/hooks/extensibility/__tests__/sdk.test.d.ts +2 -0
- package/dist/hooks/extensibility/__tests__/sdk.test.d.ts.map +1 -0
- package/dist/hooks/extensibility/__tests__/sdk.test.js +479 -0
- package/dist/hooks/extensibility/__tests__/sdk.test.js.map +1 -0
- package/dist/hooks/extensibility/dispatcher.d.ts +4 -0
- package/dist/hooks/extensibility/dispatcher.d.ts.map +1 -0
- package/dist/hooks/extensibility/dispatcher.js +302 -0
- package/dist/hooks/extensibility/dispatcher.js.map +1 -0
- package/dist/hooks/extensibility/events.d.ts +18 -0
- package/dist/hooks/extensibility/events.d.ts.map +1 -0
- package/dist/hooks/extensibility/events.js +53 -0
- package/dist/hooks/extensibility/events.js.map +1 -0
- package/dist/hooks/extensibility/index.d.ts +6 -0
- package/dist/hooks/extensibility/index.d.ts.map +1 -0
- package/dist/hooks/extensibility/index.js +6 -0
- package/dist/hooks/extensibility/index.js.map +1 -0
- package/dist/hooks/extensibility/loader.d.ts +14 -0
- package/dist/hooks/extensibility/loader.d.ts.map +1 -0
- package/dist/hooks/extensibility/loader.js +117 -0
- package/dist/hooks/extensibility/loader.js.map +1 -0
- package/dist/hooks/extensibility/logging.d.ts +4 -0
- package/dist/hooks/extensibility/logging.d.ts.map +1 -0
- package/dist/hooks/extensibility/logging.js +22 -0
- package/dist/hooks/extensibility/logging.js.map +1 -0
- package/dist/hooks/extensibility/plugin-runner-stdin.d.ts +2 -0
- package/dist/hooks/extensibility/plugin-runner-stdin.d.ts.map +1 -0
- package/dist/hooks/extensibility/plugin-runner-stdin.js +16 -0
- package/dist/hooks/extensibility/plugin-runner-stdin.js.map +1 -0
- package/dist/hooks/extensibility/plugin-runner.d.ts +2 -0
- package/dist/hooks/extensibility/plugin-runner.d.ts.map +1 -0
- package/dist/hooks/extensibility/plugin-runner.js +63 -0
- package/dist/hooks/extensibility/plugin-runner.js.map +1 -0
- package/dist/hooks/extensibility/runtime.d.ts +3 -0
- package/dist/hooks/extensibility/runtime.d.ts.map +1 -0
- package/dist/hooks/extensibility/runtime.js +42 -0
- package/dist/hooks/extensibility/runtime.js.map +1 -0
- package/dist/hooks/extensibility/sdk/logging.d.ts +6 -0
- package/dist/hooks/extensibility/sdk/logging.d.ts.map +1 -0
- package/dist/hooks/extensibility/sdk/logging.js +32 -0
- package/dist/hooks/extensibility/sdk/logging.js.map +1 -0
- package/dist/hooks/extensibility/sdk/paths.d.ts +7 -0
- package/dist/hooks/extensibility/sdk/paths.d.ts.map +1 -0
- package/dist/hooks/extensibility/sdk/paths.js +23 -0
- package/dist/hooks/extensibility/sdk/paths.js.map +1 -0
- package/dist/hooks/extensibility/sdk/plugin-state.d.ts +5 -0
- package/dist/hooks/extensibility/sdk/plugin-state.d.ts.map +1 -0
- package/dist/hooks/extensibility/sdk/plugin-state.js +66 -0
- package/dist/hooks/extensibility/sdk/plugin-state.js.map +1 -0
- package/dist/hooks/extensibility/sdk/runtime-state.d.ts +3 -0
- package/dist/hooks/extensibility/sdk/runtime-state.d.ts.map +1 -0
- package/dist/hooks/extensibility/sdk/runtime-state.js +47 -0
- package/dist/hooks/extensibility/sdk/runtime-state.js.map +1 -0
- package/dist/hooks/extensibility/sdk/tmux.d.ts +10 -0
- package/dist/hooks/extensibility/sdk/tmux.d.ts.map +1 -0
- package/dist/hooks/extensibility/sdk/tmux.js +181 -0
- package/dist/hooks/extensibility/sdk/tmux.js.map +1 -0
- package/dist/hooks/extensibility/sdk.d.ts +11 -0
- package/dist/hooks/extensibility/sdk.d.ts.map +1 -0
- package/dist/hooks/extensibility/sdk.js +21 -0
- package/dist/hooks/extensibility/sdk.js.map +1 -0
- package/dist/hooks/extensibility/types.d.ts +175 -0
- package/dist/hooks/extensibility/types.d.ts.map +1 -0
- package/dist/hooks/extensibility/types.js +2 -0
- package/dist/hooks/extensibility/types.js.map +1 -0
- package/dist/hooks/keyword-detector.d.ts +170 -0
- package/dist/hooks/keyword-detector.d.ts.map +1 -0
- package/dist/hooks/keyword-detector.js +1363 -0
- package/dist/hooks/keyword-detector.js.map +1 -0
- package/dist/hooks/keyword-registry.d.ts +15 -0
- package/dist/hooks/keyword-registry.d.ts.map +1 -0
- package/dist/hooks/keyword-registry.js +56 -0
- package/dist/hooks/keyword-registry.js.map +1 -0
- package/dist/hooks/prompt-guidance-contract.d.ts +20 -0
- package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -0
- package/dist/hooks/prompt-guidance-contract.js +380 -0
- package/dist/hooks/prompt-guidance-contract.js.map +1 -0
- package/dist/hooks/session.d.ts +83 -0
- package/dist/hooks/session.d.ts.map +1 -0
- package/dist/hooks/session.js +412 -0
- package/dist/hooks/session.js.map +1 -0
- package/dist/hooks/task-size-detector.d.ts +72 -0
- package/dist/hooks/task-size-detector.d.ts.map +1 -0
- package/dist/hooks/task-size-detector.js +203 -0
- package/dist/hooks/task-size-detector.js.map +1 -0
- package/dist/hooks/triage-config.d.ts +33 -0
- package/dist/hooks/triage-config.d.ts.map +1 -0
- package/dist/hooks/triage-config.js +87 -0
- package/dist/hooks/triage-config.js.map +1 -0
- package/dist/hooks/triage-heuristic.d.ts +20 -0
- package/dist/hooks/triage-heuristic.d.ts.map +1 -0
- package/dist/hooks/triage-heuristic.js +287 -0
- package/dist/hooks/triage-heuristic.js.map +1 -0
- package/dist/hooks/triage-state.d.ts +63 -0
- package/dist/hooks/triage-state.d.ts.map +1 -0
- package/dist/hooks/triage-state.js +139 -0
- package/dist/hooks/triage-state.js.map +1 -0
- package/dist/hud/__tests__/authority.test.d.ts +2 -0
- package/dist/hud/__tests__/authority.test.d.ts.map +1 -0
- package/dist/hud/__tests__/authority.test.js +527 -0
- package/dist/hud/__tests__/authority.test.js.map +1 -0
- package/dist/hud/__tests__/colors.test.d.ts +2 -0
- package/dist/hud/__tests__/colors.test.d.ts.map +1 -0
- package/dist/hud/__tests__/colors.test.js +92 -0
- package/dist/hud/__tests__/colors.test.js.map +1 -0
- package/dist/hud/__tests__/hud-tmux-injection.test.d.ts +10 -0
- package/dist/hud/__tests__/hud-tmux-injection.test.d.ts.map +1 -0
- package/dist/hud/__tests__/hud-tmux-injection.test.js +185 -0
- package/dist/hud/__tests__/hud-tmux-injection.test.js.map +1 -0
- package/dist/hud/__tests__/index.test.d.ts +2 -0
- package/dist/hud/__tests__/index.test.d.ts.map +1 -0
- package/dist/hud/__tests__/index.test.js +684 -0
- package/dist/hud/__tests__/index.test.js.map +1 -0
- package/dist/hud/__tests__/reconcile.test.d.ts +2 -0
- package/dist/hud/__tests__/reconcile.test.d.ts.map +1 -0
- package/dist/hud/__tests__/reconcile.test.js +1621 -0
- package/dist/hud/__tests__/reconcile.test.js.map +1 -0
- package/dist/hud/__tests__/render.test.d.ts +2 -0
- package/dist/hud/__tests__/render.test.d.ts.map +1 -0
- package/dist/hud/__tests__/render.test.js +983 -0
- package/dist/hud/__tests__/render.test.js.map +1 -0
- package/dist/hud/__tests__/resource-leak-watch.test.d.ts +2 -0
- package/dist/hud/__tests__/resource-leak-watch.test.d.ts.map +1 -0
- package/dist/hud/__tests__/resource-leak-watch.test.js +28 -0
- package/dist/hud/__tests__/resource-leak-watch.test.js.map +1 -0
- package/dist/hud/__tests__/state.test.d.ts +2 -0
- package/dist/hud/__tests__/state.test.d.ts.map +1 -0
- package/dist/hud/__tests__/state.test.js +1212 -0
- package/dist/hud/__tests__/state.test.js.map +1 -0
- package/dist/hud/__tests__/tmux.test.d.ts +2 -0
- package/dist/hud/__tests__/tmux.test.d.ts.map +1 -0
- package/dist/hud/__tests__/tmux.test.js +679 -0
- package/dist/hud/__tests__/tmux.test.js.map +1 -0
- package/dist/hud/__tests__/types.test.d.ts +2 -0
- package/dist/hud/__tests__/types.test.d.ts.map +1 -0
- package/dist/hud/__tests__/types.test.js +79 -0
- package/dist/hud/__tests__/types.test.js.map +1 -0
- package/dist/hud/__tests__/watch.test.d.ts +2 -0
- package/dist/hud/__tests__/watch.test.d.ts.map +1 -0
- package/dist/hud/__tests__/watch.test.js +63 -0
- package/dist/hud/__tests__/watch.test.js.map +1 -0
- package/dist/hud/authority.d.ts +22 -0
- package/dist/hud/authority.d.ts.map +1 -0
- package/dist/hud/authority.js +377 -0
- package/dist/hud/authority.js.map +1 -0
- package/dist/hud/colors.d.ts +20 -0
- package/dist/hud/colors.d.ts.map +1 -0
- package/dist/hud/colors.js +60 -0
- package/dist/hud/colors.js.map +1 -0
- package/dist/hud/constants.d.ts +16 -0
- package/dist/hud/constants.d.ts.map +1 -0
- package/dist/hud/constants.js +25 -0
- package/dist/hud/constants.js.map +1 -0
- package/dist/hud/index.d.ts +79 -0
- package/dist/hud/index.d.ts.map +1 -0
- package/dist/hud/index.js +384 -0
- package/dist/hud/index.js.map +1 -0
- package/dist/hud/reconcile.d.ts +37 -0
- package/dist/hud/reconcile.d.ts.map +1 -0
- package/dist/hud/reconcile.js +326 -0
- package/dist/hud/reconcile.js.map +1 -0
- package/dist/hud/render.d.ts +15 -0
- package/dist/hud/render.d.ts.map +1 -0
- package/dist/hud/render.js +453 -0
- package/dist/hud/render.js.map +1 -0
- package/dist/hud/state.d.ts +27 -0
- package/dist/hud/state.d.ts.map +1 -0
- package/dist/hud/state.js +477 -0
- package/dist/hud/state.js.map +1 -0
- package/dist/hud/tmux.d.ts +87 -0
- package/dist/hud/tmux.d.ts.map +1 -0
- package/dist/hud/tmux.js +572 -0
- package/dist/hud/tmux.js.map +1 -0
- package/dist/hud/types.d.ts +165 -0
- package/dist/hud/types.d.ts.map +1 -0
- package/dist/hud/types.js +14 -0
- package/dist/hud/types.js.map +1 -0
- package/dist/imagegen/continuation.d.ts +44 -0
- package/dist/imagegen/continuation.d.ts.map +1 -0
- package/dist/imagegen/continuation.js +220 -0
- package/dist/imagegen/continuation.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/__tests__/bootstrap.test.d.ts +2 -0
- package/dist/mcp/__tests__/bootstrap.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/bootstrap.test.js +372 -0
- package/dist/mcp/__tests__/bootstrap.test.js.map +1 -0
- package/dist/mcp/__tests__/code-intel-server.test.d.ts +2 -0
- package/dist/mcp/__tests__/code-intel-server.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/code-intel-server.test.js +70 -0
- package/dist/mcp/__tests__/code-intel-server.test.js.map +1 -0
- package/dist/mcp/__tests__/hermes-bridge.test.d.ts +2 -0
- package/dist/mcp/__tests__/hermes-bridge.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/hermes-bridge.test.js +651 -0
- package/dist/mcp/__tests__/hermes-bridge.test.js.map +1 -0
- package/dist/mcp/__tests__/memory-server.test.d.ts +2 -0
- package/dist/mcp/__tests__/memory-server.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/memory-server.test.js +36 -0
- package/dist/mcp/__tests__/memory-server.test.js.map +1 -0
- package/dist/mcp/__tests__/memory-validation.test.d.ts +2 -0
- package/dist/mcp/__tests__/memory-validation.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/memory-validation.test.js +29 -0
- package/dist/mcp/__tests__/memory-validation.test.js.map +1 -0
- package/dist/mcp/__tests__/path-traversal.test.d.ts +2 -0
- package/dist/mcp/__tests__/path-traversal.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/path-traversal.test.js +83 -0
- package/dist/mcp/__tests__/path-traversal.test.js.map +1 -0
- package/dist/mcp/__tests__/server-lifecycle.test.d.ts +2 -0
- package/dist/mcp/__tests__/server-lifecycle.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/server-lifecycle.test.js +308 -0
- package/dist/mcp/__tests__/server-lifecycle.test.js.map +1 -0
- package/dist/mcp/__tests__/state-paths.test.d.ts +2 -0
- package/dist/mcp/__tests__/state-paths.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/state-paths.test.js +477 -0
- package/dist/mcp/__tests__/state-paths.test.js.map +1 -0
- package/dist/mcp/__tests__/state-server-ralph-phase.test.d.ts +2 -0
- package/dist/mcp/__tests__/state-server-ralph-phase.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/state-server-ralph-phase.test.js +109 -0
- package/dist/mcp/__tests__/state-server-ralph-phase.test.js.map +1 -0
- package/dist/mcp/__tests__/state-server-schema.test.d.ts +2 -0
- package/dist/mcp/__tests__/state-server-schema.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/state-server-schema.test.js +29 -0
- package/dist/mcp/__tests__/state-server-schema.test.js.map +1 -0
- package/dist/mcp/__tests__/state-server-team-tools.test.d.ts +2 -0
- package/dist/mcp/__tests__/state-server-team-tools.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/state-server-team-tools.test.js +35 -0
- package/dist/mcp/__tests__/state-server-team-tools.test.js.map +1 -0
- package/dist/mcp/__tests__/state-server.test.d.ts +2 -0
- package/dist/mcp/__tests__/state-server.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/state-server.test.js +1318 -0
- package/dist/mcp/__tests__/state-server.test.js.map +1 -0
- package/dist/mcp/__tests__/trace-server.test.d.ts +2 -0
- package/dist/mcp/__tests__/trace-server.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/trace-server.test.js +119 -0
- package/dist/mcp/__tests__/trace-server.test.js.map +1 -0
- package/dist/mcp/__tests__/wiki-server.test.d.ts +2 -0
- package/dist/mcp/__tests__/wiki-server.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/wiki-server.test.js +126 -0
- package/dist/mcp/__tests__/wiki-server.test.js.map +1 -0
- package/dist/mcp/bootstrap.d.ts +44 -0
- package/dist/mcp/bootstrap.d.ts.map +1 -0
- package/dist/mcp/bootstrap.js +520 -0
- package/dist/mcp/bootstrap.js.map +1 -0
- package/dist/mcp/code-intel-server.d.ts +333 -0
- package/dist/mcp/code-intel-server.d.ts.map +1 -0
- package/dist/mcp/code-intel-server.js +605 -0
- package/dist/mcp/code-intel-server.js.map +1 -0
- package/dist/mcp/hermes-bridge.d.ts +124 -0
- package/dist/mcp/hermes-bridge.d.ts.map +1 -0
- package/dist/mcp/hermes-bridge.js +549 -0
- package/dist/mcp/hermes-bridge.js.map +1 -0
- package/dist/mcp/hermes-server.d.ts +374 -0
- package/dist/mcp/hermes-server.d.ts.map +1 -0
- package/dist/mcp/hermes-server.js +158 -0
- package/dist/mcp/hermes-server.js.map +1 -0
- package/dist/mcp/lifecycle-telemetry.d.ts +16 -0
- package/dist/mcp/lifecycle-telemetry.d.ts.map +1 -0
- package/dist/mcp/lifecycle-telemetry.js +95 -0
- package/dist/mcp/lifecycle-telemetry.js.map +1 -0
- package/dist/mcp/memory-server.d.ts +201 -0
- package/dist/mcp/memory-server.d.ts.map +1 -0
- package/dist/mcp/memory-server.js +441 -0
- package/dist/mcp/memory-server.js.map +1 -0
- package/dist/mcp/memory-validation.d.ts +9 -0
- package/dist/mcp/memory-validation.d.ts.map +1 -0
- package/dist/mcp/memory-validation.js +11 -0
- package/dist/mcp/memory-validation.js.map +1 -0
- package/dist/mcp/state-paths.d.ts +91 -0
- package/dist/mcp/state-paths.d.ts.map +1 -0
- package/dist/mcp/state-paths.js +473 -0
- package/dist/mcp/state-paths.js.map +1 -0
- package/dist/mcp/state-server.d.ts +222 -0
- package/dist/mcp/state-server.d.ts.map +1 -0
- package/dist/mcp/state-server.js +181 -0
- package/dist/mcp/state-server.js.map +1 -0
- package/dist/mcp/trace-server.d.ts +81 -0
- package/dist/mcp/trace-server.d.ts.map +1 -0
- package/dist/mcp/trace-server.js +271 -0
- package/dist/mcp/trace-server.js.map +1 -0
- package/dist/mcp/wiki-server.d.ts +181 -0
- package/dist/mcp/wiki-server.d.ts.map +1 -0
- package/dist/mcp/wiki-server.js +244 -0
- package/dist/mcp/wiki-server.js.map +1 -0
- package/dist/modes/__tests__/base-autopilot-gates.test.d.ts +2 -0
- package/dist/modes/__tests__/base-autopilot-gates.test.d.ts.map +1 -0
- package/dist/modes/__tests__/base-autopilot-gates.test.js +154 -0
- package/dist/modes/__tests__/base-autopilot-gates.test.js.map +1 -0
- package/dist/modes/__tests__/base-autoresearch-contract.test.d.ts +2 -0
- package/dist/modes/__tests__/base-autoresearch-contract.test.d.ts.map +1 -0
- package/dist/modes/__tests__/base-autoresearch-contract.test.js +129 -0
- package/dist/modes/__tests__/base-autoresearch-contract.test.js.map +1 -0
- package/dist/modes/__tests__/base-multi-state-compat.test.d.ts +2 -0
- package/dist/modes/__tests__/base-multi-state-compat.test.d.ts.map +1 -0
- package/dist/modes/__tests__/base-multi-state-compat.test.js +38 -0
- package/dist/modes/__tests__/base-multi-state-compat.test.js.map +1 -0
- package/dist/modes/__tests__/base-ralph-contract.test.d.ts +2 -0
- package/dist/modes/__tests__/base-ralph-contract.test.d.ts.map +1 -0
- package/dist/modes/__tests__/base-ralph-contract.test.js +64 -0
- package/dist/modes/__tests__/base-ralph-contract.test.js.map +1 -0
- package/dist/modes/__tests__/base-session-scope.test.d.ts +2 -0
- package/dist/modes/__tests__/base-session-scope.test.d.ts.map +1 -0
- package/dist/modes/__tests__/base-session-scope.test.js +146 -0
- package/dist/modes/__tests__/base-session-scope.test.js.map +1 -0
- package/dist/modes/__tests__/base-tmux-pane.test.d.ts +2 -0
- package/dist/modes/__tests__/base-tmux-pane.test.d.ts.map +1 -0
- package/dist/modes/__tests__/base-tmux-pane.test.js +100 -0
- package/dist/modes/__tests__/base-tmux-pane.test.js.map +1 -0
- package/dist/modes/base.d.ts +60 -0
- package/dist/modes/base.d.ts.map +1 -0
- package/dist/modes/base.js +346 -0
- package/dist/modes/base.js.map +1 -0
- package/dist/notifications/__tests__/config.test.d.ts +2 -0
- package/dist/notifications/__tests__/config.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/config.test.js +269 -0
- package/dist/notifications/__tests__/config.test.js.map +1 -0
- package/dist/notifications/__tests__/custom-alias-enablement.test.d.ts +2 -0
- package/dist/notifications/__tests__/custom-alias-enablement.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/custom-alias-enablement.test.js +84 -0
- package/dist/notifications/__tests__/custom-alias-enablement.test.js.map +1 -0
- package/dist/notifications/__tests__/dispatch-cooldown.test.d.ts +5 -0
- package/dist/notifications/__tests__/dispatch-cooldown.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/dispatch-cooldown.test.js +100 -0
- package/dist/notifications/__tests__/dispatch-cooldown.test.js.map +1 -0
- package/dist/notifications/__tests__/dispatcher.test.d.ts +2 -0
- package/dist/notifications/__tests__/dispatcher.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/dispatcher.test.js +202 -0
- package/dist/notifications/__tests__/dispatcher.test.js.map +1 -0
- package/dist/notifications/__tests__/formatter.test.d.ts +2 -0
- package/dist/notifications/__tests__/formatter.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/formatter.test.js +270 -0
- package/dist/notifications/__tests__/formatter.test.js.map +1 -0
- package/dist/notifications/__tests__/hook-config.test.d.ts +5 -0
- package/dist/notifications/__tests__/hook-config.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/hook-config.test.js +139 -0
- package/dist/notifications/__tests__/hook-config.test.js.map +1 -0
- package/dist/notifications/__tests__/http-client-resource.test.d.ts +2 -0
- package/dist/notifications/__tests__/http-client-resource.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/http-client-resource.test.js +41 -0
- package/dist/notifications/__tests__/http-client-resource.test.js.map +1 -0
- package/dist/notifications/__tests__/http-client.test.d.ts +2 -0
- package/dist/notifications/__tests__/http-client.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/http-client.test.js +90 -0
- package/dist/notifications/__tests__/http-client.test.js.map +1 -0
- package/dist/notifications/__tests__/idle-cooldown.test.d.ts +5 -0
- package/dist/notifications/__tests__/idle-cooldown.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/idle-cooldown.test.js +209 -0
- package/dist/notifications/__tests__/idle-cooldown.test.js.map +1 -0
- package/dist/notifications/__tests__/index.test.d.ts +2 -0
- package/dist/notifications/__tests__/index.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/index.test.js +188 -0
- package/dist/notifications/__tests__/index.test.js.map +1 -0
- package/dist/notifications/__tests__/lifecycle-dedupe.test.d.ts +2 -0
- package/dist/notifications/__tests__/lifecycle-dedupe.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/lifecycle-dedupe.test.js +86 -0
- package/dist/notifications/__tests__/lifecycle-dedupe.test.js.map +1 -0
- package/dist/notifications/__tests__/notifier.test.d.ts +2 -0
- package/dist/notifications/__tests__/notifier.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/notifier.test.js +201 -0
- package/dist/notifications/__tests__/notifier.test.js.map +1 -0
- package/dist/notifications/__tests__/profiles.test.d.ts +2 -0
- package/dist/notifications/__tests__/profiles.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/profiles.test.js +404 -0
- package/dist/notifications/__tests__/profiles.test.js.map +1 -0
- package/dist/notifications/__tests__/reply-config.test.d.ts +2 -0
- package/dist/notifications/__tests__/reply-config.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/reply-config.test.js +79 -0
- package/dist/notifications/__tests__/reply-config.test.js.map +1 -0
- package/dist/notifications/__tests__/reply-listener.test.d.ts +2 -0
- package/dist/notifications/__tests__/reply-listener.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/reply-listener.test.js +723 -0
- package/dist/notifications/__tests__/reply-listener.test.js.map +1 -0
- package/dist/notifications/__tests__/session-idle-tail-dedupe.test.d.ts +2 -0
- package/dist/notifications/__tests__/session-idle-tail-dedupe.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/session-idle-tail-dedupe.test.js +93 -0
- package/dist/notifications/__tests__/session-idle-tail-dedupe.test.js.map +1 -0
- package/dist/notifications/__tests__/session-registry.test.d.ts +2 -0
- package/dist/notifications/__tests__/session-registry.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/session-registry.test.js +234 -0
- package/dist/notifications/__tests__/session-registry.test.js.map +1 -0
- package/dist/notifications/__tests__/session-status.test.d.ts +2 -0
- package/dist/notifications/__tests__/session-status.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/session-status.test.js +249 -0
- package/dist/notifications/__tests__/session-status.test.js.map +1 -0
- package/dist/notifications/__tests__/temp-mode.test.d.ts +2 -0
- package/dist/notifications/__tests__/temp-mode.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/temp-mode.test.js +172 -0
- package/dist/notifications/__tests__/temp-mode.test.js.map +1 -0
- package/dist/notifications/__tests__/template-engine.test.d.ts +5 -0
- package/dist/notifications/__tests__/template-engine.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/template-engine.test.js +158 -0
- package/dist/notifications/__tests__/template-engine.test.js.map +1 -0
- package/dist/notifications/__tests__/tmux-detector.test.d.ts +2 -0
- package/dist/notifications/__tests__/tmux-detector.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/tmux-detector.test.js +204 -0
- package/dist/notifications/__tests__/tmux-detector.test.js.map +1 -0
- package/dist/notifications/__tests__/tmux.test.d.ts +2 -0
- package/dist/notifications/__tests__/tmux.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/tmux.test.js +285 -0
- package/dist/notifications/__tests__/tmux.test.js.map +1 -0
- package/dist/notifications/__tests__/verbosity.test.d.ts +2 -0
- package/dist/notifications/__tests__/verbosity.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/verbosity.test.js +257 -0
- package/dist/notifications/__tests__/verbosity.test.js.map +1 -0
- package/dist/notifications/config.d.ts +65 -0
- package/dist/notifications/config.d.ts.map +1 -0
- package/dist/notifications/config.js +615 -0
- package/dist/notifications/config.js.map +1 -0
- package/dist/notifications/dispatch-cooldown.d.ts +36 -0
- package/dist/notifications/dispatch-cooldown.d.ts.map +1 -0
- package/dist/notifications/dispatch-cooldown.js +109 -0
- package/dist/notifications/dispatch-cooldown.js.map +1 -0
- package/dist/notifications/dispatcher.d.ts +15 -0
- package/dist/notifications/dispatcher.d.ts.map +1 -0
- package/dist/notifications/dispatcher.js +385 -0
- package/dist/notifications/dispatcher.js.map +1 -0
- package/dist/notifications/formatter.d.ts +30 -0
- package/dist/notifications/formatter.d.ts.map +1 -0
- package/dist/notifications/formatter.js +234 -0
- package/dist/notifications/formatter.js.map +1 -0
- package/dist/notifications/hook-config-types.d.ts +43 -0
- package/dist/notifications/hook-config-types.d.ts.map +1 -0
- package/dist/notifications/hook-config-types.js +8 -0
- package/dist/notifications/hook-config-types.js.map +1 -0
- package/dist/notifications/hook-config.d.ts +40 -0
- package/dist/notifications/hook-config.d.ts.map +1 -0
- package/dist/notifications/hook-config.js +127 -0
- package/dist/notifications/hook-config.js.map +1 -0
- package/dist/notifications/http-client.d.ts +22 -0
- package/dist/notifications/http-client.d.ts.map +1 -0
- package/dist/notifications/http-client.js +349 -0
- package/dist/notifications/http-client.js.map +1 -0
- package/dist/notifications/idle-cooldown.d.ts +61 -0
- package/dist/notifications/idle-cooldown.d.ts.map +1 -0
- package/dist/notifications/idle-cooldown.js +207 -0
- package/dist/notifications/idle-cooldown.js.map +1 -0
- package/dist/notifications/index.d.ts +40 -0
- package/dist/notifications/index.d.ts.map +1 -0
- package/dist/notifications/index.js +228 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/notifications/lifecycle-dedupe.d.ts +8 -0
- package/dist/notifications/lifecycle-dedupe.d.ts.map +1 -0
- package/dist/notifications/lifecycle-dedupe.js +112 -0
- package/dist/notifications/lifecycle-dedupe.js.map +1 -0
- package/dist/notifications/notifier.d.ts +45 -0
- package/dist/notifications/notifier.d.ts.map +1 -0
- package/dist/notifications/notifier.js +146 -0
- package/dist/notifications/notifier.js.map +1 -0
- package/dist/notifications/reply-listener.d.ts +123 -0
- package/dist/notifications/reply-listener.d.ts.map +1 -0
- package/dist/notifications/reply-listener.js +846 -0
- package/dist/notifications/reply-listener.js.map +1 -0
- package/dist/notifications/session-registry.d.ts +26 -0
- package/dist/notifications/session-registry.d.ts.map +1 -0
- package/dist/notifications/session-registry.js +293 -0
- package/dist/notifications/session-registry.js.map +1 -0
- package/dist/notifications/session-status.d.ts +25 -0
- package/dist/notifications/session-status.d.ts.map +1 -0
- package/dist/notifications/session-status.js +202 -0
- package/dist/notifications/session-status.js.map +1 -0
- package/dist/notifications/temp-contract.d.ts +22 -0
- package/dist/notifications/temp-contract.d.ts.map +1 -0
- package/dist/notifications/temp-contract.js +147 -0
- package/dist/notifications/temp-contract.js.map +1 -0
- package/dist/notifications/template-engine.d.ts +34 -0
- package/dist/notifications/template-engine.d.ts.map +1 -0
- package/dist/notifications/template-engine.js +249 -0
- package/dist/notifications/template-engine.js.map +1 -0
- package/dist/notifications/tmux-detector.d.ts +59 -0
- package/dist/notifications/tmux-detector.d.ts.map +1 -0
- package/dist/notifications/tmux-detector.js +126 -0
- package/dist/notifications/tmux-detector.js.map +1 -0
- package/dist/notifications/tmux.d.ts +44 -0
- package/dist/notifications/tmux.d.ts.map +1 -0
- package/dist/notifications/tmux.js +293 -0
- package/dist/notifications/tmux.js.map +1 -0
- package/dist/notifications/types.d.ts +226 -0
- package/dist/notifications/types.d.ts.map +1 -0
- package/dist/notifications/types.js +9 -0
- package/dist/notifications/types.js.map +1 -0
- package/dist/openclaw/__tests__/config.test.d.ts +6 -0
- package/dist/openclaw/__tests__/config.test.d.ts.map +1 -0
- package/dist/openclaw/__tests__/config.test.js +344 -0
- package/dist/openclaw/__tests__/config.test.js.map +1 -0
- package/dist/openclaw/__tests__/dispatcher.test.d.ts +5 -0
- package/dist/openclaw/__tests__/dispatcher.test.d.ts.map +1 -0
- package/dist/openclaw/__tests__/dispatcher.test.js +278 -0
- package/dist/openclaw/__tests__/dispatcher.test.js.map +1 -0
- package/dist/openclaw/__tests__/index.test.d.ts +6 -0
- package/dist/openclaw/__tests__/index.test.d.ts.map +1 -0
- package/dist/openclaw/__tests__/index.test.js +382 -0
- package/dist/openclaw/__tests__/index.test.js.map +1 -0
- package/dist/openclaw/config.d.ts +59 -0
- package/dist/openclaw/config.d.ts.map +1 -0
- package/dist/openclaw/config.js +400 -0
- package/dist/openclaw/config.js.map +1 -0
- package/dist/openclaw/dispatcher.d.ts +75 -0
- package/dist/openclaw/dispatcher.d.ts.map +1 -0
- package/dist/openclaw/dispatcher.js +223 -0
- package/dist/openclaw/dispatcher.js.map +1 -0
- package/dist/openclaw/index.d.ts +29 -0
- package/dist/openclaw/index.d.ts.map +1 -0
- package/dist/openclaw/index.js +149 -0
- package/dist/openclaw/index.js.map +1 -0
- package/dist/openclaw/types.d.ts +123 -0
- package/dist/openclaw/types.d.ts.map +1 -0
- package/dist/openclaw/types.js +12 -0
- package/dist/openclaw/types.js.map +1 -0
- package/dist/performance-goal/artifacts.d.ts +76 -0
- package/dist/performance-goal/artifacts.d.ts.map +1 -0
- package/dist/performance-goal/artifacts.js +221 -0
- package/dist/performance-goal/artifacts.js.map +1 -0
- package/dist/pipeline/__tests__/orchestrator.test.d.ts +2 -0
- package/dist/pipeline/__tests__/orchestrator.test.d.ts.map +1 -0
- package/dist/pipeline/__tests__/orchestrator.test.js +645 -0
- package/dist/pipeline/__tests__/orchestrator.test.js.map +1 -0
- package/dist/pipeline/__tests__/stages.test.d.ts +2 -0
- package/dist/pipeline/__tests__/stages.test.d.ts.map +1 -0
- package/dist/pipeline/__tests__/stages.test.js +1638 -0
- package/dist/pipeline/__tests__/stages.test.js.map +1 -0
- package/dist/pipeline/index.d.ts +25 -0
- package/dist/pipeline/index.d.ts.map +1 -0
- package/dist/pipeline/index.js +17 -0
- package/dist/pipeline/index.js.map +1 -0
- package/dist/pipeline/orchestrator.d.ts +52 -0
- package/dist/pipeline/orchestrator.d.ts.map +1 -0
- package/dist/pipeline/orchestrator.js +392 -0
- package/dist/pipeline/orchestrator.js.map +1 -0
- package/dist/pipeline/review-verdict.d.ts +3 -0
- package/dist/pipeline/review-verdict.d.ts.map +1 -0
- package/dist/pipeline/review-verdict.js +14 -0
- package/dist/pipeline/review-verdict.js.map +1 -0
- package/dist/pipeline/stages/code-review.d.ts +35 -0
- package/dist/pipeline/stages/code-review.d.ts.map +1 -0
- package/dist/pipeline/stages/code-review.js +55 -0
- package/dist/pipeline/stages/code-review.js.map +1 -0
- package/dist/pipeline/stages/deep-interview.d.ts +15 -0
- package/dist/pipeline/stages/deep-interview.d.ts.map +1 -0
- package/dist/pipeline/stages/deep-interview.js +32 -0
- package/dist/pipeline/stages/deep-interview.js.map +1 -0
- package/dist/pipeline/stages/ralph-verify.d.ts +53 -0
- package/dist/pipeline/stages/ralph-verify.d.ts.map +1 -0
- package/dist/pipeline/stages/ralph-verify.js +89 -0
- package/dist/pipeline/stages/ralph-verify.js.map +1 -0
- package/dist/pipeline/stages/ralplan.d.ts +26 -0
- package/dist/pipeline/stages/ralplan.d.ts.map +1 -0
- package/dist/pipeline/stages/ralplan.js +151 -0
- package/dist/pipeline/stages/ralplan.js.map +1 -0
- package/dist/pipeline/stages/team-exec.d.ts +52 -0
- package/dist/pipeline/stages/team-exec.d.ts.map +1 -0
- package/dist/pipeline/stages/team-exec.js +266 -0
- package/dist/pipeline/stages/team-exec.js.map +1 -0
- package/dist/pipeline/stages/ultragoal.d.ts +19 -0
- package/dist/pipeline/stages/ultragoal.d.ts.map +1 -0
- package/dist/pipeline/stages/ultragoal.js +38 -0
- package/dist/pipeline/stages/ultragoal.js.map +1 -0
- package/dist/pipeline/stages/ultraqa.d.ts +33 -0
- package/dist/pipeline/stages/ultraqa.d.ts.map +1 -0
- package/dist/pipeline/stages/ultraqa.js +49 -0
- package/dist/pipeline/stages/ultraqa.js.map +1 -0
- package/dist/pipeline/types.d.ts +124 -0
- package/dist/pipeline/types.d.ts.map +1 -0
- package/dist/pipeline/types.js +8 -0
- package/dist/pipeline/types.js.map +1 -0
- package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.d.ts +2 -0
- package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.d.ts.map +1 -0
- package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.js +158 -0
- package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.js.map +1 -0
- package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.d.ts +2 -0
- package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.d.ts.map +1 -0
- package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.js +440 -0
- package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.js.map +1 -0
- package/dist/planning/__tests__/artifacts.test.d.ts +2 -0
- package/dist/planning/__tests__/artifacts.test.d.ts.map +1 -0
- package/dist/planning/__tests__/artifacts.test.js +942 -0
- package/dist/planning/__tests__/artifacts.test.js.map +1 -0
- package/dist/planning/__tests__/markdown-structure.test.d.ts +2 -0
- package/dist/planning/__tests__/markdown-structure.test.d.ts.map +1 -0
- package/dist/planning/__tests__/markdown-structure.test.js +459 -0
- package/dist/planning/__tests__/markdown-structure.test.js.map +1 -0
- package/dist/planning/artifact-names.d.ts +13 -0
- package/dist/planning/artifact-names.d.ts.map +1 -0
- package/dist/planning/artifact-names.js +108 -0
- package/dist/planning/artifact-names.js.map +1 -0
- package/dist/planning/artifacts.d.ts +65 -0
- package/dist/planning/artifacts.d.ts.map +1 -0
- package/dist/planning/artifacts.js +561 -0
- package/dist/planning/artifacts.js.map +1 -0
- package/dist/planning/markdown-structure.d.ts +20 -0
- package/dist/planning/markdown-structure.d.ts.map +1 -0
- package/dist/planning/markdown-structure.js +137 -0
- package/dist/planning/markdown-structure.js.map +1 -0
- package/dist/question/__tests__/client.test.d.ts +2 -0
- package/dist/question/__tests__/client.test.d.ts.map +1 -0
- package/dist/question/__tests__/client.test.js +90 -0
- package/dist/question/__tests__/client.test.js.map +1 -0
- package/dist/question/__tests__/deep-interview.test.d.ts +2 -0
- package/dist/question/__tests__/deep-interview.test.d.ts.map +1 -0
- package/dist/question/__tests__/deep-interview.test.js +440 -0
- package/dist/question/__tests__/deep-interview.test.js.map +1 -0
- package/dist/question/__tests__/policy.test.d.ts +2 -0
- package/dist/question/__tests__/policy.test.d.ts.map +1 -0
- package/dist/question/__tests__/policy.test.js +273 -0
- package/dist/question/__tests__/policy.test.js.map +1 -0
- package/dist/question/__tests__/renderer.test.d.ts +2 -0
- package/dist/question/__tests__/renderer.test.d.ts.map +1 -0
- package/dist/question/__tests__/renderer.test.js +1461 -0
- package/dist/question/__tests__/renderer.test.js.map +1 -0
- package/dist/question/__tests__/state.test.d.ts +2 -0
- package/dist/question/__tests__/state.test.d.ts.map +1 -0
- package/dist/question/__tests__/state.test.js +541 -0
- package/dist/question/__tests__/state.test.js.map +1 -0
- package/dist/question/__tests__/types.test.d.ts +2 -0
- package/dist/question/__tests__/types.test.d.ts.map +1 -0
- package/dist/question/__tests__/types.test.js +65 -0
- package/dist/question/__tests__/types.test.js.map +1 -0
- package/dist/question/__tests__/ui.test.d.ts +2 -0
- package/dist/question/__tests__/ui.test.d.ts.map +1 -0
- package/dist/question/__tests__/ui.test.js +483 -0
- package/dist/question/__tests__/ui.test.js.map +1 -0
- package/dist/question/autopilot-wait.d.ts +21 -0
- package/dist/question/autopilot-wait.d.ts.map +1 -0
- package/dist/question/autopilot-wait.js +251 -0
- package/dist/question/autopilot-wait.js.map +1 -0
- package/dist/question/client.d.ts +64 -0
- package/dist/question/client.d.ts.map +1 -0
- package/dist/question/client.js +77 -0
- package/dist/question/client.js.map +1 -0
- package/dist/question/deep-interview.d.ts +33 -0
- package/dist/question/deep-interview.d.ts.map +1 -0
- package/dist/question/deep-interview.js +216 -0
- package/dist/question/deep-interview.js.map +1 -0
- package/dist/question/events.d.ts +53 -0
- package/dist/question/events.d.ts.map +1 -0
- package/dist/question/events.js +201 -0
- package/dist/question/events.js.map +1 -0
- package/dist/question/policy.d.ts +19 -0
- package/dist/question/policy.d.ts.map +1 -0
- package/dist/question/policy.js +95 -0
- package/dist/question/policy.js.map +1 -0
- package/dist/question/renderer.d.ts +66 -0
- package/dist/question/renderer.d.ts.map +1 -0
- package/dist/question/renderer.js +748 -0
- package/dist/question/renderer.js.map +1 -0
- package/dist/question/state.d.ts +56 -0
- package/dist/question/state.d.ts.map +1 -0
- package/dist/question/state.js +432 -0
- package/dist/question/state.js.map +1 -0
- package/dist/question/types.d.ts +92 -0
- package/dist/question/types.d.ts.map +1 -0
- package/dist/question/types.js +117 -0
- package/dist/question/types.js.map +1 -0
- package/dist/question/ui.d.ts +66 -0
- package/dist/question/ui.d.ts.map +1 -0
- package/dist/question/ui.js +458 -0
- package/dist/question/ui.js.map +1 -0
- package/dist/ralph/__tests__/completion-audit.test.d.ts +2 -0
- package/dist/ralph/__tests__/completion-audit.test.d.ts.map +1 -0
- package/dist/ralph/__tests__/completion-audit.test.js +160 -0
- package/dist/ralph/__tests__/completion-audit.test.js.map +1 -0
- package/dist/ralph/__tests__/persistence.test.d.ts +2 -0
- package/dist/ralph/__tests__/persistence.test.d.ts.map +1 -0
- package/dist/ralph/__tests__/persistence.test.js +116 -0
- package/dist/ralph/__tests__/persistence.test.js.map +1 -0
- package/dist/ralph/completion-audit.d.ts +8 -0
- package/dist/ralph/completion-audit.d.ts.map +1 -0
- package/dist/ralph/completion-audit.js +99 -0
- package/dist/ralph/completion-audit.js.map +1 -0
- package/dist/ralph/contract.d.ts +17 -0
- package/dist/ralph/contract.d.ts.map +1 -0
- package/dist/ralph/contract.js +108 -0
- package/dist/ralph/contract.js.map +1 -0
- package/dist/ralph/persistence.d.ts +29 -0
- package/dist/ralph/persistence.d.ts.map +1 -0
- package/dist/ralph/persistence.js +273 -0
- package/dist/ralph/persistence.js.map +1 -0
- package/dist/ralplan/__tests__/consensus-gate.test.d.ts +2 -0
- package/dist/ralplan/__tests__/consensus-gate.test.d.ts.map +1 -0
- package/dist/ralplan/__tests__/consensus-gate.test.js +192 -0
- package/dist/ralplan/__tests__/consensus-gate.test.js.map +1 -0
- package/dist/ralplan/__tests__/runtime.test.d.ts +2 -0
- package/dist/ralplan/__tests__/runtime.test.d.ts.map +1 -0
- package/dist/ralplan/__tests__/runtime.test.js +548 -0
- package/dist/ralplan/__tests__/runtime.test.js.map +1 -0
- package/dist/ralplan/consensus-gate.d.ts +37 -0
- package/dist/ralplan/consensus-gate.d.ts.map +1 -0
- package/dist/ralplan/consensus-gate.js +422 -0
- package/dist/ralplan/consensus-gate.js.map +1 -0
- package/dist/ralplan/runtime.d.ts +86 -0
- package/dist/ralplan/runtime.d.ts.map +1 -0
- package/dist/ralplan/runtime.js +365 -0
- package/dist/ralplan/runtime.js.map +1 -0
- package/dist/runtime/__tests__/bridge.test.d.ts +2 -0
- package/dist/runtime/__tests__/bridge.test.d.ts.map +1 -0
- package/dist/runtime/__tests__/bridge.test.js +194 -0
- package/dist/runtime/__tests__/bridge.test.js.map +1 -0
- package/dist/runtime/__tests__/process-tree.test.d.ts +2 -0
- package/dist/runtime/__tests__/process-tree.test.d.ts.map +1 -0
- package/dist/runtime/__tests__/process-tree.test.js +107 -0
- package/dist/runtime/__tests__/process-tree.test.js.map +1 -0
- package/dist/runtime/__tests__/run-loop.test.d.ts +2 -0
- package/dist/runtime/__tests__/run-loop.test.d.ts.map +1 -0
- package/dist/runtime/__tests__/run-loop.test.js +35 -0
- package/dist/runtime/__tests__/run-loop.test.js.map +1 -0
- package/dist/runtime/__tests__/run-outcome.test.d.ts +2 -0
- package/dist/runtime/__tests__/run-outcome.test.d.ts.map +1 -0
- package/dist/runtime/__tests__/run-outcome.test.js +102 -0
- package/dist/runtime/__tests__/run-outcome.test.js.map +1 -0
- package/dist/runtime/__tests__/run-state.test.d.ts +2 -0
- package/dist/runtime/__tests__/run-state.test.d.ts.map +1 -0
- package/dist/runtime/__tests__/run-state.test.js +37 -0
- package/dist/runtime/__tests__/run-state.test.js.map +1 -0
- package/dist/runtime/bridge.d.ts +214 -0
- package/dist/runtime/bridge.d.ts.map +1 -0
- package/dist/runtime/bridge.js +223 -0
- package/dist/runtime/bridge.js.map +1 -0
- package/dist/runtime/process-tree.d.ts +28 -0
- package/dist/runtime/process-tree.d.ts.map +1 -0
- package/dist/runtime/process-tree.js +230 -0
- package/dist/runtime/process-tree.js.map +1 -0
- package/dist/runtime/run-loop.d.ts +45 -0
- package/dist/runtime/run-loop.d.ts.map +1 -0
- package/dist/runtime/run-loop.js +51 -0
- package/dist/runtime/run-loop.js.map +1 -0
- package/dist/runtime/run-outcome.d.ts +46 -0
- package/dist/runtime/run-outcome.d.ts.map +1 -0
- package/dist/runtime/run-outcome.js +285 -0
- package/dist/runtime/run-outcome.js.map +1 -0
- package/dist/runtime/run-state.d.ts +40 -0
- package/dist/runtime/run-state.d.ts.map +1 -0
- package/dist/runtime/run-state.js +120 -0
- package/dist/runtime/run-state.js.map +1 -0
- package/dist/runtime/terminal-lifecycle.d.ts +11 -0
- package/dist/runtime/terminal-lifecycle.d.ts.map +1 -0
- package/dist/runtime/terminal-lifecycle.js +52 -0
- package/dist/runtime/terminal-lifecycle.js.map +1 -0
- package/dist/scripts/__tests__/codex-native-hook.test.d.ts +2 -0
- package/dist/scripts/__tests__/codex-native-hook.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/codex-native-hook.test.js +14253 -0
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -0
- package/dist/scripts/__tests__/docs-site-contract.test.d.ts +2 -0
- package/dist/scripts/__tests__/docs-site-contract.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/docs-site-contract.test.js +42 -0
- package/dist/scripts/__tests__/docs-site-contract.test.js.map +1 -0
- package/dist/scripts/__tests__/generate-release-body.test.d.ts +2 -0
- package/dist/scripts/__tests__/generate-release-body.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/generate-release-body.test.js +233 -0
- package/dist/scripts/__tests__/generate-release-body.test.js.map +1 -0
- package/dist/scripts/__tests__/hook-derived-watcher.test.d.ts +2 -0
- package/dist/scripts/__tests__/hook-derived-watcher.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/hook-derived-watcher.test.js +227 -0
- package/dist/scripts/__tests__/hook-derived-watcher.test.js.map +1 -0
- package/dist/scripts/__tests__/notify-dispatcher.test.d.ts +2 -0
- package/dist/scripts/__tests__/notify-dispatcher.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/notify-dispatcher.test.js +421 -0
- package/dist/scripts/__tests__/notify-dispatcher.test.js.map +1 -0
- package/dist/scripts/__tests__/notify-state-io.test.d.ts +2 -0
- package/dist/scripts/__tests__/notify-state-io.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/notify-state-io.test.js +111 -0
- package/dist/scripts/__tests__/notify-state-io.test.js.map +1 -0
- package/dist/scripts/__tests__/notify-tmux-injection.test.d.ts +2 -0
- package/dist/scripts/__tests__/notify-tmux-injection.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/notify-tmux-injection.test.js +57 -0
- package/dist/scripts/__tests__/notify-tmux-injection.test.js.map +1 -0
- package/dist/scripts/__tests__/postinstall.test.d.ts +2 -0
- package/dist/scripts/__tests__/postinstall.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/postinstall.test.js +92 -0
- package/dist/scripts/__tests__/postinstall.test.js.map +1 -0
- package/dist/scripts/__tests__/prompt-inventory.test.d.ts +2 -0
- package/dist/scripts/__tests__/prompt-inventory.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/prompt-inventory.test.js +56 -0
- package/dist/scripts/__tests__/prompt-inventory.test.js.map +1 -0
- package/dist/scripts/__tests__/run-test-files.test.d.ts +2 -0
- package/dist/scripts/__tests__/run-test-files.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/run-test-files.test.js +365 -0
- package/dist/scripts/__tests__/run-test-files.test.js.map +1 -0
- package/dist/scripts/__tests__/smoke-packed-install.test.d.ts +2 -0
- package/dist/scripts/__tests__/smoke-packed-install.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/smoke-packed-install.test.js +160 -0
- package/dist/scripts/__tests__/smoke-packed-install.test.js.map +1 -0
- package/dist/scripts/__tests__/test-reply-listener-live.test.d.ts +2 -0
- package/dist/scripts/__tests__/test-reply-listener-live.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/test-reply-listener-live.test.js +82 -0
- package/dist/scripts/__tests__/test-reply-listener-live.test.js.map +1 -0
- package/dist/scripts/__tests__/verify-native-agents.test.d.ts +2 -0
- package/dist/scripts/__tests__/verify-native-agents.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/verify-native-agents.test.js +246 -0
- package/dist/scripts/__tests__/verify-native-agents.test.js.map +1 -0
- package/dist/scripts/build-api.d.ts +2 -0
- package/dist/scripts/build-api.d.ts.map +1 -0
- package/dist/scripts/build-api.js +44 -0
- package/dist/scripts/build-api.js.map +1 -0
- package/dist/scripts/build-explore-harness.d.ts +3 -0
- package/dist/scripts/build-explore-harness.d.ts.map +1 -0
- package/dist/scripts/build-explore-harness.js +50 -0
- package/dist/scripts/build-explore-harness.js.map +1 -0
- package/dist/scripts/build-sparkshell.d.ts +2 -0
- package/dist/scripts/build-sparkshell.d.ts.map +1 -0
- package/dist/scripts/build-sparkshell.js +46 -0
- package/dist/scripts/build-sparkshell.js.map +1 -0
- package/dist/scripts/check-runtime-syntax.d.ts +3 -0
- package/dist/scripts/check-runtime-syntax.d.ts.map +1 -0
- package/dist/scripts/check-runtime-syntax.js +57 -0
- package/dist/scripts/check-runtime-syntax.js.map +1 -0
- package/dist/scripts/check-version-sync.d.ts +3 -0
- package/dist/scripts/check-version-sync.d.ts.map +1 -0
- package/dist/scripts/check-version-sync.js +53 -0
- package/dist/scripts/check-version-sync.js.map +1 -0
- package/dist/scripts/cleanup-explore-harness.d.ts +3 -0
- package/dist/scripts/cleanup-explore-harness.d.ts.map +1 -0
- package/dist/scripts/cleanup-explore-harness.js +17 -0
- package/dist/scripts/cleanup-explore-harness.js.map +1 -0
- package/dist/scripts/codex-execution-surface.d.ts +16 -0
- package/dist/scripts/codex-execution-surface.d.ts.map +1 -0
- package/dist/scripts/codex-execution-surface.js +42 -0
- package/dist/scripts/codex-execution-surface.js.map +1 -0
- package/dist/scripts/codex-native-hook.d.ts +26 -0
- package/dist/scripts/codex-native-hook.d.ts.map +1 -0
- package/dist/scripts/codex-native-hook.js +3842 -0
- package/dist/scripts/codex-native-hook.js.map +1 -0
- package/dist/scripts/codex-native-pre-post.d.ts +46 -0
- package/dist/scripts/codex-native-pre-post.d.ts.map +1 -0
- package/dist/scripts/codex-native-pre-post.js +1186 -0
- package/dist/scripts/codex-native-pre-post.js.map +1 -0
- package/dist/scripts/eval/eval-candidate-handoff.d.ts +2 -0
- package/dist/scripts/eval/eval-candidate-handoff.d.ts.map +1 -0
- package/dist/scripts/eval/eval-candidate-handoff.js +11 -0
- package/dist/scripts/eval/eval-candidate-handoff.js.map +1 -0
- package/dist/scripts/eval/eval-cli-discoverability.d.ts +3 -0
- package/dist/scripts/eval/eval-cli-discoverability.d.ts.map +1 -0
- package/dist/scripts/eval/eval-cli-discoverability.js +37 -0
- package/dist/scripts/eval/eval-cli-discoverability.js.map +1 -0
- package/dist/scripts/eval/eval-fresh-run-tagging.d.ts +2 -0
- package/dist/scripts/eval/eval-fresh-run-tagging.d.ts.map +1 -0
- package/dist/scripts/eval/eval-fresh-run-tagging.js +11 -0
- package/dist/scripts/eval/eval-fresh-run-tagging.js.map +1 -0
- package/dist/scripts/eval/eval-help-consistency.d.ts +2 -0
- package/dist/scripts/eval/eval-help-consistency.d.ts.map +1 -0
- package/dist/scripts/eval/eval-help-consistency.js +12 -0
- package/dist/scripts/eval/eval-help-consistency.js.map +1 -0
- package/dist/scripts/eval/eval-in-action-cat-shellout-demo.d.ts +2 -0
- package/dist/scripts/eval/eval-in-action-cat-shellout-demo.d.ts.map +1 -0
- package/dist/scripts/eval/eval-in-action-cat-shellout-demo.js +31 -0
- package/dist/scripts/eval/eval-in-action-cat-shellout-demo.js.map +1 -0
- package/dist/scripts/eval/eval-parity-smoke.d.ts +2 -0
- package/dist/scripts/eval/eval-parity-smoke.d.ts.map +1 -0
- package/dist/scripts/eval/eval-parity-smoke.js +23 -0
- package/dist/scripts/eval/eval-parity-smoke.js.map +1 -0
- package/dist/scripts/eval/eval-parity-sweep.d.ts +2 -0
- package/dist/scripts/eval/eval-parity-sweep.d.ts.map +1 -0
- package/dist/scripts/eval/eval-parity-sweep.js +29 -0
- package/dist/scripts/eval/eval-parity-sweep.js.map +1 -0
- package/dist/scripts/eval/eval-resume-dirty-guard.d.ts +2 -0
- package/dist/scripts/eval/eval-resume-dirty-guard.d.ts.map +1 -0
- package/dist/scripts/eval/eval-resume-dirty-guard.js +11 -0
- package/dist/scripts/eval/eval-resume-dirty-guard.js.map +1 -0
- package/dist/scripts/eval/eval-security-path-traversal.d.ts +3 -0
- package/dist/scripts/eval/eval-security-path-traversal.d.ts.map +1 -0
- package/dist/scripts/eval/eval-security-path-traversal.js +35 -0
- package/dist/scripts/eval/eval-security-path-traversal.js.map +1 -0
- package/dist/scripts/fixtures/ask-advisor-stub.d.ts +3 -0
- package/dist/scripts/fixtures/ask-advisor-stub.d.ts.map +1 -0
- package/dist/scripts/fixtures/ask-advisor-stub.js +13 -0
- package/dist/scripts/fixtures/ask-advisor-stub.js.map +1 -0
- package/dist/scripts/generate-catalog-docs.d.ts +3 -0
- package/dist/scripts/generate-catalog-docs.d.ts.map +1 -0
- package/dist/scripts/generate-catalog-docs.js +99 -0
- package/dist/scripts/generate-catalog-docs.js.map +1 -0
- package/dist/scripts/generate-native-release-manifest.d.ts +3 -0
- package/dist/scripts/generate-native-release-manifest.d.ts.map +1 -0
- package/dist/scripts/generate-native-release-manifest.js +107 -0
- package/dist/scripts/generate-native-release-manifest.js.map +1 -0
- package/dist/scripts/generate-release-body.d.ts +35 -0
- package/dist/scripts/generate-release-body.d.ts.map +1 -0
- package/dist/scripts/generate-release-body.js +278 -0
- package/dist/scripts/generate-release-body.js.map +1 -0
- package/dist/scripts/hook-derived-watcher.d.ts +3 -0
- package/dist/scripts/hook-derived-watcher.d.ts.map +1 -0
- package/dist/scripts/hook-derived-watcher.js +557 -0
- package/dist/scripts/hook-derived-watcher.js.map +1 -0
- package/dist/scripts/hook-payload-guard.d.ts +9 -0
- package/dist/scripts/hook-payload-guard.d.ts.map +1 -0
- package/dist/scripts/hook-payload-guard.js +111 -0
- package/dist/scripts/hook-payload-guard.js.map +1 -0
- package/dist/scripts/notify-dispatcher.d.ts +7 -0
- package/dist/scripts/notify-dispatcher.d.ts.map +1 -0
- package/dist/scripts/notify-dispatcher.js +359 -0
- package/dist/scripts/notify-dispatcher.js.map +1 -0
- package/dist/scripts/notify-fallback-watcher.d.ts +3 -0
- package/dist/scripts/notify-fallback-watcher.d.ts.map +1 -0
- package/dist/scripts/notify-fallback-watcher.js +1771 -0
- package/dist/scripts/notify-fallback-watcher.js.map +1 -0
- package/dist/scripts/notify-hook/__tests__/operational-events.test.d.ts +2 -0
- package/dist/scripts/notify-hook/__tests__/operational-events.test.d.ts.map +1 -0
- package/dist/scripts/notify-hook/__tests__/operational-events.test.js +24 -0
- package/dist/scripts/notify-hook/__tests__/operational-events.test.js.map +1 -0
- package/dist/scripts/notify-hook/__tests__/payload-guard.test.d.ts +2 -0
- package/dist/scripts/notify-hook/__tests__/payload-guard.test.d.ts.map +1 -0
- package/dist/scripts/notify-hook/__tests__/payload-guard.test.js +39 -0
- package/dist/scripts/notify-hook/__tests__/payload-guard.test.js.map +1 -0
- package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.d.ts +2 -0
- package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.d.ts.map +1 -0
- package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.js +153 -0
- package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.js.map +1 -0
- package/dist/scripts/notify-hook/active-team.d.ts +9 -0
- package/dist/scripts/notify-hook/active-team.d.ts.map +1 -0
- package/dist/scripts/notify-hook/active-team.js +45 -0
- package/dist/scripts/notify-hook/active-team.js.map +1 -0
- package/dist/scripts/notify-hook/auto-nudge.d.ts +96 -0
- package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -0
- package/dist/scripts/notify-hook/auto-nudge.js +698 -0
- package/dist/scripts/notify-hook/auto-nudge.js.map +1 -0
- package/dist/scripts/notify-hook/log.d.ts +6 -0
- package/dist/scripts/notify-hook/log.d.ts.map +1 -0
- package/dist/scripts/notify-hook/log.js +22 -0
- package/dist/scripts/notify-hook/log.js.map +1 -0
- package/dist/scripts/notify-hook/managed-tmux.d.ts +21 -0
- package/dist/scripts/notify-hook/managed-tmux.d.ts.map +1 -0
- package/dist/scripts/notify-hook/managed-tmux.js +541 -0
- package/dist/scripts/notify-hook/managed-tmux.js.map +1 -0
- package/dist/scripts/notify-hook/operational-events.d.ts +14 -0
- package/dist/scripts/notify-hook/operational-events.d.ts.map +1 -0
- package/dist/scripts/notify-hook/operational-events.js +255 -0
- package/dist/scripts/notify-hook/operational-events.js.map +1 -0
- package/dist/scripts/notify-hook/orchestration-intent.d.ts +17 -0
- package/dist/scripts/notify-hook/orchestration-intent.d.ts.map +1 -0
- package/dist/scripts/notify-hook/orchestration-intent.js +71 -0
- package/dist/scripts/notify-hook/orchestration-intent.js.map +1 -0
- package/dist/scripts/notify-hook/payload-parser.d.ts +13 -0
- package/dist/scripts/notify-hook/payload-parser.d.ts.map +1 -0
- package/dist/scripts/notify-hook/payload-parser.js +134 -0
- package/dist/scripts/notify-hook/payload-parser.js.map +1 -0
- package/dist/scripts/notify-hook/process-runner.d.ts +9 -0
- package/dist/scripts/notify-hook/process-runner.d.ts.map +1 -0
- package/dist/scripts/notify-hook/process-runner.js +74 -0
- package/dist/scripts/notify-hook/process-runner.js.map +1 -0
- package/dist/scripts/notify-hook/ralph-session-resume.d.ts +22 -0
- package/dist/scripts/notify-hook/ralph-session-resume.d.ts.map +1 -0
- package/dist/scripts/notify-hook/ralph-session-resume.js +381 -0
- package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -0
- package/dist/scripts/notify-hook/state-io.d.ts +21 -0
- package/dist/scripts/notify-hook/state-io.d.ts.map +1 -0
- package/dist/scripts/notify-hook/state-io.js +169 -0
- package/dist/scripts/notify-hook/state-io.js.map +1 -0
- package/dist/scripts/notify-hook/team-dispatch.d.ts +36 -0
- package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -0
- package/dist/scripts/notify-hook/team-dispatch.js +1084 -0
- package/dist/scripts/notify-hook/team-dispatch.js.map +1 -0
- package/dist/scripts/notify-hook/team-leader-nudge.d.ts +21 -0
- package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -0
- package/dist/scripts/notify-hook/team-leader-nudge.js +1029 -0
- package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -0
- package/dist/scripts/notify-hook/team-tmux-guard.d.ts +15 -0
- package/dist/scripts/notify-hook/team-tmux-guard.d.ts.map +1 -0
- package/dist/scripts/notify-hook/team-tmux-guard.js +205 -0
- package/dist/scripts/notify-hook/team-tmux-guard.js.map +1 -0
- package/dist/scripts/notify-hook/team-worker-posttooluse.d.ts +34 -0
- package/dist/scripts/notify-hook/team-worker-posttooluse.d.ts.map +1 -0
- package/dist/scripts/notify-hook/team-worker-posttooluse.js +434 -0
- package/dist/scripts/notify-hook/team-worker-posttooluse.js.map +1 -0
- package/dist/scripts/notify-hook/team-worker-stop.d.ts +15 -0
- package/dist/scripts/notify-hook/team-worker-stop.d.ts.map +1 -0
- package/dist/scripts/notify-hook/team-worker-stop.js +418 -0
- package/dist/scripts/notify-hook/team-worker-stop.js.map +1 -0
- package/dist/scripts/notify-hook/team-worker.d.ts +33 -0
- package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -0
- package/dist/scripts/notify-hook/team-worker.js +705 -0
- package/dist/scripts/notify-hook/team-worker.js.map +1 -0
- package/dist/scripts/notify-hook/tmux-injection.d.ts +15 -0
- package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -0
- package/dist/scripts/notify-hook/tmux-injection.js +673 -0
- package/dist/scripts/notify-hook/tmux-injection.js.map +1 -0
- package/dist/scripts/notify-hook/utils.d.ts +9 -0
- package/dist/scripts/notify-hook/utils.d.ts.map +1 -0
- package/dist/scripts/notify-hook/utils.js +36 -0
- package/dist/scripts/notify-hook/utils.js.map +1 -0
- package/dist/scripts/notify-hook/visual-verdict.d.ts +29 -0
- package/dist/scripts/notify-hook/visual-verdict.d.ts.map +1 -0
- package/dist/scripts/notify-hook/visual-verdict.js +145 -0
- package/dist/scripts/notify-hook/visual-verdict.js.map +1 -0
- package/dist/scripts/notify-hook.d.ts +20 -0
- package/dist/scripts/notify-hook.d.ts.map +1 -0
- package/dist/scripts/notify-hook.js +950 -0
- package/dist/scripts/notify-hook.js.map +1 -0
- package/dist/scripts/postinstall.d.ts +18 -0
- package/dist/scripts/postinstall.d.ts.map +1 -0
- package/dist/scripts/postinstall.js +66 -0
- package/dist/scripts/postinstall.js.map +1 -0
- package/dist/scripts/prompt-inventory.d.ts +29 -0
- package/dist/scripts/prompt-inventory.d.ts.map +1 -0
- package/dist/scripts/prompt-inventory.js +178 -0
- package/dist/scripts/prompt-inventory.js.map +1 -0
- package/dist/scripts/run-provider-advisor.d.ts +3 -0
- package/dist/scripts/run-provider-advisor.d.ts.map +1 -0
- package/dist/scripts/run-provider-advisor.js +177 -0
- package/dist/scripts/run-provider-advisor.js.map +1 -0
- package/dist/scripts/run-test-files.d.ts +2 -0
- package/dist/scripts/run-test-files.d.ts.map +1 -0
- package/dist/scripts/run-test-files.js +340 -0
- package/dist/scripts/run-test-files.js.map +1 -0
- package/dist/scripts/smoke-packed-install.d.ts +21 -0
- package/dist/scripts/smoke-packed-install.d.ts.map +1 -0
- package/dist/scripts/smoke-packed-install.js +221 -0
- package/dist/scripts/smoke-packed-install.js.map +1 -0
- package/dist/scripts/sync-plugin-mirror.d.ts +14 -0
- package/dist/scripts/sync-plugin-mirror.d.ts.map +1 -0
- package/dist/scripts/sync-plugin-mirror.js +306 -0
- package/dist/scripts/sync-plugin-mirror.js.map +1 -0
- package/dist/scripts/sync-prompt-guidance-fragments.d.ts +3 -0
- package/dist/scripts/sync-prompt-guidance-fragments.d.ts.map +1 -0
- package/dist/scripts/sync-prompt-guidance-fragments.js +50 -0
- package/dist/scripts/sync-prompt-guidance-fragments.js.map +1 -0
- package/dist/scripts/team-hardening-benchmark.d.ts +3 -0
- package/dist/scripts/team-hardening-benchmark.d.ts.map +1 -0
- package/dist/scripts/team-hardening-benchmark.js +91 -0
- package/dist/scripts/team-hardening-benchmark.js.map +1 -0
- package/dist/scripts/test-reply-listener-live.d.ts +24 -0
- package/dist/scripts/test-reply-listener-live.d.ts.map +1 -0
- package/dist/scripts/test-reply-listener-live.js +138 -0
- package/dist/scripts/test-reply-listener-live.js.map +1 -0
- package/dist/scripts/test-sparkshell.d.ts +2 -0
- package/dist/scripts/test-sparkshell.d.ts.map +1 -0
- package/dist/scripts/test-sparkshell.js +25 -0
- package/dist/scripts/test-sparkshell.js.map +1 -0
- package/dist/scripts/tmux-hook-engine.d.ts +45 -0
- package/dist/scripts/tmux-hook-engine.d.ts.map +1 -0
- package/dist/scripts/tmux-hook-engine.js +313 -0
- package/dist/scripts/tmux-hook-engine.js.map +1 -0
- package/dist/scripts/verify-native-agents.d.ts +16 -0
- package/dist/scripts/verify-native-agents.d.ts.map +1 -0
- package/dist/scripts/verify-native-agents.js +247 -0
- package/dist/scripts/verify-native-agents.js.map +1 -0
- package/dist/scripts/verify-native-release-assets.d.ts +3 -0
- package/dist/scripts/verify-native-release-assets.d.ts.map +1 -0
- package/dist/scripts/verify-native-release-assets.js +62 -0
- package/dist/scripts/verify-native-release-assets.js.map +1 -0
- package/dist/session-history/__tests__/search.test.d.ts +2 -0
- package/dist/session-history/__tests__/search.test.d.ts.map +1 -0
- package/dist/session-history/__tests__/search.test.js +150 -0
- package/dist/session-history/__tests__/search.test.js.map +1 -0
- package/dist/session-history/search.d.ts +31 -0
- package/dist/session-history/search.d.ts.map +1 -0
- package/dist/session-history/search.js +331 -0
- package/dist/session-history/search.js.map +1 -0
- package/dist/sidecar/__tests__/boundary.test.d.ts +2 -0
- package/dist/sidecar/__tests__/boundary.test.d.ts.map +1 -0
- package/dist/sidecar/__tests__/boundary.test.js +48 -0
- package/dist/sidecar/__tests__/boundary.test.js.map +1 -0
- package/dist/sidecar/__tests__/collector.test.d.ts +2 -0
- package/dist/sidecar/__tests__/collector.test.d.ts.map +1 -0
- package/dist/sidecar/__tests__/collector.test.js +162 -0
- package/dist/sidecar/__tests__/collector.test.js.map +1 -0
- package/dist/sidecar/__tests__/render.test.d.ts +2 -0
- package/dist/sidecar/__tests__/render.test.d.ts.map +1 -0
- package/dist/sidecar/__tests__/render.test.js +67 -0
- package/dist/sidecar/__tests__/render.test.js.map +1 -0
- package/dist/sidecar/__tests__/resource-leak-watch.test.d.ts +2 -0
- package/dist/sidecar/__tests__/resource-leak-watch.test.d.ts.map +1 -0
- package/dist/sidecar/__tests__/resource-leak-watch.test.js +38 -0
- package/dist/sidecar/__tests__/resource-leak-watch.test.js.map +1 -0
- package/dist/sidecar/__tests__/tmux.test.d.ts +2 -0
- package/dist/sidecar/__tests__/tmux.test.d.ts.map +1 -0
- package/dist/sidecar/__tests__/tmux.test.js +30 -0
- package/dist/sidecar/__tests__/tmux.test.js.map +1 -0
- package/dist/sidecar/__tests__/watch.test.d.ts +2 -0
- package/dist/sidecar/__tests__/watch.test.d.ts.map +1 -0
- package/dist/sidecar/__tests__/watch.test.js +42 -0
- package/dist/sidecar/__tests__/watch.test.js.map +1 -0
- package/dist/sidecar/collector.d.ts +4 -0
- package/dist/sidecar/collector.d.ts.map +1 -0
- package/dist/sidecar/collector.js +377 -0
- package/dist/sidecar/collector.js.map +1 -0
- package/dist/sidecar/index.d.ts +25 -0
- package/dist/sidecar/index.d.ts.map +1 -0
- package/dist/sidecar/index.js +182 -0
- package/dist/sidecar/index.js.map +1 -0
- package/dist/sidecar/render.d.ts +3 -0
- package/dist/sidecar/render.d.ts.map +1 -0
- package/dist/sidecar/render.js +72 -0
- package/dist/sidecar/render.js.map +1 -0
- package/dist/sidecar/tmux.d.ts +13 -0
- package/dist/sidecar/tmux.d.ts.map +1 -0
- package/dist/sidecar/tmux.js +44 -0
- package/dist/sidecar/tmux.js.map +1 -0
- package/dist/sidecar/types.d.ts +125 -0
- package/dist/sidecar/types.d.ts.map +1 -0
- package/dist/sidecar/types.js +2 -0
- package/dist/sidecar/types.js.map +1 -0
- package/dist/state/__tests__/mode-state-context.test.d.ts +2 -0
- package/dist/state/__tests__/mode-state-context.test.d.ts.map +1 -0
- package/dist/state/__tests__/mode-state-context.test.js +35 -0
- package/dist/state/__tests__/mode-state-context.test.js.map +1 -0
- package/dist/state/__tests__/operations-ralph-phase.test.d.ts +2 -0
- package/dist/state/__tests__/operations-ralph-phase.test.d.ts.map +1 -0
- package/dist/state/__tests__/operations-ralph-phase.test.js +190 -0
- package/dist/state/__tests__/operations-ralph-phase.test.js.map +1 -0
- package/dist/state/__tests__/operations.test.d.ts +2 -0
- package/dist/state/__tests__/operations.test.d.ts.map +1 -0
- package/dist/state/__tests__/operations.test.js +2753 -0
- package/dist/state/__tests__/operations.test.js.map +1 -0
- package/dist/state/__tests__/path-traversal.test.d.ts +2 -0
- package/dist/state/__tests__/path-traversal.test.d.ts.map +1 -0
- package/dist/state/__tests__/path-traversal.test.js +49 -0
- package/dist/state/__tests__/path-traversal.test.js.map +1 -0
- package/dist/state/__tests__/planning-gate.test.d.ts +2 -0
- package/dist/state/__tests__/planning-gate.test.d.ts.map +1 -0
- package/dist/state/__tests__/planning-gate.test.js +219 -0
- package/dist/state/__tests__/planning-gate.test.js.map +1 -0
- package/dist/state/__tests__/skill-active.test.d.ts +2 -0
- package/dist/state/__tests__/skill-active.test.d.ts.map +1 -0
- package/dist/state/__tests__/skill-active.test.js +314 -0
- package/dist/state/__tests__/skill-active.test.js.map +1 -0
- package/dist/state/__tests__/workflow-transition.test.d.ts +2 -0
- package/dist/state/__tests__/workflow-transition.test.d.ts.map +1 -0
- package/dist/state/__tests__/workflow-transition.test.js +293 -0
- package/dist/state/__tests__/workflow-transition.test.js.map +1 -0
- package/dist/state/mode-state-context.d.ts +14 -0
- package/dist/state/mode-state-context.d.ts.map +1 -0
- package/dist/state/mode-state-context.js +49 -0
- package/dist/state/mode-state-context.js.map +1 -0
- package/dist/state/operations.d.ts +13 -0
- package/dist/state/operations.d.ts.map +1 -0
- package/dist/state/operations.js +544 -0
- package/dist/state/operations.js.map +1 -0
- package/dist/state/paths.d.ts +3 -0
- package/dist/state/paths.d.ts.map +1 -0
- package/dist/state/paths.js +2 -0
- package/dist/state/paths.js.map +1 -0
- package/dist/state/skill-active.d.ts +64 -0
- package/dist/state/skill-active.d.ts.map +1 -0
- package/dist/state/skill-active.js +375 -0
- package/dist/state/skill-active.js.map +1 -0
- package/dist/state/workflow-transition-reconcile.d.ts +22 -0
- package/dist/state/workflow-transition-reconcile.d.ts.map +1 -0
- package/dist/state/workflow-transition-reconcile.js +144 -0
- package/dist/state/workflow-transition-reconcile.js.map +1 -0
- package/dist/state/workflow-transition.d.ts +45 -0
- package/dist/state/workflow-transition.d.ts.map +1 -0
- package/dist/state/workflow-transition.js +268 -0
- package/dist/state/workflow-transition.js.map +1 -0
- package/dist/subagents/__tests__/tracker.test.d.ts +2 -0
- package/dist/subagents/__tests__/tracker.test.d.ts.map +1 -0
- package/dist/subagents/__tests__/tracker.test.js +255 -0
- package/dist/subagents/__tests__/tracker.test.js.map +1 -0
- package/dist/subagents/tracker.d.ts +60 -0
- package/dist/subagents/tracker.d.ts.map +1 -0
- package/dist/subagents/tracker.js +229 -0
- package/dist/subagents/tracker.js.map +1 -0
- package/dist/team/__tests__/allocation-policy.test.d.ts +2 -0
- package/dist/team/__tests__/allocation-policy.test.d.ts.map +1 -0
- package/dist/team/__tests__/allocation-policy.test.js +111 -0
- package/dist/team/__tests__/allocation-policy.test.js.map +1 -0
- package/dist/team/__tests__/api-interop.test.d.ts +2 -0
- package/dist/team/__tests__/api-interop.test.d.ts.map +1 -0
- package/dist/team/__tests__/api-interop.test.js +2321 -0
- package/dist/team/__tests__/api-interop.test.js.map +1 -0
- package/dist/team/__tests__/approved-execution.test.d.ts +2 -0
- package/dist/team/__tests__/approved-execution.test.d.ts.map +1 -0
- package/dist/team/__tests__/approved-execution.test.js +304 -0
- package/dist/team/__tests__/approved-execution.test.js.map +1 -0
- package/dist/team/__tests__/commit-hygiene.test.d.ts +2 -0
- package/dist/team/__tests__/commit-hygiene.test.d.ts.map +1 -0
- package/dist/team/__tests__/commit-hygiene.test.js +93 -0
- package/dist/team/__tests__/commit-hygiene.test.js.map +1 -0
- package/dist/team/__tests__/coordination-protocol.test.d.ts +2 -0
- package/dist/team/__tests__/coordination-protocol.test.d.ts.map +1 -0
- package/dist/team/__tests__/coordination-protocol.test.js +173 -0
- package/dist/team/__tests__/coordination-protocol.test.js.map +1 -0
- package/dist/team/__tests__/cross-rebase-smoke.test.d.ts +2 -0
- package/dist/team/__tests__/cross-rebase-smoke.test.d.ts.map +1 -0
- package/dist/team/__tests__/cross-rebase-smoke.test.js +161 -0
- package/dist/team/__tests__/cross-rebase-smoke.test.js.map +1 -0
- package/dist/team/__tests__/current-task-baseline.test.d.ts +2 -0
- package/dist/team/__tests__/current-task-baseline.test.d.ts.map +1 -0
- package/dist/team/__tests__/current-task-baseline.test.js +87 -0
- package/dist/team/__tests__/current-task-baseline.test.js.map +1 -0
- package/dist/team/__tests__/delegation-policy.test.d.ts +2 -0
- package/dist/team/__tests__/delegation-policy.test.d.ts.map +1 -0
- package/dist/team/__tests__/delegation-policy.test.js +69 -0
- package/dist/team/__tests__/delegation-policy.test.js.map +1 -0
- package/dist/team/__tests__/delivery-e2e-smoke.test.d.ts +2 -0
- package/dist/team/__tests__/delivery-e2e-smoke.test.d.ts.map +1 -0
- package/dist/team/__tests__/delivery-e2e-smoke.test.js +677 -0
- package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +1 -0
- package/dist/team/__tests__/delivery-log.test.d.ts +2 -0
- package/dist/team/__tests__/delivery-log.test.d.ts.map +1 -0
- package/dist/team/__tests__/delivery-log.test.js +62 -0
- package/dist/team/__tests__/delivery-log.test.js.map +1 -0
- package/dist/team/__tests__/events.test.d.ts +2 -0
- package/dist/team/__tests__/events.test.d.ts.map +1 -0
- package/dist/team/__tests__/events.test.js +313 -0
- package/dist/team/__tests__/events.test.js.map +1 -0
- package/dist/team/__tests__/followup-planner.test.d.ts +2 -0
- package/dist/team/__tests__/followup-planner.test.d.ts.map +1 -0
- package/dist/team/__tests__/followup-planner.test.js +100 -0
- package/dist/team/__tests__/followup-planner.test.js.map +1 -0
- package/dist/team/__tests__/hardening-e2e.test.d.ts +2 -0
- package/dist/team/__tests__/hardening-e2e.test.d.ts.map +1 -0
- package/dist/team/__tests__/hardening-e2e.test.js +98 -0
- package/dist/team/__tests__/hardening-e2e.test.js.map +1 -0
- package/dist/team/__tests__/hook-primary-e2e-contract.test.d.ts +2 -0
- package/dist/team/__tests__/hook-primary-e2e-contract.test.d.ts.map +1 -0
- package/dist/team/__tests__/hook-primary-e2e-contract.test.js +78 -0
- package/dist/team/__tests__/hook-primary-e2e-contract.test.js.map +1 -0
- package/dist/team/__tests__/idle-nudge.test.d.ts +2 -0
- package/dist/team/__tests__/idle-nudge.test.d.ts.map +1 -0
- package/dist/team/__tests__/idle-nudge.test.js +230 -0
- package/dist/team/__tests__/idle-nudge.test.js.map +1 -0
- package/dist/team/__tests__/leader-activity.test.d.ts +2 -0
- package/dist/team/__tests__/leader-activity.test.d.ts.map +1 -0
- package/dist/team/__tests__/leader-activity.test.js +261 -0
- package/dist/team/__tests__/leader-activity.test.js.map +1 -0
- package/dist/team/__tests__/mcp-comm.test.d.ts +2 -0
- package/dist/team/__tests__/mcp-comm.test.d.ts.map +1 -0
- package/dist/team/__tests__/mcp-comm.test.js +289 -0
- package/dist/team/__tests__/mcp-comm.test.js.map +1 -0
- package/dist/team/__tests__/model-contract.test.d.ts +2 -0
- package/dist/team/__tests__/model-contract.test.d.ts.map +1 -0
- package/dist/team/__tests__/model-contract.test.js +187 -0
- package/dist/team/__tests__/model-contract.test.js.map +1 -0
- package/dist/team/__tests__/orchestrator.test.d.ts +2 -0
- package/dist/team/__tests__/orchestrator.test.d.ts.map +1 -0
- package/dist/team/__tests__/orchestrator.test.js +111 -0
- package/dist/team/__tests__/orchestrator.test.js.map +1 -0
- package/dist/team/__tests__/phase-controller.test.d.ts +2 -0
- package/dist/team/__tests__/phase-controller.test.d.ts.map +1 -0
- package/dist/team/__tests__/phase-controller.test.js +50 -0
- package/dist/team/__tests__/phase-controller.test.js.map +1 -0
- package/dist/team/__tests__/rebalance-policy.test.d.ts +2 -0
- package/dist/team/__tests__/rebalance-policy.test.d.ts.map +1 -0
- package/dist/team/__tests__/rebalance-policy.test.js +168 -0
- package/dist/team/__tests__/rebalance-policy.test.js.map +1 -0
- package/dist/team/__tests__/repo-aware-decomposition.test.d.ts +2 -0
- package/dist/team/__tests__/repo-aware-decomposition.test.d.ts.map +1 -0
- package/dist/team/__tests__/repo-aware-decomposition.test.js +156 -0
- package/dist/team/__tests__/repo-aware-decomposition.test.js.map +1 -0
- package/dist/team/__tests__/role-router.test.d.ts +2 -0
- package/dist/team/__tests__/role-router.test.d.ts.map +1 -0
- package/dist/team/__tests__/role-router.test.js +263 -0
- package/dist/team/__tests__/role-router.test.js.map +1 -0
- package/dist/team/__tests__/runtime-boxed-state.test.d.ts +2 -0
- package/dist/team/__tests__/runtime-boxed-state.test.d.ts.map +1 -0
- package/dist/team/__tests__/runtime-boxed-state.test.js +39 -0
- package/dist/team/__tests__/runtime-boxed-state.test.js.map +1 -0
- package/dist/team/__tests__/runtime-cli.test.d.ts +2 -0
- package/dist/team/__tests__/runtime-cli.test.d.ts.map +1 -0
- package/dist/team/__tests__/runtime-cli.test.js +320 -0
- package/dist/team/__tests__/runtime-cli.test.js.map +1 -0
- package/dist/team/__tests__/runtime.test.d.ts +2 -0
- package/dist/team/__tests__/runtime.test.d.ts.map +1 -0
- package/dist/team/__tests__/runtime.test.js +6464 -0
- package/dist/team/__tests__/runtime.test.js.map +1 -0
- package/dist/team/__tests__/scaling.test.d.ts +2 -0
- package/dist/team/__tests__/scaling.test.d.ts.map +1 -0
- package/dist/team/__tests__/scaling.test.js +1664 -0
- package/dist/team/__tests__/scaling.test.js.map +1 -0
- package/dist/team/__tests__/shutdown-fallback.test.d.ts +2 -0
- package/dist/team/__tests__/shutdown-fallback.test.d.ts.map +1 -0
- package/dist/team/__tests__/shutdown-fallback.test.js +125 -0
- package/dist/team/__tests__/shutdown-fallback.test.js.map +1 -0
- package/dist/team/__tests__/state-root.test.d.ts +2 -0
- package/dist/team/__tests__/state-root.test.d.ts.map +1 -0
- package/dist/team/__tests__/state-root.test.js +208 -0
- package/dist/team/__tests__/state-root.test.js.map +1 -0
- package/dist/team/__tests__/state.test.d.ts +2 -0
- package/dist/team/__tests__/state.test.d.ts.map +1 -0
- package/dist/team/__tests__/state.test.js +1942 -0
- package/dist/team/__tests__/state.test.js.map +1 -0
- package/dist/team/__tests__/team-identity.test.d.ts +2 -0
- package/dist/team/__tests__/team-identity.test.d.ts.map +1 -0
- package/dist/team/__tests__/team-identity.test.js +166 -0
- package/dist/team/__tests__/team-identity.test.js.map +1 -0
- package/dist/team/__tests__/team-ops-contract.test.d.ts +2 -0
- package/dist/team/__tests__/team-ops-contract.test.d.ts.map +1 -0
- package/dist/team/__tests__/team-ops-contract.test.js +96 -0
- package/dist/team/__tests__/team-ops-contract.test.js.map +1 -0
- package/dist/team/__tests__/tmux-claude-workers-demo.test.d.ts +2 -0
- package/dist/team/__tests__/tmux-claude-workers-demo.test.d.ts.map +1 -0
- package/dist/team/__tests__/tmux-claude-workers-demo.test.js +191 -0
- package/dist/team/__tests__/tmux-claude-workers-demo.test.js.map +1 -0
- package/dist/team/__tests__/tmux-session.test.d.ts +2 -0
- package/dist/team/__tests__/tmux-session.test.d.ts.map +1 -0
- package/dist/team/__tests__/tmux-session.test.js +4546 -0
- package/dist/team/__tests__/tmux-session.test.js.map +1 -0
- package/dist/team/__tests__/tmux-test-fixture.d.ts +20 -0
- package/dist/team/__tests__/tmux-test-fixture.d.ts.map +1 -0
- package/dist/team/__tests__/tmux-test-fixture.js +148 -0
- package/dist/team/__tests__/tmux-test-fixture.js.map +1 -0
- package/dist/team/__tests__/tmux-test-fixture.test.d.ts +2 -0
- package/dist/team/__tests__/tmux-test-fixture.test.d.ts.map +1 -0
- package/dist/team/__tests__/tmux-test-fixture.test.js +114 -0
- package/dist/team/__tests__/tmux-test-fixture.test.js.map +1 -0
- package/dist/team/__tests__/worker-bootstrap.test.d.ts +2 -0
- package/dist/team/__tests__/worker-bootstrap.test.d.ts.map +1 -0
- package/dist/team/__tests__/worker-bootstrap.test.js +1122 -0
- package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -0
- package/dist/team/__tests__/worker-runtime-identity.test.d.ts +2 -0
- package/dist/team/__tests__/worker-runtime-identity.test.d.ts.map +1 -0
- package/dist/team/__tests__/worker-runtime-identity.test.js +258 -0
- package/dist/team/__tests__/worker-runtime-identity.test.js.map +1 -0
- package/dist/team/__tests__/worktree.test.d.ts +2 -0
- package/dist/team/__tests__/worktree.test.d.ts.map +1 -0
- package/dist/team/__tests__/worktree.test.js +317 -0
- package/dist/team/__tests__/worktree.test.js.map +1 -0
- package/dist/team/allocation-policy.d.ts +29 -0
- package/dist/team/allocation-policy.d.ts.map +1 -0
- package/dist/team/allocation-policy.js +153 -0
- package/dist/team/allocation-policy.js.map +1 -0
- package/dist/team/api-interop.d.ts +20 -0
- package/dist/team/api-interop.d.ts.map +1 -0
- package/dist/team/api-interop.js +1084 -0
- package/dist/team/api-interop.js.map +1 -0
- package/dist/team/approved-execution.d.ts +64 -0
- package/dist/team/approved-execution.d.ts.map +1 -0
- package/dist/team/approved-execution.js +242 -0
- package/dist/team/approved-execution.js.map +1 -0
- package/dist/team/commit-hygiene.d.ts +79 -0
- package/dist/team/commit-hygiene.d.ts.map +1 -0
- package/dist/team/commit-hygiene.js +364 -0
- package/dist/team/commit-hygiene.js.map +1 -0
- package/dist/team/contracts.d.ts +26 -0
- package/dist/team/contracts.d.ts.map +1 -0
- package/dist/team/contracts.js +103 -0
- package/dist/team/contracts.js.map +1 -0
- package/dist/team/coordination-protocol.d.ts +14 -0
- package/dist/team/coordination-protocol.d.ts.map +1 -0
- package/dist/team/coordination-protocol.js +244 -0
- package/dist/team/coordination-protocol.js.map +1 -0
- package/dist/team/current-task-baseline.d.ts +32 -0
- package/dist/team/current-task-baseline.d.ts.map +1 -0
- package/dist/team/current-task-baseline.js +85 -0
- package/dist/team/current-task-baseline.js.map +1 -0
- package/dist/team/dag-schema.d.ts +38 -0
- package/dist/team/dag-schema.d.ts.map +1 -0
- package/dist/team/dag-schema.js +221 -0
- package/dist/team/dag-schema.js.map +1 -0
- package/dist/team/delegation-policy.d.ts +3 -0
- package/dist/team/delegation-policy.d.ts.map +1 -0
- package/dist/team/delegation-policy.js +82 -0
- package/dist/team/delegation-policy.js.map +1 -0
- package/dist/team/delivery-log.d.ts +14 -0
- package/dist/team/delivery-log.d.ts.map +1 -0
- package/dist/team/delivery-log.js +43 -0
- package/dist/team/delivery-log.js.map +1 -0
- package/dist/team/followup-planner.d.ts +45 -0
- package/dist/team/followup-planner.d.ts.map +1 -0
- package/dist/team/followup-planner.js +200 -0
- package/dist/team/followup-planner.js.map +1 -0
- package/dist/team/goal-workflow.d.ts +20 -0
- package/dist/team/goal-workflow.d.ts.map +1 -0
- package/dist/team/goal-workflow.js +57 -0
- package/dist/team/goal-workflow.js.map +1 -0
- package/dist/team/idle-nudge.d.ts +53 -0
- package/dist/team/idle-nudge.d.ts.map +1 -0
- package/dist/team/idle-nudge.js +141 -0
- package/dist/team/idle-nudge.js.map +1 -0
- package/dist/team/leader-activity.d.ts +15 -0
- package/dist/team/leader-activity.d.ts.map +1 -0
- package/dist/team/leader-activity.js +224 -0
- package/dist/team/leader-activity.js.map +1 -0
- package/dist/team/mcp-comm.d.ts +73 -0
- package/dist/team/mcp-comm.d.ts.map +1 -0
- package/dist/team/mcp-comm.js +314 -0
- package/dist/team/mcp-comm.js.map +1 -0
- package/dist/team/model-contract.d.ts +26 -0
- package/dist/team/model-contract.d.ts.map +1 -0
- package/dist/team/model-contract.js +205 -0
- package/dist/team/model-contract.js.map +1 -0
- package/dist/team/orchestrator.d.ts +47 -0
- package/dist/team/orchestrator.d.ts.map +1 -0
- package/dist/team/orchestrator.js +131 -0
- package/dist/team/orchestrator.js.map +1 -0
- package/dist/team/pane-status.d.ts +149 -0
- package/dist/team/pane-status.d.ts.map +1 -0
- package/dist/team/pane-status.js +558 -0
- package/dist/team/pane-status.js.map +1 -0
- package/dist/team/phase-controller.d.ts +12 -0
- package/dist/team/phase-controller.d.ts.map +1 -0
- package/dist/team/phase-controller.js +142 -0
- package/dist/team/phase-controller.js.map +1 -0
- package/dist/team/progress-evidence.d.ts +2 -0
- package/dist/team/progress-evidence.d.ts.map +1 -0
- package/dist/team/progress-evidence.js +77 -0
- package/dist/team/progress-evidence.js.map +1 -0
- package/dist/team/rebalance-policy.d.ts +19 -0
- package/dist/team/rebalance-policy.d.ts.map +1 -0
- package/dist/team/rebalance-policy.js +48 -0
- package/dist/team/rebalance-policy.js.map +1 -0
- package/dist/team/reminder-intents.d.ts +11 -0
- package/dist/team/reminder-intents.d.ts.map +1 -0
- package/dist/team/reminder-intents.js +40 -0
- package/dist/team/reminder-intents.js.map +1 -0
- package/dist/team/repo-aware-decomposition.d.ts +68 -0
- package/dist/team/repo-aware-decomposition.d.ts.map +1 -0
- package/dist/team/repo-aware-decomposition.js +235 -0
- package/dist/team/repo-aware-decomposition.js.map +1 -0
- package/dist/team/role-router.d.ts +32 -0
- package/dist/team/role-router.d.ts.map +1 -0
- package/dist/team/role-router.js +298 -0
- package/dist/team/role-router.js.map +1 -0
- package/dist/team/runtime-cli.d.ts +78 -0
- package/dist/team/runtime-cli.d.ts.map +1 -0
- package/dist/team/runtime-cli.js +376 -0
- package/dist/team/runtime-cli.js.map +1 -0
- package/dist/team/runtime.d.ts +162 -0
- package/dist/team/runtime.d.ts.map +1 -0
- package/dist/team/runtime.js +4160 -0
- package/dist/team/runtime.js.map +1 -0
- package/dist/team/scaling.d.ts +59 -0
- package/dist/team/scaling.d.ts.map +1 -0
- package/dist/team/scaling.js +650 -0
- package/dist/team/scaling.js.map +1 -0
- package/dist/team/state/approvals.d.ts +25 -0
- package/dist/team/state/approvals.d.ts.map +1 -0
- package/dist/team/state/approvals.js +31 -0
- package/dist/team/state/approvals.js.map +1 -0
- package/dist/team/state/config.d.ts +2 -0
- package/dist/team/state/config.d.ts.map +1 -0
- package/dist/team/state/config.js +2 -0
- package/dist/team/state/config.js.map +1 -0
- package/dist/team/state/dispatch-lock.d.ts +3 -0
- package/dist/team/state/dispatch-lock.d.ts.map +1 -0
- package/dist/team/state/dispatch-lock.js +81 -0
- package/dist/team/state/dispatch-lock.js.map +1 -0
- package/dist/team/state/dispatch.d.ts +67 -0
- package/dist/team/state/dispatch.d.ts.map +1 -0
- package/dist/team/state/dispatch.js +302 -0
- package/dist/team/state/dispatch.js.map +1 -0
- package/dist/team/state/events.d.ts +26 -0
- package/dist/team/state/events.d.ts.map +1 -0
- package/dist/team/state/events.js +145 -0
- package/dist/team/state/events.js.map +1 -0
- package/dist/team/state/index.d.ts +11 -0
- package/dist/team/state/index.d.ts.map +1 -0
- package/dist/team/state/index.js +11 -0
- package/dist/team/state/index.js.map +1 -0
- package/dist/team/state/io.d.ts +2 -0
- package/dist/team/state/io.d.ts.map +1 -0
- package/dist/team/state/io.js +2 -0
- package/dist/team/state/io.js.map +1 -0
- package/dist/team/state/locks.d.ts +16 -0
- package/dist/team/state/locks.d.ts.map +1 -0
- package/dist/team/state/locks.js +201 -0
- package/dist/team/state/locks.js.map +1 -0
- package/dist/team/state/mailbox.d.ts +43 -0
- package/dist/team/state/mailbox.d.ts.map +1 -0
- package/dist/team/state/mailbox.js +222 -0
- package/dist/team/state/mailbox.js.map +1 -0
- package/dist/team/state/monitor.d.ts +108 -0
- package/dist/team/state/monitor.d.ts.map +1 -0
- package/dist/team/state/monitor.js +193 -0
- package/dist/team/state/monitor.js.map +1 -0
- package/dist/team/state/shutdown.d.ts +2 -0
- package/dist/team/state/shutdown.d.ts.map +1 -0
- package/dist/team/state/shutdown.js +2 -0
- package/dist/team/state/shutdown.js.map +1 -0
- package/dist/team/state/summary.d.ts +2 -0
- package/dist/team/state/summary.d.ts.map +1 -0
- package/dist/team/state/summary.js +2 -0
- package/dist/team/state/summary.js.map +1 -0
- package/dist/team/state/tasks.d.ts +53 -0
- package/dist/team/state/tasks.d.ts.map +1 -0
- package/dist/team/state/tasks.js +284 -0
- package/dist/team/state/tasks.js.map +1 -0
- package/dist/team/state/types.d.ts +356 -0
- package/dist/team/state/types.d.ts.map +1 -0
- package/dist/team/state/types.js +3 -0
- package/dist/team/state/types.js.map +1 -0
- package/dist/team/state/workers.d.ts +2 -0
- package/dist/team/state/workers.d.ts.map +1 -0
- package/dist/team/state/workers.js +2 -0
- package/dist/team/state/workers.js.map +1 -0
- package/dist/team/state-root.d.ts +40 -0
- package/dist/team/state-root.d.ts.map +1 -0
- package/dist/team/state-root.js +297 -0
- package/dist/team/state-root.js.map +1 -0
- package/dist/team/state.d.ts +471 -0
- package/dist/team/state.d.ts.map +1 -0
- package/dist/team/state.js +1418 -0
- package/dist/team/state.js.map +1 -0
- package/dist/team/team-identity.d.ts +26 -0
- package/dist/team/team-identity.d.ts.map +1 -0
- package/dist/team/team-identity.js +169 -0
- package/dist/team/team-identity.js.map +1 -0
- package/dist/team/team-ops.d.ts +66 -0
- package/dist/team/team-ops.d.ts.map +1 -0
- package/dist/team/team-ops.js +79 -0
- package/dist/team/team-ops.js.map +1 -0
- package/dist/team/tmux-session.d.ts +190 -0
- package/dist/team/tmux-session.d.ts.map +1 -0
- package/dist/team/tmux-session.js +2071 -0
- package/dist/team/tmux-session.js.map +1 -0
- package/dist/team/ultragoal-context.d.ts +47 -0
- package/dist/team/ultragoal-context.d.ts.map +1 -0
- package/dist/team/ultragoal-context.js +215 -0
- package/dist/team/ultragoal-context.js.map +1 -0
- package/dist/team/worker-bootstrap.d.ts +92 -0
- package/dist/team/worker-bootstrap.d.ts.map +1 -0
- package/dist/team/worker-bootstrap.js +860 -0
- package/dist/team/worker-bootstrap.js.map +1 -0
- package/dist/team/worktree.d.ts +69 -0
- package/dist/team/worktree.d.ts.map +1 -0
- package/dist/team/worktree.js +437 -0
- package/dist/team/worktree.js.map +1 -0
- package/dist/ultragoal/__tests__/artifacts.test.d.ts +2 -0
- package/dist/ultragoal/__tests__/artifacts.test.d.ts.map +1 -0
- package/dist/ultragoal/__tests__/artifacts.test.js +1423 -0
- package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -0
- package/dist/ultragoal/__tests__/docs-contract.test.d.ts +2 -0
- package/dist/ultragoal/__tests__/docs-contract.test.d.ts.map +1 -0
- package/dist/ultragoal/__tests__/docs-contract.test.js +132 -0
- package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -0
- package/dist/ultragoal/__tests__/steering-fixtures.d.ts +68 -0
- package/dist/ultragoal/__tests__/steering-fixtures.d.ts.map +1 -0
- package/dist/ultragoal/__tests__/steering-fixtures.js +259 -0
- package/dist/ultragoal/__tests__/steering-fixtures.js.map +1 -0
- package/dist/ultragoal/__tests__/steering-fixtures.test.d.ts +2 -0
- package/dist/ultragoal/__tests__/steering-fixtures.test.d.ts.map +1 -0
- package/dist/ultragoal/__tests__/steering-fixtures.test.js +65 -0
- package/dist/ultragoal/__tests__/steering-fixtures.test.js.map +1 -0
- package/dist/ultragoal/artifacts.d.ts +249 -0
- package/dist/ultragoal/artifacts.d.ts.map +1 -0
- package/dist/ultragoal/artifacts.js +1349 -0
- package/dist/ultragoal/artifacts.js.map +1 -0
- package/dist/utils/__tests__/agents-md.test.d.ts +2 -0
- package/dist/utils/__tests__/agents-md.test.d.ts.map +1 -0
- package/dist/utils/__tests__/agents-md.test.js +96 -0
- package/dist/utils/__tests__/agents-md.test.js.map +1 -0
- package/dist/utils/__tests__/agents-model-table.test.d.ts +2 -0
- package/dist/utils/__tests__/agents-model-table.test.d.ts.map +1 -0
- package/dist/utils/__tests__/agents-model-table.test.js +108 -0
- package/dist/utils/__tests__/agents-model-table.test.js.map +1 -0
- package/dist/utils/__tests__/dep-versions.test.d.ts +2 -0
- package/dist/utils/__tests__/dep-versions.test.d.ts.map +1 -0
- package/dist/utils/__tests__/dep-versions.test.js +46 -0
- package/dist/utils/__tests__/dep-versions.test.js.map +1 -0
- package/dist/utils/__tests__/package.test.d.ts +2 -0
- package/dist/utils/__tests__/package.test.d.ts.map +1 -0
- package/dist/utils/__tests__/package.test.js +21 -0
- package/dist/utils/__tests__/package.test.js.map +1 -0
- package/dist/utils/__tests__/paths.test.d.ts +2 -0
- package/dist/utils/__tests__/paths.test.d.ts.map +1 -0
- package/dist/utils/__tests__/paths.test.js +647 -0
- package/dist/utils/__tests__/paths.test.js.map +1 -0
- package/dist/utils/__tests__/platform-command.test.d.ts +2 -0
- package/dist/utils/__tests__/platform-command.test.d.ts.map +1 -0
- package/dist/utils/__tests__/platform-command.test.js +399 -0
- package/dist/utils/__tests__/platform-command.test.js.map +1 -0
- package/dist/utils/__tests__/repo-deps.test.d.ts +2 -0
- package/dist/utils/__tests__/repo-deps.test.d.ts.map +1 -0
- package/dist/utils/__tests__/repo-deps.test.js +71 -0
- package/dist/utils/__tests__/repo-deps.test.js.map +1 -0
- package/dist/utils/__tests__/sleep-resource.test.d.ts +2 -0
- package/dist/utils/__tests__/sleep-resource.test.d.ts.map +1 -0
- package/dist/utils/__tests__/sleep-resource.test.js +39 -0
- package/dist/utils/__tests__/sleep-resource.test.js.map +1 -0
- package/dist/utils/__tests__/version.test.d.ts +2 -0
- package/dist/utils/__tests__/version.test.d.ts.map +1 -0
- package/dist/utils/__tests__/version.test.js +78 -0
- package/dist/utils/__tests__/version.test.js.map +1 -0
- package/dist/utils/agents-md.d.ts +10 -0
- package/dist/utils/agents-md.d.ts.map +1 -0
- package/dist/utils/agents-md.js +76 -0
- package/dist/utils/agents-md.js.map +1 -0
- package/dist/utils/agents-model-table.d.ts +16 -0
- package/dist/utils/agents-model-table.d.ts.map +1 -0
- package/dist/utils/agents-model-table.js +102 -0
- package/dist/utils/agents-model-table.js.map +1 -0
- package/dist/utils/git-layout.d.ts +8 -0
- package/dist/utils/git-layout.d.ts.map +1 -0
- package/dist/utils/git-layout.js +58 -0
- package/dist/utils/git-layout.js.map +1 -0
- package/dist/utils/package.d.ts +9 -0
- package/dist/utils/package.d.ts.map +1 -0
- package/dist/utils/package.js +31 -0
- package/dist/utils/package.js.map +1 -0
- package/dist/utils/paths.d.ts +101 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +314 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/platform-command.d.ts +29 -0
- package/dist/utils/platform-command.d.ts.map +1 -0
- package/dist/utils/platform-command.js +239 -0
- package/dist/utils/platform-command.js.map +1 -0
- package/dist/utils/repo-deps.d.ts +20 -0
- package/dist/utils/repo-deps.d.ts.map +1 -0
- package/dist/utils/repo-deps.js +78 -0
- package/dist/utils/repo-deps.js.map +1 -0
- package/dist/utils/safe-json.d.ts +3 -0
- package/dist/utils/safe-json.d.ts.map +1 -0
- package/dist/utils/safe-json.js +19 -0
- package/dist/utils/safe-json.js.map +1 -0
- package/dist/utils/sleep.d.ts +3 -0
- package/dist/utils/sleep.d.ts.map +1 -0
- package/dist/utils/sleep.js +35 -0
- package/dist/utils/sleep.js.map +1 -0
- package/dist/utils/toml.d.ts +4 -0
- package/dist/utils/toml.d.ts.map +1 -0
- package/dist/utils/toml.js +75 -0
- package/dist/utils/toml.js.map +1 -0
- package/dist/utils/version.d.ts +7 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +72 -0
- package/dist/utils/version.js.map +1 -0
- package/dist/verification/__tests__/ci-rust-gates.test.d.ts +2 -0
- package/dist/verification/__tests__/ci-rust-gates.test.d.ts.map +1 -0
- package/dist/verification/__tests__/ci-rust-gates.test.js +293 -0
- package/dist/verification/__tests__/ci-rust-gates.test.js.map +1 -0
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.d.ts +2 -0
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.d.ts.map +1 -0
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js +68 -0
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js.map +1 -0
- package/dist/verification/__tests__/explore-harness-release-workflow.test.d.ts +2 -0
- package/dist/verification/__tests__/explore-harness-release-workflow.test.d.ts.map +1 -0
- package/dist/verification/__tests__/explore-harness-release-workflow.test.js +74 -0
- package/dist/verification/__tests__/explore-harness-release-workflow.test.js.map +1 -0
- package/dist/verification/__tests__/native-release-manifest.test.d.ts +2 -0
- package/dist/verification/__tests__/native-release-manifest.test.d.ts.map +1 -0
- package/dist/verification/__tests__/native-release-manifest.test.js +80 -0
- package/dist/verification/__tests__/native-release-manifest.test.js.map +1 -0
- package/dist/verification/__tests__/pr-check-workflow.test.d.ts +2 -0
- package/dist/verification/__tests__/pr-check-workflow.test.d.ts.map +1 -0
- package/dist/verification/__tests__/pr-check-workflow.test.js +27 -0
- package/dist/verification/__tests__/pr-check-workflow.test.js.map +1 -0
- package/dist/verification/__tests__/ralph-persistence-gate.test.d.ts +2 -0
- package/dist/verification/__tests__/ralph-persistence-gate.test.d.ts.map +1 -0
- package/dist/verification/__tests__/ralph-persistence-gate.test.js +55 -0
- package/dist/verification/__tests__/ralph-persistence-gate.test.js.map +1 -0
- package/dist/verification/__tests__/rust-runtime-thin-adapter-gate.test.d.ts +2 -0
- package/dist/verification/__tests__/rust-runtime-thin-adapter-gate.test.d.ts.map +1 -0
- package/dist/verification/__tests__/rust-runtime-thin-adapter-gate.test.js +32 -0
- package/dist/verification/__tests__/rust-runtime-thin-adapter-gate.test.js.map +1 -0
- package/dist/verification/__tests__/verifier.test.d.ts +2 -0
- package/dist/verification/__tests__/verifier.test.d.ts.map +1 -0
- package/dist/verification/__tests__/verifier.test.js +113 -0
- package/dist/verification/__tests__/verifier.test.js.map +1 -0
- package/dist/verification/verifier.d.ts +37 -0
- package/dist/verification/verifier.d.ts.map +1 -0
- package/dist/verification/verifier.js +100 -0
- package/dist/verification/verifier.js.map +1 -0
- package/dist/visual/__tests__/verdict.test.d.ts +2 -0
- package/dist/visual/__tests__/verdict.test.d.ts.map +1 -0
- package/dist/visual/__tests__/verdict.test.js +81 -0
- package/dist/visual/__tests__/verdict.test.js.map +1 -0
- package/dist/visual/constants.d.ts +4 -0
- package/dist/visual/constants.d.ts.map +1 -0
- package/dist/visual/constants.js +3 -0
- package/dist/visual/constants.js.map +1 -0
- package/dist/visual/verdict.d.ts +17 -0
- package/dist/visual/verdict.d.ts.map +1 -0
- package/dist/visual/verdict.js +61 -0
- package/dist/visual/verdict.js.map +1 -0
- package/dist/wiki/__tests__/cjk-tokenize.test.d.ts +12 -0
- package/dist/wiki/__tests__/cjk-tokenize.test.d.ts.map +1 -0
- package/dist/wiki/__tests__/cjk-tokenize.test.js +139 -0
- package/dist/wiki/__tests__/cjk-tokenize.test.js.map +1 -0
- package/dist/wiki/__tests__/crlf-parse.test.d.ts +2 -0
- package/dist/wiki/__tests__/crlf-parse.test.d.ts.map +1 -0
- package/dist/wiki/__tests__/crlf-parse.test.js +24 -0
- package/dist/wiki/__tests__/crlf-parse.test.js.map +1 -0
- package/dist/wiki/__tests__/escape-newline.test.d.ts +2 -0
- package/dist/wiki/__tests__/escape-newline.test.d.ts.map +1 -0
- package/dist/wiki/__tests__/escape-newline.test.js +45 -0
- package/dist/wiki/__tests__/escape-newline.test.js.map +1 -0
- package/dist/wiki/__tests__/ingest.test.d.ts +5 -0
- package/dist/wiki/__tests__/ingest.test.d.ts.map +1 -0
- package/dist/wiki/__tests__/ingest.test.js +215 -0
- package/dist/wiki/__tests__/ingest.test.js.map +1 -0
- package/dist/wiki/__tests__/lint.test.d.ts +5 -0
- package/dist/wiki/__tests__/lint.test.d.ts.map +1 -0
- package/dist/wiki/__tests__/lint.test.js +176 -0
- package/dist/wiki/__tests__/lint.test.js.map +1 -0
- package/dist/wiki/__tests__/query.test.d.ts +5 -0
- package/dist/wiki/__tests__/query.test.d.ts.map +1 -0
- package/dist/wiki/__tests__/query.test.js +166 -0
- package/dist/wiki/__tests__/query.test.js.map +1 -0
- package/dist/wiki/__tests__/reserved-file-guard.test.d.ts +2 -0
- package/dist/wiki/__tests__/reserved-file-guard.test.d.ts.map +1 -0
- package/dist/wiki/__tests__/reserved-file-guard.test.js +44 -0
- package/dist/wiki/__tests__/reserved-file-guard.test.js.map +1 -0
- package/dist/wiki/__tests__/session-hooks.test.d.ts +5 -0
- package/dist/wiki/__tests__/session-hooks.test.d.ts.map +1 -0
- package/dist/wiki/__tests__/session-hooks.test.js +64 -0
- package/dist/wiki/__tests__/session-hooks.test.js.map +1 -0
- package/dist/wiki/__tests__/slug-nonascii.test.d.ts +2 -0
- package/dist/wiki/__tests__/slug-nonascii.test.d.ts.map +1 -0
- package/dist/wiki/__tests__/slug-nonascii.test.js +30 -0
- package/dist/wiki/__tests__/slug-nonascii.test.js.map +1 -0
- package/dist/wiki/__tests__/storage.test.d.ts +5 -0
- package/dist/wiki/__tests__/storage.test.d.ts.map +1 -0
- package/dist/wiki/__tests__/storage.test.js +318 -0
- package/dist/wiki/__tests__/storage.test.js.map +1 -0
- package/dist/wiki/__tests__/test-helpers.d.ts +31 -0
- package/dist/wiki/__tests__/test-helpers.d.ts.map +1 -0
- package/dist/wiki/__tests__/test-helpers.js +108 -0
- package/dist/wiki/__tests__/test-helpers.js.map +1 -0
- package/dist/wiki/index.d.ts +14 -0
- package/dist/wiki/index.d.ts.map +1 -0
- package/dist/wiki/index.js +17 -0
- package/dist/wiki/index.js.map +1 -0
- package/dist/wiki/ingest.d.ts +20 -0
- package/dist/wiki/ingest.d.ts.map +1 -0
- package/dist/wiki/ingest.js +115 -0
- package/dist/wiki/ingest.js.map +1 -0
- package/dist/wiki/lifecycle.d.ts +25 -0
- package/dist/wiki/lifecycle.d.ts.map +1 -0
- package/dist/wiki/lifecycle.js +239 -0
- package/dist/wiki/lifecycle.js.map +1 -0
- package/dist/wiki/lint.d.ts +25 -0
- package/dist/wiki/lint.d.ts.map +1 -0
- package/dist/wiki/lint.js +170 -0
- package/dist/wiki/lint.js.map +1 -0
- package/dist/wiki/query.d.ts +36 -0
- package/dist/wiki/query.d.ts.map +1 -0
- package/dist/wiki/query.js +139 -0
- package/dist/wiki/query.js.map +1 -0
- package/dist/wiki/storage.d.ts +37 -0
- package/dist/wiki/storage.d.ts.map +1 -0
- package/dist/wiki/storage.js +358 -0
- package/dist/wiki/storage.js.map +1 -0
- package/dist/wiki/types.d.ts +83 -0
- package/dist/wiki/types.d.ts.map +1 -0
- package/dist/wiki/types.js +15 -0
- package/dist/wiki/types.js.map +1 -0
- package/package.json +110 -0
- package/plugins/oh-my-codex/.app.json +3 -0
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +31 -0
- package/plugins/oh-my-codex/.mcp.json +52 -0
- package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +420 -0
- package/plugins/oh-my-codex/hooks/hooks.json +76 -0
- package/plugins/oh-my-codex/skills/ai-slop-cleaner/SKILL.md +148 -0
- package/plugins/oh-my-codex/skills/analyze/SKILL.md +146 -0
- package/plugins/oh-my-codex/skills/ask/SKILL.md +58 -0
- package/plugins/oh-my-codex/skills/autopilot/SKILL.md +215 -0
- package/plugins/oh-my-codex/skills/autoresearch/SKILL.md +72 -0
- package/plugins/oh-my-codex/skills/autoresearch-goal/SKILL.md +36 -0
- package/plugins/oh-my-codex/skills/best-practice-research/SKILL.md +88 -0
- package/plugins/oh-my-codex/skills/cancel/SKILL.md +399 -0
- package/plugins/oh-my-codex/skills/code-review/SKILL.md +292 -0
- package/plugins/oh-my-codex/skills/configure-notifications/SKILL.md +287 -0
- package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +579 -0
- package/plugins/oh-my-codex/skills/design/SKILL.md +180 -0
- package/plugins/oh-my-codex/skills/doctor/SKILL.md +239 -0
- package/plugins/oh-my-codex/skills/hud/SKILL.md +98 -0
- package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +135 -0
- package/plugins/oh-my-codex/skills/performance-goal/SKILL.md +65 -0
- package/plugins/oh-my-codex/skills/pipeline/SKILL.md +97 -0
- package/plugins/oh-my-codex/skills/plan/SKILL.md +277 -0
- package/plugins/oh-my-codex/skills/prometheus-strict/README.md +35 -0
- package/plugins/oh-my-codex/skills/prometheus-strict/SKILL.md +219 -0
- package/plugins/oh-my-codex/skills/ralph/SKILL.md +294 -0
- package/plugins/oh-my-codex/skills/ralplan/SKILL.md +203 -0
- package/plugins/oh-my-codex/skills/skill/SKILL.md +836 -0
- package/plugins/oh-my-codex/skills/team/SKILL.md +536 -0
- package/plugins/oh-my-codex/skills/ultragoal/SKILL.md +139 -0
- package/plugins/oh-my-codex/skills/ultraqa/SKILL.md +263 -0
- package/plugins/oh-my-codex/skills/ultrawork/SKILL.md +190 -0
- package/plugins/oh-my-codex/skills/visual-ralph/SKILL.md +161 -0
- package/plugins/oh-my-codex/skills/wiki/SKILL.md +57 -0
- package/plugins/oh-my-codex/skills/worker/SKILL.md +120 -0
- package/prompts/analyst.md +135 -0
- package/prompts/api-reviewer.md +113 -0
- package/prompts/architect.md +111 -0
- package/prompts/build-fixer.md +115 -0
- package/prompts/code-reviewer.md +139 -0
- package/prompts/code-simplifier.md +134 -0
- package/prompts/critic.md +80 -0
- package/prompts/debugger.md +117 -0
- package/prompts/dependency-expert.md +129 -0
- package/prompts/designer.md +126 -0
- package/prompts/executor.md +108 -0
- package/prompts/explore-harness.md +64 -0
- package/prompts/explore.md +85 -0
- package/prompts/git-master.md +114 -0
- package/prompts/information-architect.md +226 -0
- package/prompts/performance-reviewer.md +109 -0
- package/prompts/planner.md +110 -0
- package/prompts/product-analyst.md +304 -0
- package/prompts/product-manager.md +245 -0
- package/prompts/prometheus-strict-metis.md +274 -0
- package/prompts/prometheus-strict-momus.md +82 -0
- package/prompts/prometheus-strict-oracle.md +107 -0
- package/prompts/qa-tester.md +124 -0
- package/prompts/quality-reviewer.md +123 -0
- package/prompts/quality-strategist.md +274 -0
- package/prompts/researcher.md +122 -0
- package/prompts/scholastic.md +11 -0
- package/prompts/security-reviewer.md +143 -0
- package/prompts/sisyphus-lite.md +111 -0
- package/prompts/style-reviewer.md +102 -0
- package/prompts/team-executor.md +57 -0
- package/prompts/team-orchestrator.md +8 -0
- package/prompts/test-engineer.md +130 -0
- package/prompts/ux-researcher.md +327 -0
- package/prompts/verifier.md +85 -0
- package/prompts/vision.md +98 -0
- package/prompts/writer.md +109 -0
- package/skills/ai-slop-cleaner/SKILL.md +148 -0
- package/skills/analyze/SKILL.md +146 -0
- package/skills/ask/SKILL.md +58 -0
- package/skills/ask-claude/SKILL.md +12 -0
- package/skills/ask-gemini/SKILL.md +12 -0
- package/skills/autopilot/SKILL.md +215 -0
- package/skills/autoresearch/SKILL.md +72 -0
- package/skills/autoresearch-goal/SKILL.md +36 -0
- package/skills/best-practice-research/SKILL.md +88 -0
- package/skills/build-fix/SKILL.md +10 -0
- package/skills/cancel/SKILL.md +399 -0
- package/skills/code-review/SKILL.md +292 -0
- package/skills/configure-notifications/SKILL.md +287 -0
- package/skills/deep-interview/SKILL.md +579 -0
- package/skills/deepsearch/SKILL.md +10 -0
- package/skills/design/SKILL.md +180 -0
- package/skills/doctor/SKILL.md +239 -0
- package/skills/ecomode/SKILL.md +114 -0
- package/skills/frontend-ui-ux/SKILL.md +16 -0
- package/skills/git-master/SKILL.md +27 -0
- package/skills/help/SKILL.md +10 -0
- package/skills/hud/SKILL.md +98 -0
- package/skills/note/SKILL.md +10 -0
- package/skills/omx-setup/SKILL.md +135 -0
- package/skills/performance-goal/SKILL.md +65 -0
- package/skills/pipeline/SKILL.md +97 -0
- package/skills/plan/SKILL.md +277 -0
- package/skills/prometheus-strict/README.md +35 -0
- package/skills/prometheus-strict/SKILL.md +219 -0
- package/skills/ralph/SKILL.md +294 -0
- package/skills/ralph-init/SKILL.md +10 -0
- package/skills/ralplan/SKILL.md +203 -0
- package/skills/review/SKILL.md +10 -0
- package/skills/security-review/SKILL.md +10 -0
- package/skills/skill/SKILL.md +836 -0
- package/skills/swarm/SKILL.md +12 -0
- package/skills/tdd/SKILL.md +104 -0
- package/skills/team/SKILL.md +536 -0
- package/skills/trace/SKILL.md +10 -0
- package/skills/ultragoal/SKILL.md +139 -0
- package/skills/ultraqa/SKILL.md +263 -0
- package/skills/ultrawork/SKILL.md +190 -0
- package/skills/visual-ralph/SKILL.md +161 -0
- package/skills/visual-verdict/SKILL.md +10 -0
- package/skills/web-clone/SKILL.md +357 -0
- package/skills/wiki/SKILL.md +57 -0
- package/skills/worker/SKILL.md +120 -0
- package/src/scripts/__tests__/codex-native-hook.test.ts +17173 -0
- package/src/scripts/__tests__/docs-site-contract.test.ts +47 -0
- package/src/scripts/__tests__/generate-release-body.test.ts +275 -0
- package/src/scripts/__tests__/hook-derived-watcher.test.ts +285 -0
- package/src/scripts/__tests__/notify-dispatcher.test.ts +504 -0
- package/src/scripts/__tests__/notify-state-io.test.ts +168 -0
- package/src/scripts/__tests__/notify-tmux-injection.test.ts +82 -0
- package/src/scripts/__tests__/postinstall.test.ts +113 -0
- package/src/scripts/__tests__/prompt-inventory.test.ts +64 -0
- package/src/scripts/__tests__/run-test-files.test.ts +455 -0
- package/src/scripts/__tests__/smoke-packed-install.test.ts +192 -0
- package/src/scripts/__tests__/test-reply-listener-live.test.ts +101 -0
- package/src/scripts/__tests__/verify-native-agents.test.ts +299 -0
- package/src/scripts/ask-claude.sh +17 -0
- package/src/scripts/ask-gemini.sh +14 -0
- package/src/scripts/build-api.ts +48 -0
- package/src/scripts/build-explore-harness.ts +54 -0
- package/src/scripts/build-sparkshell.ts +52 -0
- package/src/scripts/check-runtime-syntax.ts +63 -0
- package/src/scripts/check-version-sync.ts +54 -0
- package/src/scripts/cleanup-explore-harness.ts +18 -0
- package/src/scripts/codex-execution-surface.ts +75 -0
- package/src/scripts/codex-native-hook.ts +4877 -0
- package/src/scripts/codex-native-pre-post.ts +1360 -0
- package/src/scripts/demo-claude-workers.sh +241 -0
- package/src/scripts/demo-team-e2e.sh +184 -0
- package/src/scripts/eval/eval-adaptive-sort-optimization.py +24 -0
- package/src/scripts/eval/eval-candidate-handoff.ts +8 -0
- package/src/scripts/eval/eval-cli-discoverability.ts +40 -0
- package/src/scripts/eval/eval-fresh-run-tagging.ts +8 -0
- package/src/scripts/eval/eval-help-consistency.ts +11 -0
- package/src/scripts/eval/eval-in-action-cat-shellout-demo.ts +31 -0
- package/src/scripts/eval/eval-ml-kaggle-model-optimization.py +29 -0
- package/src/scripts/eval/eval-noisy-bayesopt-highdim.py +44 -0
- package/src/scripts/eval/eval-noisy-latent-subspace-discovery.py +44 -0
- package/src/scripts/eval/eval-parity-smoke.ts +20 -0
- package/src/scripts/eval/eval-parity-sweep.ts +26 -0
- package/src/scripts/eval/eval-resume-dirty-guard.ts +8 -0
- package/src/scripts/eval/eval-security-path-traversal.ts +38 -0
- package/src/scripts/fixtures/ask-advisor-stub.ts +12 -0
- package/src/scripts/generate-catalog-docs.ts +112 -0
- package/src/scripts/generate-native-release-manifest.ts +147 -0
- package/src/scripts/generate-release-body.ts +327 -0
- package/src/scripts/hook-derived-watcher.ts +649 -0
- package/src/scripts/hook-payload-guard.ts +113 -0
- package/src/scripts/notify-dispatcher.ts +408 -0
- package/src/scripts/notify-fallback-watcher.ts +2022 -0
- package/src/scripts/notify-hook/__tests__/operational-events.test.ts +24 -0
- package/src/scripts/notify-hook/__tests__/payload-guard.test.ts +41 -0
- package/src/scripts/notify-hook/__tests__/team-worker-posttooluse.test.ts +180 -0
- package/src/scripts/notify-hook/active-team.ts +55 -0
- package/src/scripts/notify-hook/auto-nudge.ts +758 -0
- package/src/scripts/notify-hook/log.ts +30 -0
- package/src/scripts/notify-hook/managed-tmux.ts +568 -0
- package/src/scripts/notify-hook/operational-events.ts +282 -0
- package/src/scripts/notify-hook/orchestration-intent.ts +80 -0
- package/src/scripts/notify-hook/payload-parser.ts +143 -0
- package/src/scripts/notify-hook/process-runner.ts +75 -0
- package/src/scripts/notify-hook/ralph-session-resume.ts +465 -0
- package/src/scripts/notify-hook/state-io.ts +220 -0
- package/src/scripts/notify-hook/team-dispatch.ts +1162 -0
- package/src/scripts/notify-hook/team-leader-nudge.ts +1068 -0
- package/src/scripts/notify-hook/team-tmux-guard.ts +236 -0
- package/src/scripts/notify-hook/team-worker-posttooluse.ts +536 -0
- package/src/scripts/notify-hook/team-worker-stop.ts +438 -0
- package/src/scripts/notify-hook/team-worker.ts +709 -0
- package/src/scripts/notify-hook/tmux-injection.ts +740 -0
- package/src/scripts/notify-hook/utils.ts +31 -0
- package/src/scripts/notify-hook/visual-verdict.ts +158 -0
- package/src/scripts/notify-hook.ts +1033 -0
- package/src/scripts/postinstall.ts +107 -0
- package/src/scripts/prepare-build.js +83 -0
- package/src/scripts/prompt-inventory.ts +218 -0
- package/src/scripts/run-autoresearch-showcase.sh +75 -0
- package/src/scripts/run-provider-advisor.ts +213 -0
- package/src/scripts/run-test-files.ts +379 -0
- package/src/scripts/smoke-packed-install.ts +268 -0
- package/src/scripts/sync-plugin-mirror.ts +458 -0
- package/src/scripts/sync-prompt-guidance-fragments.ts +55 -0
- package/src/scripts/team-hardening-benchmark.ts +90 -0
- package/src/scripts/test-reply-listener-live.ts +188 -0
- package/src/scripts/test-sparkshell.ts +29 -0
- package/src/scripts/tmux-hook-engine.ts +349 -0
- package/src/scripts/verify-native-agents.ts +311 -0
- package/src/scripts/verify-native-release-assets.ts +68 -0
- package/templates/AGENTS.md +187 -0
- package/templates/catalog-manifest.json +547 -0
- package/templates/model-instructions/explore-lightweight-AGENTS.md +11 -0
- package/templates/model-instructions/sparkshell-lightweight-AGENTS.md +10 -0
|
@@ -0,0 +1,3619 @@
|
|
|
1
|
+
import { afterEach, describe, it, mock } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync, utimesSync } from "node:fs";
|
|
4
|
+
import { chmod, lstat, mkdir, mkdtemp, readFile, rm, stat, symlink, writeFile } from "node:fs/promises";
|
|
5
|
+
import { delimiter, dirname, join } from "node:path";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { once } from "node:events";
|
|
9
|
+
import TOML from "@iarna/toml";
|
|
10
|
+
import { HELP, normalizeCodexLaunchArgs, buildTmuxShellCommand, buildTmuxPaneCommand, shouldSourceTmuxPaneShellRc, buildWindowsPromptCommand, buildTmuxSessionName, resolveCliInvocation, resolveUpdateChannelArg, commandOwnsLocalHelp, resolveCodexLaunchPolicy, resolveEffectiveLeaderLaunchPolicyOverride, resolveEnvLaunchPolicyOverride, resolveLeaderLaunchPolicyOverride, classifyCodexExecFailure, resolveSignalExitCode, parseTmuxPaneSnapshot, findHudWatchPaneIds, buildHudPaneCleanupTargets, readTopLevelTomlString, upsertTopLevelTomlString, collectInheritableTeamWorkerArgs, resolveTeamWorkerLaunchArgsEnv, injectModelInstructionsBypassArgs, resolveWorkerSparkModel, resolveSetupInstallModeArg, resolveSetupMcpModeArg, resolveSetupScopeArg, resolveSetupTeamModeArg, resolveLaunchConfigRepairOptions, readPersistedSetupPreferences, readPersistedSetupScope, resolveCodexConfigPathForLaunch, resolveCodexHomeForLaunch, resolveProjectLocalCodexHomeForLaunch, shouldAutoIsolateMadmaxLaunch, createMadmaxIsolatedRoot, buildMadmaxDetachedLaunchContextKey, withMadmaxDetachedContextLock, resolveOmxRootForLaunch, resolveDisposableWorktreeOmxRootForLaunch, prepareCodexHomeForLaunch, persistProjectLaunchRuntimeAuthState, persistProjectLaunchRuntimeProjectTrustState, runtimeCodexHomePath, buildDetachedSessionBootstrapSteps, buildDetachedTmuxSessionName, buildDetachedSessionFinalizeSteps, shouldAttachDetachedTmuxSession, buildDetachedSessionRollbackSteps, detectDetachedSessionWindowIndex, resolveNotifyTempContract, buildNotifyTempStartupMessages, buildNotifyFallbackWatcherEnv, shouldEnableNotifyFallbackWatcher, reapStaleNotifyFallbackWatcher, cleanupLaunchOrphanedMcpProcesses, reapPostLaunchOrphanedMcpProcesses, cleanupPostLaunchModeStateFiles, resolveBackgroundHelperLaunchMode, shouldDetachBackgroundHelper, resolveNotifyFallbackWatcherScript, resolveHookDerivedWatcherScript, resolveNotifyHookScript, buildDetachedWindowsBootstrapScript, acquireTmuxExtendedKeysLease, resolveNativeSessionName, releaseTmuxExtendedKeysLease, withTmuxExtendedKeys, serializeDetachedSessionParentEnv, buildInsideTmuxHudHookEnv, registerInsideTmuxHudResizeHook, buildDetachedHudHookEnv, registerDetachedHudLayoutReconcileHook, ensureOmxRuntimeCommandShim, omxRuntimeCommandShimPath, prependOmxRuntimeCommandShimToEnv, CODEX_SQLITE_HOME_ENV, DETACHED_TMUX_HISTORY_LIMIT, isExistingTmuxWindowTooCrampedForLaunchHud, } from "../index.js";
|
|
11
|
+
import { mergeConfig, repairConfigIfNeeded } from "../../config/generator.js";
|
|
12
|
+
import { ensureReusableNodeModules } from "../../utils/repo-deps.js";
|
|
13
|
+
import { readAllState } from "../../hud/state.js";
|
|
14
|
+
import { generateOverlay } from "../../hooks/agents-overlay.js";
|
|
15
|
+
import { HUD_TMUX_HEIGHT_LINES, HUD_TMUX_MIN_LAUNCH_WINDOW_HEIGHT_LINES } from "../../hud/constants.js";
|
|
16
|
+
import { createHudWatchPane as createSharedHudWatchPane, listCurrentWindowHudPaneIds } from "../../hud/tmux.js";
|
|
17
|
+
import { DEFAULT_FRONTIER_MODEL, getTeamLowComplexityModel, } from "../../config/models.js";
|
|
18
|
+
const testDir = dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
const repoRoot = join(testDir, "..", "..", "..");
|
|
20
|
+
function normalizeDarwinTmpPath(value) {
|
|
21
|
+
return process.platform === "darwin" ? value.replaceAll("/private/var/", "/var/") : value;
|
|
22
|
+
}
|
|
23
|
+
function escapeRegExp(value) {
|
|
24
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
25
|
+
}
|
|
26
|
+
function countMatches(text, pattern) {
|
|
27
|
+
return text.match(pattern)?.length ?? 0;
|
|
28
|
+
}
|
|
29
|
+
function expectedLowComplexityModel(codexHomeOverride) {
|
|
30
|
+
return getTeamLowComplexityModel(codexHomeOverride);
|
|
31
|
+
}
|
|
32
|
+
afterEach(() => {
|
|
33
|
+
mock.restoreAll();
|
|
34
|
+
});
|
|
35
|
+
describe("madmax state isolation", () => {
|
|
36
|
+
it("auto-isolates only madmax launch and exec invocations", () => {
|
|
37
|
+
assert.equal(shouldAutoIsolateMadmaxLaunch("launch", ["--madmax"], {}), true);
|
|
38
|
+
assert.equal(shouldAutoIsolateMadmaxLaunch("exec", ["--madmax-spark"], {}), true);
|
|
39
|
+
assert.equal(shouldAutoIsolateMadmaxLaunch("team", ["--madmax"], {}), false);
|
|
40
|
+
assert.equal(shouldAutoIsolateMadmaxLaunch("launch", ["--yolo"], {}), false);
|
|
41
|
+
assert.equal(shouldAutoIsolateMadmaxLaunch("launch", ["--madmax"], { OMX_ROOT: "/already/boxed" }), false);
|
|
42
|
+
assert.equal(shouldAutoIsolateMadmaxLaunch("launch", ["--madmax"], { OMXBOX_ACTIVE: "1" }), false);
|
|
43
|
+
assert.equal(shouldAutoIsolateMadmaxLaunch("launch", ["--madmax"], { OMX_NO_BOX: "1" }), false);
|
|
44
|
+
});
|
|
45
|
+
it("creates a per-run OMX_ROOT registry entry without touching source .omx", async () => {
|
|
46
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-madmax-source-"));
|
|
47
|
+
const runs = await mkdtemp(join(tmpdir(), "omx-madmax-runs-"));
|
|
48
|
+
try {
|
|
49
|
+
const runDir = createMadmaxIsolatedRoot(wd, ["--madmax"], { OMX_RUNS_DIR: runs });
|
|
50
|
+
assert.equal(runDir.startsWith(runs), true);
|
|
51
|
+
assert.equal(existsSync(join(wd, ".omx")), false);
|
|
52
|
+
const metadata = JSON.parse(await readFile(join(runDir, ".omxbox-run.json"), "utf-8"));
|
|
53
|
+
assert.equal(metadata.source_cwd, wd);
|
|
54
|
+
assert.equal(metadata.cwd, runDir);
|
|
55
|
+
assert.deepEqual(metadata.argv, ["--madmax"]);
|
|
56
|
+
const registry = await readFile(join(runs, "registry.jsonl"), "utf-8");
|
|
57
|
+
assert.match(registry, /"launcher":"omx --madmax"/);
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
await rm(wd, { recursive: true, force: true });
|
|
61
|
+
await rm(runs, { recursive: true, force: true });
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
it("stamps a stable detached launch context and exposes it to boxed launch", async () => {
|
|
65
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-madmax-source-"));
|
|
66
|
+
const runs = await mkdtemp(join(tmpdir(), "omx-madmax-runs-"));
|
|
67
|
+
try {
|
|
68
|
+
const env = { OMX_RUNS_DIR: runs };
|
|
69
|
+
const runDir = createMadmaxIsolatedRoot(wd, ["--madmax", "--xhigh", "--tmux"], env);
|
|
70
|
+
const metadata = JSON.parse(await readFile(join(runDir, ".omxbox-run.json"), "utf-8"));
|
|
71
|
+
const expectedContext = buildMadmaxDetachedLaunchContextKey(wd, ["--madmax", "--xhigh", "--tmux"], runDir);
|
|
72
|
+
assert.equal(metadata.detached_launch_context, expectedContext);
|
|
73
|
+
assert.equal(env.OMX_MADMAX_DETACHED_CONTEXT, expectedContext);
|
|
74
|
+
assert.equal(buildMadmaxDetachedLaunchContextKey(wd, ["--madmax", "--xhigh", "--tmux"], runDir), buildMadmaxDetachedLaunchContextKey(wd, ["--madmax", "--xhigh"], runDir), "explicit --tmux is a transport choice and must not create a second context");
|
|
75
|
+
assert.equal(buildMadmaxDetachedLaunchContextKey(wd, ["--madmax", "--xhigh", "--tmux"], runDir), buildMadmaxDetachedLaunchContextKey(wd, ["--xhigh", "--madmax", "--direct"], runDir), "argument order and transport choices must not create duplicate detached contexts");
|
|
76
|
+
assert.notEqual(expectedContext, buildMadmaxDetachedLaunchContextKey(wd, ["--madmax", "--low"], runDir), "different launch semantics may run concurrently");
|
|
77
|
+
assert.notEqual(buildMadmaxDetachedLaunchContextKey(wd, ["--madmax", "--high", "--xhigh"], runDir), buildMadmaxDetachedLaunchContextKey(wd, ["--madmax", "--xhigh", "--high"], runDir), "last reasoning shorthand wins, so reversed reasoning order is a distinct context");
|
|
78
|
+
const otherWd = await mkdtemp(join(tmpdir(), "omx-madmax-other-source-"));
|
|
79
|
+
try {
|
|
80
|
+
assert.notEqual(expectedContext, buildMadmaxDetachedLaunchContextKey(otherWd, ["--madmax", "--xhigh"], runDir), "different work contexts may run concurrently");
|
|
81
|
+
}
|
|
82
|
+
finally {
|
|
83
|
+
await rm(otherWd, { recursive: true, force: true });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
finally {
|
|
87
|
+
await rm(wd, { recursive: true, force: true });
|
|
88
|
+
await rm(runs, { recursive: true, force: true });
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
it("gives independent madmax run roots distinct detached launch context locks", async () => {
|
|
92
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-madmax-source-"));
|
|
93
|
+
const runs = await mkdtemp(join(tmpdir(), "omx-madmax-runs-"));
|
|
94
|
+
try {
|
|
95
|
+
const firstEnv = { OMX_RUNS_DIR: runs };
|
|
96
|
+
const secondEnv = { OMX_RUNS_DIR: runs };
|
|
97
|
+
const firstRunDir = createMadmaxIsolatedRoot(wd, ["--madmax", "--high"], firstEnv);
|
|
98
|
+
const secondRunDir = createMadmaxIsolatedRoot(wd, ["--madmax", "--high"], secondEnv);
|
|
99
|
+
assert.notEqual(firstRunDir, secondRunDir);
|
|
100
|
+
assert.notEqual(firstEnv.OMX_MADMAX_DETACHED_CONTEXT, secondEnv.OMX_MADMAX_DETACHED_CONTEXT, "same cwd and argv from independent boxed runs must not contend on one active-detached lock");
|
|
101
|
+
assert.equal(firstEnv.OMX_MADMAX_DETACHED_CONTEXT, buildMadmaxDetachedLaunchContextKey(wd, ["--high", "--madmax", "--tmux"], firstRunDir), "transport and order normalization still deduplicates within the same isolated run");
|
|
102
|
+
}
|
|
103
|
+
finally {
|
|
104
|
+
await rm(wd, { recursive: true, force: true });
|
|
105
|
+
await rm(runs, { recursive: true, force: true });
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
it("recovers a madmax detached context lock whose holder pid has already exited", async () => {
|
|
109
|
+
const runs = await mkdtemp(join(tmpdir(), "omx-madmax-lock-stale-"));
|
|
110
|
+
try {
|
|
111
|
+
const contextKey = "stale-context";
|
|
112
|
+
const lockPath = join(runs, "active-detached", `${contextKey}.lock`);
|
|
113
|
+
mkdirSync(lockPath, { recursive: true });
|
|
114
|
+
await writeFile(join(lockPath, "pid"), "2147483647");
|
|
115
|
+
let ran = false;
|
|
116
|
+
const result = withMadmaxDetachedContextLock(runs, contextKey, () => {
|
|
117
|
+
ran = true;
|
|
118
|
+
return "acquired";
|
|
119
|
+
}, { maxAttempts: 2, retryMs: 0 });
|
|
120
|
+
assert.equal(result, "acquired");
|
|
121
|
+
assert.equal(ran, true);
|
|
122
|
+
assert.equal(existsSync(lockPath), false);
|
|
123
|
+
}
|
|
124
|
+
finally {
|
|
125
|
+
await rm(runs, { recursive: true, force: true });
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
it("preserves a live madmax detached context lock and reports holder diagnostics on timeout", async () => {
|
|
129
|
+
const runs = await mkdtemp(join(tmpdir(), "omx-madmax-lock-live-"));
|
|
130
|
+
try {
|
|
131
|
+
const contextKey = "live-context";
|
|
132
|
+
const lockPath = join(runs, "active-detached", `${contextKey}.lock`);
|
|
133
|
+
mkdirSync(lockPath, { recursive: true });
|
|
134
|
+
await writeFile(join(lockPath, "owner.json"), `${JSON.stringify({
|
|
135
|
+
version: 1,
|
|
136
|
+
pid: process.pid,
|
|
137
|
+
context_key: contextKey,
|
|
138
|
+
acquired_at: new Date().toISOString(),
|
|
139
|
+
})}\n`);
|
|
140
|
+
await writeFile(join(lockPath, "pid"), String(process.pid));
|
|
141
|
+
assert.throws(() => withMadmaxDetachedContextLock(runs, contextKey, () => "should-not-run", { maxAttempts: 1, retryMs: 0 }), (err) => {
|
|
142
|
+
assert.ok(err instanceof Error);
|
|
143
|
+
assert.match(err.message, /timed out waiting for madmax detached launch context lock/);
|
|
144
|
+
assert.match(err.message, new RegExp(`holder pid ${process.pid} is still running`));
|
|
145
|
+
assert.match(err.message, /owner context live-context/);
|
|
146
|
+
assert.match(err.message, /Another madmax detached launch is active for this directory/);
|
|
147
|
+
assert.match(err.message, /close the existing madmax session or use --worktree for concurrent work/);
|
|
148
|
+
assert.match(err.message, /Multiple madmax sessions in one directory are unsafe/);
|
|
149
|
+
return true;
|
|
150
|
+
});
|
|
151
|
+
assert.equal(existsSync(lockPath), true);
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
await rm(runs, { recursive: true, force: true });
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
describe("resolveOmxRootForLaunch", () => {
|
|
159
|
+
it("preserves POSIX absolute OMX_ROOT", () => {
|
|
160
|
+
assert.equal(resolveOmxRootForLaunch("/repo", { OMX_ROOT: "/var/tmp/omx" }), "/var/tmp/omx");
|
|
161
|
+
});
|
|
162
|
+
it("preserves Windows drive-letter absolute OMX_ROOT", () => {
|
|
163
|
+
assert.equal(resolveOmxRootForLaunch("/repo", { OMX_ROOT: "C:\\Users\\me\\omx" }), "C:\\Users\\me\\omx");
|
|
164
|
+
});
|
|
165
|
+
it("preserves Windows drive-letter absolute OMX_STATE_ROOT", () => {
|
|
166
|
+
assert.equal(resolveOmxRootForLaunch("/repo", { OMX_STATE_ROOT: "D:\\omx-state" }), "D:\\omx-state");
|
|
167
|
+
});
|
|
168
|
+
it("preserves UNC absolute OMX_ROOT", () => {
|
|
169
|
+
assert.equal(resolveOmxRootForLaunch("/repo", { OMX_ROOT: "\\\\server\\share\\omx" }), "\\\\server\\share\\omx");
|
|
170
|
+
});
|
|
171
|
+
it("joins relative OMX_ROOT to cwd", () => {
|
|
172
|
+
assert.equal(resolveOmxRootForLaunch("/repo", { OMX_ROOT: "relative/omx" }), join("/repo", "relative/omx"));
|
|
173
|
+
});
|
|
174
|
+
it("returns undefined for blank OMX_ROOT and OMX_STATE_ROOT", () => {
|
|
175
|
+
assert.equal(resolveOmxRootForLaunch("/repo", { OMX_ROOT: " ", OMX_STATE_ROOT: "" }), undefined);
|
|
176
|
+
});
|
|
177
|
+
it("prefers OMX_ROOT over OMX_STATE_ROOT", () => {
|
|
178
|
+
assert.equal(resolveOmxRootForLaunch("/repo", {
|
|
179
|
+
OMX_ROOT: "C:\\Users\\me\\root",
|
|
180
|
+
OMX_STATE_ROOT: "/state-root",
|
|
181
|
+
}), "C:\\Users\\me\\root");
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
describe("disposable worktree state root resolution", () => {
|
|
185
|
+
it("uses the source repo root for launch worktrees when no explicit root is set", () => {
|
|
186
|
+
assert.equal(resolveDisposableWorktreeOmxRootForLaunch({ enabled: true, repoRoot: "/repo" }, {}), "/repo");
|
|
187
|
+
});
|
|
188
|
+
it("preserves explicit OMX_ROOT and OMX_STATE_ROOT precedence", () => {
|
|
189
|
+
assert.equal(resolveDisposableWorktreeOmxRootForLaunch({ enabled: true, repoRoot: "/repo" }, { OMX_ROOT: "/explicit" }), undefined);
|
|
190
|
+
assert.equal(resolveDisposableWorktreeOmxRootForLaunch({ enabled: true, repoRoot: "/repo" }, { OMX_STATE_ROOT: "/state-root" }), undefined);
|
|
191
|
+
});
|
|
192
|
+
it("does not affect non-worktree launches", () => {
|
|
193
|
+
assert.equal(resolveDisposableWorktreeOmxRootForLaunch({ enabled: false }, {}), undefined);
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
describe("normalizeCodexLaunchArgs", () => {
|
|
197
|
+
it("maps --madmax to codex bypass flag", () => {
|
|
198
|
+
assert.deepEqual(normalizeCodexLaunchArgs(["--madmax"]), [
|
|
199
|
+
"--dangerously-bypass-approvals-and-sandbox",
|
|
200
|
+
]);
|
|
201
|
+
});
|
|
202
|
+
it("does not forward --madmax and preserves other args", () => {
|
|
203
|
+
assert.deepEqual(normalizeCodexLaunchArgs(["--model", "gpt-5", "--madmax", "--yolo"]), [
|
|
204
|
+
"--model",
|
|
205
|
+
"gpt-5",
|
|
206
|
+
"--yolo",
|
|
207
|
+
"--dangerously-bypass-approvals-and-sandbox",
|
|
208
|
+
]);
|
|
209
|
+
});
|
|
210
|
+
it("avoids duplicate bypass flags when both are present", () => {
|
|
211
|
+
assert.deepEqual(normalizeCodexLaunchArgs([
|
|
212
|
+
"--dangerously-bypass-approvals-and-sandbox",
|
|
213
|
+
"--madmax",
|
|
214
|
+
]), ["--dangerously-bypass-approvals-and-sandbox"]);
|
|
215
|
+
});
|
|
216
|
+
it("deduplicates repeated bypass-related flags", () => {
|
|
217
|
+
assert.deepEqual(normalizeCodexLaunchArgs([
|
|
218
|
+
"--madmax",
|
|
219
|
+
"--dangerously-bypass-approvals-and-sandbox",
|
|
220
|
+
"--madmax",
|
|
221
|
+
"--dangerously-bypass-approvals-and-sandbox",
|
|
222
|
+
]), ["--dangerously-bypass-approvals-and-sandbox"]);
|
|
223
|
+
});
|
|
224
|
+
it("leaves unrelated args unchanged", () => {
|
|
225
|
+
assert.deepEqual(normalizeCodexLaunchArgs(["--model", "gpt-5", "--yolo"]), [
|
|
226
|
+
"--model",
|
|
227
|
+
"gpt-5",
|
|
228
|
+
"--yolo",
|
|
229
|
+
]);
|
|
230
|
+
});
|
|
231
|
+
it("maps --high to reasoning override", () => {
|
|
232
|
+
assert.deepEqual(normalizeCodexLaunchArgs(["--high"]), [
|
|
233
|
+
"-c",
|
|
234
|
+
'model_reasoning_effort="high"',
|
|
235
|
+
]);
|
|
236
|
+
});
|
|
237
|
+
it("maps --xhigh to reasoning override", () => {
|
|
238
|
+
assert.deepEqual(normalizeCodexLaunchArgs(["--xhigh"]), [
|
|
239
|
+
"-c",
|
|
240
|
+
'model_reasoning_effort="xhigh"',
|
|
241
|
+
]);
|
|
242
|
+
});
|
|
243
|
+
it("uses the last reasoning shorthand when both are present", () => {
|
|
244
|
+
assert.deepEqual(normalizeCodexLaunchArgs(["--high", "--xhigh"]), [
|
|
245
|
+
"-c",
|
|
246
|
+
'model_reasoning_effort="xhigh"',
|
|
247
|
+
]);
|
|
248
|
+
});
|
|
249
|
+
it("maps --xhigh --madmax to codex-native flags only", () => {
|
|
250
|
+
assert.deepEqual(normalizeCodexLaunchArgs(["--xhigh", "--madmax"]), [
|
|
251
|
+
"--dangerously-bypass-approvals-and-sandbox",
|
|
252
|
+
"-c",
|
|
253
|
+
'model_reasoning_effort="xhigh"',
|
|
254
|
+
]);
|
|
255
|
+
});
|
|
256
|
+
it("--spark is stripped from leader args (model goes to workers only)", () => {
|
|
257
|
+
assert.deepEqual(normalizeCodexLaunchArgs(["--spark", "--yolo"]), [
|
|
258
|
+
"--yolo",
|
|
259
|
+
]);
|
|
260
|
+
});
|
|
261
|
+
it("--spark alone produces no leader args", () => {
|
|
262
|
+
assert.deepEqual(normalizeCodexLaunchArgs(["--spark"]), []);
|
|
263
|
+
});
|
|
264
|
+
it("--madmax-spark adds bypass flag to leader args and is otherwise consumed", () => {
|
|
265
|
+
assert.deepEqual(normalizeCodexLaunchArgs(["--madmax-spark"]), [
|
|
266
|
+
"--dangerously-bypass-approvals-and-sandbox",
|
|
267
|
+
]);
|
|
268
|
+
});
|
|
269
|
+
it("--madmax-spark deduplicates bypass when --madmax also present", () => {
|
|
270
|
+
assert.deepEqual(normalizeCodexLaunchArgs(["--madmax", "--madmax-spark"]), [
|
|
271
|
+
"--dangerously-bypass-approvals-and-sandbox",
|
|
272
|
+
]);
|
|
273
|
+
});
|
|
274
|
+
it("--madmax-spark does not inject spark model into leader args", () => {
|
|
275
|
+
const args = normalizeCodexLaunchArgs(["--madmax-spark"]);
|
|
276
|
+
assert.ok(!args.includes("--model"), "leader args must not contain --model from --madmax-spark");
|
|
277
|
+
assert.ok(!args.some((a) => a.includes("spark")), "leader args must not reference spark model");
|
|
278
|
+
});
|
|
279
|
+
it("strips detached worktree flag from leader codex args", () => {
|
|
280
|
+
assert.deepEqual(normalizeCodexLaunchArgs(["--worktree", "--yolo"]), [
|
|
281
|
+
"--yolo",
|
|
282
|
+
]);
|
|
283
|
+
});
|
|
284
|
+
it("strips named worktree flag from leader codex args", () => {
|
|
285
|
+
assert.deepEqual(normalizeCodexLaunchArgs(["--worktree=feature/demo", "--model", "gpt-5"]), ["--model", "gpt-5"]);
|
|
286
|
+
});
|
|
287
|
+
it("does not forward notify-temp flags/selectors to leader codex args", () => {
|
|
288
|
+
const parsed = resolveNotifyTempContract([
|
|
289
|
+
"--notify-temp",
|
|
290
|
+
"--discord",
|
|
291
|
+
"--custom",
|
|
292
|
+
"openclaw:ops",
|
|
293
|
+
"--custom=my-hook",
|
|
294
|
+
"--model",
|
|
295
|
+
"gpt-5",
|
|
296
|
+
], {});
|
|
297
|
+
assert.deepEqual(normalizeCodexLaunchArgs(parsed.passthroughArgs), [
|
|
298
|
+
"--model",
|
|
299
|
+
"gpt-5",
|
|
300
|
+
]);
|
|
301
|
+
});
|
|
302
|
+
it("strips --tmux from leader codex args", () => {
|
|
303
|
+
assert.deepEqual(normalizeCodexLaunchArgs(["--tmux", "--yolo"]), [
|
|
304
|
+
"--yolo",
|
|
305
|
+
]);
|
|
306
|
+
});
|
|
307
|
+
it("strips --direct from leader codex args", () => {
|
|
308
|
+
assert.deepEqual(normalizeCodexLaunchArgs(["--direct", "--yolo"]), [
|
|
309
|
+
"--yolo",
|
|
310
|
+
]);
|
|
311
|
+
});
|
|
312
|
+
it("preserves literal --tmux after -- in leader codex args", () => {
|
|
313
|
+
assert.deepEqual(normalizeCodexLaunchArgs(["--", "--tmux", "--yolo"]), [
|
|
314
|
+
"--",
|
|
315
|
+
"--tmux",
|
|
316
|
+
"--yolo",
|
|
317
|
+
]);
|
|
318
|
+
});
|
|
319
|
+
it("preserves literal --direct after -- in leader codex args", () => {
|
|
320
|
+
assert.deepEqual(normalizeCodexLaunchArgs(["--", "--direct", "--yolo"]), [
|
|
321
|
+
"--",
|
|
322
|
+
"--direct",
|
|
323
|
+
"--yolo",
|
|
324
|
+
]);
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
describe("resolveLeaderLaunchPolicyOverride", () => {
|
|
328
|
+
it("detects explicit detached tmux launch requests", () => {
|
|
329
|
+
assert.equal(resolveLeaderLaunchPolicyOverride(["--tmux", "--model", "gpt-5"]), "detached-tmux");
|
|
330
|
+
});
|
|
331
|
+
it("detects explicit direct launch requests", () => {
|
|
332
|
+
assert.equal(resolveLeaderLaunchPolicyOverride(["--direct", "--model", "gpt-5"]), "direct");
|
|
333
|
+
});
|
|
334
|
+
it("uses the last CLI launch policy flag before --", () => {
|
|
335
|
+
assert.equal(resolveLeaderLaunchPolicyOverride(["--direct", "--tmux"]), "detached-tmux");
|
|
336
|
+
assert.equal(resolveLeaderLaunchPolicyOverride(["--tmux", "--direct"]), "direct");
|
|
337
|
+
});
|
|
338
|
+
it("returns undefined when no explicit policy override is present", () => {
|
|
339
|
+
assert.equal(resolveLeaderLaunchPolicyOverride(["--model", "gpt-5"]), undefined);
|
|
340
|
+
});
|
|
341
|
+
it("stops scanning for --tmux after the end-of-options marker", () => {
|
|
342
|
+
assert.equal(resolveLeaderLaunchPolicyOverride(["--", "--tmux", "--model", "gpt-5"]), undefined);
|
|
343
|
+
});
|
|
344
|
+
it("stops scanning for --direct after the end-of-options marker", () => {
|
|
345
|
+
assert.equal(resolveLeaderLaunchPolicyOverride(["--", "--direct", "--model", "gpt-5"]), undefined);
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
describe("resolveEnvLaunchPolicyOverride", () => {
|
|
349
|
+
it("accepts direct, tmux, detached-tmux, auto, and empty policy values", () => {
|
|
350
|
+
assert.equal(resolveEnvLaunchPolicyOverride({ OMX_LAUNCH_POLICY: "direct" }), "direct");
|
|
351
|
+
assert.equal(resolveEnvLaunchPolicyOverride({ OMX_LAUNCH_POLICY: "tmux" }), "detached-tmux");
|
|
352
|
+
assert.equal(resolveEnvLaunchPolicyOverride({ OMX_LAUNCH_POLICY: "detached-tmux" }), "detached-tmux");
|
|
353
|
+
assert.equal(resolveEnvLaunchPolicyOverride({ OMX_LAUNCH_POLICY: "auto" }), undefined);
|
|
354
|
+
assert.equal(resolveEnvLaunchPolicyOverride({ OMX_LAUNCH_POLICY: "" }), undefined);
|
|
355
|
+
});
|
|
356
|
+
it("warns once for invalid OMX_LAUNCH_POLICY and falls back to auto", () => {
|
|
357
|
+
const warn = mock.method(console, "warn", () => { });
|
|
358
|
+
assert.equal(resolveEnvLaunchPolicyOverride({ OMX_LAUNCH_POLICY: "banana" }), undefined);
|
|
359
|
+
assert.equal(resolveEnvLaunchPolicyOverride({ OMX_LAUNCH_POLICY: "banana" }), undefined);
|
|
360
|
+
assert.equal(warn.mock.callCount(), 1);
|
|
361
|
+
});
|
|
362
|
+
});
|
|
363
|
+
describe("resolveEffectiveLeaderLaunchPolicyOverride", () => {
|
|
364
|
+
it("uses env policy when no CLI policy flag is present", () => {
|
|
365
|
+
assert.equal(resolveEffectiveLeaderLaunchPolicyOverride(["--yolo"], {
|
|
366
|
+
OMX_LAUNCH_POLICY: "direct",
|
|
367
|
+
}), "direct");
|
|
368
|
+
});
|
|
369
|
+
it("lets CLI policy flags override OMX_LAUNCH_POLICY", () => {
|
|
370
|
+
assert.equal(resolveEffectiveLeaderLaunchPolicyOverride(["--tmux", "--yolo"], {
|
|
371
|
+
OMX_LAUNCH_POLICY: "direct",
|
|
372
|
+
}), "detached-tmux");
|
|
373
|
+
assert.equal(resolveEffectiveLeaderLaunchPolicyOverride(["--direct", "--yolo"], {
|
|
374
|
+
OMX_LAUNCH_POLICY: "tmux",
|
|
375
|
+
}), "direct");
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
describe("resolveNotifyTempContract", () => {
|
|
379
|
+
it("activates from --notify-temp with no providers", () => {
|
|
380
|
+
const parsed = resolveNotifyTempContract(["--notify-temp", "--model", "gpt-5"], {});
|
|
381
|
+
assert.equal(parsed.contract.active, true);
|
|
382
|
+
assert.equal(parsed.contract.source, "cli");
|
|
383
|
+
assert.deepEqual(parsed.contract.canonicalSelectors, []);
|
|
384
|
+
assert.deepEqual(parsed.passthroughArgs, ["--model", "gpt-5"]);
|
|
385
|
+
});
|
|
386
|
+
it("auto-activates when provider selectors are present", () => {
|
|
387
|
+
const parsed = resolveNotifyTempContract(["--discord", "--slack"], {});
|
|
388
|
+
assert.equal(parsed.contract.active, true);
|
|
389
|
+
assert.equal(parsed.contract.source, "providers");
|
|
390
|
+
assert.deepEqual(parsed.contract.canonicalSelectors, ["discord", "slack"]);
|
|
391
|
+
assert.equal(parsed.contract.warnings.some((line) => line.includes("imply temp mode")), true);
|
|
392
|
+
});
|
|
393
|
+
it("supports repeated --custom forms and canonicalizes selectors", () => {
|
|
394
|
+
const parsed = resolveNotifyTempContract(["--custom", "OpenClaw:Ops", "--custom=my-hook", "--custom=", "--custom"], {});
|
|
395
|
+
assert.deepEqual(parsed.contract.canonicalSelectors, [
|
|
396
|
+
"openclaw:ops",
|
|
397
|
+
"custom:my-hook",
|
|
398
|
+
]);
|
|
399
|
+
assert.equal(parsed.contract.warnings.length >= 1, true);
|
|
400
|
+
});
|
|
401
|
+
it("activates from OMX_NOTIFY_TEMP=1 env parity", () => {
|
|
402
|
+
const parsed = resolveNotifyTempContract(["--model", "gpt-5"], {
|
|
403
|
+
OMX_NOTIFY_TEMP: "1",
|
|
404
|
+
});
|
|
405
|
+
assert.equal(parsed.contract.active, true);
|
|
406
|
+
assert.equal(parsed.contract.source, "env");
|
|
407
|
+
assert.deepEqual(parsed.passthroughArgs, ["--model", "gpt-5"]);
|
|
408
|
+
});
|
|
409
|
+
});
|
|
410
|
+
describe("cleanupLaunchOrphanedMcpProcesses", () => {
|
|
411
|
+
it("reaps only detached OMX MCP processes without a live Codex ancestor", async () => {
|
|
412
|
+
const processes = [
|
|
413
|
+
{ pid: 700, ppid: 500, command: "codex" },
|
|
414
|
+
{ pid: 701, ppid: 700, command: "node /repo/bin/omx.js" },
|
|
415
|
+
{
|
|
416
|
+
pid: 710,
|
|
417
|
+
ppid: 700,
|
|
418
|
+
command: "node /repo/oh-my-codex/dist/mcp/state-server.js",
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
pid: 800,
|
|
422
|
+
ppid: 1,
|
|
423
|
+
command: "node /tmp/oh-my-codex/dist/mcp/memory-server.js",
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
pid: 810,
|
|
427
|
+
ppid: 42,
|
|
428
|
+
command: "node /tmp/oh-my-codex/dist/mcp/trace-server.js",
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
pid: 820,
|
|
432
|
+
ppid: 50,
|
|
433
|
+
command: "codex --model gpt-5",
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
pid: 821,
|
|
437
|
+
ppid: 820,
|
|
438
|
+
command: "node /tmp/other-session/dist/mcp/state-server.js",
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
pid: 830,
|
|
442
|
+
ppid: 50,
|
|
443
|
+
command: "node /repo/bin/omx.js autoresearch --topic launch",
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
pid: 831,
|
|
447
|
+
ppid: 830,
|
|
448
|
+
command: "node /tmp/parallel-session/dist/mcp/memory-server.js",
|
|
449
|
+
},
|
|
450
|
+
];
|
|
451
|
+
const signals = [];
|
|
452
|
+
const alive = new Set([800, 810]);
|
|
453
|
+
const result = await cleanupLaunchOrphanedMcpProcesses({
|
|
454
|
+
currentPid: 701,
|
|
455
|
+
listProcesses: () => processes,
|
|
456
|
+
isPidAlive: (pid) => alive.has(pid),
|
|
457
|
+
sendSignal: (pid, signal) => {
|
|
458
|
+
signals.push({ pid, signal });
|
|
459
|
+
alive.delete(pid);
|
|
460
|
+
},
|
|
461
|
+
sleep: async () => { },
|
|
462
|
+
now: () => 0,
|
|
463
|
+
});
|
|
464
|
+
assert.equal(result.terminatedCount, 2);
|
|
465
|
+
assert.equal(result.forceKilledCount, 0);
|
|
466
|
+
assert.deepEqual(result.failedPids, []);
|
|
467
|
+
assert.deepEqual(signals, [
|
|
468
|
+
{ pid: 800, signal: "SIGTERM" },
|
|
469
|
+
{ pid: 810, signal: "SIGTERM" },
|
|
470
|
+
]);
|
|
471
|
+
assert.equal(signals.some(({ pid }) => pid === 821), false, "launch-safe cleanup must preserve OMX MCP processes still attached to another live Codex tree");
|
|
472
|
+
assert.equal(signals.some(({ pid }) => pid === 831), false, "launch-safe cleanup must preserve OMX MCP processes still attached to another live OMX launch tree");
|
|
473
|
+
});
|
|
474
|
+
});
|
|
475
|
+
describe("reapPostLaunchOrphanedMcpProcesses", () => {
|
|
476
|
+
it("logs postLaunch reaped MCP orphans and keeps cleanup non-fatal", async () => {
|
|
477
|
+
const info = [];
|
|
478
|
+
const warnings = [];
|
|
479
|
+
const errors = [];
|
|
480
|
+
await reapPostLaunchOrphanedMcpProcesses({
|
|
481
|
+
cleanup: async () => ({
|
|
482
|
+
dryRun: false,
|
|
483
|
+
candidates: [],
|
|
484
|
+
terminatedCount: 2,
|
|
485
|
+
forceKilledCount: 0,
|
|
486
|
+
failedPids: [810],
|
|
487
|
+
}),
|
|
488
|
+
writeInfo: (line) => info.push(line),
|
|
489
|
+
writeWarn: (line) => warnings.push(line),
|
|
490
|
+
writeError: (line) => errors.push(line),
|
|
491
|
+
});
|
|
492
|
+
assert.deepEqual(errors, []);
|
|
493
|
+
assert.match(info.join("\n"), /postLaunch: reaped 2 orphaned OMX MCP process/);
|
|
494
|
+
assert.match(warnings.join("\n"), /postLaunch: failed to reap 1 orphaned OMX MCP process/);
|
|
495
|
+
});
|
|
496
|
+
it("writes a non-fatal postLaunch cleanup error when the cleanup step throws", async () => {
|
|
497
|
+
const errors = [];
|
|
498
|
+
await reapPostLaunchOrphanedMcpProcesses({
|
|
499
|
+
cleanup: async () => {
|
|
500
|
+
throw new Error("boom");
|
|
501
|
+
},
|
|
502
|
+
writeError: (line) => errors.push(line),
|
|
503
|
+
});
|
|
504
|
+
assert.match(errors.join("\n"), /postLaunch MCP cleanup failed: Error: boom/);
|
|
505
|
+
});
|
|
506
|
+
});
|
|
507
|
+
describe("cleanupPostLaunchModeStateFiles", () => {
|
|
508
|
+
it("repairs empty or truncated mode state files and still cancels valid siblings", async () => {
|
|
509
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-postlaunch-mode-cleanup-"));
|
|
510
|
+
const sessionId = "sess-postlaunch-cleanup";
|
|
511
|
+
const stateDir = join(wd, ".omx", "state");
|
|
512
|
+
const sessionStateDir = join(stateDir, "sessions", sessionId);
|
|
513
|
+
const partialState = '{\n "active": true,\n "mode": "ralph",\n';
|
|
514
|
+
const warnings = [];
|
|
515
|
+
await mkdir(sessionStateDir, { recursive: true });
|
|
516
|
+
await writeFile(join(sessionStateDir, "autopilot-state.json"), JSON.stringify({ active: true, mode: "autopilot" }, null, 2), "utf-8");
|
|
517
|
+
await writeFile(join(sessionStateDir, "deep-interview-state.json"), "", "utf-8");
|
|
518
|
+
await writeFile(join(sessionStateDir, "ralph-state.json"), partialState, "utf-8");
|
|
519
|
+
await cleanupPostLaunchModeStateFiles(wd, sessionId, {
|
|
520
|
+
writeWarn: (line) => warnings.push(line),
|
|
521
|
+
});
|
|
522
|
+
const autopilot = JSON.parse(await readFile(join(sessionStateDir, "autopilot-state.json"), "utf-8"));
|
|
523
|
+
const deepInterview = JSON.parse(await readFile(join(sessionStateDir, "deep-interview-state.json"), "utf-8"));
|
|
524
|
+
const ralph = JSON.parse(await readFile(join(sessionStateDir, "ralph-state.json"), "utf-8"));
|
|
525
|
+
assert.equal(autopilot.active, false);
|
|
526
|
+
assert.equal(typeof autopilot.completed_at, "string");
|
|
527
|
+
assert.equal(deepInterview.active, false);
|
|
528
|
+
assert.equal(deepInterview.mode, "deep-interview");
|
|
529
|
+
assert.equal(deepInterview.current_phase, "cancelled");
|
|
530
|
+
assert.equal(typeof deepInterview.completed_at, "string");
|
|
531
|
+
assert.equal(typeof deepInterview.last_turn_at, "string");
|
|
532
|
+
assert.equal(ralph.active, false);
|
|
533
|
+
assert.equal(ralph.mode, "ralph");
|
|
534
|
+
assert.equal(ralph.current_phase, "cancelled");
|
|
535
|
+
assert.equal(typeof ralph.completed_at, "string");
|
|
536
|
+
assert.equal(typeof ralph.last_turn_at, "string");
|
|
537
|
+
const rootCanonicalPath = join(stateDir, "skill-active-state.json");
|
|
538
|
+
const sessionCanonicalPath = join(sessionStateDir, "skill-active-state.json");
|
|
539
|
+
if (existsSync(rootCanonicalPath)) {
|
|
540
|
+
const rootCanonical = JSON.parse(await readFile(rootCanonicalPath, "utf-8"));
|
|
541
|
+
assert.equal(rootCanonical.active, false);
|
|
542
|
+
assert.deepEqual(rootCanonical.active_skills, []);
|
|
543
|
+
}
|
|
544
|
+
if (existsSync(sessionCanonicalPath)) {
|
|
545
|
+
const sessionCanonical = JSON.parse(await readFile(sessionCanonicalPath, "utf-8"));
|
|
546
|
+
assert.equal(sessionCanonical.active, false);
|
|
547
|
+
assert.deepEqual(sessionCanonical.active_skills, []);
|
|
548
|
+
}
|
|
549
|
+
assert.deepEqual(warnings, []);
|
|
550
|
+
});
|
|
551
|
+
it("does not preserve complete Ralph cleanup state without completion-audit evidence", async () => {
|
|
552
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-postlaunch-ralph-complete-audit-missing-"));
|
|
553
|
+
const sessionId = "sess-postlaunch-ralph-complete-audit-missing";
|
|
554
|
+
const sessionStateDir = join(wd, ".omx", "state", "sessions", sessionId);
|
|
555
|
+
await mkdir(sessionStateDir, { recursive: true });
|
|
556
|
+
await writeFile(join(sessionStateDir, "ralph-state.json"), JSON.stringify({
|
|
557
|
+
active: false,
|
|
558
|
+
mode: "ralph",
|
|
559
|
+
current_phase: "complete",
|
|
560
|
+
completed_at: "2026-05-09T07:00:00.000Z",
|
|
561
|
+
}, null, 2), "utf-8");
|
|
562
|
+
try {
|
|
563
|
+
await cleanupPostLaunchModeStateFiles(wd, sessionId, {
|
|
564
|
+
now: () => new Date("2026-05-09T08:00:00.000Z"),
|
|
565
|
+
});
|
|
566
|
+
const ralph = JSON.parse(await readFile(join(sessionStateDir, "ralph-state.json"), "utf-8"));
|
|
567
|
+
assert.equal(ralph.active, false);
|
|
568
|
+
assert.equal(ralph.current_phase, "cancelled");
|
|
569
|
+
assert.equal(ralph.stop_reason, "missing_completion_audit:missing_completion_audit");
|
|
570
|
+
assert.equal(ralph.completion_audit_gate, "blocked");
|
|
571
|
+
assert.equal(ralph.completion_audit_missing_reason, "missing_completion_audit");
|
|
572
|
+
}
|
|
573
|
+
finally {
|
|
574
|
+
await rm(wd, { recursive: true, force: true });
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
it("preserves complete Ralph cleanup state when completion-audit evidence is present", async () => {
|
|
578
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-postlaunch-ralph-complete-audit-present-"));
|
|
579
|
+
const sessionId = "sess-postlaunch-ralph-complete-audit-present";
|
|
580
|
+
const sessionStateDir = join(wd, ".omx", "state", "sessions", sessionId);
|
|
581
|
+
await mkdir(sessionStateDir, { recursive: true });
|
|
582
|
+
await writeFile(join(sessionStateDir, "ralph-state.json"), JSON.stringify({
|
|
583
|
+
active: false,
|
|
584
|
+
mode: "ralph",
|
|
585
|
+
current_phase: "complete",
|
|
586
|
+
completed_at: "2026-05-09T07:00:00.000Z",
|
|
587
|
+
completion_audit: {
|
|
588
|
+
passed: true,
|
|
589
|
+
prompt_to_artifact_checklist: ["all prompt requirements mapped"],
|
|
590
|
+
verification_evidence: ["npm test"],
|
|
591
|
+
},
|
|
592
|
+
}, null, 2), "utf-8");
|
|
593
|
+
try {
|
|
594
|
+
await cleanupPostLaunchModeStateFiles(wd, sessionId, {
|
|
595
|
+
now: () => new Date("2026-05-09T08:00:00.000Z"),
|
|
596
|
+
});
|
|
597
|
+
const ralph = JSON.parse(await readFile(join(sessionStateDir, "ralph-state.json"), "utf-8"));
|
|
598
|
+
assert.equal(ralph.active, false);
|
|
599
|
+
assert.equal(ralph.current_phase, "complete");
|
|
600
|
+
assert.equal(ralph.stop_reason, undefined);
|
|
601
|
+
}
|
|
602
|
+
finally {
|
|
603
|
+
await rm(wd, { recursive: true, force: true });
|
|
604
|
+
}
|
|
605
|
+
});
|
|
606
|
+
it("marks active Ralph state cancelled with interrupted metadata during postLaunch cleanup", async () => {
|
|
607
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-postlaunch-ralph-interrupted-"));
|
|
608
|
+
const sessionId = "sess-postlaunch-ralph-interrupted";
|
|
609
|
+
const sessionStateDir = join(wd, ".omx", "state", "sessions", sessionId);
|
|
610
|
+
await mkdir(sessionStateDir, { recursive: true });
|
|
611
|
+
await writeFile(join(sessionStateDir, "ralph-state.json"), JSON.stringify({
|
|
612
|
+
active: true,
|
|
613
|
+
mode: "ralph",
|
|
614
|
+
current_phase: "executing",
|
|
615
|
+
owner_omx_session_id: sessionId,
|
|
616
|
+
}, null, 2), "utf-8");
|
|
617
|
+
try {
|
|
618
|
+
await cleanupPostLaunchModeStateFiles(wd, sessionId, {
|
|
619
|
+
now: () => new Date("2026-05-09T08:00:00.000Z"),
|
|
620
|
+
});
|
|
621
|
+
const ralph = JSON.parse(await readFile(join(sessionStateDir, "ralph-state.json"), "utf-8"));
|
|
622
|
+
assert.equal(ralph.active, false);
|
|
623
|
+
assert.equal(ralph.current_phase, "cancelled");
|
|
624
|
+
assert.equal(ralph.completed_at, "2026-05-09T08:00:00.000Z");
|
|
625
|
+
assert.equal(ralph.interrupted_at, "2026-05-09T08:00:00.000Z");
|
|
626
|
+
assert.equal(ralph.stop_reason, "session_exit");
|
|
627
|
+
}
|
|
628
|
+
finally {
|
|
629
|
+
await rm(wd, { recursive: true, force: true });
|
|
630
|
+
}
|
|
631
|
+
});
|
|
632
|
+
it("does not cancel root mode state during session-scoped postLaunch cleanup", async () => {
|
|
633
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-postlaunch-root-preserve-"));
|
|
634
|
+
const sessionId = "sess-postlaunch-root-preserve";
|
|
635
|
+
const stateDir = join(wd, ".omx", "state");
|
|
636
|
+
const sessionStateDir = join(stateDir, "sessions", sessionId);
|
|
637
|
+
await mkdir(sessionStateDir, { recursive: true });
|
|
638
|
+
await writeFile(join(stateDir, "ralph-state.json"), JSON.stringify({ active: true, mode: "ralph", current_phase: "executing" }, null, 2), "utf-8");
|
|
639
|
+
await writeFile(join(sessionStateDir, "ralplan-state.json"), JSON.stringify({ active: true, mode: "ralplan", current_phase: "planning" }, null, 2), "utf-8");
|
|
640
|
+
try {
|
|
641
|
+
await cleanupPostLaunchModeStateFiles(wd, sessionId);
|
|
642
|
+
const rootRalph = JSON.parse(await readFile(join(stateDir, "ralph-state.json"), "utf-8"));
|
|
643
|
+
const sessionRalplan = JSON.parse(await readFile(join(sessionStateDir, "ralplan-state.json"), "utf-8"));
|
|
644
|
+
assert.equal(rootRalph.active, true);
|
|
645
|
+
assert.equal(sessionRalplan.active, false);
|
|
646
|
+
assert.equal(sessionRalplan.current_phase, "cancelled");
|
|
647
|
+
}
|
|
648
|
+
finally {
|
|
649
|
+
await rm(wd, { recursive: true, force: true });
|
|
650
|
+
}
|
|
651
|
+
});
|
|
652
|
+
it("retries a transient parse failure before cancelling the rewritten mode state", async () => {
|
|
653
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-postlaunch-mode-retry-"));
|
|
654
|
+
const sessionId = "sess-postlaunch-retry";
|
|
655
|
+
const stateDir = join(wd, ".omx", "state");
|
|
656
|
+
const sessionStateDir = join(stateDir, "sessions", sessionId);
|
|
657
|
+
const statePath = join(sessionStateDir, "ralph-state.json");
|
|
658
|
+
const writes = [];
|
|
659
|
+
const validState = JSON.stringify({ active: true, mode: "ralph" }, null, 2);
|
|
660
|
+
let reads = 0;
|
|
661
|
+
await mkdir(sessionStateDir, { recursive: true });
|
|
662
|
+
const mockReaddir = (async (dir, _options) => (String(dir) === sessionStateDir ? ["ralph-state.json"] : []));
|
|
663
|
+
const mockReadFile = (async (path, _options) => {
|
|
664
|
+
assert.equal(String(path), statePath);
|
|
665
|
+
reads += 1;
|
|
666
|
+
return reads === 1
|
|
667
|
+
? '{\n "active": true,\n "mode": "ralph"'
|
|
668
|
+
: validState;
|
|
669
|
+
});
|
|
670
|
+
const mockWriteFile = (async (path, content, _options) => {
|
|
671
|
+
writes.push({ path: String(path), content: String(content) });
|
|
672
|
+
});
|
|
673
|
+
const dependencies = {
|
|
674
|
+
readdir: mockReaddir,
|
|
675
|
+
readFile: mockReadFile,
|
|
676
|
+
writeFile: mockWriteFile,
|
|
677
|
+
sleep: async () => { },
|
|
678
|
+
now: () => new Date("2026-04-07T00:00:00.000Z"),
|
|
679
|
+
};
|
|
680
|
+
await cleanupPostLaunchModeStateFiles(wd, sessionId, dependencies);
|
|
681
|
+
assert.equal(reads, 2);
|
|
682
|
+
assert.equal(writes.length, 1);
|
|
683
|
+
assert.equal(writes[0]?.path, statePath);
|
|
684
|
+
const persisted = JSON.parse(writes[0]?.content ?? "{}");
|
|
685
|
+
assert.equal(persisted.active, false);
|
|
686
|
+
assert.equal(persisted.completed_at, "2026-04-07T00:00:00.000Z");
|
|
687
|
+
});
|
|
688
|
+
it("warns on structurally complete malformed JSON without aborting sibling cleanup", async () => {
|
|
689
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-postlaunch-mode-malformed-"));
|
|
690
|
+
const sessionId = "sess-postlaunch-malformed";
|
|
691
|
+
const stateDir = join(wd, ".omx", "state");
|
|
692
|
+
const sessionStateDir = join(stateDir, "sessions", sessionId);
|
|
693
|
+
const warnings = [];
|
|
694
|
+
const malformedState = '{\n "active": true,\n}\n';
|
|
695
|
+
await mkdir(sessionStateDir, { recursive: true });
|
|
696
|
+
await writeFile(join(sessionStateDir, "ralph-state.json"), malformedState, "utf-8");
|
|
697
|
+
await writeFile(join(sessionStateDir, "ultrawork-state.json"), JSON.stringify({ active: true, mode: "ultrawork" }, null, 2), "utf-8");
|
|
698
|
+
await cleanupPostLaunchModeStateFiles(wd, sessionId, {
|
|
699
|
+
writeWarn: (line) => warnings.push(line),
|
|
700
|
+
});
|
|
701
|
+
const ultrawork = JSON.parse(await readFile(join(sessionStateDir, "ultrawork-state.json"), "utf-8"));
|
|
702
|
+
assert.equal(ultrawork.active, false);
|
|
703
|
+
assert.equal(typeof ultrawork.completed_at, "string");
|
|
704
|
+
const canonicalPath = join(stateDir, "skill-active-state.json");
|
|
705
|
+
if (existsSync(canonicalPath)) {
|
|
706
|
+
const canonical = JSON.parse(await readFile(canonicalPath, "utf-8"));
|
|
707
|
+
assert.equal(canonical.active, false);
|
|
708
|
+
assert.deepEqual(canonical.active_skills, []);
|
|
709
|
+
}
|
|
710
|
+
assert.equal(await readFile(join(sessionStateDir, "ralph-state.json"), "utf-8"), malformedState);
|
|
711
|
+
assert.equal(warnings.length, 1);
|
|
712
|
+
assert.match(warnings[0] ?? "", /skipped malformed mode state .*ralph-state\.json/);
|
|
713
|
+
});
|
|
714
|
+
it("reconciles root skill-active entries for the finished terminal session", async () => {
|
|
715
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-postlaunch-root-skill-active-"));
|
|
716
|
+
const sessionId = "sess-terminal-autopilot";
|
|
717
|
+
const otherSessionId = "sess-other";
|
|
718
|
+
const stateDir = join(wd, ".omx", "state");
|
|
719
|
+
const sessionStateDir = join(stateDir, "sessions", sessionId);
|
|
720
|
+
try {
|
|
721
|
+
await mkdir(sessionStateDir, { recursive: true });
|
|
722
|
+
await writeFile(join(stateDir, "skill-active-state.json"), JSON.stringify({
|
|
723
|
+
version: 1,
|
|
724
|
+
active: true,
|
|
725
|
+
skill: "autopilot",
|
|
726
|
+
phase: "ralph",
|
|
727
|
+
session_id: sessionId,
|
|
728
|
+
initialized_state_path: `.omx/state/sessions/${sessionId}/autopilot-state.json`,
|
|
729
|
+
active_skills: [
|
|
730
|
+
{ skill: "autopilot", phase: "ralph", active: true, session_id: sessionId },
|
|
731
|
+
{ skill: "team", phase: "running", active: true, session_id: otherSessionId },
|
|
732
|
+
],
|
|
733
|
+
}, null, 2), "utf-8");
|
|
734
|
+
await cleanupPostLaunchModeStateFiles(wd, sessionId);
|
|
735
|
+
const rootCanonical = JSON.parse(await readFile(join(stateDir, "skill-active-state.json"), "utf-8"));
|
|
736
|
+
assert.equal(rootCanonical.active, true);
|
|
737
|
+
assert.deepEqual(rootCanonical.active_skills, [
|
|
738
|
+
{ skill: "team", phase: "running", active: true, session_id: otherSessionId },
|
|
739
|
+
]);
|
|
740
|
+
}
|
|
741
|
+
finally {
|
|
742
|
+
await rm(wd, { recursive: true, force: true });
|
|
743
|
+
}
|
|
744
|
+
});
|
|
745
|
+
it("preserves other-session active skills when session mode cleanup syncs before root scrub", async () => {
|
|
746
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-postlaunch-mode-root-skill-active-"));
|
|
747
|
+
const sessionId = "sess-terminal-autopilot";
|
|
748
|
+
const otherSessionId = "sess-other-team";
|
|
749
|
+
const stateDir = join(wd, ".omx", "state");
|
|
750
|
+
const sessionStateDir = join(stateDir, "sessions", sessionId);
|
|
751
|
+
try {
|
|
752
|
+
await mkdir(sessionStateDir, { recursive: true });
|
|
753
|
+
await writeFile(join(stateDir, "skill-active-state.json"), JSON.stringify({
|
|
754
|
+
version: 1,
|
|
755
|
+
active: true,
|
|
756
|
+
skill: "autopilot",
|
|
757
|
+
phase: "ralph",
|
|
758
|
+
session_id: sessionId,
|
|
759
|
+
initialized_state_path: `.omx/state/sessions/${sessionId}/autopilot-state.json`,
|
|
760
|
+
active_skills: [
|
|
761
|
+
{ skill: "autopilot", phase: "ralph", active: true, session_id: sessionId },
|
|
762
|
+
{ skill: "team", phase: "running", active: true, session_id: otherSessionId },
|
|
763
|
+
],
|
|
764
|
+
}, null, 2), "utf-8");
|
|
765
|
+
await writeFile(join(sessionStateDir, "autopilot-state.json"), JSON.stringify({ active: true, mode: "autopilot", current_phase: "ralph" }, null, 2), "utf-8");
|
|
766
|
+
await cleanupPostLaunchModeStateFiles(wd, sessionId);
|
|
767
|
+
const autopilotState = JSON.parse(await readFile(join(sessionStateDir, "autopilot-state.json"), "utf-8"));
|
|
768
|
+
assert.equal(autopilotState.active, false);
|
|
769
|
+
assert.equal(autopilotState.current_phase, "cancelled");
|
|
770
|
+
const rootCanonical = JSON.parse(await readFile(join(stateDir, "skill-active-state.json"), "utf-8"));
|
|
771
|
+
assert.equal(rootCanonical.active, true);
|
|
772
|
+
assert.equal(rootCanonical.skill, "team");
|
|
773
|
+
assert.equal(rootCanonical.phase, "running");
|
|
774
|
+
assert.deepEqual(rootCanonical.active_skills, [
|
|
775
|
+
{ skill: "team", phase: "running", active: true, session_id: otherSessionId },
|
|
776
|
+
]);
|
|
777
|
+
}
|
|
778
|
+
finally {
|
|
779
|
+
await rm(wd, { recursive: true, force: true });
|
|
780
|
+
}
|
|
781
|
+
});
|
|
782
|
+
it("preserves review-pending Autopilot state across postLaunch compact cleanup", async () => {
|
|
783
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-postlaunch-autopilot-review-pending-"));
|
|
784
|
+
const sessionId = "sess-autopilot-review-pending";
|
|
785
|
+
const stateDir = join(wd, ".omx", "state");
|
|
786
|
+
const sessionStateDir = join(stateDir, "sessions", sessionId);
|
|
787
|
+
try {
|
|
788
|
+
await mkdir(sessionStateDir, { recursive: true });
|
|
789
|
+
await writeFile(join(stateDir, "skill-active-state.json"), JSON.stringify({
|
|
790
|
+
version: 1,
|
|
791
|
+
active: true,
|
|
792
|
+
skill: "autopilot",
|
|
793
|
+
phase: "code-review",
|
|
794
|
+
session_id: sessionId,
|
|
795
|
+
initialized_state_path: `.omx/state/sessions/${sessionId}/autopilot-state.json`,
|
|
796
|
+
active_skills: [
|
|
797
|
+
{ skill: "autopilot", phase: "code-review", active: true, session_id: sessionId },
|
|
798
|
+
],
|
|
799
|
+
}, null, 2), "utf-8");
|
|
800
|
+
await writeFile(join(sessionStateDir, "skill-active-state.json"), JSON.stringify({
|
|
801
|
+
version: 1,
|
|
802
|
+
active: true,
|
|
803
|
+
skill: "autopilot",
|
|
804
|
+
phase: "code-review",
|
|
805
|
+
session_id: sessionId,
|
|
806
|
+
active_skills: [
|
|
807
|
+
{ skill: "autopilot", phase: "code-review", active: true, session_id: sessionId },
|
|
808
|
+
],
|
|
809
|
+
}, null, 2), "utf-8");
|
|
810
|
+
await writeFile(join(sessionStateDir, "autopilot-state.json"), JSON.stringify({
|
|
811
|
+
active: true,
|
|
812
|
+
mode: "autopilot",
|
|
813
|
+
current_phase: "code-review",
|
|
814
|
+
iteration: 1,
|
|
815
|
+
review_cycle: 0,
|
|
816
|
+
state: {
|
|
817
|
+
phase_cycle: ["ralplan", "ralph", "code-review"],
|
|
818
|
+
handoff_artifacts: {
|
|
819
|
+
ralplan: ".omx/plans/prd-issue-2366.md",
|
|
820
|
+
ralph: { verification: ["npm test"], changed_files: ["src/cli/index.ts"] },
|
|
821
|
+
code_review: null,
|
|
822
|
+
},
|
|
823
|
+
review_verdict: null,
|
|
824
|
+
return_to_ralplan_reason: null,
|
|
825
|
+
},
|
|
826
|
+
}, null, 2), "utf-8");
|
|
827
|
+
await cleanupPostLaunchModeStateFiles(wd, sessionId, {
|
|
828
|
+
now: () => new Date("2026-05-16T11:00:00.000Z"),
|
|
829
|
+
});
|
|
830
|
+
const autopilotState = JSON.parse(await readFile(join(sessionStateDir, "autopilot-state.json"), "utf-8"));
|
|
831
|
+
assert.equal(autopilotState.active, true);
|
|
832
|
+
assert.equal(autopilotState.current_phase, "code-review");
|
|
833
|
+
assert.equal(autopilotState.completed_at, undefined);
|
|
834
|
+
assert.equal(autopilotState.state?.review_verdict, null);
|
|
835
|
+
const sessionSkill = JSON.parse(await readFile(join(sessionStateDir, "skill-active-state.json"), "utf-8"));
|
|
836
|
+
assert.equal(sessionSkill.active, true);
|
|
837
|
+
assert.equal(sessionSkill.skill, "autopilot");
|
|
838
|
+
assert.equal(sessionSkill.phase, "code-review");
|
|
839
|
+
const rootSkill = JSON.parse(await readFile(join(stateDir, "skill-active-state.json"), "utf-8"));
|
|
840
|
+
assert.equal(rootSkill.active, true);
|
|
841
|
+
assert.equal(rootSkill.skill, "autopilot");
|
|
842
|
+
assert.equal(rootSkill.phase, "code-review");
|
|
843
|
+
}
|
|
844
|
+
finally {
|
|
845
|
+
await rm(wd, { recursive: true, force: true });
|
|
846
|
+
}
|
|
847
|
+
});
|
|
848
|
+
it("clears canonical skill-active entries during cleanup and hides them from HUD/overlay readers", async () => {
|
|
849
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-postlaunch-skill-active-cleanup-"));
|
|
850
|
+
const sessionId = "sess-skill-active-cleanup";
|
|
851
|
+
const stateDir = join(wd, ".omx", "state");
|
|
852
|
+
const sessionStateDir = join(stateDir, "sessions", sessionId);
|
|
853
|
+
await mkdir(sessionStateDir, { recursive: true });
|
|
854
|
+
await writeFile(join(stateDir, "session.json"), JSON.stringify({ session_id: sessionId }), "utf-8");
|
|
855
|
+
await writeFile(join(sessionStateDir, "skill-active-state.json"), JSON.stringify({
|
|
856
|
+
version: 1,
|
|
857
|
+
active: true,
|
|
858
|
+
skill: "autoresearch",
|
|
859
|
+
phase: "running",
|
|
860
|
+
session_id: sessionId,
|
|
861
|
+
active_skills: [
|
|
862
|
+
{ skill: "autoresearch", phase: "running", active: true, session_id: sessionId },
|
|
863
|
+
],
|
|
864
|
+
}, null, 2), "utf-8");
|
|
865
|
+
await cleanupPostLaunchModeStateFiles(wd, sessionId);
|
|
866
|
+
const canonical = JSON.parse(await readFile(join(sessionStateDir, "skill-active-state.json"), "utf-8"));
|
|
867
|
+
assert.equal(canonical.active, false);
|
|
868
|
+
assert.equal(canonical.phase, "complete");
|
|
869
|
+
assert.deepEqual(canonical.active_skills, []);
|
|
870
|
+
const hudState = await readAllState(wd);
|
|
871
|
+
assert.equal(hudState.autoresearch, null);
|
|
872
|
+
const overlay = await generateOverlay(wd, sessionId);
|
|
873
|
+
assert.equal(overlay.includes("- autoresearch:"), false);
|
|
874
|
+
});
|
|
875
|
+
});
|
|
876
|
+
describe("watcher script path resolution", () => {
|
|
877
|
+
it("resolves packaged watcher entrypoints from dist/scripts", () => {
|
|
878
|
+
assert.equal(resolveNotifyFallbackWatcherScript("/pkg"), "/pkg/dist/scripts/notify-fallback-watcher.js");
|
|
879
|
+
assert.equal(resolveHookDerivedWatcherScript("/pkg"), "/pkg/dist/scripts/hook-derived-watcher.js");
|
|
880
|
+
assert.equal(resolveNotifyHookScript("/pkg"), "/pkg/dist/scripts/notify-hook.js");
|
|
881
|
+
});
|
|
882
|
+
});
|
|
883
|
+
describe("buildNotifyFallbackWatcherEnv", () => {
|
|
884
|
+
it("enables watcher authority and propagates CODEX_HOME override when requested", () => {
|
|
885
|
+
const env = buildNotifyFallbackWatcherEnv({ HOME: "/tmp/home", OMX_HUD_AUTHORITY: "0", TMUX: "sock,1,0", TMUX_PANE: "%2" }, { codexHomeOverride: "/tmp/codex-home", omxRootOverride: "/tmp/omx-root", enableAuthority: true });
|
|
886
|
+
assert.equal(env.OMX_HUD_AUTHORITY, "1");
|
|
887
|
+
assert.equal(env.CODEX_HOME, "/tmp/codex-home");
|
|
888
|
+
assert.equal(env.OMX_ROOT, "/tmp/omx-root");
|
|
889
|
+
assert.equal(env.HOME, "/tmp/home");
|
|
890
|
+
assert.equal(env.TMUX, undefined);
|
|
891
|
+
assert.equal(env.TMUX_PANE, undefined);
|
|
892
|
+
});
|
|
893
|
+
it("disables watcher authority explicitly when not requested", () => {
|
|
894
|
+
const env = buildNotifyFallbackWatcherEnv({ HOME: "/tmp/home", OMX_HUD_AUTHORITY: "1", TMUX: "sock,1,0", TMUX_PANE: "%3" }, { enableAuthority: false });
|
|
895
|
+
assert.equal(env.OMX_HUD_AUTHORITY, "0");
|
|
896
|
+
assert.equal(env.HOME, "/tmp/home");
|
|
897
|
+
assert.equal(env.TMUX, undefined);
|
|
898
|
+
assert.equal(env.TMUX_PANE, undefined);
|
|
899
|
+
});
|
|
900
|
+
});
|
|
901
|
+
describe("shouldEnableNotifyFallbackWatcher", () => {
|
|
902
|
+
it("keeps notify fallback enabled by default on non-Windows hosts", () => {
|
|
903
|
+
assert.equal(shouldEnableNotifyFallbackWatcher({}, "linux"), true);
|
|
904
|
+
});
|
|
905
|
+
it("disables notify fallback explicitly on non-Windows hosts", () => {
|
|
906
|
+
assert.equal(shouldEnableNotifyFallbackWatcher({ OMX_NOTIFY_FALLBACK: "0" }, "linux"), false);
|
|
907
|
+
});
|
|
908
|
+
it("disables notify fallback by default on win32", () => {
|
|
909
|
+
assert.equal(shouldEnableNotifyFallbackWatcher({}, "win32"), false);
|
|
910
|
+
});
|
|
911
|
+
it("allows explicit opt-in for notify fallback on win32", () => {
|
|
912
|
+
assert.equal(shouldEnableNotifyFallbackWatcher({ OMX_NOTIFY_FALLBACK: "1" }, "win32"), true);
|
|
913
|
+
});
|
|
914
|
+
});
|
|
915
|
+
describe("reapStaleNotifyFallbackWatcher", () => {
|
|
916
|
+
it("stops an existing watcher even when a later startup gate would skip relaunch", async () => {
|
|
917
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-stale-notify-fallback-"));
|
|
918
|
+
try {
|
|
919
|
+
const pidPath = join(cwd, "notify-fallback.pid");
|
|
920
|
+
await writeFile(pidPath, JSON.stringify({ pid: 4321, started_at: "2026-04-05T00:00:00.000Z" }), "utf-8");
|
|
921
|
+
const killed = [];
|
|
922
|
+
await reapStaleNotifyFallbackWatcher(pidPath, {
|
|
923
|
+
isWatcherProcess: () => true,
|
|
924
|
+
tryKillPid(pid, signal) {
|
|
925
|
+
killed.push({ pid, signal });
|
|
926
|
+
return true;
|
|
927
|
+
},
|
|
928
|
+
});
|
|
929
|
+
assert.deepEqual(killed, [{ pid: 4321, signal: "SIGTERM" }]);
|
|
930
|
+
assert.equal(shouldEnableNotifyFallbackWatcher({}, "win32"), false);
|
|
931
|
+
}
|
|
932
|
+
finally {
|
|
933
|
+
await rm(cwd, { recursive: true, force: true });
|
|
934
|
+
}
|
|
935
|
+
});
|
|
936
|
+
it("ignores missing pid files", async () => {
|
|
937
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-missing-notify-fallback-"));
|
|
938
|
+
try {
|
|
939
|
+
const pidPath = join(cwd, "notify-fallback.pid");
|
|
940
|
+
let killCalls = 0;
|
|
941
|
+
await reapStaleNotifyFallbackWatcher(pidPath, {
|
|
942
|
+
tryKillPid() {
|
|
943
|
+
killCalls += 1;
|
|
944
|
+
return true;
|
|
945
|
+
},
|
|
946
|
+
});
|
|
947
|
+
assert.equal(killCalls, 0);
|
|
948
|
+
}
|
|
949
|
+
finally {
|
|
950
|
+
await rm(cwd, { recursive: true, force: true });
|
|
951
|
+
}
|
|
952
|
+
});
|
|
953
|
+
it("suppresses ESRCH cleanup errors but warns on unexpected failures", async () => {
|
|
954
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-esrch-notify-fallback-"));
|
|
955
|
+
try {
|
|
956
|
+
const pidPath = join(cwd, "notify-fallback.pid");
|
|
957
|
+
await writeFile(pidPath, JSON.stringify({ pid: 99 }), "utf-8");
|
|
958
|
+
const warnings = [];
|
|
959
|
+
await reapStaleNotifyFallbackWatcher(pidPath, {
|
|
960
|
+
readFile: async () => {
|
|
961
|
+
throw Object.assign(new Error("gone"), { code: "ESRCH" });
|
|
962
|
+
},
|
|
963
|
+
warn(message, meta) {
|
|
964
|
+
warnings.push({ message, meta });
|
|
965
|
+
},
|
|
966
|
+
});
|
|
967
|
+
assert.deepEqual(warnings, []);
|
|
968
|
+
const warned = [];
|
|
969
|
+
await reapStaleNotifyFallbackWatcher(pidPath, {
|
|
970
|
+
readFile: async (path, encoding) => readFile(path, encoding),
|
|
971
|
+
isWatcherProcess: () => true,
|
|
972
|
+
tryKillPid() {
|
|
973
|
+
throw new Error("permission denied");
|
|
974
|
+
},
|
|
975
|
+
warn(message, meta) {
|
|
976
|
+
warned.push({ message, meta });
|
|
977
|
+
},
|
|
978
|
+
});
|
|
979
|
+
assert.equal(warned.length, 1);
|
|
980
|
+
assert.equal(warned[0]?.message, "[omx] warning: failed to stop stale notify fallback watcher");
|
|
981
|
+
}
|
|
982
|
+
finally {
|
|
983
|
+
await rm(cwd, { recursive: true, force: true });
|
|
984
|
+
}
|
|
985
|
+
});
|
|
986
|
+
});
|
|
987
|
+
describe("buildNotifyTempStartupMessages", () => {
|
|
988
|
+
it("always emits summary when temp mode is active", () => {
|
|
989
|
+
const result = buildNotifyTempStartupMessages({
|
|
990
|
+
active: true,
|
|
991
|
+
selectors: ["discord"],
|
|
992
|
+
canonicalSelectors: ["discord"],
|
|
993
|
+
warnings: [],
|
|
994
|
+
source: "cli",
|
|
995
|
+
}, true);
|
|
996
|
+
assert.deepEqual(result.infoLines, [
|
|
997
|
+
"notify temp: active | providers=discord | persistent-routing=bypassed",
|
|
998
|
+
]);
|
|
999
|
+
assert.deepEqual(result.warningLines, []);
|
|
1000
|
+
});
|
|
1001
|
+
it("emits no-valid-provider warning when no provider is configured", () => {
|
|
1002
|
+
const result = buildNotifyTempStartupMessages({
|
|
1003
|
+
active: true,
|
|
1004
|
+
selectors: [],
|
|
1005
|
+
canonicalSelectors: [],
|
|
1006
|
+
warnings: [
|
|
1007
|
+
"notify temp: provider selectors imply temp mode (auto-activated)",
|
|
1008
|
+
],
|
|
1009
|
+
source: "providers",
|
|
1010
|
+
}, false);
|
|
1011
|
+
assert.equal(result.warningLines.includes("notify temp: no valid providers resolved; notifications skipped"), true);
|
|
1012
|
+
});
|
|
1013
|
+
});
|
|
1014
|
+
describe("resolveWorkerSparkModel", () => {
|
|
1015
|
+
it("returns spark model string when --spark is present", () => {
|
|
1016
|
+
assert.equal(resolveWorkerSparkModel(["--spark", "--yolo"]), expectedLowComplexityModel());
|
|
1017
|
+
});
|
|
1018
|
+
it("returns spark model string when --madmax-spark is present", () => {
|
|
1019
|
+
assert.equal(resolveWorkerSparkModel(["--madmax-spark"]), expectedLowComplexityModel());
|
|
1020
|
+
});
|
|
1021
|
+
it("returns undefined when neither spark flag is present", () => {
|
|
1022
|
+
assert.equal(resolveWorkerSparkModel(["--madmax", "--yolo", "--model", "gpt-5"]), undefined);
|
|
1023
|
+
});
|
|
1024
|
+
it("returns undefined for empty args", () => {
|
|
1025
|
+
assert.equal(resolveWorkerSparkModel([]), undefined);
|
|
1026
|
+
});
|
|
1027
|
+
it("reads low-complexity team model from config when codexHomeOverride is provided", async () => {
|
|
1028
|
+
const codexHome = await mkdtemp(join(tmpdir(), "omx-codex-home-"));
|
|
1029
|
+
try {
|
|
1030
|
+
await writeFile(join(codexHome, ".omx-config.json"), JSON.stringify({ models: { team_low_complexity: "gpt-4.1-mini" } }));
|
|
1031
|
+
assert.equal(resolveWorkerSparkModel(["--spark"], codexHome), "gpt-4.1-mini");
|
|
1032
|
+
}
|
|
1033
|
+
finally {
|
|
1034
|
+
await rm(codexHome, { recursive: true, force: true });
|
|
1035
|
+
}
|
|
1036
|
+
});
|
|
1037
|
+
});
|
|
1038
|
+
describe("resolveTeamWorkerLaunchArgsEnv (spark)", () => {
|
|
1039
|
+
it("injects spark model as worker default when no explicit env model", () => {
|
|
1040
|
+
assert.equal(resolveTeamWorkerLaunchArgsEnv(undefined, [], true, expectedLowComplexityModel()), `--model ${expectedLowComplexityModel()}`);
|
|
1041
|
+
});
|
|
1042
|
+
it("explicit env model overrides spark default", () => {
|
|
1043
|
+
assert.equal(resolveTeamWorkerLaunchArgsEnv("--model gpt-5", [], true, expectedLowComplexityModel()), "--model gpt-5");
|
|
1044
|
+
});
|
|
1045
|
+
it("inherited leader model overrides spark default", () => {
|
|
1046
|
+
assert.equal(resolveTeamWorkerLaunchArgsEnv(undefined, ["--model", "gpt-4.1"], true, expectedLowComplexityModel()), "--model gpt-4.1");
|
|
1047
|
+
});
|
|
1048
|
+
});
|
|
1049
|
+
describe("commandOwnsLocalHelp", () => {
|
|
1050
|
+
it("returns true for nested commands that render their own help output", () => {
|
|
1051
|
+
for (const command of [
|
|
1052
|
+
"adapt",
|
|
1053
|
+
"agents-init",
|
|
1054
|
+
"api",
|
|
1055
|
+
"ask",
|
|
1056
|
+
"question",
|
|
1057
|
+
"autoresearch",
|
|
1058
|
+
"deepinit",
|
|
1059
|
+
"explore",
|
|
1060
|
+
"hooks",
|
|
1061
|
+
"hud",
|
|
1062
|
+
"ralph",
|
|
1063
|
+
"resume",
|
|
1064
|
+
"session",
|
|
1065
|
+
"sparkshell",
|
|
1066
|
+
"team",
|
|
1067
|
+
"tmux-hook",
|
|
1068
|
+
]) {
|
|
1069
|
+
assert.equal(commandOwnsLocalHelp(command), true, `expected ${command} to own local help`);
|
|
1070
|
+
}
|
|
1071
|
+
});
|
|
1072
|
+
it("returns false for top-level help-only commands", () => {
|
|
1073
|
+
for (const command of ["help", "launch", "version", "update"]) {
|
|
1074
|
+
assert.equal(commandOwnsLocalHelp(command), false, `expected ${command} to use top-level help`);
|
|
1075
|
+
}
|
|
1076
|
+
});
|
|
1077
|
+
});
|
|
1078
|
+
describe("resolveCliInvocation", () => {
|
|
1079
|
+
it("resolves api to api command", () => {
|
|
1080
|
+
assert.deepEqual(resolveCliInvocation(["api", "status"]), {
|
|
1081
|
+
command: "api",
|
|
1082
|
+
launchArgs: [],
|
|
1083
|
+
});
|
|
1084
|
+
});
|
|
1085
|
+
it("resolves explore to explore command", () => {
|
|
1086
|
+
assert.deepEqual(resolveCliInvocation(["explore", "--prompt", "find", "auth"]), {
|
|
1087
|
+
command: "explore",
|
|
1088
|
+
launchArgs: [],
|
|
1089
|
+
});
|
|
1090
|
+
});
|
|
1091
|
+
it("resolves ask to ask command", () => {
|
|
1092
|
+
assert.deepEqual(resolveCliInvocation(["ask", "claude", "hello"]), {
|
|
1093
|
+
command: "ask",
|
|
1094
|
+
launchArgs: [],
|
|
1095
|
+
});
|
|
1096
|
+
});
|
|
1097
|
+
it("resolves question to question command", () => {
|
|
1098
|
+
assert.deepEqual(resolveCliInvocation(["question", "--input", "{}"]), {
|
|
1099
|
+
command: "question",
|
|
1100
|
+
launchArgs: [],
|
|
1101
|
+
});
|
|
1102
|
+
});
|
|
1103
|
+
it("resolves autoresearch to autoresearch command", () => {
|
|
1104
|
+
assert.deepEqual(resolveCliInvocation(["autoresearch", "missions/demo"]), {
|
|
1105
|
+
command: "autoresearch",
|
|
1106
|
+
launchArgs: [],
|
|
1107
|
+
});
|
|
1108
|
+
});
|
|
1109
|
+
it("resolves session to session command", () => {
|
|
1110
|
+
assert.deepEqual(resolveCliInvocation(["session", "search", "startup evidence"]), {
|
|
1111
|
+
command: "session",
|
|
1112
|
+
launchArgs: [],
|
|
1113
|
+
});
|
|
1114
|
+
});
|
|
1115
|
+
it("resolves resume to resume command and forwards trailing args", () => {
|
|
1116
|
+
assert.deepEqual(resolveCliInvocation(["resume", "--last"]), {
|
|
1117
|
+
command: "resume",
|
|
1118
|
+
launchArgs: ["--last"],
|
|
1119
|
+
});
|
|
1120
|
+
});
|
|
1121
|
+
it("resolves resume session id and prompt as forwarded args", () => {
|
|
1122
|
+
assert.deepEqual(resolveCliInvocation(["resume", "session-123", "continue here"]), {
|
|
1123
|
+
command: "resume",
|
|
1124
|
+
launchArgs: ["session-123", "continue here"],
|
|
1125
|
+
});
|
|
1126
|
+
});
|
|
1127
|
+
it("resolves exec to non-interactive launch passthrough and forwards trailing args", () => {
|
|
1128
|
+
assert.deepEqual(resolveCliInvocation(["exec", "--model", "gpt-5", "say hi"]), {
|
|
1129
|
+
command: "exec",
|
|
1130
|
+
launchArgs: ["--model", "gpt-5", "say hi"],
|
|
1131
|
+
});
|
|
1132
|
+
});
|
|
1133
|
+
it("resolves update to update command", () => {
|
|
1134
|
+
assert.deepEqual(resolveCliInvocation(["update"]), {
|
|
1135
|
+
command: "update",
|
|
1136
|
+
launchArgs: [],
|
|
1137
|
+
});
|
|
1138
|
+
});
|
|
1139
|
+
it("resolves update channel flags and rejects invalid combinations", () => {
|
|
1140
|
+
assert.equal(resolveUpdateChannelArg([]), "stable");
|
|
1141
|
+
assert.equal(resolveUpdateChannelArg(["--stable"]), "stable");
|
|
1142
|
+
assert.equal(resolveUpdateChannelArg(["--dev"]), "dev");
|
|
1143
|
+
assert.throws(() => resolveUpdateChannelArg(["--dev", "--stable"]), /mutually exclusive/);
|
|
1144
|
+
assert.throws(() => resolveUpdateChannelArg(["--beta"]), /Unknown omx update option: --beta/);
|
|
1145
|
+
});
|
|
1146
|
+
it("resolves hooks to hooks command", () => {
|
|
1147
|
+
assert.deepEqual(resolveCliInvocation(["hooks"]), {
|
|
1148
|
+
command: "hooks",
|
|
1149
|
+
launchArgs: [],
|
|
1150
|
+
});
|
|
1151
|
+
});
|
|
1152
|
+
it("resolves agents-init to agents-init command", () => {
|
|
1153
|
+
assert.deepEqual(resolveCliInvocation(["agents-init", "."]), {
|
|
1154
|
+
command: "agents-init",
|
|
1155
|
+
launchArgs: [],
|
|
1156
|
+
});
|
|
1157
|
+
});
|
|
1158
|
+
it("resolves deepinit to deepinit alias command", () => {
|
|
1159
|
+
assert.deepEqual(resolveCliInvocation(["deepinit", "src"]), {
|
|
1160
|
+
command: "deepinit",
|
|
1161
|
+
launchArgs: [],
|
|
1162
|
+
});
|
|
1163
|
+
});
|
|
1164
|
+
it("resolves --help to the help command instead of launch", () => {
|
|
1165
|
+
assert.deepEqual(resolveCliInvocation(["--help"]), {
|
|
1166
|
+
command: "help",
|
|
1167
|
+
launchArgs: [],
|
|
1168
|
+
});
|
|
1169
|
+
});
|
|
1170
|
+
it("resolves --version to the version command instead of launch", () => {
|
|
1171
|
+
assert.deepEqual(resolveCliInvocation(["--version"]), {
|
|
1172
|
+
command: "version",
|
|
1173
|
+
launchArgs: [],
|
|
1174
|
+
});
|
|
1175
|
+
});
|
|
1176
|
+
it("resolves -v to the version command instead of launch", () => {
|
|
1177
|
+
assert.deepEqual(resolveCliInvocation(["-v"]), {
|
|
1178
|
+
command: "version",
|
|
1179
|
+
launchArgs: [],
|
|
1180
|
+
});
|
|
1181
|
+
});
|
|
1182
|
+
it("keeps unknown long flags as launch passthrough args", () => {
|
|
1183
|
+
assert.deepEqual(resolveCliInvocation(["--model", "gpt-5"]), {
|
|
1184
|
+
command: "launch",
|
|
1185
|
+
launchArgs: ["--model", "gpt-5"],
|
|
1186
|
+
});
|
|
1187
|
+
});
|
|
1188
|
+
it("advertises the explicit update command in top-level help", () => {
|
|
1189
|
+
assert.match(HELP, /omx update\s+Install the stable channel now, then refresh setup/);
|
|
1190
|
+
assert.match(HELP, /omx update --stable\s+Install\/rollback to npm stable \(oh-my-codex@latest\), then refresh setup/);
|
|
1191
|
+
assert.match(HELP, /omx update --dev\s+Install the upstream dev branch, then refresh setup/);
|
|
1192
|
+
});
|
|
1193
|
+
it("advertises concise launch policy controls in top-level help", () => {
|
|
1194
|
+
assert.match(HELP, /--direct\s+Launch the interactive leader directly/);
|
|
1195
|
+
assert.match(HELP, /OMX_LAUNCH_POLICY=auto[\s\S]*Use the default policy/);
|
|
1196
|
+
assert.match(HELP, /OMX_LAUNCH_POLICY=direct[\s\S]*Run without OMX tmux\/HUD management/);
|
|
1197
|
+
assert.match(HELP, /OMX_LAUNCH_POLICY=tmux[\s\S]*Force OMX-managed detached tmux launch/);
|
|
1198
|
+
assert.match(HELP, /OMX_LAUNCH_POLICY=detached-tmux[\s\S]*Force OMX-managed detached tmux launch/);
|
|
1199
|
+
assert.match(HELP, /CLI policy flags \(--direct\/--tmux\) override OMX_LAUNCH_POLICY/);
|
|
1200
|
+
assert.match(HELP, /Unset or empty OMX_LAUNCH_POLICY returns to auto\/default behavior/);
|
|
1201
|
+
assert.match(HELP, /Config files are intentionally not used/);
|
|
1202
|
+
assert.doesNotMatch(HELP, /OMX_LAUNCH_POLICY=direct\|tmux\|detached-tmux\|auto/);
|
|
1203
|
+
assert.doesNotMatch(HELP, /OMX_LAUNCH_POLICY=direct omx --tmux --yolo/);
|
|
1204
|
+
});
|
|
1205
|
+
});
|
|
1206
|
+
describe("resolveSetupInstallModeArg", () => {
|
|
1207
|
+
it("maps explicit setup install mode flags", () => {
|
|
1208
|
+
assert.equal(resolveSetupInstallModeArg(["--dry-run"]), undefined);
|
|
1209
|
+
assert.equal(resolveSetupInstallModeArg(["--plugin"]), "plugin");
|
|
1210
|
+
assert.equal(resolveSetupInstallModeArg(["--legacy"]), "legacy");
|
|
1211
|
+
assert.equal(resolveSetupInstallModeArg(["--install-mode", "legacy"]), "legacy");
|
|
1212
|
+
assert.equal(resolveSetupInstallModeArg(["--install-mode=plugin"]), "plugin");
|
|
1213
|
+
assert.equal(resolveSetupInstallModeArg(["--scope", "project", "--plugin"]), "plugin");
|
|
1214
|
+
});
|
|
1215
|
+
it("rejects invalid setup install mode flags", () => {
|
|
1216
|
+
assert.throws(() => resolveSetupInstallModeArg(["--install-mode"]), /Missing setup install mode value after --install-mode/);
|
|
1217
|
+
assert.throws(() => resolveSetupInstallModeArg(["--install-mode", "workspace"]), /Invalid setup install mode: workspace/);
|
|
1218
|
+
assert.throws(() => resolveSetupInstallModeArg(["--plugin", "--legacy"]), /Conflicting setup install mode flags/);
|
|
1219
|
+
assert.throws(() => resolveSetupInstallModeArg(["--plugin", "--install-mode", "legacy"]), /Conflicting setup install mode flags/);
|
|
1220
|
+
assert.throws(() => resolveSetupInstallModeArg(["--legacy", "--install-mode=plugin"]), /Conflicting setup install mode flags/);
|
|
1221
|
+
});
|
|
1222
|
+
});
|
|
1223
|
+
describe("resolveSetupMcpModeArg", () => {
|
|
1224
|
+
it("maps explicit setup MCP mode flags", () => {
|
|
1225
|
+
assert.equal(resolveSetupMcpModeArg(["--dry-run"]), undefined);
|
|
1226
|
+
assert.equal(resolveSetupMcpModeArg(["--no-mcp"]), "none");
|
|
1227
|
+
assert.equal(resolveSetupMcpModeArg(["--with-mcp"]), "compat");
|
|
1228
|
+
assert.equal(resolveSetupMcpModeArg(["--mcp", "none"]), "none");
|
|
1229
|
+
assert.equal(resolveSetupMcpModeArg(["--mcp=compat"]), "compat");
|
|
1230
|
+
assert.equal(resolveSetupMcpModeArg(["--scope", "project", "--mcp", "compat"]), "compat");
|
|
1231
|
+
});
|
|
1232
|
+
it("rejects invalid or conflicting setup MCP mode flags", () => {
|
|
1233
|
+
assert.throws(() => resolveSetupMcpModeArg(["--mcp"]), /Missing setup MCP mode value after --mcp/);
|
|
1234
|
+
assert.throws(() => resolveSetupMcpModeArg(["--mcp", "full"]), /Invalid setup MCP mode: full/);
|
|
1235
|
+
assert.throws(() => resolveSetupMcpModeArg(["--no-mcp", "--with-mcp"]), /Conflicting setup MCP mode flags/);
|
|
1236
|
+
assert.throws(() => resolveSetupMcpModeArg(["--no-mcp", "--mcp=compat"]), /Conflicting setup MCP mode flags/);
|
|
1237
|
+
});
|
|
1238
|
+
});
|
|
1239
|
+
describe("resolveSetupTeamModeArg", () => {
|
|
1240
|
+
it("maps explicit setup Team mode flags", () => {
|
|
1241
|
+
assert.equal(resolveSetupTeamModeArg(["--dry-run"]), undefined);
|
|
1242
|
+
assert.equal(resolveSetupTeamModeArg(["--disable-team"]), "disabled");
|
|
1243
|
+
assert.equal(resolveSetupTeamModeArg(["--no-team"]), "disabled");
|
|
1244
|
+
assert.equal(resolveSetupTeamModeArg(["--enable-team"]), "enabled");
|
|
1245
|
+
assert.equal(resolveSetupTeamModeArg(["--team"]), "enabled");
|
|
1246
|
+
assert.equal(resolveSetupTeamModeArg(["--team-mode", "disabled"]), "disabled");
|
|
1247
|
+
assert.equal(resolveSetupTeamModeArg(["--team-mode=enabled"]), "enabled");
|
|
1248
|
+
assert.equal(resolveSetupTeamModeArg(["--scope", "project", "--team-mode", "disabled"]), "disabled");
|
|
1249
|
+
});
|
|
1250
|
+
it("rejects invalid or conflicting setup Team mode flags", () => {
|
|
1251
|
+
assert.throws(() => resolveSetupTeamModeArg(["--team-mode"]), /Missing setup Team mode value after --team-mode/);
|
|
1252
|
+
assert.throws(() => resolveSetupTeamModeArg(["--team-mode", "minimal"]), /Invalid setup Team mode: minimal/);
|
|
1253
|
+
assert.throws(() => resolveSetupTeamModeArg(["--disable-team", "--enable-team"]), /Conflicting setup Team mode flags/);
|
|
1254
|
+
assert.throws(() => resolveSetupTeamModeArg(["--team-mode=enabled", "--no-team"]), /Conflicting setup Team mode flags/);
|
|
1255
|
+
});
|
|
1256
|
+
});
|
|
1257
|
+
describe("resolveSetupScopeArg", () => {
|
|
1258
|
+
it("returns undefined when scope is omitted", () => {
|
|
1259
|
+
assert.equal(resolveSetupScopeArg(["--dry-run"]), undefined);
|
|
1260
|
+
});
|
|
1261
|
+
it("parses --scope <value> form", () => {
|
|
1262
|
+
assert.equal(resolveSetupScopeArg(["--dry-run", "--scope", "project"]), "project");
|
|
1263
|
+
});
|
|
1264
|
+
it("parses --scope=<value> form", () => {
|
|
1265
|
+
assert.equal(resolveSetupScopeArg(["--scope=project"]), "project");
|
|
1266
|
+
});
|
|
1267
|
+
it("throws on invalid scope value", () => {
|
|
1268
|
+
assert.throws(() => resolveSetupScopeArg(["--scope", "workspace"]), /Invalid setup scope: workspace/);
|
|
1269
|
+
});
|
|
1270
|
+
it("throws when --scope value is missing", () => {
|
|
1271
|
+
assert.throws(() => resolveSetupScopeArg(["--scope"]), /Missing setup scope value after --scope/);
|
|
1272
|
+
});
|
|
1273
|
+
});
|
|
1274
|
+
describe("project launch scope helpers", () => {
|
|
1275
|
+
it("reads persisted setup scope when valid", async () => {
|
|
1276
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-launch-scope-"));
|
|
1277
|
+
try {
|
|
1278
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1279
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project" }));
|
|
1280
|
+
assert.equal(readPersistedSetupScope(wd), "project");
|
|
1281
|
+
}
|
|
1282
|
+
finally {
|
|
1283
|
+
await rm(wd, { recursive: true, force: true });
|
|
1284
|
+
}
|
|
1285
|
+
});
|
|
1286
|
+
it("reads persisted setup preferences when install mode is present", async () => {
|
|
1287
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-launch-scope-"));
|
|
1288
|
+
try {
|
|
1289
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1290
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "user", installMode: "plugin" }));
|
|
1291
|
+
assert.deepEqual(readPersistedSetupPreferences(wd), {
|
|
1292
|
+
scope: "user",
|
|
1293
|
+
installMode: "plugin",
|
|
1294
|
+
});
|
|
1295
|
+
}
|
|
1296
|
+
finally {
|
|
1297
|
+
await rm(wd, { recursive: true, force: true });
|
|
1298
|
+
}
|
|
1299
|
+
});
|
|
1300
|
+
it("reads persisted setup Team mode when present", async () => {
|
|
1301
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-launch-scope-"));
|
|
1302
|
+
try {
|
|
1303
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1304
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project", teamMode: "disabled" }));
|
|
1305
|
+
assert.deepEqual(readPersistedSetupPreferences(wd), {
|
|
1306
|
+
scope: "project",
|
|
1307
|
+
teamMode: "disabled",
|
|
1308
|
+
});
|
|
1309
|
+
}
|
|
1310
|
+
finally {
|
|
1311
|
+
await rm(wd, { recursive: true, force: true });
|
|
1312
|
+
}
|
|
1313
|
+
});
|
|
1314
|
+
it("ignores malformed persisted setup scope", async () => {
|
|
1315
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-launch-scope-"));
|
|
1316
|
+
try {
|
|
1317
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1318
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), "{not-json");
|
|
1319
|
+
assert.equal(readPersistedSetupScope(wd), undefined);
|
|
1320
|
+
}
|
|
1321
|
+
finally {
|
|
1322
|
+
await rm(wd, { recursive: true, force: true });
|
|
1323
|
+
}
|
|
1324
|
+
});
|
|
1325
|
+
it("uses project CODEX_HOME when persisted scope is project", async () => {
|
|
1326
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-launch-scope-"));
|
|
1327
|
+
try {
|
|
1328
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1329
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project" }));
|
|
1330
|
+
assert.equal(resolveCodexHomeForLaunch(wd, {}), join(wd, ".codex"));
|
|
1331
|
+
}
|
|
1332
|
+
finally {
|
|
1333
|
+
await rm(wd, { recursive: true, force: true });
|
|
1334
|
+
}
|
|
1335
|
+
});
|
|
1336
|
+
it("uses project CODEX_HOME when persisted scope is project even if HOME is unusable", async () => {
|
|
1337
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-launch-scope-"));
|
|
1338
|
+
try {
|
|
1339
|
+
const badHome = join(wd, "home-as-file");
|
|
1340
|
+
await writeFile(badHome, "not-a-directory");
|
|
1341
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1342
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project" }));
|
|
1343
|
+
assert.equal(resolveCodexHomeForLaunch(wd, { HOME: badHome }), join(wd, ".codex"));
|
|
1344
|
+
assert.equal(resolveCodexConfigPathForLaunch(wd, { HOME: badHome }), join(wd, ".codex", "config.toml"));
|
|
1345
|
+
}
|
|
1346
|
+
finally {
|
|
1347
|
+
await rm(wd, { recursive: true, force: true });
|
|
1348
|
+
}
|
|
1349
|
+
});
|
|
1350
|
+
it("uses project config.toml for launch repair when persisted scope is project", async () => {
|
|
1351
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-launch-scope-"));
|
|
1352
|
+
try {
|
|
1353
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1354
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project" }));
|
|
1355
|
+
assert.equal(resolveCodexConfigPathForLaunch(wd, {}), join(wd, ".codex", "config.toml"));
|
|
1356
|
+
}
|
|
1357
|
+
finally {
|
|
1358
|
+
await rm(wd, { recursive: true, force: true });
|
|
1359
|
+
}
|
|
1360
|
+
});
|
|
1361
|
+
it("preserves explicit compat MCP during launch config repair", async () => {
|
|
1362
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-launch-scope-"));
|
|
1363
|
+
try {
|
|
1364
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1365
|
+
await mkdir(join(wd, ".codex"), { recursive: true });
|
|
1366
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project", mcpMode: "compat" }));
|
|
1367
|
+
const configPath = join(wd, ".codex", "config.toml");
|
|
1368
|
+
await mergeConfig(configPath, wd, {
|
|
1369
|
+
includeFirstPartyMcp: true,
|
|
1370
|
+
sharedMcpServers: [
|
|
1371
|
+
{
|
|
1372
|
+
name: "eslint",
|
|
1373
|
+
command: "npx",
|
|
1374
|
+
args: ["@eslint/mcp@latest"],
|
|
1375
|
+
enabled: true,
|
|
1376
|
+
startupTimeoutSec: 12,
|
|
1377
|
+
},
|
|
1378
|
+
],
|
|
1379
|
+
sharedMcpRegistrySource: join(wd, ".omx", "mcp-registry.json"),
|
|
1380
|
+
});
|
|
1381
|
+
const clean = await readFile(configPath, "utf-8");
|
|
1382
|
+
assert.match(clean, /^\[mcp_servers\.omx_state\]$/m);
|
|
1383
|
+
assert.match(clean, /oh-my-codex \(OMX\) Shared MCP Registry Sync/);
|
|
1384
|
+
assert.match(clean, /^\[mcp_servers\.eslint\]$/m);
|
|
1385
|
+
await writeFile(configPath, `${clean}\n[tui]\nstatus_line = ["git-branch"]\n`);
|
|
1386
|
+
const repaired = await repairConfigIfNeeded(configPath, wd, await resolveLaunchConfigRepairOptions(wd, configPath));
|
|
1387
|
+
const repairedToml = await readFile(configPath, "utf-8");
|
|
1388
|
+
assert.equal(repaired, true);
|
|
1389
|
+
assert.match(repairedToml, /^\[mcp_servers\.omx_state\]$/m);
|
|
1390
|
+
assert.match(repairedToml, /oh-my-codex \(OMX\) Shared MCP Registry Sync/);
|
|
1391
|
+
assert.match(repairedToml, /^\[mcp_servers\.eslint\]$/m);
|
|
1392
|
+
assert.equal((repairedToml.match(/^\[tui\]$/gm) ?? []).length, 1);
|
|
1393
|
+
}
|
|
1394
|
+
finally {
|
|
1395
|
+
await rm(wd, { recursive: true, force: true });
|
|
1396
|
+
}
|
|
1397
|
+
});
|
|
1398
|
+
it("preserves existing compat MCP during launch repair without cwd-local preferences", async () => {
|
|
1399
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-launch-scope-"));
|
|
1400
|
+
try {
|
|
1401
|
+
const configPath = join(wd, "global-codex", "config.toml");
|
|
1402
|
+
await mkdir(dirname(configPath), { recursive: true });
|
|
1403
|
+
await mergeConfig(configPath, wd, { includeFirstPartyMcp: true });
|
|
1404
|
+
const clean = await readFile(configPath, "utf-8");
|
|
1405
|
+
assert.equal(existsSync(join(wd, ".omx", "setup-scope.json")), false);
|
|
1406
|
+
assert.match(clean, /^\[mcp_servers\.omx_state\]$/m);
|
|
1407
|
+
await writeFile(configPath, `${clean}\n[tui]\nstatus_line = ["git-branch"]\n`);
|
|
1408
|
+
const repaired = await repairConfigIfNeeded(configPath, wd, await resolveLaunchConfigRepairOptions(wd, configPath));
|
|
1409
|
+
const repairedToml = await readFile(configPath, "utf-8");
|
|
1410
|
+
assert.equal(repaired, true);
|
|
1411
|
+
assert.match(repairedToml, /^\[mcp_servers\.omx_state\]$/m);
|
|
1412
|
+
assert.equal((repairedToml.match(/^\[tui\]$/gm) ?? []).length, 1);
|
|
1413
|
+
}
|
|
1414
|
+
finally {
|
|
1415
|
+
await rm(wd, { recursive: true, force: true });
|
|
1416
|
+
}
|
|
1417
|
+
});
|
|
1418
|
+
it("marks only persisted project CODEX_HOME as project-local cleanup target", async () => {
|
|
1419
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-launch-scope-"));
|
|
1420
|
+
try {
|
|
1421
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1422
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project" }));
|
|
1423
|
+
assert.equal(resolveProjectLocalCodexHomeForLaunch(wd, {}), join(wd, ".codex"));
|
|
1424
|
+
}
|
|
1425
|
+
finally {
|
|
1426
|
+
await rm(wd, { recursive: true, force: true });
|
|
1427
|
+
}
|
|
1428
|
+
});
|
|
1429
|
+
it("does not mark explicit CODEX_HOME as project-local cleanup target", async () => {
|
|
1430
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-launch-scope-"));
|
|
1431
|
+
try {
|
|
1432
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1433
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project" }));
|
|
1434
|
+
assert.equal(resolveProjectLocalCodexHomeForLaunch(wd, {
|
|
1435
|
+
CODEX_HOME: "/tmp/user-global-codex-home",
|
|
1436
|
+
}), undefined);
|
|
1437
|
+
}
|
|
1438
|
+
finally {
|
|
1439
|
+
await rm(wd, { recursive: true, force: true });
|
|
1440
|
+
}
|
|
1441
|
+
});
|
|
1442
|
+
it("includes project Codex history artifacts in the runtime mirror for resume launches", async () => {
|
|
1443
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-resume-runtime-codex-home-"));
|
|
1444
|
+
try {
|
|
1445
|
+
const projectCodexHome = join(wd, ".codex");
|
|
1446
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1447
|
+
await mkdir(join(projectCodexHome, "sessions", "2026", "06", "03"), { recursive: true });
|
|
1448
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project" }));
|
|
1449
|
+
await writeFile(join(projectCodexHome, "config.toml"), 'model = "gpt-5.5"\n');
|
|
1450
|
+
await writeFile(join(projectCodexHome, "state_5.sqlite"), "state db placeholder");
|
|
1451
|
+
await writeFile(join(projectCodexHome, "state_5.sqlite-wal"), "state db wal placeholder");
|
|
1452
|
+
await writeFile(join(projectCodexHome, "logs_2.sqlite-shm"), "logs db shm placeholder");
|
|
1453
|
+
await writeFile(join(projectCodexHome, "sessions", "2026", "06", "03", "rollout-session-2712.jsonl"), '{"type":"session_meta","payload":{"id":"session-2712"}}\n');
|
|
1454
|
+
const prepared = await prepareCodexHomeForLaunch(wd, "session-resume", {}, {
|
|
1455
|
+
includeHistoryArtifacts: true,
|
|
1456
|
+
});
|
|
1457
|
+
const runtimeCodexHome = runtimeCodexHomePath(wd, "session-resume");
|
|
1458
|
+
assert.equal(prepared.codexHomeOverride, runtimeCodexHome);
|
|
1459
|
+
assert.equal(prepared.sqliteHomeOverride, projectCodexHome);
|
|
1460
|
+
assert.equal(existsSync(join(runtimeCodexHome, "state_5.sqlite")), true);
|
|
1461
|
+
assert.equal(existsSync(join(runtimeCodexHome, "state_5.sqlite-wal")), true);
|
|
1462
|
+
assert.equal(existsSync(join(runtimeCodexHome, "logs_2.sqlite-shm")), true);
|
|
1463
|
+
assert.equal(existsSync(join(runtimeCodexHome, "sessions", "2026", "06", "03", "rollout-session-2712.jsonl")), true);
|
|
1464
|
+
}
|
|
1465
|
+
finally {
|
|
1466
|
+
await rm(wd, { recursive: true, force: true });
|
|
1467
|
+
}
|
|
1468
|
+
});
|
|
1469
|
+
it("uses a session-scoped CODEX_HOME mirror for project launch config writes", async () => {
|
|
1470
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-launch-runtime-codex-home-"));
|
|
1471
|
+
try {
|
|
1472
|
+
const projectCodexHome = join(wd, ".codex");
|
|
1473
|
+
const configPath = join(projectCodexHome, "config.toml");
|
|
1474
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1475
|
+
await mkdir(join(projectCodexHome, "agents"), { recursive: true });
|
|
1476
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project" }));
|
|
1477
|
+
const originalConfig = [
|
|
1478
|
+
'model = "gpt-5.5"',
|
|
1479
|
+
"",
|
|
1480
|
+
"[tui]",
|
|
1481
|
+
'status_line = ["model-with-reasoning", "git-branch"]',
|
|
1482
|
+
"",
|
|
1483
|
+
].join("\n");
|
|
1484
|
+
await writeFile(configPath, originalConfig);
|
|
1485
|
+
await writeFile(join(projectCodexHome, "agents", "planner.toml"), 'name = "planner"\n');
|
|
1486
|
+
await writeFile(join(projectCodexHome, "hooks.json"), '{"hooks":{}}\n');
|
|
1487
|
+
await writeFile(join(projectCodexHome, "state_5.sqlite"), "state db placeholder");
|
|
1488
|
+
await writeFile(join(projectCodexHome, "state_5.sqlite-wal"), "state db wal placeholder");
|
|
1489
|
+
await writeFile(join(projectCodexHome, "logs_2.sqlite-shm"), "logs db shm placeholder");
|
|
1490
|
+
const beforeStat = await stat(configPath);
|
|
1491
|
+
const prepared = await prepareCodexHomeForLaunch(wd, "session-2033", {});
|
|
1492
|
+
const runtimeCodexHome = runtimeCodexHomePath(wd, "session-2033");
|
|
1493
|
+
assert.equal(prepared.codexHomeOverride, runtimeCodexHome);
|
|
1494
|
+
assert.equal(prepared.sqliteHomeOverride, projectCodexHome);
|
|
1495
|
+
assert.equal(prepared.projectLocalCodexHomeForCleanup, projectCodexHome);
|
|
1496
|
+
assert.equal(prepared.runtimeCodexHomeForCleanup, runtimeCodexHome);
|
|
1497
|
+
assert.equal(await readFile(join(runtimeCodexHome, "config.toml"), "utf-8"), originalConfig);
|
|
1498
|
+
assert.equal(await readFile(join(runtimeCodexHome, "agents", "planner.toml"), "utf-8"), 'name = "planner"\n');
|
|
1499
|
+
// GH #2470: hooks.json must NOT be mirrored into the runtime CODEX_HOME.
|
|
1500
|
+
// Codex still loads the canonical project .codex/hooks.json as Project
|
|
1501
|
+
// config; a runtime mirror would add a duplicate User config hook source.
|
|
1502
|
+
assert.equal(existsSync(join(runtimeCodexHome, "hooks.json")), false);
|
|
1503
|
+
assert.equal(existsSync(join(runtimeCodexHome, "state_5.sqlite")), false);
|
|
1504
|
+
assert.equal(existsSync(join(runtimeCodexHome, "state_5.sqlite-wal")), false);
|
|
1505
|
+
assert.equal(existsSync(join(runtimeCodexHome, "logs_2.sqlite-shm")), false);
|
|
1506
|
+
await writeFile(join(runtimeCodexHome, "config.toml"), `${originalConfig}\n[tui.model_availability_nux]\n"gpt-5.5" = 1\n`);
|
|
1507
|
+
assert.equal(await readFile(configPath, "utf-8"), originalConfig);
|
|
1508
|
+
assert.doesNotMatch(await readFile(configPath, "utf-8"), /model_availability_nux/);
|
|
1509
|
+
assert.equal((await stat(configPath)).mtimeMs, beforeStat.mtimeMs);
|
|
1510
|
+
await prepareCodexHomeForLaunch(wd, "session-2033-repeat", {});
|
|
1511
|
+
assert.equal(await readFile(configPath, "utf-8"), originalConfig);
|
|
1512
|
+
assert.equal((await stat(configPath)).mtimeMs, beforeStat.mtimeMs);
|
|
1513
|
+
}
|
|
1514
|
+
finally {
|
|
1515
|
+
await rm(wd, { recursive: true, force: true });
|
|
1516
|
+
}
|
|
1517
|
+
});
|
|
1518
|
+
it("persists project-scope Codex auth written into the runtime CODEX_HOME mirror", async () => {
|
|
1519
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-launch-runtime-auth-home-"));
|
|
1520
|
+
try {
|
|
1521
|
+
const projectCodexHome = join(wd, ".codex");
|
|
1522
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1523
|
+
await mkdir(projectCodexHome, { recursive: true });
|
|
1524
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project" }));
|
|
1525
|
+
await writeFile(join(projectCodexHome, "config.toml"), 'model = "gpt-5.5"\n');
|
|
1526
|
+
const prepared = await prepareCodexHomeForLaunch(wd, "session-auth", {});
|
|
1527
|
+
const runtimeCodexHome = runtimeCodexHomePath(wd, "session-auth");
|
|
1528
|
+
const opaqueAuthState = JSON.stringify({ token: "opaque-test-token" });
|
|
1529
|
+
await writeFile(join(runtimeCodexHome, "auth.json"), opaqueAuthState);
|
|
1530
|
+
await writeFile(join(runtimeCodexHome, "config.toml"), 'model = "gpt-5.5"\n[tui.model_availability_nux]\n"gpt-5.5" = 1\n');
|
|
1531
|
+
await persistProjectLaunchRuntimeAuthState(prepared.runtimeCodexHomeForCleanup, prepared.projectLocalCodexHomeForCleanup);
|
|
1532
|
+
assert.equal(await readFile(join(projectCodexHome, "auth.json"), "utf-8"), opaqueAuthState);
|
|
1533
|
+
assert.equal(await readFile(join(projectCodexHome, "config.toml"), "utf-8"), 'model = "gpt-5.5"\n');
|
|
1534
|
+
}
|
|
1535
|
+
finally {
|
|
1536
|
+
await rm(wd, { recursive: true, force: true });
|
|
1537
|
+
}
|
|
1538
|
+
});
|
|
1539
|
+
it("project-scope launch registers native hooks exactly once and persists trust state (GH #2470)", async () => {
|
|
1540
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-issue-2470-"));
|
|
1541
|
+
try {
|
|
1542
|
+
const projectCodexHome = join(wd, ".codex");
|
|
1543
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1544
|
+
await mkdir(projectCodexHome, { recursive: true });
|
|
1545
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project" }));
|
|
1546
|
+
const originalProjectConfig = [
|
|
1547
|
+
'model = "gpt-5.5"',
|
|
1548
|
+
"",
|
|
1549
|
+
"[features]",
|
|
1550
|
+
"hooks = true",
|
|
1551
|
+
"",
|
|
1552
|
+
"# OMX-owned Codex hook trust state",
|
|
1553
|
+
"# Trusts only setup-managed codex-native-hook.js wrappers.",
|
|
1554
|
+
`[hooks.state."${join(projectCodexHome, "hooks.json")}:pre_tool_use:0:0"]`,
|
|
1555
|
+
'trusted_hash = "sha256:project-hooks-trusted"',
|
|
1556
|
+
"# End OMX-owned Codex hook trust state",
|
|
1557
|
+
"",
|
|
1558
|
+
].join("\n");
|
|
1559
|
+
await writeFile(join(projectCodexHome, "config.toml"), originalProjectConfig);
|
|
1560
|
+
await writeFile(join(projectCodexHome, "hooks.json"), '{"hooks":{}}\n');
|
|
1561
|
+
const prepared = await prepareCodexHomeForLaunch(wd, "session-2470", {});
|
|
1562
|
+
const runtimeCodexHome = runtimeCodexHomePath(wd, "session-2470");
|
|
1563
|
+
// 1. Hooks register exactly once: runtime CODEX_HOME holds no hooks.json
|
|
1564
|
+
// mirror, so Codex only sees the canonical project .codex/hooks.json.
|
|
1565
|
+
assert.equal(prepared.codexHomeOverride, runtimeCodexHome);
|
|
1566
|
+
assert.equal(existsSync(join(runtimeCodexHome, "hooks.json")), false);
|
|
1567
|
+
assert.equal(existsSync(join(projectCodexHome, "hooks.json")), true);
|
|
1568
|
+
// Simulate Codex writing workspace trust + a new hook trust ledger
|
|
1569
|
+
// entry into the runtime config.toml during the session.
|
|
1570
|
+
const runtimeConfigPath = join(runtimeCodexHome, "config.toml");
|
|
1571
|
+
const runtimeConfigBefore = await readFile(runtimeConfigPath, "utf-8");
|
|
1572
|
+
await writeFile(runtimeConfigPath, [
|
|
1573
|
+
runtimeConfigBefore.replace(/\n+$/, ""),
|
|
1574
|
+
"",
|
|
1575
|
+
`[projects."${wd}"]`,
|
|
1576
|
+
'trust_level = "trusted"',
|
|
1577
|
+
"",
|
|
1578
|
+
"[tui.model_availability_nux]",
|
|
1579
|
+
'"gpt-5.5" = 1',
|
|
1580
|
+
"",
|
|
1581
|
+
].join("\n"));
|
|
1582
|
+
// 2. Workspace trust + ephemeral runtime state are persisted to the
|
|
1583
|
+
// project config.toml in a marker-fenced block; NUX counters and
|
|
1584
|
+
// other runtime-only writes are NOT leaked back to the project.
|
|
1585
|
+
await persistProjectLaunchRuntimeProjectTrustState(prepared.runtimeCodexHomeForCleanup, prepared.projectLocalCodexHomeForCleanup);
|
|
1586
|
+
const persistedProjectConfig = await readFile(join(projectCodexHome, "config.toml"), "utf-8");
|
|
1587
|
+
assert.ok(persistedProjectConfig.includes("# OMX-synced Codex project trust state"), "expected synced-trust marker block in project config.toml");
|
|
1588
|
+
assert.ok(persistedProjectConfig.includes(`[projects."${wd}"]`), "expected workspace trust entry to be persisted to project config.toml");
|
|
1589
|
+
assert.ok(persistedProjectConfig.includes('trust_level = "trusted"'), "expected trust_level to be persisted to project config.toml");
|
|
1590
|
+
assert.doesNotMatch(persistedProjectConfig, /model_availability_nux/, "NUX counters must not leak into durable project config.toml");
|
|
1591
|
+
const projectHookTrustHeader = `[hooks.state."${join(projectCodexHome, "hooks.json")}:pre_tool_use:0:0"]`;
|
|
1592
|
+
assert.ok(persistedProjectConfig.includes(projectHookTrustHeader), "setup-owned project hook trust state must remain intact");
|
|
1593
|
+
assert.equal(countMatches(persistedProjectConfig, new RegExp(`^${escapeRegExp(projectHookTrustHeader)}$`, "gm")), 1, "runtime trust sync must not duplicate setup-owned hook trust state");
|
|
1594
|
+
assert.doesNotThrow(() => TOML.parse(persistedProjectConfig));
|
|
1595
|
+
// 3. On a subsequent launch, the runtime mirror carries the persisted
|
|
1596
|
+
// project trust state forward — so Codex finds the workspace as
|
|
1597
|
+
// already-trusted and never re-prompts.
|
|
1598
|
+
await rm(runtimeCodexHome, { recursive: true, force: true });
|
|
1599
|
+
await prepareCodexHomeForLaunch(wd, "session-2470-repeat", {});
|
|
1600
|
+
const nextRuntimeCodexHome = runtimeCodexHomePath(wd, "session-2470-repeat");
|
|
1601
|
+
const nextRuntimeConfig = await readFile(join(nextRuntimeCodexHome, "config.toml"), "utf-8");
|
|
1602
|
+
assert.ok(nextRuntimeConfig.includes(`[projects."${wd}"]`), "next launch must inherit the persisted workspace trust entry");
|
|
1603
|
+
assert.equal(countMatches(nextRuntimeConfig, new RegExp(`^${escapeRegExp(projectHookTrustHeader)}$`, "gm")), 1, "next runtime config must remain parseable without duplicate hook trust tables");
|
|
1604
|
+
assert.doesNotThrow(() => TOML.parse(nextRuntimeConfig));
|
|
1605
|
+
assert.equal(existsSync(join(nextRuntimeCodexHome, "hooks.json")), false);
|
|
1606
|
+
}
|
|
1607
|
+
finally {
|
|
1608
|
+
await rm(wd, { recursive: true, force: true });
|
|
1609
|
+
}
|
|
1610
|
+
});
|
|
1611
|
+
it("repairs duplicate project hook trust state before relaunching project-scope Codex home (GH #2401)", async () => {
|
|
1612
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-issue-2401-relaunch-"));
|
|
1613
|
+
try {
|
|
1614
|
+
const projectCodexHome = join(wd, ".codex");
|
|
1615
|
+
const projectConfigPath = join(projectCodexHome, "config.toml");
|
|
1616
|
+
const projectHooksPath = join(projectCodexHome, "hooks.json");
|
|
1617
|
+
const projectHookTrustHeader = `[hooks.state."${projectHooksPath}:post_compact:0:0"]`;
|
|
1618
|
+
const escapedProjectHookTrustHeader = escapeRegExp(projectHookTrustHeader);
|
|
1619
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1620
|
+
await mkdir(projectCodexHome, { recursive: true });
|
|
1621
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project" }));
|
|
1622
|
+
await writeFile(projectHooksPath, '{"hooks":{}}\n');
|
|
1623
|
+
await writeFile(projectConfigPath, [
|
|
1624
|
+
'model = "gpt-5.5"',
|
|
1625
|
+
"",
|
|
1626
|
+
"[features]",
|
|
1627
|
+
"hooks = true",
|
|
1628
|
+
"",
|
|
1629
|
+
"# OMX-owned Codex hook trust state",
|
|
1630
|
+
"# Trusts only setup-managed native hook wrappers.",
|
|
1631
|
+
projectHookTrustHeader,
|
|
1632
|
+
'trusted_hash = "sha256:setup-owned"',
|
|
1633
|
+
"# End OMX-owned Codex hook trust state",
|
|
1634
|
+
"",
|
|
1635
|
+
"# OMX-synced Codex project trust state (from runtime CODEX_HOME)",
|
|
1636
|
+
`[projects."${wd}"]`,
|
|
1637
|
+
'trust_level = "trusted"',
|
|
1638
|
+
"",
|
|
1639
|
+
projectHookTrustHeader,
|
|
1640
|
+
'trusted_hash = "sha256:setup-owned"',
|
|
1641
|
+
"",
|
|
1642
|
+
"# End OMX-synced Codex project trust state",
|
|
1643
|
+
"",
|
|
1644
|
+
].join("\n"));
|
|
1645
|
+
assert.throws(() => TOML.parse(readFileSync(projectConfigPath, "utf-8")));
|
|
1646
|
+
await prepareCodexHomeForLaunch(wd, "session-relaunch", {});
|
|
1647
|
+
const repairedProjectConfig = await readFile(projectConfigPath, "utf-8");
|
|
1648
|
+
const runtimeConfig = await readFile(join(runtimeCodexHomePath(wd, "session-relaunch"), "config.toml"), "utf-8");
|
|
1649
|
+
assert.doesNotThrow(() => TOML.parse(repairedProjectConfig));
|
|
1650
|
+
assert.doesNotThrow(() => TOML.parse(runtimeConfig));
|
|
1651
|
+
assert.equal(countMatches(repairedProjectConfig, new RegExp(`^${escapedProjectHookTrustHeader}$`, "gm")), 1);
|
|
1652
|
+
assert.equal(countMatches(runtimeConfig, new RegExp(`^${escapedProjectHookTrustHeader}$`, "gm")), 1);
|
|
1653
|
+
assert.ok(runtimeConfig.includes(`[projects."${wd}"]`));
|
|
1654
|
+
assert.ok(repairedProjectConfig.includes(`[projects."${wd}"]`));
|
|
1655
|
+
}
|
|
1656
|
+
finally {
|
|
1657
|
+
await rm(wd, { recursive: true, force: true });
|
|
1658
|
+
}
|
|
1659
|
+
});
|
|
1660
|
+
it("keeps setup-owned hook trust state targeted at the project hooks path (GH #2470)", async () => {
|
|
1661
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-launch-runtime-hook-trust-"));
|
|
1662
|
+
try {
|
|
1663
|
+
const projectCodexHome = join(wd, ".codex");
|
|
1664
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1665
|
+
await mkdir(projectCodexHome, { recursive: true });
|
|
1666
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project" }));
|
|
1667
|
+
await writeFile(join(projectCodexHome, "hooks.json"), '{"hooks":{}}\n');
|
|
1668
|
+
const projectHookTrustHeader = `[hooks.state."${join(projectCodexHome, "hooks.json")}:pre_tool_use:0:0"]`;
|
|
1669
|
+
await writeFile(join(projectCodexHome, "config.toml"), [
|
|
1670
|
+
"[features]",
|
|
1671
|
+
"hooks = true",
|
|
1672
|
+
"",
|
|
1673
|
+
"# OMX-owned Codex hook trust state",
|
|
1674
|
+
"# Trusts only setup-managed codex-native-hook.js wrappers.",
|
|
1675
|
+
projectHookTrustHeader,
|
|
1676
|
+
'trusted_hash = "sha256:abc"',
|
|
1677
|
+
"# End OMX-owned Codex hook trust state",
|
|
1678
|
+
"",
|
|
1679
|
+
].join("\n"));
|
|
1680
|
+
await prepareCodexHomeForLaunch(wd, "session-trust", {});
|
|
1681
|
+
const runtimeCodexHome = runtimeCodexHomePath(wd, "session-trust");
|
|
1682
|
+
const runtimeConfig = await readFile(join(runtimeCodexHome, "config.toml"), "utf-8");
|
|
1683
|
+
// Runtime CODEX_HOME no longer holds a hooks.json mirror, so the trust
|
|
1684
|
+
// block must continue pointing at the canonical project hooks.json path.
|
|
1685
|
+
assert.equal(existsSync(join(runtimeCodexHome, "hooks.json")), false);
|
|
1686
|
+
assert.ok(runtimeConfig.includes(projectHookTrustHeader), `expected runtime config.toml to keep ${projectHookTrustHeader}`);
|
|
1687
|
+
assert.doesNotMatch(runtimeConfig, new RegExp(join(runtimeCodexHome, "hooks.json").replace(/[.*+?^${}()|[\]\\]/g, "\\$&")));
|
|
1688
|
+
}
|
|
1689
|
+
finally {
|
|
1690
|
+
await rm(wd, { recursive: true, force: true });
|
|
1691
|
+
}
|
|
1692
|
+
});
|
|
1693
|
+
it("uses boxed runtime root for project-scope CODEX_HOME mirrors", async () => {
|
|
1694
|
+
const source = await mkdtemp(join(tmpdir(), "omx-launch-boxed-source-"));
|
|
1695
|
+
const boxedRoot = await mkdtemp(join(tmpdir(), "omx-launch-boxed-root-"));
|
|
1696
|
+
const prevOmxRoot = process.env.OMX_ROOT;
|
|
1697
|
+
try {
|
|
1698
|
+
process.env.OMX_ROOT = boxedRoot;
|
|
1699
|
+
const projectCodexHome = join(source, ".codex");
|
|
1700
|
+
await mkdir(join(source, ".omx"), { recursive: true });
|
|
1701
|
+
await mkdir(projectCodexHome, { recursive: true });
|
|
1702
|
+
await writeFile(join(source, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project" }));
|
|
1703
|
+
await writeFile(join(projectCodexHome, "config.toml"), 'model = "gpt-5.5"\n');
|
|
1704
|
+
const prepared = await prepareCodexHomeForLaunch(source, "session-boxed", {});
|
|
1705
|
+
const runtimeCodexHome = runtimeCodexHomePath(source, "session-boxed");
|
|
1706
|
+
assert.equal(runtimeCodexHome, join(boxedRoot, ".omx", "runtime", "codex-home", "session-boxed"));
|
|
1707
|
+
assert.equal(prepared.codexHomeOverride, runtimeCodexHome);
|
|
1708
|
+
assert.equal(prepared.runtimeCodexHomeForCleanup, runtimeCodexHome);
|
|
1709
|
+
assert.equal(await readFile(join(runtimeCodexHome, "config.toml"), "utf-8"), 'model = "gpt-5.5"\n');
|
|
1710
|
+
}
|
|
1711
|
+
finally {
|
|
1712
|
+
if (typeof prevOmxRoot === "string")
|
|
1713
|
+
process.env.OMX_ROOT = prevOmxRoot;
|
|
1714
|
+
else
|
|
1715
|
+
delete process.env.OMX_ROOT;
|
|
1716
|
+
await rm(source, { recursive: true, force: true });
|
|
1717
|
+
await rm(boxedRoot, { recursive: true, force: true });
|
|
1718
|
+
}
|
|
1719
|
+
});
|
|
1720
|
+
it("keeps explicit CODEX_HOME persistent instead of creating a runtime mirror", async () => {
|
|
1721
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-launch-runtime-codex-home-"));
|
|
1722
|
+
try {
|
|
1723
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1724
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project" }));
|
|
1725
|
+
const prepared = await prepareCodexHomeForLaunch(wd, "session-explicit", {
|
|
1726
|
+
CODEX_HOME: "/tmp/explicit-codex-home",
|
|
1727
|
+
});
|
|
1728
|
+
assert.equal(prepared.codexHomeOverride, "/tmp/explicit-codex-home");
|
|
1729
|
+
assert.equal(prepared.sqliteHomeOverride, undefined);
|
|
1730
|
+
assert.equal(prepared.projectLocalCodexHomeForCleanup, undefined);
|
|
1731
|
+
assert.equal(prepared.runtimeCodexHomeForCleanup, undefined);
|
|
1732
|
+
}
|
|
1733
|
+
finally {
|
|
1734
|
+
await rm(wd, { recursive: true, force: true });
|
|
1735
|
+
}
|
|
1736
|
+
});
|
|
1737
|
+
it("respects explicit CODEX_SQLITE_HOME for project-scope launches", async () => {
|
|
1738
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-launch-sqlite-home-"));
|
|
1739
|
+
try {
|
|
1740
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1741
|
+
await mkdir(join(wd, ".codex"), { recursive: true });
|
|
1742
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project" }));
|
|
1743
|
+
await writeFile(join(wd, ".codex", "config.toml"), 'model = "gpt-5.5"\n');
|
|
1744
|
+
const prepared = await prepareCodexHomeForLaunch(wd, "session-explicit-sqlite", {
|
|
1745
|
+
[CODEX_SQLITE_HOME_ENV]: "/tmp/explicit-sqlite-home",
|
|
1746
|
+
});
|
|
1747
|
+
assert.equal(prepared.codexHomeOverride, runtimeCodexHomePath(wd, "session-explicit-sqlite"));
|
|
1748
|
+
assert.equal(prepared.sqliteHomeOverride, undefined);
|
|
1749
|
+
}
|
|
1750
|
+
finally {
|
|
1751
|
+
await rm(wd, { recursive: true, force: true });
|
|
1752
|
+
}
|
|
1753
|
+
});
|
|
1754
|
+
it("keeps explicit CODEX_HOME override from env", async () => {
|
|
1755
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-launch-scope-"));
|
|
1756
|
+
try {
|
|
1757
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1758
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project" }));
|
|
1759
|
+
assert.equal(resolveCodexHomeForLaunch(wd, {
|
|
1760
|
+
CODEX_HOME: "/tmp/explicit-codex-home",
|
|
1761
|
+
}), "/tmp/explicit-codex-home");
|
|
1762
|
+
}
|
|
1763
|
+
finally {
|
|
1764
|
+
await rm(wd, { recursive: true, force: true });
|
|
1765
|
+
}
|
|
1766
|
+
});
|
|
1767
|
+
it("uses explicit CODEX_HOME config.toml for launch repair overrides", async () => {
|
|
1768
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-launch-scope-"));
|
|
1769
|
+
try {
|
|
1770
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1771
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project" }));
|
|
1772
|
+
assert.equal(resolveCodexConfigPathForLaunch(wd, {
|
|
1773
|
+
CODEX_HOME: "/tmp/explicit-codex-home",
|
|
1774
|
+
}), "/tmp/explicit-codex-home/config.toml");
|
|
1775
|
+
}
|
|
1776
|
+
finally {
|
|
1777
|
+
await rm(wd, { recursive: true, force: true });
|
|
1778
|
+
}
|
|
1779
|
+
});
|
|
1780
|
+
it('migrates legacy "project-local" persisted scope to "project"', async () => {
|
|
1781
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-launch-scope-"));
|
|
1782
|
+
try {
|
|
1783
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1784
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project-local" }));
|
|
1785
|
+
assert.equal(readPersistedSetupScope(wd), "project");
|
|
1786
|
+
}
|
|
1787
|
+
finally {
|
|
1788
|
+
await rm(wd, { recursive: true, force: true });
|
|
1789
|
+
}
|
|
1790
|
+
});
|
|
1791
|
+
it('resolves CODEX_HOME for legacy "project-local" persisted scope', async () => {
|
|
1792
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-launch-scope-"));
|
|
1793
|
+
try {
|
|
1794
|
+
await mkdir(join(wd, ".omx"), { recursive: true });
|
|
1795
|
+
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project-local" }));
|
|
1796
|
+
assert.equal(resolveCodexHomeForLaunch(wd, {}), join(wd, ".codex"));
|
|
1797
|
+
}
|
|
1798
|
+
finally {
|
|
1799
|
+
await rm(wd, { recursive: true, force: true });
|
|
1800
|
+
}
|
|
1801
|
+
});
|
|
1802
|
+
});
|
|
1803
|
+
describe("resolveCodexLaunchPolicy", () => {
|
|
1804
|
+
it("uses detached tmux on macOS when outside tmux and tmux is available", () => {
|
|
1805
|
+
assert.equal(resolveCodexLaunchPolicy({}, "darwin", true, false, true, true), "detached-tmux");
|
|
1806
|
+
});
|
|
1807
|
+
it("uses tmux-aware launch path when already inside tmux", () => {
|
|
1808
|
+
assert.equal(resolveCodexLaunchPolicy({ TMUX: "/tmp/tmux-1000/default,123,0" }, "darwin", true), "inside-tmux");
|
|
1809
|
+
});
|
|
1810
|
+
it("uses tmux-aware launch path when already inside tmux on native Windows", () => {
|
|
1811
|
+
assert.equal(resolveCodexLaunchPolicy({ TMUX: "psmux-session" }, "win32", true, true), "inside-tmux");
|
|
1812
|
+
});
|
|
1813
|
+
it("uses detached tmux on non-macOS hosts when outside tmux and tmux is available", () => {
|
|
1814
|
+
assert.equal(resolveCodexLaunchPolicy({}, "linux", true, false, true, true), "detached-tmux");
|
|
1815
|
+
});
|
|
1816
|
+
it("launches directly on native Windows even when tmux is available", () => {
|
|
1817
|
+
assert.equal(resolveCodexLaunchPolicy({}, "win32", true, true), "direct");
|
|
1818
|
+
});
|
|
1819
|
+
it("does not force direct launch for MSYS or Git Bash on win32", () => {
|
|
1820
|
+
assert.equal(resolveCodexLaunchPolicy({ MSYSTEM: "MINGW64" }, "win32", true, false, true, true), "direct");
|
|
1821
|
+
});
|
|
1822
|
+
it("honors explicit detached tmux launch requests when tmux is available", () => {
|
|
1823
|
+
assert.equal(resolveCodexLaunchPolicy({}, "linux", true, false, true, true, "detached-tmux"), "detached-tmux");
|
|
1824
|
+
});
|
|
1825
|
+
it("honors explicit direct launch requests outside tmux", () => {
|
|
1826
|
+
assert.equal(resolveCodexLaunchPolicy({}, "linux", true, false, true, true, "direct"), "direct");
|
|
1827
|
+
});
|
|
1828
|
+
it("honors explicit direct launch requests inside tmux", () => {
|
|
1829
|
+
assert.equal(resolveCodexLaunchPolicy({ TMUX: "/tmp/tmux-1000/default,123,0" }, "linux", true, false, true, true, "direct"), "direct");
|
|
1830
|
+
});
|
|
1831
|
+
it("keeps explicit tmux policy tmux-aware inside tmux", () => {
|
|
1832
|
+
assert.equal(resolveCodexLaunchPolicy({ TMUX: "/tmp/tmux-1000/default,123,0" }, "linux", true, false, true, true, "detached-tmux"), "inside-tmux");
|
|
1833
|
+
});
|
|
1834
|
+
it("falls back directly for explicit tmux requests when tmux is unavailable", () => {
|
|
1835
|
+
assert.equal(resolveCodexLaunchPolicy({}, "linux", false, false, true, true, "detached-tmux"), "direct");
|
|
1836
|
+
});
|
|
1837
|
+
it("launches directly when stdin is not a tty outside tmux", () => {
|
|
1838
|
+
assert.equal(resolveCodexLaunchPolicy({}, "linux", true, false, false, true), "direct");
|
|
1839
|
+
});
|
|
1840
|
+
it("launches directly when stdout is not a tty outside tmux", () => {
|
|
1841
|
+
assert.equal(resolveCodexLaunchPolicy({}, "linux", true, false, true, false), "direct");
|
|
1842
|
+
});
|
|
1843
|
+
it("launches directly when tmux is unavailable outside tmux", () => {
|
|
1844
|
+
assert.equal(resolveCodexLaunchPolicy({}, "linux", false), "direct");
|
|
1845
|
+
});
|
|
1846
|
+
it("launches directly on native Windows when tmux is unavailable", () => {
|
|
1847
|
+
assert.equal(resolveCodexLaunchPolicy({}, "win32", false, true), "direct");
|
|
1848
|
+
});
|
|
1849
|
+
});
|
|
1850
|
+
describe("resolveBackgroundHelperLaunchMode", () => {
|
|
1851
|
+
it("uses the hidden Windows MSYS bootstrap for win32 Git Bash", () => {
|
|
1852
|
+
assert.equal(resolveBackgroundHelperLaunchMode({ MSYSTEM: "MINGW64" }, "win32"), "windows-msys-bootstrap");
|
|
1853
|
+
});
|
|
1854
|
+
it("spawns helpers directly on native win32", () => {
|
|
1855
|
+
assert.equal(resolveBackgroundHelperLaunchMode({}, "win32"), "direct-detached");
|
|
1856
|
+
});
|
|
1857
|
+
it("spawns helpers directly on non-Windows platforms", () => {
|
|
1858
|
+
assert.equal(resolveBackgroundHelperLaunchMode({ MSYSTEM: "MINGW64" }, "linux"), "direct-detached");
|
|
1859
|
+
});
|
|
1860
|
+
});
|
|
1861
|
+
describe("shouldDetachBackgroundHelper", () => {
|
|
1862
|
+
it("keeps the long-running helper detached under win32 Git Bash", () => {
|
|
1863
|
+
assert.equal(shouldDetachBackgroundHelper({ MSYSTEM: "MINGW64" }, "win32"), true);
|
|
1864
|
+
});
|
|
1865
|
+
it("keeps detached helpers on native win32", () => {
|
|
1866
|
+
assert.equal(shouldDetachBackgroundHelper({}, "win32"), true);
|
|
1867
|
+
});
|
|
1868
|
+
it("keeps detached helpers on non-Windows platforms", () => {
|
|
1869
|
+
assert.equal(shouldDetachBackgroundHelper({ MSYSTEM: "MINGW64" }, "linux"), true);
|
|
1870
|
+
});
|
|
1871
|
+
});
|
|
1872
|
+
describe("classifyCodexExecFailure", () => {
|
|
1873
|
+
it("classifies child process exit status as codex exit", () => {
|
|
1874
|
+
const err = Object.assign(new Error("codex exited 9"), { status: 9 });
|
|
1875
|
+
const classified = classifyCodexExecFailure(err);
|
|
1876
|
+
assert.equal(classified.kind, "exit");
|
|
1877
|
+
assert.equal(classified.exitCode, 9);
|
|
1878
|
+
});
|
|
1879
|
+
it("classifies signal termination as codex exit and maps to signal-based exit code", () => {
|
|
1880
|
+
const err = Object.assign(new Error("terminated"), {
|
|
1881
|
+
status: null,
|
|
1882
|
+
signal: "SIGTERM",
|
|
1883
|
+
});
|
|
1884
|
+
const classified = classifyCodexExecFailure(err);
|
|
1885
|
+
assert.equal(classified.kind, "exit");
|
|
1886
|
+
assert.equal(classified.signal, "SIGTERM");
|
|
1887
|
+
assert.equal(classified.exitCode, resolveSignalExitCode("SIGTERM"));
|
|
1888
|
+
});
|
|
1889
|
+
it("classifies ENOENT as launch error", () => {
|
|
1890
|
+
const err = Object.assign(new Error("spawn codex ENOENT"), {
|
|
1891
|
+
code: "ENOENT",
|
|
1892
|
+
});
|
|
1893
|
+
const classified = classifyCodexExecFailure(err);
|
|
1894
|
+
assert.equal(classified.kind, "launch-error");
|
|
1895
|
+
assert.equal(classified.code, "ENOENT");
|
|
1896
|
+
});
|
|
1897
|
+
});
|
|
1898
|
+
describe("tmux HUD pane helpers", () => {
|
|
1899
|
+
it("findHudWatchPaneIds detects stale HUD watch panes and excludes current pane", () => {
|
|
1900
|
+
const panes = parseTmuxPaneSnapshot([
|
|
1901
|
+
"%1\tzsh\tzsh",
|
|
1902
|
+
"%2\tnode\tnode /tmp/bin/omx.js hud --watch",
|
|
1903
|
+
"%3\tnode\tnode /tmp/bin/omx.js hud --watch",
|
|
1904
|
+
"%4\tcodex\tcodex --model gpt-5",
|
|
1905
|
+
].join("\n"));
|
|
1906
|
+
assert.deepEqual(findHudWatchPaneIds(panes, "%2"), ["%3"]);
|
|
1907
|
+
});
|
|
1908
|
+
it("buildHudPaneCleanupTargets de-dupes pane ids and includes created pane", () => {
|
|
1909
|
+
assert.deepEqual(buildHudPaneCleanupTargets(["%3", "%3", "invalid"], "%4"), ["%3", "%4"]);
|
|
1910
|
+
});
|
|
1911
|
+
it("buildHudPaneCleanupTargets excludes leader pane from existing ids", () => {
|
|
1912
|
+
// %5 is the leader pane — it must not be included even if findHudWatchPaneIds let it through.
|
|
1913
|
+
assert.deepEqual(buildHudPaneCleanupTargets(["%3", "%5"], "%4", "%5"), [
|
|
1914
|
+
"%3",
|
|
1915
|
+
"%4",
|
|
1916
|
+
]);
|
|
1917
|
+
});
|
|
1918
|
+
it("buildHudPaneCleanupTargets excludes leader pane even when it matches the created HUD pane id", () => {
|
|
1919
|
+
// Defensive edge case: if createHudWatchPane somehow returned the leader pane id, guard protects it.
|
|
1920
|
+
assert.deepEqual(buildHudPaneCleanupTargets(["%3"], "%5", "%5"), ["%3"]);
|
|
1921
|
+
});
|
|
1922
|
+
it("buildHudPaneCleanupTargets is a no-op guard when leaderPaneId is absent", () => {
|
|
1923
|
+
assert.deepEqual(buildHudPaneCleanupTargets(["%3"], "%4"), ["%3", "%4"]);
|
|
1924
|
+
});
|
|
1925
|
+
it("listCurrentWindowHudPaneIds scopes tmux pane listing to the emitting pane", () => {
|
|
1926
|
+
const calls = [];
|
|
1927
|
+
const panes = listCurrentWindowHudPaneIds("%leader", (args) => {
|
|
1928
|
+
calls.push(args);
|
|
1929
|
+
return [
|
|
1930
|
+
"%leader\tcodex\tcodex",
|
|
1931
|
+
"%hud\tnode\tnode /tmp/bin/omx.js hud --watch",
|
|
1932
|
+
].join("\n");
|
|
1933
|
+
});
|
|
1934
|
+
assert.deepEqual(panes, ["%hud"]);
|
|
1935
|
+
assert.deepEqual(calls[0], [
|
|
1936
|
+
"list-panes",
|
|
1937
|
+
"-t",
|
|
1938
|
+
"%leader",
|
|
1939
|
+
"-F",
|
|
1940
|
+
[
|
|
1941
|
+
"#{pane_id}",
|
|
1942
|
+
"#{pane_current_command}",
|
|
1943
|
+
"#{pane_left}",
|
|
1944
|
+
"#{pane_top}",
|
|
1945
|
+
"#{pane_width}",
|
|
1946
|
+
"#{pane_height}",
|
|
1947
|
+
"#{pane_bottom}",
|
|
1948
|
+
"#{window_width}",
|
|
1949
|
+
"#{window_height}",
|
|
1950
|
+
"#{pane_start_command}",
|
|
1951
|
+
"#{pane_current_path}",
|
|
1952
|
+
].join("\x1f"),
|
|
1953
|
+
]);
|
|
1954
|
+
});
|
|
1955
|
+
it("createHudWatchPane splits from the emitting pane target when provided", () => {
|
|
1956
|
+
const calls = [];
|
|
1957
|
+
const paneId = createSharedHudWatchPane("/repo", "node /repo/dist/cli/omx.js hud --watch", { heightLines: 3, targetPaneId: "%leader" }, (args) => {
|
|
1958
|
+
calls.push(args);
|
|
1959
|
+
return "%hud\n";
|
|
1960
|
+
});
|
|
1961
|
+
assert.equal(paneId, "%hud");
|
|
1962
|
+
assert.deepEqual(calls[0], [
|
|
1963
|
+
"split-window",
|
|
1964
|
+
"-v",
|
|
1965
|
+
"-l",
|
|
1966
|
+
"3",
|
|
1967
|
+
"-d",
|
|
1968
|
+
"-t",
|
|
1969
|
+
"%leader",
|
|
1970
|
+
"-c",
|
|
1971
|
+
"/repo",
|
|
1972
|
+
"-P",
|
|
1973
|
+
"-F",
|
|
1974
|
+
"#{pane_id}",
|
|
1975
|
+
"node /repo/dist/cli/omx.js hud --watch",
|
|
1976
|
+
]);
|
|
1977
|
+
});
|
|
1978
|
+
});
|
|
1979
|
+
describe("detached tmux new-session sequencing", () => {
|
|
1980
|
+
it("buildDetachedSessionBootstrapSteps uses shared HUD height and split-capture ordering", () => {
|
|
1981
|
+
const steps = buildDetachedSessionBootstrapSteps("omx-demo", "/tmp/project", "'codex' '--model' 'gpt-5'", "'node' '/tmp/omx.js' 'hud' '--watch'", "--model gpt-5", "/tmp/codex-home", '{"active":true}', false, "omx-session-test");
|
|
1982
|
+
assert.deepEqual(steps.map((step) => step.name), ["new-session", "tag-session", "split-and-capture-hud-pane"]);
|
|
1983
|
+
const splitStep = steps.find((step) => step.name === "split-and-capture-hud-pane");
|
|
1984
|
+
assert.ok(splitStep);
|
|
1985
|
+
assert.equal(splitStep.args[3], String(HUD_TMUX_HEIGHT_LINES));
|
|
1986
|
+
assert.equal(splitStep.args[6], "omx-demo");
|
|
1987
|
+
assert.equal(splitStep.args.includes("-P"), true);
|
|
1988
|
+
assert.equal(splitStep.args.includes("#{pane_id}"), true);
|
|
1989
|
+
assert.equal(steps[0]?.args.includes("-e"), true);
|
|
1990
|
+
assert.equal(steps[0]?.args.includes("OMX_SESSION_ID=omx-session-test"), true);
|
|
1991
|
+
assert.equal(steps[0]?.args.includes('OMX_NOTIFY_TEMP_CONTRACT={\"active\":true}'), true);
|
|
1992
|
+
});
|
|
1993
|
+
it("buildDetachedSessionBootstrapSteps forwards temp contract env to detached tmux session", () => {
|
|
1994
|
+
const steps = buildDetachedSessionBootstrapSteps("omx-demo", "/tmp/project", "'codex' '--model' 'gpt-5'", "'node' '/tmp/omx.js' 'hud' '--watch'", null, undefined, '{"active":true,"canonicalSelectors":["discord"]}');
|
|
1995
|
+
const newSession = steps.find((step) => step.name === "new-session");
|
|
1996
|
+
assert.ok(newSession);
|
|
1997
|
+
assert.equal(newSession.args.includes("-e") &&
|
|
1998
|
+
newSession.args.some((arg) => arg.startsWith("OMX_NOTIFY_TEMP_CONTRACT=")), true);
|
|
1999
|
+
});
|
|
2000
|
+
it("buildDetachedSessionBootstrapSteps forwards OMX_SESSION_ID to detached tmux session", () => {
|
|
2001
|
+
const steps = buildDetachedSessionBootstrapSteps("omx-demo", "/tmp/project", "'env' 'OMX_SESSION_ID=sess-detached-managed' 'codex' '--model' 'gpt-5'", "'node' '/tmp/omx.js' 'hud' '--watch'", null, undefined, null, false, "sess-detached-managed");
|
|
2002
|
+
const newSession = steps.find((step) => step.name === "new-session");
|
|
2003
|
+
const tagSession = steps.find((step) => step.name === "tag-session");
|
|
2004
|
+
assert.ok(newSession);
|
|
2005
|
+
assert.ok(tagSession);
|
|
2006
|
+
assert.equal(newSession.args.includes("-e") &&
|
|
2007
|
+
newSession.args.some((arg) => arg === "OMX_SESSION_ID=sess-detached-managed"), true);
|
|
2008
|
+
assert.equal(newSession.args.some((arg) => arg === "OMX_TMUX_HUD_OWNER=1"), true);
|
|
2009
|
+
assert.deepEqual(tagSession.args, [
|
|
2010
|
+
"set-option",
|
|
2011
|
+
"-t",
|
|
2012
|
+
"omx-demo",
|
|
2013
|
+
"@omx_instance_id",
|
|
2014
|
+
"sess-detached-managed",
|
|
2015
|
+
]);
|
|
2016
|
+
});
|
|
2017
|
+
it("buildDetachedSessionBootstrapSteps forwards CODEX_HOME override to detached tmux session", () => {
|
|
2018
|
+
const steps = buildDetachedSessionBootstrapSteps("omx-demo", "/tmp/project", "'codex' '--model' 'gpt-5'", "'node' '/tmp/omx.js' 'hud' '--watch'", null, "/tmp/project/.codex", null, false, "sess-detached-managed");
|
|
2019
|
+
const newSession = steps.find((step) => step.name === "new-session");
|
|
2020
|
+
assert.ok(newSession);
|
|
2021
|
+
assert.equal(newSession.args.includes("-e") &&
|
|
2022
|
+
newSession.args.some((arg) => arg === "CODEX_HOME=/tmp/project/.codex"), true);
|
|
2023
|
+
});
|
|
2024
|
+
it("buildDetachedSessionBootstrapSteps forwards CODEX_SQLITE_HOME override to detached tmux session", () => {
|
|
2025
|
+
const steps = buildDetachedSessionBootstrapSteps("omx-demo", "/tmp/project", "'codex' '--model' 'gpt-5'", "'node' '/tmp/omx.js' 'hud' '--watch'", null, "/tmp/project/.omx/runtime/codex-home/session-1", null, false, "sess-detached-managed", undefined, undefined, undefined, {}, "/tmp/project/.codex");
|
|
2026
|
+
const newSession = steps.find((step) => step.name === "new-session");
|
|
2027
|
+
assert.ok(newSession);
|
|
2028
|
+
assert.equal(newSession.args.includes("-e") &&
|
|
2029
|
+
newSession.args.some((arg) => arg === `${CODEX_SQLITE_HOME_ENV}=/tmp/project/.codex`), true);
|
|
2030
|
+
});
|
|
2031
|
+
it("buildDetachedSessionBootstrapSteps forwards OMX_ROOT override to detached tmux session", () => {
|
|
2032
|
+
const steps = buildDetachedSessionBootstrapSteps("omx-demo", "/tmp/project", "'codex' '--model' 'gpt-5'", "'node' '/tmp/omx.js' 'hud' '--watch'", null, undefined, null, false, "sess-detached-managed", undefined, undefined, "/tmp/omx-root");
|
|
2033
|
+
const newSession = steps.find((step) => step.name === "new-session");
|
|
2034
|
+
assert.ok(newSession);
|
|
2035
|
+
assert.equal(newSession.args.includes("-e") &&
|
|
2036
|
+
newSession.args.some((arg) => arg === "OMX_ROOT=/tmp/omx-root"), true);
|
|
2037
|
+
});
|
|
2038
|
+
it("buildDetachedSessionBootstrapSteps forwards boxed env to detached tmux session", () => {
|
|
2039
|
+
const steps = buildDetachedSessionBootstrapSteps("omx-demo", "/tmp/boxed-runtime", "'codex' '--model' 'gpt-5'", "'node' '/tmp/omx.js' 'hud' '--watch'", null, undefined, null, false, "sess-detached-managed", undefined, undefined, "/tmp/boxed-runtime", {
|
|
2040
|
+
OMXBOX_ACTIVE: "1",
|
|
2041
|
+
OMX_SOURCE_CWD: "/tmp/source-project",
|
|
2042
|
+
OMX_STATE_ROOT: "/tmp/boxed-state-root",
|
|
2043
|
+
});
|
|
2044
|
+
const newSession = steps.find((step) => step.name === "new-session");
|
|
2045
|
+
assert.ok(newSession);
|
|
2046
|
+
assert.equal(newSession.args.some((arg) => arg === "OMX_ROOT=/tmp/boxed-runtime"), true);
|
|
2047
|
+
assert.equal(newSession.args.some((arg) => arg === "OMX_STATE_ROOT=/tmp/boxed-state-root"), false);
|
|
2048
|
+
assert.equal(newSession.args.some((arg) => arg === "OMX_TMUX_HUD_OWNER=1"), true);
|
|
2049
|
+
assert.equal(newSession.args.some((arg) => arg === "OMXBOX_ACTIVE=1"), true);
|
|
2050
|
+
assert.equal(newSession.args.some((arg) => arg === "OMX_SOURCE_CWD=/tmp/source-project"), true);
|
|
2051
|
+
});
|
|
2052
|
+
it("buildDetachedSessionBootstrapSteps preserves OMX_STATE_ROOT identity when no root override is explicit", () => {
|
|
2053
|
+
const steps = buildDetachedSessionBootstrapSteps("omx-demo", "/tmp/project", "'codex' '--model' 'gpt-5'", "'node' '/tmp/omx.js' 'hud' '--watch'", null, undefined, null, false, "sess-detached-managed", undefined, undefined, "/tmp/state-root", { OMX_STATE_ROOT: "/tmp/state-root" });
|
|
2054
|
+
const newSession = steps.find((step) => step.name === "new-session");
|
|
2055
|
+
assert.ok(newSession);
|
|
2056
|
+
assert.equal(newSession.args.some((arg) => arg === "OMX_STATE_ROOT=/tmp/state-root"), true);
|
|
2057
|
+
assert.equal(newSession.args.some((arg) => arg === "OMX_ROOT=/tmp/state-root"), false);
|
|
2058
|
+
});
|
|
2059
|
+
it("buildDetachedSessionBootstrapSteps preserves OMX_ROOT precedence over OMX_STATE_ROOT", () => {
|
|
2060
|
+
const steps = buildDetachedSessionBootstrapSteps("omx-demo", "/tmp/project", "'codex' '--model' 'gpt-5'", "'node' '/tmp/omx.js' 'hud' '--watch'", null, undefined, null, false, "sess-detached-managed", undefined, undefined, "/tmp/root-from-omx-root", { OMX_STATE_ROOT: "/tmp/state-root-should-not-win" });
|
|
2061
|
+
const newSession = steps.find((step) => step.name === "new-session");
|
|
2062
|
+
assert.ok(newSession);
|
|
2063
|
+
assert.equal(newSession.args.some((arg) => arg === "OMX_ROOT=/tmp/root-from-omx-root"), true);
|
|
2064
|
+
assert.equal(newSession.args.some((arg) => arg === "OMX_STATE_ROOT=/tmp/state-root-should-not-win"), false);
|
|
2065
|
+
});
|
|
2066
|
+
it("buildDetachedSessionBootstrapSteps preserves OMX_TEAM_STATE_ROOT over explicit root env", () => {
|
|
2067
|
+
const steps = buildDetachedSessionBootstrapSteps("omx-demo", "/tmp/project", "'codex' '--model' 'gpt-5'", "'node' '/tmp/omx.js' 'hud' '--watch'", null, undefined, null, false, "sess-detached-managed", undefined, undefined, "/tmp/root-from-omx-root", { OMX_ROOT: "/tmp/root-from-omx-root", OMX_TEAM_STATE_ROOT: "/tmp/team-state-root" });
|
|
2068
|
+
const newSession = steps.find((step) => step.name === "new-session");
|
|
2069
|
+
assert.ok(newSession);
|
|
2070
|
+
assert.equal(newSession.args.some((arg) => arg === "OMX_TEAM_STATE_ROOT=/tmp/team-state-root"), true);
|
|
2071
|
+
assert.equal(newSession.args.some((arg) => arg === "OMX_ROOT=/tmp/root-from-omx-root"), false);
|
|
2072
|
+
});
|
|
2073
|
+
it("serializes custom parent env for the interactive detached tmux leader without logging values in tmux args", () => {
|
|
2074
|
+
const envFilePath = "/tmp/omx-runtime/tmux-env/sess.env";
|
|
2075
|
+
const steps = buildDetachedSessionBootstrapSteps("omx-demo", "/tmp/project", "'codex' '--model' 'gpt-5'", "'node' '/tmp/omx.js' 'hud' '--watch'", null, undefined, null, false, "sess-detached-managed", undefined, undefined, undefined, { CUSTOM_LLM_API_KEY: "fake-provider-key", IS_GAJAE_SLOP_GENERATOR: "1" }, undefined, envFilePath);
|
|
2076
|
+
const newSession = steps.find((step) => step.name === "new-session");
|
|
2077
|
+
assert.ok(newSession);
|
|
2078
|
+
const argsText = newSession.args.join("\n");
|
|
2079
|
+
assert.match(argsText, new RegExp(envFilePath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")));
|
|
2080
|
+
assert.doesNotMatch(argsText, /fake-provider-key/);
|
|
2081
|
+
assert.doesNotMatch(argsText, /CUSTOM_LLM_API_KEY=/);
|
|
2082
|
+
const envScript = serializeDetachedSessionParentEnv({
|
|
2083
|
+
CUSTOM_LLM_API_KEY: "fake-provider-key",
|
|
2084
|
+
IS_GAJAE_SLOP_GENERATOR: "1",
|
|
2085
|
+
"not-a-shell-name": "ignored",
|
|
2086
|
+
});
|
|
2087
|
+
assert.match(envScript, /export CUSTOM_LLM_API_KEY='fake-provider-key'/);
|
|
2088
|
+
assert.match(envScript, /export IS_GAJAE_SLOP_GENERATOR='1'/);
|
|
2089
|
+
assert.doesNotMatch(envScript, /not-a-shell-name/);
|
|
2090
|
+
});
|
|
2091
|
+
it("creates a repo-local omx command shim for launched Codex sessions", async () => {
|
|
2092
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-runtime-command-shim-"));
|
|
2093
|
+
try {
|
|
2094
|
+
const shimDir = ensureOmxRuntimeCommandShim(cwd, "/repo/dist/cli/omx.js", "/usr/local/bin/node");
|
|
2095
|
+
const shimPath = omxRuntimeCommandShimPath(cwd);
|
|
2096
|
+
assert.equal(shimDir, dirname(shimPath));
|
|
2097
|
+
assert.equal(existsSync(shimPath), true);
|
|
2098
|
+
assert.equal(await readFile(shimPath, "utf-8"), [
|
|
2099
|
+
"#!/bin/sh",
|
|
2100
|
+
`exec '/usr/local/bin/node' '/repo/dist/cli/omx.js' "$@"`,
|
|
2101
|
+
"",
|
|
2102
|
+
].join("\n"));
|
|
2103
|
+
assert.equal((await stat(shimPath)).mode & 0o700, 0o700);
|
|
2104
|
+
}
|
|
2105
|
+
finally {
|
|
2106
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2107
|
+
}
|
|
2108
|
+
});
|
|
2109
|
+
it("prepends the repo-local omx shim before global PATH entries", async () => {
|
|
2110
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-runtime-command-shim-env-"));
|
|
2111
|
+
try {
|
|
2112
|
+
const env = prependOmxRuntimeCommandShimToEnv(cwd, {
|
|
2113
|
+
PATH: "/opt/homebrew/bin:/usr/bin",
|
|
2114
|
+
OMX_ENTRY_PATH: "/opt/homebrew/lib/node_modules/oh-my-codex/dist/cli/omx.js",
|
|
2115
|
+
}, "/repo/dist/cli/omx.js", "/usr/local/bin/node");
|
|
2116
|
+
const shimDir = dirname(omxRuntimeCommandShimPath(cwd));
|
|
2117
|
+
assert.equal(env.PATH, `${shimDir}${delimiter}/opt/homebrew/bin:/usr/bin`);
|
|
2118
|
+
assert.equal(env.OMX_ENTRY_PATH, "/repo/dist/cli/omx.js");
|
|
2119
|
+
assert.equal(env.OMX_STARTUP_CWD, cwd);
|
|
2120
|
+
}
|
|
2121
|
+
finally {
|
|
2122
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2123
|
+
}
|
|
2124
|
+
});
|
|
2125
|
+
it("executes the repo-local omx shim before a stale global omx with misleading success output", async () => {
|
|
2126
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-runtime-command-shim-exec-"));
|
|
2127
|
+
try {
|
|
2128
|
+
const fakeGlobalBin = join(cwd, "fake-global-bin");
|
|
2129
|
+
const fakeLocalBin = join(cwd, "fake local's $() ; bin");
|
|
2130
|
+
await mkdir(fakeGlobalBin);
|
|
2131
|
+
await mkdir(fakeLocalBin);
|
|
2132
|
+
const globalMarker = join(cwd, "GLOBAL_CALLED");
|
|
2133
|
+
const localMarker = join(cwd, "LOCAL_CALLED");
|
|
2134
|
+
const fakeGlobalOmx = join(fakeGlobalBin, "omx");
|
|
2135
|
+
const fakeNode = join(fakeLocalBin, "node runner");
|
|
2136
|
+
const localOmxEntry = join(fakeLocalBin, "omx entry's $() ;.js");
|
|
2137
|
+
await writeFile(fakeGlobalOmx, `#!/bin/sh
|
|
2138
|
+
printf 'global-called\\n' > "${globalMarker}"
|
|
2139
|
+
printf '{"success":true,"source":"global"}\\n'
|
|
2140
|
+
exit 0
|
|
2141
|
+
`);
|
|
2142
|
+
await chmod(fakeGlobalOmx, 0o755);
|
|
2143
|
+
await writeFile(fakeNode, `#!/bin/sh
|
|
2144
|
+
printf '%s\\n' "$@" > "${localMarker}"
|
|
2145
|
+
printf '{"success":true,"source":"local"}\\n'
|
|
2146
|
+
exit 0
|
|
2147
|
+
`);
|
|
2148
|
+
await chmod(fakeNode, 0o755);
|
|
2149
|
+
const env = prependOmxRuntimeCommandShimToEnv(cwd, { PATH: `${fakeGlobalBin}${delimiter}/usr/bin:/bin` }, localOmxEntry, fakeNode);
|
|
2150
|
+
const { execFileSync } = await import("node:child_process");
|
|
2151
|
+
const output = execFileSync("omx", ["team", "status", "hud-check"], {
|
|
2152
|
+
cwd,
|
|
2153
|
+
env,
|
|
2154
|
+
encoding: "utf-8",
|
|
2155
|
+
});
|
|
2156
|
+
assert.match(output, /"source":"local"/);
|
|
2157
|
+
assert.equal(existsSync(globalMarker), false);
|
|
2158
|
+
assert.deepEqual((await readFile(localMarker, "utf-8")).trim().split("\n"), [
|
|
2159
|
+
localOmxEntry,
|
|
2160
|
+
"team",
|
|
2161
|
+
"status",
|
|
2162
|
+
"hud-check",
|
|
2163
|
+
]);
|
|
2164
|
+
}
|
|
2165
|
+
finally {
|
|
2166
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2167
|
+
}
|
|
2168
|
+
});
|
|
2169
|
+
it("overwrites stale runtime shim contents and permissions", async () => {
|
|
2170
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-runtime-command-shim-stale-"));
|
|
2171
|
+
try {
|
|
2172
|
+
const shimPath = omxRuntimeCommandShimPath(cwd);
|
|
2173
|
+
await mkdir(dirname(shimPath), { recursive: true });
|
|
2174
|
+
await writeFile(shimPath, "#!/bin/sh\necho stale-global\n");
|
|
2175
|
+
await chmod(shimPath, 0o600);
|
|
2176
|
+
ensureOmxRuntimeCommandShim(cwd, "/repo/dist/cli/omx.js", "/usr/local/bin/node");
|
|
2177
|
+
assert.equal(await readFile(shimPath, "utf-8"), [
|
|
2178
|
+
"#!/bin/sh",
|
|
2179
|
+
`exec '/usr/local/bin/node' '/repo/dist/cli/omx.js' "$@"`,
|
|
2180
|
+
"",
|
|
2181
|
+
].join("\n"));
|
|
2182
|
+
assert.equal((await stat(shimPath)).mode & 0o777, 0o700);
|
|
2183
|
+
}
|
|
2184
|
+
finally {
|
|
2185
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2186
|
+
}
|
|
2187
|
+
});
|
|
2188
|
+
it("replaces a stale runtime shim symlink without following it", async () => {
|
|
2189
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-runtime-command-shim-symlink-"));
|
|
2190
|
+
try {
|
|
2191
|
+
if (process.platform === "win32")
|
|
2192
|
+
return;
|
|
2193
|
+
const shimPath = omxRuntimeCommandShimPath(cwd);
|
|
2194
|
+
const externalTarget = join(cwd, "outside-target");
|
|
2195
|
+
await mkdir(dirname(shimPath), { recursive: true });
|
|
2196
|
+
await writeFile(externalTarget, "do not overwrite\n");
|
|
2197
|
+
await symlink(externalTarget, shimPath);
|
|
2198
|
+
ensureOmxRuntimeCommandShim(cwd, "/repo/dist/cli/omx.js", "/usr/local/bin/node");
|
|
2199
|
+
assert.equal(await readFile(externalTarget, "utf-8"), "do not overwrite\n");
|
|
2200
|
+
assert.equal((await lstat(shimPath)).isSymbolicLink(), false);
|
|
2201
|
+
assert.match(await readFile(shimPath, "utf-8"), /\/repo\/dist\/cli\/omx\.js/);
|
|
2202
|
+
}
|
|
2203
|
+
finally {
|
|
2204
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2205
|
+
}
|
|
2206
|
+
});
|
|
2207
|
+
it("throws when the runtime shim bin path is not a directory", async () => {
|
|
2208
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-runtime-command-shim-file-"));
|
|
2209
|
+
try {
|
|
2210
|
+
const shimPath = omxRuntimeCommandShimPath(cwd);
|
|
2211
|
+
await mkdir(dirname(dirname(shimPath)), { recursive: true });
|
|
2212
|
+
await writeFile(dirname(shimPath), "not a directory\n");
|
|
2213
|
+
assert.throws(() => ensureOmxRuntimeCommandShim(cwd, "/repo/dist/cli/omx.js", "/usr/local/bin/node"), /not a directory/);
|
|
2214
|
+
}
|
|
2215
|
+
finally {
|
|
2216
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2217
|
+
}
|
|
2218
|
+
});
|
|
2219
|
+
it("creates a Windows omx.cmd runtime shim with cmd batch content on win32", async () => {
|
|
2220
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-runtime-command-shim-win-"));
|
|
2221
|
+
try {
|
|
2222
|
+
const shimDir = ensureOmxRuntimeCommandShim(cwd, "C:\\repo\\dist\\cli\\omx.js", "C:\\Program Files\\nodejs\\node.exe", "win32");
|
|
2223
|
+
const shimPath = omxRuntimeCommandShimPath(cwd, "win32");
|
|
2224
|
+
assert.equal(shimDir, dirname(shimPath));
|
|
2225
|
+
assert.equal(shimPath.endsWith("omx.cmd"), true);
|
|
2226
|
+
assert.equal(existsSync(shimPath), true);
|
|
2227
|
+
assert.equal(await readFile(shimPath, "utf-8"), [
|
|
2228
|
+
"@echo off",
|
|
2229
|
+
`"C:\\Program Files\\nodejs\\node.exe" "C:\\repo\\dist\\cli\\omx.js" %*`,
|
|
2230
|
+
"",
|
|
2231
|
+
].join("\r\n"));
|
|
2232
|
+
}
|
|
2233
|
+
finally {
|
|
2234
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2235
|
+
}
|
|
2236
|
+
});
|
|
2237
|
+
it("preserves an inherited Windows Path key when prepending the shim dir", async () => {
|
|
2238
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-runtime-command-shim-winpath-"));
|
|
2239
|
+
try {
|
|
2240
|
+
const env = prependOmxRuntimeCommandShimToEnv(cwd, { Path: "C:\\Windows\\System32;C:\\Windows" }, "C:\\repo\\dist\\cli\\omx.js", "C:\\Program Files\\nodejs\\node.exe", "win32");
|
|
2241
|
+
const shimDir = dirname(omxRuntimeCommandShimPath(cwd, "win32"));
|
|
2242
|
+
assert.equal(env.Path, `${shimDir};C:\\Windows\\System32;C:\\Windows`);
|
|
2243
|
+
assert.equal(env.PATH, undefined);
|
|
2244
|
+
assert.equal(env.OMX_ENTRY_PATH, "C:\\repo\\dist\\cli\\omx.js");
|
|
2245
|
+
assert.equal(env.OMX_STARTUP_CWD, cwd);
|
|
2246
|
+
}
|
|
2247
|
+
finally {
|
|
2248
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2249
|
+
}
|
|
2250
|
+
});
|
|
2251
|
+
it("collapses duplicate Windows PATH/Path variants to a single Path key", async () => {
|
|
2252
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-runtime-command-shim-windup-"));
|
|
2253
|
+
try {
|
|
2254
|
+
const env = prependOmxRuntimeCommandShimToEnv(cwd, { PATH: "", Path: "C:\\Windows\\System32" }, "C:\\repo\\dist\\cli\\omx.js", "C:\\Program Files\\nodejs\\node.exe", "win32");
|
|
2255
|
+
const shimDir = dirname(omxRuntimeCommandShimPath(cwd, "win32"));
|
|
2256
|
+
const pathKeys = Object.keys(env).filter((key) => key.toLowerCase() === "path");
|
|
2257
|
+
assert.deepEqual(pathKeys, ["Path"]);
|
|
2258
|
+
assert.equal(env.Path, `${shimDir};C:\\Windows\\System32`);
|
|
2259
|
+
}
|
|
2260
|
+
finally {
|
|
2261
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2262
|
+
}
|
|
2263
|
+
});
|
|
2264
|
+
it("seeds a Windows Path entry from the shim dir when none is inherited", async () => {
|
|
2265
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-runtime-command-shim-winempty-"));
|
|
2266
|
+
try {
|
|
2267
|
+
const env = prependOmxRuntimeCommandShimToEnv(cwd, {}, "C:\\repo\\dist\\cli\\omx.js", "C:\\Program Files\\nodejs\\node.exe", "win32");
|
|
2268
|
+
const shimDir = dirname(omxRuntimeCommandShimPath(cwd, "win32"));
|
|
2269
|
+
assert.equal(env.Path, shimDir);
|
|
2270
|
+
assert.equal(env.PATH, undefined);
|
|
2271
|
+
}
|
|
2272
|
+
finally {
|
|
2273
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2274
|
+
}
|
|
2275
|
+
});
|
|
2276
|
+
it("keeps detached tmux bootstrap bounded when no interactive parent env file is requested", () => {
|
|
2277
|
+
const steps = buildDetachedSessionBootstrapSteps("omx-demo", "/tmp/project", "'codex' '--model' 'gpt-5'", "'node' '/tmp/omx.js' 'hud' '--watch'", null, undefined, null, false, "sess-detached-managed", undefined, undefined, undefined, { CUSTOM_LLM_API_KEY: "fake-provider-key" });
|
|
2278
|
+
const newSession = steps.find((step) => step.name === "new-session");
|
|
2279
|
+
assert.ok(newSession);
|
|
2280
|
+
const argsText = newSession.args.join("\n");
|
|
2281
|
+
assert.doesNotMatch(argsText, /CUSTOM_LLM_API_KEY/);
|
|
2282
|
+
assert.doesNotMatch(argsText, /fake-provider-key/);
|
|
2283
|
+
});
|
|
2284
|
+
it("runCodex cleans only same-session same-leader HUD panes before launch", async () => {
|
|
2285
|
+
const source = await readFile(join(repoRoot, "src", "cli", "index.ts"), "utf8");
|
|
2286
|
+
assert.match(source, /const staleHudPaneIds = currentPaneId\s*\? listHudWatchPaneIdsInCurrentWindow\(currentPaneId, \{ sessionId, leaderPaneId: currentPaneId \}\)\s*: \[\];/);
|
|
2287
|
+
assert.match(source, /const \[keeperHudPaneId, \.\.\.duplicateHudPaneIds\] = staleHudPaneIds;/);
|
|
2288
|
+
assert.match(source, /for \(const paneId of duplicateHudPaneIds\) \{\s*killTmuxPane\(paneId\);\s*\}/);
|
|
2289
|
+
assert.match(source, /if \(keeperHudPaneId\) \{\s*hudPaneId = keeperHudPaneId;/);
|
|
2290
|
+
assert.doesNotMatch(source, /const staleHudPaneIds = listHudWatchPaneIdsInCurrentWindow\(currentPaneId, \{ leaderPaneId: currentPaneId \}\);/);
|
|
2291
|
+
});
|
|
2292
|
+
it("runCodex skips launch-time HUD cleanup when TMUX_PANE is unavailable", async () => {
|
|
2293
|
+
const source = await readFile(join(repoRoot, "src", "cli", "index.ts"), "utf8");
|
|
2294
|
+
assert.match(source, /const staleHudPaneIds = currentPaneId\s*\? listHudWatchPaneIdsInCurrentWindow\(currentPaneId, \{ sessionId, leaderPaneId: currentPaneId \}\)\s*: \[\];/);
|
|
2295
|
+
});
|
|
2296
|
+
it("runCodex builds inside-tmux HUD command through explicit runtime-root resolver", async () => {
|
|
2297
|
+
const source = await readFile(join(repoRoot, 'src', 'cli', 'index.ts'), 'utf-8');
|
|
2298
|
+
assert.match(source, /const hudRuntimeRoot = resolveHudRuntimeRootForLaunch\(cwd, process\.env\);/);
|
|
2299
|
+
assert.match(source, /const hudEnvArgs = Object\.entries\(buildHudRuntimeEnv\(\{\s*sessionId,\s*leaderPaneId: currentPaneId,\s*\.\.\.hudRuntimeRoot,\s*\}\)\.env\)\.map\(\(\[key, value\]\) => `\$\{key\}=\$\{value\}`\)/);
|
|
2300
|
+
assert.match(source, /if \(env\.OMX_TEAM_STATE_ROOT\?\.trim\(\)\) return 'team-env';\s*if \(env\.OMX_ROOT\?\.trim\(\) \|\| omxRootOverride\) return 'omx-root-env';\s*if \(env\.OMX_STATE_ROOT\?\.trim\(\)\) return 'omx-state-root-env';/);
|
|
2301
|
+
assert.match(source, /buildTmuxPaneCommand\("env",\s*\[\.\.\.hudEnvArgs,\s*"node",\s*omxBin,\s*"hud",\s*"--watch"\]\)/);
|
|
2302
|
+
});
|
|
2303
|
+
it("runCodex registers a HUD resize hook immediately for inside-tmux launches", async () => {
|
|
2304
|
+
const source = await readFile(join(repoRoot, 'src', 'cli', 'index.ts'), 'utf-8');
|
|
2305
|
+
assert.match(source, /registerInsideTmuxHudResizeHook\(\{\s*hudPaneId,\s*currentPaneId,\s*cwd,\s*sessionId,\s*omxRootOverride,\s*\}\)/);
|
|
2306
|
+
assert.match(source, /if \(currentPaneId\) \{\s*unregisterHudResizeHook\(currentPaneId\);\s*\}/);
|
|
2307
|
+
});
|
|
2308
|
+
it("buildInsideTmuxHudHookEnv tags hook commands with session, owner, leader, and local root", () => {
|
|
2309
|
+
const env = buildInsideTmuxHudHookEnv({ PATH: "/bin" }, "sess-a", "%leader", "/repo");
|
|
2310
|
+
assert.equal(env.PATH, "/bin");
|
|
2311
|
+
assert.equal(env.OMX_SESSION_ID, "sess-a");
|
|
2312
|
+
assert.equal(env.OMX_TMUX_HUD_OWNER, "1");
|
|
2313
|
+
assert.equal(env.OMX_TMUX_HUD_LEADER_PANE, "%leader");
|
|
2314
|
+
assert.equal(env.OMX_ROOT, "/repo");
|
|
2315
|
+
});
|
|
2316
|
+
it("registerInsideTmuxHudResizeHook forwards cwd and env to hook registration", () => {
|
|
2317
|
+
const calls = [];
|
|
2318
|
+
const result = registerInsideTmuxHudResizeHook({
|
|
2319
|
+
hudPaneId: "%hud",
|
|
2320
|
+
currentPaneId: "%leader",
|
|
2321
|
+
cwd: "/repo",
|
|
2322
|
+
sessionId: "sess-a",
|
|
2323
|
+
omxRootOverride: "/repo",
|
|
2324
|
+
baseEnv: { PATH: "/bin" },
|
|
2325
|
+
register: (hudPaneId, leaderPaneId, heightLines, options) => {
|
|
2326
|
+
calls.push({ hudPaneId, leaderPaneId, heightLines, cwd: options?.cwd, env: options?.env });
|
|
2327
|
+
return true;
|
|
2328
|
+
},
|
|
2329
|
+
});
|
|
2330
|
+
assert.equal(result, true);
|
|
2331
|
+
assert.deepEqual(calls, [{
|
|
2332
|
+
hudPaneId: "%hud",
|
|
2333
|
+
leaderPaneId: "%leader",
|
|
2334
|
+
heightLines: HUD_TMUX_HEIGHT_LINES,
|
|
2335
|
+
cwd: "/repo",
|
|
2336
|
+
env: {
|
|
2337
|
+
PATH: "/bin",
|
|
2338
|
+
OMX_SESSION_ID: "sess-a",
|
|
2339
|
+
OMX_TMUX_HUD_OWNER: "1",
|
|
2340
|
+
OMX_TMUX_HUD_LEADER_PANE: "%leader",
|
|
2341
|
+
OMX_ROOT: "/repo",
|
|
2342
|
+
},
|
|
2343
|
+
}]);
|
|
2344
|
+
assert.equal(registerInsideTmuxHudResizeHook({
|
|
2345
|
+
hudPaneId: null,
|
|
2346
|
+
currentPaneId: "%leader",
|
|
2347
|
+
cwd: "/repo",
|
|
2348
|
+
sessionId: "sess-a",
|
|
2349
|
+
register: () => {
|
|
2350
|
+
throw new Error("should not register without a HUD pane");
|
|
2351
|
+
},
|
|
2352
|
+
}), false);
|
|
2353
|
+
});
|
|
2354
|
+
it("buildDetachedHudHookEnv preserves tmux targeting and local launcher identity", () => {
|
|
2355
|
+
const env = buildDetachedHudHookEnv({ PATH: "/bin" }, "sess-a", "%leader", "/tmp/tmux.sock,123,7", "/repo/dist/cli/omx.js", "/repo");
|
|
2356
|
+
assert.equal(env.PATH, "/bin");
|
|
2357
|
+
assert.equal(env.TMUX, "/tmp/tmux.sock,123,7");
|
|
2358
|
+
assert.equal(env.TMUX_PANE, "%leader");
|
|
2359
|
+
assert.equal(env.OMX_SESSION_ID, "sess-a");
|
|
2360
|
+
assert.equal(env.OMX_TMUX_HUD_OWNER, "1");
|
|
2361
|
+
assert.equal(env.OMX_ROOT, "/repo");
|
|
2362
|
+
assert.equal(env.OMX_ENTRY_PATH, "/repo/dist/cli/omx.js");
|
|
2363
|
+
});
|
|
2364
|
+
it("registerDetachedHudLayoutReconcileHook reads TMUX from the detached leader pane before registering", () => {
|
|
2365
|
+
const calls = [];
|
|
2366
|
+
const readTargets = [];
|
|
2367
|
+
const result = registerDetachedHudLayoutReconcileHook({
|
|
2368
|
+
hudPaneId: "%hud",
|
|
2369
|
+
detachedLeaderPaneId: "%leader",
|
|
2370
|
+
cwd: "/repo",
|
|
2371
|
+
sessionId: "sess-a",
|
|
2372
|
+
omxBin: "/repo/dist/cli/omx.js",
|
|
2373
|
+
omxRootOverride: "/repo",
|
|
2374
|
+
baseEnv: { PATH: "/bin" },
|
|
2375
|
+
readTmuxEnvValue: (targetPaneId) => {
|
|
2376
|
+
readTargets.push(targetPaneId);
|
|
2377
|
+
return "/tmp/tmux.sock,123,7";
|
|
2378
|
+
},
|
|
2379
|
+
register: (hudPaneId, leaderPaneId, heightLines, options) => {
|
|
2380
|
+
calls.push({ hudPaneId, leaderPaneId, heightLines, cwd: options?.cwd, env: options?.env });
|
|
2381
|
+
return true;
|
|
2382
|
+
},
|
|
2383
|
+
});
|
|
2384
|
+
assert.equal(result, true);
|
|
2385
|
+
assert.deepEqual(readTargets, ["%leader"]);
|
|
2386
|
+
assert.deepEqual(calls, [{
|
|
2387
|
+
hudPaneId: "%hud",
|
|
2388
|
+
leaderPaneId: "%leader",
|
|
2389
|
+
heightLines: HUD_TMUX_HEIGHT_LINES,
|
|
2390
|
+
cwd: "/repo",
|
|
2391
|
+
env: {
|
|
2392
|
+
PATH: "/bin",
|
|
2393
|
+
TMUX: "/tmp/tmux.sock,123,7",
|
|
2394
|
+
TMUX_PANE: "%leader",
|
|
2395
|
+
OMX_SESSION_ID: "sess-a",
|
|
2396
|
+
OMX_TMUX_HUD_OWNER: "1",
|
|
2397
|
+
OMX_ROOT: "/repo",
|
|
2398
|
+
OMX_ENTRY_PATH: "/repo/dist/cli/omx.js",
|
|
2399
|
+
},
|
|
2400
|
+
}]);
|
|
2401
|
+
assert.equal(registerDetachedHudLayoutReconcileHook({
|
|
2402
|
+
hudPaneId: "%hud",
|
|
2403
|
+
detachedLeaderPaneId: "%leader",
|
|
2404
|
+
cwd: "/repo",
|
|
2405
|
+
sessionId: "sess-a",
|
|
2406
|
+
omxBin: "/repo/dist/cli/omx.js",
|
|
2407
|
+
readTmuxEnvValue: () => undefined,
|
|
2408
|
+
register: () => {
|
|
2409
|
+
throw new Error("should not register without TMUX");
|
|
2410
|
+
},
|
|
2411
|
+
}), false);
|
|
2412
|
+
});
|
|
2413
|
+
it("buildDetachedSessionBootstrapSteps starts native Windows detached sessions with powershell", () => {
|
|
2414
|
+
const hudCmd = buildWindowsPromptCommand("node", [
|
|
2415
|
+
"omx.js",
|
|
2416
|
+
"hud",
|
|
2417
|
+
"--watch",
|
|
2418
|
+
]);
|
|
2419
|
+
const steps = buildDetachedSessionBootstrapSteps("omx-demo", "C:/project", "'codex' '--dangerously-bypass-approvals-and-sandbox'", hudCmd, "--model gpt-5", "C:/codex-home", null, true);
|
|
2420
|
+
assert.equal(steps[0]?.name, "new-session");
|
|
2421
|
+
assert.equal(steps[0]?.args.at(-1), "powershell.exe");
|
|
2422
|
+
assert.equal(steps[1]?.name, "split-and-capture-hud-pane");
|
|
2423
|
+
assert.equal(steps[1]?.args.at(-1), hudCmd);
|
|
2424
|
+
});
|
|
2425
|
+
it("buildDetachedWindowsBootstrapScript targets the resolved tmux-compatible command", () => {
|
|
2426
|
+
const script = buildDetachedWindowsBootstrapScript("omx-demo", "powershell.exe -NoLogo -NoExit -EncodedCommand abc", 2500, "C:\\Program Files\\psmux\\psmux.exe");
|
|
2427
|
+
assert.match(script, /const tmuxCommand = "C:\\\\Program Files\\\\psmux\\\\psmux\.exe";/);
|
|
2428
|
+
assert.match(script, /execFileSync\(tmuxCommand, \['send-keys'/);
|
|
2429
|
+
assert.doesNotMatch(script, /execFileSync\('tmux'/);
|
|
2430
|
+
});
|
|
2431
|
+
it("buildDetachedSessionBootstrapSteps kills detached tmux session on normal shell exit", () => {
|
|
2432
|
+
const steps = buildDetachedSessionBootstrapSteps("omx-demo", "/tmp/project", "'codex' '--model' 'gpt-5'", "'node' '/tmp/omx.js' 'hud' '--watch'", null);
|
|
2433
|
+
const leaderCmd = steps[0]?.args.at(-1);
|
|
2434
|
+
assert.equal(typeof leaderCmd, "string");
|
|
2435
|
+
assert.match(leaderCmd, /^\/bin\/sh -c '/);
|
|
2436
|
+
assert.doesNotMatch(leaderCmd, /^\/bin\/sh -lc '/);
|
|
2437
|
+
assert.match(leaderCmd, /acquireTmuxExtendedKeysLease/);
|
|
2438
|
+
assert.match(leaderCmd, /omx_detached_session_cleanup\(\)/);
|
|
2439
|
+
assert.match(leaderCmd, /trap omx_detached_session_cleanup 0 INT TERM HUP;/);
|
|
2440
|
+
assert.match(leaderCmd, /exec 3<&0;/);
|
|
2441
|
+
assert.match(leaderCmd, /omx_codex_pid=\$!;/);
|
|
2442
|
+
assert.match(leaderCmd, /<\&3 &/);
|
|
2443
|
+
assert.match(leaderCmd, /wait "\$omx_codex_pid";/);
|
|
2444
|
+
assert.match(leaderCmd, /kill -TERM "\$omx_codex_pid"/);
|
|
2445
|
+
assert.match(leaderCmd, /releaseTmuxExtendedKeysLease/);
|
|
2446
|
+
assert.match(leaderCmd, /if \[ "\$status" -eq 0 \]; then/);
|
|
2447
|
+
assert.match(leaderCmd, /tmux kill-session -t/);
|
|
2448
|
+
assert.match(leaderCmd, /"omx-demo"/);
|
|
2449
|
+
assert.match(leaderCmd, /codex exited immediately with code 0/);
|
|
2450
|
+
assert.match(leaderCmd, /codex exited with code/);
|
|
2451
|
+
assert.match(leaderCmd, /detached tmux session is being kept open/);
|
|
2452
|
+
assert.match(leaderCmd, /exit \$status/);
|
|
2453
|
+
});
|
|
2454
|
+
it("buildDetachedSessionBootstrapSteps finalizes postLaunch inside the detached leader when a session id is available", () => {
|
|
2455
|
+
const steps = buildDetachedSessionBootstrapSteps("omx-demo", "/tmp/project", "'codex' '--model' 'gpt-5'", "'node' '/tmp/omx.js' 'hud' '--watch'", null, "/tmp/codex-home", null, false, "omx-session-123", "/tmp/project/.codex-project", "/tmp/project/.omx/runtime/codex-home/omx-session-123");
|
|
2456
|
+
const leaderCmd = steps[0]?.args.at(-1);
|
|
2457
|
+
assert.equal(typeof leaderCmd, "string");
|
|
2458
|
+
assert.match(leaderCmd, /runDetachedSessionPostLaunch/);
|
|
2459
|
+
assert.match(leaderCmd, /omx-session-123/);
|
|
2460
|
+
assert.match(leaderCmd, /\/tmp\/codex-home/);
|
|
2461
|
+
assert.match(leaderCmd, /\/tmp\/project\/\.codex-project/);
|
|
2462
|
+
assert.match(leaderCmd, /\/tmp\/project\/\.omx\/runtime\/codex-home\/omx-session-123/);
|
|
2463
|
+
const helperIndex = leaderCmd.indexOf("runDetachedSessionPostLaunch");
|
|
2464
|
+
const signalGateIndex = leaderCmd.indexOf('if [ "$status" -eq 0 ]');
|
|
2465
|
+
assert.ok(helperIndex >= 0);
|
|
2466
|
+
assert.ok(signalGateIndex >= 0);
|
|
2467
|
+
assert.ok(helperIndex < signalGateIndex, "detached postLaunch helper must run before the signal-derived tmux kill-session gate");
|
|
2468
|
+
});
|
|
2469
|
+
it("detached leader command keeps stdin open for the Codex child", async () => {
|
|
2470
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-detached-leader-stdin-"));
|
|
2471
|
+
const fakeBin = join(cwd, "bin");
|
|
2472
|
+
const stdinLogPath = join(cwd, "stdin.log");
|
|
2473
|
+
try {
|
|
2474
|
+
await mkdir(fakeBin, { recursive: true });
|
|
2475
|
+
await writeFile(join(fakeBin, "codex"), `#!/bin/sh
|
|
2476
|
+
if IFS= read -r line; then
|
|
2477
|
+
printf 'stdin:%s\n' "$line" > "${stdinLogPath}"
|
|
2478
|
+
else
|
|
2479
|
+
printf 'stdin:EOF\n' > "${stdinLogPath}"
|
|
2480
|
+
fi
|
|
2481
|
+
`);
|
|
2482
|
+
await chmod(join(fakeBin, "codex"), 0o755);
|
|
2483
|
+
await writeFile(join(fakeBin, "tmux"), `#!/bin/sh
|
|
2484
|
+
case "$1" in
|
|
2485
|
+
display-message)
|
|
2486
|
+
if [ "$3" = '#{socket_path}' ] || [ "$4" = '#{socket_path}' ]; then
|
|
2487
|
+
printf '/tmp/tmux-test.sock\n'
|
|
2488
|
+
else
|
|
2489
|
+
printf '0\n'
|
|
2490
|
+
fi
|
|
2491
|
+
;;
|
|
2492
|
+
show-options)
|
|
2493
|
+
printf 'off\n'
|
|
2494
|
+
;;
|
|
2495
|
+
set-option|kill-session)
|
|
2496
|
+
;;
|
|
2497
|
+
esac
|
|
2498
|
+
exit 0
|
|
2499
|
+
`);
|
|
2500
|
+
await chmod(join(fakeBin, "tmux"), 0o755);
|
|
2501
|
+
const steps = buildDetachedSessionBootstrapSteps("omx-demo", cwd, buildTmuxPaneCommand("codex", [], "/bin/sh"), "'node' '/tmp/omx.js' 'hud' '--watch'", null);
|
|
2502
|
+
const leaderCmd = steps[0]?.args.at(-1);
|
|
2503
|
+
assert.equal(typeof leaderCmd, "string");
|
|
2504
|
+
const result = (await import("node:child_process")).spawnSync("/bin/sh", ["-c", leaderCmd], {
|
|
2505
|
+
cwd,
|
|
2506
|
+
env: {
|
|
2507
|
+
...process.env,
|
|
2508
|
+
PATH: `${fakeBin}:/usr/bin:/bin`,
|
|
2509
|
+
HOME: cwd,
|
|
2510
|
+
},
|
|
2511
|
+
input: "hello from leader\n",
|
|
2512
|
+
encoding: "utf-8",
|
|
2513
|
+
});
|
|
2514
|
+
assert.equal(result.status, 0, result.stderr || result.stdout);
|
|
2515
|
+
const stdinLog = await readFile(stdinLogPath, "utf-8");
|
|
2516
|
+
assert.match(stdinLog, /stdin:hello from leader/);
|
|
2517
|
+
}
|
|
2518
|
+
finally {
|
|
2519
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2520
|
+
}
|
|
2521
|
+
});
|
|
2522
|
+
it("detached leader command preserves cwd and cleanup without shell-quote breakage", async () => {
|
|
2523
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-detached-leader-"));
|
|
2524
|
+
const fakeBin = join(cwd, "bin");
|
|
2525
|
+
const logPath = join(cwd, "leader.log");
|
|
2526
|
+
try {
|
|
2527
|
+
await mkdir(fakeBin, { recursive: true });
|
|
2528
|
+
await writeFile(join(fakeBin, "codex"), `#!/bin/sh
|
|
2529
|
+
printf 'codex:%s\\n' "$*" >> "${logPath}"
|
|
2530
|
+
printf 'codex-pwd:%s\\n' "$(pwd)" >> "${logPath}"
|
|
2531
|
+
printf 'codex-bridge-env:%s\\n' "\${OMX_HERMES_MCP_BRIDGE-unset}" >> "${logPath}"
|
|
2532
|
+
exit 0
|
|
2533
|
+
`);
|
|
2534
|
+
await chmod(join(fakeBin, "codex"), 0o755);
|
|
2535
|
+
await writeFile(join(cwd, ".profile"), "cd ..\n");
|
|
2536
|
+
await writeFile(join(fakeBin, "tmux"), `#!/bin/sh
|
|
2537
|
+
printf 'tmux:%s\\n' "$*" >> "${logPath}"
|
|
2538
|
+
case "$1" in
|
|
2539
|
+
display-message)
|
|
2540
|
+
if [ "$3" = '#{socket_path}' ] || [ "$4" = '#{socket_path}' ]; then
|
|
2541
|
+
printf '/tmp/tmux-test.sock\\n'
|
|
2542
|
+
else
|
|
2543
|
+
printf '0\\n'
|
|
2544
|
+
fi
|
|
2545
|
+
;;
|
|
2546
|
+
show-options)
|
|
2547
|
+
printf 'off\\n'
|
|
2548
|
+
;;
|
|
2549
|
+
set-option|kill-session)
|
|
2550
|
+
;;
|
|
2551
|
+
esac
|
|
2552
|
+
exit 0
|
|
2553
|
+
`);
|
|
2554
|
+
await chmod(join(fakeBin, "tmux"), 0o755);
|
|
2555
|
+
const steps = buildDetachedSessionBootstrapSteps("omx-demo", cwd, buildTmuxPaneCommand("codex", ["--dangerously-bypass-approvals-and-sandbox"], "/bin/sh"), "'node' '/tmp/omx.js' 'hud' '--watch'", null);
|
|
2556
|
+
const leaderCmd = steps[0]?.args.at(-1);
|
|
2557
|
+
assert.equal(typeof leaderCmd, "string");
|
|
2558
|
+
(await import("node:child_process")).execFileSync("/bin/sh", ["-c", leaderCmd], {
|
|
2559
|
+
cwd,
|
|
2560
|
+
env: {
|
|
2561
|
+
...process.env,
|
|
2562
|
+
PATH: `${fakeBin}:/usr/bin:/bin`,
|
|
2563
|
+
HOME: cwd,
|
|
2564
|
+
OMX_HERMES_MCP_BRIDGE: "1",
|
|
2565
|
+
},
|
|
2566
|
+
stdio: "ignore",
|
|
2567
|
+
});
|
|
2568
|
+
const log = await readFile(logPath, "utf-8");
|
|
2569
|
+
assert.match(log, /codex:--dangerously-bypass-approvals-and-sandbox/);
|
|
2570
|
+
assert.match(normalizeDarwinTmpPath(log), new RegExp(`codex-pwd:${escapeRegExp(normalizeDarwinTmpPath(cwd))}`));
|
|
2571
|
+
assert.match(log, /codex-bridge-env:unset/);
|
|
2572
|
+
assert.match(log, /tmux:display-message -p #\{socket_path\}/);
|
|
2573
|
+
assert.match(log, /tmux:show-options -sv extended-keys/);
|
|
2574
|
+
assert.match(log, /tmux:set-option -sq extended-keys always/);
|
|
2575
|
+
assert.match(log, /tmux:set-option -sq extended-keys off/);
|
|
2576
|
+
assert.match(log, /tmux:kill-session -t omx-demo/);
|
|
2577
|
+
}
|
|
2578
|
+
finally {
|
|
2579
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2580
|
+
}
|
|
2581
|
+
});
|
|
2582
|
+
it("detached leader command preserves the detached tmux session on signal-derived exits", async () => {
|
|
2583
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-detached-leader-signal-"));
|
|
2584
|
+
const fakeBin = join(cwd, "bin");
|
|
2585
|
+
const logPath = join(cwd, "leader.log");
|
|
2586
|
+
try {
|
|
2587
|
+
await mkdir(fakeBin, { recursive: true });
|
|
2588
|
+
await writeFile(join(fakeBin, "codex"), `#!/bin/sh
|
|
2589
|
+
printf 'codex:%s\\n' "$*" >> "${logPath}"
|
|
2590
|
+
exit 143
|
|
2591
|
+
`);
|
|
2592
|
+
await chmod(join(fakeBin, "codex"), 0o755);
|
|
2593
|
+
await writeFile(join(fakeBin, "tmux"), `#!/bin/sh
|
|
2594
|
+
printf 'tmux:%s\\n' "$*" >> "${logPath}"
|
|
2595
|
+
case "$1" in
|
|
2596
|
+
display-message)
|
|
2597
|
+
if [ "$3" = '#{socket_path}' ] || [ "$4" = '#{socket_path}' ]; then
|
|
2598
|
+
printf '/tmp/tmux-test.sock\\n'
|
|
2599
|
+
else
|
|
2600
|
+
printf '0\\n'
|
|
2601
|
+
fi
|
|
2602
|
+
;;
|
|
2603
|
+
show-options)
|
|
2604
|
+
printf 'off\\n'
|
|
2605
|
+
;;
|
|
2606
|
+
set-option|kill-session)
|
|
2607
|
+
;;
|
|
2608
|
+
esac
|
|
2609
|
+
exit 0
|
|
2610
|
+
`);
|
|
2611
|
+
await chmod(join(fakeBin, "tmux"), 0o755);
|
|
2612
|
+
const steps = buildDetachedSessionBootstrapSteps("omx-demo", cwd, buildTmuxPaneCommand("codex", ["--dangerously-bypass-approvals-and-sandbox"], "/bin/sh"), "'node' '/tmp/omx.js' 'hud' '--watch'", null);
|
|
2613
|
+
const leaderCmd = steps[0]?.args.at(-1);
|
|
2614
|
+
assert.equal(typeof leaderCmd, "string");
|
|
2615
|
+
const result = (await import("node:child_process")).spawnSync("/bin/sh", ["-c", leaderCmd], {
|
|
2616
|
+
cwd,
|
|
2617
|
+
env: {
|
|
2618
|
+
...process.env,
|
|
2619
|
+
PATH: `${fakeBin}:/usr/bin:/bin`,
|
|
2620
|
+
HOME: cwd,
|
|
2621
|
+
},
|
|
2622
|
+
encoding: "utf-8",
|
|
2623
|
+
});
|
|
2624
|
+
assert.equal(result.status, 143);
|
|
2625
|
+
const log = await readFile(logPath, "utf-8");
|
|
2626
|
+
assert.match(log, /codex:--dangerously-bypass-approvals-and-sandbox/);
|
|
2627
|
+
assert.match(log, /tmux:display-message -p #\{socket_path\}/);
|
|
2628
|
+
assert.match(log, /tmux:show-options -sv extended-keys/);
|
|
2629
|
+
assert.match(log, /tmux:set-option -sq extended-keys always/);
|
|
2630
|
+
assert.match(log, /tmux:set-option -sq extended-keys off/);
|
|
2631
|
+
assert.doesNotMatch(log, /tmux:kill-session -t omx-demo/);
|
|
2632
|
+
}
|
|
2633
|
+
finally {
|
|
2634
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2635
|
+
}
|
|
2636
|
+
});
|
|
2637
|
+
it("detached leader command keeps child startup errors visible instead of killing the session", async () => {
|
|
2638
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-detached-leader-error-"));
|
|
2639
|
+
const fakeBin = join(cwd, "bin");
|
|
2640
|
+
const logPath = join(cwd, "leader.log");
|
|
2641
|
+
try {
|
|
2642
|
+
await mkdir(fakeBin, { recursive: true });
|
|
2643
|
+
await writeFile(join(fakeBin, "codex"), `#!/bin/sh
|
|
2644
|
+
printf 'codex-stderr: unsupported startup flag\\n' >&2
|
|
2645
|
+
exit 42
|
|
2646
|
+
`);
|
|
2647
|
+
await chmod(join(fakeBin, "codex"), 0o755);
|
|
2648
|
+
await writeFile(join(fakeBin, "tmux"), `#!/bin/sh
|
|
2649
|
+
printf 'tmux:%s\\n' "$*" >> "${logPath}"
|
|
2650
|
+
case "$1" in
|
|
2651
|
+
display-message)
|
|
2652
|
+
if [ "$3" = '#{socket_path}' ] || [ "$4" = '#{socket_path}' ]; then
|
|
2653
|
+
printf '/tmp/tmux-test.sock\\n'
|
|
2654
|
+
else
|
|
2655
|
+
printf '0\\n'
|
|
2656
|
+
fi
|
|
2657
|
+
;;
|
|
2658
|
+
show-options)
|
|
2659
|
+
printf 'off\\n'
|
|
2660
|
+
;;
|
|
2661
|
+
set-option|kill-session)
|
|
2662
|
+
;;
|
|
2663
|
+
esac
|
|
2664
|
+
exit 0
|
|
2665
|
+
`);
|
|
2666
|
+
await chmod(join(fakeBin, "tmux"), 0o755);
|
|
2667
|
+
const steps = buildDetachedSessionBootstrapSteps("omx-demo", cwd, buildTmuxPaneCommand("codex", ["--bad-startup-flag"], "/bin/sh"), "'node' '/tmp/omx.js' 'hud' '--watch'", null);
|
|
2668
|
+
const leaderCmd = steps[0]?.args.at(-1);
|
|
2669
|
+
assert.equal(typeof leaderCmd, "string");
|
|
2670
|
+
const result = (await import("node:child_process")).spawnSync("/bin/sh", ["-c", leaderCmd], {
|
|
2671
|
+
cwd,
|
|
2672
|
+
env: {
|
|
2673
|
+
...process.env,
|
|
2674
|
+
PATH: `${fakeBin}:/usr/bin:/bin`,
|
|
2675
|
+
HOME: cwd,
|
|
2676
|
+
},
|
|
2677
|
+
input: "\n",
|
|
2678
|
+
encoding: "utf-8",
|
|
2679
|
+
});
|
|
2680
|
+
assert.equal(result.status, 42);
|
|
2681
|
+
assert.match(result.stderr, /codex-stderr: unsupported startup flag/);
|
|
2682
|
+
assert.match(result.stderr, /codex exited with code 42 during startup/);
|
|
2683
|
+
assert.match(result.stderr, /detached tmux session is being kept open/);
|
|
2684
|
+
const log = await readFile(logPath, "utf-8");
|
|
2685
|
+
assert.doesNotMatch(log, /tmux:kill-session -t omx-demo/);
|
|
2686
|
+
}
|
|
2687
|
+
finally {
|
|
2688
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2689
|
+
}
|
|
2690
|
+
});
|
|
2691
|
+
it("detached leader command keeps immediate zero-code exits visible instead of silently closing", async () => {
|
|
2692
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-detached-leader-zero-"));
|
|
2693
|
+
const fakeBin = join(cwd, "bin");
|
|
2694
|
+
const logPath = join(cwd, "leader.log");
|
|
2695
|
+
try {
|
|
2696
|
+
await mkdir(fakeBin, { recursive: true });
|
|
2697
|
+
await writeFile(join(fakeBin, "codex"), `#!/bin/sh
|
|
2698
|
+
printf 'codex-started-then-quit\\n' >&2
|
|
2699
|
+
exit 0
|
|
2700
|
+
`);
|
|
2701
|
+
await chmod(join(fakeBin, "codex"), 0o755);
|
|
2702
|
+
await writeFile(join(fakeBin, "tmux"), `#!/bin/sh
|
|
2703
|
+
printf 'tmux:%s\\n' "$*" >> "${logPath}"
|
|
2704
|
+
case "$1" in
|
|
2705
|
+
display-message)
|
|
2706
|
+
if [ "$3" = '#{socket_path}' ] || [ "$4" = '#{socket_path}' ]; then
|
|
2707
|
+
printf '/tmp/tmux-test.sock\\n'
|
|
2708
|
+
else
|
|
2709
|
+
printf '0\\n'
|
|
2710
|
+
fi
|
|
2711
|
+
;;
|
|
2712
|
+
show-options)
|
|
2713
|
+
printf 'off\\n'
|
|
2714
|
+
;;
|
|
2715
|
+
set-option|kill-session)
|
|
2716
|
+
;;
|
|
2717
|
+
esac
|
|
2718
|
+
exit 0
|
|
2719
|
+
`);
|
|
2720
|
+
await chmod(join(fakeBin, "tmux"), 0o755);
|
|
2721
|
+
const steps = buildDetachedSessionBootstrapSteps("omx-demo", cwd, buildTmuxPaneCommand("codex", [], "/bin/sh"), "'node' '/tmp/omx.js' 'hud' '--watch'", null);
|
|
2722
|
+
const leaderCmd = steps[0]?.args.at(-1);
|
|
2723
|
+
assert.equal(typeof leaderCmd, "string");
|
|
2724
|
+
const result = (await import("node:child_process")).spawnSync("/bin/sh", ["-c", leaderCmd], {
|
|
2725
|
+
cwd,
|
|
2726
|
+
env: {
|
|
2727
|
+
...process.env,
|
|
2728
|
+
PATH: `${fakeBin}:/usr/bin:/bin`,
|
|
2729
|
+
HOME: cwd,
|
|
2730
|
+
},
|
|
2731
|
+
input: "\n",
|
|
2732
|
+
encoding: "utf-8",
|
|
2733
|
+
});
|
|
2734
|
+
assert.equal(result.status, 0, result.stderr || result.stdout);
|
|
2735
|
+
assert.match(result.stderr, /codex-started-then-quit/);
|
|
2736
|
+
assert.match(result.stderr, /codex exited immediately with code 0 during startup/);
|
|
2737
|
+
assert.match(result.stderr, /detached tmux session is being kept open/);
|
|
2738
|
+
const log = await readFile(logPath, "utf-8");
|
|
2739
|
+
assert.match(log, /tmux:kill-session -t omx-demo/);
|
|
2740
|
+
}
|
|
2741
|
+
finally {
|
|
2742
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2743
|
+
}
|
|
2744
|
+
});
|
|
2745
|
+
it("detached leader command terminates codex child on external SIGHUP", async () => {
|
|
2746
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-detached-leader-hup-"));
|
|
2747
|
+
const fakeBin = join(cwd, "bin");
|
|
2748
|
+
const pidFile = join(cwd, "codex.pid");
|
|
2749
|
+
try {
|
|
2750
|
+
await mkdir(fakeBin, { recursive: true });
|
|
2751
|
+
await writeFile(join(fakeBin, "codex"), `#!/bin/sh
|
|
2752
|
+
echo $$ > "${pidFile}"
|
|
2753
|
+
trap '' HUP
|
|
2754
|
+
while true; do sleep 1; done
|
|
2755
|
+
`);
|
|
2756
|
+
await chmod(join(fakeBin, "codex"), 0o755);
|
|
2757
|
+
await writeFile(join(fakeBin, "tmux"), `#!/bin/sh
|
|
2758
|
+
case "$1" in
|
|
2759
|
+
display-message)
|
|
2760
|
+
if [ "$3" = '#{socket_path}' ] || [ "$4" = '#{socket_path}' ]; then
|
|
2761
|
+
printf '/tmp/tmux-test.sock\\n'
|
|
2762
|
+
else
|
|
2763
|
+
printf '0\\n'
|
|
2764
|
+
fi
|
|
2765
|
+
;;
|
|
2766
|
+
show-options) printf 'off\\n' ;;
|
|
2767
|
+
set-option|kill-session) ;;
|
|
2768
|
+
esac
|
|
2769
|
+
exit 0
|
|
2770
|
+
`);
|
|
2771
|
+
await chmod(join(fakeBin, "tmux"), 0o755);
|
|
2772
|
+
const steps = buildDetachedSessionBootstrapSteps("omx-demo", cwd, buildTmuxPaneCommand("codex", [], "/bin/sh"), "'node' '/tmp/omx.js' 'hud' '--watch'", null);
|
|
2773
|
+
const leaderCmd = steps[0]?.args.at(-1);
|
|
2774
|
+
assert.equal(typeof leaderCmd, "string");
|
|
2775
|
+
const { spawn } = await import("node:child_process");
|
|
2776
|
+
const child = spawn("/bin/sh", ["-c", `exec ${leaderCmd}`], {
|
|
2777
|
+
cwd,
|
|
2778
|
+
env: {
|
|
2779
|
+
...process.env,
|
|
2780
|
+
PATH: `${fakeBin}:/usr/bin:/bin`,
|
|
2781
|
+
HOME: cwd,
|
|
2782
|
+
},
|
|
2783
|
+
stdio: "ignore",
|
|
2784
|
+
detached: true,
|
|
2785
|
+
});
|
|
2786
|
+
try {
|
|
2787
|
+
for (let i = 0; i < 50; i += 1) {
|
|
2788
|
+
if (existsSync(pidFile))
|
|
2789
|
+
break;
|
|
2790
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
2791
|
+
}
|
|
2792
|
+
assert.ok(existsSync(pidFile), "codex pid file not written");
|
|
2793
|
+
const codexPid = Number.parseInt((await readFile(pidFile, "utf-8")).trim(), 10);
|
|
2794
|
+
assert.ok(codexPid > 0, "codex pid must be positive");
|
|
2795
|
+
assert.doesNotThrow(() => process.kill(codexPid, 0), "codex must be alive before signal");
|
|
2796
|
+
const leaderExit = once(child, "exit");
|
|
2797
|
+
process.kill(child.pid, "SIGHUP");
|
|
2798
|
+
await Promise.race([
|
|
2799
|
+
leaderExit,
|
|
2800
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error("leader did not exit after SIGHUP")), 3000)),
|
|
2801
|
+
]);
|
|
2802
|
+
assert.throws(() => process.kill(codexPid, 0), (err) => typeof err === "object" &&
|
|
2803
|
+
err !== null &&
|
|
2804
|
+
"code" in err &&
|
|
2805
|
+
err.code === "ESRCH", "codex child must be terminated after leader SIGHUP");
|
|
2806
|
+
}
|
|
2807
|
+
finally {
|
|
2808
|
+
try {
|
|
2809
|
+
process.kill(child.pid, "SIGKILL");
|
|
2810
|
+
}
|
|
2811
|
+
catch {
|
|
2812
|
+
/* already dead */
|
|
2813
|
+
}
|
|
2814
|
+
}
|
|
2815
|
+
}
|
|
2816
|
+
finally {
|
|
2817
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2818
|
+
}
|
|
2819
|
+
});
|
|
2820
|
+
it("withTmuxExtendedKeys enables tmux extended keys during codex launch and restores them afterwards", async () => {
|
|
2821
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-tmux-lease-wrapper-"));
|
|
2822
|
+
const calls = [];
|
|
2823
|
+
const result = withTmuxExtendedKeys(cwd, () => {
|
|
2824
|
+
calls.push(["run"]);
|
|
2825
|
+
return "ok";
|
|
2826
|
+
}, (_file, args) => {
|
|
2827
|
+
calls.push([...args]);
|
|
2828
|
+
if (args[0] === "show-options")
|
|
2829
|
+
return "off\n";
|
|
2830
|
+
return "";
|
|
2831
|
+
});
|
|
2832
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2833
|
+
assert.equal(result, "ok");
|
|
2834
|
+
assert.deepEqual(calls, [
|
|
2835
|
+
["display-message", "-p", "#{socket_path}"],
|
|
2836
|
+
["show-options", "-sv", "extended-keys"],
|
|
2837
|
+
["set-option", "-sq", "extended-keys", "always"],
|
|
2838
|
+
["run"],
|
|
2839
|
+
["set-option", "-sq", "extended-keys", "off"],
|
|
2840
|
+
]);
|
|
2841
|
+
});
|
|
2842
|
+
it("acquireTmuxExtendedKeysLease can bind lease liveness to a long-lived owner pid", async () => {
|
|
2843
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-tmux-lease-owner-pid-"));
|
|
2844
|
+
try {
|
|
2845
|
+
const execStub = (_file, args) => {
|
|
2846
|
+
if (args[0] === "display-message")
|
|
2847
|
+
return "/tmp/tmux-owner-pid.sock\n";
|
|
2848
|
+
if (args[0] === "show-options")
|
|
2849
|
+
return "off\n";
|
|
2850
|
+
return "";
|
|
2851
|
+
};
|
|
2852
|
+
const lease = acquireTmuxExtendedKeysLease(cwd, execStub, 12345);
|
|
2853
|
+
assert.match(lease ?? "", /^\/tmp\/tmux-owner-pid\.sock\t12345-/);
|
|
2854
|
+
if (lease)
|
|
2855
|
+
releaseTmuxExtendedKeysLease(cwd, lease, execStub);
|
|
2856
|
+
}
|
|
2857
|
+
finally {
|
|
2858
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2859
|
+
}
|
|
2860
|
+
});
|
|
2861
|
+
it("overlapping tmux extended-keys leases restore only after the last holder exits", async () => {
|
|
2862
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-tmux-lease-overlap-"));
|
|
2863
|
+
const calls = [];
|
|
2864
|
+
const execStub = (_file, args) => {
|
|
2865
|
+
calls.push([...args]);
|
|
2866
|
+
if (args[0] === "display-message")
|
|
2867
|
+
return "/tmp/tmux-test.sock\n";
|
|
2868
|
+
if (args[0] === "show-options")
|
|
2869
|
+
return "off\n";
|
|
2870
|
+
return "";
|
|
2871
|
+
};
|
|
2872
|
+
const leaseA = acquireTmuxExtendedKeysLease(cwd, execStub);
|
|
2873
|
+
const leaseB = acquireTmuxExtendedKeysLease(cwd, execStub);
|
|
2874
|
+
assert.equal(typeof leaseA, "string");
|
|
2875
|
+
assert.equal(typeof leaseB, "string");
|
|
2876
|
+
releaseTmuxExtendedKeysLease(cwd, leaseA, execStub);
|
|
2877
|
+
const leaseDir = join(cwd, ".omx", "state", "tmux-extended-keys");
|
|
2878
|
+
const leaseFilesAfterFirstRelease = await readFile(join(leaseDir, "tmp-tmux-test-sock.json"), "utf-8");
|
|
2879
|
+
assert.match(leaseFilesAfterFirstRelease, /holders/);
|
|
2880
|
+
releaseTmuxExtendedKeysLease(cwd, leaseB, execStub);
|
|
2881
|
+
await assert.rejects(readFile(join(leaseDir, "tmp-tmux-test-sock.json"), "utf-8"), /ENOENT/);
|
|
2882
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2883
|
+
assert.deepEqual(calls, [
|
|
2884
|
+
["display-message", "-p", "#{socket_path}"],
|
|
2885
|
+
["show-options", "-sv", "extended-keys"],
|
|
2886
|
+
["set-option", "-sq", "extended-keys", "always"],
|
|
2887
|
+
["display-message", "-p", "#{socket_path}"],
|
|
2888
|
+
["set-option", "-sq", "extended-keys", "off"],
|
|
2889
|
+
]);
|
|
2890
|
+
});
|
|
2891
|
+
it("withTmuxExtendedKeys degrades cleanly when tmux option probing fails", async () => {
|
|
2892
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-tmux-lease-fail-"));
|
|
2893
|
+
const calls = [];
|
|
2894
|
+
const result = withTmuxExtendedKeys(cwd, () => {
|
|
2895
|
+
calls.push(["run"]);
|
|
2896
|
+
return "ok";
|
|
2897
|
+
}, (_file, args) => {
|
|
2898
|
+
calls.push([...args]);
|
|
2899
|
+
if (args[0] === "show-options")
|
|
2900
|
+
throw new Error("tmux unavailable");
|
|
2901
|
+
return "";
|
|
2902
|
+
});
|
|
2903
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2904
|
+
assert.equal(result, "ok");
|
|
2905
|
+
assert.deepEqual(calls, [
|
|
2906
|
+
["display-message", "-p", "#{socket_path}"],
|
|
2907
|
+
["show-options", "-sv", "extended-keys"],
|
|
2908
|
+
["run"],
|
|
2909
|
+
]);
|
|
2910
|
+
});
|
|
2911
|
+
it("withTmuxExtendedKeys ignores tmux versions without the extended-keys option", async () => {
|
|
2912
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-tmux-lease-unsupported-"));
|
|
2913
|
+
const calls = [];
|
|
2914
|
+
const stderrWrite = mock.method(process.stderr, "write", () => true);
|
|
2915
|
+
try {
|
|
2916
|
+
const result = withTmuxExtendedKeys(cwd, () => {
|
|
2917
|
+
calls.push(["run"]);
|
|
2918
|
+
return "ok";
|
|
2919
|
+
}, (_file, args) => {
|
|
2920
|
+
calls.push([...args]);
|
|
2921
|
+
if (args[0] === "display-message")
|
|
2922
|
+
return "/tmp/tmux-3-0.sock\n";
|
|
2923
|
+
if (args[0] === "show-options") {
|
|
2924
|
+
throw Object.assign(new Error("Command failed: tmux show-options -sv extended-keys"), {
|
|
2925
|
+
status: 1,
|
|
2926
|
+
stderr: Buffer.from("invalid option: extended-keys\n"),
|
|
2927
|
+
stdout: Buffer.from(""),
|
|
2928
|
+
});
|
|
2929
|
+
}
|
|
2930
|
+
return "";
|
|
2931
|
+
});
|
|
2932
|
+
assert.equal(result, "ok");
|
|
2933
|
+
assert.deepEqual(calls, [
|
|
2934
|
+
["display-message", "-p", "#{socket_path}"],
|
|
2935
|
+
["show-options", "-sv", "extended-keys"],
|
|
2936
|
+
["run"],
|
|
2937
|
+
]);
|
|
2938
|
+
assert.equal(stderrWrite.mock.callCount(), 0);
|
|
2939
|
+
}
|
|
2940
|
+
finally {
|
|
2941
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2942
|
+
}
|
|
2943
|
+
});
|
|
2944
|
+
it("acquireTmuxExtendedKeysLease returns no lease when extended-keys is unsupported", async () => {
|
|
2945
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-tmux-acquire-unsupported-"));
|
|
2946
|
+
const calls = [];
|
|
2947
|
+
const stderrWrite = mock.method(process.stderr, "write", () => true);
|
|
2948
|
+
try {
|
|
2949
|
+
const lease = acquireTmuxExtendedKeysLease(cwd, (_file, args) => {
|
|
2950
|
+
calls.push([...args]);
|
|
2951
|
+
if (args[0] === "display-message")
|
|
2952
|
+
return "/tmp/tmux-3-0.sock\n";
|
|
2953
|
+
if (args[0] === "show-options") {
|
|
2954
|
+
throw Object.assign(new Error("Command failed: tmux show-options -sv extended-keys"), {
|
|
2955
|
+
status: 1,
|
|
2956
|
+
stderr: Buffer.from("invalid option: extended-keys\n"),
|
|
2957
|
+
stdout: Buffer.from(""),
|
|
2958
|
+
});
|
|
2959
|
+
}
|
|
2960
|
+
return "";
|
|
2961
|
+
});
|
|
2962
|
+
assert.equal(lease, null);
|
|
2963
|
+
assert.deepEqual(calls, [
|
|
2964
|
+
["display-message", "-p", "#{socket_path}"],
|
|
2965
|
+
["show-options", "-sv", "extended-keys"],
|
|
2966
|
+
]);
|
|
2967
|
+
assert.equal(stderrWrite.mock.callCount(), 0);
|
|
2968
|
+
}
|
|
2969
|
+
finally {
|
|
2970
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2971
|
+
}
|
|
2972
|
+
});
|
|
2973
|
+
it("reapStaleNotifyFallbackWatcher skips kill when process identity does not match a watcher", async () => {
|
|
2974
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-reap-pid-identity-"));
|
|
2975
|
+
const pidPath = join(cwd, "watcher.pid");
|
|
2976
|
+
await writeFile(pidPath, JSON.stringify({ pid: 99999, started_at: new Date().toISOString() }));
|
|
2977
|
+
const killed = [];
|
|
2978
|
+
await reapStaleNotifyFallbackWatcher(pidPath, {
|
|
2979
|
+
isWatcherProcess: () => false,
|
|
2980
|
+
tryKillPid: (pid) => { killed.push(pid); return true; },
|
|
2981
|
+
});
|
|
2982
|
+
assert.equal(killed.length, 0, "should not kill a process that is not a watcher");
|
|
2983
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2984
|
+
});
|
|
2985
|
+
it("reapStaleNotifyFallbackWatcher sends SIGTERM only after confirming watcher identity", async () => {
|
|
2986
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-reap-pid-confirmed-"));
|
|
2987
|
+
const pidPath = join(cwd, "watcher.pid");
|
|
2988
|
+
await writeFile(pidPath, JSON.stringify({ pid: 12345, started_at: "2026-04-05T00:00:00.000Z" }));
|
|
2989
|
+
const killed = [];
|
|
2990
|
+
await reapStaleNotifyFallbackWatcher(pidPath, {
|
|
2991
|
+
isWatcherProcess: () => true,
|
|
2992
|
+
tryKillPid: (pid) => { killed.push(pid); return true; },
|
|
2993
|
+
});
|
|
2994
|
+
assert.deepEqual(killed, [12345], "should SIGTERM the verified watcher process");
|
|
2995
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2996
|
+
});
|
|
2997
|
+
it("reapStaleNotifyFallbackWatcher skips recently started watcher records to avoid respawn loops", async () => {
|
|
2998
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-reap-pid-recent-"));
|
|
2999
|
+
const pidPath = join(cwd, "watcher.pid");
|
|
3000
|
+
await writeFile(pidPath, JSON.stringify({ pid: 24680, started_at: "2026-05-15T00:00:00.000Z" }));
|
|
3001
|
+
const killed = [];
|
|
3002
|
+
const result = await reapStaleNotifyFallbackWatcher(pidPath, {
|
|
3003
|
+
isWatcherProcess: () => true,
|
|
3004
|
+
nowMs: () => Date.parse("2026-05-15T00:00:03.000Z"),
|
|
3005
|
+
reapGraceMs: 5000,
|
|
3006
|
+
tryKillPid: (pid) => { killed.push(pid); return true; },
|
|
3007
|
+
});
|
|
3008
|
+
assert.equal(result, "recent_active");
|
|
3009
|
+
assert.equal(killed.length, 0, "should not kill a watcher still inside the startup grace window");
|
|
3010
|
+
await rm(cwd, { recursive: true, force: true });
|
|
3011
|
+
});
|
|
3012
|
+
it("reuses legacy plain-text PID parsing without widening stale reap semantics across PID reuse", async () => {
|
|
3013
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-reap-legacy-pid-"));
|
|
3014
|
+
try {
|
|
3015
|
+
const pidPath = join(cwd, "watcher.pid");
|
|
3016
|
+
await writeFile(pidPath, "12345\n", "utf-8");
|
|
3017
|
+
const observed = [];
|
|
3018
|
+
await reapStaleNotifyFallbackWatcher(pidPath, {
|
|
3019
|
+
isWatcherProcess(pid) {
|
|
3020
|
+
observed.push(pid);
|
|
3021
|
+
return false;
|
|
3022
|
+
},
|
|
3023
|
+
tryKillPid: (pid) => {
|
|
3024
|
+
observed.push(pid);
|
|
3025
|
+
return true;
|
|
3026
|
+
},
|
|
3027
|
+
});
|
|
3028
|
+
assert.deepEqual(observed, [12345], "legacy plain-text PID files should still identity-check reused PIDs before any kill");
|
|
3029
|
+
}
|
|
3030
|
+
finally {
|
|
3031
|
+
await rm(cwd, { recursive: true, force: true });
|
|
3032
|
+
}
|
|
3033
|
+
});
|
|
3034
|
+
it("reaps watcher-record PIDs only after the record path confirms watcher identity across PID reuse", async () => {
|
|
3035
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-reap-record-pid-"));
|
|
3036
|
+
try {
|
|
3037
|
+
const pidPath = join(cwd, "watcher.pid");
|
|
3038
|
+
await writeFile(pidPath, JSON.stringify({ pid: 54321, started_at: "2026-04-05T00:00:00.000Z" }), "utf-8");
|
|
3039
|
+
const observed = [];
|
|
3040
|
+
await reapStaleNotifyFallbackWatcher(pidPath, {
|
|
3041
|
+
isWatcherProcess(pid) {
|
|
3042
|
+
observed.push({ step: "identity", pid });
|
|
3043
|
+
return true;
|
|
3044
|
+
},
|
|
3045
|
+
tryKillPid(pid) {
|
|
3046
|
+
observed.push({ step: "kill", pid });
|
|
3047
|
+
return true;
|
|
3048
|
+
},
|
|
3049
|
+
});
|
|
3050
|
+
assert.deepEqual(observed, [
|
|
3051
|
+
{ step: "identity", pid: 54321 },
|
|
3052
|
+
{ step: "kill", pid: 54321 },
|
|
3053
|
+
]);
|
|
3054
|
+
}
|
|
3055
|
+
finally {
|
|
3056
|
+
await rm(cwd, { recursive: true, force: true });
|
|
3057
|
+
}
|
|
3058
|
+
});
|
|
3059
|
+
it("acquireTmuxExtendedKeysLease recovers from a stale lock left by a crashed process", async () => {
|
|
3060
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-tmux-stale-lock-"));
|
|
3061
|
+
const leaseDir = join(cwd, ".omx", "state", "tmux-extended-keys");
|
|
3062
|
+
const lockDir = join(leaseDir, "tmp-stale-sock.lock");
|
|
3063
|
+
mkdirSync(lockDir, { recursive: true });
|
|
3064
|
+
const staleTime = new Date(Date.now() - 60_000);
|
|
3065
|
+
utimesSync(lockDir, staleTime, staleTime);
|
|
3066
|
+
const calls = [];
|
|
3067
|
+
const execStub = (_file, args) => {
|
|
3068
|
+
calls.push([...args]);
|
|
3069
|
+
if (args[0] === "display-message")
|
|
3070
|
+
return "/tmp/stale-sock";
|
|
3071
|
+
return "";
|
|
3072
|
+
};
|
|
3073
|
+
const lease = acquireTmuxExtendedKeysLease(cwd, execStub);
|
|
3074
|
+
assert.equal(typeof lease, "string", "lease should succeed after stale lock recovery");
|
|
3075
|
+
assert.ok(!existsSync(lockDir), "stale lock directory should be removed");
|
|
3076
|
+
if (lease)
|
|
3077
|
+
releaseTmuxExtendedKeysLease(cwd, lease, execStub);
|
|
3078
|
+
await rm(cwd, { recursive: true, force: true });
|
|
3079
|
+
});
|
|
3080
|
+
it("acquireTmuxExtendedKeysLease reaps dead holders and restores before taking a new lease", async () => {
|
|
3081
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-tmux-dead-holder-acquire-"));
|
|
3082
|
+
try {
|
|
3083
|
+
const leaseDir = join(cwd, ".omx", "state", "tmux-extended-keys");
|
|
3084
|
+
const leasePath = join(leaseDir, "tmp-stale-holder-sock.json");
|
|
3085
|
+
await mkdir(leaseDir, { recursive: true });
|
|
3086
|
+
await writeFile(leasePath, JSON.stringify({
|
|
3087
|
+
originalMode: "off",
|
|
3088
|
+
holders: ["2147483647-stale-holder"],
|
|
3089
|
+
}), "utf-8");
|
|
3090
|
+
const calls = [];
|
|
3091
|
+
const execStub = (_file, args) => {
|
|
3092
|
+
calls.push([...args]);
|
|
3093
|
+
if (args[0] === "display-message")
|
|
3094
|
+
return "/tmp/stale-holder.sock\n";
|
|
3095
|
+
if (args[0] === "show-options")
|
|
3096
|
+
return "off\n";
|
|
3097
|
+
return "";
|
|
3098
|
+
};
|
|
3099
|
+
const lease = acquireTmuxExtendedKeysLease(cwd, execStub);
|
|
3100
|
+
assert.equal(typeof lease, "string");
|
|
3101
|
+
const persisted = JSON.parse(await readFile(leasePath, "utf-8"));
|
|
3102
|
+
assert.equal(persisted.holders.length, 1);
|
|
3103
|
+
const holder = persisted.holders[0];
|
|
3104
|
+
const holderId = typeof holder === "string" ? holder : holder?.id ?? "";
|
|
3105
|
+
assert.match(holderId, new RegExp(`^${process.pid}-`));
|
|
3106
|
+
assert.equal(typeof holder === "object" ? holder.pid : process.pid, process.pid);
|
|
3107
|
+
assert.doesNotMatch(JSON.stringify(persisted), /2147483647-stale-holder/);
|
|
3108
|
+
if (lease)
|
|
3109
|
+
releaseTmuxExtendedKeysLease(cwd, lease, execStub);
|
|
3110
|
+
assert.deepEqual(calls, [
|
|
3111
|
+
["display-message", "-p", "#{socket_path}"],
|
|
3112
|
+
["set-option", "-sq", "extended-keys", "off"],
|
|
3113
|
+
["show-options", "-sv", "extended-keys"],
|
|
3114
|
+
["set-option", "-sq", "extended-keys", "always"],
|
|
3115
|
+
["set-option", "-sq", "extended-keys", "off"],
|
|
3116
|
+
]);
|
|
3117
|
+
}
|
|
3118
|
+
finally {
|
|
3119
|
+
await rm(cwd, { recursive: true, force: true });
|
|
3120
|
+
}
|
|
3121
|
+
});
|
|
3122
|
+
it("releaseTmuxExtendedKeysLease preserves live legacy string holders", async () => {
|
|
3123
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-tmux-live-legacy-holder-"));
|
|
3124
|
+
try {
|
|
3125
|
+
const leaseDir = join(cwd, ".omx", "state", "tmux-extended-keys");
|
|
3126
|
+
const leasePath = join(leaseDir, "tmp-live-legacy-sock.json");
|
|
3127
|
+
const legacyHolder = `${process.pid}-legacy-holder`;
|
|
3128
|
+
await mkdir(leaseDir, { recursive: true });
|
|
3129
|
+
await writeFile(leasePath, JSON.stringify({
|
|
3130
|
+
originalMode: "off",
|
|
3131
|
+
holders: [legacyHolder],
|
|
3132
|
+
}), "utf-8");
|
|
3133
|
+
const calls = [];
|
|
3134
|
+
const execStub = (_file, args) => {
|
|
3135
|
+
calls.push([...args]);
|
|
3136
|
+
return "";
|
|
3137
|
+
};
|
|
3138
|
+
releaseTmuxExtendedKeysLease(cwd, "/tmp/live-legacy.sock\tmissing-holder", execStub);
|
|
3139
|
+
const persisted = JSON.parse(await readFile(leasePath, "utf-8"));
|
|
3140
|
+
assert.deepEqual(persisted.holders, [legacyHolder]);
|
|
3141
|
+
assert.deepEqual(calls, [], "live legacy string holders should not be restored away");
|
|
3142
|
+
}
|
|
3143
|
+
finally {
|
|
3144
|
+
await rm(cwd, { recursive: true, force: true });
|
|
3145
|
+
}
|
|
3146
|
+
});
|
|
3147
|
+
it("acquireTmuxExtendedKeysLease reaps Linux PID-reuse identity mismatches", async () => {
|
|
3148
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-tmux-pid-reuse-holder-"));
|
|
3149
|
+
try {
|
|
3150
|
+
const leaseDir = join(cwd, ".omx", "state", "tmux-extended-keys");
|
|
3151
|
+
const leasePath = join(leaseDir, "tmp-pid-reuse-sock.json");
|
|
3152
|
+
await mkdir(leaseDir, { recursive: true });
|
|
3153
|
+
await writeFile(leasePath, JSON.stringify({
|
|
3154
|
+
originalMode: "off",
|
|
3155
|
+
holders: [{
|
|
3156
|
+
id: `${process.pid}-reused-holder`,
|
|
3157
|
+
pid: process.pid,
|
|
3158
|
+
platform: "linux",
|
|
3159
|
+
linuxStartTicks: -1,
|
|
3160
|
+
}],
|
|
3161
|
+
}), "utf-8");
|
|
3162
|
+
const calls = [];
|
|
3163
|
+
const execStub = (_file, args) => {
|
|
3164
|
+
calls.push([...args]);
|
|
3165
|
+
if (args[0] === "display-message")
|
|
3166
|
+
return "/tmp/pid-reuse.sock\n";
|
|
3167
|
+
if (args[0] === "show-options")
|
|
3168
|
+
return "off\n";
|
|
3169
|
+
return "";
|
|
3170
|
+
};
|
|
3171
|
+
const lease = acquireTmuxExtendedKeysLease(cwd, execStub);
|
|
3172
|
+
assert.equal(typeof lease, "string");
|
|
3173
|
+
const persisted = JSON.parse(await readFile(leasePath, "utf-8"));
|
|
3174
|
+
const holderIds = persisted.holders.map((holder) => typeof holder === "string" ? holder : holder.id ?? "");
|
|
3175
|
+
if (process.platform === "linux") {
|
|
3176
|
+
assert.equal(persisted.holders.length, 1);
|
|
3177
|
+
assert.match(holderIds[0] ?? "", new RegExp(`^${process.pid}-`));
|
|
3178
|
+
assert.doesNotMatch(JSON.stringify(persisted), /reused-holder/);
|
|
3179
|
+
assert.deepEqual(calls, [
|
|
3180
|
+
["display-message", "-p", "#{socket_path}"],
|
|
3181
|
+
["set-option", "-sq", "extended-keys", "off"],
|
|
3182
|
+
["show-options", "-sv", "extended-keys"],
|
|
3183
|
+
["set-option", "-sq", "extended-keys", "always"],
|
|
3184
|
+
]);
|
|
3185
|
+
}
|
|
3186
|
+
else {
|
|
3187
|
+
assert.ok(holderIds.includes(`${process.pid}-reused-holder`));
|
|
3188
|
+
}
|
|
3189
|
+
if (lease)
|
|
3190
|
+
releaseTmuxExtendedKeysLease(cwd, lease, execStub);
|
|
3191
|
+
}
|
|
3192
|
+
finally {
|
|
3193
|
+
await rm(cwd, { recursive: true, force: true });
|
|
3194
|
+
}
|
|
3195
|
+
});
|
|
3196
|
+
it("releaseTmuxExtendedKeysLease restores when all remaining holders are dead", async () => {
|
|
3197
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-tmux-dead-holder-release-"));
|
|
3198
|
+
try {
|
|
3199
|
+
const leaseDir = join(cwd, ".omx", "state", "tmux-extended-keys");
|
|
3200
|
+
const leasePath = join(leaseDir, "tmp-dead-release-sock.json");
|
|
3201
|
+
await mkdir(leaseDir, { recursive: true });
|
|
3202
|
+
await writeFile(leasePath, JSON.stringify({
|
|
3203
|
+
originalMode: "off",
|
|
3204
|
+
holders: ["2147483647-stale-holder"],
|
|
3205
|
+
}), "utf-8");
|
|
3206
|
+
const calls = [];
|
|
3207
|
+
const execStub = (_file, args) => {
|
|
3208
|
+
calls.push([...args]);
|
|
3209
|
+
return "";
|
|
3210
|
+
};
|
|
3211
|
+
releaseTmuxExtendedKeysLease(cwd, "/tmp/dead-release.sock\tmissing-holder", execStub);
|
|
3212
|
+
assert.ok(!existsSync(leasePath), "stale-only lease file should be removed");
|
|
3213
|
+
assert.deepEqual(calls, [["set-option", "-sq", "extended-keys", "off"]]);
|
|
3214
|
+
}
|
|
3215
|
+
finally {
|
|
3216
|
+
await rm(cwd, { recursive: true, force: true });
|
|
3217
|
+
}
|
|
3218
|
+
});
|
|
3219
|
+
it("buildDetachedSessionFinalizeSteps keeps schedule after split-capture and before attach", () => {
|
|
3220
|
+
const steps = buildDetachedSessionFinalizeSteps("omx-demo", "%12", "3", true, false, true, "%leader");
|
|
3221
|
+
const names = steps.map((step) => step.name);
|
|
3222
|
+
const attachedIndex = names.indexOf("register-client-attached-reconcile");
|
|
3223
|
+
const scheduleIndex = names.indexOf("schedule-delayed-resize");
|
|
3224
|
+
const attachIndex = names.indexOf("attach-session");
|
|
3225
|
+
assert.equal(attachedIndex >= 0, true);
|
|
3226
|
+
assert.equal(scheduleIndex > attachedIndex, true);
|
|
3227
|
+
assert.equal(scheduleIndex >= 0, true);
|
|
3228
|
+
assert.equal(attachIndex > scheduleIndex, true);
|
|
3229
|
+
assert.equal(names.includes("register-resize-hook"), true);
|
|
3230
|
+
assert.equal(names.includes("reconcile-hud-resize"), true);
|
|
3231
|
+
assert.equal(DETACHED_TMUX_HISTORY_LIMIT, 500);
|
|
3232
|
+
const historyHook = steps.find((step) => step.name === "register-detached-history-prune-hook");
|
|
3233
|
+
assert.ok(historyHook);
|
|
3234
|
+
assert.deepEqual(historyHook.args.slice(0, 3), ["set-hook", "-t", "omx-demo"]);
|
|
3235
|
+
assert.match(historyHook.args[3] || "", /^client-detached\[[0-9]+\]$/);
|
|
3236
|
+
assert.equal(historyHook.args[4], `if-shell -F '#{==:#{session_attached},0}' 'run-shell -b "tmux clear-history -t %leader >/dev/null 2>&1 || true"'`);
|
|
3237
|
+
});
|
|
3238
|
+
it("detached history prune hook tolerates a dead leader pane", () => {
|
|
3239
|
+
const steps = buildDetachedSessionFinalizeSteps("omx-demo", "%12", "3", true, false, true, "%leader");
|
|
3240
|
+
const historyHook = steps.find((step) => step.name === "register-detached-history-prune-hook");
|
|
3241
|
+
assert.ok(historyHook);
|
|
3242
|
+
const hookCommand = historyHook.args[4] || "";
|
|
3243
|
+
assert.match(hookCommand, /run-shell -b/);
|
|
3244
|
+
assert.match(hookCommand, />\/dev\/null 2>&1 \|\| true/);
|
|
3245
|
+
});
|
|
3246
|
+
it("buildDetachedSessionFinalizeSteps skips attach for Hermes MCP bridge launches", () => {
|
|
3247
|
+
assert.equal(shouldAttachDetachedTmuxSession({ OMX_HERMES_MCP_BRIDGE: "1" }), false);
|
|
3248
|
+
assert.equal(shouldAttachDetachedTmuxSession({}), true);
|
|
3249
|
+
const steps = buildDetachedSessionFinalizeSteps("omx-demo", "%12", "3", true, false, shouldAttachDetachedTmuxSession({ OMX_HERMES_MCP_BRIDGE: "1" }));
|
|
3250
|
+
assert.equal(steps.some((step) => step.name === "attach-session"), false);
|
|
3251
|
+
assert.equal(steps.some((step) => step.name === "register-resize-hook"), true);
|
|
3252
|
+
assert.equal(steps.some((step) => step.name === "set-mouse"), true);
|
|
3253
|
+
});
|
|
3254
|
+
it("buildDetachedSessionFinalizeSteps uses quiet best-effort tmux resize commands", () => {
|
|
3255
|
+
const steps = buildDetachedSessionFinalizeSteps("omx-demo", "%12", "3", false);
|
|
3256
|
+
const registerHook = steps.find((step) => step.name === "register-resize-hook");
|
|
3257
|
+
const schedule = steps.find((step) => step.name === "schedule-delayed-resize");
|
|
3258
|
+
const reconcile = steps.find((step) => step.name === "reconcile-hud-resize");
|
|
3259
|
+
assert.match(registerHook?.args[4] ?? "", />\/dev\/null 2>&1 \|\| true/);
|
|
3260
|
+
assert.match(registerHook?.args[4] ?? "", new RegExp(`-y ${HUD_TMUX_HEIGHT_LINES}\\b`));
|
|
3261
|
+
assert.match(schedule?.args[2] ?? "", />\/dev\/null 2>&1 \|\| true/);
|
|
3262
|
+
assert.match(schedule?.args[2] ?? "", new RegExp(`-y ${HUD_TMUX_HEIGHT_LINES}\\b`));
|
|
3263
|
+
assert.match((reconcile?.args ?? []).join(" "), />\/dev\/null 2>&1 \|\| true/);
|
|
3264
|
+
assert.match((reconcile?.args ?? []).join(" "), new RegExp(`-y ${HUD_TMUX_HEIGHT_LINES}\\b`));
|
|
3265
|
+
});
|
|
3266
|
+
it("buildDetachedSessionFinalizeSteps skips detached resize hooks on native Windows", () => {
|
|
3267
|
+
const steps = buildDetachedSessionFinalizeSteps("omx-demo", "%12", "3", true, true);
|
|
3268
|
+
assert.deepEqual(steps.map((step) => step.name), ["set-mouse", "sanitize-copy-mode-style", "attach-session"]);
|
|
3269
|
+
});
|
|
3270
|
+
it("buildDetachedSessionFinalizeSteps sanitizes copy-mode styling before attach when mouse mode is enabled", () => {
|
|
3271
|
+
const steps = buildDetachedSessionFinalizeSteps("omx-demo", "%12", "3", true);
|
|
3272
|
+
assert.equal(steps.findIndex((step) => step.name === "sanitize-copy-mode-style")
|
|
3273
|
+
> steps.findIndex((step) => step.name === "set-mouse"), true);
|
|
3274
|
+
assert.equal(steps.findIndex((step) => step.name === "attach-session")
|
|
3275
|
+
> steps.findIndex((step) => step.name === "sanitize-copy-mode-style"), true);
|
|
3276
|
+
});
|
|
3277
|
+
it("buildDetachedSessionFinalizeSteps never appends server-global terminal-overrides", () => {
|
|
3278
|
+
const steps = buildDetachedSessionFinalizeSteps("omx-demo", "%12", "3", true);
|
|
3279
|
+
assert.equal(steps.some((step) => step.name === "set-wsl-xt"), false);
|
|
3280
|
+
assert.equal(steps.some((step) => step.args.includes("terminal-overrides")), false);
|
|
3281
|
+
});
|
|
3282
|
+
it("buildDetachedSessionRollbackSteps unregisters hooks before killing session", () => {
|
|
3283
|
+
const steps = buildDetachedSessionRollbackSteps("omx-demo", "omx-demo:0", "omx_resize_launch_demo_0_12", "omx_attached_launch_demo_0_12");
|
|
3284
|
+
assert.deepEqual(steps.map((step) => step.name), [
|
|
3285
|
+
"unregister-client-attached-reconcile",
|
|
3286
|
+
"unregister-resize-hook",
|
|
3287
|
+
"kill-session",
|
|
3288
|
+
]);
|
|
3289
|
+
assert.equal(steps[0]?.args[0], "set-hook");
|
|
3290
|
+
assert.equal(steps[0]?.args[1], "-u");
|
|
3291
|
+
assert.equal(steps[0]?.args[2], "-t");
|
|
3292
|
+
assert.equal(steps[0]?.args[3], "omx-demo:0");
|
|
3293
|
+
assert.match(steps[0]?.args[4] ?? "", /^client-attached\[\d+\]$/);
|
|
3294
|
+
assert.match(steps[1]?.args[4] ?? "", /^client-resized\[\d+\]$/);
|
|
3295
|
+
assert.doesNotMatch(steps[1]?.args.join(" ") ?? "", /window-resized/);
|
|
3296
|
+
assert.deepEqual(steps[2]?.args, ["kill-session", "-t", "omx-demo"]);
|
|
3297
|
+
});
|
|
3298
|
+
it("buildDetachedSessionRollbackSteps only kills session when no hook metadata exists", () => {
|
|
3299
|
+
const steps = buildDetachedSessionRollbackSteps("omx-demo", null, null, null);
|
|
3300
|
+
assert.deepEqual(steps.map((step) => step.name), ["kill-session"]);
|
|
3301
|
+
});
|
|
3302
|
+
});
|
|
3303
|
+
describe("buildTmuxShellCommand", () => {
|
|
3304
|
+
it("preserves quoted config values for tmux shell-command execution", () => {
|
|
3305
|
+
assert.equal(buildTmuxShellCommand("codex", [
|
|
3306
|
+
"--dangerously-bypass-approvals-and-sandbox",
|
|
3307
|
+
"-c",
|
|
3308
|
+
'model_reasoning_effort="xhigh"',
|
|
3309
|
+
]), `'codex' '--dangerously-bypass-approvals-and-sandbox' '-c' 'model_reasoning_effort="xhigh"'`);
|
|
3310
|
+
});
|
|
3311
|
+
});
|
|
3312
|
+
describe("buildTmuxPaneCommand", () => {
|
|
3313
|
+
it("wraps command with zsh without sourcing rc files by default", () => {
|
|
3314
|
+
const result = buildTmuxPaneCommand("codex", ["--model", "gpt-5"], "/usr/bin/zsh", {});
|
|
3315
|
+
assert.ok(result.startsWith("'/usr/bin/zsh' -c "), "should start with zsh non-login shell to preserve tmux cwd");
|
|
3316
|
+
assert.ok(!result.includes(" -lc "), "should not use a login shell");
|
|
3317
|
+
assert.ok(!result.includes("source ~/.zshrc"), "should not source .zshrc by default");
|
|
3318
|
+
assert.ok(result.includes("exec "), "should exec the command");
|
|
3319
|
+
});
|
|
3320
|
+
it("keeps Homebrew zsh instead of downgrading to /bin/sh", () => {
|
|
3321
|
+
const result = buildTmuxPaneCommand("codex", ["--model", "gpt-5"], "/opt/homebrew/bin/zsh", {});
|
|
3322
|
+
assert.ok(result.startsWith("'/opt/homebrew/bin/zsh' -c "), "should preserve Homebrew zsh when SHELL points to it");
|
|
3323
|
+
assert.ok(!result.startsWith("'/bin/sh' -c "), "should not fall back to /bin/sh for supported Homebrew zsh");
|
|
3324
|
+
assert.ok(!result.includes("source ~/.zshrc"), "should not source .zshrc by default");
|
|
3325
|
+
});
|
|
3326
|
+
it("keeps MacPorts zsh instead of downgrading to /bin/sh", () => {
|
|
3327
|
+
const result = buildTmuxPaneCommand("codex", ["--model", "gpt-5"], "/opt/local/bin/zsh", {});
|
|
3328
|
+
assert.ok(result.startsWith("'/opt/local/bin/zsh' -c "), "should preserve MacPorts zsh when SHELL points to it");
|
|
3329
|
+
assert.ok(!result.startsWith("'/bin/sh' -c "), "should not fall back to /bin/sh for supported MacPorts zsh");
|
|
3330
|
+
assert.ok(!result.includes("source ~/.zshrc"), "should not source .zshrc by default");
|
|
3331
|
+
});
|
|
3332
|
+
it("prevents issue #2282 bash rc fan-out by default", () => {
|
|
3333
|
+
const result = buildTmuxPaneCommand("codex", [], "/bin/bash", {});
|
|
3334
|
+
assert.ok(result.startsWith("'/bin/bash' -c "), "should start with bash non-login shell to preserve tmux cwd");
|
|
3335
|
+
assert.ok(!result.includes(" -lc "), "should not use a login shell");
|
|
3336
|
+
assert.ok(!result.includes("source ~/.bashrc"), "should not source .bashrc by default");
|
|
3337
|
+
assert.ok(result.includes("exec "), "should exec the command");
|
|
3338
|
+
});
|
|
3339
|
+
it("sources zsh and bash rc files only when explicitly opted in", () => {
|
|
3340
|
+
assert.equal(shouldSourceTmuxPaneShellRc({}), false);
|
|
3341
|
+
assert.equal(shouldSourceTmuxPaneShellRc({ OMX_TMUX_SOURCE_SHELL_RC: "1" }), true);
|
|
3342
|
+
assert.ok(buildTmuxPaneCommand("codex", [], "/usr/bin/zsh", { OMX_TMUX_SOURCE_SHELL_RC: "1" }).includes("source ~/.zshrc"), "opt-in zsh launches may source .zshrc");
|
|
3343
|
+
assert.ok(buildTmuxPaneCommand("codex", [], "/bin/bash", { OMX_TMUX_SOURCE_SHELL_RC: "1" }).includes("source ~/.bashrc"), "opt-in bash launches may source .bashrc");
|
|
3344
|
+
});
|
|
3345
|
+
it("skips rc sourcing for unknown shells without using a login shell", () => {
|
|
3346
|
+
const result = buildTmuxPaneCommand("codex", [], "/bin/fish");
|
|
3347
|
+
assert.ok(result.startsWith("'/bin/fish' -c "), "should start with fish non-login shell");
|
|
3348
|
+
assert.ok(!result.includes(" -lc "), "should not use a login shell");
|
|
3349
|
+
assert.ok(!result.includes("source"), "should not source any rc file");
|
|
3350
|
+
assert.ok(result.includes("exec "), "should exec the command");
|
|
3351
|
+
});
|
|
3352
|
+
it("falls back to /bin/sh without using a login shell when shell path is empty", () => {
|
|
3353
|
+
const result = buildTmuxPaneCommand("codex", [], "");
|
|
3354
|
+
assert.ok(result.startsWith("'/bin/sh' -c "), "should fall back to /bin/sh");
|
|
3355
|
+
assert.ok(!result.includes(" -lc "), "should not use a login shell");
|
|
3356
|
+
});
|
|
3357
|
+
});
|
|
3358
|
+
describe("buildWindowsPromptCommand", () => {
|
|
3359
|
+
it("encodes detached Windows commands for safe PowerShell prompt injection", () => {
|
|
3360
|
+
const result = buildWindowsPromptCommand("codex", [
|
|
3361
|
+
"--dangerously-bypass-approvals-and-sandbox",
|
|
3362
|
+
"-c",
|
|
3363
|
+
'model_reasoning_effort="high"',
|
|
3364
|
+
"it's",
|
|
3365
|
+
]);
|
|
3366
|
+
const prefix = "powershell.exe -NoLogo -NoExit -EncodedCommand ";
|
|
3367
|
+
assert.ok(result.startsWith(prefix));
|
|
3368
|
+
const payload = result.slice(prefix.length);
|
|
3369
|
+
const decoded = Buffer.from(payload, "base64").toString("utf16le");
|
|
3370
|
+
assert.equal(decoded, "$ErrorActionPreference = 'Stop'; & { & 'codex' '--dangerously-bypass-approvals-and-sandbox' '-c' 'model_reasoning_effort=\"high\"' 'it''s' }");
|
|
3371
|
+
});
|
|
3372
|
+
});
|
|
3373
|
+
describe("buildTmuxSessionName", () => {
|
|
3374
|
+
it("uses detached fallback quietly outside git repos", () => {
|
|
3375
|
+
const name = buildTmuxSessionName("/tmp/My Repo", "omx-1770992424158-abc123");
|
|
3376
|
+
assert.equal(name, "omx-my-repo-detached-1770992424158-abc123");
|
|
3377
|
+
});
|
|
3378
|
+
it("sanitizes invalid characters", () => {
|
|
3379
|
+
const name = buildTmuxSessionName("/tmp/@#$", "omx-+++");
|
|
3380
|
+
assert.match(name, /^omx-(unknown|[a-z0-9-]+)-[a-z0-9-]+-(unknown|[a-z0-9-]+)$/);
|
|
3381
|
+
assert.equal(name.includes("_"), false);
|
|
3382
|
+
assert.equal(name.includes(" "), false);
|
|
3383
|
+
});
|
|
3384
|
+
it("includes repo name when cwd is inside .omx-worktrees", () => {
|
|
3385
|
+
const name = buildTmuxSessionName("/home/user/my-repo.omx-worktrees/launch-feature-x", "omx-123-abc");
|
|
3386
|
+
assert.match(name, /^omx-my-repo-launch-feature-x-/);
|
|
3387
|
+
});
|
|
3388
|
+
it("includes repo name for detached worktree paths", () => {
|
|
3389
|
+
const name = buildTmuxSessionName("/projects/cool-project.omx-worktrees/launch-detached", "omx-456-def");
|
|
3390
|
+
assert.match(name, /^omx-cool-project-launch-detached-/);
|
|
3391
|
+
});
|
|
3392
|
+
it("includes repo name when cwd is inside .omx/worktrees", () => {
|
|
3393
|
+
const name = buildTmuxSessionName("/home/user/my-repo/.omx/worktrees/autoresearch-demo", "omx-789-ghi");
|
|
3394
|
+
assert.match(name, /^omx-my-repo-autoresearch-demo-/);
|
|
3395
|
+
});
|
|
3396
|
+
});
|
|
3397
|
+
describe("buildDetachedTmuxSessionName", () => {
|
|
3398
|
+
it("reuses the OMX session id for the detached tmux session name", () => {
|
|
3399
|
+
const sessionName = buildDetachedTmuxSessionName("/tmp/My Repo", "omx-1770992424158-abc123");
|
|
3400
|
+
assert.equal(sessionName, "omx-my-repo-detached-1770992424158-abc123");
|
|
3401
|
+
});
|
|
3402
|
+
});
|
|
3403
|
+
describe("native Windows psmux-compatible tmux resolution", () => {
|
|
3404
|
+
it("resolveNativeSessionName uses the shared tmux-aware resolver for current session lookup", async () => {
|
|
3405
|
+
const originalPlatform = Object.getOwnPropertyDescriptor(process, "platform");
|
|
3406
|
+
const originalPath = process.env.PATH;
|
|
3407
|
+
const originalPathext = process.env.PATHEXT;
|
|
3408
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-psmux-native-session-"));
|
|
3409
|
+
const fakeBin = join(wd, "bin");
|
|
3410
|
+
Object.defineProperty(process, "platform", { value: "win32", configurable: true });
|
|
3411
|
+
try {
|
|
3412
|
+
await mkdir(fakeBin, { recursive: true });
|
|
3413
|
+
await writeFile(join(fakeBin, "psmux.exe"), `#!/bin/sh
|
|
3414
|
+
if [ "$1" = "display-message" ] && [ "$2" = "-p" ] && [ "$3" = "-t" ] && [ "$4" = "%7" ] && [ "$5" = "#S" ]; then
|
|
3415
|
+
printf 'psmux-session\\n'
|
|
3416
|
+
exit 0
|
|
3417
|
+
fi
|
|
3418
|
+
printf 'unexpected:%s\\n' "$*" >&2
|
|
3419
|
+
exit 1
|
|
3420
|
+
`);
|
|
3421
|
+
await chmod(join(fakeBin, "psmux.exe"), 0o755);
|
|
3422
|
+
process.env.PATH = fakeBin;
|
|
3423
|
+
process.env.PATHEXT = ".EXE";
|
|
3424
|
+
const sessionName = resolveNativeSessionName("/tmp/repo", "omx-abc123", {
|
|
3425
|
+
...process.env,
|
|
3426
|
+
TMUX: "1",
|
|
3427
|
+
TMUX_PANE: "%7",
|
|
3428
|
+
});
|
|
3429
|
+
assert.equal(sessionName, "psmux-session");
|
|
3430
|
+
}
|
|
3431
|
+
finally {
|
|
3432
|
+
process.env.PATH = originalPath;
|
|
3433
|
+
process.env.PATHEXT = originalPathext;
|
|
3434
|
+
if (originalPlatform)
|
|
3435
|
+
Object.defineProperty(process, "platform", originalPlatform);
|
|
3436
|
+
await rm(wd, { recursive: true, force: true });
|
|
3437
|
+
}
|
|
3438
|
+
});
|
|
3439
|
+
it("detectDetachedSessionWindowIndex uses the shared tmux-aware resolver on native Windows", async () => {
|
|
3440
|
+
const originalPlatform = Object.getOwnPropertyDescriptor(process, "platform");
|
|
3441
|
+
const originalPath = process.env.PATH;
|
|
3442
|
+
const originalPathext = process.env.PATHEXT;
|
|
3443
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-psmux-window-index-"));
|
|
3444
|
+
const fakeBin = join(wd, "bin");
|
|
3445
|
+
Object.defineProperty(process, "platform", { value: "win32", configurable: true });
|
|
3446
|
+
try {
|
|
3447
|
+
await mkdir(fakeBin, { recursive: true });
|
|
3448
|
+
await writeFile(join(fakeBin, "psmux.exe"), `#!/bin/sh
|
|
3449
|
+
if [ "$1" = "display-message" ] && [ "$2" = "-p" ] && [ "$3" = "-t" ] && [ "$4" = "omx-demo" ] && [ "$5" = "#{window_index}" ]; then
|
|
3450
|
+
printf '3\\n'
|
|
3451
|
+
exit 0
|
|
3452
|
+
fi
|
|
3453
|
+
printf 'unexpected:%s\\n' "$*" >&2
|
|
3454
|
+
exit 1
|
|
3455
|
+
`);
|
|
3456
|
+
await chmod(join(fakeBin, "psmux.exe"), 0o755);
|
|
3457
|
+
process.env.PATH = fakeBin;
|
|
3458
|
+
process.env.PATHEXT = ".EXE";
|
|
3459
|
+
assert.equal(detectDetachedSessionWindowIndex("omx-demo"), "3");
|
|
3460
|
+
}
|
|
3461
|
+
finally {
|
|
3462
|
+
process.env.PATH = originalPath;
|
|
3463
|
+
process.env.PATHEXT = originalPathext;
|
|
3464
|
+
if (originalPlatform)
|
|
3465
|
+
Object.defineProperty(process, "platform", originalPlatform);
|
|
3466
|
+
await rm(wd, { recursive: true, force: true });
|
|
3467
|
+
}
|
|
3468
|
+
});
|
|
3469
|
+
});
|
|
3470
|
+
describe("worktree dependency bootstrap helpers", () => {
|
|
3471
|
+
it("returns an explicit warning when reusable worktree dependencies are unavailable", () => {
|
|
3472
|
+
const result = ensureReusableNodeModules("/tmp/non-worktree", {
|
|
3473
|
+
gitRunner: () => ({ status: 1, stdout: "", stderr: "not a worktree" }),
|
|
3474
|
+
});
|
|
3475
|
+
assert.equal(result.strategy, "missing");
|
|
3476
|
+
assert.match(String(result.warning || ""), /No reusable parent-repo node_modules was found/);
|
|
3477
|
+
});
|
|
3478
|
+
});
|
|
3479
|
+
describe("team worker launch arg inheritance helpers", () => {
|
|
3480
|
+
it("collectInheritableTeamWorkerArgs extracts bypass, reasoning, and model overrides", () => {
|
|
3481
|
+
assert.deepEqual(collectInheritableTeamWorkerArgs([
|
|
3482
|
+
"--dangerously-bypass-approvals-and-sandbox",
|
|
3483
|
+
"-c",
|
|
3484
|
+
'model_reasoning_effort="xhigh"',
|
|
3485
|
+
"--model",
|
|
3486
|
+
"gpt-5",
|
|
3487
|
+
]), [
|
|
3488
|
+
"--dangerously-bypass-approvals-and-sandbox",
|
|
3489
|
+
"-c",
|
|
3490
|
+
'model_reasoning_effort="xhigh"',
|
|
3491
|
+
"--model",
|
|
3492
|
+
"gpt-5",
|
|
3493
|
+
]);
|
|
3494
|
+
});
|
|
3495
|
+
it("collectInheritableTeamWorkerArgs supports --model=<value> syntax", () => {
|
|
3496
|
+
assert.deepEqual(collectInheritableTeamWorkerArgs(["--model=gpt-5.3-codex"]), ["--model", "gpt-5.3-codex"]);
|
|
3497
|
+
});
|
|
3498
|
+
it("collectInheritableTeamWorkerArgs preserves only safe model_provider config overrides", () => {
|
|
3499
|
+
assert.deepEqual(collectInheritableTeamWorkerArgs([
|
|
3500
|
+
"-c",
|
|
3501
|
+
'sandbox_mode="danger-full-access"',
|
|
3502
|
+
"-c",
|
|
3503
|
+
'model_provider="cheapRouter"',
|
|
3504
|
+
"--model",
|
|
3505
|
+
"gpt-5.5",
|
|
3506
|
+
]), ["-c", 'model_provider="cheapRouter"', "--model", "gpt-5.5"]);
|
|
3507
|
+
});
|
|
3508
|
+
it("resolveTeamWorkerLaunchArgsEnv merges and normalizes with de-dupe + last reasoning/model wins", () => {
|
|
3509
|
+
assert.equal(resolveTeamWorkerLaunchArgsEnv('--dangerously-bypass-approvals-and-sandbox -c model_reasoning_effort="high" --model old-a --no-alt-screen --model=old-b', [
|
|
3510
|
+
"-c",
|
|
3511
|
+
'model_reasoning_effort="xhigh"',
|
|
3512
|
+
"--dangerously-bypass-approvals-and-sandbox",
|
|
3513
|
+
"--model",
|
|
3514
|
+
"gpt-5",
|
|
3515
|
+
], true), '--no-alt-screen --dangerously-bypass-approvals-and-sandbox -c model_reasoning_effort="xhigh" --model old-b');
|
|
3516
|
+
});
|
|
3517
|
+
it("resolveTeamWorkerLaunchArgsEnv can opt out of leader inheritance", () => {
|
|
3518
|
+
assert.equal(resolveTeamWorkerLaunchArgsEnv("--no-alt-screen", [
|
|
3519
|
+
"--dangerously-bypass-approvals-and-sandbox",
|
|
3520
|
+
"-c",
|
|
3521
|
+
'model_reasoning_effort="xhigh"',
|
|
3522
|
+
], false), "--no-alt-screen");
|
|
3523
|
+
});
|
|
3524
|
+
it("resolveTeamWorkerLaunchArgsEnv uses inherited model when env model is absent", () => {
|
|
3525
|
+
assert.equal(resolveTeamWorkerLaunchArgsEnv("--no-alt-screen", ["--model=gpt-5.3-codex"], true), "--no-alt-screen --model gpt-5.3-codex");
|
|
3526
|
+
});
|
|
3527
|
+
it("resolveTeamWorkerLaunchArgsEnv uses frontier default model when env and inherited models are absent", () => {
|
|
3528
|
+
assert.equal(resolveTeamWorkerLaunchArgsEnv("--no-alt-screen", ["--dangerously-bypass-approvals-and-sandbox"], true, DEFAULT_FRONTIER_MODEL), `--no-alt-screen --dangerously-bypass-approvals-and-sandbox --model ${DEFAULT_FRONTIER_MODEL}`);
|
|
3529
|
+
});
|
|
3530
|
+
it("resolveTeamWorkerLaunchArgsEnv keeps exactly one final model with precedence env > inherited > default", () => {
|
|
3531
|
+
assert.equal(resolveTeamWorkerLaunchArgsEnv("--model env-model --model=env-model-final", ["--model", "inherited-model"], true, "fallback-model"), "--model env-model-final");
|
|
3532
|
+
});
|
|
3533
|
+
it("resolveTeamWorkerLaunchArgsEnv prefers inherited model over default when env model is absent", () => {
|
|
3534
|
+
assert.equal(resolveTeamWorkerLaunchArgsEnv("--no-alt-screen", ["--model", "inherited-model"], true, "fallback-model"), "--no-alt-screen --model inherited-model");
|
|
3535
|
+
});
|
|
3536
|
+
});
|
|
3537
|
+
describe("readTopLevelTomlString", () => {
|
|
3538
|
+
it("reads a top-level string value", () => {
|
|
3539
|
+
const value = readTopLevelTomlString('model_reasoning_effort = "high"\n[mcp_servers.test]\nmodel_reasoning_effort = "low"\n', "model_reasoning_effort");
|
|
3540
|
+
assert.equal(value, "high");
|
|
3541
|
+
});
|
|
3542
|
+
it("ignores table-local values", () => {
|
|
3543
|
+
const value = readTopLevelTomlString('[mcp_servers.test]\nmodel_reasoning_effort = "xhigh"\n', "model_reasoning_effort");
|
|
3544
|
+
assert.equal(value, null);
|
|
3545
|
+
});
|
|
3546
|
+
});
|
|
3547
|
+
describe("injectModelInstructionsBypassArgs", () => {
|
|
3548
|
+
it("appends model_instructions_file override by default", () => {
|
|
3549
|
+
const args = injectModelInstructionsBypassArgs("/tmp/my-project", ["--model", "gpt-5"], {});
|
|
3550
|
+
assert.deepEqual(args, [
|
|
3551
|
+
"--model",
|
|
3552
|
+
"gpt-5",
|
|
3553
|
+
"-c",
|
|
3554
|
+
'model_instructions_file="/tmp/my-project/AGENTS.md"',
|
|
3555
|
+
]);
|
|
3556
|
+
});
|
|
3557
|
+
it("does not append when bypass is disabled via env", () => {
|
|
3558
|
+
const args = injectModelInstructionsBypassArgs("/tmp/my-project", ["--model", "gpt-5"], { OMX_BYPASS_DEFAULT_SYSTEM_PROMPT: "0" });
|
|
3559
|
+
assert.deepEqual(args, ["--model", "gpt-5"]);
|
|
3560
|
+
});
|
|
3561
|
+
it("does not append when model_instructions_file is already set", () => {
|
|
3562
|
+
const args = injectModelInstructionsBypassArgs("/tmp/my-project", ["-c", 'model_instructions_file="/tmp/custom.md"'], {});
|
|
3563
|
+
assert.deepEqual(args, ["-c", 'model_instructions_file="/tmp/custom.md"']);
|
|
3564
|
+
});
|
|
3565
|
+
it("respects OMX_MODEL_INSTRUCTIONS_FILE env override", () => {
|
|
3566
|
+
const args = injectModelInstructionsBypassArgs("/tmp/my-project", [], {
|
|
3567
|
+
OMX_MODEL_INSTRUCTIONS_FILE: "/tmp/alt instructions.md",
|
|
3568
|
+
});
|
|
3569
|
+
assert.deepEqual(args, [
|
|
3570
|
+
"-c",
|
|
3571
|
+
'model_instructions_file="/tmp/alt instructions.md"',
|
|
3572
|
+
]);
|
|
3573
|
+
});
|
|
3574
|
+
it("uses session-scoped default model_instructions_file when provided", () => {
|
|
3575
|
+
const args = injectModelInstructionsBypassArgs("/tmp/my-project", ["--model", "gpt-5"], {}, "/tmp/my-project/.omx/state/sessions/session-1/AGENTS.md");
|
|
3576
|
+
assert.deepEqual(args, [
|
|
3577
|
+
"--model",
|
|
3578
|
+
"gpt-5",
|
|
3579
|
+
"-c",
|
|
3580
|
+
'model_instructions_file="/tmp/my-project/.omx/state/sessions/session-1/AGENTS.md"',
|
|
3581
|
+
]);
|
|
3582
|
+
});
|
|
3583
|
+
});
|
|
3584
|
+
describe("upsertTopLevelTomlString", () => {
|
|
3585
|
+
it("replaces an existing top-level key", () => {
|
|
3586
|
+
const updated = upsertTopLevelTomlString('model_reasoning_effort = "low"\n[tui]\nstatus_line = []\n', "model_reasoning_effort", "high");
|
|
3587
|
+
assert.match(updated, /^model_reasoning_effort = "high"$/m);
|
|
3588
|
+
assert.doesNotMatch(updated, /^model_reasoning_effort = "low"$/m);
|
|
3589
|
+
});
|
|
3590
|
+
it("inserts before the first table when key is missing", () => {
|
|
3591
|
+
const updated = upsertTopLevelTomlString("[tui]\nstatus_line = []\n", "model_reasoning_effort", "xhigh");
|
|
3592
|
+
assert.equal(updated, 'model_reasoning_effort = "xhigh"\n[tui]\nstatus_line = []\n');
|
|
3593
|
+
});
|
|
3594
|
+
});
|
|
3595
|
+
describe("isExistingTmuxWindowTooCrampedForLaunchHud (#2754)", () => {
|
|
3596
|
+
it("skips the launch-time HUD split for cramped existing tmux windows", () => {
|
|
3597
|
+
// The reported repro: a 160x41 existing tmux window where forcing the HUD
|
|
3598
|
+
// split dropped the Codex TUI to 38 rows and became unreadable.
|
|
3599
|
+
assert.equal(isExistingTmuxWindowTooCrampedForLaunchHud(41), true);
|
|
3600
|
+
assert.equal(isExistingTmuxWindowTooCrampedForLaunchHud(38), true);
|
|
3601
|
+
assert.equal(isExistingTmuxWindowTooCrampedForLaunchHud(HUD_TMUX_MIN_LAUNCH_WINDOW_HEIGHT_LINES - 1), true);
|
|
3602
|
+
});
|
|
3603
|
+
it("keeps default HUD behavior for normal-height existing tmux windows", () => {
|
|
3604
|
+
assert.equal(isExistingTmuxWindowTooCrampedForLaunchHud(HUD_TMUX_MIN_LAUNCH_WINDOW_HEIGHT_LINES), false);
|
|
3605
|
+
assert.equal(isExistingTmuxWindowTooCrampedForLaunchHud(50), false);
|
|
3606
|
+
assert.equal(isExistingTmuxWindowTooCrampedForLaunchHud(120), false);
|
|
3607
|
+
});
|
|
3608
|
+
it("creates the HUD when the window height is unknown or invalid", () => {
|
|
3609
|
+
assert.equal(isExistingTmuxWindowTooCrampedForLaunchHud(null), false);
|
|
3610
|
+
assert.equal(isExistingTmuxWindowTooCrampedForLaunchHud(undefined), false);
|
|
3611
|
+
assert.equal(isExistingTmuxWindowTooCrampedForLaunchHud(0), false);
|
|
3612
|
+
assert.equal(isExistingTmuxWindowTooCrampedForLaunchHud(Number.NaN), false);
|
|
3613
|
+
});
|
|
3614
|
+
it("honors an explicit minimum-height override", () => {
|
|
3615
|
+
assert.equal(isExistingTmuxWindowTooCrampedForLaunchHud(41, 40), false);
|
|
3616
|
+
assert.equal(isExistingTmuxWindowTooCrampedForLaunchHud(39, 40), true);
|
|
3617
|
+
});
|
|
3618
|
+
});
|
|
3619
|
+
//# sourceMappingURL=index.test.js.map
|