@jahanxu/trellis 0.4.1

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 (422) hide show
  1. package/LICENSE +235 -0
  2. package/README.md +212 -0
  3. package/bin/trellis.js +3 -0
  4. package/dist/cli/index.d.ts +3 -0
  5. package/dist/cli/index.d.ts.map +1 -0
  6. package/dist/cli/index.js +97 -0
  7. package/dist/cli/index.js.map +1 -0
  8. package/dist/commands/init.d.ts +21 -0
  9. package/dist/commands/init.d.ts.map +1 -0
  10. package/dist/commands/init.js +527 -0
  11. package/dist/commands/init.js.map +1 -0
  12. package/dist/commands/update.d.ts +27 -0
  13. package/dist/commands/update.d.ts.map +1 -0
  14. package/dist/commands/update.js +1289 -0
  15. package/dist/commands/update.js.map +1 -0
  16. package/dist/configurators/antigravity.d.ts +8 -0
  17. package/dist/configurators/antigravity.d.ts.map +1 -0
  18. package/dist/configurators/antigravity.js +18 -0
  19. package/dist/configurators/antigravity.js.map +1 -0
  20. package/dist/configurators/claude.d.ts +32 -0
  21. package/dist/configurators/claude.d.ts.map +1 -0
  22. package/dist/configurators/claude.js +98 -0
  23. package/dist/configurators/claude.js.map +1 -0
  24. package/dist/configurators/codex.d.ts +8 -0
  25. package/dist/configurators/codex.d.ts.map +1 -0
  26. package/dist/configurators/codex.js +20 -0
  27. package/dist/configurators/codex.js.map +1 -0
  28. package/dist/configurators/cursor.d.ts +5 -0
  29. package/dist/configurators/cursor.d.ts.map +1 -0
  30. package/dist/configurators/cursor.js +52 -0
  31. package/dist/configurators/cursor.js.map +1 -0
  32. package/dist/configurators/gemini.d.ts +8 -0
  33. package/dist/configurators/gemini.d.ts.map +1 -0
  34. package/dist/configurators/gemini.js +52 -0
  35. package/dist/configurators/gemini.js.map +1 -0
  36. package/dist/configurators/iflow.d.ts +33 -0
  37. package/dist/configurators/iflow.d.ts.map +1 -0
  38. package/dist/configurators/iflow.js +99 -0
  39. package/dist/configurators/iflow.js.map +1 -0
  40. package/dist/configurators/index.d.ts +55 -0
  41. package/dist/configurators/index.d.ts.map +1 -0
  42. package/dist/configurators/index.js +220 -0
  43. package/dist/configurators/index.js.map +1 -0
  44. package/dist/configurators/kilo.d.ts +8 -0
  45. package/dist/configurators/kilo.d.ts.map +1 -0
  46. package/dist/configurators/kilo.js +51 -0
  47. package/dist/configurators/kilo.js.map +1 -0
  48. package/dist/configurators/kiro.d.ts +8 -0
  49. package/dist/configurators/kiro.d.ts.map +1 -0
  50. package/dist/configurators/kiro.js +20 -0
  51. package/dist/configurators/kiro.js.map +1 -0
  52. package/dist/configurators/opencode.d.ts +32 -0
  53. package/dist/configurators/opencode.d.ts.map +1 -0
  54. package/dist/configurators/opencode.js +92 -0
  55. package/dist/configurators/opencode.js.map +1 -0
  56. package/dist/configurators/shared.d.ts +12 -0
  57. package/dist/configurators/shared.d.ts.map +1 -0
  58. package/dist/configurators/shared.js +21 -0
  59. package/dist/configurators/shared.js.map +1 -0
  60. package/dist/configurators/workflow.d.ts +28 -0
  61. package/dist/configurators/workflow.d.ts.map +1 -0
  62. package/dist/configurators/workflow.js +134 -0
  63. package/dist/configurators/workflow.js.map +1 -0
  64. package/dist/constants/paths.d.ts +68 -0
  65. package/dist/constants/paths.d.ts.map +1 -0
  66. package/dist/constants/paths.js +77 -0
  67. package/dist/constants/paths.js.map +1 -0
  68. package/dist/constants/version.d.ts +9 -0
  69. package/dist/constants/version.d.ts.map +1 -0
  70. package/dist/constants/version.js +15 -0
  71. package/dist/constants/version.js.map +1 -0
  72. package/dist/index.d.ts +9 -0
  73. package/dist/index.d.ts.map +1 -0
  74. package/dist/index.js +9 -0
  75. package/dist/index.js.map +1 -0
  76. package/dist/migrations/index.d.ts +54 -0
  77. package/dist/migrations/index.d.ts.map +1 -0
  78. package/dist/migrations/index.js +160 -0
  79. package/dist/migrations/index.js.map +1 -0
  80. package/dist/migrations/manifests/0.1.9.json +30 -0
  81. package/dist/migrations/manifests/0.2.0.json +49 -0
  82. package/dist/migrations/manifests/0.2.12.json +9 -0
  83. package/dist/migrations/manifests/0.2.13.json +9 -0
  84. package/dist/migrations/manifests/0.2.14.json +175 -0
  85. package/dist/migrations/manifests/0.2.15.json +33 -0
  86. package/dist/migrations/manifests/0.3.0-beta.0.json +278 -0
  87. package/dist/migrations/manifests/0.3.0-beta.1.json +9 -0
  88. package/dist/migrations/manifests/0.3.0-beta.10.json +9 -0
  89. package/dist/migrations/manifests/0.3.0-beta.11.json +9 -0
  90. package/dist/migrations/manifests/0.3.0-beta.12.json +9 -0
  91. package/dist/migrations/manifests/0.3.0-beta.13.json +9 -0
  92. package/dist/migrations/manifests/0.3.0-beta.14.json +9 -0
  93. package/dist/migrations/manifests/0.3.0-beta.15.json +9 -0
  94. package/dist/migrations/manifests/0.3.0-beta.16.json +9 -0
  95. package/dist/migrations/manifests/0.3.0-beta.2.json +9 -0
  96. package/dist/migrations/manifests/0.3.0-beta.3.json +9 -0
  97. package/dist/migrations/manifests/0.3.0-beta.4.json +9 -0
  98. package/dist/migrations/manifests/0.3.0-beta.5.json +9 -0
  99. package/dist/migrations/manifests/0.3.0-beta.6.json +9 -0
  100. package/dist/migrations/manifests/0.3.0-beta.7.json +11 -0
  101. package/dist/migrations/manifests/0.3.0-beta.8.json +9 -0
  102. package/dist/migrations/manifests/0.3.0-beta.9.json +9 -0
  103. package/dist/migrations/manifests/0.3.0-rc.0.json +9 -0
  104. package/dist/migrations/manifests/0.3.0-rc.1.json +9 -0
  105. package/dist/migrations/manifests/0.3.0-rc.2.json +9 -0
  106. package/dist/migrations/manifests/0.3.0-rc.3.json +9 -0
  107. package/dist/migrations/manifests/0.3.0-rc.4.json +9 -0
  108. package/dist/migrations/manifests/0.3.0-rc.5.json +9 -0
  109. package/dist/migrations/manifests/0.3.0-rc.6.json +9 -0
  110. package/dist/migrations/manifests/0.3.0.json +11 -0
  111. package/dist/templates/antigravity/index.d.ts +12 -0
  112. package/dist/templates/antigravity/index.d.ts.map +1 -0
  113. package/dist/templates/antigravity/index.js +29 -0
  114. package/dist/templates/antigravity/index.js.map +1 -0
  115. package/dist/templates/claude/agents/check.md +122 -0
  116. package/dist/templates/claude/agents/debug.md +106 -0
  117. package/dist/templates/claude/agents/dispatch.md +214 -0
  118. package/dist/templates/claude/agents/implement.md +96 -0
  119. package/dist/templates/claude/agents/plan.md +396 -0
  120. package/dist/templates/claude/agents/research.md +120 -0
  121. package/dist/templates/claude/commands/trellis/before-backend-dev.md +13 -0
  122. package/dist/templates/claude/commands/trellis/before-frontend-dev.md +13 -0
  123. package/dist/templates/claude/commands/trellis/before-role-work.md +364 -0
  124. package/dist/templates/claude/commands/trellis/brainstorm.md +474 -0
  125. package/dist/templates/claude/commands/trellis/break-loop.md +125 -0
  126. package/dist/templates/claude/commands/trellis/check-backend.md +13 -0
  127. package/dist/templates/claude/commands/trellis/check-cross-layer.md +153 -0
  128. package/dist/templates/claude/commands/trellis/check-frontend.md +13 -0
  129. package/dist/templates/claude/commands/trellis/create-command.md +154 -0
  130. package/dist/templates/claude/commands/trellis/finish-work.md +153 -0
  131. package/dist/templates/claude/commands/trellis/handoff.md +445 -0
  132. package/dist/templates/claude/commands/trellis/integrate-skill.md +219 -0
  133. package/dist/templates/claude/commands/trellis/onboard.md +358 -0
  134. package/dist/templates/claude/commands/trellis/parallel.md +193 -0
  135. package/dist/templates/claude/commands/trellis/pick-task.md +515 -0
  136. package/dist/templates/claude/commands/trellis/record-session.md +62 -0
  137. package/dist/templates/claude/commands/trellis/start.md +373 -0
  138. package/dist/templates/claude/commands/trellis/update-spec.md +354 -0
  139. package/dist/templates/claude/hooks/inject-subagent-context.py +873 -0
  140. package/dist/templates/claude/hooks/ralph-loop.py +388 -0
  141. package/dist/templates/claude/hooks/session-start.py +200 -0
  142. package/dist/templates/claude/index.d.ts +54 -0
  143. package/dist/templates/claude/index.d.ts.map +1 -0
  144. package/dist/templates/claude/index.js +85 -0
  145. package/dist/templates/claude/index.js.map +1 -0
  146. package/dist/templates/claude/settings.json +41 -0
  147. package/dist/templates/codex/index.d.ts +18 -0
  148. package/dist/templates/codex/index.d.ts.map +1 -0
  149. package/dist/templates/codex/index.js +40 -0
  150. package/dist/templates/codex/index.js.map +1 -0
  151. package/dist/templates/codex/skills/before-backend-dev/SKILL.md +18 -0
  152. package/dist/templates/codex/skills/before-frontend-dev/SKILL.md +18 -0
  153. package/dist/templates/codex/skills/brainstorm/SKILL.md +479 -0
  154. package/dist/templates/codex/skills/break-loop/SKILL.md +130 -0
  155. package/dist/templates/codex/skills/check-backend/SKILL.md +18 -0
  156. package/dist/templates/codex/skills/check-cross-layer/SKILL.md +158 -0
  157. package/dist/templates/codex/skills/check-frontend/SKILL.md +18 -0
  158. package/dist/templates/codex/skills/create-command/SKILL.md +101 -0
  159. package/dist/templates/codex/skills/finish-work/SKILL.md +148 -0
  160. package/dist/templates/codex/skills/integrate-skill/SKILL.md +221 -0
  161. package/dist/templates/codex/skills/onboard/SKILL.md +363 -0
  162. package/dist/templates/codex/skills/record-session/SKILL.md +67 -0
  163. package/dist/templates/codex/skills/start/SKILL.md +330 -0
  164. package/dist/templates/codex/skills/update-spec/SKILL.md +335 -0
  165. package/dist/templates/cursor/commands/trellis-before-backend-dev.md +13 -0
  166. package/dist/templates/cursor/commands/trellis-before-frontend-dev.md +13 -0
  167. package/dist/templates/cursor/commands/trellis-brainstorm.md +474 -0
  168. package/dist/templates/cursor/commands/trellis-break-loop.md +107 -0
  169. package/dist/templates/cursor/commands/trellis-check-backend.md +13 -0
  170. package/dist/templates/cursor/commands/trellis-check-cross-layer.md +153 -0
  171. package/dist/templates/cursor/commands/trellis-check-frontend.md +13 -0
  172. package/dist/templates/cursor/commands/trellis-create-command.md +154 -0
  173. package/dist/templates/cursor/commands/trellis-finish-work.md +143 -0
  174. package/dist/templates/cursor/commands/trellis-integrate-skill.md +219 -0
  175. package/dist/templates/cursor/commands/trellis-onboard.md +358 -0
  176. package/dist/templates/cursor/commands/trellis-record-session.md +62 -0
  177. package/dist/templates/cursor/commands/trellis-start.md +366 -0
  178. package/dist/templates/cursor/commands/trellis-update-spec.md +354 -0
  179. package/dist/templates/cursor/index.d.ts +24 -0
  180. package/dist/templates/cursor/index.d.ts.map +1 -0
  181. package/dist/templates/cursor/index.js +44 -0
  182. package/dist/templates/cursor/index.js.map +1 -0
  183. package/dist/templates/extract.d.ts +166 -0
  184. package/dist/templates/extract.d.ts.map +1 -0
  185. package/dist/templates/extract.js +296 -0
  186. package/dist/templates/extract.js.map +1 -0
  187. package/dist/templates/gemini/commands/trellis/before-backend-dev.toml +17 -0
  188. package/dist/templates/gemini/commands/trellis/before-frontend-dev.toml +17 -0
  189. package/dist/templates/gemini/commands/trellis/brainstorm.toml +420 -0
  190. package/dist/templates/gemini/commands/trellis/break-loop.toml +129 -0
  191. package/dist/templates/gemini/commands/trellis/check-backend.toml +17 -0
  192. package/dist/templates/gemini/commands/trellis/check-cross-layer.toml +147 -0
  193. package/dist/templates/gemini/commands/trellis/check-frontend.toml +17 -0
  194. package/dist/templates/gemini/commands/trellis/create-command.toml +119 -0
  195. package/dist/templates/gemini/commands/trellis/finish-work.toml +133 -0
  196. package/dist/templates/gemini/commands/trellis/integrate-skill.toml +104 -0
  197. package/dist/templates/gemini/commands/trellis/onboard.toml +111 -0
  198. package/dist/templates/gemini/commands/trellis/record-session.toml +66 -0
  199. package/dist/templates/gemini/commands/trellis/start.toml +292 -0
  200. package/dist/templates/gemini/commands/trellis/update-spec.toml +132 -0
  201. package/dist/templates/gemini/index.d.ts +21 -0
  202. package/dist/templates/gemini/index.d.ts.map +1 -0
  203. package/dist/templates/gemini/index.js +44 -0
  204. package/dist/templates/gemini/index.js.map +1 -0
  205. package/dist/templates/iflow/agents/check.md +122 -0
  206. package/dist/templates/iflow/agents/debug.md +106 -0
  207. package/dist/templates/iflow/agents/dispatch.md +214 -0
  208. package/dist/templates/iflow/agents/implement.md +96 -0
  209. package/dist/templates/iflow/agents/plan.md +396 -0
  210. package/dist/templates/iflow/agents/research.md +120 -0
  211. package/dist/templates/iflow/commands/trellis/before-backend-dev.md +13 -0
  212. package/dist/templates/iflow/commands/trellis/before-frontend-dev.md +13 -0
  213. package/dist/templates/iflow/commands/trellis/brainstorm.md +474 -0
  214. package/dist/templates/iflow/commands/trellis/break-loop.md +125 -0
  215. package/dist/templates/iflow/commands/trellis/check-backend.md +13 -0
  216. package/dist/templates/iflow/commands/trellis/check-cross-layer.md +153 -0
  217. package/dist/templates/iflow/commands/trellis/check-frontend.md +13 -0
  218. package/dist/templates/iflow/commands/trellis/create-command.md +152 -0
  219. package/dist/templates/iflow/commands/trellis/finish-work.md +153 -0
  220. package/dist/templates/iflow/commands/trellis/integrate-skill.md +219 -0
  221. package/dist/templates/iflow/commands/trellis/onboard.md +358 -0
  222. package/dist/templates/iflow/commands/trellis/parallel.md +193 -0
  223. package/dist/templates/iflow/commands/trellis/record-session.md +62 -0
  224. package/dist/templates/iflow/commands/trellis/start.md +373 -0
  225. package/dist/templates/iflow/commands/trellis/update-spec.md +354 -0
  226. package/dist/templates/iflow/hooks/inject-subagent-context.py +788 -0
  227. package/dist/templates/iflow/hooks/ralph-loop.py +388 -0
  228. package/dist/templates/iflow/hooks/session-start.py +143 -0
  229. package/dist/templates/iflow/index.d.ts +54 -0
  230. package/dist/templates/iflow/index.d.ts.map +1 -0
  231. package/dist/templates/iflow/index.js +85 -0
  232. package/dist/templates/iflow/index.js.map +1 -0
  233. package/dist/templates/iflow/settings.json +40 -0
  234. package/dist/templates/kilo/commands/trellis/before-backend-dev.md +13 -0
  235. package/dist/templates/kilo/commands/trellis/before-frontend-dev.md +13 -0
  236. package/dist/templates/kilo/commands/trellis/brainstorm.md +474 -0
  237. package/dist/templates/kilo/commands/trellis/break-loop.md +125 -0
  238. package/dist/templates/kilo/commands/trellis/check-backend.md +13 -0
  239. package/dist/templates/kilo/commands/trellis/check-cross-layer.md +153 -0
  240. package/dist/templates/kilo/commands/trellis/check-frontend.md +13 -0
  241. package/dist/templates/kilo/commands/trellis/create-command.md +152 -0
  242. package/dist/templates/kilo/commands/trellis/finish-work.md +129 -0
  243. package/dist/templates/kilo/commands/trellis/integrate-skill.md +219 -0
  244. package/dist/templates/kilo/commands/trellis/onboard.md +358 -0
  245. package/dist/templates/kilo/commands/trellis/parallel.md +194 -0
  246. package/dist/templates/kilo/commands/trellis/record-session.md +62 -0
  247. package/dist/templates/kilo/commands/trellis/start.md +321 -0
  248. package/dist/templates/kilo/commands/trellis/update-spec.md +285 -0
  249. package/dist/templates/kilo/index.d.ts +16 -0
  250. package/dist/templates/kilo/index.d.ts.map +1 -0
  251. package/dist/templates/kilo/index.js +39 -0
  252. package/dist/templates/kilo/index.js.map +1 -0
  253. package/dist/templates/kiro/index.d.ts +18 -0
  254. package/dist/templates/kiro/index.d.ts.map +1 -0
  255. package/dist/templates/kiro/index.js +40 -0
  256. package/dist/templates/kiro/index.js.map +1 -0
  257. package/dist/templates/kiro/skills/before-backend-dev/SKILL.md +18 -0
  258. package/dist/templates/kiro/skills/before-frontend-dev/SKILL.md +18 -0
  259. package/dist/templates/kiro/skills/brainstorm/SKILL.md +479 -0
  260. package/dist/templates/kiro/skills/break-loop/SKILL.md +130 -0
  261. package/dist/templates/kiro/skills/check-backend/SKILL.md +18 -0
  262. package/dist/templates/kiro/skills/check-cross-layer/SKILL.md +158 -0
  263. package/dist/templates/kiro/skills/check-frontend/SKILL.md +18 -0
  264. package/dist/templates/kiro/skills/create-command/SKILL.md +101 -0
  265. package/dist/templates/kiro/skills/finish-work/SKILL.md +148 -0
  266. package/dist/templates/kiro/skills/integrate-skill/SKILL.md +221 -0
  267. package/dist/templates/kiro/skills/onboard/SKILL.md +363 -0
  268. package/dist/templates/kiro/skills/record-session/SKILL.md +67 -0
  269. package/dist/templates/kiro/skills/start/SKILL.md +330 -0
  270. package/dist/templates/kiro/skills/update-spec/SKILL.md +335 -0
  271. package/dist/templates/markdown/agents.md +18 -0
  272. package/dist/templates/markdown/gitignore.txt +12 -0
  273. package/dist/templates/markdown/index.d.ts +27 -0
  274. package/dist/templates/markdown/index.d.ts.map +1 -0
  275. package/dist/templates/markdown/index.js +52 -0
  276. package/dist/templates/markdown/index.js.map +1 -0
  277. package/dist/templates/markdown/spec/backend/database-guidelines.md.txt +51 -0
  278. package/dist/templates/markdown/spec/backend/directory-structure.md.txt +54 -0
  279. package/dist/templates/markdown/spec/backend/error-handling.md.txt +51 -0
  280. package/dist/templates/markdown/spec/backend/index.md +40 -0
  281. package/dist/templates/markdown/spec/backend/index.md.txt +38 -0
  282. package/dist/templates/markdown/spec/backend/logging-guidelines.md.txt +51 -0
  283. package/dist/templates/markdown/spec/backend/quality-guidelines.md.txt +51 -0
  284. package/dist/templates/markdown/spec/backend/script-conventions.md +467 -0
  285. package/dist/templates/markdown/spec/frontend/component-guidelines.md.txt +59 -0
  286. package/dist/templates/markdown/spec/frontend/directory-structure.md.txt +54 -0
  287. package/dist/templates/markdown/spec/frontend/hook-guidelines.md.txt +51 -0
  288. package/dist/templates/markdown/spec/frontend/index.md.txt +39 -0
  289. package/dist/templates/markdown/spec/frontend/quality-guidelines.md.txt +51 -0
  290. package/dist/templates/markdown/spec/frontend/state-management.md.txt +51 -0
  291. package/dist/templates/markdown/spec/frontend/type-safety.md.txt +51 -0
  292. package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md +118 -0
  293. package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +92 -0
  294. package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +94 -0
  295. package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md +394 -0
  296. package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +319 -0
  297. package/dist/templates/markdown/spec/guides/index.md.txt +79 -0
  298. package/dist/templates/markdown/workspace-index.md +123 -0
  299. package/dist/templates/markdown/worktree.yaml.txt +58 -0
  300. package/dist/templates/opencode/agents/check.md +146 -0
  301. package/dist/templates/opencode/agents/debug.md +129 -0
  302. package/dist/templates/opencode/agents/dispatch.md +223 -0
  303. package/dist/templates/opencode/agents/implement.md +120 -0
  304. package/dist/templates/opencode/agents/research.md +147 -0
  305. package/dist/templates/opencode/agents/trellis-plan.md +427 -0
  306. package/dist/templates/opencode/commands/trellis/before-backend-dev.md +13 -0
  307. package/dist/templates/opencode/commands/trellis/before-frontend-dev.md +13 -0
  308. package/dist/templates/opencode/commands/trellis/brainstorm.md +474 -0
  309. package/dist/templates/opencode/commands/trellis/break-loop.md +125 -0
  310. package/dist/templates/opencode/commands/trellis/check-backend.md +13 -0
  311. package/dist/templates/opencode/commands/trellis/check-cross-layer.md +153 -0
  312. package/dist/templates/opencode/commands/trellis/check-frontend.md +13 -0
  313. package/dist/templates/opencode/commands/trellis/create-command.md +154 -0
  314. package/dist/templates/opencode/commands/trellis/finish-work.md +144 -0
  315. package/dist/templates/opencode/commands/trellis/integrate-skill.md +219 -0
  316. package/dist/templates/opencode/commands/trellis/migrate-specs.md +0 -0
  317. package/dist/templates/opencode/commands/trellis/onboard.md +358 -0
  318. package/dist/templates/opencode/commands/trellis/parallel.md +194 -0
  319. package/dist/templates/opencode/commands/trellis/record-session.md +62 -0
  320. package/dist/templates/opencode/commands/trellis/start.md +338 -0
  321. package/dist/templates/opencode/commands/trellis/update-spec.md +354 -0
  322. package/dist/templates/opencode/lib/trellis-context.js +436 -0
  323. package/dist/templates/opencode/package.json +5 -0
  324. package/dist/templates/opencode/plugin/inject-subagent-context.js +538 -0
  325. package/dist/templates/opencode/plugin/session-start.js +192 -0
  326. package/dist/templates/trellis/VERSION +1 -0
  327. package/dist/templates/trellis/deliverables/README.md +51 -0
  328. package/dist/templates/trellis/gitignore.txt +29 -0
  329. package/dist/templates/trellis/index.d.ts +49 -0
  330. package/dist/templates/trellis/index.d.ts.map +1 -0
  331. package/dist/templates/trellis/index.js +92 -0
  332. package/dist/templates/trellis/index.js.map +1 -0
  333. package/dist/templates/trellis/paths.README.md +277 -0
  334. package/dist/templates/trellis/paths.yaml +41 -0
  335. package/dist/templates/trellis/pool/implementations.json +5 -0
  336. package/dist/templates/trellis/pool/prototypes.json +5 -0
  337. package/dist/templates/trellis/pool/requirements.json +5 -0
  338. package/dist/templates/trellis/scripts/__init__.py +5 -0
  339. package/dist/templates/trellis/scripts/add_session.py +391 -0
  340. package/dist/templates/trellis/scripts/common/__init__.py +80 -0
  341. package/dist/templates/trellis/scripts/common/cli_adapter.py +522 -0
  342. package/dist/templates/trellis/scripts/common/developer.py +189 -0
  343. package/dist/templates/trellis/scripts/common/git_context.py +383 -0
  344. package/dist/templates/trellis/scripts/common/paths.py +346 -0
  345. package/dist/templates/trellis/scripts/common/phase.py +253 -0
  346. package/dist/templates/trellis/scripts/common/project_paths.py +189 -0
  347. package/dist/templates/trellis/scripts/common/registry.py +365 -0
  348. package/dist/templates/trellis/scripts/common/task_queue.py +255 -0
  349. package/dist/templates/trellis/scripts/common/task_utils.py +177 -0
  350. package/dist/templates/trellis/scripts/common/worktree.py +218 -0
  351. package/dist/templates/trellis/scripts/create_bootstrap.py +290 -0
  352. package/dist/templates/trellis/scripts/get_context.py +16 -0
  353. package/dist/templates/trellis/scripts/get_developer.py +26 -0
  354. package/dist/templates/trellis/scripts/handoff_generator.py +380 -0
  355. package/dist/templates/trellis/scripts/init_developer.py +51 -0
  356. package/dist/templates/trellis/scripts/multi_agent/__init__.py +5 -0
  357. package/dist/templates/trellis/scripts/multi_agent/cleanup.py +403 -0
  358. package/dist/templates/trellis/scripts/multi_agent/create_pr.py +329 -0
  359. package/dist/templates/trellis/scripts/multi_agent/plan.py +233 -0
  360. package/dist/templates/trellis/scripts/multi_agent/start.py +461 -0
  361. package/dist/templates/trellis/scripts/multi_agent/status.py +817 -0
  362. package/dist/templates/trellis/scripts/pool.py +373 -0
  363. package/dist/templates/trellis/scripts/task.py +1162 -0
  364. package/dist/templates/trellis/scripts-shell-archive/add-session.sh +384 -0
  365. package/dist/templates/trellis/scripts-shell-archive/common/developer.sh +129 -0
  366. package/dist/templates/trellis/scripts-shell-archive/common/git-context.sh +263 -0
  367. package/dist/templates/trellis/scripts-shell-archive/common/paths.sh +208 -0
  368. package/dist/templates/trellis/scripts-shell-archive/common/phase.sh +150 -0
  369. package/dist/templates/trellis/scripts-shell-archive/common/registry.sh +247 -0
  370. package/dist/templates/trellis/scripts-shell-archive/common/task-queue.sh +142 -0
  371. package/dist/templates/trellis/scripts-shell-archive/common/task-utils.sh +151 -0
  372. package/dist/templates/trellis/scripts-shell-archive/common/worktree.sh +128 -0
  373. package/dist/templates/trellis/scripts-shell-archive/create-bootstrap.sh +299 -0
  374. package/dist/templates/trellis/scripts-shell-archive/get-context.sh +7 -0
  375. package/dist/templates/trellis/scripts-shell-archive/get-developer.sh +15 -0
  376. package/dist/templates/trellis/scripts-shell-archive/init-developer.sh +34 -0
  377. package/dist/templates/trellis/scripts-shell-archive/multi-agent/cleanup.sh +396 -0
  378. package/dist/templates/trellis/scripts-shell-archive/multi-agent/create-pr.sh +241 -0
  379. package/dist/templates/trellis/scripts-shell-archive/multi-agent/plan.sh +207 -0
  380. package/dist/templates/trellis/scripts-shell-archive/multi-agent/start.sh +317 -0
  381. package/dist/templates/trellis/scripts-shell-archive/multi-agent/status.sh +828 -0
  382. package/dist/templates/trellis/scripts-shell-archive/task.sh +1204 -0
  383. package/dist/templates/trellis/spec/roles/designer/index.md +243 -0
  384. package/dist/templates/trellis/spec/roles/designer/mock-data-standards.md +481 -0
  385. package/dist/templates/trellis/spec/roles/designer/prototype-guidelines.md +429 -0
  386. package/dist/templates/trellis/spec/roles/frontend-impl/api-integration.md +565 -0
  387. package/dist/templates/trellis/spec/roles/frontend-impl/index.md +321 -0
  388. package/dist/templates/trellis/spec/roles/frontend-impl/state-management.md +599 -0
  389. package/dist/templates/trellis/spec/roles/pm/index.md +112 -0
  390. package/dist/templates/trellis/spec/roles/pm/prd-template.md +124 -0
  391. package/dist/templates/trellis/tasks/.gitkeep +0 -0
  392. package/dist/templates/trellis/workflow.md +416 -0
  393. package/dist/templates/trellis/worktree.yaml +47 -0
  394. package/dist/types/ai-tools.d.ts +56 -0
  395. package/dist/types/ai-tools.d.ts.map +1 -0
  396. package/dist/types/ai-tools.js +103 -0
  397. package/dist/types/ai-tools.js.map +1 -0
  398. package/dist/types/migration.d.ts +86 -0
  399. package/dist/types/migration.d.ts.map +1 -0
  400. package/dist/types/migration.js +8 -0
  401. package/dist/types/migration.js.map +1 -0
  402. package/dist/utils/compare-versions.d.ts +12 -0
  403. package/dist/utils/compare-versions.d.ts.map +1 -0
  404. package/dist/utils/compare-versions.js +76 -0
  405. package/dist/utils/compare-versions.js.map +1 -0
  406. package/dist/utils/file-writer.d.ts +23 -0
  407. package/dist/utils/file-writer.d.ts.map +1 -0
  408. package/dist/utils/file-writer.js +140 -0
  409. package/dist/utils/file-writer.js.map +1 -0
  410. package/dist/utils/project-detector.d.ts +16 -0
  411. package/dist/utils/project-detector.d.ts.map +1 -0
  412. package/dist/utils/project-detector.js +186 -0
  413. package/dist/utils/project-detector.js.map +1 -0
  414. package/dist/utils/template-fetcher.d.ts +51 -0
  415. package/dist/utils/template-fetcher.d.ts.map +1 -0
  416. package/dist/utils/template-fetcher.js +174 -0
  417. package/dist/utils/template-fetcher.js.map +1 -0
  418. package/dist/utils/template-hash.d.ts +78 -0
  419. package/dist/utils/template-hash.d.ts.map +1 -0
  420. package/dist/utils/template-hash.js +233 -0
  421. package/dist/utils/template-hash.js.map +1 -0
  422. package/package.json +87 -0
@@ -0,0 +1,873 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Multi-Agent Pipeline Context Injection Hook
5
+
6
+ Core Design Philosophy:
7
+ - Dispatch becomes a pure dispatcher, only responsible for "calling subagents"
8
+ - Hook is responsible for injecting all context, subagent works autonomously with complete info
9
+ - Each agent has a dedicated jsonl file defining its context
10
+ - No resume needed, no segmentation, behavior controlled by code not prompt
11
+
12
+ Trigger: PreToolUse (before Task tool call)
13
+
14
+ Context Source: .trellis/.current-task points to task directory
15
+ - implement.jsonl - Implement agent dedicated context
16
+ - check.jsonl - Check agent dedicated context
17
+ - debug.jsonl - Debug agent dedicated context
18
+ - research.jsonl - Research agent dedicated context (optional, usually not needed)
19
+ - cr.jsonl - Code review dedicated context
20
+ - prd.md - Requirements document
21
+ - info.md - Technical design
22
+ - codex-review-output.txt - Code Review results
23
+ """
24
+
25
+ # IMPORTANT: Suppress all warnings FIRST
26
+ import warnings
27
+ warnings.filterwarnings("ignore")
28
+
29
+ import json
30
+ import os
31
+ import sys
32
+ from pathlib import Path
33
+ from typing import Optional, List, Tuple
34
+
35
+ # IMPORTANT: Force stdout to use UTF-8 on Windows
36
+ # This fixes UnicodeEncodeError when outputting non-ASCII characters
37
+ if sys.platform == "win32":
38
+ import io as _io
39
+ if hasattr(sys.stdout, "reconfigure"):
40
+ sys.stdout.reconfigure(encoding="utf-8", errors="replace") # type: ignore[union-attr]
41
+ elif hasattr(sys.stdout, "detach"):
42
+ sys.stdout = _io.TextIOWrapper(sys.stdout.detach(), encoding="utf-8", errors="replace") # type: ignore[union-attr]
43
+
44
+ # =============================================================================
45
+ # Path Constants (change here to rename directories)
46
+ # =============================================================================
47
+
48
+ DIR_WORKFLOW = ".trellis"
49
+ DIR_WORKSPACE = "workspace"
50
+ DIR_TASKS = "tasks"
51
+ DIR_SPEC = "spec"
52
+ FILE_CURRENT_TASK = ".current-task"
53
+ FILE_TASK_JSON = "task.json"
54
+
55
+ # Agents that don't update phase (can be called at any time)
56
+ AGENTS_NO_PHASE_UPDATE = {"debug", "research"}
57
+
58
+ # =============================================================================
59
+ # Subagent Constants (change here to rename subagent types)
60
+ # =============================================================================
61
+
62
+ AGENT_IMPLEMENT = "implement"
63
+ AGENT_CHECK = "check"
64
+ AGENT_DEBUG = "debug"
65
+ AGENT_RESEARCH = "research"
66
+
67
+ # Agents that require a task directory
68
+ AGENTS_REQUIRE_TASK = (AGENT_IMPLEMENT, AGENT_CHECK, AGENT_DEBUG)
69
+ # All supported agents
70
+ AGENTS_ALL = (AGENT_IMPLEMENT, AGENT_CHECK, AGENT_DEBUG, AGENT_RESEARCH)
71
+
72
+
73
+ def find_repo_root(start_path: str) -> Optional[str]:
74
+ """
75
+ Find git repo root from start_path upwards
76
+
77
+ Returns:
78
+ Repo root path, or None if not found
79
+ """
80
+ current = Path(start_path).resolve()
81
+ while current != current.parent:
82
+ if (current / ".git").exists():
83
+ return str(current)
84
+ current = current.parent
85
+ return None
86
+
87
+
88
+ def get_current_task(repo_root: str) -> Optional[str]:
89
+ """
90
+ Read current task directory path from .trellis/.current-task
91
+
92
+ Returns:
93
+ Task directory relative path (relative to repo_root)
94
+ None if not set
95
+ """
96
+ current_task_file = os.path.join(repo_root, DIR_WORKFLOW, FILE_CURRENT_TASK)
97
+ if not os.path.exists(current_task_file):
98
+ return None
99
+
100
+ try:
101
+ with open(current_task_file, "r", encoding="utf-8") as f:
102
+ content = f.read().strip()
103
+ return content if content else None
104
+ except Exception:
105
+ return None
106
+
107
+
108
+ def update_current_phase(repo_root: str, task_dir: str, subagent_type: str) -> None:
109
+ """
110
+ Update current_phase in task.json based on subagent_type.
111
+
112
+ This ensures phase tracking is always accurate, regardless of whether
113
+ dispatch agent remembers to update it.
114
+
115
+ Logic:
116
+ - Read next_action array from task.json
117
+ - Find the next phase whose action matches subagent_type
118
+ - Only move forward, never backward
119
+ - Some agents (debug, research) don't update phase
120
+ """
121
+ if subagent_type in AGENTS_NO_PHASE_UPDATE:
122
+ return
123
+
124
+ task_json_path = os.path.join(repo_root, task_dir, FILE_TASK_JSON)
125
+ if not os.path.exists(task_json_path):
126
+ return
127
+
128
+ try:
129
+ with open(task_json_path, "r", encoding="utf-8") as f:
130
+ task_data = json.load(f)
131
+
132
+ current_phase = task_data.get("current_phase", 0)
133
+ next_actions = task_data.get("next_action", [])
134
+
135
+ # Map action names to subagent types
136
+ # "implement" -> "implement", "check" -> "check", "finish" -> "check"
137
+ action_to_agent = {
138
+ "implement": "implement",
139
+ "check": "check",
140
+ "finish": "check", # finish uses check agent
141
+ }
142
+
143
+ # Find the next phase that matches this subagent_type
144
+ new_phase = None
145
+ for action in next_actions:
146
+ phase_num = action.get("phase", 0)
147
+ action_name = action.get("action", "")
148
+ expected_agent = action_to_agent.get(action_name)
149
+
150
+ # Only consider phases after current_phase
151
+ if phase_num > current_phase and expected_agent == subagent_type:
152
+ new_phase = phase_num
153
+ break
154
+
155
+ if new_phase is not None:
156
+ task_data["current_phase"] = new_phase
157
+
158
+ with open(task_json_path, "w", encoding="utf-8") as f:
159
+ json.dump(task_data, f, indent=2, ensure_ascii=False)
160
+ except Exception:
161
+ # Don't fail the hook if phase update fails
162
+ pass
163
+
164
+
165
+ def read_file_content(base_path: str, file_path: str) -> Optional[str]:
166
+ """Read file content, return None if file doesn't exist"""
167
+ full_path = os.path.join(base_path, file_path)
168
+ if os.path.exists(full_path) and os.path.isfile(full_path):
169
+ try:
170
+ with open(full_path, "r", encoding="utf-8") as f:
171
+ return f.read()
172
+ except Exception:
173
+ return None
174
+ return None
175
+
176
+
177
+ def read_directory_contents(
178
+ base_path: str, dir_path: str, max_files: int = 20
179
+ ) -> list[tuple[str, str]]:
180
+ """
181
+ Read all .md files in a directory
182
+
183
+ Args:
184
+ base_path: Base path (usually repo_root)
185
+ dir_path: Directory relative path
186
+ max_files: Max files to read (prevent huge directories)
187
+
188
+ Returns:
189
+ [(file_path, content), ...]
190
+ """
191
+ full_path = os.path.join(base_path, dir_path)
192
+ if not os.path.exists(full_path) or not os.path.isdir(full_path):
193
+ return []
194
+
195
+ results = []
196
+ try:
197
+ # Only read .md files, sorted by filename
198
+ md_files = sorted(
199
+ [
200
+ f
201
+ for f in os.listdir(full_path)
202
+ if f.endswith(".md") and os.path.isfile(os.path.join(full_path, f))
203
+ ]
204
+ )
205
+
206
+ for filename in md_files[:max_files]:
207
+ file_full_path = os.path.join(full_path, filename)
208
+ relative_path = os.path.join(dir_path, filename)
209
+ try:
210
+ with open(file_full_path, "r", encoding="utf-8") as f:
211
+ content = f.read()
212
+ results.append((relative_path, content))
213
+ except Exception:
214
+ continue
215
+ except Exception:
216
+ pass
217
+
218
+ return results
219
+
220
+
221
+ def read_jsonl_entries(base_path: str, jsonl_path: str) -> list[tuple[str, str]]:
222
+ """
223
+ Read all file/directory contents referenced in jsonl file
224
+
225
+ Schema:
226
+ {"file": "path/to/file.md", "reason": "..."}
227
+ {"file": "path/to/dir/", "type": "directory", "reason": "..."}
228
+
229
+ Returns:
230
+ [(path, content), ...]
231
+ """
232
+ full_path = os.path.join(base_path, jsonl_path)
233
+ if not os.path.exists(full_path):
234
+ return []
235
+
236
+ results = []
237
+ try:
238
+ with open(full_path, "r", encoding="utf-8") as f:
239
+ for line in f:
240
+ line = line.strip()
241
+ if not line:
242
+ continue
243
+ try:
244
+ item = json.loads(line)
245
+ file_path = item.get("file") or item.get("path")
246
+ entry_type = item.get("type", "file")
247
+
248
+ if not file_path:
249
+ continue
250
+
251
+ if entry_type == "directory":
252
+ # Read all .md files in directory
253
+ dir_contents = read_directory_contents(base_path, file_path)
254
+ results.extend(dir_contents)
255
+ else:
256
+ # Read single file
257
+ content = read_file_content(base_path, file_path)
258
+ if content:
259
+ results.append((file_path, content))
260
+ except json.JSONDecodeError:
261
+ continue
262
+ except Exception:
263
+ pass
264
+
265
+ return results
266
+
267
+
268
+ def read_source_json(repo_root: str, task_dir: str) -> Optional[dict]:
269
+ """
270
+ Read source.json from task directory (三角色协作上游引用)
271
+
272
+ Returns:
273
+ source.json data or None if not exists
274
+ """
275
+ source_json_path = os.path.join(repo_root, task_dir, "source.json")
276
+ if not os.path.exists(source_json_path):
277
+ return None
278
+
279
+ try:
280
+ with open(source_json_path, "r", encoding="utf-8") as f:
281
+ return json.load(f)
282
+ except Exception:
283
+ return None
284
+
285
+
286
+ def inject_upstream_context(repo_root: str, task_dir: str) -> list[tuple[str, str]]:
287
+ """
288
+ Inject upstream outputs for three-role collaboration
289
+
290
+ Reads source.json and injects:
291
+ 1. Upstream HANDOFF document
292
+ 2. Upstream deliverables (requirements/prototypes)
293
+
294
+ Returns:
295
+ [(path, content), ...]
296
+ """
297
+ source_data = read_source_json(repo_root, task_dir)
298
+ if not source_data or "based_on" not in source_data:
299
+ return []
300
+
301
+ results = []
302
+ based_on = source_data["based_on"]
303
+
304
+ # 1. Inject upstream HANDOFF document
305
+ handoff_doc = based_on.get("handoff_doc")
306
+ if handoff_doc:
307
+ handoff_content = read_file_content(repo_root, handoff_doc)
308
+ if handoff_content:
309
+ results.append((handoff_doc, handoff_content))
310
+
311
+ # 2. Inject upstream deliverables directory (all .md files)
312
+ upstream_path = based_on.get("path")
313
+ if upstream_path:
314
+ upstream_contents = read_directory_contents(repo_root, upstream_path)
315
+ results.extend(upstream_contents)
316
+
317
+ return results
318
+
319
+
320
+ def get_agent_context(repo_root: str, task_dir: str, agent_type: str) -> str:
321
+ """
322
+ Get complete context for specified agent
323
+
324
+ Prioritize agent-specific jsonl, fallback to spec.jsonl if not exists
325
+ """
326
+ context_parts = []
327
+
328
+ # 1. Try agent-specific jsonl
329
+ agent_jsonl = f"{task_dir}/{agent_type}.jsonl"
330
+ agent_entries = read_jsonl_entries(repo_root, agent_jsonl)
331
+
332
+ # 2. If agent-specific jsonl doesn't exist or empty, fallback to spec.jsonl
333
+ if not agent_entries:
334
+ agent_entries = read_jsonl_entries(repo_root, f"{task_dir}/spec.jsonl")
335
+
336
+ # 3. Add all files from jsonl
337
+ for file_path, content in agent_entries:
338
+ context_parts.append(f"=== {file_path} ===\n{content}")
339
+
340
+ return "\n\n".join(context_parts)
341
+
342
+
343
+ def get_implement_context(repo_root: str, task_dir: str) -> str:
344
+ """
345
+ Complete context for Implement Agent
346
+
347
+ Read order:
348
+ 1. All files in implement.jsonl (dev specs)
349
+ 2. Upstream outputs (HANDOFF + deliverables, if three-role collaboration)
350
+ 3. prd.md (requirements)
351
+ 4. info.md (technical design)
352
+ """
353
+ context_parts = []
354
+
355
+ # 1. Read implement.jsonl (or fallback to spec.jsonl)
356
+ base_context = get_agent_context(repo_root, task_dir, "implement")
357
+ if base_context:
358
+ context_parts.append(base_context)
359
+
360
+ # 2. Inject upstream outputs (三角色协作)
361
+ upstream_entries = inject_upstream_context(repo_root, task_dir)
362
+ if upstream_entries:
363
+ context_parts.append("=== Upstream Outputs (三角色协作上游产出) ===")
364
+ for file_path, content in upstream_entries:
365
+ context_parts.append(f"=== {file_path} ===\n{content}")
366
+
367
+ # 3. Requirements document
368
+ prd_content = read_file_content(repo_root, f"{task_dir}/prd.md")
369
+ if prd_content:
370
+ context_parts.append(f"=== {task_dir}/prd.md (Requirements) ===\n{prd_content}")
371
+
372
+ # 4. Technical design
373
+ info_content = read_file_content(repo_root, f"{task_dir}/info.md")
374
+ if info_content:
375
+ context_parts.append(
376
+ f"=== {task_dir}/info.md (Technical Design) ===\n{info_content}"
377
+ )
378
+
379
+ return "\n\n".join(context_parts)
380
+
381
+
382
+ def get_check_context(repo_root: str, task_dir: str) -> str:
383
+ """
384
+ Complete context for Check Agent
385
+
386
+ Read order:
387
+ 1. All files in check.jsonl (check specs + dev specs)
388
+ 2. Upstream outputs (HANDOFF + deliverables, if three-role collaboration)
389
+ 3. prd.md (for understanding task intent)
390
+ """
391
+ context_parts = []
392
+
393
+ # 1. Read check.jsonl (or fallback to spec.jsonl + hardcoded check files)
394
+ check_entries = read_jsonl_entries(repo_root, f"{task_dir}/check.jsonl")
395
+
396
+ if check_entries:
397
+ for file_path, content in check_entries:
398
+ context_parts.append(f"=== {file_path} ===\n{content}")
399
+ else:
400
+ # Fallback: use hardcoded check files + spec.jsonl
401
+ check_files = [
402
+ (".claude/commands/trellis/finish-work.md", "Finish work checklist"),
403
+ (".claude/commands/trellis/check-cross-layer.md", "Cross-layer check spec"),
404
+ (".claude/commands/trellis/check-backend.md", "Backend check spec"),
405
+ (".claude/commands/trellis/check-frontend.md", "Frontend check spec"),
406
+ ]
407
+ for file_path, description in check_files:
408
+ content = read_file_content(repo_root, file_path)
409
+ if content:
410
+ context_parts.append(f"=== {file_path} ({description}) ===\n{content}")
411
+
412
+ # Add spec.jsonl
413
+ spec_entries = read_jsonl_entries(repo_root, f"{task_dir}/spec.jsonl")
414
+ for file_path, content in spec_entries:
415
+ context_parts.append(f"=== {file_path} (Dev spec) ===\n{content}")
416
+
417
+ # 2. Inject upstream outputs (三角色协作)
418
+ upstream_entries = inject_upstream_context(repo_root, task_dir)
419
+ if upstream_entries:
420
+ context_parts.append("=== Upstream Outputs (三角色协作上游产出) ===")
421
+ for file_path, content in upstream_entries:
422
+ context_parts.append(f"=== {file_path} ===\n{content}")
423
+
424
+ # 3. Requirements document (for understanding task intent)
425
+ prd_content = read_file_content(repo_root, f"{task_dir}/prd.md")
426
+ if prd_content:
427
+ context_parts.append(
428
+ f"=== {task_dir}/prd.md (Requirements - for understanding intent) ===\n{prd_content}"
429
+ )
430
+
431
+ return "\n\n".join(context_parts)
432
+
433
+
434
+ def get_finish_context(repo_root: str, task_dir: str) -> str:
435
+ """
436
+ Complete context for Finish phase (final check before PR)
437
+
438
+ Read order:
439
+ 1. All files in finish.jsonl (if exists)
440
+ 2. Fallback to finish-work.md only (lightweight final check)
441
+ 3. Upstream outputs (HANDOFF + deliverables, if three-role collaboration)
442
+ 4. update-spec.md (for active spec sync)
443
+ 5. prd.md (for verifying requirements are met)
444
+ """
445
+ context_parts = []
446
+
447
+ # 1. Try finish.jsonl first
448
+ finish_entries = read_jsonl_entries(repo_root, f"{task_dir}/finish.jsonl")
449
+
450
+ if finish_entries:
451
+ for file_path, content in finish_entries:
452
+ context_parts.append(f"=== {file_path} ===\n{content}")
453
+ else:
454
+ # Fallback: only finish-work.md (lightweight)
455
+ finish_work = read_file_content(
456
+ repo_root, ".claude/commands/trellis/finish-work.md"
457
+ )
458
+ if finish_work:
459
+ context_parts.append(
460
+ f"=== .claude/commands/trellis/finish-work.md (Finish checklist) ===\n{finish_work}"
461
+ )
462
+
463
+ # 2. Inject upstream outputs (三角色协作)
464
+ upstream_entries = inject_upstream_context(repo_root, task_dir)
465
+ if upstream_entries:
466
+ context_parts.append("=== Upstream Outputs (三角色协作上游产出) ===")
467
+ for file_path, content in upstream_entries:
468
+ context_parts.append(f"=== {file_path} ===\n{content}")
469
+
470
+ # 3. Spec update process (for active spec sync)
471
+ update_spec = read_file_content(
472
+ repo_root, ".claude/commands/trellis/update-spec.md"
473
+ )
474
+ if update_spec:
475
+ context_parts.append(
476
+ f"=== .claude/commands/trellis/update-spec.md (Spec update process) ===\n{update_spec}"
477
+ )
478
+
479
+ # 4. Requirements document (for verifying requirements are met)
480
+ prd_content = read_file_content(repo_root, f"{task_dir}/prd.md")
481
+ if prd_content:
482
+ context_parts.append(
483
+ f"=== {task_dir}/prd.md (Requirements - verify all met) ===\n{prd_content}"
484
+ )
485
+
486
+ return "\n\n".join(context_parts)
487
+
488
+
489
+ def get_debug_context(repo_root: str, task_dir: str) -> str:
490
+ """
491
+ Complete context for Debug Agent
492
+
493
+ Read order:
494
+ 1. All files in debug.jsonl (specs needed for fixing)
495
+ 2. Upstream outputs (HANDOFF + deliverables, if three-role collaboration)
496
+ 3. codex-review-output.txt (Codex Review results)
497
+ """
498
+ context_parts = []
499
+
500
+ # 1. Read debug.jsonl (or fallback to spec.jsonl + hardcoded check files)
501
+ debug_entries = read_jsonl_entries(repo_root, f"{task_dir}/debug.jsonl")
502
+
503
+ if debug_entries:
504
+ for file_path, content in debug_entries:
505
+ context_parts.append(f"=== {file_path} ===\n{content}")
506
+ else:
507
+ # Fallback: use spec.jsonl + hardcoded check files
508
+ spec_entries = read_jsonl_entries(repo_root, f"{task_dir}/spec.jsonl")
509
+ for file_path, content in spec_entries:
510
+ context_parts.append(f"=== {file_path} (Dev spec) ===\n{content}")
511
+
512
+ check_files = [
513
+ (".claude/commands/trellis/check-backend.md", "Backend check spec"),
514
+ (".claude/commands/trellis/check-frontend.md", "Frontend check spec"),
515
+ (".claude/commands/trellis/check-cross-layer.md", "Cross-layer check spec"),
516
+ ]
517
+ for file_path, description in check_files:
518
+ content = read_file_content(repo_root, file_path)
519
+ if content:
520
+ context_parts.append(f"=== {file_path} ({description}) ===\n{content}")
521
+
522
+ # 2. Inject upstream outputs (三角色协作)
523
+ upstream_entries = inject_upstream_context(repo_root, task_dir)
524
+ if upstream_entries:
525
+ context_parts.append("=== Upstream Outputs (三角色协作上游产出) ===")
526
+ for file_path, content in upstream_entries:
527
+ context_parts.append(f"=== {file_path} ===\n{content}")
528
+
529
+ # 3. Codex review output (if exists)
530
+ codex_output = read_file_content(repo_root, f"{task_dir}/codex-review-output.txt")
531
+ if codex_output:
532
+ context_parts.append(
533
+ f"=== {task_dir}/codex-review-output.txt (Codex Review Results) ===\n{codex_output}"
534
+ )
535
+
536
+ return "\n\n".join(context_parts)
537
+
538
+
539
+ def build_implement_prompt(original_prompt: str, context: str) -> str:
540
+ """Build complete prompt for Implement"""
541
+ return f"""# Implement Agent Task
542
+
543
+ You are the Implement Agent in the Multi-Agent Pipeline.
544
+
545
+ ## Your Context
546
+
547
+ All the information you need has been prepared for you:
548
+
549
+ {context}
550
+
551
+ ---
552
+
553
+ ## Your Task
554
+
555
+ {original_prompt}
556
+
557
+ ---
558
+
559
+ ## Workflow
560
+
561
+ 1. **Understand specs** - All dev specs are injected above, understand them
562
+ 2. **Understand requirements** - Read requirements document and technical design
563
+ 3. **Implement feature** - Implement following specs and design
564
+ 4. **Self-check** - Ensure code quality against check specs
565
+
566
+ ## Important Constraints
567
+
568
+ - Do NOT execute git commit, only code modifications
569
+ - Follow all dev specs injected above
570
+ - Report list of modified/created files when done"""
571
+
572
+
573
+ def build_check_prompt(original_prompt: str, context: str) -> str:
574
+ """Build complete prompt for Check"""
575
+ return f"""# Check Agent Task
576
+
577
+ You are the Check Agent in the Multi-Agent Pipeline (code and cross-layer checker).
578
+
579
+ ## Your Context
580
+
581
+ All check specs and dev specs you need:
582
+
583
+ {context}
584
+
585
+ ---
586
+
587
+ ## Your Task
588
+
589
+ {original_prompt}
590
+
591
+ ---
592
+
593
+ ## Workflow
594
+
595
+ 1. **Get changes** - Run `git diff --name-only` and `git diff` to get code changes
596
+ 2. **Check against specs** - Check item by item against specs above
597
+ 3. **Self-fix** - Fix issues directly, don't just report
598
+ 4. **Run verification** - Run project's lint and typecheck commands
599
+
600
+ ## Important Constraints
601
+
602
+ - Fix issues yourself, don't just report
603
+ - Must execute complete checklist in check specs
604
+ - Pay special attention to impact radius analysis (L1-L5)"""
605
+
606
+
607
+ def build_finish_prompt(original_prompt: str, context: str) -> str:
608
+ """Build complete prompt for Finish (final check before PR)"""
609
+ return f"""# Finish Agent Task
610
+
611
+ You are performing the final check before creating a PR.
612
+
613
+ ## Your Context
614
+
615
+ Finish checklist and requirements:
616
+
617
+ {context}
618
+
619
+ ---
620
+
621
+ ## Your Task
622
+
623
+ {original_prompt}
624
+
625
+ ---
626
+
627
+ ## Workflow
628
+
629
+ 1. **Review changes** - Run `git diff --name-only` to see all changed files
630
+ 2. **Verify requirements** - Check each requirement in prd.md is implemented
631
+ 3. **Spec sync** - Analyze whether changes introduce new patterns, contracts, or conventions
632
+ - If new pattern/convention found: read target spec file → update it → update index.md if needed
633
+ - If infra/cross-layer change: follow the 7-section mandatory template from update-spec.md
634
+ - If pure code fix with no new patterns: skip this step
635
+ 4. **Run final checks** - Execute lint and typecheck
636
+ 5. **Confirm ready** - Ensure code is ready for PR
637
+
638
+ ## Important Constraints
639
+
640
+ - You MAY update spec files when gaps are detected (use update-spec.md as guide)
641
+ - MUST read the target spec file BEFORE editing (avoid duplicating existing content)
642
+ - Do NOT update specs for trivial changes (typos, formatting, obvious fixes)
643
+ - If critical CODE issues found, report them clearly (fix specs, not code)
644
+ - Verify all acceptance criteria in prd.md are met"""
645
+
646
+
647
+ def build_debug_prompt(original_prompt: str, context: str) -> str:
648
+ """Build complete prompt for Debug"""
649
+ return f"""# Debug Agent Task
650
+
651
+ You are the Debug Agent in the Multi-Agent Pipeline (issue fixer).
652
+
653
+ ## Your Context
654
+
655
+ Dev specs and Codex Review results:
656
+
657
+ {context}
658
+
659
+ ---
660
+
661
+ ## Your Task
662
+
663
+ {original_prompt}
664
+
665
+ ---
666
+
667
+ ## Workflow
668
+
669
+ 1. **Understand issues** - Analyze issues pointed out in Codex Review
670
+ 2. **Locate code** - Find positions that need fixing
671
+ 3. **Fix against specs** - Fix issues following dev specs
672
+ 4. **Verify fixes** - Run typecheck to ensure no new issues
673
+
674
+ ## Important Constraints
675
+
676
+ - Do NOT execute git commit, only code modifications
677
+ - Run typecheck after each fix to verify
678
+ - Report which issues were fixed and which files were modified"""
679
+
680
+
681
+ def get_research_context(repo_root: str, task_dir: Optional[str]) -> str:
682
+ """
683
+ Context for Research Agent
684
+
685
+ Research doesn't need much preset context, only needs:
686
+ 1. Project structure overview (where spec directories are)
687
+ 2. Optional research.jsonl (if there are specific search needs)
688
+ """
689
+ context_parts = []
690
+
691
+ # 1. Project structure overview (uses constants for paths)
692
+ spec_path = f"{DIR_WORKFLOW}/{DIR_SPEC}"
693
+ project_structure = f"""## Project Spec Directory Structure
694
+
695
+ ```
696
+ {spec_path}/
697
+ ├── shared/ # Cross-project common specs (TypeScript, code quality, git)
698
+ ├── frontend/ # Frontend standards
699
+ ├── backend/ # Backend standards
700
+ └── guides/ # Thinking guides (cross-layer, code reuse, etc.)
701
+
702
+ {DIR_WORKFLOW}/big-question/ # Known issues and pitfalls
703
+ ```
704
+
705
+ ## Search Tips
706
+
707
+ - Spec files: `{spec_path}/**/*.md`
708
+ - Known issues: `{DIR_WORKFLOW}/big-question/`
709
+ - Code search: Use Glob and Grep tools
710
+ - Tech solutions: Use mcp__exa__web_search_exa or mcp__exa__get_code_context_exa"""
711
+
712
+ context_parts.append(project_structure)
713
+
714
+ # 2. If task directory exists, try reading research.jsonl (optional)
715
+ if task_dir:
716
+ research_entries = read_jsonl_entries(repo_root, f"{task_dir}/research.jsonl")
717
+ if research_entries:
718
+ context_parts.append(
719
+ "\n## Additional Search Context (from research.jsonl)\n"
720
+ )
721
+ for file_path, content in research_entries:
722
+ context_parts.append(f"=== {file_path} ===\n{content}")
723
+
724
+ return "\n\n".join(context_parts)
725
+
726
+
727
+ def build_research_prompt(original_prompt: str, context: str) -> str:
728
+ """Build complete prompt for Research"""
729
+ return f"""# Research Agent Task
730
+
731
+ You are the Research Agent in the Multi-Agent Pipeline (search researcher).
732
+
733
+ ## Core Principle
734
+
735
+ **You do one thing: find and explain information.**
736
+
737
+ You are a documenter, not a reviewer.
738
+
739
+ ## Project Info
740
+
741
+ {context}
742
+
743
+ ---
744
+
745
+ ## Your Task
746
+
747
+ {original_prompt}
748
+
749
+ ---
750
+
751
+ ## Workflow
752
+
753
+ 1. **Understand query** - Determine search type (internal/external) and scope
754
+ 2. **Plan search** - List search steps for complex queries
755
+ 3. **Execute search** - Execute multiple independent searches in parallel
756
+ 4. **Organize results** - Output structured report
757
+
758
+ ## Search Tools
759
+
760
+ | Tool | Purpose |
761
+ |------|---------|
762
+ | Glob | Search by filename pattern |
763
+ | Grep | Search by content |
764
+ | Read | Read file content |
765
+ | mcp__exa__web_search_exa | External web search |
766
+ | mcp__exa__get_code_context_exa | External code/doc search |
767
+
768
+ ## Strict Boundaries
769
+
770
+ **Only allowed**: Describe what exists, where it is, how it works
771
+
772
+ **Forbidden** (unless explicitly asked):
773
+ - Suggest improvements
774
+ - Criticize implementation
775
+ - Recommend refactoring
776
+ - Modify any files
777
+
778
+ ## Report Format
779
+
780
+ Provide structured search results including:
781
+ - List of files found (with paths)
782
+ - Code pattern analysis (if applicable)
783
+ - Related spec documents
784
+ - External references (if any)"""
785
+
786
+
787
+ def main():
788
+ try:
789
+ input_data = json.load(sys.stdin)
790
+ except json.JSONDecodeError:
791
+ sys.exit(0)
792
+
793
+ tool_name = input_data.get("tool_name", "")
794
+
795
+ if tool_name != "Task":
796
+ sys.exit(0)
797
+
798
+ tool_input = input_data.get("tool_input", {})
799
+ subagent_type = tool_input.get("subagent_type", "")
800
+ original_prompt = tool_input.get("prompt", "")
801
+ cwd = input_data.get("cwd", os.getcwd())
802
+
803
+ # Only handle subagent types we care about
804
+ if subagent_type not in AGENTS_ALL:
805
+ sys.exit(0)
806
+
807
+ # Find repo root
808
+ repo_root = find_repo_root(cwd)
809
+ if not repo_root:
810
+ sys.exit(0)
811
+
812
+ # Get current task directory (research doesn't require it)
813
+ task_dir = get_current_task(repo_root)
814
+
815
+ # implement/check/debug need task directory
816
+ if subagent_type in AGENTS_REQUIRE_TASK:
817
+ if not task_dir:
818
+ sys.exit(0)
819
+ # Check if task directory exists
820
+ task_dir_full = os.path.join(repo_root, task_dir)
821
+ if not os.path.exists(task_dir_full):
822
+ sys.exit(0)
823
+
824
+ # Update current_phase in task.json (system-level enforcement)
825
+ update_current_phase(repo_root, task_dir, subagent_type)
826
+
827
+ # Check for [finish] marker in prompt (check agent with finish context)
828
+ is_finish_phase = "[finish]" in original_prompt.lower()
829
+
830
+ # Get context and build prompt based on subagent type
831
+ if subagent_type == AGENT_IMPLEMENT:
832
+ assert task_dir is not None # validated above
833
+ context = get_implement_context(repo_root, task_dir)
834
+ new_prompt = build_implement_prompt(original_prompt, context)
835
+ elif subagent_type == AGENT_CHECK:
836
+ assert task_dir is not None # validated above
837
+ if is_finish_phase:
838
+ # Finish phase: use finish context (lighter, focused on final verification)
839
+ context = get_finish_context(repo_root, task_dir)
840
+ new_prompt = build_finish_prompt(original_prompt, context)
841
+ else:
842
+ # Regular check phase: use check context (full specs for self-fix loop)
843
+ context = get_check_context(repo_root, task_dir)
844
+ new_prompt = build_check_prompt(original_prompt, context)
845
+ elif subagent_type == AGENT_DEBUG:
846
+ assert task_dir is not None # validated above
847
+ context = get_debug_context(repo_root, task_dir)
848
+ new_prompt = build_debug_prompt(original_prompt, context)
849
+ elif subagent_type == AGENT_RESEARCH:
850
+ # Research can work without task directory
851
+ context = get_research_context(repo_root, task_dir)
852
+ new_prompt = build_research_prompt(original_prompt, context)
853
+ else:
854
+ sys.exit(0)
855
+
856
+ if not context:
857
+ sys.exit(0)
858
+
859
+ # Return updated input with correct Claude Code PreToolUse format
860
+ output = {
861
+ "hookSpecificOutput": {
862
+ "hookEventName": "PreToolUse",
863
+ "permissionDecision": "allow",
864
+ "updatedInput": {**tool_input, "prompt": new_prompt},
865
+ }
866
+ }
867
+
868
+ print(json.dumps(output, ensure_ascii=False))
869
+ sys.exit(0)
870
+
871
+
872
+ if __name__ == "__main__":
873
+ main()