@blulotus/trellis 0.7.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (335) 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 -20
  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/migrations/manifests/0.1.9.json +0 -12
  27. package/dist/migrations/manifests/0.2.14.json +0 -84
  28. package/dist/migrations/manifests/0.3.0-beta.0.json +0 -87
  29. package/dist/migrations/manifests/0.3.4.json +1 -13
  30. package/dist/migrations/manifests/0.4.0-beta.1.json +24 -176
  31. package/dist/migrations/manifests/0.5.0-beta.0.json +67 -1203
  32. package/dist/migrations/manifests/0.5.0-beta.15.json +0 -96
  33. package/dist/migrations/manifests/0.5.0-beta.5.json +0 -168
  34. package/dist/migrations/manifests/0.5.0-beta.9.json +0 -20
  35. package/dist/migrations/manifests/0.6.0-beta.23.json +0 -66
  36. package/dist/migrations/manifests/0.6.3.json +1 -16
  37. package/dist/migrations/manifests/0.6.6.json +1 -9
  38. package/dist/migrations/manifests/0.7.0.json +9 -0
  39. package/dist/migrations/manifests/0.7.1.json +9 -0
  40. package/dist/migrations/manifests/0.8.0.json +9 -0
  41. package/dist/templates/codex/hooks/session-start.py +37 -13
  42. package/dist/templates/codex/hooks.json +5 -0
  43. package/dist/templates/common/bundled-skills/trellis-meta/SKILL.md +5 -5
  44. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-agents.md +0 -10
  45. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-hooks.md +1 -1
  46. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-skills-or-commands.md +1 -13
  47. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/overview.md +2 -2
  48. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/bundled-skills.md +9 -28
  49. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/generated-files.md +5 -5
  50. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/overview.md +1 -1
  51. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/agents.md +1 -17
  52. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/hooks-and-settings.md +4 -12
  53. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/overview.md +6 -6
  54. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/platform-map.md +5 -75
  55. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/skills-and-commands.md +0 -16
  56. package/dist/templates/common/bundled-skills/trellis-session-insight/SKILL.md +1 -1
  57. package/dist/templates/common/bundled-skills/trellis-session-insight/references/cli-quick-reference.md +2 -3
  58. package/dist/templates/common/commands/continue.md +24 -4
  59. package/dist/templates/common/commands/finish-work.md +19 -9
  60. package/dist/templates/common/commands/start.md +38 -29
  61. package/dist/templates/extract.d.ts +0 -10
  62. package/dist/templates/extract.d.ts.map +1 -1
  63. package/dist/templates/extract.js +0 -24
  64. package/dist/templates/extract.js.map +1 -1
  65. package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +7 -9
  66. package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +4 -8
  67. package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +5 -5
  68. package/dist/templates/shared-hooks/index.d.ts +11 -43
  69. package/dist/templates/shared-hooks/index.d.ts.map +1 -1
  70. package/dist/templates/shared-hooks/index.js +9 -86
  71. package/dist/templates/shared-hooks/index.js.map +1 -1
  72. package/dist/templates/shared-hooks/inject-spec-context.py +1 -1
  73. package/dist/templates/shared-hooks/inject-subagent-context.py +23 -85
  74. package/dist/templates/shared-hooks/inject-workflow-state.py +56 -86
  75. package/dist/templates/shared-hooks/session-start.py +76 -98
  76. package/dist/templates/trellis/index.d.ts +0 -1
  77. package/dist/templates/trellis/index.d.ts.map +1 -1
  78. package/dist/templates/trellis/index.js +0 -2
  79. package/dist/templates/trellis/index.js.map +1 -1
  80. package/dist/templates/trellis/scripts/add_session.py +4 -4
  81. package/dist/templates/trellis/scripts/common/__init__.py +2 -0
  82. package/dist/templates/trellis/scripts/common/active_task.py +80 -152
  83. package/dist/templates/trellis/scripts/common/git_context.py +1 -1
  84. package/dist/templates/trellis/scripts/common/session_context.py +2 -2
  85. package/dist/templates/trellis/scripts/common/spec_inject.py +2 -2
  86. package/dist/templates/trellis/scripts/common/task_store.py +8 -28
  87. package/dist/templates/trellis/scripts/common/workflow_phase.py +4 -8
  88. package/dist/templates/trellis/scripts/get_context.py +2 -2
  89. package/dist/templates/trellis/scripts/init_developer.py +1 -1
  90. package/dist/templates/trellis/scripts/task.py +90 -57
  91. package/dist/templates/trellis/workflow.md +44 -66
  92. package/dist/types/ai-tools.d.ts +10 -10
  93. package/dist/types/ai-tools.d.ts.map +1 -1
  94. package/dist/types/ai-tools.js +3 -434
  95. package/dist/types/ai-tools.js.map +1 -1
  96. package/dist/utils/uninstall-scrubbers.d.ts +3 -18
  97. package/dist/utils/uninstall-scrubbers.d.ts.map +1 -1
  98. package/dist/utils/uninstall-scrubbers.js +24 -154
  99. package/dist/utils/uninstall-scrubbers.js.map +1 -1
  100. package/package.json +2 -2
  101. package/dist/configurators/antigravity.d.ts +0 -7
  102. package/dist/configurators/antigravity.d.ts.map +0 -1
  103. package/dist/configurators/antigravity.js +0 -11
  104. package/dist/configurators/antigravity.js.map +0 -1
  105. package/dist/configurators/codebuddy.d.ts +0 -10
  106. package/dist/configurators/codebuddy.d.ts.map +0 -1
  107. package/dist/configurators/codebuddy.js +0 -24
  108. package/dist/configurators/codebuddy.js.map +0 -1
  109. package/dist/configurators/copilot.d.ts +0 -14
  110. package/dist/configurators/copilot.d.ts.map +0 -1
  111. package/dist/configurators/copilot.js +0 -46
  112. package/dist/configurators/copilot.js.map +0 -1
  113. package/dist/configurators/cursor.d.ts +0 -10
  114. package/dist/configurators/cursor.d.ts.map +0 -1
  115. package/dist/configurators/cursor.js +0 -23
  116. package/dist/configurators/cursor.js.map +0 -1
  117. package/dist/configurators/devin.d.ts +0 -8
  118. package/dist/configurators/devin.d.ts.map +0 -1
  119. package/dist/configurators/devin.js +0 -12
  120. package/dist/configurators/devin.js.map +0 -1
  121. package/dist/configurators/droid.d.ts +0 -10
  122. package/dist/configurators/droid.d.ts.map +0 -1
  123. package/dist/configurators/droid.js +0 -24
  124. package/dist/configurators/droid.js.map +0 -1
  125. package/dist/configurators/dsh.d.ts +0 -26
  126. package/dist/configurators/dsh.d.ts.map +0 -1
  127. package/dist/configurators/dsh.js +0 -76
  128. package/dist/configurators/dsh.js.map +0 -1
  129. package/dist/configurators/gemini.d.ts +0 -18
  130. package/dist/configurators/gemini.d.ts.map +0 -1
  131. package/dist/configurators/gemini.js +0 -39
  132. package/dist/configurators/gemini.js.map +0 -1
  133. package/dist/configurators/grok.d.ts +0 -17
  134. package/dist/configurators/grok.d.ts.map +0 -1
  135. package/dist/configurators/grok.js +0 -38
  136. package/dist/configurators/grok.js.map +0 -1
  137. package/dist/configurators/kilo.d.ts +0 -7
  138. package/dist/configurators/kilo.d.ts.map +0 -1
  139. package/dist/configurators/kilo.js +0 -11
  140. package/dist/configurators/kilo.js.map +0 -1
  141. package/dist/configurators/kimi.d.ts +0 -26
  142. package/dist/configurators/kimi.d.ts.map +0 -1
  143. package/dist/configurators/kimi.js +0 -74
  144. package/dist/configurators/kimi.js.map +0 -1
  145. package/dist/configurators/kiro.d.ts +0 -11
  146. package/dist/configurators/kiro.d.ts.map +0 -1
  147. package/dist/configurators/kiro.js +0 -30
  148. package/dist/configurators/kiro.js.map +0 -1
  149. package/dist/configurators/omp.d.ts +0 -6
  150. package/dist/configurators/omp.d.ts.map +0 -1
  151. package/dist/configurators/omp.js +0 -28
  152. package/dist/configurators/omp.js.map +0 -1
  153. package/dist/configurators/opencode.d.ts +0 -5
  154. package/dist/configurators/opencode.d.ts.map +0 -1
  155. package/dist/configurators/opencode.js +0 -84
  156. package/dist/configurators/opencode.js.map +0 -1
  157. package/dist/configurators/pi.d.ts +0 -5
  158. package/dist/configurators/pi.d.ts.map +0 -1
  159. package/dist/configurators/pi.js +0 -39
  160. package/dist/configurators/pi.js.map +0 -1
  161. package/dist/configurators/qoder.d.ts +0 -12
  162. package/dist/configurators/qoder.d.ts.map +0 -1
  163. package/dist/configurators/qoder.js +0 -30
  164. package/dist/configurators/qoder.js.map +0 -1
  165. package/dist/configurators/reasonix.d.ts +0 -17
  166. package/dist/configurators/reasonix.d.ts.map +0 -1
  167. package/dist/configurators/reasonix.js +0 -37
  168. package/dist/configurators/reasonix.js.map +0 -1
  169. package/dist/configurators/snow.d.ts +0 -25
  170. package/dist/configurators/snow.d.ts.map +0 -1
  171. package/dist/configurators/snow.js +0 -69
  172. package/dist/configurators/snow.js.map +0 -1
  173. package/dist/configurators/trae.d.ts +0 -16
  174. package/dist/configurators/trae.d.ts.map +0 -1
  175. package/dist/configurators/trae.js +0 -34
  176. package/dist/configurators/trae.js.map +0 -1
  177. package/dist/configurators/zcode.d.ts +0 -23
  178. package/dist/configurators/zcode.d.ts.map +0 -1
  179. package/dist/configurators/zcode.js +0 -63
  180. package/dist/configurators/zcode.js.map +0 -1
  181. package/dist/templates/codebuddy/agents/trellis-check.md +0 -115
  182. package/dist/templates/codebuddy/agents/trellis-implement.md +0 -115
  183. package/dist/templates/codebuddy/agents/trellis-research.md +0 -137
  184. package/dist/templates/codebuddy/index.d.ts +0 -15
  185. package/dist/templates/codebuddy/index.d.ts.map +0 -1
  186. package/dist/templates/codebuddy/index.js +0 -15
  187. package/dist/templates/codebuddy/index.js.map +0 -1
  188. package/dist/templates/codebuddy/settings.json +0 -69
  189. package/dist/templates/copilot/copilot-instructions.md +0 -11
  190. package/dist/templates/copilot/hooks/session-start.py +0 -564
  191. package/dist/templates/copilot/hooks.json +0 -19
  192. package/dist/templates/copilot/index.d.ts +0 -28
  193. package/dist/templates/copilot/index.d.ts.map +0 -1
  194. package/dist/templates/copilot/index.js +0 -61
  195. package/dist/templates/copilot/index.js.map +0 -1
  196. package/dist/templates/copilot/prompts/before-dev.prompt.md +0 -39
  197. package/dist/templates/copilot/prompts/brainstorm.prompt.md +0 -173
  198. package/dist/templates/copilot/prompts/break-loop.prompt.md +0 -129
  199. package/dist/templates/copilot/prompts/check-cross-layer.prompt.md +0 -170
  200. package/dist/templates/copilot/prompts/check.prompt.md +0 -110
  201. package/dist/templates/copilot/prompts/create-command.prompt.md +0 -116
  202. package/dist/templates/copilot/prompts/finish-work.prompt.md +0 -99
  203. package/dist/templates/copilot/prompts/integrate-skill.prompt.md +0 -223
  204. package/dist/templates/copilot/prompts/onboard.prompt.md +0 -362
  205. package/dist/templates/copilot/prompts/parallel.prompt.md +0 -204
  206. package/dist/templates/copilot/prompts/record-session.prompt.md +0 -66
  207. package/dist/templates/copilot/prompts/start.prompt.md +0 -63
  208. package/dist/templates/copilot/prompts/update-spec.prompt.md +0 -358
  209. package/dist/templates/cursor/agents/trellis-check.md +0 -114
  210. package/dist/templates/cursor/agents/trellis-implement.md +0 -114
  211. package/dist/templates/cursor/agents/trellis-research.md +0 -136
  212. package/dist/templates/cursor/hooks.json +0 -24
  213. package/dist/templates/cursor/index.d.ts +0 -13
  214. package/dist/templates/cursor/index.d.ts.map +0 -1
  215. package/dist/templates/cursor/index.js +0 -13
  216. package/dist/templates/cursor/index.js.map +0 -1
  217. package/dist/templates/droid/droids/trellis-check.md +0 -107
  218. package/dist/templates/droid/droids/trellis-implement.md +0 -107
  219. package/dist/templates/droid/droids/trellis-research.md +0 -137
  220. package/dist/templates/droid/index.d.ts +0 -15
  221. package/dist/templates/droid/index.d.ts.map +0 -1
  222. package/dist/templates/droid/index.js +0 -15
  223. package/dist/templates/droid/index.js.map +0 -1
  224. package/dist/templates/droid/settings.json +0 -69
  225. package/dist/templates/dsh/DSH.md +0 -80
  226. package/dist/templates/dsh/agents/trellis-check.md +0 -99
  227. package/dist/templates/dsh/agents/trellis-implement.md +0 -106
  228. package/dist/templates/dsh/agents/trellis-research.md +0 -134
  229. package/dist/templates/dsh/index.d.ts +0 -22
  230. package/dist/templates/dsh/index.d.ts.map +0 -1
  231. package/dist/templates/dsh/index.js +0 -27
  232. package/dist/templates/dsh/index.js.map +0 -1
  233. package/dist/templates/gemini/agents/trellis-check.md +0 -107
  234. package/dist/templates/gemini/agents/trellis-implement.md +0 -107
  235. package/dist/templates/gemini/agents/trellis-research.md +0 -136
  236. package/dist/templates/gemini/index.d.ts +0 -13
  237. package/dist/templates/gemini/index.d.ts.map +0 -1
  238. package/dist/templates/gemini/index.js +0 -13
  239. package/dist/templates/gemini/index.js.map +0 -1
  240. package/dist/templates/gemini/settings.json +0 -40
  241. package/dist/templates/grok/agents/trellis-check.md +0 -106
  242. package/dist/templates/grok/agents/trellis-implement.md +0 -121
  243. package/dist/templates/grok/agents/trellis-research.md +0 -146
  244. package/dist/templates/grok/index.d.ts +0 -16
  245. package/dist/templates/grok/index.d.ts.map +0 -1
  246. package/dist/templates/grok/index.js +0 -19
  247. package/dist/templates/grok/index.js.map +0 -1
  248. package/dist/templates/kimi/agents/trellis-check.md +0 -104
  249. package/dist/templates/kimi/agents/trellis-implement.md +0 -120
  250. package/dist/templates/kimi/agents/trellis-research.md +0 -144
  251. package/dist/templates/kimi/index.d.ts +0 -20
  252. package/dist/templates/kimi/index.d.ts.map +0 -1
  253. package/dist/templates/kimi/index.js +0 -23
  254. package/dist/templates/kimi/index.js.map +0 -1
  255. package/dist/templates/kiro/agents/trellis-check.json +0 -26
  256. package/dist/templates/kiro/agents/trellis-implement.json +0 -26
  257. package/dist/templates/kiro/agents/trellis-research.json +0 -30
  258. package/dist/templates/kiro/agents/trellis.json +0 -34
  259. package/dist/templates/kiro/hooks/trellis-workflow-state.kiro.hook +0 -14
  260. package/dist/templates/kiro/index.d.ts +0 -32
  261. package/dist/templates/kiro/index.d.ts.map +0 -1
  262. package/dist/templates/kiro/index.js +0 -28
  263. package/dist/templates/kiro/index.js.map +0 -1
  264. package/dist/templates/omp/agents/trellis-check.md +0 -41
  265. package/dist/templates/omp/agents/trellis-implement.md +0 -55
  266. package/dist/templates/omp/agents/trellis-research.md +0 -30
  267. package/dist/templates/omp/extensions/trellis/index.ts.txt +0 -592
  268. package/dist/templates/omp/index.d.ts +0 -4
  269. package/dist/templates/omp/index.d.ts.map +0 -1
  270. package/dist/templates/omp/index.js +0 -9
  271. package/dist/templates/omp/index.js.map +0 -1
  272. package/dist/templates/opencode/agents/trellis-check.md +0 -122
  273. package/dist/templates/opencode/agents/trellis-implement.md +0 -123
  274. package/dist/templates/opencode/agents/trellis-research.md +0 -145
  275. package/dist/templates/opencode/lib/context-visibility.js +0 -86
  276. package/dist/templates/opencode/lib/session-utils.js +0 -526
  277. package/dist/templates/opencode/lib/trellis-context.js +0 -627
  278. package/dist/templates/opencode/package.json +0 -5
  279. package/dist/templates/opencode/plugins/inject-spec-context.js +0 -121
  280. package/dist/templates/opencode/plugins/inject-subagent-context.js +0 -569
  281. package/dist/templates/opencode/plugins/inject-workflow-state.js +0 -340
  282. package/dist/templates/opencode/plugins/session-start.js +0 -74
  283. package/dist/templates/pi/agents/trellis-check.md +0 -37
  284. package/dist/templates/pi/agents/trellis-implement.md +0 -52
  285. package/dist/templates/pi/agents/trellis-research.md +0 -25
  286. package/dist/templates/pi/extensions/trellis/index.ts.txt +0 -2033
  287. package/dist/templates/pi/index.d.ts +0 -5
  288. package/dist/templates/pi/index.d.ts.map +0 -1
  289. package/dist/templates/pi/index.js +0 -12
  290. package/dist/templates/pi/index.js.map +0 -1
  291. package/dist/templates/pi/settings.json +0 -9
  292. package/dist/templates/qoder/agents/trellis-check.md +0 -108
  293. package/dist/templates/qoder/agents/trellis-implement.md +0 -108
  294. package/dist/templates/qoder/agents/trellis-research.md +0 -137
  295. package/dist/templates/qoder/index.d.ts +0 -15
  296. package/dist/templates/qoder/index.d.ts.map +0 -1
  297. package/dist/templates/qoder/index.js +0 -15
  298. package/dist/templates/qoder/index.js.map +0 -1
  299. package/dist/templates/qoder/settings.json +0 -59
  300. package/dist/templates/reasonix/agents/trellis-check.md +0 -36
  301. package/dist/templates/reasonix/agents/trellis-implement.md +0 -51
  302. package/dist/templates/reasonix/index.d.ts +0 -13
  303. package/dist/templates/reasonix/index.d.ts.map +0 -1
  304. package/dist/templates/reasonix/index.js +0 -16
  305. package/dist/templates/reasonix/index.js.map +0 -1
  306. package/dist/templates/shared-hooks/inject-shell-session-context.py +0 -292
  307. package/dist/templates/snow/SNOW.md +0 -86
  308. package/dist/templates/snow/agents/trellis-check.md +0 -136
  309. package/dist/templates/snow/agents/trellis-implement.md +0 -158
  310. package/dist/templates/snow/agents/trellis-research.md +0 -114
  311. package/dist/templates/snow/hooks/beforeSubAgentStart.json +0 -15
  312. package/dist/templates/snow/hooks/onSessionStart.json +0 -15
  313. package/dist/templates/snow/hooks/onUserMessage.json +0 -15
  314. package/dist/templates/snow/hooks/write-trellis-context.py +0 -644
  315. package/dist/templates/snow/index.d.ts +0 -26
  316. package/dist/templates/snow/index.d.ts.map +0 -1
  317. package/dist/templates/snow/index.js +0 -36
  318. package/dist/templates/snow/index.js.map +0 -1
  319. package/dist/templates/trae/agents/trellis-check.md +0 -108
  320. package/dist/templates/trae/agents/trellis-implement.md +0 -108
  321. package/dist/templates/trae/agents/trellis-research.md +0 -137
  322. package/dist/templates/trae/hooks.json +0 -39
  323. package/dist/templates/trae/index.d.ts +0 -15
  324. package/dist/templates/trae/index.d.ts.map +0 -1
  325. package/dist/templates/trae/index.js +0 -15
  326. package/dist/templates/trae/index.js.map +0 -1
  327. package/dist/templates/trellis/scripts/common/cli_adapter.py +0 -982
  328. package/dist/templates/zcode/agents/trellis-check.md +0 -110
  329. package/dist/templates/zcode/agents/trellis-implement.md +0 -116
  330. package/dist/templates/zcode/agents/trellis-research.md +0 -133
  331. package/dist/templates/zcode/config.json +0 -52
  332. package/dist/templates/zcode/index.d.ts +0 -25
  333. package/dist/templates/zcode/index.d.ts.map +0 -1
  334. package/dist/templates/zcode/index.js +0 -29
  335. package/dist/templates/zcode/index.js.map +0 -1
@@ -1,526 +0,0 @@
1
- /* global process */
2
- import { existsSync, readFileSync, readdirSync, statSync } from "fs"
3
- import { join } from "path"
4
- import { execFileSync } from "child_process"
5
- import { platform } from "os"
6
- import { debugLog } from "./trellis-context.js"
7
-
8
- const PYTHON_CMD = platform() === "win32" ? "python" : "python3"
9
-
10
- const FIRST_REPLY_NOTICE = `<first-reply-notice>
11
- On the first visible assistant reply in this session, briefly acknowledge that Trellis SessionStart context loaded.
12
- Choose the acknowledgment language in this order:
13
- 1. Use the language of the user's current request (the user message that triggered this reply).
14
- 2. If that request has no clear natural language, use an explicitly established project communication language.
15
- 3. If neither provides a language, output the language-neutral fallback exactly: \`Trellis SessionStart ✓\`.
16
- Continue directly with the user's request after the acknowledgment.
17
- The acknowledgment must not alter the language used for the remainder of the response.
18
- This notice is one-shot: do not repeat it after the first visible assistant reply in this session.
19
- </first-reply-notice>`
20
-
21
- function hasCuratedJsonlEntry(jsonlPath) {
22
- try {
23
- const content = readFileSync(jsonlPath, "utf-8")
24
- for (const rawLine of content.split(/\r?\n/)) {
25
- const line = rawLine.trim()
26
- if (!line) continue
27
- try {
28
- const row = JSON.parse(line)
29
- if (row && typeof row === "object" && typeof row.file === "string" && row.file) {
30
- return true
31
- }
32
- } catch {
33
- // Ignore malformed line
34
- }
35
- }
36
- } catch {
37
- return false
38
- }
39
- return false
40
- }
41
-
42
- function getTaskStatus(ctx, platformInput = null) {
43
- const active = ctx.getActiveTask(platformInput)
44
- const taskRef = active.taskPath
45
- if (!taskRef) {
46
- return (
47
- "Status: NO ACTIVE TASK\n" +
48
- "Next-Action: Work inline. Do not ask whether to create a Trellis task; " +
49
- "create one only when the user explicitly asks for it."
50
- )
51
- }
52
-
53
- const taskDir = ctx.resolveTaskDir(taskRef)
54
-
55
- if (active.stale || !taskDir || !existsSync(taskDir)) {
56
- return `Status: STALE POINTER\nTask: ${taskRef}\nNext-Action: Task directory not found. Run: python3 ./.trellis/scripts/task.py finish`
57
- }
58
-
59
- let taskData = {}
60
- const taskJsonPath = join(taskDir, "task.json")
61
- if (existsSync(taskJsonPath)) {
62
- try {
63
- taskData = JSON.parse(readFileSync(taskJsonPath, "utf-8"))
64
- } catch {
65
- // Ignore parse errors
66
- }
67
- }
68
-
69
- const taskTitle = taskData.title || taskRef
70
- const taskStatus = taskData.status || "unknown"
71
-
72
- if (taskStatus === "completed") {
73
- return `Status: COMPLETED\nTask: ${taskTitle}\nNext-Action: Run /trellis:finish-work. If the working tree is dirty, return to Phase 3.4 first.`
74
- }
75
-
76
- const hasPrd = existsSync(join(taskDir, "prd.md"))
77
- const hasDesign = existsSync(join(taskDir, "design.md"))
78
- const hasImplementPlan = existsSync(join(taskDir, "implement.md"))
79
- const artifactNames = ["prd.md", "design.md", "implement.md", "implement.jsonl", "check.jsonl"]
80
- const present = artifactNames.filter(name => existsSync(join(taskDir, name)))
81
- if (existsSync(join(taskDir, "research"))) present.push("research/")
82
- const presentLine = present.length > 0 ? present.join(", ") : "(none)"
83
- const implementJsonl = join(taskDir, "implement.jsonl")
84
- const checkJsonl = join(taskDir, "check.jsonl")
85
- const jsonlReady =
86
- (!existsSync(implementJsonl) || hasCuratedJsonlEntry(implementJsonl)) &&
87
- (!existsSync(checkJsonl) || hasCuratedJsonlEntry(checkJsonl))
88
-
89
- if (taskStatus === "planning" && !hasPrd) {
90
- return `Status: PLANNING\nTask: ${taskTitle}\nPresent: ${presentLine}\nNext-Action: Load trellis-brainstorm and write prd.md. Stay in planning.`
91
- }
92
-
93
- if (taskStatus === "planning") {
94
- const missingComplex = []
95
- if (!hasDesign) missingComplex.push("design.md")
96
- if (!hasImplementPlan) missingComplex.push("implement.md")
97
- const nextBits = []
98
- if (missingComplex.length > 0) {
99
- nextBits.push(
100
- `Planning is incomplete: add ${missingComplex.join(", ")} before start`,
101
- )
102
- } else {
103
- nextBits.push("Planning artifacts are present; ask for review before `task.py start`")
104
- }
105
- if (!jsonlReady) {
106
- nextBits.push("curate `implement.jsonl` and `check.jsonl` before sub-agent mode start")
107
- }
108
- return `Status: PLANNING\nTask: ${taskTitle}\nPresent: ${presentLine}\nNext-Action: ${nextBits.join("; ")}. Do not enter implementation until the user confirms start.`
109
- }
110
-
111
- return (
112
- `Status: ${String(taskStatus).toUpperCase()}\nTask: ${taskTitle}\n` +
113
- `Present: ${presentLine}\n` +
114
- "Next-Action: Follow the matching per-turn workflow-state. " +
115
- "Implementation/check context order is jsonl entries -> `prd.md` -> `design.md if present` -> `implement.md if present`."
116
- )
117
- }
118
-
119
- function loadTrellisConfig(directory, contextKey = null) {
120
- const scriptPath = join(directory, ".trellis", "scripts", "get_context.py")
121
- if (!existsSync(scriptPath)) {
122
- return { isMonorepo: false, packages: {}, specScope: null, activeTaskPackage: null, defaultPackage: null }
123
- }
124
- try {
125
- const output = execFileSync(PYTHON_CMD, [scriptPath, "--mode", "packages", "--json"], {
126
- cwd: directory,
127
- timeout: 5000,
128
- encoding: "utf-8",
129
- stdio: ["pipe", "pipe", "pipe"],
130
- env: {
131
- ...process.env,
132
- ...(contextKey ? { TRELLIS_CONTEXT_ID: contextKey } : {}),
133
- },
134
- })
135
- const data = JSON.parse(output)
136
- if (data.mode !== "monorepo") {
137
- return { isMonorepo: false, packages: {}, specScope: null, activeTaskPackage: null, defaultPackage: null }
138
- }
139
- const pkgDict = {}
140
- for (const pkg of (data.packages || [])) {
141
- pkgDict[pkg.name] = pkg
142
- }
143
- return {
144
- isMonorepo: true,
145
- packages: pkgDict,
146
- specScope: data.specScope || null,
147
- activeTaskPackage: data.activeTaskPackage || null,
148
- defaultPackage: data.defaultPackage || null,
149
- }
150
- } catch (e) {
151
- debugLog("session", "loadTrellisConfig error:", e.message)
152
- return { isMonorepo: false, packages: {}, specScope: null, activeTaskPackage: null, defaultPackage: null }
153
- }
154
- }
155
-
156
- function checkLegacySpec(directory, config) {
157
- if (!config.isMonorepo || Object.keys(config.packages).length === 0) {
158
- return null
159
- }
160
-
161
- const specDir = join(directory, ".trellis", "spec")
162
- if (!existsSync(specDir)) return null
163
-
164
- let hasLegacy = false
165
- for (const name of ["backend", "frontend"]) {
166
- if (existsSync(join(specDir, name, "index.md"))) {
167
- hasLegacy = true
168
- break
169
- }
170
- }
171
- if (!hasLegacy) return null
172
-
173
- const pkgNames = Object.keys(config.packages).sort()
174
- const missing = pkgNames.filter(name => !existsSync(join(specDir, name)))
175
-
176
- if (missing.length === 0) return null
177
-
178
- if (missing.length === pkgNames.length) {
179
- return (
180
- `[!] Legacy spec structure detected: found \`spec/backend/\` or \`spec/frontend/\` ` +
181
- `but no package-scoped \`spec/<package>/\` directories.\n` +
182
- `Monorepo packages: ${pkgNames.join(", ")}\n` +
183
- `Please reorganize: \`spec/backend/\` -> \`spec/<package>/backend/\``
184
- )
185
- }
186
- return (
187
- `[!] Partial spec migration detected: packages ${missing.join(", ")} ` +
188
- `still missing \`spec/<pkg>/\` directory.\n` +
189
- `Please complete migration for all packages.`
190
- )
191
- }
192
-
193
- function resolveSpecScope(config) {
194
- if (!config.isMonorepo || Object.keys(config.packages).length === 0) {
195
- return null
196
- }
197
-
198
- const { specScope, activeTaskPackage, defaultPackage, packages } = config
199
- if (specScope == null) return null
200
-
201
- if (specScope === "active_task") {
202
- if (activeTaskPackage && activeTaskPackage in packages) return new Set([activeTaskPackage])
203
- if (defaultPackage && defaultPackage in packages) return new Set([defaultPackage])
204
- return null
205
- }
206
-
207
- if (Array.isArray(specScope)) {
208
- const valid = new Set()
209
- for (const entry of specScope) {
210
- if (entry in packages) {
211
- valid.add(entry)
212
- }
213
- }
214
- if (valid.size > 0) return valid
215
- if (activeTaskPackage && activeTaskPackage in packages) return new Set([activeTaskPackage])
216
- if (defaultPackage && defaultPackage in packages) return new Set([defaultPackage])
217
- return null
218
- }
219
-
220
- return null
221
- }
222
-
223
- function collectSpecIndexPaths(directory, allowedPkgs) {
224
- const specDir = join(directory, ".trellis", "spec")
225
- const paths = []
226
-
227
- const guidesIndex = join(specDir, "guides", "index.md")
228
- if (existsSync(guidesIndex)) {
229
- paths.push(".trellis/spec/guides/index.md")
230
- }
231
-
232
- if (!existsSync(specDir)) return paths
233
-
234
- try {
235
- const subs = readdirSync(specDir).filter(name => {
236
- if (name.startsWith(".") || name === "guides") return false
237
- try {
238
- return statSync(join(specDir, name)).isDirectory()
239
- } catch {
240
- return false
241
- }
242
- }).sort()
243
-
244
- for (const sub of subs) {
245
- const indexFile = join(specDir, sub, "index.md")
246
- if (existsSync(indexFile)) {
247
- paths.push(`.trellis/spec/${sub}/index.md`)
248
- } else {
249
- if (allowedPkgs !== null && !allowedPkgs.has(sub)) continue
250
- try {
251
- const nested = readdirSync(join(specDir, sub)).filter(name => {
252
- try {
253
- return statSync(join(specDir, sub, name)).isDirectory()
254
- } catch {
255
- return false
256
- }
257
- }).sort()
258
- for (const layer of nested) {
259
- const nestedIndex = join(specDir, sub, layer, "index.md")
260
- if (existsSync(nestedIndex)) {
261
- paths.push(`.trellis/spec/${sub}/${layer}/index.md`)
262
- }
263
- }
264
- } catch {
265
- // Ignore directory read errors
266
- }
267
- }
268
- }
269
- } catch {
270
- // Ignore spec directory read errors
271
- }
272
-
273
- return paths
274
- }
275
-
276
- function readDeveloper(directory) {
277
- try {
278
- const content = readFileSync(join(directory, ".trellis", ".developer"), "utf-8")
279
- for (const line of content.split(/\r?\n/)) {
280
- if (line.startsWith("name=")) return line.slice("name=".length).trim()
281
- }
282
- } catch {
283
- // Ignore missing developer file
284
- }
285
- return "(not initialized)"
286
- }
287
-
288
- function runGit(directory, args) {
289
- try {
290
- return execFileSync("git", args, {
291
- cwd: directory,
292
- timeout: 3000,
293
- encoding: "utf-8",
294
- stdio: ["pipe", "pipe", "pipe"],
295
- }).trim()
296
- } catch {
297
- return ""
298
- }
299
- }
300
-
301
- function buildCompactCurrentState(ctx, platformInput, specIndexPaths) {
302
- const directory = ctx.directory
303
- const lines = []
304
- lines.push(`Developer: ${readDeveloper(directory)}`)
305
-
306
- const branch = runGit(directory, ["branch", "--show-current"]) || "(detached)"
307
- const dirtyCount = runGit(directory, ["status", "--porcelain"])
308
- .split(/\r?\n/)
309
- .filter(line => line.trim()).length
310
- lines.push(`Git: branch ${branch}; ${dirtyCount === 0 ? "clean" : `dirty ${dirtyCount} paths`}.`)
311
-
312
- const active = ctx.getActiveTask(platformInput)
313
- if (active.taskPath) {
314
- const taskDir = ctx.resolveTaskDir(active.taskPath)
315
- let status = "unknown"
316
- if (taskDir) {
317
- try {
318
- const data = JSON.parse(readFileSync(join(taskDir, "task.json"), "utf-8"))
319
- status = data.status || "unknown"
320
- } catch {
321
- // Ignore parse errors
322
- }
323
- }
324
- lines.push(`Current task: ${active.taskPath}; status=${status}.`)
325
- } else {
326
- lines.push("Current task: none.")
327
- }
328
-
329
- const tasksDir = join(directory, ".trellis", "tasks")
330
- if (existsSync(tasksDir)) {
331
- try {
332
- const activeTasks = readdirSync(tasksDir, { withFileTypes: true })
333
- .filter(entry => entry.isDirectory() && entry.name !== "archive" && existsSync(join(tasksDir, entry.name, "task.json")))
334
- lines.push(`Active tasks: ${activeTasks.length} total. Use \`python3 ./.trellis/scripts/task.py list --mine\` only if needed.`)
335
- } catch {
336
- // Ignore task list errors
337
- }
338
- }
339
-
340
- const developer = readDeveloper(directory)
341
- const workspaceDir = join(directory, ".trellis", "workspace", developer)
342
- if (developer !== "(not initialized)" && existsSync(workspaceDir)) {
343
- try {
344
- const journals = readdirSync(workspaceDir)
345
- .filter(name => /^journal-\d+\.md$/.test(name))
346
- .sort((a, b) => Number(a.match(/\d+/)?.[0] || 0) - Number(b.match(/\d+/)?.[0] || 0))
347
- const journal = journals[journals.length - 1]
348
- if (journal) {
349
- const journalPath = join(workspaceDir, journal)
350
- const lineCount = readFileSync(journalPath, "utf-8").split(/\r?\n/).length
351
- lines.push(`Journal: .trellis/workspace/${developer}/${journal}, ${lineCount} / 2000 lines.`)
352
- }
353
- } catch {
354
- // Ignore journal errors
355
- }
356
- }
357
-
358
- if (specIndexPaths.length > 0) {
359
- lines.push(`Spec indexes: ${specIndexPaths.length} available.`)
360
- }
361
-
362
- return lines.join("\n")
363
- }
364
-
365
- export function buildSessionContext(ctx, platformInput = null) {
366
- const directory = ctx.directory
367
- const contextKey = typeof ctx.getContextKey === "function"
368
- ? ctx.getContextKey(platformInput)
369
- : null
370
-
371
- const config = loadTrellisConfig(directory, contextKey)
372
- const allowedPkgs = resolveSpecScope(config)
373
- const paths = collectSpecIndexPaths(directory, allowedPkgs)
374
-
375
- const parts = []
376
-
377
- parts.push(`<session-context>
378
- Trellis compact SessionStart context. Use it to orient the session; load details on demand.
379
- </session-context>`)
380
- parts.push(FIRST_REPLY_NOTICE)
381
-
382
- const legacyWarning = checkLegacySpec(directory, config)
383
- if (legacyWarning) {
384
- parts.push(`<migration-warning>\n${legacyWarning}\n</migration-warning>`)
385
- }
386
-
387
- parts.push("<current-state>")
388
- parts.push(buildCompactCurrentState(ctx, platformInput, paths))
389
- parts.push("</current-state>")
390
-
391
- const workflowContent = ctx.readProjectFile(".trellis/workflow.md")
392
- if (workflowContent) {
393
- const allLines = workflowContent.split("\n")
394
- const overviewLines = [
395
- "# Development Workflow - Session Summary",
396
- "Full guide: .trellis/workflow.md. Step detail: `python3 ./.trellis/scripts/get_context.py --mode phase --step <X.Y>`.",
397
- "",
398
- ]
399
-
400
- let rangeStart = -1
401
- let rangeEnd = allLines.length
402
- for (let i = 0; i < allLines.length; i++) {
403
- const stripped = allLines[i].trim()
404
- if (rangeStart === -1 && stripped === "## Phase Index") {
405
- rangeStart = i
406
- } else if (rangeStart !== -1 && stripped === "## Phase 1: Plan") {
407
- rangeEnd = i
408
- break
409
- }
410
- }
411
- if (rangeStart !== -1) {
412
- const strippedStateBlocks = allLines
413
- .slice(rangeStart, rangeEnd)
414
- .join("\n")
415
- .replace(/\[workflow-state:([A-Za-z0-9_-]+)\]\s*\n[\s\S]*?\n\s*\[\/workflow-state:\1\]\n?/g, "")
416
- .replace(/<!--[\s\S]*?-->/g, "")
417
- .replace(/^\[(?!\/?workflow-state:)\/?[^\]\n]+\]\s*\n?/gm, "")
418
- .replace(/\n{3,}/g, "\n\n")
419
- overviewLines.push(strippedStateBlocks.trimEnd())
420
- }
421
-
422
- parts.push("<trellis-workflow>")
423
- parts.push(overviewLines.join("\n").trimEnd())
424
- parts.push("</trellis-workflow>")
425
- }
426
-
427
- parts.push("<guidelines>")
428
- parts.push(
429
- "Task context order for implementation/check: jsonl entries -> `prd.md` -> " +
430
- "`design.md` -> `implement.md`. All three " +
431
- "are required; a missing one means planning is incomplete.\n"
432
- )
433
-
434
- if (paths.length > 0) {
435
- parts.push("## Available indexes (read on demand)")
436
- for (const p of paths) {
437
- parts.push(`- ${p}`)
438
- }
439
- parts.push("")
440
- }
441
-
442
- parts.push(
443
- "Discover more via: " +
444
- "`python3 ./.trellis/scripts/get_context.py --mode packages`"
445
- )
446
- parts.push("</guidelines>")
447
-
448
- const taskStatus = getTaskStatus(ctx, platformInput)
449
- parts.push(`<task-status>\n${taskStatus}\n</task-status>`)
450
-
451
- parts.push(`<ready>
452
- Context loaded. Follow <task-status>. Load workflow/spec/task details only when needed.
453
- </ready>`)
454
-
455
- return parts.join("\n\n")
456
- }
457
-
458
- function getTrellisMetadata(metadata) {
459
- if (!metadata || typeof metadata !== "object") {
460
- return {}
461
- }
462
-
463
- const trellis = metadata.trellis
464
- if (!trellis || typeof trellis !== "object") {
465
- return {}
466
- }
467
-
468
- return trellis
469
- }
470
-
471
- function markPartAsSessionStart(part) {
472
- const metadata = part.metadata && typeof part.metadata === "object"
473
- ? part.metadata
474
- : {}
475
- part.metadata = {
476
- ...metadata,
477
- trellis: {
478
- ...getTrellisMetadata(metadata),
479
- sessionStart: true,
480
- },
481
- }
482
- }
483
-
484
- function hasSessionStartMarker(part) {
485
- if (!part || part.type !== "text" || typeof part.text !== "string") {
486
- return false
487
- }
488
-
489
- return getTrellisMetadata(part.metadata).sessionStart === true
490
- }
491
-
492
- export function hasInjectedTrellisContext(messages) {
493
- if (!Array.isArray(messages)) {
494
- return false
495
- }
496
-
497
- return messages.some(message => {
498
- if (!message?.info || message.info.role !== "user" || !Array.isArray(message.parts)) {
499
- return false
500
- }
501
-
502
- return message.parts.some(hasSessionStartMarker)
503
- })
504
- }
505
-
506
- export async function hasPersistedInjectedContext(client, directory, sessionID) {
507
- try {
508
- const response = await client.session.messages({
509
- path: { id: sessionID },
510
- query: { directory },
511
- throwOnError: true,
512
- })
513
- return hasInjectedTrellisContext(response.data || [])
514
- } catch (error) {
515
- debugLog(
516
- "session",
517
- "Failed to read session history for dedupe:",
518
- error instanceof Error ? error.message : String(error),
519
- )
520
- return false
521
- }
522
- }
523
-
524
- export function markContextInjected(part) {
525
- markPartAsSessionStart(part)
526
- }