@mindfoldhq/trellis 0.6.0-beta.2 → 0.6.0-beta.20

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 (330) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/index.d.ts +1 -1
  3. package/dist/cli/index.d.ts.map +1 -1
  4. package/dist/cli/index.js +58 -2
  5. package/dist/cli/index.js.map +1 -1
  6. package/dist/commands/channel/adapters/claude.d.ts +29 -0
  7. package/dist/commands/channel/adapters/claude.d.ts.map +1 -0
  8. package/dist/commands/channel/adapters/claude.js +203 -0
  9. package/dist/commands/channel/adapters/claude.js.map +1 -0
  10. package/dist/commands/channel/adapters/codex.d.ts +85 -0
  11. package/dist/commands/channel/adapters/codex.d.ts.map +1 -0
  12. package/dist/commands/channel/adapters/codex.js +505 -0
  13. package/dist/commands/channel/adapters/codex.js.map +1 -0
  14. package/dist/commands/channel/adapters/index.d.ts +84 -0
  15. package/dist/commands/channel/adapters/index.d.ts.map +1 -0
  16. package/dist/commands/channel/adapters/index.js +115 -0
  17. package/dist/commands/channel/adapters/index.js.map +1 -0
  18. package/dist/commands/channel/adapters/types.d.ts +33 -0
  19. package/dist/commands/channel/adapters/types.d.ts.map +1 -0
  20. package/dist/commands/channel/adapters/types.js +2 -0
  21. package/dist/commands/channel/adapters/types.js.map +1 -0
  22. package/dist/commands/channel/agent-loader.d.ts +32 -0
  23. package/dist/commands/channel/agent-loader.d.ts.map +1 -0
  24. package/dist/commands/channel/agent-loader.js +154 -0
  25. package/dist/commands/channel/agent-loader.js.map +1 -0
  26. package/dist/commands/channel/context-loader.d.ts +26 -0
  27. package/dist/commands/channel/context-loader.d.ts.map +1 -0
  28. package/dist/commands/channel/context-loader.js +290 -0
  29. package/dist/commands/channel/context-loader.js.map +1 -0
  30. package/dist/commands/channel/context.d.ts +16 -0
  31. package/dist/commands/channel/context.d.ts.map +1 -0
  32. package/dist/commands/channel/context.js +83 -0
  33. package/dist/commands/channel/context.js.map +1 -0
  34. package/dist/commands/channel/create.d.ts +27 -0
  35. package/dist/commands/channel/create.d.ts.map +1 -0
  36. package/dist/commands/channel/create.js +39 -0
  37. package/dist/commands/channel/create.js.map +1 -0
  38. package/dist/commands/channel/dev-parse-trace.d.ts +14 -0
  39. package/dist/commands/channel/dev-parse-trace.d.ts.map +1 -0
  40. package/dist/commands/channel/dev-parse-trace.js +70 -0
  41. package/dist/commands/channel/dev-parse-trace.js.map +1 -0
  42. package/dist/commands/channel/guard.d.ts +150 -0
  43. package/dist/commands/channel/guard.d.ts.map +1 -0
  44. package/dist/commands/channel/guard.js +474 -0
  45. package/dist/commands/channel/guard.js.map +1 -0
  46. package/dist/commands/channel/index.d.ts +3 -0
  47. package/dist/commands/channel/index.d.ts.map +1 -0
  48. package/dist/commands/channel/index.js +531 -0
  49. package/dist/commands/channel/index.js.map +1 -0
  50. package/dist/commands/channel/interrupt.d.ts +10 -0
  51. package/dist/commands/channel/interrupt.d.ts.map +1 -0
  52. package/dist/commands/channel/interrupt.js +22 -0
  53. package/dist/commands/channel/interrupt.js.map +1 -0
  54. package/dist/commands/channel/kill.d.ts +7 -0
  55. package/dist/commands/channel/kill.d.ts.map +1 -0
  56. package/dist/commands/channel/kill.js +121 -0
  57. package/dist/commands/channel/kill.js.map +1 -0
  58. package/dist/commands/channel/list.d.ts +17 -0
  59. package/dist/commands/channel/list.d.ts.map +1 -0
  60. package/dist/commands/channel/list.js +233 -0
  61. package/dist/commands/channel/list.js.map +1 -0
  62. package/dist/commands/channel/messages.d.ts +15 -0
  63. package/dist/commands/channel/messages.d.ts.map +1 -0
  64. package/dist/commands/channel/messages.js +245 -0
  65. package/dist/commands/channel/messages.js.map +1 -0
  66. package/dist/commands/channel/rm.d.ts +27 -0
  67. package/dist/commands/channel/rm.d.ts.map +1 -0
  68. package/dist/commands/channel/rm.js +216 -0
  69. package/dist/commands/channel/rm.js.map +1 -0
  70. package/dist/commands/channel/run.d.ts +30 -0
  71. package/dist/commands/channel/run.d.ts.map +1 -0
  72. package/dist/commands/channel/run.js +130 -0
  73. package/dist/commands/channel/run.js.map +1 -0
  74. package/dist/commands/channel/send.d.ts +11 -0
  75. package/dist/commands/channel/send.d.ts.map +1 -0
  76. package/dist/commands/channel/send.js +24 -0
  77. package/dist/commands/channel/send.js.map +1 -0
  78. package/dist/commands/channel/spawn.d.ts +40 -0
  79. package/dist/commands/channel/spawn.d.ts.map +1 -0
  80. package/dist/commands/channel/spawn.js +244 -0
  81. package/dist/commands/channel/spawn.js.map +1 -0
  82. package/dist/commands/channel/store/events.d.ts +39 -0
  83. package/dist/commands/channel/store/events.d.ts.map +1 -0
  84. package/dist/commands/channel/store/events.js +87 -0
  85. package/dist/commands/channel/store/events.js.map +1 -0
  86. package/dist/commands/channel/store/filter.d.ts +3 -0
  87. package/dist/commands/channel/store/filter.d.ts.map +1 -0
  88. package/dist/commands/channel/store/filter.js +2 -0
  89. package/dist/commands/channel/store/filter.js.map +1 -0
  90. package/dist/commands/channel/store/lock.d.ts +23 -0
  91. package/dist/commands/channel/store/lock.d.ts.map +1 -0
  92. package/dist/commands/channel/store/lock.js +99 -0
  93. package/dist/commands/channel/store/lock.js.map +1 -0
  94. package/dist/commands/channel/store/paths.d.ts +63 -0
  95. package/dist/commands/channel/store/paths.d.ts.map +1 -0
  96. package/dist/commands/channel/store/paths.js +246 -0
  97. package/dist/commands/channel/store/paths.js.map +1 -0
  98. package/dist/commands/channel/store/schema.d.ts +27 -0
  99. package/dist/commands/channel/store/schema.d.ts.map +1 -0
  100. package/dist/commands/channel/store/schema.js +34 -0
  101. package/dist/commands/channel/store/schema.js.map +1 -0
  102. package/dist/commands/channel/store/thread-state.d.ts +5 -0
  103. package/dist/commands/channel/store/thread-state.d.ts.map +1 -0
  104. package/dist/commands/channel/store/thread-state.js +16 -0
  105. package/dist/commands/channel/store/thread-state.js.map +1 -0
  106. package/dist/commands/channel/store/watch.d.ts +19 -0
  107. package/dist/commands/channel/store/watch.d.ts.map +1 -0
  108. package/dist/commands/channel/store/watch.js +146 -0
  109. package/dist/commands/channel/store/watch.js.map +1 -0
  110. package/dist/commands/channel/supervisor/idle.d.ts +46 -0
  111. package/dist/commands/channel/supervisor/idle.d.ts.map +1 -0
  112. package/dist/commands/channel/supervisor/idle.js +72 -0
  113. package/dist/commands/channel/supervisor/idle.js.map +1 -0
  114. package/dist/commands/channel/supervisor/inbox.d.ts +30 -0
  115. package/dist/commands/channel/supervisor/inbox.d.ts.map +1 -0
  116. package/dist/commands/channel/supervisor/inbox.js +160 -0
  117. package/dist/commands/channel/supervisor/inbox.js.map +1 -0
  118. package/dist/commands/channel/supervisor/shutdown.d.ts +68 -0
  119. package/dist/commands/channel/supervisor/shutdown.d.ts.map +1 -0
  120. package/dist/commands/channel/supervisor/shutdown.js +146 -0
  121. package/dist/commands/channel/supervisor/shutdown.js.map +1 -0
  122. package/dist/commands/channel/supervisor/stdout.d.ts +51 -0
  123. package/dist/commands/channel/supervisor/stdout.d.ts.map +1 -0
  124. package/dist/commands/channel/supervisor/stdout.js +121 -0
  125. package/dist/commands/channel/supervisor/stdout.js.map +1 -0
  126. package/dist/commands/channel/supervisor/turns.d.ts +31 -0
  127. package/dist/commands/channel/supervisor/turns.d.ts.map +1 -0
  128. package/dist/commands/channel/supervisor/turns.js +45 -0
  129. package/dist/commands/channel/supervisor/turns.js.map +1 -0
  130. package/dist/commands/channel/supervisor/warning.d.ts +48 -0
  131. package/dist/commands/channel/supervisor/warning.d.ts.map +1 -0
  132. package/dist/commands/channel/supervisor/warning.js +77 -0
  133. package/dist/commands/channel/supervisor/warning.js.map +1 -0
  134. package/dist/commands/channel/supervisor.d.ts +59 -0
  135. package/dist/commands/channel/supervisor.d.ts.map +1 -0
  136. package/dist/commands/channel/supervisor.js +344 -0
  137. package/dist/commands/channel/supervisor.js.map +1 -0
  138. package/dist/commands/channel/text-body.d.ts +13 -0
  139. package/dist/commands/channel/text-body.d.ts.map +1 -0
  140. package/dist/commands/channel/text-body.js +47 -0
  141. package/dist/commands/channel/text-body.js.map +1 -0
  142. package/dist/commands/channel/threads.d.ts +39 -0
  143. package/dist/commands/channel/threads.d.ts.map +1 -0
  144. package/dist/commands/channel/threads.js +106 -0
  145. package/dist/commands/channel/threads.js.map +1 -0
  146. package/dist/commands/channel/title.d.ts +12 -0
  147. package/dist/commands/channel/title.d.ts.map +1 -0
  148. package/dist/commands/channel/title.js +24 -0
  149. package/dist/commands/channel/title.js.map +1 -0
  150. package/dist/commands/channel/wait.d.ts +17 -0
  151. package/dist/commands/channel/wait.d.ts.map +1 -0
  152. package/dist/commands/channel/wait.js +75 -0
  153. package/dist/commands/channel/wait.js.map +1 -0
  154. package/dist/commands/init.d.ts +2 -0
  155. package/dist/commands/init.d.ts.map +1 -1
  156. package/dist/commands/init.js +97 -42
  157. package/dist/commands/init.js.map +1 -1
  158. package/dist/commands/mem.d.ts +13 -117
  159. package/dist/commands/mem.d.ts.map +1 -1
  160. package/dist/commands/mem.js +168 -1074
  161. package/dist/commands/mem.js.map +1 -1
  162. package/dist/commands/uninstall.d.ts.map +1 -1
  163. package/dist/commands/uninstall.js +28 -2
  164. package/dist/commands/uninstall.js.map +1 -1
  165. package/dist/commands/update.d.ts.map +1 -1
  166. package/dist/commands/update.js +31 -111
  167. package/dist/commands/update.js.map +1 -1
  168. package/dist/commands/upgrade.d.ts +28 -0
  169. package/dist/commands/upgrade.d.ts.map +1 -0
  170. package/dist/commands/upgrade.js +84 -0
  171. package/dist/commands/upgrade.js.map +1 -0
  172. package/dist/commands/workflow.d.ts +35 -0
  173. package/dist/commands/workflow.d.ts.map +1 -0
  174. package/dist/commands/workflow.js +219 -0
  175. package/dist/commands/workflow.js.map +1 -0
  176. package/dist/configurators/claude.d.ts.map +1 -1
  177. package/dist/configurators/claude.js +1 -0
  178. package/dist/configurators/claude.js.map +1 -1
  179. package/dist/configurators/codex.d.ts.map +1 -1
  180. package/dist/configurators/codex.js +5 -3
  181. package/dist/configurators/codex.js.map +1 -1
  182. package/dist/configurators/shared.js +4 -4
  183. package/dist/configurators/shared.js.map +1 -1
  184. package/dist/configurators/workflow.d.ts +8 -0
  185. package/dist/configurators/workflow.d.ts.map +1 -1
  186. package/dist/configurators/workflow.js +3 -2
  187. package/dist/configurators/workflow.js.map +1 -1
  188. package/dist/migrations/manifests/0.5.10.json +9 -0
  189. package/dist/migrations/manifests/0.5.11.json +16 -0
  190. package/dist/migrations/manifests/0.5.12.json +9 -0
  191. package/dist/migrations/manifests/0.5.13.json +9 -0
  192. package/dist/migrations/manifests/0.5.14.json +9 -0
  193. package/dist/migrations/manifests/0.5.15.json +9 -0
  194. package/dist/migrations/manifests/0.5.16.json +9 -0
  195. package/dist/migrations/manifests/0.5.17.json +9 -0
  196. package/dist/migrations/manifests/0.5.18.json +9 -0
  197. package/dist/migrations/manifests/0.6.0-beta.10.json +9 -0
  198. package/dist/migrations/manifests/0.6.0-beta.11.json +9 -0
  199. package/dist/migrations/manifests/0.6.0-beta.12.json +9 -0
  200. package/dist/migrations/manifests/0.6.0-beta.13.json +9 -0
  201. package/dist/migrations/manifests/0.6.0-beta.14.json +9 -0
  202. package/dist/migrations/manifests/0.6.0-beta.15.json +9 -0
  203. package/dist/migrations/manifests/0.6.0-beta.16.json +9 -0
  204. package/dist/migrations/manifests/0.6.0-beta.17.json +9 -0
  205. package/dist/migrations/manifests/0.6.0-beta.18.json +16 -0
  206. package/dist/migrations/manifests/0.6.0-beta.19.json +9 -0
  207. package/dist/migrations/manifests/0.6.0-beta.20.json +9 -0
  208. package/dist/migrations/manifests/0.6.0-beta.3.json +9 -0
  209. package/dist/migrations/manifests/0.6.0-beta.4.json +9 -0
  210. package/dist/migrations/manifests/0.6.0-beta.5.json +9 -0
  211. package/dist/migrations/manifests/0.6.0-beta.6.json +16 -0
  212. package/dist/migrations/manifests/0.6.0-beta.7.json +9 -0
  213. package/dist/migrations/manifests/0.6.0-beta.8.json +9 -0
  214. package/dist/migrations/manifests/0.6.0-beta.9.json +9 -0
  215. package/dist/templates/claude/agents/trellis-check.md +13 -7
  216. package/dist/templates/claude/agents/trellis-implement.md +8 -7
  217. package/dist/templates/claude/settings.json +4 -4
  218. package/dist/templates/codebuddy/agents/trellis-check.md +13 -7
  219. package/dist/templates/codebuddy/agents/trellis-implement.md +8 -7
  220. package/dist/templates/codebuddy/settings.json +4 -4
  221. package/dist/templates/codex/agents/trellis-check.toml +4 -4
  222. package/dist/templates/codex/agents/trellis-implement.toml +4 -4
  223. package/dist/templates/codex/config.toml +5 -3
  224. package/dist/templates/codex/hooks/session-start.py +205 -119
  225. package/dist/templates/codex/hooks.json +2 -2
  226. package/dist/templates/codex/skills/before-dev/SKILL.md +12 -6
  227. package/dist/templates/codex/skills/brainstorm/SKILL.md +69 -457
  228. package/dist/templates/codex/skills/check/SKILL.md +86 -18
  229. package/dist/templates/codex/skills/start/SKILL.md +33 -323
  230. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-context-loading.md +7 -4
  231. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-spec-structure.md +1 -1
  232. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-workflow.md +3 -2
  233. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/context-injection.md +5 -5
  234. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/spec-system.md +1 -1
  235. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/task-system.md +35 -6
  236. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/agents.md +5 -4
  237. package/dist/templates/common/bundled-skills/trellis-spec-bootstarp/SKILL.md +41 -0
  238. package/dist/templates/common/bundled-skills/trellis-spec-bootstarp/references/mcp-setup.md +90 -0
  239. package/dist/templates/common/bundled-skills/trellis-spec-bootstarp/references/repository-analysis.md +59 -0
  240. package/dist/templates/common/bundled-skills/trellis-spec-bootstarp/references/spec-task-planning.md +61 -0
  241. package/dist/templates/common/bundled-skills/trellis-spec-bootstarp/references/spec-writing.md +70 -0
  242. package/dist/templates/common/commands/continue.md +6 -5
  243. package/dist/templates/common/commands/start.md +9 -6
  244. package/dist/templates/common/skills/before-dev.md +12 -6
  245. package/dist/templates/common/skills/brainstorm.md +68 -504
  246. package/dist/templates/common/skills/check.md +7 -1
  247. package/dist/templates/copilot/hooks/session-start.py +219 -101
  248. package/dist/templates/copilot/hooks.json +2 -2
  249. package/dist/templates/copilot/prompts/before-dev.prompt.md +12 -6
  250. package/dist/templates/copilot/prompts/brainstorm.prompt.md +69 -457
  251. package/dist/templates/copilot/prompts/check.prompt.md +86 -18
  252. package/dist/templates/copilot/prompts/parallel.prompt.md +16 -8
  253. package/dist/templates/copilot/prompts/start.prompt.md +33 -367
  254. package/dist/templates/cursor/agents/trellis-check.md +13 -7
  255. package/dist/templates/cursor/agents/trellis-implement.md +8 -7
  256. package/dist/templates/cursor/hooks.json +1 -7
  257. package/dist/templates/droid/droids/trellis-check.md +13 -7
  258. package/dist/templates/droid/droids/trellis-implement.md +8 -7
  259. package/dist/templates/droid/settings.json +4 -4
  260. package/dist/templates/gemini/agents/trellis-check.md +11 -5
  261. package/dist/templates/gemini/agents/trellis-implement.md +7 -6
  262. package/dist/templates/gemini/settings.json +2 -2
  263. package/dist/templates/kiro/agents/trellis-check.json +1 -1
  264. package/dist/templates/kiro/agents/trellis-implement.json +1 -1
  265. package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +127 -9
  266. package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +171 -6
  267. package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +333 -43
  268. package/dist/templates/markdown/spec/guides/index.md.txt +18 -0
  269. package/dist/templates/opencode/agents/trellis-check.md +13 -7
  270. package/dist/templates/opencode/agents/trellis-implement.md +9 -8
  271. package/dist/templates/opencode/lib/session-utils.js +212 -123
  272. package/dist/templates/opencode/lib/trellis-context.js +73 -11
  273. package/dist/templates/opencode/plugins/inject-subagent-context.js +131 -29
  274. package/dist/templates/opencode/plugins/inject-workflow-state.js +9 -5
  275. package/dist/templates/opencode/plugins/session-start.js +9 -1
  276. package/dist/templates/pi/agents/trellis-check.md +5 -4
  277. package/dist/templates/pi/agents/trellis-implement.md +5 -4
  278. package/dist/templates/pi/extensions/trellis/index.ts.txt +1357 -754
  279. package/dist/templates/qoder/agents/trellis-check.md +11 -5
  280. package/dist/templates/qoder/agents/trellis-implement.md +7 -6
  281. package/dist/templates/qoder/settings.json +4 -4
  282. package/dist/templates/shared-hooks/index.d.ts.map +1 -1
  283. package/dist/templates/shared-hooks/index.js +0 -1
  284. package/dist/templates/shared-hooks/index.js.map +1 -1
  285. package/dist/templates/shared-hooks/inject-subagent-context.py +36 -14
  286. package/dist/templates/shared-hooks/inject-workflow-state.py +40 -42
  287. package/dist/templates/shared-hooks/session-start.py +222 -171
  288. package/dist/templates/trellis/config.yaml +38 -0
  289. package/dist/templates/trellis/index.d.ts +1 -0
  290. package/dist/templates/trellis/index.d.ts.map +1 -1
  291. package/dist/templates/trellis/index.js +2 -0
  292. package/dist/templates/trellis/index.js.map +1 -1
  293. package/dist/templates/trellis/scripts/add_session.py +50 -24
  294. package/dist/templates/trellis/scripts/common/config.py +57 -1
  295. package/dist/templates/trellis/scripts/common/safe_commit.py +285 -0
  296. package/dist/templates/trellis/scripts/common/session_context.py +384 -137
  297. package/dist/templates/trellis/scripts/common/task_context.py +3 -3
  298. package/dist/templates/trellis/scripts/common/task_store.py +161 -15
  299. package/dist/templates/trellis/scripts/common/workflow_phase.py +7 -10
  300. package/dist/templates/trellis/scripts/task.py +3 -3
  301. package/dist/templates/trellis/workflow.md +119 -98
  302. package/dist/utils/cwd-guard.d.ts +38 -0
  303. package/dist/utils/cwd-guard.d.ts.map +1 -0
  304. package/dist/utils/cwd-guard.js +62 -0
  305. package/dist/utils/cwd-guard.js.map +1 -0
  306. package/dist/utils/file-writer.d.ts +13 -0
  307. package/dist/utils/file-writer.d.ts.map +1 -1
  308. package/dist/utils/file-writer.js +59 -1
  309. package/dist/utils/file-writer.js.map +1 -1
  310. package/dist/utils/manifest-prune.d.ts +61 -0
  311. package/dist/utils/manifest-prune.d.ts.map +1 -0
  312. package/dist/utils/manifest-prune.js +136 -0
  313. package/dist/utils/manifest-prune.js.map +1 -0
  314. package/dist/utils/task-json.d.ts +9 -42
  315. package/dist/utils/task-json.d.ts.map +1 -1
  316. package/dist/utils/task-json.js +8 -45
  317. package/dist/utils/task-json.js.map +1 -1
  318. package/dist/utils/template-hash.d.ts +32 -6
  319. package/dist/utils/template-hash.d.ts.map +1 -1
  320. package/dist/utils/template-hash.js +53 -31
  321. package/dist/utils/template-hash.js.map +1 -1
  322. package/dist/utils/uninstall-scrubbers.d.ts +1 -0
  323. package/dist/utils/uninstall-scrubbers.d.ts.map +1 -1
  324. package/dist/utils/uninstall-scrubbers.js +21 -0
  325. package/dist/utils/uninstall-scrubbers.js.map +1 -1
  326. package/dist/utils/workflow-resolver.d.ts +86 -0
  327. package/dist/utils/workflow-resolver.d.ts.map +1 -0
  328. package/dist/utils/workflow-resolver.js +265 -0
  329. package/dist/utils/workflow-resolver.js.map +1 -0
  330. package/package.json +9 -8
@@ -14,48 +14,80 @@ import { TrellisContext, debugLog } from "../lib/trellis-context.js"
14
14
  const AGENTS_ALL = ["implement", "check", "research"]
15
15
  const AGENTS_REQUIRE_TASK = ["implement", "check"]
16
16
 
17
+ // Match `Active task: <path>` on the first non-empty line of the dispatch
18
+ // prompt. Mirrors the contract in workflow.md's [workflow-state:in_progress]
19
+ // breadcrumb so multi-window users can disambiguate which task is targeted.
20
+ const ACTIVE_TASK_HINT_RE = /^\s*Active task:\s*(\S+)\s*$/m
21
+
22
+ function extractActiveTaskHint(prompt) {
23
+ if (typeof prompt !== "string" || !prompt) return null
24
+ const match = prompt.match(ACTIVE_TASK_HINT_RE)
25
+ return match ? match[1].trim() : null
26
+ }
27
+
17
28
  /**
18
- * Get context for implement agent
29
+ * Get context for implement agent. `taskDir` may be relative
30
+ * (`.trellis/tasks/foo`) or absolute; both are resolved via
31
+ * `ctx.resolveTaskDir`.
19
32
  */
20
33
  function getImplementContext(ctx, taskDir) {
21
34
  const parts = []
35
+ const taskDirFull = ctx.resolveTaskDir(taskDir)
36
+ if (!taskDirFull) return ""
22
37
 
23
- const jsonlPath = join(ctx.directory, taskDir, "implement.jsonl")
38
+ const jsonlPath = join(taskDirFull, "implement.jsonl")
24
39
  const entries = ctx.readJsonlWithFiles(jsonlPath)
25
40
  if (entries.length > 0) {
26
41
  parts.push(ctx.buildContextFromEntries(entries))
27
42
  }
28
43
 
29
- const prd = ctx.readProjectFile(join(taskDir, "prd.md"))
44
+ const prd = ctx.readFile(join(taskDirFull, "prd.md"))
30
45
  if (prd) {
31
46
  parts.push(`=== ${taskDir}/prd.md (Requirements) ===\n${prd}`)
32
47
  }
33
48
 
34
- const info = ctx.readProjectFile(join(taskDir, "info.md"))
35
- if (info) {
36
- parts.push(`=== ${taskDir}/info.md (Technical Design) ===\n${info}`)
49
+ const design = ctx.readFile(join(taskDirFull, "design.md"))
50
+ if (design) {
51
+ parts.push(`=== ${taskDir}/design.md (Technical Design) ===\n${design}`)
52
+ }
53
+
54
+ const implementPlan = ctx.readFile(join(taskDirFull, "implement.md"))
55
+ if (implementPlan) {
56
+ parts.push(`=== ${taskDir}/implement.md (Execution Plan) ===\n${implementPlan}`)
37
57
  }
38
58
 
39
59
  return parts.join("\n\n")
40
60
  }
41
61
 
42
62
  /**
43
- * Get context for check agent
63
+ * Get context for check agent. `taskDir` may be relative or absolute.
44
64
  */
45
65
  function getCheckContext(ctx, taskDir) {
46
66
  const parts = []
67
+ const taskDirFull = ctx.resolveTaskDir(taskDir)
68
+ if (!taskDirFull) return ""
47
69
 
48
- const jsonlPath = join(ctx.directory, taskDir, "check.jsonl")
70
+ const jsonlPath = join(taskDirFull, "check.jsonl")
49
71
  const entries = ctx.readJsonlWithFiles(jsonlPath)
50
72
  if (entries.length > 0) {
51
73
  parts.push(ctx.buildContextFromEntries(entries))
52
74
  }
53
75
 
54
- const prd = ctx.readProjectFile(join(taskDir, "prd.md"))
76
+ const prd = ctx.readFile(join(taskDirFull, "prd.md"))
55
77
  if (prd) {
56
78
  parts.push(`=== ${taskDir}/prd.md (Requirements) ===\n${prd}`)
57
79
  }
58
80
 
81
+ const design = ctx.readFile(join(taskDirFull, "design.md"))
82
+ if (design) {
83
+ parts.push(`=== ${taskDir}/design.md (Technical Design) ===\n${design}`)
84
+ }
85
+
86
+ const implementPlan = ctx.readFile(join(taskDirFull, "implement.md"))
87
+ if (implementPlan) {
88
+ parts.push(`=== ${taskDir}/implement.md (Execution Plan) ===\n${implementPlan}`)
89
+ }
90
+
59
91
  return parts.join("\n\n")
60
92
  }
61
93
 
@@ -128,7 +160,8 @@ function getResearchContext(ctx) {
128
160
  */
129
161
  function buildPrompt(agentType, originalPrompt, context, isFinish = false) {
130
162
  const templates = {
131
- implement: `# Implement Agent Task
163
+ implement: `<!-- trellis-hook-injected -->
164
+ # Implement Agent Task
132
165
 
133
166
  You are the Implement Agent in the Multi-Agent Pipeline.
134
167
 
@@ -147,8 +180,8 @@ ${originalPrompt}
147
180
  ## Workflow
148
181
 
149
182
  1. **Understand specs** - All dev specs are injected above
150
- 2. **Understand requirements** - Read requirements and technical design
151
- 3. **Implement feature** - Follow specs and design
183
+ 2. **Understand task artifacts** - Read requirements, technical design if present, and execution plan if present
184
+ 3. **Implement feature** - Follow specs and task artifacts
152
185
  4. **Self-check** - Ensure code quality
153
186
 
154
187
  ## Important Constraints
@@ -157,7 +190,8 @@ ${originalPrompt}
157
190
  - Follow all dev specs injected above
158
191
  - Report list of modified/created files when done`,
159
192
 
160
- check: isFinish ? `# Finish Agent Task
193
+ check: isFinish ? `<!-- trellis-hook-injected -->
194
+ # Finish Agent Task
161
195
 
162
196
  You are performing the final check before creating a PR.
163
197
 
@@ -176,7 +210,7 @@ ${originalPrompt}
176
210
  ## Workflow
177
211
 
178
212
  1. **Review changes** - Run \`git diff --name-only\` to see all changed files
179
- 2. **Verify requirements** - Check each requirement in prd.md is implemented
213
+ 2. **Verify task artifacts** - Check prd.md and, when present, design.md / implement.md
180
214
  3. **Spec sync** - Analyze whether changes introduce new patterns, contracts, or conventions
181
215
  - If new pattern/convention found: read target spec file → update it → update index.md if needed
182
216
  - If infra/cross-layer change: follow the 7-section mandatory template from update-spec.md
@@ -190,8 +224,10 @@ ${originalPrompt}
190
224
  - MUST read the target spec file BEFORE editing (avoid duplicating existing content)
191
225
  - Do NOT update specs for trivial changes (typos, formatting, obvious fixes)
192
226
  - If critical CODE issues found, report them clearly (fix specs, not code)
193
- - Verify all acceptance criteria in prd.md are met` :
194
- `# Check Agent Task
227
+ - Verify all acceptance criteria in prd.md are met
228
+ - Verify design.md and implement.md constraints when those files are present` :
229
+ `<!-- trellis-hook-injected -->
230
+ # Check Agent Task
195
231
 
196
232
  You are the Check Agent in the Multi-Agent Pipeline.
197
233
 
@@ -219,7 +255,8 @@ ${originalPrompt}
219
255
  - Fix issues yourself, don't just report
220
256
  - Must execute complete checklist`,
221
257
 
222
- research: `# Research Agent Task
258
+ research: `<!-- trellis-hook-injected -->
259
+ # Research Agent Task
223
260
 
224
261
  You are the Research Agent in the Multi-Agent Pipeline.
225
262
 
@@ -264,9 +301,29 @@ function powershellQuote(value) {
264
301
  return `'${String(value).replace(/'/g, "''")}'`
265
302
  }
266
303
 
267
- function buildTrellisContextPrefix(contextKey, hostPlatform = process.platform) {
268
- if (hostPlatform === "win32") {
269
- // OpenCode's Windows Bash tool runs through PowerShell, not a POSIX shell.
304
+ function envValue(env, key) {
305
+ const value = env?.[key]
306
+ return typeof value === "string" && value.trim() ? value.trim() : null
307
+ }
308
+
309
+ function shellBasename(value) {
310
+ return value.replace(/\\/g, "/").split("/").pop()?.toLowerCase() || ""
311
+ }
312
+
313
+ function isWindowsPosixShell(env = process.env) {
314
+ if (envValue(env, "MSYSTEM")) return true
315
+ if (envValue(env, "MINGW_PREFIX")) return true
316
+ if (envValue(env, "OPENCODE_GIT_BASH_PATH")) return true
317
+
318
+ const ostype = envValue(env, "OSTYPE")?.toLowerCase() || ""
319
+ if (/(msys|mingw|cygwin)/.test(ostype)) return true
320
+
321
+ const shell = shellBasename(envValue(env, "SHELL") || "")
322
+ return /^(bash|sh|zsh)(\.exe)?$/.test(shell)
323
+ }
324
+
325
+ function buildTrellisContextPrefix(contextKey, hostPlatform = process.platform, env = process.env) {
326
+ if (hostPlatform === "win32" && !isWindowsPosixShell(env)) {
270
327
  return `$env:TRELLIS_CONTEXT_ID = ${powershellQuote(contextKey)}; `
271
328
  }
272
329
 
@@ -285,7 +342,7 @@ function commandStartsWithTrellisContext(command) {
285
342
  return (
286
343
  /^TRELLIS_CONTEXT_ID\s*=/.test(firstCommand) ||
287
344
  /^export\s+TRELLIS_CONTEXT_ID\s*=/.test(firstCommand) ||
288
- /^env\s+(?:[^\s=]+\s+)*TRELLIS_CONTEXT_ID\s*=/.test(firstCommand) ||
345
+ /^env\s+(?:(?:-\S+|[A-Za-z_][A-Za-z0-9_]*=\S*)\s+)*TRELLIS_CONTEXT_ID\s*=/.test(firstCommand) ||
289
346
  /^\$env:TRELLIS_CONTEXT_ID\s*=/i.test(firstCommand)
290
347
  )
291
348
  }
@@ -294,7 +351,7 @@ function commandStartsWithTrellisContext(command) {
294
351
  * OpenCode TUI may not expose OPENCODE_RUN_ID to Bash. The plugin hook still
295
352
  * receives session identity, so inject it into Bash commands before execution.
296
353
  */
297
- function injectTrellisContextIntoBash(ctx, input, output, hostPlatform) {
354
+ function injectTrellisContextIntoBash(ctx, input, output, hostPlatform, env) {
298
355
  const args = output?.args
299
356
  const commandKey = getBashCommandKey(args)
300
357
  if (!commandKey) return false
@@ -306,7 +363,7 @@ function injectTrellisContextIntoBash(ctx, input, output, hostPlatform) {
306
363
  const contextKey = ctx.getContextKey(input)
307
364
  if (!contextKey) return false
308
365
 
309
- args[commandKey] = `${buildTrellisContextPrefix(contextKey, hostPlatform)}${command}`
366
+ args[commandKey] = `${buildTrellisContextPrefix(contextKey, hostPlatform, env)}${command}`
310
367
  return true
311
368
  }
312
369
 
@@ -315,7 +372,7 @@ function injectTrellisContextIntoBash(ctx, input, output, hostPlatform) {
315
372
  // (packages/opencode/src/plugin/index.ts — `for ([_, fn] of Object.entries(mod)) await fn(input)`);
316
373
  // the previous `{ id, server }` object shape failed with
317
374
  // `TypeError: fn is not a function` in 1.2.x.
318
- export default async ({ directory, platform: hostPlatform = process.platform }) => {
375
+ export default async ({ directory, platform: hostPlatform = process.platform, env = process.env }) => {
319
376
  const ctx = new TrellisContext(directory)
320
377
  debugLog("inject", "Plugin loaded, directory:", directory)
321
378
 
@@ -329,7 +386,7 @@ export default async ({ directory, platform: hostPlatform = process.platform })
329
386
 
330
387
  const toolName = input?.tool?.toLowerCase()
331
388
  if (toolName === "bash") {
332
- if (injectTrellisContextIntoBash(ctx, input, output, hostPlatform)) {
389
+ if (injectTrellisContextIntoBash(ctx, input, output, hostPlatform, env)) {
333
390
  debugLog("inject", "Injected TRELLIS_CONTEXT_ID into Bash command")
334
391
  }
335
392
  return
@@ -354,8 +411,53 @@ export default async ({ directory, platform: hostPlatform = process.platform })
354
411
  return
355
412
  }
356
413
 
357
- // Resolve active task through session runtime context.
358
- const taskDir = ctx.getCurrentTask(input)
414
+ // Resolve active task in this priority order (only later steps
415
+ // run when earlier ones miss):
416
+ // 1. Exact session runtime context lookup for input.sessionID
417
+ // 2. `Active task: <path>` hint in the dispatch prompt
418
+ // (explicit per-dispatch override — beats single-session
419
+ // inference so multi-window users can disambiguate)
420
+ // 3. Single-session fallback — only when exactly 1 session
421
+ // runtime file exists locally
422
+ let taskDir = null
423
+ let taskSource = null
424
+
425
+ const contextKey = ctx.getContextKey(input)
426
+ if (contextKey) {
427
+ const context = ctx.readContext(contextKey)
428
+ const exactRef = ctx.normalizeTaskRef(context?.current_task || "")
429
+ if (exactRef) {
430
+ taskDir = exactRef
431
+ taskSource = `session:${contextKey}`
432
+ }
433
+ }
434
+
435
+ if (!taskDir) {
436
+ const hintRef = extractActiveTaskHint(originalPrompt)
437
+ if (hintRef) {
438
+ const hintNormalized = ctx.normalizeTaskRef(hintRef)
439
+ if (hintNormalized) {
440
+ const hintDir = ctx.resolveTaskDir(hintNormalized)
441
+ if (hintDir && existsSync(hintDir)) {
442
+ taskDir = hintNormalized
443
+ taskSource = "prompt-hint"
444
+ debugLog("inject", "Resolved task from Active task: hint:", hintNormalized)
445
+ }
446
+ }
447
+ }
448
+ }
449
+
450
+ if (!taskDir) {
451
+ const fallback = ctx._resolveSingleSessionFallback()
452
+ if (fallback?.taskPath) {
453
+ const fallbackDir = ctx.resolveTaskDir(fallback.taskPath)
454
+ if (fallbackDir && existsSync(fallbackDir)) {
455
+ taskDir = fallback.taskPath
456
+ taskSource = fallback.source
457
+ debugLog("inject", "Resolved task via single-session fallback:", taskDir, "source:", taskSource)
458
+ }
459
+ }
460
+ }
359
461
 
360
462
  // Agents requiring task directory
361
463
  if (AGENTS_REQUIRE_TASK.includes(subagentType)) {
@@ -364,8 +466,8 @@ export default async ({ directory, platform: hostPlatform = process.platform })
364
466
  debugLog("inject", "Skipping - no current task")
365
467
  return
366
468
  }
367
- const taskDirFull = join(directory, taskDir)
368
- if (!existsSync(taskDirFull)) {
469
+ const taskDirFull = ctx.resolveTaskDir(taskDir)
470
+ if (!taskDirFull || !existsSync(taskDirFull)) {
369
471
  debugLog("inject", "Skipping - task directory not found")
370
472
  return
371
473
  }
@@ -25,7 +25,7 @@
25
25
 
26
26
  import { existsSync, readFileSync } from "fs"
27
27
  import { join } from "path"
28
- import { TrellisContext, debugLog } from "../lib/trellis-context.js"
28
+ import { TrellisContext, debugLog, isTrellisSubagent } from "../lib/trellis-context.js"
29
29
 
30
30
  // Supports STATUS values with letters, digits, underscores, hyphens
31
31
  // (so "in-review" / "blocked-by-team" work alongside "in_progress").
@@ -89,15 +89,12 @@ function getActiveTask(ctx, platformInput = null) {
89
89
  * "Refer to workflow.md for current step." line
90
90
  * - no_task pseudo-status (id === null) → header omits task info
91
91
  */
92
- function buildBreadcrumb(id, status, templates, source = null) {
92
+ function buildBreadcrumb(id, status, templates) {
93
93
  let body = templates[status]
94
94
  if (body === undefined) {
95
95
  body = "Refer to workflow.md for current step."
96
96
  }
97
97
  let header = id === null ? `Status: ${status}` : `Task: ${id} (${status})`
98
- if (source) {
99
- header = `${header}\nSource: ${source}`
100
- }
101
98
  return `<workflow-state>\n${header}\n${body}\n</workflow-state>`
102
99
  }
103
100
 
@@ -111,6 +108,13 @@ export default async ({ directory }) => {
111
108
  // so it persists in conversation history.
112
109
  "chat.message": async (input, output) => {
113
110
  try {
111
+ // Skip Trellis sub-agent turns — the per-turn breadcrumb is for the
112
+ // main session only; sub-agent context comes from the parent's
113
+ // tool.execute.before injection.
114
+ if (isTrellisSubagent(input)) {
115
+ debugLog("workflow-state", "Skipping trellis subagent turn:", input?.agent)
116
+ return
117
+ }
114
118
  if (process.env.TRELLIS_HOOKS === "0" || process.env.TRELLIS_DISABLE_HOOKS === "1") {
115
119
  return
116
120
  }
@@ -6,7 +6,7 @@
6
6
  * Uses OpenCode's chat.message hook directly so the context persists in history.
7
7
  */
8
8
 
9
- import { TrellisContext, contextCollector, debugLog } from "../lib/trellis-context.js"
9
+ import { TrellisContext, contextCollector, debugLog, isTrellisSubagent } from "../lib/trellis-context.js"
10
10
  import {
11
11
  buildSessionContext,
12
12
  hasPersistedInjectedContext,
@@ -43,6 +43,14 @@ export default async ({ directory, client }) => {
43
43
  const agent = input.agent || "unknown"
44
44
  debugLog("session", "chat.message called, sessionID:", sessionID, "agent:", agent)
45
45
 
46
+ // Skip Trellis sub-agent turns — sub-agent context is injected by
47
+ // `inject-subagent-context.js` on the parent's tool.execute.before;
48
+ // re-injecting the main-session SessionStart here would drown that.
49
+ if (isTrellisSubagent(input)) {
50
+ debugLog("session", "Skipping trellis subagent turn:", agent)
51
+ return
52
+ }
53
+
46
54
  if (process.env.TRELLIS_HOOKS === "0" || process.env.TRELLIS_DISABLE_HOOKS === "1") {
47
55
  debugLog("session", "Skipping - TRELLIS_HOOKS disabled")
48
56
  return
@@ -19,10 +19,11 @@ You are already the `trellis-check` sub-agent that the main session dispatched.
19
19
  ## Core Responsibilities
20
20
 
21
21
  1. Inspect the current git diff.
22
- 2. Read and follow the spec and research files listed in the task's `check.jsonl`.
23
- 3. Review all changed code against the task PRD and project specs.
24
- 4. Fix issues directly when they are within scope.
25
- 5. Run the relevant lint, typecheck, and focused tests available for the touched code.
22
+ 2. Read `prd.md`, `design.md` if present, and `implement.md` if present.
23
+ 3. Read and follow the spec and research files listed in the task's `check.jsonl`.
24
+ 4. Review all changed code against the task artifacts and project specs.
25
+ 5. Fix issues directly when they are within scope.
26
+ 6. Run the relevant lint, typecheck, and focused tests available for the touched code.
26
27
 
27
28
  ## Review Priorities
28
29
 
@@ -19,10 +19,11 @@ You are already the `trellis-implement` sub-agent that the main session dispatch
19
19
  ## Core Responsibilities
20
20
 
21
21
  1. Understand the active task requirements.
22
- 2. Read and follow the spec and research files listed in the task's `implement.jsonl`.
23
- 3. Implement the requested change using existing project patterns.
24
- 4. Run the relevant lint, typecheck, and focused tests available for the touched code.
25
- 5. Report files changed and verification results.
22
+ 2. Read `prd.md`, `design.md` if present, and `implement.md` if present.
23
+ 3. Read and follow the spec and research files listed in the task's `implement.jsonl`.
24
+ 4. Implement the requested change using existing project patterns.
25
+ 5. Run the relevant lint, typecheck, and focused tests available for the touched code.
26
+ 6. Report files changed and verification results.
26
27
 
27
28
  ## Forbidden Operations
28
29