oh-my-opencode 4.16.1 → 4.16.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 (151) hide show
  1. package/.agents/skills/pre-publish-review/SKILL.md +3 -0
  2. package/README.md +2 -2
  3. package/dist/agents/hephaestus/agent.d.ts +1 -1
  4. package/dist/agents/hephaestus/gpt-5-6.d.ts +2 -0
  5. package/dist/agents/momus-gpt-5-6.d.ts +1 -0
  6. package/dist/agents/types.d.ts +2 -0
  7. package/dist/cli/index.js +800 -536
  8. package/dist/cli-node/index.js +800 -536
  9. package/dist/features/background-agent/error-classifier.d.ts +5 -0
  10. package/dist/features/background-agent/parent-wake-dedupe.d.ts +1 -0
  11. package/dist/features/background-agent/parent-wake-flush-runner.d.ts +2 -0
  12. package/dist/features/background-agent/parent-wake-prompt-dispatch.d.ts +1 -0
  13. package/dist/features/builtin-commands/templates/refactor-sections/intro-and-analysis.d.ts +1 -1
  14. package/dist/features/builtin-commands/templates/remove-ai-slops.d.ts +1 -1
  15. package/dist/index.js +464 -54
  16. package/dist/shared/live-server-route.d.ts +1 -1
  17. package/dist/skills/review-work/SKILL.md +4 -2
  18. package/dist/skills/start-work/SKILL.md +2 -0
  19. package/dist/skills/ulw-plan/references/full-workflow.md +1 -1
  20. package/dist/skills/ulw-research/SKILL.md +5 -3
  21. package/dist/skills/visual-qa/SKILL.md +1 -1
  22. package/dist/tui.js +125 -13
  23. package/package.json +13 -13
  24. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  25. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +398 -246
  26. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  27. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  28. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  29. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  30. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  31. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  32. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  33. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  34. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  35. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  36. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  37. package/packages/omo-codex/plugin/components/rules/bundled-rules/{hephaestus.md → hephaestus/gpt-5.5.md} +1 -1
  38. package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus/gpt-5.6.md +93 -0
  39. package/packages/omo-codex/plugin/components/rules/dist/cli.js +43 -24
  40. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  41. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  42. package/packages/omo-codex/plugin/components/rules/src/codex-hook.ts +2 -1
  43. package/packages/omo-codex/plugin/components/rules/src/dynamic-target-fingerprints.ts +15 -6
  44. package/packages/omo-codex/plugin/components/rules/src/rules-engine-factory.ts +7 -2
  45. package/packages/omo-codex/plugin/components/rules/src/static-injection.ts +2 -2
  46. package/packages/omo-codex/plugin/components/rules/test/codex-hook.test.ts +32 -0
  47. package/packages/omo-codex/plugin/components/rules/test/hephaestus-model-variant.test.ts +106 -0
  48. package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +1 -1
  49. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  50. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  51. package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +1 -1
  52. package/packages/omo-codex/plugin/components/teammode/AGENTS.md +12 -9
  53. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  54. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  55. package/packages/omo-codex/plugin/components/teammode/skills/teammode/SKILL.md +136 -76
  56. package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team-guide.mjs +94 -23
  57. package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team-state.mjs +94 -14
  58. package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team-transport.mjs +55 -0
  59. package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team.mjs +72 -18
  60. package/packages/omo-codex/plugin/components/teammode/test/thread-title-hook.test.ts +23 -0
  61. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  62. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  63. package/packages/omo-codex/plugin/components/ultrawork/agents/explorer.toml +24 -41
  64. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-clone-fidelity-reviewer.toml +1 -1
  65. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-code-reviewer.toml +1 -1
  66. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-executor.toml +2 -2
  67. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +1 -1
  68. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-qa-executor.toml +1 -1
  69. package/packages/omo-codex/plugin/components/ultrawork/agents/librarian.toml +21 -49
  70. package/packages/omo-codex/plugin/components/ultrawork/agents/metis.toml +17 -29
  71. package/packages/omo-codex/plugin/components/ultrawork/agents/momus.toml +20 -50
  72. package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +18 -39
  73. package/packages/omo-codex/plugin/components/ultrawork/directive.md +1 -0
  74. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  75. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  76. package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +1 -0
  77. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +2 -0
  78. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +3 -1
  79. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +1 -0
  80. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +2 -2
  81. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  82. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +2 -0
  83. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +1 -1
  84. package/packages/omo-codex/plugin/components/ulw-loop/test/skill-contract.test.ts +1 -1
  85. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  86. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  87. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  88. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  89. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  90. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  91. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  92. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  93. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  94. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  95. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  96. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  97. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  98. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  99. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  100. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
  101. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
  102. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  103. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  104. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  105. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  106. package/packages/omo-codex/plugin/package-lock.json +13 -13
  107. package/packages/omo-codex/plugin/package.json +1 -1
  108. package/packages/omo-codex/plugin/scripts/auto-update.mjs +73 -19
  109. package/packages/omo-codex/plugin/scripts/entry-guard.mjs +26 -0
  110. package/packages/omo-codex/plugin/scripts/materialize-shared-upstreams.mjs +3 -1
  111. package/packages/omo-codex/plugin/scripts/migrate-codex-config/multi-agent-v2-guard.mjs +221 -20
  112. package/packages/omo-codex/plugin/scripts/migrate-codex-config/subagent-limit-guard.mjs +71 -3
  113. package/packages/omo-codex/plugin/scripts/migrate-codex-config.mjs +35 -7
  114. package/packages/omo-codex/plugin/scripts/migrate-omo-sot.mjs +2 -2
  115. package/packages/omo-codex/plugin/scripts/sync-hook-status-messages.mjs +2 -2
  116. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +7 -5
  117. package/packages/omo-codex/plugin/scripts/sync-version.mjs +4 -2
  118. package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +2 -2
  119. package/packages/omo-codex/plugin/skills/refactor/SKILL.md +2 -2
  120. package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +2 -2
  121. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +2 -2
  122. package/packages/omo-codex/plugin/skills/start-work/SKILL.md +2 -2
  123. package/packages/omo-codex/plugin/skills/teammode/SKILL.md +136 -76
  124. package/packages/omo-codex/plugin/skills/teammode/scripts/team-guide.mjs +94 -23
  125. package/packages/omo-codex/plugin/skills/teammode/scripts/team-state.mjs +94 -14
  126. package/packages/omo-codex/plugin/skills/teammode/scripts/team-transport.mjs +55 -0
  127. package/packages/omo-codex/plugin/skills/teammode/scripts/team.mjs +72 -18
  128. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +1 -0
  129. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +2 -0
  130. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +1 -1
  131. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +2 -0
  132. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +3 -1
  133. package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +3 -3
  134. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +3 -3
  135. package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +47 -1
  136. package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +1 -1
  137. package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +4 -2
  138. package/packages/omo-codex/plugin/test/auto-update-restart-notice.test.mjs +33 -0
  139. package/packages/omo-codex/plugin/test/auto-update.test.mjs +35 -1
  140. package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +412 -19
  141. package/packages/omo-codex/plugin/test/multi-agent-v2-regression.test.mjs +71 -0
  142. package/packages/omo-codex/plugin/test/subagent-limit-migration.test.mjs +65 -0
  143. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +13 -4
  144. package/packages/omo-codex/plugin/test/teammode-transport.test.mjs +345 -0
  145. package/packages/omo-codex/scripts/install-dist/install-local.mjs +436 -284
  146. package/packages/omo-codex/scripts/install-generated-bundle.test.mjs +111 -1
  147. package/packages/shared-skills/skills/review-work/SKILL.md +4 -2
  148. package/packages/shared-skills/skills/start-work/SKILL.md +2 -0
  149. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +1 -1
  150. package/packages/shared-skills/skills/ulw-research/SKILL.md +5 -3
  151. package/packages/shared-skills/skills/visual-qa/SKILL.md +1 -1
@@ -14,11 +14,11 @@ This skill may include examples copied from the OpenCode harness. In Codex, do n
14
14
  | `task(subagent_type="oracle", ...)` for final verification | `multi_agent_v1.spawn_agent({"message":"TASK: act as a rigorous reviewer. ...","agent_type":"lazycodex-gate-reviewer","fork_context":false})` |
15
15
  | `task(category="...", ...)` for implementation or QA | `multi_agent_v1.spawn_agent({"message":"TASK: act as an implementation or QA worker. ...","fork_context":false})` |
16
16
  | `background_output(task_id="...")` | `multi_agent_v1.wait_agent(...)` for mailbox signals |
17
- | `team_*(...)` | Use Codex native subagents via `multi_agent_v1.spawn_agent`, `multi_agent_v1.send_input`, `multi_agent_v1.wait_agent`, and `multi_agent_v1.close_agent` |
17
+ | `team_*(...)` | Use Codex native subagents via `multi_agent_v1.spawn_agent` and `multi_agent_v1.wait_agent`; use `multi_agent_v1.send_input` and `multi_agent_v1.close_agent` only when exposed in the active tools list |
18
18
 
19
19
  Role-specific behavior must be described in a self-contained `message`. Use `fork_context: false` to start the child with only the initial prompt (no parent history); use `fork_context: true` only when full parent history is truly required. Include any required conversation context, files, diffs, constraints, and requested skill names directly in the spawned agent's `message`. OMO installs these selectable agent roles into `~/.codex/agents/`: `explorer`, `librarian`, `plan`, `momus`, `metis`, `lazycodex-code-reviewer`, `lazycodex-qa-executor`, and `lazycodex-gate-reviewer` - pass the matching name as `agent_type` so the child gets that role's model and instructions. If the spawn tool exposes no `agent_type` parameter, omit it and describe the role inside `message`. If a code block below conflicts with this section, this section wins.
20
20
 
21
- On `multi_agent_v2` sessions the same `agent_type` applies (the OMO installer exposes it) with `fork_turns` instead of `fork_context`. If a code block below conflicts with this section, this section wins.
21
+ Codex exposes ONE of two subagent tool surfaces per session; check your own tool list and route accordingly. If `multi_agent_v1.*` tools exist, use the table above as written. If instead a flat `spawn_agent` with a required `task_name` exists (`multi_agent_v2`), rewrite every `multi_agent_v1.*` example: `multi_agent_v1.spawn_agent({...,"fork_context":false})` becomes `spawn_agent({"task_name":"<lowercase_digits_underscores>","message":...,"agent_type":...,"fork_turns":"none"})` (`"all"` only when full parent history is truly required); `send_input` becomes `send_message`; do not call `close_agent`/`resume_agent` (finished agents end on their own; `followup_task` re-tasks one, `interrupt_agent` stops one); `wait_agent` takes only `timeout_ms` and returns on any child mailbox activity. `agent_type` works the same on both surfaces. If a code block below conflicts with this section, this section wins.
22
22
 
23
23
  When translating `load_skills=[...]`, include the requested skill names in the spawned agent's `message`. If a code block below conflicts with this section, this section wins.
24
24
 
@@ -15,11 +15,11 @@ This skill may include examples copied from the OpenCode harness. In Codex, do n
15
15
  | `task(subagent_type="oracle", ...)` for final verification | `multi_agent_v1.spawn_agent({"message":"TASK: act as a rigorous reviewer. ...","agent_type":"lazycodex-gate-reviewer","fork_context":false})` |
16
16
  | `task(category="...", ...)` for implementation or QA | `multi_agent_v1.spawn_agent({"message":"TASK: act as an implementation or QA worker. ...","fork_context":false})` |
17
17
  | `background_output(task_id="...")` | `multi_agent_v1.wait_agent(...)` for mailbox signals |
18
- | `team_*(...)` | Use Codex native subagents via `multi_agent_v1.spawn_agent`, `multi_agent_v1.send_input`, `multi_agent_v1.wait_agent`, and `multi_agent_v1.close_agent` |
18
+ | `team_*(...)` | Use Codex native subagents via `multi_agent_v1.spawn_agent` and `multi_agent_v1.wait_agent`; use `multi_agent_v1.send_input` and `multi_agent_v1.close_agent` only when exposed in the active tools list |
19
19
 
20
20
  Role-specific behavior must be described in a self-contained `message`. Use `fork_context: false` to start the child with only the initial prompt (no parent history); use `fork_context: true` only when full parent history is truly required. Include any required conversation context, files, diffs, constraints, and requested skill names directly in the spawned agent's `message`. OMO installs these selectable agent roles into `~/.codex/agents/`: `explorer`, `librarian`, `plan`, `momus`, `metis`, `lazycodex-code-reviewer`, `lazycodex-qa-executor`, and `lazycodex-gate-reviewer` - pass the matching name as `agent_type` so the child gets that role's model and instructions. If the spawn tool exposes no `agent_type` parameter, omit it and describe the role inside `message`. If a code block below conflicts with this section, this section wins.
21
21
 
22
- On `multi_agent_v2` sessions the same `agent_type` applies (the OMO installer exposes it) with `fork_turns` instead of `fork_context`. If a code block below conflicts with this section, this section wins.
22
+ Codex exposes ONE of two subagent tool surfaces per session; check your own tool list and route accordingly. If `multi_agent_v1.*` tools exist, use the table above as written. If instead a flat `spawn_agent` with a required `task_name` exists (`multi_agent_v2`), rewrite every `multi_agent_v1.*` example: `multi_agent_v1.spawn_agent({...,"fork_context":false})` becomes `spawn_agent({"task_name":"<lowercase_digits_underscores>","message":...,"agent_type":...,"fork_turns":"none"})` (`"all"` only when full parent history is truly required); `send_input` becomes `send_message`; do not call `close_agent`/`resume_agent` (finished agents end on their own; `followup_task` re-tasks one, `interrupt_agent` stops one); `wait_agent` takes only `timeout_ms` and returns on any child mailbox activity. `agent_type` works the same on both surfaces. If a code block below conflicts with this section, this section wins.
23
23
 
24
24
  When translating `load_skills=[...]`, include the requested skill names in the spawned agent's `message`. If a code block below conflicts with this section, this section wins.
25
25
 
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  name: teammode
3
- description: "Codex-only team orchestration: run a named team of cooperating Codex threads with durable, script-managed state. MUST USE when the user asks Codex to create, run, coordinate, inspect, archive, or delete a team of threads/sessions, or to work on something as a team in parallel. The main session is always the leader; members are defined by a concrete part, ownership area, or perspective - never a vague job role; a bundled cross-platform script writes the .omo/teams state plus an auto-generated member field manual. Use a team when the work is not perfectly isolated but parallelizing helps, or when a task still needs exploration under a clear goal; use plain subagents when scope is perfectly isolated or the goal is ambiguous. Triggers: team mode, teammode, make a team, run as a team, team of agents, coordinate threads, parallel Codex threads, archive the team, delete the team."
3
+ description: "Codex-only team orchestration: run a named team of cooperating Codex workers with durable, script-managed state. MUST USE when the user asks Codex to create, run, coordinate, inspect, archive, or delete a team of agents/threads/sessions, or to work on something as a team in parallel. FIRST inspects the active tool surface and tells the user which transport it selected: native MultiAgentV2 agents (flat spawn_agent with task_name) when available, Codex App threads as the fallback. The main session is always the leader; members are defined by a concrete part, ownership area, or perspective - never a vague job role; a bundled cross-platform script writes the .omo/teams state plus an auto-generated member field manual. Use a team when the work is not perfectly isolated but parallelizing helps; use plain subagents when scope is perfectly isolated or the goal is ambiguous. Triggers: team mode, teammode, make a team, run as a team, team of agents, coordinate threads, parallel Codex threads, archive the team."
4
4
  ---
5
5
 
6
6
  # Teammode
7
7
 
8
- Run a named team of cooperating Codex threads under one leader, with durable state on disk.
9
- This is a Codex-only workflow. It is inspired by the lifecycle concerns in the
10
- Yeachan-Heo/oh-my-codex team skill, but it does not copy that runtime model and never depends
11
- on an external terminal runner - it coordinates through Codex's own thread tools plus a bundled
12
- state script.
8
+ Run a named team of cooperating Codex workers under one leader, with durable state on disk.
9
+ This is a Codex-only workflow. It never depends on an external terminal runner - it
10
+ coordinates through Codex's own collaboration tools plus a bundled state script, on ONE of
11
+ two transports chosen up front: native MultiAgentV2 agents, or Codex App threads as the
12
+ fallback.
13
13
 
14
14
  ## When to use a team (and when to use plain subagents instead)
15
15
 
@@ -19,17 +19,43 @@ Use a TEAM when EITHER holds:
19
19
  - one task still needs exploration, yet its GOAL is already clear - parallel investigation under
20
20
  a fixed objective.
21
21
 
22
- Use plain subagents (`$ulw` / `multi_agent_v1.spawn_agent`) - NOT a team - when EITHER holds:
22
+ Use plain fire-and-forget subagents (`$ulw` / one-off `spawn_agent` workers) - NOT a team - when
23
+ EITHER holds:
23
24
  - the work IS perfectly isolated, so there is no coordination cost worth paying; or
24
25
  - the GOAL is still ambiguous, where one mind should resolve direction before any fan-out.
25
26
 
26
27
  A team buys cross-member coordination at a real overhead cost; only spend it when coordination
27
28
  is the thing you actually need.
28
29
 
30
+ ## Pick the transport FIRST - then tell the user
31
+
32
+ Before creating any team state, decide which transport this session can run.
33
+ Inspect your active tool list and select:
34
+
35
+ 1. **MultiAgentV2 (preferred)** - select when the flat V2 collaboration tools are ALL active:
36
+ flat `spawn_agent` whose schema requires `task_name`, plus `send_message`, `followup_task`,
37
+ `wait_agent`, `list_agents`, and `interrupt_agent`. Members are durable native agents
38
+ addressed by task name / agent path (`/root/<task_name>`). The namespaced
39
+ `multi_agent_v1.*` surface never qualifies as a team transport.
40
+ 2. **Codex App threads (fallback)** - select when flat V2 is not available but the
41
+ `codex_app.*` thread tools are (`create_thread`, `read_thread`, `send_message_to_thread`,
42
+ `set_thread_title`, `set_thread_archived`).
43
+ 3. **Neither complete set available** - STOP before `init`. Tell the user which tools are
44
+ missing; do not fake a team with partial tooling.
45
+
46
+ Then, BEFORE running `init`, tell the user in one line which transport you selected and why,
47
+ e.g. `Teammode transport: MultiAgentV2 (flat spawn_agent with task_name).` or
48
+ `Teammode transport: Codex App threads (flat V2 tools not present in this session).`
49
+
50
+ Pass that choice to `init` as `--transport multi_agent_v2` or `--transport codex_app`. The
51
+ transport is recorded in `team.json` and is IMMUTABLE for the team's lifetime: a V2 spawn
52
+ failure is a V2 blocker to report, never permission to mix Codex App threads into the same
53
+ team. Never probe by trial-calling tools; read your tool list.
54
+
29
55
  ## You are the leader - orchestrate, do not implement
30
56
 
31
57
  The main session is ALWAYS the team leader; you orchestrate directly and never spin up a separate
32
- leader thread. Your job is orchestration, NOT writing product code: split the work and assign each
58
+ leader worker. Your job is orchestration, NOT writing product code: split the work and assign each
33
59
  slice, hold live situational awareness of every member, verify and QA what they deliver, relay
34
60
  findings between members, instruct and unblock, and synthesize the result. DELEGATE every code edit
35
61
  to a member - if you catch yourself editing product files while the team runs, that work was a
@@ -39,7 +65,7 @@ merge), not the keystrokes.
39
65
  ## Compose by part, ownership, or perspective - not by job title
40
66
 
41
67
  A team is ALWAYS two or more members - never a single-member team. One worker on an isolated
42
- job is a subagent (`multi_agent_v1.spawn_agent`), not a team; if you end up with a single member,
68
+ job is a plain subagent, not a team; if you end up with a single member,
43
69
  either split off a second distinct slice or drop the team and use a subagent.
44
70
 
45
71
  Compose the team from what you actually KNOW about the work. Ground the split in real knowledge
@@ -50,8 +76,10 @@ perspective/lens. Assigning a vague role ("backend dev", "release analyst", "the
50
76
  anti-pattern - it gives the member no real boundary and invites overlap. Each member's `focus`
51
77
  names what they own concretely; the `lens` is one of `area`, `ownership`, or `perspective`.
52
78
  Give each member a short, distinct `--name` too - its role or what it watches (e.g.
53
- `app-server-lifecycle`, `mailbox-delivery`) - because that name titles its thread; never reuse
54
- one name for two members.
79
+ `app-server-lifecycle`, `mailbox-delivery`) - it labels the member everywhere; never reuse
80
+ one name for two members. On MultiAgentV2 teams also give each member a unique
81
+ `--task-name` in `lowercase_digits_underscores` form - it becomes the member's permanent
82
+ agent path `/root/<task_name>`.
55
83
 
56
84
  ## Run the script - never hand-write team state
57
85
 
@@ -60,9 +88,10 @@ the member manual by hand. Run it with `node` (or `bun`); it works on macOS, Lin
60
88
  Replace `<skill-root>` with this skill's own directory.
61
89
 
62
90
  ```
63
- node "<skill-root>/scripts/team.mjs" init --name "<team>" --session-name "<session>" [--session <leader_session_id>] [--worktree] [--base-branch dev]
64
- node "<skill-root>/scripts/team.mjs" add-member --team <session_id> --id A --name "<short role>" --focus "<part/ownership/perspective>" --lens area|ownership|perspective --deliverable "<...>" [--branch <branch>]
65
- node "<skill-root>/scripts/team.mjs" bind-thread --team <session_id> --id A --thread <thread_id> [--cwd <path>]
91
+ node "<skill-root>/scripts/team.mjs" init --name "<team>" --session-name "<session>" --transport multi_agent_v2|codex_app [--session <leader_thread_id>] [--worktree] [--base-branch dev]
92
+ node "<skill-root>/scripts/team.mjs" add-member --team <session_id> --id A --name "<short role>" [--task-name <v2_task_name>] --focus "<part/ownership/perspective>" --lens area|ownership|perspective --deliverable "<...>" [--branch <branch>]
93
+ node "<skill-root>/scripts/team.mjs" bind-agent --team <session_id> --id A --agent-path /root/<task_name> [--cwd <path>] # multi_agent_v2 teams
94
+ node "<skill-root>/scripts/team.mjs" bind-thread --team <session_id> --id A --thread <thread_id> [--cwd <path>] # codex_app teams
66
95
  node "<skill-root>/scripts/team.mjs" member-prompt --team <session_id> --id A
67
96
  node "<skill-root>/scripts/team.mjs" set-status --team <session_id> --id A --status reported|blocked|active|archived [--note "<...>"]
68
97
  node "<skill-root>/scripts/team.mjs" worktree-add --team <session_id> --id A [--base-branch <branch>]
@@ -74,70 +103,93 @@ node "<skill-root>/scripts/team.mjs" status --team <session_id>
74
103
  ```
75
104
 
76
105
  `init` creates `.omo/teams/{session_id}/` containing `team.json` (the single durable state file:
77
- team id, the main-session leader, the member roster, status, worktree config, and a lifecycle
78
- log), `guide.md` (the auto-generated member field manual), and `artifacts/` (a shared exchange
79
- space). `{session_id}` is the leader's Codex session id when you can pass it via `--session`;
80
- otherwise the script generates a stable handle. Re-running `init` is a safe no-op. Every mutating
81
- subcommand rewrites `guide.md`, so the manual always matches the current team.
106
+ team id, transport, the main-session leader, the member roster, status, worktree config, and a
107
+ lifecycle log), `guide.md` (the auto-generated member field manual), and `artifacts/` (a shared
108
+ exchange space). On codex_app teams `{session_id}` is the leader's Codex session id when you can
109
+ pass it via `--session`; otherwise the script generates a stable handle. Re-running `init` is a
110
+ safe no-op. Every mutating subcommand rewrites `guide.md`, so the manual always matches the
111
+ current team.
82
112
 
83
113
  Mutating subcommands take a per-team state lock before reading and rewriting `team.json`. It is
84
- safe to run independent `add-member`, `bind-thread`, `set-status`, `archive`, `delete`, `guide`,
85
- and worktree mutation commands concurrently against the same team: they serialize and each command
86
- reads the latest committed state before writing. If a command reports that team state is locked,
87
- do not treat the intended mutation as complete; retry after the named command finishes, or inspect
88
- `.omo/teams/{session_id}/.team.lock/owner.json` if the previous command crashed.
89
-
90
- ## Create the team and its threads
91
-
92
- 1. `init` the team, then `add-member` once per member.
93
- 2. Create a durable thread per member with `codex_app.create_thread` - ALWAYS this tool for every
94
- member, never a spawned agent - titled `[team name] <member name>`, using THAT member's own
95
- name (its role / what it watches), so no two threads share a title. `add-member` prints the
96
- exact title to use. If `codex_app.create_thread` accepts a working directory / cwd argument,
97
- set it to that member's worktree; otherwise the member's manual tells it to `cd` there first.
98
- Use `codex_app.set_thread_title` if the title did not land at creation.
99
- If Codex returns only `pendingWorktreeId`, the worktree-backed thread is not ready yet: do not
100
- `bind-thread` and do not send the member bootstrap. Wait until Codex surfaces a real `threadId`
101
- or the thread appears in the thread list, then set the title, bind that real id with the cwd,
102
- and only then send the bootstrap.
103
- 3. `bind-thread` to record each thread id (and `--cwd`), then send that member's bootstrap
104
- trigger (printed by `add-member` / `member-prompt`) as the thread's first message. The trigger
105
- is short on purpose: it tells the new thread to READ its `guide.md` and `team.json` rather than
106
- carrying the whole protocol inline.
107
- 4. Whenever you report, audit, reopen, or hand off a member thread, include the app deep link
108
- `codex://threads/<thread_id>` next to the raw id. For example:
109
- `codex://threads/019ef350-ee78-72a3-bd5e-e40cebc3d814`. Worktree-backed threads are easy to
110
- lose in the sidebar without this link.
111
-
112
- Every team member is a real Codex thread created with `codex_app.create_thread` - this is strict,
113
- not a preference. NEVER substitute `multi_agent_v1.spawn_agent`, or any other in-process subagent,
114
- for a team member: a spawned agent is an ephemeral helper that does not show up as a team thread,
115
- cannot carry the `[team name] <member name>` title, and cannot be inspected, titled, archived, or
116
- re-opened with the `codex_app.*` thread tools - which defeats the entire point of a durable team.
117
- A member only counts once you have `bind-thread`-ed it to a real `codex_app.create_thread` thread
118
- id. If the thread-creation tool is unavailable, STOP and say so (see Stop rules); do not quietly
119
- fall back to a spawned agent.
114
+ safe to run independent `add-member`, `bind-agent`, `bind-thread`, `set-status`, `archive`,
115
+ `delete`, `guide`, and worktree mutation commands concurrently against the same team: they
116
+ serialize and each command reads the latest committed state before writing. If a command reports
117
+ that team state is locked, do not treat the intended mutation as complete; retry after the named
118
+ command finishes, or inspect `.omo/teams/{session_id}/.team.lock/owner.json` if the previous
119
+ command crashed. `bind-agent` refuses codex_app teams and `bind-thread` refuses multi_agent_v2
120
+ teams, and a refused command never changes `team.json`.
121
+
122
+ ## Create the team and its members
123
+
124
+ `init` the team, then `add-member` once per member. What happens next depends on the transport.
125
+
126
+ **MultiAgentV2 teams:**
127
+ 1. If a member needs an isolated worktree, run `worktree-add` BEFORE spawning it - flat
128
+ `spawn_agent` has no cwd argument, so the path must ride in the bootstrap message.
129
+ 2. Spawn each member with flat `spawn_agent`: `task_name` is that member's `--task-name`,
130
+ `message` is the bootstrap printed by `add-member` / `member-prompt`, and
131
+ `fork_turns: "none"` (members read `guide.md` for context; full parent history is not
132
+ their context model). Do not set `agent_type`, `model`, or `reasoning_effort`.
133
+ 3. `bind-agent --agent-path` with the canonical task name the spawn returned (normally
134
+ `/root/<task_name>`); binding confirms the runtime identity matches the roster and records
135
+ the member's cwd. Members are durable: they persist as subagent threads, survive idling,
136
+ and are re-tasked with `followup_task` - never respawned under a second name.
137
+ 4. Members appear in `list_agents` with their task paths; inspect status there instead of
138
+ deep links (V2 exposes no thread title or `codex://` link surface to you).
139
+
140
+ **Codex App teams:**
141
+ 1. Create a durable thread per member with `codex_app.create_thread` - ALWAYS this tool for
142
+ every member - titled `[team name] <member name>`, using THAT member's own name, so no two
143
+ threads share a title. `add-member` prints the exact title to use. If the tool accepts a
144
+ working directory / cwd argument, set it to that member's worktree; otherwise the member's
145
+ manual tells it to `cd` there first. Use `codex_app.set_thread_title` if the title did not
146
+ land at creation. If Codex returns only `pendingWorktreeId`, the worktree-backed thread is
147
+ not ready yet: do not `bind-thread` and do not send the member bootstrap. Wait until Codex
148
+ surfaces a real `threadId`, then set the title, bind that real id with the cwd, and only
149
+ then send the bootstrap.
150
+ 2. `bind-thread` to record each thread id (and `--cwd`), then send that member's bootstrap
151
+ trigger as the thread's first message. The trigger is short on purpose: it tells the new
152
+ thread to READ its `guide.md` and `team.json` rather than carrying the whole protocol inline.
153
+ 3. Whenever you report, audit, reopen, or hand off a member thread, include the app deep link
154
+ `codex://threads/<thread_id>` next to the raw id - worktree-backed threads are easy to lose
155
+ in the sidebar without it. On a codex_app team, a spawned in-process agent is never a
156
+ member substitute: it cannot carry the team title or be inspected, titled, archived, or
157
+ re-opened with the `codex_app.*` tools this team runs on.
158
+
159
+ On either transport, a member only counts once it is bound (`bind-agent` / `bind-thread`). If
160
+ the selected transport's tools stop working mid-run, STOP and say so (see Stop rules); do not
161
+ quietly switch transports.
120
162
 
121
163
  ## Communication
122
164
 
123
- Members push to you and to one another with `codex_app.send_message_to_thread`; you inspect their
124
- state with `codex_app.read_thread`. So members can actually reach you, run `init` with
125
- `--session <your own thread id>` - that makes `leader.sessionId` in team.json a real, messageable
126
- thread; without it members cannot report to you and you are stuck polling. The generated manual binds
127
- members to the hard rules, so you mainly keep the channel open: expect frequent small inbound updates
128
- from each member - findings, `WORKING:`/`BLOCKED:` markers, peer digests - rather than one final
129
- dump, and act on them as they arrive. All member-to-member and member-to-leader traffic is in English;
130
- when the END user addresses a member, that member replies in the user's own language. Members hand off
131
- files and memos through the team `artifacts/` directory and reference them by path.
165
+ Members push to you and to one another; you never poll them as a routine. The address book is
166
+ `team.json`, and the generated manual binds members to the hard rules, so you mainly keep the
167
+ channel open: expect frequent small inbound updates from each member - findings,
168
+ `WORKING:`/`BLOCKED:` markers, peer digests - rather than one final dump, and act on them as
169
+ they arrive.
170
+
171
+ - **MultiAgentV2:** members reach you with `send_message` to `/root` and reach peers by their
172
+ `members[].agentPath`. You reach members the same way; use `followup_task` when you hand an
173
+ idle member NEW work (it wakes the member), `send_message` for context that should not
174
+ interrupt, and `wait_agent` only when you are genuinely blocked on their next update - a
175
+ `wait_agent` timeout only means no new mailbox update arrived, never that a member failed.
176
+ Your own session IS `/root` - members can always reach you; leave `--session` unset.
177
+ - **Codex App:** members push with `codex_app.send_message_to_thread`; you inspect state with
178
+ `codex_app.read_thread`. So members can actually reach you, run `init` with
179
+ `--session <your own thread id>` - that makes `leader.sessionId` in team.json a real,
180
+ messageable thread; without it members cannot report to you and you are stuck polling.
181
+
182
+ All member-to-member and member-to-leader traffic is in English; when the END user addresses a
183
+ member, that member replies in the user's own language. Members hand off files and memos
184
+ through the team `artifacts/` directory and reference them by path.
132
185
 
133
186
  ## Let members work - do not rush them
134
187
 
135
188
  Members heartbeat every few tool calls and message you on every finding, blocker, and finished
136
189
  slice (their manual binds them to this). So a member that is quiet between heartbeats is **working,
137
190
  not stalled** - a stretch of silence is the normal sound of focused work, not a problem to chase.
138
- Re-reading `codex_app.read_thread` to check on a calm member, or sending "any update?" / "are you
139
- done?" / "hurry up" pings, interrupts that member and slows the whole team. Trust the heartbeat and
140
- let them cook.
191
+ Re-reading a calm member's state, or sending "any update?" / "are you done?" / "hurry up" pings,
192
+ interrupts that member and slows the whole team. Trust the heartbeat and let them cook.
141
193
 
142
194
  Message a member only when one of these is true:
143
195
  - you have new information, context, or a correction it needs to do its slice right;
@@ -147,7 +199,9 @@ Message a member only when one of these is true:
147
199
  then send one specific question, not a barrage.
148
200
 
149
201
  Otherwise stay calm and keep the channel open: read inbound updates as they arrive and act on them.
150
- A long-running member is alive; a heartbeat you have not received yet is not a failure. Wait for
202
+ A long-running member is alive; a heartbeat you have not received yet is not a failure. Fallback only when
203
+ a member is completed without its deliverable, explicitly `BLOCKED:`, or no longer running - then
204
+ unblock, reassign, or re-task that slice instead of waiting on it. Wait for
151
205
  every required member's final report before you declare the team done - rushing toward "done" while
152
206
  members are still mid-slice just produces half-built work you will have to redo.
153
207
 
@@ -162,10 +216,12 @@ its own worktree. To land the work, `integrate --team <id>` merges every member
162
216
  current branch with a merge commit (never a squash or rebase); resolve any conflict it reports, then
163
217
  `worktree-remove` each worktree at cleanup.
164
218
 
165
- After `worktree-add`, immediately send the member a follow-up that includes both its assigned
166
- worktree path and its `codex://threads/<thread_id>` link. Use `bind-thread --cwd <worktree>` or
167
- `--worktree-path <worktree>` after the thread exists so `team.json`, `guide.md`, `status`, and
168
- `member-prompt` all point at the same worktree-backed thread.
219
+ Delivering the path differs by transport: on MultiAgentV2, create the worktree BEFORE spawning
220
+ so the bootstrap carries it, or send it to an already-running member as a `followup_task`; on
221
+ Codex App, send a follow-up message that includes both the worktree path and the member's
222
+ `codex://threads/<thread_id>` link. Either way, run `bind-agent`/`bind-thread` with
223
+ `--cwd <worktree>` (or `--worktree-path`) so `team.json`, `guide.md`, `status`, and
224
+ `member-prompt` all point at the same worktree-backed member.
169
225
 
170
226
  When the member starts inside a worktree, it must verify the assigned cwd exists and contains the
171
227
  repository checkout before editing. If the directory is missing, empty, or does not look like a git
@@ -194,8 +250,11 @@ then delete the team state only after archival evidence is clean or preserved. A
194
250
  is never disbanded is a leak.
195
251
 
196
252
  - `archive` closes the team: notify each active member, copy anything useful into `artifacts/`,
197
- then try to archive each member thread with `codex_app.set_thread_archived`. Treat Codex App
198
- failures such as "Ambiguous Codex thread id" or a thread id that is ambiguous across hosts as an
253
+ then close each member on its transport. On MultiAgentV2, `interrupt_agent` any member still
254
+ mid-turn and record in the note that V2 exposes no runtime archive operation - the durable
255
+ `team.json` state IS the archive; never claim a V2 agent itself was archived. On Codex App,
256
+ try `codex_app.set_thread_archived` per member thread; treat failures such as
257
+ "Ambiguous Codex thread id" or an id that is ambiguous across hosts as an
199
258
  app-thread archival blocker, not as a team-state blocker: record the failure in the team log,
200
259
  tell the user which member thread was not proven archived, and continue the team-state archive
201
260
  with `archive --note "<blocker>"`. Never pretend a member thread was archived. Do not delete the
@@ -212,5 +271,6 @@ is never disbanded is a leak.
212
271
  - Stop and ask before deleting an unarchived team while any member is still active.
213
272
  - Member communication stays English unless the user explicitly requests otherwise; user-facing
214
273
  replies follow the user's language.
215
- - Stop if the requested operation needs Codex thread tools (create/read/send/title/archive) and
216
- they are unavailable; say so instead of faking it.
274
+ - Stop if the selected transport's tools (V2 spawn/message/wait/list/interrupt, or Codex App
275
+ create/read/send/title/archive) are unavailable or stop working; say so instead of faking it
276
+ or silently switching transports.
@@ -1,23 +1,57 @@
1
1
  // team-guide.mjs - render the member-facing field manual (guide.md) and the short
2
- // bootstrap trigger a new thread reads on startup. Pure string builders, no I/O.
2
+ // bootstrap trigger a new member reads on startup. Pure string builders, no I/O.
3
3
  //
4
4
  // The manual is the durable, two-channel replacement for per-prompt guidance: the leader
5
- // writes it once at team creation, and every member thread is told to READ it instead of
6
- // receiving the rules inline each turn.
5
+ // writes it once at team creation, and every member is told to READ it instead of
6
+ // receiving the rules inline each turn. Every rendered surface branches on the team's
7
+ // transport: multi_agent_v2 members are native agents addressed by agent path; codex_app
8
+ // members are app threads addressed by thread id.
9
+
10
+ import { isMultiAgentV2, LEADER_AGENT_PATH } from "./team-transport.mjs";
7
11
 
8
12
  export function codexThreadLink(threadId) {
9
13
  return `codex://threads/${threadId}`;
10
14
  }
11
15
 
12
- function memberLine(member) {
16
+ function transportLabel(team) {
17
+ return isMultiAgentV2(team)
18
+ ? "MultiAgentV2 (native agents: flat `spawn_agent` / `send_message` / `followup_task`)"
19
+ : "Codex App threads (`codex_app.*` tools)";
20
+ }
21
+
22
+ function memberEndpoint(member, v2) {
23
+ if (v2) {
24
+ return member.agentPath ? ` | task \`${member.taskName}\` | agent \`${member.agentPath}\`` : " | agent not spawned yet";
25
+ }
13
26
  const thread = member.threadId ? ` | thread ${member.threadId} (${codexThreadLink(member.threadId)})` : " | thread not created yet";
27
+ const title = member.threadTitle ? ` | thread title \`${member.threadTitle}\`` : "";
28
+ return `${title}${thread}`;
29
+ }
30
+
31
+ function memberLine(member, v2) {
14
32
  const wt = member.worktree?.path ? ` | worktree ${member.worktree.path}` : "";
15
33
  const name = member.name ? ` "${member.name}"` : "";
16
- const title = member.threadTitle ? ` | thread title \`${member.threadTitle}\`` : "";
17
- return `- **${member.id}**${name} (${member.lens}) - ${member.focus}${member.deliverable ? ` -> ${member.deliverable}` : ""}${title}${thread}${wt} [${member.status}]`;
34
+ return `- **${member.id}**${name} (${member.lens}) - ${member.focus}${member.deliverable ? ` -> ${member.deliverable}` : ""}${memberEndpoint(member, v2)}${wt} [${member.status}]`;
35
+ }
36
+
37
+ function worktreeMemberEndpoint(member, v2) {
38
+ if (v2) return member.agentPath ? `; agent \`${member.agentPath}\`` : "";
39
+ return member.threadId ? `; thread ${codexThreadLink(member.threadId)}` : "";
40
+ }
41
+
42
+ function worktreeReadinessNote(v2) {
43
+ if (v2) {
44
+ return `Your worktree is created by the leader BEFORE you spawn; the exact path is in your row
45
+ above and in your bootstrap. If the leader enables isolation mid-run, the new path arrives
46
+ as a \`followup_task\` - switch to it before your next edit.`;
47
+ }
48
+ return `If Codex returns only \`pendingWorktreeId\` while the leader is creating a worktree-backed member
49
+ thread, the thread is not ready yet. The leader must wait until Codex surfaces a real thread id,
50
+ then bind that real id and send the bootstrap.`;
18
51
  }
19
52
 
20
53
  function worktreeSection(team) {
54
+ const v2 = isMultiAgentV2(team);
21
55
  if (!team.worktree?.enabled) {
22
56
  return `## Worktrees
23
57
 
@@ -28,8 +62,8 @@ that is a coordination signal: mark yourself \`blocked\` and tell the leader at
28
62
  const lines = team.members
29
63
  .filter((m) => m.worktree?.path || m.worktree?.branch)
30
64
  .map((m) => {
31
- const thread = m.threadId ? `; thread ${codexThreadLink(m.threadId)}` : "";
32
- return `- **${m.id}**: worktree \`${m.worktree.path ?? "(assign with bind-thread --cwd)"}\` on branch \`${m.worktree.branch ?? team.worktree.baseBranch}\`${thread}`;
65
+ const bindHint = v2 ? "(assign with bind-agent --cwd)" : "(assign with bind-thread --cwd)";
66
+ return `- **${m.id}**: worktree \`${m.worktree.path ?? bindHint}\` on branch \`${m.worktree.branch ?? team.worktree.baseBranch}\`${worktreeMemberEndpoint(m, v2)}`;
33
67
  });
34
68
  return `## Worktrees (ISOLATION IS ON - this is not optional for you)
35
69
 
@@ -41,25 +75,48 @@ Before editing, verify that your assigned worktree exists and contains repo file
41
75
  missing, empty, or does not look like a git worktree/repository yet, send \`BLOCKED: worktree not ready\`
42
76
  to the leader and wait instead of editing any parent checkout or empty directory.
43
77
 
44
- If Codex returns only \`pendingWorktreeId\` while the leader is creating a worktree-backed member
45
- thread, the thread is not ready yet. The leader must wait until Codex surfaces a real thread id,
46
- then bind that real id and send the bootstrap.
78
+ ${worktreeReadinessNote(v2)}
47
79
 
48
- ${lines.length ? lines.join("\n") : "- (worktree paths are assigned as threads are bound; read team.json for yours)"}`;
80
+ ${lines.length ? lines.join("\n") : "- (worktree paths are assigned as members are bound; read team.json for yours)"}`;
81
+ }
82
+
83
+ function addressBookRules(team) {
84
+ if (isMultiAgentV2(team)) {
85
+ return `- **Reach the leader and your peers with \`send_message\` - not by narrating in your own
86
+ transcript, where no one reads it.** The address book is in team.json: the leader's target
87
+ is \`${LEADER_AGENT_PATH}\`, and each peer's target is its \`members[].agentPath\` (built from its
88
+ \`members[].taskName\`).
89
+ - **Use \`send_message\` for updates and \`followup_task\` only when handing a peer a NEW task**
90
+ that should wake it. Never invent an agent path - read it from team.json.`;
91
+ }
92
+ return `- **Reach the leader and your peers with \`codex_app.send_message_to_thread\` - not by narrating in
93
+ your own thread, where no one reads it.** The address book is in team.json: the leader thread id
94
+ is \`leader.sessionId\`, and each peer thread id is its \`members[].threadId\`.
95
+ - **When you mention a Codex thread, include its app link too:** \`codex://threads/<threadId>\`.
96
+ These links are the fastest way for the leader to reopen worktree-backed member threads.`;
97
+ }
98
+
99
+ function identityHeaderLine(team) {
100
+ if (isMultiAgentV2(team)) {
101
+ return `- Member identity convention: each member is the agent path \`${LEADER_AGENT_PATH}/<task name>\` - your row below shows yours; two members never share a task name`;
102
+ }
103
+ return `- Thread title convention: \`${team.threadTitleConvention}\` - each member's thread takes its OWN title from its name (your row below shows yours); two members never share a title`;
49
104
  }
50
105
 
51
106
  export function buildGuide(team) {
107
+ const v2 = isMultiAgentV2(team);
52
108
  const artifacts = team.paths?.artifacts ?? ".omo/teams/<session_id>/artifacts";
53
109
  const teamJson = team.paths?.team ?? ".omo/teams/<session_id>/team.json";
54
- const roster = team.members.length ? team.members.map(memberLine).join("\n") : "- (no members yet)";
110
+ const roster = team.members.length ? team.members.map((member) => memberLine(member, v2)).join("\n") : "- (no members yet)";
55
111
  return `# Team ${team.teamName} - Member Field Manual
56
112
 
57
113
  > Auto-generated by the teammode script. This file is the single source of truth for how
58
114
  > this team works. Re-read it whenever you are unsure - do not improvise the protocol.
59
115
 
60
116
  - Team: **${team.teamName}** (id \`${team.teamId}\`)
117
+ - Transport: **${transportLabel(team)}**
61
118
  - Team state: \`${teamJson}\`
62
- - Thread title convention: \`${team.threadTitleConvention}\` - each member's thread takes its OWN title from its name (your row below shows yours); two members never share a title
119
+ ${identityHeaderLine(team)}
63
120
 
64
121
  ## Who you are (your identity is fixed)
65
122
 
@@ -82,11 +139,7 @@ coordinate with each other, but the leader owns the final decision and integrati
82
139
  is mandatory regardless of the language the task was given in.
83
140
  - **Exception: when the END USER addresses you directly, reply in the user's own language.**
84
141
  Team-internal traffic stays English; user-facing replies match the user.
85
- - **Reach the leader and your peers with \`codex_app.send_message_to_thread\` - not by narrating in
86
- your own thread, where no one reads it.** The address book is in team.json: the leader thread id
87
- is \`leader.sessionId\`, and each peer thread id is its \`members[].threadId\`.
88
- - **When you mention a Codex thread, include its app link too:** \`codex://threads/<threadId>\`.
89
- These links are the fastest way for the leader to reopen worktree-backed member threads.
142
+ ${addressBookRules(team)}
90
143
  - **Push a short message at each of these moments - never batch them into one report at the end:**
91
144
  - to the **leader**: every finding or decision, every file or sub-task you finish, a
92
145
  \`WORKING: <focus> - <phase>\` heartbeat every few tool calls so you never look stale, a
@@ -116,6 +169,25 @@ Your slice is done only when (1) the deliverable exists, (2) you have evidence i
116
169
  (3) you have reported it to the leader. Until all three are true, keep going.`;
117
170
  }
118
171
 
172
+ function memberIdentityLine(team, member) {
173
+ if (isMultiAgentV2(team)) {
174
+ return `Your task name is \`${member.taskName}\` (agent path \`${member.agentPath}\`).`;
175
+ }
176
+ return `Your thread title is \`${member.threadTitle}\`.`;
177
+ }
178
+
179
+ function memberEndpointNote(team, member) {
180
+ if (isMultiAgentV2(team)) return "";
181
+ return member.threadId ? `\nYour Codex thread link is ${codexThreadLink(member.threadId)}. Include it when reporting handoffs or worktree status.` : "";
182
+ }
183
+
184
+ function pushInstruction(team) {
185
+ if (isMultiAgentV2(team)) {
186
+ return `Push updates to the leader (target \`${LEADER_AGENT_PATH}\`) and relevant peers (their team.json \`members[].agentPath\`) with \`send_message\` as you work`;
187
+ }
188
+ return "Push updates to the leader and relevant peers with `codex_app.send_message_to_thread` as you work";
189
+ }
190
+
119
191
  export function buildMemberPrompt(team, id) {
120
192
  const member = team.members.find((m) => m.id === id);
121
193
  if (!member) throw new Error(`no member with id "${id}"`);
@@ -126,14 +198,13 @@ export function buildMemberPrompt(team, id) {
126
198
  : team.worktree?.enabled
127
199
  ? "Wait for the leader to bind your worktree cwd before editing."
128
200
  : "Work from the repository root unless your manual assigns a worktree.";
129
- const threadLink = member.threadId ? `\nYour Codex thread link is ${codexThreadLink(member.threadId)}. Include it when reporting handoffs or worktree status.` : "";
130
201
  const readiness =
131
202
  team.worktree?.enabled
132
203
  ? "\nBefore editing, verify that your assigned worktree exists and contains repo files. If this prompt arrived before your Codex worktree checkout is ready, or the path is missing, empty, or not a git worktree/repository yet, report `BLOCKED: worktree not ready` to the leader and wait."
133
204
  : "";
134
- return `You are member ${member.id}${member.name ? ` (${member.name})` : ""} of team ${team.teamName} - owner of: ${member.focus}. Your thread title is \`${member.threadTitle}\`.
205
+ return `You are member ${member.id}${member.name ? ` (${member.name})` : ""} of team ${team.teamName} - owner of: ${member.focus}. ${memberIdentityLine(team, member)}
135
206
  FIRST read your field manual at \`${guide}\`, then the team state at \`${teamJson}\`; they define your scope, deliverable, the leader, the artifacts directory, and the communication rules.
136
- ${where}${threadLink}${readiness}
207
+ ${where}${memberEndpointNote(team, member)}${readiness}
137
208
  Communicate with the team and leader in English; reply to the end user in the user's own language.
138
- Start now. Push updates to the leader and relevant peers with \`codex_app.send_message_to_thread\` as you work - findings, \`WORKING:\` heartbeats, and \`BLOCKED:\` the instant you stall - never just one report at the end.`;
209
+ Start now. ${pushInstruction(team)} - findings, \`WORKING:\` heartbeats, and \`BLOCKED:\` the instant you stall - never just one report at the end.`;
139
210
  }