codetrellis 0.0.0-stage → 0.3.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 (448) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +27 -2
  3. package/bin/codetrellis.mjs +4 -0
  4. package/package.json +41 -4
  5. package/reader/material-reader.mjs +130346 -0
  6. package/resources/tree-sitter/README.md +150 -0
  7. package/resources/tree-sitter/tree-sitter-c-sharp.wasm +0 -0
  8. package/resources/tree-sitter/tree-sitter-go.wasm +0 -0
  9. package/resources/tree-sitter/tree-sitter-java.wasm +0 -0
  10. package/resources/tree-sitter/tree-sitter-javascript.wasm +0 -0
  11. package/resources/tree-sitter/tree-sitter-kotlin.wasm +0 -0
  12. package/resources/tree-sitter/tree-sitter-php.wasm +0 -0
  13. package/resources/tree-sitter/tree-sitter-python.wasm +0 -0
  14. package/resources/tree-sitter/tree-sitter-ruby.wasm +0 -0
  15. package/resources/tree-sitter/tree-sitter-rust.wasm +0 -0
  16. package/resources/tree-sitter/tree-sitter-swift.wasm +0 -0
  17. package/resources/tree-sitter/tree-sitter-tsx.wasm +0 -0
  18. package/resources/tree-sitter/tree-sitter-typescript.wasm +0 -0
  19. package/resources/tree-sitter/tree-sitter.wasm +0 -0
  20. package/src/backend/agent/claude-code-watcher.js +270 -0
  21. package/src/backend/index.js +8 -0
  22. package/src/backend/lib/sha256-file.js +39 -0
  23. package/src/backend/lib/zip-entries.js +98 -0
  24. package/src/backend/lifecycle.js +102 -0
  25. package/src/backend/mcp/binding-headers.js +54 -0
  26. package/src/backend/mcp/client-identity.js +44 -0
  27. package/src/backend/mcp/connector/command.js +110 -0
  28. package/src/backend/mcp/connector/core.js +278 -0
  29. package/src/backend/mcp/connector/files.js +121 -0
  30. package/src/backend/mcp/connector/hook.js +284 -0
  31. package/src/backend/mcp/connector/main.js +126 -0
  32. package/src/backend/mcp/connector/sse-upstream.js +152 -0
  33. package/src/backend/mcp/helpers.js +43 -0
  34. package/src/backend/mcp/prompt-builders.js +104 -0
  35. package/src/backend/mcp/resources.js +197 -0
  36. package/src/backend/mcp/server.js +813 -0
  37. package/src/backend/mcp/skill-guide.js +1528 -0
  38. package/src/backend/mcp/tools/architecture-tools.js +273 -0
  39. package/src/backend/mcp/tools/audio-tools.js +117 -0
  40. package/src/backend/mcp/tools/awareness-tools.js +623 -0
  41. package/src/backend/mcp/tools/budget-tools.js +185 -0
  42. package/src/backend/mcp/tools/channel-tools.js +205 -0
  43. package/src/backend/mcp/tools/contribution-tools.js +181 -0
  44. package/src/backend/mcp/tools/drift-tools.js +252 -0
  45. package/src/backend/mcp/tools/git-tools.js +316 -0
  46. package/src/backend/mcp/tools/governance-tools.js +175 -0
  47. package/src/backend/mcp/tools/graph-tools.js +181 -0
  48. package/src/backend/mcp/tools/intake-tools.js +244 -0
  49. package/src/backend/mcp/tools/mobile-tools.js +118 -0
  50. package/src/backend/mcp/tools/peer-tools.js +330 -0
  51. package/src/backend/mcp/tools/plan-item-tools.js +1601 -0
  52. package/src/backend/mcp/tools/plan-tools.js +680 -0
  53. package/src/backend/mcp/tools/presence-tools.js +185 -0
  54. package/src/backend/mcp/tools/project-config-tools.js +150 -0
  55. package/src/backend/mcp/tools/review-tools.js +172 -0
  56. package/src/backend/mcp/tools/session-tools.js +554 -0
  57. package/src/backend/mcp/tools/system-docs-tools.js +168 -0
  58. package/src/backend/mcp/tools/terminal-tools.js +186 -0
  59. package/src/backend/mcp/tools/test-tools.js +117 -0
  60. package/src/backend/mcp/tools/ui-tools.js +356 -0
  61. package/src/backend/mcp/types.js +15 -0
  62. package/src/backend/middleware/local-auth.js +116 -0
  63. package/src/backend/server.js +5951 -0
  64. package/src/backend/services/agent-event-log.js +350 -0
  65. package/src/backend/services/architecture-rule.js +584 -0
  66. package/src/backend/services/architecture-rules.js +275 -0
  67. package/src/backend/services/artefact-content-service.js +181 -0
  68. package/src/backend/services/artefact-service.js +305 -0
  69. package/src/backend/services/artefact-watcher.js +167 -0
  70. package/src/backend/services/ast-parser.js +327 -0
  71. package/src/backend/services/audio-buffer-service.js +152 -0
  72. package/src/backend/services/awareness-notices.js +139 -0
  73. package/src/backend/services/awareness-replies.js +194 -0
  74. package/src/backend/services/awareness-service.js +344 -0
  75. package/src/backend/services/awareness-signals.js +267 -0
  76. package/src/backend/services/baseline-store.js +83 -0
  77. package/src/backend/services/branch-workstreams.js +341 -0
  78. package/src/backend/services/breakpoint-service.js +584 -0
  79. package/src/backend/services/brief-service.js +299 -0
  80. package/src/backend/services/budget-service.js +528 -0
  81. package/src/backend/services/callsites/base.js +15 -0
  82. package/src/backend/services/callsites/csharp.js +148 -0
  83. package/src/backend/services/callsites/go.js +163 -0
  84. package/src/backend/services/callsites/index.js +53 -0
  85. package/src/backend/services/callsites/kotlin.js +123 -0
  86. package/src/backend/services/callsites/process-env.js +125 -0
  87. package/src/backend/services/callsites/python.js +91 -0
  88. package/src/backend/services/callsites/ruby.js +164 -0
  89. package/src/backend/services/callsites/shared.js +198 -0
  90. package/src/backend/services/callsites/swift.js +115 -0
  91. package/src/backend/services/callsites/typescript.js +87 -0
  92. package/src/backend/services/capability-token.js +108 -0
  93. package/src/backend/services/change-check.js +156 -0
  94. package/src/backend/services/channel-dispatcher-service.js +235 -0
  95. package/src/backend/services/channel-event-file-service.js +125 -0
  96. package/src/backend/services/channel-event-service.js +297 -0
  97. package/src/backend/services/check-runs.js +177 -0
  98. package/src/backend/services/checkout-identity.js +73 -0
  99. package/src/backend/services/claude-code-parallel.js +221 -0
  100. package/src/backend/services/claude-desktop-config.js +186 -0
  101. package/src/backend/services/cli-install.js +249 -0
  102. package/src/backend/services/clock.js +57 -0
  103. package/src/backend/services/cloud-files.js +191 -0
  104. package/src/backend/services/coalesce.js +50 -0
  105. package/src/backend/services/code-breakpoints.js +291 -0
  106. package/src/backend/services/comment-service.js +168 -0
  107. package/src/backend/services/commit-attribution.js +134 -0
  108. package/src/backend/services/commit-edges.js +99 -0
  109. package/src/backend/services/confined-fs.js +241 -0
  110. package/src/backend/services/conformity-gate.js +132 -0
  111. package/src/backend/services/contribution-service.js +409 -0
  112. package/src/backend/services/coverage-service.js +173 -0
  113. package/src/backend/services/criteria-service.js +721 -0
  114. package/src/backend/services/criterion-checks.js +387 -0
  115. package/src/backend/services/criterion-loop-service.js +411 -0
  116. package/src/backend/services/cross-system-service.js +231 -0
  117. package/src/backend/services/database.js +916 -0
  118. package/src/backend/services/db-schema.js +1358 -0
  119. package/src/backend/services/deviation-service.js +344 -0
  120. package/src/backend/services/diff-engine.js +168 -0
  121. package/src/backend/services/evidence.js +363 -0
  122. package/src/backend/services/external-intake-service.js +269 -0
  123. package/src/backend/services/external-pointer-service.js +195 -0
  124. package/src/backend/services/external-refs-service.js +214 -0
  125. package/src/backend/services/file-history.js +158 -0
  126. package/src/backend/services/file-watcher.js +193 -0
  127. package/src/backend/services/folder-requests.js +118 -0
  128. package/src/backend/services/freeze-service.js +189 -0
  129. package/src/backend/services/gemini-cli-hook.js +172 -0
  130. package/src/backend/services/git-activity-service.js +325 -0
  131. package/src/backend/services/git-blobs.js +70 -0
  132. package/src/backend/services/git-branches.js +357 -0
  133. package/src/backend/services/git-checkout.js +153 -0
  134. package/src/backend/services/git-commit-service.js +91 -0
  135. package/src/backend/services/git-env.js +121 -0
  136. package/src/backend/services/git-identity.js +84 -0
  137. package/src/backend/services/git-refs.js +386 -0
  138. package/src/backend/services/git-safety.js +58 -0
  139. package/src/backend/services/grant-guard.js +67 -0
  140. package/src/backend/services/html-view-policy.js +135 -0
  141. package/src/backend/services/human-decision.js +55 -0
  142. package/src/backend/services/importers.js +159 -0
  143. package/src/backend/services/intent-service.js +105 -0
  144. package/src/backend/services/ipc-dispatcher.js +164 -0
  145. package/src/backend/services/item-git-state.js +208 -0
  146. package/src/backend/services/line-changes.js +232 -0
  147. package/src/backend/services/line-history.js +174 -0
  148. package/src/backend/services/local-api-changes.js +40 -0
  149. package/src/backend/services/logger.js +217 -0
  150. package/src/backend/services/material-footprints.js +203 -0
  151. package/src/backend/services/material-place.js +82 -0
  152. package/src/backend/services/material-reader/docx-markdown.js +198 -0
  153. package/src/backend/services/material-reader/fixtures.test-helper.js +169 -0
  154. package/src/backend/services/material-reader/quote.js +44 -0
  155. package/src/backend/services/material-reader/reader-host.js +202 -0
  156. package/src/backend/services/material-signals.js +141 -0
  157. package/src/backend/services/mcp-capabilities.js +390 -0
  158. package/src/backend/services/mdns-service.js +304 -0
  159. package/src/backend/services/mobile-api-server.js +281 -0
  160. package/src/backend/services/mobile-approvals.js +306 -0
  161. package/src/backend/services/mobile-awareness.js +180 -0
  162. package/src/backend/services/mobile-breakpoints.js +115 -0
  163. package/src/backend/services/mobile-budget.js +98 -0
  164. package/src/backend/services/mobile-freeze.js +106 -0
  165. package/src/backend/services/mobile-proposals.js +100 -0
  166. package/src/backend/services/mobile-rpc-service.js +1289 -0
  167. package/src/backend/services/mobile-workstreams.js +160 -0
  168. package/src/backend/services/monorepo-detector.js +131 -0
  169. package/src/backend/services/other-work.js +45 -0
  170. package/src/backend/services/pack-seal.js +129 -0
  171. package/src/backend/services/paired-device-service.js +192 -0
  172. package/src/backend/services/pairing-server.js +323 -0
  173. package/src/backend/services/pairing-service.js +200 -0
  174. package/src/backend/services/pantry-resolution-service.js +166 -0
  175. package/src/backend/services/parsers/base.js +124 -0
  176. package/src/backend/services/parsers/csharp.js +224 -0
  177. package/src/backend/services/parsers/go.js +180 -0
  178. package/src/backend/services/parsers/index.js +101 -0
  179. package/src/backend/services/parsers/java.js +103 -0
  180. package/src/backend/services/parsers/kotlin.js +252 -0
  181. package/src/backend/services/parsers/php.js +113 -0
  182. package/src/backend/services/parsers/python.js +189 -0
  183. package/src/backend/services/parsers/ruby.js +212 -0
  184. package/src/backend/services/parsers/rust.js +97 -0
  185. package/src/backend/services/parsers/swift.js +221 -0
  186. package/src/backend/services/parsers/typescript.js +235 -0
  187. package/src/backend/services/pattern-scan.js +65 -0
  188. package/src/backend/services/patterns.js +281 -0
  189. package/src/backend/services/peer-audit-service.js +123 -0
  190. package/src/backend/services/peer-auth.js +153 -0
  191. package/src/backend/services/peer-capabilities.js +209 -0
  192. package/src/backend/services/peer-connection-service.js +450 -0
  193. package/src/backend/services/peer-grants.js +33 -0
  194. package/src/backend/services/persistence.js +116 -0
  195. package/src/backend/services/personal-sync-service.js +232 -0
  196. package/src/backend/services/pipeline-approvals.js +72 -0
  197. package/src/backend/services/pipeline.js +232 -0
  198. package/src/backend/services/plan-arrivals.js +68 -0
  199. package/src/backend/services/plan-changes-service.js +273 -0
  200. package/src/backend/services/plan-conflict-service.js +288 -0
  201. package/src/backend/services/plan-dependencies.js +91 -0
  202. package/src/backend/services/plan-doc-guard.js +90 -0
  203. package/src/backend/services/plan-documents-service.js +275 -0
  204. package/src/backend/services/plan-event-service.js +154 -0
  205. package/src/backend/services/plan-file-refs.js +106 -0
  206. package/src/backend/services/plan-file-service.js +1564 -0
  207. package/src/backend/services/plan-history-service.js +156 -0
  208. package/src/backend/services/plan-import-service.js +261 -0
  209. package/src/backend/services/plan-item-service.js +1223 -0
  210. package/src/backend/services/plan-migrate-service.js +395 -0
  211. package/src/backend/services/plan-overlay-service.js +173 -0
  212. package/src/backend/services/plan-phases-service.js +182 -0
  213. package/src/backend/services/plan-progress-service.js +134 -0
  214. package/src/backend/services/plan-review-service.js +262 -0
  215. package/src/backend/services/plan-service.js +682 -0
  216. package/src/backend/services/plan-status.js +113 -0
  217. package/src/backend/services/plan-template-publish-service.js +217 -0
  218. package/src/backend/services/plan-templates-service.js +242 -0
  219. package/src/backend/services/plan-templates.js +1164 -0
  220. package/src/backend/services/planned-overlap-actions.js +200 -0
  221. package/src/backend/services/plans-home.js +224 -0
  222. package/src/backend/services/play-forward.js +256 -0
  223. package/src/backend/services/playback-service.js +117 -0
  224. package/src/backend/services/power-service.js +167 -0
  225. package/src/backend/services/power-signals.js +81 -0
  226. package/src/backend/services/pr-draft-service.js +142 -0
  227. package/src/backend/services/presence-service.js +122 -0
  228. package/src/backend/services/pricing.js +60 -0
  229. package/src/backend/services/project-config-service.js +474 -0
  230. package/src/backend/services/project-scanner.js +184 -0
  231. package/src/backend/services/projection-service.js +69 -0
  232. package/src/backend/services/push-notification-service.js +288 -0
  233. package/src/backend/services/recent-projects-service.js +204 -0
  234. package/src/backend/services/record-chain.js +162 -0
  235. package/src/backend/services/recurrence-rule.js +63 -0
  236. package/src/backend/services/recurring-agent.js +89 -0
  237. package/src/backend/services/recurring-scheduler.js +77 -0
  238. package/src/backend/services/recurring-service.js +276 -0
  239. package/src/backend/services/reference-service.js +169 -0
  240. package/src/backend/services/release-public-key.js +30 -0
  241. package/src/backend/services/release-signature.js +64 -0
  242. package/src/backend/services/remote-audio-service.js +224 -0
  243. package/src/backend/services/remote-interaction-service.js +275 -0
  244. package/src/backend/services/remote-terminal-service.js +324 -0
  245. package/src/backend/services/rendition/child/main.js +76 -0
  246. package/src/backend/services/rendition/engine-host.js +249 -0
  247. package/src/backend/services/rendition/engine-lock.js +39 -0
  248. package/src/backend/services/rendition/engine-lock.json +14 -0
  249. package/src/backend/services/rendition/engine-manifest.js +97 -0
  250. package/src/backend/services/rendition/network-proof.js +73 -0
  251. package/src/backend/services/rendition/rendition-service.js +175 -0
  252. package/src/backend/services/replay-frames.js +387 -0
  253. package/src/backend/services/replay-state.js +201 -0
  254. package/src/backend/services/resolvers/base.js +108 -0
  255. package/src/backend/services/resolvers/csharp.js +109 -0
  256. package/src/backend/services/resolvers/go.js +105 -0
  257. package/src/backend/services/resolvers/index.js +60 -0
  258. package/src/backend/services/resolvers/java.js +63 -0
  259. package/src/backend/services/resolvers/kotlin.js +109 -0
  260. package/src/backend/services/resolvers/php.js +89 -0
  261. package/src/backend/services/resolvers/python.js +154 -0
  262. package/src/backend/services/resolvers/ruby.js +103 -0
  263. package/src/backend/services/resolvers/rust.js +77 -0
  264. package/src/backend/services/resolvers/swift.js +98 -0
  265. package/src/backend/services/resolvers/typescript.js +71 -0
  266. package/src/backend/services/retention.js +54 -0
  267. package/src/backend/services/review-architecture.js +236 -0
  268. package/src/backend/services/review-attest.js +68 -0
  269. package/src/backend/services/review-bundle.js +226 -0
  270. package/src/backend/services/review-graduation.js +93 -0
  271. package/src/backend/services/review-host/bitbucket.js +79 -0
  272. package/src/backend/services/review-host/detect.js +80 -0
  273. package/src/backend/services/review-host/github.js +97 -0
  274. package/src/backend/services/review-host/gitlab.js +77 -0
  275. package/src/backend/services/review-host/host-state.js +103 -0
  276. package/src/backend/services/review-host/http.js +58 -0
  277. package/src/backend/services/review-host/switch.js +120 -0
  278. package/src/backend/services/review-marks.js +72 -0
  279. package/src/backend/services/review-notes.js +169 -0
  280. package/src/backend/services/review-other-work.js +90 -0
  281. package/src/backend/services/review-queue-service.js +147 -0
  282. package/src/backend/services/review-risk.js +127 -0
  283. package/src/backend/services/review-task.js +121 -0
  284. package/src/backend/services/rule-approvals.js +275 -0
  285. package/src/backend/services/rule-baseline.js +134 -0
  286. package/src/backend/services/rule-changes.js +162 -0
  287. package/src/backend/services/rule-preview.js +47 -0
  288. package/src/backend/services/rule-proposals.js +104 -0
  289. package/src/backend/services/rule-scope.js +76 -0
  290. package/src/backend/services/rulebook.js +286 -0
  291. package/src/backend/services/rules-at.js +56 -0
  292. package/src/backend/services/rules-overview.js +88 -0
  293. package/src/backend/services/schema-reconciler.js +250 -0
  294. package/src/backend/services/secret-store.js +119 -0
  295. package/src/backend/services/section-workstreams.js +95 -0
  296. package/src/backend/services/self-write-tracker.js +75 -0
  297. package/src/backend/services/sensor-bridge-service.js +285 -0
  298. package/src/backend/services/session-service.js +192 -0
  299. package/src/backend/services/settings-service.js +324 -0
  300. package/src/backend/services/signal-breakpoints.js +172 -0
  301. package/src/backend/services/signed-approval-record.js +86 -0
  302. package/src/backend/services/signed-approvals.js +244 -0
  303. package/src/backend/services/signoff-pack.js +328 -0
  304. package/src/backend/services/signoff-rows.js +114 -0
  305. package/src/backend/services/skill-arrival-service.js +138 -0
  306. package/src/backend/services/skill-model.js +193 -0
  307. package/src/backend/services/skill-use-service.js +140 -0
  308. package/src/backend/services/skills-service.js +150 -0
  309. package/src/backend/services/snapshot-compare-service.js +397 -0
  310. package/src/backend/services/source-control.js +189 -0
  311. package/src/backend/services/spec-links-service.js +123 -0
  312. package/src/backend/services/spec-proposal-withdraw.js +50 -0
  313. package/src/backend/services/spec-proposals-service.js +470 -0
  314. package/src/backend/services/sql/embedded.js +95 -0
  315. package/src/backend/services/sql/index.js +63 -0
  316. package/src/backend/services/sql/refs.js +357 -0
  317. package/src/backend/services/sql/schema.js +312 -0
  318. package/src/backend/services/sql/tokenizer.js +195 -0
  319. package/src/backend/services/stack-overlaps.js +117 -0
  320. package/src/backend/services/stack-service.js +225 -0
  321. package/src/backend/services/state-sync-service.js +384 -0
  322. package/src/backend/services/stuck-sensor-service.js +200 -0
  323. package/src/backend/services/system-discovery.js +481 -0
  324. package/src/backend/services/system-docs-service.js +701 -0
  325. package/src/backend/services/task-attachments-service.js +340 -0
  326. package/src/backend/services/task-grounding.js +60 -0
  327. package/src/backend/services/task-records/check-run-record.js +146 -0
  328. package/src/backend/services/task-records/check-runs.js +115 -0
  329. package/src/backend/services/task-records/heads.js +88 -0
  330. package/src/backend/services/task-records/material-reads.js +225 -0
  331. package/src/backend/services/task-records/read-record.js +100 -0
  332. package/src/backend/services/task-records/record.js +173 -0
  333. package/src/backend/services/task-records/run-record.js +136 -0
  334. package/src/backend/services/task-records/shared-state.js +548 -0
  335. package/src/backend/services/task-records/signing.js +140 -0
  336. package/src/backend/services/task-records/split-signals.js +52 -0
  337. package/src/backend/services/task-records/test-runs.js +164 -0
  338. package/src/backend/services/task-records/trust.js +243 -0
  339. package/src/backend/services/task-rules.js +81 -0
  340. package/src/backend/services/task-workstreams.js +90 -0
  341. package/src/backend/services/terminal-history-service.js +266 -0
  342. package/src/backend/services/terminal-service.js +267 -0
  343. package/src/backend/services/test-clock.js +53 -0
  344. package/src/backend/services/tests/grounding.js +266 -0
  345. package/src/backend/services/tests/junit.js +104 -0
  346. package/src/backend/services/tests/teammate-runs.js +134 -0
  347. package/src/backend/services/tests/test-results.js +234 -0
  348. package/src/backend/services/tree-watcher.js +204 -0
  349. package/src/backend/services/trellis-service.js +204 -0
  350. package/src/backend/services/trusted-roots.js +186 -0
  351. package/src/backend/services/update-download-service.js +342 -0
  352. package/src/backend/services/update-service.js +266 -0
  353. package/src/backend/services/watch-ignore.js +76 -0
  354. package/src/backend/services/webhook-egress.js +206 -0
  355. package/src/backend/services/webrtc-service.js +413 -0
  356. package/src/backend/services/work-changes.js +59 -0
  357. package/src/backend/services/workstream-binding.js +82 -0
  358. package/src/backend/services/workstream-commits.js +116 -0
  359. package/src/backend/services/workstream-imports.js +177 -0
  360. package/src/backend/services/workstream-service.js +335 -0
  361. package/src/backend/services/workstream-symbols.js +223 -0
  362. package/src/backend/services/workstream-watch-service.js +391 -0
  363. package/src/backend/services/worktree-service.js +235 -0
  364. package/src/cli/agent.js +100 -0
  365. package/src/cli/args.js +209 -0
  366. package/src/cli/conformity.js +106 -0
  367. package/src/cli/desktop.js +91 -0
  368. package/src/cli/main.js +411 -0
  369. package/src/cli/pipeline.js +109 -0
  370. package/src/cli/plan-verbs.js +259 -0
  371. package/src/cli/review-adapters.js +220 -0
  372. package/src/cli/review-output.js +93 -0
  373. package/src/cli/review-post.js +89 -0
  374. package/src/cli/review-sink.js +183 -0
  375. package/src/cli/review-skill.js +44 -0
  376. package/src/cli/review-verify.js +104 -0
  377. package/src/cli/review.js +386 -0
  378. package/src/cli/sarif.js +148 -0
  379. package/src/cli/verbs.js +360 -0
  380. package/src/shared/build-info.js +39 -0
  381. package/src/shared/lib/agent-review.js +199 -0
  382. package/src/shared/lib/agent-turns.js +140 -0
  383. package/src/shared/lib/awareness-digest.js +120 -0
  384. package/src/shared/lib/branch-name.js +45 -0
  385. package/src/shared/lib/breakpoint-words.js +118 -0
  386. package/src/shared/lib/budget-words.js +56 -0
  387. package/src/shared/lib/burst.js +69 -0
  388. package/src/shared/lib/call-entry.js +105 -0
  389. package/src/shared/lib/check-compare.js +42 -0
  390. package/src/shared/lib/check-words.js +216 -0
  391. package/src/shared/lib/csv.js +62 -0
  392. package/src/shared/lib/folder-entry.js +87 -0
  393. package/src/shared/lib/freeze-words.js +60 -0
  394. package/src/shared/lib/fuzzy.js +84 -0
  395. package/src/shared/lib/git-state-words.js +80 -0
  396. package/src/shared/lib/grep-entry.js +86 -0
  397. package/src/shared/lib/grounding-line.js +61 -0
  398. package/src/shared/lib/import-line.js +71 -0
  399. package/src/shared/lib/item-status.js +249 -0
  400. package/src/shared/lib/line-changes.js +53 -0
  401. package/src/shared/lib/locator.js +71 -0
  402. package/src/shared/lib/matcher.js +120 -0
  403. package/src/shared/lib/merge-order.js +65 -0
  404. package/src/shared/lib/open-findings.js +68 -0
  405. package/src/shared/lib/other-work.js +108 -0
  406. package/src/shared/lib/package-entry.js +142 -0
  407. package/src/shared/lib/plan-vocab.js +40 -0
  408. package/src/shared/lib/pptx-xml.js +86 -0
  409. package/src/shared/lib/proposal-words.js +61 -0
  410. package/src/shared/lib/recurrence.js +183 -0
  411. package/src/shared/lib/references.js +72 -0
  412. package/src/shared/lib/rule-pattern.js +56 -0
  413. package/src/shared/lib/sdp-fingerprint.js +115 -0
  414. package/src/shared/lib/sdp-minimal.js +123 -0
  415. package/src/shared/lib/secret-paths.js +34 -0
  416. package/src/shared/lib/signal-words.js +172 -0
  417. package/src/shared/lib/signoff.js +56 -0
  418. package/src/shared/lib/skills-note.js +60 -0
  419. package/src/shared/lib/spec-sections.js +78 -0
  420. package/src/shared/lib/symbol-entry.js +60 -0
  421. package/src/shared/lib/tool-phrasing.js +338 -0
  422. package/src/shared/lib/turn-gap.js +27 -0
  423. package/src/shared/lib/workstream-words.js +38 -0
  424. package/src/shared/lib/xlsx-xml.js +144 -0
  425. package/src/shared/lib/zip-reader.js +99 -0
  426. package/src/shared/types/agent.js +27 -0
  427. package/src/shared/types/architecture-rules.js +30 -0
  428. package/src/shared/types/ast.js +15 -0
  429. package/src/shared/types/breakpoint.js +33 -0
  430. package/src/shared/types/channel.js +41 -0
  431. package/src/shared/types/criteria.js +15 -0
  432. package/src/shared/types/graph.js +15 -0
  433. package/src/shared/types/index.js +53 -0
  434. package/src/shared/types/peer.js +36 -0
  435. package/src/shared/types/pipeline.js +15 -0
  436. package/src/shared/types/plan.js +15 -0
  437. package/src/shared/types/play-forward.js +15 -0
  438. package/src/shared/types/power.js +15 -0
  439. package/src/shared/types/presence.js +15 -0
  440. package/src/shared/types/project-config.js +35 -0
  441. package/src/shared/types/project.js +15 -0
  442. package/src/shared/types/record.js +15 -0
  443. package/src/shared/types/recurring.js +15 -0
  444. package/src/shared/types/review.js +15 -0
  445. package/src/shared/types/settings.js +114 -0
  446. package/src/shared/types/stack.js +15 -0
  447. package/src/shared/types/system-doc.js +15 -0
  448. package/src/shared/types/system.js +15 -0
@@ -0,0 +1,1164 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var plan_templates_exports = {};
29
+ __export(plan_templates_exports, {
30
+ PLAN_TEMPLATES: () => PLAN_TEMPLATES,
31
+ getTemplate: () => getTemplate,
32
+ listTemplates: () => listTemplates,
33
+ substitutePlaceholders: () => substitutePlaceholders
34
+ });
35
+ module.exports = __toCommonJS(plan_templates_exports);
36
+ var import_node_fs = __toESM(require("node:fs"));
37
+ var import_confined_fs = require("./confined-fs");
38
+ var import_node_path = __toESM(require("node:path"));
39
+ var import_node_os = __toESM(require("node:os"));
40
+ var import_yaml = require("yaml");
41
+ const MASS_REFACTOR_OVERVIEW = `# Mass refactor \u2014 executive overview
42
+
43
+ This plan is a **deep-mode** plan (Phase 12 \xA7A): instead of a flat
44
+ list of tasks, it's broken into six phases that run mostly in
45
+ sequence. Each phase has its own scope, prerequisites, git
46
+ checkpoint, and acceptance criteria \u2014 bind tasks to a phase via
47
+ \`update_task(..., phase_uid)\` and pull the next available task with
48
+ \`get_next_task(plan_uid, phase_uid?)\`.
49
+
50
+ ## Why the swf shape
51
+
52
+ This template mirrors swf's \`docs/oms/002-oms-integration/\`
53
+ structure so multiple agents working in parallel can share rich
54
+ context: a numbered overview, one doc per phase, plus cross-cutting
55
+ patterns / testing / security guidance. Read the relevant
56
+ phase doc + the patterns + testing docs before claiming a task.
57
+
58
+ ## How to operate
59
+
60
+ 1. Read the executive overview (this doc) end-to-end.
61
+ 2. Read the phase doc for the phase you're about to work in.
62
+ 3. Skim **Patterns** + **Testing strategy**; they apply across phases.
63
+ 4. \`get_next_task(plan_uid, phase_uid)\` to pick a task.
64
+ 5. \`claim_task(plan_uid, task_uid)\` then \`update_task(..., 'in_progress')\`.
65
+ 6. Implement, then \`get_drift_report(plan_uid)\` before marking done.
66
+
67
+ ## Out of scope
68
+
69
+ (fill this in \u2014 what this refactor explicitly does NOT touch)
70
+ `;
71
+ const PHASE_DOC_BODY = (n, title) => `# ${String(n).padStart(2, "0")} \u2014 ${title}
72
+
73
+ ## Scope
74
+
75
+ (what this phase covers \u2014 e.g. backend models, routes, frontend types)
76
+
77
+ ## Prerequisites
78
+
79
+ (what must be done before this phase starts)
80
+
81
+ ## Plan of attack
82
+
83
+ 1.
84
+ 2.
85
+ 3.
86
+
87
+ ## Backend changes
88
+
89
+ ### Models
90
+
91
+ ### Routes / handlers
92
+
93
+ ### Services
94
+
95
+ ## Frontend changes
96
+
97
+ ### Types
98
+
99
+ ### API client
100
+
101
+ ### Components
102
+
103
+ ## Testing
104
+
105
+ ### Unit
106
+
107
+ ### Integration
108
+
109
+ ### Manual smoke
110
+
111
+ ## Acceptance criteria
112
+
113
+ - [ ]
114
+ - [ ]
115
+ - [ ]
116
+
117
+ ## Git checkpoint
118
+
119
+ Tag: \`<your-prefix>-${String(n).padStart(2, "0")}-${title.toLowerCase().replace(/[^a-z0-9]+/g, "-")}\`
120
+ `;
121
+ const PATTERNS_DOC = `# Patterns to follow
122
+
123
+ ## Code style
124
+
125
+ -
126
+
127
+ ## Naming
128
+
129
+ -
130
+
131
+ ## File organisation
132
+
133
+ -
134
+
135
+ # Anti-patterns to avoid
136
+
137
+ -
138
+ `;
139
+ const TESTING_DOC = `# Testing strategy
140
+
141
+ ## Coverage targets
142
+
143
+ | Area | Target | Notes |
144
+ |---|---|---|
145
+ | Models | 90% line | Core data layer |
146
+ | Routes | 80% endpoint | Each endpoint must have \u22651 happy path + \u22651 error path |
147
+ | UI components | Smoke render | Snapshot is fine |
148
+
149
+ ## Per-phase strategy
150
+
151
+ - **01 Foundation** \u2014 types compile, lints clean, no functional tests required yet
152
+ - **02 Data layer** \u2014 model unit tests + a migration round-trip test
153
+ - **03 API** \u2014 route integration tests covering happy + auth + error paths
154
+ - **04 Frontend** \u2014 component smoke tests + e2e for critical flows
155
+ - **05 Integration** \u2014 e2e covering the full cross-system flow
156
+ - **06 Cutover** \u2014 pre/post-deploy smoke; rollback rehearsal
157
+
158
+ ## Fixtures / mocks
159
+
160
+ -
161
+ `;
162
+ const SECURITY_DOC = `# Security threat model
163
+
164
+ ## Surface area changes
165
+
166
+ (what new attack surface this refactor introduces)
167
+
168
+ ## Sensitive data paths
169
+
170
+ (which paths handle credentials / PII / financial data)
171
+
172
+ ## Do-not-touch
173
+
174
+ (files, endpoints, secrets that must not be modified by this plan)
175
+
176
+ ## Per-phase checks
177
+
178
+ - **01 Foundation** \u2014
179
+ - **02 Data layer** \u2014
180
+ - **03 API** \u2014 auth on every new endpoint; rate limits where applicable
181
+ - **04 Frontend** \u2014 XSS-safe rendering; avoid leaking IDs in URLs
182
+ - **05 Integration** \u2014
183
+ - **06 Cutover** \u2014 rotate any new secrets before turning on traffic
184
+ `;
185
+ const ARCHITECTURE_DOC = `# Architecture overview
186
+
187
+ ## Components touched by this refactor
188
+
189
+ | Component | Role | Phase that changes it |
190
+ |---|---|---|
191
+ | | | |
192
+
193
+ ## Data flow
194
+
195
+ (diagram or prose \u2014 how data moves between the components above)
196
+
197
+ ## New connections this introduces
198
+
199
+ -
200
+
201
+ ## Connections this removes
202
+
203
+ -
204
+
205
+ ## Boundaries
206
+
207
+ (what's the contract between the touched components and everything else)
208
+ `;
209
+ const NEW_FEATURE_REQUIREMENTS = `# Requirements \u2014 {{feature}}
210
+
211
+ ## What this feature does
212
+
213
+ (one-paragraph description in plain language)
214
+
215
+ ## User stories
216
+
217
+ - As a [user type], I want to [goal] so that [benefit]
218
+ - ...
219
+
220
+ ## Success criteria
221
+
222
+ - [ ]
223
+ - [ ]
224
+
225
+ ## Out of scope
226
+
227
+ (what this feature explicitly does NOT do \u2014 anti-scope)
228
+
229
+ ## Open questions
230
+
231
+ -
232
+ `;
233
+ const NEW_FEATURE_DESIGN = `# Design \u2014 {{feature}}
234
+
235
+ ## High-level approach
236
+
237
+ (2-3 sentences on the chosen approach + why)
238
+
239
+ ## New files / modules
240
+
241
+ | Path | Role |
242
+ |---|---|
243
+ | | |
244
+
245
+ ## Modified files
246
+
247
+ | Path | Change |
248
+ |---|---|
249
+ | | |
250
+
251
+ ## Data model changes
252
+
253
+ (new tables / columns / types \u2014 link to migration if applicable)
254
+
255
+ ## API surface
256
+
257
+ | Method | Path | Purpose |
258
+ |---|---|---|
259
+ | | | |
260
+
261
+ ## UI surface
262
+
263
+ (screens / components affected)
264
+ `;
265
+ const NEW_FEATURE_UX = `# UX journey \u2014 {{feature}}
266
+
267
+ ## Entry point
268
+
269
+ (how the user discovers / triggers this feature)
270
+
271
+ ## Happy path
272
+
273
+ 1.
274
+ 2.
275
+ 3.
276
+
277
+ ## Empty / loading / error states
278
+
279
+ | State | What user sees |
280
+ |---|---|
281
+ | First-time / empty | |
282
+ | Loading | |
283
+ | Error | |
284
+
285
+ ## Cross-references
286
+
287
+ (other features / screens that link to this one or are linked from it)
288
+ `;
289
+ const NEW_FEATURE_TESTING = `# Testing \u2014 {{feature}}
290
+
291
+ ## Unit
292
+
293
+ -
294
+
295
+ ## Integration
296
+
297
+ -
298
+
299
+ ## Manual / e2e
300
+
301
+ | Scenario | Steps | Expected |
302
+ |---|---|---|
303
+ | | | |
304
+ `;
305
+ const BUG_FIX_REPORT = `# Bug \u2014 {{bug}}
306
+
307
+ ## Symptom
308
+
309
+ (what the user sees that's wrong)
310
+
311
+ ## Reproduction
312
+
313
+ 1.
314
+ 2.
315
+ 3.
316
+
317
+ **Expected**:
318
+ **Actual**:
319
+
320
+ ## Affected area
321
+
322
+ {{area}}
323
+
324
+ ## First reported
325
+
326
+ (date / version / customer)
327
+
328
+ ## Severity
329
+
330
+ - [ ] Blocker \u2014 production down or data loss
331
+ - [ ] High \u2014 common path broken
332
+ - [ ] Medium \u2014 workaround exists
333
+ - [ ] Low \u2014 cosmetic
334
+ `;
335
+ const BUG_FIX_ROOT_CAUSE = `# Root cause hypothesis
336
+
337
+ ## Suspected files / functions
338
+
339
+ - {{area}}
340
+
341
+ ## Why it happens
342
+
343
+ (one-paragraph hypothesis \u2014 disprove if possible)
344
+
345
+ ## Why we didn't catch it
346
+
347
+ (missing test? missing type guard? missing review checklist?)
348
+
349
+ ## Related code
350
+
351
+ (grep / xref hits \u2014 places that look similar and might also be broken)
352
+ `;
353
+ const BUG_FIX_REGRESSION = `# Regression test
354
+
355
+ ## Test that would have caught this
356
+
357
+ (unit / integration / e2e \u2014 and where in the suite it should live)
358
+
359
+ ## Test fixture
360
+
361
+ \`\`\`
362
+ (input)
363
+ \`\`\`
364
+
365
+ \`\`\`
366
+ (expected output)
367
+ \`\`\`
368
+
369
+ ## Other tests to add or strengthen
370
+
371
+ (if the bug class suggests a missing pattern of coverage)
372
+ `;
373
+ const LIB_MIG_OVERVIEW = `# Library migration \u2014 {{from_library}} \u2192 {{to_library}}
374
+
375
+ ## Why migrate
376
+
377
+ (perf / maintenance / sunset / API improvements / bundle size \u2014 be specific)
378
+
379
+ ## Risk profile
380
+
381
+ | Dimension | Old | New | Risk |
382
+ |---|---|---|---|
383
+ | Maintenance status | | | |
384
+ | Bundle size | | | |
385
+ | Breaking changes | | | |
386
+ | Type safety | | | |
387
+
388
+ ## Migration strategy
389
+
390
+ - [ ] **Big bang** \u2014 replace everywhere at once. Choose only if blast radius is small.
391
+ - [ ] **Adapter** \u2014 wrap old behind a thin adapter, swap implementations one callsite at a time. Default for non-trivial migrations.
392
+ - [ ] **Strangler** \u2014 both old and new live side-by-side; flag-flip per code path. For very large or risky migrations.
393
+
394
+ ## Rollback plan
395
+
396
+ (what triggers rollback, how to roll back, what's lost)
397
+ `;
398
+ const LIB_MIG_COMPAT = `# Compatibility matrix \u2014 {{from_library}} vs {{to_library}}
399
+
400
+ | {{from_library}} API | {{to_library}} equivalent | Notes |
401
+ |---|---|---|
402
+ | | | |
403
+ | | | |
404
+
405
+ ## Behaviours that change
406
+
407
+ (silent semantic differences \u2014 places where calling code "looks the same" but does something subtly different)
408
+
409
+ ## Behaviours that disappear
410
+
411
+ (deprecated APIs with no replacement \u2014 list each callsite that needs custom handling)
412
+ `;
413
+ const LIB_MIG_ROLLOUT = `# Rollout plan
414
+
415
+ ## Order of callsites
416
+
417
+ (why this order \u2014 usually: smallest / lowest-risk first, hottest path last)
418
+
419
+ | Order | Callsite | Owner | Notes |
420
+ |---|---|---|---|
421
+ | 1 | | | |
422
+ | 2 | | | |
423
+
424
+ ## Verification per step
425
+
426
+ (what test confirms the migrated callsite still works \u2014 and that the rest of the app didn't regress)
427
+
428
+ ## Coexistence
429
+
430
+ (can old and new run in the same process? if not, what's the cut?)
431
+ `;
432
+ const PERF_BUDGET = `# Performance budget \u2014 {{target_metric}}
433
+
434
+ ## Goal
435
+
436
+ Target **{{target_metric}} \u2264 {{target_value}}** on the {{benchmark}} workload.
437
+
438
+ ## Why this metric
439
+
440
+ (p95 latency? cold-start time? bundle size? memory under load? \u2014 pick the one that matters to users and explain)
441
+
442
+ ## Out of scope
443
+
444
+ (metrics that this pass explicitly does NOT optimise; tradeoffs we'll accept)
445
+ `;
446
+ const PERF_BASELINE = `# Baseline measurements
447
+
448
+ ## Reproducer
449
+
450
+ \`\`\`bash
451
+ (exact command / steps to measure \u2014 must be repeatable on a clean machine)
452
+ \`\`\`
453
+
454
+ ## Current numbers
455
+
456
+ | Run | {{target_metric}} | Notes |
457
+ |---|---|---|
458
+ | 1 | | |
459
+ | 2 | | |
460
+ | 3 | | |
461
+ | **Median** | | |
462
+
463
+ ## Hardware / env
464
+
465
+ (machine, OS, node version, etc.)
466
+
467
+ ## Sub-metrics
468
+
469
+ (CPU? memory? syscalls? \u2014 anything that helps narrow the hotspot before profiling)
470
+ `;
471
+ const PERF_HOTSPOTS = `# Hotspot inventory
472
+
473
+ ## Profiler output
474
+
475
+ (paste flame graph / sampled stack \u2014 at minimum, top-10 by self-time)
476
+
477
+ ## Suspect functions / files
478
+
479
+ | Function / file | Why suspected | Estimated win |
480
+ |---|---|---|
481
+ | | | |
482
+
483
+ ## Anti-suspects
484
+
485
+ (places that look hot but are likely not \u2014 saves wasted optimisation effort)
486
+
487
+ ## Picked first
488
+
489
+ (which hotspot we're tackling first + why \u2014 usually highest estimated win \xD7 lowest risk)
490
+ `;
491
+ const PERF_VERIFY = `# Verification
492
+
493
+ ## Re-measurement script
494
+
495
+ (same command as baseline \u2014 copy-paste-able)
496
+
497
+ ## Acceptance
498
+
499
+ | Run | {{target_metric}} | \u0394 vs baseline | Notes |
500
+ |---|---|---|---|
501
+ | 1 | | | |
502
+ | 2 | | | |
503
+ | 3 | | | |
504
+ | **Median** | | | |
505
+
506
+ ## Regression guard
507
+
508
+ (microbenchmark / CI assertion that fails if the metric backslides above the new ceiling \u2014 without this, the win decays in 2 sprints)
509
+
510
+ ## What we didn't do
511
+
512
+ (optimisations considered but skipped \u2014 and why; future-you will want this list)
513
+ `;
514
+ const FROM_TICKET_INTAKE = `# Intake
515
+
516
+ What the ticket says, and what it leaves unsaid.
517
+
518
+ ## The ask, in the requester's words
519
+
520
+ <paste the ticket description verbatim \u2014 do not paraphrase it here, a
521
+ paraphrase loses the thing you will argue about later>
522
+
523
+ ## What this actually touches
524
+
525
+ Fill this in from the graph, not from the ticket. A ticket describes
526
+ intent; the graph knows which files and which services the intent lands
527
+ on. This section is the reason the plan exists rather than the ticket
528
+ being worked directly.
529
+
530
+ - Systems:
531
+ - Files / symbols:
532
+ - Cross-system edges crossed (HTTP, SQL):
533
+
534
+ ## Contradictions found
535
+
536
+ Where the ticket and the codebase disagree. "No API changes" next to a
537
+ story that rewrites a route file belongs here, and belongs here BEFORE
538
+ anyone starts.
539
+
540
+ ## Questions for the requester
541
+
542
+ Answer these before building, not after.
543
+ `;
544
+ const FROM_TICKET_ACCEPTANCE = `# Acceptance criteria
545
+
546
+ Copied from the ticket, one checkbox each, in the requester's words.
547
+
548
+ Keeping the requester's wording matters: this is the list they will
549
+ check against, and a helpfully-reworded criterion is one nobody agreed
550
+ to.
551
+
552
+ - [ ] <criterion>
553
+
554
+ ## Out of scope
555
+
556
+ What the ticket explicitly does NOT cover. Writing it down is what stops
557
+ the plan quietly growing.
558
+ `;
559
+ const ANALYSIS_GUIDE = `# How we do the {{report}}
560
+
561
+ > The guide an agent reads before it starts, and a new analyst reads on day one.
562
+ > Replace each prompt with how your team actually does it.
563
+
564
+ ## Who it is for
565
+
566
+ > The audience, what they decide with it, and what they already know.
567
+
568
+ ## Sources we trust
569
+
570
+ > Which systems or files are the source of truth for each figure, and which are not.
571
+
572
+ ## House rules
573
+
574
+ > Rounding, units, currency, period definitions, how to label a restatement.
575
+
576
+ ## What "done" looks like
577
+
578
+ > Each task's acceptance criteria say it precisely \u2014 this is the short version.
579
+ `;
580
+ const ANALYSIS_MATERIALS = `# Materials
581
+
582
+ Attach what this {{report}} is built from \u2014 record each file as a **material** on this page:
583
+
584
+ - the source data for {{period}} (exports, ledgers, the workbook itself);
585
+ - last period's report, for comparison and tone;
586
+ - the style guide or template the output must follow.
587
+
588
+ An agent reads these through \`read_material\` and cites the exact place \u2014 the sheet and cell,
589
+ the page, the line \u2014 for every figure it uses.
590
+ `;
591
+ const REFACTOR_DESCRIPTION = `## What are you refactoring?
592
+
593
+ > Describe the code you want to change. What module, class, or pattern is being restructured?
594
+
595
+ ## Why refactor now?
596
+
597
+ > What's wrong with the current structure? Is it causing bugs, slowing development, or creating confusion?
598
+
599
+ ## From \u2192 To
600
+
601
+ > What does the current structure look like? What should it look like after?
602
+
603
+ ## Constraints
604
+
605
+ > What must NOT change? Public APIs? Database schemas? Test expectations?
606
+ `;
607
+ const API_CHANGE_DESCRIPTION = `## Endpoint(s)
608
+
609
+ > Which endpoints are changing? Method, path, purpose.
610
+
611
+ ## Current contract
612
+
613
+ > What does the API accept/return today?
614
+
615
+ ## New contract
616
+
617
+ > What should it accept/return after?
618
+
619
+ ## Consumers
620
+
621
+ > Who calls this API? Frontend components? Other services? External clients?
622
+
623
+ ## Migration strategy
624
+
625
+ > How do you handle existing clients? Versioning? Deprecation period?
626
+ `;
627
+ const PLAN_TEMPLATES = [
628
+ {
629
+ id: "from-ticket",
630
+ label: "From a ticket",
631
+ shortDescription: "Intake scaffold for work arriving from Jira, Linear or an issue tracker.",
632
+ longDescription: "For work that starts outside CodeTrellis. An agent holding both your tracker's MCP server and this one can fill it in one turn \u2014 see `create_plan_from_external`, which builds the nested plan directly from a fetched epic. The template is the manual path, and the shape that path produces: an intake page that records what the ticket says AND what the graph says it touches, acceptance criteria in the requester's own words, and two phases that keep clarification separate from building. Use `{{ticket}}` for the key and `{{summary}}` for the title.",
633
+ defaultTitle: "{{ticket}}: {{summary}}",
634
+ defaultPlanDescription: "Work arriving from a tracker. Read the intake page first \u2014 especially the contradictions section \u2014 and get the open questions answered before starting Phase 2.",
635
+ placeholders: [
636
+ { key: "ticket", label: "Ticket key", default: "PROJ-000" },
637
+ { key: "summary", label: "Ticket summary", default: "<what the ticket asks for>" }
638
+ ],
639
+ phases: [
640
+ {
641
+ phaseNumber: 1,
642
+ title: "Clarify",
643
+ scope: "Map the ticket onto the codebase. Which systems does it touch, which files, does it cross a service boundary nobody mentioned? Answer the open questions. No implementation.",
644
+ acceptanceCriteria: "- [ ] Intake page lists the real files and systems, taken from the graph\n- [ ] Acceptance criteria transcribed in the requester's words\n- [ ] Contradictions between the ticket and the codebase written down\n- [ ] Open questions answered by the requester, not guessed at\n"
645
+ },
646
+ {
647
+ phaseNumber: 2,
648
+ title: "Deliver",
649
+ scope: "Build against the acceptance criteria. Each criterion should map to something in the diff.",
650
+ prerequisites: "Phase 1 questions answered and contradictions resolved.",
651
+ acceptanceCriteria: "- [ ] Every acceptance criterion is checked off and traceable to a change\n- [ ] Drift report against the plan: clean\n- [ ] Ticket status written back (get_external_sync_state, then your tracker's MCP)\n"
652
+ }
653
+ ],
654
+ docs: [
655
+ { key: "intake", orderHint: "00", docType: "requirements", title: "Intake", body: FROM_TICKET_INTAKE },
656
+ { key: "acceptance", orderHint: "01", docType: "acceptance_criteria", title: "Acceptance criteria", body: FROM_TICKET_ACCEPTANCE }
657
+ ]
658
+ },
659
+ {
660
+ id: "mass-refactor",
661
+ label: "Mass refactor (swf-style)",
662
+ shortDescription: "6-phase modernization with executive overview, per-phase docs, patterns/testing/security guidance.",
663
+ longDescription: `Models swf's \`docs/oms/002-oms-integration/\` shape: 1 executive overview + 6 numbered phase docs + 1 architecture overview + cross-cutting patterns / testing / security. Each phase is a first-class checkpoint with scope, prereqs, git checkpoint, and acceptance criteria \u2014 built for multiple agents working in parallel on a long migration.`,
664
+ defaultTitle: "Mass refactor: {name}",
665
+ defaultPlanDescription: "Deep-mode plan with phases. Read the executive overview first, then the phase doc you're about to work in.",
666
+ phases: [
667
+ { phaseNumber: 1, title: "Foundation", scope: "Set up shared types, packages, lint config, CI gates. No behavior changes yet.", acceptanceCriteria: "- [ ] Types compile across all packages\n- [ ] Lint and CI pass on the new structure\n" },
668
+ { phaseNumber: 2, title: "Data layer", scope: "New / migrated models, schema migrations, seed data.", prerequisites: "Phase 01 complete.", acceptanceCriteria: "- [ ] Migrations run forward and reverse cleanly\n- [ ] Model unit tests cover happy + edge cases\n" },
669
+ { phaseNumber: 3, title: "API", scope: "New / refactored endpoints, auth wiring, error handling.", prerequisites: "Phase 02 data layer in place.", acceptanceCriteria: "- [ ] Every new endpoint has auth\n- [ ] Integration tests cover happy + auth + error paths\n" },
670
+ { phaseNumber: 4, title: "Frontend", scope: "Types, API client, components, screens.", prerequisites: "Phase 03 endpoints stable.", acceptanceCriteria: "- [ ] Components compile and lint\n- [ ] Critical-flow e2e passes\n" },
671
+ { phaseNumber: 5, title: "Integration", scope: "End-to-end cross-system flows, sync / orchestration jobs.", prerequisites: "Phases 02\u201304 deployable to staging.", acceptanceCriteria: "- [ ] Full cross-system flow passes in staging\n- [ ] Drift report clean against the plan\n" },
672
+ { phaseNumber: 6, title: "Cutover", scope: "Feature flags off \u2192 on, traffic migration, decommission of the old path.", prerequisites: "Phase 05 integration green for at least 24h.", acceptanceCriteria: "- [ ] Old path code-paths removed\n- [ ] Rollback rehearsed and documented\n" }
673
+ ],
674
+ docs: [
675
+ { key: "overview", orderHint: "00", docType: "executive_summary", title: "00 \u2014 Executive overview", body: MASS_REFACTOR_OVERVIEW },
676
+ { key: "arch", orderHint: "00.5", docType: "architecture", title: "Architecture overview", body: ARCHITECTURE_DOC },
677
+ { key: "phase1", orderHint: "01", docType: "architecture", title: "01 \u2014 Foundation", body: PHASE_DOC_BODY(1, "Foundation") },
678
+ { key: "phase2", orderHint: "02", docType: "architecture", title: "02 \u2014 Data layer", body: PHASE_DOC_BODY(2, "Data layer") },
679
+ { key: "phase3", orderHint: "03", docType: "architecture", title: "03 \u2014 API", body: PHASE_DOC_BODY(3, "API") },
680
+ { key: "phase4", orderHint: "04", docType: "architecture", title: "04 \u2014 Frontend", body: PHASE_DOC_BODY(4, "Frontend") },
681
+ { key: "phase5", orderHint: "05", docType: "architecture", title: "05 \u2014 Integration", body: PHASE_DOC_BODY(5, "Integration") },
682
+ { key: "phase6", orderHint: "06", docType: "architecture", title: "06 \u2014 Cutover", body: PHASE_DOC_BODY(6, "Cutover") },
683
+ { key: "patterns", orderHint: "90", docType: "patterns", title: "Patterns", body: PATTERNS_DOC },
684
+ { key: "testing", orderHint: "91", docType: "testing", title: "Testing strategy", body: TESTING_DOC },
685
+ { key: "security", orderHint: "92", docType: "security", title: "Security threat model", body: SECURITY_DOC }
686
+ ]
687
+ },
688
+ {
689
+ id: "new-feature",
690
+ label: "New feature",
691
+ shortDescription: "Three-phase scaffold for adding a feature: design \u2192 implementation \u2192 testing.",
692
+ longDescription: 'Lighter than mass-refactor \u2014 for net-new features. Seeds a requirements doc, design doc, UX journey, and testing plan, plus three phases that map cleanly to "decide \u2192 build \u2192 ship". Use the `{{feature}}` placeholder to give the plan a name in one place.',
693
+ defaultTitle: "Feature: {{feature}}",
694
+ defaultPlanDescription: "Add a new feature. Read the requirements + design docs first, then pick up tasks from the Implementation phase.",
695
+ placeholders: [
696
+ { key: "feature", label: "Feature name", default: "<the feature>" }
697
+ ],
698
+ phases: [
699
+ {
700
+ phaseNumber: 1,
701
+ title: "Design",
702
+ scope: "Lock down requirements, design, and UX journey. No code yet.",
703
+ acceptanceCriteria: "- [ ] Requirements doc complete (success criteria + out-of-scope filled in)\n- [ ] Design doc lists every new / modified file\n- [ ] UX journey covers happy path + empty / loading / error states\n"
704
+ },
705
+ {
706
+ phaseNumber: 2,
707
+ title: "Implementation",
708
+ scope: "Build the feature against the design doc. Backend first if there's a data layer, then API, then UI.",
709
+ prerequisites: "Phase 1 design signed off.",
710
+ acceptanceCriteria: "- [ ] Every file listed in the design doc exists\n- [ ] Lints + typechecks clean\n- [ ] Drift report against the plan: clean\n"
711
+ },
712
+ {
713
+ phaseNumber: 3,
714
+ title: "Testing & polish",
715
+ scope: "Tests for every path in the testing doc, accessibility pass, copy review, telemetry hooks if applicable.",
716
+ prerequisites: "Phase 2 implementation complete and self-tested.",
717
+ acceptanceCriteria: '- [ ] Unit + integration tests for every callout in the testing doc\n- [ ] Manual happy path passes on a clean install\n- [ ] No new "(TODO)" or "(fix me)" comments left in the diff\n'
718
+ }
719
+ ],
720
+ docs: [
721
+ { key: "requirements", orderHint: "00", docType: "acceptance_criteria", title: "Requirements", body: NEW_FEATURE_REQUIREMENTS },
722
+ { key: "design", orderHint: "01", docType: "architecture", title: "Design", body: NEW_FEATURE_DESIGN },
723
+ { key: "ux", orderHint: "02", docType: "ux_ui", title: "UX journey", body: NEW_FEATURE_UX },
724
+ { key: "testing", orderHint: "03", docType: "testing", title: "Testing", body: NEW_FEATURE_TESTING }
725
+ ]
726
+ },
727
+ {
728
+ id: "bug-fix",
729
+ label: "Bug fix",
730
+ shortDescription: "Lean two-phase template: investigate \u2192 fix-with-regression-test.",
731
+ longDescription: 'Built for "something is wrong, find it, fix it, prove it stays fixed". Three docs (bug report, root-cause hypothesis, regression test) and two phases. Use `{{bug}}` for the short description and `{{area}}` to point investigators at the suspected module.',
732
+ defaultTitle: "Bug: {{bug}}",
733
+ defaultPlanDescription: "Reproduce, root-cause, fix, and add a regression test. Don't mark done without the regression test.",
734
+ placeholders: [
735
+ { key: "bug", label: "Bug summary", default: "<one-line description>" },
736
+ { key: "area", label: "Suspected area", default: "<file or module to start in>" }
737
+ ],
738
+ phases: [
739
+ {
740
+ phaseNumber: 1,
741
+ title: "Investigate",
742
+ scope: "Reproduce reliably, identify the root cause, decide the fix shape.",
743
+ acceptanceCriteria: "- [ ] Reliable reproduction documented\n- [ ] Root cause confirmed (not just hypothesised)\n- [ ] Fix approach agreed (with one alternative considered + rejected)\n"
744
+ },
745
+ {
746
+ phaseNumber: 2,
747
+ title: "Fix + regression",
748
+ scope: "Apply the fix, write a regression test that fails on the bug and passes on the fix, ship.",
749
+ prerequisites: "Phase 1 root cause confirmed.",
750
+ acceptanceCriteria: '- [ ] Fix applied, scoped to the root cause\n- [ ] Regression test fails on `git stash` of the fix and passes with it\n- [ ] No nearby suspects left untouched (check the "related code" section)\n'
751
+ }
752
+ ],
753
+ docs: [
754
+ { key: "report", orderHint: "00", docType: "executive_summary", title: "Bug report", body: BUG_FIX_REPORT },
755
+ { key: "rootcause", orderHint: "01", docType: "research", title: "Root cause", body: BUG_FIX_ROOT_CAUSE },
756
+ { key: "regression", orderHint: "02", docType: "testing", title: "Regression test", body: BUG_FIX_REGRESSION }
757
+ ]
758
+ },
759
+ {
760
+ id: "library-migration",
761
+ label: "Library migration",
762
+ shortDescription: "Four-phase scaffold for swapping a dependency: audit \u2192 adapter \u2192 per-callsite \u2192 decommission.",
763
+ longDescription: "For replacing or upgrading a dependency that touches many callsites. Strategy is configurable (big-bang vs adapter vs strangler \u2014 picked in the overview doc). Use `{{from_library}}` and `{{to_library}}` placeholders. The compatibility matrix doc forces you to think through silent-semantic-change traps before code touches any callsite.",
764
+ defaultTitle: "Migrate {{from_library}} \u2192 {{to_library}}",
765
+ defaultPlanDescription: "Replace a dependency without breaking anything. The compatibility matrix is the most important doc \u2014 fill it in honestly before touching any callsite.",
766
+ placeholders: [
767
+ { key: "from_library", label: "From (current library)", default: "<old-lib>" },
768
+ { key: "to_library", label: "To (new library)", default: "<new-lib>" }
769
+ ],
770
+ phases: [
771
+ {
772
+ phaseNumber: 1,
773
+ title: "Audit",
774
+ scope: "Inventory every callsite of {{from_library}}, document API differences, pick a migration strategy.",
775
+ acceptanceCriteria: "- [ ] Compatibility matrix complete\n- [ ] Migration strategy chosen + documented\n- [ ] Rollback plan written\n"
776
+ },
777
+ {
778
+ phaseNumber: 2,
779
+ title: "Adapter / scaffolding",
780
+ scope: 'If the strategy is "adapter," build the adapter layer + tests. If "strangler," set up the flag plumbing. If "big bang," skip \u2014 but reconsider the strategy.',
781
+ prerequisites: "Phase 1 audit complete.",
782
+ acceptanceCriteria: "- [ ] Adapter / flag plumbing in place\n- [ ] One pilot callsite migrated through the adapter and proven equivalent\n"
783
+ },
784
+ {
785
+ phaseNumber: 3,
786
+ title: "Per-callsite migration",
787
+ scope: "Walk the rollout-plan order. One callsite per task; tests for each before moving on.",
788
+ prerequisites: "Phase 2 pilot green.",
789
+ acceptanceCriteria: "- [ ] Every callsite migrated\n- [ ] Per-callsite verification passing\n- [ ] No regressions in the rest of the suite\n"
790
+ },
791
+ {
792
+ phaseNumber: 4,
793
+ title: "Decommission",
794
+ scope: "Remove the adapter, drop {{from_library}} from package.json, prove no leftover imports.",
795
+ prerequisites: "Phase 3 complete + at least 24h of staging soak.",
796
+ acceptanceCriteria: "- [ ] `{{from_library}}` removed from dependencies\n- [ ] `grep` for `{{from_library}}` in src/ returns nothing meaningful\n- [ ] Bundle size measured before / after\n"
797
+ }
798
+ ],
799
+ docs: [
800
+ { key: "overview", orderHint: "00", docType: "executive_summary", title: "Migration overview", body: LIB_MIG_OVERVIEW },
801
+ { key: "compat", orderHint: "01", docType: "architecture", title: "Compatibility matrix", body: LIB_MIG_COMPAT },
802
+ { key: "rollout", orderHint: "02", docType: "rollout", title: "Rollout plan", body: LIB_MIG_ROLLOUT }
803
+ ]
804
+ },
805
+ {
806
+ id: "perf-pass",
807
+ label: "Performance pass",
808
+ shortDescription: "Measure \u2192 identify \u2192 fix \u2192 verify, with a regression guard at the end.",
809
+ longDescription: 'Forces you to measure first and verify last. Four phases that match the only good way to do perf work: baseline measurement, hotspot identification, fix, then re-measurement + a regression guard so the win doesn\'t silently decay. Use `{{target_metric}}` (e.g. "p95 cold-start time") and `{{target_value}}` (e.g. "<400 ms") to set the budget up front.',
810
+ defaultTitle: "Perf pass: {{target_metric}}",
811
+ defaultPlanDescription: "Don't optimise without measuring. The baseline is the contract; the regression guard is the win.",
812
+ placeholders: [
813
+ { key: "target_metric", label: "Target metric", default: "p95 latency" },
814
+ { key: "target_value", label: "Target value", default: "<400 ms" },
815
+ { key: "benchmark", label: "Benchmark workload", default: "production-replay" }
816
+ ],
817
+ phases: [
818
+ {
819
+ phaseNumber: 1,
820
+ title: "Baseline",
821
+ scope: "Lock the metric, lock the workload, capture current numbers reproducibly.",
822
+ acceptanceCriteria: "- [ ] Reproducer command documented\n- [ ] Median of \u22653 runs recorded\n- [ ] Sub-metrics captured (CPU / memory / syscalls etc.)\n"
823
+ },
824
+ {
825
+ phaseNumber: 2,
826
+ title: "Identify hotspots",
827
+ scope: "Profile, surface the suspects, pick the highest-leverage hotspot first.",
828
+ prerequisites: "Phase 1 baseline locked.",
829
+ acceptanceCriteria: "- [ ] Profile output captured + reviewed\n- [ ] Top suspects ranked by estimated win\n- [ ] First hotspot picked with a written estimate\n"
830
+ },
831
+ {
832
+ phaseNumber: 3,
833
+ title: "Fix",
834
+ scope: "Apply the optimisation. One hotspot per task. Don't rewrite anything that wasn't in the suspect list.",
835
+ prerequisites: "Phase 2 hotspot picked.",
836
+ acceptanceCriteria: `- [ ] Fix is scoped to the picked hotspot
837
+ - [ ] Local micro-benchmark shows the expected win
838
+ - [ ] No new abstraction layers added "while we're in here"
839
+ `
840
+ },
841
+ {
842
+ phaseNumber: 4,
843
+ title: "Verify + guard",
844
+ scope: "Re-measure on the same reproducer, write a regression guard so future commits can't silently undo the win.",
845
+ prerequisites: "Phase 3 fix landed.",
846
+ acceptanceCriteria: `- [ ] Re-measured median meets {{target_value}}
847
+ - [ ] Regression guard wired (microbenchmark in CI / perf assertion)
848
+ - [ ] "What we didn't do" list filled in for future-us
849
+ `
850
+ }
851
+ ],
852
+ docs: [
853
+ { key: "budget", orderHint: "00", docType: "constraints", title: "Performance budget", body: PERF_BUDGET },
854
+ { key: "baseline", orderHint: "01", docType: "research", title: "Baseline measurements", body: PERF_BASELINE },
855
+ { key: "hotspots", orderHint: "02", docType: "research", title: "Hotspot inventory", body: PERF_HOTSPOTS },
856
+ { key: "verify", orderHint: "03", docType: "testing", title: "Verification", body: PERF_VERIFY }
857
+ ]
858
+ },
859
+ {
860
+ id: "analysis-report",
861
+ label: "Analysis report",
862
+ shortDescription: "Gather \u2192 Analyse \u2192 Draft \u2192 Review, with a guide, the materials, and criteria for each step.",
863
+ longDescription: "A playbook for a report built from data \u2014 a quarterly pack, a board paper, a regional review. The guide page says how your team does it; the materials page holds what it is built from; four steps carry acceptance criteria that show each kind of evidence once: a recorded output, a figure that cites its cell, the analysis code, its tests, and a person's sign-off. Publish your own version of this plan as a template once it fits how you work.",
864
+ defaultTitle: "{{report}} \u2014 {{period}}",
865
+ defaultPlanDescription: "Read the guide first, then the materials. Every figure in the draft cites the place it came from; the Review step is signed off by a person.",
866
+ placeholders: [
867
+ { key: "report", label: "Report", default: "Quarterly report" },
868
+ { key: "period", label: "Period", default: "Q3" }
869
+ ],
870
+ phases: [],
871
+ docs: [],
872
+ items: [
873
+ { kind: "object", title: "Guide \u2014 how we do the {{report}}", body: ANALYSIS_GUIDE },
874
+ { kind: "object", title: "Materials", body: ANALYSIS_MATERIALS },
875
+ {
876
+ kind: "action",
877
+ title: "Gather",
878
+ body: "Collect the {{period}} source data and record each file as a material. Note anything missing or late.",
879
+ criteria: [
880
+ { text: "Every source file used for {{period}} is recorded as a material", kind: "artefact" }
881
+ ]
882
+ },
883
+ {
884
+ kind: "action",
885
+ title: "Analyse",
886
+ body: "Work the figures. Any calculation is a script in the repo, not a hand edit in a copy of the data.",
887
+ criteria: [
888
+ { text: "Every figure in the analysis cites the sheet and cell it came from", kind: "citation" },
889
+ { text: "The analysis script is committed where the plan says", kind: "code" },
890
+ { text: "The analysis script's tests pass", kind: "test" }
891
+ ]
892
+ },
893
+ {
894
+ kind: "action",
895
+ title: "Draft",
896
+ body: "Write the {{report}} to the house style in the guide, and record it as this step's output.",
897
+ criteria: [
898
+ { text: "The draft {{report}} is recorded as an output", kind: "artefact" }
899
+ ]
900
+ },
901
+ {
902
+ kind: "action",
903
+ title: "Review",
904
+ body: "The report owner reads the draft against the materials and signs it off \u2014 on the desktop or the phone.",
905
+ criteria: [
906
+ { text: "Reviewed and approved by the report owner", kind: "manual" }
907
+ ]
908
+ }
909
+ ]
910
+ },
911
+ {
912
+ id: "refactor",
913
+ label: "Refactor",
914
+ shortDescription: "Rename, move, or restructure existing code.",
915
+ longDescription: "A light, three-step refactor: prepare, migrate, verify. For a long multi-agent modernisation, use Mass refactor instead.",
916
+ defaultTitle: "Refactor: {name}",
917
+ defaultPlanDescription: REFACTOR_DESCRIPTION,
918
+ phases: [],
919
+ docs: [],
920
+ items: [
921
+ { kind: "object", title: "Context & Analysis", body: "## Current structure\n\n> Describe the existing code\n\n## Problems\n\n> What specific issues exist?" },
922
+ { kind: "action", title: "Phase 1: Prepare", body: "Set up any scaffolding, create new files, update imports that need to change." },
923
+ { kind: "action", title: "Phase 2: Migrate", body: "Move/rename the core code. Update all callers." },
924
+ {
925
+ kind: "action",
926
+ title: "Phase 3: Verify & Clean up",
927
+ body: "Run tests, remove old code, update docs.",
928
+ criteria: [{ text: "The test suite passes after the move", kind: "test" }]
929
+ }
930
+ ]
931
+ },
932
+ {
933
+ id: "api-change",
934
+ label: "API change",
935
+ shortDescription: "Add, modify, or deprecate API endpoints.",
936
+ longDescription: "The contract first, then the handlers, then every consumer \u2014 and the tests and docs that describe it.",
937
+ defaultTitle: "API change: {name}",
938
+ defaultPlanDescription: API_CHANGE_DESCRIPTION,
939
+ phases: [],
940
+ docs: [],
941
+ items: [
942
+ { kind: "object", title: "API Design", body: "## Endpoints\n\n| Method | Path | Change |\n|--------|------|--------|\n| | | |\n\n## Request/Response schemas\n\n> ..." },
943
+ { kind: "action", title: "Backend changes", body: "Update route handlers, validation, database queries." },
944
+ { kind: "action", title: "Update consumers", body: "Update all clients/callers of the changed endpoints." },
945
+ { kind: "action", title: "Tests & documentation", body: "Update API tests and any API documentation." }
946
+ ]
947
+ }
948
+ ];
949
+ function listTemplates(projectRoot) {
950
+ const all = collectTemplates(projectRoot);
951
+ return all.map((t) => {
952
+ const tplAny = t;
953
+ const isV2 = Array.isArray(tplAny.items) && tplAny.items.length > 0;
954
+ return {
955
+ id: t.id,
956
+ label: t.label,
957
+ shortDescription: t.shortDescription,
958
+ longDescription: t.longDescription,
959
+ defaultTitle: t.defaultTitle,
960
+ source: t.source ?? "builtin",
961
+ placeholders: t.placeholders,
962
+ phaseCount: t.phases.length,
963
+ docCount: t.docs.length,
964
+ ...isV2 ? { version: 2, itemCount: countTemplateItems(tplAny.items), criteriaCount: countTemplateCriteria(tplAny.items) } : {}
965
+ };
966
+ });
967
+ }
968
+ function countTemplateCriteria(items) {
969
+ let count = 0;
970
+ for (const item of items) {
971
+ if (Array.isArray(item.criteria)) count += item.criteria.length;
972
+ if (Array.isArray(item.children)) count += countTemplateCriteria(item.children);
973
+ }
974
+ return count;
975
+ }
976
+ function countTemplateItems(items) {
977
+ let count = 0;
978
+ for (const item of items) {
979
+ count++;
980
+ if (Array.isArray(item.children)) {
981
+ count += countTemplateItems(item.children);
982
+ }
983
+ }
984
+ return count;
985
+ }
986
+ function getTemplate(id, projectRoot) {
987
+ return collectTemplates(projectRoot).find((t) => t.id === id) ?? null;
988
+ }
989
+ function collectTemplates(projectRoot) {
990
+ const byId = /* @__PURE__ */ new Map();
991
+ for (const t of PLAN_TEMPLATES) {
992
+ byId.set(t.id, { ...t, source: "builtin" });
993
+ }
994
+ for (const t of loadTemplatesFromDir(import_node_path.default.join(import_node_os.default.homedir(), ".codetrellis", "templates"), "user")) {
995
+ byId.set(t.id, t);
996
+ }
997
+ if (projectRoot) {
998
+ for (const t of loadTemplatesFromDir(import_node_path.default.join(projectRoot, ".codetrellis", "templates"), "project")) {
999
+ byId.set(t.id, t);
1000
+ }
1001
+ }
1002
+ return [...byId.values()];
1003
+ }
1004
+ function loadTemplatesFromDir(dir, source) {
1005
+ if (!import_node_fs.default.existsSync(dir)) return [];
1006
+ const out = [];
1007
+ for (const entry of safeReaddir(dir)) {
1008
+ const tplDir = import_node_path.default.join(dir, entry);
1009
+ let stat;
1010
+ try {
1011
+ stat = import_node_fs.default.statSync(tplDir);
1012
+ } catch {
1013
+ continue;
1014
+ }
1015
+ if (!stat.isDirectory()) continue;
1016
+ const yamlPath = import_node_path.default.join(tplDir, "template.yaml");
1017
+ if (!import_node_fs.default.existsSync(yamlPath)) continue;
1018
+ try {
1019
+ const tpl = readTemplate(tplDir, source);
1020
+ if (tpl) out.push(tpl);
1021
+ } catch (err) {
1022
+ console.warn(`[Templates] Failed to load ${tplDir}:`, err instanceof Error ? err.message : err);
1023
+ }
1024
+ }
1025
+ return out;
1026
+ }
1027
+ function readTemplate(tplDir, source) {
1028
+ const yamlPath = import_node_path.default.join(tplDir, "template.yaml");
1029
+ const raw = (0, import_yaml.parse)(import_node_fs.default.readFileSync(yamlPath, "utf-8"));
1030
+ if (!raw || typeof raw !== "object") return null;
1031
+ if (!raw.id || !raw.label) return null;
1032
+ const docs = [];
1033
+ for (const d of raw.docs ?? []) {
1034
+ if (!d) continue;
1035
+ let body = typeof d.body === "string" ? d.body : "";
1036
+ if (!body && typeof d.bodyPath === "string") {
1037
+ try {
1038
+ body = (0, import_confined_fs.readTextWithin)(tplDir, d.bodyPath, "template doc bodyPath");
1039
+ } catch {
1040
+ body = "";
1041
+ }
1042
+ }
1043
+ docs.push({
1044
+ docType: String(d.docType ?? "custom"),
1045
+ title: String(d.title ?? ""),
1046
+ body,
1047
+ orderHint: typeof d.orderHint === "string" ? d.orderHint : void 0,
1048
+ parentKey: typeof d.parentKey === "string" ? d.parentKey : void 0,
1049
+ key: typeof d.key === "string" ? d.key : void 0
1050
+ });
1051
+ }
1052
+ const phases = (raw.phases ?? []).map((p) => ({
1053
+ phaseNumber: Number(p.phaseNumber ?? 1),
1054
+ title: String(p.title ?? ""),
1055
+ scope: typeof p.scope === "string" ? p.scope : void 0,
1056
+ prerequisites: typeof p.prerequisites === "string" ? p.prerequisites : void 0,
1057
+ acceptanceCriteria: typeof p.acceptanceCriteria === "string" ? p.acceptanceCriteria : void 0,
1058
+ status: p.status,
1059
+ tasks: Array.isArray(p.tasks) ? p.tasks : void 0
1060
+ }));
1061
+ const placeholders = (raw.placeholders ?? []).filter((p) => p && typeof p.key === "string").map((p) => ({
1062
+ key: String(p.key),
1063
+ label: typeof p.label === "string" ? p.label : void 0,
1064
+ default: typeof p.default === "string" ? p.default : void 0
1065
+ }));
1066
+ const result = {
1067
+ id: String(raw.id),
1068
+ label: String(raw.label),
1069
+ shortDescription: String(raw.shortDescription ?? ""),
1070
+ longDescription: String(raw.longDescription ?? ""),
1071
+ defaultTitle: String(raw.defaultTitle ?? raw.label),
1072
+ defaultPlanDescription: String(raw.defaultPlanDescription ?? ""),
1073
+ phases,
1074
+ docs,
1075
+ placeholders: placeholders.length ? placeholders : void 0,
1076
+ source
1077
+ };
1078
+ if (Array.isArray(raw.items) && raw.items.length > 0) {
1079
+ result.items = resolveItemBodyPaths(raw.items, tplDir);
1080
+ }
1081
+ return result;
1082
+ }
1083
+ function resolveItemBodyPaths(items, tplDir) {
1084
+ return items.map((item) => {
1085
+ const resolved = { ...item };
1086
+ if (!resolved.body && typeof resolved.bodyPath === "string") {
1087
+ try {
1088
+ resolved.body = (0, import_confined_fs.readTextWithin)(tplDir, resolved.bodyPath, "template item bodyPath");
1089
+ } catch {
1090
+ resolved.body = "";
1091
+ }
1092
+ }
1093
+ if (Array.isArray(resolved.children)) {
1094
+ resolved.children = resolveItemBodyPaths(resolved.children, tplDir);
1095
+ }
1096
+ return resolved;
1097
+ });
1098
+ }
1099
+ function safeReaddir(dir) {
1100
+ try {
1101
+ return import_node_fs.default.readdirSync(dir);
1102
+ } catch {
1103
+ return [];
1104
+ }
1105
+ }
1106
+ function substitutePlaceholders(template, values) {
1107
+ const sub = (s) => {
1108
+ if (typeof s !== "string") return s;
1109
+ return s.replace(/\{\{(\w+)\}\}/g, (_, k) => values[k] ?? `{{${k}}}`);
1110
+ };
1111
+ return {
1112
+ ...template,
1113
+ label: sub(template.label) ?? template.label,
1114
+ defaultTitle: sub(template.defaultTitle) ?? template.defaultTitle,
1115
+ defaultPlanDescription: sub(template.defaultPlanDescription) ?? template.defaultPlanDescription,
1116
+ phases: template.phases.map((p) => ({
1117
+ ...p,
1118
+ title: sub(p.title) ?? p.title,
1119
+ scope: sub(p.scope),
1120
+ prerequisites: sub(p.prerequisites),
1121
+ acceptanceCriteria: sub(p.acceptanceCriteria),
1122
+ tasks: p.tasks?.map((t) => ({
1123
+ ...t,
1124
+ description: sub(t.description) ?? t.description,
1125
+ affectedFiles: t.affectedFiles?.map((f) => sub(f) ?? f)
1126
+ }))
1127
+ })),
1128
+ docs: template.docs.map((d) => ({
1129
+ ...d,
1130
+ title: sub(d.title) ?? d.title,
1131
+ body: sub(d.body) ?? d.body
1132
+ })),
1133
+ // V2 items — substitute placeholders recursively
1134
+ ...template.items ? { items: substituteItemPlaceholders(template.items, sub) } : {}
1135
+ };
1136
+ }
1137
+ function substituteItemPlaceholders(items, sub) {
1138
+ return items.map((item) => {
1139
+ const result = { ...item };
1140
+ if (typeof result.title === "string") result.title = sub(result.title) ?? result.title;
1141
+ if (typeof result.body === "string") result.body = sub(result.body) ?? result.body;
1142
+ if (typeof result.scopePath === "string") result.scopePath = sub(result.scopePath) ?? result.scopePath;
1143
+ if (Array.isArray(result.criteria)) {
1144
+ result.criteria = result.criteria.map((c) => {
1145
+ if (typeof c === "string") return sub(c) ?? c;
1146
+ if (c && typeof c === "object" && typeof c.text === "string") {
1147
+ return { ...c, text: sub(c.text) };
1148
+ }
1149
+ return c;
1150
+ });
1151
+ }
1152
+ if (Array.isArray(result.children)) {
1153
+ result.children = substituteItemPlaceholders(result.children, sub);
1154
+ }
1155
+ return result;
1156
+ });
1157
+ }
1158
+ // Annotate the CommonJS export names for ESM import in node:
1159
+ 0 && (module.exports = {
1160
+ PLAN_TEMPLATES,
1161
+ getTemplate,
1162
+ listTemplates,
1163
+ substitutePlaceholders
1164
+ });