aicodeman 1.41.1 → 1.43.0

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 (276) hide show
  1. package/README.md +54 -24
  2. package/dist/claude-session-title.d.ts +6 -4
  3. package/dist/claude-session-title.d.ts.map +1 -1
  4. package/dist/claude-session-title.js +6 -4
  5. package/dist/claude-session-title.js.map +1 -1
  6. package/dist/cli-agent.js +1 -1
  7. package/dist/cli-agent.js.map +1 -1
  8. package/dist/config/cli-registry/patterns.d.ts +1 -1
  9. package/dist/config/cli-registry/patterns.d.ts.map +1 -1
  10. package/dist/config/cli-registry/patterns.js +3 -0
  11. package/dist/config/cli-registry/patterns.js.map +1 -1
  12. package/dist/config/cli-registry/schema.d.ts +3 -0
  13. package/dist/config/cli-registry/schema.d.ts.map +1 -1
  14. package/dist/config/cli-registry/schema.js +19 -3
  15. package/dist/config/cli-registry/schema.js.map +1 -1
  16. package/dist/config/cli-registry/stock.d.ts.map +1 -1
  17. package/dist/config/cli-registry/stock.js +302 -7
  18. package/dist/config/cli-registry/stock.js.map +1 -1
  19. package/dist/config/cli-registry/types.d.ts +37 -3
  20. package/dist/config/cli-registry/types.d.ts.map +1 -1
  21. package/dist/git-worktrees.d.ts +292 -0
  22. package/dist/git-worktrees.d.ts.map +1 -0
  23. package/dist/git-worktrees.js +791 -0
  24. package/dist/git-worktrees.js.map +1 -0
  25. package/dist/hooks-config.d.ts +9 -0
  26. package/dist/hooks-config.d.ts.map +1 -1
  27. package/dist/hooks-config.js +12 -0
  28. package/dist/hooks-config.js.map +1 -1
  29. package/dist/mcp-server.d.ts.map +1 -1
  30. package/dist/mcp-server.js +2 -1
  31. package/dist/mcp-server.js.map +1 -1
  32. package/dist/mcp-sync-targets.d.ts +6 -3
  33. package/dist/mcp-sync-targets.d.ts.map +1 -1
  34. package/dist/mcp-sync-targets.js +6 -3
  35. package/dist/mcp-sync-targets.js.map +1 -1
  36. package/dist/mux-interface.d.ts +7 -3
  37. package/dist/mux-interface.d.ts.map +1 -1
  38. package/dist/services/unified-session-service.d.ts +8 -0
  39. package/dist/services/unified-session-service.d.ts.map +1 -1
  40. package/dist/services/unified-session-service.js +21 -0
  41. package/dist/services/unified-session-service.js.map +1 -1
  42. package/dist/session-activity.d.ts +51 -0
  43. package/dist/session-activity.d.ts.map +1 -1
  44. package/dist/session-activity.js +62 -0
  45. package/dist/session-activity.js.map +1 -1
  46. package/dist/session-cli-registry-bridge.d.ts +2 -1
  47. package/dist/session-cli-registry-bridge.d.ts.map +1 -1
  48. package/dist/session-cli-registry-bridge.js.map +1 -1
  49. package/dist/session-submit-verifier.js +1 -1
  50. package/dist/session.d.ts +84 -9
  51. package/dist/session.d.ts.map +1 -1
  52. package/dist/session.js +232 -18
  53. package/dist/session.js.map +1 -1
  54. package/dist/tmux-manager.d.ts +62 -7
  55. package/dist/tmux-manager.d.ts.map +1 -1
  56. package/dist/tmux-manager.js +98 -20
  57. package/dist/tmux-manager.js.map +1 -1
  58. package/dist/types/session.d.ts +32 -4
  59. package/dist/types/session.d.ts.map +1 -1
  60. package/dist/types/session.js +2 -1
  61. package/dist/types/session.js.map +1 -1
  62. package/dist/utils/cli-installed-probes.d.ts +1 -1
  63. package/dist/utils/cli-installed-probes.d.ts.map +1 -1
  64. package/dist/utils/cli-installed-probes.js +4 -2
  65. package/dist/utils/cli-installed-probes.js.map +1 -1
  66. package/dist/utils/copilot-cli-resolver.d.ts +48 -0
  67. package/dist/utils/copilot-cli-resolver.d.ts.map +1 -0
  68. package/dist/utils/copilot-cli-resolver.js +112 -0
  69. package/dist/utils/copilot-cli-resolver.js.map +1 -0
  70. package/dist/utils/deepseek-cli-resolver.d.ts.map +1 -1
  71. package/dist/utils/deepseek-cli-resolver.js +1 -1
  72. package/dist/utils/deepseek-cli-resolver.js.map +1 -1
  73. package/dist/utils/index.d.ts +1 -0
  74. package/dist/utils/index.d.ts.map +1 -1
  75. package/dist/utils/index.js +1 -0
  76. package/dist/utils/index.js.map +1 -1
  77. package/dist/web/approval-inbox.d.ts +12 -2
  78. package/dist/web/approval-inbox.d.ts.map +1 -1
  79. package/dist/web/approval-inbox.js +7 -2
  80. package/dist/web/approval-inbox.js.map +1 -1
  81. package/dist/web/case-path.d.ts +4 -2
  82. package/dist/web/case-path.d.ts.map +1 -1
  83. package/dist/web/case-path.js +13 -4
  84. package/dist/web/case-path.js.map +1 -1
  85. package/dist/web/public/admin-ui.js.gz +0 -0
  86. package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
  87. package/dist/web/public/app.ae50029a.js +43 -0
  88. package/dist/web/public/app.ae50029a.js.br +0 -0
  89. package/dist/web/public/app.ae50029a.js.gz +0 -0
  90. package/dist/web/public/approvals-ui.js.gz +0 -0
  91. package/dist/web/public/{constants.17d77b65.js → constants.e5e588db.js} +156 -2
  92. package/dist/web/public/constants.e5e588db.js.br +0 -0
  93. package/dist/web/public/constants.e5e588db.js.gz +0 -0
  94. package/dist/web/public/cron-ui.js.gz +0 -0
  95. package/dist/web/public/entrance-animations.js.gz +0 -0
  96. package/dist/web/public/git-status-ui.js.gz +0 -0
  97. package/dist/web/public/home-sessions.js.gz +0 -0
  98. package/dist/web/public/host-wake-ui.js.gz +0 -0
  99. package/dist/web/public/i18n.8f291f06.js +2 -0
  100. package/dist/web/public/i18n.8f291f06.js.br +0 -0
  101. package/dist/web/public/i18n.8f291f06.js.gz +0 -0
  102. package/dist/web/public/{image-input.9ed1d0d2.js → image-input.941386e7.js} +41 -22
  103. package/dist/web/public/image-input.941386e7.js.br +0 -0
  104. package/dist/web/public/image-input.941386e7.js.gz +0 -0
  105. package/dist/web/public/index.html +88 -16
  106. package/dist/web/public/index.html.br +0 -0
  107. package/dist/web/public/index.html.gz +0 -0
  108. package/dist/web/public/input-cjk.8bc46081.js.gz +0 -0
  109. package/dist/web/public/{keyboard-accessory.c458eea8.js → keyboard-accessory.c283e827.js} +40 -29
  110. package/dist/web/public/keyboard-accessory.c283e827.js.br +0 -0
  111. package/dist/web/public/keyboard-accessory.c283e827.js.gz +0 -0
  112. package/dist/web/public/mobile-handlers.0ef9c311.js.gz +0 -0
  113. package/dist/web/public/mobile-ime-preview.2dbaf262.js.gz +0 -0
  114. package/dist/web/public/mobile-overview.js +1 -0
  115. package/dist/web/public/mobile-overview.js.br +0 -0
  116. package/dist/web/public/mobile-overview.js.gz +0 -0
  117. package/dist/web/public/mobile.13514863.css +1 -0
  118. package/dist/web/public/mobile.13514863.css.br +0 -0
  119. package/dist/web/public/mobile.13514863.css.gz +0 -0
  120. package/dist/web/public/notification-manager.feb82c04.js.gz +0 -0
  121. package/dist/web/public/orchestrator-panel.js.gz +0 -0
  122. package/dist/web/public/{panels-ui.73ec0137.js → panels-ui.b7bfb9da.js} +6 -6
  123. package/dist/web/public/panels-ui.b7bfb9da.js.br +0 -0
  124. package/dist/web/public/panels-ui.b7bfb9da.js.gz +0 -0
  125. package/dist/web/public/ralph-panel.b350e2ef.js.gz +0 -0
  126. package/dist/web/public/ralph-wizard.b6c0dd19.js.gz +0 -0
  127. package/dist/web/public/readmymind-ui.js.gz +0 -0
  128. package/dist/web/public/reboot-restore-ui.js.gz +0 -0
  129. package/dist/web/public/{respawn-ui.ff0dae4c.js → respawn-ui.d7adcf6a.js} +1 -1
  130. package/dist/web/public/respawn-ui.d7adcf6a.js.br +0 -0
  131. package/dist/web/public/respawn-ui.d7adcf6a.js.gz +0 -0
  132. package/dist/web/public/sanitize-html.e7147e76.js.gz +0 -0
  133. package/dist/web/public/security-notices.json +21 -0
  134. package/dist/web/public/session-lineage.js.gz +0 -0
  135. package/dist/web/public/session-ui.be076c88.js +100 -0
  136. package/dist/web/public/session-ui.be076c88.js.br +0 -0
  137. package/dist/web/public/session-ui.be076c88.js.gz +0 -0
  138. package/dist/web/public/settings-ui.fc4cc50a.js +97 -0
  139. package/dist/web/public/settings-ui.fc4cc50a.js.br +0 -0
  140. package/dist/web/public/settings-ui.fc4cc50a.js.gz +0 -0
  141. package/dist/web/public/spreadsheet-preview-worker.js.gz +0 -0
  142. package/dist/web/public/spreadsheet-preview.75c751de.js.gz +0 -0
  143. package/dist/web/public/spreadsheet-xlsx-core.js.gz +0 -0
  144. package/dist/web/public/styles.dcfa907f.css +1 -0
  145. package/dist/web/public/styles.dcfa907f.css.br +0 -0
  146. package/dist/web/public/styles.dcfa907f.css.gz +0 -0
  147. package/dist/web/public/subagent-windows.07277a58.js.gz +0 -0
  148. package/dist/web/public/sw.js +2 -2
  149. package/dist/web/public/sw.js.br +0 -0
  150. package/dist/web/public/sw.js.gz +0 -0
  151. package/dist/web/public/tab-layout-browser.2d6189f7.js.gz +0 -0
  152. package/dist/web/public/tab-rail-resize.7157e0bd.js.gz +0 -0
  153. package/dist/web/public/terminal-keycode229-recovery.af09f99a.js.gz +0 -0
  154. package/dist/web/public/terminal-split.js.gz +0 -0
  155. package/dist/web/public/terminal-tile.js +1 -0
  156. package/dist/web/public/terminal-tile.js.br +0 -0
  157. package/dist/web/public/terminal-tile.js.gz +0 -0
  158. package/dist/web/public/terminal-ui.ae01a7d1.js +2 -0
  159. package/dist/web/public/terminal-ui.ae01a7d1.js.br +0 -0
  160. package/dist/web/public/terminal-ui.ae01a7d1.js.gz +0 -0
  161. package/dist/web/public/tile-grid.js +3 -6
  162. package/dist/web/public/tile-grid.js.br +0 -0
  163. package/dist/web/public/tile-grid.js.gz +0 -0
  164. package/dist/web/public/ultracode-panel.js.gz +0 -0
  165. package/dist/web/public/ultracode-windows.js.gz +0 -0
  166. package/dist/web/public/vendor/dompurify.min.js.gz +0 -0
  167. package/dist/web/public/vendor/exceljs.min.js.gz +0 -0
  168. package/dist/web/public/vendor/fflate.min.js.gz +0 -0
  169. package/dist/web/public/vendor/marked.min.js.gz +0 -0
  170. package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
  171. package/dist/web/public/vendor/xterm-addon-serialize.min.js.gz +0 -0
  172. package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
  173. package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
  174. package/dist/web/public/vendor/xterm-predictive-echo.ae5e3d5d.js.gz +0 -0
  175. package/dist/web/public/vendor/xterm-zerolag-input.0b69623c.js.gz +0 -0
  176. package/dist/web/public/vendor/xterm.css.gz +0 -0
  177. package/dist/web/public/vendor/xterm.min.js.gz +0 -0
  178. package/dist/web/public/voice-input.2342c37b.js.gz +0 -0
  179. package/dist/web/public/voice-pcm-worklet.js.gz +0 -0
  180. package/dist/web/public/webview-tabs.js.gz +0 -0
  181. package/dist/web/public/whats-new.json +13 -0
  182. package/dist/web/response-viewer-transcript.d.ts +6 -0
  183. package/dist/web/response-viewer-transcript.d.ts.map +1 -1
  184. package/dist/web/response-viewer-transcript.js +134 -1
  185. package/dist/web/response-viewer-transcript.js.map +1 -1
  186. package/dist/web/routes/approval-routes.d.ts.map +1 -1
  187. package/dist/web/routes/approval-routes.js +12 -8
  188. package/dist/web/routes/approval-routes.js.map +1 -1
  189. package/dist/web/routes/case-routes.d.ts.map +1 -1
  190. package/dist/web/routes/case-routes.js +9 -2
  191. package/dist/web/routes/case-routes.js.map +1 -1
  192. package/dist/web/routes/index.d.ts +1 -0
  193. package/dist/web/routes/index.d.ts.map +1 -1
  194. package/dist/web/routes/index.js +1 -0
  195. package/dist/web/routes/index.js.map +1 -1
  196. package/dist/web/routes/mcp-sync-routes.d.ts +4 -4
  197. package/dist/web/routes/mcp-sync-routes.js +4 -4
  198. package/dist/web/routes/ralph-routes.d.ts.map +1 -1
  199. package/dist/web/routes/ralph-routes.js +19 -14
  200. package/dist/web/routes/ralph-routes.js.map +1 -1
  201. package/dist/web/routes/session-routes.d.ts +19 -7
  202. package/dist/web/routes/session-routes.d.ts.map +1 -1
  203. package/dist/web/routes/session-routes.js +227 -66
  204. package/dist/web/routes/session-routes.js.map +1 -1
  205. package/dist/web/routes/status-telemetry-routes.d.ts.map +1 -1
  206. package/dist/web/routes/status-telemetry-routes.js +9 -5
  207. package/dist/web/routes/status-telemetry-routes.js.map +1 -1
  208. package/dist/web/routes/system-routes.d.ts +9 -0
  209. package/dist/web/routes/system-routes.d.ts.map +1 -1
  210. package/dist/web/routes/system-routes.js +102 -12
  211. package/dist/web/routes/system-routes.js.map +1 -1
  212. package/dist/web/routes/worktree-routes.d.ts +52 -0
  213. package/dist/web/routes/worktree-routes.d.ts.map +1 -0
  214. package/dist/web/routes/worktree-routes.js +220 -0
  215. package/dist/web/routes/worktree-routes.js.map +1 -0
  216. package/dist/web/schemas.d.ts +30 -1
  217. package/dist/web/schemas.d.ts.map +1 -1
  218. package/dist/web/schemas.js +74 -3
  219. package/dist/web/schemas.js.map +1 -1
  220. package/dist/web/screen-blocked.d.ts +80 -0
  221. package/dist/web/screen-blocked.d.ts.map +1 -0
  222. package/dist/web/screen-blocked.js +106 -0
  223. package/dist/web/screen-blocked.js.map +1 -0
  224. package/dist/web/server.d.ts.map +1 -1
  225. package/dist/web/server.js +23 -2
  226. package/dist/web/server.js.map +1 -1
  227. package/dist/web/session-listener-wiring.d.ts +1 -0
  228. package/dist/web/session-listener-wiring.d.ts.map +1 -1
  229. package/dist/web/session-listener-wiring.js +20 -0
  230. package/dist/web/session-listener-wiring.js.map +1 -1
  231. package/dist/web/session-wait-registry.d.ts +27 -9
  232. package/dist/web/session-wait-registry.d.ts.map +1 -1
  233. package/dist/web/session-wait-registry.js +36 -13
  234. package/dist/web/session-wait-registry.js.map +1 -1
  235. package/dist/web/sse-events.d.ts +7 -2
  236. package/dist/web/sse-events.d.ts.map +1 -1
  237. package/dist/web/sse-events.js +7 -2
  238. package/dist/web/sse-events.js.map +1 -1
  239. package/package.json +2 -2
  240. package/skills/codeman/SKILL.md +21 -17
  241. package/skills/codeman/preamble.sh +14 -11
  242. package/skills/codeman/reference/endpoints.md +8 -8
  243. package/skills/codeman/reference/messaging.md +5 -5
  244. package/skills/codeman/reference/recipes.md +13 -10
  245. package/skills/codeman/reference/verbs.md +7 -5
  246. package/dist/web/public/app.24689381.js +0 -43
  247. package/dist/web/public/app.24689381.js.br +0 -0
  248. package/dist/web/public/app.24689381.js.gz +0 -0
  249. package/dist/web/public/constants.17d77b65.js.br +0 -0
  250. package/dist/web/public/constants.17d77b65.js.gz +0 -0
  251. package/dist/web/public/i18n.9afd8e4d.js +0 -2
  252. package/dist/web/public/i18n.9afd8e4d.js.br +0 -0
  253. package/dist/web/public/i18n.9afd8e4d.js.gz +0 -0
  254. package/dist/web/public/image-input.9ed1d0d2.js.br +0 -0
  255. package/dist/web/public/image-input.9ed1d0d2.js.gz +0 -0
  256. package/dist/web/public/keyboard-accessory.c458eea8.js.br +0 -0
  257. package/dist/web/public/keyboard-accessory.c458eea8.js.gz +0 -0
  258. package/dist/web/public/mobile.2dff1580.css +0 -1
  259. package/dist/web/public/mobile.2dff1580.css.br +0 -0
  260. package/dist/web/public/mobile.2dff1580.css.gz +0 -0
  261. package/dist/web/public/panels-ui.73ec0137.js.br +0 -0
  262. package/dist/web/public/panels-ui.73ec0137.js.gz +0 -0
  263. package/dist/web/public/respawn-ui.ff0dae4c.js.br +0 -0
  264. package/dist/web/public/respawn-ui.ff0dae4c.js.gz +0 -0
  265. package/dist/web/public/session-ui.dbc6819b.js +0 -100
  266. package/dist/web/public/session-ui.dbc6819b.js.br +0 -0
  267. package/dist/web/public/session-ui.dbc6819b.js.gz +0 -0
  268. package/dist/web/public/settings-ui.81ac264e.js +0 -97
  269. package/dist/web/public/settings-ui.81ac264e.js.br +0 -0
  270. package/dist/web/public/settings-ui.81ac264e.js.gz +0 -0
  271. package/dist/web/public/styles.900a28e4.css +0 -1
  272. package/dist/web/public/styles.900a28e4.css.br +0 -0
  273. package/dist/web/public/styles.900a28e4.css.gz +0 -0
  274. package/dist/web/public/terminal-ui.858f5da5.js +0 -2
  275. package/dist/web/public/terminal-ui.858f5da5.js.br +0 -0
  276. package/dist/web/public/terminal-ui.858f5da5.js.gz +0 -0
@@ -70,7 +70,7 @@ later call opens with, and your first REAL call performs them anyway:
70
70
 
71
71
  ```bash
72
72
  . "${XDG_CACHE_HOME:-$HOME/.cache}/codeman-agent-$CODEMAN_SESSION_ID.sh" 2>/dev/null
73
- [ "${CODEMAN_PREAMBLE:-}" = 1.33.4 ] || { echo "preamble missing or stale; run the full §0 block"; exit 1; }
73
+ [ "${CODEMAN_PREAMBLE:-}" = 1.42.0 ] || { echo "preamble missing or stale; run the full §0 block"; exit 1; }
74
74
  ```
75
75
 
76
76
  ⚠️ **Never spend a Bash call on this check alone.** §1's block opens with this same
@@ -98,8 +98,11 @@ PRE="${XDG_CACHE_HOME:-$HOME/.cache}/codeman-agent-$CODEMAN_SESSION_ID.sh"
98
98
  mkdir -p "$(dirname "$PRE")"
99
99
  # Rewrite unless the file already ends with THIS version's stamp, so a stale or a
100
100
  # half-written file self-heals here instead of costing you a round trip to rm it.
101
- grep -qs '^CODEMAN_PREAMBLE=1.33.4$' "$PRE" || (umask 077; cat > "$PRE" <<'PREAMBLE'
102
- # ---- Codeman agent preamble 1.33.4 (seeded by Codeman at session spawn; the SKILL.md §0 bootstrap rewrites it when missing or stale) ----
101
+ grep -qs '^CODEMAN_PREAMBLE=1.42.0$' "$PRE" || (umask 077; cat > "$PRE" <<'PREAMBLE'
102
+ # ---- Codeman agent preamble 1.42.0 (seeded by Codeman at session spawn; the SKILL.md §0 bootstrap rewrites it when missing or stale) ----
103
+ # Positional parameters are always written with braces, ${1} and never a bare dollar-digit: Claude Code
104
+ # replaces a bare one in a skill body with the matching word of the skill's arguments, and §0 is pasted
105
+ # from that body (test/agent-skill.test.ts pins it).
103
106
  API="${CODEMAN_API_URL:?CODEMAN_API_URL not set; refusing to guess}"
104
107
  SELF="${CODEMAN_SESSION_ID:?CODEMAN_SESSION_ID not set}"
105
108
  # Credentials, cheapest first. Your session has usually INHERITED the server's
@@ -108,7 +111,7 @@ SELF="${CODEMAN_SESSION_ID:?CODEMAN_SESSION_ID not set}"
108
111
  # reads. The data dir is wherever the hook-secret file lives. Values may be
109
112
  # quoted or `export`-prefixed.
110
113
  ENV_FILE="${CODEMAN_HOOK_SECRET_FILE:+${CODEMAN_HOOK_SECRET_FILE%hook-secret}.env}"
111
- envval() { sed -n "s/^\(export \)\{0,1\}$1=//p" "$ENV_FILE" | tail -1 | sed 's/^"\(.*\)"$/\1/; s/^'\''\(.*\)'\''$/\1/'; }
114
+ envval() { sed -n "s/^\(export \)\{0,1\}${1}=//p" "$ENV_FILE" | tail -1 | sed 's/^"\(.*\)"$/\1/; s/^'\''\(.*\)'\''$/\1/'; }
112
115
  if [ -z "${CODEMAN_PASSWORD:-}" ] && [ -n "$ENV_FILE" ] && [ -f "$ENV_FILE" ]; then
113
116
  CODEMAN_USERNAME=$(envval CODEMAN_USERNAME)
114
117
  CODEMAN_PASSWORD=$(envval CODEMAN_PASSWORD)
@@ -143,15 +146,15 @@ delete_session() {
143
146
 
144
147
  # ---- fast path: the four verbs, already written. §1 composes them. ----
145
148
  _composer_up() { # <sid> <timeoutMs> -> "true"/"false". `shift+tab` is the one token
146
- "${CURL[@]}" -G "$API/api/v1/sessions/$1/wait-output" \
149
+ "${CURL[@]}" -G "$API/api/v1/sessions/${1}/wait-output" \
147
150
  --data-urlencode 'match=shift+tab' --data-urlencode 'from=buffer' \
148
- --data-urlencode "timeout=$2" | jq -r '.data.wait.matched // false'
151
+ --data-urlencode "timeout=${2}" | jq -r '.data.wait.matched // false'
149
152
  }
150
153
  _dsh_up() { # <sid> <timeoutMs> -> "true"/"false". The DeepSeek Harness TUI's
151
154
  # composer glyph. Override with DSH_READY_MARK for a profile that draws another one.
152
- "${CURL[@]}" -G "$API/api/v1/sessions/$1/wait-output" \
155
+ "${CURL[@]}" -G "$API/api/v1/sessions/${1}/wait-output" \
153
156
  --data-urlencode "match=${DSH_READY_MARK:-❯}" --data-urlencode 'from=buffer' \
154
- --data-urlencode "timeout=$2" | jq -r '.data.wait.matched // false'
157
+ --data-urlencode "timeout=${2}" | jq -r '.data.wait.matched // false'
155
158
  }
156
159
  # ---- the workspace-trust dialog: READ the screen, never press Enter blind ----
157
160
  # Claude Code 2.1.252 dropped the option numbers, REVERSED them, and highlights
@@ -167,7 +170,7 @@ _trust_key() { # <sid> -> "confirm" | "move" | "" (nothing safe to press)
167
170
  # full=1 returns the RENDERED pane; a claude pane keeps no tmux history, so that
168
171
  # is the current frame rather than every repaint since launch. tail -1 anyway,
169
172
  # because the freshest marked row is the only one still true.
170
- "${CURL[@]}" -G "$API/api/v1/sessions/$1/terminal" --data-urlencode 'full=1' \
173
+ "${CURL[@]}" -G "$API/api/v1/sessions/${1}/terminal" --data-urlencode 'full=1' \
171
174
  | jq -r '.data.terminalBuffer // empty' \
172
175
  | sed -e "s/$(printf '\033')\[[0-9;?]*[a-zA-Z]//g" -e "s/$(printf '\033')[()][AB0]//g" \
173
176
  | tr -d ' \t' | grep -i '❯[0-9.]*\(yes,itrustthisfolder\|no,exit\)' | tail -1 \
@@ -185,7 +188,7 @@ _composer_text() { # <sid> -> the composer's text with ALL whitespace removed: "
185
188
  # the LAST `❯` line: Claude Code echoes a submitted prompt with the same glyph higher
186
189
  # up in the transcript, so only the last one says whether the text was taken.
187
190
  local t
188
- t=$("${CURL[@]}" -G "$API/api/v1/sessions/$1/terminal" --data-urlencode 'full=1' \
191
+ t=$("${CURL[@]}" -G "$API/api/v1/sessions/${1}/terminal" --data-urlencode 'full=1' \
189
192
  | jq -r '.data.terminalBuffer // empty' \
190
193
  | sed -e "s/$(printf '\033')\[[0-9;?]*[a-zA-Z]//g" -e "s/$(printf '\033')[()][AB0]//g" \
191
194
  | tr -d '\r' | grep -a '^[[:space:]]*❯' | tail -1)
@@ -195,7 +198,7 @@ _composer_text() { # <sid> -> the composer's text with ALL whitespace removed: "
195
198
  printf '%s' "$t" | sed 's/^[[:space:]]*❯//' | tr -d '[:space:]' | sed "s/$(printf '\302\240')//g"
196
199
  }
197
200
  _accept_trust() { # <sid> -> 0 once it has answered the dialog, 1 if it could not
198
- local sid="$1" k i=1
201
+ local sid="${1}" k i=1
199
202
  while [ "$i" -le 6 ]; do
200
203
  k=$(_trust_key "$sid")
201
204
  [ -n "$k" ] || return 1 # no dialog on screen, or a layout this cannot read
@@ -396,7 +399,7 @@ sendwait() {
396
399
  last_text() {
397
400
  local t="" prev="${2:-}"
398
401
  for _ in $(seq 1 15); do
399
- t=$("${CURL[@]}" "$API/api/v1/sessions/$1/last-response" | jq -r '.data.text // empty')
402
+ t=$("${CURL[@]}" "$API/api/v1/sessions/${1}/last-response" | jq -r '.data.text // empty')
400
403
  [ -n "$t" ] && [ "$t" != "$prev" ] && { printf '%s\n' "$t"; return 0; }
401
404
  sleep 1
402
405
  done
@@ -407,10 +410,10 @@ last_text() {
407
410
  # The stamp is the LAST line on purpose (a truncated write leaves it unset) and is kept
408
411
  # bare on purpose: the write condition above anchors on it with $, so an inline comment
409
412
  # here would fail that match and rewrite this file on every single bootstrap.
410
- CODEMAN_PREAMBLE=1.33.4
413
+ CODEMAN_PREAMBLE=1.42.0
411
414
  PREAMBLE
412
415
  )
413
- . "$PRE"; [ "${CODEMAN_PREAMBLE:-}" = 1.33.4 ] || { echo "preamble at $PRE is stale or truncated: rm it and re-run this block"; exit 1; }
416
+ . "$PRE"; [ "${CODEMAN_PREAMBLE:-}" = 1.42.0 ] || { echo "preamble at $PRE is stale or truncated: rm it and re-run this block"; exit 1; }
414
417
  ```
415
418
 
416
419
  Every later Bash call that touches the API starts with the same two loader lines from
@@ -461,7 +464,7 @@ and no per-call body to hand-build.
461
464
 
462
465
  ```bash
463
466
  . "${XDG_CACHE_HOME:-$HOME/.cache}/codeman-agent-$CODEMAN_SESSION_ID.sh" 2>/dev/null # §0 loader
464
- [ "${CODEMAN_PREAMBLE:-}" = 1.33.4 ] || { echo "preamble missing or stale; run the full §0 block"; exit 1; }
467
+ [ "${CODEMAN_PREAMBLE:-}" = 1.42.0 ] || { echo "preamble missing or stale; run the full §0 block"; exit 1; }
465
468
  N=(alpha beta) # INVENT one fresh case name per worker; never list cases first
466
469
  # (a name may carry a mode: `beta:deepseek`, see below)
467
470
  T=('reply with one line: the absolute path of your working directory'
@@ -549,8 +552,9 @@ That is true of no other non-claude mode, and it is worth knowing why: the DeepS
549
552
  Harness TUI reports `idle`/`working`/`blocked` to Codeman over the supervisor contract it
550
553
  implements, so dsh is the one external CLI with definitive `stop`/`blocked` signals
551
554
  instead of guessed-from-silence ones — and it writes a structured transcript, which is
552
- what `last-response` reads for it. `shell`, `opencode`, `codex`, `gemini`, `antigravity`,
553
- `pi`, `grok` and `omp` have neither and still need markers ([§5.5](reference/verbs.md#55-markers-for-hook-less-workers)).
555
+ what `last-response` reads for it. `shell`, `opencode`, `gemini`, `antigravity`, `pi`,
556
+ `grok`, `omp` and `copilot` have neither, and `codex` has a transcript and a screen-read `blocked` but
557
+ no `stop`, so all of them still need markers ([§5.5](reference/verbs.md#55-markers-for-hook-less-workers)).
554
558
 
555
559
  Three things to know before you spawn one:
556
560
 
@@ -1,4 +1,7 @@
1
- # ---- Codeman agent preamble 1.33.4 (seeded by Codeman at session spawn; the SKILL.md §0 bootstrap rewrites it when missing or stale) ----
1
+ # ---- Codeman agent preamble 1.42.0 (seeded by Codeman at session spawn; the SKILL.md §0 bootstrap rewrites it when missing or stale) ----
2
+ # Positional parameters are always written with braces, ${1} and never a bare dollar-digit: Claude Code
3
+ # replaces a bare one in a skill body with the matching word of the skill's arguments, and §0 is pasted
4
+ # from that body (test/agent-skill.test.ts pins it).
2
5
  API="${CODEMAN_API_URL:?CODEMAN_API_URL not set; refusing to guess}"
3
6
  SELF="${CODEMAN_SESSION_ID:?CODEMAN_SESSION_ID not set}"
4
7
  # Credentials, cheapest first. Your session has usually INHERITED the server's
@@ -7,7 +10,7 @@ SELF="${CODEMAN_SESSION_ID:?CODEMAN_SESSION_ID not set}"
7
10
  # reads. The data dir is wherever the hook-secret file lives. Values may be
8
11
  # quoted or `export`-prefixed.
9
12
  ENV_FILE="${CODEMAN_HOOK_SECRET_FILE:+${CODEMAN_HOOK_SECRET_FILE%hook-secret}.env}"
10
- envval() { sed -n "s/^\(export \)\{0,1\}$1=//p" "$ENV_FILE" | tail -1 | sed 's/^"\(.*\)"$/\1/; s/^'\''\(.*\)'\''$/\1/'; }
13
+ envval() { sed -n "s/^\(export \)\{0,1\}${1}=//p" "$ENV_FILE" | tail -1 | sed 's/^"\(.*\)"$/\1/; s/^'\''\(.*\)'\''$/\1/'; }
11
14
  if [ -z "${CODEMAN_PASSWORD:-}" ] && [ -n "$ENV_FILE" ] && [ -f "$ENV_FILE" ]; then
12
15
  CODEMAN_USERNAME=$(envval CODEMAN_USERNAME)
13
16
  CODEMAN_PASSWORD=$(envval CODEMAN_PASSWORD)
@@ -42,15 +45,15 @@ delete_session() {
42
45
 
43
46
  # ---- fast path: the four verbs, already written. §1 composes them. ----
44
47
  _composer_up() { # <sid> <timeoutMs> -> "true"/"false". `shift+tab` is the one token
45
- "${CURL[@]}" -G "$API/api/v1/sessions/$1/wait-output" \
48
+ "${CURL[@]}" -G "$API/api/v1/sessions/${1}/wait-output" \
46
49
  --data-urlencode 'match=shift+tab' --data-urlencode 'from=buffer' \
47
- --data-urlencode "timeout=$2" | jq -r '.data.wait.matched // false'
50
+ --data-urlencode "timeout=${2}" | jq -r '.data.wait.matched // false'
48
51
  }
49
52
  _dsh_up() { # <sid> <timeoutMs> -> "true"/"false". The DeepSeek Harness TUI's
50
53
  # composer glyph. Override with DSH_READY_MARK for a profile that draws another one.
51
- "${CURL[@]}" -G "$API/api/v1/sessions/$1/wait-output" \
54
+ "${CURL[@]}" -G "$API/api/v1/sessions/${1}/wait-output" \
52
55
  --data-urlencode "match=${DSH_READY_MARK:-❯}" --data-urlencode 'from=buffer' \
53
- --data-urlencode "timeout=$2" | jq -r '.data.wait.matched // false'
56
+ --data-urlencode "timeout=${2}" | jq -r '.data.wait.matched // false'
54
57
  }
55
58
  # ---- the workspace-trust dialog: READ the screen, never press Enter blind ----
56
59
  # Claude Code 2.1.252 dropped the option numbers, REVERSED them, and highlights
@@ -66,7 +69,7 @@ _trust_key() { # <sid> -> "confirm" | "move" | "" (nothing safe to press)
66
69
  # full=1 returns the RENDERED pane; a claude pane keeps no tmux history, so that
67
70
  # is the current frame rather than every repaint since launch. tail -1 anyway,
68
71
  # because the freshest marked row is the only one still true.
69
- "${CURL[@]}" -G "$API/api/v1/sessions/$1/terminal" --data-urlencode 'full=1' \
72
+ "${CURL[@]}" -G "$API/api/v1/sessions/${1}/terminal" --data-urlencode 'full=1' \
70
73
  | jq -r '.data.terminalBuffer // empty' \
71
74
  | sed -e "s/$(printf '\033')\[[0-9;?]*[a-zA-Z]//g" -e "s/$(printf '\033')[()][AB0]//g" \
72
75
  | tr -d ' \t' | grep -i '❯[0-9.]*\(yes,itrustthisfolder\|no,exit\)' | tail -1 \
@@ -84,7 +87,7 @@ _composer_text() { # <sid> -> the composer's text with ALL whitespace removed: "
84
87
  # the LAST `❯` line: Claude Code echoes a submitted prompt with the same glyph higher
85
88
  # up in the transcript, so only the last one says whether the text was taken.
86
89
  local t
87
- t=$("${CURL[@]}" -G "$API/api/v1/sessions/$1/terminal" --data-urlencode 'full=1' \
90
+ t=$("${CURL[@]}" -G "$API/api/v1/sessions/${1}/terminal" --data-urlencode 'full=1' \
88
91
  | jq -r '.data.terminalBuffer // empty' \
89
92
  | sed -e "s/$(printf '\033')\[[0-9;?]*[a-zA-Z]//g" -e "s/$(printf '\033')[()][AB0]//g" \
90
93
  | tr -d '\r' | grep -a '^[[:space:]]*❯' | tail -1)
@@ -94,7 +97,7 @@ _composer_text() { # <sid> -> the composer's text with ALL whitespace removed: "
94
97
  printf '%s' "$t" | sed 's/^[[:space:]]*❯//' | tr -d '[:space:]' | sed "s/$(printf '\302\240')//g"
95
98
  }
96
99
  _accept_trust() { # <sid> -> 0 once it has answered the dialog, 1 if it could not
97
- local sid="$1" k i=1
100
+ local sid="${1}" k i=1
98
101
  while [ "$i" -le 6 ]; do
99
102
  k=$(_trust_key "$sid")
100
103
  [ -n "$k" ] || return 1 # no dialog on screen, or a layout this cannot read
@@ -295,7 +298,7 @@ sendwait() {
295
298
  last_text() {
296
299
  local t="" prev="${2:-}"
297
300
  for _ in $(seq 1 15); do
298
- t=$("${CURL[@]}" "$API/api/v1/sessions/$1/last-response" | jq -r '.data.text // empty')
301
+ t=$("${CURL[@]}" "$API/api/v1/sessions/${1}/last-response" | jq -r '.data.text // empty')
299
302
  [ -n "$t" ] && [ "$t" != "$prev" ] && { printf '%s\n' "$t"; return 0; }
300
303
  sleep 1
301
304
  done
@@ -306,4 +309,4 @@ last_text() {
306
309
  # The stamp is the LAST line on purpose (a truncated write leaves it unset) and is kept
307
310
  # bare on purpose: the write condition above anchors on it with $, so an inline comment
308
311
  # here would fail that match and rewrite this file on every single bootstrap.
309
- CODEMAN_PREAMBLE=1.33.4
312
+ CODEMAN_PREAMBLE=1.42.0
@@ -237,7 +237,7 @@ minutes, never retry the credential.
237
237
  flushed slightly *after* the `stop` hook fires, so a read taken the instant the wait
238
238
  returns is too early (verified live: empty on the first call, full prose seconds later).
239
239
  It is also `""` before the worker's first completed turn, and permanently `""` for
240
- `shell`, `opencode`, `gemini`, `antigravity`, `pi`, `grok` and `omp`, which write no transcript at
240
+ `shell`, `opencode`, `gemini`, `antigravity`, `pi`, `grok`, `omp` and `copilot`, which write no transcript at
241
241
  all. `deepseek` is NOT one of those — it is read from `$DSH_HOME/sessions/**` and lags
242
242
  for the same reason claude does (the harness finalizes the assistant message just after
243
243
  it reports `idle`), so poll it the same way.
@@ -341,7 +341,7 @@ ESC=$(printf '\033')
341
341
 
342
342
  `POST /api/v1/quick-start` body (all optional):
343
343
  `{"caseName":"worker-1","mode":"claude","sessionName":"auth-worker","effort":"high"}`
344
- , `mode` ∈ `claude|shell|opencode|codex|gemini|antigravity|pi|grok|deepseek|omp`; response is
344
+ , `mode` ∈ `claude|shell|opencode|codex|gemini|antigravity|pi|grok|deepseek|omp|copilot`; response is
345
345
  `.data.{sessionId, caseName, casePath}`. Creates the case directory (a real directory
346
346
  on the user's disk) if missing, do not retry it in a loop, and remember the name.
347
347
 
@@ -356,9 +356,9 @@ a soft default the worker can change with `/advisor`. Remote and docker cases re
356
356
  `OPERATION_FAILED`; it never falls back to claude. Probe first whenever you did not pick
357
357
  the mode yourself: `GET /api/v1/claude/status`, `GET /api/v1/opencode/status`,
358
358
  `GET /api/v1/codex/status`, `GET /api/v1/gemini/status`, `GET /api/v1/antigravity/status`, `GET /api/v1/grok/status`, `GET /api/v1/deepseek/status`,
359
- `GET /api/v1/pi/status` and `GET /api/v1/omp/status` each return `.data.{available, path}` (no session needed).
360
- Pi's, grok's and OMP's also carry `.data.version`, because `pi` is a short generic name,
361
- `grok` is a name with npm squatters, and `omp` is a similarly short name, so an unrelated
359
+ `GET /api/v1/pi/status`, `GET /api/v1/omp/status` and `GET /api/v1/copilot/status` each return `.data.{available, path}` (no session needed).
360
+ Pi's, grok's, OMP's and Copilot's also carry `.data.version`, because `pi` is a short generic name,
361
+ `grok` is a name with npm squatters, and `omp` is a similarly short name, and `copilot` is a generic one, so an unrelated
362
362
  binary on `$PATH` can shadow any of them: the resolver rejects one whose `--version` is
363
363
  not version-shaped, so `available:false` there can mean "a different program of the same
364
364
  name is in front" rather than "nothing is installed". `shell` has no CLI to probe.
@@ -486,7 +486,7 @@ Quirks that will bite you:
486
486
  - ⚠️ **`active-tools` proves presence, never absence.** It is fed by the BashToolParser,
487
487
  which reads Claude's rendered `● Bash(…)` lines, and `_processExpensiveParsers`
488
488
  returns early for every external CLI mode (`session.ts:~2225`), so it is permanently
489
- `[]` on `opencode`/`codex`/`gemini`/`antigravity`/`pi`/`grok`/`deepseek`/`omp`. ⚠️ **`shell` is NOT one of those**
489
+ `[]` on `opencode`/`codex`/`gemini`/`antigravity`/`pi`/`grok`/`deepseek`/`omp`/`copilot`. ⚠️ **`shell` is NOT one of those**
490
490
  (`isExternalCliMode`, `session.ts:176-187`, lists only those seven), so the parser does
491
491
  run on a shell worker, and `TEXT_COMMAND_PATTERN` (`bash-tool-parser.ts:89`) matches
492
492
  bare `tail|cat|head|less|grep|watch|multitail <path>` lines with no `● Bash(` wrapper:
@@ -634,8 +634,8 @@ Three bounded long-polls. Shared semantics:
634
634
  |--------|---------|---------------|
635
635
  | `idle` | output stabilized + prompt detected, heuristic, can flap mid-turn | every mode |
636
636
  | `working` | session started producing output | every mode |
637
- | `stop` | Claude Code `stop` hook, the definitive end-of-turn | `claude` only |
638
- | `blocked` | `permission_prompt` / `elicitation_dialog` hook, the worker needs an answer | `claude` only |
637
+ | `stop` | Claude Code `stop` hook, the definitive end-of-turn | `claude`; also `deepseek`, whose harness reports its own end of turn while its status bridge is on |
638
+ | `blocked` | `permission_prompt` / `elicitation_dialog` hook, the worker needs an answer | `claude`; also `deepseek` (its harness reports its dialogs, same condition), and `codex`, whose approval, question and trust dialogs Codeman reads off its screen (answer both in the terminal, never through the inbox) |
639
639
  | `exit` | PTY exited or session deleted | every mode |
640
640
 
641
641
  ⚠️ **`claude` mode is necessary for `stop`/`blocked`, not sufficient. The real
@@ -56,7 +56,7 @@ own head: the worker enforcing the cap is the one who has to be told about it.
56
56
  | synchronize on end of turn | HTTP `wait until=stop` (fires for message-initiated turns too, verified live) |
57
57
  | liveness / death check | HTTP `wait?until=exit` |
58
58
  | interrupt a running turn (break-glass) | HTTP input, a bare `\x1b` with no `\r` |
59
- | non-claude modes (`shell`/`opencode`/`codex`/`gemini`/`antigravity`/`pi`/`grok`/`deepseek`/`omp`) | HTTP only (no other CLI has messaging) |
59
+ | non-claude modes (`shell`/`opencode`/`codex`/`gemini`/`antigravity`/`pi`/`grok`/`deepseek`/`omp`/`copilot`) | HTTP only (no other CLI has messaging) |
60
60
  | delete | HTTP, via SKILL.md's `delete_session` guard |
61
61
 
62
62
  ## Availability: probe, never assume
@@ -105,11 +105,11 @@ CLI is 2.1.224+ (`buildNameCliArgs`, `session-cli-builder.ts:97-101`, wired in a
105
105
  the worker's messages arrive tagged `from-name="<that name>"`; a derived-name worker's
106
106
  messages carry no `from-name`). Name your workers: a quick-start WITHOUT
107
107
  `sessionName` leaves the Codeman name empty, so there is nothing to pass and the
108
- peer name stays derived. ⚠️ Give them a DESCRIPTIVE name: only a name the user chose
109
- is pinned (`Session.cliPinnedName`), because `--name` is also the conversation's
108
+ peer name stays derived. ⚠️ Give them a DESCRIPTIVE name: by default only a name the user chose
109
+ is pinned (`Session.cliPinnedName`; the opt-in `pinCliSessionName` setting pins every tab name, and a rename then holds only until the next turn), because `--name` is also the conversation's
110
110
  `/resume` title and terminal title and suppresses Claude's own generated title. A
111
111
  placeholder-shaped name (`w9-msgtest`, anything matching `isGeneratedSessionName`)
112
- and an auto name are NOT passed, so such a worker's peer name is derived; use
112
+ and an auto name are NOT passed (with `pinCliSessionName` off, the default), so such a worker's peer name is derived; use
113
113
  `msgtest-worker` rather than `w9-msgtest`. The flag is fail-closed (older/unknown CLI omits it, because an
114
114
  unknown flag aborts startup and would kill every spawn) and allowlist-sanitized (a name of
115
115
  only unsafe characters is dropped), and the docker/remote builders never see it at all
@@ -352,7 +352,7 @@ Without a break-glass, a pair with a bad brief is a token bonfire with no off sw
352
352
 
353
353
  ### Mixed fleets: the pairing matrix
354
354
 
355
- Non-claude workers (`shell`, `opencode`, `codex`, `gemini`, `antigravity`, `pi`, `grok`, `deepseek`, `omp`) cannot be peers
355
+ Non-claude workers (`shell`, `opencode`, `codex`, `gemini`, `antigravity`, `pi`, `grok`, `deepseek`, `omp`, `copilot`) cannot be peers
356
356
  at all; no other CLI has this feature. Their tasks route over HTTP, and you never mention
357
357
  messaging in their briefs. The claude half of the fleet can use messaging among itself,
358
358
  subject to the namespace rule: **messaging works between two sessions that share one
@@ -21,7 +21,7 @@ by sourcing the preamble file the §0 bootstrap wrote, and checking its version
21
21
 
22
22
  ```bash
23
23
  . "${XDG_CACHE_HOME:-$HOME/.cache}/codeman-agent-$CODEMAN_SESSION_ID.sh" 2>/dev/null
24
- [ "${CODEMAN_PREAMBLE:-}" = 1.33.4 ] || { echo "preamble missing or stale; re-run the §0 bootstrap"; exit 1; }
24
+ [ "${CODEMAN_PREAMBLE:-}" = 1.42.0 ] || { echo "preamble missing or stale; re-run the §0 bootstrap"; exit 1; }
25
25
  ```
26
26
 
27
27
  Do **not** re-paste the preamble body into each call. Sourcing it is what retires the
@@ -188,7 +188,7 @@ for _ in $(seq 1 10); do
188
188
  done
189
189
  printf '%s\n' "$TXT"
190
190
  # (.data is {text,timestamp}; text is also "" before the first completed turn and
191
- # always "" for shell/opencode/gemini/antigravity/pi/grok/omp, which have no transcript, use
191
+ # always "" for shell/opencode/gemini/antigravity/pi/grok/omp/copilot, which have no transcript, use
192
192
  # the terminal tail there, and here only to diagnose an unsubmitted prompt.)
193
193
 
194
194
  # 6. clean up: exact id, own list only, through the fail-closed preamble helper
@@ -391,10 +391,10 @@ the worker remembering to print a token.
391
391
 
392
392
  ## Flow 5: watch for a worker stuck on a prompt
393
393
 
394
- Claude workers can block on a permission dialog. `blocked` is a wait signal
395
- (claude-mode only, and it needs Codeman's hooks in the worker's directory: see Flow 7
396
- step 4), so watch for it and surface the question to the user instead of guessing an
397
- answer. Expect it routinely on a server whose `claudeMode` is not the default bypass
394
+ Claude workers can block on a permission dialog. `blocked` is a wait signal (a claude
395
+ worker needs Codeman's hooks in its directory for it: see Flow 7 step 4; a codex worker
396
+ gets it from its screen, see below), so watch for it and surface the question to the user
397
+ instead of guessing an answer. Expect it routinely on a server whose `claudeMode` is not the default bypass
398
398
  one (the same setting that decides whether the readiness marker in Flow 1 ever
399
399
  appears):
400
400
 
@@ -409,10 +409,13 @@ if [ "$(jq -r '.data.wait.signal' <<<"$R")" = blocked ]; then
409
409
  fi
410
410
  ```
411
411
 
412
- Where the worker has no hooks, `blocked` never fires and a stuck worker looks exactly
413
- like a slow one: your marker wait burns its whole bound. The fallback is the same
414
- terminal tail, taken when a bound runs out, and the same rule about not answering it
415
- yourself.
412
+ Codex workers are the one exception without hooks: Codeman reads their approval,
413
+ question and trust dialogs off the screen, so the same watch works with
414
+ `until=blocked,exit` (codex has no `stop`, a `400`), and the dialog is answered in the
415
+ terminal, never through the Approvals Inbox. Anywhere else without hooks, `blocked` never
416
+ fires and a stuck worker looks exactly like a slow one: your marker wait burns its whole
417
+ bound. The fallback is the same terminal tail, taken when a bound runs out, and the same
418
+ rule about not answering it yourself.
416
419
 
417
420
  ## Flow 6: claude fan-out over messaging
418
421
 
@@ -376,8 +376,10 @@ recovered by submitting it with `{"input":"\r"}`.
376
376
  only when the workspace actually has them, see [§5.1](#51-where-to-spawn)) **and for
377
377
  `deepseek`** — the one external CLI that reports its own lifecycle, so its `stop` is a
378
378
  real end-of-turn signal rather than a guess. On
379
- `shell`/`opencode`/`codex`/`gemini`/`antigravity`/`pi`/`grok`/`omp`, requesting them explicitly is a
380
- 400, and lifecycle transitions there are coarse (a short shell command may emit **no**
379
+ `shell`/`opencode`/`codex`/`gemini`/`antigravity`/`pi`/`grok`/`omp`/`copilot`, requesting them explicitly is a
380
+ 400 (except `blocked` on `codex`, which Codeman reads off its screen when an approval,
381
+ question or trust dialog is up; a wait for it answers at once if one already is), and
382
+ lifecycle transitions there are coarse (a short shell command may emit **no**
381
383
  `idle` transition at all, verified live), so synchronize those with markers.
382
384
 
383
385
  ⚠️ A dsh session can still refuse them for a per-SESSION reason: `statusReporting:
@@ -428,7 +430,7 @@ from the transcript file, which is flushed slightly *after* the `stop` hook fire
428
430
  single read taken the instant send-and-wait returns comes back `""` even though the
429
431
  turn finished (verified live: empty on the first call, full text seconds later). `text`
430
432
  is also `""` before the worker's first completed turn, and always `""` for modes with
431
- no transcript (`shell`, `opencode`, `gemini`, `antigravity`, `pi`, `grok`, `omp`; the first four
433
+ no transcript (`shell`, `opencode`, `gemini`, `antigravity`, `pi`, `grok`, `omp`, `copilot`; the first four
432
434
  verified live, pi from the same source path), which is
433
435
  why the loop above is bounded rather than open-ended. A dsh worker lags too, for its own
434
436
  reason: the harness finalizes the assistant message just after it reports `idle`. Fall back to the terminal buffer
@@ -514,7 +516,7 @@ turn), and both better than diffing terminal samples:
514
516
  ```
515
517
 
516
518
  ⚠️ `active-tools` is parsed out of Claude's own output format, so it is **empty for
517
- `opencode`/`codex`/`gemini`/`antigravity`/`pi`/`grok`/`deepseek`/`omp`** (those parsers are skipped wholesale) and
519
+ `opencode`/`codex`/`gemini`/`antigravity`/`pi`/`grok`/`deepseek`/`omp`/`copilot`** (those parsers are skipped wholesale) and
518
520
  in practice empty for `shell`. Source-verified, not measured live.
519
521
 
520
522
  Only if neither helps: sample `terminal?tail=` twice a few seconds apart. A changing
@@ -697,7 +699,7 @@ The shape, each step verified live (probes, failure modes and safety detail in
697
699
  column; the row's `name [ref]` is the address. On Codeman 1.16+ with claude
698
700
  2.1.224+ a worker's peer name is its Codeman session name, so pass a DESCRIPTIVE
699
701
  `sessionName` in quick-start to pick it (a `w<N>-` placeholder-shaped name is not
700
- pinned, so it lists derived); older setups list a name derived from the case folder.
702
+ pinned by default, so it lists derived); older setups list a name derived from the case folder.
701
703
  No row = messaging is off for that worker (it is feature-flagged even on matching
702
704
  CLI versions, observed live): fall back to the HTTP recipes without complaint.
703
705
  3. `SendMessage` the task; first contact must use the `name [ref]` form copied from