trellis-herbivore 0.1.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 (629) hide show
  1. package/bin/trellis.js +3 -0
  2. package/dist/cli/index.d.ts +3 -0
  3. package/dist/cli/index.d.ts.map +1 -0
  4. package/dist/cli/index.js +174 -0
  5. package/dist/cli/index.js.map +1 -0
  6. package/dist/commands/channel/adapters/claude.d.ts +38 -0
  7. package/dist/commands/channel/adapters/claude.d.ts.map +1 -0
  8. package/dist/commands/channel/adapters/claude.js +209 -0
  9. package/dist/commands/channel/adapters/claude.js.map +1 -0
  10. package/dist/commands/channel/adapters/codex.d.ts +77 -0
  11. package/dist/commands/channel/adapters/codex.d.ts.map +1 -0
  12. package/dist/commands/channel/adapters/codex.js +495 -0
  13. package/dist/commands/channel/adapters/codex.js.map +1 -0
  14. package/dist/commands/channel/adapters/index.d.ts +79 -0
  15. package/dist/commands/channel/adapters/index.d.ts.map +1 -0
  16. package/dist/commands/channel/adapters/index.js +109 -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/index.d.ts +3 -0
  43. package/dist/commands/channel/index.d.ts.map +1 -0
  44. package/dist/commands/channel/index.js +496 -0
  45. package/dist/commands/channel/index.js.map +1 -0
  46. package/dist/commands/channel/kill.d.ts +7 -0
  47. package/dist/commands/channel/kill.d.ts.map +1 -0
  48. package/dist/commands/channel/kill.js +121 -0
  49. package/dist/commands/channel/kill.js.map +1 -0
  50. package/dist/commands/channel/list.d.ts +17 -0
  51. package/dist/commands/channel/list.d.ts.map +1 -0
  52. package/dist/commands/channel/list.js +233 -0
  53. package/dist/commands/channel/list.js.map +1 -0
  54. package/dist/commands/channel/messages.d.ts +16 -0
  55. package/dist/commands/channel/messages.d.ts.map +1 -0
  56. package/dist/commands/channel/messages.js +237 -0
  57. package/dist/commands/channel/messages.js.map +1 -0
  58. package/dist/commands/channel/rm.d.ts +27 -0
  59. package/dist/commands/channel/rm.d.ts.map +1 -0
  60. package/dist/commands/channel/rm.js +216 -0
  61. package/dist/commands/channel/rm.js.map +1 -0
  62. package/dist/commands/channel/run.d.ts +31 -0
  63. package/dist/commands/channel/run.d.ts.map +1 -0
  64. package/dist/commands/channel/run.js +137 -0
  65. package/dist/commands/channel/run.js.map +1 -0
  66. package/dist/commands/channel/send.d.ts +12 -0
  67. package/dist/commands/channel/send.d.ts.map +1 -0
  68. package/dist/commands/channel/send.js +24 -0
  69. package/dist/commands/channel/send.js.map +1 -0
  70. package/dist/commands/channel/spawn.d.ts +25 -0
  71. package/dist/commands/channel/spawn.d.ts.map +1 -0
  72. package/dist/commands/channel/spawn.js +192 -0
  73. package/dist/commands/channel/spawn.js.map +1 -0
  74. package/dist/commands/channel/store/events.d.ts +39 -0
  75. package/dist/commands/channel/store/events.d.ts.map +1 -0
  76. package/dist/commands/channel/store/events.js +87 -0
  77. package/dist/commands/channel/store/events.js.map +1 -0
  78. package/dist/commands/channel/store/filter.d.ts +3 -0
  79. package/dist/commands/channel/store/filter.d.ts.map +1 -0
  80. package/dist/commands/channel/store/filter.js +2 -0
  81. package/dist/commands/channel/store/filter.js.map +1 -0
  82. package/dist/commands/channel/store/lock.d.ts +23 -0
  83. package/dist/commands/channel/store/lock.d.ts.map +1 -0
  84. package/dist/commands/channel/store/lock.js +99 -0
  85. package/dist/commands/channel/store/lock.js.map +1 -0
  86. package/dist/commands/channel/store/paths.d.ts +63 -0
  87. package/dist/commands/channel/store/paths.d.ts.map +1 -0
  88. package/dist/commands/channel/store/paths.js +246 -0
  89. package/dist/commands/channel/store/paths.js.map +1 -0
  90. package/dist/commands/channel/store/schema.d.ts +27 -0
  91. package/dist/commands/channel/store/schema.d.ts.map +1 -0
  92. package/dist/commands/channel/store/schema.js +34 -0
  93. package/dist/commands/channel/store/schema.js.map +1 -0
  94. package/dist/commands/channel/store/thread-state.d.ts +5 -0
  95. package/dist/commands/channel/store/thread-state.d.ts.map +1 -0
  96. package/dist/commands/channel/store/thread-state.js +16 -0
  97. package/dist/commands/channel/store/thread-state.js.map +1 -0
  98. package/dist/commands/channel/store/watch.d.ts +19 -0
  99. package/dist/commands/channel/store/watch.d.ts.map +1 -0
  100. package/dist/commands/channel/store/watch.js +130 -0
  101. package/dist/commands/channel/store/watch.js.map +1 -0
  102. package/dist/commands/channel/supervisor/inbox.d.ts +25 -0
  103. package/dist/commands/channel/supervisor/inbox.d.ts.map +1 -0
  104. package/dist/commands/channel/supervisor/inbox.js +99 -0
  105. package/dist/commands/channel/supervisor/inbox.js.map +1 -0
  106. package/dist/commands/channel/supervisor/shutdown.d.ts +66 -0
  107. package/dist/commands/channel/supervisor/shutdown.d.ts.map +1 -0
  108. package/dist/commands/channel/supervisor/shutdown.js +143 -0
  109. package/dist/commands/channel/supervisor/shutdown.js.map +1 -0
  110. package/dist/commands/channel/supervisor/stdout.d.ts +49 -0
  111. package/dist/commands/channel/supervisor/stdout.d.ts.map +1 -0
  112. package/dist/commands/channel/supervisor/stdout.js +107 -0
  113. package/dist/commands/channel/supervisor/stdout.js.map +1 -0
  114. package/dist/commands/channel/supervisor.d.ts +47 -0
  115. package/dist/commands/channel/supervisor.d.ts.map +1 -0
  116. package/dist/commands/channel/supervisor.js +283 -0
  117. package/dist/commands/channel/supervisor.js.map +1 -0
  118. package/dist/commands/channel/text-body.d.ts +13 -0
  119. package/dist/commands/channel/text-body.d.ts.map +1 -0
  120. package/dist/commands/channel/text-body.js +47 -0
  121. package/dist/commands/channel/text-body.js.map +1 -0
  122. package/dist/commands/channel/threads.d.ts +39 -0
  123. package/dist/commands/channel/threads.d.ts.map +1 -0
  124. package/dist/commands/channel/threads.js +106 -0
  125. package/dist/commands/channel/threads.js.map +1 -0
  126. package/dist/commands/channel/title.d.ts +12 -0
  127. package/dist/commands/channel/title.d.ts.map +1 -0
  128. package/dist/commands/channel/title.js +24 -0
  129. package/dist/commands/channel/title.js.map +1 -0
  130. package/dist/commands/channel/wait.d.ts +18 -0
  131. package/dist/commands/channel/wait.d.ts.map +1 -0
  132. package/dist/commands/channel/wait.js +76 -0
  133. package/dist/commands/channel/wait.js.map +1 -0
  134. package/dist/commands/init.d.ts +57 -0
  135. package/dist/commands/init.d.ts.map +1 -0
  136. package/dist/commands/init.js +1466 -0
  137. package/dist/commands/init.js.map +1 -0
  138. package/dist/commands/mem.d.ts +234 -0
  139. package/dist/commands/mem.d.ts.map +1 -0
  140. package/dist/commands/mem.js +1869 -0
  141. package/dist/commands/mem.js.map +1 -0
  142. package/dist/commands/uninstall.d.ts +27 -0
  143. package/dist/commands/uninstall.d.ts.map +1 -0
  144. package/dist/commands/uninstall.js +339 -0
  145. package/dist/commands/uninstall.js.map +1 -0
  146. package/dist/commands/update.d.ts +72 -0
  147. package/dist/commands/update.d.ts.map +1 -0
  148. package/dist/commands/update.js +1926 -0
  149. package/dist/commands/update.js.map +1 -0
  150. package/dist/commands/upgrade.d.ts +28 -0
  151. package/dist/commands/upgrade.d.ts.map +1 -0
  152. package/dist/commands/upgrade.js +84 -0
  153. package/dist/commands/upgrade.js.map +1 -0
  154. package/dist/configurators/antigravity.d.ts +7 -0
  155. package/dist/configurators/antigravity.d.ts.map +1 -0
  156. package/dist/configurators/antigravity.js +19 -0
  157. package/dist/configurators/antigravity.js.map +1 -0
  158. package/dist/configurators/claude.d.ts +9 -0
  159. package/dist/configurators/claude.d.ts.map +1 -0
  160. package/dist/configurators/claude.js +72 -0
  161. package/dist/configurators/claude.js.map +1 -0
  162. package/dist/configurators/codebuddy.d.ts +10 -0
  163. package/dist/configurators/codebuddy.d.ts.map +1 -0
  164. package/dist/configurators/codebuddy.js +30 -0
  165. package/dist/configurators/codebuddy.js.map +1 -0
  166. package/dist/configurators/codex.d.ts +8 -0
  167. package/dist/configurators/codex.d.ts.map +1 -0
  168. package/dist/configurators/codex.js +87 -0
  169. package/dist/configurators/codex.js.map +1 -0
  170. package/dist/configurators/copilot.d.ts +10 -0
  171. package/dist/configurators/copilot.d.ts.map +1 -0
  172. package/dist/configurators/copilot.js +51 -0
  173. package/dist/configurators/copilot.js.map +1 -0
  174. package/dist/configurators/cursor.d.ts +10 -0
  175. package/dist/configurators/cursor.d.ts.map +1 -0
  176. package/dist/configurators/cursor.js +29 -0
  177. package/dist/configurators/cursor.js.map +1 -0
  178. package/dist/configurators/droid.d.ts +10 -0
  179. package/dist/configurators/droid.d.ts.map +1 -0
  180. package/dist/configurators/droid.js +30 -0
  181. package/dist/configurators/droid.js.map +1 -0
  182. package/dist/configurators/gemini.d.ts +16 -0
  183. package/dist/configurators/gemini.d.ts.map +1 -0
  184. package/dist/configurators/gemini.js +38 -0
  185. package/dist/configurators/gemini.js.map +1 -0
  186. package/dist/configurators/index.d.ts +65 -0
  187. package/dist/configurators/index.d.ts.map +1 -0
  188. package/dist/configurators/index.js +367 -0
  189. package/dist/configurators/index.js.map +1 -0
  190. package/dist/configurators/kilo.d.ts +7 -0
  191. package/dist/configurators/kilo.d.ts.map +1 -0
  192. package/dist/configurators/kilo.js +19 -0
  193. package/dist/configurators/kilo.js.map +1 -0
  194. package/dist/configurators/kiro.d.ts +8 -0
  195. package/dist/configurators/kiro.d.ts.map +1 -0
  196. package/dist/configurators/kiro.js +24 -0
  197. package/dist/configurators/kiro.js.map +1 -0
  198. package/dist/configurators/opencode.d.ts +14 -0
  199. package/dist/configurators/opencode.d.ts.map +1 -0
  200. package/dist/configurators/opencode.js +96 -0
  201. package/dist/configurators/opencode.js.map +1 -0
  202. package/dist/configurators/pi.d.ts +3 -0
  203. package/dist/configurators/pi.d.ts.map +1 -0
  204. package/dist/configurators/pi.js +45 -0
  205. package/dist/configurators/pi.js.map +1 -0
  206. package/dist/configurators/qoder.d.ts +11 -0
  207. package/dist/configurators/qoder.d.ts.map +1 -0
  208. package/dist/configurators/qoder.js +31 -0
  209. package/dist/configurators/qoder.js.map +1 -0
  210. package/dist/configurators/shared.d.ts +178 -0
  211. package/dist/configurators/shared.d.ts.map +1 -0
  212. package/dist/configurators/shared.js +538 -0
  213. package/dist/configurators/shared.js.map +1 -0
  214. package/dist/configurators/windsurf.d.ts +7 -0
  215. package/dist/configurators/windsurf.d.ts.map +1 -0
  216. package/dist/configurators/windsurf.js +19 -0
  217. package/dist/configurators/windsurf.js.map +1 -0
  218. package/dist/configurators/workflow.d.ts +29 -0
  219. package/dist/configurators/workflow.d.ts.map +1 -0
  220. package/dist/configurators/workflow.js +163 -0
  221. package/dist/configurators/workflow.js.map +1 -0
  222. package/dist/constants/paths.d.ts +70 -0
  223. package/dist/constants/paths.d.ts.map +1 -0
  224. package/dist/constants/paths.js +79 -0
  225. package/dist/constants/paths.js.map +1 -0
  226. package/dist/constants/version.d.ts +9 -0
  227. package/dist/constants/version.d.ts.map +1 -0
  228. package/dist/constants/version.js +15 -0
  229. package/dist/constants/version.js.map +1 -0
  230. package/dist/index.d.ts +9 -0
  231. package/dist/index.d.ts.map +1 -0
  232. package/dist/index.js +9 -0
  233. package/dist/index.js.map +1 -0
  234. package/dist/migrations/index.d.ts +62 -0
  235. package/dist/migrations/index.d.ts.map +1 -0
  236. package/dist/migrations/index.js +187 -0
  237. package/dist/migrations/index.js.map +1 -0
  238. package/dist/migrations/manifests/0.1.9.json +30 -0
  239. package/dist/migrations/manifests/0.2.0.json +49 -0
  240. package/dist/migrations/manifests/0.2.12.json +9 -0
  241. package/dist/migrations/manifests/0.2.13.json +9 -0
  242. package/dist/migrations/manifests/0.2.14.json +175 -0
  243. package/dist/migrations/manifests/0.2.15.json +33 -0
  244. package/dist/migrations/manifests/0.3.0-beta.0.json +297 -0
  245. package/dist/migrations/manifests/0.3.0-beta.1.json +9 -0
  246. package/dist/migrations/manifests/0.3.0-beta.10.json +9 -0
  247. package/dist/migrations/manifests/0.3.0-beta.11.json +9 -0
  248. package/dist/migrations/manifests/0.3.0-beta.12.json +9 -0
  249. package/dist/migrations/manifests/0.3.0-beta.13.json +9 -0
  250. package/dist/migrations/manifests/0.3.0-beta.14.json +9 -0
  251. package/dist/migrations/manifests/0.3.0-beta.15.json +9 -0
  252. package/dist/migrations/manifests/0.3.0-beta.16.json +9 -0
  253. package/dist/migrations/manifests/0.3.0-beta.2.json +9 -0
  254. package/dist/migrations/manifests/0.3.0-beta.3.json +9 -0
  255. package/dist/migrations/manifests/0.3.0-beta.4.json +9 -0
  256. package/dist/migrations/manifests/0.3.0-beta.5.json +9 -0
  257. package/dist/migrations/manifests/0.3.0-beta.6.json +9 -0
  258. package/dist/migrations/manifests/0.3.0-beta.7.json +11 -0
  259. package/dist/migrations/manifests/0.3.0-beta.8.json +9 -0
  260. package/dist/migrations/manifests/0.3.0-beta.9.json +9 -0
  261. package/dist/migrations/manifests/0.3.0-rc.0.json +9 -0
  262. package/dist/migrations/manifests/0.3.0-rc.1.json +9 -0
  263. package/dist/migrations/manifests/0.3.0-rc.2.json +9 -0
  264. package/dist/migrations/manifests/0.3.0-rc.3.json +9 -0
  265. package/dist/migrations/manifests/0.3.0-rc.4.json +9 -0
  266. package/dist/migrations/manifests/0.3.0-rc.5.json +9 -0
  267. package/dist/migrations/manifests/0.3.0-rc.6.json +9 -0
  268. package/dist/migrations/manifests/0.3.0.json +11 -0
  269. package/dist/migrations/manifests/0.3.1.json +9 -0
  270. package/dist/migrations/manifests/0.3.10.json +9 -0
  271. package/dist/migrations/manifests/0.3.2.json +9 -0
  272. package/dist/migrations/manifests/0.3.3.json +9 -0
  273. package/dist/migrations/manifests/0.3.4.json +21 -0
  274. package/dist/migrations/manifests/0.3.5.json +9 -0
  275. package/dist/migrations/manifests/0.3.6.json +9 -0
  276. package/dist/migrations/manifests/0.3.7.json +9 -0
  277. package/dist/migrations/manifests/0.3.8.json +9 -0
  278. package/dist/migrations/manifests/0.3.9.json +9 -0
  279. package/dist/migrations/manifests/0.4.0-beta.1.json +228 -0
  280. package/dist/migrations/manifests/0.4.0-beta.10.json +9 -0
  281. package/dist/migrations/manifests/0.4.0-beta.2.json +9 -0
  282. package/dist/migrations/manifests/0.4.0-beta.3.json +9 -0
  283. package/dist/migrations/manifests/0.4.0-beta.4.json +9 -0
  284. package/dist/migrations/manifests/0.4.0-beta.5.json +9 -0
  285. package/dist/migrations/manifests/0.4.0-beta.6.json +9 -0
  286. package/dist/migrations/manifests/0.4.0-beta.7.json +9 -0
  287. package/dist/migrations/manifests/0.4.0-beta.8.json +34 -0
  288. package/dist/migrations/manifests/0.4.0-beta.9.json +9 -0
  289. package/dist/migrations/manifests/0.4.0-rc.0.json +9 -0
  290. package/dist/migrations/manifests/0.4.0-rc.1.json +9 -0
  291. package/dist/migrations/manifests/0.4.0.json +9 -0
  292. package/dist/migrations/manifests/0.5.0-beta.0.json +1646 -0
  293. package/dist/migrations/manifests/0.5.0-beta.1.json +9 -0
  294. package/dist/migrations/manifests/0.5.0-beta.10.json +9 -0
  295. package/dist/migrations/manifests/0.5.0-beta.11.json +9 -0
  296. package/dist/migrations/manifests/0.5.0-beta.12.json +9 -0
  297. package/dist/migrations/manifests/0.5.0-beta.13.json +9 -0
  298. package/dist/migrations/manifests/0.5.0-beta.14.json +9 -0
  299. package/dist/migrations/manifests/0.5.0-beta.15.json +116 -0
  300. package/dist/migrations/manifests/0.5.0-beta.16.json +9 -0
  301. package/dist/migrations/manifests/0.5.0-beta.17.json +9 -0
  302. package/dist/migrations/manifests/0.5.0-beta.18.json +9 -0
  303. package/dist/migrations/manifests/0.5.0-beta.19.json +9 -0
  304. package/dist/migrations/manifests/0.5.0-beta.2.json +9 -0
  305. package/dist/migrations/manifests/0.5.0-beta.3.json +9 -0
  306. package/dist/migrations/manifests/0.5.0-beta.4.json +9 -0
  307. package/dist/migrations/manifests/0.5.0-beta.5.json +222 -0
  308. package/dist/migrations/manifests/0.5.0-beta.6.json +9 -0
  309. package/dist/migrations/manifests/0.5.0-beta.7.json +9 -0
  310. package/dist/migrations/manifests/0.5.0-beta.8.json +9 -0
  311. package/dist/migrations/manifests/0.5.0-beta.9.json +48 -0
  312. package/dist/migrations/manifests/0.5.0-rc.0.json +9 -0
  313. package/dist/migrations/manifests/0.5.0-rc.1.json +9 -0
  314. package/dist/migrations/manifests/0.5.0-rc.2.json +9 -0
  315. package/dist/migrations/manifests/0.5.0-rc.3.json +9 -0
  316. package/dist/migrations/manifests/0.5.0-rc.4.json +9 -0
  317. package/dist/migrations/manifests/0.5.0-rc.5.json +9 -0
  318. package/dist/migrations/manifests/0.5.0-rc.6.json +9 -0
  319. package/dist/migrations/manifests/0.5.0-rc.7.json +9 -0
  320. package/dist/migrations/manifests/0.5.0.json +9 -0
  321. package/dist/migrations/manifests/0.5.1.json +9 -0
  322. package/dist/migrations/manifests/0.5.10.json +9 -0
  323. package/dist/migrations/manifests/0.5.11.json +16 -0
  324. package/dist/migrations/manifests/0.5.12.json +9 -0
  325. package/dist/migrations/manifests/0.5.13.json +9 -0
  326. package/dist/migrations/manifests/0.5.14.json +9 -0
  327. package/dist/migrations/manifests/0.5.15.json +9 -0
  328. package/dist/migrations/manifests/0.5.2.json +9 -0
  329. package/dist/migrations/manifests/0.5.3.json +9 -0
  330. package/dist/migrations/manifests/0.5.4.json +9 -0
  331. package/dist/migrations/manifests/0.5.5.json +9 -0
  332. package/dist/migrations/manifests/0.5.6.json +9 -0
  333. package/dist/migrations/manifests/0.5.7.json +16 -0
  334. package/dist/migrations/manifests/0.5.8.json +9 -0
  335. package/dist/migrations/manifests/0.5.9.json +9 -0
  336. package/dist/migrations/manifests/0.6.0-beta.0.json +16 -0
  337. package/dist/migrations/manifests/0.6.0-beta.1.json +9 -0
  338. package/dist/migrations/manifests/0.6.0-beta.10.json +9 -0
  339. package/dist/migrations/manifests/0.6.0-beta.11.json +9 -0
  340. package/dist/migrations/manifests/0.6.0-beta.12.json +9 -0
  341. package/dist/migrations/manifests/0.6.0-beta.13.json +9 -0
  342. package/dist/migrations/manifests/0.6.0-beta.14.json +9 -0
  343. package/dist/migrations/manifests/0.6.0-beta.2.json +9 -0
  344. package/dist/migrations/manifests/0.6.0-beta.3.json +9 -0
  345. package/dist/migrations/manifests/0.6.0-beta.4.json +9 -0
  346. package/dist/migrations/manifests/0.6.0-beta.5.json +9 -0
  347. package/dist/migrations/manifests/0.6.0-beta.6.json +16 -0
  348. package/dist/migrations/manifests/0.6.0-beta.7.json +9 -0
  349. package/dist/migrations/manifests/0.6.0-beta.8.json +9 -0
  350. package/dist/migrations/manifests/0.6.0-beta.9.json +9 -0
  351. package/dist/templates/claude/agents/trellis-check.md +114 -0
  352. package/dist/templates/claude/agents/trellis-implement.md +113 -0
  353. package/dist/templates/claude/agents/trellis-research.md +137 -0
  354. package/dist/templates/claude/index.d.ts +22 -0
  355. package/dist/templates/claude/index.d.ts.map +1 -0
  356. package/dist/templates/claude/index.js +46 -0
  357. package/dist/templates/claude/index.js.map +1 -0
  358. package/dist/templates/claude/settings.json +73 -0
  359. package/dist/templates/codebuddy/agents/trellis-check.md +109 -0
  360. package/dist/templates/codebuddy/agents/trellis-implement.md +110 -0
  361. package/dist/templates/codebuddy/agents/trellis-research.md +137 -0
  362. package/dist/templates/codebuddy/index.d.ts +15 -0
  363. package/dist/templates/codebuddy/index.d.ts.map +1 -0
  364. package/dist/templates/codebuddy/index.js +15 -0
  365. package/dist/templates/codebuddy/index.js.map +1 -0
  366. package/dist/templates/codebuddy/settings.json +59 -0
  367. package/dist/templates/codex/agents/trellis-check.toml +84 -0
  368. package/dist/templates/codex/agents/trellis-implement.toml +65 -0
  369. package/dist/templates/codex/agents/trellis-research.toml +73 -0
  370. package/dist/templates/codex/config.toml +35 -0
  371. package/dist/templates/codex/hooks/session-start.py +545 -0
  372. package/dist/templates/codex/hooks.json +15 -0
  373. package/dist/templates/codex/index.d.ts +39 -0
  374. package/dist/templates/codex/index.d.ts.map +1 -0
  375. package/dist/templates/codex/index.js +85 -0
  376. package/dist/templates/codex/index.js.map +1 -0
  377. package/dist/templates/codex/skills/before-dev/SKILL.md +40 -0
  378. package/dist/templates/codex/skills/brainstorm/SKILL.md +112 -0
  379. package/dist/templates/codex/skills/break-loop/SKILL.md +130 -0
  380. package/dist/templates/codex/skills/check/SKILL.md +98 -0
  381. package/dist/templates/codex/skills/check-cross-layer/SKILL.md +158 -0
  382. package/dist/templates/codex/skills/create-command/SKILL.md +101 -0
  383. package/dist/templates/codex/skills/finish-work/SKILL.md +90 -0
  384. package/dist/templates/codex/skills/improve-ut/SKILL.md +69 -0
  385. package/dist/templates/codex/skills/integrate-skill/SKILL.md +221 -0
  386. package/dist/templates/codex/skills/onboard/SKILL.md +363 -0
  387. package/dist/templates/codex/skills/record-session/SKILL.md +67 -0
  388. package/dist/templates/codex/skills/start/SKILL.md +64 -0
  389. package/dist/templates/codex/skills/update-spec/SKILL.md +335 -0
  390. package/dist/templates/common/bundled-skills/trellis-meta/SKILL.md +73 -0
  391. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/add-project-local-conventions.md +83 -0
  392. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-agents.md +54 -0
  393. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-context-loading.md +84 -0
  394. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-hooks.md +57 -0
  395. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-skills-or-commands.md +78 -0
  396. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-spec-structure.md +83 -0
  397. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-task-lifecycle.md +90 -0
  398. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-workflow.md +65 -0
  399. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/overview.md +55 -0
  400. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/context-injection.md +68 -0
  401. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/generated-files.md +80 -0
  402. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/overview.md +51 -0
  403. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/spec-system.md +102 -0
  404. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/task-system.md +103 -0
  405. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/workflow.md +75 -0
  406. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/workspace-memory.md +71 -0
  407. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/agents.md +80 -0
  408. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/hooks-and-settings.md +69 -0
  409. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/overview.md +59 -0
  410. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/platform-map.md +74 -0
  411. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/skills-and-commands.md +83 -0
  412. package/dist/templates/common/commands/continue.md +56 -0
  413. package/dist/templates/common/commands/finish-work.md +66 -0
  414. package/dist/templates/common/commands/start.md +59 -0
  415. package/dist/templates/common/index.d.ts +48 -0
  416. package/dist/templates/common/index.d.ts.map +1 -0
  417. package/dist/templates/common/index.js +104 -0
  418. package/dist/templates/common/index.js.map +1 -0
  419. package/dist/templates/common/skills/before-dev.md +35 -0
  420. package/dist/templates/common/skills/brainstorm.md +112 -0
  421. package/dist/templates/common/skills/break-loop.md +125 -0
  422. package/dist/templates/common/skills/check.md +93 -0
  423. package/dist/templates/common/skills/update-spec.md +351 -0
  424. package/dist/templates/copilot/hooks/session-start.py +547 -0
  425. package/dist/templates/copilot/hooks.json +19 -0
  426. package/dist/templates/copilot/index.d.ts +23 -0
  427. package/dist/templates/copilot/index.d.ts.map +1 -0
  428. package/dist/templates/copilot/index.js +54 -0
  429. package/dist/templates/copilot/index.js.map +1 -0
  430. package/dist/templates/copilot/prompts/before-dev.prompt.md +39 -0
  431. package/dist/templates/copilot/prompts/brainstorm.prompt.md +111 -0
  432. package/dist/templates/copilot/prompts/break-loop.prompt.md +129 -0
  433. package/dist/templates/copilot/prompts/check-cross-layer.prompt.md +157 -0
  434. package/dist/templates/copilot/prompts/check.prompt.md +97 -0
  435. package/dist/templates/copilot/prompts/create-command.prompt.md +116 -0
  436. package/dist/templates/copilot/prompts/finish-work.prompt.md +99 -0
  437. package/dist/templates/copilot/prompts/integrate-skill.prompt.md +223 -0
  438. package/dist/templates/copilot/prompts/onboard.prompt.md +362 -0
  439. package/dist/templates/copilot/prompts/parallel.prompt.md +204 -0
  440. package/dist/templates/copilot/prompts/record-session.prompt.md +66 -0
  441. package/dist/templates/copilot/prompts/start.prompt.md +63 -0
  442. package/dist/templates/copilot/prompts/update-spec.prompt.md +358 -0
  443. package/dist/templates/cursor/agents/trellis-check.md +108 -0
  444. package/dist/templates/cursor/agents/trellis-implement.md +109 -0
  445. package/dist/templates/cursor/agents/trellis-research.md +136 -0
  446. package/dist/templates/cursor/hooks.json +30 -0
  447. package/dist/templates/cursor/index.d.ts +13 -0
  448. package/dist/templates/cursor/index.d.ts.map +1 -0
  449. package/dist/templates/cursor/index.js +13 -0
  450. package/dist/templates/cursor/index.js.map +1 -0
  451. package/dist/templates/droid/droids/trellis-check.md +101 -0
  452. package/dist/templates/droid/droids/trellis-implement.md +102 -0
  453. package/dist/templates/droid/droids/trellis-research.md +137 -0
  454. package/dist/templates/droid/index.d.ts +15 -0
  455. package/dist/templates/droid/index.d.ts.map +1 -0
  456. package/dist/templates/droid/index.js +15 -0
  457. package/dist/templates/droid/index.js.map +1 -0
  458. package/dist/templates/droid/settings.json +59 -0
  459. package/dist/templates/extract.d.ts +40 -0
  460. package/dist/templates/extract.d.ts.map +1 -0
  461. package/dist/templates/extract.js +106 -0
  462. package/dist/templates/extract.js.map +1 -0
  463. package/dist/templates/gemini/agents/trellis-check.md +101 -0
  464. package/dist/templates/gemini/agents/trellis-implement.md +102 -0
  465. package/dist/templates/gemini/agents/trellis-research.md +136 -0
  466. package/dist/templates/gemini/index.d.ts +13 -0
  467. package/dist/templates/gemini/index.d.ts.map +1 -0
  468. package/dist/templates/gemini/index.js +13 -0
  469. package/dist/templates/gemini/index.js.map +1 -0
  470. package/dist/templates/gemini/settings.json +28 -0
  471. package/dist/templates/kiro/agents/trellis-check.json +26 -0
  472. package/dist/templates/kiro/agents/trellis-implement.json +26 -0
  473. package/dist/templates/kiro/agents/trellis-research.json +30 -0
  474. package/dist/templates/kiro/index.d.ts +18 -0
  475. package/dist/templates/kiro/index.d.ts.map +1 -0
  476. package/dist/templates/kiro/index.js +18 -0
  477. package/dist/templates/kiro/index.js.map +1 -0
  478. package/dist/templates/markdown/agents.md +21 -0
  479. package/dist/templates/markdown/gitignore.txt +15 -0
  480. package/dist/templates/markdown/index.d.ts +27 -0
  481. package/dist/templates/markdown/index.d.ts.map +1 -0
  482. package/dist/templates/markdown/index.js +52 -0
  483. package/dist/templates/markdown/index.js.map +1 -0
  484. package/dist/templates/markdown/spec/backend/database-guidelines.md.txt +51 -0
  485. package/dist/templates/markdown/spec/backend/directory-structure.md.txt +54 -0
  486. package/dist/templates/markdown/spec/backend/error-handling.md.txt +51 -0
  487. package/dist/templates/markdown/spec/backend/index.md.txt +38 -0
  488. package/dist/templates/markdown/spec/backend/logging-guidelines.md.txt +51 -0
  489. package/dist/templates/markdown/spec/backend/quality-guidelines.md.txt +51 -0
  490. package/dist/templates/markdown/spec/frontend/component-guidelines.md.txt +59 -0
  491. package/dist/templates/markdown/spec/frontend/directory-structure.md.txt +54 -0
  492. package/dist/templates/markdown/spec/frontend/hook-guidelines.md.txt +51 -0
  493. package/dist/templates/markdown/spec/frontend/index.md.txt +39 -0
  494. package/dist/templates/markdown/spec/frontend/quality-guidelines.md.txt +51 -0
  495. package/dist/templates/markdown/spec/frontend/state-management.md.txt +51 -0
  496. package/dist/templates/markdown/spec/frontend/type-safety.md.txt +51 -0
  497. package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +223 -0
  498. package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +259 -0
  499. package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +595 -0
  500. package/dist/templates/markdown/spec/guides/index.md.txt +97 -0
  501. package/dist/templates/markdown/workspace-index.md +125 -0
  502. package/dist/templates/markdown/worktree.yaml.txt +58 -0
  503. package/dist/templates/opencode/agents/trellis-check.md +116 -0
  504. package/dist/templates/opencode/agents/trellis-implement.md +118 -0
  505. package/dist/templates/opencode/agents/trellis-research.md +145 -0
  506. package/dist/templates/opencode/lib/session-utils.js +521 -0
  507. package/dist/templates/opencode/lib/trellis-context.js +381 -0
  508. package/dist/templates/opencode/package.json +5 -0
  509. package/dist/templates/opencode/plugins/inject-subagent-context.js +513 -0
  510. package/dist/templates/opencode/plugins/inject-workflow-state.js +159 -0
  511. package/dist/templates/opencode/plugins/session-start.js +101 -0
  512. package/dist/templates/pi/agents/trellis-check.md +36 -0
  513. package/dist/templates/pi/agents/trellis-implement.md +41 -0
  514. package/dist/templates/pi/agents/trellis-research.md +25 -0
  515. package/dist/templates/pi/extensions/trellis/index.ts.txt +1174 -0
  516. package/dist/templates/pi/index.d.ts +5 -0
  517. package/dist/templates/pi/index.d.ts.map +1 -0
  518. package/dist/templates/pi/index.js +12 -0
  519. package/dist/templates/pi/index.js.map +1 -0
  520. package/dist/templates/pi/settings.json +21 -0
  521. package/dist/templates/qoder/agents/trellis-check.md +102 -0
  522. package/dist/templates/qoder/agents/trellis-implement.md +103 -0
  523. package/dist/templates/qoder/agents/trellis-research.md +137 -0
  524. package/dist/templates/qoder/index.d.ts +15 -0
  525. package/dist/templates/qoder/index.d.ts.map +1 -0
  526. package/dist/templates/qoder/index.js +15 -0
  527. package/dist/templates/qoder/index.js.map +1 -0
  528. package/dist/templates/qoder/settings.json +47 -0
  529. package/dist/templates/shared-hooks/index.d.ts +50 -0
  530. package/dist/templates/shared-hooks/index.d.ts.map +1 -0
  531. package/dist/templates/shared-hooks/index.js +89 -0
  532. package/dist/templates/shared-hooks/index.js.map +1 -0
  533. package/dist/templates/shared-hooks/inject-shell-session-context.py +183 -0
  534. package/dist/templates/shared-hooks/inject-subagent-context.py +771 -0
  535. package/dist/templates/shared-hooks/inject-workflow-state.py +363 -0
  536. package/dist/templates/shared-hooks/session-start.py +827 -0
  537. package/dist/templates/template-utils.d.ts +26 -0
  538. package/dist/templates/template-utils.d.ts.map +1 -0
  539. package/dist/templates/template-utils.js +60 -0
  540. package/dist/templates/template-utils.js.map +1 -0
  541. package/dist/templates/trellis/config.yaml +90 -0
  542. package/dist/templates/trellis/gitignore.txt +32 -0
  543. package/dist/templates/trellis/index.d.ts +52 -0
  544. package/dist/templates/trellis/index.d.ts.map +1 -0
  545. package/dist/templates/trellis/index.js +97 -0
  546. package/dist/templates/trellis/index.js.map +1 -0
  547. package/dist/templates/trellis/scripts/__init__.py +5 -0
  548. package/dist/templates/trellis/scripts/add_session.py +547 -0
  549. package/dist/templates/trellis/scripts/common/__init__.py +92 -0
  550. package/dist/templates/trellis/scripts/common/active_task.py +626 -0
  551. package/dist/templates/trellis/scripts/common/cli_adapter.py +811 -0
  552. package/dist/templates/trellis/scripts/common/config.py +445 -0
  553. package/dist/templates/trellis/scripts/common/developer.py +190 -0
  554. package/dist/templates/trellis/scripts/common/git.py +31 -0
  555. package/dist/templates/trellis/scripts/common/git_context.py +106 -0
  556. package/dist/templates/trellis/scripts/common/io.py +37 -0
  557. package/dist/templates/trellis/scripts/common/log.py +45 -0
  558. package/dist/templates/trellis/scripts/common/packages_context.py +238 -0
  559. package/dist/templates/trellis/scripts/common/paths.py +447 -0
  560. package/dist/templates/trellis/scripts/common/safe_commit.py +285 -0
  561. package/dist/templates/trellis/scripts/common/session_context.py +821 -0
  562. package/dist/templates/trellis/scripts/common/task_context.py +223 -0
  563. package/dist/templates/trellis/scripts/common/task_queue.py +188 -0
  564. package/dist/templates/trellis/scripts/common/task_store.py +698 -0
  565. package/dist/templates/trellis/scripts/common/task_utils.py +274 -0
  566. package/dist/templates/trellis/scripts/common/tasks.py +112 -0
  567. package/dist/templates/trellis/scripts/common/trellis_config.py +131 -0
  568. package/dist/templates/trellis/scripts/common/types.py +110 -0
  569. package/dist/templates/trellis/scripts/common/workflow_phase.py +212 -0
  570. package/dist/templates/trellis/scripts/get_context.py +16 -0
  571. package/dist/templates/trellis/scripts/get_developer.py +26 -0
  572. package/dist/templates/trellis/scripts/hooks/linear_sync.py +243 -0
  573. package/dist/templates/trellis/scripts/init_developer.py +51 -0
  574. package/dist/templates/trellis/scripts/task.py +500 -0
  575. package/dist/templates/trellis/tasks/.gitkeep +0 -0
  576. package/dist/templates/trellis/workflow.md +690 -0
  577. package/dist/types/ai-tools.d.ts +95 -0
  578. package/dist/types/ai-tools.d.ts.map +1 -0
  579. package/dist/types/ai-tools.js +280 -0
  580. package/dist/types/ai-tools.js.map +1 -0
  581. package/dist/types/migration.d.ts +125 -0
  582. package/dist/types/migration.d.ts.map +1 -0
  583. package/dist/types/migration.js +8 -0
  584. package/dist/types/migration.js.map +1 -0
  585. package/dist/utils/compare-versions.d.ts +12 -0
  586. package/dist/utils/compare-versions.d.ts.map +1 -0
  587. package/dist/utils/compare-versions.js +86 -0
  588. package/dist/utils/compare-versions.js.map +1 -0
  589. package/dist/utils/cwd-guard.d.ts +38 -0
  590. package/dist/utils/cwd-guard.d.ts.map +1 -0
  591. package/dist/utils/cwd-guard.js +62 -0
  592. package/dist/utils/cwd-guard.js.map +1 -0
  593. package/dist/utils/file-writer.d.ts +36 -0
  594. package/dist/utils/file-writer.d.ts.map +1 -0
  595. package/dist/utils/file-writer.js +203 -0
  596. package/dist/utils/file-writer.js.map +1 -0
  597. package/dist/utils/manifest-prune.d.ts +61 -0
  598. package/dist/utils/manifest-prune.d.ts.map +1 -0
  599. package/dist/utils/manifest-prune.js +136 -0
  600. package/dist/utils/manifest-prune.js.map +1 -0
  601. package/dist/utils/posix.d.ts +13 -0
  602. package/dist/utils/posix.d.ts.map +1 -0
  603. package/dist/utils/posix.js +15 -0
  604. package/dist/utils/posix.js.map +1 -0
  605. package/dist/utils/project-detector.d.ts +46 -0
  606. package/dist/utils/project-detector.d.ts.map +1 -0
  607. package/dist/utils/project-detector.js +666 -0
  608. package/dist/utils/project-detector.js.map +1 -0
  609. package/dist/utils/proxy.d.ts +25 -0
  610. package/dist/utils/proxy.d.ts.map +1 -0
  611. package/dist/utils/proxy.js +60 -0
  612. package/dist/utils/proxy.js.map +1 -0
  613. package/dist/utils/task-json.d.ts +13 -0
  614. package/dist/utils/task-json.d.ts.map +1 -0
  615. package/dist/utils/task-json.js +12 -0
  616. package/dist/utils/task-json.js.map +1 -0
  617. package/dist/utils/template-fetcher.d.ts +150 -0
  618. package/dist/utils/template-fetcher.d.ts.map +1 -0
  619. package/dist/utils/template-fetcher.js +907 -0
  620. package/dist/utils/template-fetcher.js.map +1 -0
  621. package/dist/utils/template-hash.d.ts +123 -0
  622. package/dist/utils/template-hash.d.ts.map +1 -0
  623. package/dist/utils/template-hash.js +334 -0
  624. package/dist/utils/template-hash.js.map +1 -0
  625. package/dist/utils/uninstall-scrubbers.d.ts +66 -0
  626. package/dist/utils/uninstall-scrubbers.d.ts.map +1 -0
  627. package/dist/utils/uninstall-scrubbers.js +342 -0
  628. package/dist/utils/uninstall-scrubbers.js.map +1 -0
  629. package/package.json +90 -0
@@ -0,0 +1,626 @@
1
+ #!/usr/bin/env python3
2
+ """Session-scoped active task resolution.
3
+
4
+ The user-facing concept is a single "active task". Trellis stores that pointer
5
+ per AI session/window under `.trellis/.runtime/sessions/`; without a stable
6
+ session key there is no active task.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import hashlib
12
+ import json
13
+ import os
14
+ import re
15
+ import sys
16
+ import time
17
+ from dataclasses import dataclass
18
+ from datetime import datetime, timezone
19
+ from pathlib import Path
20
+ from typing import Any
21
+
22
+ DIR_WORKFLOW = ".trellis"
23
+ DIR_TASKS = "tasks"
24
+ DIR_RUNTIME = ".runtime"
25
+ DIR_SESSIONS = "sessions"
26
+ DIR_CURSOR_SHELL = "cursor-shell"
27
+ CURSOR_SHELL_TICKET_TTL_SECONDS = 30
28
+ TASK_SESSION_COMMANDS = {"start", "current", "finish"}
29
+
30
+ _SESSION_KEYS = ("session_id", "sessionId", "sessionID")
31
+ _CONVERSATION_KEYS = ("conversation_id", "conversationId", "conversationID")
32
+ _TRANSCRIPT_KEYS = ("transcript_path", "transcriptPath", "transcript")
33
+ _NESTED_KEYS = ("input", "properties", "event", "hook_input", "hookInput")
34
+ _KNOWN_PLATFORMS = {
35
+ "claude",
36
+ "codex",
37
+ "cursor",
38
+ "opencode",
39
+ "gemini",
40
+ "droid",
41
+ "qoder",
42
+ "codebuddy",
43
+ "kiro",
44
+ "copilot",
45
+ "pi",
46
+ }
47
+
48
+ _ENV_SESSION_KEYS: tuple[tuple[str, tuple[str, ...]], ...] = (
49
+ ("claude", ("CLAUDE_SESSION_ID", "CLAUDE_CODE_SESSION_ID")),
50
+ ("codex", ("CODEX_SESSION_ID", "CODEX_THREAD_ID")),
51
+ ("cursor", ("CURSOR_SESSION_ID",)),
52
+ ("opencode", ("OPENCODE_SESSION_ID", "OPENCODE_SESSIONID", "OPENCODE_RUN_ID")),
53
+ ("gemini", ("GEMINI_SESSION_ID",)),
54
+ ("droid", ("FACTORY_SESSION_ID", "DROID_SESSION_ID")),
55
+ ("qoder", ("QODER_SESSION_ID",)),
56
+ ("codebuddy", ("CODEBUDDY_SESSION_ID",)),
57
+ ("kiro", ("KIRO_SESSION_ID",)),
58
+ ("copilot", ("COPILOT_SESSION_ID", "COPILOT_SESSIONID")),
59
+ ("pi", ("PI_SESSION_ID", "PI_SESSIONID")),
60
+ )
61
+ _ENV_CONVERSATION_KEYS: tuple[tuple[str, tuple[str, ...]], ...] = (
62
+ ("cursor", ("CURSOR_CONVERSATION_ID", "CURSOR_CONVERSATIONID")),
63
+ )
64
+ _ENV_TRANSCRIPT_KEYS: tuple[tuple[str, tuple[str, ...]], ...] = (
65
+ ("claude", ("CLAUDE_TRANSCRIPT_PATH",)),
66
+ ("codex", ("CODEX_TRANSCRIPT_PATH",)),
67
+ ("cursor", ("CURSOR_TRANSCRIPT_PATH",)),
68
+ ("gemini", ("GEMINI_TRANSCRIPT_PATH",)),
69
+ ("droid", ("FACTORY_TRANSCRIPT_PATH", "DROID_TRANSCRIPT_PATH")),
70
+ ("qoder", ("QODER_TRANSCRIPT_PATH",)),
71
+ ("codebuddy", ("CODEBUDDY_TRANSCRIPT_PATH",)),
72
+ )
73
+ _ENV_PLATFORM_ALIASES = {
74
+ "claude-code": "claude",
75
+ "factory": "droid",
76
+ "factory-ai": "droid",
77
+ "github-copilot": "copilot",
78
+ }
79
+
80
+
81
+ @dataclass(frozen=True)
82
+ class ActiveTask:
83
+ """Resolved active task state."""
84
+
85
+ task_path: str | None
86
+ source_type: str
87
+ context_key: str | None = None
88
+ stale: bool = False
89
+
90
+ @property
91
+ def source(self) -> str:
92
+ """Human-readable source label."""
93
+ if self.source_type == "session" and self.context_key:
94
+ return f"session:{self.context_key}"
95
+ if self.source_type == "session-fallback" and self.context_key:
96
+ return f"session-fallback:{self.context_key}"
97
+ return self.source_type
98
+
99
+
100
+ def normalize_task_ref(task_ref: str) -> str:
101
+ """Normalize a task ref for stable storage and comparison."""
102
+ normalized = task_ref.strip()
103
+ if not normalized:
104
+ return ""
105
+
106
+ path_obj = Path(normalized)
107
+ if path_obj.is_absolute():
108
+ return str(path_obj)
109
+
110
+ normalized = normalized.replace("\\", "/")
111
+ while normalized.startswith("./"):
112
+ normalized = normalized[2:]
113
+
114
+ if normalized.startswith(f"{DIR_TASKS}/"):
115
+ return f"{DIR_WORKFLOW}/{normalized}"
116
+
117
+ return normalized
118
+
119
+
120
+ def resolve_task_ref(task_ref: str, repo_root: Path) -> Path | None:
121
+ """Resolve a task ref to an absolute task directory."""
122
+ normalized = normalize_task_ref(task_ref)
123
+ if not normalized:
124
+ return None
125
+
126
+ path_obj = Path(normalized)
127
+ if path_obj.is_absolute():
128
+ return path_obj
129
+
130
+ if normalized.startswith(f"{DIR_WORKFLOW}/"):
131
+ return repo_root / path_obj
132
+
133
+ return repo_root / DIR_WORKFLOW / DIR_TASKS / path_obj
134
+
135
+
136
+ def _runtime_sessions_dir(repo_root: Path) -> Path:
137
+ return repo_root / DIR_WORKFLOW / DIR_RUNTIME / DIR_SESSIONS
138
+
139
+
140
+ def _sanitize_key(raw: str) -> str:
141
+ safe = re.sub(r"[^A-Za-z0-9._-]+", "_", raw.strip())
142
+ safe = safe.strip("._-")
143
+ return safe[:160] if safe else ""
144
+
145
+
146
+ def _hash_value(raw: str) -> str:
147
+ return hashlib.sha256(raw.encode("utf-8")).hexdigest()[:24]
148
+
149
+
150
+ def _as_dict(value: Any) -> dict[str, Any] | None:
151
+ return value if isinstance(value, dict) else None
152
+
153
+
154
+ def _string_value(value: Any) -> str | None:
155
+ if isinstance(value, str):
156
+ stripped = value.strip()
157
+ return stripped or None
158
+ return None
159
+
160
+
161
+ def _lookup_string(data: dict[str, Any], keys: tuple[str, ...]) -> str | None:
162
+ for key in keys:
163
+ value = _string_value(data.get(key))
164
+ if value:
165
+ return value
166
+
167
+ for nested_key in _NESTED_KEYS:
168
+ nested = _as_dict(data.get(nested_key))
169
+ if not nested:
170
+ continue
171
+ value = _lookup_string(nested, keys)
172
+ if value:
173
+ return value
174
+
175
+ return None
176
+
177
+
178
+ def _detect_platform(platform_input: dict[str, Any] | None, platform: str | None) -> str:
179
+ if platform:
180
+ return _sanitize_key(platform) or "session"
181
+ if platform_input:
182
+ for key in ("_trellis_platform", "trellis_platform", "platform", "source"):
183
+ value = _string_value(platform_input.get(key))
184
+ if value:
185
+ return _sanitize_key(value) or "session"
186
+ if _string_value(platform_input.get("cursor_version")):
187
+ return "cursor"
188
+ return "session"
189
+
190
+
191
+ def _context_key(platform_name: str, kind: str, value: str) -> str:
192
+ if kind == "transcript":
193
+ return f"{platform_name}_transcript_{_hash_value(value)}"
194
+ safe_value = _sanitize_key(value)
195
+ if safe_value:
196
+ return f"{platform_name}_{safe_value}"
197
+ return f"{platform_name}_{_hash_value(value)}"
198
+
199
+
200
+ def _iter_env_keys(
201
+ env_keys: tuple[tuple[str, tuple[str, ...]], ...],
202
+ platform_name: str | None,
203
+ ) -> tuple[tuple[str, tuple[str, ...]], ...]:
204
+ if not platform_name:
205
+ return env_keys
206
+ matched = tuple((name, keys) for name, keys in env_keys if name == platform_name)
207
+ return matched
208
+
209
+
210
+ def _env_platform_name(platform_name: str | None) -> str | None:
211
+ if not platform_name or platform_name == "session":
212
+ return None
213
+ return _ENV_PLATFORM_ALIASES.get(platform_name, platform_name)
214
+
215
+
216
+ def _lookup_env_context_key(platform_name: str | None) -> str | None:
217
+ """Resolve a context key from platform-provided environment variables.
218
+
219
+ Hooks pass `TRELLIS_CONTEXT_ID` to subprocesses they launch, but an AI-run
220
+ shell command can only see session identity if the host platform exports it
221
+ in the command environment. These names are best-effort adapters; if none
222
+ are present, there is no session-scoped active task.
223
+ """
224
+ env_platform_name = _env_platform_name(platform_name)
225
+
226
+ for name, keys in _iter_env_keys(_ENV_SESSION_KEYS, env_platform_name):
227
+ for key in keys:
228
+ value = _string_value(os.environ.get(key))
229
+ if value:
230
+ return _context_key(name, "session", value)
231
+
232
+ for name, keys in _iter_env_keys(_ENV_CONVERSATION_KEYS, env_platform_name):
233
+ for key in keys:
234
+ value = _string_value(os.environ.get(key))
235
+ if value:
236
+ return _context_key(name, "conversation", value)
237
+
238
+ for name, keys in _iter_env_keys(_ENV_TRANSCRIPT_KEYS, env_platform_name):
239
+ for key in keys:
240
+ value = _string_value(os.environ.get(key))
241
+ if value:
242
+ return _context_key(name, "transcript", value)
243
+
244
+ return None
245
+
246
+
247
+ def _find_repo_root_from_cwd() -> Path | None:
248
+ current = Path.cwd().resolve()
249
+ while True:
250
+ if (current / DIR_WORKFLOW).is_dir():
251
+ return current
252
+ if current == current.parent:
253
+ return None
254
+ current = current.parent
255
+
256
+
257
+ def _cursor_shell_ticket_dir(repo_root: Path) -> Path:
258
+ return repo_root / DIR_WORKFLOW / DIR_RUNTIME / DIR_CURSOR_SHELL
259
+
260
+
261
+ def _remove_file(path: Path) -> bool:
262
+ try:
263
+ path.unlink()
264
+ return True
265
+ except OSError:
266
+ return False
267
+
268
+
269
+ def _task_refs_match(left: str | None, right: str | None, repo_root: Path) -> bool:
270
+ if not left or not right:
271
+ return False
272
+ left_path = resolve_task_ref(left, repo_root)
273
+ right_path = resolve_task_ref(right, repo_root)
274
+ if left_path is not None and right_path is not None:
275
+ return left_path == right_path
276
+ return normalize_task_ref(left) == normalize_task_ref(right)
277
+
278
+
279
+ def _pending_ticket_matches_args(ticket: dict[str, Any], repo_root: Path) -> bool:
280
+ if Path(sys.argv[0]).name != "task.py":
281
+ return False
282
+ args = tuple(sys.argv[1:])
283
+ if not args:
284
+ return False
285
+
286
+ command_name = args[0]
287
+ if command_name not in TASK_SESSION_COMMANDS:
288
+ return False
289
+
290
+ subcommands = ticket.get("subcommands")
291
+ if not isinstance(subcommands, list):
292
+ return False
293
+
294
+ for subcommand in subcommands:
295
+ if not isinstance(subcommand, dict):
296
+ continue
297
+ if _string_value(subcommand.get("name")) != command_name:
298
+ continue
299
+ if command_name != "start":
300
+ return True
301
+ task_ref = args[1] if len(args) > 1 else None
302
+ if _task_refs_match(_string_value(subcommand.get("task_ref")), task_ref, repo_root):
303
+ return True
304
+
305
+ return False
306
+
307
+
308
+ def _ticket_is_fresh(ticket: dict[str, Any], ticket_path: Path, now: float) -> bool:
309
+ expires_at = ticket.get("expires_at_epoch")
310
+ if isinstance(expires_at, (int, float)) and expires_at < now:
311
+ _remove_file(ticket_path)
312
+ return False
313
+
314
+ created_at = ticket.get("created_at_epoch")
315
+ if isinstance(created_at, (int, float)):
316
+ if now - created_at <= CURSOR_SHELL_TICKET_TTL_SECONDS:
317
+ return True
318
+ _remove_file(ticket_path)
319
+ return False
320
+ return True
321
+
322
+
323
+ def _ticket_cwd_matches_repo(ticket: dict[str, Any], repo_root: Path) -> bool:
324
+ cwd = _string_value(ticket.get("cwd"))
325
+ if not cwd:
326
+ return True
327
+ try:
328
+ Path(cwd).resolve().relative_to(repo_root)
329
+ except ValueError:
330
+ return False
331
+ return True
332
+
333
+
334
+ def _matching_cursor_ticket_context_key(
335
+ ticket_path: Path,
336
+ repo_root: Path,
337
+ now: float,
338
+ ) -> str | None:
339
+ ticket = _read_json(ticket_path)
340
+ if ticket is None or ticket.get("platform") != "cursor":
341
+ return None
342
+ if not _ticket_is_fresh(ticket, ticket_path, now):
343
+ return None
344
+ if not _ticket_cwd_matches_repo(ticket, repo_root):
345
+ return None
346
+ if not _pending_ticket_matches_args(ticket, repo_root):
347
+ return None
348
+ return _string_value(ticket.get("context_key"))
349
+
350
+
351
+ def _lookup_cursor_shell_ticket_context_key() -> str | None:
352
+ """Resolve Cursor conversation identity from a short-lived shell ticket.
353
+
354
+ Cursor exposes `conversation_id` to `beforeShellExecution`, but does not
355
+ export it into the shell command environment. The Cursor hook writes a
356
+ short-lived ticket just before `task.py` runs. We accept a ticket only when
357
+ the current `task.py` subcommand matches and exactly one fresh context key
358
+ matches, which avoids cross-window pointer contamination.
359
+ """
360
+ repo_root = _find_repo_root_from_cwd()
361
+ if repo_root is None:
362
+ return None
363
+
364
+ ticket_dir = _cursor_shell_ticket_dir(repo_root)
365
+ if not ticket_dir.is_dir():
366
+ return None
367
+
368
+ now = time.time()
369
+ candidates: set[str] = set()
370
+ for ticket_path in ticket_dir.glob("*.json"):
371
+ context_key = _matching_cursor_ticket_context_key(ticket_path, repo_root, now)
372
+ if context_key:
373
+ candidates.add(context_key)
374
+
375
+ if len(candidates) == 1:
376
+ return next(iter(candidates))
377
+ return None
378
+
379
+
380
+ def resolve_context_key(
381
+ platform_input: dict[str, Any] | None = None,
382
+ platform: str | None = None,
383
+ ) -> str | None:
384
+ """Resolve a stable session/window context key, if one is available.
385
+
386
+ `TRELLIS_CONTEXT_ID` is an explicit context-key override used by CLI
387
+ scripts and subprocesses. It does not store the task itself.
388
+ """
389
+ override = _string_value(os.environ.get("TRELLIS_CONTEXT_ID"))
390
+ if override:
391
+ return _sanitize_key(override) or _hash_value(override)
392
+
393
+ data = _as_dict(platform_input)
394
+ platform_name = _detect_platform(data, platform) if data or platform else None
395
+
396
+ if data:
397
+ session_id = _lookup_string(data, _SESSION_KEYS)
398
+ if session_id:
399
+ return _context_key(platform_name or "session", "session", session_id)
400
+
401
+ conversation_id = _lookup_string(data, _CONVERSATION_KEYS)
402
+ if conversation_id:
403
+ return _context_key(platform_name or "session", "conversation", conversation_id)
404
+
405
+ transcript_path = _lookup_string(data, _TRANSCRIPT_KEYS)
406
+ if transcript_path:
407
+ return _context_key(platform_name or "session", "transcript", transcript_path)
408
+
409
+ env_context_key = _lookup_env_context_key(platform_name)
410
+ if env_context_key:
411
+ return env_context_key
412
+
413
+ if platform_name in (None, "session", "cursor"):
414
+ return _lookup_cursor_shell_ticket_context_key()
415
+ return None
416
+
417
+
418
+ def _read_json(path: Path) -> dict[str, Any] | None:
419
+ try:
420
+ data = json.loads(path.read_text(encoding="utf-8"))
421
+ except (FileNotFoundError, json.JSONDecodeError, OSError):
422
+ return None
423
+ return data if isinstance(data, dict) else None
424
+
425
+
426
+ def _write_json(path: Path, data: dict[str, Any]) -> bool:
427
+ try:
428
+ path.parent.mkdir(parents=True, exist_ok=True)
429
+ path.write_text(
430
+ json.dumps(data, indent=2, ensure_ascii=False) + "\n",
431
+ encoding="utf-8",
432
+ )
433
+ return True
434
+ except OSError:
435
+ return False
436
+
437
+
438
+ def _canonical_task_ref(task_path: str, repo_root: Path) -> str | None:
439
+ normalized = normalize_task_ref(task_path)
440
+ if not normalized:
441
+ return None
442
+ full_path = resolve_task_ref(normalized, repo_root)
443
+ if full_path is None or not full_path.is_dir():
444
+ return None
445
+ try:
446
+ return full_path.relative_to(repo_root).as_posix()
447
+ except ValueError:
448
+ return str(full_path)
449
+
450
+
451
+ def _active_from_ref(
452
+ task_ref: str | None,
453
+ repo_root: Path,
454
+ source_type: str,
455
+ context_key: str | None = None,
456
+ ) -> ActiveTask | None:
457
+ if not task_ref:
458
+ return None
459
+ resolved = resolve_task_ref(task_ref, repo_root)
460
+ stale = resolved is None or not resolved.is_dir()
461
+ return ActiveTask(task_ref, source_type, context_key, stale)
462
+
463
+
464
+ def _context_path(repo_root: Path, context_key: str) -> Path:
465
+ return _runtime_sessions_dir(repo_root) / f"{context_key}.json"
466
+
467
+
468
+ def resolve_active_task(
469
+ repo_root: Path,
470
+ platform_input: dict[str, Any] | None = None,
471
+ platform: str | None = None,
472
+ ) -> ActiveTask:
473
+ """Resolve the active task from session runtime state only.
474
+
475
+ A stale session task is returned as stale. Missing context identity or a
476
+ missing/empty session context falls back to single-session inference: if
477
+ exactly one session file exists in the runtime, return its task with
478
+ source_type="session-fallback" — covers class-2 platform sub-agents (codex,
479
+ copilot, gemini, qoder) that don't inherit the parent's session id. ≥2
480
+ files or 0 files yield ActiveTask(None) — refuses to guess across windows.
481
+ """
482
+ context_key = resolve_context_key(platform_input, platform)
483
+ if context_key:
484
+ context = _read_json(_context_path(repo_root, context_key)) or {}
485
+ task_ref = _string_value(context.get("current_task"))
486
+ active = _active_from_ref(task_ref, repo_root, "session", context_key)
487
+ if active:
488
+ return active
489
+
490
+ fallback = _resolve_single_session_fallback(repo_root)
491
+ if fallback is not None:
492
+ return fallback
493
+
494
+ return ActiveTask(None, "none", context_key)
495
+
496
+
497
+ def _resolve_single_session_fallback(repo_root: Path) -> ActiveTask | None:
498
+ """Return the task pointed at by the sole session file, if exactly one exists.
499
+
500
+ Used when context-key resolution fails (typical for class-2 platform
501
+ sub-agents). Returns None if 0 or ≥2 session files are present — refuses
502
+ to pick across windows so 04-21's multi-session isolation contract holds.
503
+ """
504
+ sessions_dir = _runtime_sessions_dir(repo_root)
505
+ if not sessions_dir.is_dir():
506
+ return None
507
+
508
+ session_files = sorted(sessions_dir.glob("*.json"))
509
+ if len(session_files) != 1:
510
+ return None
511
+
512
+ session_file = session_files[0]
513
+ context = _read_json(session_file) or {}
514
+ task_ref = _string_value(context.get("current_task"))
515
+ if not task_ref:
516
+ return None
517
+
518
+ fallback_key = session_file.stem
519
+ return _active_from_ref(task_ref, repo_root, "session-fallback", fallback_key)
520
+
521
+
522
+ def _utc_now() -> str:
523
+ return datetime.now(timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
524
+
525
+
526
+ def _context_metadata(
527
+ platform_input: dict[str, Any] | None,
528
+ platform: str | None,
529
+ context_key: str | None = None,
530
+ ) -> dict[str, Any]:
531
+ data = _as_dict(platform_input) or {}
532
+ platform_name = _detect_platform(data, platform)
533
+ if platform_name == "session" and context_key:
534
+ prefix = context_key.split("_", 1)[0]
535
+ if prefix in _KNOWN_PLATFORMS:
536
+ platform_name = prefix
537
+ metadata: dict[str, Any] = {
538
+ "platform": platform_name,
539
+ "last_seen_at": _utc_now(),
540
+ }
541
+ for key in (*_SESSION_KEYS, *_CONVERSATION_KEYS, *_TRANSCRIPT_KEYS):
542
+ value = _lookup_string(data, (key,))
543
+ if value:
544
+ metadata[key] = value
545
+ return metadata
546
+
547
+
548
+ def set_active_task(
549
+ task_path: str,
550
+ repo_root: Path,
551
+ platform_input: dict[str, Any] | None = None,
552
+ platform: str | None = None,
553
+ ) -> ActiveTask | None:
554
+ """Set the active task in session scope.
555
+
556
+ Returns None when no context key is available; callers should surface a
557
+ user-facing error that explains how to provide session identity.
558
+ """
559
+ canonical = _canonical_task_ref(task_path, repo_root)
560
+ if canonical is None:
561
+ return None
562
+
563
+ context_key = resolve_context_key(platform_input, platform)
564
+ if not context_key:
565
+ return None
566
+
567
+ context_path = _context_path(repo_root, context_key)
568
+ context = _read_json(context_path) or {}
569
+ context.update(_context_metadata(platform_input, platform, context_key))
570
+ context["current_task"] = canonical
571
+ context.setdefault("current_run", None)
572
+ if not _write_json(context_path, context):
573
+ return None
574
+ return ActiveTask(canonical, "session", context_key)
575
+
576
+
577
+ def clear_active_task(
578
+ repo_root: Path,
579
+ platform_input: dict[str, Any] | None = None,
580
+ platform: str | None = None,
581
+ ) -> ActiveTask:
582
+ """Clear the active task by deleting the current session context file."""
583
+ context_key = resolve_context_key(platform_input, platform)
584
+ if not context_key:
585
+ return ActiveTask(None, "none")
586
+
587
+ previous = resolve_active_task(repo_root, platform_input, platform)
588
+ context_path = _context_path(repo_root, context_key)
589
+ if context_path.is_file():
590
+ _remove_file(context_path)
591
+ return previous
592
+
593
+
594
+ def clear_task_from_sessions(task_path: str, repo_root: Path) -> int:
595
+ """Delete all session runtime files that point at a task."""
596
+ target = _canonical_task_ref(task_path, repo_root) or normalize_task_ref(task_path)
597
+ if not target:
598
+ return 0
599
+
600
+ cleared = 0
601
+ sessions_dir = _runtime_sessions_dir(repo_root)
602
+ if not sessions_dir.is_dir():
603
+ return cleared
604
+
605
+ for session_path in sessions_dir.glob("*.json"):
606
+ context = _read_json(session_path) or {}
607
+ current = _string_value(context.get("current_task"))
608
+ if not current:
609
+ continue
610
+ current_ref = _canonical_task_ref(current, repo_root) or normalize_task_ref(current)
611
+ if current_ref != target:
612
+ continue
613
+ if session_path.is_file() and _remove_file(session_path):
614
+ cleared += 1
615
+
616
+ return cleared
617
+
618
+
619
+ def get_current_task_source(
620
+ repo_root: Path,
621
+ platform_input: dict[str, Any] | None = None,
622
+ platform: str | None = None,
623
+ ) -> tuple[str, str | None, str | None]:
624
+ """Return (`source_type`, `context_key`, `task_path`) for compatibility."""
625
+ active = resolve_active_task(repo_root, platform_input, platform)
626
+ return active.source_type, active.context_key, active.task_path