@blulotus/trellis 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (821) hide show
  1. package/LICENSE +235 -0
  2. package/README.md +149 -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 +276 -0
  7. package/dist/cli/index.js.map +1 -0
  8. package/dist/commands/channel/adapters/claude.d.ts +29 -0
  9. package/dist/commands/channel/adapters/claude.d.ts.map +1 -0
  10. package/dist/commands/channel/adapters/claude.js +203 -0
  11. package/dist/commands/channel/adapters/claude.js.map +1 -0
  12. package/dist/commands/channel/adapters/codex.d.ts +93 -0
  13. package/dist/commands/channel/adapters/codex.d.ts.map +1 -0
  14. package/dist/commands/channel/adapters/codex.js +573 -0
  15. package/dist/commands/channel/adapters/codex.js.map +1 -0
  16. package/dist/commands/channel/adapters/index.d.ts +86 -0
  17. package/dist/commands/channel/adapters/index.d.ts.map +1 -0
  18. package/dist/commands/channel/adapters/index.js +115 -0
  19. package/dist/commands/channel/adapters/index.js.map +1 -0
  20. package/dist/commands/channel/adapters/types.d.ts +33 -0
  21. package/dist/commands/channel/adapters/types.d.ts.map +1 -0
  22. package/dist/commands/channel/adapters/types.js +2 -0
  23. package/dist/commands/channel/adapters/types.js.map +1 -0
  24. package/dist/commands/channel/agent-loader.d.ts +32 -0
  25. package/dist/commands/channel/agent-loader.d.ts.map +1 -0
  26. package/dist/commands/channel/agent-loader.js +158 -0
  27. package/dist/commands/channel/agent-loader.js.map +1 -0
  28. package/dist/commands/channel/context-loader.d.ts +26 -0
  29. package/dist/commands/channel/context-loader.d.ts.map +1 -0
  30. package/dist/commands/channel/context-loader.js +311 -0
  31. package/dist/commands/channel/context-loader.js.map +1 -0
  32. package/dist/commands/channel/context-trust.d.ts +31 -0
  33. package/dist/commands/channel/context-trust.d.ts.map +1 -0
  34. package/dist/commands/channel/context-trust.js +139 -0
  35. package/dist/commands/channel/context-trust.js.map +1 -0
  36. package/dist/commands/channel/context.d.ts +16 -0
  37. package/dist/commands/channel/context.d.ts.map +1 -0
  38. package/dist/commands/channel/context.js +83 -0
  39. package/dist/commands/channel/context.js.map +1 -0
  40. package/dist/commands/channel/create.d.ts +27 -0
  41. package/dist/commands/channel/create.d.ts.map +1 -0
  42. package/dist/commands/channel/create.js +39 -0
  43. package/dist/commands/channel/create.js.map +1 -0
  44. package/dist/commands/channel/dev-parse-trace.d.ts +14 -0
  45. package/dist/commands/channel/dev-parse-trace.d.ts.map +1 -0
  46. package/dist/commands/channel/dev-parse-trace.js +70 -0
  47. package/dist/commands/channel/dev-parse-trace.js.map +1 -0
  48. package/dist/commands/channel/guard.d.ts +150 -0
  49. package/dist/commands/channel/guard.d.ts.map +1 -0
  50. package/dist/commands/channel/guard.js +479 -0
  51. package/dist/commands/channel/guard.js.map +1 -0
  52. package/dist/commands/channel/index.d.ts +3 -0
  53. package/dist/commands/channel/index.d.ts.map +1 -0
  54. package/dist/commands/channel/index.js +535 -0
  55. package/dist/commands/channel/index.js.map +1 -0
  56. package/dist/commands/channel/interrupt.d.ts +10 -0
  57. package/dist/commands/channel/interrupt.d.ts.map +1 -0
  58. package/dist/commands/channel/interrupt.js +22 -0
  59. package/dist/commands/channel/interrupt.js.map +1 -0
  60. package/dist/commands/channel/kill.d.ts +7 -0
  61. package/dist/commands/channel/kill.d.ts.map +1 -0
  62. package/dist/commands/channel/kill.js +121 -0
  63. package/dist/commands/channel/kill.js.map +1 -0
  64. package/dist/commands/channel/list.d.ts +17 -0
  65. package/dist/commands/channel/list.d.ts.map +1 -0
  66. package/dist/commands/channel/list.js +233 -0
  67. package/dist/commands/channel/list.js.map +1 -0
  68. package/dist/commands/channel/messages.d.ts +15 -0
  69. package/dist/commands/channel/messages.d.ts.map +1 -0
  70. package/dist/commands/channel/messages.js +245 -0
  71. package/dist/commands/channel/messages.js.map +1 -0
  72. package/dist/commands/channel/rm.d.ts +27 -0
  73. package/dist/commands/channel/rm.d.ts.map +1 -0
  74. package/dist/commands/channel/rm.js +216 -0
  75. package/dist/commands/channel/rm.js.map +1 -0
  76. package/dist/commands/channel/run.d.ts +30 -0
  77. package/dist/commands/channel/run.d.ts.map +1 -0
  78. package/dist/commands/channel/run.js +130 -0
  79. package/dist/commands/channel/run.js.map +1 -0
  80. package/dist/commands/channel/send.d.ts +11 -0
  81. package/dist/commands/channel/send.d.ts.map +1 -0
  82. package/dist/commands/channel/send.js +24 -0
  83. package/dist/commands/channel/send.js.map +1 -0
  84. package/dist/commands/channel/spawn.d.ts +43 -0
  85. package/dist/commands/channel/spawn.d.ts.map +1 -0
  86. package/dist/commands/channel/spawn.js +247 -0
  87. package/dist/commands/channel/spawn.js.map +1 -0
  88. package/dist/commands/channel/store/events.d.ts +39 -0
  89. package/dist/commands/channel/store/events.d.ts.map +1 -0
  90. package/dist/commands/channel/store/events.js +87 -0
  91. package/dist/commands/channel/store/events.js.map +1 -0
  92. package/dist/commands/channel/store/filter.d.ts +3 -0
  93. package/dist/commands/channel/store/filter.d.ts.map +1 -0
  94. package/dist/commands/channel/store/filter.js +2 -0
  95. package/dist/commands/channel/store/filter.js.map +1 -0
  96. package/dist/commands/channel/store/lock.d.ts +23 -0
  97. package/dist/commands/channel/store/lock.d.ts.map +1 -0
  98. package/dist/commands/channel/store/lock.js +99 -0
  99. package/dist/commands/channel/store/lock.js.map +1 -0
  100. package/dist/commands/channel/store/paths.d.ts +77 -0
  101. package/dist/commands/channel/store/paths.d.ts.map +1 -0
  102. package/dist/commands/channel/store/paths.js +272 -0
  103. package/dist/commands/channel/store/paths.js.map +1 -0
  104. package/dist/commands/channel/store/schema.d.ts +27 -0
  105. package/dist/commands/channel/store/schema.d.ts.map +1 -0
  106. package/dist/commands/channel/store/schema.js +34 -0
  107. package/dist/commands/channel/store/schema.js.map +1 -0
  108. package/dist/commands/channel/store/thread-state.d.ts +5 -0
  109. package/dist/commands/channel/store/thread-state.d.ts.map +1 -0
  110. package/dist/commands/channel/store/thread-state.js +16 -0
  111. package/dist/commands/channel/store/thread-state.js.map +1 -0
  112. package/dist/commands/channel/store/watch.d.ts +19 -0
  113. package/dist/commands/channel/store/watch.d.ts.map +1 -0
  114. package/dist/commands/channel/store/watch.js +146 -0
  115. package/dist/commands/channel/store/watch.js.map +1 -0
  116. package/dist/commands/channel/supervisor/idle.d.ts +45 -0
  117. package/dist/commands/channel/supervisor/idle.d.ts.map +1 -0
  118. package/dist/commands/channel/supervisor/idle.js +70 -0
  119. package/dist/commands/channel/supervisor/idle.js.map +1 -0
  120. package/dist/commands/channel/supervisor/inbox.d.ts +30 -0
  121. package/dist/commands/channel/supervisor/inbox.d.ts.map +1 -0
  122. package/dist/commands/channel/supervisor/inbox.js +160 -0
  123. package/dist/commands/channel/supervisor/inbox.js.map +1 -0
  124. package/dist/commands/channel/supervisor/shutdown.d.ts +68 -0
  125. package/dist/commands/channel/supervisor/shutdown.d.ts.map +1 -0
  126. package/dist/commands/channel/supervisor/shutdown.js +146 -0
  127. package/dist/commands/channel/supervisor/shutdown.js.map +1 -0
  128. package/dist/commands/channel/supervisor/stdout.d.ts +53 -0
  129. package/dist/commands/channel/supervisor/stdout.d.ts.map +1 -0
  130. package/dist/commands/channel/supervisor/stdout.js +168 -0
  131. package/dist/commands/channel/supervisor/stdout.js.map +1 -0
  132. package/dist/commands/channel/supervisor/turns.d.ts +31 -0
  133. package/dist/commands/channel/supervisor/turns.d.ts.map +1 -0
  134. package/dist/commands/channel/supervisor/turns.js +45 -0
  135. package/dist/commands/channel/supervisor/turns.js.map +1 -0
  136. package/dist/commands/channel/supervisor/warning.d.ts +48 -0
  137. package/dist/commands/channel/supervisor/warning.d.ts.map +1 -0
  138. package/dist/commands/channel/supervisor/warning.js +77 -0
  139. package/dist/commands/channel/supervisor/warning.js.map +1 -0
  140. package/dist/commands/channel/supervisor.d.ts +75 -0
  141. package/dist/commands/channel/supervisor.d.ts.map +1 -0
  142. package/dist/commands/channel/supervisor.js +397 -0
  143. package/dist/commands/channel/supervisor.js.map +1 -0
  144. package/dist/commands/channel/text-body.d.ts +13 -0
  145. package/dist/commands/channel/text-body.d.ts.map +1 -0
  146. package/dist/commands/channel/text-body.js +47 -0
  147. package/dist/commands/channel/text-body.js.map +1 -0
  148. package/dist/commands/channel/threads.d.ts +39 -0
  149. package/dist/commands/channel/threads.d.ts.map +1 -0
  150. package/dist/commands/channel/threads.js +106 -0
  151. package/dist/commands/channel/threads.js.map +1 -0
  152. package/dist/commands/channel/title.d.ts +12 -0
  153. package/dist/commands/channel/title.d.ts.map +1 -0
  154. package/dist/commands/channel/title.js +24 -0
  155. package/dist/commands/channel/title.js.map +1 -0
  156. package/dist/commands/channel/wait.d.ts +17 -0
  157. package/dist/commands/channel/wait.d.ts.map +1 -0
  158. package/dist/commands/channel/wait.js +75 -0
  159. package/dist/commands/channel/wait.js.map +1 -0
  160. package/dist/commands/init.d.ts +71 -0
  161. package/dist/commands/init.d.ts.map +1 -0
  162. package/dist/commands/init.js +1603 -0
  163. package/dist/commands/init.js.map +1 -0
  164. package/dist/commands/mem.d.ts +30 -0
  165. package/dist/commands/mem.d.ts.map +1 -0
  166. package/dist/commands/mem.js +447 -0
  167. package/dist/commands/mem.js.map +1 -0
  168. package/dist/commands/uninstall.d.ts +36 -0
  169. package/dist/commands/uninstall.d.ts.map +1 -0
  170. package/dist/commands/uninstall.js +410 -0
  171. package/dist/commands/uninstall.js.map +1 -0
  172. package/dist/commands/update.d.ts +111 -0
  173. package/dist/commands/update.d.ts.map +1 -0
  174. package/dist/commands/update.js +2152 -0
  175. package/dist/commands/update.js.map +1 -0
  176. package/dist/commands/upgrade.d.ts +28 -0
  177. package/dist/commands/upgrade.d.ts.map +1 -0
  178. package/dist/commands/upgrade.js +84 -0
  179. package/dist/commands/upgrade.js.map +1 -0
  180. package/dist/commands/workflow.d.ts +52 -0
  181. package/dist/commands/workflow.d.ts.map +1 -0
  182. package/dist/commands/workflow.js +454 -0
  183. package/dist/commands/workflow.js.map +1 -0
  184. package/dist/configurators/antigravity.d.ts +7 -0
  185. package/dist/configurators/antigravity.d.ts.map +1 -0
  186. package/dist/configurators/antigravity.js +11 -0
  187. package/dist/configurators/antigravity.js.map +1 -0
  188. package/dist/configurators/claude.d.ts +23 -0
  189. package/dist/configurators/claude.d.ts.map +1 -0
  190. package/dist/configurators/claude.js +123 -0
  191. package/dist/configurators/claude.js.map +1 -0
  192. package/dist/configurators/codebuddy.d.ts +10 -0
  193. package/dist/configurators/codebuddy.d.ts.map +1 -0
  194. package/dist/configurators/codebuddy.js +24 -0
  195. package/dist/configurators/codebuddy.js.map +1 -0
  196. package/dist/configurators/codex.d.ts +57 -0
  197. package/dist/configurators/codex.d.ts.map +1 -0
  198. package/dist/configurators/codex.js +170 -0
  199. package/dist/configurators/codex.js.map +1 -0
  200. package/dist/configurators/copilot.d.ts +14 -0
  201. package/dist/configurators/copilot.d.ts.map +1 -0
  202. package/dist/configurators/copilot.js +46 -0
  203. package/dist/configurators/copilot.js.map +1 -0
  204. package/dist/configurators/cursor.d.ts +10 -0
  205. package/dist/configurators/cursor.d.ts.map +1 -0
  206. package/dist/configurators/cursor.js +23 -0
  207. package/dist/configurators/cursor.js.map +1 -0
  208. package/dist/configurators/devin.d.ts +8 -0
  209. package/dist/configurators/devin.d.ts.map +1 -0
  210. package/dist/configurators/devin.js +12 -0
  211. package/dist/configurators/devin.js.map +1 -0
  212. package/dist/configurators/droid.d.ts +10 -0
  213. package/dist/configurators/droid.d.ts.map +1 -0
  214. package/dist/configurators/droid.js +24 -0
  215. package/dist/configurators/droid.js.map +1 -0
  216. package/dist/configurators/dsh.d.ts +26 -0
  217. package/dist/configurators/dsh.d.ts.map +1 -0
  218. package/dist/configurators/dsh.js +76 -0
  219. package/dist/configurators/dsh.js.map +1 -0
  220. package/dist/configurators/gemini.d.ts +18 -0
  221. package/dist/configurators/gemini.d.ts.map +1 -0
  222. package/dist/configurators/gemini.js +39 -0
  223. package/dist/configurators/gemini.js.map +1 -0
  224. package/dist/configurators/grok.d.ts +17 -0
  225. package/dist/configurators/grok.d.ts.map +1 -0
  226. package/dist/configurators/grok.js +38 -0
  227. package/dist/configurators/grok.js.map +1 -0
  228. package/dist/configurators/index.d.ts +68 -0
  229. package/dist/configurators/index.d.ts.map +1 -0
  230. package/dist/configurators/index.js +191 -0
  231. package/dist/configurators/index.js.map +1 -0
  232. package/dist/configurators/kilo.d.ts +7 -0
  233. package/dist/configurators/kilo.d.ts.map +1 -0
  234. package/dist/configurators/kilo.js +11 -0
  235. package/dist/configurators/kilo.js.map +1 -0
  236. package/dist/configurators/kimi.d.ts +26 -0
  237. package/dist/configurators/kimi.d.ts.map +1 -0
  238. package/dist/configurators/kimi.js +74 -0
  239. package/dist/configurators/kimi.js.map +1 -0
  240. package/dist/configurators/kiro.d.ts +11 -0
  241. package/dist/configurators/kiro.d.ts.map +1 -0
  242. package/dist/configurators/kiro.js +30 -0
  243. package/dist/configurators/kiro.js.map +1 -0
  244. package/dist/configurators/omp.d.ts +6 -0
  245. package/dist/configurators/omp.d.ts.map +1 -0
  246. package/dist/configurators/omp.js +28 -0
  247. package/dist/configurators/omp.js.map +1 -0
  248. package/dist/configurators/opencode.d.ts +5 -0
  249. package/dist/configurators/opencode.d.ts.map +1 -0
  250. package/dist/configurators/opencode.js +84 -0
  251. package/dist/configurators/opencode.js.map +1 -0
  252. package/dist/configurators/pi.d.ts +5 -0
  253. package/dist/configurators/pi.d.ts.map +1 -0
  254. package/dist/configurators/pi.js +39 -0
  255. package/dist/configurators/pi.js.map +1 -0
  256. package/dist/configurators/qoder.d.ts +12 -0
  257. package/dist/configurators/qoder.d.ts.map +1 -0
  258. package/dist/configurators/qoder.js +30 -0
  259. package/dist/configurators/qoder.js.map +1 -0
  260. package/dist/configurators/reasonix.d.ts +17 -0
  261. package/dist/configurators/reasonix.d.ts.map +1 -0
  262. package/dist/configurators/reasonix.js +37 -0
  263. package/dist/configurators/reasonix.js.map +1 -0
  264. package/dist/configurators/shared.d.ts +187 -0
  265. package/dist/configurators/shared.d.ts.map +1 -0
  266. package/dist/configurators/shared.js +590 -0
  267. package/dist/configurators/shared.js.map +1 -0
  268. package/dist/configurators/snow.d.ts +25 -0
  269. package/dist/configurators/snow.d.ts.map +1 -0
  270. package/dist/configurators/snow.js +69 -0
  271. package/dist/configurators/snow.js.map +1 -0
  272. package/dist/configurators/trae.d.ts +16 -0
  273. package/dist/configurators/trae.d.ts.map +1 -0
  274. package/dist/configurators/trae.js +34 -0
  275. package/dist/configurators/trae.js.map +1 -0
  276. package/dist/configurators/workflow.d.ts +51 -0
  277. package/dist/configurators/workflow.d.ts.map +1 -0
  278. package/dist/configurators/workflow.js +210 -0
  279. package/dist/configurators/workflow.js.map +1 -0
  280. package/dist/configurators/zcode.d.ts +23 -0
  281. package/dist/configurators/zcode.d.ts.map +1 -0
  282. package/dist/configurators/zcode.js +63 -0
  283. package/dist/configurators/zcode.js.map +1 -0
  284. package/dist/constants/paths.d.ts +74 -0
  285. package/dist/constants/paths.d.ts.map +1 -0
  286. package/dist/constants/paths.js +83 -0
  287. package/dist/constants/paths.js.map +1 -0
  288. package/dist/constants/version.d.ts +9 -0
  289. package/dist/constants/version.d.ts.map +1 -0
  290. package/dist/constants/version.js +15 -0
  291. package/dist/constants/version.js.map +1 -0
  292. package/dist/index.d.ts +9 -0
  293. package/dist/index.d.ts.map +1 -0
  294. package/dist/index.js +9 -0
  295. package/dist/index.js.map +1 -0
  296. package/dist/migrations/index.d.ts +62 -0
  297. package/dist/migrations/index.d.ts.map +1 -0
  298. package/dist/migrations/index.js +187 -0
  299. package/dist/migrations/index.js.map +1 -0
  300. package/dist/migrations/manifests/0.1.9.json +30 -0
  301. package/dist/migrations/manifests/0.2.0.json +49 -0
  302. package/dist/migrations/manifests/0.2.12.json +9 -0
  303. package/dist/migrations/manifests/0.2.13.json +9 -0
  304. package/dist/migrations/manifests/0.2.14.json +175 -0
  305. package/dist/migrations/manifests/0.2.15.json +33 -0
  306. package/dist/migrations/manifests/0.3.0-beta.0.json +297 -0
  307. package/dist/migrations/manifests/0.3.0-beta.1.json +9 -0
  308. package/dist/migrations/manifests/0.3.0-beta.10.json +9 -0
  309. package/dist/migrations/manifests/0.3.0-beta.11.json +9 -0
  310. package/dist/migrations/manifests/0.3.0-beta.12.json +9 -0
  311. package/dist/migrations/manifests/0.3.0-beta.13.json +9 -0
  312. package/dist/migrations/manifests/0.3.0-beta.14.json +9 -0
  313. package/dist/migrations/manifests/0.3.0-beta.15.json +9 -0
  314. package/dist/migrations/manifests/0.3.0-beta.16.json +9 -0
  315. package/dist/migrations/manifests/0.3.0-beta.2.json +9 -0
  316. package/dist/migrations/manifests/0.3.0-beta.3.json +9 -0
  317. package/dist/migrations/manifests/0.3.0-beta.4.json +9 -0
  318. package/dist/migrations/manifests/0.3.0-beta.5.json +9 -0
  319. package/dist/migrations/manifests/0.3.0-beta.6.json +9 -0
  320. package/dist/migrations/manifests/0.3.0-beta.7.json +11 -0
  321. package/dist/migrations/manifests/0.3.0-beta.8.json +9 -0
  322. package/dist/migrations/manifests/0.3.0-beta.9.json +9 -0
  323. package/dist/migrations/manifests/0.3.0-rc.0.json +9 -0
  324. package/dist/migrations/manifests/0.3.0-rc.1.json +9 -0
  325. package/dist/migrations/manifests/0.3.0-rc.2.json +9 -0
  326. package/dist/migrations/manifests/0.3.0-rc.3.json +9 -0
  327. package/dist/migrations/manifests/0.3.0-rc.4.json +9 -0
  328. package/dist/migrations/manifests/0.3.0-rc.5.json +9 -0
  329. package/dist/migrations/manifests/0.3.0-rc.6.json +9 -0
  330. package/dist/migrations/manifests/0.3.0.json +11 -0
  331. package/dist/migrations/manifests/0.3.1.json +9 -0
  332. package/dist/migrations/manifests/0.3.10.json +9 -0
  333. package/dist/migrations/manifests/0.3.2.json +9 -0
  334. package/dist/migrations/manifests/0.3.3.json +9 -0
  335. package/dist/migrations/manifests/0.3.4.json +21 -0
  336. package/dist/migrations/manifests/0.3.5.json +9 -0
  337. package/dist/migrations/manifests/0.3.6.json +9 -0
  338. package/dist/migrations/manifests/0.3.7.json +9 -0
  339. package/dist/migrations/manifests/0.3.8.json +9 -0
  340. package/dist/migrations/manifests/0.3.9.json +9 -0
  341. package/dist/migrations/manifests/0.4.0-beta.1.json +228 -0
  342. package/dist/migrations/manifests/0.4.0-beta.10.json +9 -0
  343. package/dist/migrations/manifests/0.4.0-beta.2.json +9 -0
  344. package/dist/migrations/manifests/0.4.0-beta.3.json +9 -0
  345. package/dist/migrations/manifests/0.4.0-beta.4.json +9 -0
  346. package/dist/migrations/manifests/0.4.0-beta.5.json +9 -0
  347. package/dist/migrations/manifests/0.4.0-beta.6.json +9 -0
  348. package/dist/migrations/manifests/0.4.0-beta.7.json +9 -0
  349. package/dist/migrations/manifests/0.4.0-beta.8.json +34 -0
  350. package/dist/migrations/manifests/0.4.0-beta.9.json +9 -0
  351. package/dist/migrations/manifests/0.4.0-rc.0.json +9 -0
  352. package/dist/migrations/manifests/0.4.0-rc.1.json +9 -0
  353. package/dist/migrations/manifests/0.4.0.json +9 -0
  354. package/dist/migrations/manifests/0.5.0-beta.0.json +1646 -0
  355. package/dist/migrations/manifests/0.5.0-beta.1.json +9 -0
  356. package/dist/migrations/manifests/0.5.0-beta.10.json +9 -0
  357. package/dist/migrations/manifests/0.5.0-beta.11.json +9 -0
  358. package/dist/migrations/manifests/0.5.0-beta.12.json +9 -0
  359. package/dist/migrations/manifests/0.5.0-beta.13.json +9 -0
  360. package/dist/migrations/manifests/0.5.0-beta.14.json +9 -0
  361. package/dist/migrations/manifests/0.5.0-beta.15.json +116 -0
  362. package/dist/migrations/manifests/0.5.0-beta.16.json +9 -0
  363. package/dist/migrations/manifests/0.5.0-beta.17.json +9 -0
  364. package/dist/migrations/manifests/0.5.0-beta.18.json +9 -0
  365. package/dist/migrations/manifests/0.5.0-beta.19.json +9 -0
  366. package/dist/migrations/manifests/0.5.0-beta.2.json +9 -0
  367. package/dist/migrations/manifests/0.5.0-beta.3.json +9 -0
  368. package/dist/migrations/manifests/0.5.0-beta.4.json +9 -0
  369. package/dist/migrations/manifests/0.5.0-beta.5.json +222 -0
  370. package/dist/migrations/manifests/0.5.0-beta.6.json +9 -0
  371. package/dist/migrations/manifests/0.5.0-beta.7.json +9 -0
  372. package/dist/migrations/manifests/0.5.0-beta.8.json +9 -0
  373. package/dist/migrations/manifests/0.5.0-beta.9.json +48 -0
  374. package/dist/migrations/manifests/0.5.0-rc.0.json +9 -0
  375. package/dist/migrations/manifests/0.5.0-rc.1.json +9 -0
  376. package/dist/migrations/manifests/0.5.0-rc.2.json +9 -0
  377. package/dist/migrations/manifests/0.5.0-rc.3.json +9 -0
  378. package/dist/migrations/manifests/0.5.0-rc.4.json +9 -0
  379. package/dist/migrations/manifests/0.5.0-rc.5.json +9 -0
  380. package/dist/migrations/manifests/0.5.0-rc.6.json +9 -0
  381. package/dist/migrations/manifests/0.5.0-rc.7.json +9 -0
  382. package/dist/migrations/manifests/0.5.0.json +9 -0
  383. package/dist/migrations/manifests/0.5.1.json +9 -0
  384. package/dist/migrations/manifests/0.5.10.json +9 -0
  385. package/dist/migrations/manifests/0.5.11.json +16 -0
  386. package/dist/migrations/manifests/0.5.12.json +9 -0
  387. package/dist/migrations/manifests/0.5.13.json +9 -0
  388. package/dist/migrations/manifests/0.5.14.json +9 -0
  389. package/dist/migrations/manifests/0.5.15.json +9 -0
  390. package/dist/migrations/manifests/0.5.16.json +9 -0
  391. package/dist/migrations/manifests/0.5.17.json +9 -0
  392. package/dist/migrations/manifests/0.5.18.json +9 -0
  393. package/dist/migrations/manifests/0.5.19.json +9 -0
  394. package/dist/migrations/manifests/0.5.2.json +9 -0
  395. package/dist/migrations/manifests/0.5.3.json +9 -0
  396. package/dist/migrations/manifests/0.5.4.json +9 -0
  397. package/dist/migrations/manifests/0.5.5.json +9 -0
  398. package/dist/migrations/manifests/0.5.6.json +9 -0
  399. package/dist/migrations/manifests/0.5.7.json +16 -0
  400. package/dist/migrations/manifests/0.5.8.json +9 -0
  401. package/dist/migrations/manifests/0.5.9.json +9 -0
  402. package/dist/migrations/manifests/0.6.0-beta.0.json +16 -0
  403. package/dist/migrations/manifests/0.6.0-beta.1.json +9 -0
  404. package/dist/migrations/manifests/0.6.0-beta.10.json +9 -0
  405. package/dist/migrations/manifests/0.6.0-beta.11.json +9 -0
  406. package/dist/migrations/manifests/0.6.0-beta.12.json +9 -0
  407. package/dist/migrations/manifests/0.6.0-beta.13.json +9 -0
  408. package/dist/migrations/manifests/0.6.0-beta.14.json +9 -0
  409. package/dist/migrations/manifests/0.6.0-beta.15.json +9 -0
  410. package/dist/migrations/manifests/0.6.0-beta.16.json +9 -0
  411. package/dist/migrations/manifests/0.6.0-beta.17.json +9 -0
  412. package/dist/migrations/manifests/0.6.0-beta.18.json +16 -0
  413. package/dist/migrations/manifests/0.6.0-beta.19.json +9 -0
  414. package/dist/migrations/manifests/0.6.0-beta.2.json +9 -0
  415. package/dist/migrations/manifests/0.6.0-beta.20.json +9 -0
  416. package/dist/migrations/manifests/0.6.0-beta.21.json +9 -0
  417. package/dist/migrations/manifests/0.6.0-beta.22.json +9 -0
  418. package/dist/migrations/manifests/0.6.0-beta.23.json +88 -0
  419. package/dist/migrations/manifests/0.6.0-beta.3.json +9 -0
  420. package/dist/migrations/manifests/0.6.0-beta.4.json +9 -0
  421. package/dist/migrations/manifests/0.6.0-beta.5.json +9 -0
  422. package/dist/migrations/manifests/0.6.0-beta.6.json +16 -0
  423. package/dist/migrations/manifests/0.6.0-beta.7.json +9 -0
  424. package/dist/migrations/manifests/0.6.0-beta.8.json +9 -0
  425. package/dist/migrations/manifests/0.6.0-beta.9.json +9 -0
  426. package/dist/migrations/manifests/0.6.0-rc.0.json +9 -0
  427. package/dist/migrations/manifests/0.6.0.json +1 -0
  428. package/dist/migrations/manifests/0.6.1.json +9 -0
  429. package/dist/migrations/manifests/0.6.10.json +9 -0
  430. package/dist/migrations/manifests/0.6.11.json +9 -0
  431. package/dist/migrations/manifests/0.6.12.json +9 -0
  432. package/dist/migrations/manifests/0.6.13.json +9 -0
  433. package/dist/migrations/manifests/0.6.14.json +9 -0
  434. package/dist/migrations/manifests/0.6.2.json +9 -0
  435. package/dist/migrations/manifests/0.6.3.json +24 -0
  436. package/dist/migrations/manifests/0.6.4.json +9 -0
  437. package/dist/migrations/manifests/0.6.5.json +9 -0
  438. package/dist/migrations/manifests/0.6.6.json +17 -0
  439. package/dist/migrations/manifests/0.6.7.json +9 -0
  440. package/dist/migrations/manifests/0.6.8.json +17 -0
  441. package/dist/migrations/manifests/0.6.9.json +9 -0
  442. package/dist/migrations/manifests/0.7.0-beta.0.json +9 -0
  443. package/dist/migrations/manifests/0.7.0-beta.1.json +9 -0
  444. package/dist/migrations/manifests/0.7.0-beta.2.json +9 -0
  445. package/dist/migrations/manifests/0.7.0-beta.3.json +9 -0
  446. package/dist/templates/claude/agents/trellis-check.md +115 -0
  447. package/dist/templates/claude/agents/trellis-implement.md +115 -0
  448. package/dist/templates/claude/agents/trellis-research.md +137 -0
  449. package/dist/templates/claude/hooks/statusline.py +332 -0
  450. package/dist/templates/claude/index.d.ts +31 -0
  451. package/dist/templates/claude/index.d.ts.map +1 -0
  452. package/dist/templates/claude/index.js +57 -0
  453. package/dist/templates/claude/index.js.map +1 -0
  454. package/dist/templates/claude/settings.json +95 -0
  455. package/dist/templates/codebuddy/agents/trellis-check.md +115 -0
  456. package/dist/templates/codebuddy/agents/trellis-implement.md +115 -0
  457. package/dist/templates/codebuddy/agents/trellis-research.md +137 -0
  458. package/dist/templates/codebuddy/index.d.ts +15 -0
  459. package/dist/templates/codebuddy/index.d.ts.map +1 -0
  460. package/dist/templates/codebuddy/index.js +15 -0
  461. package/dist/templates/codebuddy/index.js.map +1 -0
  462. package/dist/templates/codebuddy/settings.json +69 -0
  463. package/dist/templates/codex/agents/trellis-check.toml +56 -0
  464. package/dist/templates/codex/agents/trellis-implement.toml +37 -0
  465. package/dist/templates/codex/agents/trellis-research.toml +78 -0
  466. package/dist/templates/codex/config.toml +39 -0
  467. package/dist/templates/codex/hooks/session-start.py +568 -0
  468. package/dist/templates/codex/hooks.json +52 -0
  469. package/dist/templates/codex/index.d.ts +35 -0
  470. package/dist/templates/codex/index.d.ts.map +1 -0
  471. package/dist/templates/codex/index.js +67 -0
  472. package/dist/templates/codex/index.js.map +1 -0
  473. package/dist/templates/common/bundled-skills/trellis-channel/SKILL.md +67 -0
  474. package/dist/templates/common/bundled-skills/trellis-channel/references/command-reference.md +480 -0
  475. package/dist/templates/common/bundled-skills/trellis-channel/references/forum.md +233 -0
  476. package/dist/templates/common/bundled-skills/trellis-channel/references/progress-debugging.md +226 -0
  477. package/dist/templates/common/bundled-skills/trellis-channel/references/workers.md +276 -0
  478. package/dist/templates/common/bundled-skills/trellis-channel/references/workflows.md +128 -0
  479. package/dist/templates/common/bundled-skills/trellis-meta/SKILL.md +85 -0
  480. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/add-project-local-conventions.md +83 -0
  481. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-agents.md +56 -0
  482. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-context-loading.md +84 -0
  483. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-hooks.md +57 -0
  484. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-skills-or-commands.md +123 -0
  485. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-spec-structure.md +83 -0
  486. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-task-lifecycle.md +90 -0
  487. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-workflow.md +65 -0
  488. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/overview.md +55 -0
  489. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/bundled-skills.md +159 -0
  490. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/context-injection.md +68 -0
  491. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/generated-files.md +80 -0
  492. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/multi-agent-channel.md +69 -0
  493. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/overview.md +51 -0
  494. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/spec-system.md +102 -0
  495. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/task-system.md +130 -0
  496. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/workflow.md +75 -0
  497. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/workspace-memory.md +71 -0
  498. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/agents.md +84 -0
  499. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/hooks-and-settings.md +73 -0
  500. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/overview.md +59 -0
  501. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/platform-map.md +113 -0
  502. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/skills-and-commands.md +87 -0
  503. package/dist/templates/common/bundled-skills/trellis-session-insight/SKILL.md +81 -0
  504. package/dist/templates/common/bundled-skills/trellis-session-insight/references/cli-quick-reference.md +65 -0
  505. package/dist/templates/common/bundled-skills/trellis-session-insight/references/triggering-patterns.md +93 -0
  506. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/SKILL.md +41 -0
  507. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/mcp-setup.md +90 -0
  508. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/repository-analysis.md +59 -0
  509. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/spec-task-planning.md +61 -0
  510. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/spec-writing.md +70 -0
  511. package/dist/templates/common/commands/continue.md +56 -0
  512. package/dist/templates/common/commands/finish-work.md +66 -0
  513. package/dist/templates/common/commands/start.md +59 -0
  514. package/dist/templates/common/index.d.ts +48 -0
  515. package/dist/templates/common/index.d.ts.map +1 -0
  516. package/dist/templates/common/index.js +104 -0
  517. package/dist/templates/common/index.js.map +1 -0
  518. package/dist/templates/common/skills/before-dev.md +46 -0
  519. package/dist/templates/common/skills/brainstorm.md +212 -0
  520. package/dist/templates/common/skills/break-loop.md +184 -0
  521. package/dist/templates/common/skills/check.md +106 -0
  522. package/dist/templates/common/skills/tdd.md +142 -0
  523. package/dist/templates/common/skills/update-spec.md +351 -0
  524. package/dist/templates/copilot/copilot-instructions.md +11 -0
  525. package/dist/templates/copilot/hooks/session-start.py +564 -0
  526. package/dist/templates/copilot/hooks.json +19 -0
  527. package/dist/templates/copilot/index.d.ts +28 -0
  528. package/dist/templates/copilot/index.d.ts.map +1 -0
  529. package/dist/templates/copilot/index.js +61 -0
  530. package/dist/templates/copilot/index.js.map +1 -0
  531. package/dist/templates/copilot/prompts/before-dev.prompt.md +39 -0
  532. package/dist/templates/copilot/prompts/brainstorm.prompt.md +173 -0
  533. package/dist/templates/copilot/prompts/break-loop.prompt.md +129 -0
  534. package/dist/templates/copilot/prompts/check-cross-layer.prompt.md +170 -0
  535. package/dist/templates/copilot/prompts/check.prompt.md +110 -0
  536. package/dist/templates/copilot/prompts/create-command.prompt.md +116 -0
  537. package/dist/templates/copilot/prompts/finish-work.prompt.md +99 -0
  538. package/dist/templates/copilot/prompts/integrate-skill.prompt.md +223 -0
  539. package/dist/templates/copilot/prompts/onboard.prompt.md +362 -0
  540. package/dist/templates/copilot/prompts/parallel.prompt.md +204 -0
  541. package/dist/templates/copilot/prompts/record-session.prompt.md +66 -0
  542. package/dist/templates/copilot/prompts/start.prompt.md +63 -0
  543. package/dist/templates/copilot/prompts/update-spec.prompt.md +358 -0
  544. package/dist/templates/cursor/agents/trellis-check.md +114 -0
  545. package/dist/templates/cursor/agents/trellis-implement.md +114 -0
  546. package/dist/templates/cursor/agents/trellis-research.md +136 -0
  547. package/dist/templates/cursor/hooks.json +24 -0
  548. package/dist/templates/cursor/index.d.ts +13 -0
  549. package/dist/templates/cursor/index.d.ts.map +1 -0
  550. package/dist/templates/cursor/index.js +13 -0
  551. package/dist/templates/cursor/index.js.map +1 -0
  552. package/dist/templates/droid/droids/trellis-check.md +107 -0
  553. package/dist/templates/droid/droids/trellis-implement.md +107 -0
  554. package/dist/templates/droid/droids/trellis-research.md +137 -0
  555. package/dist/templates/droid/index.d.ts +15 -0
  556. package/dist/templates/droid/index.d.ts.map +1 -0
  557. package/dist/templates/droid/index.js +15 -0
  558. package/dist/templates/droid/index.js.map +1 -0
  559. package/dist/templates/droid/settings.json +69 -0
  560. package/dist/templates/dsh/DSH.md +80 -0
  561. package/dist/templates/dsh/agents/trellis-check.md +99 -0
  562. package/dist/templates/dsh/agents/trellis-implement.md +106 -0
  563. package/dist/templates/dsh/agents/trellis-research.md +134 -0
  564. package/dist/templates/dsh/index.d.ts +22 -0
  565. package/dist/templates/dsh/index.d.ts.map +1 -0
  566. package/dist/templates/dsh/index.js +27 -0
  567. package/dist/templates/dsh/index.js.map +1 -0
  568. package/dist/templates/extract.d.ts +40 -0
  569. package/dist/templates/extract.d.ts.map +1 -0
  570. package/dist/templates/extract.js +106 -0
  571. package/dist/templates/extract.js.map +1 -0
  572. package/dist/templates/gemini/agents/trellis-check.md +107 -0
  573. package/dist/templates/gemini/agents/trellis-implement.md +107 -0
  574. package/dist/templates/gemini/agents/trellis-research.md +136 -0
  575. package/dist/templates/gemini/index.d.ts +13 -0
  576. package/dist/templates/gemini/index.d.ts.map +1 -0
  577. package/dist/templates/gemini/index.js +13 -0
  578. package/dist/templates/gemini/index.js.map +1 -0
  579. package/dist/templates/gemini/settings.json +40 -0
  580. package/dist/templates/grok/agents/trellis-check.md +106 -0
  581. package/dist/templates/grok/agents/trellis-implement.md +121 -0
  582. package/dist/templates/grok/agents/trellis-research.md +146 -0
  583. package/dist/templates/grok/index.d.ts +16 -0
  584. package/dist/templates/grok/index.d.ts.map +1 -0
  585. package/dist/templates/grok/index.js +19 -0
  586. package/dist/templates/grok/index.js.map +1 -0
  587. package/dist/templates/kimi/agents/trellis-check.md +104 -0
  588. package/dist/templates/kimi/agents/trellis-implement.md +120 -0
  589. package/dist/templates/kimi/agents/trellis-research.md +144 -0
  590. package/dist/templates/kimi/index.d.ts +20 -0
  591. package/dist/templates/kimi/index.d.ts.map +1 -0
  592. package/dist/templates/kimi/index.js +23 -0
  593. package/dist/templates/kimi/index.js.map +1 -0
  594. package/dist/templates/kiro/agents/trellis-check.json +26 -0
  595. package/dist/templates/kiro/agents/trellis-implement.json +26 -0
  596. package/dist/templates/kiro/agents/trellis-research.json +30 -0
  597. package/dist/templates/kiro/agents/trellis.json +34 -0
  598. package/dist/templates/kiro/hooks/trellis-workflow-state.kiro.hook +14 -0
  599. package/dist/templates/kiro/index.d.ts +32 -0
  600. package/dist/templates/kiro/index.d.ts.map +1 -0
  601. package/dist/templates/kiro/index.js +28 -0
  602. package/dist/templates/kiro/index.js.map +1 -0
  603. package/dist/templates/markdown/agents.md +21 -0
  604. package/dist/templates/markdown/gitignore.txt +15 -0
  605. package/dist/templates/markdown/index.d.ts +27 -0
  606. package/dist/templates/markdown/index.d.ts.map +1 -0
  607. package/dist/templates/markdown/index.js +52 -0
  608. package/dist/templates/markdown/index.js.map +1 -0
  609. package/dist/templates/markdown/spec/backend/database-guidelines.md.txt +51 -0
  610. package/dist/templates/markdown/spec/backend/directory-structure.md.txt +54 -0
  611. package/dist/templates/markdown/spec/backend/error-handling.md.txt +51 -0
  612. package/dist/templates/markdown/spec/backend/index.md.txt +38 -0
  613. package/dist/templates/markdown/spec/backend/logging-guidelines.md.txt +51 -0
  614. package/dist/templates/markdown/spec/backend/quality-guidelines.md.txt +51 -0
  615. package/dist/templates/markdown/spec/frontend/component-guidelines.md.txt +59 -0
  616. package/dist/templates/markdown/spec/frontend/directory-structure.md.txt +54 -0
  617. package/dist/templates/markdown/spec/frontend/hook-guidelines.md.txt +51 -0
  618. package/dist/templates/markdown/spec/frontend/index.md.txt +39 -0
  619. package/dist/templates/markdown/spec/frontend/quality-guidelines.md.txt +51 -0
  620. package/dist/templates/markdown/spec/frontend/state-management.md.txt +51 -0
  621. package/dist/templates/markdown/spec/frontend/type-safety.md.txt +51 -0
  622. package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +223 -0
  623. package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +327 -0
  624. package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +633 -0
  625. package/dist/templates/markdown/spec/guides/index.md.txt +97 -0
  626. package/dist/templates/markdown/workspace-index.md +125 -0
  627. package/dist/templates/markdown/worktree.yaml.txt +58 -0
  628. package/dist/templates/omp/agents/trellis-check.md +41 -0
  629. package/dist/templates/omp/agents/trellis-implement.md +55 -0
  630. package/dist/templates/omp/agents/trellis-research.md +30 -0
  631. package/dist/templates/omp/extensions/trellis/index.ts.txt +592 -0
  632. package/dist/templates/omp/index.d.ts +4 -0
  633. package/dist/templates/omp/index.d.ts.map +1 -0
  634. package/dist/templates/omp/index.js +9 -0
  635. package/dist/templates/omp/index.js.map +1 -0
  636. package/dist/templates/opencode/agents/trellis-check.md +122 -0
  637. package/dist/templates/opencode/agents/trellis-implement.md +123 -0
  638. package/dist/templates/opencode/agents/trellis-research.md +145 -0
  639. package/dist/templates/opencode/lib/context-visibility.js +86 -0
  640. package/dist/templates/opencode/lib/session-utils.js +526 -0
  641. package/dist/templates/opencode/lib/trellis-context.js +627 -0
  642. package/dist/templates/opencode/package.json +5 -0
  643. package/dist/templates/opencode/plugins/inject-spec-context.js +121 -0
  644. package/dist/templates/opencode/plugins/inject-subagent-context.js +569 -0
  645. package/dist/templates/opencode/plugins/inject-workflow-state.js +340 -0
  646. package/dist/templates/opencode/plugins/session-start.js +74 -0
  647. package/dist/templates/pi/agents/trellis-check.md +37 -0
  648. package/dist/templates/pi/agents/trellis-implement.md +52 -0
  649. package/dist/templates/pi/agents/trellis-research.md +25 -0
  650. package/dist/templates/pi/extensions/trellis/index.ts.txt +2033 -0
  651. package/dist/templates/pi/index.d.ts +5 -0
  652. package/dist/templates/pi/index.d.ts.map +1 -0
  653. package/dist/templates/pi/index.js +12 -0
  654. package/dist/templates/pi/index.js.map +1 -0
  655. package/dist/templates/pi/settings.json +9 -0
  656. package/dist/templates/qoder/agents/trellis-check.md +108 -0
  657. package/dist/templates/qoder/agents/trellis-implement.md +108 -0
  658. package/dist/templates/qoder/agents/trellis-research.md +137 -0
  659. package/dist/templates/qoder/index.d.ts +15 -0
  660. package/dist/templates/qoder/index.d.ts.map +1 -0
  661. package/dist/templates/qoder/index.js +15 -0
  662. package/dist/templates/qoder/index.js.map +1 -0
  663. package/dist/templates/qoder/settings.json +59 -0
  664. package/dist/templates/reasonix/agents/trellis-check.md +36 -0
  665. package/dist/templates/reasonix/agents/trellis-implement.md +51 -0
  666. package/dist/templates/reasonix/index.d.ts +13 -0
  667. package/dist/templates/reasonix/index.d.ts.map +1 -0
  668. package/dist/templates/reasonix/index.js +16 -0
  669. package/dist/templates/reasonix/index.js.map +1 -0
  670. package/dist/templates/shared-hooks/index.d.ts +83 -0
  671. package/dist/templates/shared-hooks/index.d.ts.map +1 -0
  672. package/dist/templates/shared-hooks/index.js +152 -0
  673. package/dist/templates/shared-hooks/index.js.map +1 -0
  674. package/dist/templates/shared-hooks/inject-shell-session-context.py +292 -0
  675. package/dist/templates/shared-hooks/inject-spec-context.py +844 -0
  676. package/dist/templates/shared-hooks/inject-subagent-context.py +1175 -0
  677. package/dist/templates/shared-hooks/inject-workflow-state.py +501 -0
  678. package/dist/templates/shared-hooks/session-start.py +969 -0
  679. package/dist/templates/snow/SNOW.md +86 -0
  680. package/dist/templates/snow/agents/trellis-check.md +136 -0
  681. package/dist/templates/snow/agents/trellis-implement.md +158 -0
  682. package/dist/templates/snow/agents/trellis-research.md +114 -0
  683. package/dist/templates/snow/hooks/beforeSubAgentStart.json +15 -0
  684. package/dist/templates/snow/hooks/onSessionStart.json +15 -0
  685. package/dist/templates/snow/hooks/onUserMessage.json +15 -0
  686. package/dist/templates/snow/hooks/write-trellis-context.py +644 -0
  687. package/dist/templates/snow/index.d.ts +26 -0
  688. package/dist/templates/snow/index.d.ts.map +1 -0
  689. package/dist/templates/snow/index.js +36 -0
  690. package/dist/templates/snow/index.js.map +1 -0
  691. package/dist/templates/template-utils.d.ts +26 -0
  692. package/dist/templates/template-utils.d.ts.map +1 -0
  693. package/dist/templates/template-utils.js +64 -0
  694. package/dist/templates/template-utils.js.map +1 -0
  695. package/dist/templates/trae/agents/trellis-check.md +108 -0
  696. package/dist/templates/trae/agents/trellis-implement.md +108 -0
  697. package/dist/templates/trae/agents/trellis-research.md +137 -0
  698. package/dist/templates/trae/hooks.json +39 -0
  699. package/dist/templates/trae/index.d.ts +15 -0
  700. package/dist/templates/trae/index.d.ts.map +1 -0
  701. package/dist/templates/trae/index.js +15 -0
  702. package/dist/templates/trae/index.js.map +1 -0
  703. package/dist/templates/trellis/agents/check.md +70 -0
  704. package/dist/templates/trellis/agents/implement.md +81 -0
  705. package/dist/templates/trellis/config.yaml +205 -0
  706. package/dist/templates/trellis/gitattributes.txt +9 -0
  707. package/dist/templates/trellis/gitignore.txt +32 -0
  708. package/dist/templates/trellis/index.d.ts +70 -0
  709. package/dist/templates/trellis/index.d.ts.map +1 -0
  710. package/dist/templates/trellis/index.js +127 -0
  711. package/dist/templates/trellis/index.js.map +1 -0
  712. package/dist/templates/trellis/scripts/__init__.py +5 -0
  713. package/dist/templates/trellis/scripts/add_session.py +681 -0
  714. package/dist/templates/trellis/scripts/common/__init__.py +92 -0
  715. package/dist/templates/trellis/scripts/common/active_task.py +787 -0
  716. package/dist/templates/trellis/scripts/common/cli_adapter.py +982 -0
  717. package/dist/templates/trellis/scripts/common/config.py +587 -0
  718. package/dist/templates/trellis/scripts/common/developer.py +190 -0
  719. package/dist/templates/trellis/scripts/common/git.py +74 -0
  720. package/dist/templates/trellis/scripts/common/git_context.py +138 -0
  721. package/dist/templates/trellis/scripts/common/io.py +61 -0
  722. package/dist/templates/trellis/scripts/common/log.py +45 -0
  723. package/dist/templates/trellis/scripts/common/packages_context.py +238 -0
  724. package/dist/templates/trellis/scripts/common/paths.py +508 -0
  725. package/dist/templates/trellis/scripts/common/safe_commit.py +315 -0
  726. package/dist/templates/trellis/scripts/common/session_context.py +892 -0
  727. package/dist/templates/trellis/scripts/common/spec_inject.py +439 -0
  728. package/dist/templates/trellis/scripts/common/spec_match.py +395 -0
  729. package/dist/templates/trellis/scripts/common/task_context.py +372 -0
  730. package/dist/templates/trellis/scripts/common/task_queue.py +188 -0
  731. package/dist/templates/trellis/scripts/common/task_store.py +1016 -0
  732. package/dist/templates/trellis/scripts/common/task_utils.py +309 -0
  733. package/dist/templates/trellis/scripts/common/tasks.py +112 -0
  734. package/dist/templates/trellis/scripts/common/trellis_config.py +132 -0
  735. package/dist/templates/trellis/scripts/common/types.py +110 -0
  736. package/dist/templates/trellis/scripts/common/workflow_phase.py +243 -0
  737. package/dist/templates/trellis/scripts/common/workflow_selection.py +177 -0
  738. package/dist/templates/trellis/scripts/get_context.py +16 -0
  739. package/dist/templates/trellis/scripts/get_developer.py +26 -0
  740. package/dist/templates/trellis/scripts/hooks/linear_sync.py +243 -0
  741. package/dist/templates/trellis/scripts/init_developer.py +51 -0
  742. package/dist/templates/trellis/scripts/task.py +694 -0
  743. package/dist/templates/trellis/tasks/.gitkeep +0 -0
  744. package/dist/templates/trellis/workflow.md +777 -0
  745. package/dist/templates/zcode/agents/trellis-check.md +110 -0
  746. package/dist/templates/zcode/agents/trellis-implement.md +116 -0
  747. package/dist/templates/zcode/agents/trellis-research.md +133 -0
  748. package/dist/templates/zcode/config.json +52 -0
  749. package/dist/templates/zcode/index.d.ts +25 -0
  750. package/dist/templates/zcode/index.d.ts.map +1 -0
  751. package/dist/templates/zcode/index.js +29 -0
  752. package/dist/templates/zcode/index.js.map +1 -0
  753. package/dist/types/ai-tools.d.ts +95 -0
  754. package/dist/types/ai-tools.d.ts.map +1 -0
  755. package/dist/types/ai-tools.js +509 -0
  756. package/dist/types/ai-tools.js.map +1 -0
  757. package/dist/types/migration.d.ts +125 -0
  758. package/dist/types/migration.d.ts.map +1 -0
  759. package/dist/types/migration.js +8 -0
  760. package/dist/types/migration.js.map +1 -0
  761. package/dist/utils/agent-refs.d.ts +31 -0
  762. package/dist/utils/agent-refs.d.ts.map +1 -0
  763. package/dist/utils/agent-refs.js +63 -0
  764. package/dist/utils/agent-refs.js.map +1 -0
  765. package/dist/utils/atomic-write.d.ts +12 -0
  766. package/dist/utils/atomic-write.d.ts.map +1 -0
  767. package/dist/utils/atomic-write.js +30 -0
  768. package/dist/utils/atomic-write.js.map +1 -0
  769. package/dist/utils/compare-versions.d.ts +12 -0
  770. package/dist/utils/compare-versions.d.ts.map +1 -0
  771. package/dist/utils/compare-versions.js +86 -0
  772. package/dist/utils/compare-versions.js.map +1 -0
  773. package/dist/utils/cwd-guard.d.ts +38 -0
  774. package/dist/utils/cwd-guard.d.ts.map +1 -0
  775. package/dist/utils/cwd-guard.js +62 -0
  776. package/dist/utils/cwd-guard.js.map +1 -0
  777. package/dist/utils/file-writer.d.ts +36 -0
  778. package/dist/utils/file-writer.d.ts.map +1 -0
  779. package/dist/utils/file-writer.js +204 -0
  780. package/dist/utils/file-writer.js.map +1 -0
  781. package/dist/utils/manifest-prune.d.ts +61 -0
  782. package/dist/utils/manifest-prune.d.ts.map +1 -0
  783. package/dist/utils/manifest-prune.js +136 -0
  784. package/dist/utils/manifest-prune.js.map +1 -0
  785. package/dist/utils/posix.d.ts +13 -0
  786. package/dist/utils/posix.d.ts.map +1 -0
  787. package/dist/utils/posix.js +15 -0
  788. package/dist/utils/posix.js.map +1 -0
  789. package/dist/utils/project-detector.d.ts +46 -0
  790. package/dist/utils/project-detector.d.ts.map +1 -0
  791. package/dist/utils/project-detector.js +666 -0
  792. package/dist/utils/project-detector.js.map +1 -0
  793. package/dist/utils/proxy.d.ts +25 -0
  794. package/dist/utils/proxy.d.ts.map +1 -0
  795. package/dist/utils/proxy.js +60 -0
  796. package/dist/utils/proxy.js.map +1 -0
  797. package/dist/utils/registry-config.d.ts +7 -0
  798. package/dist/utils/registry-config.d.ts.map +1 -0
  799. package/dist/utils/registry-config.js +172 -0
  800. package/dist/utils/registry-config.js.map +1 -0
  801. package/dist/utils/task-json.d.ts +13 -0
  802. package/dist/utils/task-json.d.ts.map +1 -0
  803. package/dist/utils/task-json.js +12 -0
  804. package/dist/utils/task-json.js.map +1 -0
  805. package/dist/utils/template-fetcher.d.ts +161 -0
  806. package/dist/utils/template-fetcher.d.ts.map +1 -0
  807. package/dist/utils/template-fetcher.js +994 -0
  808. package/dist/utils/template-fetcher.js.map +1 -0
  809. package/dist/utils/template-hash.d.ts +123 -0
  810. package/dist/utils/template-hash.d.ts.map +1 -0
  811. package/dist/utils/template-hash.js +335 -0
  812. package/dist/utils/template-hash.js.map +1 -0
  813. package/dist/utils/uninstall-scrubbers.d.ts +67 -0
  814. package/dist/utils/uninstall-scrubbers.d.ts.map +1 -0
  815. package/dist/utils/uninstall-scrubbers.js +361 -0
  816. package/dist/utils/uninstall-scrubbers.js.map +1 -0
  817. package/dist/utils/workflow-resolver.d.ts +86 -0
  818. package/dist/utils/workflow-resolver.d.ts.map +1 -0
  819. package/dist/utils/workflow-resolver.js +265 -0
  820. package/dist/utils/workflow-resolver.js.map +1 -0
  821. package/package.json +89 -0
@@ -0,0 +1,1016 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Task CRUD operations.
4
+
5
+ Provides:
6
+ ensure_tasks_dir - Ensure tasks directory exists
7
+ cmd_create - Create a new task
8
+ cmd_archive - Archive completed task
9
+ cmd_set_branch - Set git branch for task
10
+ cmd_set_base_branch - Set PR target branch
11
+ cmd_set_scope - Set scope for PR title
12
+ cmd_set_meta - Set/overwrite a task metadata key
13
+ cmd_add_subtask - Link child task to parent
14
+ cmd_remove_subtask - Unlink child task from parent
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import argparse
20
+ import json
21
+ import re
22
+ import sys
23
+ from datetime import datetime
24
+ from pathlib import Path
25
+
26
+ from .config import (
27
+ get_codex_dispatch_mode,
28
+ get_packages,
29
+ get_session_auto_commit,
30
+ is_monorepo,
31
+ resolve_package,
32
+ validate_package,
33
+ )
34
+ from .git import branch_exists_locally, resolve_default_branch, run_git
35
+ from .io import read_json, write_json
36
+ from .log import Colors, colored
37
+ from .paths import (
38
+ DIR_ARCHIVE,
39
+ DIR_TASKS,
40
+ DIR_WORKFLOW,
41
+ FILE_TASK_JSON,
42
+ generate_task_date_prefix,
43
+ get_developer,
44
+ get_repo_root,
45
+ get_tasks_dir,
46
+ )
47
+ from .safe_commit import (
48
+ print_gitignore_warning,
49
+ safe_archive_paths_to_add,
50
+ safe_git_add,
51
+ )
52
+ from .task_utils import (
53
+ archive_task_complete,
54
+ find_task_by_name,
55
+ is_within_tasks_dir,
56
+ resolve_task_dir,
57
+ run_task_hooks,
58
+ )
59
+ from .workflow_selection import DIR_WORKFLOWS, WORKFLOW_ID_RE
60
+
61
+
62
+ # =============================================================================
63
+ # Helper Functions
64
+ # =============================================================================
65
+
66
+ def _slugify(title: str) -> str:
67
+ """Convert title to slug (only works with ASCII)."""
68
+ result = title.lower()
69
+ result = re.sub(r"[^a-z0-9]", "-", result)
70
+ result = re.sub(r"-+", "-", result)
71
+ result = result.strip("-")
72
+ return result
73
+
74
+
75
+ def ensure_tasks_dir(repo_root: Path) -> Path:
76
+ """Ensure tasks directory exists."""
77
+ tasks_dir = get_tasks_dir(repo_root)
78
+ archive_dir = tasks_dir / "archive"
79
+
80
+ if not tasks_dir.exists():
81
+ tasks_dir.mkdir(parents=True)
82
+ print(colored(f"Created tasks directory: {tasks_dir}", Colors.GREEN), file=sys.stderr)
83
+
84
+ if not archive_dir.exists():
85
+ archive_dir.mkdir(parents=True)
86
+
87
+ return tasks_dir
88
+
89
+
90
+ def _find_archived_task_by_dir_name(tasks_dir: Path, dir_name: str) -> Path | None:
91
+ """Find an archived task directory with the exact active-task dir name."""
92
+ archive_dir = tasks_dir / DIR_ARCHIVE
93
+ if not archive_dir.is_dir():
94
+ return None
95
+
96
+ for month_dir in sorted(archive_dir.iterdir()):
97
+ if not month_dir.is_dir():
98
+ continue
99
+ candidate = month_dir / dir_name
100
+ if candidate.is_dir():
101
+ return candidate
102
+
103
+ return None
104
+
105
+
106
+ def _repo_relative_path(path: Path, repo_root: Path) -> str:
107
+ """Format a path relative to the repo root when possible."""
108
+ try:
109
+ return path.relative_to(repo_root).as_posix()
110
+ except ValueError:
111
+ return str(path)
112
+
113
+
114
+ # =============================================================================
115
+ # Sub-agent platform detection + JSONL seeding
116
+ # =============================================================================
117
+
118
+ # Config directories of platforms that consume implement.jsonl / check.jsonl.
119
+ # Keep in sync with src/types/ai-tools.ts AI_TOOLS entries — these are the
120
+ # platforms listed in workflow.md's "agent-capable" Skill Routing block.
121
+ # Codex is checked separately because explicit inline mode does not consume
122
+ # JSONL. Kilo / Antigravity / Devin are NOT in this list either: they load
123
+ # specs through skills instead of JSONL.
124
+ _SUBAGENT_CONFIG_DIRS: tuple[str, ...] = (
125
+ ".claude",
126
+ ".cursor",
127
+ ".kiro",
128
+ ".gemini",
129
+ ".opencode",
130
+ ".qoder",
131
+ ".codebuddy",
132
+ ".factory", # Factory Droid
133
+ ".github/copilot",
134
+ ".pi", # Pi Agent
135
+ ".trae", # Trae IDE
136
+ ".omp", # Oh My Pi
137
+ ".zcode", # ZCode
138
+ ".grok", # Grok Build
139
+ ".kimi-code", # Kimi Code
140
+ ".dsh", # DeepSeek Harness
141
+ )
142
+ _CODEX_CONFIG_DIR = ".codex"
143
+
144
+ _SEED_EXAMPLE = (
145
+ "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. "
146
+ "Put spec/research files only — no code paths. "
147
+ "Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. "
148
+ "Delete this line once real entries are added."
149
+ )
150
+
151
+
152
+ def _has_subagent_platform(repo_root: Path) -> bool:
153
+ """Return True if any sub-agent-capable platform is configured.
154
+
155
+ Detected by probing well-known config directories at the repo root. Codex
156
+ counts by default through ``codex.dispatch_mode: auto`` (including the
157
+ legacy ``sub-agent`` alias); explicit inline mode loads context through
158
+ skills, not JSONL.
159
+ """
160
+ for config_dir in _SUBAGENT_CONFIG_DIRS:
161
+ if (repo_root / config_dir).is_dir():
162
+ return True
163
+ if (repo_root / _CODEX_CONFIG_DIR).is_dir():
164
+ return get_codex_dispatch_mode(repo_root) == "auto"
165
+ return False
166
+
167
+
168
+ def _write_seed_jsonl(path: Path) -> None:
169
+ """Write a one-line seed JSONL file with a self-describing ``_example``.
170
+
171
+ The seed row has no ``file`` field, so downstream consumers (hooks +
172
+ preludes) that iterate entries via ``item.get("file")`` naturally skip
173
+ it. The row exists purely as an in-file prompt for the AI curator.
174
+ """
175
+ seed = {"_example": _SEED_EXAMPLE}
176
+ path.write_text(json.dumps(seed, ensure_ascii=False) + "\n", encoding="utf-8")
177
+
178
+
179
+ def _parse_meta_pairs(pairs: list[str] | None) -> dict[str, str] | None:
180
+ """Parse repeatable ``--meta key=value`` pairs into a dict.
181
+
182
+ Returns ``None`` (after printing an error naming the bad value) on the
183
+ first malformed pair: missing ``=`` or an empty key. Values are stored
184
+ as-is (strings, no nesting, no type coercion).
185
+ """
186
+ meta: dict[str, str] = {}
187
+ for pair in pairs or []:
188
+ key, sep, value = pair.partition("=")
189
+ if not sep or not key:
190
+ print(
191
+ colored(f"Error: malformed --meta value '{pair}' (expected key=value)", Colors.RED),
192
+ file=sys.stderr,
193
+ )
194
+ return None
195
+ meta[key] = value
196
+ return meta
197
+
198
+
199
+ def _default_prd_content(title: str, description: str | None = None) -> str:
200
+ """Return the default PRD skeleton created with every task."""
201
+ goal = (description or "").strip() or "TBD."
202
+ heading = title.strip() or "Untitled task"
203
+ return f"""# {heading}
204
+
205
+ ## Goal
206
+
207
+ {goal}
208
+
209
+ ## Requirements
210
+
211
+ - TBD
212
+
213
+ ## Acceptance Criteria
214
+
215
+ - [ ] TBD
216
+
217
+ ## Notes
218
+
219
+ - Keep `prd.md` focused on requirements, constraints, and acceptance criteria.
220
+ - Add `design.md` for technical design and `implement.md` for the ordered slice checklist before `task.py start`. Both are required.
221
+ - Record the task kind with `task.py set-meta <task-dir> kind <bug|feature|chore>`; it selects the red-evidence gate.
222
+ """
223
+
224
+
225
+ # =============================================================================
226
+ # Command: create
227
+ # =============================================================================
228
+
229
+ def cmd_create(args: argparse.Namespace) -> int:
230
+ """Create a new task."""
231
+ repo_root = get_repo_root()
232
+
233
+ if not args.title:
234
+ print(colored("Error: title is required", Colors.RED), file=sys.stderr)
235
+ return 1
236
+
237
+ # Validate --meta (CLI source: fail-fast, before any directory is created)
238
+ meta = _parse_meta_pairs(getattr(args, "meta", None))
239
+ if meta is None:
240
+ return 1
241
+
242
+ # Validate --package (CLI source: fail-fast)
243
+ package: str | None = getattr(args, "package", None)
244
+ if not is_monorepo(repo_root):
245
+ # Single-repo: ignore --package, no package prefix
246
+ if package:
247
+ print(colored(f"Warning: --package ignored in single-repo project", Colors.YELLOW), file=sys.stderr)
248
+ package = None
249
+ elif package:
250
+ if not validate_package(package, repo_root):
251
+ packages = get_packages(repo_root)
252
+ available = ", ".join(sorted(packages.keys())) if packages else "(none)"
253
+ print(colored(f"Error: unknown package '{package}'. Available: {available}", Colors.RED), file=sys.stderr)
254
+ return 1
255
+ else:
256
+ # Inferred: default_package → None (no task.json yet for create)
257
+ package = resolve_package(repo_root=repo_root)
258
+
259
+ # Validate --workflow (CLI source: fail-fast on invalid id; a missing
260
+ # library file only warns — it may be saved later via `trellis workflow --save`)
261
+ workflow_id: str | None = getattr(args, "workflow", None)
262
+ if workflow_id:
263
+ if not WORKFLOW_ID_RE.match(workflow_id):
264
+ print(
265
+ colored(
266
+ f"Error: invalid workflow id '{workflow_id}' (allowed: letters, digits, '-', '_')",
267
+ Colors.RED,
268
+ ),
269
+ file=sys.stderr,
270
+ )
271
+ return 1
272
+ workflow_md = repo_root / DIR_WORKFLOW / DIR_WORKFLOWS / f"{workflow_id}.md"
273
+ if not workflow_md.is_file():
274
+ print(
275
+ colored(
276
+ f"Warning: {DIR_WORKFLOW}/{DIR_WORKFLOWS}/{workflow_id}.md does not exist yet; "
277
+ "default workflow resolution is used until it is saved "
278
+ "(trellis workflow --save).",
279
+ Colors.YELLOW,
280
+ ),
281
+ file=sys.stderr,
282
+ )
283
+
284
+ # Default assignee to current developer
285
+ assignee = args.assignee
286
+ if not assignee:
287
+ assignee = get_developer(repo_root)
288
+ if not assignee:
289
+ print(colored("Error: No developer set. Run init_developer.py first or use --assignee", Colors.RED), file=sys.stderr)
290
+ return 1
291
+
292
+ ensure_tasks_dir(repo_root)
293
+
294
+ # Get current developer as creator
295
+ creator = get_developer(repo_root) or assignee
296
+
297
+ # Generate slug if not provided
298
+ slug = args.slug or _slugify(args.title)
299
+ if not slug:
300
+ print(colored("Error: could not generate slug from title", Colors.RED), file=sys.stderr)
301
+ return 1
302
+
303
+ # Create task directory with MM-DD-slug format
304
+ tasks_dir = get_tasks_dir(repo_root)
305
+ date_prefix = generate_task_date_prefix()
306
+
307
+ # Guard against date-prefixed --slug (e.g. a full task dir name pasted in),
308
+ # which would otherwise produce MM-DD-MM-DD-slug (issue #377). Only an
309
+ # explicit --slug is guarded; title-derived slugs are left untouched.
310
+ if args.slug:
311
+ m = re.match(r"^(\d{2})-(\d{2})-(.+)$", slug)
312
+ if m and 1 <= int(m.group(1)) <= 12 and 1 <= int(m.group(2)) <= 31:
313
+ slug_prefix = f"{m.group(1)}-{m.group(2)}"
314
+ if slug_prefix == date_prefix:
315
+ slug = m.group(3)
316
+ print(
317
+ colored(
318
+ f'warning: --slug should not include the MM-DD prefix; normalized to "{slug}"',
319
+ Colors.YELLOW,
320
+ ),
321
+ file=sys.stderr,
322
+ )
323
+ else:
324
+ print(
325
+ colored(
326
+ f"Error: --slug starts with a date prefix ({slug_prefix}-), but task.py create always uses today's date ({date_prefix}).",
327
+ Colors.RED,
328
+ ),
329
+ file=sys.stderr,
330
+ )
331
+ print(f"Pass only the slug body, e.g. --slug {m.group(3)}", file=sys.stderr)
332
+ return 1
333
+
334
+ dir_name = f"{date_prefix}-{slug}"
335
+ task_dir = tasks_dir / dir_name
336
+ task_json_path = task_dir / FILE_TASK_JSON
337
+
338
+ archived_task_dir = _find_archived_task_by_dir_name(tasks_dir, dir_name)
339
+ if archived_task_dir:
340
+ print(colored(f"Error: Task already archived: {dir_name}", Colors.RED), file=sys.stderr)
341
+ print(f"Archived at: {_repo_relative_path(archived_task_dir, repo_root)}", file=sys.stderr)
342
+ print("Use a new slug if you intend to create a new task.", file=sys.stderr)
343
+ return 1
344
+
345
+ if task_dir.exists():
346
+ print(colored(f"Warning: Task directory already exists: {dir_name}", Colors.YELLOW), file=sys.stderr)
347
+ else:
348
+ task_dir.mkdir(parents=True)
349
+
350
+ today = datetime.now().strftime("%Y-%m-%d")
351
+
352
+ # Record the PR target branch. Prefer the repo's actual default branch
353
+ # (origin/HEAD) so creating a task from a feature branch doesn't
354
+ # mis-stamp that feature branch as the PR target (#399 item 1). Falls
355
+ # back to the checked-out branch when the default can't be resolved
356
+ # (no remote configured, offline, etc.) — the pre-existing behavior.
357
+ # --base-branch lets the caller override both when neither is correct.
358
+ _, branch_out, _ = run_git(["branch", "--show-current"], cwd=repo_root)
359
+ current_branch = branch_out.strip() or "main"
360
+ explicit_base_branch: str | None = getattr(args, "base_branch", None)
361
+ if explicit_base_branch:
362
+ base_branch = explicit_base_branch
363
+ else:
364
+ resolved_base_branch = resolve_default_branch(repo_root)
365
+ if resolved_base_branch:
366
+ base_branch = resolved_base_branch
367
+ else:
368
+ base_branch = current_branch
369
+ print(
370
+ colored(
371
+ f"warning: could not resolve the repository's default branch "
372
+ f"(no remote configured, offline, etc.); stamping base_branch as "
373
+ f"the checked-out branch '{base_branch}'. Pass --base-branch to override.",
374
+ Colors.YELLOW,
375
+ ),
376
+ file=sys.stderr,
377
+ )
378
+
379
+ description = (args.description or "").strip()
380
+ if not description.strip():
381
+ print(
382
+ colored(
383
+ "warning: task description is empty; pass --description to improve search and later audits.",
384
+ Colors.YELLOW,
385
+ ),
386
+ file=sys.stderr,
387
+ )
388
+
389
+ task_data = {
390
+ "id": slug,
391
+ "name": slug,
392
+ "title": args.title,
393
+ "description": description,
394
+ "status": "planning",
395
+ "dev_type": None,
396
+ "scope": None,
397
+ "package": package,
398
+ "priority": args.priority,
399
+ "creator": creator,
400
+ "assignee": assignee,
401
+ "createdAt": today,
402
+ "completedAt": None,
403
+ "branch": None,
404
+ "base_branch": base_branch,
405
+ "worktree_path": None,
406
+ "commit": None,
407
+ "pr_url": None,
408
+ "subtasks": [],
409
+ "children": [],
410
+ "parent": None,
411
+ "relatedFiles": [],
412
+ "notes": "",
413
+ "meta": meta,
414
+ }
415
+ # Optional per-task workflow selection: key present only when opted in,
416
+ # so tasks without a selection keep today's task.json shape byte-for-byte.
417
+ if workflow_id:
418
+ task_data["workflow"] = workflow_id
419
+
420
+ write_json(task_json_path, task_data)
421
+
422
+ prd_path = task_dir / "prd.md"
423
+ if not prd_path.exists():
424
+ prd_path.write_text(
425
+ _default_prd_content(args.title, description),
426
+ encoding="utf-8",
427
+ )
428
+
429
+ # Seed implement.jsonl / check.jsonl for sub-agent-capable platforms.
430
+ # Agent curates real entries during planning when the task needs them.
431
+ # Agent-less platforms (Kilo / Antigravity / Devin) skip this — they
432
+ # load specs via the trellis-before-dev skill instead of JSONL.
433
+ seeded_jsonl = False
434
+ if _has_subagent_platform(repo_root):
435
+ for jsonl_name in ("implement.jsonl", "check.jsonl"):
436
+ jsonl_path = task_dir / jsonl_name
437
+ if not jsonl_path.exists():
438
+ _write_seed_jsonl(jsonl_path)
439
+ seeded_jsonl = True
440
+
441
+ # Handle --parent: establish bidirectional link
442
+ if args.parent:
443
+ parent_dir = resolve_task_dir(args.parent, repo_root)
444
+ if not parent_dir or not (parent_dir / FILE_TASK_JSON).is_file():
445
+ print(colored(f"Warning: Parent task.json not found: {args.parent}", Colors.YELLOW), file=sys.stderr)
446
+ else:
447
+ parent_json_path = parent_dir / FILE_TASK_JSON
448
+ parent_data = read_json(parent_json_path)
449
+ if parent_data:
450
+ # Add child to parent's children list
451
+ parent_children = parent_data.get("children", [])
452
+ if dir_name not in parent_children:
453
+ parent_children.append(dir_name)
454
+ parent_data["children"] = parent_children
455
+ write_json(parent_json_path, parent_data)
456
+
457
+ # Set parent in child's task.json
458
+ task_data["parent"] = parent_dir.name
459
+ write_json(task_json_path, task_data)
460
+
461
+ print(colored(f"Linked as child of: {parent_dir.name}", Colors.GREEN), file=sys.stderr)
462
+
463
+ # Auto-activate the new task so the per-turn breadcrumb fires planning
464
+ # state. Best-effort: gracefully degrade if no session identity (CLI run
465
+ # outside an AI session) — the task is still created, the user can run
466
+ # task.py start later. Pointer is session-scoped so this never affects
467
+ # other AI sessions.
468
+ if getattr(args, "no_start", False):
469
+ print(
470
+ colored(
471
+ "Skipped session activation (--no-start); run task.py start when ready.",
472
+ Colors.YELLOW,
473
+ ),
474
+ file=sys.stderr,
475
+ )
476
+ else:
477
+ try:
478
+ from .active_task import resolve_context_key, set_active_task
479
+ except Exception as exc:
480
+ print(
481
+ colored(f"Warning: session activation unavailable (import failed: {exc})", Colors.YELLOW),
482
+ file=sys.stderr,
483
+ )
484
+ else:
485
+ try:
486
+ context_key = resolve_context_key()
487
+ except Exception as exc:
488
+ print(
489
+ colored(f"Warning: session activation failed (context resolution: {exc})", Colors.YELLOW),
490
+ file=sys.stderr,
491
+ )
492
+ else:
493
+ # No session identity is the normal CLI-outside-an-AI-session
494
+ # case (see comment above) — stay silent, not a failure.
495
+ if context_key:
496
+ try:
497
+ rel_dir = task_dir.relative_to(repo_root).as_posix()
498
+ except ValueError:
499
+ rel_dir = str(task_dir)
500
+ try:
501
+ active = set_active_task(rel_dir, repo_root)
502
+ except Exception as exc:
503
+ print(
504
+ colored(f"Warning: session activation failed (pointer persistence: {exc})", Colors.YELLOW),
505
+ file=sys.stderr,
506
+ )
507
+ else:
508
+ if active:
509
+ print(
510
+ colored(f"Activated task for this session: {active.task_path}", Colors.GREEN),
511
+ file=sys.stderr,
512
+ )
513
+ print(f"Source: {active.source}", file=sys.stderr)
514
+ else:
515
+ print(
516
+ colored("Warning: session activation failed (no pointer returned)", Colors.YELLOW),
517
+ file=sys.stderr,
518
+ )
519
+
520
+ print(colored(f"Created task: {dir_name}", Colors.GREEN), file=sys.stderr)
521
+ print("", file=sys.stderr)
522
+ print(colored("Next steps:", Colors.BLUE), file=sys.stderr)
523
+ print(" - Fill prd.md with requirements and acceptance criteria", file=sys.stderr)
524
+ print(" - Add design.md and implement.md before task.py start (both required)", file=sys.stderr)
525
+ print(" - Set the task kind: task.py set-meta <task-dir> kind <bug|feature|chore>", file=sys.stderr)
526
+ if seeded_jsonl:
527
+ print(
528
+ " - Curate implement.jsonl / check.jsonl as spec/research manifests when sub-agents need context",
529
+ file=sys.stderr,
530
+ )
531
+ print(" - Use /trellis:continue or phase context to decide the next step", file=sys.stderr)
532
+ print("", file=sys.stderr)
533
+
534
+ # Output relative path for script chaining
535
+ print(f"{DIR_WORKFLOW}/{DIR_TASKS}/{dir_name}")
536
+
537
+ run_task_hooks("after_create", task_json_path, repo_root)
538
+ return 0
539
+
540
+
541
+ # =============================================================================
542
+ # Command: archive
543
+ # =============================================================================
544
+
545
+ def cmd_archive(args: argparse.Namespace) -> int:
546
+ """Archive completed task."""
547
+ repo_root = get_repo_root()
548
+ task_name = args.name
549
+
550
+ if not task_name:
551
+ print(colored("Error: Task name is required", Colors.RED), file=sys.stderr)
552
+ return 1
553
+
554
+ tasks_dir = get_tasks_dir(repo_root)
555
+
556
+ # Resolve task directory (supports task name, relative path, or absolute path)
557
+ task_dir = resolve_task_dir(task_name, repo_root)
558
+
559
+ if not task_dir or not task_dir.is_dir():
560
+ print(colored(f"Error: Task not found: {task_name}", Colors.RED), file=sys.stderr)
561
+ print("Active tasks:", file=sys.stderr)
562
+ # Import lazily to avoid circular dependency
563
+ from .tasks import iter_active_tasks
564
+ for t in iter_active_tasks(tasks_dir):
565
+ print(f" - {t.dir_name}/", file=sys.stderr)
566
+ return 1
567
+
568
+ # Refuse to archive anything that isn't a real task directly under
569
+ # .trellis/tasks/. A mistyped name (e.g. "src") resolves to repo_root/src,
570
+ # which is a dir but not a task — without this guard archive would move the
571
+ # user's source directory out of the repo.
572
+ if not is_within_tasks_dir(task_dir, repo_root):
573
+ print(colored(
574
+ f"Error: refusing to archive '{task_name}': "
575
+ f"{task_dir} is not a task under {tasks_dir}",
576
+ Colors.RED), file=sys.stderr)
577
+ return 1
578
+
579
+ dir_name = task_dir.name
580
+ task_json_path = task_dir / FILE_TASK_JSON
581
+
582
+ # Update status before archiving
583
+ today = datetime.now().strftime("%Y-%m-%d")
584
+ # Names of child task dirs whose task.json gets modified below; passed
585
+ # into safe_archive_paths_to_add so they're staged in this commit.
586
+ modified_children: list[str] = []
587
+ if task_json_path.is_file():
588
+ data = read_json(task_json_path)
589
+ if data:
590
+ # Warn (don't block) when the recorded branch is stale — it was
591
+ # likely already merged and deleted (#399 item 2).
592
+ stored_branch = data.get("branch")
593
+ if stored_branch and not branch_exists_locally(stored_branch, repo_root):
594
+ print(
595
+ colored(
596
+ f"Warning: recorded branch '{stored_branch}' no longer exists locally "
597
+ "(likely merged and deleted).",
598
+ Colors.YELLOW,
599
+ ),
600
+ file=sys.stderr,
601
+ )
602
+
603
+ data["status"] = "completed"
604
+ data["completedAt"] = today
605
+ write_json(task_json_path, data)
606
+
607
+ # Handle subtask relationships on archive.
608
+ # Keep this task in its parent's children list so progress
609
+ # counters (children_progress) stay consistent — children
610
+ # missing from the active set are treated as completed.
611
+ task_children = data.get("children", [])
612
+
613
+ # If this is a parent, clear parent field in all children
614
+ if task_children:
615
+ for child_name in task_children:
616
+ child_dir_path = find_task_by_name(child_name, tasks_dir)
617
+ if child_dir_path:
618
+ child_json = child_dir_path / FILE_TASK_JSON
619
+ if child_json.is_file():
620
+ child_data = read_json(child_json)
621
+ if child_data:
622
+ child_data["parent"] = None
623
+ write_json(child_json, child_data)
624
+ modified_children.append(child_dir_path.name)
625
+
626
+ # Clear any session that still points at this task before the path moves.
627
+ from .active_task import clear_task_from_sessions
628
+ clear_task_from_sessions(str(task_dir), repo_root)
629
+
630
+ # Archive
631
+ result = archive_task_complete(task_dir, repo_root)
632
+ if "archived_to" in result:
633
+ archive_dest = Path(result["archived_to"])
634
+ year_month = archive_dest.parent.name
635
+ print(colored(f"Archived: {dir_name} -> archive/{year_month}/", Colors.GREEN), file=sys.stderr)
636
+
637
+ # Auto-commit unless --no-commit
638
+ if not getattr(args, "no_commit", False):
639
+ if not _auto_commit_archive(dir_name, repo_root, modified_children):
640
+ print(
641
+ colored(
642
+ "Archive moved on disk, but git auto-commit did not complete. "
643
+ "Resolve `git status` before continuing.",
644
+ Colors.RED,
645
+ ),
646
+ file=sys.stderr,
647
+ )
648
+ return 1
649
+
650
+ # Return the archive path
651
+ print(f"{DIR_WORKFLOW}/{DIR_TASKS}/{DIR_ARCHIVE}/{year_month}/{dir_name}")
652
+
653
+ # Run hooks with the archived path
654
+ archived_json = archive_dest / FILE_TASK_JSON
655
+ run_task_hooks("after_archive", archived_json, repo_root)
656
+ return 0
657
+
658
+ return 1
659
+
660
+
661
+ def _auto_commit_archive(
662
+ task_name: str,
663
+ repo_root: Path,
664
+ modified_children: list[str] | None = None,
665
+ ) -> bool:
666
+ """Stage Trellis-owned task paths and commit after archive.
667
+
668
+ Scoped narrowly to the archived task's source + destination paths
669
+ plus any child task dirs whose ``task.json`` was edited (parent →
670
+ children relationship update). Dirty changes in OTHER active task
671
+ dirs are NOT bundled into the archive commit.
672
+
673
+ If ``.gitignore`` blocks the paths, we warn + skip — we do NOT
674
+ retry with ``git add -f``. The warning explicitly forbids
675
+ ``git add -f .trellis/`` (which would fan out to caches/backups)
676
+ and points users at ``session_auto_commit: false``.
677
+
678
+ Honors ``session_auto_commit`` in ``.trellis/config.yaml``: when
679
+ set to ``false``, this function returns immediately without
680
+ touching git (the archive directory move on disk is unaffected).
681
+ """
682
+ if not get_session_auto_commit(repo_root):
683
+ print(
684
+ "[OK] session_auto_commit: false — skipping git stage/commit.",
685
+ file=sys.stderr,
686
+ )
687
+ return True
688
+
689
+ source_rel = f"{DIR_WORKFLOW}/{DIR_TASKS}/{task_name}"
690
+ rc, tracked_out, _ = run_git(
691
+ ["ls-files", "--", source_rel],
692
+ cwd=repo_root,
693
+ )
694
+ source_was_tracked = rc == 0 and bool(tracked_out.strip())
695
+
696
+ paths = safe_archive_paths_to_add(
697
+ repo_root, task_name=task_name, modified_children=modified_children
698
+ )
699
+ if not paths:
700
+ print("[OK] No task changes to commit.", file=sys.stderr)
701
+ return True
702
+
703
+ success, _, err = safe_git_add(paths, repo_root)
704
+ if not success:
705
+ if err and "ignored by" in err.lower():
706
+ print_gitignore_warning(paths)
707
+ else:
708
+ print(
709
+ f"[WARN] git add failed: {err.strip() if err else 'unknown error'}",
710
+ file=sys.stderr,
711
+ )
712
+ return not source_was_tracked
713
+
714
+ # Belt-and-suspenders for the phantom-delete bug: `safe_git_add` uses
715
+ # `git add` (no -A) which only stages additions/modifications. The
716
+ # source task directory was moved away by `shutil.move`, so its files
717
+ # need an explicit `git rm --cached` to stage the deletions in this
718
+ # same commit — otherwise they sit as uncommitted "phantom deletes"
719
+ # against HEAD until something later picks them up.
720
+ #
721
+ # `--ignore-unmatch` makes this a no-op when the task was never tracked
722
+ # (e.g. archiving a task that lived only in working tree).
723
+ run_git(
724
+ ["rm", "-r", "--cached", "--ignore-unmatch", "--", source_rel],
725
+ cwd=repo_root,
726
+ )
727
+
728
+ rc, _, _ = run_git(
729
+ ["diff", "--cached", "--quiet", "--", *paths, source_rel],
730
+ cwd=repo_root,
731
+ )
732
+ if rc == 0:
733
+ print("[OK] No task changes to commit.", file=sys.stderr)
734
+ return True
735
+
736
+ commit_msg = f"chore(task): archive {task_name}"
737
+ rc, _, err = run_git(["commit", "-m", commit_msg], cwd=repo_root)
738
+ if rc == 0:
739
+ print(f"[OK] Auto-committed: {commit_msg}", file=sys.stderr)
740
+ return True
741
+ else:
742
+ print(f"[WARN] Auto-commit failed: {err.strip()}", file=sys.stderr)
743
+ return not source_was_tracked
744
+
745
+
746
+ # =============================================================================
747
+ # Command: add-subtask
748
+ # =============================================================================
749
+
750
+ def cmd_add_subtask(args: argparse.Namespace) -> int:
751
+ """Link a child task to a parent task."""
752
+ repo_root = get_repo_root()
753
+
754
+ parent_dir = resolve_task_dir(args.parent_dir, repo_root)
755
+ child_dir = resolve_task_dir(args.child_dir, repo_root)
756
+
757
+ if not parent_dir:
758
+ print(colored(f"Error: Parent task.json not found: {args.parent_dir}", Colors.RED), file=sys.stderr)
759
+ return 1
760
+
761
+ if not child_dir:
762
+ print(colored(f"Error: Child task.json not found: {args.child_dir}", Colors.RED), file=sys.stderr)
763
+ return 1
764
+
765
+ parent_json_path = parent_dir / FILE_TASK_JSON
766
+ child_json_path = child_dir / FILE_TASK_JSON
767
+
768
+ if not parent_json_path.is_file():
769
+ print(colored(f"Error: Parent task.json not found: {args.parent_dir}", Colors.RED), file=sys.stderr)
770
+ return 1
771
+
772
+ if not child_json_path.is_file():
773
+ print(colored(f"Error: Child task.json not found: {args.child_dir}", Colors.RED), file=sys.stderr)
774
+ return 1
775
+
776
+ parent_data = read_json(parent_json_path)
777
+ child_data = read_json(child_json_path)
778
+
779
+ if not parent_data or not child_data:
780
+ print(colored("Error: Failed to read task.json", Colors.RED), file=sys.stderr)
781
+ return 1
782
+
783
+ # Check if child already has a parent
784
+ existing_parent = child_data.get("parent")
785
+ if existing_parent:
786
+ print(colored(f"Error: Child task already has a parent: {existing_parent}", Colors.RED), file=sys.stderr)
787
+ return 1
788
+
789
+ # Add child to parent's children list
790
+ parent_children = parent_data.get("children", [])
791
+ child_dir_name = child_dir.name
792
+ if child_dir_name not in parent_children:
793
+ parent_children.append(child_dir_name)
794
+ parent_data["children"] = parent_children
795
+
796
+ # Set parent in child's task.json
797
+ child_data["parent"] = parent_dir.name
798
+
799
+ # Write both
800
+ write_json(parent_json_path, parent_data)
801
+ write_json(child_json_path, child_data)
802
+
803
+ print(colored(f"Linked: {child_dir.name} -> {parent_dir.name}", Colors.GREEN), file=sys.stderr)
804
+ return 0
805
+
806
+
807
+ # =============================================================================
808
+ # Command: remove-subtask
809
+ # =============================================================================
810
+
811
+ def cmd_remove_subtask(args: argparse.Namespace) -> int:
812
+ """Unlink a child task from a parent task."""
813
+ repo_root = get_repo_root()
814
+
815
+ parent_dir = resolve_task_dir(args.parent_dir, repo_root)
816
+ child_dir = resolve_task_dir(args.child_dir, repo_root)
817
+
818
+ if not parent_dir:
819
+ print(colored(f"Error: Parent task.json not found: {args.parent_dir}", Colors.RED), file=sys.stderr)
820
+ return 1
821
+
822
+ if not child_dir:
823
+ print(colored(f"Error: Child task.json not found: {args.child_dir}", Colors.RED), file=sys.stderr)
824
+ return 1
825
+
826
+ parent_json_path = parent_dir / FILE_TASK_JSON
827
+ child_json_path = child_dir / FILE_TASK_JSON
828
+
829
+ if not parent_json_path.is_file():
830
+ print(colored(f"Error: Parent task.json not found: {args.parent_dir}", Colors.RED), file=sys.stderr)
831
+ return 1
832
+
833
+ if not child_json_path.is_file():
834
+ print(colored(f"Error: Child task.json not found: {args.child_dir}", Colors.RED), file=sys.stderr)
835
+ return 1
836
+
837
+ parent_data = read_json(parent_json_path)
838
+ child_data = read_json(child_json_path)
839
+
840
+ if not parent_data or not child_data:
841
+ print(colored("Error: Failed to read task.json", Colors.RED), file=sys.stderr)
842
+ return 1
843
+
844
+ # Remove child from parent's children list
845
+ parent_children = parent_data.get("children", [])
846
+ child_dir_name = child_dir.name
847
+ if child_dir_name in parent_children:
848
+ parent_children.remove(child_dir_name)
849
+ parent_data["children"] = parent_children
850
+
851
+ # Clear parent in child's task.json
852
+ child_data["parent"] = None
853
+
854
+ # Write both
855
+ write_json(parent_json_path, parent_data)
856
+ write_json(child_json_path, child_data)
857
+
858
+ print(colored(f"Unlinked: {child_dir.name} from {parent_dir.name}", Colors.GREEN), file=sys.stderr)
859
+ return 0
860
+
861
+
862
+ # =============================================================================
863
+ # Command: set-branch
864
+ # =============================================================================
865
+
866
+ def cmd_set_branch(args: argparse.Namespace) -> int:
867
+ """Set git branch for task."""
868
+ repo_root = get_repo_root()
869
+ target_dir = resolve_task_dir(args.dir, repo_root)
870
+ branch = args.branch
871
+
872
+ if not branch:
873
+ print(colored("Error: Missing arguments", Colors.RED))
874
+ print("Usage: python3 task.py set-branch <task-dir> <branch-name>")
875
+ return 1
876
+
877
+ if not target_dir:
878
+ # target_dir is None here, so it must not appear in the message. This
879
+ # is also the branch a ref pointing outside the repo lands in.
880
+ print(colored(f"Error: Task not found: {args.dir}", Colors.RED))
881
+ return 1
882
+
883
+ task_json = target_dir / FILE_TASK_JSON
884
+ if not task_json.is_file():
885
+ print(colored(f"Error: task.json not found at {target_dir}", Colors.RED))
886
+ return 1
887
+
888
+ data = read_json(task_json)
889
+ if not data:
890
+ return 1
891
+
892
+ data["branch"] = branch
893
+ write_json(task_json, data)
894
+
895
+ print(colored(f"✓ Branch set to: {branch}", Colors.GREEN))
896
+ return 0
897
+
898
+
899
+ # =============================================================================
900
+ # Command: set-base-branch
901
+ # =============================================================================
902
+
903
+ def cmd_set_base_branch(args: argparse.Namespace) -> int:
904
+ """Set the base branch (PR target) for task."""
905
+ repo_root = get_repo_root()
906
+ target_dir = resolve_task_dir(args.dir, repo_root)
907
+ base_branch = args.base_branch
908
+
909
+ if not base_branch:
910
+ print(colored("Error: Missing arguments", Colors.RED))
911
+ print("Usage: python3 task.py set-base-branch <task-dir> <base-branch>")
912
+ print("Example: python3 task.py set-base-branch <dir> develop")
913
+ print()
914
+ print("This sets the target branch for PR (the branch your feature will merge into).")
915
+ return 1
916
+
917
+ if not target_dir:
918
+ # target_dir is None here, so it must not appear in the message. This
919
+ # is also the branch a ref pointing outside the repo lands in.
920
+ print(colored(f"Error: Task not found: {args.dir}", Colors.RED))
921
+ return 1
922
+
923
+ task_json = target_dir / FILE_TASK_JSON
924
+ if not task_json.is_file():
925
+ print(colored(f"Error: task.json not found at {target_dir}", Colors.RED))
926
+ return 1
927
+
928
+ data = read_json(task_json)
929
+ if not data:
930
+ return 1
931
+
932
+ data["base_branch"] = base_branch
933
+ write_json(task_json, data)
934
+
935
+ print(colored(f"✓ Base branch set to: {base_branch}", Colors.GREEN))
936
+ print(f" PR will target: {base_branch}")
937
+ return 0
938
+
939
+
940
+ # =============================================================================
941
+ # Command: set-scope
942
+ # =============================================================================
943
+
944
+ def cmd_set_scope(args: argparse.Namespace) -> int:
945
+ """Set scope for PR title."""
946
+ repo_root = get_repo_root()
947
+ target_dir = resolve_task_dir(args.dir, repo_root)
948
+ scope = args.scope
949
+
950
+ if not scope:
951
+ print(colored("Error: Missing arguments", Colors.RED))
952
+ print("Usage: python3 task.py set-scope <task-dir> <scope>")
953
+ return 1
954
+
955
+ if not target_dir:
956
+ # target_dir is None here, so it must not appear in the message. This
957
+ # is also the branch a ref pointing outside the repo lands in.
958
+ print(colored(f"Error: Task not found: {args.dir}", Colors.RED))
959
+ return 1
960
+
961
+ task_json = target_dir / FILE_TASK_JSON
962
+ if not task_json.is_file():
963
+ print(colored(f"Error: task.json not found at {target_dir}", Colors.RED))
964
+ return 1
965
+
966
+ data = read_json(task_json)
967
+ if not data:
968
+ return 1
969
+
970
+ data["scope"] = scope
971
+ write_json(task_json, data)
972
+
973
+ print(colored(f"✓ Scope set to: {scope}", Colors.GREEN))
974
+ return 0
975
+
976
+
977
+ # =============================================================================
978
+ # Command: set-meta
979
+ # =============================================================================
980
+
981
+ def cmd_set_meta(args: argparse.Namespace) -> int:
982
+ """Set/overwrite one metadata key on an existing task."""
983
+ repo_root = get_repo_root()
984
+ target_dir = resolve_task_dir(args.dir, repo_root)
985
+ key = args.key
986
+ value = args.value
987
+
988
+ if not key:
989
+ print(colored("Error: Missing arguments", Colors.RED))
990
+ print("Usage: python3 task.py set-meta <task-dir> <key> <value>")
991
+ return 1
992
+
993
+ if not target_dir:
994
+ # target_dir is None here, so it must not appear in the message. This
995
+ # is also the branch a ref pointing outside the repo lands in.
996
+ print(colored(f"Error: Task not found: {args.dir}", Colors.RED))
997
+ return 1
998
+
999
+ task_json = target_dir / FILE_TASK_JSON
1000
+ if not task_json.is_file():
1001
+ print(colored(f"Error: task.json not found at {target_dir}", Colors.RED))
1002
+ return 1
1003
+
1004
+ data = read_json(task_json)
1005
+ if not data:
1006
+ return 1
1007
+
1008
+ meta = data.get("meta")
1009
+ if not isinstance(meta, dict):
1010
+ meta = {}
1011
+ meta[key] = value
1012
+ data["meta"] = meta
1013
+ write_json(task_json, data)
1014
+
1015
+ print(colored(f"✓ Meta set: {key} = {value}", Colors.GREEN))
1016
+ return 0