@mindfoldhq/trellis 0.3.10 → 0.4.0-beta.10

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 (304) hide show
  1. package/README.md +19 -5
  2. package/dist/cli/index.js +5 -0
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/commands/init.d.ts +4 -0
  5. package/dist/commands/init.d.ts.map +1 -1
  6. package/dist/commands/init.js +240 -43
  7. package/dist/commands/init.js.map +1 -1
  8. package/dist/commands/update.d.ts.map +1 -1
  9. package/dist/commands/update.js +206 -47
  10. package/dist/commands/update.js.map +1 -1
  11. package/dist/configurators/codebuddy.d.ts +11 -0
  12. package/dist/configurators/codebuddy.d.ts.map +1 -0
  13. package/dist/configurators/codebuddy.js +58 -0
  14. package/dist/configurators/codebuddy.js.map +1 -0
  15. package/dist/configurators/codex.d.ts +7 -4
  16. package/dist/configurators/codex.d.ts.map +1 -1
  17. package/dist/configurators/codex.js +40 -10
  18. package/dist/configurators/codex.js.map +1 -1
  19. package/dist/configurators/copilot.d.ts +9 -0
  20. package/dist/configurators/copilot.d.ts.map +1 -0
  21. package/dist/configurators/copilot.js +34 -0
  22. package/dist/configurators/copilot.js.map +1 -0
  23. package/dist/configurators/index.d.ts +11 -1
  24. package/dist/configurators/index.d.ts.map +1 -1
  25. package/dist/configurators/index.js +72 -4
  26. package/dist/configurators/index.js.map +1 -1
  27. package/dist/configurators/opencode.d.ts +1 -1
  28. package/dist/configurators/opencode.js +1 -1
  29. package/dist/configurators/windsurf.d.ts +8 -0
  30. package/dist/configurators/windsurf.d.ts.map +1 -0
  31. package/dist/configurators/windsurf.js +18 -0
  32. package/dist/configurators/windsurf.js.map +1 -0
  33. package/dist/configurators/workflow.d.ts +6 -2
  34. package/dist/configurators/workflow.d.ts.map +1 -1
  35. package/dist/configurators/workflow.js +90 -58
  36. package/dist/configurators/workflow.js.map +1 -1
  37. package/dist/migrations/index.d.ts +1 -0
  38. package/dist/migrations/index.d.ts.map +1 -1
  39. package/dist/migrations/index.js +2 -0
  40. package/dist/migrations/index.js.map +1 -1
  41. package/dist/migrations/manifests/0.4.0-beta.1.json +228 -0
  42. package/dist/migrations/manifests/0.4.0-beta.10.json +9 -0
  43. package/dist/migrations/manifests/0.4.0-beta.2.json +9 -0
  44. package/dist/migrations/manifests/0.4.0-beta.3.json +9 -0
  45. package/dist/migrations/manifests/0.4.0-beta.4.json +9 -0
  46. package/dist/migrations/manifests/0.4.0-beta.5.json +9 -0
  47. package/dist/migrations/manifests/0.4.0-beta.6.json +9 -0
  48. package/dist/migrations/manifests/0.4.0-beta.7.json +9 -0
  49. package/dist/migrations/manifests/0.4.0-beta.8.json +34 -0
  50. package/dist/migrations/manifests/0.4.0-beta.9.json +9 -0
  51. package/dist/templates/claude/agents/dispatch.md +1 -2
  52. package/dist/templates/claude/agents/implement.md +2 -3
  53. package/dist/templates/claude/commands/trellis/before-dev.md +29 -0
  54. package/dist/templates/claude/commands/trellis/check.md +25 -0
  55. package/dist/templates/claude/commands/trellis/create-command.md +2 -2
  56. package/dist/templates/claude/commands/trellis/onboard.md +13 -13
  57. package/dist/templates/claude/commands/trellis/parallel.md +1 -2
  58. package/dist/templates/claude/commands/trellis/record-session.md +3 -2
  59. package/dist/templates/claude/commands/trellis/start.md +8 -4
  60. package/dist/templates/claude/hooks/inject-subagent-context.py +29 -14
  61. package/dist/templates/claude/hooks/ralph-loop.py +18 -10
  62. package/dist/templates/claude/hooks/session-start.py +201 -9
  63. package/dist/templates/claude/hooks/statusline.py +211 -0
  64. package/dist/templates/claude/settings.json +4 -0
  65. package/dist/templates/codebuddy/commands/trellis/before-dev.md +29 -0
  66. package/dist/templates/codebuddy/commands/trellis/brainstorm.md +487 -0
  67. package/dist/templates/codebuddy/commands/trellis/break-loop.md +107 -0
  68. package/dist/templates/codebuddy/commands/trellis/check-cross-layer.md +153 -0
  69. package/dist/templates/codebuddy/commands/trellis/check.md +25 -0
  70. package/dist/templates/codebuddy/commands/trellis/create-command.md +154 -0
  71. package/dist/templates/codebuddy/commands/trellis/finish-work.md +143 -0
  72. package/dist/templates/codebuddy/commands/trellis/integrate-skill.md +219 -0
  73. package/dist/templates/codebuddy/commands/trellis/onboard.md +358 -0
  74. package/dist/templates/codebuddy/commands/trellis/record-session.md +61 -0
  75. package/dist/templates/codebuddy/commands/trellis/start.md +373 -0
  76. package/dist/templates/codebuddy/commands/trellis/update-spec.md +354 -0
  77. package/dist/templates/codebuddy/index.d.ts +25 -0
  78. package/dist/templates/codebuddy/index.d.ts.map +1 -0
  79. package/dist/templates/codebuddy/index.js +45 -0
  80. package/dist/templates/codebuddy/index.js.map +1 -0
  81. package/dist/templates/codex/agents/check.toml +23 -0
  82. package/dist/templates/codex/agents/implement.toml +19 -0
  83. package/dist/templates/codex/agents/research.toml +26 -0
  84. package/dist/templates/codex/codex-skills/parallel/SKILL.md +194 -0
  85. package/dist/templates/codex/config.toml +5 -0
  86. package/dist/templates/codex/hooks/session-start.py +228 -0
  87. package/dist/templates/codex/hooks.json +16 -0
  88. package/dist/templates/codex/index.d.ts +27 -5
  89. package/dist/templates/codex/index.d.ts.map +1 -1
  90. package/dist/templates/codex/index.js +60 -8
  91. package/dist/templates/codex/index.js.map +1 -1
  92. package/dist/templates/codex/skills/before-dev/SKILL.md +34 -0
  93. package/dist/templates/codex/skills/brainstorm/SKILL.md +1 -1
  94. package/dist/templates/codex/skills/break-loop/SKILL.md +1 -1
  95. package/dist/templates/codex/skills/check/SKILL.md +30 -0
  96. package/dist/templates/codex/skills/check-cross-layer/SKILL.md +1 -1
  97. package/dist/templates/codex/skills/create-command/SKILL.md +3 -3
  98. package/dist/templates/codex/skills/finish-work/SKILL.md +1 -1
  99. package/dist/templates/codex/skills/improve-ut/SKILL.md +69 -0
  100. package/dist/templates/codex/skills/integrate-skill/SKILL.md +1 -1
  101. package/dist/templates/codex/skills/onboard/SKILL.md +12 -12
  102. package/dist/templates/codex/skills/record-session/SKILL.md +4 -3
  103. package/dist/templates/codex/skills/start/SKILL.md +9 -4
  104. package/dist/templates/codex/skills/update-spec/SKILL.md +1 -1
  105. package/dist/templates/copilot/hooks/session-start.py +218 -0
  106. package/dist/templates/copilot/hooks.json +11 -0
  107. package/dist/templates/copilot/index.d.ts +23 -0
  108. package/dist/templates/copilot/index.d.ts.map +1 -0
  109. package/dist/templates/copilot/index.js +54 -0
  110. package/dist/templates/copilot/index.js.map +1 -0
  111. package/dist/templates/copilot/prompts/before-dev.prompt.md +33 -0
  112. package/dist/templates/copilot/prompts/brainstorm.prompt.md +491 -0
  113. package/dist/templates/copilot/prompts/break-loop.prompt.md +129 -0
  114. package/dist/templates/copilot/prompts/check-cross-layer.prompt.md +157 -0
  115. package/dist/templates/copilot/prompts/check.prompt.md +29 -0
  116. package/dist/templates/copilot/prompts/create-command.prompt.md +116 -0
  117. package/dist/templates/copilot/prompts/finish-work.prompt.md +157 -0
  118. package/dist/templates/copilot/prompts/integrate-skill.prompt.md +223 -0
  119. package/dist/templates/copilot/prompts/onboard.prompt.md +362 -0
  120. package/dist/templates/copilot/prompts/parallel.prompt.md +196 -0
  121. package/dist/templates/copilot/prompts/record-session.prompt.md +66 -0
  122. package/dist/templates/copilot/prompts/start.prompt.md +397 -0
  123. package/dist/templates/copilot/prompts/update-spec.prompt.md +358 -0
  124. package/dist/templates/cursor/commands/trellis-before-dev.md +29 -0
  125. package/dist/templates/cursor/commands/trellis-check.md +25 -0
  126. package/dist/templates/cursor/commands/trellis-create-command.md +2 -2
  127. package/dist/templates/cursor/commands/trellis-onboard.md +13 -13
  128. package/dist/templates/cursor/commands/trellis-record-session.md +3 -2
  129. package/dist/templates/cursor/commands/trellis-start.md +7 -16
  130. package/dist/templates/extract.d.ts +36 -0
  131. package/dist/templates/extract.d.ts.map +1 -1
  132. package/dist/templates/extract.js +64 -0
  133. package/dist/templates/extract.js.map +1 -1
  134. package/dist/templates/gemini/commands/trellis/before-dev.toml +33 -0
  135. package/dist/templates/gemini/commands/trellis/check.toml +29 -0
  136. package/dist/templates/gemini/commands/trellis/create-command.toml +2 -2
  137. package/dist/templates/gemini/commands/trellis/onboard.toml +2 -2
  138. package/dist/templates/gemini/commands/trellis/record-session.toml +3 -2
  139. package/dist/templates/gemini/commands/trellis/start.toml +9 -4
  140. package/dist/templates/iflow/agents/dispatch.md +1 -2
  141. package/dist/templates/iflow/agents/implement.md +2 -3
  142. package/dist/templates/iflow/commands/trellis/before-dev.md +29 -0
  143. package/dist/templates/iflow/commands/trellis/check.md +25 -0
  144. package/dist/templates/iflow/commands/trellis/create-command.md +2 -2
  145. package/dist/templates/iflow/commands/trellis/onboard.md +13 -13
  146. package/dist/templates/iflow/commands/trellis/parallel.md +1 -2
  147. package/dist/templates/iflow/commands/trellis/record-session.md +3 -2
  148. package/dist/templates/iflow/commands/trellis/start.md +8 -4
  149. package/dist/templates/iflow/hooks/inject-subagent-context.py +29 -14
  150. package/dist/templates/iflow/hooks/ralph-loop.py +8 -1
  151. package/dist/templates/iflow/hooks/session-start.py +187 -8
  152. package/dist/templates/kilo/workflows/before-dev.md +29 -0
  153. package/dist/templates/kilo/workflows/check.md +25 -0
  154. package/dist/templates/kilo/workflows/create-command.md +2 -2
  155. package/dist/templates/kilo/workflows/onboard.md +13 -13
  156. package/dist/templates/kilo/workflows/parallel.md +1 -2
  157. package/dist/templates/kilo/workflows/record-session.md +3 -2
  158. package/dist/templates/kilo/workflows/start.md +8 -3
  159. package/dist/templates/kiro/skills/before-dev/SKILL.md +34 -0
  160. package/dist/templates/kiro/skills/brainstorm/SKILL.md +1 -1
  161. package/dist/templates/kiro/skills/break-loop/SKILL.md +1 -1
  162. package/dist/templates/kiro/skills/check/SKILL.md +30 -0
  163. package/dist/templates/kiro/skills/check-cross-layer/SKILL.md +1 -1
  164. package/dist/templates/kiro/skills/create-command/SKILL.md +3 -3
  165. package/dist/templates/kiro/skills/finish-work/SKILL.md +1 -1
  166. package/dist/templates/kiro/skills/integrate-skill/SKILL.md +1 -1
  167. package/dist/templates/kiro/skills/onboard/SKILL.md +12 -12
  168. package/dist/templates/kiro/skills/record-session/SKILL.md +4 -3
  169. package/dist/templates/kiro/skills/start/SKILL.md +9 -4
  170. package/dist/templates/kiro/skills/update-spec/SKILL.md +1 -1
  171. package/dist/templates/markdown/agents.md +4 -0
  172. package/dist/templates/markdown/spec/backend/directory-structure.md +1 -1
  173. package/dist/templates/markdown/spec/backend/script-conventions.md +93 -0
  174. package/dist/templates/markdown/workspace-index.md +2 -0
  175. package/dist/templates/opencode/agents/dispatch.md +21 -21
  176. package/dist/templates/opencode/agents/implement.md +2 -2
  177. package/dist/templates/opencode/agents/research.md +1 -2
  178. package/dist/templates/opencode/commands/trellis/before-dev.md +29 -0
  179. package/dist/templates/opencode/commands/trellis/check.md +25 -0
  180. package/dist/templates/opencode/commands/trellis/create-command.md +2 -2
  181. package/dist/templates/opencode/commands/trellis/onboard.md +13 -13
  182. package/dist/templates/opencode/commands/trellis/parallel.md +1 -2
  183. package/dist/templates/opencode/commands/trellis/record-session.md +3 -2
  184. package/dist/templates/opencode/commands/trellis/start.md +8 -3
  185. package/dist/templates/opencode/lib/trellis-context.js +42 -2
  186. package/dist/templates/opencode/{plugin → plugins}/inject-subagent-context.js +45 -18
  187. package/dist/templates/opencode/{plugin → plugins}/session-start.js +156 -28
  188. package/dist/templates/qoder/skills/before-dev/SKILL.md +34 -0
  189. package/dist/templates/qoder/skills/brainstorm/SKILL.md +1 -1
  190. package/dist/templates/qoder/skills/break-loop/SKILL.md +1 -1
  191. package/dist/templates/qoder/skills/check/SKILL.md +30 -0
  192. package/dist/templates/qoder/skills/check-cross-layer/SKILL.md +1 -1
  193. package/dist/templates/qoder/skills/create-command/SKILL.md +3 -3
  194. package/dist/templates/qoder/skills/finish-work/SKILL.md +1 -1
  195. package/dist/templates/qoder/skills/integrate-skill/SKILL.md +1 -1
  196. package/dist/templates/qoder/skills/onboard/SKILL.md +14 -14
  197. package/dist/templates/qoder/skills/record-session/SKILL.md +4 -3
  198. package/dist/templates/qoder/skills/start/SKILL.md +9 -4
  199. package/dist/templates/qoder/skills/update-spec/SKILL.md +1 -1
  200. package/dist/templates/trellis/config.yaml +20 -0
  201. package/dist/templates/trellis/index.d.ts +11 -0
  202. package/dist/templates/trellis/index.d.ts.map +1 -1
  203. package/dist/templates/trellis/index.js +22 -0
  204. package/dist/templates/trellis/index.js.map +1 -1
  205. package/dist/templates/trellis/scripts/add_session.py +111 -13
  206. package/dist/templates/trellis/scripts/common/__init__.py +2 -0
  207. package/dist/templates/trellis/scripts/common/cli_adapter.py +164 -64
  208. package/dist/templates/trellis/scripts/common/config.py +192 -0
  209. package/dist/templates/trellis/scripts/common/developer.py +2 -2
  210. package/dist/templates/trellis/scripts/common/git.py +31 -0
  211. package/dist/templates/trellis/scripts/common/git_context.py +23 -586
  212. package/dist/templates/trellis/scripts/common/io.py +37 -0
  213. package/dist/templates/trellis/scripts/common/log.py +45 -0
  214. package/dist/templates/trellis/scripts/common/packages_context.py +238 -0
  215. package/dist/templates/trellis/scripts/common/paths.py +103 -6
  216. package/dist/templates/trellis/scripts/common/phase.py +50 -49
  217. package/dist/templates/trellis/scripts/common/registry.py +41 -72
  218. package/dist/templates/trellis/scripts/common/session_context.py +562 -0
  219. package/dist/templates/trellis/scripts/common/task_context.py +410 -0
  220. package/dist/templates/trellis/scripts/common/task_queue.py +27 -98
  221. package/dist/templates/trellis/scripts/common/task_store.py +536 -0
  222. package/dist/templates/trellis/scripts/common/task_utils.py +106 -10
  223. package/dist/templates/trellis/scripts/common/tasks.py +109 -0
  224. package/dist/templates/trellis/scripts/common/types.py +112 -0
  225. package/dist/templates/trellis/scripts/create_bootstrap.py +32 -27
  226. package/dist/templates/trellis/scripts/hooks/linear_sync.py +243 -0
  227. package/dist/templates/trellis/scripts/multi_agent/_bootstrap.py +17 -0
  228. package/dist/templates/trellis/scripts/multi_agent/cleanup.py +43 -48
  229. package/dist/templates/trellis/scripts/multi_agent/create_pr.py +336 -45
  230. package/dist/templates/trellis/scripts/multi_agent/plan.py +9 -32
  231. package/dist/templates/trellis/scripts/multi_agent/start.py +142 -68
  232. package/dist/templates/trellis/scripts/multi_agent/status.py +12 -753
  233. package/dist/templates/trellis/scripts/multi_agent/status_display.py +542 -0
  234. package/dist/templates/trellis/scripts/multi_agent/status_monitor.py +225 -0
  235. package/dist/templates/trellis/scripts/task.py +51 -976
  236. package/dist/templates/trellis/scripts-shell-archive/create-bootstrap.sh +1 -1
  237. package/dist/templates/trellis/workflow.md +38 -38
  238. package/dist/templates/windsurf/index.d.ts +21 -0
  239. package/dist/templates/windsurf/index.d.ts.map +1 -0
  240. package/dist/templates/windsurf/index.js +44 -0
  241. package/dist/templates/windsurf/index.js.map +1 -0
  242. package/dist/templates/windsurf/workflows/trellis-before-dev.md +31 -0
  243. package/dist/templates/windsurf/workflows/trellis-brainstorm.md +491 -0
  244. package/dist/templates/windsurf/workflows/trellis-break-loop.md +111 -0
  245. package/dist/templates/windsurf/workflows/trellis-check-cross-layer.md +157 -0
  246. package/dist/templates/windsurf/workflows/trellis-check.md +27 -0
  247. package/dist/templates/windsurf/workflows/trellis-create-command.md +154 -0
  248. package/dist/templates/windsurf/workflows/trellis-finish-work.md +147 -0
  249. package/dist/templates/windsurf/workflows/trellis-integrate-skill.md +220 -0
  250. package/dist/templates/windsurf/workflows/trellis-onboard.md +362 -0
  251. package/dist/templates/windsurf/workflows/trellis-record-session.md +66 -0
  252. package/dist/templates/windsurf/workflows/trellis-start.md +373 -0
  253. package/dist/templates/windsurf/workflows/trellis-update-spec.md +358 -0
  254. package/dist/types/ai-tools.d.ts +15 -3
  255. package/dist/types/ai-tools.d.ts.map +1 -1
  256. package/dist/types/ai-tools.js +42 -2
  257. package/dist/types/ai-tools.js.map +1 -1
  258. package/dist/types/migration.d.ts +3 -1
  259. package/dist/types/migration.d.ts.map +1 -1
  260. package/dist/utils/project-detector.d.ts +28 -0
  261. package/dist/utils/project-detector.d.ts.map +1 -1
  262. package/dist/utils/project-detector.js +371 -0
  263. package/dist/utils/project-detector.js.map +1 -1
  264. package/dist/utils/template-fetcher.d.ts +19 -6
  265. package/dist/utils/template-fetcher.d.ts.map +1 -1
  266. package/dist/utils/template-fetcher.js +99 -17
  267. package/dist/utils/template-fetcher.js.map +1 -1
  268. package/package.json +1 -1
  269. package/dist/templates/claude/commands/trellis/before-backend-dev.md +0 -13
  270. package/dist/templates/claude/commands/trellis/before-frontend-dev.md +0 -13
  271. package/dist/templates/claude/commands/trellis/check-backend.md +0 -13
  272. package/dist/templates/claude/commands/trellis/check-frontend.md +0 -13
  273. package/dist/templates/codex/skills/before-backend-dev/SKILL.md +0 -18
  274. package/dist/templates/codex/skills/before-frontend-dev/SKILL.md +0 -18
  275. package/dist/templates/codex/skills/check-backend/SKILL.md +0 -18
  276. package/dist/templates/codex/skills/check-frontend/SKILL.md +0 -18
  277. package/dist/templates/cursor/commands/trellis-before-backend-dev.md +0 -13
  278. package/dist/templates/cursor/commands/trellis-before-frontend-dev.md +0 -13
  279. package/dist/templates/cursor/commands/trellis-check-backend.md +0 -13
  280. package/dist/templates/cursor/commands/trellis-check-frontend.md +0 -13
  281. package/dist/templates/gemini/commands/trellis/before-backend-dev.toml +0 -17
  282. package/dist/templates/gemini/commands/trellis/before-frontend-dev.toml +0 -17
  283. package/dist/templates/gemini/commands/trellis/check-backend.toml +0 -17
  284. package/dist/templates/gemini/commands/trellis/check-frontend.toml +0 -17
  285. package/dist/templates/iflow/commands/trellis/before-backend-dev.md +0 -13
  286. package/dist/templates/iflow/commands/trellis/before-frontend-dev.md +0 -13
  287. package/dist/templates/iflow/commands/trellis/check-backend.md +0 -13
  288. package/dist/templates/iflow/commands/trellis/check-frontend.md +0 -13
  289. package/dist/templates/kilo/workflows/before-backend-dev.md +0 -13
  290. package/dist/templates/kilo/workflows/before-frontend-dev.md +0 -13
  291. package/dist/templates/kilo/workflows/check-backend.md +0 -13
  292. package/dist/templates/kilo/workflows/check-frontend.md +0 -13
  293. package/dist/templates/kiro/skills/before-backend-dev/SKILL.md +0 -18
  294. package/dist/templates/kiro/skills/before-frontend-dev/SKILL.md +0 -18
  295. package/dist/templates/kiro/skills/check-backend/SKILL.md +0 -18
  296. package/dist/templates/kiro/skills/check-frontend/SKILL.md +0 -18
  297. package/dist/templates/opencode/commands/trellis/before-backend-dev.md +0 -13
  298. package/dist/templates/opencode/commands/trellis/before-frontend-dev.md +0 -13
  299. package/dist/templates/opencode/commands/trellis/check-backend.md +0 -13
  300. package/dist/templates/opencode/commands/trellis/check-frontend.md +0 -13
  301. package/dist/templates/qoder/skills/before-backend-dev/SKILL.md +0 -18
  302. package/dist/templates/qoder/skills/before-frontend-dev/SKILL.md +0 -18
  303. package/dist/templates/qoder/skills/check-backend/SKILL.md +0 -18
  304. package/dist/templates/qoder/skills/check-frontend/SKILL.md +0 -18
@@ -99,7 +99,14 @@ def get_current_task(repo_root: str) -> str | None:
99
99
  try:
100
100
  with open(current_task_file, "r", encoding="utf-8") as f:
101
101
  content = f.read().strip()
102
- return content if content else None
102
+ if not content:
103
+ return None
104
+ normalized = content.replace("\\", "/")
105
+ while normalized.startswith("./"):
106
+ normalized = normalized[2:]
107
+ if normalized.startswith("tasks/"):
108
+ normalized = f".trellis/{normalized}"
109
+ return normalized
103
110
  except Exception:
104
111
  return None
105
112
 
@@ -339,8 +346,7 @@ def get_check_context(repo_root: str, task_dir: str) -> str:
339
346
  check_files = [
340
347
  (".claude/commands/trellis/finish-work.md", "Finish work checklist"),
341
348
  (".claude/commands/trellis/check-cross-layer.md", "Cross-layer check spec"),
342
- (".claude/commands/trellis/check-backend.md", "Backend check spec"),
343
- (".claude/commands/trellis/check-frontend.md", "Frontend check spec"),
349
+ (".claude/commands/trellis/check.md", "Code quality check spec"),
344
350
  ]
345
351
  for file_path, description in check_files:
346
352
  content = read_file_content(repo_root, file_path)
@@ -432,8 +438,7 @@ def get_debug_context(repo_root: str, task_dir: str) -> str:
432
438
  context_parts.append(f"=== {file_path} (Dev spec) ===\n{content}")
433
439
 
434
440
  check_files = [
435
- (".claude/commands/trellis/check-backend.md", "Backend check spec"),
436
- (".claude/commands/trellis/check-frontend.md", "Frontend check spec"),
441
+ (".claude/commands/trellis/check.md", "Code quality check spec"),
437
442
  (".claude/commands/trellis/check-cross-layer.md", "Cross-layer check spec"),
438
443
  ]
439
444
  for file_path, description in check_files:
@@ -603,24 +608,34 @@ def get_research_context(repo_root: str, task_dir: str | None) -> str:
603
608
  """
604
609
  context_parts = []
605
610
 
606
- # 1. Project structure overview (uses constants for paths)
611
+ # 1. Project structure overview (dynamically discover spec directories)
607
612
  spec_path = f"{DIR_WORKFLOW}/{DIR_SPEC}"
613
+ spec_root = Path(repo_root) / DIR_WORKFLOW / DIR_SPEC
614
+
615
+ # Build spec tree dynamically
616
+ tree_lines = [f"{spec_path}/"]
617
+ if spec_root.is_dir():
618
+ pkg_dirs = sorted(d for d in spec_root.iterdir() if d.is_dir())
619
+ for i, pkg_dir in enumerate(pkg_dirs):
620
+ is_last = i == len(pkg_dirs) - 1
621
+ prefix = "└── " if is_last else "├── "
622
+ layers = sorted(d.name for d in pkg_dir.iterdir() if d.is_dir())
623
+ layer_info = f" ({', '.join(layers)})" if layers else ""
624
+ tree_lines.append(f"{prefix}{pkg_dir.name}/{layer_info}")
625
+
626
+ spec_tree = "\n".join(tree_lines)
627
+
608
628
  project_structure = f"""## Project Spec Directory Structure
609
629
 
610
630
  ```
611
- {spec_path}/
612
- ├── shared/ # Cross-project common specs (TypeScript, code quality, git)
613
- ├── frontend/ # Frontend standards
614
- ├── backend/ # Backend standards
615
- └── guides/ # Thinking guides (cross-layer, code reuse, etc.)
616
-
617
- {DIR_WORKFLOW}/big-question/ # Known issues and pitfalls
631
+ {spec_tree}
618
632
  ```
619
633
 
634
+ To get structured package info, run: `python3 ./{DIR_WORKFLOW}/scripts/get_context.py --mode packages`
635
+
620
636
  ## Search Tips
621
637
 
622
638
  - Spec files: `{spec_path}/**/*.md`
623
- - Known issues: `{DIR_WORKFLOW}/big-question/`
624
639
  - Code search: Use Glob and Grep tools
625
640
  - Tech solutions: Use mcp__exa__web_search_exa or mcp__exa__get_code_context_exa"""
626
641
 
@@ -72,7 +72,14 @@ def get_current_task(repo_root: str) -> str | None:
72
72
  try:
73
73
  with open(current_task_file, "r", encoding="utf-8") as f:
74
74
  content = f.read().strip()
75
- return content if content else None
75
+ if not content:
76
+ return None
77
+ normalized = content.replace("\\", "/")
78
+ while normalized.startswith("./"):
79
+ normalized = normalized[2:]
80
+ if normalized.startswith("tasks/"):
81
+ normalized = f".trellis/{normalized}"
82
+ return normalized
76
83
  except Exception:
77
84
  return None
78
85
 
@@ -258,17 +265,18 @@ def main():
258
265
  sys.exit(0)
259
266
 
260
267
  # Get subagent info
261
- subagent_type = input_data.get("subagent_type", "")
262
- agent_output = input_data.get("agent_output", "")
263
- original_prompt = input_data.get("prompt", "")
268
+ # Field names per Claude Code SubagentStop event schema:
269
+ # agent_type, last_assistant_message, agent_id, agent_transcript_path, cwd
270
+ # The event does NOT carry a `prompt` field, so finish-phase detection
271
+ # based on a `[finish]` marker in the user prompt is no longer possible
272
+ # here; finish-phase skip logic should be reintroduced via task.json
273
+ # state (e.g. current_phase) in a follow-up.
274
+ agent_type = input_data.get("agent_type", "")
275
+ last_assistant_message = input_data.get("last_assistant_message", "")
264
276
  cwd = input_data.get("cwd", os.getcwd())
265
277
 
266
278
  # Only control check agent
267
- if subagent_type != TARGET_AGENT:
268
- sys.exit(0)
269
-
270
- # Skip Ralph Loop for finish phase (already verified in check phase)
271
- if "[finish]" in original_prompt.lower():
279
+ if agent_type != TARGET_AGENT:
272
280
  sys.exit(0)
273
281
 
274
282
  # Find repo root
@@ -350,7 +358,7 @@ def main():
350
358
  else:
351
359
  # No verify commands, fall back to completion markers
352
360
  markers = get_completion_markers(repo_root, task_dir)
353
- all_complete, missing = check_completion(agent_output, markers)
361
+ all_complete, missing = check_completion(last_assistant_message, markers)
354
362
 
355
363
  if all_complete:
356
364
  # All checks complete, allow stop
@@ -65,23 +65,47 @@ def run_script(script_path: Path) -> str:
65
65
  return "No context available"
66
66
 
67
67
 
68
+ def _normalize_task_ref(task_ref: str) -> str:
69
+ normalized = task_ref.strip()
70
+ if not normalized:
71
+ return ""
72
+
73
+ path_obj = Path(normalized)
74
+ if path_obj.is_absolute():
75
+ return str(path_obj)
76
+
77
+ normalized = normalized.replace("\\", "/")
78
+ while normalized.startswith("./"):
79
+ normalized = normalized[2:]
80
+
81
+ if normalized.startswith("tasks/"):
82
+ return f".trellis/{normalized}"
83
+
84
+ return normalized
85
+
86
+
87
+ def _resolve_task_dir(trellis_dir: Path, task_ref: str) -> Path:
88
+ normalized = _normalize_task_ref(task_ref)
89
+ path_obj = Path(normalized)
90
+ if path_obj.is_absolute():
91
+ return path_obj
92
+ if normalized.startswith(".trellis/"):
93
+ return trellis_dir.parent / path_obj
94
+ return trellis_dir / "tasks" / path_obj
95
+
96
+
68
97
  def _get_task_status(trellis_dir: Path) -> str:
69
98
  """Check current task status and return structured status string."""
70
99
  current_task_file = trellis_dir / ".current-task"
71
100
  if not current_task_file.is_file():
72
101
  return "Status: NO ACTIVE TASK\nNext: Describe what you want to work on"
73
102
 
74
- task_ref = current_task_file.read_text(encoding="utf-8").strip()
103
+ task_ref = _normalize_task_ref(current_task_file.read_text(encoding="utf-8").strip())
75
104
  if not task_ref:
76
105
  return "Status: NO ACTIVE TASK\nNext: Describe what you want to work on"
77
106
 
78
107
  # Resolve task directory
79
- if Path(task_ref).is_absolute():
80
- task_dir = Path(task_ref)
81
- elif task_ref.startswith(".trellis/"):
82
- task_dir = trellis_dir.parent / task_ref
83
- else:
84
- task_dir = trellis_dir / "tasks" / task_ref
108
+ task_dir = _resolve_task_dir(trellis_dir, task_ref)
85
109
  if not task_dir.is_dir():
86
110
  return f"Status: STALE POINTER\nTask: {task_ref}\nNext: Task directory not found. Run: python3 ./.trellis/scripts/task.py finish"
87
111
 
@@ -119,6 +143,151 @@ def _get_task_status(trellis_dir: Path) -> str:
119
143
  return f"Status: READY\nTask: {task_title}\nNext: Continue with implement or check"
120
144
 
121
145
 
146
+ def _load_trellis_config(trellis_dir: Path) -> tuple:
147
+ """Load Trellis config for session-start decisions.
148
+
149
+ Returns:
150
+ (is_mono, packages_dict, spec_scope, task_pkg, default_pkg)
151
+ """
152
+ scripts_dir = trellis_dir / "scripts"
153
+ if str(scripts_dir) not in sys.path:
154
+ sys.path.insert(0, str(scripts_dir))
155
+
156
+ try:
157
+ from common.config import get_default_package, get_packages, get_spec_scope, is_monorepo # type: ignore[import-not-found]
158
+ from common.paths import get_current_task # type: ignore[import-not-found]
159
+
160
+ repo_root = trellis_dir.parent
161
+ is_mono = is_monorepo(repo_root)
162
+ packages = get_packages(repo_root) or {}
163
+ scope = get_spec_scope(repo_root)
164
+
165
+ # Get active task's package
166
+ task_pkg = None
167
+ current = get_current_task(repo_root)
168
+ if current:
169
+ task_json = repo_root / current / "task.json"
170
+ if task_json.is_file():
171
+ try:
172
+ data = json.loads(task_json.read_text(encoding="utf-8"))
173
+ if isinstance(data, dict):
174
+ tp = data.get("package")
175
+ if isinstance(tp, str) and tp:
176
+ task_pkg = tp
177
+ except (json.JSONDecodeError, OSError):
178
+ pass
179
+
180
+ default_pkg = get_default_package(repo_root)
181
+ return is_mono, packages, scope, task_pkg, default_pkg
182
+ except Exception:
183
+ return False, {}, None, None, None
184
+
185
+
186
+ def _check_legacy_spec(trellis_dir: Path, is_mono: bool, packages: dict) -> str | None:
187
+ """Check for legacy spec directory structure in monorepo.
188
+
189
+ Returns warning message if legacy structure detected, None otherwise.
190
+ """
191
+ if not is_mono or not packages:
192
+ return None
193
+
194
+ spec_dir = trellis_dir / "spec"
195
+ if not spec_dir.is_dir():
196
+ return None
197
+
198
+ # Check for legacy flat spec dirs (spec/backend/, spec/frontend/ with index.md)
199
+ has_legacy = False
200
+ for legacy_name in ("backend", "frontend"):
201
+ legacy_dir = spec_dir / legacy_name
202
+ if legacy_dir.is_dir() and (legacy_dir / "index.md").is_file():
203
+ has_legacy = True
204
+ break
205
+
206
+ if not has_legacy:
207
+ return None
208
+
209
+ # Check which packages are missing spec/<pkg>/ directory
210
+ missing = [
211
+ name for name in sorted(packages.keys())
212
+ if not (spec_dir / name).is_dir()
213
+ ]
214
+
215
+ if not missing:
216
+ return None # All packages have spec dirs
217
+
218
+ if len(missing) == len(packages):
219
+ return (
220
+ f"[!] Legacy spec structure detected: found `spec/backend/` or `spec/frontend/` "
221
+ f"but no package-scoped `spec/<package>/` directories.\n"
222
+ f"Monorepo packages: {', '.join(sorted(packages.keys()))}\n"
223
+ f"Please reorganize: `spec/backend/` -> `spec/<package>/backend/`"
224
+ )
225
+ return (
226
+ f"[!] Partial spec migration detected: packages {', '.join(missing)} "
227
+ f"still missing `spec/<pkg>/` directory.\n"
228
+ f"Please complete migration for all packages."
229
+ )
230
+
231
+
232
+ def _resolve_spec_scope(
233
+ is_mono: bool,
234
+ packages: dict,
235
+ scope,
236
+ task_pkg: str | None,
237
+ default_pkg: str | None,
238
+ ) -> set | None:
239
+ """Resolve which packages should have their specs injected.
240
+
241
+ Returns:
242
+ Set of package names to include, or None for full scan.
243
+ """
244
+ if not is_mono or not packages:
245
+ return None # Single-repo: full scan
246
+
247
+ if scope is None:
248
+ return None # No scope configured: full scan
249
+
250
+ if isinstance(scope, str) and scope == "active_task":
251
+ if task_pkg and task_pkg in packages:
252
+ return {task_pkg}
253
+ if default_pkg and default_pkg in packages:
254
+ return {default_pkg}
255
+ return None # Fallback to full scan
256
+
257
+ if isinstance(scope, list):
258
+ valid = set()
259
+ for entry in scope:
260
+ if entry in packages:
261
+ valid.add(entry)
262
+ else:
263
+ print(
264
+ f"Warning: spec_scope contains unknown package: {entry}, ignoring",
265
+ file=sys.stderr,
266
+ )
267
+
268
+ if valid:
269
+ # Warn if active task is out of scope
270
+ if task_pkg and task_pkg not in valid:
271
+ print(
272
+ f"Warning: active task package '{task_pkg}' is out of configured spec_scope",
273
+ file=sys.stderr,
274
+ )
275
+ return valid
276
+
277
+ # All entries invalid: fallback chain
278
+ print(
279
+ "Warning: all spec_scope entries invalid, falling back to task/default/full",
280
+ file=sys.stderr,
281
+ )
282
+ if task_pkg and task_pkg in packages:
283
+ return {task_pkg}
284
+ if default_pkg and default_pkg in packages:
285
+ return {default_pkg}
286
+ return None # Full scan
287
+
288
+ return None # Unknown scope type: full scan
289
+
290
+
122
291
  def main():
123
292
  if should_skip_injection():
124
293
  sys.exit(0)
@@ -127,6 +296,10 @@ def main():
127
296
  trellis_dir = project_dir / ".trellis"
128
297
  claude_dir = project_dir / ".claude"
129
298
 
299
+ # Load config for scope filtering and legacy detection
300
+ is_mono, packages, scope_config, task_pkg, default_pkg = _load_trellis_config(trellis_dir)
301
+ allowed_pkgs = _resolve_spec_scope(is_mono, packages, scope_config, task_pkg, default_pkg)
302
+
130
303
  output = StringIO()
131
304
 
132
305
  output.write("""<session-context>
@@ -136,6 +309,11 @@ Read and follow all instructions below carefully.
136
309
 
137
310
  """)
138
311
 
312
+ # Legacy migration warning
313
+ legacy_warning = _check_legacy_spec(trellis_dir, is_mono, packages)
314
+ if legacy_warning:
315
+ output.write(f"<migration-warning>\n{legacy_warning}\n</migration-warning>\n\n")
316
+
139
317
  output.write("<current-state>\n")
140
318
  context_script = trellis_dir / "scripts" / "get_context.py"
141
319
  output.write(run_script(context_script))
@@ -155,13 +333,27 @@ Read and follow all instructions below carefully.
155
333
  for sub in sorted(spec_dir.iterdir()):
156
334
  if not sub.is_dir() or sub.name.startswith("."):
157
335
  continue
336
+
337
+ # Always include guides/ regardless of scope
338
+ if sub.name == "guides":
339
+ index_file = sub / "index.md"
340
+ if index_file.is_file():
341
+ output.write(f"## {sub.name}\n")
342
+ output.write(read_file(index_file))
343
+ output.write("\n\n")
344
+ continue
345
+
158
346
  index_file = sub / "index.md"
159
347
  if index_file.is_file():
348
+ # Flat spec dir (single-repo layer like spec/backend/)
160
349
  output.write(f"## {sub.name}\n")
161
350
  output.write(read_file(index_file))
162
351
  output.write("\n\n")
163
352
  else:
164
- # Check for nested package dirs (monorepo: spec/<pkg>/<layer>/index.md)
353
+ # Nested package dirs (monorepo: spec/<pkg>/<layer>/index.md)
354
+ # Apply scope filter
355
+ if allowed_pkgs is not None and sub.name not in allowed_pkgs:
356
+ continue
165
357
  for nested in sorted(sub.iterdir()):
166
358
  if not nested.is_dir():
167
359
  continue
@@ -180,7 +372,7 @@ Read and follow all instructions below carefully.
180
372
  output.write(start_md)
181
373
  output.write("\n</instructions>\n\n")
182
374
 
183
- # R2: Check task status and inject structured tag
375
+ # Check task status and inject structured tag
184
376
  task_status = _get_task_status(trellis_dir)
185
377
  output.write(f"<task-status>\n{task_status}\n</task-status>\n\n")
186
378
 
@@ -0,0 +1,211 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Trellis StatusLine — project-level status display for Claude Code.
5
+
6
+ Reads Claude Code session JSON from stdin + Trellis task data from filesystem.
7
+ Outputs 1-2 lines:
8
+ With active task: [P1] Task title (status) + info line
9
+ Without task: info line only
10
+ Info line: model · ctx% · branch · duration · developer · tasks · rate limits
11
+ """
12
+ from __future__ import annotations
13
+
14
+ import json
15
+ import re
16
+ import subprocess
17
+ import sys
18
+ from pathlib import Path
19
+
20
+
21
+ def _read_text(path: Path) -> str:
22
+ try:
23
+ return path.read_text(encoding="utf-8").strip()
24
+ except (FileNotFoundError, PermissionError, OSError):
25
+ return ""
26
+
27
+
28
+ def _read_json(path: Path) -> dict:
29
+ text = _read_text(path)
30
+ if not text:
31
+ return {}
32
+ try:
33
+ return json.loads(text)
34
+ except (json.JSONDecodeError, ValueError):
35
+ return {}
36
+
37
+
38
+ def _normalize_task_ref(task_ref: str) -> str:
39
+ normalized = task_ref.strip()
40
+ if not normalized:
41
+ return ""
42
+
43
+ path_obj = Path(normalized)
44
+ if path_obj.is_absolute():
45
+ return str(path_obj)
46
+
47
+ normalized = normalized.replace("\\", "/")
48
+ while normalized.startswith("./"):
49
+ normalized = normalized[2:]
50
+
51
+ if normalized.startswith("tasks/"):
52
+ return f".trellis/{normalized}"
53
+
54
+ return normalized
55
+
56
+
57
+ def _resolve_task_dir(trellis_dir: Path, task_ref: str) -> Path:
58
+ normalized = _normalize_task_ref(task_ref)
59
+ path_obj = Path(normalized)
60
+ if path_obj.is_absolute():
61
+ return path_obj
62
+ if normalized.startswith(".trellis/"):
63
+ return trellis_dir.parent / path_obj
64
+ return trellis_dir / "tasks" / path_obj
65
+
66
+
67
+ def _find_trellis_dir() -> Path | None:
68
+ """Walk up from cwd to find .trellis/ directory."""
69
+ current = Path.cwd()
70
+ for parent in [current, *current.parents]:
71
+ candidate = parent / ".trellis"
72
+ if candidate.is_dir():
73
+ return candidate
74
+ return None
75
+
76
+
77
+ def _get_current_task(trellis_dir: Path) -> dict | None:
78
+ """Load current task info. Returns dict with title/status/priority or None."""
79
+ task_ref = _normalize_task_ref(_read_text(trellis_dir / ".current-task"))
80
+ if not task_ref:
81
+ return None
82
+
83
+ # Resolve task directory
84
+ task_path = _resolve_task_dir(trellis_dir, task_ref)
85
+ task_data = _read_json(task_path / "task.json")
86
+ if not task_data:
87
+ return None
88
+
89
+ return {
90
+ "title": task_data.get("title") or task_data.get("name") or "unknown",
91
+ "status": task_data.get("status", "unknown"),
92
+ "priority": task_data.get("priority", "P2"),
93
+ }
94
+
95
+
96
+ def _count_active_tasks(trellis_dir: Path) -> int:
97
+ """Count non-archived task directories with valid task.json."""
98
+ tasks_dir = trellis_dir / "tasks"
99
+ if not tasks_dir.is_dir():
100
+ return 0
101
+ count = 0
102
+ for d in tasks_dir.iterdir():
103
+ if d.is_dir() and d.name != "archive" and (d / "task.json").is_file():
104
+ count += 1
105
+ return count
106
+
107
+
108
+ def _get_developer(trellis_dir: Path) -> str:
109
+ content = _read_text(trellis_dir / ".developer")
110
+ if not content:
111
+ return "unknown"
112
+ for line in content.splitlines():
113
+ if line.startswith("name="):
114
+ return line[5:].strip()
115
+ return content.splitlines()[0].strip() or "unknown"
116
+
117
+
118
+ def _get_git_branch() -> str:
119
+ try:
120
+ result = subprocess.run(
121
+ ["git", "branch", "--show-current"],
122
+ capture_output=True, text=True, timeout=3,
123
+ )
124
+ return result.stdout.strip() if result.returncode == 0 else ""
125
+ except (FileNotFoundError, subprocess.TimeoutExpired):
126
+ return ""
127
+
128
+
129
+ def _format_ctx_size(size: int) -> str:
130
+ if size >= 1_000_000:
131
+ return f"{size // 1_000_000}M"
132
+ if size >= 1_000:
133
+ return f"{size // 1_000}K"
134
+ return str(size)
135
+
136
+
137
+ def _format_duration(ms: int) -> str:
138
+ secs = ms // 1000
139
+ hours, remainder = divmod(secs, 3600)
140
+ mins = remainder // 60
141
+ if hours > 0:
142
+ return f"{hours}h{mins}m"
143
+ return f"{mins}m"
144
+
145
+
146
+ def main() -> None:
147
+ # Read Claude Code session JSON from stdin
148
+ try:
149
+ cc_data = json.loads(sys.stdin.read())
150
+ except (json.JSONDecodeError, ValueError):
151
+ cc_data = {}
152
+
153
+ trellis_dir = _find_trellis_dir()
154
+ SEP = " \033[90m·\033[0m "
155
+
156
+ # --- Trellis data ---
157
+ task = _get_current_task(trellis_dir) if trellis_dir else None
158
+ dev = _get_developer(trellis_dir) if trellis_dir else ""
159
+ task_count = _count_active_tasks(trellis_dir) if trellis_dir else 0
160
+
161
+ # --- CC session data ---
162
+ model = cc_data.get("model", {}).get("display_name", "?")
163
+ ctx_pct = int(cc_data.get("context_window", {}).get("used_percentage") or 0)
164
+ ctx_size = _format_ctx_size(cc_data.get("context_window", {}).get("context_window_size") or 0)
165
+ duration = _format_duration(cc_data.get("cost", {}).get("total_duration_ms") or 0)
166
+ branch = _get_git_branch()
167
+
168
+ # Avoid "Opus 4.6 (1M context) (1M)"
169
+ if re.search(r"\d+[KMG]\b", model, re.IGNORECASE):
170
+ model_label = model
171
+ else:
172
+ model_label = f"{model} ({ctx_size})"
173
+
174
+ # Context % with color
175
+ if ctx_pct >= 90:
176
+ ctx_color = "\033[31m"
177
+ elif ctx_pct >= 70:
178
+ ctx_color = "\033[33m"
179
+ else:
180
+ ctx_color = "\033[32m"
181
+
182
+ # Build info line: model · ctx · branch · duration · dev · tasks [· rate limits]
183
+ parts = [
184
+ model_label,
185
+ f"ctx {ctx_color}{ctx_pct}%\033[0m",
186
+ ]
187
+ if branch:
188
+ parts.append(f"\033[35m{branch}\033[0m")
189
+ parts.append(duration)
190
+ if dev:
191
+ parts.append(f"\033[32m{dev}\033[0m")
192
+ if task_count:
193
+ parts.append(f"{task_count} task(s)")
194
+
195
+ five_hr = cc_data.get("rate_limits", {}).get("five_hour", {}).get("used_percentage")
196
+ if five_hr is not None:
197
+ parts.append(f"5h {int(five_hr)}%")
198
+ seven_day = cc_data.get("rate_limits", {}).get("seven_day", {}).get("used_percentage")
199
+ if seven_day is not None:
200
+ parts.append(f"7d {int(seven_day)}%")
201
+
202
+ info_line = SEP.join(parts)
203
+
204
+ # Output: task line (only if active) + info line
205
+ if task:
206
+ print(f"\033[36m[{task['priority']}]\033[0m {task['title']} \033[33m({task['status']})\033[0m")
207
+ print(info_line)
208
+
209
+
210
+ if __name__ == "__main__":
211
+ main()
@@ -1,4 +1,8 @@
1
1
  {
2
+ "statusLine": {
3
+ "type": "command",
4
+ "command": "{{PYTHON_CMD}} .claude/hooks/statusline.py"
5
+ },
2
6
  "hooks": {
3
7
  "SessionStart": [
4
8
  {
@@ -0,0 +1,29 @@
1
+ Read the relevant development guidelines before starting your task.
2
+
3
+ Execute these steps:
4
+
5
+ 1. **Discover packages and their spec layers**:
6
+ ```bash
7
+ python3 ./.trellis/scripts/get_context.py --mode packages
8
+ ```
9
+
10
+ 2. **Identify which specs apply** to your task based on:
11
+ - Which package you're modifying (e.g., `cli/`, `docs-site/`)
12
+ - What type of work (backend, frontend, unit-test, docs, etc.)
13
+
14
+ 3. **Read the spec index** for each relevant module:
15
+ ```bash
16
+ cat .trellis/spec/<package>/<layer>/index.md
17
+ ```
18
+ Follow the **"Pre-Development Checklist"** section in the index.
19
+
20
+ 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.
21
+
22
+ 5. **Always read shared guides**:
23
+ ```bash
24
+ cat .trellis/spec/guides/index.md
25
+ ```
26
+
27
+ 6. Understand the coding standards and patterns you need to follow, then proceed with your development plan.
28
+
29
+ This step is **mandatory** before writing any code.