@blulotus/trellis 0.7.0 → 0.7.2

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 (343) hide show
  1. package/README.md +2 -2
  2. package/dist/cli/index.js +2 -29
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/commands/init.d.ts +0 -22
  5. package/dist/commands/init.d.ts.map +1 -1
  6. package/dist/commands/init.js +5 -12
  7. package/dist/commands/init.js.map +1 -1
  8. package/dist/commands/mem.d.ts +2 -2
  9. package/dist/commands/mem.d.ts.map +1 -1
  10. package/dist/commands/mem.js +7 -40
  11. package/dist/commands/mem.js.map +1 -1
  12. package/dist/commands/uninstall.d.ts +1 -1
  13. package/dist/commands/uninstall.d.ts.map +1 -1
  14. package/dist/commands/uninstall.js +4 -34
  15. package/dist/commands/uninstall.js.map +1 -1
  16. package/dist/commands/update.d.ts.map +1 -1
  17. package/dist/commands/update.js +2 -28
  18. package/dist/commands/update.js.map +1 -1
  19. package/dist/configurators/index.d.ts.map +1 -1
  20. package/dist/configurators/index.js +7 -73
  21. package/dist/configurators/index.js.map +1 -1
  22. package/dist/configurators/shared.d.ts +18 -70
  23. package/dist/configurators/shared.d.ts.map +1 -1
  24. package/dist/configurators/shared.js +20 -299
  25. package/dist/configurators/shared.js.map +1 -1
  26. package/dist/configurators/workflow.d.ts +0 -14
  27. package/dist/configurators/workflow.d.ts.map +1 -1
  28. package/dist/configurators/workflow.js +1 -37
  29. package/dist/configurators/workflow.js.map +1 -1
  30. package/dist/migrations/manifests/0.1.9.json +0 -12
  31. package/dist/migrations/manifests/0.2.14.json +0 -84
  32. package/dist/migrations/manifests/0.3.0-beta.0.json +0 -87
  33. package/dist/migrations/manifests/0.3.4.json +1 -13
  34. package/dist/migrations/manifests/0.4.0-beta.1.json +24 -176
  35. package/dist/migrations/manifests/0.5.0-beta.0.json +67 -1203
  36. package/dist/migrations/manifests/0.5.0-beta.15.json +0 -96
  37. package/dist/migrations/manifests/0.5.0-beta.5.json +0 -168
  38. package/dist/migrations/manifests/0.5.0-beta.9.json +0 -20
  39. package/dist/migrations/manifests/0.6.0-beta.23.json +0 -66
  40. package/dist/migrations/manifests/0.6.3.json +1 -16
  41. package/dist/migrations/manifests/0.6.6.json +1 -9
  42. package/dist/migrations/manifests/0.7.0.json +9 -0
  43. package/dist/migrations/manifests/0.7.1.json +9 -0
  44. package/dist/migrations/manifests/0.7.2.json +9 -0
  45. package/dist/migrations/manifests/0.8.0.json +9 -0
  46. package/dist/templates/codex/hooks/session-start.py +37 -13
  47. package/dist/templates/codex/hooks.json +5 -0
  48. package/dist/templates/common/bundled-skills/trellis-meta/SKILL.md +5 -5
  49. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-agents.md +0 -10
  50. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-hooks.md +1 -1
  51. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-skills-or-commands.md +1 -13
  52. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/overview.md +2 -2
  53. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/bundled-skills.md +9 -28
  54. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/generated-files.md +5 -5
  55. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/overview.md +1 -1
  56. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/agents.md +1 -17
  57. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/hooks-and-settings.md +4 -12
  58. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/overview.md +6 -6
  59. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/platform-map.md +5 -75
  60. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/skills-and-commands.md +0 -16
  61. package/dist/templates/common/bundled-skills/trellis-session-insight/SKILL.md +1 -1
  62. package/dist/templates/common/bundled-skills/trellis-session-insight/references/cli-quick-reference.md +2 -3
  63. package/dist/templates/common/commands/continue.md +24 -4
  64. package/dist/templates/common/commands/finish-work.md +19 -9
  65. package/dist/templates/common/commands/start.md +38 -29
  66. package/dist/templates/extract.d.ts +0 -10
  67. package/dist/templates/extract.d.ts.map +1 -1
  68. package/dist/templates/extract.js +0 -24
  69. package/dist/templates/extract.js.map +1 -1
  70. package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +7 -9
  71. package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +4 -8
  72. package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +5 -5
  73. package/dist/templates/shared-hooks/index.d.ts +11 -43
  74. package/dist/templates/shared-hooks/index.d.ts.map +1 -1
  75. package/dist/templates/shared-hooks/index.js +9 -86
  76. package/dist/templates/shared-hooks/index.js.map +1 -1
  77. package/dist/templates/shared-hooks/inject-spec-context.py +1 -1
  78. package/dist/templates/shared-hooks/inject-subagent-context.py +23 -85
  79. package/dist/templates/shared-hooks/inject-workflow-state.py +56 -86
  80. package/dist/templates/shared-hooks/session-start.py +76 -98
  81. package/dist/templates/trellis/config.yaml +8 -8
  82. package/dist/templates/trellis/index.d.ts +1 -4
  83. package/dist/templates/trellis/index.d.ts.map +1 -1
  84. package/dist/templates/trellis/index.js +1 -5
  85. package/dist/templates/trellis/index.js.map +1 -1
  86. package/dist/templates/trellis/scripts/add_session.py +12 -11
  87. package/dist/templates/trellis/scripts/common/__init__.py +2 -0
  88. package/dist/templates/trellis/scripts/common/active_task.py +80 -152
  89. package/dist/templates/trellis/scripts/common/config.py +7 -7
  90. package/dist/templates/trellis/scripts/common/git_context.py +1 -1
  91. package/dist/templates/trellis/scripts/common/session_context.py +2 -2
  92. package/dist/templates/trellis/scripts/common/spec_inject.py +2 -2
  93. package/dist/templates/trellis/scripts/common/task_store.py +8 -28
  94. package/dist/templates/trellis/scripts/common/workflow_phase.py +4 -8
  95. package/dist/templates/trellis/scripts/get_context.py +2 -2
  96. package/dist/templates/trellis/scripts/init_developer.py +1 -1
  97. package/dist/templates/trellis/scripts/task.py +90 -57
  98. package/dist/templates/trellis/workflow.md +44 -66
  99. package/dist/types/ai-tools.d.ts +10 -10
  100. package/dist/types/ai-tools.d.ts.map +1 -1
  101. package/dist/types/ai-tools.js +3 -434
  102. package/dist/types/ai-tools.js.map +1 -1
  103. package/dist/utils/uninstall-scrubbers.d.ts +3 -18
  104. package/dist/utils/uninstall-scrubbers.d.ts.map +1 -1
  105. package/dist/utils/uninstall-scrubbers.js +24 -154
  106. package/dist/utils/uninstall-scrubbers.js.map +1 -1
  107. package/package.json +2 -2
  108. package/dist/configurators/antigravity.d.ts +0 -7
  109. package/dist/configurators/antigravity.d.ts.map +0 -1
  110. package/dist/configurators/antigravity.js +0 -11
  111. package/dist/configurators/antigravity.js.map +0 -1
  112. package/dist/configurators/codebuddy.d.ts +0 -10
  113. package/dist/configurators/codebuddy.d.ts.map +0 -1
  114. package/dist/configurators/codebuddy.js +0 -24
  115. package/dist/configurators/codebuddy.js.map +0 -1
  116. package/dist/configurators/copilot.d.ts +0 -14
  117. package/dist/configurators/copilot.d.ts.map +0 -1
  118. package/dist/configurators/copilot.js +0 -46
  119. package/dist/configurators/copilot.js.map +0 -1
  120. package/dist/configurators/cursor.d.ts +0 -10
  121. package/dist/configurators/cursor.d.ts.map +0 -1
  122. package/dist/configurators/cursor.js +0 -23
  123. package/dist/configurators/cursor.js.map +0 -1
  124. package/dist/configurators/devin.d.ts +0 -8
  125. package/dist/configurators/devin.d.ts.map +0 -1
  126. package/dist/configurators/devin.js +0 -12
  127. package/dist/configurators/devin.js.map +0 -1
  128. package/dist/configurators/droid.d.ts +0 -10
  129. package/dist/configurators/droid.d.ts.map +0 -1
  130. package/dist/configurators/droid.js +0 -24
  131. package/dist/configurators/droid.js.map +0 -1
  132. package/dist/configurators/dsh.d.ts +0 -26
  133. package/dist/configurators/dsh.d.ts.map +0 -1
  134. package/dist/configurators/dsh.js +0 -76
  135. package/dist/configurators/dsh.js.map +0 -1
  136. package/dist/configurators/gemini.d.ts +0 -18
  137. package/dist/configurators/gemini.d.ts.map +0 -1
  138. package/dist/configurators/gemini.js +0 -39
  139. package/dist/configurators/gemini.js.map +0 -1
  140. package/dist/configurators/grok.d.ts +0 -17
  141. package/dist/configurators/grok.d.ts.map +0 -1
  142. package/dist/configurators/grok.js +0 -38
  143. package/dist/configurators/grok.js.map +0 -1
  144. package/dist/configurators/kilo.d.ts +0 -7
  145. package/dist/configurators/kilo.d.ts.map +0 -1
  146. package/dist/configurators/kilo.js +0 -11
  147. package/dist/configurators/kilo.js.map +0 -1
  148. package/dist/configurators/kimi.d.ts +0 -26
  149. package/dist/configurators/kimi.d.ts.map +0 -1
  150. package/dist/configurators/kimi.js +0 -74
  151. package/dist/configurators/kimi.js.map +0 -1
  152. package/dist/configurators/kiro.d.ts +0 -11
  153. package/dist/configurators/kiro.d.ts.map +0 -1
  154. package/dist/configurators/kiro.js +0 -30
  155. package/dist/configurators/kiro.js.map +0 -1
  156. package/dist/configurators/omp.d.ts +0 -6
  157. package/dist/configurators/omp.d.ts.map +0 -1
  158. package/dist/configurators/omp.js +0 -28
  159. package/dist/configurators/omp.js.map +0 -1
  160. package/dist/configurators/opencode.d.ts +0 -5
  161. package/dist/configurators/opencode.d.ts.map +0 -1
  162. package/dist/configurators/opencode.js +0 -84
  163. package/dist/configurators/opencode.js.map +0 -1
  164. package/dist/configurators/pi.d.ts +0 -5
  165. package/dist/configurators/pi.d.ts.map +0 -1
  166. package/dist/configurators/pi.js +0 -39
  167. package/dist/configurators/pi.js.map +0 -1
  168. package/dist/configurators/qoder.d.ts +0 -12
  169. package/dist/configurators/qoder.d.ts.map +0 -1
  170. package/dist/configurators/qoder.js +0 -30
  171. package/dist/configurators/qoder.js.map +0 -1
  172. package/dist/configurators/reasonix.d.ts +0 -17
  173. package/dist/configurators/reasonix.d.ts.map +0 -1
  174. package/dist/configurators/reasonix.js +0 -37
  175. package/dist/configurators/reasonix.js.map +0 -1
  176. package/dist/configurators/snow.d.ts +0 -25
  177. package/dist/configurators/snow.d.ts.map +0 -1
  178. package/dist/configurators/snow.js +0 -69
  179. package/dist/configurators/snow.js.map +0 -1
  180. package/dist/configurators/trae.d.ts +0 -16
  181. package/dist/configurators/trae.d.ts.map +0 -1
  182. package/dist/configurators/trae.js +0 -34
  183. package/dist/configurators/trae.js.map +0 -1
  184. package/dist/configurators/zcode.d.ts +0 -23
  185. package/dist/configurators/zcode.d.ts.map +0 -1
  186. package/dist/configurators/zcode.js +0 -63
  187. package/dist/configurators/zcode.js.map +0 -1
  188. package/dist/templates/codebuddy/agents/trellis-check.md +0 -115
  189. package/dist/templates/codebuddy/agents/trellis-implement.md +0 -115
  190. package/dist/templates/codebuddy/agents/trellis-research.md +0 -137
  191. package/dist/templates/codebuddy/index.d.ts +0 -15
  192. package/dist/templates/codebuddy/index.d.ts.map +0 -1
  193. package/dist/templates/codebuddy/index.js +0 -15
  194. package/dist/templates/codebuddy/index.js.map +0 -1
  195. package/dist/templates/codebuddy/settings.json +0 -69
  196. package/dist/templates/copilot/copilot-instructions.md +0 -11
  197. package/dist/templates/copilot/hooks/session-start.py +0 -564
  198. package/dist/templates/copilot/hooks.json +0 -19
  199. package/dist/templates/copilot/index.d.ts +0 -28
  200. package/dist/templates/copilot/index.d.ts.map +0 -1
  201. package/dist/templates/copilot/index.js +0 -61
  202. package/dist/templates/copilot/index.js.map +0 -1
  203. package/dist/templates/copilot/prompts/before-dev.prompt.md +0 -39
  204. package/dist/templates/copilot/prompts/brainstorm.prompt.md +0 -173
  205. package/dist/templates/copilot/prompts/break-loop.prompt.md +0 -129
  206. package/dist/templates/copilot/prompts/check-cross-layer.prompt.md +0 -170
  207. package/dist/templates/copilot/prompts/check.prompt.md +0 -110
  208. package/dist/templates/copilot/prompts/create-command.prompt.md +0 -116
  209. package/dist/templates/copilot/prompts/finish-work.prompt.md +0 -99
  210. package/dist/templates/copilot/prompts/integrate-skill.prompt.md +0 -223
  211. package/dist/templates/copilot/prompts/onboard.prompt.md +0 -362
  212. package/dist/templates/copilot/prompts/parallel.prompt.md +0 -204
  213. package/dist/templates/copilot/prompts/record-session.prompt.md +0 -66
  214. package/dist/templates/copilot/prompts/start.prompt.md +0 -63
  215. package/dist/templates/copilot/prompts/update-spec.prompt.md +0 -358
  216. package/dist/templates/cursor/agents/trellis-check.md +0 -114
  217. package/dist/templates/cursor/agents/trellis-implement.md +0 -114
  218. package/dist/templates/cursor/agents/trellis-research.md +0 -136
  219. package/dist/templates/cursor/hooks.json +0 -24
  220. package/dist/templates/cursor/index.d.ts +0 -13
  221. package/dist/templates/cursor/index.d.ts.map +0 -1
  222. package/dist/templates/cursor/index.js +0 -13
  223. package/dist/templates/cursor/index.js.map +0 -1
  224. package/dist/templates/droid/droids/trellis-check.md +0 -107
  225. package/dist/templates/droid/droids/trellis-implement.md +0 -107
  226. package/dist/templates/droid/droids/trellis-research.md +0 -137
  227. package/dist/templates/droid/index.d.ts +0 -15
  228. package/dist/templates/droid/index.d.ts.map +0 -1
  229. package/dist/templates/droid/index.js +0 -15
  230. package/dist/templates/droid/index.js.map +0 -1
  231. package/dist/templates/droid/settings.json +0 -69
  232. package/dist/templates/dsh/DSH.md +0 -80
  233. package/dist/templates/dsh/agents/trellis-check.md +0 -99
  234. package/dist/templates/dsh/agents/trellis-implement.md +0 -106
  235. package/dist/templates/dsh/agents/trellis-research.md +0 -134
  236. package/dist/templates/dsh/index.d.ts +0 -22
  237. package/dist/templates/dsh/index.d.ts.map +0 -1
  238. package/dist/templates/dsh/index.js +0 -27
  239. package/dist/templates/dsh/index.js.map +0 -1
  240. package/dist/templates/gemini/agents/trellis-check.md +0 -107
  241. package/dist/templates/gemini/agents/trellis-implement.md +0 -107
  242. package/dist/templates/gemini/agents/trellis-research.md +0 -136
  243. package/dist/templates/gemini/index.d.ts +0 -13
  244. package/dist/templates/gemini/index.d.ts.map +0 -1
  245. package/dist/templates/gemini/index.js +0 -13
  246. package/dist/templates/gemini/index.js.map +0 -1
  247. package/dist/templates/gemini/settings.json +0 -40
  248. package/dist/templates/grok/agents/trellis-check.md +0 -106
  249. package/dist/templates/grok/agents/trellis-implement.md +0 -121
  250. package/dist/templates/grok/agents/trellis-research.md +0 -146
  251. package/dist/templates/grok/index.d.ts +0 -16
  252. package/dist/templates/grok/index.d.ts.map +0 -1
  253. package/dist/templates/grok/index.js +0 -19
  254. package/dist/templates/grok/index.js.map +0 -1
  255. package/dist/templates/kimi/agents/trellis-check.md +0 -104
  256. package/dist/templates/kimi/agents/trellis-implement.md +0 -120
  257. package/dist/templates/kimi/agents/trellis-research.md +0 -144
  258. package/dist/templates/kimi/index.d.ts +0 -20
  259. package/dist/templates/kimi/index.d.ts.map +0 -1
  260. package/dist/templates/kimi/index.js +0 -23
  261. package/dist/templates/kimi/index.js.map +0 -1
  262. package/dist/templates/kiro/agents/trellis-check.json +0 -26
  263. package/dist/templates/kiro/agents/trellis-implement.json +0 -26
  264. package/dist/templates/kiro/agents/trellis-research.json +0 -30
  265. package/dist/templates/kiro/agents/trellis.json +0 -34
  266. package/dist/templates/kiro/hooks/trellis-workflow-state.kiro.hook +0 -14
  267. package/dist/templates/kiro/index.d.ts +0 -32
  268. package/dist/templates/kiro/index.d.ts.map +0 -1
  269. package/dist/templates/kiro/index.js +0 -28
  270. package/dist/templates/kiro/index.js.map +0 -1
  271. package/dist/templates/omp/agents/trellis-check.md +0 -41
  272. package/dist/templates/omp/agents/trellis-implement.md +0 -55
  273. package/dist/templates/omp/agents/trellis-research.md +0 -30
  274. package/dist/templates/omp/extensions/trellis/index.ts.txt +0 -592
  275. package/dist/templates/omp/index.d.ts +0 -4
  276. package/dist/templates/omp/index.d.ts.map +0 -1
  277. package/dist/templates/omp/index.js +0 -9
  278. package/dist/templates/omp/index.js.map +0 -1
  279. package/dist/templates/opencode/agents/trellis-check.md +0 -122
  280. package/dist/templates/opencode/agents/trellis-implement.md +0 -123
  281. package/dist/templates/opencode/agents/trellis-research.md +0 -145
  282. package/dist/templates/opencode/lib/context-visibility.js +0 -86
  283. package/dist/templates/opencode/lib/session-utils.js +0 -526
  284. package/dist/templates/opencode/lib/trellis-context.js +0 -627
  285. package/dist/templates/opencode/package.json +0 -5
  286. package/dist/templates/opencode/plugins/inject-spec-context.js +0 -121
  287. package/dist/templates/opencode/plugins/inject-subagent-context.js +0 -569
  288. package/dist/templates/opencode/plugins/inject-workflow-state.js +0 -340
  289. package/dist/templates/opencode/plugins/session-start.js +0 -74
  290. package/dist/templates/pi/agents/trellis-check.md +0 -37
  291. package/dist/templates/pi/agents/trellis-implement.md +0 -52
  292. package/dist/templates/pi/agents/trellis-research.md +0 -25
  293. package/dist/templates/pi/extensions/trellis/index.ts.txt +0 -2033
  294. package/dist/templates/pi/index.d.ts +0 -5
  295. package/dist/templates/pi/index.d.ts.map +0 -1
  296. package/dist/templates/pi/index.js +0 -12
  297. package/dist/templates/pi/index.js.map +0 -1
  298. package/dist/templates/pi/settings.json +0 -9
  299. package/dist/templates/qoder/agents/trellis-check.md +0 -108
  300. package/dist/templates/qoder/agents/trellis-implement.md +0 -108
  301. package/dist/templates/qoder/agents/trellis-research.md +0 -137
  302. package/dist/templates/qoder/index.d.ts +0 -15
  303. package/dist/templates/qoder/index.d.ts.map +0 -1
  304. package/dist/templates/qoder/index.js +0 -15
  305. package/dist/templates/qoder/index.js.map +0 -1
  306. package/dist/templates/qoder/settings.json +0 -59
  307. package/dist/templates/reasonix/agents/trellis-check.md +0 -36
  308. package/dist/templates/reasonix/agents/trellis-implement.md +0 -51
  309. package/dist/templates/reasonix/index.d.ts +0 -13
  310. package/dist/templates/reasonix/index.d.ts.map +0 -1
  311. package/dist/templates/reasonix/index.js +0 -16
  312. package/dist/templates/reasonix/index.js.map +0 -1
  313. package/dist/templates/shared-hooks/inject-shell-session-context.py +0 -292
  314. package/dist/templates/snow/SNOW.md +0 -86
  315. package/dist/templates/snow/agents/trellis-check.md +0 -136
  316. package/dist/templates/snow/agents/trellis-implement.md +0 -158
  317. package/dist/templates/snow/agents/trellis-research.md +0 -114
  318. package/dist/templates/snow/hooks/beforeSubAgentStart.json +0 -15
  319. package/dist/templates/snow/hooks/onSessionStart.json +0 -15
  320. package/dist/templates/snow/hooks/onUserMessage.json +0 -15
  321. package/dist/templates/snow/hooks/write-trellis-context.py +0 -644
  322. package/dist/templates/snow/index.d.ts +0 -26
  323. package/dist/templates/snow/index.d.ts.map +0 -1
  324. package/dist/templates/snow/index.js +0 -36
  325. package/dist/templates/snow/index.js.map +0 -1
  326. package/dist/templates/trae/agents/trellis-check.md +0 -108
  327. package/dist/templates/trae/agents/trellis-implement.md +0 -108
  328. package/dist/templates/trae/agents/trellis-research.md +0 -137
  329. package/dist/templates/trae/hooks.json +0 -39
  330. package/dist/templates/trae/index.d.ts +0 -15
  331. package/dist/templates/trae/index.d.ts.map +0 -1
  332. package/dist/templates/trae/index.js +0 -15
  333. package/dist/templates/trae/index.js.map +0 -1
  334. package/dist/templates/trellis/gitattributes.txt +0 -9
  335. package/dist/templates/trellis/scripts/common/cli_adapter.py +0 -982
  336. package/dist/templates/zcode/agents/trellis-check.md +0 -110
  337. package/dist/templates/zcode/agents/trellis-implement.md +0 -116
  338. package/dist/templates/zcode/agents/trellis-research.md +0 -133
  339. package/dist/templates/zcode/config.json +0 -52
  340. package/dist/templates/zcode/index.d.ts +0 -25
  341. package/dist/templates/zcode/index.d.ts.map +0 -1
  342. package/dist/templates/zcode/index.js +0 -29
  343. package/dist/templates/zcode/index.js.map +0 -1
@@ -1,592 +0,0 @@
1
- import type { ExtensionAPI } from "@oh-my-pi/pi-coding-agent";
2
- import { existsSync, lstatSync, readFileSync, readdirSync, realpathSync } from "node:fs";
3
- import { join, dirname, isAbsolute, relative, resolve } from "node:path";
4
- import { spawnSync } from "node:child_process";
5
- import { createHash } from "node:crypto";
6
-
7
- // ---------------------------------------------------------------------------
8
- // Project root detection
9
- // ---------------------------------------------------------------------------
10
-
11
- function findProjectRoot(startDir: string): string | null {
12
- let current = startDir;
13
- while (true) {
14
- if (existsSync(join(current, ".trellis"))) return current;
15
- const parent = dirname(current);
16
- if (parent === current) break;
17
- current = parent;
18
- }
19
- return null;
20
- }
21
-
22
- // ---------------------------------------------------------------------------
23
- // Session identity helpers (mirrors Python _sanitize_key / _hash_value / _context_key)
24
- // ---------------------------------------------------------------------------
25
-
26
- function sanitizeKey(raw: string): string {
27
- const safe = raw.trim().replace(/[^A-Za-z0-9._-]+/g, "_").replace(/^[._-]+|[._-]+$/g, "");
28
- return safe ? safe.slice(0, 160) : "";
29
- }
30
-
31
- function hashValue(raw: string): string {
32
- return createHash("sha256").update(raw).digest("hex").slice(0, 24);
33
- }
34
-
35
- function buildContextKey(platformName: string, kind: string, value: string): string {
36
- if (kind === "transcript") {
37
- return `${platformName}_transcript_${hashValue(value)}`;
38
- }
39
- const safeValue = sanitizeKey(value);
40
- return safeValue ? `${platformName}_${safeValue}` : `${platformName}_${hashValue(value)}`;
41
- }
42
-
43
- function deriveContextKey(ctx?: { sessionManager?: { getSessionId?: () => string | undefined; getSessionFile?: () => string | undefined } }): string | null {
44
- const sessionId = ctx?.sessionManager?.getSessionId?.();
45
- if (sessionId) {
46
- return buildContextKey("omp", "session", sessionId);
47
- }
48
- const sessionFile = ctx?.sessionManager?.getSessionFile?.();
49
- if (sessionFile) {
50
- return buildContextKey("omp", "transcript", sessionFile);
51
- }
52
- const override = process.env.TRELLIS_CONTEXT_ID?.trim();
53
- return override ? sanitizeKey(override) || hashValue(override) : null;
54
- }
55
-
56
- function isInsideRoot(root: string, candidate: string): boolean {
57
- const rel = relative(root, candidate);
58
- return rel === "" || (rel !== ".." && !rel.startsWith("../") && !rel.startsWith("..\\") && !isAbsolute(rel));
59
- }
60
-
61
- // ---------------------------------------------------------------------------
62
- // Trusted context roots (mirrors packages/cli/src/commands/channel/context-trust.ts;
63
- // standalone copy since templates don't import from the CLI package).
64
- // ---------------------------------------------------------------------------
65
-
66
- const AUTO_TRUST_ENTRIES = ["tasks", "workspace"];
67
-
68
- function stripTrustValue(s: string): string {
69
- return s.trim().replace(/\s*#.*$/, "").trim().replace(/^['"]|['"]$/g, "");
70
- }
71
-
72
- function parseChannelTrustSection(content: string): { trustedDirs: string[]; autoTrustSymlinks?: boolean } {
73
- const lines = content.split("\n");
74
- const trustedDirs: string[] = [];
75
- let autoTrustSymlinks: boolean | undefined;
76
- let inChannel = false;
77
- let inList = false;
78
-
79
- for (const raw of lines) {
80
- const line = raw.replace(/\r$/, "");
81
- const trimmed = line.trimEnd();
82
- if (trimmed.trim().startsWith("#")) continue;
83
-
84
- if (/^channel:\s*$/.test(trimmed)) {
85
- inChannel = true;
86
- inList = false;
87
- continue;
88
- }
89
- if (!inChannel) continue;
90
-
91
- if (trimmed.trim() !== "" && /^\S/.test(line)) {
92
- inChannel = false;
93
- inList = false;
94
- continue;
95
- }
96
- if (trimmed.trim() === "") continue;
97
-
98
- if (inList) {
99
- const item = trimmed.match(/^ {4}-\s*(.+)$/);
100
- if (item) {
101
- const val = stripTrustValue(item[1]!);
102
- if (val) trustedDirs.push(val);
103
- continue;
104
- }
105
- inList = false;
106
- }
107
-
108
- if (/^ {2}trusted_context_dirs:\s*$/.test(trimmed)) {
109
- inList = true;
110
- continue;
111
- }
112
-
113
- const boolMatch = trimmed.match(/^ {2}auto_trust_trellis_symlinks:\s*(.+)$/);
114
- if (boolMatch) {
115
- const val = stripTrustValue(boolMatch[1]!).toLowerCase();
116
- if (val === "false") autoTrustSymlinks = false;
117
- else if (val === "true") autoTrustSymlinks = true;
118
- else process.stderr.write(`[channel] channel.auto_trust_trellis_symlinks: invalid value '${val}', ignoring\n`);
119
- continue;
120
- }
121
- }
122
-
123
- return { trustedDirs, autoTrustSymlinks };
124
- }
125
-
126
- function resolveTrustedRoots(projectRoot: string): string[] {
127
- const configPath = join(projectRoot, ".trellis", "config.yaml");
128
- let config: { trustedDirs: string[]; autoTrustSymlinks?: boolean } = { trustedDirs: [] };
129
- if (existsSync(configPath)) {
130
- try {
131
- config = parseChannelTrustSection(readFileSync(configPath, "utf-8"));
132
- } catch {
133
- // ignore
134
- }
135
- }
136
-
137
- const roots: string[] = [];
138
- for (const entry of config.trustedDirs) {
139
- try {
140
- roots.push(realpathSync(resolve(projectRoot, entry)));
141
- } catch {
142
- // entry not found or invalid — skip
143
- }
144
- }
145
-
146
- if (config.autoTrustSymlinks !== false) {
147
- for (const entryName of AUTO_TRUST_ENTRIES) {
148
- const entryPath = join(projectRoot, ".trellis", entryName);
149
- try {
150
- if (lstatSync(entryPath).isSymbolicLink()) {
151
- roots.push(realpathSync(entryPath));
152
- }
153
- } catch {
154
- // missing / broken symlink — nothing to trust
155
- }
156
- }
157
- }
158
-
159
- return [...new Set(roots)];
160
- }
161
-
162
- function resolveProjectFile(
163
- projectRoot: string,
164
- file: string,
165
- trustedRoots: string[],
166
- ): string | null {
167
- try {
168
- const rootReal = realpathSync(projectRoot);
169
- const targetReal = realpathSync(resolve(projectRoot, file));
170
- if (isInsideRoot(rootReal, targetReal)) return targetReal;
171
- if (trustedRoots.some((root) => isInsideRoot(root, targetReal))) return targetReal;
172
- return null;
173
- } catch {
174
- return null;
175
- }
176
- }
177
-
178
- // ---------------------------------------------------------------------------
179
- // Active task resolution
180
- // ---------------------------------------------------------------------------
181
-
182
- function resolveActiveTaskStatus(
183
- projectRoot: string,
184
- contextKey: string | null,
185
- ): { status: string; taskDir: string | null; taskTitle: string | null } {
186
- const sessionsDir = join(projectRoot, ".trellis", ".runtime", "sessions");
187
- if (!existsSync(sessionsDir)) return { status: "no_task", taskDir: null, taskTitle: null };
188
-
189
- // --- 通过 context key 解析 session 文件 ---
190
- let sessionFilePath: string | null = null;
191
-
192
- if (contextKey) {
193
- const candidate = join(sessionsDir, `${contextKey}.json`);
194
- if (existsSync(candidate)) {
195
- sessionFilePath = candidate;
196
- } else {
197
- return { status: "no_task", taskDir: null, taskTitle: null };
198
- }
199
- } else {
200
- // No identity: use single-session fallback only when there is exactly one session file.
201
- let sessionFiles: string[];
202
- try {
203
- sessionFiles = readdirSync(sessionsDir).filter((f) => f.endsWith(".json"));
204
- } catch {
205
- return { status: "no_task", taskDir: null, taskTitle: null };
206
- }
207
- if (sessionFiles.length === 1) {
208
- sessionFilePath = join(sessionsDir, sessionFiles[0]);
209
- } else {
210
- return { status: "no_task", taskDir: null, taskTitle: null };
211
- }
212
- }
213
-
214
- // --- 读取 session 数据 ---
215
- let sessionData: Record<string, unknown>;
216
- try {
217
- sessionData = JSON.parse(readFileSync(sessionFilePath, "utf-8"));
218
- } catch {
219
- return { status: "no_task", taskDir: null, taskTitle: null };
220
- }
221
-
222
- const currentTask = sessionData.current_task;
223
- if (typeof currentTask !== "string" || !currentTask)
224
- return { status: "no_task", taskDir: null, taskTitle: null };
225
-
226
- // Same jail the jsonl-referenced files already go through below. `task.py`
227
- // now refuses to store a ref that leaves the project, but a session file
228
- // written before that fix can still hold one, and `trellis update` does not
229
- // rewrite session files — so a poisoned pointer outlives the upgrade that
230
- // closed the writer.
231
- const taskDir = resolveProjectFile(projectRoot, currentTask, resolveTrustedRoots(projectRoot));
232
- if (!taskDir) return { status: "no_task", taskDir: null, taskTitle: null };
233
- const taskJsonPath = join(taskDir, "task.json");
234
- if (!existsSync(taskJsonPath)) return { status: "no_task", taskDir: null, taskTitle: null };
235
-
236
- let taskData: Record<string, unknown>;
237
- try {
238
- taskData = JSON.parse(readFileSync(taskJsonPath, "utf-8"));
239
- } catch {
240
- return { status: "no_task", taskDir: null, taskTitle: null };
241
- }
242
-
243
- return {
244
- status: typeof taskData.status === "string" ? taskData.status : "planning",
245
- taskDir,
246
- taskTitle: typeof taskData.title === "string" ? taskData.title : null,
247
- };
248
- }
249
-
250
- // ---------------------------------------------------------------------------
251
- // Session context — spawns get_context.py default mode (same as Claude hook)
252
- // ---------------------------------------------------------------------------
253
-
254
- const SESSION_CONTEXT_TIMEOUT_MS = 5000;
255
-
256
- function buildSessionContext(projectRoot: string, contextKey: string | null): string {
257
- const script = join(projectRoot, ".trellis", "scripts", "get_context.py");
258
- if (!existsSync(script)) return "";
259
-
260
- try {
261
- const result = spawnSync("python3", [script], {
262
- cwd: projectRoot,
263
- encoding: "utf-8",
264
- env: contextKey
265
- ? { ...process.env, TRELLIS_CONTEXT_ID: contextKey }
266
- : process.env,
267
- timeout: SESSION_CONTEXT_TIMEOUT_MS,
268
- windowsHide: true,
269
- });
270
- if (result.status !== 0 || !result.stdout?.trim()) {
271
- return "";
272
- }
273
- return `<session-context>\n${result.stdout.trim()}\n</session-context>`;
274
- } catch {
275
- return "";
276
- }
277
- }
278
-
279
- // ---------------------------------------------------------------------------
280
- // Task context — prd.md, info.md, and jsonl-referenced spec/research files
281
- // ---------------------------------------------------------------------------
282
-
283
- type AgentType = "trellis-implement" | "trellis-check" | "trellis-research" | null;
284
-
285
- function buildTaskContext(projectRoot: string, taskDir: string, agentType?: AgentType): string {
286
- const parts: string[] = [];
287
- // Resolved once per call (not per referenced file) — avoids re-parsing
288
- // config.yaml for every jsonl row.
289
- const trustedRoots = resolveTrustedRoots(projectRoot);
290
-
291
- // prd.md and info.md — always included
292
- let prd = "";
293
- try { prd = readFileSync(join(taskDir, "prd.md"), "utf-8"); } catch { }
294
- if (prd.trim()) parts.push(`## PRD\n\n${prd.trim()}`);
295
-
296
- let info = "";
297
- try { info = readFileSync(join(taskDir, "info.md"), "utf-8"); } catch { }
298
- if (info.trim()) parts.push(`## Info\n\n${info.trim()}`);
299
-
300
- // Determine which jsonl files to read based on agent type
301
- let jsonlNames: string[];
302
- if (agentType === "trellis-implement") {
303
- jsonlNames = ["implement.jsonl"];
304
- } else if (agentType === "trellis-check") {
305
- jsonlNames = ["check.jsonl"];
306
- } else if (agentType === "trellis-research") {
307
- jsonlNames = []; // research agent gets only prd + info
308
- } else {
309
- jsonlNames = ["implement.jsonl", "check.jsonl"]; // main session: all
310
- }
311
-
312
- for (const jsonlName of jsonlNames) {
313
- const jsonlPath = join(taskDir, jsonlName);
314
- if (!existsSync(jsonlPath)) continue;
315
-
316
- let lines: string[];
317
- try {
318
- lines = readFileSync(jsonlPath, "utf-8").split(/\r?\n/);
319
- } catch {
320
- continue;
321
- }
322
-
323
- const fileChunks: string[] = [];
324
- for (const line of lines) {
325
- const trimmed = line.trim();
326
- if (!trimmed) continue;
327
- try {
328
- const row = JSON.parse(trimmed) as Record<string, unknown>;
329
- const file = typeof row.file === "string" ? row.file.trim() : "";
330
- if (!file) continue;
331
- const targetPath = resolveProjectFile(projectRoot, file, trustedRoots);
332
- if (!targetPath) continue;
333
- let content = "";
334
- try { content = readFileSync(targetPath, "utf-8"); } catch { }
335
- if (content.trim()) {
336
- fileChunks.push(`### ${file}\n\n${content.trim()}`);
337
- }
338
- } catch {
339
- // seed rows and malformed lines are non-fatal
340
- }
341
- }
342
-
343
- if (fileChunks.length > 0) {
344
- parts.push(`## ${jsonlName}\n\n${fileChunks.join("\n\n---\n\n")}`);
345
- }
346
- }
347
-
348
- return parts.length > 0
349
- ? `<task-context>\n${parts.join("\n\n")}\n</task-context>`
350
- : "";
351
- }
352
-
353
- // ---------------------------------------------------------------------------
354
- // Per-turn cache — prevents redundant workflow-state resolution within a
355
- // single event cascade (input, before_agent_start, and context fire closely)
356
- // ---------------------------------------------------------------------------
357
-
358
- const SESSION_OVERVIEW_TEXT =
359
- "Trellis workflow system active. Use skills and agents as directed by the workflow state.";
360
-
361
- class TurnContextCache {
362
- private key: string | null = null;
363
- private timestamp = 0;
364
- private workflowMsg = "";
365
- private static readonly TTL_MS = 1500;
366
-
367
- get(projectRoot: string, contextKey: string | null): { workflowMsg: string } {
368
- const now = Date.now();
369
- const cacheKey = `${projectRoot}:${contextKey ?? ""}`;
370
- if (
371
- this.key === cacheKey &&
372
- now - this.timestamp < TurnContextCache.TTL_MS
373
- ) {
374
- return { workflowMsg: this.workflowMsg };
375
- }
376
-
377
- const { status } = resolveActiveTaskStatus(projectRoot, contextKey);
378
-
379
- const workflowPath = join(projectRoot, ".trellis", "workflow.md");
380
- let workflowMd = "";
381
- try { workflowMd = readFileSync(workflowPath, "utf-8"); } catch { }
382
-
383
- let workflowBody = "";
384
- if (workflowMd) {
385
- const blocks = parseWorkflowStateBlocks(workflowMd);
386
- const activeBlock = blocks.find((b) => b.status === status);
387
- if (activeBlock) {
388
- workflowBody = `[workflow-state:${activeBlock.status}]\n${activeBlock.content}\n[/workflow-state:${activeBlock.status}]`;
389
- }
390
- }
391
- if (!workflowBody) {
392
- workflowBody = "Refer to workflow.md for current step.";
393
- }
394
-
395
- this.workflowMsg = `<workflow-state>\n${workflowBody}\n</workflow-state>\n\n<session-overview>\n${SESSION_OVERVIEW_TEXT}\n</session-overview>`;
396
-
397
- this.key = cacheKey;
398
- this.timestamp = now;
399
- return { workflowMsg: this.workflowMsg };
400
- }
401
- }
402
-
403
- // ---------------------------------------------------------------------------
404
- // Workflow-state tag parsing
405
- // ---------------------------------------------------------------------------
406
-
407
- const WORKFLOW_STATE_RE =
408
- /\[workflow-state:([A-Za-z0-9_-]+)\]\s*\n([\s\S]*?)\n\s*\[\/workflow-state:\1\]/g;
409
-
410
- interface WorkflowStateBlock {
411
- status: string;
412
- content: string;
413
- }
414
-
415
- function parseWorkflowStateBlocks(markdown: string): WorkflowStateBlock[] {
416
- const blocks: WorkflowStateBlock[] = [];
417
- for (const match of markdown.matchAll(WORKFLOW_STATE_RE)) {
418
- blocks.push({
419
- status: match[1],
420
- content: match[2].trim(),
421
- });
422
- }
423
- return blocks;
424
- }
425
-
426
- // ---------------------------------------------------------------------------
427
- // Sub-agent detection
428
- // ---------------------------------------------------------------------------
429
-
430
- const TRELLIS_AGENTS = new Set(["trellis-implement", "trellis-check", "trellis-research"]);
431
-
432
- function detectAgentType(): AgentType {
433
- const blocked = process.env.PI_BLOCKED_AGENT;
434
- if (blocked && TRELLIS_AGENTS.has(blocked)) {
435
- return blocked as AgentType;
436
- }
437
- return null;
438
- }
439
-
440
- // ---------------------------------------------------------------------------
441
- // Extension entry point
442
- // ---------------------------------------------------------------------------
443
-
444
- export default function(pi: ExtensionAPI): void {
445
- let projectRoot: string | null = null;
446
- const turnCache = new TurnContextCache();
447
- const agentType = detectAgentType();
448
- const isSubAgent = agentType !== null;
449
-
450
- // Tracks compaction boundaries — context handler skips scanning when no
451
- // compaction has occurred since last injection.
452
- let lastCompactionTs = 0;
453
- let lastInjectionTs = 0;
454
-
455
- const rememberContextKey = (ctx?: { sessionManager?: { getSessionId?: () => string | undefined; getSessionFile?: () => string | undefined } }): string | null => {
456
- const key = deriveContextKey(ctx);
457
- if (!key) return null;
458
- return key;
459
- };
460
-
461
- pi.on("session_start", async (_event, ctx) => {
462
- projectRoot = findProjectRoot(ctx.cwd);
463
- const contextKey = rememberContextKey(ctx);
464
-
465
- if (!projectRoot) return;
466
-
467
- if (isSubAgent) {
468
- // Sub-agent: inject precise task context once
469
- const { taskDir } = resolveActiveTaskStatus(projectRoot, contextKey);
470
- if (taskDir) {
471
- const taskContext = buildTaskContext(projectRoot, taskDir, agentType);
472
- if (taskContext) {
473
- await pi.sendMessage({
474
- customType: "trellis-task-context",
475
- content: taskContext,
476
- display: false,
477
- });
478
- }
479
- }
480
- } else {
481
- // Main session: inject session context (global map) + task context
482
- const sessionContext = buildSessionContext(projectRoot, contextKey);
483
- if (sessionContext) {
484
- await pi.sendMessage({
485
- customType: "trellis-session-context",
486
- content: sessionContext,
487
- display: false,
488
- });
489
- }
490
-
491
- const { taskDir } = resolveActiveTaskStatus(projectRoot, contextKey);
492
- if (taskDir) {
493
- const taskContext = buildTaskContext(projectRoot, taskDir);
494
- if (taskContext) {
495
- await pi.sendMessage({
496
- customType: "trellis-task-context",
497
- content: taskContext,
498
- display: false,
499
- });
500
- }
501
- }
502
-
503
- ctx.ui.notify("Trellis workflow system available", "info");
504
- }
505
- });
506
-
507
- pi.on("session_before_compact", async () => {
508
- lastCompactionTs = Date.now();
509
- });
510
-
511
- pi.on("before_agent_start", async (_event, ctx) => {
512
- if (!projectRoot) {
513
- projectRoot = findProjectRoot(ctx.cwd);
514
- }
515
- if (!projectRoot) return;
516
- const contextKey = rememberContextKey(ctx);
517
-
518
- // Persistent injection: workflow state for this turn
519
- const cached = turnCache.get(projectRoot, contextKey);
520
- lastInjectionTs = Date.now();
521
-
522
- return {
523
- message: {
524
- customType: "trellis-workflow-state",
525
- content: cached.workflowMsg,
526
- display: false,
527
- },
528
- };
529
- });
530
-
531
- // context fires before EVERY LLM API call (including tool-use continuations
532
- // and post-compaction agent.continue() paths). Acts as a safety net when
533
- // before_agent_start's persisted message was removed by compaction.
534
- pi.on("context", async (event, ctx) => {
535
- if (!projectRoot) return;
536
- const contextKey = rememberContextKey(ctx);
537
-
538
- // Fast path: no compaction since last injection — message is still present
539
- if (lastInjectionTs > lastCompactionTs) return;
540
-
541
- const cached = turnCache.get(projectRoot, contextKey);
542
- if (!cached.workflowMsg) return;
543
-
544
- // Post-compaction: reverse-scan to confirm absence before injecting
545
- const messages = event.messages as { role?: string; customType?: string }[];
546
- for (let i = messages.length - 1; i >= 0; i--) {
547
- if (messages[i].role === "custom" && messages[i].customType === "trellis-workflow-state") {
548
- lastInjectionTs = Date.now();
549
- return;
550
- }
551
- }
552
-
553
- lastInjectionTs = Date.now();
554
- return {
555
- messages: [
556
- ...event.messages,
557
- {
558
- role: "custom" as const,
559
- customType: "trellis-workflow-state",
560
- content: cached.workflowMsg,
561
- display: false,
562
- timestamp: Date.now(),
563
- },
564
- ],
565
- };
566
- });
567
-
568
- // OMP passes Bash event.input through to the tool execution parameters, so
569
- // inject the session key through the shell-agnostic env field. An explicit
570
- // per-call value wins over the derived key.
571
- pi.on("tool_call", (event, ctx) => {
572
- if (event.toolName !== "bash") return;
573
- const contextKey = rememberContextKey(ctx);
574
- if (!contextKey) return;
575
- const input = event.input as { env?: Record<string, string> };
576
- input.env = {
577
- TRELLIS_CONTEXT_ID: contextKey,
578
- ...input.env,
579
- };
580
- });
581
-
582
- pi.on("input", async (_event, ctx) => {
583
- if (!projectRoot) {
584
- projectRoot = findProjectRoot(ctx.cwd);
585
- }
586
- // Resolve projectRoot on first input if session_start missed it
587
- if (!projectRoot) return;
588
- const contextKey = rememberContextKey(ctx);
589
- // Pre-warm the cache so before_agent_start and context can use it
590
- turnCache.get(projectRoot, contextKey);
591
- });
592
- }
@@ -1,4 +0,0 @@
1
- import type { AgentTemplate } from "../template-utils.js";
2
- export declare function getAllAgents(): AgentTemplate[];
3
- export declare function getExtensionTemplate(): string;
4
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/omp/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAI1D,wBAAgB,YAAY,IAAI,aAAa,EAAE,CAE9C;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C"}
@@ -1,9 +0,0 @@
1
- import { createTemplateReader } from "../template-utils.js";
2
- const { listMdAgents, readTemplate } = createTemplateReader(import.meta.url);
3
- export function getAllAgents() {
4
- return listMdAgents();
5
- }
6
- export function getExtensionTemplate() {
7
- return readTemplate("extensions/trellis/index.ts.txt");
8
- }
9
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/omp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAG5D,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,oBAAoB,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE7E,MAAM,UAAU,YAAY;IAC1B,OAAO,YAAY,EAAE,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO,YAAY,CAAC,iCAAiC,CAAC,CAAC;AACzD,CAAC"}