@mindfoldhq/trellis 0.3.10 → 0.4.0-beta.10

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 (304) hide show
  1. package/README.md +19 -5
  2. package/dist/cli/index.js +5 -0
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/commands/init.d.ts +4 -0
  5. package/dist/commands/init.d.ts.map +1 -1
  6. package/dist/commands/init.js +240 -43
  7. package/dist/commands/init.js.map +1 -1
  8. package/dist/commands/update.d.ts.map +1 -1
  9. package/dist/commands/update.js +206 -47
  10. package/dist/commands/update.js.map +1 -1
  11. package/dist/configurators/codebuddy.d.ts +11 -0
  12. package/dist/configurators/codebuddy.d.ts.map +1 -0
  13. package/dist/configurators/codebuddy.js +58 -0
  14. package/dist/configurators/codebuddy.js.map +1 -0
  15. package/dist/configurators/codex.d.ts +7 -4
  16. package/dist/configurators/codex.d.ts.map +1 -1
  17. package/dist/configurators/codex.js +40 -10
  18. package/dist/configurators/codex.js.map +1 -1
  19. package/dist/configurators/copilot.d.ts +9 -0
  20. package/dist/configurators/copilot.d.ts.map +1 -0
  21. package/dist/configurators/copilot.js +34 -0
  22. package/dist/configurators/copilot.js.map +1 -0
  23. package/dist/configurators/index.d.ts +11 -1
  24. package/dist/configurators/index.d.ts.map +1 -1
  25. package/dist/configurators/index.js +72 -4
  26. package/dist/configurators/index.js.map +1 -1
  27. package/dist/configurators/opencode.d.ts +1 -1
  28. package/dist/configurators/opencode.js +1 -1
  29. package/dist/configurators/windsurf.d.ts +8 -0
  30. package/dist/configurators/windsurf.d.ts.map +1 -0
  31. package/dist/configurators/windsurf.js +18 -0
  32. package/dist/configurators/windsurf.js.map +1 -0
  33. package/dist/configurators/workflow.d.ts +6 -2
  34. package/dist/configurators/workflow.d.ts.map +1 -1
  35. package/dist/configurators/workflow.js +90 -58
  36. package/dist/configurators/workflow.js.map +1 -1
  37. package/dist/migrations/index.d.ts +1 -0
  38. package/dist/migrations/index.d.ts.map +1 -1
  39. package/dist/migrations/index.js +2 -0
  40. package/dist/migrations/index.js.map +1 -1
  41. package/dist/migrations/manifests/0.4.0-beta.1.json +228 -0
  42. package/dist/migrations/manifests/0.4.0-beta.10.json +9 -0
  43. package/dist/migrations/manifests/0.4.0-beta.2.json +9 -0
  44. package/dist/migrations/manifests/0.4.0-beta.3.json +9 -0
  45. package/dist/migrations/manifests/0.4.0-beta.4.json +9 -0
  46. package/dist/migrations/manifests/0.4.0-beta.5.json +9 -0
  47. package/dist/migrations/manifests/0.4.0-beta.6.json +9 -0
  48. package/dist/migrations/manifests/0.4.0-beta.7.json +9 -0
  49. package/dist/migrations/manifests/0.4.0-beta.8.json +34 -0
  50. package/dist/migrations/manifests/0.4.0-beta.9.json +9 -0
  51. package/dist/templates/claude/agents/dispatch.md +1 -2
  52. package/dist/templates/claude/agents/implement.md +2 -3
  53. package/dist/templates/claude/commands/trellis/before-dev.md +29 -0
  54. package/dist/templates/claude/commands/trellis/check.md +25 -0
  55. package/dist/templates/claude/commands/trellis/create-command.md +2 -2
  56. package/dist/templates/claude/commands/trellis/onboard.md +13 -13
  57. package/dist/templates/claude/commands/trellis/parallel.md +1 -2
  58. package/dist/templates/claude/commands/trellis/record-session.md +3 -2
  59. package/dist/templates/claude/commands/trellis/start.md +8 -4
  60. package/dist/templates/claude/hooks/inject-subagent-context.py +29 -14
  61. package/dist/templates/claude/hooks/ralph-loop.py +18 -10
  62. package/dist/templates/claude/hooks/session-start.py +201 -9
  63. package/dist/templates/claude/hooks/statusline.py +211 -0
  64. package/dist/templates/claude/settings.json +4 -0
  65. package/dist/templates/codebuddy/commands/trellis/before-dev.md +29 -0
  66. package/dist/templates/codebuddy/commands/trellis/brainstorm.md +487 -0
  67. package/dist/templates/codebuddy/commands/trellis/break-loop.md +107 -0
  68. package/dist/templates/codebuddy/commands/trellis/check-cross-layer.md +153 -0
  69. package/dist/templates/codebuddy/commands/trellis/check.md +25 -0
  70. package/dist/templates/codebuddy/commands/trellis/create-command.md +154 -0
  71. package/dist/templates/codebuddy/commands/trellis/finish-work.md +143 -0
  72. package/dist/templates/codebuddy/commands/trellis/integrate-skill.md +219 -0
  73. package/dist/templates/codebuddy/commands/trellis/onboard.md +358 -0
  74. package/dist/templates/codebuddy/commands/trellis/record-session.md +61 -0
  75. package/dist/templates/codebuddy/commands/trellis/start.md +373 -0
  76. package/dist/templates/codebuddy/commands/trellis/update-spec.md +354 -0
  77. package/dist/templates/codebuddy/index.d.ts +25 -0
  78. package/dist/templates/codebuddy/index.d.ts.map +1 -0
  79. package/dist/templates/codebuddy/index.js +45 -0
  80. package/dist/templates/codebuddy/index.js.map +1 -0
  81. package/dist/templates/codex/agents/check.toml +23 -0
  82. package/dist/templates/codex/agents/implement.toml +19 -0
  83. package/dist/templates/codex/agents/research.toml +26 -0
  84. package/dist/templates/codex/codex-skills/parallel/SKILL.md +194 -0
  85. package/dist/templates/codex/config.toml +5 -0
  86. package/dist/templates/codex/hooks/session-start.py +228 -0
  87. package/dist/templates/codex/hooks.json +16 -0
  88. package/dist/templates/codex/index.d.ts +27 -5
  89. package/dist/templates/codex/index.d.ts.map +1 -1
  90. package/dist/templates/codex/index.js +60 -8
  91. package/dist/templates/codex/index.js.map +1 -1
  92. package/dist/templates/codex/skills/before-dev/SKILL.md +34 -0
  93. package/dist/templates/codex/skills/brainstorm/SKILL.md +1 -1
  94. package/dist/templates/codex/skills/break-loop/SKILL.md +1 -1
  95. package/dist/templates/codex/skills/check/SKILL.md +30 -0
  96. package/dist/templates/codex/skills/check-cross-layer/SKILL.md +1 -1
  97. package/dist/templates/codex/skills/create-command/SKILL.md +3 -3
  98. package/dist/templates/codex/skills/finish-work/SKILL.md +1 -1
  99. package/dist/templates/codex/skills/improve-ut/SKILL.md +69 -0
  100. package/dist/templates/codex/skills/integrate-skill/SKILL.md +1 -1
  101. package/dist/templates/codex/skills/onboard/SKILL.md +12 -12
  102. package/dist/templates/codex/skills/record-session/SKILL.md +4 -3
  103. package/dist/templates/codex/skills/start/SKILL.md +9 -4
  104. package/dist/templates/codex/skills/update-spec/SKILL.md +1 -1
  105. package/dist/templates/copilot/hooks/session-start.py +218 -0
  106. package/dist/templates/copilot/hooks.json +11 -0
  107. package/dist/templates/copilot/index.d.ts +23 -0
  108. package/dist/templates/copilot/index.d.ts.map +1 -0
  109. package/dist/templates/copilot/index.js +54 -0
  110. package/dist/templates/copilot/index.js.map +1 -0
  111. package/dist/templates/copilot/prompts/before-dev.prompt.md +33 -0
  112. package/dist/templates/copilot/prompts/brainstorm.prompt.md +491 -0
  113. package/dist/templates/copilot/prompts/break-loop.prompt.md +129 -0
  114. package/dist/templates/copilot/prompts/check-cross-layer.prompt.md +157 -0
  115. package/dist/templates/copilot/prompts/check.prompt.md +29 -0
  116. package/dist/templates/copilot/prompts/create-command.prompt.md +116 -0
  117. package/dist/templates/copilot/prompts/finish-work.prompt.md +157 -0
  118. package/dist/templates/copilot/prompts/integrate-skill.prompt.md +223 -0
  119. package/dist/templates/copilot/prompts/onboard.prompt.md +362 -0
  120. package/dist/templates/copilot/prompts/parallel.prompt.md +196 -0
  121. package/dist/templates/copilot/prompts/record-session.prompt.md +66 -0
  122. package/dist/templates/copilot/prompts/start.prompt.md +397 -0
  123. package/dist/templates/copilot/prompts/update-spec.prompt.md +358 -0
  124. package/dist/templates/cursor/commands/trellis-before-dev.md +29 -0
  125. package/dist/templates/cursor/commands/trellis-check.md +25 -0
  126. package/dist/templates/cursor/commands/trellis-create-command.md +2 -2
  127. package/dist/templates/cursor/commands/trellis-onboard.md +13 -13
  128. package/dist/templates/cursor/commands/trellis-record-session.md +3 -2
  129. package/dist/templates/cursor/commands/trellis-start.md +7 -16
  130. package/dist/templates/extract.d.ts +36 -0
  131. package/dist/templates/extract.d.ts.map +1 -1
  132. package/dist/templates/extract.js +64 -0
  133. package/dist/templates/extract.js.map +1 -1
  134. package/dist/templates/gemini/commands/trellis/before-dev.toml +33 -0
  135. package/dist/templates/gemini/commands/trellis/check.toml +29 -0
  136. package/dist/templates/gemini/commands/trellis/create-command.toml +2 -2
  137. package/dist/templates/gemini/commands/trellis/onboard.toml +2 -2
  138. package/dist/templates/gemini/commands/trellis/record-session.toml +3 -2
  139. package/dist/templates/gemini/commands/trellis/start.toml +9 -4
  140. package/dist/templates/iflow/agents/dispatch.md +1 -2
  141. package/dist/templates/iflow/agents/implement.md +2 -3
  142. package/dist/templates/iflow/commands/trellis/before-dev.md +29 -0
  143. package/dist/templates/iflow/commands/trellis/check.md +25 -0
  144. package/dist/templates/iflow/commands/trellis/create-command.md +2 -2
  145. package/dist/templates/iflow/commands/trellis/onboard.md +13 -13
  146. package/dist/templates/iflow/commands/trellis/parallel.md +1 -2
  147. package/dist/templates/iflow/commands/trellis/record-session.md +3 -2
  148. package/dist/templates/iflow/commands/trellis/start.md +8 -4
  149. package/dist/templates/iflow/hooks/inject-subagent-context.py +29 -14
  150. package/dist/templates/iflow/hooks/ralph-loop.py +8 -1
  151. package/dist/templates/iflow/hooks/session-start.py +187 -8
  152. package/dist/templates/kilo/workflows/before-dev.md +29 -0
  153. package/dist/templates/kilo/workflows/check.md +25 -0
  154. package/dist/templates/kilo/workflows/create-command.md +2 -2
  155. package/dist/templates/kilo/workflows/onboard.md +13 -13
  156. package/dist/templates/kilo/workflows/parallel.md +1 -2
  157. package/dist/templates/kilo/workflows/record-session.md +3 -2
  158. package/dist/templates/kilo/workflows/start.md +8 -3
  159. package/dist/templates/kiro/skills/before-dev/SKILL.md +34 -0
  160. package/dist/templates/kiro/skills/brainstorm/SKILL.md +1 -1
  161. package/dist/templates/kiro/skills/break-loop/SKILL.md +1 -1
  162. package/dist/templates/kiro/skills/check/SKILL.md +30 -0
  163. package/dist/templates/kiro/skills/check-cross-layer/SKILL.md +1 -1
  164. package/dist/templates/kiro/skills/create-command/SKILL.md +3 -3
  165. package/dist/templates/kiro/skills/finish-work/SKILL.md +1 -1
  166. package/dist/templates/kiro/skills/integrate-skill/SKILL.md +1 -1
  167. package/dist/templates/kiro/skills/onboard/SKILL.md +12 -12
  168. package/dist/templates/kiro/skills/record-session/SKILL.md +4 -3
  169. package/dist/templates/kiro/skills/start/SKILL.md +9 -4
  170. package/dist/templates/kiro/skills/update-spec/SKILL.md +1 -1
  171. package/dist/templates/markdown/agents.md +4 -0
  172. package/dist/templates/markdown/spec/backend/directory-structure.md +1 -1
  173. package/dist/templates/markdown/spec/backend/script-conventions.md +93 -0
  174. package/dist/templates/markdown/workspace-index.md +2 -0
  175. package/dist/templates/opencode/agents/dispatch.md +21 -21
  176. package/dist/templates/opencode/agents/implement.md +2 -2
  177. package/dist/templates/opencode/agents/research.md +1 -2
  178. package/dist/templates/opencode/commands/trellis/before-dev.md +29 -0
  179. package/dist/templates/opencode/commands/trellis/check.md +25 -0
  180. package/dist/templates/opencode/commands/trellis/create-command.md +2 -2
  181. package/dist/templates/opencode/commands/trellis/onboard.md +13 -13
  182. package/dist/templates/opencode/commands/trellis/parallel.md +1 -2
  183. package/dist/templates/opencode/commands/trellis/record-session.md +3 -2
  184. package/dist/templates/opencode/commands/trellis/start.md +8 -3
  185. package/dist/templates/opencode/lib/trellis-context.js +42 -2
  186. package/dist/templates/opencode/{plugin → plugins}/inject-subagent-context.js +45 -18
  187. package/dist/templates/opencode/{plugin → plugins}/session-start.js +156 -28
  188. package/dist/templates/qoder/skills/before-dev/SKILL.md +34 -0
  189. package/dist/templates/qoder/skills/brainstorm/SKILL.md +1 -1
  190. package/dist/templates/qoder/skills/break-loop/SKILL.md +1 -1
  191. package/dist/templates/qoder/skills/check/SKILL.md +30 -0
  192. package/dist/templates/qoder/skills/check-cross-layer/SKILL.md +1 -1
  193. package/dist/templates/qoder/skills/create-command/SKILL.md +3 -3
  194. package/dist/templates/qoder/skills/finish-work/SKILL.md +1 -1
  195. package/dist/templates/qoder/skills/integrate-skill/SKILL.md +1 -1
  196. package/dist/templates/qoder/skills/onboard/SKILL.md +14 -14
  197. package/dist/templates/qoder/skills/record-session/SKILL.md +4 -3
  198. package/dist/templates/qoder/skills/start/SKILL.md +9 -4
  199. package/dist/templates/qoder/skills/update-spec/SKILL.md +1 -1
  200. package/dist/templates/trellis/config.yaml +20 -0
  201. package/dist/templates/trellis/index.d.ts +11 -0
  202. package/dist/templates/trellis/index.d.ts.map +1 -1
  203. package/dist/templates/trellis/index.js +22 -0
  204. package/dist/templates/trellis/index.js.map +1 -1
  205. package/dist/templates/trellis/scripts/add_session.py +111 -13
  206. package/dist/templates/trellis/scripts/common/__init__.py +2 -0
  207. package/dist/templates/trellis/scripts/common/cli_adapter.py +164 -64
  208. package/dist/templates/trellis/scripts/common/config.py +192 -0
  209. package/dist/templates/trellis/scripts/common/developer.py +2 -2
  210. package/dist/templates/trellis/scripts/common/git.py +31 -0
  211. package/dist/templates/trellis/scripts/common/git_context.py +23 -586
  212. package/dist/templates/trellis/scripts/common/io.py +37 -0
  213. package/dist/templates/trellis/scripts/common/log.py +45 -0
  214. package/dist/templates/trellis/scripts/common/packages_context.py +238 -0
  215. package/dist/templates/trellis/scripts/common/paths.py +103 -6
  216. package/dist/templates/trellis/scripts/common/phase.py +50 -49
  217. package/dist/templates/trellis/scripts/common/registry.py +41 -72
  218. package/dist/templates/trellis/scripts/common/session_context.py +562 -0
  219. package/dist/templates/trellis/scripts/common/task_context.py +410 -0
  220. package/dist/templates/trellis/scripts/common/task_queue.py +27 -98
  221. package/dist/templates/trellis/scripts/common/task_store.py +536 -0
  222. package/dist/templates/trellis/scripts/common/task_utils.py +106 -10
  223. package/dist/templates/trellis/scripts/common/tasks.py +109 -0
  224. package/dist/templates/trellis/scripts/common/types.py +112 -0
  225. package/dist/templates/trellis/scripts/create_bootstrap.py +32 -27
  226. package/dist/templates/trellis/scripts/hooks/linear_sync.py +243 -0
  227. package/dist/templates/trellis/scripts/multi_agent/_bootstrap.py +17 -0
  228. package/dist/templates/trellis/scripts/multi_agent/cleanup.py +43 -48
  229. package/dist/templates/trellis/scripts/multi_agent/create_pr.py +336 -45
  230. package/dist/templates/trellis/scripts/multi_agent/plan.py +9 -32
  231. package/dist/templates/trellis/scripts/multi_agent/start.py +142 -68
  232. package/dist/templates/trellis/scripts/multi_agent/status.py +12 -753
  233. package/dist/templates/trellis/scripts/multi_agent/status_display.py +542 -0
  234. package/dist/templates/trellis/scripts/multi_agent/status_monitor.py +225 -0
  235. package/dist/templates/trellis/scripts/task.py +51 -976
  236. package/dist/templates/trellis/scripts-shell-archive/create-bootstrap.sh +1 -1
  237. package/dist/templates/trellis/workflow.md +38 -38
  238. package/dist/templates/windsurf/index.d.ts +21 -0
  239. package/dist/templates/windsurf/index.d.ts.map +1 -0
  240. package/dist/templates/windsurf/index.js +44 -0
  241. package/dist/templates/windsurf/index.js.map +1 -0
  242. package/dist/templates/windsurf/workflows/trellis-before-dev.md +31 -0
  243. package/dist/templates/windsurf/workflows/trellis-brainstorm.md +491 -0
  244. package/dist/templates/windsurf/workflows/trellis-break-loop.md +111 -0
  245. package/dist/templates/windsurf/workflows/trellis-check-cross-layer.md +157 -0
  246. package/dist/templates/windsurf/workflows/trellis-check.md +27 -0
  247. package/dist/templates/windsurf/workflows/trellis-create-command.md +154 -0
  248. package/dist/templates/windsurf/workflows/trellis-finish-work.md +147 -0
  249. package/dist/templates/windsurf/workflows/trellis-integrate-skill.md +220 -0
  250. package/dist/templates/windsurf/workflows/trellis-onboard.md +362 -0
  251. package/dist/templates/windsurf/workflows/trellis-record-session.md +66 -0
  252. package/dist/templates/windsurf/workflows/trellis-start.md +373 -0
  253. package/dist/templates/windsurf/workflows/trellis-update-spec.md +358 -0
  254. package/dist/types/ai-tools.d.ts +15 -3
  255. package/dist/types/ai-tools.d.ts.map +1 -1
  256. package/dist/types/ai-tools.js +42 -2
  257. package/dist/types/ai-tools.js.map +1 -1
  258. package/dist/types/migration.d.ts +3 -1
  259. package/dist/types/migration.d.ts.map +1 -1
  260. package/dist/utils/project-detector.d.ts +28 -0
  261. package/dist/utils/project-detector.d.ts.map +1 -1
  262. package/dist/utils/project-detector.js +371 -0
  263. package/dist/utils/project-detector.js.map +1 -1
  264. package/dist/utils/template-fetcher.d.ts +19 -6
  265. package/dist/utils/template-fetcher.d.ts.map +1 -1
  266. package/dist/utils/template-fetcher.js +99 -17
  267. package/dist/utils/template-fetcher.js.map +1 -1
  268. package/package.json +1 -1
  269. package/dist/templates/claude/commands/trellis/before-backend-dev.md +0 -13
  270. package/dist/templates/claude/commands/trellis/before-frontend-dev.md +0 -13
  271. package/dist/templates/claude/commands/trellis/check-backend.md +0 -13
  272. package/dist/templates/claude/commands/trellis/check-frontend.md +0 -13
  273. package/dist/templates/codex/skills/before-backend-dev/SKILL.md +0 -18
  274. package/dist/templates/codex/skills/before-frontend-dev/SKILL.md +0 -18
  275. package/dist/templates/codex/skills/check-backend/SKILL.md +0 -18
  276. package/dist/templates/codex/skills/check-frontend/SKILL.md +0 -18
  277. package/dist/templates/cursor/commands/trellis-before-backend-dev.md +0 -13
  278. package/dist/templates/cursor/commands/trellis-before-frontend-dev.md +0 -13
  279. package/dist/templates/cursor/commands/trellis-check-backend.md +0 -13
  280. package/dist/templates/cursor/commands/trellis-check-frontend.md +0 -13
  281. package/dist/templates/gemini/commands/trellis/before-backend-dev.toml +0 -17
  282. package/dist/templates/gemini/commands/trellis/before-frontend-dev.toml +0 -17
  283. package/dist/templates/gemini/commands/trellis/check-backend.toml +0 -17
  284. package/dist/templates/gemini/commands/trellis/check-frontend.toml +0 -17
  285. package/dist/templates/iflow/commands/trellis/before-backend-dev.md +0 -13
  286. package/dist/templates/iflow/commands/trellis/before-frontend-dev.md +0 -13
  287. package/dist/templates/iflow/commands/trellis/check-backend.md +0 -13
  288. package/dist/templates/iflow/commands/trellis/check-frontend.md +0 -13
  289. package/dist/templates/kilo/workflows/before-backend-dev.md +0 -13
  290. package/dist/templates/kilo/workflows/before-frontend-dev.md +0 -13
  291. package/dist/templates/kilo/workflows/check-backend.md +0 -13
  292. package/dist/templates/kilo/workflows/check-frontend.md +0 -13
  293. package/dist/templates/kiro/skills/before-backend-dev/SKILL.md +0 -18
  294. package/dist/templates/kiro/skills/before-frontend-dev/SKILL.md +0 -18
  295. package/dist/templates/kiro/skills/check-backend/SKILL.md +0 -18
  296. package/dist/templates/kiro/skills/check-frontend/SKILL.md +0 -18
  297. package/dist/templates/opencode/commands/trellis/before-backend-dev.md +0 -13
  298. package/dist/templates/opencode/commands/trellis/before-frontend-dev.md +0 -13
  299. package/dist/templates/opencode/commands/trellis/check-backend.md +0 -13
  300. package/dist/templates/opencode/commands/trellis/check-frontend.md +0 -13
  301. package/dist/templates/qoder/skills/before-backend-dev/SKILL.md +0 -18
  302. package/dist/templates/qoder/skills/before-frontend-dev/SKILL.md +0 -18
  303. package/dist/templates/qoder/skills/check-backend/SKILL.md +0 -18
  304. package/dist/templates/qoder/skills/check-frontend/SKILL.md +0 -18
@@ -21,7 +21,6 @@ Configuration: .trellis/worktree.yaml
21
21
 
22
22
  from __future__ import annotations
23
23
 
24
- import json
25
24
  import os
26
25
  import shutil
27
26
  import subprocess
@@ -29,11 +28,12 @@ import sys
29
28
  import uuid
30
29
  from pathlib import Path
31
30
 
32
- # Add parent directory to path for imports
33
- sys.path.insert(0, str(Path(__file__).parent.parent))
31
+ import _bootstrap # noqa: F401 — adds parent scripts/ dir to sys.path
34
32
 
35
- from common.cli_adapter import CLIAdapter, get_cli_adapter
36
- from common.git_context import _run_git_command
33
+ from common.cli_adapter import get_cli_adapter
34
+ from common.git import run_git
35
+ from common.io import read_json, write_json
36
+ from common.log import Colors, log_info, log_success, log_warn, log_error
37
37
  from common.paths import (
38
38
  DIR_WORKFLOW,
39
39
  FILE_CURRENT_TASK,
@@ -44,6 +44,12 @@ from common.registry import (
44
44
  registry_add_agent,
45
45
  registry_get_file,
46
46
  )
47
+ from common.config import (
48
+ get_default_package,
49
+ get_packages,
50
+ get_submodule_packages,
51
+ validate_package,
52
+ )
47
53
  from common.worktree import (
48
54
  get_worktree_base_dir,
49
55
  get_worktree_config,
@@ -51,64 +57,121 @@ from common.worktree import (
51
57
  get_worktree_post_create_hooks,
52
58
  )
53
59
 
54
- # =============================================================================
55
- # Colors
56
- # =============================================================================
57
-
58
-
59
- class Colors:
60
- RED = "\033[0;31m"
61
- GREEN = "\033[0;32m"
62
- YELLOW = "\033[1;33m"
63
- BLUE = "\033[0;34m"
64
- NC = "\033[0m"
65
-
66
-
67
- def log_info(msg: str) -> None:
68
- print(f"{Colors.BLUE}[INFO]{Colors.NC} {msg}")
69
-
70
-
71
- def log_success(msg: str) -> None:
72
- print(f"{Colors.GREEN}[SUCCESS]{Colors.NC} {msg}")
73
-
60
+ # Colors, log_info, log_success, log_warn, log_error, read_json, write_json
61
+ # are now imported from common.log and common.io above.
74
62
 
75
- def log_warn(msg: str) -> None:
76
- print(f"{Colors.YELLOW}[WARN]{Colors.NC} {msg}")
77
63
 
64
+ # =============================================================================
65
+ # Constants
66
+ # =============================================================================
78
67
 
79
- def log_error(msg: str) -> None:
80
- print(f"{Colors.RED}[ERROR]{Colors.NC} {msg}")
68
+ DEFAULT_PLATFORM = "claude"
81
69
 
82
70
 
83
71
  # =============================================================================
84
- # Helper Functions
72
+ # Submodule Init
85
73
  # =============================================================================
86
74
 
87
75
 
88
- def _read_json_file(path: Path) -> dict | None:
89
- """Read and parse a JSON file."""
90
- try:
91
- return json.loads(path.read_text(encoding="utf-8"))
92
- except (FileNotFoundError, json.JSONDecodeError, OSError):
93
- return None
94
-
76
+ def _init_submodules_for_task(
77
+ task_data: dict, worktree_path: str, project_root: Path
78
+ ) -> None:
79
+ """Initialize submodules in worktree based on task's target package.
95
80
 
96
- def _write_json_file(path: Path, data: dict) -> bool:
97
- """Write dict to JSON file."""
98
- try:
99
- path.write_text(
100
- json.dumps(data, indent=2, ensure_ascii=False), encoding="utf-8"
101
- )
102
- return True
103
- except (OSError, IOError):
104
- return False
81
+ Resolves the target package from task_data.package -> default_package -> None.
82
+ Only initializes submodule-type packages. Idempotent: skips already-initialized
83
+ submodules to avoid detaching HEAD on in-progress work.
84
+ """
85
+ # Skip if not a monorepo (no packages configured)
86
+ if get_packages(project_root) is None:
87
+ return
105
88
 
89
+ # Resolve package: task.package -> default_package -> None
90
+ task_package = task_data.get("package")
91
+ package = None
106
92
 
107
- # =============================================================================
108
- # Constants
109
- # =============================================================================
93
+ if task_package and isinstance(task_package, str):
94
+ if validate_package(task_package, project_root):
95
+ package = task_package
96
+ else:
97
+ log_warn(
98
+ f"package '{task_package}' not found in config.yaml, "
99
+ "skipping submodule init"
100
+ )
101
+ return
102
+ else:
103
+ # Fallback to default_package
104
+ default_pkg = get_default_package(project_root)
105
+ if default_pkg:
106
+ if validate_package(default_pkg, project_root):
107
+ package = default_pkg
108
+ else:
109
+ log_warn(
110
+ f"package '{default_pkg}' not found in config.yaml, "
111
+ "skipping submodule init"
112
+ )
113
+ return
114
+
115
+ if not package:
116
+ log_warn("no package specified, skipping submodule init")
117
+ return
118
+
119
+ # Check if this package is a submodule
120
+ submodule_packages = get_submodule_packages(project_root)
121
+ if package not in submodule_packages:
122
+ log_info(f"Package '{package}' is not a submodule, skipping submodule init")
123
+ return
124
+
125
+ submodule_path = submodule_packages[package]
126
+ log_info(f"Checking submodule status for '{package}' ({submodule_path})...")
127
+
128
+ # Run git submodule status in worktree directory
129
+ ret, status_out, status_err = run_git(
130
+ ["submodule", "status", submodule_path], cwd=Path(worktree_path)
131
+ )
110
132
 
111
- DEFAULT_PLATFORM = "claude"
133
+ if ret != 0:
134
+ log_warn(
135
+ f"git submodule status failed for '{submodule_path}': {status_err.strip()}, "
136
+ "skipping submodule init"
137
+ )
138
+ return
139
+
140
+ # Parse the prefix character from submodule status output
141
+ # Format: "<prefix><sha1> <path> (<describe>)"
142
+ # Prefix: '-' (uninitialized), ' ' (normal), '+' (commit mismatch), 'U' (conflict)
143
+ status_line = status_out.rstrip("\n\r")
144
+ if not status_line:
145
+ log_warn(f"Empty submodule status for '{submodule_path}', skipping")
146
+ return
147
+
148
+ prefix = status_line[0]
149
+
150
+ if prefix == "-":
151
+ # Uninitialized: run git submodule update --init
152
+ log_info(f"Initializing submodule '{submodule_path}'...")
153
+ ret, _, err = run_git(
154
+ ["submodule", "update", "--init", submodule_path],
155
+ cwd=Path(worktree_path),
156
+ )
157
+ if ret != 0:
158
+ log_warn(f"Failed to initialize submodule '{submodule_path}': {err.strip()}")
159
+ else:
160
+ log_success(f"Submodule '{submodule_path}' initialized")
161
+ elif prefix == " ":
162
+ log_info(f"Submodule '{submodule_path}' already initialized, skipping")
163
+ elif prefix == "+":
164
+ log_warn(
165
+ f"submodule {submodule_path} has local changes, skipping update"
166
+ )
167
+ elif prefix == "U":
168
+ log_warn(
169
+ f"submodule {submodule_path} has conflicts, skipping"
170
+ )
171
+ else:
172
+ log_warn(
173
+ f"Unknown submodule status prefix '{prefix}' for '{submodule_path}', skipping"
174
+ )
112
175
 
113
176
 
114
177
  # =============================================================================
@@ -124,7 +187,7 @@ def main() -> int:
124
187
  parser.add_argument("task_dir", help="Task directory path")
125
188
  parser.add_argument(
126
189
  "--platform", "-p",
127
- choices=["claude", "cursor", "iflow", "opencode", "qoder"],
190
+ choices=["claude", "cursor", "iflow", "opencode", "codex", "qoder"],
128
191
  default=DEFAULT_PLATFORM,
129
192
  help="Platform to use (default: claude)"
130
193
  )
@@ -139,12 +202,16 @@ def main() -> int:
139
202
  project_root = get_repo_root()
140
203
 
141
204
  # Normalize paths
142
- if task_dir_arg.startswith("/"):
143
- task_dir_relative = task_dir_arg[len(str(project_root)) + 1 :]
144
- task_dir_abs = Path(task_dir_arg)
205
+ task_dir_path = Path(task_dir_arg)
206
+ if task_dir_path.is_absolute():
207
+ task_dir_abs = task_dir_path
145
208
  else:
146
- task_dir_relative = task_dir_arg
147
- task_dir_abs = project_root / task_dir_arg
209
+ task_dir_abs = project_root / task_dir_path
210
+
211
+ try:
212
+ task_dir_relative = task_dir_abs.relative_to(project_root).as_posix()
213
+ except ValueError:
214
+ task_dir_relative = str(task_dir_abs)
148
215
 
149
216
  task_json_path = task_dir_abs / FILE_TASK_JSON
150
217
 
@@ -155,11 +222,12 @@ def main() -> int:
155
222
  log_error(f"task.json not found at {task_json_path}")
156
223
  return 1
157
224
 
158
- dispatch_md = adapter.get_agent_path("dispatch", project_root)
159
- if not dispatch_md.is_file():
160
- log_error(f"dispatch.md not found at {dispatch_md}")
161
- log_info(f"Platform: {platform}")
162
- return 1
225
+ if adapter.requires_agent_definition_file:
226
+ dispatch_md = adapter.get_agent_path("dispatch", project_root)
227
+ if not dispatch_md.is_file():
228
+ log_error(f"Agent definition not found at {dispatch_md}")
229
+ log_info(f"Platform: {platform}")
230
+ return 1
163
231
 
164
232
  config_file = get_worktree_config(project_root)
165
233
  if not config_file.is_file():
@@ -173,7 +241,7 @@ def main() -> int:
173
241
  print(f"{Colors.BLUE}=== Multi-Agent Pipeline: Start ==={Colors.NC}")
174
242
  log_info(f"Task: {task_dir_abs}")
175
243
 
176
- task_data = _read_json_file(task_json_path)
244
+ task_data = read_json(task_json_path)
177
245
  if not task_data:
178
246
  log_error("Failed to read task.json")
179
247
  return 1
@@ -222,7 +290,7 @@ def main() -> int:
222
290
  log_info("Step 1: Creating worktree...")
223
291
 
224
292
  # Record current branch as base_branch (PR target)
225
- _, base_branch_out, _ = _run_git_command(
293
+ _, base_branch_out, _ = run_git(
226
294
  ["branch", "--show-current"], cwd=project_root
227
295
  )
228
296
  base_branch = base_branch_out.strip()
@@ -239,18 +307,18 @@ def main() -> int:
239
307
  worktree_path_obj.parent.mkdir(parents=True, exist_ok=True)
240
308
 
241
309
  # Create branch if not exists
242
- ret, _, _ = _run_git_command(
310
+ ret, _, _ = run_git(
243
311
  ["show-ref", "--verify", "--quiet", f"refs/heads/{branch}"],
244
312
  cwd=project_root,
245
313
  )
246
314
  if ret == 0:
247
315
  log_info("Branch exists, checking out...")
248
- ret, _, err = _run_git_command(
316
+ ret, _, err = run_git(
249
317
  ["worktree", "add", worktree_path, branch], cwd=project_root
250
318
  )
251
319
  else:
252
320
  log_info(f"Creating new branch: {branch}")
253
- ret, _, err = _run_git_command(
321
+ ret, _, err = run_git(
254
322
  ["worktree", "add", "-b", branch, worktree_path], cwd=project_root
255
323
  )
256
324
 
@@ -263,7 +331,7 @@ def main() -> int:
263
331
  # Update task.json with worktree_path and base_branch
264
332
  task_data["worktree_path"] = worktree_path
265
333
  task_data["base_branch"] = base_branch
266
- _write_json_file(task_json_path, task_data)
334
+ write_json(task_json_path, task_data)
267
335
 
268
336
  # ----- Copy environment files -----
269
337
  log_info("Copying environment files...")
@@ -294,6 +362,9 @@ def main() -> int:
294
362
  shutil.copytree(str(task_dir_abs), str(task_target_dir))
295
363
  log_success("Task directory copied to worktree")
296
364
 
365
+ # ----- Initialize submodules (before hooks, so hooks can use submodule content) -----
366
+ _init_submodules_for_task(task_data, worktree_path, project_root)
367
+
297
368
  # ----- Run post_create hooks -----
298
369
  log_info("Running post_create hooks...")
299
370
  post_create = get_worktree_post_create_hooks(project_root)
@@ -315,6 +386,9 @@ def main() -> int:
315
386
  else:
316
387
  log_info(f"Step 1: Using existing worktree: {worktree_path}")
317
388
 
389
+ # ----- Initialize submodules (idempotent, for reused worktrees) -----
390
+ _init_submodules_for_task(task_data, worktree_path, project_root)
391
+
318
392
  # =============================================================================
319
393
  # Step 2: Set .current-task in Worktree
320
394
  # =============================================================================
@@ -334,7 +408,7 @@ def main() -> int:
334
408
 
335
409
  # Update task status
336
410
  task_data["status"] = "in_progress"
337
- _write_json_file(task_json_path, task_data)
411
+ write_json(task_json_path, task_data)
338
412
 
339
413
  log_file = Path(worktree_path) / ".agent-log"
340
414
  session_id_file = Path(worktree_path) / ".session-id"