oh-my-codex 0.18.7 → 0.18.8
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 +6 -6
- package/Cargo.toml +1 -1
- package/README.md +5 -5
- package/crates/omx-sparkshell/tests/execution.rs +1 -1
- package/dist/agents/__tests__/native-config.test.js +42 -1
- package/dist/agents/__tests__/native-config.test.js.map +1 -1
- package/dist/agents/definitions.d.ts +8 -0
- package/dist/agents/definitions.d.ts.map +1 -1
- package/dist/agents/definitions.js +1 -0
- package/dist/agents/definitions.js.map +1 -1
- package/dist/agents/native-config.d.ts +5 -1
- package/dist/agents/native-config.d.ts.map +1 -1
- package/dist/agents/native-config.js +17 -2
- package/dist/agents/native-config.js.map +1 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js +512 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js +39 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +61 -5
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/package-bin-contract.test.js +8 -4
- package/dist/cli/__tests__/package-bin-contract.test.js.map +1 -1
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +13 -0
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
- package/dist/cli/__tests__/ralph.test.js +14 -0
- package/dist/cli/__tests__/ralph.test.js.map +1 -1
- package/dist/cli/__tests__/setup-install-mode.test.js +89 -0
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
- package/dist/cli/__tests__/setup-refresh.test.js +65 -0
- package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
- package/dist/cli/__tests__/state.test.js +21 -0
- package/dist/cli/__tests__/state.test.js.map +1 -1
- package/dist/cli/__tests__/team.test.js +2 -2
- package/dist/cli/__tests__/update.test.js +110 -2
- package/dist/cli/__tests__/update.test.js.map +1 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +8 -1
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.d.ts +11 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +108 -15
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/plugin-marketplace.d.ts +14 -2
- package/dist/cli/plugin-marketplace.d.ts.map +1 -1
- package/dist/cli/plugin-marketplace.js +62 -15
- package/dist/cli/plugin-marketplace.js.map +1 -1
- package/dist/cli/ralph.d.ts.map +1 -1
- package/dist/cli/ralph.js +3 -1
- package/dist/cli/ralph.js.map +1 -1
- package/dist/cli/setup-preferences.d.ts +2 -0
- package/dist/cli/setup-preferences.d.ts.map +1 -1
- package/dist/cli/setup-preferences.js +4 -0
- package/dist/cli/setup-preferences.js.map +1 -1
- package/dist/cli/setup.d.ts +3 -0
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +166 -27
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/state.d.ts.map +1 -1
- package/dist/cli/state.js +8 -1
- package/dist/cli/state.js.map +1 -1
- package/dist/cli/tmux-hook.d.ts.map +1 -1
- package/dist/cli/tmux-hook.js +16 -0
- package/dist/cli/tmux-hook.js.map +1 -1
- package/dist/cli/update.d.ts +2 -0
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +47 -3
- package/dist/cli/update.js.map +1 -1
- package/dist/config/__tests__/generator-notify.test.js +1 -0
- package/dist/config/__tests__/generator-notify.test.js.map +1 -1
- package/dist/config/generator.d.ts +2 -2
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +2 -2
- package/dist/config/generator.js.map +1 -1
- package/dist/config/team-mode.d.ts +12 -0
- package/dist/config/team-mode.d.ts.map +1 -0
- package/dist/config/team-mode.js +91 -0
- package/dist/config/team-mode.js.map +1 -0
- package/dist/hooks/__tests__/agents-overlay.test.js +88 -0
- package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
- package/dist/hooks/__tests__/code-review-skill-contract.test.js +8 -0
- package/dist/hooks/__tests__/code-review-skill-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +423 -3
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js +1 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +189 -0
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +35 -2
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +3 -3
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
- package/dist/hooks/__tests__/skill-guidance-contract.test.js +21 -0
- package/dist/hooks/__tests__/skill-guidance-contract.test.js.map +1 -1
- package/dist/hooks/agents-overlay.d.ts.map +1 -1
- package/dist/hooks/agents-overlay.js +36 -50
- package/dist/hooks/agents-overlay.js.map +1 -1
- package/dist/hooks/extensibility/__tests__/plugin-runner.test.js +31 -0
- package/dist/hooks/extensibility/__tests__/plugin-runner.test.js.map +1 -1
- package/dist/hooks/extensibility/plugin-runner.js +17 -21
- package/dist/hooks/extensibility/plugin-runner.js.map +1 -1
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +258 -12
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
- package/dist/hooks/prompt-guidance-contract.js +6 -0
- package/dist/hooks/prompt-guidance-contract.js.map +1 -1
- package/dist/hooks/session.d.ts +1 -0
- package/dist/hooks/session.d.ts.map +1 -1
- package/dist/hooks/session.js.map +1 -1
- package/dist/hud/__tests__/authority.test.js +435 -32
- package/dist/hud/__tests__/authority.test.js.map +1 -1
- package/dist/hud/__tests__/hud-tmux-injection.test.js +2 -1
- package/dist/hud/__tests__/hud-tmux-injection.test.js.map +1 -1
- package/dist/hud/__tests__/index.test.js +42 -0
- package/dist/hud/__tests__/index.test.js.map +1 -1
- package/dist/hud/__tests__/reconcile.test.js +521 -15
- package/dist/hud/__tests__/reconcile.test.js.map +1 -1
- package/dist/hud/__tests__/render.test.js +61 -0
- package/dist/hud/__tests__/render.test.js.map +1 -1
- package/dist/hud/__tests__/state.test.js +132 -4
- package/dist/hud/__tests__/state.test.js.map +1 -1
- package/dist/hud/__tests__/tmux.test.js +180 -21
- package/dist/hud/__tests__/tmux.test.js.map +1 -1
- package/dist/hud/authority.d.ts +5 -0
- package/dist/hud/authority.d.ts.map +1 -1
- package/dist/hud/authority.js +324 -28
- package/dist/hud/authority.js.map +1 -1
- package/dist/hud/index.d.ts +3 -2
- package/dist/hud/index.d.ts.map +1 -1
- package/dist/hud/index.js +42 -19
- package/dist/hud/index.js.map +1 -1
- package/dist/hud/reconcile.d.ts +3 -3
- package/dist/hud/reconcile.d.ts.map +1 -1
- package/dist/hud/reconcile.js +128 -19
- package/dist/hud/reconcile.js.map +1 -1
- package/dist/hud/render.d.ts.map +1 -1
- package/dist/hud/render.js +35 -0
- package/dist/hud/render.js.map +1 -1
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +61 -62
- package/dist/hud/state.js.map +1 -1
- package/dist/hud/tmux.d.ts +24 -6
- package/dist/hud/tmux.d.ts.map +1 -1
- package/dist/hud/tmux.js +136 -38
- package/dist/hud/tmux.js.map +1 -1
- package/dist/hud/types.d.ts +11 -0
- package/dist/hud/types.d.ts.map +1 -1
- package/dist/hud/types.js.map +1 -1
- package/dist/mcp/__tests__/state-paths.test.js +71 -1
- package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
- package/dist/mcp/state-paths.d.ts +32 -0
- package/dist/mcp/state-paths.d.ts.map +1 -1
- package/dist/mcp/state-paths.js +113 -17
- package/dist/mcp/state-paths.js.map +1 -1
- package/dist/mcp/state-server.d.ts +4 -4
- package/dist/scripts/__tests__/codex-native-hook.test.js +593 -11
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/notify-state-io.test.js +72 -1
- package/dist/scripts/__tests__/notify-state-io.test.js.map +1 -1
- package/dist/scripts/__tests__/notify-tmux-injection.test.d.ts +2 -0
- package/dist/scripts/__tests__/notify-tmux-injection.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/notify-tmux-injection.test.js +57 -0
- package/dist/scripts/__tests__/notify-tmux-injection.test.js.map +1 -0
- package/dist/scripts/__tests__/run-test-files.test.js +74 -0
- package/dist/scripts/__tests__/run-test-files.test.js.map +1 -1
- package/dist/scripts/__tests__/verify-native-agents.test.js +65 -0
- package/dist/scripts/__tests__/verify-native-agents.test.js.map +1 -1
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +88 -31
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/eval/eval-parity-smoke.js +1 -1
- package/dist/scripts/eval/eval-parity-smoke.js.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.js +3 -1
- package/dist/scripts/notify-hook/auto-nudge.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 +3 -10
- 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 +62 -38
- package/dist/scripts/notify-hook/state-io.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 +7 -0
- package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.d.ts +7 -0
- package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.js +24 -18
- package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
- package/dist/scripts/notify-hook.js +75 -11
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/scripts/run-test-files.js +193 -22
- package/dist/scripts/run-test-files.js.map +1 -1
- package/dist/scripts/sync-plugin-mirror.d.ts.map +1 -1
- package/dist/scripts/sync-plugin-mirror.js +61 -3
- package/dist/scripts/sync-plugin-mirror.js.map +1 -1
- package/dist/scripts/verify-native-agents.d.ts.map +1 -1
- package/dist/scripts/verify-native-agents.js +58 -1
- package/dist/scripts/verify-native-agents.js.map +1 -1
- package/dist/state/__tests__/operations.test.js +113 -0
- package/dist/state/__tests__/operations.test.js.map +1 -1
- package/dist/state/__tests__/skill-active.test.js +3 -16
- package/dist/state/__tests__/skill-active.test.js.map +1 -1
- package/dist/state/__tests__/workflow-transition.test.js +25 -0
- 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 +57 -2
- package/dist/state/operations.js.map +1 -1
- package/dist/state/skill-active.d.ts.map +1 -1
- package/dist/state/skill-active.js +7 -39
- package/dist/state/skill-active.js.map +1 -1
- package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
- package/dist/state/workflow-transition-reconcile.js +10 -14
- package/dist/state/workflow-transition-reconcile.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +1 -1
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/scaling.test.js +9 -4
- package/dist/team/__tests__/scaling.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +195 -2
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/__tests__/worker-runtime-identity.test.js +4 -2
- package/dist/team/__tests__/worker-runtime-identity.test.js.map +1 -1
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +3 -2
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/tmux-session.d.ts +2 -0
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +142 -12
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/verification/__tests__/ci-rust-gates.test.js +81 -1
- package/dist/verification/__tests__/ci-rust-gates.test.js.map +1 -1
- package/package.json +8 -8
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +334 -21
- package/plugins/oh-my-codex/hooks/hooks.json +1 -2
- package/plugins/oh-my-codex/skills/autopilot/SKILL.md +3 -1
- package/plugins/oh-my-codex/skills/code-review/SKILL.md +7 -7
- package/plugins/oh-my-codex/skills/ralph/SKILL.md +22 -22
- package/plugins/oh-my-codex/skills/ultraqa/SKILL.md +9 -0
- package/skills/autopilot/SKILL.md +3 -1
- package/skills/code-review/SKILL.md +7 -7
- package/skills/ralph/SKILL.md +22 -22
- package/skills/ultraqa/SKILL.md +9 -0
- package/src/scripts/__tests__/codex-native-hook.test.ts +686 -13
- package/src/scripts/__tests__/notify-state-io.test.ts +95 -0
- package/src/scripts/__tests__/notify-tmux-injection.test.ts +82 -0
- package/src/scripts/__tests__/run-test-files.test.ts +102 -0
- package/src/scripts/__tests__/verify-native-agents.test.ts +75 -0
- package/src/scripts/codex-native-hook.ts +105 -28
- package/src/scripts/demo-team-e2e.sh +10 -7
- package/src/scripts/eval/eval-parity-smoke.ts +1 -1
- package/src/scripts/notify-hook/auto-nudge.ts +3 -1
- package/src/scripts/notify-hook/ralph-session-resume.ts +2 -8
- package/src/scripts/notify-hook/state-io.ts +75 -37
- package/src/scripts/notify-hook/team-leader-nudge.ts +7 -0
- package/src/scripts/notify-hook/tmux-injection.ts +35 -19
- package/src/scripts/notify-hook.ts +91 -4
- package/src/scripts/run-test-files.ts +192 -22
- package/src/scripts/sync-plugin-mirror.ts +98 -9
- package/src/scripts/verify-native-agents.ts +65 -1
|
@@ -15,6 +15,7 @@ import { findGitLayout } from "../utils/git-layout.js";
|
|
|
15
15
|
import { getBaseStateDir, getStateFilePath, getStatePath } from "../mcp/state-paths.js";
|
|
16
16
|
import { detectKeywords, detectPrimaryKeyword, recordSkillActivation, } from "../hooks/keyword-detector.js";
|
|
17
17
|
import { buildDeepInterviewConfigInstruction } from "../hooks/deep-interview-config-instruction.js";
|
|
18
|
+
import { readTeamModeConfig } from "../config/team-mode.js";
|
|
18
19
|
import { detectNativeStopStallPattern, loadAutoNudgeConfig, normalizeAutoNudgeSignatureText, resolveEffectiveAutoNudgeResponse, } from "./notify-hook/auto-nudge.js";
|
|
19
20
|
import { SLOPPY_FALLBACK_GROUNDING_PATTERNS, SLOPPY_FALLBACK_IMPLEMENTATION_CONTEXT_PATTERNS, SLOPPY_FALLBACK_PHRASE_PATTERNS, buildNativePostToolUseOutput, buildNativePreToolUseOutput, detectMcpTransportFailure, hasAnyPattern, } from "./codex-native-pre-post.js";
|
|
20
21
|
import { handleTeamWorkerPostToolUseSuccess } from "./notify-hook/team-worker-posttooluse.js";
|
|
@@ -80,6 +81,19 @@ function resolveHudReconcileSessionId(currentSessionState, canonicalSessionId, s
|
|
|
80
81
|
return ownerOmxSessionId;
|
|
81
82
|
return canonicalSessionId || sessionIdForState || undefined;
|
|
82
83
|
}
|
|
84
|
+
function resolveHudReconcileSessionIds(currentSessionState, canonicalSessionId, sessionIdForState, nativeSessionId) {
|
|
85
|
+
const ownerOmxSessionId = safeString(currentSessionState?.owner_omx_session_id).trim();
|
|
86
|
+
return uniqueNonEmpty([
|
|
87
|
+
resolveHudReconcileSessionId(currentSessionState, canonicalSessionId, sessionIdForState),
|
|
88
|
+
canonicalSessionId ?? undefined,
|
|
89
|
+
sessionIdForState ?? undefined,
|
|
90
|
+
nativeSessionId ?? undefined,
|
|
91
|
+
safeString(currentSessionState?.session_id),
|
|
92
|
+
safeString(currentSessionState?.native_session_id),
|
|
93
|
+
OMX_OWNER_SESSION_ID_PATTERN.test(ownerOmxSessionId) ? ownerOmxSessionId : undefined,
|
|
94
|
+
safeString(currentSessionState?.owner_codex_session_id),
|
|
95
|
+
]);
|
|
96
|
+
}
|
|
83
97
|
function safeContextSnippet(value, maxLength = 300) {
|
|
84
98
|
const text = safeString(value).replace(/\s+/g, " ").trim();
|
|
85
99
|
if (text.length <= maxLength)
|
|
@@ -1384,6 +1398,8 @@ function buildTeamHelpInstruction(cwd, payload) {
|
|
|
1384
1398
|
}).teamHelpInstruction;
|
|
1385
1399
|
}
|
|
1386
1400
|
function buildNativeOutsideTmuxTeamPromptBlockState(prompt, cwd, payload, sessionId, threadId, turnId) {
|
|
1401
|
+
if (!readTeamModeConfig(cwd).enabled)
|
|
1402
|
+
return null;
|
|
1387
1403
|
const match = detectPrimaryKeyword(prompt);
|
|
1388
1404
|
if (match?.skill !== "team")
|
|
1389
1405
|
return null;
|
|
@@ -1418,8 +1434,11 @@ function buildSkillStateCliInstruction(mode, statePath) {
|
|
|
1418
1434
|
function buildAutopilotPromptActivationNote(skillState, options = {}) {
|
|
1419
1435
|
if (skillState?.initialized_mode !== "autopilot")
|
|
1420
1436
|
return null;
|
|
1437
|
+
const teamHandoff = readTeamModeConfig(options.cwd).enabled
|
|
1438
|
+
? " (+ $team if needed)"
|
|
1439
|
+
: "";
|
|
1421
1440
|
return [
|
|
1422
|
-
|
|
1441
|
+
`Autopilot protocol: the durable default chain is $deep-interview -> $ralplan -> $ultragoal${teamHandoff} -> $code-review -> $ultraqa (deep-interview -> ralplan -> ultragoal -> code-review -> ultraqa).`,
|
|
1423
1442
|
"Start/resume at current_phase=deep-interview unless the task is clear and bounded; if deep-interview is intentionally skipped, persist and state an explicit deep_interview_gate.skip_reason before moving to ralplan.",
|
|
1424
1443
|
"Deep-interview is a structured question chain, not a one-question gate: after an omx question answer, re-score ambiguity against the active threshold, treat max_rounds as a cap, and crystallize once ambiguity is at or below threshold and readiness gates pass.",
|
|
1425
1444
|
options.markedQuestionAnswer
|
|
@@ -1431,12 +1450,18 @@ function buildAutopilotPromptActivationNote(skillState, options = {}) {
|
|
|
1431
1450
|
"When Codex goal tools are available, call get_goal/create_goal only from the active thread handoff and treat the active goal as the completion contract until code-review and ultraqa are clean.",
|
|
1432
1451
|
].filter(Boolean).join(" ");
|
|
1433
1452
|
}
|
|
1453
|
+
function formatExecutionHandoffList(cwd) {
|
|
1454
|
+
return readTeamModeConfig(cwd).enabled
|
|
1455
|
+
? "`$ultragoal`, `$team`, or `$ralph`"
|
|
1456
|
+
: "`$ultragoal` or `$ralph`";
|
|
1457
|
+
}
|
|
1434
1458
|
function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(), payload) {
|
|
1435
1459
|
if (!prompt)
|
|
1436
1460
|
return null;
|
|
1437
1461
|
const promptPriorityMessage = buildPromptPriorityMessage(prompt);
|
|
1438
|
-
const
|
|
1439
|
-
const
|
|
1462
|
+
const teamMode = readTeamModeConfig(cwd);
|
|
1463
|
+
const matches = detectKeywords(prompt).filter((entry) => teamMode.enabled || entry.skill !== "team");
|
|
1464
|
+
const match = matches[0] ?? null;
|
|
1440
1465
|
if (!match) {
|
|
1441
1466
|
const continuedSkill = safeString(skillState?.skill).trim();
|
|
1442
1467
|
if (!continuedSkill)
|
|
@@ -1446,7 +1471,7 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
|
|
|
1446
1471
|
: null;
|
|
1447
1472
|
const deepInterviewConfigPromptActivationNote = buildDeepInterviewConfigInstruction(cwd, skillState);
|
|
1448
1473
|
const markedQuestionAnswer = /^\s*\[omx question answered\]/i.test(prompt);
|
|
1449
|
-
const autopilotPromptActivationNote = buildAutopilotPromptActivationNote(skillState, { markedQuestionAnswer });
|
|
1474
|
+
const autopilotPromptActivationNote = buildAutopilotPromptActivationNote(skillState, { markedQuestionAnswer, cwd });
|
|
1450
1475
|
return [
|
|
1451
1476
|
`OMX native UserPromptSubmit continued active workflow skill "${continuedSkill}".`,
|
|
1452
1477
|
promptPriorityMessage,
|
|
@@ -1470,7 +1495,7 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
|
|
|
1470
1495
|
? buildDeepInterviewQuestionBridgeInstruction(cwd, payload)
|
|
1471
1496
|
: null;
|
|
1472
1497
|
const deepInterviewConfigPromptActivationNote = buildDeepInterviewConfigInstruction(cwd, skillState);
|
|
1473
|
-
const autopilotPromptActivationNote = buildAutopilotPromptActivationNote(skillState, { markedQuestionAnswer: true });
|
|
1498
|
+
const autopilotPromptActivationNote = buildAutopilotPromptActivationNote(skillState, { markedQuestionAnswer: true, cwd });
|
|
1474
1499
|
return [
|
|
1475
1500
|
`OMX native UserPromptSubmit continued active workflow skill "${continuedSkill}"; workflow-like tokens inside the marked omx question answer are treated as answer text, not a new workflow activation.`,
|
|
1476
1501
|
promptPriorityMessage,
|
|
@@ -1503,7 +1528,7 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
|
|
|
1503
1528
|
const ultragoalPromptActivationNote = match.skill === "ultragoal"
|
|
1504
1529
|
? "Ultragoal protocol: use `omx ultragoal create-goals` / `complete-goals` / `checkpoint` for `.omx/ultragoal` artifacts, then use Codex goal model tools only from the active agent handoff (`get_goal`, `create_goal`, `update_goal`) and never overwrite a different active Codex goal. Ultragoal does not call `/goal clear`; for multiple sequential ultragoal runs in one Codex session/thread, manually clear the completed Codex goal in the UI before creating the next aggregate goal."
|
|
1505
1530
|
: null;
|
|
1506
|
-
const autopilotPromptActivationNote = buildAutopilotPromptActivationNote(skillState);
|
|
1531
|
+
const autopilotPromptActivationNote = buildAutopilotPromptActivationNote(skillState, { cwd });
|
|
1507
1532
|
const combinedTransitionMessage = (() => {
|
|
1508
1533
|
if (!skillState?.transition_message)
|
|
1509
1534
|
return null;
|
|
@@ -2012,8 +2037,10 @@ function readPayloadThreadId(payload) {
|
|
|
2012
2037
|
function readPayloadTurnId(payload) {
|
|
2013
2038
|
return safeString(payload.turn_id ?? payload.turnId).trim();
|
|
2014
2039
|
}
|
|
2015
|
-
async function resolveInternalSessionIdForPayload(cwd, payloadSessionId) {
|
|
2016
|
-
const currentSession =
|
|
2040
|
+
async function resolveInternalSessionIdForPayload(cwd, payloadSessionId, stateDir) {
|
|
2041
|
+
const currentSession = stateDir
|
|
2042
|
+
? await readUsableSessionStateFromStateDir(cwd, stateDir)
|
|
2043
|
+
: await readUsableSessionState(cwd);
|
|
2017
2044
|
const canonicalSessionId = safeString(currentSession?.session_id).trim();
|
|
2018
2045
|
if (!canonicalSessionId)
|
|
2019
2046
|
return payloadSessionId;
|
|
@@ -2026,6 +2053,19 @@ async function resolveInternalSessionIdForPayload(cwd, payloadSessionId) {
|
|
|
2026
2053
|
return canonicalSessionId;
|
|
2027
2054
|
return payloadSessionId;
|
|
2028
2055
|
}
|
|
2056
|
+
async function readUsableSessionStateFromStateDir(cwd, stateDir) {
|
|
2057
|
+
const sessionPath = join(stateDir, "session.json");
|
|
2058
|
+
if (!existsSync(sessionPath))
|
|
2059
|
+
return null;
|
|
2060
|
+
try {
|
|
2061
|
+
const content = await readFile(sessionPath, "utf-8");
|
|
2062
|
+
const state = JSON.parse(content);
|
|
2063
|
+
return isSessionStateUsable(state, cwd) ? state : null;
|
|
2064
|
+
}
|
|
2065
|
+
catch {
|
|
2066
|
+
return null;
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2029
2069
|
async function readStopSessionPinnedState(fileName, cwd, sessionId, stateDir) {
|
|
2030
2070
|
const statePath = stateDir && sessionId
|
|
2031
2071
|
? join(stateDir, "sessions", sessionId, fileName)
|
|
@@ -2054,7 +2094,8 @@ const PLANNING_MODE_IMPLEMENTATION_TOOL_NAMES = new Set([
|
|
|
2054
2094
|
]);
|
|
2055
2095
|
const DEEP_INTERVIEW_IMPLEMENTATION_TOOL_NAMES = PLANNING_MODE_IMPLEMENTATION_TOOL_NAMES;
|
|
2056
2096
|
const RALPLAN_EXECUTION_HANDOFF_SKILLS = new Set([
|
|
2057
|
-
|
|
2097
|
+
// Autopilot is intentionally excluded: it supervises planning phases such as
|
|
2098
|
+
// ralplan/replan and is not by itself an execution authorization.
|
|
2058
2099
|
"autoresearch",
|
|
2059
2100
|
"ralph",
|
|
2060
2101
|
"team",
|
|
@@ -2091,7 +2132,7 @@ function isActiveAutopilotRalplanPhase(state) {
|
|
|
2091
2132
|
if (mode && mode !== "autopilot")
|
|
2092
2133
|
return false;
|
|
2093
2134
|
const phase = safeString(state.current_phase ?? state.currentPhase).trim().toLowerCase();
|
|
2094
|
-
return phase === "ralplan";
|
|
2135
|
+
return phase === "ralplan" || phase === "replan" || phase === "autopilot:replan";
|
|
2095
2136
|
}
|
|
2096
2137
|
function hasExplicitExecutionHandoffSkill(state, sessionId, threadId) {
|
|
2097
2138
|
return listActiveSkills(state ?? {}).some((entry) => (RALPLAN_EXECUTION_HANDOFF_SKILLS.has(entry.skill)
|
|
@@ -2176,7 +2217,7 @@ async function readActiveDeepInterviewStateForPreToolUse(cwd, stateDir, sessionI
|
|
|
2176
2217
|
? await readVisibleSkillActiveStateForStateDir(stateDir, sessionId)
|
|
2177
2218
|
: await readSkillActiveState(join(stateDir, SKILL_ACTIVE_STATE_FILE));
|
|
2178
2219
|
if (!canonicalState)
|
|
2179
|
-
return
|
|
2220
|
+
return null;
|
|
2180
2221
|
const hasActiveDeepInterviewSkill = listActiveSkills(canonicalState).some((entry) => (entry.skill === "deep-interview"
|
|
2181
2222
|
&& matchesSkillStopContext(entry, canonicalState, sessionId, threadId)));
|
|
2182
2223
|
return hasActiveDeepInterviewSkill ? modeState : null;
|
|
@@ -2192,7 +2233,7 @@ async function readActiveRalplanStateForPreToolUse(cwd, stateDir, sessionId, thr
|
|
|
2192
2233
|
if (hasExplicitExecutionHandoffSkill(canonicalState, sessionId, threadId))
|
|
2193
2234
|
return null;
|
|
2194
2235
|
if (!canonicalState)
|
|
2195
|
-
return
|
|
2236
|
+
return null;
|
|
2196
2237
|
const hasActiveRalplanSkill = listActiveSkills(canonicalState).some((entry) => (entry.skill === "ralplan"
|
|
2197
2238
|
&& matchesSkillStopContext(entry, canonicalState, sessionId, threadId)));
|
|
2198
2239
|
if (hasActiveRalplanSkill)
|
|
@@ -2209,7 +2250,7 @@ async function readActiveRalplanStateForPreToolUse(cwd, stateDir, sessionId, thr
|
|
|
2209
2250
|
if (terminalAutopilotRunState)
|
|
2210
2251
|
return null;
|
|
2211
2252
|
if (!canonicalState)
|
|
2212
|
-
return
|
|
2253
|
+
return null;
|
|
2213
2254
|
const hasActiveAutopilotSkill = listActiveSkills(canonicalState).some((entry) => (entry.skill === "autopilot"
|
|
2214
2255
|
&& matchesSkillStopContext(entry, canonicalState, sessionId, threadId)));
|
|
2215
2256
|
return hasActiveAutopilotSkill ? autopilotState : null;
|
|
@@ -2222,8 +2263,8 @@ function isAllowedRalplanBashWrite(cwd, command) {
|
|
|
2222
2263
|
const targets = extractDeepInterviewCommandWriteTargets(command);
|
|
2223
2264
|
return targets.length > 0 && targets.every((target) => isAllowedRalplanArtifactPath(cwd, target));
|
|
2224
2265
|
}
|
|
2225
|
-
async function buildRalplanPreToolUseBoundaryOutput(payload, cwd, stateDir) {
|
|
2226
|
-
const sessionId = readPayloadSessionId(payload);
|
|
2266
|
+
async function buildRalplanPreToolUseBoundaryOutput(payload, cwd, stateDir, resolvedSessionId) {
|
|
2267
|
+
const sessionId = safeString(resolvedSessionId ?? readPayloadSessionId(payload)).trim();
|
|
2227
2268
|
const threadId = readPayloadThreadId(payload);
|
|
2228
2269
|
const activeState = await readActiveRalplanStateForPreToolUse(cwd, stateDir, sessionId, threadId);
|
|
2229
2270
|
if (!activeState)
|
|
@@ -2242,17 +2283,25 @@ async function buildRalplanPreToolUseBoundaryOutput(payload, cwd, stateDir) {
|
|
|
2242
2283
|
if (!blocked)
|
|
2243
2284
|
return null;
|
|
2244
2285
|
const phase = formatPhase(activeState.current_phase ?? activeState.currentPhase, "planning");
|
|
2286
|
+
const activeMode = safeString(activeState.mode).trim().toLowerCase();
|
|
2287
|
+
const planningModeLabel = activeMode === "autopilot" ? "Autopilot planning" : "Ralplan";
|
|
2288
|
+
const planningModeDescription = activeMode === "autopilot"
|
|
2289
|
+
? "Autopilot is supervising a planning phase"
|
|
2290
|
+
: "Ralplan is consensus-planning mode";
|
|
2245
2291
|
return {
|
|
2246
2292
|
decision: "block",
|
|
2247
|
-
reason:
|
|
2293
|
+
reason: `${planningModeLabel} is active (phase: ${phase}); implementation/write tools are blocked until an explicit execution handoff workflow is activated.`,
|
|
2248
2294
|
hookSpecificOutput: {
|
|
2249
2295
|
hookEventName: "PreToolUse",
|
|
2250
|
-
additionalContext:
|
|
2296
|
+
additionalContext: `${planningModeDescription}. `
|
|
2297
|
+
+ "Write only planning artifacts under `.omx/context/`, `.omx/plans/`, `.omx/specs/`, or required `.omx/state/` files. "
|
|
2298
|
+
+ "Do not edit implementation files or run implementation-focused writes from planning phases. "
|
|
2299
|
+
+ `To execute, first process an explicit handoff such as ${formatExecutionHandoffList(cwd)}, which must emit terminal planning state before implementation begins.`,
|
|
2251
2300
|
},
|
|
2252
2301
|
};
|
|
2253
2302
|
}
|
|
2254
|
-
async function buildDeepInterviewPreToolUseBoundaryOutput(payload, cwd, stateDir) {
|
|
2255
|
-
const sessionId = readPayloadSessionId(payload);
|
|
2303
|
+
async function buildDeepInterviewPreToolUseBoundaryOutput(payload, cwd, stateDir, resolvedSessionId) {
|
|
2304
|
+
const sessionId = safeString(resolvedSessionId ?? readPayloadSessionId(payload)).trim();
|
|
2256
2305
|
const threadId = readPayloadThreadId(payload);
|
|
2257
2306
|
const activeState = await readActiveDeepInterviewStateForPreToolUse(cwd, stateDir, sessionId, threadId);
|
|
2258
2307
|
if (!activeState)
|
|
@@ -2276,7 +2325,7 @@ async function buildDeepInterviewPreToolUseBoundaryOutput(payload, cwd, stateDir
|
|
|
2276
2325
|
reason: `Deep-interview is active (phase: ${phase}); implementation/write tools are blocked until an explicit handoff workflow is activated.`,
|
|
2277
2326
|
hookSpecificOutput: {
|
|
2278
2327
|
hookEventName: "PreToolUse",
|
|
2279
|
-
additionalContext:
|
|
2328
|
+
additionalContext: `Deep-interview is requirements/spec mode. Treat detailed user answers as interview/spec material, not implicit implementation authorization. You may write only deep-interview artifacts under \`.omx/context/\`, \`.omx/interviews/\`, \`.omx/specs/\`, or required \`.omx/state/\` files. To implement, first ask for or process an explicit transition such as \`$ralplan\`, \`$autopilot\`, ${formatExecutionHandoffList(cwd)}.`,
|
|
2280
2329
|
},
|
|
2281
2330
|
};
|
|
2282
2331
|
}
|
|
@@ -2465,7 +2514,7 @@ async function reconcileStaleRootSkillActiveStateForStop(cwd, stateDir, sessionI
|
|
|
2465
2514
|
}
|
|
2466
2515
|
await writeFile(rootPath, JSON.stringify(nextRoot, null, 2));
|
|
2467
2516
|
}
|
|
2468
|
-
function buildRalplanContinuationStatus(blocker, activeSubagentCount) {
|
|
2517
|
+
function buildRalplanContinuationStatus(blocker, activeSubagentCount, cwd) {
|
|
2469
2518
|
const phase = blocker.phase || "planning";
|
|
2470
2519
|
const artifact = blocker.latestPlanPath
|
|
2471
2520
|
? ` Artifact: ${blocker.latestPlanPath}.`
|
|
@@ -2491,7 +2540,7 @@ function buildRalplanContinuationStatus(blocker, activeSubagentCount) {
|
|
|
2491
2540
|
};
|
|
2492
2541
|
}
|
|
2493
2542
|
const completeHint = blocker.planningComplete
|
|
2494
|
-
?
|
|
2543
|
+
? ` The planning artifacts are present; if consensus is approved, emit terminal ralplan complete/approved handoff state and stop planning. Implementation must wait for an explicit ${formatExecutionHandoffList(cwd).replaceAll("`", "")} handoff.`
|
|
2495
2544
|
: "";
|
|
2496
2545
|
return {
|
|
2497
2546
|
reason: `Status: continue_from_artifact — ralplan is still active (phase: ${phase}) and has not emitted a terminal complete/paused/waiting status. Continue from the current ralplan artifact, resolve any review ambiguity conservatively or ask the user if needed, and proceed to the next planning/review step before stopping; do not begin implementation from ralplan.${artifact}${completeHint}`,
|
|
@@ -2650,6 +2699,9 @@ function readIsoTimeMs(value) {
|
|
|
2650
2699
|
return Number.isFinite(parsed) ? parsed : null;
|
|
2651
2700
|
}
|
|
2652
2701
|
async function maybeBuildOrdinaryStopNoProgressOutput(payload, stateDir, canonicalSessionId) {
|
|
2702
|
+
const lastAssistantMessage = safeString(payload.last_assistant_message ?? payload.lastAssistantMessage).trim();
|
|
2703
|
+
if (!lastAssistantMessage)
|
|
2704
|
+
return null;
|
|
2653
2705
|
const statePath = join(stateDir, NATIVE_STOP_STATE_FILE);
|
|
2654
2706
|
const state = await readJsonIfExists(statePath) ?? {};
|
|
2655
2707
|
const sessions = safeObject(state.sessions);
|
|
@@ -2679,9 +2731,6 @@ async function maybeBuildOrdinaryStopNoProgressOutput(payload, stateDir, canonic
|
|
|
2679
2731
|
};
|
|
2680
2732
|
await mkdir(stateDir, { recursive: true });
|
|
2681
2733
|
await writeFile(statePath, JSON.stringify({ ...state, sessions }, null, 2));
|
|
2682
|
-
const stopHookActive = payload.stop_hook_active === true || payload.stopHookActive === true;
|
|
2683
|
-
if (!stopHookActive)
|
|
2684
|
-
return null;
|
|
2685
2734
|
const maxRepeats = parseBoundedPositiveInteger(process.env.OMX_NATIVE_STOP_NO_PROGRESS_MAX_REPEATS, ORDINARY_STOP_NO_PROGRESS_DEFAULT_MAX_REPEATS);
|
|
2686
2735
|
const idleMs = parseBoundedNonNegativeInteger(process.env.OMX_NATIVE_STOP_NO_PROGRESS_IDLE_MS, ORDINARY_STOP_NO_PROGRESS_DEFAULT_IDLE_MS);
|
|
2687
2736
|
const firstSeenMs = readIsoTimeMs(firstSeenAt) ?? Date.now();
|
|
@@ -2811,7 +2860,7 @@ async function buildSkillStopOutput(cwd, stateDir, sessionId, threadId) {
|
|
|
2811
2860
|
const subagentSummary = await readSubagentSessionSummary(cwd, sessionId).catch(() => null);
|
|
2812
2861
|
const activeSubagentCount = subagentSummary?.activeSubagentThreadIds.length ?? 0;
|
|
2813
2862
|
if (blocker.skill === "ralplan") {
|
|
2814
|
-
const status = buildRalplanContinuationStatus(blocker, activeSubagentCount);
|
|
2863
|
+
const status = buildRalplanContinuationStatus(blocker, activeSubagentCount, cwd);
|
|
2815
2864
|
return {
|
|
2816
2865
|
decision: "block",
|
|
2817
2866
|
reason: status.reason,
|
|
@@ -3076,7 +3125,9 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
3076
3125
|
// Native hooks must use the same authoritative runtime state root as HUD/MCP
|
|
3077
3126
|
// when boxed/team roots are active; do not bypass it with cwd/.omx/state.
|
|
3078
3127
|
const stateDir = getBaseStateDir(cwd);
|
|
3079
|
-
|
|
3128
|
+
if (hookEventName !== "Stop") {
|
|
3129
|
+
await mkdir(stateDir, { recursive: true });
|
|
3130
|
+
}
|
|
3080
3131
|
const omxEventName = mapCodexHookEventToOmxEvent(hookEventName);
|
|
3081
3132
|
let skillState = null;
|
|
3082
3133
|
let triageAdditionalContext = null;
|
|
@@ -3237,12 +3288,14 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
3237
3288
|
triageAdditionalContext = null;
|
|
3238
3289
|
}
|
|
3239
3290
|
}
|
|
3291
|
+
const skipHudReconcileForDoctorSmoke = process.env.OMX_NATIVE_HOOK_DOCTOR_SMOKE === "1";
|
|
3240
3292
|
const skipHudReconcileForTeamWorkerPane = !isSubagentPromptSubmit
|
|
3241
3293
|
&& await isConfirmedTeamWorkerPromptSubmitPane(cwd).catch(() => false);
|
|
3242
|
-
if (!skipHudReconcileForTeamWorkerPane) {
|
|
3294
|
+
if (!skipHudReconcileForDoctorSmoke && !skipHudReconcileForTeamWorkerPane) {
|
|
3243
3295
|
const reconcileHudForPromptSubmitFn = options.reconcileHudForPromptSubmitFn ?? reconcileHudForPromptSubmit;
|
|
3244
3296
|
const hudSessionId = resolveHudReconcileSessionId(currentSessionState, canonicalSessionId, sessionIdForState);
|
|
3245
|
-
|
|
3297
|
+
const hudSessionIds = resolveHudReconcileSessionIds(currentSessionState, canonicalSessionId, sessionIdForState, nativeSessionId);
|
|
3298
|
+
await reconcileHudForPromptSubmitFn(cwd, { sessionId: hudSessionId, sessionIds: hudSessionIds }).catch(() => { });
|
|
3246
3299
|
}
|
|
3247
3300
|
}
|
|
3248
3301
|
if (omxEventName && !skipCanonicalSessionStartContext && !suppressNoisySubagentLifecycleDispatch) {
|
|
@@ -3298,8 +3351,12 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
3298
3351
|
}
|
|
3299
3352
|
}
|
|
3300
3353
|
else if (hookEventName === "PreToolUse") {
|
|
3301
|
-
|
|
3302
|
-
|
|
3354
|
+
const payloadSessionId = readPayloadSessionId(payload);
|
|
3355
|
+
const preToolUseSessionId = payloadSessionId
|
|
3356
|
+
? await resolveInternalSessionIdForPayload(cwd, payloadSessionId, stateDir)
|
|
3357
|
+
: "";
|
|
3358
|
+
outputJson = await buildDeepInterviewPreToolUseBoundaryOutput(payload, cwd, stateDir, preToolUseSessionId)
|
|
3359
|
+
?? await buildRalplanPreToolUseBoundaryOutput(payload, cwd, stateDir, preToolUseSessionId)
|
|
3303
3360
|
?? buildNativePreToolUseOutput(payload);
|
|
3304
3361
|
}
|
|
3305
3362
|
else if (hookEventName === "PostToolUse") {
|