@mindfoldhq/trellis 0.6.0-beta.8 → 0.6.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (337) hide show
  1. package/README.md +49 -49
  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 +59 -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 +3 -0
  155. package/dist/commands/init.d.ts.map +1 -1
  156. package/dist/commands/init.js +162 -43
  157. package/dist/commands/init.js.map +1 -1
  158. package/dist/commands/mem.d.ts +13 -217
  159. package/dist/commands/mem.d.ts.map +1 -1
  160. package/dist/commands/mem.js +142 -1587
  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 +104 -7
  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 +232 -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/index.d.ts.map +1 -1
  180. package/dist/configurators/index.js +5 -0
  181. package/dist/configurators/index.js.map +1 -1
  182. package/dist/configurators/reasonix.d.ts +23 -0
  183. package/dist/configurators/reasonix.d.ts.map +1 -0
  184. package/dist/configurators/reasonix.js +60 -0
  185. package/dist/configurators/reasonix.js.map +1 -0
  186. package/dist/configurators/shared.d.ts.map +1 -1
  187. package/dist/configurators/shared.js +8 -0
  188. package/dist/configurators/shared.js.map +1 -1
  189. package/dist/configurators/workflow.d.ts +8 -0
  190. package/dist/configurators/workflow.d.ts.map +1 -1
  191. package/dist/configurators/workflow.js +14 -3
  192. package/dist/configurators/workflow.js.map +1 -1
  193. package/dist/constants/paths.d.ts +4 -0
  194. package/dist/constants/paths.d.ts.map +1 -1
  195. package/dist/constants/paths.js +4 -0
  196. package/dist/constants/paths.js.map +1 -1
  197. package/dist/migrations/manifests/0.5.13.json +9 -0
  198. package/dist/migrations/manifests/0.5.14.json +9 -0
  199. package/dist/migrations/manifests/0.5.15.json +9 -0
  200. package/dist/migrations/manifests/0.5.16.json +9 -0
  201. package/dist/migrations/manifests/0.5.17.json +9 -0
  202. package/dist/migrations/manifests/0.5.18.json +9 -0
  203. package/dist/migrations/manifests/0.5.19.json +9 -0
  204. package/dist/migrations/manifests/0.6.0-beta.10.json +9 -0
  205. package/dist/migrations/manifests/0.6.0-beta.11.json +9 -0
  206. package/dist/migrations/manifests/0.6.0-beta.12.json +9 -0
  207. package/dist/migrations/manifests/0.6.0-beta.13.json +9 -0
  208. package/dist/migrations/manifests/0.6.0-beta.14.json +9 -0
  209. package/dist/migrations/manifests/0.6.0-beta.15.json +9 -0
  210. package/dist/migrations/manifests/0.6.0-beta.16.json +9 -0
  211. package/dist/migrations/manifests/0.6.0-beta.17.json +9 -0
  212. package/dist/migrations/manifests/0.6.0-beta.18.json +16 -0
  213. package/dist/migrations/manifests/0.6.0-beta.19.json +9 -0
  214. package/dist/migrations/manifests/0.6.0-beta.20.json +9 -0
  215. package/dist/migrations/manifests/0.6.0-beta.21.json +9 -0
  216. package/dist/migrations/manifests/0.6.0-beta.22.json +9 -0
  217. package/dist/migrations/manifests/0.6.0-beta.23.json +88 -0
  218. package/dist/migrations/manifests/0.6.0-beta.9.json +9 -0
  219. package/dist/migrations/manifests/0.6.0-rc.0.json +9 -0
  220. package/dist/templates/claude/agents/trellis-check.md +12 -6
  221. package/dist/templates/claude/agents/trellis-implement.md +1 -1
  222. package/dist/templates/claude/agents/trellis-research.md +1 -1
  223. package/dist/templates/claude/settings.json +4 -4
  224. package/dist/templates/codebuddy/agents/trellis-check.md +12 -6
  225. package/dist/templates/codebuddy/agents/trellis-implement.md +1 -1
  226. package/dist/templates/codebuddy/agents/trellis-research.md +1 -1
  227. package/dist/templates/codebuddy/settings.json +4 -4
  228. package/dist/templates/codex/agents/trellis-check.toml +0 -25
  229. package/dist/templates/codex/agents/trellis-implement.toml +0 -25
  230. package/dist/templates/codex/config.toml +9 -16
  231. package/dist/templates/codex/hooks/session-start.py +22 -0
  232. package/dist/templates/codex/hooks.json +2 -2
  233. package/dist/templates/codex/skills/brainstorm/SKILL.md +69 -519
  234. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/task-system.md +27 -0
  235. package/dist/templates/common/bundled-skills/trellis-session-insight/SKILL.md +81 -0
  236. package/dist/templates/common/bundled-skills/trellis-session-insight/references/cli-quick-reference.md +66 -0
  237. package/dist/templates/common/bundled-skills/trellis-session-insight/references/triggering-patterns.md +93 -0
  238. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/SKILL.md +41 -0
  239. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/mcp-setup.md +90 -0
  240. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/repository-analysis.md +59 -0
  241. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/spec-task-planning.md +61 -0
  242. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/spec-writing.md +70 -0
  243. package/dist/templates/common/skills/brainstorm.md +68 -518
  244. package/dist/templates/copilot/hooks/session-start.py +36 -11
  245. package/dist/templates/copilot/hooks.json +2 -2
  246. package/dist/templates/copilot/prompts/brainstorm.prompt.md +69 -519
  247. package/dist/templates/cursor/agents/trellis-check.md +12 -6
  248. package/dist/templates/cursor/agents/trellis-implement.md +1 -1
  249. package/dist/templates/cursor/agents/trellis-research.md +1 -1
  250. package/dist/templates/cursor/hooks.json +1 -7
  251. package/dist/templates/droid/droids/trellis-check.md +12 -6
  252. package/dist/templates/droid/droids/trellis-implement.md +1 -1
  253. package/dist/templates/droid/droids/trellis-research.md +1 -1
  254. package/dist/templates/droid/settings.json +4 -4
  255. package/dist/templates/gemini/agents/trellis-check.md +11 -5
  256. package/dist/templates/gemini/settings.json +2 -2
  257. package/dist/templates/kiro/agents/trellis-check.json +1 -1
  258. package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +127 -9
  259. package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +171 -6
  260. package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +48 -4
  261. package/dist/templates/markdown/spec/guides/index.md.txt +18 -0
  262. package/dist/templates/opencode/agents/trellis-check.md +11 -5
  263. package/dist/templates/opencode/lib/trellis-context.js +73 -11
  264. package/dist/templates/opencode/plugins/inject-subagent-context.js +112 -26
  265. package/dist/templates/opencode/plugins/inject-workflow-state.js +8 -1
  266. package/dist/templates/opencode/plugins/session-start.js +9 -1
  267. package/dist/templates/pi/agents/trellis-check.md +5 -4
  268. package/dist/templates/pi/agents/trellis-implement.md +5 -4
  269. package/dist/templates/pi/extensions/trellis/index.ts.txt +1339 -913
  270. package/dist/templates/pi/settings.json +0 -9
  271. package/dist/templates/qoder/agents/trellis-check.md +12 -6
  272. package/dist/templates/qoder/agents/trellis-implement.md +1 -1
  273. package/dist/templates/qoder/agents/trellis-research.md +1 -1
  274. package/dist/templates/qoder/settings.json +4 -4
  275. package/dist/templates/reasonix/agents/trellis-check.md +36 -0
  276. package/dist/templates/reasonix/agents/trellis-implement.md +41 -0
  277. package/dist/templates/reasonix/index.d.ts +13 -0
  278. package/dist/templates/reasonix/index.d.ts.map +1 -0
  279. package/dist/templates/reasonix/index.js +16 -0
  280. package/dist/templates/reasonix/index.js.map +1 -0
  281. package/dist/templates/shared-hooks/index.d.ts.map +1 -1
  282. package/dist/templates/shared-hooks/index.js +0 -1
  283. package/dist/templates/shared-hooks/index.js.map +1 -1
  284. package/dist/templates/shared-hooks/inject-workflow-state.py +22 -0
  285. package/dist/templates/shared-hooks/session-start.py +25 -8
  286. package/dist/templates/trellis/agents/check.md +70 -0
  287. package/dist/templates/trellis/agents/implement.md +71 -0
  288. package/dist/templates/trellis/config.yaml +20 -0
  289. package/dist/templates/trellis/index.d.ts +13 -0
  290. package/dist/templates/trellis/index.d.ts.map +1 -1
  291. package/dist/templates/trellis/index.js +22 -0
  292. package/dist/templates/trellis/index.js.map +1 -1
  293. package/dist/templates/trellis/scripts/common/safe_commit.py +49 -19
  294. package/dist/templates/trellis/scripts/common/session_context.py +215 -138
  295. package/dist/templates/trellis/scripts/common/task_store.py +94 -16
  296. package/dist/templates/trellis/workflow.md +21 -0
  297. package/dist/types/ai-tools.d.ts +4 -4
  298. package/dist/types/ai-tools.d.ts.map +1 -1
  299. package/dist/types/ai-tools.js +16 -0
  300. package/dist/types/ai-tools.js.map +1 -1
  301. package/dist/utils/agent-refs.d.ts +31 -0
  302. package/dist/utils/agent-refs.d.ts.map +1 -0
  303. package/dist/utils/agent-refs.js +63 -0
  304. package/dist/utils/agent-refs.js.map +1 -0
  305. package/dist/utils/cwd-guard.d.ts +38 -0
  306. package/dist/utils/cwd-guard.d.ts.map +1 -0
  307. package/dist/utils/cwd-guard.js +62 -0
  308. package/dist/utils/cwd-guard.js.map +1 -0
  309. package/dist/utils/file-writer.d.ts +13 -0
  310. package/dist/utils/file-writer.d.ts.map +1 -1
  311. package/dist/utils/file-writer.js +59 -1
  312. package/dist/utils/file-writer.js.map +1 -1
  313. package/dist/utils/manifest-prune.d.ts +61 -0
  314. package/dist/utils/manifest-prune.d.ts.map +1 -0
  315. package/dist/utils/manifest-prune.js +136 -0
  316. package/dist/utils/manifest-prune.js.map +1 -0
  317. package/dist/utils/registry-config.d.ts +7 -0
  318. package/dist/utils/registry-config.d.ts.map +1 -0
  319. package/dist/utils/registry-config.js +171 -0
  320. package/dist/utils/registry-config.js.map +1 -0
  321. package/dist/utils/task-json.d.ts +9 -42
  322. package/dist/utils/task-json.d.ts.map +1 -1
  323. package/dist/utils/task-json.js +8 -45
  324. package/dist/utils/task-json.js.map +1 -1
  325. package/dist/utils/template-fetcher.d.ts +11 -0
  326. package/dist/utils/template-fetcher.d.ts.map +1 -1
  327. package/dist/utils/template-fetcher.js +51 -2
  328. package/dist/utils/template-fetcher.js.map +1 -1
  329. package/dist/utils/template-hash.d.ts +32 -6
  330. package/dist/utils/template-hash.d.ts.map +1 -1
  331. package/dist/utils/template-hash.js +53 -31
  332. package/dist/utils/template-hash.js.map +1 -1
  333. package/dist/utils/workflow-resolver.d.ts +86 -0
  334. package/dist/utils/workflow-resolver.d.ts.map +1 -0
  335. package/dist/utils/workflow-resolver.js +265 -0
  336. package/dist/utils/workflow-resolver.js.map +1 -0
  337. package/package.json +9 -8
@@ -2,6 +2,7 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import chalk from "chalk";
4
4
  import inquirer from "inquirer";
5
+ import { toPosix } from "./posix.js";
5
6
  // Global write mode (set from CLI options)
6
7
  let globalWriteMode = "ask";
7
8
  export function setWriteMode(mode) {
@@ -10,6 +11,51 @@ export function setWriteMode(mode) {
10
11
  export function getWriteMode() {
11
12
  return globalWriteMode;
12
13
  }
14
+ // ---------------------------------------------------------------------------
15
+ // Write recording
16
+ //
17
+ // `trellis init` uses recording to capture exactly which files were actually
18
+ // written this run (vs skipped because they already existed). The captured
19
+ // set is what `.template-hashes.json` should contain — NOT a blind directory
20
+ // walk of `.codex/` / `.claude/` / etc, which would include user-owned files
21
+ // that pre-dated init. See `pruneOrphanManifestKeys` for the self-heal side
22
+ // of the same contract.
23
+ // ---------------------------------------------------------------------------
24
+ /** When recording is active, every actual `writeFile` disk write appends here. */
25
+ let writeRecorder = null;
26
+ /** Project root used to convert absolute write paths to POSIX-relative keys. */
27
+ let writeRecorderRoot = null;
28
+ /**
29
+ * Begin recording every write into the returned Set. Calls accumulate into the
30
+ * same set until `stopRecordingWrites` runs. POSIX relative paths (relative to
31
+ * `cwd`) are stored, matching `.template-hashes.json` keys.
32
+ *
33
+ * Nested recording sessions are NOT supported — the caller must ensure
34
+ * `stopRecordingWrites` runs before the next `startRecordingWrites`. Failure
35
+ * is silent (the second `start` replaces the first set), so callers should
36
+ * always pair start/stop in try/finally.
37
+ */
38
+ export function startRecordingWrites(cwd) {
39
+ const sink = new Set();
40
+ writeRecorder = sink;
41
+ writeRecorderRoot = cwd;
42
+ return sink;
43
+ }
44
+ /** End recording. Subsequent writes are not captured until `start` is called again. */
45
+ export function stopRecordingWrites() {
46
+ writeRecorder = null;
47
+ writeRecorderRoot = null;
48
+ }
49
+ /** Record a successful write. Called internally by `writeFile`. */
50
+ function recordWrite(absPath) {
51
+ if (!writeRecorder || !writeRecorderRoot)
52
+ return;
53
+ const rel = path.relative(writeRecorderRoot, absPath);
54
+ // Defensive: skip writes outside cwd (no meaningful manifest key).
55
+ if (rel.startsWith("..") || path.isAbsolute(rel))
56
+ return;
57
+ writeRecorder.add(toPosix(rel));
58
+ }
13
59
  /**
14
60
  * Get relative path from cwd for display
15
61
  */
@@ -49,12 +95,15 @@ export async function writeFile(filePath, content, options) {
49
95
  if (options?.executable) {
50
96
  fs.chmodSync(filePath, "755");
51
97
  }
98
+ recordWrite(filePath);
52
99
  return true;
53
100
  }
54
101
  // File exists, check if content is identical
55
102
  const existingContent = fs.readFileSync(filePath, "utf-8");
56
103
  if (existingContent === content) {
57
- // Content identical, skip silently (no output)
104
+ // Content identical, but no disk write happened. Do not record it for
105
+ // init-time manifests: pre-existing user files can legitimately be
106
+ // byte-identical to a Trellis template and still not be Trellis-owned.
58
107
  return false;
59
108
  }
60
109
  // File exists with different content, handle based on mode.
@@ -70,15 +119,22 @@ export async function writeFile(filePath, content, options) {
70
119
  fs.chmodSync(filePath, "755");
71
120
  }
72
121
  console.log(chalk.yellow(` ↻ Overwritten: ${displayPath}`));
122
+ recordWrite(filePath);
73
123
  return true;
74
124
  }
75
125
  if (mode === "skip") {
76
126
  console.log(chalk.gray(` ○ Skipped: ${displayPath} (already exists)`));
127
+ // Skipped: trellis did NOT write this file — caller should not track it
128
+ // in the manifest. This is the AGENTS.md skip-existing case.
77
129
  return false;
78
130
  }
79
131
  if (mode === "append") {
80
132
  appendToFile(filePath, content, options);
81
133
  console.log(chalk.blue(` + Appended: ${displayPath}`));
134
+ // Append: trellis added trellis content to a user-owned file. Tracking
135
+ // is risky here (uninstall would unlink the whole file), so we do NOT
136
+ // record appended files. Users on `--append` get a fresh manifest miss
137
+ // on next update; that's the safer default.
82
138
  return true;
83
139
  }
84
140
  // mode === 'ask': Interactive prompt
@@ -107,6 +163,7 @@ export async function writeFile(filePath, content, options) {
107
163
  fs.chmodSync(filePath, "755");
108
164
  }
109
165
  console.log(chalk.yellow(` ↻ Overwritten: ${displayPath}`));
166
+ recordWrite(filePath);
110
167
  return true;
111
168
  }
112
169
  if (action === "append") {
@@ -126,6 +183,7 @@ export async function writeFile(filePath, content, options) {
126
183
  fs.chmodSync(filePath, "755");
127
184
  }
128
185
  console.log(chalk.yellow(` ↻ Overwritten: ${displayPath}`));
186
+ recordWrite(filePath);
129
187
  return true;
130
188
  }
131
189
  if (action === "append-all") {
@@ -1 +1 @@
1
- {"version":3,"file":"file-writer.js","sourceRoot":"","sources":["../../src/utils/file-writer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"file-writer.js","sourceRoot":"","sources":["../../src/utils/file-writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,QAAQ,MAAM,UAAU,CAAC;AAEhC,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAYrC,2CAA2C;AAC3C,IAAI,eAAe,GAAc,KAAK,CAAC;AAEvC,MAAM,UAAU,YAAY,CAAC,IAAe;IAC1C,eAAe,GAAG,IAAI,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,eAAe,CAAC;AACzB,CAAC;AAED,8EAA8E;AAC9E,kBAAkB;AAClB,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,6EAA6E;AAC7E,6EAA6E;AAC7E,4EAA4E;AAC5E,wBAAwB;AACxB,8EAA8E;AAE9E,kFAAkF;AAClF,IAAI,aAAa,GAAuB,IAAI,CAAC;AAC7C,gFAAgF;AAChF,IAAI,iBAAiB,GAAkB,IAAI,CAAC;AAE5C;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,aAAa,GAAG,IAAI,CAAC;IACrB,iBAAiB,GAAG,GAAG,CAAC;IACxB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,mBAAmB;IACjC,aAAa,GAAG,IAAI,CAAC;IACrB,iBAAiB,GAAG,IAAI,CAAC;AAC3B,CAAC;AAED,mEAAmE;AACnE,SAAS,WAAW,CAAC,OAAe;IAClC,IAAI,CAAC,aAAa,IAAI,CAAC,iBAAiB;QAAE,OAAO;IACjD,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;IACtD,mEAAmE;IACnE,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO;IACzD,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,QAAgB;IACvC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAClD,OAAO,YAAY,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CACnB,QAAgB,EAChB,OAAe,EACf,OAAkC;IAElC,MAAM,eAAe,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3D,MAAM,UAAU,GAAG,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC;QAC/C,CAAC,CAAC,eAAe,GAAG,OAAO;QAC3B,CAAC,CAAC,eAAe,GAAG,IAAI,GAAG,OAAO,CAAC;IACrC,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACvC,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC;QACxB,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAChC,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,QAAgB,EAChB,OAAe,EACf,OAAkC;IAElC,MAAM,MAAM,GAAG,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,WAAW,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAE9C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,qCAAqC;QACrC,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACpC,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC;YACxB,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAChC,CAAC;QACD,WAAW,CAAC,QAAQ,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6CAA6C;IAC7C,MAAM,eAAe,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3D,IAAI,eAAe,KAAK,OAAO,EAAE,CAAC;QAChC,sEAAsE;QACtE,mEAAmE;QACnE,uEAAuE;QACvE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,4DAA4D;IAC5D,uEAAuE;IACvE,0EAA0E;IAC1E,gEAAgE;IAChE,MAAM,IAAI,GACR,eAAe,KAAK,KAAK,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK;QAC/C,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,eAAe,CAAC;IAEtB,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACpC,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC;YACxB,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,oBAAoB,WAAW,EAAE,CAAC,CAAC,CAAC;QAC7D,WAAW,CAAC,QAAQ,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,WAAW,mBAAmB,CAAC,CAAC,CAAC;QACxE,wEAAwE;QACxE,6DAA6D;QAC7D,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,WAAW,EAAE,CAAC,CAAC,CAAC;QACxD,uEAAuE;QACvE,sEAAsE;QACtE,uEAAuE;QACvE,4CAA4C;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,qCAAqC;IACrC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAe;QACrD;YACE,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,SAAS,WAAW,8CAA8C;YAC3E,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,MAAM,EAAE;gBAC/C,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE;gBACzC,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,QAAQ,EAAE;gBAC1C,EAAE,IAAI,EAAE,8BAA8B,EAAE,KAAK,EAAE,UAAU,EAAE;gBAC3D,EAAE,IAAI,EAAE,mCAAmC,EAAE,KAAK,EAAE,eAAe,EAAE;gBACrE,EAAE,IAAI,EAAE,gCAAgC,EAAE,KAAK,EAAE,YAAY,EAAE;aAChE;SACF;KACF,CAAC,CAAC;IAEH,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,WAAW,EAAE,CAAC,CAAC,CAAC;QACvD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;QAC3B,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACpC,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC;YACxB,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,oBAAoB,WAAW,EAAE,CAAC,CAAC,CAAC;QAC7D,WAAW,CAAC,QAAQ,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACxB,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,WAAW,EAAE,CAAC,CAAC,CAAC;QACxD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;QAC1B,eAAe,GAAG,MAAM,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,WAAW,EAAE,CAAC,CAAC,CAAC;QACvD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,MAAM,KAAK,eAAe,EAAE,CAAC;QAC/B,eAAe,GAAG,OAAO,CAAC;QAC1B,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACpC,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC;YACxB,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,oBAAoB,WAAW,EAAE,CAAC,CAAC,CAAC;QAC7D,WAAW,CAAC,QAAQ,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAM,KAAK,YAAY,EAAE,CAAC;QAC5B,eAAe,GAAG,QAAQ,CAAC;QAC3B,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,WAAW,EAAE,CAAC,CAAC,CAAC;QACxD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Self-heal poisoned `.template-hashes.json` manifests.
3
+ *
4
+ * Versions before this fix walked `.codex/`, `.claude/`, etc. with a blind
5
+ * recursive scan when computing the manifest, so they hashed user-owned
6
+ * runtime data (`.codex/sessions/*`, `.claude/projects/*.jsonl`, pre-existing
7
+ * `AGENTS.md`, user-added `.codex/skills/<custom>/`, …). On uninstall, every
8
+ * manifest entry is unlinked, which silently deletes user data.
9
+ *
10
+ * `pruneOrphanManifestKeys` removes any manifest entry that no current
11
+ * platform configurator owns. The two entry points that consume it are
12
+ * `trellis update` (before migration classification) and `trellis uninstall`
13
+ * (before plan building). Together they ensure existing poisoned manifests
14
+ * self-correct on the next routine command.
15
+ *
16
+ * Rules:
17
+ * - `.trellis/*` entries are ALWAYS kept. `trellis uninstall` removes
18
+ * `.trellis/` wholesale via `fs.rmSync(..., { recursive: true })`, so
19
+ * manifest accuracy there doesn't affect uninstall data-loss. `update`
20
+ * also relies on these entries to detect user-modified workflow files.
21
+ * - Root-level `AGENTS.md` is kept only when it still looks Trellis-managed
22
+ * (contains the managed block markers) or is missing on disk. This
23
+ * self-heals old poisoned manifests for user-owned AGENTS.md files that
24
+ * predated init and were skipped.
25
+ * - Paths referenced by `from`/`to` of any migration manifest entry
26
+ * (rename, rename-dir, delete, safe-file-delete) are preserved. Pruning
27
+ * them would prevent legitimate pending migrations from finding their
28
+ * source/target.
29
+ * - Everything else: if the path is not in the union of
30
+ * `collectPlatformTemplates()` for currently-configured platforms, it is
31
+ * pruned. This matches "files trellis actually wrote during init/update".
32
+ */
33
+ import type { AITool } from "../types/ai-tools.js";
34
+ import type { TemplateHashes } from "../types/migration.js";
35
+ export interface PruneResult {
36
+ /** Manifest keys removed (POSIX-style relative paths). */
37
+ pruned: string[];
38
+ /** The post-prune manifest (saved to disk only when `pruned.length > 0`). */
39
+ hashes: TemplateHashes;
40
+ }
41
+ export interface PruneOptions {
42
+ /**
43
+ * Save the pruned manifest to `.template-hashes.json`. Defaults to true.
44
+ * Callers can pass `false` to compute the prune without mutating disk
45
+ * (dry-run, change-analysis passes).
46
+ */
47
+ persist?: boolean;
48
+ }
49
+ /**
50
+ * Walk the manifest and split it into kept vs pruned entries.
51
+ *
52
+ * @param cwd Project root — used to save the rewritten manifest.
53
+ * @param configuredPlatforms Output of `getConfiguredPlatforms(cwd)` — caller
54
+ * resolves this so we don't have to re-walk the filesystem.
55
+ * @param hashes Already-loaded manifest contents. Passing it in (vs reading
56
+ * from disk) lets the caller chain `loadHashes` → prune → use the result.
57
+ * @param options.persist When true (default), saves the pruned manifest to
58
+ * disk. Pass `false` for dry-run flows.
59
+ */
60
+ export declare function pruneOrphanManifestKeys(cwd: string, configuredPlatforms: readonly AITool[], hashes: TemplateHashes, options?: PruneOptions): PruneResult;
61
+ //# sourceMappingURL=manifest-prune.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest-prune.d.ts","sourceRoot":"","sources":["../../src/utils/manifest-prune.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAUH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAK5D,MAAM,WAAW,WAAW;IAC1B,0DAA0D;IAC1D,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,6EAA6E;IAC7E,MAAM,EAAE,cAAc,CAAC;CACxB;AAoDD,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,MAAM,EACX,mBAAmB,EAAE,SAAS,MAAM,EAAE,EACtC,MAAM,EAAE,cAAc,EACtB,OAAO,GAAE,YAAiB,GACzB,WAAW,CAmCb"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Self-heal poisoned `.template-hashes.json` manifests.
3
+ *
4
+ * Versions before this fix walked `.codex/`, `.claude/`, etc. with a blind
5
+ * recursive scan when computing the manifest, so they hashed user-owned
6
+ * runtime data (`.codex/sessions/*`, `.claude/projects/*.jsonl`, pre-existing
7
+ * `AGENTS.md`, user-added `.codex/skills/<custom>/`, …). On uninstall, every
8
+ * manifest entry is unlinked, which silently deletes user data.
9
+ *
10
+ * `pruneOrphanManifestKeys` removes any manifest entry that no current
11
+ * platform configurator owns. The two entry points that consume it are
12
+ * `trellis update` (before migration classification) and `trellis uninstall`
13
+ * (before plan building). Together they ensure existing poisoned manifests
14
+ * self-correct on the next routine command.
15
+ *
16
+ * Rules:
17
+ * - `.trellis/*` entries are ALWAYS kept. `trellis uninstall` removes
18
+ * `.trellis/` wholesale via `fs.rmSync(..., { recursive: true })`, so
19
+ * manifest accuracy there doesn't affect uninstall data-loss. `update`
20
+ * also relies on these entries to detect user-modified workflow files.
21
+ * - Root-level `AGENTS.md` is kept only when it still looks Trellis-managed
22
+ * (contains the managed block markers) or is missing on disk. This
23
+ * self-heals old poisoned manifests for user-owned AGENTS.md files that
24
+ * predated init and were skipped.
25
+ * - Paths referenced by `from`/`to` of any migration manifest entry
26
+ * (rename, rename-dir, delete, safe-file-delete) are preserved. Pruning
27
+ * them would prevent legitimate pending migrations from finding their
28
+ * source/target.
29
+ * - Everything else: if the path is not in the union of
30
+ * `collectPlatformTemplates()` for currently-configured platforms, it is
31
+ * pruned. This matches "files trellis actually wrote during init/update".
32
+ */
33
+ import fs from "node:fs";
34
+ import path from "node:path";
35
+ import { collectPlatformTemplates } from "../configurators/index.js";
36
+ import { FILE_NAMES } from "../constants/paths.js";
37
+ import { getAllMigrations } from "../migrations/index.js";
38
+ import { saveHashes } from "./template-hash.js";
39
+ import { toPosix } from "./posix.js";
40
+ const TRELLIS_BLOCK_START = "<!-- TRELLIS:START -->";
41
+ const TRELLIS_BLOCK_END = "<!-- TRELLIS:END -->";
42
+ /**
43
+ * Compute the union of "what trellis writes" across:
44
+ * - every configured platform's collectTemplates() output
45
+ * - root-level AGENTS.md when it still carries Trellis managed-block markers
46
+ * - every migration manifest's from/to path (preserve so legitimate
47
+ * pending migrations can find their source/target)
48
+ */
49
+ function buildKnownKeys(configuredPlatforms) {
50
+ const known = new Set();
51
+ for (const id of configuredPlatforms) {
52
+ const templates = collectPlatformTemplates(id);
53
+ if (!templates)
54
+ continue;
55
+ for (const key of templates.keys()) {
56
+ known.add(toPosix(key));
57
+ }
58
+ }
59
+ // Preserve any path referenced by a migration: legitimate pending
60
+ // rename/delete operations need to resolve their `from` (and the target's
61
+ // hash record for `to`) even if the current registry doesn't list it.
62
+ for (const migration of getAllMigrations()) {
63
+ if (migration.from)
64
+ known.add(toPosix(migration.from));
65
+ if (migration.to)
66
+ known.add(toPosix(migration.to));
67
+ }
68
+ return known;
69
+ }
70
+ /**
71
+ * Root-level AGENTS.md needs special handling because it has no platform
72
+ * registry owner. New fixed inits record it only when written, but old
73
+ * manifests may contain a user-owned AGENTS.md that init skipped. The
74
+ * managed block markers are the least destructive ownership signal: no
75
+ * markers means preserve the user's file by pruning the stale manifest key.
76
+ */
77
+ function shouldKeepAgentsMd(cwd) {
78
+ const fullPath = path.join(cwd, FILE_NAMES.AGENTS);
79
+ if (!fs.existsSync(fullPath)) {
80
+ return true;
81
+ }
82
+ try {
83
+ const content = fs.readFileSync(fullPath, "utf-8");
84
+ return (content.includes(TRELLIS_BLOCK_START) &&
85
+ content.includes(TRELLIS_BLOCK_END));
86
+ }
87
+ catch {
88
+ return true;
89
+ }
90
+ }
91
+ /**
92
+ * Walk the manifest and split it into kept vs pruned entries.
93
+ *
94
+ * @param cwd Project root — used to save the rewritten manifest.
95
+ * @param configuredPlatforms Output of `getConfiguredPlatforms(cwd)` — caller
96
+ * resolves this so we don't have to re-walk the filesystem.
97
+ * @param hashes Already-loaded manifest contents. Passing it in (vs reading
98
+ * from disk) lets the caller chain `loadHashes` → prune → use the result.
99
+ * @param options.persist When true (default), saves the pruned manifest to
100
+ * disk. Pass `false` for dry-run flows.
101
+ */
102
+ export function pruneOrphanManifestKeys(cwd, configuredPlatforms, hashes, options = {}) {
103
+ const persist = options.persist ?? true;
104
+ const known = buildKnownKeys(configuredPlatforms);
105
+ const pruned = [];
106
+ const kept = {};
107
+ for (const [rawKey, value] of Object.entries(hashes)) {
108
+ const key = toPosix(rawKey);
109
+ // Always preserve .trellis/ entries — they're for the workflow tree
110
+ // which uninstall removes wholesale and which update needs for
111
+ // modified-file detection.
112
+ if (key.startsWith(".trellis/") || key === ".trellis") {
113
+ kept[key] = value;
114
+ continue;
115
+ }
116
+ if (key === FILE_NAMES.AGENTS) {
117
+ if (shouldKeepAgentsMd(cwd)) {
118
+ kept[key] = value;
119
+ }
120
+ else {
121
+ pruned.push(key);
122
+ }
123
+ continue;
124
+ }
125
+ if (known.has(key)) {
126
+ kept[key] = value;
127
+ continue;
128
+ }
129
+ pruned.push(key);
130
+ }
131
+ if (persist && pruned.length > 0) {
132
+ saveHashes(cwd, kept);
133
+ }
134
+ return { pruned, hashes: kept };
135
+ }
136
+ //# sourceMappingURL=manifest-prune.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest-prune.js","sourceRoot":"","sources":["../../src/utils/manifest-prune.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface SpecRegistryConfig {
2
+ source: string;
3
+ template?: string;
4
+ }
5
+ export declare function loadSpecRegistryConfig(cwd: string): SpecRegistryConfig | null;
6
+ export declare function writeSpecRegistryConfig(cwd: string, config: SpecRegistryConfig): void;
7
+ //# sourceMappingURL=registry-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-config.d.ts","sourceRoot":"","sources":["../../src/utils/registry-config.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAmBD,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAmD7E;AAED,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,kBAAkB,GACzB,IAAI,CAmGN"}
@@ -0,0 +1,171 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { DIR_NAMES } from "../constants/paths.js";
4
+ import { toPosix } from "./posix.js";
5
+ function configPath(cwd) {
6
+ return path.join(cwd, DIR_NAMES.WORKFLOW, "config.yaml");
7
+ }
8
+ function stripYamlScalar(value) {
9
+ return value.trim().replace(/^['"]|['"]$/g, "");
10
+ }
11
+ function specRegistryLines(config) {
12
+ const normalizedSource = toPosix(config.source);
13
+ return [
14
+ " spec:",
15
+ ` source: ${normalizedSource}`,
16
+ ...(config.template ? [` template: ${config.template}`] : []),
17
+ ];
18
+ }
19
+ export function loadSpecRegistryConfig(cwd) {
20
+ const filePath = configPath(cwd);
21
+ if (!fs.existsSync(filePath))
22
+ return null;
23
+ const lines = fs.readFileSync(filePath, "utf-8").split("\n");
24
+ let inRegistry = false;
25
+ let inSpec = false;
26
+ let source = null;
27
+ let template;
28
+ for (const line of lines) {
29
+ const trimmed = line.trimEnd();
30
+ if (/^registry:\s*$/.test(trimmed)) {
31
+ inRegistry = true;
32
+ inSpec = false;
33
+ continue;
34
+ }
35
+ if (inRegistry && /^\s{2}spec:\s*$/.test(trimmed)) {
36
+ inSpec = true;
37
+ continue;
38
+ }
39
+ if (inRegistry && trimmed !== "" && !trimmed.startsWith(" ")) {
40
+ if (source)
41
+ return { source, ...(template ? { template } : {}) };
42
+ inRegistry = false;
43
+ inSpec = false;
44
+ continue;
45
+ }
46
+ if (inSpec) {
47
+ const sourceMatch = trimmed.match(/^\s{4}source:\s+(.+)$/);
48
+ if (sourceMatch) {
49
+ source = stripYamlScalar(sourceMatch[1]);
50
+ continue;
51
+ }
52
+ const templateMatch = trimmed.match(/^\s{4}template:\s+(.+)$/);
53
+ if (templateMatch) {
54
+ template = stripYamlScalar(templateMatch[1]);
55
+ continue;
56
+ }
57
+ if (trimmed !== "" && !trimmed.startsWith(" ")) {
58
+ if (source)
59
+ return { source, ...(template ? { template } : {}) };
60
+ inSpec = false;
61
+ }
62
+ }
63
+ }
64
+ if (source)
65
+ return { source, ...(template ? { template } : {}) };
66
+ return null;
67
+ }
68
+ export function writeSpecRegistryConfig(cwd, config) {
69
+ const filePath = configPath(cwd);
70
+ if (!fs.existsSync(filePath))
71
+ return;
72
+ const normalizedSource = toPosix(config.source);
73
+ const specLines = specRegistryLines(config);
74
+ const content = fs.readFileSync(filePath, "utf-8");
75
+ if (/^registry:\s*$/m.test(content)) {
76
+ const lines = content.split("\n");
77
+ const output = [];
78
+ let inRegistry = false;
79
+ let inSpec = false;
80
+ let sawSpec = false;
81
+ let wroteSource = false;
82
+ let wroteTemplate = false;
83
+ for (const line of lines) {
84
+ const trimmed = line.trimEnd();
85
+ if (/^registry:\s*$/.test(trimmed)) {
86
+ inRegistry = true;
87
+ inSpec = false;
88
+ sawSpec = false;
89
+ wroteSource = false;
90
+ output.push(line);
91
+ continue;
92
+ }
93
+ if (inRegistry && trimmed !== "" && !trimmed.startsWith(" ")) {
94
+ if (inSpec) {
95
+ if (!wroteSource)
96
+ output.push(` source: ${normalizedSource}`);
97
+ if (config.template && !wroteTemplate) {
98
+ output.push(` template: ${config.template}`);
99
+ }
100
+ }
101
+ else if (!sawSpec) {
102
+ output.push(...specLines);
103
+ }
104
+ inRegistry = false;
105
+ inSpec = false;
106
+ }
107
+ if (inRegistry && /^\s{2}spec:\s*$/.test(trimmed)) {
108
+ inSpec = true;
109
+ sawSpec = true;
110
+ wroteSource = false;
111
+ wroteTemplate = false;
112
+ output.push(line);
113
+ continue;
114
+ }
115
+ if (inSpec && /^\s{4}source:\s+/.test(trimmed)) {
116
+ output.push(` source: ${normalizedSource}`);
117
+ wroteSource = true;
118
+ continue;
119
+ }
120
+ if (inSpec && /^\s{4}template:\s+/.test(trimmed)) {
121
+ if (config.template) {
122
+ output.push(` template: ${config.template}`);
123
+ wroteTemplate = true;
124
+ }
125
+ continue;
126
+ }
127
+ if (inSpec && trimmed !== "" && !trimmed.startsWith(" ")) {
128
+ if (!wroteSource)
129
+ output.push(` source: ${normalizedSource}`);
130
+ if (config.template && !wroteTemplate) {
131
+ output.push(` template: ${config.template}`);
132
+ wroteTemplate = true;
133
+ }
134
+ inSpec = false;
135
+ }
136
+ if (inRegistry && trimmed !== "" && !trimmed.startsWith(" ")) {
137
+ inRegistry = false;
138
+ }
139
+ output.push(line);
140
+ }
141
+ if (inRegistry) {
142
+ if (inSpec) {
143
+ if (!wroteSource)
144
+ output.push(` source: ${normalizedSource}`);
145
+ if (config.template && !wroteTemplate) {
146
+ output.push(` template: ${config.template}`);
147
+ }
148
+ }
149
+ else if (!sawSpec) {
150
+ output.push(...specLines);
151
+ }
152
+ }
153
+ fs.writeFileSync(filePath, output.join("\n"), "utf-8");
154
+ return;
155
+ }
156
+ const section = [
157
+ "",
158
+ "#-------------------------------------------------------------------------------",
159
+ "# Registry",
160
+ "#-------------------------------------------------------------------------------",
161
+ "",
162
+ "# Source used to install .trellis/spec. trellis update refreshes this",
163
+ "# hash-tracked spec template while preserving local edits through the",
164
+ "# normal update conflict flow.",
165
+ "registry:",
166
+ ...specLines,
167
+ "",
168
+ ].join("\n");
169
+ fs.writeFileSync(filePath, content.trimEnd() + "\n" + section, "utf-8");
170
+ }
171
+ //# sourceMappingURL=registry-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-config.js","sourceRoot":"","sources":["../../src/utils/registry-config.ts"],"names":[],"mappings":"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"}
@@ -1,46 +1,13 @@
1
1
  /**
2
- * Canonical task.json shape — single source of truth shared by all TS writers.
2
+ * Canonical task.json shape — single source of truth shared by all TS
3
+ * writers. The canonical types and factory now live in the
4
+ * `@mindfoldhq/trellis-core` task API; this module re-exports them under
5
+ * the legacy `TaskJson` / `emptyTaskJson` names for CLI call sites.
3
6
  *
4
- * The runtime Python writer is `.trellis/scripts/common/task_store.py` in
5
- * `cmd_create` (lines ~147-172). This TS factory mirrors that 24-field shape
6
- * so bootstrap tasks (trellis init) and migration tasks (trellis update
7
- * --migrate) produce structurally identical task.json files.
8
- *
9
- * Field names, order, and null defaults match task_store.py exactly.
10
- */
11
- export interface TaskJson {
12
- id: string;
13
- name: string;
14
- title: string;
15
- description: string;
16
- status: string;
17
- dev_type: string | null;
18
- scope: string | null;
19
- package: string | null;
20
- priority: string;
21
- creator: string;
22
- assignee: string;
23
- createdAt: string;
24
- completedAt: string | null;
25
- branch: string | null;
26
- base_branch: string | null;
27
- worktree_path: string | null;
28
- commit: string | null;
29
- pr_url: string | null;
30
- subtasks: string[];
31
- children: string[];
32
- parent: string | null;
33
- relatedFiles: string[];
34
- notes: string;
35
- meta: Record<string, unknown>;
36
- }
37
- /**
38
- * Produce a fully-populated canonical-shape TaskJson.
39
- *
40
- * All 24 fields are emitted in canonical order. `overrides` shallow-merges on
41
- * top — callers should supply the per-task values (id, name, title, assignee,
42
- * createdAt, etc.) and leave null-default fields untouched unless they have a
43
- * real value.
7
+ * New code should prefer `TrellisTaskRecord` / `emptyTaskRecord` from
8
+ * `@mindfoldhq/trellis-core/task` directly.
44
9
  */
45
- export declare function emptyTaskJson(overrides?: Partial<TaskJson>): TaskJson;
10
+ import { emptyTaskRecord, type TrellisTaskRecord } from "@mindfoldhq/trellis-core/task";
11
+ export type TaskJson = TrellisTaskRecord;
12
+ export declare const emptyTaskJson: typeof emptyTaskRecord;
46
13
  //# sourceMappingURL=task-json.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"task-json.d.ts","sourceRoot":"","sources":["../../src/utils/task-json.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,SAAS,GAAE,OAAO,CAAC,QAAQ,CAAM,GAAG,QAAQ,CA6BzE"}
1
+ {"version":3,"file":"task-json.d.ts","sourceRoot":"","sources":["../../src/utils/task-json.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,eAAe,EACf,KAAK,iBAAiB,EACvB,MAAM,+BAA+B,CAAC;AAEvC,MAAM,MAAM,QAAQ,GAAG,iBAAiB,CAAC;AAEzC,eAAO,MAAM,aAAa,wBAAkB,CAAC"}