oh-my-codex 0.18.1 → 0.18.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.
Files changed (310) hide show
  1. package/Cargo.lock +6 -6
  2. package/Cargo.toml +1 -1
  3. package/README.md +4 -2
  4. package/dist/agents/__tests__/definitions.test.js +23 -0
  5. package/dist/agents/__tests__/definitions.test.js.map +1 -1
  6. package/dist/agents/__tests__/native-config.test.js +20 -0
  7. package/dist/agents/__tests__/native-config.test.js.map +1 -1
  8. package/dist/agents/definitions.d.ts.map +1 -1
  9. package/dist/agents/definitions.js +40 -0
  10. package/dist/agents/definitions.js.map +1 -1
  11. package/dist/agents/native-config.d.ts +1 -0
  12. package/dist/agents/native-config.d.ts.map +1 -1
  13. package/dist/agents/native-config.js +4 -0
  14. package/dist/agents/native-config.js.map +1 -1
  15. package/dist/auth/__tests__/config-sessions.test.d.ts +2 -0
  16. package/dist/auth/__tests__/config-sessions.test.d.ts.map +1 -0
  17. package/dist/auth/__tests__/config-sessions.test.js +48 -0
  18. package/dist/auth/__tests__/config-sessions.test.js.map +1 -0
  19. package/dist/auth/__tests__/quota-rotation.test.d.ts +2 -0
  20. package/dist/auth/__tests__/quota-rotation.test.d.ts.map +1 -0
  21. package/dist/auth/__tests__/quota-rotation.test.js +33 -0
  22. package/dist/auth/__tests__/quota-rotation.test.js.map +1 -0
  23. package/dist/auth/__tests__/redact.test.d.ts +2 -0
  24. package/dist/auth/__tests__/redact.test.d.ts.map +1 -0
  25. package/dist/auth/__tests__/redact.test.js +20 -0
  26. package/dist/auth/__tests__/redact.test.js.map +1 -0
  27. package/dist/auth/__tests__/storage.test.d.ts +2 -0
  28. package/dist/auth/__tests__/storage.test.d.ts.map +1 -0
  29. package/dist/auth/__tests__/storage.test.js +108 -0
  30. package/dist/auth/__tests__/storage.test.js.map +1 -0
  31. package/dist/auth/config.d.ts +9 -0
  32. package/dist/auth/config.d.ts.map +1 -0
  33. package/dist/auth/config.js +77 -0
  34. package/dist/auth/config.js.map +1 -0
  35. package/dist/auth/hotswap.d.ts +36 -0
  36. package/dist/auth/hotswap.d.ts.map +1 -0
  37. package/dist/auth/hotswap.js +159 -0
  38. package/dist/auth/hotswap.js.map +1 -0
  39. package/dist/auth/index.d.ts +8 -0
  40. package/dist/auth/index.d.ts.map +1 -0
  41. package/dist/auth/index.js +8 -0
  42. package/dist/auth/index.js.map +1 -0
  43. package/dist/auth/paths.d.ts +12 -0
  44. package/dist/auth/paths.d.ts.map +1 -0
  45. package/dist/auth/paths.js +78 -0
  46. package/dist/auth/paths.js.map +1 -0
  47. package/dist/auth/quota-detector.d.ts +10 -0
  48. package/dist/auth/quota-detector.d.ts.map +1 -0
  49. package/dist/auth/quota-detector.js +40 -0
  50. package/dist/auth/quota-detector.js.map +1 -0
  51. package/dist/auth/redact.d.ts +2 -0
  52. package/dist/auth/redact.d.ts.map +1 -0
  53. package/dist/auth/redact.js +26 -0
  54. package/dist/auth/redact.js.map +1 -0
  55. package/dist/auth/rotation.d.ts +9 -0
  56. package/dist/auth/rotation.d.ts.map +1 -0
  57. package/dist/auth/rotation.js +26 -0
  58. package/dist/auth/rotation.js.map +1 -0
  59. package/dist/auth/sessions.d.ts +15 -0
  60. package/dist/auth/sessions.d.ts.map +1 -0
  61. package/dist/auth/sessions.js +62 -0
  62. package/dist/auth/sessions.js.map +1 -0
  63. package/dist/auth/storage.d.ts +27 -0
  64. package/dist/auth/storage.d.ts.map +1 -0
  65. package/dist/auth/storage.js +111 -0
  66. package/dist/auth/storage.js.map +1 -0
  67. package/dist/catalog/__tests__/generator.test.js +4 -0
  68. package/dist/catalog/__tests__/generator.test.js.map +1 -1
  69. package/dist/cli/__tests__/auth.test.d.ts +2 -0
  70. package/dist/cli/__tests__/auth.test.d.ts.map +1 -0
  71. package/dist/cli/__tests__/auth.test.js +168 -0
  72. package/dist/cli/__tests__/auth.test.js.map +1 -0
  73. package/dist/cli/__tests__/doctor-warning-copy.test.js +112 -5
  74. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  75. package/dist/cli/__tests__/explore.test.js +20 -0
  76. package/dist/cli/__tests__/explore.test.js.map +1 -1
  77. package/dist/cli/__tests__/index.test.js +171 -21
  78. package/dist/cli/__tests__/index.test.js.map +1 -1
  79. package/dist/cli/__tests__/launch-fallback.test.js +51 -3
  80. package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
  81. package/dist/cli/__tests__/nested-help-routing.test.js +1 -0
  82. package/dist/cli/__tests__/nested-help-routing.test.js.map +1 -1
  83. package/dist/cli/__tests__/question.test.js +2 -2
  84. package/dist/cli/__tests__/question.test.js.map +1 -1
  85. package/dist/cli/__tests__/setup-agents-overwrite.test.js +30 -1
  86. package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
  87. package/dist/cli/__tests__/setup-install-mode.test.js +47 -0
  88. package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
  89. package/dist/cli/auth.d.ts +4 -0
  90. package/dist/cli/auth.d.ts.map +1 -0
  91. package/dist/cli/auth.js +89 -0
  92. package/dist/cli/auth.js.map +1 -0
  93. package/dist/cli/doctor.d.ts.map +1 -1
  94. package/dist/cli/doctor.js +190 -7
  95. package/dist/cli/doctor.js.map +1 -1
  96. package/dist/cli/explore.d.ts.map +1 -1
  97. package/dist/cli/explore.js +12 -0
  98. package/dist/cli/explore.js.map +1 -1
  99. package/dist/cli/index.d.ts +27 -3
  100. package/dist/cli/index.d.ts.map +1 -1
  101. package/dist/cli/index.js +245 -47
  102. package/dist/cli/index.js.map +1 -1
  103. package/dist/cli/setup.d.ts.map +1 -1
  104. package/dist/cli/setup.js +11 -3
  105. package/dist/cli/setup.js.map +1 -1
  106. package/dist/config/__tests__/codex-hooks.test.js +3 -3
  107. package/dist/config/__tests__/codex-hooks.test.js.map +1 -1
  108. package/dist/config/__tests__/deep-interview.test.d.ts +2 -0
  109. package/dist/config/__tests__/deep-interview.test.d.ts.map +1 -0
  110. package/dist/config/__tests__/deep-interview.test.js +239 -0
  111. package/dist/config/__tests__/deep-interview.test.js.map +1 -0
  112. package/dist/config/__tests__/generator-idempotent.test.js +123 -0
  113. package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
  114. package/dist/config/codex-hooks.d.ts +1 -0
  115. package/dist/config/codex-hooks.d.ts.map +1 -1
  116. package/dist/config/codex-hooks.js +2 -4
  117. package/dist/config/codex-hooks.js.map +1 -1
  118. package/dist/config/deep-interview.d.ts +22 -0
  119. package/dist/config/deep-interview.d.ts.map +1 -0
  120. package/dist/config/deep-interview.js +151 -0
  121. package/dist/config/deep-interview.js.map +1 -0
  122. package/dist/config/generator.d.ts +19 -2
  123. package/dist/config/generator.d.ts.map +1 -1
  124. package/dist/config/generator.js +198 -29
  125. package/dist/config/generator.js.map +1 -1
  126. package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js +21 -0
  127. package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js.map +1 -1
  128. package/dist/goal-workflows/codex-goal-snapshot.d.ts +3 -0
  129. package/dist/goal-workflows/codex-goal-snapshot.d.ts.map +1 -1
  130. package/dist/goal-workflows/codex-goal-snapshot.js +45 -2
  131. package/dist/goal-workflows/codex-goal-snapshot.js.map +1 -1
  132. package/dist/hooks/__tests__/agents-overlay.test.js +2 -0
  133. package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
  134. package/dist/hooks/__tests__/autopilot-skill-contract.test.js +17 -0
  135. package/dist/hooks/__tests__/autopilot-skill-contract.test.js.map +1 -1
  136. package/dist/hooks/__tests__/explore-routing.test.js +1 -0
  137. package/dist/hooks/__tests__/explore-routing.test.js.map +1 -1
  138. package/dist/hooks/__tests__/keyword-detector.test.js +471 -15
  139. package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
  140. package/dist/hooks/__tests__/prometheus-strict-contract.test.d.ts +2 -0
  141. package/dist/hooks/__tests__/prometheus-strict-contract.test.d.ts.map +1 -0
  142. package/dist/hooks/__tests__/prometheus-strict-contract.test.js +320 -0
  143. package/dist/hooks/__tests__/prometheus-strict-contract.test.js.map +1 -0
  144. package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js +12 -0
  145. package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js.map +1 -1
  146. package/dist/hooks/__tests__/research-workflow-boundaries.test.d.ts +2 -0
  147. package/dist/hooks/__tests__/research-workflow-boundaries.test.d.ts.map +1 -0
  148. package/dist/hooks/__tests__/research-workflow-boundaries.test.js +35 -0
  149. package/dist/hooks/__tests__/research-workflow-boundaries.test.js.map +1 -0
  150. package/dist/hooks/deep-interview-config-instruction.d.ts +3 -0
  151. package/dist/hooks/deep-interview-config-instruction.d.ts.map +1 -0
  152. package/dist/hooks/deep-interview-config-instruction.js +47 -0
  153. package/dist/hooks/deep-interview-config-instruction.js.map +1 -0
  154. package/dist/hooks/explore-routing.d.ts.map +1 -1
  155. package/dist/hooks/explore-routing.js +1 -0
  156. package/dist/hooks/explore-routing.js.map +1 -1
  157. package/dist/hooks/keyword-detector.d.ts +6 -1
  158. package/dist/hooks/keyword-detector.d.ts.map +1 -1
  159. package/dist/hooks/keyword-detector.js +80 -14
  160. package/dist/hooks/keyword-detector.js.map +1 -1
  161. package/dist/hooks/keyword-registry.d.ts.map +1 -1
  162. package/dist/hooks/keyword-registry.js +1 -0
  163. package/dist/hooks/keyword-registry.js.map +1 -1
  164. package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
  165. package/dist/hooks/prompt-guidance-contract.js +11 -0
  166. package/dist/hooks/prompt-guidance-contract.js.map +1 -1
  167. package/dist/hud/__tests__/hud-tmux-injection.test.js +22 -0
  168. package/dist/hud/__tests__/hud-tmux-injection.test.js.map +1 -1
  169. package/dist/hud/__tests__/reconcile.test.js +213 -17
  170. package/dist/hud/__tests__/reconcile.test.js.map +1 -1
  171. package/dist/hud/__tests__/render.test.js +84 -0
  172. package/dist/hud/__tests__/render.test.js.map +1 -1
  173. package/dist/hud/__tests__/state.test.js +51 -1
  174. package/dist/hud/__tests__/state.test.js.map +1 -1
  175. package/dist/hud/__tests__/tmux.test.js +171 -23
  176. package/dist/hud/__tests__/tmux.test.js.map +1 -1
  177. package/dist/hud/index.d.ts +1 -1
  178. package/dist/hud/index.d.ts.map +1 -1
  179. package/dist/hud/index.js +8 -3
  180. package/dist/hud/index.js.map +1 -1
  181. package/dist/hud/reconcile.d.ts +1 -1
  182. package/dist/hud/reconcile.d.ts.map +1 -1
  183. package/dist/hud/reconcile.js +14 -3
  184. package/dist/hud/reconcile.js.map +1 -1
  185. package/dist/hud/render.d.ts.map +1 -1
  186. package/dist/hud/render.js +26 -0
  187. package/dist/hud/render.js.map +1 -1
  188. package/dist/hud/state.d.ts +2 -1
  189. package/dist/hud/state.d.ts.map +1 -1
  190. package/dist/hud/state.js +62 -1
  191. package/dist/hud/state.js.map +1 -1
  192. package/dist/hud/tmux.d.ts +17 -3
  193. package/dist/hud/tmux.d.ts.map +1 -1
  194. package/dist/hud/tmux.js +96 -10
  195. package/dist/hud/tmux.js.map +1 -1
  196. package/dist/hud/types.d.ts +22 -0
  197. package/dist/hud/types.d.ts.map +1 -1
  198. package/dist/hud/types.js.map +1 -1
  199. package/dist/pipeline/__tests__/orchestrator.test.js +63 -1
  200. package/dist/pipeline/__tests__/orchestrator.test.js.map +1 -1
  201. package/dist/pipeline/__tests__/stages.test.js +410 -4
  202. package/dist/pipeline/__tests__/stages.test.js.map +1 -1
  203. package/dist/pipeline/orchestrator.d.ts.map +1 -1
  204. package/dist/pipeline/orchestrator.js +29 -2
  205. package/dist/pipeline/orchestrator.js.map +1 -1
  206. package/dist/pipeline/stages/ralplan.d.ts.map +1 -1
  207. package/dist/pipeline/stages/ralplan.js +41 -6
  208. package/dist/pipeline/stages/ralplan.js.map +1 -1
  209. package/dist/question/__tests__/ui.test.js +43 -10
  210. package/dist/question/__tests__/ui.test.js.map +1 -1
  211. package/dist/question/deep-interview.d.ts +2 -0
  212. package/dist/question/deep-interview.d.ts.map +1 -1
  213. package/dist/question/deep-interview.js.map +1 -1
  214. package/dist/question/ui.d.ts +12 -0
  215. package/dist/question/ui.d.ts.map +1 -1
  216. package/dist/question/ui.js +83 -46
  217. package/dist/question/ui.js.map +1 -1
  218. package/dist/ralplan/__tests__/runtime.test.js +200 -10
  219. package/dist/ralplan/__tests__/runtime.test.js.map +1 -1
  220. package/dist/ralplan/consensus-gate.d.ts +23 -0
  221. package/dist/ralplan/consensus-gate.d.ts.map +1 -0
  222. package/dist/ralplan/consensus-gate.js +212 -0
  223. package/dist/ralplan/consensus-gate.js.map +1 -0
  224. package/dist/ralplan/runtime.d.ts +25 -0
  225. package/dist/ralplan/runtime.d.ts.map +1 -1
  226. package/dist/ralplan/runtime.js +144 -8
  227. package/dist/ralplan/runtime.js.map +1 -1
  228. package/dist/scripts/__tests__/codex-native-hook.test.js +1034 -28
  229. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  230. package/dist/scripts/__tests__/docs-site-contract.test.d.ts +2 -0
  231. package/dist/scripts/__tests__/docs-site-contract.test.d.ts.map +1 -0
  232. package/dist/scripts/__tests__/docs-site-contract.test.js +42 -0
  233. package/dist/scripts/__tests__/docs-site-contract.test.js.map +1 -0
  234. package/dist/scripts/__tests__/notify-dispatcher.test.js +115 -2
  235. package/dist/scripts/__tests__/notify-dispatcher.test.js.map +1 -1
  236. package/dist/scripts/__tests__/run-test-files.test.js +57 -0
  237. package/dist/scripts/__tests__/run-test-files.test.js.map +1 -1
  238. package/dist/scripts/__tests__/verify-native-agents.test.js +2 -2
  239. package/dist/scripts/__tests__/verify-native-agents.test.js.map +1 -1
  240. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  241. package/dist/scripts/codex-native-hook.js +238 -36
  242. package/dist/scripts/codex-native-hook.js.map +1 -1
  243. package/dist/scripts/notify-dispatcher.js +188 -4
  244. package/dist/scripts/notify-dispatcher.js.map +1 -1
  245. package/dist/scripts/run-test-files.js +13 -0
  246. package/dist/scripts/run-test-files.js.map +1 -1
  247. package/dist/state/__tests__/planning-gate.test.d.ts +2 -0
  248. package/dist/state/__tests__/planning-gate.test.d.ts.map +1 -0
  249. package/dist/state/__tests__/planning-gate.test.js +219 -0
  250. package/dist/state/__tests__/planning-gate.test.js.map +1 -0
  251. package/dist/state/__tests__/workflow-transition.test.js +6 -0
  252. package/dist/state/__tests__/workflow-transition.test.js.map +1 -1
  253. package/dist/state/workflow-transition.d.ts +24 -1
  254. package/dist/state/workflow-transition.d.ts.map +1 -1
  255. package/dist/state/workflow-transition.js +70 -0
  256. package/dist/state/workflow-transition.js.map +1 -1
  257. package/dist/subagents/tracker.d.ts.map +1 -1
  258. package/dist/subagents/tracker.js +4 -3
  259. package/dist/subagents/tracker.js.map +1 -1
  260. package/dist/team/__tests__/runtime.test.js +36 -44
  261. package/dist/team/__tests__/runtime.test.js.map +1 -1
  262. package/dist/team/__tests__/tmux-session.test.js +144 -18
  263. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  264. package/dist/team/runtime.d.ts.map +1 -1
  265. package/dist/team/runtime.js +10 -20
  266. package/dist/team/runtime.js.map +1 -1
  267. package/dist/team/tmux-session.d.ts.map +1 -1
  268. package/dist/team/tmux-session.js +22 -6
  269. package/dist/team/tmux-session.js.map +1 -1
  270. package/dist/ultragoal/__tests__/artifacts.test.js +50 -0
  271. package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
  272. package/dist/ultragoal/artifacts.d.ts.map +1 -1
  273. package/dist/ultragoal/artifacts.js +28 -2
  274. package/dist/ultragoal/artifacts.js.map +1 -1
  275. package/package.json +1 -1
  276. package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
  277. package/plugins/oh-my-codex/skills/autopilot/SKILL.md +16 -4
  278. package/plugins/oh-my-codex/skills/autoresearch/SKILL.md +4 -0
  279. package/plugins/oh-my-codex/skills/autoresearch-goal/SKILL.md +1 -1
  280. package/plugins/oh-my-codex/skills/best-practice-research/SKILL.md +1 -1
  281. package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +10 -0
  282. package/plugins/oh-my-codex/skills/pipeline/SKILL.md +1 -1
  283. package/plugins/oh-my-codex/skills/plan/SKILL.md +1 -1
  284. package/plugins/oh-my-codex/skills/prometheus-strict/README.md +35 -0
  285. package/plugins/oh-my-codex/skills/prometheus-strict/SKILL.md +219 -0
  286. package/plugins/oh-my-codex/skills/ralplan/SKILL.md +24 -5
  287. package/prompts/prometheus-strict-metis.md +274 -0
  288. package/prompts/prometheus-strict-momus.md +82 -0
  289. package/prompts/prometheus-strict-oracle.md +107 -0
  290. package/prompts/researcher.md +22 -3
  291. package/prompts/scholastic.md +11 -0
  292. package/skills/autopilot/SKILL.md +16 -4
  293. package/skills/autoresearch/SKILL.md +4 -0
  294. package/skills/autoresearch-goal/SKILL.md +1 -1
  295. package/skills/best-practice-research/SKILL.md +1 -1
  296. package/skills/deep-interview/SKILL.md +10 -0
  297. package/skills/pipeline/SKILL.md +1 -1
  298. package/skills/plan/SKILL.md +1 -1
  299. package/skills/prometheus-strict/README.md +35 -0
  300. package/skills/prometheus-strict/SKILL.md +219 -0
  301. package/skills/ralplan/SKILL.md +24 -5
  302. package/src/scripts/__tests__/codex-native-hook.test.ts +1307 -61
  303. package/src/scripts/__tests__/docs-site-contract.test.ts +47 -0
  304. package/src/scripts/__tests__/notify-dispatcher.test.ts +132 -3
  305. package/src/scripts/__tests__/run-test-files.test.ts +67 -0
  306. package/src/scripts/__tests__/verify-native-agents.test.ts +2 -2
  307. package/src/scripts/codex-native-hook.ts +260 -31
  308. package/src/scripts/notify-dispatcher.ts +202 -4
  309. package/src/scripts/run-test-files.ts +13 -0
  310. package/templates/catalog-manifest.json +27 -0
@@ -3,9 +3,9 @@ import { closeSync, existsSync, openSync, readFileSync, readSync } from "fs";
3
3
  import { appendFile, mkdir, readFile, readdir, stat, writeFile } from "fs/promises";
4
4
  import { extname, join, relative, resolve } from "path";
5
5
  import { pathToFileURL } from "url";
6
- import { readModeState, readModeStateForActiveDecision, readModeStateForSession, updateModeState } from "../modes/base.js";
7
- import { extractSessionIdFromInitializedStatePath, getSkillActiveStatePathsForStateDir, listActiveSkills, readSkillActiveState, readVisibleSkillActiveStateForStateDir, } from "../state/skill-active.js";
8
- import { readSubagentSessionSummary, recordSubagentTurnForSession, } from "../subagents/tracker.js";
6
+ import { readModeStateForActiveDecision, readModeStateForSession, updateModeState } from "../modes/base.js";
7
+ import { SKILL_ACTIVE_STATE_FILE, extractSessionIdFromInitializedStatePath, getSkillActiveStatePathsForStateDir, listActiveSkills, readSkillActiveState, readVisibleSkillActiveStateForStateDir, } from "../state/skill-active.js";
8
+ import { readSubagentSessionSummary, readSubagentTrackingState, recordSubagentTurnForSession, } from "../subagents/tracker.js";
9
9
  import { resolveCanonicalTeamStateRoot, resolveWorkerNotifyTeamStateRootPath } from "../team/state-root.js";
10
10
  import { appendToLog, isSessionStateUsable, readSessionState, readUsableSessionState, reconcileNativeSessionStart, } from "../hooks/session.js";
11
11
  import { appendTeamEvent, readTeamLeaderAttention, readTeamManifestV2, readTeamPhase, writeTeamLeaderAttention, writeTeamPhase, } from "../team/state.js";
@@ -13,6 +13,7 @@ import { omxNotepadPath, resolveProjectMemoryPath } from "../utils/paths.js";
13
13
  import { findGitLayout } from "../utils/git-layout.js";
14
14
  import { getBaseStateDir, getStateFilePath, getStatePath } from "../mcp/state-paths.js";
15
15
  import { detectKeywords, detectPrimaryKeyword, recordSkillActivation, } from "../hooks/keyword-detector.js";
16
+ import { buildDeepInterviewConfigInstruction } from "../hooks/deep-interview-config-instruction.js";
16
17
  import { detectNativeStopStallPattern, loadAutoNudgeConfig, normalizeAutoNudgeSignatureText, resolveEffectiveAutoNudgeResponse, } from "./notify-hook/auto-nudge.js";
17
18
  import { SLOPPY_FALLBACK_GROUNDING_PATTERNS, SLOPPY_FALLBACK_IMPLEMENTATION_CONTEXT_PATTERNS, SLOPPY_FALLBACK_PHRASE_PATTERNS, buildNativePostToolUseOutput, buildNativePreToolUseOutput, detectMcpTransportFailure, hasAnyPattern, } from "./codex-native-pre-post.js";
18
19
  import { handleTeamWorkerPostToolUseSuccess } from "./notify-hook/team-worker-posttooluse.js";
@@ -175,18 +176,29 @@ async function nativeSubagentSessionStartBelongsToCanonicalSession(cwd, canonica
175
176
  return summary.allThreadIds.includes(parentThreadId);
176
177
  }
177
178
  async function isNativeSubagentHook(cwd, canonicalSessionId, nativeSessionId, threadId) {
178
- const sessionId = canonicalSessionId.trim();
179
- if (!sessionId)
180
- return false;
181
- const summary = await readSubagentSessionSummary(cwd, sessionId).catch(() => null);
182
- if (!summary)
183
- return false;
184
179
  const candidateIds = [nativeSessionId, threadId]
185
180
  .map((value) => value.trim())
186
181
  .filter(Boolean);
187
182
  if (candidateIds.length === 0)
188
183
  return false;
189
- return candidateIds.some((id) => summary.allSubagentThreadIds.includes(id));
184
+ const sessionId = canonicalSessionId.trim();
185
+ if (sessionId) {
186
+ const summary = await readSubagentSessionSummary(cwd, sessionId).catch(() => null);
187
+ if (summary && candidateIds.some((id) => summary.allSubagentThreadIds.includes(id))) {
188
+ return true;
189
+ }
190
+ }
191
+ // Native Codex resume can report the child native session as the canonical
192
+ // session id before OMX reconciles it back to the owning session. In that
193
+ // window the per-session summary lookup above misses the child and a
194
+ // subagent UserPromptSubmit can accidentally activate workflow keywords from
195
+ // quoted review context. Fall back to the global tracking index so any known
196
+ // subagent thread is treated as subagent-scoped, regardless of the current
197
+ // hook payload's session-id mapping.
198
+ const trackingState = await readSubagentTrackingState(cwd).catch(() => null);
199
+ if (!trackingState)
200
+ return false;
201
+ return Object.values(trackingState.sessions).some((session) => (candidateIds.some((id) => session.threads[id]?.kind === "subagent")));
190
202
  }
191
203
  function shouldSuppressSubagentLifecycleHookDispatch() {
192
204
  const config = getNotificationConfig();
@@ -1361,14 +1373,42 @@ function buildNativeOutsideTmuxTeamPromptBlockState(prompt, cwd, payload, sessio
1361
1373
  function buildSkillStateCliInstruction(mode, statePath) {
1362
1374
  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.`;
1363
1375
  }
1376
+ function buildAutopilotPromptActivationNote(skillState) {
1377
+ if (skillState?.initialized_mode !== "autopilot")
1378
+ return null;
1379
+ return [
1380
+ "Autopilot protocol: the durable default chain is $deep-interview -> $ralplan -> $ultragoal (+ $team if needed) -> $code-review -> $ultraqa (deep-interview -> ralplan -> ultragoal -> code-review -> ultraqa).",
1381
+ "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.",
1382
+ "The ralplan phase is not complete until Planner output has been reviewed sequentially by Architect and then Critic; do not hand off to Ultragoal or implementation until the ralplan state/artifact records both ralplan_architect_review and ralplan_critic_review with approval or an explicit blocker.",
1383
+ "Do not silently fall back to ordinary $plan/ralplan-only handling; keep autopilot-state.json, skill-active-state.json, HUD/statusline, and Codex goal-mode handoff guidance visible while the workflow is active.",
1384
+ "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.",
1385
+ ].join(" ");
1386
+ }
1364
1387
  function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(), payload) {
1365
1388
  if (!prompt)
1366
1389
  return null;
1367
1390
  const promptPriorityMessage = buildPromptPriorityMessage(prompt);
1368
1391
  const matches = detectKeywords(prompt);
1369
1392
  const match = detectPrimaryKeyword(prompt);
1370
- if (!match)
1371
- return promptPriorityMessage;
1393
+ if (!match) {
1394
+ const continuedSkill = safeString(skillState?.skill).trim();
1395
+ if (!continuedSkill)
1396
+ return promptPriorityMessage;
1397
+ const deepInterviewPromptActivationNote = skillState?.initialized_mode === "deep-interview"
1398
+ ? buildDeepInterviewQuestionBridgeInstruction(cwd, payload)
1399
+ : null;
1400
+ const deepInterviewConfigPromptActivationNote = buildDeepInterviewConfigInstruction(cwd, skillState);
1401
+ return [
1402
+ `OMX native UserPromptSubmit continued active workflow skill "${continuedSkill}".`,
1403
+ promptPriorityMessage,
1404
+ skillState?.initialized_mode && skillState.initialized_state_path
1405
+ ? buildSkillStateCliInstruction(skillState.initialized_mode, skillState.initialized_state_path)
1406
+ : null,
1407
+ deepInterviewPromptActivationNote,
1408
+ deepInterviewConfigPromptActivationNote,
1409
+ "Follow AGENTS.md routing and preserve workflow transition and planning-safety rules.",
1410
+ ].filter(Boolean).join(" ");
1411
+ }
1372
1412
  const detectedKeywordMessage = matches.length > 1
1373
1413
  ? `OMX native UserPromptSubmit detected workflow keywords ${matches.map((entry) => `"${entry.keyword}" -> ${entry.skill}`).join(", ")}.`
1374
1414
  : `OMX native UserPromptSubmit detected workflow keyword "${match.keyword}" -> ${match.skill}.`;
@@ -1385,12 +1425,14 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
1385
1425
  const deepInterviewPromptActivationNote = skillState?.initialized_mode === "deep-interview"
1386
1426
  ? buildDeepInterviewQuestionBridgeInstruction(cwd, payload)
1387
1427
  : null;
1428
+ const deepInterviewConfigPromptActivationNote = buildDeepInterviewConfigInstruction(cwd, skillState);
1388
1429
  const ultraworkPromptActivationNote = skillState?.initialized_mode === "ultrawork"
1389
1430
  ? "Ultrawork protocol: ground the task before editing, define pass/fail acceptance criteria, keep shared-file work local, and use direct-tool plus background evidence lanes only for truly independent work. Direct ultrawork provides lightweight verification only; Ralph owns persistence and the full verified-completion promise."
1390
1431
  : null;
1391
1432
  const ultragoalPromptActivationNote = match.skill === "ultragoal"
1392
1433
  ? "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."
1393
1434
  : null;
1435
+ const autopilotPromptActivationNote = buildAutopilotPromptActivationNote(skillState);
1394
1436
  const combinedTransitionMessage = (() => {
1395
1437
  if (!skillState?.transition_message)
1396
1438
  return null;
@@ -1419,6 +1461,8 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
1419
1461
  : null,
1420
1462
  promptPriorityMessage,
1421
1463
  ultragoalPromptActivationNote,
1464
+ autopilotPromptActivationNote,
1465
+ deepInterviewConfigPromptActivationNote,
1422
1466
  skillState.initialized_mode && skillState.initialized_state_path
1423
1467
  ? buildSkillStateCliInstruction(skillState.initialized_mode, skillState.initialized_state_path)
1424
1468
  : null,
@@ -1442,8 +1486,10 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
1442
1486
  promptPriorityMessage,
1443
1487
  initializedStateMessage,
1444
1488
  deepInterviewPromptActivationNote,
1489
+ deepInterviewConfigPromptActivationNote,
1445
1490
  ultraworkPromptActivationNote,
1446
1491
  ultragoalPromptActivationNote,
1492
+ autopilotPromptActivationNote,
1447
1493
  buildTeamRuntimeInstruction(cwd, payload),
1448
1494
  buildTeamHelpInstruction(cwd, payload),
1449
1495
  "Follow AGENTS.md routing and preserve workflow transition and planning-safety rules.",
@@ -1459,13 +1505,15 @@ function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd(),
1459
1505
  promptPriorityMessage,
1460
1506
  buildSkillStateCliInstruction(skillState.initialized_mode, skillState.initialized_state_path),
1461
1507
  deepInterviewPromptActivationNote,
1508
+ deepInterviewConfigPromptActivationNote,
1462
1509
  ultraworkPromptActivationNote,
1463
1510
  ultragoalPromptActivationNote,
1511
+ autopilotPromptActivationNote,
1464
1512
  ralphPromptActivationNote,
1465
1513
  "Follow AGENTS.md routing and preserve workflow transition and planning-safety rules.",
1466
1514
  ].join(" ");
1467
1515
  }
1468
- return [detectedKeywordMessage, promptPriorityMessage, ultragoalPromptActivationNote, "Follow AGENTS.md routing and preserve workflow transition and planning-safety rules."].filter(Boolean).join(" ");
1516
+ return [detectedKeywordMessage, promptPriorityMessage, ultragoalPromptActivationNote, autopilotPromptActivationNote, "Follow AGENTS.md routing and preserve workflow transition and planning-safety rules."].filter(Boolean).join(" ");
1469
1517
  }
1470
1518
  function parseTeamWorkerEnv(rawValue) {
1471
1519
  const match = /^([a-z0-9][a-z0-9-]{0,29})\/(worker-\d+)$/.exec(rawValue.trim());
@@ -1664,6 +1712,7 @@ async function findActiveGoalWorkflowReconciliationRequirement(cwd) {
1664
1712
  `If get_goal returns a completed task-scoped objective for the same aggregate ultragoal plan, checkpoint ${goalId} with evidence naming ${goalId} plus .omx/ultragoal/goals.json or ledger.jsonl and pass final quality-gate JSON; OMX will reconcile the completed planned scope without mutating Codex goal state.`,
1665
1713
  `If get_goal instead returns a different completed legacy objective and complete checkpointing fails, do not repeat --status complete in this thread.`,
1666
1714
  `Record the non-terminal blocker with: omx ultragoal checkpoint --goal-id ${goalId} --status blocked --codex-goal-json '<different completed get_goal JSON or path>' --evidence '<completed legacy Codex goal blocks create_goal in this thread>'.`,
1715
+ `If get_goal itself is unavailable with a Codex DB/schema/context error such as "no such table: thread_goals", record an auditable safe-recovery blocker instead: omx ultragoal checkpoint --goal-id ${goalId} --status blocked --codex-goal-json '<unavailable get_goal error JSON or path>' --evidence '<get_goal unavailable due to Codex DB/schema/context error; safe recovery requires a working Codex goal context>'.`,
1667
1716
  "Then continue only from a Codex goal context with no active/completed conflicting goal in the same repo/worktree and create the intended goal there.",
1668
1717
  ].join(" "),
1669
1718
  };
@@ -1744,30 +1793,46 @@ async function buildGoalWorkflowReconciliationStopOutput(payload, cwd) {
1744
1793
  systemMessage,
1745
1794
  };
1746
1795
  }
1747
- async function readTeamModeStateForStop(cwd, stateDir, sessionId) {
1796
+ function teamStateMatchesThreadForStop(state, threadId, options = {}) {
1797
+ const normalizedThreadId = safeString(threadId).trim();
1798
+ if (!normalizedThreadId)
1799
+ return true;
1800
+ const ownerThreadId = safeString(state.owner_codex_thread_id ?? state.thread_id).trim();
1801
+ if (!ownerThreadId)
1802
+ return options.requireOwnerThread !== true;
1803
+ return ownerThreadId === normalizedThreadId;
1804
+ }
1805
+ async function readTeamModeStateForStop(cwd, stateDir, sessionId, threadId) {
1748
1806
  const normalizedSessionId = safeString(sessionId).trim();
1749
- if (!normalizedSessionId) {
1750
- return await readModeState("team", cwd);
1751
- }
1807
+ if (!normalizedSessionId)
1808
+ return null;
1752
1809
  const scopedState = await readStopSessionPinnedState("team-state.json", cwd, normalizedSessionId, stateDir);
1753
- if (scopedState)
1754
- return scopedState;
1810
+ if (scopedState) {
1811
+ return teamStateMatchesThreadForStop(scopedState, threadId)
1812
+ ? { state: scopedState, scope: "session" }
1813
+ : null;
1814
+ }
1755
1815
  const rootState = await readJsonIfExists(join(stateDir, "team-state.json"));
1756
1816
  if (rootState?.active !== true)
1757
1817
  return null;
1818
+ const teamName = safeString(rootState.team_name).trim();
1819
+ if (!teamName)
1820
+ return null;
1758
1821
  const ownerSessionId = safeString(rootState.session_id).trim();
1759
- if (ownerSessionId && ownerSessionId !== normalizedSessionId) {
1822
+ if (!ownerSessionId || ownerSessionId !== normalizedSessionId)
1760
1823
  return null;
1761
- }
1762
- return rootState;
1824
+ if (!teamStateMatchesThreadForStop(rootState, threadId, { requireOwnerThread: true }))
1825
+ return null;
1826
+ return { state: rootState, scope: "root" };
1763
1827
  }
1764
- async function buildTeamStopOutput(cwd, sessionId) {
1828
+ async function buildTeamStopOutput(cwd, sessionId, threadId) {
1765
1829
  if (await readCanonicalTerminalRunStateForStop(cwd, sessionId, "team")) {
1766
1830
  return null;
1767
1831
  }
1768
- const teamState = await readTeamModeStateForStop(cwd, getBaseStateDir(cwd), sessionId);
1769
- if (teamState?.active !== true)
1832
+ const teamStateForStop = await readTeamModeStateForStop(cwd, getBaseStateDir(cwd), sessionId, threadId);
1833
+ if (!teamStateForStop || teamStateForStop.state.active !== true)
1770
1834
  return null;
1835
+ const teamState = teamStateForStop.state;
1771
1836
  const teamName = safeString(teamState.team_name).trim();
1772
1837
  if (teamName) {
1773
1838
  const canonicalTeamDir = join(resolveCanonicalTeamStateRoot(cwd), "team", teamName);
@@ -1776,7 +1841,10 @@ async function buildTeamStopOutput(cwd, sessionId) {
1776
1841
  }
1777
1842
  }
1778
1843
  const coarsePhase = teamState.current_phase;
1779
- const canonicalPhase = teamName ? (await readTeamPhase(teamName, cwd))?.current_phase ?? coarsePhase : coarsePhase;
1844
+ const canonicalPhaseState = teamName ? await readTeamPhase(teamName, cwd) : null;
1845
+ if (teamStateForStop.scope === "root" && !canonicalPhaseState)
1846
+ return null;
1847
+ const canonicalPhase = canonicalPhaseState?.current_phase ?? coarsePhase;
1780
1848
  if (!isNonTerminalPhase(canonicalPhase))
1781
1849
  return null;
1782
1850
  return buildTeamStopOutputForPhase(teamName, formatPhase(canonicalPhase));
@@ -1859,6 +1927,137 @@ async function readStopSessionPinnedState(fileName, cwd, sessionId, stateDir) {
1859
1927
  : getStateFilePath(fileName, cwd, sessionId || undefined);
1860
1928
  return readJsonIfExists(statePath);
1861
1929
  }
1930
+ const DEEP_INTERVIEW_ALLOWED_WRITE_PREFIXES = [
1931
+ ".omx/context",
1932
+ ".omx/interviews",
1933
+ ".omx/specs",
1934
+ ".omx/state",
1935
+ ];
1936
+ const DEEP_INTERVIEW_IMPLEMENTATION_TOOL_NAMES = new Set([
1937
+ "Write",
1938
+ "Edit",
1939
+ "MultiEdit",
1940
+ "apply_patch",
1941
+ "ApplyPatch",
1942
+ ]);
1943
+ function isActiveDeepInterviewPhase(state) {
1944
+ if (!state || state.active !== true)
1945
+ return false;
1946
+ const mode = safeString(state.mode).trim();
1947
+ if (mode && mode !== "deep-interview")
1948
+ return false;
1949
+ const phase = safeString(state.current_phase ?? state.currentPhase).trim().toLowerCase();
1950
+ if (phase && (TERMINAL_MODE_PHASES.has(phase) || phase === "completing"))
1951
+ return false;
1952
+ return true;
1953
+ }
1954
+ function isAllowedDeepInterviewArtifactPath(cwd, rawPath) {
1955
+ const trimmed = rawPath.trim().replace(/^['"]|['"]$/g, "");
1956
+ if (!trimmed || trimmed.includes("\0"))
1957
+ return false;
1958
+ let relativePath;
1959
+ try {
1960
+ const absolute = resolve(cwd, trimmed);
1961
+ relativePath = relative(cwd, absolute).replace(/\\/g, "/");
1962
+ }
1963
+ catch {
1964
+ return false;
1965
+ }
1966
+ if (!relativePath || relativePath.startsWith("..") || relativePath.startsWith("/"))
1967
+ return false;
1968
+ return DEEP_INTERVIEW_ALLOWED_WRITE_PREFIXES.some((prefix) => (relativePath === prefix || relativePath.startsWith(`${prefix}/`)));
1969
+ }
1970
+ function readPreToolUseCommand(payload) {
1971
+ const toolInput = safeObject(payload.tool_input);
1972
+ return safeString(toolInput.command).trim();
1973
+ }
1974
+ function readPreToolUsePathCandidates(payload) {
1975
+ const input = safeObject(payload.tool_input);
1976
+ const candidates = [
1977
+ input.file_path,
1978
+ input.filePath,
1979
+ input.path,
1980
+ input.target_path,
1981
+ input.targetPath,
1982
+ ];
1983
+ return candidates.map((candidate) => safeString(candidate).trim()).filter(Boolean);
1984
+ }
1985
+ function commandHasDeepInterviewWriteIntent(command) {
1986
+ return /\bapply_patch\b/.test(command)
1987
+ || /(?:^|[;&|]\s*)(?:cat|printf|echo)\b[\s\S]{0,240}>\s*[^\s&|;]+/.test(command)
1988
+ || /\btee\s+(?:-a\s+)?[^\s&|;]+/.test(command)
1989
+ || /\bsed\s+(?:[^\n;&|]*\s)?-i(?:\b|['"])/.test(command)
1990
+ || /\b(?:python3?|node|perl|ruby)\b[\s\S]{0,260}\b(?:writeFileSync|writeFile|write_text|open\([^)]*["']w|File\.write|Path\()/.test(command)
1991
+ || /\b(?:git\s+(?:checkout|switch|restore|reset|apply|am|merge|rebase)|npm\s+(?:install|i|ci)|pnpm\s+(?:install|i)|yarn\s+(?:install|add))\b/.test(command);
1992
+ }
1993
+ function extractDeepInterviewCommandWriteTargets(command) {
1994
+ const targets = [];
1995
+ for (const match of command.matchAll(/(?:^|[^>])>{1,2}\s*(["']?)([^\s&|;<>]+)\1/g)) {
1996
+ const candidate = safeString(match[2]).trim();
1997
+ if (candidate)
1998
+ targets.push(candidate);
1999
+ }
2000
+ for (const match of command.matchAll(/\btee\s+(?:-a\s+)?(["']?)([^\s&|;<>]+)\1/g)) {
2001
+ const candidate = safeString(match[2]).trim();
2002
+ if (candidate)
2003
+ targets.push(candidate);
2004
+ }
2005
+ return targets;
2006
+ }
2007
+ function isAllowedDeepInterviewBashWrite(cwd, command) {
2008
+ if (!commandHasDeepInterviewWriteIntent(command))
2009
+ return true;
2010
+ if (/\bomx\s+(?:state\s+(?:write|read|clear)|question)\b/.test(command))
2011
+ return true;
2012
+ const targets = extractDeepInterviewCommandWriteTargets(command);
2013
+ return targets.length > 0 && targets.every((target) => isAllowedDeepInterviewArtifactPath(cwd, target));
2014
+ }
2015
+ async function readActiveDeepInterviewStateForPreToolUse(cwd, stateDir, sessionId, threadId) {
2016
+ const modeState = sessionId
2017
+ ? await readStopSessionPinnedState("deep-interview-state.json", cwd, sessionId, stateDir)
2018
+ : await readJsonIfExists(join(stateDir, "deep-interview-state.json"));
2019
+ if (!isActiveDeepInterviewPhase(modeState) || !modeState)
2020
+ return null;
2021
+ if (!modeStateMatchesSkillStopContext(modeState, cwd, sessionId))
2022
+ return null;
2023
+ const canonicalState = sessionId
2024
+ ? await readVisibleSkillActiveStateForStateDir(stateDir, sessionId)
2025
+ : await readSkillActiveState(join(stateDir, SKILL_ACTIVE_STATE_FILE));
2026
+ if (!canonicalState)
2027
+ return modeState;
2028
+ const hasActiveDeepInterviewSkill = listActiveSkills(canonicalState).some((entry) => (entry.skill === "deep-interview"
2029
+ && matchesSkillStopContext(entry, canonicalState, sessionId, threadId)));
2030
+ return hasActiveDeepInterviewSkill ? modeState : null;
2031
+ }
2032
+ async function buildDeepInterviewPreToolUseBoundaryOutput(payload, cwd, stateDir) {
2033
+ const sessionId = readPayloadSessionId(payload);
2034
+ const threadId = readPayloadThreadId(payload);
2035
+ const activeState = await readActiveDeepInterviewStateForPreToolUse(cwd, stateDir, sessionId, threadId);
2036
+ if (!activeState)
2037
+ return null;
2038
+ const toolName = safeString(payload.tool_name).trim();
2039
+ const command = readPreToolUseCommand(payload);
2040
+ const pathCandidates = readPreToolUsePathCandidates(payload);
2041
+ let blocked = false;
2042
+ if (toolName === "Bash") {
2043
+ blocked = !isAllowedDeepInterviewBashWrite(cwd, command);
2044
+ }
2045
+ else if (DEEP_INTERVIEW_IMPLEMENTATION_TOOL_NAMES.has(toolName)) {
2046
+ blocked = pathCandidates.length === 0
2047
+ || !pathCandidates.every((candidate) => isAllowedDeepInterviewArtifactPath(cwd, candidate));
2048
+ }
2049
+ if (!blocked)
2050
+ return null;
2051
+ const phase = formatPhase(activeState.current_phase ?? activeState.currentPhase, "planning");
2052
+ return {
2053
+ decision: "block",
2054
+ reason: `Deep-interview is active (phase: ${phase}); implementation/write tools are blocked until an explicit handoff workflow is activated.`,
2055
+ hookSpecificOutput: {
2056
+ hookEventName: "PreToolUse",
2057
+ 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`, `$ralph`, `$team`, or `$ultragoal`.",
2058
+ },
2059
+ };
2060
+ }
1862
2061
  function matchesSkillStopContext(entry, state, sessionId, threadId) {
1863
2062
  const entrySessionId = safeString(entry.session_id ?? state.session_id).trim();
1864
2063
  const entryThreadId = safeString(entry.thread_id ?? state.thread_id).trim();
@@ -2310,7 +2509,7 @@ async function maybeReturnRepeatableStopOutput(payload, stateDir, signature, out
2310
2509
  async function returnPersistentStopBlock(payload, stateDir, signatureKind, signatureValue, output, canonicalSessionId, options = { allowRepeatDuringStopHook: true }) {
2311
2510
  return await maybeReturnRepeatableStopOutput(payload, stateDir, buildRepeatableStopSignature(payload, signatureKind, signatureValue, canonicalSessionId), output, canonicalSessionId, options);
2312
2511
  }
2313
- async function findCanonicalActiveTeamForSession(cwd, sessionId) {
2512
+ async function findCanonicalActiveTeamForSession(cwd, sessionId, threadId) {
2314
2513
  if (!sessionId.trim())
2315
2514
  return null;
2316
2515
  const teamsRoot = join(resolveCanonicalTeamStateRoot(cwd), "team");
@@ -2332,6 +2531,8 @@ async function findCanonicalActiveTeamForSession(cwd, sessionId) {
2332
2531
  const ownerSessionId = (manifest.leader?.session_id ?? "").trim();
2333
2532
  if (ownerSessionId && ownerSessionId !== sessionId.trim())
2334
2533
  continue;
2534
+ if (!teamStateMatchesThreadForStop(manifest.leader, threadId))
2535
+ continue;
2335
2536
  if (!isNonTerminalPhase(phaseState.current_phase))
2336
2537
  continue;
2337
2538
  return {
@@ -2341,18 +2542,18 @@ async function findCanonicalActiveTeamForSession(cwd, sessionId) {
2341
2542
  }
2342
2543
  return null;
2343
2544
  }
2344
- async function resolveActiveTeamNameForStop(cwd, stateDir, sessionId) {
2345
- const directState = await readTeamModeStateForStop(cwd, stateDir, sessionId);
2346
- const directTeamName = safeString(directState?.team_name).trim();
2347
- if (directState?.active === true && directTeamName)
2545
+ async function resolveActiveTeamNameForStop(cwd, stateDir, sessionId, threadId) {
2546
+ const directState = await readTeamModeStateForStop(cwd, stateDir, sessionId, threadId);
2547
+ const directTeamName = safeString(directState?.state.team_name).trim();
2548
+ if (directState?.state.active === true && directTeamName)
2348
2549
  return directTeamName;
2349
- const canonicalTeam = await findCanonicalActiveTeamForSession(cwd, sessionId);
2550
+ const canonicalTeam = await findCanonicalActiveTeamForSession(cwd, sessionId, threadId);
2350
2551
  return canonicalTeam?.teamName ?? "";
2351
2552
  }
2352
2553
  async function maybeBuildReleaseReadinessFinalizeStopOutput(payload, cwd, stateDir, sessionId) {
2353
2554
  if (!sessionId)
2354
2555
  return { matched: false, output: null };
2355
- const teamName = await resolveActiveTeamNameForStop(cwd, stateDir, sessionId);
2556
+ const teamName = await resolveActiveTeamNameForStop(cwd, stateDir, sessionId, readPayloadThreadId(payload));
2356
2557
  if (!teamName)
2357
2558
  return { matched: false, output: null };
2358
2559
  const explicitReleaseReadinessContext = hasReleaseReadinessMode(payload)
@@ -2569,7 +2770,7 @@ async function buildStopHookOutput(payload, cwd, stateDir, options = {}) {
2569
2770
  const releaseReadinessFinalizeResult = await maybeBuildReleaseReadinessFinalizeStopOutput(payload, cwd, stateDir, canonicalSessionId);
2570
2771
  if (releaseReadinessFinalizeResult.matched)
2571
2772
  return releaseReadinessFinalizeResult.output;
2572
- const teamOutput = await buildTeamStopOutput(cwd, canonicalSessionId);
2773
+ const teamOutput = await buildTeamStopOutput(cwd, canonicalSessionId, threadId);
2573
2774
  if (teamOutput) {
2574
2775
  return await returnPersistentStopBlock(payload, stateDir, "team-stop", safeString(teamOutput.stopReason), teamOutput, canonicalSessionId);
2575
2776
  }
@@ -2580,7 +2781,7 @@ async function buildStopHookOutput(payload, cwd, stateDir, options = {}) {
2580
2781
  }
2581
2782
  const canonicalTeam = await readCanonicalTerminalRunStateForStop(cwd, canonicalSessionId, "team")
2582
2783
  ? null
2583
- : await findCanonicalActiveTeamForSession(cwd, canonicalSessionId);
2784
+ : await findCanonicalActiveTeamForSession(cwd, canonicalSessionId, threadId);
2584
2785
  if (canonicalTeam) {
2585
2786
  const canonicalTeamOutput = buildTeamStopOutputForPhase(canonicalTeam.teamName, canonicalTeam.phase);
2586
2787
  const repeatedCanonicalTeamOutput = await returnPersistentStopBlock(payload, stateDir, "team-stop", `${canonicalTeam.teamName}|${canonicalTeam.phase}`, canonicalTeamOutput, canonicalSessionId);
@@ -2857,7 +3058,8 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
2857
3058
  }
2858
3059
  }
2859
3060
  else if (hookEventName === "PreToolUse") {
2860
- outputJson = buildNativePreToolUseOutput(payload);
3061
+ outputJson = await buildDeepInterviewPreToolUseBoundaryOutput(payload, cwd, stateDir)
3062
+ ?? buildNativePreToolUseOutput(payload);
2861
3063
  }
2862
3064
  else if (hookEventName === "PostToolUse") {
2863
3065
  if (detectMcpTransportFailure(payload)) {