@treeseed/sdk 0.11.0 → 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 (473) hide show
  1. package/README.md +9 -4
  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 +117 -60
  27. package/dist/capacity-provider.js +215 -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 +2 -2
  36. package/dist/copilot.d.ts +3 -0
  37. package/dist/copilot.js +16 -1
  38. package/dist/d1-http.d.ts +1 -1
  39. package/dist/d1-store.d.ts +32 -57
  40. package/dist/d1-store.js +115 -318
  41. package/dist/db/d1.d.ts +1 -232
  42. package/dist/db/index.d.ts +3 -3
  43. package/dist/db/market-schema.d.ts +49037 -11843
  44. package/dist/db/market-schema.js +1788 -50
  45. package/dist/db/node-sqlite.d.ts +1 -232
  46. package/dist/db/schema.d.ts +0 -462
  47. package/dist/db/schema.js +2 -22
  48. package/dist/dispatch.d.ts +1 -1
  49. package/dist/dispatch.js +0 -11
  50. package/dist/fixture-support.js +52 -4
  51. package/dist/governance.d.ts +133 -0
  52. package/dist/governance.js +285 -0
  53. package/dist/graph/build.d.ts +2 -2
  54. package/dist/graph/context-query-contracts.d.ts +1 -1
  55. package/dist/graph/dsl.d.ts +1 -1
  56. package/dist/graph/query.d.ts +4 -4
  57. package/dist/graph/ranking.d.ts +1 -1
  58. package/dist/graph/schema.d.ts +1 -1
  59. package/dist/graph.d.ts +11 -11
  60. package/dist/guarantees/index.d.ts +425 -0
  61. package/dist/guarantees/index.js +1146 -0
  62. package/dist/hosting/apps.d.ts +1 -1
  63. package/dist/hosting/builtins.d.ts +1 -1
  64. package/dist/hosting/builtins.js +9 -198
  65. package/dist/hosting/contracts.d.ts +3 -2
  66. package/dist/hosting/graph.d.ts +24 -21
  67. package/dist/hosting/graph.js +280 -294
  68. package/dist/hosting/index.d.ts +4 -4
  69. package/dist/index.d.ts +88 -74
  70. package/dist/index.js +81 -10
  71. package/dist/local-dev/managed-dev.d.ts +85 -0
  72. package/dist/local-dev/managed-dev.js +368 -0
  73. package/dist/managed-dependencies.d.ts +9 -0
  74. package/dist/managed-dependencies.js +10 -8
  75. package/dist/market-client.d.ts +265 -7
  76. package/dist/market-client.js +381 -9
  77. package/dist/model-registry.d.ts +1 -1
  78. package/dist/model-registry.js +19 -19
  79. package/dist/operations/agent-tools.d.ts +2 -11
  80. package/dist/operations/agent-tools.js +2 -14
  81. package/dist/operations/providers/default.d.ts +1 -1
  82. package/dist/operations/providers/default.js +20 -37
  83. package/dist/operations/repository-operations.d.ts +26 -2
  84. package/dist/operations/repository-operations.js +159 -1
  85. package/dist/operations/runtime.d.ts +3 -3
  86. package/dist/operations/services/bootstrap-runner.d.ts +1 -1
  87. package/dist/operations/services/build-warning-policy.d.ts +34 -0
  88. package/dist/operations/services/build-warning-policy.js +81 -82
  89. package/dist/operations/services/commit-message-provider.js +4 -4
  90. package/dist/operations/services/config-runtime.d.ts +73 -19
  91. package/dist/operations/services/config-runtime.js +276 -100
  92. package/dist/operations/services/deploy.d.ts +41 -622
  93. package/dist/operations/services/deploy.js +181 -213
  94. package/dist/operations/services/deployment-readiness.d.ts +1 -1
  95. package/dist/operations/services/deployment-readiness.js +38 -7
  96. package/dist/operations/services/git-remote-policy.js +12 -4
  97. package/dist/operations/services/git-runner.d.ts +66 -0
  98. package/dist/operations/services/git-runner.js +479 -0
  99. package/dist/operations/services/git-workflow.d.ts +43 -5
  100. package/dist/operations/services/git-workflow.js +242 -20
  101. package/dist/operations/services/github-actions-verification.d.ts +3 -1
  102. package/dist/operations/services/github-actions-verification.js +11 -3
  103. package/dist/operations/services/github-api.js +21 -5
  104. package/dist/operations/services/github-automation.d.ts +3 -3
  105. package/dist/operations/services/github-automation.js +15 -18
  106. package/dist/operations/services/github-credentials.js +2 -1
  107. package/dist/operations/services/hosted-service-checks.d.ts +19 -1
  108. package/dist/operations/services/hosted-service-checks.js +162 -11
  109. package/dist/operations/services/hosting-audit.d.ts +2 -2
  110. package/dist/operations/services/hosting-audit.js +7 -7
  111. package/dist/operations/services/hub-launch.d.ts +1 -1
  112. package/dist/operations/services/hub-provider-launch.d.ts +5 -5
  113. package/dist/operations/services/hub-provider-launch.js +19 -14
  114. package/dist/operations/services/live-hosted-service-checks.d.ts +2 -1
  115. package/dist/operations/services/live-hosted-service-checks.js +193 -80
  116. package/dist/operations/services/local-dev.js +0 -1
  117. package/dist/operations/services/managed-host-security.d.ts +1 -1
  118. package/dist/operations/services/managed-repositories.d.ts +37 -0
  119. package/dist/operations/services/managed-repositories.js +177 -0
  120. package/dist/operations/services/operations-runner-smoke.d.ts +3 -2
  121. package/dist/operations/services/operations-runner-smoke.js +22 -4
  122. package/dist/operations/services/package-adapters.d.ts +77 -2
  123. package/dist/operations/services/package-adapters.js +627 -56
  124. package/dist/operations/services/package-reference-policy.d.ts +12 -88
  125. package/dist/operations/services/package-reference-policy.js +81 -213
  126. package/dist/operations/services/project-host-operations.d.ts +4 -4
  127. package/dist/operations/services/project-platform.d.ts +19 -193
  128. package/dist/operations/services/project-platform.js +31 -103
  129. package/dist/operations/services/project-web-monitor.d.ts +2 -2
  130. package/dist/operations/services/project-web-monitor.js +97 -2
  131. package/dist/operations/services/railway-api.d.ts +36 -7
  132. package/dist/operations/services/railway-api.js +331 -100
  133. package/dist/operations/services/railway-deploy.d.ts +7 -95
  134. package/dist/operations/services/railway-deploy.js +334 -742
  135. package/dist/operations/services/release-history.js +3 -4
  136. package/dist/operations/services/release-proof-ledger.d.ts +13 -0
  137. package/dist/operations/services/release-proof-ledger.js +81 -0
  138. package/dist/operations/services/release-proof-planner.d.ts +48 -0
  139. package/dist/operations/services/release-proof-planner.js +195 -0
  140. package/dist/operations/services/release-proof-runner.d.ts +16 -0
  141. package/dist/operations/services/release-proof-runner.js +169 -0
  142. package/dist/operations/services/release-proof.d.ts +81 -0
  143. package/dist/operations/services/release-proof.js +79 -0
  144. package/dist/operations/services/repository-save-orchestrator.d.ts +6 -7
  145. package/dist/operations/services/repository-save-orchestrator.js +353 -174
  146. package/dist/operations/services/runtime-paths.d.ts +1 -3
  147. package/dist/operations/services/runtime-paths.js +0 -4
  148. package/dist/operations/services/runtime-tools.d.ts +1 -192
  149. package/dist/operations/services/runtime-tools.js +4 -444
  150. package/dist/operations/services/save-deploy-preflight.js +9 -1
  151. package/dist/operations/services/template-host-bindings.d.ts +2 -2
  152. package/dist/operations/services/template-host-bindings.js +3 -2
  153. package/dist/operations/services/template-registry.d.ts +6 -6
  154. package/dist/operations/services/template-registry.js +33 -14
  155. package/dist/operations/services/template-secret-sync.d.ts +3 -3
  156. package/dist/operations/services/workflow-timing.d.ts +25 -0
  157. package/dist/operations/services/workflow-timing.js +79 -0
  158. package/dist/operations/services/workspace-dependency-mode.js +41 -4
  159. package/dist/operations/services/workspace-preflight.js +8 -8
  160. package/dist/operations/services/workspace-save-script.d.ts +4 -4
  161. package/dist/operations/services/workspace-save.d.ts +1 -0
  162. package/dist/operations/services/workspace-save.js +41 -18
  163. package/dist/operations/services/workspace-tools.js +40 -6
  164. package/dist/operations-registry.d.ts +1 -1
  165. package/dist/operations-registry.js +5 -6
  166. package/dist/operations-types.d.ts +1 -1
  167. package/dist/operations.d.ts +17 -11
  168. package/dist/operations.js +57 -3
  169. package/dist/platform/book-export.js +2 -0
  170. package/dist/platform/books-data.d.ts +1 -1
  171. package/dist/platform/config.d.ts +27 -0
  172. package/dist/platform/config.js +100 -0
  173. package/dist/platform/content-runtime-source.d.ts +54 -0
  174. package/dist/platform/content-runtime-source.js +169 -0
  175. package/dist/platform/contracts.d.ts +6 -1
  176. package/dist/platform/deploy-config.d.ts +1 -1
  177. package/dist/platform/deploy-config.js +7 -1
  178. package/dist/platform/deploy-runtime.d.ts +1 -1
  179. package/dist/platform/desired-state.d.ts +63 -0
  180. package/dist/platform/desired-state.js +1021 -0
  181. package/dist/platform/env.yaml +414 -19
  182. package/dist/platform/environment.d.ts +2 -2
  183. package/dist/platform/environment.js +54 -22
  184. package/dist/platform/local-content-materialization.d.ts +9 -0
  185. package/dist/platform/local-content-materialization.js +212 -0
  186. package/dist/platform/plugin.d.ts +5 -5
  187. package/dist/platform/plugins/runtime.d.ts +3 -3
  188. package/dist/platform/plugins/runtime.js +62 -1
  189. package/dist/platform/plugins.d.ts +6 -6
  190. package/dist/platform/published-content-pipeline.d.ts +3 -3
  191. package/dist/platform/published-content-pipeline.js +5 -1
  192. package/dist/platform/published-content.d.ts +4 -3
  193. package/dist/platform/site-config-schema.d.ts +1 -0
  194. package/dist/platform/site-config-schema.js +4 -1
  195. package/dist/platform/tenant/runtime-config.d.ts +152 -2
  196. package/dist/platform/tenant-config.d.ts +1 -1
  197. package/dist/platform/utils/site-config-schema.d.ts +154 -0
  198. package/dist/platform/utils/site-config-schema.js +400 -461
  199. package/dist/platform-operation-store.d.ts +1 -1
  200. package/dist/plugin-default.d.ts +1 -1
  201. package/dist/plugin-default.js +27 -12
  202. package/dist/project-import.d.ts +91 -0
  203. package/dist/project-import.js +257 -0
  204. package/dist/project-workflow.d.ts +1 -1
  205. package/dist/reconcile/bootstrap-systems.d.ts +2 -2
  206. package/dist/reconcile/bootstrap-systems.js +3 -3
  207. package/dist/reconcile/builtin-adapters.d.ts +7 -1
  208. package/dist/reconcile/builtin-adapters.js +2924 -346
  209. package/dist/reconcile/contracts.d.ts +15 -2
  210. package/dist/reconcile/desired-state.d.ts +2 -193
  211. package/dist/reconcile/desired-state.js +24 -33
  212. package/dist/reconcile/engine.d.ts +60 -397
  213. package/dist/reconcile/engine.js +182 -18
  214. package/dist/reconcile/index.d.ts +10 -10
  215. package/dist/reconcile/live-acceptance.d.ts +22 -1
  216. package/dist/reconcile/live-acceptance.js +456 -44
  217. package/dist/reconcile/providers/docker-private.d.ts +54 -0
  218. package/dist/reconcile/providers/docker-private.js +101 -0
  219. package/dist/reconcile/providers/github-private.d.ts +65 -0
  220. package/dist/reconcile/providers/github-private.js +119 -0
  221. package/dist/reconcile/providers/local-private.d.ts +28 -0
  222. package/dist/reconcile/providers/local-private.js +75 -0
  223. package/dist/reconcile/providers/railway-iac.d.ts +66 -0
  224. package/dist/reconcile/providers/railway-iac.js +275 -0
  225. package/dist/reconcile/providers/release-private.d.ts +92 -0
  226. package/dist/reconcile/providers/release-private.js +152 -0
  227. package/dist/reconcile/registry.d.ts +2 -2
  228. package/dist/reconcile/registry.js +16 -1
  229. package/dist/reconcile/state.d.ts +1 -1
  230. package/dist/reconcile/state.js +3 -40
  231. package/dist/reconcile/units.d.ts +1 -1
  232. package/dist/reconcile/units.js +7 -1
  233. package/dist/remote.d.ts +6 -6
  234. package/dist/scenes/artifacts.d.ts +16 -0
  235. package/dist/scenes/artifacts.js +61 -0
  236. package/dist/scenes/auth.d.ts +2 -0
  237. package/dist/scenes/auth.js +28 -0
  238. package/dist/scenes/base-url.d.ts +12 -0
  239. package/dist/scenes/base-url.js +123 -0
  240. package/dist/scenes/builtin-plugins.d.ts +2 -0
  241. package/dist/scenes/builtin-plugins.js +447 -0
  242. package/dist/scenes/checkpoints.d.ts +14 -0
  243. package/dist/scenes/checkpoints.js +33 -0
  244. package/dist/scenes/device-matrix.d.ts +2 -0
  245. package/dist/scenes/device-matrix.js +97 -0
  246. package/dist/scenes/devices.d.ts +11 -0
  247. package/dist/scenes/devices.js +22 -0
  248. package/dist/scenes/diagnostics.d.ts +5 -0
  249. package/dist/scenes/diagnostics.js +22 -0
  250. package/dist/scenes/diagram-providers.d.ts +2 -0
  251. package/dist/scenes/diagram-providers.js +181 -0
  252. package/dist/scenes/diagram-validation.d.ts +22 -0
  253. package/dist/scenes/diagram-validation.js +74 -0
  254. package/dist/scenes/environment.d.ts +2 -0
  255. package/dist/scenes/environment.js +65 -0
  256. package/dist/scenes/evidence-bundle.d.ts +5 -0
  257. package/dist/scenes/evidence-bundle.js +42 -0
  258. package/dist/scenes/evidence-report.d.ts +10 -0
  259. package/dist/scenes/evidence-report.js +73 -0
  260. package/dist/scenes/evidence.d.ts +16 -0
  261. package/dist/scenes/evidence.js +277 -0
  262. package/dist/scenes/index.d.ts +48 -0
  263. package/dist/scenes/index.js +312 -0
  264. package/dist/scenes/inspect.d.ts +9 -0
  265. package/dist/scenes/inspect.js +64 -0
  266. package/dist/scenes/loader.d.ts +3 -0
  267. package/dist/scenes/loader.js +38 -0
  268. package/dist/scenes/logs.d.ts +2 -0
  269. package/dist/scenes/logs.js +47 -0
  270. package/dist/scenes/operations.d.ts +3 -0
  271. package/dist/scenes/operations.js +128 -0
  272. package/dist/scenes/phase0.d.ts +9 -0
  273. package/dist/scenes/phase0.js +637 -0
  274. package/dist/scenes/planner.d.ts +12 -0
  275. package/dist/scenes/planner.js +166 -0
  276. package/dist/scenes/playwright-adapter.d.ts +2 -0
  277. package/dist/scenes/playwright-adapter.js +63 -0
  278. package/dist/scenes/plugins.d.ts +5 -0
  279. package/dist/scenes/plugins.js +115 -0
  280. package/dist/scenes/progress.d.ts +17 -0
  281. package/dist/scenes/progress.js +24 -0
  282. package/dist/scenes/publish-destinations.d.ts +12 -0
  283. package/dist/scenes/publish-destinations.js +99 -0
  284. package/dist/scenes/publish-plan-report.d.ts +10 -0
  285. package/dist/scenes/publish-plan-report.js +70 -0
  286. package/dist/scenes/publish-plan.d.ts +15 -0
  287. package/dist/scenes/publish-plan.js +248 -0
  288. package/dist/scenes/publish-redaction.d.ts +16 -0
  289. package/dist/scenes/publish-redaction.js +148 -0
  290. package/dist/scenes/publish-release-record.d.ts +13 -0
  291. package/dist/scenes/publish-release-record.js +34 -0
  292. package/dist/scenes/publish-report.d.ts +10 -0
  293. package/dist/scenes/publish-report.js +67 -0
  294. package/dist/scenes/publish.d.ts +16 -0
  295. package/dist/scenes/publish.js +298 -0
  296. package/dist/scenes/registry.d.ts +12 -0
  297. package/dist/scenes/registry.js +65 -0
  298. package/dist/scenes/remotion-adapter.d.ts +3 -0
  299. package/dist/scenes/remotion-adapter.js +94 -0
  300. package/dist/scenes/remotion-composition-registry.d.ts +2 -0
  301. package/dist/scenes/remotion-composition-registry.js +12 -0
  302. package/dist/scenes/remotion-compositions.d.ts +15 -0
  303. package/dist/scenes/remotion-compositions.js +464 -0
  304. package/dist/scenes/remotion-diagrams.d.ts +9 -0
  305. package/dist/scenes/remotion-diagrams.js +188 -0
  306. package/dist/scenes/remotion-input.d.ts +13 -0
  307. package/dist/scenes/remotion-input.js +291 -0
  308. package/dist/scenes/remotion-visuals.d.ts +29 -0
  309. package/dist/scenes/remotion-visuals.js +198 -0
  310. package/dist/scenes/render-media-assets.d.ts +9 -0
  311. package/dist/scenes/render-media-assets.js +117 -0
  312. package/dist/scenes/render-report.d.ts +10 -0
  313. package/dist/scenes/render-report.js +27 -0
  314. package/dist/scenes/render.d.ts +2 -0
  315. package/dist/scenes/render.js +218 -0
  316. package/dist/scenes/reporter.d.ts +3 -0
  317. package/dist/scenes/reporter.js +101 -0
  318. package/dist/scenes/resume.d.ts +2 -0
  319. package/dist/scenes/resume.js +79 -0
  320. package/dist/scenes/runner.d.ts +2 -0
  321. package/dist/scenes/runner.js +674 -0
  322. package/dist/scenes/schema.d.ts +6 -0
  323. package/dist/scenes/schema.js +994 -0
  324. package/dist/scenes/seed.d.ts +2 -0
  325. package/dist/scenes/seed.js +83 -0
  326. package/dist/scenes/segments.d.ts +15 -0
  327. package/dist/scenes/segments.js +79 -0
  328. package/dist/scenes/selectors.d.ts +3 -0
  329. package/dist/scenes/selectors.js +21 -0
  330. package/dist/scenes/timeline.d.ts +11 -0
  331. package/dist/scenes/timeline.js +26 -0
  332. package/dist/scenes/timeouts.d.ts +6 -0
  333. package/dist/scenes/timeouts.js +17 -0
  334. package/dist/scenes/training-captions.d.ts +14 -0
  335. package/dist/scenes/training-captions.js +98 -0
  336. package/dist/scenes/training-report.d.ts +10 -0
  337. package/dist/scenes/training-report.js +78 -0
  338. package/dist/scenes/training-transcript.d.ts +24 -0
  339. package/dist/scenes/training-transcript.js +204 -0
  340. package/dist/scenes/training.d.ts +10 -0
  341. package/dist/scenes/training.js +134 -0
  342. package/dist/scenes/types.d.ts +1872 -0
  343. package/dist/scenes/types.js +8 -0
  344. package/dist/scenes/visual-audit-contact-sheets.d.ts +6 -0
  345. package/dist/scenes/visual-audit-contact-sheets.js +119 -0
  346. package/dist/scenes/visual-audit-fixtures.d.ts +25 -0
  347. package/dist/scenes/visual-audit-fixtures.js +210 -0
  348. package/dist/scenes/visual-audit-report.d.ts +11 -0
  349. package/dist/scenes/visual-audit-report.js +85 -0
  350. package/dist/scenes/visual-audit-review.d.ts +23 -0
  351. package/dist/scenes/visual-audit-review.js +829 -0
  352. package/dist/scenes/visual-audit-routes.d.ts +13 -0
  353. package/dist/scenes/visual-audit-routes.js +308 -0
  354. package/dist/scenes/visual-audit.d.ts +3 -0
  355. package/dist/scenes/visual-audit.js +596 -0
  356. package/dist/scripts/build-dist.js +154 -40
  357. package/dist/scripts/check-build-warnings.js +42 -53
  358. package/dist/scripts/cleanup-markdown.js +1 -1
  359. package/dist/scripts/cli-test-fixtures.js +24 -28
  360. package/dist/scripts/migrate-journey-csv-to-guarantees.js +140 -0
  361. package/dist/scripts/package-tools.js +12 -1
  362. package/dist/scripts/prepare.js +3 -7
  363. package/dist/scripts/release-verify.js +2 -5
  364. package/dist/scripts/run-fixture-astro-command.js +1 -1
  365. package/dist/scripts/template-catalog.test.js +68 -82
  366. package/dist/scripts/tenant-dev.js +0 -10
  367. package/dist/scripts/test-cloudflare-local.js +1 -1
  368. package/dist/scripts/test-scaffold.js +0 -1
  369. package/dist/scripts/test-smoke.js +3 -3
  370. package/dist/scripts/treeseed-build-dist.js +4 -7
  371. package/dist/scripts/treeseed-release-verify.js +1 -1
  372. package/dist/scripts/verify-driver.js +30 -21
  373. package/dist/scripts/workflow-commands.test.js +18 -27
  374. package/dist/scripts/workspace-command-e2e.js +1 -1
  375. package/dist/scripts/workspace-lint.js +6 -0
  376. package/dist/scripts/workspace-release-test.js +90 -1
  377. package/dist/scripts/workspace-test.js +6 -0
  378. package/dist/sdk-dispatch.d.ts +1 -1
  379. package/dist/sdk-dispatch.js +0 -16
  380. package/dist/sdk-fields.d.ts +1 -1
  381. package/dist/sdk-filters.d.ts +1 -1
  382. package/dist/sdk-types.d.ts +1184 -113
  383. package/dist/sdk-types.js +393 -0
  384. package/dist/sdk.d.ts +74 -79
  385. package/dist/sdk.js +27 -36
  386. package/dist/secrets-capability.d.ts +421 -0
  387. package/dist/secrets-capability.js +530 -0
  388. package/dist/seeds/normalize.js +1 -0
  389. package/dist/seeds/planner.js +38 -0
  390. package/dist/seeds/schema.js +293 -4
  391. package/dist/seeds/types.d.ts +60 -0
  392. package/dist/seeds/types.js +9 -1
  393. package/dist/service-credentials.d.ts +54 -0
  394. package/dist/service-credentials.js +112 -0
  395. package/dist/stores/cursor-store.d.ts +2 -2
  396. package/dist/stores/envelopes.d.ts +1 -1
  397. package/dist/stores/helpers.d.ts +1 -1
  398. package/dist/stores/lease-store.d.ts +2 -2
  399. package/dist/stores/message-store.d.ts +2 -2
  400. package/dist/stores/operational-store.d.ts +3 -26
  401. package/dist/stores/operational-store.js +0 -225
  402. package/dist/stores/project-workflow-store.d.ts +2 -2
  403. package/dist/stores/run-store.d.ts +2 -3
  404. package/dist/stores/run-store.js +0 -98
  405. package/dist/stores/subscription-store.d.ts +2 -3
  406. package/dist/stores/subscription-store.js +0 -100
  407. package/dist/template-catalog.d.ts +1 -1
  408. package/dist/template-launch-requirements.d.ts +2 -2
  409. package/dist/template-launch-ui.d.ts +2 -2
  410. package/dist/treedx/adapters.d.ts +6 -6
  411. package/dist/treedx/client.d.ts +1 -1
  412. package/dist/treedx/errors.d.ts +1 -1
  413. package/dist/treedx/federated-client.d.ts +3 -3
  414. package/dist/treedx/graph-adapter.d.ts +2 -2
  415. package/dist/treedx/index.d.ts +14 -14
  416. package/dist/treedx/market-integration.d.ts +1 -1
  417. package/dist/treedx/ports.d.ts +30 -30
  418. package/dist/treedx/query-adapter.d.ts +3 -3
  419. package/dist/treedx/registry-client.d.ts +2 -2
  420. package/dist/treedx/repository-adapter.d.ts +4 -4
  421. package/dist/treedx/repository-adapter.js +14 -3
  422. package/dist/treedx/sdk-integration.d.ts +3 -3
  423. package/dist/treedx/types.d.ts +2 -2
  424. package/dist/treedx/workspace-adapter.d.ts +2 -2
  425. package/dist/treedx-backends.d.ts +13 -11
  426. package/dist/treedx-backends.js +52 -50
  427. package/dist/treedx-client.d.ts +3 -0
  428. package/dist/treedx-client.js +10 -1
  429. package/dist/treeseed/services/compose.yml +2 -3
  430. package/dist/treeseed/template-catalog/catalog.fixture.json +4 -4
  431. package/dist/types/agents.d.ts +256 -0
  432. package/dist/types/agents.js +42 -1
  433. package/dist/verification.d.ts +1 -0
  434. package/dist/verification.js +143 -14
  435. package/dist/workflow/operations.d.ts +510 -559
  436. package/dist/workflow/operations.js +1891 -1342
  437. package/dist/workflow/policy.js +19 -7
  438. package/dist/workflow/runs.d.ts +9 -3
  439. package/dist/workflow/runs.js +66 -26
  440. package/dist/workflow/session.d.ts +4 -1
  441. package/dist/workflow/session.js +50 -10
  442. package/dist/workflow/worktrees.d.ts +6 -2
  443. package/dist/workflow/worktrees.js +98 -15
  444. package/dist/workflow-state.d.ts +5 -5
  445. package/dist/workflow-state.js +27 -17
  446. package/dist/workflow-support.d.ts +26 -25
  447. package/dist/workflow-support.js +27 -31
  448. package/dist/workflow.d.ts +46 -16
  449. package/dist/workflow.js +19 -7
  450. package/drizzle/d1/0000_treeseed_d1.sql +0 -18
  451. package/drizzle/market/0000_market_control_plane.sql +1793 -1499
  452. package/drizzle/market/0005_agent_capacity_coordination.sql +145 -0
  453. package/drizzle/market/0006_provider_assignment_lifecycle.sql +9 -0
  454. package/drizzle/market/0007_agent_architecture_gap_closure.sql +157 -0
  455. package/drizzle/market/0008_agent_capacity_operational_closure.sql +27 -0
  456. package/drizzle/market/0009_agent_capacity_runtime_hardening.sql +29 -0
  457. package/drizzle/market/0010_secrets_capability_persistence.sql +130 -0
  458. package/drizzle/market/0011_github_app_adapter.sql +47 -0
  459. package/drizzle/market/0012_workday_test_runs.sql +44 -0
  460. package/drizzle/market/0013_runtime_task_lifecycle.sql +39 -0
  461. package/drizzle/market/0014_governance_pipeline.sql +189 -0
  462. package/package.json +75 -18
  463. package/scripts/{verify-driver.mjs → verify-driver.ts} +19 -4
  464. package/templates/github/deploy-web.workflow.yml +12 -8
  465. package/dist/operations/services/mailpit-runtime.d.ts +0 -20
  466. package/dist/operations/services/mailpit-runtime.js +0 -67
  467. package/dist/operations/services/release-candidate.d.ts +0 -60
  468. package/dist/operations/services/release-candidate.js +0 -953
  469. package/dist/scripts/ensure-mailpit.js +0 -48
  470. package/dist/scripts/logs-mailpit.js +0 -2
  471. package/dist/scripts/run-ts.js +0 -45
  472. package/dist/scripts/stop-mailpit.js +0 -5
  473. package/dist/scripts/treeseed-run-ts.js +0 -45
@@ -1,6 +1,8 @@
1
- import { existsSync, readFileSync, writeFileSync } from "node:fs";
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
2
  import { basename, resolve, relative } from "node:path";
3
3
  import { spawn, spawnSync } from "node:child_process";
4
+ import { tmpdir } from "node:os";
5
+ import { classifyTreeseedGitMode, runTreeseedGitText } from "./git-runner.js";
4
6
  import {
5
7
  ensureSshPushUrlForOrigin,
6
8
  remoteWriteUrl,
@@ -10,8 +12,8 @@ import {
10
12
  generateRepositoryCommitMessage
11
13
  } from "./commit-message-provider.js";
12
14
  import {
13
- createDevTagMessage,
14
15
  createPackageDependencyReference,
16
+ normalizeGitRemoteForDependency,
15
17
  updateInternalDependencySpecs
16
18
  } from "./package-reference-policy.js";
17
19
  import {
@@ -32,7 +34,6 @@ import {
32
34
  } from "./workspace-save.js";
33
35
  import {
34
36
  hasCompleteTreeseedPackageCheckout,
35
- run,
36
37
  sortWorkspacePackages,
37
38
  workspacePackages
38
39
  } from "./workspace-tools.js";
@@ -48,6 +49,24 @@ import {
48
49
  import {
49
50
  discoverTreeseedPackageAdapters
50
51
  } from "./package-adapters.js";
52
+ import {
53
+ discoverTreeseedManagedRepositories,
54
+ parseGitmodulesPaths,
55
+ readTreeseedTemplateRepositoryManifest
56
+ } from "./managed-repositories.js";
57
+ function runGit(args, options) {
58
+ return runTreeseedGitText(args, {
59
+ cwd: options.cwd,
60
+ mode: classifyTreeseedGitMode(args),
61
+ timeoutMs: options.timeoutMs,
62
+ maxBuffer: options.maxBuffer
63
+ });
64
+ }
65
+ function sleepMs(durationMs) {
66
+ return new Promise((resolvePromise) => {
67
+ setTimeout(resolvePromise, durationMs);
68
+ });
69
+ }
51
70
  class RepositorySaveError extends Error {
52
71
  exitCode;
53
72
  details;
@@ -77,11 +96,66 @@ function emitProgress(options, node, phase, message, stream = "stdout") {
77
96
  function prefixedOutput(node, phase, output) {
78
97
  return String(output ?? "").split(/\r?\n/u).map((line) => line.trimEnd()).filter(Boolean).map((line) => `${progressPrefix(node, phase)} ${line}`).join("\n");
79
98
  }
99
+ function withShortProcessTempEnv(env = {}) {
100
+ const merged = { ...process.env, ...env };
101
+ if (process.platform === "win32") {
102
+ return merged;
103
+ }
104
+ const shortTemp = tmpdir();
105
+ const tempKeys = ["TMPDIR", "TMP", "TEMP"];
106
+ for (const key of tempKeys) {
107
+ const value = merged[key];
108
+ if (value && value.length > shortTemp.length) {
109
+ merged[key] = shortTemp;
110
+ }
111
+ }
112
+ return merged;
113
+ }
114
+ function npmCacheForCwd(cwd) {
115
+ const cacheDir = resolve(cwd, ".treeseed", "cache", "npm");
116
+ mkdirSync(cacheDir, { recursive: true });
117
+ return cacheDir;
118
+ }
119
+ function npmWorkflowEnv(env = {}, cwd = process.cwd()) {
120
+ const npmCache = env.npm_config_cache ?? env.NPM_CONFIG_CACHE ?? process.env.npm_config_cache ?? process.env.NPM_CONFIG_CACHE ?? npmCacheForCwd(cwd);
121
+ return withShortProcessTempEnv({
122
+ ...env,
123
+ NPM_CONFIG_CACHE: npmCache,
124
+ npm_config_audit: env.npm_config_audit ?? process.env.npm_config_audit ?? "false",
125
+ npm_config_cache: npmCache,
126
+ npm_config_fetch_retries: env.npm_config_fetch_retries ?? process.env.npm_config_fetch_retries ?? "2",
127
+ npm_config_fund: env.npm_config_fund ?? process.env.npm_config_fund ?? "false",
128
+ npm_config_foreground_scripts: env.npm_config_foreground_scripts ?? process.env.npm_config_foreground_scripts ?? "true",
129
+ npm_config_loglevel: env.npm_config_loglevel ?? process.env.npm_config_loglevel ?? "warn",
130
+ npm_config_maxsockets: env.npm_config_maxsockets ?? process.env.npm_config_maxsockets ?? "4",
131
+ npm_config_prefer_offline: env.npm_config_prefer_offline ?? process.env.npm_config_prefer_offline ?? "true",
132
+ npm_config_progress: env.npm_config_progress ?? process.env.npm_config_progress ?? "false"
133
+ });
134
+ }
135
+ function npmCommandForSpawn(args) {
136
+ if (process.platform === "win32") {
137
+ return { command: "npm", args };
138
+ }
139
+ return {
140
+ command: "bash",
141
+ args: [
142
+ "-lc",
143
+ 'ulimit -n 65535 2>/dev/null || ulimit -n 32768 2>/dev/null || ulimit -n 16384 2>/dev/null || true; exec npm "$@"',
144
+ "npm-fd-guard",
145
+ ...args
146
+ ]
147
+ };
148
+ }
149
+ function displayCommand(command, args) {
150
+ return command === "npm" ? `npm ${args.join(" ")}` : `${command} ${args.join(" ")}`;
151
+ }
80
152
  function runCapturedCommand(node, options, phase, command, args, commandOptions = {}) {
81
- emitProgress(options, node, phase, `$ ${command} ${args.join(" ")}`);
82
- const result = spawnSync(command, args, {
83
- cwd: commandOptions.cwd ?? node.path,
84
- env: { ...process.env, ...commandOptions.env ?? {} },
153
+ const cwd = commandOptions.cwd ?? node.path;
154
+ const spawnCommand = command === "npm" ? npmCommandForSpawn(args) : { command, args };
155
+ emitProgress(options, node, phase, `$ ${displayCommand(command, args)}`);
156
+ const result = spawnSync(spawnCommand.command, spawnCommand.args, {
157
+ cwd,
158
+ env: command === "npm" ? npmWorkflowEnv(commandOptions.env, cwd) : withShortProcessTempEnv(commandOptions.env),
85
159
  stdio: "pipe",
86
160
  encoding: "utf8",
87
161
  timeout: commandOptions.timeoutMs
@@ -94,12 +168,12 @@ function runCapturedCommand(node, options, phase, command, args, commandOptions
94
168
  }
95
169
  if (result.status !== 0) {
96
170
  const message = (result.error?.message ? `${result.error.message}
97
- ` : "") + (prefixedOutput(node, phase, stderr) || prefixedOutput(node, phase, stdout) || `${progressPrefix(node, phase)} ${command} ${args.join(" ")} failed`);
171
+ ` : "") + (prefixedOutput(node, phase, stderr) || prefixedOutput(node, phase, stdout) || `${progressPrefix(node, phase)} ${displayCommand(command, args)} failed`);
98
172
  throw new RepositorySaveError(message, {
99
173
  details: {
100
174
  failingRepo: node.name,
101
175
  phase,
102
- command: `${command} ${args.join(" ")}`
176
+ command: displayCommand(command, args)
103
177
  }
104
178
  });
105
179
  }
@@ -127,9 +201,11 @@ function isNoOpGitCommitError(error) {
127
201
  return /nothing to commit|no changes added to commit/u.test(error.message);
128
202
  }
129
203
  function runQuietCommand(node, phase, command, args, commandOptions = {}) {
130
- const result = spawnSync(command, args, {
131
- cwd: commandOptions.cwd ?? node.path,
132
- env: { ...process.env, ...commandOptions.env ?? {} },
204
+ const cwd = commandOptions.cwd ?? node.path;
205
+ const spawnCommand = command === "npm" ? npmCommandForSpawn(args) : { command, args };
206
+ const result = spawnSync(spawnCommand.command, spawnCommand.args, {
207
+ cwd,
208
+ env: command === "npm" ? npmWorkflowEnv(commandOptions.env, cwd) : withShortProcessTempEnv(commandOptions.env),
133
209
  stdio: "pipe",
134
210
  encoding: "utf8",
135
211
  timeout: commandOptions.timeoutMs
@@ -139,14 +215,14 @@ function runQuietCommand(node, phase, command, args, commandOptions = {}) {
139
215
  if (result.status !== 0) {
140
216
  throw new RepositorySaveError(
141
217
  [
142
- `${progressPrefix(node, phase)} ${command} ${args.join(" ")} failed`,
218
+ `${progressPrefix(node, phase)} ${displayCommand(command, args)} failed`,
143
219
  stderr || stdout
144
220
  ].filter(Boolean).join("\n"),
145
221
  {
146
222
  details: {
147
223
  failingRepo: node.name,
148
224
  phase,
149
- command: `${command} ${args.join(" ")}`
225
+ command: displayCommand(command, args)
150
226
  }
151
227
  }
152
228
  );
@@ -154,11 +230,13 @@ function runQuietCommand(node, phase, command, args, commandOptions = {}) {
154
230
  return stdout;
155
231
  }
156
232
  async function runStreamingCommand(node, options, phase, command, args, commandOptions = {}) {
157
- emitProgress(options, node, phase, `$ ${command} ${args.join(" ")}`);
233
+ const cwd = commandOptions.cwd ?? node.path;
234
+ const spawnCommand = command === "npm" ? npmCommandForSpawn(args) : { command, args };
235
+ emitProgress(options, node, phase, `$ ${displayCommand(command, args)}`);
158
236
  return await new Promise((resolvePromise, reject) => {
159
- const child = spawn(command, args, {
160
- cwd: commandOptions.cwd ?? node.path,
161
- env: { ...process.env, ...commandOptions.env ?? {} },
237
+ const child = spawn(spawnCommand.command, spawnCommand.args, {
238
+ cwd,
239
+ env: command === "npm" ? npmWorkflowEnv(commandOptions.env, cwd) : withShortProcessTempEnv(commandOptions.env),
162
240
  stdio: ["ignore", "pipe", "pipe"]
163
241
  });
164
242
  let stdout = "";
@@ -185,7 +263,7 @@ async function runStreamingCommand(node, options, phase, command, args, commandO
185
263
  if (settled) return;
186
264
  settled = true;
187
265
  child.kill("SIGTERM");
188
- reject(new Error(`${progressPrefix(node, phase)} ${command} ${args.join(" ")} timed out after ${commandOptions.timeoutMs}ms`));
266
+ reject(new Error(`${progressPrefix(node, phase)} ${displayCommand(command, args)} timed out after ${commandOptions.timeoutMs}ms`));
189
267
  }, commandOptions.timeoutMs) : null;
190
268
  child.stdout?.on("data", (chunk) => {
191
269
  const text = chunk.toString();
@@ -225,12 +303,12 @@ async function runStreamingCommand(node, options, phase, command, args, commandO
225
303
  return;
226
304
  }
227
305
  reject(new RepositorySaveError(
228
- prefixedOutput(node, phase, stderr) || prefixedOutput(node, phase, stdout) || `${progressPrefix(node, phase)} ${command} ${args.join(" ")} failed with exit code ${code ?? "unknown"}`,
306
+ prefixedOutput(node, phase, stderr) || prefixedOutput(node, phase, stdout) || `${progressPrefix(node, phase)} ${displayCommand(command, args)} failed with exit code ${code ?? "unknown"}`,
229
307
  {
230
308
  details: {
231
309
  failingRepo: node.name,
232
310
  phase,
233
- command: `${command} ${args.join(" ")}`
311
+ command: displayCommand(command, args)
234
312
  }
235
313
  }
236
314
  ));
@@ -241,7 +319,9 @@ function packageScripts(packageJson) {
241
319
  const scripts = packageJson?.scripts;
242
320
  return scripts && typeof scripts === "object" && !Array.isArray(scripts) ? Object.fromEntries(Object.entries(scripts).map(([key, value]) => [key, String(value)])) : {};
243
321
  }
244
- function classifyRepoKind(packageJson) {
322
+ function classifyRepoKind(packageJson, managedKind) {
323
+ if (managedKind === "template") return "template";
324
+ if (managedKind === "fixture") return "fixture";
245
325
  if (typeof packageJson?.name !== "string" || typeof packageJson?.version !== "string") {
246
326
  return "project";
247
327
  }
@@ -261,7 +341,7 @@ function repoIdForPath(root, repoDir) {
261
341
  }
262
342
  function isGitRepo(repoDir) {
263
343
  try {
264
- run("git", ["rev-parse", "--is-inside-work-tree"], { cwd: repoDir, capture: true });
344
+ runGit(["rev-parse", "--is-inside-work-tree"], { cwd: repoDir, capture: true });
265
345
  return true;
266
346
  } catch {
267
347
  return false;
@@ -294,17 +374,20 @@ function repoDisplayName(repoDir, packageJson) {
294
374
  function emptyManifestVerifyCommands() {
295
375
  return { fast: null, local: null, release: null };
296
376
  }
377
+ function verifyCommandFromString(repoDir, label, command) {
378
+ return command ? { label, command: "bash", args: ["-lc", command], cwd: repoDir } : null;
379
+ }
380
+ function templateVerifyCommands(repoDir) {
381
+ const manifest = readTreeseedTemplateRepositoryManifest(repoDir);
382
+ if (!manifest) return null;
383
+ return {
384
+ fast: verifyCommandFromString(repoDir, "fast", manifest.verify.fast),
385
+ local: verifyCommandFromString(repoDir, "local", manifest.verify.local),
386
+ release: verifyCommandFromString(repoDir, "release", manifest.verify.release)
387
+ };
388
+ }
297
389
  function parseGitmodules(root) {
298
- const gitmodulesPath = resolve(root, ".gitmodules");
299
- if (!existsSync(gitmodulesPath)) {
300
- return [];
301
- }
302
- const source = readFileSync(gitmodulesPath, "utf8");
303
- const paths = [];
304
- for (const match of source.matchAll(/^\s*path\s*=\s*(.+?)\s*$/gmu)) {
305
- paths.push(match[1].replaceAll("\\", "/"));
306
- }
307
- return paths;
390
+ return parseGitmodulesPaths(root);
308
391
  }
309
392
  function slugBranch(branch) {
310
393
  return branch.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40) || "dev";
@@ -328,13 +411,29 @@ function isDevVersionForBranch(version, branch) {
328
411
  function packageVersionAtHead(node) {
329
412
  if (!node.packageJsonPath) return null;
330
413
  try {
331
- const source = run("git", ["show", "HEAD:package.json"], { cwd: node.path, capture: true });
414
+ const source = runGit(["show", "HEAD:package.json"], { cwd: node.path, capture: true });
332
415
  const packageJson = JSON.parse(source);
333
416
  return typeof packageJson.version === "string" ? packageJson.version : null;
334
417
  } catch {
335
418
  return null;
336
419
  }
337
420
  }
421
+ function headCommitOrPlanPlaceholder(cwd) {
422
+ try {
423
+ return headCommit(cwd);
424
+ } catch {
425
+ return "HEAD";
426
+ }
427
+ }
428
+ function remoteBranchCommitSafe(cwd, branch) {
429
+ try {
430
+ const output = runGit(["ls-remote", "origin", `refs/heads/${branch}`], { cwd, capture: true });
431
+ const [sha] = output.trim().split(/\s+/u);
432
+ return /^[a-f0-9]{40}$/u.test(sha ?? "") ? sha : null;
433
+ } catch {
434
+ return null;
435
+ }
436
+ }
338
437
  function canManagePackageJsonVersion(node) {
339
438
  return node.kind === "package" && Boolean(node.packageJsonPath) && typeof node.packageJson?.version === "string";
340
439
  }
@@ -343,6 +442,7 @@ function packageVersionEligibleForBranch(node, version, options) {
343
442
  }
344
443
  function packageVersionTagConflictsWithHead(node, options) {
345
444
  if (node.kind !== "package") return false;
445
+ if (node.branchMode === "package-dev-save" && (options.devDependencyReferenceMode ?? "git-commit") === "git-commit") return false;
346
446
  const version = typeof node.packageJson?.version === "string" ? node.packageJson.version : null;
347
447
  if (!version || !packageVersionEligibleForBranch(node, version, options)) return false;
348
448
  const head = headCommit(node.path);
@@ -351,7 +451,7 @@ function packageVersionTagConflictsWithHead(node, options) {
351
451
  }
352
452
  function selectPackageVersion(node, options) {
353
453
  const current = String(node.packageJson?.version ?? "0.0.0");
354
- if (node.branchMode === "package-dev-save" && isDevVersionForBranch(current, node.branch || options.branch) && !tagExists(node.path, current)) {
454
+ if (node.branchMode === "package-dev-save" && isDevVersionForBranch(current, node.branch || options.branch) && ((options.devDependencyReferenceMode ?? "git-commit") === "git-commit" || !tagExists(node.path, current))) {
355
455
  return { version: current, reused: true };
356
456
  }
357
457
  if (node.branchMode === "package-release-main") {
@@ -382,8 +482,6 @@ function createReport(node) {
382
482
  publishWait: null,
383
483
  version: typeof node.packageJson?.version === "string" ? node.packageJson.version : null,
384
484
  dependencySpec: node.plannedDependencySpec,
385
- devTagMetadata: null,
386
- replacedDevTags: [],
387
485
  branchMode: node.branchMode,
388
486
  verification: null,
389
487
  install: null,
@@ -396,8 +494,14 @@ function createReport(node) {
396
494
  }
397
495
  function discoverRepositorySaveNodes(root, gitRoot = repoRoot(root), branch = currentBranch(gitRoot), options = {}) {
398
496
  const repoDirs = /* @__PURE__ */ new Map();
399
- repoDirs.set(".", gitRoot);
400
497
  const packageAdaptersByDir = new Map(discoverTreeseedPackageAdapters(root).map((adapter) => [resolve(adapter.dir), adapter]));
498
+ const managedRepositoriesByDir = new Map(discoverTreeseedManagedRepositories(root).map((repo) => [resolve(repo.dir), repo]));
499
+ for (const repo of managedRepositoriesByDir.values()) {
500
+ repoDirs.set(repo.relativeDir, repo.dir);
501
+ }
502
+ if (!repoDirs.has(".")) {
503
+ repoDirs.set(".", gitRoot);
504
+ }
401
505
  if (hasCompleteTreeseedPackageCheckout(root)) {
402
506
  for (const pkg of workspacePackages(root)) {
403
507
  if (isIndependentGitRepo(pkg.dir)) {
@@ -420,12 +524,13 @@ function discoverRepositorySaveNodes(root, gitRoot = repoRoot(root), branch = cu
420
524
  const packageJsonPath = resolve(repoDir, "package.json");
421
525
  const packageJson = existsSync(packageJsonPath) ? readJson(packageJsonPath) : null;
422
526
  const adapter = packageAdaptersByDir.get(resolve(repoDir)) ?? null;
423
- const kind = adapter && !packageJson ? "package" : classifyRepoKind(packageJson);
527
+ const managed = managedRepositoriesByDir.get(resolve(repoDir)) ?? null;
528
+ const kind = adapter && !packageJson ? "package" : classifyRepoKind(packageJson, managed?.kind);
424
529
  const repoBranch = relativePath === "." ? currentBranch(repoDir) || branch || null : branch || currentBranch(repoDir) || null;
425
530
  const branchMode = kind === "project" ? "project-save" : options.stablePackageRelease === true && repoBranch === PRODUCTION_BRANCH ? "package-release-main" : "package-dev-save";
426
531
  return {
427
532
  id: relativePath,
428
- name: adapter?.id ?? repoDisplayName(repoDir, packageJson),
533
+ name: managed?.kind === "template" || managed?.kind === "fixture" ? managed.name : adapter?.id ?? repoDisplayName(repoDir, packageJson),
429
534
  path: repoDir,
430
535
  relativePath,
431
536
  kind,
@@ -434,7 +539,7 @@ function discoverRepositorySaveNodes(root, gitRoot = repoRoot(root), branch = cu
434
539
  packageJsonPath: packageJson ? packageJsonPath : null,
435
540
  packageJson,
436
541
  scripts: packageScripts(packageJson),
437
- manifestVerifyCommands: adapter?.verifyCommands ?? emptyManifestVerifyCommands(),
542
+ manifestVerifyCommands: adapter?.verifyCommands ?? templateVerifyCommands(repoDir) ?? emptyManifestVerifyCommands(),
438
543
  remoteUrl: originRemoteUrlSafe(repoDir),
439
544
  dependencies: [],
440
545
  dependents: [],
@@ -529,9 +634,16 @@ function runLimited(items, limit, action) {
529
634
  });
530
635
  return Promise.all(workers);
531
636
  }
637
+ function repositorySaveConcurrency(options) {
638
+ if (options.verifyMode && options.verifyMode !== "skip") {
639
+ return 1;
640
+ }
641
+ const configured = Number.parseInt(process.env.TREESEED_SAVE_REPOSITORY_CONCURRENCY ?? "", 10);
642
+ return Number.isFinite(configured) && configured > 0 ? configured : 3;
643
+ }
532
644
  function remoteBranchExistsSafe(repoDir, branch) {
533
645
  try {
534
- run("git", ["rev-parse", "--verify", `refs/remotes/origin/${branch}`], { cwd: repoDir, capture: true });
646
+ runGit(["rev-parse", "--verify", `refs/remotes/origin/${branch}`], { cwd: repoDir, capture: true });
535
647
  return true;
536
648
  } catch {
537
649
  }
@@ -580,8 +692,8 @@ function commitSubject(message) {
580
692
  return String(message ?? "").split(/\r?\n/u)[0]?.trim() || null;
581
693
  }
582
694
  function gitDiffSummary(repoDir) {
583
- const changedFiles = run("git", ["status", "--porcelain"], { cwd: repoDir, capture: true });
584
- const rawDiff = run("git", ["diff", "--cached"], { cwd: repoDir, capture: true, maxBuffer: 1024 * 1024 * 32 });
695
+ const changedFiles = runGit(["status", "--porcelain"], { cwd: repoDir, capture: true });
696
+ const rawDiff = runGit(["diff", "--cached"], { cwd: repoDir, capture: true, maxBuffer: 1024 * 1024 * 32 });
585
697
  const maxDiffChars = 12e4;
586
698
  const diff = rawDiff.length > maxDiffChars ? `${rawDiff.slice(0, maxDiffChars)}
587
699
 
@@ -591,7 +703,7 @@ function gitDiffSummary(repoDir) {
591
703
  }
592
704
  function hasStagedChanges(repoDir) {
593
705
  try {
594
- return run("git", ["diff", "--cached", "--name-only"], { cwd: repoDir, capture: true }).trim().length > 0;
706
+ return runGit(["diff", "--cached", "--name-only"], { cwd: repoDir, capture: true }).trim().length > 0;
595
707
  } catch {
596
708
  return false;
597
709
  }
@@ -604,6 +716,54 @@ function updateDependencyReferences(node, finalizedReferences) {
604
716
  }
605
717
  return changed;
606
718
  }
719
+ function isRootWorkspaceRepository(node, options) {
720
+ const packageJson = node.packageJson ?? (existsSync(resolve(node.path, "package.json")) ? readJson(resolve(node.path, "package.json")) : null);
721
+ return node.path === options.root && Array.isArray(packageJson?.workspaces);
722
+ }
723
+ function syncDirectGitDependencyLockfileEntries(node, options, references) {
724
+ if (references.length === 0) return false;
725
+ const lockfilePath = resolve(node.path, "package-lock.json");
726
+ if (!existsSync(lockfilePath)) return false;
727
+ const lockfile = readJson(lockfilePath);
728
+ const rootPackage = lockfile.packages && typeof lockfile.packages === "object" && !Array.isArray(lockfile.packages) ? lockfile.packages[""] : null;
729
+ const packageEntries = lockfile.packages && typeof lockfile.packages === "object" && !Array.isArray(lockfile.packages) ? lockfile.packages : null;
730
+ if (!rootPackage || !packageEntries) return false;
731
+ let changed = false;
732
+ for (const reference of references) {
733
+ const manifestSpec = reference.manifestSpec ?? reference.spec;
734
+ for (const field of dependencyFields(rootPackage)) {
735
+ const values = rootPackage[field];
736
+ if (!values || typeof values !== "object" || Array.isArray(values)) continue;
737
+ const dependencies = values;
738
+ if (reference.packageName in dependencies && dependencies[reference.packageName] !== manifestSpec) {
739
+ dependencies[reference.packageName] = manifestSpec;
740
+ changed = true;
741
+ }
742
+ }
743
+ const entryKey = `node_modules/${reference.packageName}`;
744
+ const entry = packageEntries[entryKey];
745
+ if (entry) {
746
+ const nextResolved = normalizeGitRemoteForDependency(reference.remoteUrl ?? "", "ssh");
747
+ const resolved = nextResolved ? `${nextResolved}#${manifestSpec.slice(manifestSpec.lastIndexOf("#") + 1)}` : manifestSpec;
748
+ if (entry.resolved !== resolved) {
749
+ entry.resolved = resolved;
750
+ changed = true;
751
+ }
752
+ if (typeof reference.version === "string" && reference.version && entry.version !== reference.version) {
753
+ entry.version = reference.version;
754
+ changed = true;
755
+ }
756
+ if ("integrity" in entry) {
757
+ delete entry.integrity;
758
+ changed = true;
759
+ }
760
+ }
761
+ }
762
+ if (!changed) return false;
763
+ writeJson(lockfilePath, lockfile);
764
+ emitProgress(options, node, "lockfile", "Synchronized direct internal Git dependency lockfile entries without npm git preparation.");
765
+ return true;
766
+ }
607
767
  function planPackageVersion(node, options) {
608
768
  if (!node.packageJson || !node.packageJsonPath) return null;
609
769
  const current = String(node.packageJson.version ?? "0.0.0");
@@ -635,6 +795,25 @@ function syncRootWorkspaceLockfileMetadata(node, options) {
635
795
  let changed = false;
636
796
  const packageEntries = packages;
637
797
  const rootEntry = packageEntries[""] ?? {};
798
+ const workspacePackageList = workspacePackages(node.path);
799
+ const workspaceVersionByName = new Map(workspacePackageList.map((workspacePackage) => [String(workspacePackage.packageJson.name ?? ""), String(workspacePackage.packageJson.version ?? "")]).filter(([name, version]) => name.length > 0 && version.length > 0));
800
+ const rootDependencySpecs = /* @__PURE__ */ new Map();
801
+ for (const field of dependencyFields(node.packageJson)) {
802
+ const rootDeps = node.packageJson[field];
803
+ if (!rootDeps || typeof rootDeps !== "object" || Array.isArray(rootDeps)) continue;
804
+ for (const [dependencyName, dependencySpec] of Object.entries(rootDeps)) {
805
+ if (typeof dependencySpec === "string") {
806
+ rootDependencySpecs.set(dependencyName, dependencySpec);
807
+ }
808
+ }
809
+ }
810
+ const stableWorkspaceDependencySpec = (dependencyName) => rootDependencySpecs.get(dependencyName) ?? workspaceVersionByName.get(dependencyName) ?? null;
811
+ const normalizeWorkspaceDependencySpecs = (value) => Object.fromEntries(
812
+ Object.entries(value).map(([dependencyName, dependencySpec]) => [
813
+ dependencyName,
814
+ workspaceVersionByName.has(dependencyName) ? stableWorkspaceDependencySpec(dependencyName) : dependencySpec
815
+ ])
816
+ );
638
817
  if (JSON.stringify(rootEntry.workspaces ?? []) !== JSON.stringify(node.packageJson.workspaces)) {
639
818
  rootEntry.workspaces = node.packageJson.workspaces;
640
819
  packageEntries[""] = rootEntry;
@@ -659,7 +838,7 @@ function syncRootWorkspaceLockfileMetadata(node, options) {
659
838
  }
660
839
  }
661
840
  }
662
- for (const workspacePackage of workspacePackages(node.path)) {
841
+ for (const workspacePackage of workspacePackageList) {
663
842
  const relativeDir = workspacePackage.relativeDir.replace(/\\/gu, "/");
664
843
  const packageJson = workspacePackage.packageJson;
665
844
  const packageName = String(packageJson.name ?? "");
@@ -676,8 +855,9 @@ function syncRootWorkspaceLockfileMetadata(node, options) {
676
855
  for (const field of dependencyFields(packageJson)) {
677
856
  const nextValue = packageJson[field];
678
857
  if (nextValue && typeof nextValue === "object" && !Array.isArray(nextValue)) {
679
- if (JSON.stringify(packageEntry[field] ?? {}) !== JSON.stringify(nextValue)) {
680
- packageEntry[field] = nextValue;
858
+ const normalizedValue = normalizeWorkspaceDependencySpecs(nextValue);
859
+ if (JSON.stringify(packageEntry[field] ?? {}) !== JSON.stringify(normalizedValue)) {
860
+ packageEntry[field] = normalizedValue;
681
861
  changed = true;
682
862
  }
683
863
  }
@@ -702,24 +882,9 @@ function syncRootWorkspaceLockfileMetadata(node, options) {
702
882
  return true;
703
883
  }
704
884
  async function runGitDependencySmoke(node, options, reference) {
705
- if (reference.mode !== "dev-git-tag" || shouldSkipGitDependencySmoke(options)) return;
706
- const tagName = reference.tagName ?? reference.version;
707
- if (!reference.remoteUrl || !tagName) {
708
- throw new RepositorySaveError(`Git dependency smoke cannot verify ${reference.packageName}; remote URL or tag is missing.`);
709
- }
710
- const tagRef = `refs/tags/${tagName}`;
711
- emitProgress(options, node, "smoke", `Verifying ${reference.packageName} tag ${tagName} exists on ${reference.remoteUrl}.`);
712
- try {
713
- await runStreamingCommand(node, options, "smoke", "git", ["ls-remote", "--exit-code", "--tags", reference.remoteUrl, tagRef]);
714
- } catch (error) {
715
- const detail = error instanceof Error ? error.message : String(error);
716
- throw new RepositorySaveError([
717
- `Git dependency smoke failed for ${reference.packageName}; tag is not reachable on the remote.`,
718
- `Remote: ${reference.remoteUrl}`,
719
- `Tag: ${tagName}`,
720
- detail
721
- ].join("\n"));
722
- }
885
+ void node;
886
+ void options;
887
+ void reference;
723
888
  }
724
889
  async function runNpmInstallWithRetry(node, options, gitDependencyRefreshSpecs = []) {
725
890
  if (shouldSkipNetworkInstall()) {
@@ -741,14 +906,14 @@ async function runNpmInstallWithRetry(node, options, gitDependencyRefreshSpecs =
741
906
  }
742
907
  if (attempt < 5) {
743
908
  emitProgress(options, node, "install", "npm install failed; retrying in 60 seconds.", "stderr");
744
- spawnSync("sleep", ["60"], { stdio: "ignore" });
909
+ await sleepMs(6e4);
745
910
  }
746
911
  }
747
912
  throw new RepositorySaveError(`npm install failed after 5 attempts.
748
913
  ${lastError ?? ""}`);
749
914
  }
750
915
  async function runProjectVerificationInstallWithRetry(node, options) {
751
- if (node.branchMode !== "project-save" || !hasNpmLockfile(node.path)) return;
916
+ if (!hasNpmLockfile(node.path)) return;
752
917
  if (shouldSkipNetworkInstall()) {
753
918
  emitProgress(options, node, "install", "Skipped project verification dependency install because network install mode is disabled.");
754
919
  return;
@@ -770,8 +935,8 @@ async function runProjectVerificationInstallWithRetry(node, options) {
770
935
  lastError = error instanceof Error ? error.message : String(error);
771
936
  }
772
937
  if (attempt < 5) {
773
- emitProgress(options, node, "install", "npm ci for project verification failed; retrying in 60 seconds.", "stderr");
774
- spawnSync("sleep", ["60"], { stdio: "ignore" });
938
+ emitProgress(options, node, "install", "npm ci for verification failed; retrying in 60 seconds.", "stderr");
939
+ await sleepMs(6e4);
775
940
  }
776
941
  }
777
942
  throw new RepositorySaveError(`Project verification dependency install failed after 5 attempts.
@@ -993,9 +1158,57 @@ function pushCurrentBranch(node, options, branch, tagName) {
993
1158
  combinedBranchAndTagPush: pushedTag
994
1159
  };
995
1160
  }
1161
+ async function finishRepositorySavePublish(node, options, state, report, input) {
1162
+ const reference = input.reference ?? null;
1163
+ const tagName = input.tagName ?? reference?.tagName ?? null;
1164
+ const shouldDeferPush = options.deferPushUntilVerified === true && node.id === ".";
1165
+ if (shouldDeferPush) {
1166
+ state.deferredPushes.push({
1167
+ node,
1168
+ report,
1169
+ branch: input.branch,
1170
+ tagName,
1171
+ rebase: input.rebase,
1172
+ reference
1173
+ });
1174
+ report.pushed = false;
1175
+ report.publishWait = {
1176
+ ...input.rebase,
1177
+ deferredPush: true
1178
+ };
1179
+ return;
1180
+ }
1181
+ const push = pushCurrentBranch(node, options, input.branch, tagName);
1182
+ if (reference) {
1183
+ await runGitDependencySmoke(node, options, reference);
1184
+ report.dependencySpec = reference.spec;
1185
+ }
1186
+ report.pushed = push.pushed;
1187
+ report.publishWait = {
1188
+ ...input.rebase,
1189
+ ...push
1190
+ };
1191
+ }
1192
+ async function publishDeferredRepositoryPushes(options, state) {
1193
+ if (state.deferredPushes.length === 0) return;
1194
+ for (const deferred of state.deferredPushes) {
1195
+ const push = pushCurrentBranch(deferred.node, options, deferred.branch, deferred.tagName);
1196
+ if (deferred.reference) {
1197
+ await runGitDependencySmoke(deferred.node, options, deferred.reference);
1198
+ deferred.report.dependencySpec = deferred.reference.spec;
1199
+ }
1200
+ deferred.report.pushed = push.pushed;
1201
+ deferred.report.publishWait = {
1202
+ ...deferred.rebase,
1203
+ ...push,
1204
+ deferredPush: true
1205
+ };
1206
+ }
1207
+ state.deferredPushes = [];
1208
+ }
996
1209
  function tagExists(repoDir, tagName) {
997
1210
  try {
998
- run("git", ["rev-parse", "--verify", `refs/tags/${tagName}`], { cwd: repoDir, capture: true });
1211
+ runGit(["rev-parse", "--verify", `refs/tags/${tagName}`], { cwd: repoDir, capture: true });
999
1212
  return true;
1000
1213
  } catch {
1001
1214
  return false;
@@ -1003,14 +1216,14 @@ function tagExists(repoDir, tagName) {
1003
1216
  }
1004
1217
  function localTagCommit(repoDir, tagName) {
1005
1218
  try {
1006
- return run("git", ["rev-list", "-n", "1", tagName], { cwd: repoDir, capture: true }).trim();
1219
+ return runGit(["rev-list", "-n", "1", tagName], { cwd: repoDir, capture: true }).trim();
1007
1220
  } catch {
1008
1221
  return null;
1009
1222
  }
1010
1223
  }
1011
1224
  function remoteTagCommit(repoDir, tagName) {
1012
1225
  try {
1013
- const output = run("git", ["ls-remote", "--tags", "origin", `refs/tags/${tagName}*`], { cwd: repoDir, capture: true });
1226
+ const output = runGit(["ls-remote", "--tags", "origin", `refs/tags/${tagName}*`], { cwd: repoDir, capture: true });
1014
1227
  const lines = output.split(/\r?\n/u).map((line) => line.trim()).filter(Boolean);
1015
1228
  const dereferenced = lines.find((line) => line.endsWith(`refs/tags/${tagName}^{}`));
1016
1229
  const exact = lines.find((line) => line.endsWith(`refs/tags/${tagName}`));
@@ -1022,7 +1235,7 @@ function remoteTagCommit(repoDir, tagName) {
1022
1235
  }
1023
1236
  function localTagMessage(repoDir, tagName) {
1024
1237
  try {
1025
- return run("git", ["tag", "-l", tagName, "--format=%(contents)"], { cwd: repoDir, capture: true }).trim();
1238
+ return runGit(["tag", "-l", tagName, "--format=%(contents)"], { cwd: repoDir, capture: true }).trim();
1026
1239
  } catch {
1027
1240
  return null;
1028
1241
  }
@@ -1063,13 +1276,9 @@ function assertTagStateMatchesHead(node, tagName, state, head) {
1063
1276
  }
1064
1277
  }
1065
1278
  function createPackageTagMessage(node, tagName, branch, workflowRunId) {
1066
- return tagName.includes("-dev.") ? createDevTagMessage({
1067
- packageName: node.name,
1068
- version: tagName,
1069
- branch,
1070
- commitSha: headCommit(node.path),
1071
- workflowRunId
1072
- }) : `release: ${tagName}`;
1279
+ void branch;
1280
+ void workflowRunId;
1281
+ return `release: ${tagName}`;
1073
1282
  }
1074
1283
  function ensureRemoteAccessBeforeVerification(node, options, state) {
1075
1284
  if (shouldSkipRemoteAccessPreflight()) return;
@@ -1099,12 +1308,6 @@ function ensureRemoteAccessBeforeVerification(node, options, state) {
1099
1308
  function shouldSkipRemoteAccessPreflight() {
1100
1309
  return process.env.TREESEED_SAVE_REMOTE_PREFLIGHT === "skip";
1101
1310
  }
1102
- function localTreeseedTagWasCreatedByThisRun(node, tagName, workflowRunId) {
1103
- const message = localTagMessage(node.path, tagName);
1104
- if (!message?.includes("treeseed-dev-tag: true")) return false;
1105
- if (!workflowRunId) return true;
1106
- return message.includes(`workflowRunId: ${workflowRunId}`);
1107
- }
1108
1311
  function ensurePackageTagReady(node, options, tagName, branch, workflowRunId) {
1109
1312
  let message = null;
1110
1313
  ensureWritableRemote(node, options);
@@ -1129,7 +1332,7 @@ function ensurePackageTagReady(node, options, tagName, branch, workflowRunId) {
1129
1332
  }
1130
1333
  function treeCommitForPath(repoDir, ref, path) {
1131
1334
  try {
1132
- const output = run("git", ["ls-tree", ref, "--", path], { cwd: repoDir, capture: true }).trim();
1335
+ const output = runGit(["ls-tree", ref, "--", path], { cwd: repoDir, capture: true }).trim();
1133
1336
  const match = output.match(/^\d+\s+commit\s+([0-9a-f]{40})\t/u);
1134
1337
  return match?.[1] ?? null;
1135
1338
  } catch {
@@ -1143,7 +1346,7 @@ function collectSubmodulePointerChanges(node, finalizedCommits) {
1143
1346
  if (!childRelativePath) continue;
1144
1347
  const childPath = resolve(node.path, childRelativePath);
1145
1348
  if (!existsSync(childPath) || !isGitRepo(childPath)) continue;
1146
- const status = run("git", ["status", "--porcelain", "--", childRelativePath], { cwd: node.path, capture: true });
1349
+ const status = runGit(["status", "--porcelain", "--", childRelativePath], { cwd: node.path, capture: true });
1147
1350
  const oldSha = treeCommitForPath(node.path, "HEAD", childRelativePath);
1148
1351
  const newSha = finalizedCommit || headCommit(childPath);
1149
1352
  if (status.trim().length > 0 || oldSha && newSha && oldSha !== newSha) {
@@ -1210,7 +1413,8 @@ function finalizePackageReference(node, version, options) {
1210
1413
  version,
1211
1414
  branchMode: node.branchMode === "package-release-main" ? "package-release-main" : "package-dev-save",
1212
1415
  remoteUrl: node.remoteUrl,
1213
- devDependencyReferenceMode: options.devDependencyReferenceMode ?? "git-tag",
1416
+ commitSha: headCommit(node.path),
1417
+ devDependencyReferenceMode: options.devDependencyReferenceMode ?? "git-commit",
1214
1418
  gitDependencyProtocol: options.gitDependencyProtocol ?? "preserve-origin"
1215
1419
  });
1216
1420
  node.plannedDependencySpec = reference.spec;
@@ -1222,21 +1426,25 @@ async function finalizeCleanPackageVersion(node, options, state, report, branch)
1222
1426
  return false;
1223
1427
  }
1224
1428
  const head = headCommit(node.path);
1225
- const currentTagState = tagState(node.path, version);
1226
- assertTagStateMatchesHead(node, version, currentTagState, head);
1429
+ const reference = finalizePackageReference(node, version, options);
1430
+ const currentTagState = reference.tagName ? tagState(node.path, reference.tagName) : null;
1431
+ if (reference.tagName && currentTagState) {
1432
+ assertTagStateMatchesHead(node, reference.tagName, currentTagState, head);
1433
+ }
1227
1434
  const remoteBranchExists2 = remoteBranchExistsSafe(node.path, branch);
1228
- const finalizedRemotely = currentTagState.localCommit === head && currentTagState.remoteCommit === head && remoteBranchExists2;
1435
+ const remoteBranchCommit = remoteBranchCommitSafe(node.path, branch);
1436
+ const finalizedRemotely = remoteBranchExists2 && remoteBranchCommit === head && (!reference.tagName || currentTagState?.localCommit === head && currentTagState?.remoteCommit === head);
1229
1437
  report.version = version;
1230
- report.tagName = version;
1438
+ report.tagName = reference.tagName;
1231
1439
  report.commitSha = head;
1232
- report.dependencySpec = finalizePackageReference(node, version, options).spec;
1440
+ report.dependencySpec = reference.spec;
1233
1441
  state.finalizedVersions.set(node.name, version);
1234
- state.finalizedReferences.set(node.name, finalizePackageReference(node, version, options));
1442
+ state.finalizedReferences.set(node.name, reference);
1235
1443
  state.finalizedCommits.set(node.relativePath, head);
1236
1444
  if (finalizedRemotely) {
1237
1445
  report.pushed = true;
1238
1446
  report.skippedReason = "already-finalized";
1239
- report.publishWait = { recoveredPartialSave: true, remoteBranchExisted: true, tagAlreadyPushed: true };
1447
+ report.publishWait = { recoveredPartialSave: true, remoteBranchExisted: true, tagAlreadyPushed: Boolean(reference.tagName) };
1240
1448
  emitProgress(options, node, "finalize", `Using existing finalized package version ${version}.`);
1241
1449
  return true;
1242
1450
  }
@@ -1246,36 +1454,24 @@ async function finalizeCleanPackageVersion(node, options, state, report, branch)
1246
1454
  report.lockfileValidation = await validateRepositoryLockfile(node, options);
1247
1455
  }
1248
1456
  const rebase = pullRebaseFromOrigin(node, options, branch);
1249
- if (currentTagState.localCommit === head && localTreeseedTagWasCreatedByThisRun(node, version, options.workflowRunId)) {
1250
- emitProgress(options, node, "verify", `Reusing verification from interrupted tag ${version}.`);
1251
- report.verification = {
1252
- mode: options.verifyMode ?? "action-first",
1253
- status: "skipped",
1254
- primary: null,
1255
- fallbackUsed: false,
1256
- error: "verified-before-interruption"
1257
- };
1258
- report.verified = true;
1259
- } else {
1260
- ensureRemoteAccessBeforeVerification(node, options, state);
1261
- report.verification = await runRepoVerification(node, options, options.verifyMode ?? "action-first");
1262
- report.verified = report.verification.status === "passed";
1263
- }
1264
- const tagMessage = ensurePackageTagReady(node, options, version, branch, options.workflowRunId);
1265
- report.devTagMetadata = tagMessage?.includes("treeseed-dev-tag: true") ? tagMessage : null;
1266
- const reference = finalizePackageReference(node, version, options);
1267
- const push = pushCurrentBranch(node, options, branch, version);
1268
- await runGitDependencySmoke(node, options, reference);
1457
+ ensureRemoteAccessBeforeVerification(node, options, state);
1458
+ report.verification = await runRepoVerification(node, options, options.verifyMode ?? "action-first");
1459
+ report.verified = report.verification.status === "passed";
1460
+ const tagMessage = reference.tagName ? ensurePackageTagReady(node, options, reference.tagName, branch, options.workflowRunId) : null;
1461
+ void tagMessage;
1269
1462
  report.dependencySpec = reference.spec;
1270
- report.pushed = push.pushed;
1271
1463
  report.skippedReason = "finalized-partial-save";
1272
1464
  report.commitSha = headCommit(node.path);
1273
1465
  state.finalizedCommits.set(node.relativePath, report.commitSha);
1274
- report.publishWait = {
1275
- ...rebase,
1276
- ...push,
1277
- recoveredPartialSave: true
1278
- };
1466
+ await finishRepositorySavePublish(node, options, state, report, {
1467
+ branch,
1468
+ rebase: {
1469
+ ...rebase,
1470
+ recoveredPartialSave: true
1471
+ },
1472
+ reference,
1473
+ tagName: reference.tagName
1474
+ });
1279
1475
  return true;
1280
1476
  }
1281
1477
  function branchModeLabel(branchMode) {
@@ -1308,8 +1504,8 @@ function repoPlanCommands(node, options, plannedVersion, plannedDependencySpec,
1308
1504
  const rootWorkspaceInstall = node.path === options.root && Array.isArray(packageJson?.workspaces);
1309
1505
  if (node.kind === "package" && plannedVersion) {
1310
1506
  commands.push(`update package.json version to ${plannedVersion}`);
1311
- commands.push("npm install --workspaces=false # explicitly refresh changed git-tag dependencies with --force; retry up to 5 times with 60s delay");
1312
- } else if (node.kind === "project" && dependencyUpdates.length > 0 && hasNpmLockfile(node.path)) {
1507
+ commands.push("npm install --workspaces=false # explicitly refresh changed git commit dependencies with --force; retry up to 5 times with 60s delay");
1508
+ } else if (node.kind === "project" && (dependencyUpdates.length > 0 || rootWorkspaceInstall && node.submoduleDependencies.length > 0) && hasNpmLockfile(node.path)) {
1313
1509
  commands.push(rootWorkspaceInstall ? "npm install --package-lock-only --ignore-scripts # refresh root workspace lockfile without installing git dependencies" : "npm install --workspaces=false # refresh project lockfile after internal dependency updates");
1314
1510
  }
1315
1511
  if (hasNpmLockfile(node.path) && (node.kind === "project" || plannedVersion || dependencyUpdates.length > 0 || node.submoduleDependencies.length > 0)) {
@@ -1341,11 +1537,14 @@ function repoPlanCommands(node, options, plannedVersion, plannedDependencySpec,
1341
1537
  commands.push("skip verification # project repository has no Treeseed verify script");
1342
1538
  }
1343
1539
  if (node.kind === "package") {
1344
- if (plannedVersion) {
1345
- commands.push(`git tag -a ${plannedVersion} -m <${plannedVersion.includes("-dev.") ? "dev metadata" : "release"}>`);
1540
+ const plansTag = plannedVersion && node.branchMode === "package-release-main";
1541
+ if (plannedVersion && plansTag) {
1542
+ commands.push(`git tag -a ${plannedVersion} -m <release>`);
1346
1543
  commands.push(remoteExists ? `git push origin ${branch} ${plannedVersion}` : `git push -u origin ${branch} ${plannedVersion}`);
1544
+ } else if (plannedVersion) {
1545
+ commands.push(remoteExists ? `git push origin ${branch}` : `git push -u origin ${branch}`);
1347
1546
  if (plannedDependencySpec && node.branchMode === "package-dev-save") {
1348
- commands.push(`git ls-remote --exit-code --tags origin refs/tags/${plannedVersion} # validate dependency tag reachability`);
1547
+ commands.push(`npm install ${node.name}@${plannedDependencySpec} --package-lock-only --ignore-scripts --force # validate dependency commit reachability`);
1349
1548
  }
1350
1549
  } else {
1351
1550
  commands.push(remoteExists ? `git push origin ${branch}` : `git push -u origin ${branch}`);
@@ -1388,7 +1587,8 @@ function planRepositorySave(options) {
1388
1587
  version: plannedVersion,
1389
1588
  branchMode: node.branchMode === "package-release-main" ? "package-release-main" : "package-dev-save",
1390
1589
  remoteUrl: node.remoteUrl,
1391
- devDependencyReferenceMode: options.devDependencyReferenceMode ?? "git-tag",
1590
+ commitSha: headCommitOrPlanPlaceholder(node.path),
1591
+ devDependencyReferenceMode: options.devDependencyReferenceMode ?? "git-commit",
1392
1592
  gitDependencyProtocol: options.gitDependencyProtocol ?? "preserve-origin"
1393
1593
  });
1394
1594
  plannedDependencySpec = reference.spec;
@@ -1400,7 +1600,7 @@ function planRepositorySave(options) {
1400
1600
  const notes = [
1401
1601
  `${branchModeLabel(node.branchMode)} on top-level ${options.branch}`,
1402
1602
  ...current && current !== branch ? [`current branch ${current} will be switched to ${branch}`] : [],
1403
- ...node.kind === "package" && plannedVersion?.includes("-dev.") ? ["dev Git tag only; publish workflows reject prerelease/dev tags"] : []
1603
+ ...node.kind === "package" && plannedVersion?.includes("-dev.") ? ["development and staging dependency refs use the package commit SHA; no Git tag is created"] : []
1404
1604
  ];
1405
1605
  const repoPlan = {
1406
1606
  id: node.id,
@@ -1417,7 +1617,7 @@ function planRepositorySave(options) {
1417
1617
  submoduleDependencies: node.submoduleDependencies,
1418
1618
  currentVersion,
1419
1619
  plannedVersion,
1420
- plannedTag: plannedVersion,
1620
+ plannedTag: plannedReferences.get(node.name)?.tagName ?? null,
1421
1621
  plannedDependencySpec,
1422
1622
  remoteUrl: node.remoteUrl,
1423
1623
  commands: repoPlanCommands(node, options, plannedVersion, plannedDependencySpec, dependencyUpdates),
@@ -1445,7 +1645,7 @@ function planRepositorySave(options) {
1445
1645
  mode,
1446
1646
  branch: options.branch,
1447
1647
  scope,
1448
- devDependencyReferenceMode: options.devDependencyReferenceMode ?? "git-tag",
1648
+ devDependencyReferenceMode: options.devDependencyReferenceMode ?? "git-commit",
1449
1649
  gitDependencyProtocol: options.gitDependencyProtocol ?? "preserve-origin",
1450
1650
  verifyMode: options.verifyMode ?? "action-first",
1451
1651
  commitMessageMode: options.commitMessageMode ?? "auto",
@@ -1503,9 +1703,11 @@ async function saveOneRepository(node, options, state) {
1503
1703
  report.branch = node.branch;
1504
1704
  refreshRepositoryNodePackageMetadata(node);
1505
1705
  ensureWritableRemote(node, options);
1506
- const dependencyUpdates = updateDependencyReferences(node, state.finalizedReferences);
1706
+ const dependencyUpdates = isRootWorkspaceRepository(node, options) ? [] : updateDependencyReferences(node, state.finalizedReferences);
1507
1707
  const dependencyChanged = dependencyUpdates.length > 0;
1508
- const gitDependencyRefreshSpecs = dependencyUpdates.map((update) => state.finalizedReferences.get(update.packageName)).filter((reference) => Boolean(reference) && reference.mode === "dev-git-tag").map((reference) => `${reference.packageName}@${reference.installSpec ?? reference.spec}`);
1708
+ const gitDependencyRefreshReferences = dependencyUpdates.map((update) => state.finalizedReferences.get(update.packageName)).filter((reference) => Boolean(reference) && reference.mode === "dev-git-commit");
1709
+ const lockfileGitDependenciesSynced = syncDirectGitDependencyLockfileEntries(node, options, gitDependencyRefreshReferences);
1710
+ const gitDependencyRefreshSpecs = lockfileGitDependenciesSynced ? [] : gitDependencyRefreshReferences.map((reference) => `${reference.packageName}@${reference.installSpec ?? reference.spec}`);
1509
1711
  const submodulePointers = collectSubmodulePointerChanges(node, state.finalizedCommits);
1510
1712
  const submodulesChanged = submodulePointers.length > 0;
1511
1713
  const packageHasMeaningfulChanges = hasMeaningfulChanges(node.path);
@@ -1523,18 +1725,18 @@ async function saveOneRepository(node, options, state) {
1523
1725
  applyPackageVersion(node, plannedVersion);
1524
1726
  }
1525
1727
  node.plannedVersion = plannedVersion;
1526
- node.plannedTag = plannedVersion;
1527
1728
  report.version = plannedVersion;
1528
- report.tagName = plannedVersion;
1529
1729
  if (!selection.reused) {
1530
1730
  emitProgress(options, node, "version", `Planned ${plannedVersion}.`);
1531
1731
  }
1532
1732
  const reference = finalizePackageReference(node, plannedVersion, options);
1733
+ node.plannedTag = reference.tagName;
1734
+ report.tagName = reference.tagName;
1533
1735
  report.dependencySpec = reference.spec;
1534
1736
  report.install = await runNpmInstallWithRetry(node, options, gitDependencyRefreshSpecs);
1535
1737
  } else if (node.kind === "package") {
1536
1738
  report.version = String(node.packageJson?.version ?? report.version ?? "");
1537
- } else if (node.kind === "project" && dependencyChanged && hasNpmLockfile(node.path)) {
1739
+ } else if (node.kind === "project" && (dependencyChanged || node.path === options.root && submodulesChanged) && hasNpmLockfile(node.path)) {
1538
1740
  report.install = await runNpmInstallWithRetry(node, options, gitDependencyRefreshSpecs);
1539
1741
  }
1540
1742
  if (hasNpmLockfile(node.path) && (node.kind === "project" || packageNeedsVersion || dependencyChanged || submodulesChanged)) {
@@ -1559,12 +1761,7 @@ async function saveOneRepository(node, options, state) {
1559
1761
  }
1560
1762
  if (node.kind === "project" || node.kind === "package" && !canManagePackageJsonVersion(node)) {
1561
1763
  const rebase2 = pullRebaseFromOrigin(node, options, branch);
1562
- const push = pushCurrentBranch(node, options, branch);
1563
- report.pushed = push.pushed;
1564
- report.publishWait = {
1565
- ...rebase2,
1566
- ...push
1567
- };
1764
+ await finishRepositorySavePublish(node, options, state, report, { branch, rebase: rebase2 });
1568
1765
  report.commitSha = headCommit(node.path);
1569
1766
  }
1570
1767
  state.finalizedCommits.set(node.relativePath, report.commitSha);
@@ -1584,12 +1781,7 @@ async function saveOneRepository(node, options, state) {
1584
1781
  }
1585
1782
  if (node.kind === "project" || node.kind === "package" && !canManagePackageJsonVersion(node)) {
1586
1783
  const rebase2 = pullRebaseFromOrigin(node, options, branch);
1587
- const push = pushCurrentBranch(node, options, branch);
1588
- report.pushed = push.pushed;
1589
- report.publishWait = {
1590
- ...rebase2,
1591
- ...push
1592
- };
1784
+ await finishRepositorySavePublish(node, options, state, report, { branch, rebase: rebase2 });
1593
1785
  report.commitSha = headCommit(node.path);
1594
1786
  }
1595
1787
  state.finalizedCommits.set(node.relativePath, report.commitSha);
@@ -1629,12 +1821,7 @@ async function saveOneRepository(node, options, state) {
1629
1821
  }
1630
1822
  if (node.kind === "project" || node.kind === "package" && !canManagePackageJsonVersion(node)) {
1631
1823
  const rebase2 = pullRebaseFromOrigin(node, options, branch);
1632
- const push = pushCurrentBranch(node, options, branch);
1633
- report.pushed = push.pushed;
1634
- report.publishWait = {
1635
- ...rebase2,
1636
- ...push
1637
- };
1824
+ await finishRepositorySavePublish(node, options, state, report, { branch, rebase: rebase2 });
1638
1825
  report.commitSha = headCommit(node.path);
1639
1826
  }
1640
1827
  state.finalizedCommits.set(node.relativePath, report.commitSha);
@@ -1657,28 +1844,17 @@ async function saveOneRepository(node, options, state) {
1657
1844
  report.verified = report.verification.status === "passed";
1658
1845
  if (canManagePackageJsonVersion(node)) {
1659
1846
  const version = plannedVersion ?? String(readJson(resolve(node.path, "package.json")).version ?? report.version ?? "");
1660
- const tagMessage = ensurePackageTagReady(node, options, version, branch, options.workflowRunId);
1661
- report.tagName = version;
1662
- report.version = version;
1663
- report.devTagMetadata = tagMessage?.includes("treeseed-dev-tag: true") ? tagMessage : null;
1664
1847
  const reference = finalizePackageReference(node, version, options);
1665
- const push = pushCurrentBranch(node, options, branch, version);
1666
- await runGitDependencySmoke(node, options, reference);
1848
+ const tagMessage = reference.tagName ? ensurePackageTagReady(node, options, reference.tagName, branch, options.workflowRunId) : null;
1849
+ void tagMessage;
1850
+ report.tagName = reference.tagName;
1851
+ report.version = version;
1667
1852
  report.dependencySpec = reference.spec;
1668
1853
  state.finalizedVersions.set(node.name, version);
1669
1854
  state.finalizedReferences.set(node.name, reference);
1670
- report.pushed = push.pushed;
1671
- report.publishWait = {
1672
- ...rebase,
1673
- ...push
1674
- };
1855
+ await finishRepositorySavePublish(node, options, state, report, { branch, rebase, reference, tagName: reference.tagName });
1675
1856
  } else {
1676
- const push = pushCurrentBranch(node, options, branch);
1677
- report.pushed = push.pushed;
1678
- report.publishWait = {
1679
- ...rebase,
1680
- ...push
1681
- };
1857
+ await finishRepositorySavePublish(node, options, state, report, { branch, rebase });
1682
1858
  }
1683
1859
  report.commitSha = headCommit(node.path);
1684
1860
  report.skippedReason = null;
@@ -1703,10 +1879,12 @@ async function runRepositorySaveOrchestrator(options) {
1703
1879
  finalizedCommits: /* @__PURE__ */ new Map(),
1704
1880
  reports: new Map(nodes.map((node) => [node.id, createReport(node)])),
1705
1881
  remoteAccessChecked: /* @__PURE__ */ new Set(),
1706
- workflowGates: []
1882
+ workflowGates: [],
1883
+ deferredPushes: []
1707
1884
  };
1885
+ const concurrency = repositorySaveConcurrency(options);
1708
1886
  for (const [index, wave] of waves.entries()) {
1709
- await runLimited(wave, 3, async (node) => {
1887
+ await runLimited(wave, concurrency, async (node) => {
1710
1888
  try {
1711
1889
  await saveOneRepository(node, options, state);
1712
1890
  } catch (error) {
@@ -1767,6 +1945,7 @@ async function runRepositorySaveOrchestrator(options) {
1767
1945
  state.workflowGates.push(...waveGates);
1768
1946
  }
1769
1947
  }
1948
+ await publishDeferredRepositoryPushes(options, state);
1770
1949
  const rootNode = nodes.find((node) => node.id === ".") ?? allNodes.find((node) => node.id === ".");
1771
1950
  const rootReport = rootNode ? state.reports.get(rootNode.id) ?? createReport(rootNode) : createReport({
1772
1951
  id: ".",