oh-my-codex 0.16.2 → 0.16.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +5 -5
- package/Cargo.toml +1 -1
- package/README.md +3 -3
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.js +9 -0
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.js.map +1 -1
- package/dist/cli/__tests__/cleanup.test.js +27 -0
- package/dist/cli/__tests__/cleanup.test.js.map +1 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js +7 -5
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js +137 -6
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +303 -4
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/launch-fallback.test.js +58 -0
- package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +2 -0
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
- package/dist/cli/__tests__/ralph.test.js +48 -0
- package/dist/cli/__tests__/ralph.test.js.map +1 -1
- package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js +8 -0
- package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js.map +1 -1
- package/dist/cli/__tests__/setup-install-mode.test.js +350 -27
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
- package/dist/cli/__tests__/setup-refresh.test.js +85 -3
- package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
- package/dist/cli/__tests__/setup-scope.test.js +1 -1
- package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
- package/dist/cli/__tests__/setup-skills-overwrite.test.js +2 -1
- package/dist/cli/__tests__/setup-skills-overwrite.test.js.map +1 -1
- package/dist/cli/__tests__/team.test.js +269 -0
- package/dist/cli/__tests__/team.test.js.map +1 -1
- package/dist/cli/__tests__/ultragoal.test.js +69 -0
- package/dist/cli/__tests__/ultragoal.test.js.map +1 -1
- package/dist/cli/__tests__/uninstall.test.js +90 -6
- package/dist/cli/__tests__/uninstall.test.js.map +1 -1
- package/dist/cli/__tests__/update.test.js +109 -19
- package/dist/cli/__tests__/update.test.js.map +1 -1
- package/dist/cli/cleanup.d.ts.map +1 -1
- package/dist/cli/cleanup.js +8 -4
- package/dist/cli/cleanup.js.map +1 -1
- package/dist/cli/codex-feature-probe.d.ts +9 -0
- package/dist/cli/codex-feature-probe.d.ts.map +1 -0
- package/dist/cli/codex-feature-probe.js +28 -0
- package/dist/cli/codex-feature-probe.js.map +1 -0
- package/dist/cli/doctor.d.ts +1 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +168 -16
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.d.ts +9 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +168 -20
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-parity.js +8 -8
- package/dist/cli/mcp-parity.js.map +1 -1
- package/dist/cli/plugin-marketplace.d.ts +3 -0
- package/dist/cli/plugin-marketplace.d.ts.map +1 -1
- package/dist/cli/plugin-marketplace.js +88 -0
- package/dist/cli/plugin-marketplace.js.map +1 -1
- package/dist/cli/ralph.d.ts.map +1 -1
- package/dist/cli/ralph.js +21 -0
- package/dist/cli/ralph.js.map +1 -1
- package/dist/cli/setup-preferences.d.ts +4 -0
- package/dist/cli/setup-preferences.d.ts.map +1 -1
- package/dist/cli/setup-preferences.js +7 -0
- package/dist/cli/setup-preferences.js.map +1 -1
- package/dist/cli/setup.d.ts +5 -3
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +177 -43
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/team.d.ts.map +1 -1
- package/dist/cli/team.js +54 -15
- package/dist/cli/team.js.map +1 -1
- package/dist/cli/ultragoal.d.ts +1 -1
- package/dist/cli/ultragoal.d.ts.map +1 -1
- package/dist/cli/ultragoal.js +64 -5
- package/dist/cli/ultragoal.js.map +1 -1
- package/dist/cli/uninstall.d.ts +2 -0
- package/dist/cli/uninstall.d.ts.map +1 -1
- package/dist/cli/uninstall.js +76 -5
- package/dist/cli/uninstall.js.map +1 -1
- package/dist/cli/update.d.ts +10 -2
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +99 -5
- package/dist/cli/update.js.map +1 -1
- 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 +35 -0
- package/dist/config/__tests__/codex-feature-flags.test.js.map +1 -0
- package/dist/config/__tests__/codex-hooks.test.js +188 -4
- package/dist/config/__tests__/codex-hooks.test.js.map +1 -1
- package/dist/config/__tests__/generator-idempotent.test.js +129 -10
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
- package/dist/config/__tests__/generator-notify.test.js +148 -7
- package/dist/config/__tests__/generator-notify.test.js.map +1 -1
- package/dist/config/__tests__/wiki-config-contract.test.js +6 -3
- package/dist/config/__tests__/wiki-config-contract.test.js.map +1 -1
- package/dist/config/codex-feature-flags.d.ts +21 -0
- package/dist/config/codex-feature-flags.d.ts.map +1 -0
- package/dist/config/codex-feature-flags.js +56 -0
- package/dist/config/codex-feature-flags.js.map +1 -0
- package/dist/config/codex-hooks.d.ts +40 -4
- package/dist/config/codex-hooks.d.ts.map +1 -1
- package/dist/config/codex-hooks.js +204 -18
- package/dist/config/codex-hooks.js.map +1 -1
- package/dist/config/generator.d.ts +19 -1
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +319 -83
- package/dist/config/generator.js.map +1 -1
- package/dist/config/omx-first-party-mcp.d.ts +3 -1
- package/dist/config/omx-first-party-mcp.d.ts.map +1 -1
- package/dist/config/omx-first-party-mcp.js +2 -2
- package/dist/config/omx-first-party-mcp.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +92 -2
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js +29 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +10 -0
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js +1 -0
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js.map +1 -1
- 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.js +148 -0
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js +3 -0
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js.map +1 -1
- 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__/wiki-docs-contract.test.js +1 -2
- package/dist/hooks/__tests__/wiki-docs-contract.test.js.map +1 -1
- package/dist/hooks/agents-overlay.js +2 -2
- package/dist/hooks/agents-overlay.js.map +1 -1
- package/dist/hooks/keyword-detector.d.ts +1 -0
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +7 -5
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/hud/__tests__/state.test.js +164 -0
- package/dist/hud/__tests__/state.test.js.map +1 -1
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +4 -5
- package/dist/hud/state.js.map +1 -1
- package/dist/mcp/__tests__/state-paths.test.js +61 -0
- package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
- package/dist/mcp/__tests__/state-server.test.js +166 -0
- package/dist/mcp/__tests__/state-server.test.js.map +1 -1
- package/dist/mcp/state-paths.d.ts.map +1 -1
- package/dist/mcp/state-paths.js +23 -2
- package/dist/mcp/state-paths.js.map +1 -1
- package/dist/modes/__tests__/base-session-scope.test.js +22 -0
- package/dist/modes/__tests__/base-session-scope.test.js.map +1 -1
- package/dist/modes/__tests__/base-tmux-pane.test.js +57 -26
- package/dist/modes/__tests__/base-tmux-pane.test.js.map +1 -1
- package/dist/modes/base.d.ts.map +1 -1
- package/dist/modes/base.js +5 -0
- package/dist/modes/base.js.map +1 -1
- 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 +316 -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 +481 -0
- package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.js.map +1 -0
- package/dist/planning/__tests__/artifacts.test.js +597 -4
- package/dist/planning/__tests__/artifacts.test.js.map +1 -1
- package/dist/planning/__tests__/context-pack-status.test.js +524 -0
- package/dist/planning/__tests__/context-pack-status.test.js.map +1 -1
- 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/__tests__/ready-context-pack-role-refs.test.d.ts +2 -0
- package/dist/planning/__tests__/ready-context-pack-role-refs.test.d.ts.map +1 -0
- package/dist/planning/__tests__/ready-context-pack-role-refs.test.js +612 -0
- package/dist/planning/__tests__/ready-context-pack-role-refs.test.js.map +1 -0
- package/dist/planning/artifacts.d.ts +7 -2
- package/dist/planning/artifacts.d.ts.map +1 -1
- package/dist/planning/artifacts.js +279 -26
- package/dist/planning/artifacts.js.map +1 -1
- package/dist/planning/context-pack-status.d.ts +31 -0
- package/dist/planning/context-pack-status.d.ts.map +1 -1
- package/dist/planning/context-pack-status.js +291 -25
- package/dist/planning/context-pack-status.js.map +1 -1
- 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/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 +121 -0
- package/dist/ralph/__tests__/completion-audit.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/persistence.d.ts +1 -1
- package/dist/ralph/persistence.d.ts.map +1 -1
- package/dist/ralph/persistence.js +8 -2
- package/dist/ralph/persistence.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +359 -24
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- 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 +126 -0
- package/dist/scripts/__tests__/notify-dispatcher.test.js.map +1 -0
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +142 -76
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
- package/dist/scripts/codex-native-pre-post.js +4 -2
- package/dist/scripts/codex-native-pre-post.js.map +1 -1
- 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 +87 -0
- package/dist/scripts/notify-dispatcher.js.map +1 -0
- package/dist/scripts/notify-fallback-watcher.js +4 -0
- package/dist/scripts/notify-fallback-watcher.js.map +1 -1
- package/dist/scripts/notify-hook/ralph-session-resume.d.ts.map +1 -1
- package/dist/scripts/notify-hook/ralph-session-resume.js +96 -8
- package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -1
- package/dist/scripts/notify-hook/state-io.d.ts.map +1 -1
- package/dist/scripts/notify-hook/state-io.js +6 -2
- package/dist/scripts/notify-hook/state-io.js.map +1 -1
- package/dist/scripts/notify-hook/visual-verdict.js +3 -3
- package/dist/scripts/notify-hook/visual-verdict.js.map +1 -1
- package/dist/scripts/notify-hook.js +127 -1
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/state/__tests__/workflow-transition.test.js +102 -27
- package/dist/state/__tests__/workflow-transition.test.js.map +1 -1
- package/dist/state/operations.d.ts.map +1 -1
- package/dist/state/operations.js +9 -3
- package/dist/state/operations.js.map +1 -1
- package/dist/state/skill-active.d.ts +7 -0
- package/dist/state/skill-active.d.ts.map +1 -1
- package/dist/state/skill-active.js +25 -8
- package/dist/state/skill-active.js.map +1 -1
- package/dist/state/workflow-transition-reconcile.d.ts +1 -0
- package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
- package/dist/state/workflow-transition-reconcile.js +22 -15
- package/dist/state/workflow-transition-reconcile.js.map +1 -1
- package/dist/state/workflow-transition.js +3 -3
- package/dist/state/workflow-transition.js.map +1 -1
- package/dist/team/__tests__/approved-execution.test.js +84 -1
- package/dist/team/__tests__/approved-execution.test.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +178 -19
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/scaling.test.js +497 -2
- package/dist/team/__tests__/scaling.test.js.map +1 -1
- package/dist/team/__tests__/state-root.test.js +1 -1
- package/dist/team/__tests__/state-root.test.js.map +1 -1
- package/dist/team/__tests__/worker-bootstrap.test.js +45 -0
- package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
- package/dist/team/approved-execution.d.ts +1 -0
- package/dist/team/approved-execution.d.ts.map +1 -1
- package/dist/team/approved-execution.js +53 -0
- package/dist/team/approved-execution.js.map +1 -1
- package/dist/team/delivery-log.d.ts.map +1 -1
- package/dist/team/delivery-log.js +8 -1
- package/dist/team/delivery-log.js.map +1 -1
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +104 -18
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +43 -0
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/state/mailbox.d.ts +1 -0
- package/dist/team/state/mailbox.d.ts.map +1 -1
- package/dist/team/state/mailbox.js +10 -1
- package/dist/team/state/mailbox.js.map +1 -1
- package/dist/team/state-root.d.ts.map +1 -1
- package/dist/team/state-root.js +5 -1
- package/dist/team/state-root.js.map +1 -1
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +3 -7
- package/dist/team/state.js.map +1 -1
- package/dist/team/worker-bootstrap.d.ts +7 -2
- package/dist/team/worker-bootstrap.d.ts.map +1 -1
- package/dist/team/worker-bootstrap.js +17 -4
- package/dist/team/worker-bootstrap.js.map +1 -1
- package/dist/ultragoal/__tests__/artifacts.test.js +124 -1
- package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
- package/dist/ultragoal/__tests__/docs-contract.test.js +21 -0
- package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -1
- package/dist/ultragoal/artifacts.d.ts +44 -2
- package/dist/ultragoal/artifacts.d.ts.map +1 -1
- package/dist/ultragoal/artifacts.js +197 -13
- package/dist/ultragoal/artifacts.js.map +1 -1
- package/dist/wiki/lifecycle.js +1 -1
- package/dist/wiki/lifecycle.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/.mcp.json +5 -5
- package/plugins/oh-my-codex/skills/analyze/SKILL.md +0 -2
- package/plugins/oh-my-codex/skills/autopilot/SKILL.md +2 -2
- package/plugins/oh-my-codex/skills/code-review/SKILL.md +1 -3
- package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +5 -7
- package/plugins/oh-my-codex/skills/doctor/SKILL.md +2 -2
- package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +3 -3
- package/plugins/oh-my-codex/skills/pipeline/SKILL.md +3 -3
- package/plugins/oh-my-codex/skills/plan/SKILL.md +3 -6
- package/plugins/oh-my-codex/skills/ralph/SKILL.md +9 -10
- package/plugins/oh-my-codex/skills/ultragoal/SKILL.md +36 -3
- package/plugins/oh-my-codex/skills/ultraqa/SKILL.md +21 -24
- package/plugins/oh-my-codex/skills/ultrawork/SKILL.md +8 -8
- package/plugins/oh-my-codex/skills/wiki/SKILL.md +13 -13
- package/skills/analyze/SKILL.md +0 -2
- package/skills/ask-claude/SKILL.md +5 -3
- package/skills/ask-gemini/SKILL.md +5 -3
- package/skills/autopilot/SKILL.md +2 -2
- package/skills/code-review/SKILL.md +1 -3
- package/skills/deep-interview/SKILL.md +5 -7
- package/skills/doctor/SKILL.md +2 -2
- package/skills/ecomode/SKILL.md +105 -1
- package/skills/frontend-ui-ux/SKILL.md +4 -26
- package/skills/git-master/SKILL.md +2 -4
- package/skills/omx-setup/SKILL.md +3 -3
- package/skills/pipeline/SKILL.md +3 -3
- package/skills/plan/SKILL.md +3 -6
- package/skills/ralph/SKILL.md +9 -10
- package/skills/swarm/SKILL.md +5 -3
- package/skills/tdd/SKILL.md +95 -1
- package/skills/ultragoal/SKILL.md +36 -3
- package/skills/ultraqa/SKILL.md +21 -24
- package/skills/ultrawork/SKILL.md +8 -8
- package/skills/web-clone/SKILL.md +348 -1
- package/skills/wiki/SKILL.md +13 -13
- package/src/scripts/__tests__/codex-native-hook.test.ts +389 -24
- package/src/scripts/__tests__/notify-dispatcher.test.ts +153 -0
- package/src/scripts/codex-native-hook.ts +168 -64
- package/src/scripts/codex-native-pre-post.ts +4 -1
- package/src/scripts/notify-dispatcher.ts +113 -0
- package/src/scripts/notify-fallback-watcher.ts +6 -2
- package/src/scripts/notify-hook/ralph-session-resume.ts +117 -8
- package/src/scripts/notify-hook/state-io.ts +4 -2
- package/src/scripts/notify-hook/visual-verdict.ts +3 -3
- package/src/scripts/notify-hook.ts +119 -1
|
@@ -6,10 +6,10 @@ import { pathToFileURL } from "url";
|
|
|
6
6
|
import { readModeState, readModeStateForActiveDecision, readModeStateForSession, updateModeState } from "../modes/base.js";
|
|
7
7
|
import {
|
|
8
8
|
extractSessionIdFromInitializedStatePath,
|
|
9
|
-
|
|
9
|
+
getSkillActiveStatePathsForStateDir,
|
|
10
10
|
listActiveSkills,
|
|
11
11
|
readSkillActiveState,
|
|
12
|
-
|
|
12
|
+
readVisibleSkillActiveStateForStateDir,
|
|
13
13
|
type SkillActiveStateLike,
|
|
14
14
|
} from "../state/skill-active.js";
|
|
15
15
|
import {
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
} from "../team/state.js";
|
|
36
36
|
import { omxNotepadPath, omxProjectMemoryPath } from "../utils/paths.js";
|
|
37
37
|
import { findGitLayout } from "../utils/git-layout.js";
|
|
38
|
-
import { getStateFilePath, getStatePath } from "../mcp/state-paths.js";
|
|
38
|
+
import { getBaseStateDir, getStateFilePath, getStatePath } from "../mcp/state-paths.js";
|
|
39
39
|
import {
|
|
40
40
|
detectKeywords,
|
|
41
41
|
detectPrimaryKeyword,
|
|
@@ -71,12 +71,12 @@ import type { HookEventEnvelope } from "../hooks/extensibility/types.js";
|
|
|
71
71
|
import { dispatchHookEventRuntime } from "../hooks/extensibility/runtime.js";
|
|
72
72
|
import { reconcileHudForPromptSubmit } from "../hud/reconcile.js";
|
|
73
73
|
import {
|
|
74
|
-
onPostCompact as buildWikiPostCompactContext,
|
|
75
74
|
onPreCompact as buildWikiPreCompactContext,
|
|
76
75
|
onSessionStart as buildWikiSessionStartContext,
|
|
77
76
|
} from "../wiki/lifecycle.js";
|
|
78
77
|
import { readAutoresearchCompletionStatus, readAutoresearchModeStateForActiveDecision } from "../autoresearch/skill-validation.js";
|
|
79
78
|
import { readRunState } from "../runtime/run-state.js";
|
|
79
|
+
import { evaluateRalphCompletionAuditEvidence, isRalphCompletePhase } from "../ralph/completion-audit.js";
|
|
80
80
|
import { getRunContinuationSnapshot, shouldContinueRun } from "../runtime/run-loop.js";
|
|
81
81
|
import { triagePrompt } from "../hooks/triage-heuristic.js";
|
|
82
82
|
import { readTriageConfig } from "../hooks/triage-config.js";
|
|
@@ -486,6 +486,12 @@ interface ActiveRalphStopState {
|
|
|
486
486
|
path: string;
|
|
487
487
|
}
|
|
488
488
|
|
|
489
|
+
interface RalphCompletionAuditBlockState {
|
|
490
|
+
state: Record<string, unknown>;
|
|
491
|
+
path: string;
|
|
492
|
+
reason: string;
|
|
493
|
+
}
|
|
494
|
+
|
|
489
495
|
interface RalphStopOwnershipContext {
|
|
490
496
|
sessionId: string;
|
|
491
497
|
payloadSessionId: string;
|
|
@@ -560,8 +566,8 @@ async function readCanonicalTerminalRunStateForStop(
|
|
|
560
566
|
return shouldHonorCanonicalTerminalRunState(runRecord, mode) ? runRecord : null;
|
|
561
567
|
}
|
|
562
568
|
|
|
563
|
-
async function isVisibleRalphActiveForSession(
|
|
564
|
-
const canonicalState = await
|
|
569
|
+
async function isVisibleRalphActiveForSession(stateDir: string, sessionId: string): Promise<boolean> {
|
|
570
|
+
const canonicalState = await readVisibleSkillActiveStateForStateDir(stateDir, sessionId);
|
|
565
571
|
if (!canonicalState) return false;
|
|
566
572
|
return listActiveSkills(canonicalState).some((entry) => (
|
|
567
573
|
entry.skill === "ralph"
|
|
@@ -569,8 +575,8 @@ async function isVisibleRalphActiveForSession(cwd: string, sessionId: string): P
|
|
|
569
575
|
));
|
|
570
576
|
}
|
|
571
577
|
|
|
572
|
-
async function hasConsistentRalphSkillActivation(
|
|
573
|
-
const canonicalState = await
|
|
578
|
+
async function hasConsistentRalphSkillActivation(stateDir: string, sessionId: string): Promise<boolean> {
|
|
579
|
+
const canonicalState = await readVisibleSkillActiveStateForStateDir(stateDir, sessionId);
|
|
574
580
|
if (!canonicalState) return true;
|
|
575
581
|
|
|
576
582
|
const initializedMode = safeString(canonicalState.initialized_mode).trim();
|
|
@@ -582,7 +588,74 @@ async function hasConsistentRalphSkillActivation(cwd: string, sessionId: string)
|
|
|
582
588
|
return true;
|
|
583
589
|
}
|
|
584
590
|
|
|
591
|
+
|
|
592
|
+
async function readRalphCompletionAuditBlockState(
|
|
593
|
+
cwd: string,
|
|
594
|
+
stateDir: string,
|
|
595
|
+
preferredSessionId?: string,
|
|
596
|
+
ownerContext?: {
|
|
597
|
+
payloadSessionId?: string;
|
|
598
|
+
threadId?: string;
|
|
599
|
+
tmuxPaneId?: string;
|
|
600
|
+
},
|
|
601
|
+
): Promise<RalphCompletionAuditBlockState | null> {
|
|
602
|
+
const [rawSessionInfo, usableSessionInfo] = await Promise.all([
|
|
603
|
+
readSessionState(cwd),
|
|
604
|
+
readUsableSessionState(cwd),
|
|
605
|
+
]);
|
|
606
|
+
const currentOmxSessionId = safeString(usableSessionInfo?.session_id).trim();
|
|
607
|
+
const currentNativeSessionId = safeString(usableSessionInfo?.native_session_id).trim();
|
|
608
|
+
const staleCurrentSessionId = rawSessionInfo && !isSessionStateUsable(rawSessionInfo, cwd)
|
|
609
|
+
? safeString(rawSessionInfo.session_id).trim()
|
|
610
|
+
: "";
|
|
611
|
+
const sessionCandidates = [...new Set([
|
|
612
|
+
safeString(preferredSessionId).trim(),
|
|
613
|
+
currentOmxSessionId,
|
|
614
|
+
].filter(Boolean))];
|
|
615
|
+
|
|
616
|
+
const evaluateCandidate = (state: Record<string, unknown> | null, path: string, sessionId: string): RalphCompletionAuditBlockState | null => {
|
|
617
|
+
if (!state || state.mode && safeString(state.mode) !== "ralph") return null;
|
|
618
|
+
if (!isRalphCompletePhase(state.current_phase ?? state.currentPhase)) return null;
|
|
619
|
+
if (activeRalphStateMatchesStopOwner(state, {
|
|
620
|
+
sessionId,
|
|
621
|
+
payloadSessionId: safeString(ownerContext?.payloadSessionId).trim(),
|
|
622
|
+
threadId: safeString(ownerContext?.threadId).trim(),
|
|
623
|
+
currentNativeSessionId,
|
|
624
|
+
tmuxPaneId: safeString(ownerContext?.tmuxPaneId).trim(),
|
|
625
|
+
}) !== true) return null;
|
|
626
|
+
const audit = evaluateRalphCompletionAuditEvidence(state, cwd);
|
|
627
|
+
return audit.complete ? null : { state, path, reason: audit.reason };
|
|
628
|
+
};
|
|
629
|
+
|
|
630
|
+
for (const sessionId of sessionCandidates) {
|
|
631
|
+
if (staleCurrentSessionId && sessionId === staleCurrentSessionId) continue;
|
|
632
|
+
const sessionScopedPath = getStateFilePath("ralph-state.json", cwd, sessionId);
|
|
633
|
+
const result = evaluateCandidate(await readJsonIfExists(sessionScopedPath), sessionScopedPath, sessionId);
|
|
634
|
+
if (result) return result;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
if (sessionCandidates.length > 0) return null;
|
|
638
|
+
|
|
639
|
+
const directPath = join(stateDir, "ralph-state.json");
|
|
640
|
+
return evaluateCandidate(await readJsonIfExists(directPath), directPath, "");
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
async function reopenRalphCompletionAuditBlock(block: RalphCompletionAuditBlockState): Promise<void> {
|
|
644
|
+
const nowIso = new Date().toISOString();
|
|
645
|
+
const next: Record<string, unknown> = {
|
|
646
|
+
...block.state,
|
|
647
|
+
active: true,
|
|
648
|
+
current_phase: "verifying",
|
|
649
|
+
completion_audit_gate: "blocked",
|
|
650
|
+
completion_audit_missing_reason: block.reason,
|
|
651
|
+
completion_audit_blocked_at: nowIso,
|
|
652
|
+
};
|
|
653
|
+
delete next.completed_at;
|
|
654
|
+
await writeFile(block.path, JSON.stringify(next, null, 2));
|
|
655
|
+
}
|
|
656
|
+
|
|
585
657
|
async function readActiveRalphState(
|
|
658
|
+
cwd: string,
|
|
586
659
|
stateDir: string,
|
|
587
660
|
preferredSessionId?: string,
|
|
588
661
|
ownerContext?: {
|
|
@@ -591,7 +664,6 @@ async function readActiveRalphState(
|
|
|
591
664
|
tmuxPaneId?: string;
|
|
592
665
|
},
|
|
593
666
|
): Promise<ActiveRalphStopState | null> {
|
|
594
|
-
const cwd = resolve(stateDir, "..", "..");
|
|
595
667
|
const [rawSessionInfo, usableSessionInfo] = await Promise.all([
|
|
596
668
|
readSessionState(cwd),
|
|
597
669
|
readUsableSessionState(cwd),
|
|
@@ -621,7 +693,7 @@ async function readActiveRalphState(
|
|
|
621
693
|
if (
|
|
622
694
|
sessionScoped?.active === true
|
|
623
695
|
&& isRalphStartingPhase(sessionScoped)
|
|
624
|
-
&& !(await isVisibleRalphActiveForSession(
|
|
696
|
+
&& !(await isVisibleRalphActiveForSession(stateDir, sessionId))
|
|
625
697
|
) {
|
|
626
698
|
continue;
|
|
627
699
|
}
|
|
@@ -635,7 +707,7 @@ async function readActiveRalphState(
|
|
|
635
707
|
currentNativeSessionId,
|
|
636
708
|
tmuxPaneId: safeString(ownerContext?.tmuxPaneId).trim(),
|
|
637
709
|
})
|
|
638
|
-
&& await hasConsistentRalphSkillActivation(
|
|
710
|
+
&& await hasConsistentRalphSkillActivation(stateDir, sessionId)
|
|
639
711
|
) {
|
|
640
712
|
return { state: sessionScoped, path: sessionScopedPath };
|
|
641
713
|
}
|
|
@@ -1314,6 +1386,10 @@ function buildNativeOutsideTmuxTeamPromptBlockState(
|
|
|
1314
1386
|
};
|
|
1315
1387
|
}
|
|
1316
1388
|
|
|
1389
|
+
function buildSkillStateCliInstruction(mode: string, statePath: string): string {
|
|
1390
|
+
return `skill: ${mode} activated and initial state initialized at ${statePath}; use CLI-first state updates via \`omx state write/read/clear --input '<json>' --json\`; use omx_state MCP only when explicit MCP compatibility is enabled.`;
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1317
1393
|
function buildAdditionalContextMessage(
|
|
1318
1394
|
prompt: string,
|
|
1319
1395
|
skillState?: SkillActiveState | null,
|
|
@@ -1375,7 +1451,7 @@ function buildAdditionalContextMessage(
|
|
|
1375
1451
|
promptPriorityMessage,
|
|
1376
1452
|
ultragoalPromptActivationNote,
|
|
1377
1453
|
skillState.initialized_mode && skillState.initialized_state_path
|
|
1378
|
-
?
|
|
1454
|
+
? buildSkillStateCliInstruction(skillState.initialized_mode, skillState.initialized_state_path)
|
|
1379
1455
|
: null,
|
|
1380
1456
|
teamDetected
|
|
1381
1457
|
? buildTeamRuntimeInstruction(cwd, payload)
|
|
@@ -1387,7 +1463,7 @@ function buildAdditionalContextMessage(
|
|
|
1387
1463
|
|
|
1388
1464
|
if (teamDetected) {
|
|
1389
1465
|
const initializedStateMessage = skillState?.initialized_mode && skillState.initialized_state_path
|
|
1390
|
-
?
|
|
1466
|
+
? buildSkillStateCliInstruction(skillState.initialized_mode, skillState.initialized_state_path)
|
|
1391
1467
|
: null;
|
|
1392
1468
|
return [
|
|
1393
1469
|
detectedKeywordMessage,
|
|
@@ -1414,7 +1490,7 @@ function buildAdditionalContextMessage(
|
|
|
1414
1490
|
? `planning preserved over simultaneous execution follow-up; deferred skills: ${deferredSkills.join(", ")}.`
|
|
1415
1491
|
: null,
|
|
1416
1492
|
promptPriorityMessage,
|
|
1417
|
-
|
|
1493
|
+
buildSkillStateCliInstruction(skillState.initialized_mode, skillState.initialized_state_path),
|
|
1418
1494
|
deepInterviewPromptActivationNote,
|
|
1419
1495
|
ultraworkPromptActivationNote,
|
|
1420
1496
|
ultragoalPromptActivationNote,
|
|
@@ -1481,7 +1557,7 @@ async function resolveTeamWorkerStopDecision(
|
|
|
1481
1557
|
const blockWorkerStop = (
|
|
1482
1558
|
reasonCode: string,
|
|
1483
1559
|
detail: string,
|
|
1484
|
-
stateDirForDecision =
|
|
1560
|
+
stateDirForDecision = getBaseStateDir(cwd),
|
|
1485
1561
|
): TeamWorkerStopDecision => ({
|
|
1486
1562
|
kind: "blocked",
|
|
1487
1563
|
stateDir: stateDirForDecision,
|
|
@@ -1654,7 +1730,10 @@ async function findActiveGoalWorkflowReconciliationRequirement(cwd: string): Pro
|
|
|
1654
1730
|
if (!entry.isDirectory()) continue;
|
|
1655
1731
|
const mission = await readJsonIfExists(join(autoresearchRoot, entry.name, "mission.json"));
|
|
1656
1732
|
const status = safeString(mission?.status);
|
|
1657
|
-
|
|
1733
|
+
const completion = await readJsonIfExists(join(autoresearchRoot, entry.name, "completion.json"));
|
|
1734
|
+
const completionVerdict = safeString(completion?.verdict);
|
|
1735
|
+
const completionPassed = completion?.passed === true || completionVerdict === "pass";
|
|
1736
|
+
if (mission?.workflow === "autoresearch-goal" && status && status !== "complete" && completionPassed) {
|
|
1658
1737
|
return {
|
|
1659
1738
|
workflow: "autoresearch-goal",
|
|
1660
1739
|
command: `omx autoresearch-goal complete --slug ${safeString(mission.slug) || entry.name} --codex-goal-json '<get_goal JSON or path>'`,
|
|
@@ -1696,6 +1775,7 @@ async function buildGoalWorkflowReconciliationStopOutput(
|
|
|
1696
1775
|
|
|
1697
1776
|
async function readTeamModeStateForStop(
|
|
1698
1777
|
cwd: string,
|
|
1778
|
+
stateDir: string,
|
|
1699
1779
|
sessionId?: string,
|
|
1700
1780
|
): Promise<Record<string, unknown> | null> {
|
|
1701
1781
|
const normalizedSessionId = safeString(sessionId).trim();
|
|
@@ -1703,10 +1783,10 @@ async function readTeamModeStateForStop(
|
|
|
1703
1783
|
return await readModeState("team", cwd);
|
|
1704
1784
|
}
|
|
1705
1785
|
|
|
1706
|
-
const scopedState = await readStopSessionPinnedState("team-state.json", cwd, normalizedSessionId);
|
|
1786
|
+
const scopedState = await readStopSessionPinnedState("team-state.json", cwd, normalizedSessionId, stateDir);
|
|
1707
1787
|
if (scopedState) return scopedState;
|
|
1708
1788
|
|
|
1709
|
-
const rootState = await readJsonIfExists(join(
|
|
1789
|
+
const rootState = await readJsonIfExists(join(stateDir, "team-state.json"));
|
|
1710
1790
|
if (rootState?.active !== true) return null;
|
|
1711
1791
|
|
|
1712
1792
|
const ownerSessionId = safeString(rootState.session_id).trim();
|
|
@@ -1721,7 +1801,7 @@ async function buildTeamStopOutput(cwd: string, sessionId?: string): Promise<Rec
|
|
|
1721
1801
|
if (await readCanonicalTerminalRunStateForStop(cwd, sessionId, "team")) {
|
|
1722
1802
|
return null;
|
|
1723
1803
|
}
|
|
1724
|
-
const teamState = await readTeamModeStateForStop(cwd, sessionId);
|
|
1804
|
+
const teamState = await readTeamModeStateForStop(cwd, getBaseStateDir(cwd), sessionId);
|
|
1725
1805
|
if (teamState?.active !== true) return null;
|
|
1726
1806
|
const teamName = safeString(teamState.team_name).trim();
|
|
1727
1807
|
if (teamName) {
|
|
@@ -1779,12 +1859,13 @@ function hasReleaseReadinessMode(payload: CodexHookPayload): boolean {
|
|
|
1779
1859
|
|
|
1780
1860
|
async function hasReleaseReadinessStopMarker(
|
|
1781
1861
|
cwd: string,
|
|
1862
|
+
stateDir: string,
|
|
1782
1863
|
sessionId: string,
|
|
1783
1864
|
teamName: string,
|
|
1784
1865
|
): Promise<boolean> {
|
|
1785
1866
|
if (!sessionId) return false;
|
|
1786
1867
|
|
|
1787
|
-
const markerState = await readStopSessionPinnedState("release-readiness-state.json", cwd, sessionId);
|
|
1868
|
+
const markerState = await readStopSessionPinnedState("release-readiness-state.json", cwd, sessionId, stateDir);
|
|
1788
1869
|
if (markerState?.active !== true || markerState.stable_final_recommendation_emitted !== true) {
|
|
1789
1870
|
return false;
|
|
1790
1871
|
}
|
|
@@ -1829,8 +1910,11 @@ async function readStopSessionPinnedState(
|
|
|
1829
1910
|
fileName: string,
|
|
1830
1911
|
cwd: string,
|
|
1831
1912
|
sessionId: string,
|
|
1913
|
+
stateDir?: string,
|
|
1832
1914
|
): Promise<Record<string, unknown> | null> {
|
|
1833
|
-
const statePath =
|
|
1915
|
+
const statePath = stateDir && sessionId
|
|
1916
|
+
? join(stateDir, "sessions", sessionId, fileName)
|
|
1917
|
+
: getStateFilePath(fileName, cwd, sessionId || undefined);
|
|
1834
1918
|
return readJsonIfExists(statePath);
|
|
1835
1919
|
}
|
|
1836
1920
|
|
|
@@ -1881,11 +1965,12 @@ function modeStateMatchesSkillStopContext(
|
|
|
1881
1965
|
|
|
1882
1966
|
async function readBlockingSkillForStop(
|
|
1883
1967
|
cwd: string,
|
|
1968
|
+
stateDir: string,
|
|
1884
1969
|
sessionId: string,
|
|
1885
1970
|
threadId: string,
|
|
1886
1971
|
requiredSkill?: string,
|
|
1887
1972
|
): Promise<{ skill: string; phase: string; latestPlanPath?: string; planningComplete?: boolean; runOutcome?: string } | null> {
|
|
1888
|
-
const canonicalState = await
|
|
1973
|
+
const canonicalState = await readVisibleSkillActiveStateForStateDir(stateDir, sessionId);
|
|
1889
1974
|
const visibleEntries = canonicalState ? listActiveSkills(canonicalState) : [];
|
|
1890
1975
|
const candidateSkills = requiredSkill
|
|
1891
1976
|
? [requiredSkill]
|
|
@@ -1895,7 +1980,7 @@ async function readBlockingSkillForStop(
|
|
|
1895
1980
|
const terminalRunState = await readCanonicalTerminalRunStateForStop(cwd, sessionId, skill);
|
|
1896
1981
|
if (terminalRunState) continue;
|
|
1897
1982
|
|
|
1898
|
-
const modeState = await readStopSessionPinnedState(`${skill}-state.json`, cwd, sessionId);
|
|
1983
|
+
const modeState = await readStopSessionPinnedState(`${skill}-state.json`, cwd, sessionId, stateDir);
|
|
1899
1984
|
if (!modeState || modeState.active !== true) continue;
|
|
1900
1985
|
if (!modeStateMatchesSkillStopContext(modeState, cwd, sessionId)) continue;
|
|
1901
1986
|
|
|
@@ -1955,11 +2040,12 @@ function isTerminalOrInactiveModeState(state: Record<string, unknown> | null): b
|
|
|
1955
2040
|
|
|
1956
2041
|
async function readSessionScopedModeStateForRootSkill(
|
|
1957
2042
|
cwd: string,
|
|
2043
|
+
stateDir: string,
|
|
1958
2044
|
skill: string,
|
|
1959
2045
|
sessionIds: string[],
|
|
1960
2046
|
): Promise<Record<string, unknown> | null> {
|
|
1961
2047
|
for (const sessionId of sessionIds) {
|
|
1962
|
-
const state = await
|
|
2048
|
+
const state = await readStopSessionPinnedState(`${skill}-state.json`, cwd, sessionId, stateDir);
|
|
1963
2049
|
if (state) return state;
|
|
1964
2050
|
}
|
|
1965
2051
|
return null;
|
|
@@ -1967,9 +2053,10 @@ async function readSessionScopedModeStateForRootSkill(
|
|
|
1967
2053
|
|
|
1968
2054
|
async function reconcileStaleRootSkillActiveStateForStop(
|
|
1969
2055
|
cwd: string,
|
|
2056
|
+
stateDir: string,
|
|
1970
2057
|
sessionId: string,
|
|
1971
2058
|
): Promise<void> {
|
|
1972
|
-
const { rootPath } =
|
|
2059
|
+
const { rootPath } = getSkillActiveStatePathsForStateDir(stateDir);
|
|
1973
2060
|
const rootState = await readSkillActiveState(rootPath);
|
|
1974
2061
|
if (!rootState?.active) return;
|
|
1975
2062
|
|
|
@@ -1995,7 +2082,7 @@ async function reconcileStaleRootSkillActiveStateForStop(
|
|
|
1995
2082
|
initializedSessionId,
|
|
1996
2083
|
safeString(rootState.session_id),
|
|
1997
2084
|
]);
|
|
1998
|
-
const modeState = await readSessionScopedModeStateForRootSkill(cwd, skill, candidateSessionIds);
|
|
2085
|
+
const modeState = await readSessionScopedModeStateForRootSkill(cwd, stateDir, skill, candidateSessionIds);
|
|
1999
2086
|
if (isTerminalOrInactiveModeState(modeState)) {
|
|
2000
2087
|
changed = true;
|
|
2001
2088
|
continue;
|
|
@@ -2074,12 +2161,13 @@ function buildRalplanContinuationStatus(
|
|
|
2074
2161
|
|
|
2075
2162
|
async function readStopAutoNudgePhase(
|
|
2076
2163
|
cwd: string,
|
|
2164
|
+
stateDir: string,
|
|
2077
2165
|
sessionId: string,
|
|
2078
2166
|
threadId: string,
|
|
2079
2167
|
): Promise<string> {
|
|
2080
2168
|
const normalizedSessionId = sessionId.trim();
|
|
2081
2169
|
if (normalizedSessionId) {
|
|
2082
|
-
const scopedModeState = await readStopSessionPinnedState("deep-interview-state.json", cwd, normalizedSessionId);
|
|
2170
|
+
const scopedModeState = await readStopSessionPinnedState("deep-interview-state.json", cwd, normalizedSessionId, stateDir);
|
|
2083
2171
|
if (
|
|
2084
2172
|
scopedModeState?.active === true
|
|
2085
2173
|
&& safeString(scopedModeState.current_phase).trim().toLowerCase() === "intent-first"
|
|
@@ -2087,7 +2175,7 @@ async function readStopAutoNudgePhase(
|
|
|
2087
2175
|
return "planning";
|
|
2088
2176
|
}
|
|
2089
2177
|
} else {
|
|
2090
|
-
const rootModeState = await readJsonIfExists(join(
|
|
2178
|
+
const rootModeState = await readJsonIfExists(join(stateDir, "deep-interview-state.json"));
|
|
2091
2179
|
if (
|
|
2092
2180
|
rootModeState?.active === true
|
|
2093
2181
|
&& safeString(rootModeState.current_phase).trim().toLowerCase() === "intent-first"
|
|
@@ -2098,7 +2186,7 @@ async function readStopAutoNudgePhase(
|
|
|
2098
2186
|
|
|
2099
2187
|
if (!normalizedSessionId) return "";
|
|
2100
2188
|
|
|
2101
|
-
const canonicalState = await
|
|
2189
|
+
const canonicalState = await readVisibleSkillActiveStateForStateDir(stateDir, normalizedSessionId);
|
|
2102
2190
|
const visibleEntries = canonicalState ? listActiveSkills(canonicalState) : [];
|
|
2103
2191
|
const deepInterview = visibleEntries.find((entry) => (
|
|
2104
2192
|
entry.skill === "deep-interview"
|
|
@@ -2106,7 +2194,7 @@ async function readStopAutoNudgePhase(
|
|
|
2106
2194
|
));
|
|
2107
2195
|
if (!deepInterview) return "";
|
|
2108
2196
|
|
|
2109
|
-
const modeState = await readStopSessionPinnedState("deep-interview-state.json", cwd, normalizedSessionId);
|
|
2197
|
+
const modeState = await readStopSessionPinnedState("deep-interview-state.json", cwd, normalizedSessionId, stateDir);
|
|
2110
2198
|
if (!modeState || modeState.active !== true) return "";
|
|
2111
2199
|
|
|
2112
2200
|
const modePhase = safeString(modeState.current_phase).trim().toLowerCase();
|
|
@@ -2115,11 +2203,12 @@ async function readStopAutoNudgePhase(
|
|
|
2115
2203
|
|
|
2116
2204
|
async function buildDeepInterviewQuestionStopOutput(
|
|
2117
2205
|
cwd: string,
|
|
2206
|
+
stateDir: string,
|
|
2118
2207
|
sessionId: string,
|
|
2119
2208
|
threadId: string,
|
|
2120
2209
|
): Promise<{ output: Record<string, unknown>; obligationId: string } | null> {
|
|
2121
2210
|
await reconcileDeepInterviewQuestionEnforcementFromAnsweredRecords(cwd, sessionId);
|
|
2122
|
-
const modeState = await readStopSessionPinnedState("deep-interview-state.json", cwd, sessionId);
|
|
2211
|
+
const modeState = await readStopSessionPinnedState("deep-interview-state.json", cwd, sessionId, stateDir);
|
|
2123
2212
|
if (!modeState) return null;
|
|
2124
2213
|
|
|
2125
2214
|
const questionEnforcement = safeObject(modeState.question_enforcement);
|
|
@@ -2131,7 +2220,7 @@ async function buildDeepInterviewQuestionStopOutput(
|
|
|
2131
2220
|
return null;
|
|
2132
2221
|
}
|
|
2133
2222
|
|
|
2134
|
-
const canonicalState = await
|
|
2223
|
+
const canonicalState = await readVisibleSkillActiveStateForStateDir(stateDir, sessionId);
|
|
2135
2224
|
if (canonicalState) {
|
|
2136
2225
|
const blocker = listActiveSkills(canonicalState).find((entry) => (
|
|
2137
2226
|
entry.skill === "deep-interview"
|
|
@@ -2334,9 +2423,10 @@ async function findCanonicalActiveTeamForSession(
|
|
|
2334
2423
|
|
|
2335
2424
|
async function resolveActiveTeamNameForStop(
|
|
2336
2425
|
cwd: string,
|
|
2426
|
+
stateDir: string,
|
|
2337
2427
|
sessionId: string,
|
|
2338
2428
|
): Promise<string> {
|
|
2339
|
-
const directState = await readTeamModeStateForStop(cwd, sessionId);
|
|
2429
|
+
const directState = await readTeamModeStateForStop(cwd, stateDir, sessionId);
|
|
2340
2430
|
const directTeamName = safeString(directState?.team_name).trim();
|
|
2341
2431
|
if (directState?.active === true && directTeamName) return directTeamName;
|
|
2342
2432
|
|
|
@@ -2352,12 +2442,12 @@ async function maybeBuildReleaseReadinessFinalizeStopOutput(
|
|
|
2352
2442
|
): Promise<{ matched: boolean; output: Record<string, unknown> | null }> {
|
|
2353
2443
|
if (!sessionId) return { matched: false, output: null };
|
|
2354
2444
|
|
|
2355
|
-
const teamName = await resolveActiveTeamNameForStop(cwd, sessionId);
|
|
2445
|
+
const teamName = await resolveActiveTeamNameForStop(cwd, stateDir, sessionId);
|
|
2356
2446
|
if (!teamName) return { matched: false, output: null };
|
|
2357
2447
|
|
|
2358
2448
|
const explicitReleaseReadinessContext =
|
|
2359
2449
|
hasReleaseReadinessMode(payload)
|
|
2360
|
-
|| await hasReleaseReadinessStopMarker(cwd, sessionId, teamName);
|
|
2450
|
+
|| await hasReleaseReadinessStopMarker(cwd, stateDir, sessionId, teamName);
|
|
2361
2451
|
if (!explicitReleaseReadinessContext) {
|
|
2362
2452
|
return { matched: false, output: null };
|
|
2363
2453
|
}
|
|
@@ -2395,10 +2485,11 @@ async function maybeBuildReleaseReadinessFinalizeStopOutput(
|
|
|
2395
2485
|
|
|
2396
2486
|
async function buildSkillStopOutput(
|
|
2397
2487
|
cwd: string,
|
|
2488
|
+
stateDir: string,
|
|
2398
2489
|
sessionId: string,
|
|
2399
2490
|
threadId: string,
|
|
2400
2491
|
): Promise<Record<string, unknown> | null> {
|
|
2401
|
-
const blocker = await readBlockingSkillForStop(cwd, sessionId, threadId);
|
|
2492
|
+
const blocker = await readBlockingSkillForStop(cwd, stateDir, sessionId, threadId);
|
|
2402
2493
|
if (!blocker) return null;
|
|
2403
2494
|
|
|
2404
2495
|
const subagentSummary = await readSubagentSessionSummary(cwd, sessionId).catch(() => null);
|
|
@@ -2545,17 +2636,41 @@ async function buildStopHookOutput(
|
|
|
2545
2636
|
const canonicalSessionId = await resolveInternalSessionIdForPayload(cwd, sessionId);
|
|
2546
2637
|
const threadId = readPayloadThreadId(payload);
|
|
2547
2638
|
if (canonicalSessionId) {
|
|
2548
|
-
await reconcileStaleRootSkillActiveStateForStop(cwd, canonicalSessionId);
|
|
2639
|
+
await reconcileStaleRootSkillActiveStateForStop(cwd, stateDir, canonicalSessionId);
|
|
2549
2640
|
}
|
|
2550
2641
|
const execFollowupOutput = await buildExecFollowupStopOutput(cwd, canonicalSessionId);
|
|
2551
2642
|
if (execFollowupOutput) return execFollowupOutput;
|
|
2643
|
+
const ralphOwnerContext = {
|
|
2644
|
+
payloadSessionId: sessionId,
|
|
2645
|
+
threadId,
|
|
2646
|
+
tmuxPaneId: safeString(process.env.TMUX_PANE).trim(),
|
|
2647
|
+
};
|
|
2648
|
+
const ralphCompletionAuditBlock = options.skipRalphStopBlock === true
|
|
2649
|
+
? null
|
|
2650
|
+
: await readRalphCompletionAuditBlockState(cwd, stateDir, canonicalSessionId, ralphOwnerContext);
|
|
2651
|
+
if (ralphCompletionAuditBlock) {
|
|
2652
|
+
await reopenRalphCompletionAuditBlock(ralphCompletionAuditBlock);
|
|
2653
|
+
const blockingPath = formatStopStatePath(cwd, ralphCompletionAuditBlock.path);
|
|
2654
|
+
const systemMessage =
|
|
2655
|
+
`OMX Ralph completion audit is missing required evidence (${ralphCompletionAuditBlock.reason}; state: ${blockingPath}); continue verification, record a prompt-to-artifact checklist plus verification evidence, and do not report complete yet.`;
|
|
2656
|
+
return await returnPersistentStopBlock(
|
|
2657
|
+
payload,
|
|
2658
|
+
stateDir,
|
|
2659
|
+
"ralph-completion-audit-stop",
|
|
2660
|
+
`${blockingPath}|${ralphCompletionAuditBlock.reason}`,
|
|
2661
|
+
{
|
|
2662
|
+
decision: "block",
|
|
2663
|
+
reason: systemMessage,
|
|
2664
|
+
stopReason: `ralph_completion_audit_${ralphCompletionAuditBlock.reason}`,
|
|
2665
|
+
systemMessage,
|
|
2666
|
+
},
|
|
2667
|
+
canonicalSessionId,
|
|
2668
|
+
{ allowRepeatDuringStopHook: true },
|
|
2669
|
+
);
|
|
2670
|
+
}
|
|
2552
2671
|
const ralphState = options.skipRalphStopBlock === true
|
|
2553
2672
|
? null
|
|
2554
|
-
: await readActiveRalphState(stateDir, canonicalSessionId,
|
|
2555
|
-
payloadSessionId: sessionId,
|
|
2556
|
-
threadId,
|
|
2557
|
-
tmuxPaneId: safeString(process.env.TMUX_PANE).trim(),
|
|
2558
|
-
});
|
|
2673
|
+
: await readActiveRalphState(cwd, stateDir, canonicalSessionId, ralphOwnerContext);
|
|
2559
2674
|
if (!ralphState) {
|
|
2560
2675
|
const autoresearchState = await readActiveAutoresearchState(cwd, canonicalSessionId);
|
|
2561
2676
|
if (autoresearchState) {
|
|
@@ -2665,6 +2780,7 @@ async function buildStopHookOutput(
|
|
|
2665
2780
|
if (canonicalSessionId) {
|
|
2666
2781
|
const deepInterviewQuestionOutput = await buildDeepInterviewQuestionStopOutput(
|
|
2667
2782
|
cwd,
|
|
2783
|
+
stateDir,
|
|
2668
2784
|
canonicalSessionId,
|
|
2669
2785
|
threadId,
|
|
2670
2786
|
);
|
|
@@ -2698,7 +2814,7 @@ async function buildStopHookOutput(
|
|
|
2698
2814
|
if (repeatedCanonicalTeamOutput) return repeatedCanonicalTeamOutput;
|
|
2699
2815
|
}
|
|
2700
2816
|
|
|
2701
|
-
const skillOutput = await buildSkillStopOutput(cwd, canonicalSessionId, threadId);
|
|
2817
|
+
const skillOutput = await buildSkillStopOutput(cwd, stateDir, canonicalSessionId, threadId);
|
|
2702
2818
|
if (skillOutput) {
|
|
2703
2819
|
return await returnPersistentStopBlock(
|
|
2704
2820
|
payload,
|
|
@@ -2728,7 +2844,7 @@ async function buildStopHookOutput(
|
|
|
2728
2844
|
);
|
|
2729
2845
|
}
|
|
2730
2846
|
const autoNudgeConfig = await loadAutoNudgeConfig();
|
|
2731
|
-
const autoNudgePhase = await readStopAutoNudgePhase(cwd, canonicalSessionId, threadId);
|
|
2847
|
+
const autoNudgePhase = await readStopAutoNudgePhase(cwd, stateDir, canonicalSessionId, threadId);
|
|
2732
2848
|
|
|
2733
2849
|
if (
|
|
2734
2850
|
autoNudgeConfig.enabled
|
|
@@ -2814,7 +2930,9 @@ export async function dispatchCodexNativeHook(
|
|
|
2814
2930
|
): Promise<NativeHookDispatchResult> {
|
|
2815
2931
|
const hookEventName = readHookEventName(payload);
|
|
2816
2932
|
const cwd = options.cwd ?? (safeString(payload.cwd).trim() || process.cwd());
|
|
2817
|
-
|
|
2933
|
+
// Native hooks must use the same authoritative runtime state root as HUD/MCP
|
|
2934
|
+
// when boxed/team roots are active; do not bypass it with cwd/.omx/state.
|
|
2935
|
+
const stateDir = getBaseStateDir(cwd);
|
|
2818
2936
|
await mkdir(stateDir, { recursive: true });
|
|
2819
2937
|
|
|
2820
2938
|
const omxEventName = mapCodexHookEventToOmxEvent(hookEventName);
|
|
@@ -2916,6 +3034,7 @@ export async function dispatchCodexNativeHook(
|
|
|
2916
3034
|
turnId || undefined,
|
|
2917
3035
|
) ?? await recordSkillActivation({
|
|
2918
3036
|
stateDir,
|
|
3037
|
+
sourceCwd: cwd,
|
|
2919
3038
|
text: prompt,
|
|
2920
3039
|
sessionId: sessionIdForState,
|
|
2921
3040
|
threadId,
|
|
@@ -3023,25 +3142,10 @@ export async function dispatchCodexNativeHook(
|
|
|
3023
3142
|
}
|
|
3024
3143
|
|
|
3025
3144
|
if (hookEventName === "PreCompact") {
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
hookEventName,
|
|
3031
|
-
additionalContext: compactContext.additionalContext,
|
|
3032
|
-
},
|
|
3033
|
-
};
|
|
3034
|
-
}
|
|
3035
|
-
} else if (hookEventName === "PostCompact") {
|
|
3036
|
-
const compactContext = buildWikiPostCompactContext({ cwd });
|
|
3037
|
-
if (compactContext.additionalContext) {
|
|
3038
|
-
outputJson = {
|
|
3039
|
-
hookSpecificOutput: {
|
|
3040
|
-
hookEventName,
|
|
3041
|
-
additionalContext: compactContext.additionalContext,
|
|
3042
|
-
},
|
|
3043
|
-
};
|
|
3044
|
-
}
|
|
3145
|
+
// Codex native PreCompact currently accepts only the common continuation fields.
|
|
3146
|
+
// Keep the OMX lifecycle dispatch above, but do not emit `hookSpecificOutput`
|
|
3147
|
+
// unless Codex defines a supported PreCompact output contract.
|
|
3148
|
+
buildWikiPreCompactContext({ cwd });
|
|
3045
3149
|
} else if ((hookEventName === "SessionStart" && !skipCanonicalSessionStartContext) || hookEventName === "UserPromptSubmit") {
|
|
3046
3150
|
const additionalContext = hookEventName === "SessionStart"
|
|
3047
3151
|
? await buildSessionStartContext(cwd, canonicalSessionId || nativeSessionId, {
|
|
@@ -185,7 +185,10 @@ function resolveOmxParityTarget(toolName: string): { command: OmxParityCommand;
|
|
|
185
185
|
if (!match) return null;
|
|
186
186
|
|
|
187
187
|
const [, server, tool] = match;
|
|
188
|
-
if (server === "state")
|
|
188
|
+
if (server === "state") {
|
|
189
|
+
const stateTool = tool.replace(/^state_/, "").replace(/_/g, "-");
|
|
190
|
+
return { command: "state", tool: stateTool };
|
|
191
|
+
}
|
|
189
192
|
if (server === "trace") return { command: "trace", tool };
|
|
190
193
|
if (server === "code_intel") return { command: "code-intel", tool };
|
|
191
194
|
if (server === "memory" && tool.startsWith("notepad_")) {
|