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

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 (331) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/index.d.ts +1 -1
  3. package/dist/cli/index.d.ts.map +1 -1
  4. package/dist/cli/index.js +58 -2
  5. package/dist/cli/index.js.map +1 -1
  6. package/dist/commands/channel/adapters/claude.d.ts +29 -0
  7. package/dist/commands/channel/adapters/claude.d.ts.map +1 -0
  8. package/dist/commands/channel/adapters/claude.js +203 -0
  9. package/dist/commands/channel/adapters/claude.js.map +1 -0
  10. package/dist/commands/channel/adapters/codex.d.ts +85 -0
  11. package/dist/commands/channel/adapters/codex.d.ts.map +1 -0
  12. package/dist/commands/channel/adapters/codex.js +505 -0
  13. package/dist/commands/channel/adapters/codex.js.map +1 -0
  14. package/dist/commands/channel/adapters/index.d.ts +84 -0
  15. package/dist/commands/channel/adapters/index.d.ts.map +1 -0
  16. package/dist/commands/channel/adapters/index.js +115 -0
  17. package/dist/commands/channel/adapters/index.js.map +1 -0
  18. package/dist/commands/channel/adapters/types.d.ts +33 -0
  19. package/dist/commands/channel/adapters/types.d.ts.map +1 -0
  20. package/dist/commands/channel/adapters/types.js +2 -0
  21. package/dist/commands/channel/adapters/types.js.map +1 -0
  22. package/dist/commands/channel/agent-loader.d.ts +32 -0
  23. package/dist/commands/channel/agent-loader.d.ts.map +1 -0
  24. package/dist/commands/channel/agent-loader.js +154 -0
  25. package/dist/commands/channel/agent-loader.js.map +1 -0
  26. package/dist/commands/channel/context-loader.d.ts +26 -0
  27. package/dist/commands/channel/context-loader.d.ts.map +1 -0
  28. package/dist/commands/channel/context-loader.js +290 -0
  29. package/dist/commands/channel/context-loader.js.map +1 -0
  30. package/dist/commands/channel/context.d.ts +16 -0
  31. package/dist/commands/channel/context.d.ts.map +1 -0
  32. package/dist/commands/channel/context.js +83 -0
  33. package/dist/commands/channel/context.js.map +1 -0
  34. package/dist/commands/channel/create.d.ts +27 -0
  35. package/dist/commands/channel/create.d.ts.map +1 -0
  36. package/dist/commands/channel/create.js +39 -0
  37. package/dist/commands/channel/create.js.map +1 -0
  38. package/dist/commands/channel/dev-parse-trace.d.ts +14 -0
  39. package/dist/commands/channel/dev-parse-trace.d.ts.map +1 -0
  40. package/dist/commands/channel/dev-parse-trace.js +70 -0
  41. package/dist/commands/channel/dev-parse-trace.js.map +1 -0
  42. package/dist/commands/channel/guard.d.ts +150 -0
  43. package/dist/commands/channel/guard.d.ts.map +1 -0
  44. package/dist/commands/channel/guard.js +474 -0
  45. package/dist/commands/channel/guard.js.map +1 -0
  46. package/dist/commands/channel/index.d.ts +3 -0
  47. package/dist/commands/channel/index.d.ts.map +1 -0
  48. package/dist/commands/channel/index.js +531 -0
  49. package/dist/commands/channel/index.js.map +1 -0
  50. package/dist/commands/channel/interrupt.d.ts +10 -0
  51. package/dist/commands/channel/interrupt.d.ts.map +1 -0
  52. package/dist/commands/channel/interrupt.js +22 -0
  53. package/dist/commands/channel/interrupt.js.map +1 -0
  54. package/dist/commands/channel/kill.d.ts +7 -0
  55. package/dist/commands/channel/kill.d.ts.map +1 -0
  56. package/dist/commands/channel/kill.js +121 -0
  57. package/dist/commands/channel/kill.js.map +1 -0
  58. package/dist/commands/channel/list.d.ts +17 -0
  59. package/dist/commands/channel/list.d.ts.map +1 -0
  60. package/dist/commands/channel/list.js +233 -0
  61. package/dist/commands/channel/list.js.map +1 -0
  62. package/dist/commands/channel/messages.d.ts +15 -0
  63. package/dist/commands/channel/messages.d.ts.map +1 -0
  64. package/dist/commands/channel/messages.js +245 -0
  65. package/dist/commands/channel/messages.js.map +1 -0
  66. package/dist/commands/channel/rm.d.ts +27 -0
  67. package/dist/commands/channel/rm.d.ts.map +1 -0
  68. package/dist/commands/channel/rm.js +216 -0
  69. package/dist/commands/channel/rm.js.map +1 -0
  70. package/dist/commands/channel/run.d.ts +30 -0
  71. package/dist/commands/channel/run.d.ts.map +1 -0
  72. package/dist/commands/channel/run.js +130 -0
  73. package/dist/commands/channel/run.js.map +1 -0
  74. package/dist/commands/channel/send.d.ts +11 -0
  75. package/dist/commands/channel/send.d.ts.map +1 -0
  76. package/dist/commands/channel/send.js +24 -0
  77. package/dist/commands/channel/send.js.map +1 -0
  78. package/dist/commands/channel/spawn.d.ts +40 -0
  79. package/dist/commands/channel/spawn.d.ts.map +1 -0
  80. package/dist/commands/channel/spawn.js +244 -0
  81. package/dist/commands/channel/spawn.js.map +1 -0
  82. package/dist/commands/channel/store/events.d.ts +39 -0
  83. package/dist/commands/channel/store/events.d.ts.map +1 -0
  84. package/dist/commands/channel/store/events.js +87 -0
  85. package/dist/commands/channel/store/events.js.map +1 -0
  86. package/dist/commands/channel/store/filter.d.ts +3 -0
  87. package/dist/commands/channel/store/filter.d.ts.map +1 -0
  88. package/dist/commands/channel/store/filter.js +2 -0
  89. package/dist/commands/channel/store/filter.js.map +1 -0
  90. package/dist/commands/channel/store/lock.d.ts +23 -0
  91. package/dist/commands/channel/store/lock.d.ts.map +1 -0
  92. package/dist/commands/channel/store/lock.js +99 -0
  93. package/dist/commands/channel/store/lock.js.map +1 -0
  94. package/dist/commands/channel/store/paths.d.ts +63 -0
  95. package/dist/commands/channel/store/paths.d.ts.map +1 -0
  96. package/dist/commands/channel/store/paths.js +246 -0
  97. package/dist/commands/channel/store/paths.js.map +1 -0
  98. package/dist/commands/channel/store/schema.d.ts +27 -0
  99. package/dist/commands/channel/store/schema.d.ts.map +1 -0
  100. package/dist/commands/channel/store/schema.js +34 -0
  101. package/dist/commands/channel/store/schema.js.map +1 -0
  102. package/dist/commands/channel/store/thread-state.d.ts +5 -0
  103. package/dist/commands/channel/store/thread-state.d.ts.map +1 -0
  104. package/dist/commands/channel/store/thread-state.js +16 -0
  105. package/dist/commands/channel/store/thread-state.js.map +1 -0
  106. package/dist/commands/channel/store/watch.d.ts +19 -0
  107. package/dist/commands/channel/store/watch.d.ts.map +1 -0
  108. package/dist/commands/channel/store/watch.js +146 -0
  109. package/dist/commands/channel/store/watch.js.map +1 -0
  110. package/dist/commands/channel/supervisor/idle.d.ts +46 -0
  111. package/dist/commands/channel/supervisor/idle.d.ts.map +1 -0
  112. package/dist/commands/channel/supervisor/idle.js +72 -0
  113. package/dist/commands/channel/supervisor/idle.js.map +1 -0
  114. package/dist/commands/channel/supervisor/inbox.d.ts +30 -0
  115. package/dist/commands/channel/supervisor/inbox.d.ts.map +1 -0
  116. package/dist/commands/channel/supervisor/inbox.js +160 -0
  117. package/dist/commands/channel/supervisor/inbox.js.map +1 -0
  118. package/dist/commands/channel/supervisor/shutdown.d.ts +68 -0
  119. package/dist/commands/channel/supervisor/shutdown.d.ts.map +1 -0
  120. package/dist/commands/channel/supervisor/shutdown.js +146 -0
  121. package/dist/commands/channel/supervisor/shutdown.js.map +1 -0
  122. package/dist/commands/channel/supervisor/stdout.d.ts +51 -0
  123. package/dist/commands/channel/supervisor/stdout.d.ts.map +1 -0
  124. package/dist/commands/channel/supervisor/stdout.js +121 -0
  125. package/dist/commands/channel/supervisor/stdout.js.map +1 -0
  126. package/dist/commands/channel/supervisor/turns.d.ts +31 -0
  127. package/dist/commands/channel/supervisor/turns.d.ts.map +1 -0
  128. package/dist/commands/channel/supervisor/turns.js +45 -0
  129. package/dist/commands/channel/supervisor/turns.js.map +1 -0
  130. package/dist/commands/channel/supervisor/warning.d.ts +48 -0
  131. package/dist/commands/channel/supervisor/warning.d.ts.map +1 -0
  132. package/dist/commands/channel/supervisor/warning.js +77 -0
  133. package/dist/commands/channel/supervisor/warning.js.map +1 -0
  134. package/dist/commands/channel/supervisor.d.ts +59 -0
  135. package/dist/commands/channel/supervisor.d.ts.map +1 -0
  136. package/dist/commands/channel/supervisor.js +344 -0
  137. package/dist/commands/channel/supervisor.js.map +1 -0
  138. package/dist/commands/channel/text-body.d.ts +13 -0
  139. package/dist/commands/channel/text-body.d.ts.map +1 -0
  140. package/dist/commands/channel/text-body.js +47 -0
  141. package/dist/commands/channel/text-body.js.map +1 -0
  142. package/dist/commands/channel/threads.d.ts +39 -0
  143. package/dist/commands/channel/threads.d.ts.map +1 -0
  144. package/dist/commands/channel/threads.js +106 -0
  145. package/dist/commands/channel/threads.js.map +1 -0
  146. package/dist/commands/channel/title.d.ts +12 -0
  147. package/dist/commands/channel/title.d.ts.map +1 -0
  148. package/dist/commands/channel/title.js +24 -0
  149. package/dist/commands/channel/title.js.map +1 -0
  150. package/dist/commands/channel/wait.d.ts +17 -0
  151. package/dist/commands/channel/wait.d.ts.map +1 -0
  152. package/dist/commands/channel/wait.js +75 -0
  153. package/dist/commands/channel/wait.js.map +1 -0
  154. package/dist/commands/init.d.ts +2 -0
  155. package/dist/commands/init.d.ts.map +1 -1
  156. package/dist/commands/init.js +97 -42
  157. package/dist/commands/init.js.map +1 -1
  158. package/dist/commands/mem.d.ts +13 -117
  159. package/dist/commands/mem.d.ts.map +1 -1
  160. package/dist/commands/mem.js +168 -1074
  161. package/dist/commands/mem.js.map +1 -1
  162. package/dist/commands/uninstall.d.ts.map +1 -1
  163. package/dist/commands/uninstall.js +28 -2
  164. package/dist/commands/uninstall.js.map +1 -1
  165. package/dist/commands/update.d.ts.map +1 -1
  166. package/dist/commands/update.js +31 -111
  167. package/dist/commands/update.js.map +1 -1
  168. package/dist/commands/upgrade.d.ts +28 -0
  169. package/dist/commands/upgrade.d.ts.map +1 -0
  170. package/dist/commands/upgrade.js +84 -0
  171. package/dist/commands/upgrade.js.map +1 -0
  172. package/dist/commands/workflow.d.ts +35 -0
  173. package/dist/commands/workflow.d.ts.map +1 -0
  174. package/dist/commands/workflow.js +219 -0
  175. package/dist/commands/workflow.js.map +1 -0
  176. package/dist/configurators/claude.d.ts.map +1 -1
  177. package/dist/configurators/claude.js +1 -0
  178. package/dist/configurators/claude.js.map +1 -1
  179. package/dist/configurators/codex.d.ts.map +1 -1
  180. package/dist/configurators/codex.js +5 -3
  181. package/dist/configurators/codex.js.map +1 -1
  182. package/dist/configurators/shared.js +4 -4
  183. package/dist/configurators/shared.js.map +1 -1
  184. package/dist/configurators/workflow.d.ts +8 -0
  185. package/dist/configurators/workflow.d.ts.map +1 -1
  186. package/dist/configurators/workflow.js +3 -2
  187. package/dist/configurators/workflow.js.map +1 -1
  188. package/dist/migrations/manifests/0.5.10.json +9 -0
  189. package/dist/migrations/manifests/0.5.11.json +16 -0
  190. package/dist/migrations/manifests/0.5.12.json +9 -0
  191. package/dist/migrations/manifests/0.5.13.json +9 -0
  192. package/dist/migrations/manifests/0.5.14.json +9 -0
  193. package/dist/migrations/manifests/0.5.15.json +9 -0
  194. package/dist/migrations/manifests/0.5.16.json +9 -0
  195. package/dist/migrations/manifests/0.5.17.json +9 -0
  196. package/dist/migrations/manifests/0.5.18.json +9 -0
  197. package/dist/migrations/manifests/0.6.0-beta.10.json +9 -0
  198. package/dist/migrations/manifests/0.6.0-beta.11.json +9 -0
  199. package/dist/migrations/manifests/0.6.0-beta.12.json +9 -0
  200. package/dist/migrations/manifests/0.6.0-beta.13.json +9 -0
  201. package/dist/migrations/manifests/0.6.0-beta.14.json +9 -0
  202. package/dist/migrations/manifests/0.6.0-beta.15.json +9 -0
  203. package/dist/migrations/manifests/0.6.0-beta.16.json +9 -0
  204. package/dist/migrations/manifests/0.6.0-beta.17.json +9 -0
  205. package/dist/migrations/manifests/0.6.0-beta.18.json +16 -0
  206. package/dist/migrations/manifests/0.6.0-beta.19.json +9 -0
  207. package/dist/migrations/manifests/0.6.0-beta.20.json +9 -0
  208. package/dist/migrations/manifests/0.6.0-beta.21.json +9 -0
  209. package/dist/migrations/manifests/0.6.0-beta.3.json +9 -0
  210. package/dist/migrations/manifests/0.6.0-beta.4.json +9 -0
  211. package/dist/migrations/manifests/0.6.0-beta.5.json +9 -0
  212. package/dist/migrations/manifests/0.6.0-beta.6.json +16 -0
  213. package/dist/migrations/manifests/0.6.0-beta.7.json +9 -0
  214. package/dist/migrations/manifests/0.6.0-beta.8.json +9 -0
  215. package/dist/migrations/manifests/0.6.0-beta.9.json +9 -0
  216. package/dist/templates/claude/agents/trellis-check.md +13 -7
  217. package/dist/templates/claude/agents/trellis-implement.md +8 -7
  218. package/dist/templates/claude/settings.json +4 -4
  219. package/dist/templates/codebuddy/agents/trellis-check.md +13 -7
  220. package/dist/templates/codebuddy/agents/trellis-implement.md +8 -7
  221. package/dist/templates/codebuddy/settings.json +4 -4
  222. package/dist/templates/codex/agents/trellis-check.toml +4 -4
  223. package/dist/templates/codex/agents/trellis-implement.toml +4 -4
  224. package/dist/templates/codex/config.toml +9 -16
  225. package/dist/templates/codex/hooks/session-start.py +205 -119
  226. package/dist/templates/codex/hooks.json +2 -2
  227. package/dist/templates/codex/skills/before-dev/SKILL.md +12 -6
  228. package/dist/templates/codex/skills/brainstorm/SKILL.md +69 -457
  229. package/dist/templates/codex/skills/check/SKILL.md +86 -18
  230. package/dist/templates/codex/skills/start/SKILL.md +33 -323
  231. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-context-loading.md +7 -4
  232. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-spec-structure.md +1 -1
  233. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-workflow.md +3 -2
  234. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/context-injection.md +5 -5
  235. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/spec-system.md +1 -1
  236. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/task-system.md +35 -6
  237. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/agents.md +5 -4
  238. package/dist/templates/common/bundled-skills/trellis-spec-bootstarp/SKILL.md +41 -0
  239. package/dist/templates/common/bundled-skills/trellis-spec-bootstarp/references/mcp-setup.md +90 -0
  240. package/dist/templates/common/bundled-skills/trellis-spec-bootstarp/references/repository-analysis.md +59 -0
  241. package/dist/templates/common/bundled-skills/trellis-spec-bootstarp/references/spec-task-planning.md +61 -0
  242. package/dist/templates/common/bundled-skills/trellis-spec-bootstarp/references/spec-writing.md +70 -0
  243. package/dist/templates/common/commands/continue.md +6 -5
  244. package/dist/templates/common/commands/start.md +9 -6
  245. package/dist/templates/common/skills/before-dev.md +12 -6
  246. package/dist/templates/common/skills/brainstorm.md +68 -504
  247. package/dist/templates/common/skills/check.md +7 -1
  248. package/dist/templates/copilot/hooks/session-start.py +219 -101
  249. package/dist/templates/copilot/hooks.json +2 -2
  250. package/dist/templates/copilot/prompts/before-dev.prompt.md +12 -6
  251. package/dist/templates/copilot/prompts/brainstorm.prompt.md +69 -457
  252. package/dist/templates/copilot/prompts/check.prompt.md +86 -18
  253. package/dist/templates/copilot/prompts/parallel.prompt.md +16 -8
  254. package/dist/templates/copilot/prompts/start.prompt.md +33 -367
  255. package/dist/templates/cursor/agents/trellis-check.md +13 -7
  256. package/dist/templates/cursor/agents/trellis-implement.md +8 -7
  257. package/dist/templates/cursor/hooks.json +1 -7
  258. package/dist/templates/droid/droids/trellis-check.md +13 -7
  259. package/dist/templates/droid/droids/trellis-implement.md +8 -7
  260. package/dist/templates/droid/settings.json +4 -4
  261. package/dist/templates/gemini/agents/trellis-check.md +11 -5
  262. package/dist/templates/gemini/agents/trellis-implement.md +7 -6
  263. package/dist/templates/gemini/settings.json +2 -2
  264. package/dist/templates/kiro/agents/trellis-check.json +1 -1
  265. package/dist/templates/kiro/agents/trellis-implement.json +1 -1
  266. package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +127 -9
  267. package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +171 -6
  268. package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +333 -43
  269. package/dist/templates/markdown/spec/guides/index.md.txt +18 -0
  270. package/dist/templates/opencode/agents/trellis-check.md +13 -7
  271. package/dist/templates/opencode/agents/trellis-implement.md +9 -8
  272. package/dist/templates/opencode/lib/session-utils.js +212 -123
  273. package/dist/templates/opencode/lib/trellis-context.js +73 -11
  274. package/dist/templates/opencode/plugins/inject-subagent-context.js +131 -29
  275. package/dist/templates/opencode/plugins/inject-workflow-state.js +9 -5
  276. package/dist/templates/opencode/plugins/session-start.js +9 -1
  277. package/dist/templates/pi/agents/trellis-check.md +5 -4
  278. package/dist/templates/pi/agents/trellis-implement.md +5 -4
  279. package/dist/templates/pi/extensions/trellis/index.ts.txt +1357 -754
  280. package/dist/templates/qoder/agents/trellis-check.md +11 -5
  281. package/dist/templates/qoder/agents/trellis-implement.md +7 -6
  282. package/dist/templates/qoder/settings.json +4 -4
  283. package/dist/templates/shared-hooks/index.d.ts.map +1 -1
  284. package/dist/templates/shared-hooks/index.js +0 -1
  285. package/dist/templates/shared-hooks/index.js.map +1 -1
  286. package/dist/templates/shared-hooks/inject-subagent-context.py +36 -14
  287. package/dist/templates/shared-hooks/inject-workflow-state.py +40 -42
  288. package/dist/templates/shared-hooks/session-start.py +222 -171
  289. package/dist/templates/trellis/config.yaml +38 -0
  290. package/dist/templates/trellis/index.d.ts +1 -0
  291. package/dist/templates/trellis/index.d.ts.map +1 -1
  292. package/dist/templates/trellis/index.js +2 -0
  293. package/dist/templates/trellis/index.js.map +1 -1
  294. package/dist/templates/trellis/scripts/add_session.py +50 -24
  295. package/dist/templates/trellis/scripts/common/config.py +57 -1
  296. package/dist/templates/trellis/scripts/common/safe_commit.py +285 -0
  297. package/dist/templates/trellis/scripts/common/session_context.py +384 -137
  298. package/dist/templates/trellis/scripts/common/task_context.py +3 -3
  299. package/dist/templates/trellis/scripts/common/task_store.py +161 -15
  300. package/dist/templates/trellis/scripts/common/workflow_phase.py +7 -10
  301. package/dist/templates/trellis/scripts/task.py +3 -3
  302. package/dist/templates/trellis/workflow.md +119 -98
  303. package/dist/utils/cwd-guard.d.ts +38 -0
  304. package/dist/utils/cwd-guard.d.ts.map +1 -0
  305. package/dist/utils/cwd-guard.js +62 -0
  306. package/dist/utils/cwd-guard.js.map +1 -0
  307. package/dist/utils/file-writer.d.ts +13 -0
  308. package/dist/utils/file-writer.d.ts.map +1 -1
  309. package/dist/utils/file-writer.js +59 -1
  310. package/dist/utils/file-writer.js.map +1 -1
  311. package/dist/utils/manifest-prune.d.ts +61 -0
  312. package/dist/utils/manifest-prune.d.ts.map +1 -0
  313. package/dist/utils/manifest-prune.js +136 -0
  314. package/dist/utils/manifest-prune.js.map +1 -0
  315. package/dist/utils/task-json.d.ts +9 -42
  316. package/dist/utils/task-json.d.ts.map +1 -1
  317. package/dist/utils/task-json.js +8 -45
  318. package/dist/utils/task-json.js.map +1 -1
  319. package/dist/utils/template-hash.d.ts +32 -6
  320. package/dist/utils/template-hash.d.ts.map +1 -1
  321. package/dist/utils/template-hash.js +53 -31
  322. package/dist/utils/template-hash.js.map +1 -1
  323. package/dist/utils/uninstall-scrubbers.d.ts +1 -0
  324. package/dist/utils/uninstall-scrubbers.d.ts.map +1 -1
  325. package/dist/utils/uninstall-scrubbers.js +21 -0
  326. package/dist/utils/uninstall-scrubbers.js.map +1 -1
  327. package/dist/utils/workflow-resolver.d.ts +86 -0
  328. package/dist/utils/workflow-resolver.d.ts.map +1 -0
  329. package/dist/utils/workflow-resolver.js +265 -0
  330. package/dist/utils/workflow-resolver.js.map +1 -0
  331. package/package.json +9 -8
@@ -18,6 +18,28 @@ import warnings
18
18
  from io import StringIO
19
19
  from pathlib import Path
20
20
 
21
+ # Force UTF-8 on stdin/stdout/stderr on Windows. Default codepage there is
22
+ # cp936 / cp1252 / etc. — non-ASCII content (Chinese task names, prd snippets)
23
+ # both in stdin (hook payload from host CLI) and stdout (our emitted blocks)
24
+ # raises UnicodeDecodeError / UnicodeEncodeError. Equivalent to `python -X utf8`
25
+ # but applied per-stream so we don't depend on host CLI's command wiring.
26
+ if sys.platform.startswith("win"):
27
+ import io as _io
28
+ for _stream_name in ("stdin", "stdout", "stderr"):
29
+ _stream = getattr(sys, _stream_name, None)
30
+ if _stream is None:
31
+ continue
32
+ if hasattr(_stream, "reconfigure"):
33
+ try:
34
+ _stream.reconfigure(encoding="utf-8", errors="replace") # type: ignore[union-attr]
35
+ except Exception:
36
+ pass
37
+ elif hasattr(_stream, "detach"):
38
+ try:
39
+ setattr(sys, _stream_name, _io.TextIOWrapper(_stream.detach(), encoding="utf-8", errors="replace"))
40
+ except Exception:
41
+ pass
42
+
21
43
 
22
44
  def _normalize_windows_shell_path(path_str: str) -> str:
23
45
  """Normalize Unix-style shell paths to real Windows paths.
@@ -75,23 +97,6 @@ Trellis SessionStart 已注入:workflow、当前任务状态、开发者身份
75
97
  Then continue directly with the user's request. This notice is one-shot: do not repeat it after the first assistant reply in the same session.
76
98
  </first-reply-notice>"""
77
99
 
78
- SUB_AGENT_NOTICE = """<sub-agent-notice>
79
- SUB-AGENT NOTICE - READ FIRST IF SPAWNED VIA spawn_agent
80
-
81
- If your parent session spawned you via spawn_agent with an explicit task
82
- message above this hook output, that message is your only job.
83
- - Execute the parent message exactly as written, then return.
84
- - Ignore all Trellis workflow guidance below this notice.
85
- - Do NOT call task.py start, task.py add-context, or task.py archive.
86
- - Do NOT call wait_agent or spawn_agent.
87
- - Do NOT modify .trellis/tasks/* or any other file unless the parent message
88
- explicitly asks for that.
89
-
90
- If you are the main interactive Codex session and the user is typing at the
91
- terminal with no parent agent, use the workflow guidance below normally.
92
- </sub-agent-notice>"""
93
-
94
-
95
100
  def should_skip_injection() -> bool:
96
101
  if os.environ.get("TRELLIS_HOOKS") == "0":
97
102
  return True
@@ -218,12 +223,19 @@ def _resolve_task_dir(trellis_dir: Path, task_ref: str) -> Path:
218
223
  def _get_task_status(trellis_dir: Path, hook_input: dict) -> str:
219
224
  active = _resolve_active_task(trellis_dir, hook_input)
220
225
  if not active.task_path:
221
- return f"Status: NO ACTIVE TASK\nSource: {active.source}\nNext: Describe what you want to work on"
226
+ return (
227
+ "Status: NO ACTIVE TASK\n"
228
+ "Next: Classify the current turn and ask for task-creation consent "
229
+ "before creating any Trellis task."
230
+ )
222
231
 
223
232
  task_ref = active.task_path
224
233
  task_dir = _resolve_task_dir(trellis_dir, task_ref)
225
234
  if active.stale or not task_dir.is_dir():
226
- return f"Status: STALE POINTER\nTask: {task_ref}\nSource: {active.source}\nNext: Task directory not found. Run: python3 ./.trellis/scripts/task.py finish"
235
+ return (
236
+ f"Status: STALE POINTER\nTask: {task_ref}\n"
237
+ "Next: Task directory not found. Run: python3 ./.trellis/scripts/task.py finish"
238
+ )
227
239
 
228
240
  task_json_path = task_dir / "task.json"
229
241
  task_data: dict = {}
@@ -237,40 +249,170 @@ def _get_task_status(trellis_dir: Path, hook_input: dict) -> str:
237
249
  task_status = task_data.get("status", "unknown")
238
250
 
239
251
  if task_status == "completed":
240
- return f"Status: COMPLETED\nTask: {task_title}\nSource: {active.source}\nNext: Archive with `python3 ./.trellis/scripts/task.py archive {task_dir.name}` or start a new task"
241
-
242
- has_context = False
243
- for jsonl_name in ("implement.jsonl", "check.jsonl", "spec.jsonl"):
244
- jsonl_path = task_dir / jsonl_name
245
- if jsonl_path.is_file() and _has_curated_jsonl_entry(jsonl_path):
246
- has_context = True
247
- break
252
+ return (
253
+ f"Status: COMPLETED\nTask: {task_title}\n"
254
+ f"Next: Archive with `python3 ./.trellis/scripts/task.py archive {task_dir.name}` "
255
+ "or start a new task."
256
+ )
248
257
 
249
258
  has_prd = (task_dir / "prd.md").is_file()
259
+ has_design = (task_dir / "design.md").is_file()
260
+ has_implement = (task_dir / "implement.md").is_file()
261
+ present = [
262
+ name
263
+ for name in ("prd.md", "design.md", "implement.md", "implement.jsonl", "check.jsonl")
264
+ if (task_dir / name).is_file()
265
+ ]
266
+ present_line = ", ".join(present) if present else "none"
250
267
 
251
268
  if not has_prd:
252
- return f"Status: NOT READY\nTask: {task_title}\nSource: {active.source}\nMissing: prd.md not created\nNext: Write PRD (see workflow.md Phase 1.1) then curate implement.jsonl per Phase 1.3"
269
+ return (
270
+ f"Status: PLANNING\nTask: {task_title}\nPresent: {present_line}\n"
271
+ "Next: Load trellis-brainstorm and write prd.md. Stay in planning."
272
+ )
253
273
 
254
- if not has_context:
255
- return f"Status: NOT READY\nTask: {task_title}\nSource: {active.source}\nMissing: implement.jsonl / check.jsonl missing or empty\nNext: Curate entries per workflow.md Phase 1.3 (spec + research files only), then `task.py start`"
274
+ if task_status == "planning":
275
+ if has_design and has_implement:
276
+ next_action = "Review planning artifacts with the user before `task.py start`."
277
+ else:
278
+ next_action = (
279
+ "Lightweight task can ask for start review with PRD-only; "
280
+ "complex task must add design.md and implement.md before `task.py start`."
281
+ )
282
+ return (
283
+ f"Status: PLANNING\nTask: {task_title}\nPresent: {present_line}\n"
284
+ f"Next: {next_action}"
285
+ )
256
286
 
257
287
  return (
258
- f"Status: READY\nTask: {task_title}\n"
259
- f"Source: {active.source}\n"
260
- "Next required action: dispatch `trellis-implement` per Phase 2.1. "
261
- "For agent-capable platforms, the default is to NOT edit code in the main session. "
262
- "After implementation, dispatch `trellis-check` per Phase 2.2 before reporting completion.\n"
263
- "Sub-agent self-exemption: if you are reading this as a `trellis-implement` or "
264
- "`trellis-check` sub-agent (your own role / agent name reflects that), this dispatch "
265
- "instruction does NOT apply to you — you are already the dispatched sub-agent. "
266
- "Implement / check directly without spawning another sub-agent of the same kind.\n"
267
- "User override (per-turn escape hatch): if the user's CURRENT message explicitly tells the "
268
- "main session to handle it directly (\"你直接改\" / \"别派 sub-agent\" / \"main session 写就行\" / "
269
- "\"do it inline\" / \"不用 sub-agent\"), honor it for this turn and edit code directly. "
270
- "Per-turn only; do NOT invent an override the user did not say."
288
+ f"Status: {task_status.upper()}\nTask: {task_title}\nPresent: {present_line}\n"
289
+ "Next: Follow the matching per-turn workflow-state. Context order is jsonl entries, "
290
+ "prd.md, design.md if present, implement.md if present."
271
291
  )
272
292
 
273
293
 
294
+ def _run_git(repo_root: Path, args: list[str]) -> str:
295
+ try:
296
+ result = subprocess.run(
297
+ ["git", *args],
298
+ capture_output=True,
299
+ text=True,
300
+ encoding="utf-8",
301
+ errors="replace",
302
+ timeout=3,
303
+ cwd=str(repo_root),
304
+ )
305
+ except (subprocess.TimeoutExpired, FileNotFoundError, PermissionError):
306
+ return ""
307
+ if result.returncode != 0:
308
+ return ""
309
+ return result.stdout.strip()
310
+
311
+
312
+ def _format_git_state(repo_root: Path) -> str:
313
+ branch = _run_git(repo_root, ["branch", "--show-current"]) or "(detached)"
314
+ dirty_lines = [
315
+ line for line in _run_git(repo_root, ["status", "--porcelain"]).splitlines()
316
+ if line.strip()
317
+ ]
318
+ dirty_text = "clean" if not dirty_lines else f"dirty {len(dirty_lines)} paths"
319
+ return f"Git: branch {branch}; {dirty_text}."
320
+
321
+
322
+ def _repo_relative(repo_root: Path, path: Path) -> str:
323
+ try:
324
+ return path.relative_to(repo_root).as_posix()
325
+ except ValueError:
326
+ return str(path)
327
+
328
+
329
+ def _collect_spec_index_paths(trellis_dir: Path) -> list[str]:
330
+ paths: list[str] = []
331
+ guides_index = trellis_dir / "spec" / "guides" / "index.md"
332
+ if guides_index.is_file():
333
+ paths.append(".trellis/spec/guides/index.md")
334
+
335
+ spec_dir = trellis_dir / "spec"
336
+ if not spec_dir.is_dir():
337
+ return paths
338
+
339
+ for sub in sorted(spec_dir.iterdir()):
340
+ if not sub.is_dir() or sub.name.startswith(".") or sub.name == "guides":
341
+ continue
342
+ index_file = sub / "index.md"
343
+ if index_file.is_file():
344
+ paths.append(f".trellis/spec/{sub.name}/index.md")
345
+ continue
346
+ for nested in sorted(sub.iterdir()):
347
+ if not nested.is_dir():
348
+ continue
349
+ nested_index = nested / "index.md"
350
+ if nested_index.is_file():
351
+ paths.append(f".trellis/spec/{sub.name}/{nested.name}/index.md")
352
+
353
+ return paths
354
+
355
+
356
+ def _build_compact_current_state(
357
+ trellis_dir: Path,
358
+ hook_input: dict,
359
+ spec_index_paths: list[str],
360
+ ) -> str:
361
+ repo_root = trellis_dir.parent
362
+ lines: list[str] = []
363
+
364
+ try:
365
+ from common.paths import get_active_journal_file, get_developer, get_tasks_dir, count_lines # type: ignore[import-not-found]
366
+ from common.tasks import iter_active_tasks # type: ignore[import-not-found]
367
+ except Exception:
368
+ get_active_journal_file = None # type: ignore[assignment]
369
+ get_developer = None # type: ignore[assignment]
370
+ get_tasks_dir = None # type: ignore[assignment]
371
+ count_lines = None # type: ignore[assignment]
372
+ iter_active_tasks = None # type: ignore[assignment]
373
+
374
+ developer = get_developer(repo_root) if get_developer else None
375
+ lines.append(f"Developer: {developer or '(not initialized)'}")
376
+ lines.append(_format_git_state(repo_root))
377
+
378
+ active = _resolve_active_task(trellis_dir, hook_input)
379
+ if active.task_path:
380
+ task_dir = _resolve_task_dir(trellis_dir, active.task_path)
381
+ status = "unknown"
382
+ task_json = task_dir / "task.json"
383
+ if task_json.is_file():
384
+ try:
385
+ data = json.loads(task_json.read_text(encoding="utf-8"))
386
+ if isinstance(data, dict):
387
+ status = str(data.get("status") or "unknown")
388
+ except (json.JSONDecodeError, OSError):
389
+ pass
390
+ lines.append(f"Current task: {_repo_relative(repo_root, task_dir)}; status={status}.")
391
+ else:
392
+ lines.append("Current task: none.")
393
+
394
+ if get_tasks_dir and iter_active_tasks:
395
+ try:
396
+ task_count = sum(1 for _ in iter_active_tasks(get_tasks_dir(repo_root)))
397
+ lines.append(
398
+ f"Active tasks: {task_count} total. Use `python3 ./.trellis/scripts/task.py list --mine` only if needed."
399
+ )
400
+ except Exception:
401
+ pass
402
+
403
+ if get_active_journal_file and count_lines:
404
+ journal = get_active_journal_file(repo_root)
405
+ if journal:
406
+ lines.append(
407
+ f"Journal: {_repo_relative(repo_root, journal)}, {count_lines(journal)} / 2000 lines."
408
+ )
409
+
410
+ if spec_index_paths:
411
+ lines.append(f"Spec indexes: {len(spec_index_paths)} available.")
412
+
413
+ return "\n".join(lines)
414
+
415
+
274
416
  def _extract_range(content: str, start_header: str, end_header: str) -> str:
275
417
  """Extract lines starting at `## start_header` up to (but excluding) `## end_header`."""
276
418
  lines = content.splitlines()
@@ -298,33 +440,25 @@ _BREADCRUMB_TAG_RE = re.compile(
298
440
 
299
441
 
300
442
  def _strip_breadcrumb_tag_blocks(content: str) -> str:
301
- return _BREADCRUMB_TAG_RE.sub("", content)
443
+ stripped = _BREADCRUMB_TAG_RE.sub("", content)
444
+ stripped = re.sub(r"<!--.*?-->", "", stripped, flags=re.DOTALL)
445
+ stripped = re.sub(r"^\[(?!/?workflow-state:)/?[^\]\n]+\]\s*\n?", "", stripped, flags=re.MULTILINE)
446
+ return re.sub(r"\n{3,}", "\n\n", stripped).strip()
302
447
 
303
448
 
304
449
  def _build_workflow_toc(workflow_path: Path) -> str:
305
- """Inject workflow guide: TOC + Phase Index + Phase 1/2/3 step details.
306
-
307
- Since v0.5.0-rc.0 the [workflow-state:STATUS] breadcrumb tag blocks
308
- live inside ## Phase Index. They're consumed by inject-workflow-state.py
309
- on each UserPromptSubmit, so strip them from the session-start payload
310
- to avoid duplicating context.
311
- """
450
+ """Inject only the compact Phase Index summary for SessionStart."""
312
451
  content = read_file(workflow_path)
313
452
  if not content:
314
453
  return "No workflow.md found"
315
454
 
316
455
  out_lines = [
317
- "# Development Workflow Section Index",
318
- "Full guide: .trellis/workflow.md (read on demand)",
456
+ "# Development Workflow - Session Summary",
457
+ "Full guide: .trellis/workflow.md. Step detail: `python3 ./.trellis/scripts/get_context.py --mode phase --step <X.Y>`.",
319
458
  "",
320
- "## Table of Contents",
321
459
  ]
322
- for line in content.splitlines():
323
- if line.startswith("## "):
324
- out_lines.append(line)
325
- out_lines += ["", "---", ""]
326
460
 
327
- phases = _extract_range(content, "Phase Index", "Customizing Trellis (for forks)")
461
+ phases = _extract_range(content, "Phase Index", "Phase 1: Plan")
328
462
  if phases:
329
463
  out_lines.append(_strip_breadcrumb_tag_blocks(phases).rstrip())
330
464
 
@@ -348,16 +482,12 @@ def main() -> None:
348
482
  configure_project_encoding(project_dir)
349
483
 
350
484
  trellis_dir = project_dir / ".trellis"
351
- context_key = _resolve_context_key(project_dir, hook_input)
485
+ spec_index_paths = _collect_spec_index_paths(trellis_dir)
352
486
 
353
487
  output = StringIO()
354
488
 
355
- output.write(SUB_AGENT_NOTICE)
356
- output.write("\n\n")
357
-
358
489
  output.write("""<session-context>
359
- You are starting a new session in a Trellis-managed project.
360
- Read and follow all instructions below carefully.
490
+ Trellis compact SessionStart context. Use it to orient the session; load details on demand.
361
491
  </session-context>
362
492
 
363
493
  """)
@@ -365,65 +495,23 @@ Read and follow all instructions below carefully.
365
495
  output.write("\n\n")
366
496
 
367
497
  output.write("<current-state>\n")
368
- context_script = trellis_dir / "scripts" / "get_context.py"
369
- output.write(run_script(context_script, context_key))
498
+ output.write(_build_compact_current_state(trellis_dir, hook_input, spec_index_paths))
370
499
  output.write("\n</current-state>\n\n")
371
500
 
372
- output.write("<workflow>\n")
501
+ output.write("<trellis-workflow>\n")
373
502
  output.write(_build_workflow_toc(trellis_dir / "workflow.md"))
374
- output.write("\n</workflow>\n\n")
503
+ output.write("\n</trellis-workflow>\n\n")
375
504
 
376
505
  output.write("<guidelines>\n")
377
506
  output.write(
378
- "Project spec indexes are listed by path below. Each index contains a "
379
- "**Pre-Development Checklist** listing the specific guideline files to "
380
- "read before coding.\n\n"
381
- "- If you're spawning an implement/check sub-agent, context is injected "
382
- "automatically via `{task}/implement.jsonl` / `check.jsonl`. You do NOT "
383
- "need to read these indexes yourself.\n"
384
- "- For agent-capable platforms, the default is to dispatch "
385
- "`trellis-implement` and `trellis-check` (so JSONL context is loaded by "
386
- "the sub-agents) rather than editing code in the main session. "
387
- "Honor a per-turn user override only if the user's current message "
388
- "explicitly opts out (see <task-status> below for override phrases).\n"
389
- "- Sub-agent self-exemption: if you are reading this as a `trellis-implement` "
390
- "or `trellis-check` sub-agent, the \"dispatch trellis-implement / trellis-check\" "
391
- "rule above does NOT apply to you — you are already the dispatched sub-agent. "
392
- "Do NOT spawn another sub-agent of the same kind; implement / check directly.\n\n"
507
+ "Task context order for implementation/check: jsonl entries -> `prd.md` -> "
508
+ "`design.md if present` -> `implement.md if present`. Missing optional artifacts "
509
+ "are skipped for lightweight tasks.\n\n"
393
510
  )
394
511
 
395
- # guides/ inlined (cross-package thinking, broadly useful)
396
- guides_index = trellis_dir / "spec" / "guides" / "index.md"
397
- if guides_index.is_file():
398
- output.write("## guides (inlined — cross-package thinking guides)\n")
399
- output.write(read_file(guides_index))
400
- output.write("\n\n")
401
-
402
- # Other indexes — paths only
403
- paths: list[str] = []
404
- spec_dir = trellis_dir / "spec"
405
- if spec_dir.is_dir():
406
- for sub in sorted(spec_dir.iterdir()):
407
- if not sub.is_dir() or sub.name.startswith("."):
408
- continue
409
- if sub.name == "guides":
410
- continue
411
- index_file = sub / "index.md"
412
- if index_file.is_file():
413
- paths.append(f".trellis/spec/{sub.name}/index.md")
414
- else:
415
- for nested in sorted(sub.iterdir()):
416
- if not nested.is_dir():
417
- continue
418
- nested_index = nested / "index.md"
419
- if nested_index.is_file():
420
- paths.append(
421
- f".trellis/spec/{sub.name}/{nested.name}/index.md"
422
- )
423
-
424
- if paths:
425
- output.write("## Available spec indexes (read on demand)\n")
426
- for p in paths:
512
+ if spec_index_paths:
513
+ output.write("## Available indexes (read on demand)\n")
514
+ for p in spec_index_paths:
427
515
  output.write(f"- {p}\n")
428
516
  output.write("\n")
429
517
 
@@ -437,9 +525,7 @@ Read and follow all instructions below carefully.
437
525
  output.write(f"<task-status>\n{task_status}\n</task-status>\n\n")
438
526
 
439
527
  output.write("""<ready>
440
- Context loaded. Workflow index, project state, and guidelines are already injected above — do NOT re-read them.
441
- When the user sends the first message, follow <task-status> and the workflow guide.
442
- If a task is READY, execute its Next required action without asking whether to continue.
528
+ Context loaded. Follow <task-status>. Load workflow/spec/task details only when needed.
443
529
  </ready>""")
444
530
 
445
531
  context = output.getvalue()
@@ -5,8 +5,8 @@
5
5
  "hooks": [
6
6
  {
7
7
  "type": "command",
8
- "command": "{{PYTHON_CMD}} .codex/hooks/inject-workflow-state.py",
9
- "timeout": 5
8
+ "command": "{{PYTHON_CMD}} -X utf8 .codex/hooks/inject-workflow-state.py",
9
+ "timeout": 15
10
10
  }
11
11
  ]
12
12
  }
@@ -7,28 +7,34 @@ Read the relevant development guidelines before starting your task.
7
7
 
8
8
  Execute these steps:
9
9
 
10
- 1. **Discover packages and their spec layers**:
10
+ 1. **Read current task artifacts**:
11
+ - `prd.md` for requirements and acceptance criteria
12
+ - `design.md` if present for technical design
13
+ - `implement.md` if present for execution order and validation plan
14
+
15
+ 2. **Discover packages and their spec layers**:
11
16
  ```bash
12
17
  python3 ./.trellis/scripts/get_context.py --mode packages
13
18
  ```
14
19
 
15
- 2. **Identify which specs apply** to your task based on:
20
+ 3. **Identify which specs apply** to your task based on:
16
21
  - Which package you're modifying (e.g., `cli/`, `docs-site/`)
17
22
  - What type of work (backend, frontend, unit-test, docs, etc.)
23
+ - Any spec/research paths referenced by the task artifacts
18
24
 
19
- 3. **Read the spec index** for each relevant module:
25
+ 4. **Read the spec index** for each relevant module:
20
26
  ```bash
21
27
  cat .trellis/spec/<package>/<layer>/index.md
22
28
  ```
23
29
  Follow the **"Pre-Development Checklist"** section in the index.
24
30
 
25
- 4. **Read the specific guideline files** listed in the Pre-Development Checklist that are relevant to your task. The index is NOT the goal — it points you to the actual guideline files (e.g., `error-handling.md`, `conventions.md`, `mock-strategies.md`). Read those files to understand the coding standards and patterns.
31
+ 5. **Read the specific guideline files** listed in the Pre-Development Checklist that are relevant to your task. The index is NOT the goal — it points you to the actual guideline files (e.g., `error-handling.md`, `conventions.md`, `mock-strategies.md`). Read those files to understand the coding standards and patterns.
26
32
 
27
- 5. **Always read shared guides**:
33
+ 6. **Always read shared guides**:
28
34
  ```bash
29
35
  cat .trellis/spec/guides/index.md
30
36
  ```
31
37
 
32
- 6. Understand the coding standards and patterns you need to follow, then proceed with your development plan.
38
+ 7. Understand the coding standards and patterns you need to follow, then proceed with your development plan.
33
39
 
34
40
  This step is **mandatory** before writing any code.