oh-my-codex 0.20.2 → 0.20.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +7 -6
- package/Cargo.toml +1 -1
- package/README.md +26 -0
- package/crates/omx-runtime/Cargo.toml +1 -0
- package/crates/omx-runtime/src/main.rs +25 -2
- package/crates/omx-runtime/tests/execution.rs +219 -0
- package/crates/omx-runtime-core/src/dispatch.rs +96 -10
- package/crates/omx-runtime-core/src/engine.rs +839 -29
- package/crates/omx-runtime-core/src/lib.rs +8 -0
- package/dist/agents/__tests__/definitions.test.js +81 -0
- package/dist/agents/__tests__/definitions.test.js.map +1 -1
- package/dist/agents/__tests__/native-config.test.js +25 -0
- package/dist/agents/__tests__/native-config.test.js.map +1 -1
- package/dist/agents/native-config.d.ts +2 -1
- package/dist/agents/native-config.d.ts.map +1 -1
- package/dist/agents/native-config.js.map +1 -1
- package/dist/auth/hotswap.d.ts +6 -0
- package/dist/auth/hotswap.d.ts.map +1 -1
- package/dist/auth/hotswap.js +85 -15
- package/dist/auth/hotswap.js.map +1 -1
- package/dist/autopilot/__tests__/ralplan-gate.test.js +1 -1
- package/dist/autopilot/__tests__/ralplan-gate.test.js.map +1 -1
- package/dist/cli/__tests__/auth.test.js +60 -6
- package/dist/cli/__tests__/auth.test.js.map +1 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js +80 -0
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js +103 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/exec.test.js +136 -0
- package/dist/cli/__tests__/exec.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +258 -4
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/launch-fallback.test.js +287 -1
- package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
- package/dist/cli/__tests__/mcp-parity.test.js +4 -1
- package/dist/cli/__tests__/mcp-parity.test.js.map +1 -1
- package/dist/cli/__tests__/native-hook-claim-journal.test.js +84 -6
- package/dist/cli/__tests__/native-hook-claim-journal.test.js.map +1 -1
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +3 -3
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
- package/dist/cli/__tests__/ralph.test.js +3 -3
- package/dist/cli/__tests__/ralph.test.js.map +1 -1
- package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js +56 -171
- package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js.map +1 -1
- package/dist/cli/__tests__/ralplan.test.js +37 -111
- package/dist/cli/__tests__/ralplan.test.js.map +1 -1
- package/dist/cli/__tests__/resume.test.js +11 -10
- package/dist/cli/__tests__/resume.test.js.map +1 -1
- package/dist/cli/__tests__/session-search-help.test.js +25 -1
- package/dist/cli/__tests__/session-search-help.test.js.map +1 -1
- package/dist/cli/__tests__/setup-install-mode.test.js +42 -4
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
- package/dist/cli/__tests__/team.test.js +105 -7
- package/dist/cli/__tests__/team.test.js.map +1 -1
- package/dist/cli/__tests__/uninstall.test.js +46 -0
- package/dist/cli/__tests__/uninstall.test.js.map +1 -1
- package/dist/cli/__tests__/windows-popup-loop-contract.test.js +2 -1
- package/dist/cli/__tests__/windows-popup-loop-contract.test.js.map +1 -1
- package/dist/cli/doctor.d.ts +3 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +15 -2
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.d.ts +4 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +138 -38
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-parity.js +2 -2
- package/dist/cli/mcp-parity.js.map +1 -1
- package/dist/cli/native-hook-claim-journal.d.ts +16 -5
- package/dist/cli/native-hook-claim-journal.d.ts.map +1 -1
- package/dist/cli/native-hook-claim-journal.js +42 -29
- package/dist/cli/native-hook-claim-journal.js.map +1 -1
- package/dist/cli/ralph.js +2 -2
- package/dist/cli/ralph.js.map +1 -1
- package/dist/cli/ralplan.d.ts +4 -8
- package/dist/cli/ralplan.d.ts.map +1 -1
- package/dist/cli/ralplan.js +19 -112
- package/dist/cli/ralplan.js.map +1 -1
- package/dist/cli/session-search.d.ts +5 -0
- package/dist/cli/session-search.d.ts.map +1 -1
- package/dist/cli/session-search.js +87 -0
- package/dist/cli/session-search.js.map +1 -1
- package/dist/cli/setup.d.ts +5 -0
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +80 -31
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/uninstall.d.ts +9 -0
- package/dist/cli/uninstall.d.ts.map +1 -1
- package/dist/cli/uninstall.js +61 -19
- package/dist/cli/uninstall.js.map +1 -1
- package/dist/compat/__tests__/rust-runtime-compat.test.js +1 -1
- package/dist/config/__tests__/generator-idempotent.test.js +330 -1
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
- package/dist/config/__tests__/generator-notify.test.js +2 -2
- package/dist/config/__tests__/generator-notify.test.js.map +1 -1
- package/dist/config/__tests__/models.test.js +67 -3
- package/dist/config/__tests__/models.test.js.map +1 -1
- package/dist/config/generator.d.ts +4 -20
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +499 -119
- package/dist/config/generator.js.map +1 -1
- package/dist/config/models.d.ts +12 -2
- package/dist/config/models.d.ts.map +1 -1
- package/dist/config/models.js +15 -1
- package/dist/config/models.js.map +1 -1
- package/dist/hooks/__tests__/agents-overlay.test.js +2 -2
- package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +4 -4
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js +238 -543
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +38 -4
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +96 -9
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +531 -12
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +155 -23
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +482 -32
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +68 -1
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js +7 -1
- package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +43 -4
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
- package/dist/hooks/__tests__/session.test.js +348 -2
- package/dist/hooks/__tests__/session.test.js.map +1 -1
- package/dist/hooks/agents-overlay.js +1 -1
- package/dist/hooks/session.d.ts +26 -2
- package/dist/hooks/session.d.ts.map +1 -1
- package/dist/hooks/session.js +169 -13
- package/dist/hooks/session.js.map +1 -1
- package/dist/leader/__tests__/contract.test.js +57 -7
- package/dist/leader/__tests__/contract.test.js.map +1 -1
- package/dist/leader/contract.d.ts +16 -0
- package/dist/leader/contract.d.ts.map +1 -1
- package/dist/leader/contract.js +79 -4
- package/dist/leader/contract.js.map +1 -1
- package/dist/mcp/__tests__/code-intel-server.test.js +31 -3
- package/dist/mcp/__tests__/code-intel-server.test.js.map +1 -1
- package/dist/mcp/__tests__/wiki-server.test.js +18 -0
- package/dist/mcp/__tests__/wiki-server.test.js.map +1 -1
- package/dist/mcp/code-intel-server.d.ts.map +1 -1
- package/dist/mcp/code-intel-server.js +13 -3
- package/dist/mcp/code-intel-server.js.map +1 -1
- package/dist/mcp/wiki-server.d.ts +11 -0
- package/dist/mcp/wiki-server.d.ts.map +1 -1
- package/dist/mcp/wiki-server.js +9 -2
- package/dist/mcp/wiki-server.js.map +1 -1
- package/dist/modes/__tests__/base-tmux-pane.test.js +4 -4
- package/dist/modes/__tests__/base-tmux-pane.test.js.map +1 -1
- package/dist/notifications/temp-contract.d.ts.map +1 -1
- package/dist/notifications/temp-contract.js +4 -0
- package/dist/notifications/temp-contract.js.map +1 -1
- package/dist/pipeline/__tests__/orchestrator.test.js +4 -4
- package/dist/pipeline/__tests__/orchestrator.test.js.map +1 -1
- package/dist/pipeline/__tests__/stages.test.js +8 -8
- package/dist/pipeline/__tests__/stages.test.js.map +1 -1
- package/dist/ralplan/__tests__/consensus-gate.test.js +134 -10
- package/dist/ralplan/__tests__/consensus-gate.test.js.map +1 -1
- package/dist/ralplan/__tests__/documented-leader-preflight.test.d.ts +2 -0
- package/dist/ralplan/__tests__/documented-leader-preflight.test.d.ts.map +1 -0
- package/dist/ralplan/__tests__/documented-leader-preflight.test.js +46 -0
- package/dist/ralplan/__tests__/documented-leader-preflight.test.js.map +1 -0
- package/dist/ralplan/__tests__/runtime.test.js +8 -4
- package/dist/ralplan/__tests__/runtime.test.js.map +1 -1
- package/dist/ralplan/consensus-gate.d.ts.map +1 -1
- package/dist/ralplan/consensus-gate.js +58 -50
- package/dist/ralplan/consensus-gate.js.map +1 -1
- package/dist/ralplan/documented-leader-preflight.d.ts +34 -0
- package/dist/ralplan/documented-leader-preflight.d.ts.map +1 -0
- package/dist/ralplan/documented-leader-preflight.js +58 -0
- package/dist/ralplan/documented-leader-preflight.js.map +1 -0
- package/dist/ralplan/runtime.d.ts +1 -0
- package/dist/ralplan/runtime.d.ts.map +1 -1
- package/dist/ralplan/runtime.js +11 -7
- package/dist/ralplan/runtime.js.map +1 -1
- package/dist/runtime/__tests__/bridge.test.js +42 -1
- package/dist/runtime/__tests__/bridge.test.js.map +1 -1
- package/dist/runtime/bridge.d.ts +12 -0
- package/dist/runtime/bridge.d.ts.map +1 -1
- package/dist/runtime/bridge.js +52 -1
- package/dist/runtime/bridge.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +2620 -487
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/reasoning-artifact-contract.test.d.ts +2 -0
- package/dist/scripts/__tests__/reasoning-artifact-contract.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/reasoning-artifact-contract.test.js +108 -0
- package/dist/scripts/__tests__/reasoning-artifact-contract.test.js.map +1 -0
- package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js +46 -173
- package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js.map +1 -1
- package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js +39 -159
- package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js.map +1 -1
- package/dist/scripts/__tests__/smoke-packed-install.test.js +254 -2
- package/dist/scripts/__tests__/smoke-packed-install.test.js.map +1 -1
- package/dist/scripts/codex-native-hook.d.ts +4 -1
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +11013 -1153
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/notify-fallback-watcher.js +82 -108
- package/dist/scripts/notify-fallback-watcher.js.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.js +74 -3
- package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/team-dispatch.d.ts +9 -0
- package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-dispatch.js +234 -79
- package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.js +39 -13
- package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.d.ts +12 -4
- package/dist/scripts/notify-hook/team-tmux-guard.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.js +365 -44
- package/dist/scripts/notify-hook/team-tmux-guard.js.map +1 -1
- package/dist/scripts/notify-hook/team-worker-stop.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-worker-stop.js +19 -18
- package/dist/scripts/notify-hook/team-worker-stop.js.map +1 -1
- package/dist/scripts/notify-hook/team-worker.d.ts +3 -0
- package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-worker.js +37 -28
- package/dist/scripts/notify-hook/team-worker.js.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.js +28 -2
- package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
- package/dist/scripts/notify-hook.js +1 -0
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/scripts/smoke-packed-install.d.ts +48 -3
- package/dist/scripts/smoke-packed-install.d.ts.map +1 -1
- package/dist/scripts/smoke-packed-install.js +2796 -13
- package/dist/scripts/smoke-packed-install.js.map +1 -1
- package/dist/state/__tests__/mode-state-context.test.js +54 -0
- package/dist/state/__tests__/mode-state-context.test.js.map +1 -1
- package/dist/state/__tests__/operations.test.js +2 -0
- package/dist/state/__tests__/operations.test.js.map +1 -1
- package/dist/state/mode-state-context.d.ts +5 -0
- package/dist/state/mode-state-context.d.ts.map +1 -1
- package/dist/state/mode-state-context.js +59 -0
- package/dist/state/mode-state-context.js.map +1 -1
- package/dist/subagents/__tests__/leader-bootstrap-3181.test.js +24 -245
- package/dist/subagents/__tests__/leader-bootstrap-3181.test.js.map +1 -1
- package/dist/subagents/tracker.d.ts +1 -82
- package/dist/subagents/tracker.d.ts.map +1 -1
- package/dist/subagents/tracker.js +3 -275
- package/dist/subagents/tracker.js.map +1 -1
- package/dist/team/__tests__/api-interop.test.js +91 -1
- package/dist/team/__tests__/api-interop.test.js.map +1 -1
- package/dist/team/__tests__/delivery-e2e-smoke.test.js +52 -10
- package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +1 -1
- package/dist/team/__tests__/idle-nudge.test.js +45 -15
- package/dist/team/__tests__/idle-nudge.test.js.map +1 -1
- package/dist/team/__tests__/mcp-comm.test.js +93 -27
- package/dist/team/__tests__/mcp-comm.test.js.map +1 -1
- package/dist/team/__tests__/model-contract.test.js +110 -3
- package/dist/team/__tests__/model-contract.test.js.map +1 -1
- package/dist/team/__tests__/runtime-cli.test.js +9 -0
- package/dist/team/__tests__/runtime-cli.test.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +3204 -335
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/scaling.test.js +2359 -142
- package/dist/team/__tests__/scaling.test.js.map +1 -1
- package/dist/team/__tests__/state.test.js +804 -36
- package/dist/team/__tests__/state.test.js.map +1 -1
- package/dist/team/__tests__/team-ops-contract.test.js +6 -0
- package/dist/team/__tests__/team-ops-contract.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +3049 -784
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/__tests__/worker-runtime-identity.test.js +38 -2
- package/dist/team/__tests__/worker-runtime-identity.test.js.map +1 -1
- package/dist/team/__tests__/worktree.test.js +6 -0
- package/dist/team/__tests__/worktree.test.js.map +1 -1
- package/dist/team/api-interop.d.ts.map +1 -1
- package/dist/team/api-interop.js +15 -9
- package/dist/team/api-interop.js.map +1 -1
- package/dist/team/exact-pane.d.ts +23 -0
- package/dist/team/exact-pane.d.ts.map +1 -0
- package/dist/team/exact-pane.js +133 -0
- package/dist/team/exact-pane.js.map +1 -0
- package/dist/team/idle-nudge.d.ts +12 -1
- package/dist/team/idle-nudge.d.ts.map +1 -1
- package/dist/team/idle-nudge.js +41 -14
- package/dist/team/idle-nudge.js.map +1 -1
- package/dist/team/model-contract.d.ts +2 -5
- package/dist/team/model-contract.d.ts.map +1 -1
- package/dist/team/model-contract.js +59 -17
- package/dist/team/model-contract.js.map +1 -1
- package/dist/team/runtime.d.ts +1 -0
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +1244 -180
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/scaling.d.ts +13 -1
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +1430 -384
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/state/dispatch.d.ts.map +1 -1
- package/dist/team/state/dispatch.js +26 -8
- package/dist/team/state/dispatch.js.map +1 -1
- package/dist/team/state/locks.d.ts.map +1 -1
- package/dist/team/state/locks.js +61 -13
- package/dist/team/state/locks.js.map +1 -1
- package/dist/team/state/tasks.d.ts.map +1 -1
- package/dist/team/state/tasks.js +4 -3
- package/dist/team/state/tasks.js.map +1 -1
- package/dist/team/state.d.ts +67 -1
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +636 -129
- package/dist/team/state.js.map +1 -1
- package/dist/team/team-ops.d.ts +5 -0
- package/dist/team/team-ops.d.ts.map +1 -1
- package/dist/team/team-ops.js +4 -0
- package/dist/team/team-ops.js.map +1 -1
- package/dist/team/tmux-session.d.ts +123 -23
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +1250 -291
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/worktree.d.ts.map +1 -1
- package/dist/team/worktree.js +4 -0
- package/dist/team/worktree.js.map +1 -1
- package/dist/utils/__tests__/file-durability.test.d.ts +2 -0
- package/dist/utils/__tests__/file-durability.test.d.ts.map +1 -0
- package/dist/utils/__tests__/file-durability.test.js +57 -0
- package/dist/utils/__tests__/file-durability.test.js.map +1 -0
- package/dist/utils/file-durability.d.ts +15 -0
- package/dist/utils/file-durability.d.ts.map +1 -0
- package/dist/utils/file-durability.js +37 -0
- package/dist/utils/file-durability.js.map +1 -0
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js +3 -0
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js.map +1 -1
- package/dist/wiki/lint.d.ts +4 -1
- package/dist/wiki/lint.d.ts.map +1 -1
- package/dist/wiki/lint.js +3 -2
- package/dist/wiki/lint.js.map +1 -1
- package/package.json +1 -1
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +24 -0
- package/plugins/oh-my-codex/skills/ralph/SKILL.md +6 -4
- package/plugins/oh-my-codex/skills/ralplan/SKILL.md +3 -2
- package/plugins/oh-my-codex/skills/team/SKILL.md +13 -9
- package/skills/ralph/SKILL.md +6 -4
- package/skills/ralplan/SKILL.md +3 -2
- package/skills/team/SKILL.md +13 -9
- package/src/scripts/__tests__/codex-native-hook.test.ts +2826 -497
- package/src/scripts/__tests__/reasoning-artifact-contract.test.ts +129 -0
- package/src/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.ts +48 -185
- package/src/scripts/__tests__/role-intent-durable-recovery-3181.test.ts +44 -177
- package/src/scripts/__tests__/smoke-packed-install.test.ts +320 -2
- package/src/scripts/codex-native-hook.ts +10715 -1069
- package/src/scripts/notify-fallback-watcher.ts +84 -115
- package/src/scripts/notify-hook/auto-nudge.ts +71 -3
- package/src/scripts/notify-hook/team-dispatch.ts +242 -75
- package/src/scripts/notify-hook/team-leader-nudge.ts +40 -18
- package/src/scripts/notify-hook/team-tmux-guard.ts +366 -39
- package/src/scripts/notify-hook/team-worker-stop.ts +20 -16
- package/src/scripts/notify-hook/team-worker.ts +39 -26
- package/src/scripts/notify-hook/tmux-injection.ts +28 -2
- package/src/scripts/notify-hook.ts +1 -0
- package/src/scripts/smoke-packed-install.ts +3196 -14
- package/dist/subagents/__tests__/adapted-role-binding.test.d.ts +0 -2
- package/dist/subagents/__tests__/adapted-role-binding.test.d.ts.map +0 -1
- package/dist/subagents/__tests__/adapted-role-binding.test.js +0 -988
- package/dist/subagents/__tests__/adapted-role-binding.test.js.map +0 -1
- package/dist/subagents/adapted-role-binding.d.ts +0 -17
- package/dist/subagents/adapted-role-binding.d.ts.map +0 -1
- package/dist/subagents/adapted-role-binding.js +0 -75
- package/dist/subagents/adapted-role-binding.js.map +0 -1
package/dist/config/generator.js
CHANGED
|
@@ -37,8 +37,8 @@ const LEGACY_SEEDED_MODEL_CONTEXT_WINDOW = 250000;
|
|
|
37
37
|
const LEGACY_SEEDED_MODEL_AUTO_COMPACT_TOKEN_LIMIT = 200000;
|
|
38
38
|
const OMX_SEEDED_BEHAVIORAL_DEFAULTS_START_MARKER = "# oh-my-codex seeded behavioral defaults (uninstall removes unchanged defaults)";
|
|
39
39
|
const OMX_SEEDED_BEHAVIORAL_DEFAULTS_END_MARKER = "# End oh-my-codex seeded behavioral defaults";
|
|
40
|
-
export const OMX_DEVELOPER_INSTRUCTIONS = "You have oh-my-codex installed. AGENTS.md is the orchestration brain and main control surface. Follow AGENTS.md for skill/keyword routing, $name workflow invocation, and role-specialized subagents; when the native surface exposes `agent_type` role routing, set `agent_type` to an installed role and never omit it for OMX work. When it
|
|
41
|
-
export const OMX_PLUGIN_DEVELOPER_INSTRUCTIONS = '<omx version="1">You have oh-my-codex installed through Codex plugin mode. AGENTS.md is the orchestration brain and main control surface. Follow AGENTS.md for skill/keyword routing and $name workflow invocation. When the native surface exposes `agent_type` role routing, set `agent_type` to an installed role and never omit it for OMX work. When it
|
|
40
|
+
export const OMX_DEVELOPER_INSTRUCTIONS = "You have oh-my-codex installed. AGENTS.md is the orchestration brain and main control surface. Follow AGENTS.md for skill/keyword routing, $name workflow invocation, and role-specialized subagents; when the native surface exposes `agent_type` role routing, set `agent_type` to an installed role and never omit it for OMX work. When it reports `role_routing_unavailable`, do not fabricate `agent_type`; before Ralplan planning, state, HUD, runtime, or delegation work, run `omx ralplan preflight --json` and stop on `unsupported_documented_leader_proof`. Never fake the role via a prompt label or infer authority from session/thread/pointer/transcript/cwd state. Use outcome-first, concise progress updates: state the target result, constraints, validation evidence, and stop condition before adding process detail. Native subagents live in .codex/agents and may handle independent parallel subtasks within one Codex session or team pane. Skills load from .codex/skills, not native-agent TOMLs. Treat installed prompts as narrower execution surfaces under AGENTS.md authority.";
|
|
41
|
+
export const OMX_PLUGIN_DEVELOPER_INSTRUCTIONS = '<omx version="1">You have oh-my-codex installed through Codex plugin mode. AGENTS.md is the orchestration brain and main control surface. Follow AGENTS.md for skill/keyword routing and $name workflow invocation. When the native surface exposes `agent_type` role routing, set `agent_type` to an installed role and never omit it for OMX work. When it reports `role_routing_unavailable`, do not fabricate `agent_type`; before Ralplan planning, state, HUD, runtime, or delegation work, run `omx ralplan preflight --json` and stop on `unsupported_documented_leader_proof`. Never fake the role via a prompt label or infer authority from session/thread/pointer/transcript/cwd state. Registered Codex plugin marketplace surfaces supply OMX workflows and plugin-scoped companion resources when the plugin is installed; native agent roles are installed as setup-owned Codex agent TOML files in plugin mode so agent_type routing works. User-installed skills may still live under ~/.codex/skills. Use outcome-first, concise progress updates: state the target result, constraints, validation evidence, and stop condition before adding process detail.</omx>';
|
|
42
42
|
const SHARED_MCP_REGISTRY_MARKER = "oh-my-codex (OMX) Shared MCP Registry Sync";
|
|
43
43
|
const SHARED_MCP_REGISTRY_END_MARKER = "# End oh-my-codex shared MCP registry sync";
|
|
44
44
|
const LEGACY_MULTI_AGENT_KEYS = [
|
|
@@ -653,45 +653,8 @@ const OMX_HOOK_TRUST_START_MARKER = "# OMX-owned Codex hook trust state";
|
|
|
653
653
|
const OMX_HOOK_TRUST_END_MARKER = "# End OMX-owned Codex hook trust state";
|
|
654
654
|
const OMX_PROJECT_TRUST_START_MARKER = "# OMX-synced Codex project trust state (from runtime CODEX_HOME)";
|
|
655
655
|
const OMX_PROJECT_TRUST_END_MARKER = "# End OMX-synced Codex project trust state";
|
|
656
|
-
function extractMarkerBlockContent(config, startMarker, endMarker) {
|
|
657
|
-
const lines = config.split(/\r?\n/);
|
|
658
|
-
for (let i = 0; i < lines.length; i++) {
|
|
659
|
-
if (lines[i].trim() !== startMarker)
|
|
660
|
-
continue;
|
|
661
|
-
const nextEndIdx = lines.findIndex((line, index) => index > i && line.trim() === endMarker);
|
|
662
|
-
const nextStartIdx = lines.findIndex((line, index) => index > i && line.trim() === startMarker);
|
|
663
|
-
if (nextEndIdx === -1 || (nextStartIdx !== -1 && nextStartIdx < nextEndIdx)) {
|
|
664
|
-
return undefined;
|
|
665
|
-
}
|
|
666
|
-
return lines.slice(i + 1, nextEndIdx).join("\n").trim();
|
|
667
|
-
}
|
|
668
|
-
return undefined;
|
|
669
|
-
}
|
|
670
|
-
function stripMarkerBlock(config, startMarker, endMarker) {
|
|
671
|
-
const lines = config.split(/\r?\n/);
|
|
672
|
-
const kept = [];
|
|
673
|
-
for (let i = 0; i < lines.length;) {
|
|
674
|
-
if (lines[i].trim() !== startMarker) {
|
|
675
|
-
kept.push(lines[i]);
|
|
676
|
-
i += 1;
|
|
677
|
-
continue;
|
|
678
|
-
}
|
|
679
|
-
const nextEndIdx = lines.findIndex((line, index) => index > i && line.trim() === endMarker);
|
|
680
|
-
const nextStartIdx = lines.findIndex((line, index) => index > i && line.trim() === startMarker);
|
|
681
|
-
if (nextEndIdx === -1 || (nextStartIdx !== -1 && nextStartIdx < nextEndIdx)) {
|
|
682
|
-
kept.push(lines[i]);
|
|
683
|
-
i += 1;
|
|
684
|
-
continue;
|
|
685
|
-
}
|
|
686
|
-
i = nextEndIdx + 1;
|
|
687
|
-
}
|
|
688
|
-
return kept.join("\n").replace(/\n{3,}/g, "\n\n").trimEnd();
|
|
689
|
-
}
|
|
690
656
|
function isPlainTomlRecord(value) {
|
|
691
|
-
return
|
|
692
|
-
value !== null &&
|
|
693
|
-
!Array.isArray(value) &&
|
|
694
|
-
Object.getPrototypeOf(value) === Object.prototype);
|
|
657
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
|
|
695
658
|
}
|
|
696
659
|
function safeParseToml(content) {
|
|
697
660
|
try {
|
|
@@ -702,97 +665,514 @@ function safeParseToml(content) {
|
|
|
702
665
|
return undefined;
|
|
703
666
|
}
|
|
704
667
|
}
|
|
705
|
-
function
|
|
706
|
-
const
|
|
707
|
-
const
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
668
|
+
function projectHookTrustState(config) {
|
|
669
|
+
const hooks = safeParseToml(config)?.hooks;
|
|
670
|
+
const state = isPlainTomlRecord(hooks) ? hooks.state : undefined;
|
|
671
|
+
return isPlainTomlRecord(state) ? state : undefined;
|
|
672
|
+
}
|
|
673
|
+
function projectTrustSemanticView(config) {
|
|
674
|
+
const hasLeadingBom = config.startsWith("\uFEFF");
|
|
675
|
+
const source = hasLeadingBom ? config.slice(1) : config;
|
|
676
|
+
if (source.includes("\uFEFF"))
|
|
677
|
+
return undefined;
|
|
678
|
+
return { source, prefix: hasLeadingBom ? "\uFEFF" : "" };
|
|
679
|
+
}
|
|
680
|
+
function projectTrustMarkerRange(config) {
|
|
681
|
+
const lexical = analyzeTomlSource(config);
|
|
682
|
+
if (!lexical.isUnambiguous)
|
|
683
|
+
return undefined;
|
|
684
|
+
const lines = sourceLines(config);
|
|
685
|
+
const starts = lines.filter((line, index) => lexical.lineStartsOutsideMultiline[index] && line.content.trim() === OMX_PROJECT_TRUST_START_MARKER);
|
|
686
|
+
const ends = lines.filter((line, index) => lexical.lineStartsOutsideMultiline[index] && line.content.trim() === OMX_PROJECT_TRUST_END_MARKER);
|
|
687
|
+
if (starts.length === 0 && ends.length === 0)
|
|
688
|
+
return { start: config.length, end: config.length, payloadStart: config.length, payloadEnd: config.length };
|
|
689
|
+
if (starts.length !== 1 || ends.length !== 1 || starts[0].start >= ends[0].start)
|
|
690
|
+
return undefined;
|
|
691
|
+
const start = starts[0];
|
|
692
|
+
const end = ends[0];
|
|
693
|
+
return { start: start.start, end: end.end, payloadStart: start.end, payloadEnd: end.start };
|
|
694
|
+
}
|
|
695
|
+
function hasInlineProjectTrustMarkerComment(config) {
|
|
696
|
+
const lexical = analyzeTomlSource(config);
|
|
697
|
+
return sourceLines(config).some((line, index) => {
|
|
698
|
+
if (!lexical.lineStartsOutsideMultiline[index])
|
|
699
|
+
return false;
|
|
700
|
+
const trimmed = line.content.trim();
|
|
701
|
+
return (trimmed.startsWith(OMX_PROJECT_TRUST_START_MARKER) && trimmed !== OMX_PROJECT_TRUST_START_MARKER) ||
|
|
702
|
+
(trimmed.startsWith(OMX_PROJECT_TRUST_END_MARKER) && trimmed !== OMX_PROJECT_TRUST_END_MARKER);
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
function projectTrustHeaderPath(line) {
|
|
706
|
+
if (/^\s*\[\[/.test(line))
|
|
707
|
+
return undefined;
|
|
708
|
+
const header = parseTomlSourceTableHeader(line);
|
|
709
|
+
if (!header?.parsed)
|
|
710
|
+
return undefined;
|
|
711
|
+
const path = [];
|
|
712
|
+
let cursor = header.parsed;
|
|
713
|
+
while (isPlainTomlRecord(cursor)) {
|
|
714
|
+
const keys = Object.keys(cursor);
|
|
715
|
+
if (keys.length === 0)
|
|
716
|
+
return path;
|
|
717
|
+
if (keys.length !== 1)
|
|
718
|
+
return undefined;
|
|
719
|
+
const key = keys[0];
|
|
720
|
+
path.push(key);
|
|
721
|
+
cursor = cursor[key];
|
|
716
722
|
}
|
|
717
|
-
return
|
|
723
|
+
return path;
|
|
718
724
|
}
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
const
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
725
|
+
function dominantProjectTrustEol(source) {
|
|
726
|
+
const crlfCount = (source.match(/\r\n/g) ?? []).length;
|
|
727
|
+
const lfCount = (source.match(/(?<!\r)\n/g) ?? []).length;
|
|
728
|
+
return crlfCount > lfCount ? "\r\n" : "\n";
|
|
729
|
+
}
|
|
730
|
+
function projectTrustPayloadIsSemanticallyEmpty(payload) {
|
|
731
|
+
const parsed = safeParseToml(payload);
|
|
732
|
+
return parsed !== undefined && Object.keys(parsed).length === 0;
|
|
733
|
+
}
|
|
734
|
+
function projectTrustValueAtPath(source, path) {
|
|
735
|
+
let value = source;
|
|
736
|
+
for (const key of path) {
|
|
737
|
+
if (!isPlainTomlRecord(value))
|
|
738
|
+
return undefined;
|
|
739
|
+
value = value[key];
|
|
740
|
+
}
|
|
741
|
+
return value;
|
|
731
742
|
}
|
|
732
743
|
/**
|
|
733
|
-
*
|
|
734
|
-
*
|
|
735
|
-
* hook trust ledger into the runtime config.toml during the session. Without
|
|
736
|
-
* persistence, those entries die with the runtime, so Codex prompts to trust
|
|
737
|
-
* the workspace and hooks on every launch (issue #2470).
|
|
738
|
-
*
|
|
739
|
-
* This function extracts only trust-state tables (`[projects."<cwd>"]` and
|
|
740
|
-
* `[hooks.state."<projectHooksPath>:..."]`) from the runtime config.toml and
|
|
741
|
-
* upserts them into the durable project config.toml inside a marker-fenced
|
|
742
|
-
* block, preserving any surrounding user-managed content and comments and
|
|
743
|
-
* ignoring Codex's NUX counters or other ephemeral runtime-only writes.
|
|
744
|
+
* Marker contents are an ownership boundary, not general TOML. Reject every
|
|
745
|
+
* source form that OMX did not emit rather than rebuilding it and losing data.
|
|
744
746
|
*/
|
|
745
|
-
|
|
746
|
-
const parsed = safeParseToml(
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
continue;
|
|
765
|
-
trustBlockLines.push(renderedHeader, body, "");
|
|
747
|
+
function inventoryProjectTrustPayload(payload, projectHooksPath) {
|
|
748
|
+
const parsed = safeParseToml(payload);
|
|
749
|
+
const lexical = analyzeTomlSource(payload);
|
|
750
|
+
const headers = projectTrustHeaders(payload, { start: 0, end: payload.length });
|
|
751
|
+
if (!parsed || !lexical.isUnambiguous || !headers)
|
|
752
|
+
return undefined;
|
|
753
|
+
if (Object.keys(parsed).some((key) => key !== "projects" && key !== "hooks"))
|
|
754
|
+
return undefined;
|
|
755
|
+
const lines = sourceLines(payload);
|
|
756
|
+
const headerStarts = new Set(headers.map((header) => header.start));
|
|
757
|
+
for (const [index, line] of lines.entries()) {
|
|
758
|
+
if (!lexical.lineStartsOutsideMultiline[index])
|
|
759
|
+
return undefined;
|
|
760
|
+
const isHeader = headerStarts.has(line.start);
|
|
761
|
+
const isBlankOrComment = line.content.trim() === "" || /^\s*#/.test(line.content);
|
|
762
|
+
if (isHeader || isBlankOrComment) {
|
|
763
|
+
if (isHeader && lexical.lineHasTomlComment[index])
|
|
764
|
+
return undefined;
|
|
765
|
+
continue;
|
|
766
766
|
}
|
|
767
|
+
if (lexical.lineHasTomlComment[index])
|
|
768
|
+
return undefined;
|
|
769
|
+
const priorHeader = headers.some((header) => header.start < line.start);
|
|
770
|
+
if (!priorHeader)
|
|
771
|
+
return undefined;
|
|
767
772
|
}
|
|
768
|
-
const
|
|
769
|
-
const
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
773
|
+
const managedHeaders = [];
|
|
774
|
+
for (const header of headers) {
|
|
775
|
+
if (header.path[0] === "projects" && header.path.length >= 2) {
|
|
776
|
+
if (!isPlainTomlRecord(projectTrustValueAtPath(parsed, header.path)))
|
|
777
|
+
return undefined;
|
|
778
|
+
managedHeaders.push({ ...header, kind: "project" });
|
|
779
|
+
continue;
|
|
780
|
+
}
|
|
781
|
+
if (header.path[0] === "hooks" &&
|
|
782
|
+
header.path[1] === "state" &&
|
|
783
|
+
header.path.length === 3 &&
|
|
784
|
+
header.path[2].startsWith(`${projectHooksPath}:`)) {
|
|
785
|
+
const value = projectTrustValueAtPath(parsed, header.path);
|
|
786
|
+
if (!isPlainTomlRecord(value) || typeof value.trusted_hash !== "string" || value.trusted_hash.length === 0 || Object.keys(value).some((key) => key !== "trusted_hash"))
|
|
787
|
+
return undefined;
|
|
788
|
+
managedHeaders.push({ ...header, kind: "hook" });
|
|
789
|
+
continue;
|
|
790
|
+
}
|
|
791
|
+
return undefined;
|
|
792
|
+
}
|
|
793
|
+
if (!projectTrustPayloadProjectFamiliesAreValid(managedHeaders))
|
|
794
|
+
return undefined;
|
|
795
|
+
if (!projectTrustPayloadNestedStructuresAreExplicit(parsed, managedHeaders))
|
|
796
|
+
return undefined;
|
|
797
|
+
return { parsed, headers: managedHeaders };
|
|
798
|
+
}
|
|
799
|
+
function projectTrustSourceNestedStructuresAreExplicit(parsed, headers) {
|
|
800
|
+
const projects = parsed.projects;
|
|
801
|
+
if (projects === undefined)
|
|
802
|
+
return true;
|
|
803
|
+
if (!isPlainTomlRecord(projects))
|
|
804
|
+
return false;
|
|
805
|
+
const hasHeader = (path) => headers.some((header) => projectTrustEqual(header.path, path));
|
|
806
|
+
const visit = (value, path) => {
|
|
807
|
+
for (const [key, child] of Object.entries(value)) {
|
|
808
|
+
if (!isPlainTomlRecord(child))
|
|
777
809
|
continue;
|
|
778
|
-
const
|
|
779
|
-
if (
|
|
810
|
+
const childPath = [...path, key];
|
|
811
|
+
if (!hasHeader(childPath) || !visit(child, childPath))
|
|
812
|
+
return false;
|
|
813
|
+
}
|
|
814
|
+
return true;
|
|
815
|
+
};
|
|
816
|
+
return Object.entries(projects).every(([key, value]) => isPlainTomlRecord(value) && hasHeader(["projects", key]) && visit(value, ["projects", key]));
|
|
817
|
+
}
|
|
818
|
+
function projectTrustPayloadNestedStructuresAreExplicit(parsed, headers) {
|
|
819
|
+
const hasHeader = (path) => headers.some((header) => header.kind === "project" && projectTrustEqual(header.path, path));
|
|
820
|
+
const visit = (value, path) => {
|
|
821
|
+
for (const [key, child] of Object.entries(value)) {
|
|
822
|
+
if (!isPlainTomlRecord(child))
|
|
780
823
|
continue;
|
|
781
|
-
|
|
824
|
+
const childPath = [...path, key];
|
|
825
|
+
if (!hasHeader(childPath) || !visit(child, childPath))
|
|
826
|
+
return false;
|
|
827
|
+
}
|
|
828
|
+
return true;
|
|
829
|
+
};
|
|
830
|
+
return headers
|
|
831
|
+
.filter((header) => header.kind === "project" && header.path.length === 2)
|
|
832
|
+
.every((header) => {
|
|
833
|
+
const value = projectTrustValueAtPath(parsed, header.path);
|
|
834
|
+
return isPlainTomlRecord(value) && visit(value, header.path);
|
|
835
|
+
});
|
|
836
|
+
}
|
|
837
|
+
function projectTrustPayloadTableSpan(source) {
|
|
838
|
+
const lines = sourceLines(source);
|
|
839
|
+
const lastBodyLine = lines
|
|
840
|
+
.slice(1)
|
|
841
|
+
.reverse()
|
|
842
|
+
.find((line) => line.content.trim() !== "" && !/^\s*#/.test(line.content));
|
|
843
|
+
if (!lastBodyLine)
|
|
844
|
+
return { source, gap: "" };
|
|
845
|
+
const bodyEnd = lastBodyLine.end;
|
|
846
|
+
return { source: source.slice(0, bodyEnd), gap: source.slice(bodyEnd) };
|
|
847
|
+
}
|
|
848
|
+
function projectTrustPayloadTableBodyHasCommentsOrBlanks(source) {
|
|
849
|
+
return sourceLines(source).some((line) => line.content.trim() === "" || /^\s*#/.test(line.content));
|
|
850
|
+
}
|
|
851
|
+
function reconcileProjectTrustPayload(payload, payloadInventory, externalProjects, runtimeProjects, runtimeHooksState, externalHookTrustState, projectHooksPath, eol) {
|
|
852
|
+
const { headers } = payloadInventory;
|
|
853
|
+
const payloadProjectKeys = new Set(headers.filter((header) => header.kind === "project").map((header) => header.path[1]));
|
|
854
|
+
const replacementByHeader = new Map();
|
|
855
|
+
for (const key of payloadProjectKeys) {
|
|
856
|
+
const projectHeaders = headers.filter((header) => header.kind === "project" && header.path[1] === key);
|
|
857
|
+
const parent = projectHeaders.find((header) => header.path.length === 2);
|
|
858
|
+
const payloadValue = projectTrustValueAtPath(payloadInventory.parsed, ["projects", key]);
|
|
859
|
+
const externalValue = externalProjects[key];
|
|
860
|
+
const runtimeValue = runtimeProjects[key];
|
|
861
|
+
if (externalValue !== undefined) {
|
|
862
|
+
if (!projectTrustEqual(payloadValue, externalValue) || (runtimeValue !== undefined && !projectTrustEqual(runtimeValue, externalValue)))
|
|
863
|
+
return undefined;
|
|
864
|
+
for (const header of projectHeaders)
|
|
865
|
+
replacementByHeader.set(header.start, undefined);
|
|
866
|
+
continue;
|
|
867
|
+
}
|
|
868
|
+
if (runtimeValue === undefined) {
|
|
869
|
+
for (const header of projectHeaders)
|
|
870
|
+
replacementByHeader.set(header.start, undefined);
|
|
871
|
+
continue;
|
|
872
|
+
}
|
|
873
|
+
if (!parent || projectHeaders.length !== 1 || !isPlainTomlRecord(runtimeValue))
|
|
874
|
+
return undefined;
|
|
875
|
+
const rendered = renderProjectTrust(key, runtimeValue);
|
|
876
|
+
if (!rendered)
|
|
877
|
+
return undefined;
|
|
878
|
+
replacementByHeader.set(parent.start, rendered.replaceAll("\n", eol));
|
|
879
|
+
}
|
|
880
|
+
for (const header of headers.filter((candidate) => candidate.kind === "hook")) {
|
|
881
|
+
const key = header.path[2];
|
|
882
|
+
const payloadValue = projectTrustValueAtPath(payloadInventory.parsed, header.path);
|
|
883
|
+
const runtimeValue = runtimeHooksState?.[key];
|
|
884
|
+
const externalValue = externalHookTrustState?.[key];
|
|
885
|
+
if (externalValue !== undefined) {
|
|
886
|
+
if (!projectTrustEqual(payloadValue, externalValue))
|
|
887
|
+
return undefined;
|
|
888
|
+
replacementByHeader.set(header.start, undefined);
|
|
889
|
+
continue;
|
|
782
890
|
}
|
|
891
|
+
if (!isPlainTomlRecord(runtimeValue) || typeof runtimeValue.trusted_hash !== "string" || runtimeValue.trusted_hash.length === 0) {
|
|
892
|
+
replacementByHeader.set(header.start, undefined);
|
|
893
|
+
continue;
|
|
894
|
+
}
|
|
895
|
+
replacementByHeader.set(header.start, `[hooks.state."${escapeTomlBasicString(key)}"]${eol}trusted_hash = "${escapeTomlBasicString(runtimeValue.trusted_hash)}"`);
|
|
896
|
+
}
|
|
897
|
+
const leadingGap = payload.slice(0, headers[0]?.start ?? payload.length);
|
|
898
|
+
const parts = headers.length === 0 ? [] : [leadingGap];
|
|
899
|
+
let trailingGap = headers.length === 0 ? leadingGap : "";
|
|
900
|
+
const appendPart = (part) => {
|
|
901
|
+
if (!part)
|
|
902
|
+
return;
|
|
903
|
+
const previous = parts.at(-1);
|
|
904
|
+
if (previous && !/(?:\r\n|\n)$/.test(previous) && !/^(?:\r\n|\n)/.test(part))
|
|
905
|
+
parts.push(eol);
|
|
906
|
+
parts.push(part);
|
|
907
|
+
};
|
|
908
|
+
for (const [index, header] of headers.entries()) {
|
|
909
|
+
const next = headers[index + 1];
|
|
910
|
+
const segmentEnd = next?.start ?? payload.length;
|
|
911
|
+
const replacement = replacementByHeader.get(header.start);
|
|
912
|
+
const span = projectTrustPayloadTableSpan(payload.slice(header.start, segmentEnd));
|
|
913
|
+
const tableBody = span.source.slice(header.end - header.start);
|
|
914
|
+
if (replacement !== undefined &&
|
|
915
|
+
replacement !== span.source &&
|
|
916
|
+
projectTrustPayloadTableBodyHasCommentsOrBlanks(tableBody)) {
|
|
917
|
+
return undefined;
|
|
918
|
+
}
|
|
919
|
+
if (!next) {
|
|
920
|
+
trailingGap = span.gap;
|
|
921
|
+
if (replacement !== undefined)
|
|
922
|
+
appendPart(replacement);
|
|
923
|
+
continue;
|
|
924
|
+
}
|
|
925
|
+
if (replacement !== undefined)
|
|
926
|
+
appendPart(replacement);
|
|
927
|
+
if (span.gap)
|
|
928
|
+
appendPart(span.gap);
|
|
783
929
|
}
|
|
784
|
-
|
|
785
|
-
|
|
930
|
+
const additions = [];
|
|
931
|
+
for (const [key, value] of Object.entries(runtimeProjects).sort(([left], [right]) => left.localeCompare(right))) {
|
|
932
|
+
if (externalProjects[key] !== undefined || payloadProjectKeys.has(key))
|
|
933
|
+
continue;
|
|
934
|
+
if (!isPlainTomlRecord(value))
|
|
935
|
+
return undefined;
|
|
936
|
+
const rendered = renderProjectTrust(key, value);
|
|
937
|
+
if (!rendered)
|
|
938
|
+
return undefined;
|
|
939
|
+
additions.push(`${rendered.replaceAll("\n", eol)}${eol}`);
|
|
786
940
|
}
|
|
787
|
-
const
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
941
|
+
for (const [key, value] of Object.entries(runtimeHooksState ?? {}).sort(([left], [right]) => left.localeCompare(right))) {
|
|
942
|
+
if (!key.startsWith(`${projectHooksPath}:`) || externalHookTrustState?.[key] !== undefined || headers.some((header) => header.kind === "hook" && header.path[2] === key))
|
|
943
|
+
continue;
|
|
944
|
+
if (!isPlainTomlRecord(value) || typeof value.trusted_hash !== "string" || value.trusted_hash.length === 0)
|
|
945
|
+
continue;
|
|
946
|
+
additions.push(`[hooks.state."${escapeTomlBasicString(key)}"]${eol}trusted_hash = "${escapeTomlBasicString(value.trusted_hash)}"${eol}`);
|
|
947
|
+
}
|
|
948
|
+
let reconciled = parts.join("");
|
|
949
|
+
if (additions.length > 0 && reconciled && !/(?:\r\n|\n)$/.test(reconciled))
|
|
950
|
+
reconciled += eol;
|
|
951
|
+
reconciled += additions.join("");
|
|
952
|
+
if (trailingGap && reconciled && !/(?:\r\n|\n)$/.test(reconciled) && !/^(?:\r\n|\n)/.test(trailingGap))
|
|
953
|
+
reconciled += eol;
|
|
954
|
+
reconciled += trailingGap;
|
|
955
|
+
reconciled = reconciled.replace(/(?:\r\n|\n)$/, "");
|
|
956
|
+
return Object.keys(safeParseToml(reconciled) ?? {}).length === 0 ? "" : reconciled;
|
|
957
|
+
}
|
|
958
|
+
function projectTrustHeaders(config, region) {
|
|
959
|
+
const lexical = analyzeTomlSource(config);
|
|
960
|
+
if (!lexical.isUnambiguous)
|
|
961
|
+
return undefined;
|
|
962
|
+
const lines = sourceLines(config);
|
|
963
|
+
const headers = [];
|
|
964
|
+
for (const [index, line] of lines.entries()) {
|
|
965
|
+
if (line.start < region.start || line.start >= region.end || !lexical.lineStartsOutsideMultiline[index])
|
|
966
|
+
continue;
|
|
967
|
+
if (!/^\s*\[/.test(line.content))
|
|
968
|
+
continue;
|
|
969
|
+
const path = projectTrustHeaderPath(line.content);
|
|
970
|
+
if (!path) {
|
|
971
|
+
if (/^\s*\[\[?\s*(?:projects|"projects"|'projects')/.test(line.content))
|
|
972
|
+
return undefined;
|
|
973
|
+
continue;
|
|
974
|
+
}
|
|
975
|
+
headers.push({ start: line.start, end: line.end, path });
|
|
976
|
+
}
|
|
977
|
+
return headers;
|
|
978
|
+
}
|
|
979
|
+
function inventoryProjectTrustSource(config) {
|
|
980
|
+
const parsed = safeParseToml(config);
|
|
981
|
+
if (!parsed)
|
|
982
|
+
return undefined;
|
|
983
|
+
const projects = parsed.projects;
|
|
984
|
+
if (projects !== undefined && !isPlainTomlRecord(projects))
|
|
985
|
+
return undefined;
|
|
986
|
+
const headers = projectTrustHeaders(config, { start: 0, end: config.length });
|
|
987
|
+
if (!headers)
|
|
988
|
+
return undefined;
|
|
989
|
+
const projectHeaders = headers.filter((header) => header.path[0] === "projects");
|
|
990
|
+
if (projectHeaders.some((header) => header.path.length < 2))
|
|
991
|
+
return undefined;
|
|
992
|
+
for (const key of Object.keys(projects ?? {})) {
|
|
993
|
+
if (projectHeaders.filter((header) => header.path.length === 2 && header.path[1] === key).length !== 1) {
|
|
994
|
+
return undefined;
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
if (!projectTrustSourceNestedStructuresAreExplicit(parsed, projectHeaders))
|
|
998
|
+
return undefined;
|
|
999
|
+
return { projects: projects ?? {}, headers };
|
|
1000
|
+
}
|
|
1001
|
+
function projectTrustCandidateIsSafe(candidate, external, runtimeProjects) {
|
|
1002
|
+
const marker = projectTrustMarkerRange(candidate);
|
|
1003
|
+
const inventory = inventoryProjectTrustSource(candidate);
|
|
1004
|
+
const externalInventory = inventoryProjectTrustSource(external);
|
|
1005
|
+
if (!inventory || !externalInventory)
|
|
1006
|
+
return false;
|
|
1007
|
+
const hasMarker = marker !== undefined && marker.start !== marker.end;
|
|
1008
|
+
const hasEquivalentExternalBytes = (actual) => {
|
|
1009
|
+
if (actual === external)
|
|
1010
|
+
return true;
|
|
1011
|
+
return splitProjectTrustTrailingEols(actual).body === splitProjectTrustTrailingEols(external).body;
|
|
1012
|
+
};
|
|
1013
|
+
if (hasMarker) {
|
|
1014
|
+
const candidateExternal = `${candidate.slice(0, marker.start)}${candidate.slice(marker.end)}`;
|
|
1015
|
+
if (!hasEquivalentExternalBytes(candidateExternal) && !(candidate.startsWith(external) && candidate.slice(marker.end).length === 0 && /^(?:\r\n|\n)+$/.test(candidate.slice(external.length, marker.start))))
|
|
1016
|
+
return false;
|
|
1017
|
+
}
|
|
1018
|
+
else if (!hasEquivalentExternalBytes(candidate)) {
|
|
1019
|
+
return false;
|
|
1020
|
+
}
|
|
1021
|
+
const expectedProjects = { ...externalInventory.projects, ...runtimeProjects };
|
|
1022
|
+
if (!projectTrustEqual(inventory.projects, expectedProjects))
|
|
1023
|
+
return false;
|
|
1024
|
+
for (const [key, value] of Object.entries(expectedProjects)) {
|
|
1025
|
+
if (!projectTrustEqual(inventory.projects[key], value))
|
|
1026
|
+
return false;
|
|
1027
|
+
if (inventory.headers.filter((header) => header.path[0] === "projects" && header.path.length === 2 && header.path[1] === key).length !== 1)
|
|
1028
|
+
return false;
|
|
1029
|
+
}
|
|
1030
|
+
return true;
|
|
1031
|
+
}
|
|
1032
|
+
function projectTrustPayloadProjectFamiliesAreValid(headers) {
|
|
1033
|
+
const projectKeys = new Set(headers.filter((header) => header.kind === "project").map((header) => header.path[1]));
|
|
1034
|
+
for (const key of projectKeys) {
|
|
1035
|
+
const family = headers.filter((header) => header.kind === "project" && header.path[1] === key);
|
|
1036
|
+
const parents = family.filter((header) => header.path.length === 2);
|
|
1037
|
+
if (parents.length !== 1 || !projectTrustFamilyIsContiguous(headers, parents[0]))
|
|
1038
|
+
return false;
|
|
1039
|
+
}
|
|
1040
|
+
return true;
|
|
1041
|
+
}
|
|
1042
|
+
function projectTrustFamilyIsContiguous(headers, parent) {
|
|
1043
|
+
const first = headers.indexOf(parent);
|
|
1044
|
+
let ended = false;
|
|
1045
|
+
for (let index = first + 1; index < headers.length; index += 1) {
|
|
1046
|
+
const path = headers[index].path;
|
|
1047
|
+
const belongsToFamily = path[0] === "projects" && path[1] === parent.path[1];
|
|
1048
|
+
if (!belongsToFamily) {
|
|
1049
|
+
ended = true;
|
|
1050
|
+
continue;
|
|
1051
|
+
}
|
|
1052
|
+
if (ended || path.length < 3)
|
|
1053
|
+
return false;
|
|
1054
|
+
}
|
|
1055
|
+
return true;
|
|
1056
|
+
}
|
|
1057
|
+
function projectTrustEqual(left, right) {
|
|
1058
|
+
if (Object.is(left, right))
|
|
1059
|
+
return true;
|
|
1060
|
+
if (left instanceof Date || right instanceof Date) {
|
|
1061
|
+
return left instanceof Date && right instanceof Date && left.constructor === right.constructor && String(left) === String(right);
|
|
1062
|
+
}
|
|
1063
|
+
if (Array.isArray(left) || Array.isArray(right)) {
|
|
1064
|
+
return Array.isArray(left) && Array.isArray(right) && left.length === right.length && left.every((value, index) => projectTrustEqual(value, right[index]));
|
|
1065
|
+
}
|
|
1066
|
+
if (!isPlainTomlRecord(left) || !isPlainTomlRecord(right))
|
|
1067
|
+
return false;
|
|
1068
|
+
const leftKeys = Object.keys(left).sort();
|
|
1069
|
+
const rightKeys = Object.keys(right).sort();
|
|
1070
|
+
return leftKeys.length === rightKeys.length && leftKeys.every((key, index) => key === rightKeys[index] && projectTrustEqual(left[key], right[key]));
|
|
1071
|
+
}
|
|
1072
|
+
function canRenderFlatProjectTrust(entry) {
|
|
1073
|
+
const isValue = (value) => {
|
|
1074
|
+
if (Array.isArray(value))
|
|
1075
|
+
return value.every(isValue);
|
|
1076
|
+
return !isPlainTomlRecord(value);
|
|
1077
|
+
};
|
|
1078
|
+
return Object.values(entry).every(isValue);
|
|
1079
|
+
}
|
|
1080
|
+
function renderProjectTrust(projectKey, entry) {
|
|
1081
|
+
if (!canRenderFlatProjectTrust(entry))
|
|
1082
|
+
return undefined;
|
|
1083
|
+
const serialized = TOML.stringify({ [projectKey]: entry });
|
|
1084
|
+
const body = serialized.split(/\r?\n/).filter((line) => !/^\s*\[/.test(line) && line.trim() !== "").join("\n");
|
|
1085
|
+
return body ? `[projects."${escapeTomlBasicString(projectKey)}"]\n${body}` : undefined;
|
|
1086
|
+
}
|
|
1087
|
+
function splitProjectTrustTrailingEols(source) {
|
|
1088
|
+
const match = source.match(/(?:(?:\r\n|\n))*$/);
|
|
1089
|
+
const trailingEols = match?.[0] ?? "";
|
|
1090
|
+
return { body: source.slice(0, source.length - trailingEols.length), trailingEols };
|
|
1091
|
+
}
|
|
1092
|
+
function appendProjectTrustMarker(base, payload, eol, trailingEols) {
|
|
1093
|
+
if (!payload)
|
|
1094
|
+
return `${splitProjectTrustTrailingEols(base).body}${trailingEols}`;
|
|
1095
|
+
const { body } = splitProjectTrustTrailingEols(base);
|
|
1096
|
+
const separator = body ? `${eol}${eol}` : "";
|
|
1097
|
+
const block = `${OMX_PROJECT_TRUST_START_MARKER}${eol}${payload}${eol}${OMX_PROJECT_TRUST_END_MARKER}`;
|
|
1098
|
+
return `${body}${separator}${block}${trailingEols}`;
|
|
1099
|
+
}
|
|
1100
|
+
function reconcileProjectScopeTrustState(projectConfig, runtimeConfig, projectHooksPath, requireExistingPayload) {
|
|
1101
|
+
const durable = projectTrustSemanticView(projectConfig);
|
|
1102
|
+
const runtime = projectTrustSemanticView(runtimeConfig);
|
|
1103
|
+
if (!durable || !runtime)
|
|
1104
|
+
return projectConfig;
|
|
1105
|
+
if (hasInlineProjectTrustMarkerComment(durable.source) || hasInlineProjectTrustMarkerComment(runtime.source))
|
|
1106
|
+
return projectConfig;
|
|
1107
|
+
const parsedRuntime = safeParseToml(runtime.source);
|
|
1108
|
+
const runtimeInventory = inventoryProjectTrustSource(runtime.source);
|
|
1109
|
+
if (!parsedRuntime || !runtimeInventory)
|
|
1110
|
+
return projectConfig;
|
|
1111
|
+
const marker = projectTrustMarkerRange(durable.source);
|
|
1112
|
+
if (!marker)
|
|
1113
|
+
return projectConfig;
|
|
1114
|
+
const hasMarker = marker.start !== marker.end;
|
|
1115
|
+
const payload = durable.source.slice(marker.payloadStart, marker.payloadEnd);
|
|
1116
|
+
const payloadIsEmpty = projectTrustPayloadIsSemanticallyEmpty(payload);
|
|
1117
|
+
const payloadInventory = hasMarker
|
|
1118
|
+
? inventoryProjectTrustPayload(payload, projectHooksPath)
|
|
1119
|
+
: { parsed: {}, headers: [] };
|
|
1120
|
+
if (!payloadInventory)
|
|
1121
|
+
return projectConfig;
|
|
1122
|
+
if (requireExistingPayload && (!hasMarker || payloadIsEmpty))
|
|
1123
|
+
return projectConfig;
|
|
1124
|
+
const external = hasMarker
|
|
1125
|
+
? `${durable.source.slice(0, marker.start)}${durable.source.slice(marker.end)}`
|
|
1126
|
+
: durable.source;
|
|
1127
|
+
const trailingEols = splitProjectTrustTrailingEols(durable.source).trailingEols;
|
|
1128
|
+
const externalInventory = inventoryProjectTrustSource(external);
|
|
1129
|
+
if (!externalInventory)
|
|
1130
|
+
return projectConfig;
|
|
1131
|
+
const projects = runtimeInventory.projects;
|
|
1132
|
+
const externalProjects = externalInventory.projects;
|
|
1133
|
+
const headersBeforeMarker = projectTrustHeaders(durable.source, { start: 0, end: marker.start });
|
|
1134
|
+
const headersAfterMarker = projectTrustHeaders(durable.source, { start: marker.end, end: durable.source.length });
|
|
1135
|
+
if (!headersBeforeMarker || !headersAfterMarker)
|
|
1136
|
+
return projectConfig;
|
|
1137
|
+
const headers = [...headersBeforeMarker, ...headersAfterMarker];
|
|
1138
|
+
for (const key of Object.keys(externalProjects)) {
|
|
1139
|
+
const family = headers.filter((header) => header.path[0] === "projects" && header.path[1] === key);
|
|
1140
|
+
const parents = family.filter((header) => header.path.length === 2);
|
|
1141
|
+
if (parents.length !== 1)
|
|
1142
|
+
return projectConfig;
|
|
1143
|
+
const parentIsBeforeMarker = parents[0].start < marker.start;
|
|
1144
|
+
if (family.some((header) => (header.start < marker.start) !== parentIsBeforeMarker))
|
|
1145
|
+
return projectConfig;
|
|
1146
|
+
if (!projectTrustFamilyIsContiguous(headers, parents[0]))
|
|
1147
|
+
return projectConfig;
|
|
1148
|
+
}
|
|
1149
|
+
const eol = dominantProjectTrustEol(durable.source);
|
|
1150
|
+
const hooks = parsedRuntime.hooks;
|
|
1151
|
+
const hooksState = isPlainTomlRecord(hooks) && isPlainTomlRecord(hooks.state) ? hooks.state : undefined;
|
|
1152
|
+
const nextPayload = reconcileProjectTrustPayload(payload, payloadInventory, externalProjects, projects, hooksState, projectHookTrustState(external), projectHooksPath, eol);
|
|
1153
|
+
if (nextPayload === undefined)
|
|
1154
|
+
return projectConfig;
|
|
1155
|
+
if (!inventoryProjectTrustPayload(nextPayload, projectHooksPath))
|
|
1156
|
+
return projectConfig;
|
|
1157
|
+
const candidate = appendProjectTrustMarker(external, nextPayload, eol, trailingEols);
|
|
1158
|
+
if (!projectTrustCandidateIsSafe(candidate, external, projects))
|
|
1159
|
+
return projectConfig;
|
|
1160
|
+
return `${durable.prefix}${candidate}`;
|
|
1161
|
+
}
|
|
1162
|
+
/** Repairs only a uniquely parseable, nonempty project-sync payload before mirror creation. */
|
|
1163
|
+
export function repairProjectScopeTrustStateForLaunch(projectConfig, projectHooksPath) {
|
|
1164
|
+
const durable = projectTrustSemanticView(projectConfig);
|
|
1165
|
+
if (!durable)
|
|
1166
|
+
return projectConfig;
|
|
1167
|
+
const marker = projectTrustMarkerRange(durable.source);
|
|
1168
|
+
if (!marker || marker.start === marker.end)
|
|
1169
|
+
return projectConfig;
|
|
1170
|
+
const payload = durable.source.slice(marker.payloadStart, marker.payloadEnd);
|
|
1171
|
+
return reconcileProjectScopeTrustState(projectConfig, payload, projectHooksPath, true);
|
|
1172
|
+
}
|
|
1173
|
+
/** Conservatively persists runtime project and hook trust without rewriting external TOML. */
|
|
1174
|
+
export function syncProjectScopeTrustStateFromRuntime(projectConfig, runtimeConfig, projectHooksPath) {
|
|
1175
|
+
return reconcileProjectScopeTrustState(projectConfig, runtimeConfig, projectHooksPath, false);
|
|
796
1176
|
}
|
|
797
1177
|
function isMultilineTomlString(mode) {
|
|
798
1178
|
return mode === "multiline-basic" || mode === "multiline-literal";
|