@treeseed/sdk 0.10.28 → 0.12.4

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 (509) hide show
  1. package/README.md +213 -7
  2. package/dist/agent-capacity.d.ts +916 -0
  3. package/dist/agent-capacity.js +1600 -0
  4. package/dist/agent-tools.d.ts +37 -0
  5. package/dist/agent-tools.js +301 -0
  6. package/dist/api/app.d.ts +1 -1
  7. package/dist/api/auth/d1-database.d.ts +2 -2
  8. package/dist/api/auth/d1-provider.d.ts +4 -4
  9. package/dist/api/auth/d1-store.d.ts +2 -2
  10. package/dist/api/auth/memory-provider.d.ts +1 -1
  11. package/dist/api/auth/tokens.d.ts +1 -1
  12. package/dist/api/config.d.ts +3 -1
  13. package/dist/api/config.js +34 -10
  14. package/dist/api/http.d.ts +2 -2
  15. package/dist/api/index.d.ts +10 -10
  16. package/dist/api/index.js +4 -2
  17. package/dist/api/operations-routes.d.ts +3 -3
  18. package/dist/api/operations.d.ts +1 -1
  19. package/dist/api/providers.d.ts +1 -1
  20. package/dist/api/providers.js +21 -4
  21. package/dist/api/railway.d.ts +3 -2
  22. package/dist/api/sdk-dispatch.d.ts +4 -4
  23. package/dist/api/sdk-routes.d.ts +2 -2
  24. package/dist/api/templates.d.ts +2 -2
  25. package/dist/api/types.d.ts +3 -2
  26. package/dist/capacity-provider.d.ts +118 -59
  27. package/dist/capacity-provider.js +235 -43
  28. package/dist/capacity.d.ts +2 -2
  29. package/dist/cli-tools.d.ts +1 -1
  30. package/dist/content-operations.d.ts +97 -0
  31. package/dist/content-operations.js +250 -0
  32. package/dist/content-store.d.ts +4 -4
  33. package/dist/control-plane-client.d.ts +13 -18
  34. package/dist/control-plane-client.js +8 -86
  35. package/dist/control-plane.d.ts +3 -2
  36. package/dist/control-plane.js +38 -13
  37. package/dist/copilot.d.ts +3 -0
  38. package/dist/copilot.js +16 -1
  39. package/dist/d1-http.d.ts +1 -1
  40. package/dist/d1-store.d.ts +32 -57
  41. package/dist/d1-store.js +115 -318
  42. package/dist/db/d1.d.ts +1 -232
  43. package/dist/db/index.d.ts +3 -3
  44. package/dist/db/market-schema.d.ts +50900 -11018
  45. package/dist/db/market-schema.js +2313 -467
  46. package/dist/db/node-sqlite.d.ts +1 -232
  47. package/dist/db/node-sqlite.js +7 -2
  48. package/dist/db/schema.d.ts +0 -462
  49. package/dist/db/schema.js +2 -22
  50. package/dist/dispatch.d.ts +1 -1
  51. package/dist/dispatch.js +0 -11
  52. package/dist/fixture-support.js +52 -4
  53. package/dist/governance.d.ts +133 -0
  54. package/dist/governance.js +285 -0
  55. package/dist/graph/build.d.ts +2 -2
  56. package/dist/graph/context-query-contracts.d.ts +1 -1
  57. package/dist/graph/dsl.d.ts +1 -1
  58. package/dist/graph/query.d.ts +4 -4
  59. package/dist/graph/ranking.d.ts +1 -1
  60. package/dist/graph/schema.d.ts +1 -1
  61. package/dist/graph.d.ts +11 -11
  62. package/dist/guarantees/index.d.ts +425 -0
  63. package/dist/guarantees/index.js +1146 -0
  64. package/dist/hosting/apps.d.ts +12 -0
  65. package/dist/hosting/apps.js +107 -0
  66. package/dist/hosting/builtins.d.ts +25 -0
  67. package/dist/hosting/builtins.js +602 -0
  68. package/dist/hosting/contracts.d.ts +208 -0
  69. package/dist/hosting/contracts.js +0 -0
  70. package/dist/hosting/graph.d.ts +195 -0
  71. package/dist/hosting/graph.js +1092 -0
  72. package/dist/hosting/index.d.ts +4 -0
  73. package/dist/hosting/index.js +4 -0
  74. package/dist/index.d.ts +88 -67
  75. package/dist/index.js +142 -14
  76. package/dist/local-dev/managed-dev.d.ts +85 -0
  77. package/dist/local-dev/managed-dev.js +368 -0
  78. package/dist/managed-dependencies.d.ts +9 -0
  79. package/dist/managed-dependencies.js +10 -9
  80. package/dist/market-client.d.ts +327 -9
  81. package/dist/market-client.js +464 -20
  82. package/dist/model-registry.d.ts +1 -1
  83. package/dist/model-registry.js +19 -19
  84. package/dist/operations/agent-tools.d.ts +2 -11
  85. package/dist/operations/agent-tools.js +2 -14
  86. package/dist/operations/providers/default.d.ts +1 -1
  87. package/dist/operations/providers/default.js +20 -37
  88. package/dist/operations/repository-operations.d.ts +26 -2
  89. package/dist/operations/repository-operations.js +159 -1
  90. package/dist/operations/runtime.d.ts +3 -3
  91. package/dist/operations/services/bootstrap-runner.d.ts +4 -2
  92. package/dist/operations/services/bootstrap-runner.js +22 -2
  93. package/dist/operations/services/build-warning-policy.d.ts +34 -0
  94. package/dist/operations/services/build-warning-policy.js +81 -82
  95. package/dist/operations/services/commit-message-provider.js +4 -4
  96. package/dist/operations/services/config-runtime.d.ts +83 -24
  97. package/dist/operations/services/config-runtime.js +449 -130
  98. package/dist/operations/services/deploy.d.ts +106 -624
  99. package/dist/operations/services/deploy.js +746 -263
  100. package/dist/operations/services/deployment-readiness.d.ts +30 -0
  101. package/dist/operations/services/deployment-readiness.js +206 -0
  102. package/dist/operations/services/git-remote-policy.js +12 -4
  103. package/dist/operations/services/git-runner.d.ts +66 -0
  104. package/dist/operations/services/git-runner.js +479 -0
  105. package/dist/operations/services/git-workflow.d.ts +45 -6
  106. package/dist/operations/services/git-workflow.js +251 -23
  107. package/dist/operations/services/github-actions-verification.d.ts +4 -1
  108. package/dist/operations/services/github-actions-verification.js +12 -3
  109. package/dist/operations/services/github-api.js +22 -6
  110. package/dist/operations/services/github-automation.d.ts +4 -4
  111. package/dist/operations/services/github-automation.js +19 -21
  112. package/dist/operations/services/github-credentials.d.ts +13 -0
  113. package/dist/operations/services/github-credentials.js +59 -0
  114. package/dist/operations/services/hosted-service-checks.d.ts +81 -0
  115. package/dist/operations/services/hosted-service-checks.js +478 -0
  116. package/dist/operations/services/hosting-audit.d.ts +2 -2
  117. package/dist/operations/services/hosting-audit.js +7 -7
  118. package/dist/operations/services/hub-launch.d.ts +1 -1
  119. package/dist/operations/services/hub-provider-launch.d.ts +5 -5
  120. package/dist/operations/services/hub-provider-launch.js +22 -17
  121. package/dist/operations/services/live-hosted-service-checks.d.ts +26 -0
  122. package/dist/operations/services/live-hosted-service-checks.js +463 -0
  123. package/dist/operations/services/local-dev.js +0 -1
  124. package/dist/operations/services/managed-host-security.d.ts +1 -1
  125. package/dist/operations/services/managed-host-security.js +1 -1
  126. package/dist/operations/services/managed-repositories.d.ts +37 -0
  127. package/dist/operations/services/managed-repositories.js +177 -0
  128. package/dist/operations/services/operations-runner-smoke.d.ts +31 -0
  129. package/dist/operations/services/operations-runner-smoke.js +198 -0
  130. package/dist/operations/services/package-adapters.d.ts +170 -0
  131. package/dist/operations/services/package-adapters.js +859 -0
  132. package/dist/operations/services/package-reference-policy.d.ts +13 -88
  133. package/dist/operations/services/package-reference-policy.js +96 -215
  134. package/dist/operations/services/project-host-operations.d.ts +4 -4
  135. package/dist/operations/services/project-platform.d.ts +57 -173
  136. package/dist/operations/services/project-platform.js +80 -111
  137. package/dist/operations/services/project-web-monitor.d.ts +2 -2
  138. package/dist/operations/services/project-web-monitor.js +122 -5
  139. package/dist/operations/services/railway-api.d.ts +117 -5
  140. package/dist/operations/services/railway-api.js +915 -93
  141. package/dist/operations/services/railway-deploy.d.ts +30 -112
  142. package/dist/operations/services/railway-deploy.js +521 -961
  143. package/dist/operations/services/release-history.js +3 -4
  144. package/dist/operations/services/release-proof-ledger.d.ts +13 -0
  145. package/dist/operations/services/release-proof-ledger.js +81 -0
  146. package/dist/operations/services/release-proof-planner.d.ts +48 -0
  147. package/dist/operations/services/release-proof-planner.js +195 -0
  148. package/dist/operations/services/release-proof-runner.d.ts +16 -0
  149. package/dist/operations/services/release-proof-runner.js +169 -0
  150. package/dist/operations/services/release-proof.d.ts +81 -0
  151. package/dist/operations/services/release-proof.js +79 -0
  152. package/dist/operations/services/repository-save-orchestrator.d.ts +8 -7
  153. package/dist/operations/services/repository-save-orchestrator.js +604 -212
  154. package/dist/operations/services/runtime-paths.d.ts +1 -3
  155. package/dist/operations/services/runtime-paths.js +0 -4
  156. package/dist/operations/services/runtime-tools.d.ts +1 -191
  157. package/dist/operations/services/runtime-tools.js +4 -443
  158. package/dist/operations/services/save-deploy-preflight.js +9 -1
  159. package/dist/operations/services/template-host-bindings.d.ts +2 -2
  160. package/dist/operations/services/template-host-bindings.js +3 -2
  161. package/dist/operations/services/template-registry.d.ts +6 -6
  162. package/dist/operations/services/template-registry.js +33 -14
  163. package/dist/operations/services/template-secret-sync.d.ts +3 -3
  164. package/dist/operations/services/verification-cache.d.ts +25 -0
  165. package/dist/operations/services/verification-cache.js +71 -0
  166. package/dist/operations/services/workflow-timing.d.ts +25 -0
  167. package/dist/operations/services/workflow-timing.js +79 -0
  168. package/dist/operations/services/workspace-dependency-mode.js +50 -5
  169. package/dist/operations/services/workspace-preflight.js +8 -8
  170. package/dist/operations/services/workspace-save-script.d.ts +4 -4
  171. package/dist/operations/services/workspace-save.d.ts +1 -0
  172. package/dist/operations/services/workspace-save.js +42 -19
  173. package/dist/operations/services/workspace-tools.js +42 -7
  174. package/dist/operations-registry.d.ts +1 -1
  175. package/dist/operations-registry.js +5 -6
  176. package/dist/operations-types.d.ts +1 -1
  177. package/dist/operations.d.ts +17 -11
  178. package/dist/operations.js +57 -3
  179. package/dist/platform/book-export.js +2 -0
  180. package/dist/platform/books-data.d.ts +1 -1
  181. package/dist/platform/config.d.ts +27 -0
  182. package/dist/platform/config.js +100 -0
  183. package/dist/platform/content-runtime-source.d.ts +54 -0
  184. package/dist/platform/content-runtime-source.js +169 -0
  185. package/dist/platform/contracts.d.ts +38 -2
  186. package/dist/platform/deploy-config.d.ts +1 -1
  187. package/dist/platform/deploy-config.js +80 -9
  188. package/dist/platform/deploy-runtime.d.ts +1 -1
  189. package/dist/platform/desired-state.d.ts +63 -0
  190. package/dist/platform/desired-state.js +1021 -0
  191. package/dist/platform/env.yaml +568 -45
  192. package/dist/platform/environment.d.ts +3 -2
  193. package/dist/platform/environment.js +122 -21
  194. package/dist/platform/local-content-materialization.d.ts +9 -0
  195. package/dist/platform/local-content-materialization.js +212 -0
  196. package/dist/platform/plugin.d.ts +13 -4
  197. package/dist/platform/plugins/runtime.d.ts +3 -3
  198. package/dist/platform/plugins/runtime.js +62 -1
  199. package/dist/platform/plugins.d.ts +6 -6
  200. package/dist/platform/published-content-pipeline.d.ts +3 -3
  201. package/dist/platform/published-content-pipeline.js +5 -1
  202. package/dist/platform/published-content.d.ts +4 -3
  203. package/dist/platform/site-config-schema.d.ts +1 -0
  204. package/dist/platform/site-config-schema.js +4 -1
  205. package/dist/platform/tenant/runtime-config.d.ts +152 -2
  206. package/dist/platform/tenant-config.d.ts +1 -1
  207. package/dist/platform/utils/site-config-schema.d.ts +154 -0
  208. package/dist/platform/utils/site-config-schema.js +400 -461
  209. package/dist/platform-operation-store.d.ts +1 -1
  210. package/dist/platform-operation-store.js +2 -2
  211. package/dist/platform-operations.js +1 -1
  212. package/dist/plugin-default.d.ts +1 -1
  213. package/dist/plugin-default.js +27 -12
  214. package/dist/project-import.d.ts +91 -0
  215. package/dist/project-import.js +257 -0
  216. package/dist/project-workflow.d.ts +1 -1
  217. package/dist/reconcile/bootstrap-systems.d.ts +2 -2
  218. package/dist/reconcile/bootstrap-systems.js +5 -5
  219. package/dist/reconcile/builtin-adapters.d.ts +7 -1
  220. package/dist/reconcile/builtin-adapters.js +3190 -429
  221. package/dist/reconcile/contracts.d.ts +23 -6
  222. package/dist/reconcile/desired-state.d.ts +2 -192
  223. package/dist/reconcile/desired-state.js +29 -38
  224. package/dist/reconcile/engine.d.ts +61 -395
  225. package/dist/reconcile/engine.js +229 -44
  226. package/dist/reconcile/index.d.ts +10 -8
  227. package/dist/reconcile/index.js +2 -0
  228. package/dist/reconcile/live-acceptance.d.ts +100 -0
  229. package/dist/reconcile/live-acceptance.js +2027 -0
  230. package/dist/reconcile/platform.d.ts +104 -0
  231. package/dist/reconcile/platform.js +100 -0
  232. package/dist/reconcile/providers/docker-private.d.ts +54 -0
  233. package/dist/reconcile/providers/docker-private.js +101 -0
  234. package/dist/reconcile/providers/github-private.d.ts +65 -0
  235. package/dist/reconcile/providers/github-private.js +119 -0
  236. package/dist/reconcile/providers/local-private.d.ts +28 -0
  237. package/dist/reconcile/providers/local-private.js +75 -0
  238. package/dist/reconcile/providers/railway-iac.d.ts +66 -0
  239. package/dist/reconcile/providers/railway-iac.js +275 -0
  240. package/dist/reconcile/providers/release-private.d.ts +92 -0
  241. package/dist/reconcile/providers/release-private.js +152 -0
  242. package/dist/reconcile/registry.d.ts +2 -2
  243. package/dist/reconcile/registry.js +16 -1
  244. package/dist/reconcile/state.d.ts +1 -1
  245. package/dist/reconcile/state.js +7 -44
  246. package/dist/reconcile/units.d.ts +1 -1
  247. package/dist/reconcile/units.js +9 -3
  248. package/dist/remote.d.ts +6 -6
  249. package/dist/scenes/artifacts.d.ts +16 -0
  250. package/dist/scenes/artifacts.js +61 -0
  251. package/dist/scenes/auth.d.ts +2 -0
  252. package/dist/scenes/auth.js +28 -0
  253. package/dist/scenes/base-url.d.ts +12 -0
  254. package/dist/scenes/base-url.js +123 -0
  255. package/dist/scenes/builtin-plugins.d.ts +2 -0
  256. package/dist/scenes/builtin-plugins.js +447 -0
  257. package/dist/scenes/checkpoints.d.ts +14 -0
  258. package/dist/scenes/checkpoints.js +33 -0
  259. package/dist/scenes/device-matrix.d.ts +2 -0
  260. package/dist/scenes/device-matrix.js +97 -0
  261. package/dist/scenes/devices.d.ts +11 -0
  262. package/dist/scenes/devices.js +22 -0
  263. package/dist/scenes/diagnostics.d.ts +5 -0
  264. package/dist/scenes/diagnostics.js +22 -0
  265. package/dist/scenes/diagram-providers.d.ts +2 -0
  266. package/dist/scenes/diagram-providers.js +181 -0
  267. package/dist/scenes/diagram-validation.d.ts +22 -0
  268. package/dist/scenes/diagram-validation.js +74 -0
  269. package/dist/scenes/environment.d.ts +2 -0
  270. package/dist/scenes/environment.js +65 -0
  271. package/dist/scenes/evidence-bundle.d.ts +5 -0
  272. package/dist/scenes/evidence-bundle.js +42 -0
  273. package/dist/scenes/evidence-report.d.ts +10 -0
  274. package/dist/scenes/evidence-report.js +73 -0
  275. package/dist/scenes/evidence.d.ts +16 -0
  276. package/dist/scenes/evidence.js +277 -0
  277. package/dist/scenes/index.d.ts +48 -0
  278. package/dist/scenes/index.js +312 -0
  279. package/dist/scenes/inspect.d.ts +9 -0
  280. package/dist/scenes/inspect.js +64 -0
  281. package/dist/scenes/loader.d.ts +3 -0
  282. package/dist/scenes/loader.js +38 -0
  283. package/dist/scenes/logs.d.ts +2 -0
  284. package/dist/scenes/logs.js +47 -0
  285. package/dist/scenes/operations.d.ts +3 -0
  286. package/dist/scenes/operations.js +128 -0
  287. package/dist/scenes/phase0.d.ts +9 -0
  288. package/dist/scenes/phase0.js +637 -0
  289. package/dist/scenes/planner.d.ts +12 -0
  290. package/dist/scenes/planner.js +166 -0
  291. package/dist/scenes/playwright-adapter.d.ts +2 -0
  292. package/dist/scenes/playwright-adapter.js +63 -0
  293. package/dist/scenes/plugins.d.ts +5 -0
  294. package/dist/scenes/plugins.js +115 -0
  295. package/dist/scenes/progress.d.ts +17 -0
  296. package/dist/scenes/progress.js +24 -0
  297. package/dist/scenes/publish-destinations.d.ts +12 -0
  298. package/dist/scenes/publish-destinations.js +99 -0
  299. package/dist/scenes/publish-plan-report.d.ts +10 -0
  300. package/dist/scenes/publish-plan-report.js +70 -0
  301. package/dist/scenes/publish-plan.d.ts +15 -0
  302. package/dist/scenes/publish-plan.js +248 -0
  303. package/dist/scenes/publish-redaction.d.ts +16 -0
  304. package/dist/scenes/publish-redaction.js +148 -0
  305. package/dist/scenes/publish-release-record.d.ts +13 -0
  306. package/dist/scenes/publish-release-record.js +34 -0
  307. package/dist/scenes/publish-report.d.ts +10 -0
  308. package/dist/scenes/publish-report.js +67 -0
  309. package/dist/scenes/publish.d.ts +16 -0
  310. package/dist/scenes/publish.js +298 -0
  311. package/dist/scenes/registry.d.ts +12 -0
  312. package/dist/scenes/registry.js +65 -0
  313. package/dist/scenes/remotion-adapter.d.ts +3 -0
  314. package/dist/scenes/remotion-adapter.js +94 -0
  315. package/dist/scenes/remotion-composition-registry.d.ts +2 -0
  316. package/dist/scenes/remotion-composition-registry.js +12 -0
  317. package/dist/scenes/remotion-compositions.d.ts +15 -0
  318. package/dist/scenes/remotion-compositions.js +464 -0
  319. package/dist/scenes/remotion-diagrams.d.ts +9 -0
  320. package/dist/scenes/remotion-diagrams.js +188 -0
  321. package/dist/scenes/remotion-input.d.ts +13 -0
  322. package/dist/scenes/remotion-input.js +291 -0
  323. package/dist/scenes/remotion-visuals.d.ts +29 -0
  324. package/dist/scenes/remotion-visuals.js +198 -0
  325. package/dist/scenes/render-media-assets.d.ts +9 -0
  326. package/dist/scenes/render-media-assets.js +117 -0
  327. package/dist/scenes/render-report.d.ts +10 -0
  328. package/dist/scenes/render-report.js +27 -0
  329. package/dist/scenes/render.d.ts +2 -0
  330. package/dist/scenes/render.js +218 -0
  331. package/dist/scenes/reporter.d.ts +3 -0
  332. package/dist/scenes/reporter.js +101 -0
  333. package/dist/scenes/resume.d.ts +2 -0
  334. package/dist/scenes/resume.js +79 -0
  335. package/dist/scenes/runner.d.ts +2 -0
  336. package/dist/scenes/runner.js +674 -0
  337. package/dist/scenes/schema.d.ts +6 -0
  338. package/dist/scenes/schema.js +994 -0
  339. package/dist/scenes/seed.d.ts +2 -0
  340. package/dist/scenes/seed.js +83 -0
  341. package/dist/scenes/segments.d.ts +15 -0
  342. package/dist/scenes/segments.js +79 -0
  343. package/dist/scenes/selectors.d.ts +3 -0
  344. package/dist/scenes/selectors.js +21 -0
  345. package/dist/scenes/timeline.d.ts +11 -0
  346. package/dist/scenes/timeline.js +26 -0
  347. package/dist/scenes/timeouts.d.ts +6 -0
  348. package/dist/scenes/timeouts.js +17 -0
  349. package/dist/scenes/training-captions.d.ts +14 -0
  350. package/dist/scenes/training-captions.js +98 -0
  351. package/dist/scenes/training-report.d.ts +10 -0
  352. package/dist/scenes/training-report.js +78 -0
  353. package/dist/scenes/training-transcript.d.ts +24 -0
  354. package/dist/scenes/training-transcript.js +204 -0
  355. package/dist/scenes/training.d.ts +10 -0
  356. package/dist/scenes/training.js +134 -0
  357. package/dist/scenes/types.d.ts +1872 -0
  358. package/dist/scenes/types.js +8 -0
  359. package/dist/scenes/visual-audit-contact-sheets.d.ts +6 -0
  360. package/dist/scenes/visual-audit-contact-sheets.js +119 -0
  361. package/dist/scenes/visual-audit-fixtures.d.ts +25 -0
  362. package/dist/scenes/visual-audit-fixtures.js +210 -0
  363. package/dist/scenes/visual-audit-report.d.ts +11 -0
  364. package/dist/scenes/visual-audit-report.js +85 -0
  365. package/dist/scenes/visual-audit-review.d.ts +23 -0
  366. package/dist/scenes/visual-audit-review.js +829 -0
  367. package/dist/scenes/visual-audit-routes.d.ts +13 -0
  368. package/dist/scenes/visual-audit-routes.js +308 -0
  369. package/dist/scenes/visual-audit.d.ts +3 -0
  370. package/dist/scenes/visual-audit.js +596 -0
  371. package/dist/scripts/build-dist.js +154 -40
  372. package/dist/scripts/check-build-warnings.js +42 -53
  373. package/dist/scripts/cleanup-markdown.js +1 -1
  374. package/dist/scripts/cli-test-fixtures.js +24 -28
  375. package/dist/scripts/deployment-readiness.js +20 -0
  376. package/dist/scripts/generate-treedx-openapi-types.js +186 -0
  377. package/dist/scripts/migrate-journey-csv-to-guarantees.js +140 -0
  378. package/dist/scripts/operations-runner-smoke.js +16 -0
  379. package/dist/scripts/package-tools.js +12 -1
  380. package/dist/scripts/prepare.js +3 -7
  381. package/dist/scripts/release-verify.js +6 -6
  382. package/dist/scripts/run-fixture-astro-command.js +1 -1
  383. package/dist/scripts/template-catalog.test.js +68 -82
  384. package/dist/scripts/tenant-dev.js +0 -10
  385. package/dist/scripts/tenant-workflow-action.js +10 -1
  386. package/dist/scripts/test-cloudflare-local.js +1 -1
  387. package/dist/scripts/test-scaffold.js +0 -1
  388. package/dist/scripts/test-smoke.js +3 -3
  389. package/dist/scripts/treeseed-build-dist.js +4 -7
  390. package/dist/scripts/treeseed-release-verify.js +1 -1
  391. package/dist/scripts/verify-driver.js +30 -21
  392. package/dist/scripts/workflow-commands.test.js +18 -27
  393. package/dist/scripts/workspace-command-e2e.js +1 -1
  394. package/dist/scripts/workspace-lint.js +6 -0
  395. package/dist/scripts/workspace-release-test.js +90 -1
  396. package/dist/scripts/workspace-test.js +6 -0
  397. package/dist/sdk-dispatch.d.ts +1 -1
  398. package/dist/sdk-dispatch.js +0 -16
  399. package/dist/sdk-fields.d.ts +1 -1
  400. package/dist/sdk-filters.d.ts +1 -1
  401. package/dist/sdk-types.d.ts +1352 -116
  402. package/dist/sdk-types.js +413 -2
  403. package/dist/sdk.d.ts +106 -100
  404. package/dist/sdk.js +211 -51
  405. package/dist/secrets-capability.d.ts +421 -0
  406. package/dist/secrets-capability.js +530 -0
  407. package/dist/seeds/normalize.js +1 -0
  408. package/dist/seeds/planner.js +38 -0
  409. package/dist/seeds/schema.js +293 -4
  410. package/dist/seeds/types.d.ts +60 -0
  411. package/dist/seeds/types.js +9 -1
  412. package/dist/service-credentials.d.ts +54 -0
  413. package/dist/service-credentials.js +112 -0
  414. package/dist/stores/cursor-store.d.ts +2 -2
  415. package/dist/stores/envelopes.d.ts +1 -1
  416. package/dist/stores/helpers.d.ts +1 -1
  417. package/dist/stores/lease-store.d.ts +2 -2
  418. package/dist/stores/message-store.d.ts +2 -2
  419. package/dist/stores/operational-store.d.ts +3 -26
  420. package/dist/stores/operational-store.js +0 -225
  421. package/dist/stores/project-workflow-store.d.ts +2 -2
  422. package/dist/stores/run-store.d.ts +2 -3
  423. package/dist/stores/run-store.js +0 -98
  424. package/dist/stores/subscription-store.d.ts +2 -3
  425. package/dist/stores/subscription-store.js +0 -100
  426. package/dist/template-catalog.d.ts +1 -1
  427. package/dist/template-launch-requirements.d.ts +2 -2
  428. package/dist/template-launch-requirements.js +9 -0
  429. package/dist/template-launch-ui.d.ts +2 -2
  430. package/dist/treedx/adapters.d.ts +6 -0
  431. package/dist/treedx/adapters.js +36 -0
  432. package/dist/treedx/client.d.ts +222 -0
  433. package/dist/treedx/client.js +871 -0
  434. package/dist/treedx/errors.d.ts +13 -0
  435. package/dist/treedx/errors.js +17 -0
  436. package/dist/treedx/federated-client.d.ts +27 -0
  437. package/dist/treedx/federated-client.js +158 -0
  438. package/dist/treedx/generated/openapi-types.d.ts +3558 -0
  439. package/dist/treedx/generated/openapi-types.js +0 -0
  440. package/dist/treedx/graph-adapter.d.ts +33 -0
  441. package/dist/treedx/graph-adapter.js +156 -0
  442. package/dist/treedx/index.d.ts +14 -0
  443. package/dist/treedx/index.js +48 -0
  444. package/dist/treedx/market-integration.d.ts +27 -0
  445. package/dist/treedx/market-integration.js +131 -0
  446. package/dist/treedx/ports.d.ts +166 -0
  447. package/dist/treedx/ports.js +231 -0
  448. package/dist/treedx/query-adapter.d.ts +19 -0
  449. package/dist/treedx/query-adapter.js +62 -0
  450. package/dist/treedx/registry-client.d.ts +11 -0
  451. package/dist/treedx/registry-client.js +19 -0
  452. package/dist/treedx/repository-adapter.d.ts +45 -0
  453. package/dist/treedx/repository-adapter.js +319 -0
  454. package/dist/treedx/sdk-integration.d.ts +27 -0
  455. package/dist/treedx/sdk-integration.js +63 -0
  456. package/dist/treedx/types.d.ts +1084 -0
  457. package/dist/treedx/types.js +8 -0
  458. package/dist/treedx/workspace-adapter.d.ts +27 -0
  459. package/dist/treedx/workspace-adapter.js +65 -0
  460. package/dist/treedx-backends.d.ts +220 -0
  461. package/dist/treedx-backends.js +634 -0
  462. package/dist/treedx-client.d.ts +89 -0
  463. package/dist/treedx-client.js +184 -0
  464. package/dist/treeseed/services/compose.yml +2 -3
  465. package/dist/treeseed/template-catalog/catalog.fixture.json +27 -27
  466. package/dist/types/agents.d.ts +256 -0
  467. package/dist/types/agents.js +42 -1
  468. package/dist/verification.d.ts +1 -0
  469. package/dist/verification.js +143 -14
  470. package/dist/workflow/operations.d.ts +580 -523
  471. package/dist/workflow/operations.js +2084 -1279
  472. package/dist/workflow/policy.js +19 -7
  473. package/dist/workflow/runs.d.ts +9 -3
  474. package/dist/workflow/runs.js +66 -26
  475. package/dist/workflow/session.d.ts +4 -1
  476. package/dist/workflow/session.js +50 -10
  477. package/dist/workflow/worktrees.d.ts +6 -2
  478. package/dist/workflow/worktrees.js +98 -15
  479. package/dist/workflow-state.d.ts +17 -4
  480. package/dist/workflow-state.js +68 -41
  481. package/dist/workflow-support.d.ts +26 -17
  482. package/dist/workflow-support.js +84 -24
  483. package/dist/workflow.d.ts +51 -16
  484. package/dist/workflow.js +19 -7
  485. package/drizzle/d1/0000_treeseed_d1.sql +0 -18
  486. package/drizzle/market/0000_market_control_plane.sql +1793 -1499
  487. package/drizzle/market/0004_treedx_market_integration.sql +99 -0
  488. package/drizzle/market/0005_agent_capacity_coordination.sql +145 -0
  489. package/drizzle/market/0006_provider_assignment_lifecycle.sql +9 -0
  490. package/drizzle/market/0007_agent_architecture_gap_closure.sql +157 -0
  491. package/drizzle/market/0008_agent_capacity_operational_closure.sql +27 -0
  492. package/drizzle/market/0009_agent_capacity_runtime_hardening.sql +29 -0
  493. package/drizzle/market/0010_secrets_capability_persistence.sql +130 -0
  494. package/drizzle/market/0011_github_app_adapter.sql +47 -0
  495. package/drizzle/market/0012_workday_test_runs.sql +44 -0
  496. package/drizzle/market/0013_runtime_task_lifecycle.sql +39 -0
  497. package/drizzle/market/0014_governance_pipeline.sql +189 -0
  498. package/package.json +106 -18
  499. package/scripts/{verify-driver.mjs → verify-driver.ts} +19 -4
  500. package/templates/github/deploy-web.workflow.yml +49 -12
  501. package/dist/operations/services/mailpit-runtime.d.ts +0 -20
  502. package/dist/operations/services/mailpit-runtime.js +0 -67
  503. package/dist/operations/services/release-candidate.d.ts +0 -41
  504. package/dist/operations/services/release-candidate.js +0 -616
  505. package/dist/scripts/ensure-mailpit.js +0 -48
  506. package/dist/scripts/logs-mailpit.js +0 -2
  507. package/dist/scripts/run-ts.js +0 -45
  508. package/dist/scripts/stop-mailpit.js +0 -5
  509. package/dist/scripts/treeseed-run-ts.js +0 -45
@@ -0,0 +1,1021 @@
1
+ import { createHash } from "node:crypto";
2
+ import { existsSync, readFileSync, statSync } from "node:fs";
3
+ import { basename, dirname, resolve as resolvePath } from "node:path";
4
+ import { parse as parseYaml } from "yaml";
5
+ import {
6
+ discoverTreeseedPackageAdapters
7
+ } from "../operations/services/package-adapters.js";
8
+ import { resolveCapacityProviderLaunchPlan } from "../capacity-provider.js";
9
+ import { workspaceRoot } from "../operations/services/workspace-tools.js";
10
+ import {
11
+ checkedOutTemplateRepositories
12
+ } from "../operations/services/managed-repositories.js";
13
+ import { deriveTreeseedDesiredUnits } from "../reconcile/desired-state.js";
14
+ import {
15
+ buildProjectLocalContentResources
16
+ } from "./local-content-materialization.js";
17
+ function resolveLocalGitCommonDir(tenantRoot) {
18
+ const dotGitPath = resolvePath(tenantRoot, ".git");
19
+ if (!existsSync(dotGitPath)) return "";
20
+ try {
21
+ if (statSync(dotGitPath).isDirectory()) return dotGitPath;
22
+ const stat = readFileSync(dotGitPath, "utf8");
23
+ const match = /^gitdir:\s*(.+)\s*$/imu.exec(stat);
24
+ if (!match?.[1]) return dotGitPath;
25
+ const gitDir = resolvePath(tenantRoot, match[1].trim());
26
+ const commonDirPath = resolvePath(gitDir, "commondir");
27
+ if (existsSync(commonDirPath)) {
28
+ const commonDir = readFileSync(commonDirPath, "utf8").trim();
29
+ if (commonDir) return resolvePath(gitDir, commonDir);
30
+ }
31
+ const marker = `${resolvePath("/").replace(/\/$/u, "")}.git/worktrees/`;
32
+ const normalized = gitDir.replace(/\\/gu, "/");
33
+ const markerIndex = normalized.indexOf("/.git/worktrees/");
34
+ if (markerIndex >= 0) return normalized.slice(0, markerIndex + "/.git".length);
35
+ if (normalized.includes(marker)) return normalized.slice(0, normalized.indexOf(marker) + "/.git".length);
36
+ return dirname(gitDir);
37
+ } catch {
38
+ return "";
39
+ }
40
+ }
41
+ const INTERNAL_PACKAGE_DEPENDENCY_FIELDS = [
42
+ "dependencies",
43
+ "optionalDependencies",
44
+ "peerDependencies",
45
+ "devDependencies"
46
+ ];
47
+ function hashJson(value) {
48
+ return createHash("sha256").update(JSON.stringify(value)).digest("hex");
49
+ }
50
+ function reconcileIdentityForGraph(workspaceId, environment) {
51
+ return {
52
+ teamId: workspaceId,
53
+ projectId: workspaceId,
54
+ slug: workspaceId,
55
+ environment,
56
+ deploymentKey: `${workspaceId}:${environment}`,
57
+ environmentKey: environment
58
+ };
59
+ }
60
+ function environmentFromTarget(target) {
61
+ if (target.kind === "persistent") return target.scope;
62
+ return "staging";
63
+ }
64
+ function packageReleaseCapability(adapter) {
65
+ if (adapter.artifacts.some((artifact) => artifact.provider === "docker")) return "image";
66
+ if (adapter.artifacts.some((artifact) => artifact.provider === "npm")) return "npm";
67
+ if (adapter.releaseChecks.length > 0) return "deploy-only";
68
+ return "none";
69
+ }
70
+ function packageUnitFromAdapter(adapter) {
71
+ return {
72
+ id: adapter.id,
73
+ name: adapter.name,
74
+ kind: adapter.kind,
75
+ path: adapter.relativeDir,
76
+ version: adapter.version,
77
+ publishTarget: adapter.publishTarget,
78
+ manifestPath: adapter.manifestPath,
79
+ repository: typeof adapter.metadata.repository === "string" ? adapter.metadata.repository : null,
80
+ releaseCapability: packageReleaseCapability(adapter)
81
+ };
82
+ }
83
+ function templateReleaseTag(manifest) {
84
+ return manifest.version ? `${manifest.release.tagPrefix}${manifest.id}/v${manifest.version}` : null;
85
+ }
86
+ function templateUnitFromRepository(repo) {
87
+ const manifest = repo.templateManifest;
88
+ return {
89
+ id: manifest.id,
90
+ name: manifest.name,
91
+ category: manifest.category,
92
+ path: repo.relativeDir,
93
+ version: manifest.version,
94
+ repository: manifest.repository,
95
+ manifestPath: manifest.manifestPath,
96
+ releaseTag: templateReleaseTag(manifest),
97
+ recordPath: manifest.release.recordPath
98
+ };
99
+ }
100
+ function stringRecord(value) {
101
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
102
+ }
103
+ function stringArray(value) {
104
+ return Array.isArray(value) ? value.filter((entry) => typeof entry === "string" && entry.trim().length > 0) : [];
105
+ }
106
+ function workflowName(value, fallback) {
107
+ return (typeof value === "string" && value.trim() ? value.trim() : fallback).replace(/^\.github\/workflows\//u, "");
108
+ }
109
+ function packageShortSha(adapter) {
110
+ const envSha = process.env.GITHUB_SHA;
111
+ if (typeof envSha === "string" && /^[a-f0-9]{7,40}$/iu.test(envSha)) return envSha.slice(0, 12).toLowerCase();
112
+ return createHash("sha256").update(`${adapter.id}:${adapter.dir}:${adapter.version ?? ""}`).digest("hex").slice(0, 12);
113
+ }
114
+ function materializeDockerImageTags(tags, adapter, branch) {
115
+ const shortSha = packageShortSha(adapter);
116
+ const branchSlug = branch.replace(/[^A-Za-z0-9_.-]+/gu, "-").replace(/^-+|-+$/gu, "") || "branch";
117
+ return tags.map((tag) => tag.replace(/<short-sha>/gu, shortSha).replace(/<branch-slug>/gu, branchSlug).replace(/<branch>/gu, branchSlug).replace(/<version>/gu, String(adapter.version ?? "latest").replace(/[^A-Za-z0-9_.-]+/gu, "-")));
118
+ }
119
+ function dockerPlatforms(artifactArchitectures, adapterArchitectures) {
120
+ const architectures = stringArray(artifactArchitectures).length > 0 ? stringArray(artifactArchitectures) : stringArray(adapterArchitectures);
121
+ const normalized = architectures.length > 0 ? architectures : ["amd64", "arm64"];
122
+ return normalized.map((arch) => arch.startsWith("linux/") ? arch : `linux/${arch}`);
123
+ }
124
+ function localDockerPlatform() {
125
+ if (process.arch === "arm64") return "linux/arm64";
126
+ if (process.arch === "arm") return "linux/arm/v7";
127
+ return "linux/amd64";
128
+ }
129
+ function safeTreeDxRepositoryName(value) {
130
+ return value.trim().toLowerCase().replace(/[^a-z0-9_.-]+/gu, "-").replace(/^-+|-+$/gu, "") || "project";
131
+ }
132
+ function localTreeDxContentProjects(tenantRoot) {
133
+ const seedPath = resolvePath(tenantRoot, "seeds", "treeseed.yaml");
134
+ if (!existsSync(seedPath)) return [];
135
+ const parsed = parseYaml(readFileSync(seedPath, "utf8"));
136
+ const resources = stringRecord(parsed?.resources);
137
+ const projects = Array.isArray(resources.projects) ? resources.projects : [];
138
+ return projects.flatMap((entry) => {
139
+ const project = stringRecord(entry);
140
+ const slug = typeof project.slug === "string" && project.slug.trim() ? project.slug.trim() : "";
141
+ const repository = stringRecord(project.repository);
142
+ const architecture = stringRecord(project.architecture);
143
+ const contentPath = typeof architecture.contentPath === "string" && architecture.contentPath.trim() ? architecture.contentPath.trim() : null;
144
+ if (!slug || !contentPath) return [];
145
+ const checkoutPath = typeof repository.checkoutPath === "string" && repository.checkoutPath.trim() ? repository.checkoutPath.trim() : ".";
146
+ return [{
147
+ projectKey: typeof project.key === "string" ? project.key : `project:treeseed/${slug}`,
148
+ slug,
149
+ repositoryName: safeTreeDxRepositoryName(`treeseed-${slug}`),
150
+ repositoryId: safeTreeDxRepositoryName(`treeseed-${slug}`),
151
+ localRoot: checkoutPath === "." ? tenantRoot : resolvePath(tenantRoot, checkoutPath),
152
+ contentPath,
153
+ defaultRef: "refs/heads/main",
154
+ seedPaths: [
155
+ `${contentPath.replace(/\/+$/u, "")}/objectives`,
156
+ `${contentPath.replace(/\/+$/u, "")}/agents`
157
+ ]
158
+ }];
159
+ });
160
+ }
161
+ function releasePhaseForEnvironment(environment) {
162
+ return environment === "prod" ? "release" : "stage";
163
+ }
164
+ function internalPackageDependencies(packages, pkg) {
165
+ const packageIds = new Set(packages.map((entry) => entry.id));
166
+ const packageJsonPath = resolvePath(pkg.path, "package.json");
167
+ if (!existsSync(packageJsonPath)) return [];
168
+ try {
169
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
170
+ const dependencies = /* @__PURE__ */ new Set();
171
+ for (const field of INTERNAL_PACKAGE_DEPENDENCY_FIELDS) {
172
+ const entries = packageJson[field];
173
+ if (!entries || typeof entries !== "object" || Array.isArray(entries)) continue;
174
+ for (const dependencyName of Object.keys(entries)) {
175
+ if (dependencyName !== pkg.id && packageIds.has(dependencyName)) {
176
+ dependencies.add(dependencyName);
177
+ }
178
+ }
179
+ }
180
+ return [...dependencies].sort();
181
+ } catch {
182
+ return [];
183
+ }
184
+ }
185
+ function resourceKindForUnit(unit) {
186
+ if (unit.provider === "railway") {
187
+ if (unit.unitType.startsWith("railway-service:")) return "railway-service";
188
+ if (unit.unitType === "custom-domain:api") return "railway-domain";
189
+ }
190
+ if (unit.provider === "cloudflare" || unit.provider === "cloudflare-dns") return "cloudflare-resource";
191
+ if (unit.provider === "treeseed" && /runtime$/u.test(unit.unitType)) return "release-gate";
192
+ return "cloudflare-resource";
193
+ }
194
+ function serviceIdForUnit(unit) {
195
+ const serviceKey = unit.metadata.serviceKey;
196
+ if (typeof serviceKey === "string" && serviceKey.trim()) return serviceKey;
197
+ if (unit.unitType.startsWith("railway-service:")) return unit.unitType.slice("railway-service:".length);
198
+ return null;
199
+ }
200
+ function packageIdForUnit(unit) {
201
+ const app = unit.metadata.applicationId ?? unit.metadata.packageId;
202
+ return typeof app === "string" && app.trim() ? app : null;
203
+ }
204
+ function resourceFromUnit(unit, environment) {
205
+ return {
206
+ id: unit.unitId,
207
+ kind: resourceKindForUnit(unit),
208
+ provider: unit.provider,
209
+ environment,
210
+ packageId: packageIdForUnit(unit),
211
+ serviceId: serviceIdForUnit(unit),
212
+ logicalName: unit.logicalName,
213
+ dependencies: unit.dependencies,
214
+ spec: {
215
+ unitType: unit.unitType,
216
+ identity: unit.identity,
217
+ target: unit.target,
218
+ spec: unit.spec,
219
+ secrets: Object.keys(unit.secrets),
220
+ metadata: unit.metadata
221
+ },
222
+ source: {
223
+ type: "reconcile-unit",
224
+ id: unit.unitId
225
+ }
226
+ };
227
+ }
228
+ function packageResources(adapter, environment) {
229
+ const resources = [];
230
+ const packageId = adapter.id;
231
+ const repository = typeof adapter.metadata.repository === "string" ? adapter.metadata.repository : null;
232
+ const dockerImageConfig = stringRecord(adapter.metadata.dockerImages);
233
+ const dockerWorkflow = workflowName(
234
+ environment === "prod" ? dockerImageConfig.releaseWorkflow : null,
235
+ environment === "prod" ? "publish.yml" : "source-build"
236
+ );
237
+ resources.push({
238
+ id: `package-manifest:${packageId}`,
239
+ kind: "package-manifest",
240
+ provider: "treeseed",
241
+ environment,
242
+ packageId,
243
+ serviceId: null,
244
+ logicalName: `${packageId} manifest`,
245
+ dependencies: [],
246
+ spec: {
247
+ packageId,
248
+ packageRoot: adapter.dir,
249
+ manifestPath: adapter.manifestPath,
250
+ kind: adapter.kind,
251
+ type: adapter.metadata.type ?? null,
252
+ releaseCapability: packageReleaseCapability(adapter),
253
+ requiredSecrets: adapter.metadata.requiredSecrets ?? [],
254
+ githubEnvironments: adapter.metadata.githubEnvironments ?? []
255
+ },
256
+ source: { type: "package-adapter", id: packageId }
257
+ });
258
+ if (adapter.releaseChecks.length > 0) {
259
+ resources.push({
260
+ id: `package-workflow:${packageId}`,
261
+ kind: "package-workflow",
262
+ provider: "github",
263
+ environment,
264
+ packageId,
265
+ serviceId: null,
266
+ logicalName: `${packageId} workflows`,
267
+ dependencies: [`package-manifest:${packageId}`],
268
+ spec: {
269
+ packageId,
270
+ packageRoot: adapter.dir,
271
+ repository,
272
+ releaseChecks: adapter.releaseChecks,
273
+ verifyCommands: adapter.verifyCommands,
274
+ githubEnvironments: adapter.metadata.githubEnvironments ?? [],
275
+ workflowTemplateVersion: adapter.metadata.workflowTemplateVersion ?? 1
276
+ },
277
+ source: { type: "package-adapter", id: packageId }
278
+ });
279
+ for (const environmentName of Array.isArray(adapter.metadata.githubEnvironments) ? adapter.metadata.githubEnvironments : []) {
280
+ if (typeof environmentName !== "string" || !environmentName.trim()) continue;
281
+ resources.push({
282
+ id: `github-environment:${packageId}:${environmentName}`,
283
+ kind: "github-environment",
284
+ provider: "github",
285
+ environment,
286
+ packageId,
287
+ serviceId: null,
288
+ logicalName: `${packageId} ${environmentName}`,
289
+ dependencies: [`package-workflow:${packageId}`],
290
+ spec: {
291
+ packageId,
292
+ packageRoot: adapter.dir,
293
+ repository,
294
+ environment: environmentName
295
+ },
296
+ source: { type: "package-adapter", id: packageId }
297
+ });
298
+ for (const secretName of Array.isArray(adapter.metadata.requiredSecrets) ? adapter.metadata.requiredSecrets : []) {
299
+ if (typeof secretName !== "string" || !secretName.trim()) continue;
300
+ resources.push({
301
+ id: `github-secret-binding:${packageId}:${environmentName}:${secretName}`,
302
+ kind: "github-secret-binding",
303
+ provider: "github",
304
+ environment,
305
+ packageId,
306
+ serviceId: null,
307
+ logicalName: `${packageId} ${environmentName} ${secretName}`,
308
+ dependencies: [`github-environment:${packageId}:${environmentName}`],
309
+ spec: {
310
+ packageId,
311
+ packageRoot: adapter.dir,
312
+ repository,
313
+ environment: environmentName,
314
+ secretName,
315
+ envName: secretName
316
+ },
317
+ source: { type: "package-adapter", id: packageId }
318
+ });
319
+ }
320
+ }
321
+ }
322
+ for (const artifact of adapter.artifacts) {
323
+ if (artifact.provider !== "docker") continue;
324
+ const dockerfile = artifact.dockerfile ?? "Dockerfile";
325
+ const context = artifact.context ?? ".";
326
+ const platforms = dockerPlatforms(artifact.architectures, adapter.metadata.dockerImageArchitectures);
327
+ const localBuildPlatforms = environment === "local" ? [localDockerPlatform()] : platforms;
328
+ const branch = environment === "prod" ? "main" : "staging";
329
+ const configuredTags = stringRecord(dockerImageConfig.tags);
330
+ const imageTagTemplates = environment === "prod" ? stringArray(configuredTags.release).length > 0 ? stringArray(configuredTags.release) : ["<version>"] : [];
331
+ const imageTags = materializeDockerImageTags(imageTagTemplates, adapter, branch);
332
+ const workflowSpec = repository ? {
333
+ packageId,
334
+ repository,
335
+ workflow: dockerWorkflow,
336
+ branch,
337
+ inputs: {
338
+ image: artifact.name,
339
+ ...artifact.target ? { target: artifact.target } : {}
340
+ },
341
+ wait: environment === "prod"
342
+ } : null;
343
+ resources.push({
344
+ id: `package-image:${artifact.name}`,
345
+ kind: "package-image",
346
+ provider: "dockerhub",
347
+ environment,
348
+ packageId,
349
+ serviceId: null,
350
+ logicalName: artifact.name,
351
+ dependencies: [`package-workflow:${packageId}`],
352
+ spec: {
353
+ packageId,
354
+ packageRoot: adapter.dir,
355
+ repository,
356
+ image: artifact.name,
357
+ role: artifact.role ?? null,
358
+ tags: imageTags,
359
+ architectures: platforms,
360
+ workflow: dockerWorkflow,
361
+ workflowDispatch: workflowSpec,
362
+ requiredSecrets: ["TREESEED_DOCKERHUB_TOKEN"],
363
+ requiredVariables: ["TREESEED_DOCKERHUB_USERNAME"]
364
+ },
365
+ source: { type: "package-adapter", id: packageId }
366
+ });
367
+ resources.push({
368
+ id: `docker-image-build:${artifact.name}`,
369
+ kind: "docker-image-build",
370
+ provider: "docker",
371
+ environment,
372
+ packageId,
373
+ serviceId: null,
374
+ logicalName: artifact.name,
375
+ dependencies: [`package-manifest:${packageId}`],
376
+ spec: {
377
+ packageId,
378
+ packageRoot: adapter.dir,
379
+ image: artifact.name,
380
+ dockerfile,
381
+ context,
382
+ prepareCommand: packageId === "@treeseed/agent" ? {
383
+ command: "bash",
384
+ args: ["-lc", "ulimit -n 65535 2>/dev/null || true; npm run capacity-provider:build -- --prepare-only"]
385
+ } : null,
386
+ target: artifact.target ?? null,
387
+ role: artifact.role ?? null,
388
+ platforms: localBuildPlatforms,
389
+ tags: imageTags.map((tag) => `${artifact.name}:${tag}`),
390
+ labels: {
391
+ "org.opencontainers.image.source": repository ? `https://github.com/${repository}` : adapter.relativeDir,
392
+ "org.treeseed.package": packageId
393
+ },
394
+ buildArgs: {},
395
+ push: false,
396
+ load: true,
397
+ provenance: false,
398
+ workflow: dockerWorkflow
399
+ },
400
+ source: { type: "package-adapter", id: packageId }
401
+ });
402
+ }
403
+ return resources;
404
+ }
405
+ function templateResources(templates, environment) {
406
+ return templates.map((template) => ({
407
+ id: `template-manifest:${template.id}`,
408
+ kind: "template-manifest",
409
+ provider: "treeseed",
410
+ environment,
411
+ packageId: template.id,
412
+ serviceId: null,
413
+ logicalName: `${template.name} template manifest`,
414
+ dependencies: [],
415
+ spec: {
416
+ templateId: template.id,
417
+ templateName: template.name,
418
+ category: template.category,
419
+ templateRoot: template.path,
420
+ manifestPath: template.manifestPath,
421
+ version: template.version,
422
+ repository: template.repository,
423
+ releaseTag: template.releaseTag,
424
+ recordPath: template.recordPath
425
+ },
426
+ source: { type: "package-adapter", id: `template:${template.id}` }
427
+ }));
428
+ }
429
+ function localDevelopmentResources(tenantRoot, environment, localContent) {
430
+ if (environment !== "local") return [];
431
+ const composeId = "local-docker-compose:agent-capacity-provider";
432
+ const treeDxComposeId = "local-docker-compose:treedx";
433
+ const apiPostgresComposeId = "local-docker-compose:api-postgres";
434
+ const mailpitComposeId = "local-docker-compose:mailpit";
435
+ const capacityProviderDataDir = resolvePath(tenantRoot, ".treeseed/local-capacity-provider/data");
436
+ const localGitCommonDir = resolveLocalGitCommonDir(tenantRoot);
437
+ const hostCodexAuthFile = [
438
+ process.env.TREESEED_CODEX_AUTH_FILE,
439
+ process.env.CODEX_AUTH_FILE,
440
+ process.env.HOME ? resolvePath(process.env.HOME, ".codex/auth.json") : ""
441
+ ].find((candidate) => candidate && existsSync(candidate)) ?? "";
442
+ const capacityPlan = resolveCapacityProviderLaunchPlan({
443
+ schemaVersion: 1,
444
+ provider: {
445
+ dataDir: capacityProviderDataDir,
446
+ environment: "local",
447
+ market: {
448
+ url: "http://host.docker.internal:3000",
449
+ id: "local"
450
+ }
451
+ },
452
+ runtime: {
453
+ images: {
454
+ roles: {
455
+ manager: { image: "treeseed/agent-manager", tag: "latest" },
456
+ runner: { image: "treeseed/agent-runner", tag: "latest" }
457
+ }
458
+ }
459
+ }
460
+ });
461
+ const localTreeDxApiEnv = {
462
+ TREESEED_TREEDX_JWT_ISSUER: "https://api.treeseed.local/treedx",
463
+ TREESEED_TREEDX_JWT_AUDIENCE: "treedx-local",
464
+ TREESEED_TREEDX_JWT_HS256_SECRET: "treeseed-local-treedx-jwt-secret",
465
+ TREESEED_TREEDX_PROXY_ACTOR_ID: "treeseed-api",
466
+ TREESEED_TREEDX_PROXY_TENANT_ID: "treeseed-control-plane"
467
+ };
468
+ const localCapacityProviderTreeDxEnv = {
469
+ TREESEED_TREEDX_BASE_URL: "http://host.docker.internal:4000",
470
+ TREESEED_TREEDX_URL: "http://host.docker.internal:4000",
471
+ ...localTreeDxApiEnv
472
+ };
473
+ const localCapacityProviderEnv = {
474
+ ...capacityPlan.composeEnv,
475
+ ...localCapacityProviderTreeDxEnv,
476
+ TREESEED_PROVIDER_HOST_DATA_DIR: capacityProviderDataDir,
477
+ ...hostCodexAuthFile ? {
478
+ TREESEED_HOST_CODEX_AUTH_FILE: hostCodexAuthFile,
479
+ TREESEED_CODEX_AUTH_FILE: "/data/codex/auth.json"
480
+ } : {},
481
+ ...localGitCommonDir ? {
482
+ TREESEED_PROVIDER_WORKSPACE_ABSOLUTE_CONTAINER: tenantRoot,
483
+ TREESEED_PROVIDER_WORKSPACE_GITDIR_CONTAINER: `/.treeseed/worktrees/${basename(tenantRoot)}`,
484
+ TREESEED_MARKET_GIT_COMMON_DIR_HOST: localGitCommonDir,
485
+ TREESEED_MARKET_GIT_COMMON_DIR_ABSOLUTE_CONTAINER: localGitCommonDir,
486
+ TREESEED_MARKET_GIT_COMMON_DIR_ROOT_CONTAINER: "/.git"
487
+ } : {},
488
+ TREESEED_PROVIDER_CONTAINER_UID: String(process.getuid?.() ?? 1e3),
489
+ TREESEED_PROVIDER_CONTAINER_GID: String(process.getgid?.() ?? 1e3),
490
+ TREESEED_CAPACITY_PROVIDER_API_KEY: "tsp_local_treeseed_demo_capacity_provider",
491
+ TREESEED_CAPACITY_PROVIDER_ID: "treeseed-local-dev",
492
+ TREESEED_CAPACITY_PROVIDER_TEAM_ID: "treeseed",
493
+ TREESEED_MANAGEMENT_API_URL: "http://host.docker.internal:3000"
494
+ };
495
+ return [
496
+ {
497
+ id: apiPostgresComposeId,
498
+ kind: "local-docker-compose",
499
+ provider: "local",
500
+ environment,
501
+ packageId: "@treeseed/api",
502
+ serviceId: "api-postgres",
503
+ logicalName: "local API PostgreSQL compose",
504
+ dependencies: [],
505
+ spec: {
506
+ composeFile: "packages/api/compose.postgres.yml",
507
+ projectName: "treeseed-local-api-postgres",
508
+ cwd: ".",
509
+ dataDir: ".treeseed/local-api-postgres/data",
510
+ env: {
511
+ TREESEED_LOCAL_POSTGRES_PASSWORD: "treeseed-local-dev",
512
+ TREESEED_LOCAL_POSTGRES_PORT: "54329"
513
+ },
514
+ ports: [{ host: 54329, container: 5432 }],
515
+ volumes: [{ name: "treeseed-api-postgres-volume", mountPath: "/var/lib/postgresql/data", sharedLocalOnly: true }],
516
+ healthChecks: [
517
+ { id: "api-postgres-compose", kind: "container", service: "treeseed-api-postgres" }
518
+ ]
519
+ },
520
+ source: { type: "package-adapter", id: "@treeseed/api" }
521
+ },
522
+ {
523
+ id: mailpitComposeId,
524
+ kind: "local-docker-compose",
525
+ provider: "local",
526
+ environment,
527
+ packageId: "@treeseed/sdk",
528
+ serviceId: "mailpit",
529
+ logicalName: "local Mailpit email capture compose",
530
+ dependencies: [],
531
+ spec: {
532
+ composeFile: "packages/sdk/src/treeseed/services/compose.yml",
533
+ projectName: "treeseed-local-mailpit",
534
+ cwd: ".",
535
+ env: {
536
+ TREESEED_MAILPIT_SMTP_BIND: "127.0.0.1",
537
+ TREESEED_MAILPIT_SMTP_PORT: "1025",
538
+ TREESEED_MAILPIT_UI_BIND: "127.0.0.1",
539
+ TREESEED_MAILPIT_UI_PORT: "8025"
540
+ },
541
+ ports: [
542
+ { host: 1025, container: 1025 },
543
+ { host: 8025, container: 8025 }
544
+ ],
545
+ healthChecks: [
546
+ { id: "mailpit-ui", kind: "http", url: "http://127.0.0.1:8025" }
547
+ ]
548
+ },
549
+ source: { type: "package-adapter", id: "@treeseed/sdk" }
550
+ },
551
+ {
552
+ id: "local-treedx:team-primary",
553
+ kind: "local-treedx",
554
+ provider: "local",
555
+ environment,
556
+ packageId: "treedx",
557
+ serviceId: "treedx",
558
+ logicalName: "local TreeDX team content repository plane",
559
+ dependencies: [treeDxComposeId],
560
+ spec: {
561
+ mode: "private-team",
562
+ contentRepositoryAccessMode: "treedx",
563
+ siteRepositoryAccessMode: "filesystem",
564
+ projectRepositoryAccessMode: "filesystem",
565
+ baseUrl: "http://127.0.0.1:4000",
566
+ dataDir: ".treeseed/local-treedx/data",
567
+ healthEndpoint: "http://127.0.0.1:4000/api/v1/health",
568
+ auth: localTreeDxApiEnv,
569
+ projects: localTreeDxContentProjects(tenantRoot)
570
+ },
571
+ source: { type: "package-adapter", id: "treedx" }
572
+ },
573
+ {
574
+ id: treeDxComposeId,
575
+ kind: "local-docker-compose",
576
+ provider: "local",
577
+ environment,
578
+ packageId: "treedx",
579
+ serviceId: "treedx",
580
+ logicalName: "local TreeDX compose",
581
+ dependencies: [],
582
+ spec: {
583
+ composeFile: "packages/treedx/compose.yaml",
584
+ projectName: "treeseed-local-treedx",
585
+ cwd: "packages/treedx",
586
+ dataDir: ".treeseed/local-treedx/data",
587
+ ports: [{ host: 4e3, container: 4e3 }],
588
+ env: {
589
+ TREEDX_ALLOW_DEV_VERIFIER_IN_PROD: "true",
590
+ ...localTreeDxApiEnv
591
+ },
592
+ volumes: [{ name: "treeseed-local-treedx-data", mountPath: "/data", sharedLocalOnly: true }],
593
+ healthChecks: [
594
+ { id: "treedx-api", kind: "http", url: "http://127.0.0.1:4000/api/v1/health" }
595
+ ]
596
+ },
597
+ source: { type: "package-adapter", id: "treedx" }
598
+ },
599
+ {
600
+ id: "capacity-provider:local",
601
+ kind: "capacity-provider",
602
+ provider: "local",
603
+ environment,
604
+ packageId: "@treeseed/agent",
605
+ serviceId: "capacity-provider",
606
+ logicalName: "local capacity provider",
607
+ dependencies: [composeId],
608
+ spec: {
609
+ mode: "local",
610
+ roles: ["api", "manager", "runner"],
611
+ volumePolicy: "shared-local",
612
+ healthEndpoint: "http://127.0.0.1:4783/healthz"
613
+ },
614
+ source: { type: "package-adapter", id: "@treeseed/agent" }
615
+ },
616
+ {
617
+ id: composeId,
618
+ kind: "local-docker-compose",
619
+ provider: "local",
620
+ environment,
621
+ packageId: "@treeseed/agent",
622
+ serviceId: "agent-capacity-provider",
623
+ logicalName: "agent capacity provider compose",
624
+ dependencies: ["local-process:api", treeDxComposeId],
625
+ spec: {
626
+ composeFile: "packages/agent/compose.capacity-provider.yml",
627
+ composeFiles: [
628
+ "packages/agent/compose.capacity-provider.yml",
629
+ "packages/agent/compose.capacity-provider.dev.yml"
630
+ ],
631
+ projectName: "treeseed-capacity-provider",
632
+ cwd: ".",
633
+ dataDir: ".treeseed/local-capacity-provider/data",
634
+ buildPolicy: "missing",
635
+ devMode: "typescript",
636
+ redactedEnv: capacityPlan.redactedEnv,
637
+ envKeys: Object.keys(localCapacityProviderEnv).sort(),
638
+ env: localCapacityProviderEnv,
639
+ services: ["agent-manager", "agent-runner"],
640
+ volumes: [{ name: "treeseed-capacity-provider-data", mountPath: "/data", sharedLocalOnly: true }],
641
+ healthChecks: [
642
+ { id: "compose-services", kind: "container", service: "agent-manager" }
643
+ ]
644
+ },
645
+ source: { type: "package-adapter", id: "@treeseed/agent" }
646
+ },
647
+ ...[
648
+ ["market-web", "Market web dev process"],
649
+ ["api", "API dev process"],
650
+ ["operations-runner", "Operations runner dev process"]
651
+ ].map(([id, label]) => ({
652
+ id: `local-process:${id}`,
653
+ kind: "local-process",
654
+ provider: "local",
655
+ environment,
656
+ packageId: id === "market-web" ? "@treeseed/market" : "@treeseed/api",
657
+ serviceId: id,
658
+ logicalName: label,
659
+ dependencies: id === "market-web" ? ["local-process:api", mailpitComposeId] : id === "api" ? [apiPostgresComposeId, mailpitComposeId] : ["local-process:api"],
660
+ spec: {
661
+ processId: id,
662
+ surfaces: id === "market-web" ? ["web"] : id === "api" ? ["api"] : ["operations-runner"],
663
+ supervisor: "sdk-managed-dev",
664
+ action: "start",
665
+ options: {
666
+ apiPort: 3e3
667
+ },
668
+ stateDir: ".treeseed/dev",
669
+ logDir: ".treeseed/logs",
670
+ cwd: id === "market-web" ? "." : "packages/api"
671
+ },
672
+ source: { type: "package-adapter", id }
673
+ })),
674
+ ...buildProjectLocalContentResources({ tenantRoot, environment, localContent })
675
+ ];
676
+ }
677
+ function releaseGateResources(packages, templates, environment) {
678
+ const phase = releasePhaseForEnvironment(environment);
679
+ const hostedEnvironment = environment === "prod" ? "prod" : "staging";
680
+ const packageGates = packages.flatMap((pkg) => {
681
+ const fingerprint = hashJson({ packageId: pkg.id, version: pkg.version, capability: pkg.releaseCapability, environment, phase });
682
+ const verifyDependencies = [
683
+ `package-manifest:${pkg.id}`,
684
+ ...internalPackageDependencies(packages, pkg).map((dependencyId) => `release-gate:verify:${dependencyId}`)
685
+ ];
686
+ const verifyGate = {
687
+ id: `release-gate:verify:${pkg.id}`,
688
+ kind: "release-gate",
689
+ provider: "treeseed",
690
+ environment,
691
+ packageId: pkg.id,
692
+ serviceId: null,
693
+ logicalName: `${pkg.id} verify gate`,
694
+ dependencies: verifyDependencies,
695
+ spec: {
696
+ gateKind: "release-gate:verify",
697
+ phase,
698
+ packageId: pkg.id,
699
+ environment: hostedEnvironment,
700
+ fingerprint,
701
+ capability: pkg.releaseCapability,
702
+ command: "verify.release"
703
+ },
704
+ source: { type: "package-adapter", id: pkg.id }
705
+ };
706
+ const publishGateKind = pkg.releaseCapability === "npm" ? "release-gate:npm-publish" : pkg.releaseCapability === "image" ? "release-gate:image-publish" : null;
707
+ return [
708
+ verifyGate,
709
+ ...publishGateKind ? [{
710
+ id: `${publishGateKind}:${pkg.id}`,
711
+ kind: "release-gate",
712
+ provider: "treeseed",
713
+ environment,
714
+ packageId: pkg.id,
715
+ serviceId: null,
716
+ logicalName: `${pkg.id} publish gate`,
717
+ dependencies: [verifyGate.id],
718
+ spec: {
719
+ gateKind: publishGateKind,
720
+ phase,
721
+ packageId: pkg.id,
722
+ environment: hostedEnvironment,
723
+ repository: pkg.repository,
724
+ fingerprint: hashJson({ publishGateKind, packageId: pkg.id, version: pkg.version, environment, phase }),
725
+ capability: pkg.releaseCapability
726
+ },
727
+ source: { type: "package-adapter", id: pkg.id }
728
+ }] : []
729
+ ];
730
+ });
731
+ const templateGates = templates.flatMap((template) => {
732
+ const verifyGate = {
733
+ id: `release-gate:template-verify:${template.id}`,
734
+ kind: "release-gate",
735
+ provider: "treeseed",
736
+ environment,
737
+ packageId: template.id,
738
+ serviceId: null,
739
+ logicalName: `${template.name} template verify gate`,
740
+ dependencies: [`template-manifest:${template.id}`],
741
+ spec: {
742
+ gateKind: "release-gate:template-verify",
743
+ phase,
744
+ templateId: template.id,
745
+ environment: hostedEnvironment,
746
+ fingerprint: hashJson({ templateId: template.id, version: template.version, repository: template.repository, environment, phase }),
747
+ releaseTag: template.releaseTag,
748
+ recordPath: template.recordPath
749
+ },
750
+ source: { type: "package-adapter", id: `template:${template.id}` }
751
+ };
752
+ return [
753
+ verifyGate,
754
+ {
755
+ id: `release-gate:template-release-record:${template.id}`,
756
+ kind: "release-gate",
757
+ provider: "treeseed",
758
+ environment,
759
+ packageId: template.id,
760
+ serviceId: null,
761
+ logicalName: `${template.name} template release record`,
762
+ dependencies: [verifyGate.id],
763
+ spec: {
764
+ gateKind: "release-gate:template-release-record",
765
+ phase,
766
+ templateId: template.id,
767
+ environment: hostedEnvironment,
768
+ fingerprint: hashJson({ gate: "template-release-record", templateId: template.id, version: template.version, releaseTag: template.releaseTag, environment, phase }),
769
+ releaseTag: template.releaseTag,
770
+ recordPath: template.recordPath
771
+ },
772
+ source: { type: "package-adapter", id: `template:${template.id}` }
773
+ }
774
+ ];
775
+ });
776
+ const releaseDependencies = [...packageGates.map((gate) => gate.id), ...templateGates.map((gate) => gate.id)];
777
+ return [
778
+ ...packageGates,
779
+ ...templateGates,
780
+ {
781
+ id: `release-gate:hosted-reconcile:${hostedEnvironment}:all`,
782
+ kind: "release-gate",
783
+ provider: "treeseed",
784
+ environment,
785
+ packageId: null,
786
+ serviceId: "hosted-reconcile",
787
+ logicalName: `${hostedEnvironment} hosted reconciliation gate`,
788
+ dependencies: releaseDependencies,
789
+ spec: {
790
+ gateKind: "release-gate:hosted-reconcile",
791
+ phase,
792
+ environment: hostedEnvironment,
793
+ appId: "all",
794
+ fingerprint: hashJson({ gate: "hosted-reconcile", environment: hostedEnvironment, packages, templates }),
795
+ hostedSelector: {
796
+ environment: hostedEnvironment,
797
+ provider: ["cloudflare", "cloudflare-dns", "railway"]
798
+ }
799
+ },
800
+ source: { type: "package-adapter", id: "release" }
801
+ },
802
+ {
803
+ id: `release-gate:live-verify:${hostedEnvironment}:all`,
804
+ kind: "release-gate",
805
+ provider: "treeseed",
806
+ environment,
807
+ packageId: null,
808
+ serviceId: "live-verify",
809
+ logicalName: `${hostedEnvironment} live verification gate`,
810
+ dependencies: [`release-gate:hosted-reconcile:${hostedEnvironment}:all`],
811
+ spec: {
812
+ gateKind: "release-gate:live-verify",
813
+ phase,
814
+ environment: hostedEnvironment,
815
+ appId: "all",
816
+ fingerprint: hashJson({ gate: "live-verify", environment: hostedEnvironment, packages, templates }),
817
+ hostedSelector: {
818
+ environment: hostedEnvironment,
819
+ provider: ["cloudflare", "cloudflare-dns", "railway"]
820
+ }
821
+ },
822
+ source: { type: "package-adapter", id: "release" }
823
+ },
824
+ {
825
+ id: environment === "prod" ? "release-gate:production-record:prod" : "release-gate:candidate-record:staging",
826
+ kind: "release-gate",
827
+ provider: "treeseed",
828
+ environment,
829
+ packageId: null,
830
+ serviceId: environment === "prod" ? "production-record" : "candidate-record",
831
+ logicalName: environment === "prod" ? "production release record" : "staging candidate record",
832
+ dependencies: [`release-gate:live-verify:${hostedEnvironment}:all`],
833
+ spec: {
834
+ gateKind: environment === "prod" ? "release-gate:production-record" : "release-gate:candidate-record",
835
+ phase,
836
+ environment,
837
+ fingerprint: hashJson({ gate: environment === "prod" ? "production-record" : "candidate-record", packages, templates }),
838
+ recordPath: environment === "prod" ? ".treeseed/workflow/releases/latest-production.json" : ".treeseed/workflow/release-candidates/latest-staging.json"
839
+ },
840
+ source: { type: "package-adapter", id: "release" }
841
+ }
842
+ ];
843
+ }
844
+ function slugBranchName(branchName) {
845
+ return branchName.toLowerCase().replace(/[^a-z0-9]+/gu, "-").replace(/^-+|-+$/gu, "").slice(0, 48) || "preview";
846
+ }
847
+ function branchPreviewResources(target, environment) {
848
+ if (target.kind !== "branch") return [];
849
+ const branchSlug = slugBranchName(target.branchName);
850
+ const previewId = `branch-preview:${branchSlug}:web`;
851
+ return [
852
+ {
853
+ id: previewId,
854
+ kind: "branch-preview",
855
+ provider: "treeseed",
856
+ environment,
857
+ packageId: "@treeseed/market",
858
+ serviceId: "market-web",
859
+ logicalName: `Branch preview for ${target.branchName}`,
860
+ dependencies: [],
861
+ spec: {
862
+ branch: target.branchName,
863
+ branchSlug,
864
+ environment: "staging",
865
+ appId: "web",
866
+ host: "cloudflare",
867
+ ttlHours: 72,
868
+ resources: {
869
+ environment: "staging",
870
+ appId: ["web"],
871
+ provider: ["cloudflare", "cloudflare-dns"]
872
+ }
873
+ },
874
+ source: { type: "package-adapter", id: "branch-preview" }
875
+ },
876
+ {
877
+ id: `branch-preview-cleanup:${branchSlug}:web`,
878
+ kind: "branch-preview-cleanup",
879
+ provider: "treeseed",
880
+ environment,
881
+ packageId: "@treeseed/market",
882
+ serviceId: "market-web",
883
+ logicalName: `Branch preview cleanup for ${target.branchName}`,
884
+ dependencies: [previewId],
885
+ spec: {
886
+ branch: target.branchName,
887
+ branchSlug,
888
+ environment: "staging",
889
+ reason: "manual",
890
+ selector: {
891
+ environment: "staging",
892
+ unitId: [previewId]
893
+ }
894
+ },
895
+ source: { type: "package-adapter", id: "branch-preview-cleanup" }
896
+ }
897
+ ];
898
+ }
899
+ function resourceMatchesSelector(resource, selector) {
900
+ if (!selector) return true;
901
+ const has = (values, candidates) => {
902
+ const normalized = new Set((values ?? []).map((value) => value.trim()).filter(Boolean));
903
+ return normalized.size === 0 || candidates.some((candidate) => candidate != null && normalized.has(candidate));
904
+ };
905
+ return has(selector.host ?? selector.provider, [resource.provider]) && has(selector.packageId, [resource.packageId]) && has(selector.serviceId, [resource.serviceId, resource.logicalName]) && has(selector.resourceKind, [resource.kind]) && has(selector.unitId, [resource.id, resource.source.type === "reconcile-unit" ? resource.source.id : null]) && has(selector.serviceType, [typeof resource.spec.unitType === "string" ? resource.spec.unitType : null]);
906
+ }
907
+ function compileTreeseedDesiredResourceGraph({
908
+ tenantRoot = workspaceRoot(),
909
+ target,
910
+ localContent = "auto"
911
+ }) {
912
+ const environment = environmentFromTarget(target);
913
+ const derived = deriveTreeseedDesiredUnits({ tenantRoot, target });
914
+ const packageAdapters = discoverTreeseedPackageAdapters(tenantRoot);
915
+ const packages = packageAdapters.map(packageUnitFromAdapter);
916
+ const templates = checkedOutTemplateRepositories(tenantRoot).map(templateUnitFromRepository);
917
+ const resources = [
918
+ ...derived.units.map((unit) => resourceFromUnit(unit, environment)),
919
+ ...packageAdapters.flatMap((adapter) => packageResources(adapter, environment)),
920
+ ...templateResources(templates, environment),
921
+ ...localDevelopmentResources(tenantRoot, environment, localContent),
922
+ ...branchPreviewResources(target, environment),
923
+ ...releaseGateResources(packages, templates, environment)
924
+ ];
925
+ const edges = resources.flatMap((resource) => resource.dependencies.map((dependency) => ({
926
+ from: dependency,
927
+ to: resource.id,
928
+ reason: "depends-on"
929
+ })));
930
+ const fingerprints = Object.fromEntries(resources.map((resource) => [resource.id, hashJson(resource)]));
931
+ return {
932
+ workspaceId: derived.deployConfig.slug,
933
+ environment,
934
+ packages,
935
+ templates,
936
+ resources,
937
+ edges,
938
+ fingerprints
939
+ };
940
+ }
941
+ function selectTreeseedDesiredResources(graph, selector) {
942
+ if (!selector) return graph;
943
+ const selected = graph.resources.filter((resource) => resourceMatchesSelector(resource, selector));
944
+ const selectedIds = new Set(selected.map((resource) => resource.id));
945
+ const include = new Map(selected.map((resource) => [resource.id, resource]));
946
+ const byId = new Map(graph.resources.map((resource) => [resource.id, resource]));
947
+ const visit = (resource) => {
948
+ for (const dependencyId of resource.dependencies) {
949
+ const dependency = byId.get(dependencyId);
950
+ if (!dependency || include.has(dependency.id)) continue;
951
+ include.set(dependency.id, dependency);
952
+ visit(dependency);
953
+ }
954
+ };
955
+ for (const resource of selected) visit(resource);
956
+ const resources = graph.resources.filter((resource) => include.has(resource.id));
957
+ const resourceIds = new Set(resources.map((resource) => resource.id));
958
+ return {
959
+ ...graph,
960
+ resources,
961
+ edges: graph.edges.filter((edge) => resourceIds.has(edge.from) && resourceIds.has(edge.to)),
962
+ fingerprints: Object.fromEntries(Object.entries(graph.fingerprints).filter(([id]) => resourceIds.has(id))),
963
+ packages: graph.packages.filter((pkg) => resources.some((resource) => resource.packageId === pkg.id) || selectedIds.size === 0),
964
+ templates: graph.templates.filter((template) => resources.some((resource) => resource.packageId === template.id) || selectedIds.size === 0)
965
+ };
966
+ }
967
+ function convertDesiredResourceToReconcileUnit(graph, resource) {
968
+ const identity = reconcileIdentityForGraph(graph.workspaceId, graph.environment);
969
+ if (resource.source.type !== "reconcile-unit") {
970
+ const unitType2 = (() => {
971
+ if (resource.kind === "release-gate") return String(resource.spec.gateKind ?? "release-gate:verify");
972
+ if (resource.kind === "save-gate") return String(resource.spec.gateKind ?? "save-gate:promotion-readiness");
973
+ return resource.kind;
974
+ })();
975
+ return {
976
+ unitId: resource.id,
977
+ unitType: unitType2,
978
+ provider: resource.provider,
979
+ identity,
980
+ target: { kind: "persistent", scope: graph.environment },
981
+ logicalName: resource.logicalName,
982
+ dependencies: resource.dependencies,
983
+ spec: resource.spec,
984
+ secrets: {},
985
+ metadata: {
986
+ resourceKind: resource.kind,
987
+ packageId: resource.packageId,
988
+ serviceId: resource.serviceId,
989
+ source: resource.source
990
+ }
991
+ };
992
+ }
993
+ const spec = resource.spec;
994
+ const unitType = typeof spec.unitType === "string" ? spec.unitType : null;
995
+ const resourceIdentity = spec.identity && typeof spec.identity === "object" ? spec.identity : null;
996
+ const target = spec.target && typeof spec.target === "object" ? spec.target : { kind: "persistent", scope: graph.environment };
997
+ const unitSpec = spec.spec && typeof spec.spec === "object" ? spec.spec : {};
998
+ const metadata = spec.metadata && typeof spec.metadata === "object" ? spec.metadata : {};
999
+ if (!unitType || !resourceIdentity) return null;
1000
+ return {
1001
+ unitId: resource.source.id,
1002
+ unitType,
1003
+ provider: resource.provider,
1004
+ identity: resourceIdentity,
1005
+ target,
1006
+ logicalName: resource.logicalName,
1007
+ dependencies: resource.dependencies,
1008
+ spec: unitSpec,
1009
+ secrets: {},
1010
+ metadata
1011
+ };
1012
+ }
1013
+ function compileTreeseedDesiredUnitsFromGraph(graph, selector) {
1014
+ return selectTreeseedDesiredResources(graph, selector).resources.map((resource) => convertDesiredResourceToReconcileUnit(graph, resource)).filter((unit) => Boolean(unit));
1015
+ }
1016
+ export {
1017
+ compileTreeseedDesiredResourceGraph,
1018
+ compileTreeseedDesiredUnitsFromGraph,
1019
+ convertDesiredResourceToReconcileUnit,
1020
+ selectTreeseedDesiredResources
1021
+ };