gate-evm-tools 1.0.31 → 1.2.1

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 (349) hide show
  1. package/README.md +34 -20
  2. package/bin/cli.js +3 -0
  3. package/bin/delivery.cjs +8 -7
  4. package/dist/commands/check.d.ts.map +1 -1
  5. package/dist/commands/check.js +26 -2
  6. package/dist/commands/check.js.map +1 -1
  7. package/dist/commands/plan/index.d.ts.map +1 -1
  8. package/dist/commands/plan/index.js +1 -1
  9. package/dist/commands/plan/index.js.map +1 -1
  10. package/dist/core/preparation/batch.d.ts +26 -0
  11. package/dist/core/preparation/batch.d.ts.map +1 -0
  12. package/dist/core/preparation/batch.js +72 -0
  13. package/dist/core/preparation/batch.js.map +1 -0
  14. package/dist/core/preparation/evm.d.ts +23 -4
  15. package/dist/core/preparation/evm.d.ts.map +1 -1
  16. package/dist/core/preparation/evm.js +19 -3
  17. package/dist/core/preparation/evm.js.map +1 -1
  18. package/dist/core/preparation/evmManifestSync.d.ts +5 -0
  19. package/dist/core/preparation/evmManifestSync.d.ts.map +1 -1
  20. package/dist/core/preparation/evmManifestSync.js +15 -7
  21. package/dist/core/preparation/evmManifestSync.js.map +1 -1
  22. package/dist/core/preparation/index.d.ts +2 -2
  23. package/dist/core/preparation/index.d.ts.map +1 -1
  24. package/dist/core/preparation/manifest.d.ts +2 -0
  25. package/dist/core/preparation/manifest.d.ts.map +1 -1
  26. package/dist/core/preparation/manifest.js +2 -2
  27. package/dist/core/preparation/manifest.js.map +1 -1
  28. package/dist/core/preparation/normalize.d.ts.map +1 -1
  29. package/dist/core/preparation/normalize.js +53 -11
  30. package/dist/core/preparation/normalize.js.map +1 -1
  31. package/dist/core/preparation/transparent.d.ts +23 -0
  32. package/dist/core/preparation/transparent.d.ts.map +1 -0
  33. package/dist/core/preparation/transparent.js +103 -0
  34. package/dist/core/preparation/transparent.js.map +1 -0
  35. package/dist/core/preparation/types.d.ts +47 -5
  36. package/dist/core/preparation/types.d.ts.map +1 -1
  37. package/dist/core/preparation/zksync.d.ts.map +1 -1
  38. package/dist/core/preparation/zksync.js +2 -0
  39. package/dist/core/preparation/zksync.js.map +1 -1
  40. package/dist/custody/credential.d.ts.map +1 -1
  41. package/dist/custody/credential.js +1 -6
  42. package/dist/custody/credential.js.map +1 -1
  43. package/dist/deployment-evm/index.d.ts +4 -0
  44. package/dist/deployment-evm/index.d.ts.map +1 -0
  45. package/dist/deployment-evm/index.js +3 -0
  46. package/dist/deployment-evm/index.js.map +1 -0
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +4 -0
  49. package/dist/index.js.map +1 -1
  50. package/dist/sync/index.d.ts.map +1 -1
  51. package/dist/sync/index.js +5 -0
  52. package/dist/sync/index.js.map +1 -1
  53. package/dist/types.d.ts +3 -0
  54. package/dist/types.d.ts.map +1 -1
  55. package/dist/workflow/index.d.ts +4 -1
  56. package/dist/workflow/index.d.ts.map +1 -1
  57. package/dist/workflow/index.js +2 -0
  58. package/dist/workflow/index.js.map +1 -1
  59. package/dist-cjs/core/preparation/batch.js +76 -0
  60. package/dist-cjs/core/preparation/batch.js.map +1 -0
  61. package/dist-cjs/core/preparation/evm.js +25 -7
  62. package/dist-cjs/core/preparation/evm.js.map +1 -1
  63. package/dist-cjs/core/preparation/evmManifestSync.js +15 -7
  64. package/dist-cjs/core/preparation/evmManifestSync.js.map +1 -1
  65. package/dist-cjs/core/preparation/manifest.js +2 -2
  66. package/dist-cjs/core/preparation/manifest.js.map +1 -1
  67. package/dist-cjs/core/preparation/normalize.js +53 -11
  68. package/dist-cjs/core/preparation/normalize.js.map +1 -1
  69. package/dist-cjs/core/preparation/transparent.js +110 -0
  70. package/dist-cjs/core/preparation/transparent.js.map +1 -0
  71. package/dist-cjs/core/preparation/zksync.js +2 -0
  72. package/dist-cjs/core/preparation/zksync.js.map +1 -1
  73. package/dist-cjs/custody/credential.js +1 -6
  74. package/dist-cjs/custody/credential.js.map +1 -1
  75. package/dist-cjs/deployment-evm/index.js +10 -0
  76. package/dist-cjs/deployment-evm/index.js.map +1 -0
  77. package/dist-cjs/sync/index.js +5 -0
  78. package/dist-cjs/sync/index.js.map +1 -1
  79. package/dist-cjs/workflow/index.js +11 -1
  80. package/dist-cjs/workflow/index.js.map +1 -1
  81. package/dist-runtime/config/hardhatAdapters.js +2 -1
  82. package/dist-runtime/config/hardhatAdapters.js.map +1 -1
  83. package/dist-runtime/delivery/aggregate-bootstrap.js +3 -1
  84. package/dist-runtime/delivery/aggregate-bootstrap.js.map +1 -1
  85. package/dist-runtime/delivery/aggregate-channel.js +7 -3
  86. package/dist-runtime/delivery/aggregate-channel.js.map +1 -1
  87. package/dist-runtime/delivery/aggregate-diagnostics.d.ts +14 -0
  88. package/dist-runtime/delivery/aggregate-diagnostics.js +73 -0
  89. package/dist-runtime/delivery/aggregate-diagnostics.js.map +1 -0
  90. package/dist-runtime/delivery/aggregate-inputs.d.ts +13 -9
  91. package/dist-runtime/delivery/aggregate-source.js +11 -3
  92. package/dist-runtime/delivery/aggregate-source.js.map +1 -1
  93. package/dist-runtime/delivery/aggregate-worker.js +12 -4
  94. package/dist-runtime/delivery/aggregate-worker.js.map +1 -1
  95. package/dist-runtime/delivery/aggregate.js +2 -2
  96. package/dist-runtime/delivery/aggregate.js.map +1 -1
  97. package/dist-runtime/delivery/business-extension.d.ts +10 -0
  98. package/dist-runtime/delivery/business-extension.js +38 -0
  99. package/dist-runtime/delivery/business-extension.js.map +1 -0
  100. package/dist-runtime/delivery/calldata-archive.d.ts +18 -0
  101. package/dist-runtime/delivery/calldata-archive.js +31 -0
  102. package/dist-runtime/delivery/calldata-archive.js.map +1 -0
  103. package/dist-runtime/delivery/calldata-details.d.ts +47 -0
  104. package/dist-runtime/delivery/calldata-details.js +94 -0
  105. package/dist-runtime/delivery/calldata-details.js.map +1 -0
  106. package/dist-runtime/delivery/calldata-format.d.ts +4 -0
  107. package/dist-runtime/delivery/calldata-format.js +17 -0
  108. package/dist-runtime/delivery/calldata-format.js.map +1 -0
  109. package/dist-runtime/delivery/calldata-preparations.d.ts +13 -0
  110. package/dist-runtime/delivery/calldata-preparations.js +85 -0
  111. package/dist-runtime/delivery/calldata-preparations.js.map +1 -0
  112. package/dist-runtime/delivery/calldata-review.d.ts +44 -0
  113. package/dist-runtime/delivery/calldata-review.js +131 -0
  114. package/dist-runtime/delivery/calldata-review.js.map +1 -0
  115. package/dist-runtime/delivery/codec-pin.d.ts +2 -2
  116. package/dist-runtime/delivery/codec-pin.js +4 -4
  117. package/dist-runtime/delivery/codec-pin.js.map +1 -1
  118. package/dist-runtime/delivery/compiler-files.js +3 -1
  119. package/dist-runtime/delivery/compiler-files.js.map +1 -1
  120. package/dist-runtime/delivery/compiler-pins.js +1 -1
  121. package/dist-runtime/delivery/compiler.js +17 -16
  122. package/dist-runtime/delivery/compiler.js.map +1 -1
  123. package/dist-runtime/delivery/config.d.ts +1 -1
  124. package/dist-runtime/delivery/config.js +27 -2
  125. package/dist-runtime/delivery/config.js.map +1 -1
  126. package/dist-runtime/delivery/configuration-definition.d.ts +9 -0
  127. package/dist-runtime/delivery/configuration-definition.js +33 -6
  128. package/dist-runtime/delivery/configuration-definition.js.map +1 -1
  129. package/dist-runtime/delivery/configuration.js +7 -4
  130. package/dist-runtime/delivery/configuration.js.map +1 -1
  131. package/dist-runtime/delivery/contract-source.d.ts +14 -0
  132. package/dist-runtime/delivery/contract-source.js +138 -0
  133. package/dist-runtime/delivery/contract-source.js.map +1 -0
  134. package/dist-runtime/delivery/custom-format.js +51 -24
  135. package/dist-runtime/delivery/custom-format.js.map +1 -1
  136. package/dist-runtime/delivery/development-inputs.d.ts +14 -0
  137. package/dist-runtime/delivery/development-inputs.js +76 -0
  138. package/dist-runtime/delivery/development-inputs.js.map +1 -0
  139. package/dist-runtime/delivery/development.d.ts +3 -1
  140. package/dist-runtime/delivery/development.js +24 -10
  141. package/dist-runtime/delivery/development.js.map +1 -1
  142. package/dist-runtime/delivery/eoa.d.ts +1 -0
  143. package/dist-runtime/delivery/execution-identity.d.ts +15 -0
  144. package/dist-runtime/delivery/execution-identity.js +33 -0
  145. package/dist-runtime/delivery/execution-identity.js.map +1 -0
  146. package/dist-runtime/delivery/existing-code.js +14 -6
  147. package/dist-runtime/delivery/existing-code.js.map +1 -1
  148. package/dist-runtime/delivery/history-package.d.ts +2 -0
  149. package/dist-runtime/delivery/history-package.js +70 -0
  150. package/dist-runtime/delivery/history-package.js.map +1 -0
  151. package/dist-runtime/delivery/history-registration.d.ts +1 -1
  152. package/dist-runtime/delivery/inputs.js +22 -15
  153. package/dist-runtime/delivery/inputs.js.map +1 -1
  154. package/dist-runtime/delivery/journal.js +18 -10
  155. package/dist-runtime/delivery/journal.js.map +1 -1
  156. package/dist-runtime/delivery/parameter-defaults.d.ts +10 -0
  157. package/dist-runtime/delivery/parameter-defaults.js +86 -0
  158. package/dist-runtime/delivery/parameter-defaults.js.map +1 -0
  159. package/dist-runtime/delivery/parameters.d.ts +2 -0
  160. package/dist-runtime/delivery/parameters.js +22 -0
  161. package/dist-runtime/delivery/parameters.js.map +1 -1
  162. package/dist-runtime/delivery/planning.d.ts +4 -1
  163. package/dist-runtime/delivery/planning.js +19 -3
  164. package/dist-runtime/delivery/planning.js.map +1 -1
  165. package/dist-runtime/delivery/preparation.js +43 -23
  166. package/dist-runtime/delivery/preparation.js.map +1 -1
  167. package/dist-runtime/delivery/production-environment.js +2 -1
  168. package/dist-runtime/delivery/production-environment.js.map +1 -1
  169. package/dist-runtime/delivery/production-finalization.js +23 -9
  170. package/dist-runtime/delivery/production-finalization.js.map +1 -1
  171. package/dist-runtime/delivery/production-intent.d.ts +2 -0
  172. package/dist-runtime/delivery/production-intent.js +16 -0
  173. package/dist-runtime/delivery/production-intent.js.map +1 -0
  174. package/dist-runtime/delivery/production.d.ts +129 -8
  175. package/dist-runtime/delivery/production.js +60 -11
  176. package/dist-runtime/delivery/production.js.map +1 -1
  177. package/dist-runtime/delivery/project-files.d.ts +3 -3
  178. package/dist-runtime/delivery/project-files.js +19 -14
  179. package/dist-runtime/delivery/project-files.js.map +1 -1
  180. package/dist-runtime/delivery/project-rpc.d.ts +19 -0
  181. package/dist-runtime/delivery/project-rpc.js +138 -0
  182. package/dist-runtime/delivery/project-rpc.js.map +1 -0
  183. package/dist-runtime/delivery/project.d.ts +3 -1
  184. package/dist-runtime/delivery/project.js +21 -8
  185. package/dist-runtime/delivery/project.js.map +1 -1
  186. package/dist-runtime/delivery/public-calldata.d.ts +25 -0
  187. package/dist-runtime/delivery/public-calldata.js +97 -0
  188. package/dist-runtime/delivery/public-calldata.js.map +1 -0
  189. package/dist-runtime/delivery/release-graph.d.ts +7 -3
  190. package/dist-runtime/delivery/release-graph.js +58 -25
  191. package/dist-runtime/delivery/release-graph.js.map +1 -1
  192. package/dist-runtime/delivery/release-history-capture.js +22 -26
  193. package/dist-runtime/delivery/release-history-capture.js.map +1 -1
  194. package/dist-runtime/delivery/release-history.d.ts +3 -2
  195. package/dist-runtime/delivery/release-history.js +97 -50
  196. package/dist-runtime/delivery/release-history.js.map +1 -1
  197. package/dist-runtime/delivery/release-inputs.d.ts +33 -0
  198. package/dist-runtime/delivery/release-inputs.js +129 -0
  199. package/dist-runtime/delivery/release-inputs.js.map +1 -0
  200. package/dist-runtime/delivery/release.d.ts +38 -14
  201. package/dist-runtime/delivery/release.js +81 -29
  202. package/dist-runtime/delivery/release.js.map +1 -1
  203. package/dist-runtime/delivery/safe.d.ts +1 -0
  204. package/dist-runtime/delivery/safe.js +13 -2
  205. package/dist-runtime/delivery/safe.js.map +1 -1
  206. package/dist-runtime/delivery/same-fork-baseline.d.ts +1 -1
  207. package/dist-runtime/delivery/same-fork-baseline.js +5 -4
  208. package/dist-runtime/delivery/same-fork-baseline.js.map +1 -1
  209. package/dist-runtime/delivery/setup.d.ts +1 -1
  210. package/dist-runtime/delivery/setup.js +21 -6
  211. package/dist-runtime/delivery/setup.js.map +1 -1
  212. package/dist-runtime/delivery/source.d.ts +1 -0
  213. package/dist-runtime/delivery/source.js +12 -10
  214. package/dist-runtime/delivery/source.js.map +1 -1
  215. package/dist-runtime/delivery/task-identity.d.ts +23 -0
  216. package/dist-runtime/delivery/task-identity.js +109 -0
  217. package/dist-runtime/delivery/task-identity.js.map +1 -0
  218. package/dist-runtime/delivery/toolchain.d.ts +3 -0
  219. package/dist-runtime/delivery/toolchain.js +52 -0
  220. package/dist-runtime/delivery/toolchain.js.map +1 -0
  221. package/dist-runtime/delivery/validation.js +7 -2
  222. package/dist-runtime/delivery/validation.js.map +1 -1
  223. package/dist-runtime/runtime-identity.json +2 -2
  224. package/dist-runtime/vendor/plan-codec/index.cjs +97 -20
  225. package/dist-runtime/vendor/plan-codec/index.d.cts +6 -0
  226. package/dist-runtime/vendor/plan-codec/provenance.json +9 -8
  227. package/dist-runtime/workflow/lib/calls.js +1 -0
  228. package/dist-runtime/workflow/lib/calls.js.map +1 -1
  229. package/dist-runtime/workflow/lib/checkCodeRunner.js +7 -4
  230. package/dist-runtime/workflow/lib/checkCodeRunner.js.map +1 -1
  231. package/dist-runtime/workflow/lib/context.d.ts +1 -0
  232. package/dist-runtime/workflow/lib/create2.d.ts +4 -26
  233. package/dist-runtime/workflow/lib/create2.js +2 -67
  234. package/dist-runtime/workflow/lib/create2.js.map +1 -1
  235. package/dist-runtime/workflow/lib/deploymentInfo.d.ts +2 -0
  236. package/dist-runtime/workflow/lib/deploymentInfo.js +6 -0
  237. package/dist-runtime/workflow/lib/deploymentInfo.js.map +1 -1
  238. package/dist-runtime/workflow/lib/deploymentRecords.d.ts +2 -0
  239. package/dist-runtime/workflow/lib/deploymentRecords.js +1 -1
  240. package/dist-runtime/workflow/lib/deploymentRecords.js.map +1 -1
  241. package/dist-runtime/workflow/lib/externalExecutionScanner.js +2 -1
  242. package/dist-runtime/workflow/lib/externalExecutionScanner.js.map +1 -1
  243. package/dist-runtime/workflow/lib/gateTool.js +2 -2
  244. package/dist-runtime/workflow/lib/gateTool.js.map +1 -1
  245. package/dist-runtime/workflow/lib/gateToolSync.d.ts +3 -0
  246. package/dist-runtime/workflow/lib/gateToolSync.js +5 -0
  247. package/dist-runtime/workflow/lib/gateToolSync.js.map +1 -1
  248. package/dist-runtime/workflow/lib/parameters.js +5 -0
  249. package/dist-runtime/workflow/lib/parameters.js.map +1 -1
  250. package/dist-runtime/workflow/lib/proxy.d.ts +1 -0
  251. package/dist-runtime/workflow/lib/proxy.js.map +1 -1
  252. package/dist-runtime/workflow/run.js +1 -3
  253. package/dist-runtime/workflow/run.js.map +1 -1
  254. package/dist-runtime/workflow/steps/deploy.js +53 -0
  255. package/dist-runtime/workflow/steps/deploy.js.map +1 -1
  256. package/dist-runtime/workflow/steps/upgrade.js +24 -10
  257. package/dist-runtime/workflow/steps/upgrade.js.map +1 -1
  258. package/docs/compiler-qualification.md +8 -2
  259. package/docs/delivery-aggregate.md +2 -0
  260. package/docs/delivery-calldata.md +27 -0
  261. package/docs/delivery-development.md +6 -0
  262. package/docs/delivery-execution-store.md +1 -1
  263. package/docs/delivery-inputs.md +55 -6
  264. package/docs/delivery-parameters.md +1 -1
  265. package/docs/delivery-release.md +77 -7
  266. package/docs/delivery-safe.md +7 -4
  267. package/docs/delivery-setup.md +72 -20
  268. package/docs/delivery-source.md +8 -8
  269. package/docs/direct-package-acceptance.md +2 -0
  270. package/docs/openzeppelin-acceptance.md +86 -0
  271. package/docs/openzeppelin-baseline.json +27 -0
  272. package/docs/openzeppelin-integration.md +115 -0
  273. package/docs/plans/2026-10-28-openzeppelin-toolkit-consolidation.md +396 -0
  274. package/docs/plans/2026-11-02-transparent-proxy-delivery.md +78 -0
  275. package/docs/superpowers/plans/2026-08-17-custody-hardhat-signers.md +1 -1
  276. package/docs/workflow-reference.md +12 -4
  277. package/docs/workflow-runtime.md +6 -0
  278. package/package.json +19 -5
  279. package/runtime/config/hardhatAdapters.ts +2 -1
  280. package/runtime/delivery/aggregate-bootstrap.ts +3 -1
  281. package/runtime/delivery/aggregate-channel.ts +6 -3
  282. package/runtime/delivery/aggregate-diagnostics.ts +63 -0
  283. package/runtime/delivery/aggregate-source.ts +6 -2
  284. package/runtime/delivery/aggregate-worker.ts +15 -5
  285. package/runtime/delivery/aggregate.ts +2 -2
  286. package/runtime/delivery/business-extension.ts +33 -0
  287. package/runtime/delivery/calldata-archive.ts +25 -0
  288. package/runtime/delivery/calldata-details.ts +90 -0
  289. package/runtime/delivery/calldata-format.ts +14 -0
  290. package/runtime/delivery/calldata-preparations.ts +76 -0
  291. package/runtime/delivery/calldata-review.ts +126 -0
  292. package/runtime/delivery/codec-pin.ts +3 -3
  293. package/runtime/delivery/compiler-files.ts +3 -1
  294. package/runtime/delivery/compiler-pins.ts +1 -1
  295. package/runtime/delivery/compiler.ts +18 -17
  296. package/runtime/delivery/config.ts +25 -2
  297. package/runtime/delivery/configuration-definition.ts +34 -7
  298. package/runtime/delivery/configuration.ts +8 -5
  299. package/runtime/delivery/contract-source.ts +112 -0
  300. package/runtime/delivery/custom-format.ts +20 -5
  301. package/runtime/delivery/development-inputs.ts +42 -0
  302. package/runtime/delivery/development.ts +14 -11
  303. package/runtime/delivery/execution-identity.ts +32 -0
  304. package/runtime/delivery/existing-code.ts +7 -6
  305. package/runtime/delivery/history-package.ts +50 -0
  306. package/runtime/delivery/inputs.ts +18 -11
  307. package/runtime/delivery/journal.ts +14 -10
  308. package/runtime/delivery/parameter-defaults.ts +75 -0
  309. package/runtime/delivery/parameters.ts +18 -0
  310. package/runtime/delivery/planning.ts +19 -5
  311. package/runtime/delivery/preparation.ts +17 -1
  312. package/runtime/delivery/production-environment.ts +2 -1
  313. package/runtime/delivery/production-finalization.ts +19 -10
  314. package/runtime/delivery/production-intent.ts +14 -0
  315. package/runtime/delivery/production.ts +51 -11
  316. package/runtime/delivery/project-files.ts +16 -11
  317. package/runtime/delivery/project-rpc.ts +116 -0
  318. package/runtime/delivery/project.ts +19 -7
  319. package/runtime/delivery/public-calldata.ts +74 -0
  320. package/runtime/delivery/release-graph.ts +44 -14
  321. package/runtime/delivery/release-history-capture.ts +19 -9
  322. package/runtime/delivery/release-history.ts +76 -22
  323. package/runtime/delivery/release-inputs.ts +107 -0
  324. package/runtime/delivery/release.ts +56 -18
  325. package/runtime/delivery/safe.ts +14 -3
  326. package/runtime/delivery/same-fork-baseline.ts +5 -4
  327. package/runtime/delivery/setup.ts +20 -8
  328. package/runtime/delivery/source.ts +10 -10
  329. package/runtime/delivery/task-identity.ts +85 -0
  330. package/runtime/delivery/toolchain.ts +48 -0
  331. package/runtime/delivery/validation.ts +7 -2
  332. package/runtime/vendor/plan-codec/index.cjs +97 -20
  333. package/runtime/vendor/plan-codec/index.d.cts +6 -0
  334. package/runtime/vendor/plan-codec/provenance.json +9 -8
  335. package/runtime/workflow/lib/calls.ts +1 -0
  336. package/runtime/workflow/lib/checkCodeRunner.ts +7 -3
  337. package/runtime/workflow/lib/context.ts +1 -0
  338. package/runtime/workflow/lib/create2.ts +7 -108
  339. package/runtime/workflow/lib/deploymentInfo.ts +8 -0
  340. package/runtime/workflow/lib/deploymentRecords.ts +3 -1
  341. package/runtime/workflow/lib/externalExecutionScanner.ts +2 -1
  342. package/runtime/workflow/lib/gateTool.ts +2 -2
  343. package/runtime/workflow/lib/gateToolSync.ts +8 -0
  344. package/runtime/workflow/lib/parameters.ts +4 -0
  345. package/runtime/workflow/lib/proxy.ts +1 -0
  346. package/runtime/workflow/run.ts +1 -2
  347. package/runtime/workflow/steps/deploy.ts +42 -0
  348. package/runtime/workflow/steps/upgrade.ts +19 -11
  349. package/bin/workflow.cjs +0 -19
@@ -1,3 +1,5 @@
1
+ import {deploymentPurpose} from './source';
2
+ import {parseCalldataReviews} from './calldata-review';
1
3
  /** Developer-owned production qualification and two-phase, marker-last release publication. */
2
4
  import fs from 'node:fs';
3
5
  import path from 'node:path';
@@ -11,13 +13,16 @@ import {parsePreparationJournal} from './journal';
11
13
  import {expectedDevelopmentAssertions} from './development';
12
14
  import {verifyCapturedForkAudit} from './forkAudit';
13
15
  import {parseCanonicalPlan,projectCanonicalDefinitions} from './source';
14
- import {readReleaseUniverse,currentReleasePrerequisites,readReleaseGraph,sameReleaseData as same,type ReleaseGraphOptions} from './release-graph';
16
+ import {readReleaseUniverse,currentReleasePrerequisites,readReleaseGraph,isDevelopmentAcceptancePrerequisite,sameReleaseData as same,type ReleaseGraphOptions} from './release-graph';
15
17
  import {aggregateInputHash,validateHistoricalDevelopmentFiles,verifyHistoricalDevelopmentChain,type HistoricalDevelopmentFiles} from './release-history';
16
18
  import {atomicDevelopmentWrite,fileBytes,withDevelopmentFileLock,byteHash} from './materialization';
17
19
  import {canonicalJson,deepFreeze,semanticHash,exactObject} from '../workflow/lib/canonicalData';
18
20
  import {strictData} from './data';
19
21
  import {historicalRegistrationFile} from './history-registration';
20
- export {readReleaseGraph} from './release-graph';
22
+ import {captureCommittedContractSource} from './contract-source';
23
+ import {captureReleaseInputs,readReleaseInputSnapshot,restoreReleaseInputs} from './release-inputs';
24
+ export type {ContractSourceIdentity} from './contract-source';
25
+ export {readReleaseGraph,isDevelopmentAcceptancePrerequisite} from './release-graph';
21
26
  export {captureDevelopmentReleaseHistory} from './release-history-capture';
22
27
  export type {HistoricalDevelopmentFiles} from './release-history';
23
28
  type Scope=Omit<ReleaseGraphOptions,'releaseRef'>;
@@ -32,10 +37,11 @@ function taskEvidence(input:Scope&{planKey:string}){
32
37
  if(!row||plan.lanes[row.lane].state!=='enabled'||row.task.status!=='completed'||row.task.result?.kind!=='success'||row.task.adoptedRev!==row.task.rev)throw Error('Prerequisite current task is incomplete or stale');
33
38
  const result=row.task.result,codeRef=result.codeRef??(row.task.scope?.deployment as any)?.sourceCodeRef;
34
39
  if(typeof codeRef!=='string'||!codeRef.trim()||!Array.isArray(result.evidence)||!result.evidence.length)throw Error('Prerequisite requires codeRef and actual report evidence');
35
- const artifacts=result.evidence.map((entry:any)=>{if(!entry||typeof entry.ref!=='string')throw Error('Prerequisite report ref missing');portablePath(entry.ref,'prerequisite artifact');const bytes=readInputBytes(root,entry.ref);if(!bytes.length)throw Error('Empty prerequisite report');return {path:entry.ref,sha256:inputDigest(bytes)};});
36
- for(const expected of row.task.expectedArtifacts??[])if(!artifacts.some(a=>a.path===expected))throw Error('Missing declared prerequisite artifact');
37
- if(new Set(artifacts.map(a=>a.path)).size!==artifacts.length)throw Error('Duplicate prerequisite artifact');
38
- if(row.lane==='audit'&&!artifacts.some(a=>a.path==='audit-reports/security-audit-report.md'))throw Error('Audit prerequisite requires actual security audit report');
40
+ const refs=result.evidence.map((entry:any)=>{if(!entry||typeof entry.ref!=='string')throw Error('Prerequisite report ref missing');return entry.ref as string;});
41
+ if(new Set(refs).size!==refs.length)throw Error('Duplicate prerequisite artifact');
42
+ for(const expected of row.task.expectedArtifacts??[])if(!refs.includes(expected))refs.push(expected);
43
+ const artifacts=refs.map(ref=>{portablePath(ref,'prerequisite artifact');const bytes=readInputBytes(root,ref);if(!bytes.length)throw Error('Empty prerequisite report/artifact');return {path:ref,sha256:inputDigest(bytes)};});
44
+ if(row.lane==='audit'&&!result.evidence.some((entry:any)=>entry.ref==='audit-reports/security-audit-report.md'))throw Error('Audit prerequisite requires actual security audit report');
39
45
  return {root,envelope:{schema:'gate-delivery-prerequisite',version:1,producer:'gate-evm-tools/delivery-release',taskId:plan.taskId,planKey:row.task.planKey,rev:row.task.rev,definitionHash:semanticHash(projectCanonicalDefinitions(text,{roots:[row.task.planKey],mode:'full'}).snapshot),codeRef,artifacts}};
40
46
  }
41
47
  /** Invoke after the corresponding skill has produced its report and completed the current task.
@@ -44,15 +50,17 @@ export function recordDeliveryPrerequisite(input:Scope&{planKey:string}){const {
44
50
  export function validateDeliveryPrerequisite(input:Scope&{planKey:string}){const {root,envelope}=taskEvidence(input),actual=JSON.parse(readInputBytes(root,prerequisitePath(input.taskId,input.planKey)).toString());same(actual,envelope,'Current prerequisite report/artifact binding');return deepFreeze(actual);}
45
51
  function prerequisites(scope:Scope,history:ReturnType<typeof validateHistoricalDevelopmentFiles>){
46
52
  const current=currentReleasePrerequisites(scope),receipts=[];
47
- for(const {task} of current.required){if(['deploy','check-code'].includes(task.step??'')){const d=task.scope?.deployment as any;if(d?.environment!=='dev'||d.targetNetwork!==history.plan.target||d.deploymentId!==history.plan.deploymentId)throw Error('Development prerequisite scope mismatch');if(task.step==='deploy'&&(task.planKey!==history.source.targets[0].request.sourceRef.planKey||task.rev!==history.source.targets[0].request.sourceRef.rev))throw Error('Stale development prerequisite revision');const evidence=task.result?.evidence;if(!Array.isArray(evidence)||!evidence.some((e:any)=>e.ref===scopePath(history,task.step!)))throw Error('Development prerequisite must reference actual acceptance/CheckCode');receipts.push({planKey:task.planKey,rev:task.rev,definitionHash:semanticHash(projectCanonicalDefinitions(current.text,{roots:[task.planKey],mode:'full'}).snapshot),evidenceHash:semanticHash(task.step==='deploy'?history.acceptance:history.acceptance.checkCode)});}
53
+ for(const {task} of current.required){if(isDevelopmentAcceptancePrerequisite(task)){const d=task.scope?.deployment as any;if(d?.environment!=='dev'||d.targetNetwork!==history.plan.target||d.deploymentId!==history.plan.deploymentId)throw Error('Development prerequisite scope mismatch');if(!verificationOnly(task)&&(task.planKey!==history.source.targets[0].request.sourceRef.planKey||task.rev!==history.source.targets[0].request.sourceRef.rev))throw Error('Stale development prerequisite revision');const evidence=task.result?.evidence;if(!Array.isArray(evidence)||!evidence.some((e:any)=>e.ref===scopePath(history,verificationOnly(task))))throw Error('Development prerequisite must reference actual acceptance/CheckCode');receipts.push({planKey:task.planKey,rev:task.rev,definitionHash:semanticHash(projectCanonicalDefinitions(current.text,{roots:[task.planKey],mode:'full'}).snapshot),evidenceHash:semanticHash(verificationOnly(task)?history.acceptance.checkCode:history.acceptance)});}
48
54
  else receipts.push(validateDeliveryPrerequisite({...scope,planKey:task.planKey}));}
49
55
  return receipts;
50
56
  }
51
- function scopePath(history:ReturnType<typeof validateHistoricalDevelopmentFiles>,step:string){return step==='check-code'?history.acceptance.checkCode.rawFile:`.gate-delivery/development/${history.plan.executionId}.acceptance.json`;}
57
+ function verificationOnly(task:any){const actions=task.scope?.deployment?.allowedActions;return Array.isArray(actions)&&actions.length===1&&actions[0]==='verify';}
58
+ function scopePath(history:ReturnType<typeof validateHistoricalDevelopmentFiles>,verifyOnly:boolean){return verifyOnly?history.acceptance.checkCode.rawFile:`.gate-delivery/development/${history.plan.executionId}.acceptance.json`;}
52
59
  function verifyQualification(aggregate:DeliveryAggregate,source:DeliveryAggregateOptions){
53
60
  if(aggregate.version!==1||aggregateInputHash(aggregate)!==aggregate.inputsHash||semanticHash(aggregate.inputs.sourceDefinitions)!==aggregate.sourceDefinitionHash)throw Error('Qualification aggregate identity mismatch');
54
61
  same(aggregate.collections.map(c=>c.plan.target),aggregate.inputs.business.targets.map(t=>t.id),'Complete target qualification');same(source.targets.map(t=>t.request.network),aggregate.inputs.business.targets.map(t=>t.id),'Current selected target order');
55
62
  for(const [i,c] of aggregate.collections.entries()){const plan=parseDeliveryPlan(c.plan),request=source.targets[i].request;
63
+ parseCalldataReviews(c.calldata,plan.transactions);
56
64
  if(plan.environment!=='prod'||plan.inputsHash!==aggregate.inputsHash||plan.sourceDefinitionHash!==aggregate.sourceDefinitionHash||plan.executionId!==source.targets[i].executionId||plan.operator!==request.operator?.toLowerCase()||!request.fork||!plan.transactions.length)throw Error('Invalid production qualification identity');
57
65
  same(plan.runtimeIdentity,aggregate.inputs.runtime.declared,'Qualification runtime');expectedDevelopmentAssertions(c,aggregate.inputs.business.steps);
58
66
  parsePreparationJournal(c.preparations,plan.transactions,plan.derivedBindings,{target:plan.target,chainId:plan.chainId,expectedStepIds:plan.deploymentBindings.map(b=>b.stepId)});
@@ -60,17 +68,22 @@ function verifyQualification(aggregate:DeliveryAggregate,source:DeliveryAggregat
60
68
  }
61
69
  }
62
70
  function currentFiles(root:string,files:readonly {path:string;digest:string}[]){for(const file of files)if(inputDigest(readInputBytes(root,file.path))!==file.digest)throw Error(`Current release input changed: ${file.path}`);}
63
- function currentCandidate(scope:Scope,c:any){
71
+ function currentCandidate(scope:Scope,c:any,requireCommittedSources=false){
64
72
  if(c.schema!=='gate-delivery-release-candidate'||c.version!==1||c.generation!=='complete'||c.producer!=='gate-evm-tools/delivery-release')throw Error('Invalid completed release candidate');
65
73
  same(c.scope,{projectRoot:scope.projectRoot,handoff:scope.handoff,taskId:scope.taskId,deploymentId:scope.deploymentId},'Release current scope');
66
74
  const {candidateHash,...body}=c;same(semanticHash(body),candidateHash,'Release candidate hash');
75
+ if(c.inputSnapshot?.path!==`scripts/tasks/${scope.deploymentId}/releases/${c.releaseRef.releaseId}/inputs.snapshot.json`)throw Error('Noncanonical release input snapshot reference');
67
76
  const root=projectRoot(scope.workspaceRoot,scope.projectRoot),source={workspaceRoot:scope.workspaceRoot,projectRoot:scope.projectRoot,selection:'release' as const,targets:c.targets};
77
+ if(requireCommittedSources)same(captureCommittedContractSource(root,c.aggregate),c.contractSource,'Current committed contract source');
78
+ const snapshot=readReleaseInputSnapshot(root,c.inputSnapshot);same(snapshot.contractSource,c.contractSource,'Release snapshot contract source');
79
+ const snapshotFiles=new Map(snapshot.files.map(file=>[file.path,file.digest]));
80
+ for(const file of c.aggregate.inputs.files)if(!file.path.split('/').includes('node_modules')&&snapshotFiles.get(file.path)!==file.digest)throw Error('Release snapshot does not cover qualified input');
81
+ for(const file of snapshot.files)if(inputDigest(readInputBytes(root,file.path))!==file.digest)throw Error(`Current release snapshot input changed: ${file.path}`);
68
82
  verifyQualification(c.aggregate,source);currentFiles(root,c.aggregate.inputs.files);currentFiles(root,c.historical.files.filter((f:any)=>!historicalRegistrationFile(f.path)));
69
83
  same(openAggregateSources({workspaceRoot:scope.workspaceRoot,projectRoot:scope.projectRoot,requests:c.targets.map((t:any)=>t.request)}).definitions,c.aggregate.inputs.sourceDefinitions,'Current full upstream source');
70
84
  const h=validateHistoricalDevelopmentFiles({root,workspaceRoot:scope.workspaceRoot,projectRoot:scope.projectRoot,history:c.development});same(h.association,c.historical.association,'Historical development association');same(prerequisites(scope,h),c.prerequisites,'Current prerequisite evidence');
71
85
  same(h.files.filter(f=>historicalRegistrationFile(f.path)),c.historical.files.filter((f:any)=>historicalRegistrationFile(f.path)),'Original historical registry baseline');
72
86
  same(readReleaseUniverse(scope).targets,c.aggregate.inputs.business.targets.map((t:any)=>t.id),'Current full selected target set');
73
- const docs=readInputBytes(root,'docs/prod-execution-plan.md');same(inputDigest(docs),c.explanationHash,'Production execution explanation');
74
87
  return {root,source,history:h};
75
88
  }
76
89
  /** Qualification is generated by the actual owned aggregate, never accepted from caller JSON. */
@@ -81,17 +94,25 @@ export async function prepareDeliveryRelease(raw:ReleasePreparationOptions){
81
94
  if(fileBytes(root,`scripts/tasks/${deploymentId}/releases/${input.releaseId}/release.json`)!==null)throw Error('Release already has a ready marker');
82
95
  same(input.targets.map(t=>({network:t.request.network,sourceRef:t.request.sourceRef,purpose:t.request.purpose,environment:t.request.environment,mode:t.request.mode})),u.qualifications.map(t=>({network:(t.scope!.deployment as any).targetNetwork,sourceRef:{path:handoff,taskId,planKey:t.planKey,rev:t.rev},purpose:'prod-qualification',environment:'prod',mode:'simulate'})),'Exact current qualification tasks');
83
96
  const history=validateHistoricalDevelopmentFiles({root,workspaceRoot,projectRoot:relative,history:input.development}),prerequisiteEvidence=prerequisites(scope,history);
97
+ const committedBefore=captureCommittedContractSource(root,history.aggregate);
84
98
  await verifyHistoricalDevelopmentChain(history,root);
85
- const explanation=readInputBytes(root,'docs/prod-execution-plan.md').toString();for(const ref of ['manifest.yaml','parameters.yaml','recovery'])if(!explanation.includes(ref))throw Error('Production explanation must reference canonical inputs and recovery instructions');
86
99
  const source:DeliveryAggregateOptions={workspaceRoot,projectRoot:relative,selection:'release',targets:input.targets};
87
100
  const aggregate=await collectDeliveryAggregate(source);verifyQualification(aggregate,source);
101
+ const contractSource=captureCommittedContractSource(root,aggregate),snapshot=captureReleaseInputs(root,aggregate,contractSource);
102
+ same(contractSource,committedBefore,'Contract source during release qualification');
103
+ const inputSnapshot={path:`scripts/tasks/${deploymentId}/releases/${input.releaseId}/inputs.snapshot.json`,hash:snapshot.snapshotHash,sha256:byteHash(encode(snapshot))};
88
104
  const releaseRef={path:`scripts/tasks/${deploymentId}/releases/${input.releaseId}/release.json`,releaseId:input.releaseId,inputsHash:aggregate.inputsHash};
89
- const body={schema:'gate-delivery-release-candidate',version:1,generation:'complete',producer:'gate-evm-tools/delivery-release',releaseRef,scope:{projectRoot:relative,handoff,taskId,deploymentId},targets:input.targets,development:input.development,aggregate,historical:{files:history.files,association:history.association,acceptanceHash:semanticHash(history.acceptance)},prerequisites:prerequisiteEvidence,explanationHash:inputDigest(Buffer.from(explanation))};
90
- const candidate=deepFreeze({...body,candidateHash:semanticHash(body)});currentCandidate(scope,candidate);
91
- await withDevelopmentFileLock(root,async()=>{const previous=fileBytes(root,candidatePath(input.releaseId));if(previous!==null&&previous!==encode(candidate))throw Error('Release ID already belongs to a different frozen generation');atomicDevelopmentWrite(root,candidatePath(input.releaseId),encode(candidate));});
105
+ const body={schema:'gate-delivery-release-candidate',version:1,generation:'complete',producer:'gate-evm-tools/delivery-release',releaseRef,scope:{projectRoot:relative,handoff,taskId,deploymentId},targets:input.targets,development:input.development,aggregate,contractSource,inputSnapshot,historical:{files:history.files,association:history.association,acceptanceHash:semanticHash(history.acceptance)},prerequisites:prerequisiteEvidence};
106
+ const candidate=deepFreeze({...body,candidateHash:semanticHash(body)});
107
+ await withDevelopmentFileLock(root,async()=>{
108
+ const previous=fileBytes(root,candidatePath(input.releaseId));if(previous!==null&&previous!==encode(candidate))throw Error('Release ID already belongs to a different frozen generation');
109
+ const saved=fileBytes(root,inputSnapshot.path);if(saved!==null&&saved!==encode(snapshot))throw Error('Immutable release input snapshot conflict');
110
+ atomicDevelopmentWrite(root,inputSnapshot.path,encode(snapshot));currentCandidate(scope,candidate,true);
111
+ atomicDevelopmentWrite(root,candidatePath(input.releaseId),encode(candidate));
112
+ });
92
113
  return deepFreeze({status:'prepared' as const,releaseRef,sourceDefinitionHash:aggregate.sourceDefinitionHash,inputsHash:aggregate.inputsHash,candidateHash:candidate.candidateHash});
93
114
  }
94
- function bundleFor(c:any,graph:ReturnType<typeof readReleaseGraph>){return {schema:'gate-delivery-release',version:1,releaseRef:c.releaseRef,sourceDefinitionHash:c.aggregate.sourceDefinitionHash,inputsHash:c.aggregate.inputsHash,prodTaskGraphHash:graph.prodTaskGraphHash,prodTaskGraph:graph.graph,targets:c.aggregate.inputs.business.targets,operations:c.aggregate.inputs.business.steps,parameters:c.aggregate.inputs.business.parameters,qualification:c.aggregate.collections,runtime:c.aggregate.inputs.runtime,immutableFiles:c.aggregate.inputs.files,sourceDefinitions:c.aggregate.inputs.sourceDefinitions,historicalDevelopment:{...c.historical.association,acceptanceHash:c.historical.acceptanceHash},prerequisites:c.prerequisites,explanation:{path:'docs/prod-execution-plan.md',sha256:c.explanationHash},candidate:{path:candidatePath(c.releaseRef.releaseId),sha256:byteHash(encode(c))}};}
115
+ function bundleFor(c:any,graph:ReturnType<typeof readReleaseGraph>){return {schema:'gate-delivery-release',version:1,releaseRef:c.releaseRef,sourceDefinitionHash:c.aggregate.sourceDefinitionHash,inputsHash:c.aggregate.inputsHash,prodTaskGraphHash:graph.prodTaskGraphHash,prodTaskGraph:graph.graph,targets:c.aggregate.inputs.business.targets,operations:c.aggregate.inputs.business.steps,parameters:c.aggregate.inputs.business.parameters,qualification:c.aggregate.collections,runtime:c.aggregate.inputs.runtime,immutableFiles:c.aggregate.inputs.files,sourceDefinitions:c.aggregate.inputs.sourceDefinitions,contractSource:c.contractSource,inputSnapshot:c.inputSnapshot,historicalDevelopment:{...c.historical.association,acceptanceHash:c.historical.acceptanceHash},prerequisites:c.prerequisites,recovery:{strategy:'resume-original-execution',instructions:'Reconcile the original per-network executionId before retrying; preserve submitted transactions, receipts and finality records. Never replay completed operations as a new execution.'},candidate:{path:candidatePath(c.releaseRef.releaseId),sha256:byteHash(encode(c))}};}
95
116
  /** Finalizer rereads the actual handoff AFTER mainAgent writes all existing production stages. */
96
117
  export async function finalizeDeliveryRelease(raw:Scope&{releaseId:string;onFileCommitted?:(file:string)=>void}){
97
118
  // Detach own scalar data before the RPC boundary; caller options may be reused while it awaits.
@@ -103,16 +124,16 @@ export async function finalizeDeliveryRelease(raw:Scope&{releaseId:string;onFile
103
124
  if(Object.values(input).some(value=>typeof value!=='string'))throw Error('Release finalization scope requires strings');
104
125
  safeId(input.taskId,'taskId');safeId(input.deploymentId,'deploymentId');portablePath(input.handoff,'handoff');
105
126
  const root=projectRoot(input.workspaceRoot,input.projectRoot),c=JSON.parse(readInputBytes(root,candidatePath(input.releaseId)).toString());
106
- const initial=currentCandidate(input,c);await verifyHistoricalDevelopmentChain(initial.history,root);
127
+ const initial=currentCandidate(input,c,true);await verifyHistoricalDevelopmentChain(initial.history,root);
107
128
  return withDevelopmentFileLock(root,async()=>{
108
- same(JSON.parse(readInputBytes(root,candidatePath(input.releaseId)).toString()),c,'Current candidate generation');currentCandidate(input,c);
129
+ same(JSON.parse(readInputBytes(root,candidatePath(input.releaseId)).toString()),c,'Current candidate generation');currentCandidate(input,c,true);
109
130
  const graph=readReleaseGraph({...input,releaseRef:c.releaseRef}),bundle=bundleFor(c,graph),bundleHash=semanticHash(bundle),bundlePath=`scripts/tasks/${input.deploymentId}/releases/${input.releaseId}/bundle.json`;
110
131
  const marker={schema:'gate-delivery-release-ready',version:1,status:'release_ready',generation:'complete',releaseRef:c.releaseRef,sourceDefinitionHash:c.aggregate.sourceDefinitionHash,inputsHash:c.aggregate.inputsHash,prodTaskGraphHash:graph.prodTaskGraphHash,bundle:{path:bundlePath,hash:bundleHash,sha256:byteHash(encode(bundle))}};
111
132
  const previous=fileBytes(root,c.releaseRef.path);if(previous!==null){same(JSON.parse(previous),marker,'Published release is immutable');return inspectDeliveryRelease({...input,releaseRef:c.releaseRef});}
112
133
  const existing=fileBytes(root,bundlePath);if(existing!==null&&existing!==encode(bundle))throw Error('Immutable release bundle conflict');
113
134
  atomicDevelopmentWrite(root,bundlePath,encode(bundle));onFileCommitted?.(bundlePath);
114
135
  // Async notification or competing edits cannot publish stale graph/evidence. Authoritative marker comes last.
115
- currentCandidate(input,c);same(readReleaseGraph({...input,releaseRef:c.releaseRef}),graph,'Current production graph');
136
+ currentCandidate(input,c,true);same(readReleaseGraph({...input,releaseRef:c.releaseRef}),graph,'Current production graph');
116
137
  if(fileBytes(root,bundlePath)!==encode(bundle))throw Error('Prepared bundle changed before publication');
117
138
  atomicDevelopmentWrite(root,c.releaseRef.path,encode(marker));return inspectDeliveryRelease({...input,releaseRef:c.releaseRef});
118
139
  });
@@ -126,3 +147,20 @@ export function inspectDeliveryRelease(input:Scope&{releaseRef:ReleaseGraphOptio
126
147
  const expected={schema:'gate-delivery-release-ready',version:1,status:'release_ready',generation:'complete',releaseRef:c.releaseRef,sourceDefinitionHash:c.aggregate.sourceDefinitionHash,inputsHash:c.aggregate.inputsHash,prodTaskGraphHash:graph.prodTaskGraphHash,bundle:{path:bundlePath,hash:semanticHash(bundle),sha256:byteHash(encode(bundle))}};
127
148
  same(marker,expected,'Complete ready content identity');same(readInputBytes(root,bundlePath).toString(),encode(bundle),'Immutable published bundle bytes');return deepFreeze({status:'release_ready' as const,release:bundle,bundleHash:marker.bundle.hash});
128
149
  }
150
+ /** File-only historical input recovery; current project edits do not rewrite the old release. */
151
+ export function restoreDeliveryReleaseInputs(raw:Scope&{releaseRef:ReleaseGraphOptions['releaseRef'];destination:string}){
152
+ const input=strictData(raw);exactObject(input,['workspaceRoot','projectRoot','handoff','taskId','deploymentId','releaseRef','destination'],'release input restore');
153
+ const root=projectRoot(input.workspaceRoot,input.projectRoot),ref=input.releaseRef;
154
+ safeId(input.deploymentId,'deploymentId');safeId(ref.releaseId,'releaseId');
155
+ const base=`scripts/tasks/${input.deploymentId}/releases/${ref.releaseId}`;
156
+ if(ref.path!==`${base}/release.json`)throw Error('Noncanonical release restore reference');
157
+ const marker=JSON.parse(readInputBytes(root,ref.path).toString());
158
+ if(marker.schema!=='gate-delivery-release-ready'||marker.version!==1||marker.status!=='release_ready'||marker.generation!=='complete')throw Error('Release restore requires a completed published release');
159
+ same(marker.releaseRef,ref,'Restore release reference');
160
+ const bytes=readInputBytes(root,`${base}/bundle.json`),bundle=JSON.parse(bytes.toString());
161
+ if(marker.bundle.path!==`${base}/bundle.json`||marker.bundle.sha256!==byteHash(bytes)||marker.bundle.hash!==semanticHash(bundle)||bytes.toString()!==encode(bundle))throw Error('Published release bundle changed');
162
+ if(bundle.schema!=='gate-delivery-release'||bundle.version!==1||bundle.inputSnapshot.path!==`${base}/inputs.snapshot.json`)throw Error('Invalid release restore bundle');
163
+ same(bundle.releaseRef,ref,'Restore bundle release reference');same(bundle.inputsHash,ref.inputsHash,'Restore bundle input identity');
164
+ const snapshot=readReleaseInputSnapshot(root,bundle.inputSnapshot);same(snapshot.contractSource,bundle.contractSource,'Restore committed contract source');
165
+ return {...restoreReleaseInputs(root,bundle.inputSnapshot,input.destination),releaseRef:ref};
166
+ }
@@ -12,6 +12,7 @@ import { uint256 } from "./observations";
12
12
  import type { EoaFinality } from "./eoa-observation";
13
13
  import type { DeliveryPlan } from "./plan";
14
14
  import { SAFE_RUNTIME_HASHES } from "./safe-manifest";
15
+ import { createCalldataInvocation } from './calldata-review';
15
16
  export const SAFE_ADAPTER = deepFreeze({
16
17
  id: "safe-1.4.1-call-only/v1",
17
18
  version: "1.4.1",
@@ -326,14 +327,24 @@ export function verifySafeExec(
326
327
  }
327
328
  export function renderSafeExport(rawPlan: unknown, raw: unknown) {
328
329
  const plan = immutableDeliveryPlan(rawPlan),
329
- envelope = parseSafeEnvelope(raw, plan),
330
- model = deepFreeze({
330
+ envelope = parseSafeEnvelope(raw, plan);
331
+ const unsignedExecTransaction = encodeSafeExec(envelope, '0x');
332
+ const payloads = envelope.operation === 1 ? [{ argumentPath: [2], invocation: createCalldataInvocation({
333
+ abi: multi.fragments, method: 'multiSend', args: [
334
+ '0x' + plan.transactions.slice(envelope.start, envelope.start + envelope.count).map(c =>
335
+ solidityPacked(['uint8', 'address', 'uint256', 'uint256', 'bytes'], [0, c.to, c.value, (c.data.length - 2) / 2, c.data]).slice(2)).join(''),
336
+ ], data: envelope.data,
337
+ }) }] : [];
338
+ const unsignedExecReview = createCalldataInvocation({ abi: SAFE_INTERFACE.fragments, method: 'execTransaction',
339
+ args: [...execKeys.map(k => (envelope as any)[k]), '0x'], data: unsignedExecTransaction, payloads });
340
+ const model = deepFreeze({
331
341
  schema: "gate-safe-export",
332
342
  version: 1,
333
343
  status: "artifact-delivered",
334
344
  plan,
335
345
  envelope,
336
- unsignedExecTransaction: encodeSafeExec(envelope, "0x"),
346
+ unsignedExecTransaction,
347
+ unsignedExecReview,
337
348
  });
338
349
  const json = canonicalJson(model);
339
350
  return deepFreeze({
@@ -5,12 +5,13 @@ export interface SameForkInitialPreparation { request: GateToolPreparationReques
5
5
  /** Stable initial preparation and full prior layout commitment. Auxiliary compiler randomness is excluded. */
6
6
  export function sameForkBaselineDigest(initial: SameForkInitialPreparation, oldLayoutHash: string): string {
7
7
  const request = normalizePreparationRequest(initial.request), plan = normalizePreparationPlan(initial.plan);
8
- if (request.kind !== 'uups-placeholder-deploy' || plan.kind !== request.kind || plan.requestHash !== hashPreparationRequest(request)
9
- || plan.target !== request.target || !/^[a-f0-9]{64}$/.test(oldLayoutHash)) throw new Error('Invalid same-fork initial preparation');
8
+ if ((request.kind !== 'uups-placeholder-deploy' && request.kind !== 'transparent-deploy') || plan.kind !== request.kind || plan.requestHash !== hashPreparationRequest(request)
9
+ || plan.proxyKind !== request.proxyKind || plan.target !== request.target || !/^[a-f0-9]{64}$/.test(oldLayoutHash)) throw new Error('Invalid same-fork initial preparation');
10
10
  return semanticHash({kind:'same-fork',request,plan,oldLayoutHash});
11
11
  }
12
- export function matchesSameForkInitial(initial: SameForkInitialPreparation, target: string, chainId: string, proxy: string, implementation?: string): boolean {
13
- return initial.request.kind === 'uups-placeholder-deploy' && initial.request.target === target && initial.plan.target === target && initial.plan.chainId === chainId
12
+ export function matchesSameForkInitial(initial: SameForkInitialPreparation, target: string, chainId: string, proxy: string, implementation?: string, proxyKind?: 'uups' | 'transparent'): boolean {
13
+ return (initial.request.kind === 'uups-placeholder-deploy' || initial.request.kind === 'transparent-deploy') && initial.request.target === target && initial.plan.target === target && initial.plan.chainId === chainId
14
+ && initial.plan.proxyKind === initial.request.proxyKind && (proxyKind === undefined || initial.request.proxyKind === proxyKind)
14
15
  && initial.plan.deployments.some(d => d.role === 'proxy' && d.address.toLowerCase() === proxy.toLowerCase())
15
16
  && (implementation === undefined || initial.plan.deployments.some(d => d.role === 'implementation' && d.address.toLowerCase() === implementation.toLowerCase()));
16
17
  }
@@ -4,16 +4,20 @@ import crypto from 'node:crypto';
4
4
  import { createRequire } from 'node:module';
5
5
  import { spawnSync } from 'node:child_process';
6
6
  import YAML from 'yaml';
7
+ import { REVIEWED_DELIVERY_OVERRIDES } from './toolchain';
7
8
  import { object } from './protocol';
8
- import { coreMarker, projectRoot, readFile, confinedFile, stat, integratedConfig, readProjectNetworkSnapshots, projectSourcesDirectory } from './project';
9
- import { configDocument, validateDeliveryTarget, type DeliveryTarget } from './config';
10
- export { readProjectNetworkSnapshots } from './project';
9
+ import { deliveryProjectMarker, projectRoot, readFile, confinedFile, stat, integratedConfig, readPublicProjectNetworkSnapshots, projectSourcesDirectory } from './project';
10
+ import { configDocument, parseDeliveryPublicTargets, validateDeliveryTarget, type DeliveryTarget } from './config';
11
+ export { readProjectNetworkSnapshots, readPublicProjectNetworkSnapshots } from './project';
11
12
  export { loadDeliveryTarget } from './config';
12
13
  export { configureDeliveryEnvironment } from './manifest';
13
14
  export type { DeliveryTarget, DeliveryTargetConfig } from './config';
14
15
 
15
16
  const TOOLCHAIN: Record<string, string> = { hardhat: '2.26.3', ethers: '6.15.0', '@nomicfoundation/hardhat-ethers': '3.1.0', typescript: '5.9.3', 'ts-node': '10.9.2' };
16
- const DEPENDENCIES: Record<string, string> = { 'gate-evm-tools': '1.0.29', '@openzeppelin/hardhat-upgrades': '3.9.1', '@openzeppelin/upgrades-core': '1.44.2', '@openzeppelin/contracts': '5.4.0' };
17
+ // Resolve our identity from the executing package, including an explicitly installed tarball.
18
+ const toolIdentity = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../../package.json'), 'utf8'));
19
+ if (toolIdentity.name !== 'gate-evm-tools' || typeof toolIdentity.version !== 'string') throw new Error('Invalid GateTool package identity');
20
+ const DEPENDENCIES: Record<string, string> = { 'gate-evm-tools': toolIdentity.version, '@openzeppelin/hardhat-upgrades': '3.9.1', '@openzeppelin/upgrades-core': '1.44.2', '@openzeppelin/contracts': '5.4.0' };
17
21
  export interface DeliverySetupOptions {
18
22
  workspaceRoot: string;
19
23
  projectRoot: string;
@@ -65,10 +69,14 @@ function preflight(input: DeliverySetupOptions): { result: DeliveryInspection; w
65
69
  const targets = input.targets.map(validateDeliveryTarget);
66
70
  if (new Set(targets.map(target => target.network)).size !== targets.length) throw new Error('Duplicate selected target');
67
71
  const root = projectRoot(input.workspaceRoot, input.projectRoot);
68
- coreMarker(root);
72
+ deliveryProjectMarker(root);
69
73
  const before = new Map<string, string | undefined>();
70
74
  for (const file of ['.gate-template.json', 'package.json', 'hardhat.config.ts', 'config.yaml', 'contractInfo.json']) before.set(file, readFile(root, file));
71
75
  const pkg = object(JSON.parse(before.get('package.json') ?? 'null'), 'package.json');
76
+ const overrides = pkg.overrides === undefined ? {} : object(pkg.overrides, 'package overrides');
77
+ for (const [name, version] of Object.entries(REVIEWED_DELIVERY_OVERRIDES)) {
78
+ if (overrides[name] !== undefined && overrides[name] !== version) throw new Error(`Reviewed delivery dependency override conflict: ${name}`);
79
+ }
72
80
  const declarations: Record<string, unknown> = {};
73
81
  for (const section of ['dependencies', 'devDependencies']) {
74
82
  const entries = pkg[section] === undefined ? {} : object(pkg[section], section);
@@ -89,7 +97,7 @@ function preflight(input: DeliverySetupOptions): { result: DeliveryInspection; w
89
97
  const localTool = name === 'gate-evm-tools' && input.toolPackage === undefined && typeof declared === 'string' && /^file:.*\.tgz$/.test(declared);
90
98
  if ((name in TOOLCHAIN && declared === undefined) || (declared !== undefined && declared !== version && !localTool)) throw new Error(`Dependency declaration conflict for ${name}: expected ${version}`);
91
99
  }
92
- const networks = readProjectNetworkSnapshots(root, targets.map(target => target.network));
100
+ const networks = readPublicProjectNetworkSnapshots(root, targets.map(target => target.network));
93
101
  const source = before.get('hardhat.config.ts')!;
94
102
  const withPlugin = integratedConfig(source); // Check integration conflicts even when dependencies are missing.
95
103
  const doc = configDocument(root);
@@ -106,6 +114,9 @@ function preflight(input: DeliverySetupOptions): { result: DeliveryInspection; w
106
114
  confinedFile(root, target.openzeppelin!.manifestDir, 'directory');
107
115
  merge([network], target);
108
116
  }
117
+ // Validate the same effective facilities used by input qualification, while keeping inherited
118
+ // addresses in their profiles so later base edits propagate to non-overridden targets.
119
+ parseDeliveryPublicTargets(Buffer.from(doc.toString()), Buffer.from(source), targets);
109
120
  if (before.get('contractInfo.json') !== undefined) object(JSON.parse(before.get('contractInfo.json')!), 'contractInfo.json');
110
121
  const dependencies: DeliveryInspection['dependencies'] = [];
111
122
  const projectRequire = createRequire(path.join(root, 'package.json'));
@@ -140,10 +151,11 @@ function preflight(input: DeliverySetupOptions): { result: DeliveryInspection; w
140
151
  }
141
152
  const writes = new Map<string, string>();
142
153
  const missing = Object.entries(required).filter(([name]) => declarations[name] === undefined);
143
- if (missing.length) {
154
+ const missingOverrides = Object.entries(REVIEWED_DELIVERY_OVERRIDES).some(([name]) => overrides[name] === undefined);
155
+ if (missing.length || missingOverrides) {
144
156
  const dev = { ...(pkg.devDependencies as Record<string, unknown> ?? {}) };
145
157
  for (const [name, version] of missing) dev[name] = version;
146
- writes.set('package.json', JSON.stringify({ ...pkg, devDependencies: dev }, null, 2) + '\n');
158
+ writes.set('package.json', JSON.stringify({ ...pkg, devDependencies: dev, overrides: { ...overrides, ...REVIEWED_DELIVERY_OVERRIDES } }, null, 2) + '\n');
147
159
  }
148
160
  if (changedYaml) writes.set('config.yaml', doc.toString());
149
161
  if (before.get('contractInfo.json') === undefined) writes.set('contractInfo.json', '{}\n');
@@ -1,7 +1,7 @@
1
1
  /** Actual-file source binding only. This API grants no host approval or execution authority. */
2
2
  import fs from 'node:fs';
3
3
  import { createHash } from 'node:crypto';
4
- import { coreMarker, projectRoot, confinedFile } from './project-files';
4
+ import { deliveryProjectMarker, projectRoot, confinedFile } from './project-files';
5
5
  import { object, parseDeliveryRequest, validateDeliveryRpc, type DeliveryRequest, type ChainIdProvider, type ProjectNetworkSnapshot } from './protocol';
6
6
  import { loadPlanCodec } from './codec';
7
7
  import type { Plan, PlanTask, DefinitionSelection, DefinitionSnapshot, DeepReadonly } from '../vendor/plan-codec/index.cjs';
@@ -37,11 +37,9 @@ export function parseCanonicalPlan(text: string): Plan { return loadPlanCodec().
37
37
  export function projectCanonicalDefinitions(text: string, selection: DefinitionSelection): ReturnType<ReturnType<typeof loadPlanCodec>['projectDefinitions']> {
38
38
  return loadPlanCodec().projectDefinitions(text, selection);
39
39
  }
40
- const purposeSteps = {
41
- 'dev-execution': ['deploy', 'check-code'],
42
- 'prod-qualification': ['deploy-test'],
43
- 'prod-execution': ['release-prepare', 'release-execute', 'release-verify'],
44
- };
40
+ export function deploymentPurpose(task: Pick<PlanTask, 'step' | 'scope'>) {
41
+ return loadPlanCodec().deploymentPurpose(task);
42
+ }
45
43
  function sameRelease(actual: unknown, expected: DeliveryRequest['releaseRef']): boolean {
46
44
  if (expected === undefined) return actual === undefined;
47
45
  if (!actual || typeof actual !== 'object' || Array.isArray(actual)) return false;
@@ -78,7 +76,7 @@ function readSource(input: Omit<DeliverySourceOptions, 'sourceRoots'> & { source
78
76
  const request = parseDeliveryRequest(input.request);
79
77
  const workspace = projectRoot(input.workspaceRoot, '.');
80
78
  const root = projectRoot(workspace, input.projectRoot);
81
- coreMarker(root);
79
+ deliveryProjectMarker(root);
82
80
  const bytes = actualSource(workspace, request.sourceRef.path);
83
81
  const text = new TextDecoder('utf-8', { fatal: true }).decode(bytes);
84
82
  if (input.sourceRoots === undefined) (require('./input-files') as typeof import('./input-files')).assertUnambiguousHandoff(text);
@@ -89,15 +87,17 @@ function readSource(input: Omit<DeliverySourceOptions, 'sourceRoots'> & { source
89
87
  const invocation = entries.find(({ task }) => task.planKey === request.sourceRef.planKey);
90
88
  if (!invocation || invocation.task.rev !== request.sourceRef.rev) throw new Error('sourceRef planKey/rev does not match actual handoff');
91
89
  if (plan.lanes[invocation.lane].state !== 'enabled' || invocation.task.status === 'cancelled') throw new Error('Invocation task is disabled or cancelled');
90
+ const requirementIssue = codec.deploymentRequirementIssue(plan, invocation.task);
91
+ if (requirementIssue) throw new Error(requirementIssue);
92
92
  const deployment = object(invocation.task.scope?.deployment, 'invocation scope.deployment');
93
93
  if (deployment.projectRoot !== input.projectRoot) throw new Error('Invocation projectRoot mismatch');
94
94
  if (deployment.chainFamily !== 'evm' || deployment.framework !== 'hardhat2') throw new Error('Invocation requires an EVM Hardhat2 deployment');
95
- if (!purposeSteps[request.purpose].includes(invocation.task.step ?? '')) throw new Error('Invocation purpose/step mismatch');
95
+ if (deploymentPurpose(invocation.task) !== request.purpose) throw new Error('Invocation purpose mismatch');
96
96
  if (deployment.environment !== request.environment || deployment.targetNetwork !== request.network) throw new Error('Invocation environment/targetNetwork mismatch');
97
97
  if (!Array.isArray(deployment.allowedActions) || !deployment.allowedActions.includes(request.mode)) throw new Error('Invocation mode is not in allowedActions');
98
98
  if (!sameRelease(deployment.releaseRef, request.releaseRef)) throw new Error('Invocation releaseRef mismatch');
99
99
  const sourceRoots = input.sourceRoots ?? (request.purpose === 'prod-execution'
100
- ? entries.filter(({ task }) => task.step === 'deploy-test'
100
+ ? entries.filter(({ task }) => deploymentPurpose(task) === 'prod-qualification'
101
101
  && (task.scope?.deployment as Record<string, unknown> | undefined)?.projectRoot === input.projectRoot
102
102
  && (task.scope?.deployment as Record<string, unknown> | undefined)?.deploymentId === deployment.deploymentId).map(({ task }) => task.planKey)
103
103
  : [invocation.task.planKey]);
@@ -109,7 +109,7 @@ function readSource(input: Omit<DeliverySourceOptions, 'sourceRoots'> & { source
109
109
  }
110
110
  let production: ReturnType<typeof codec.projectDefinitions> | undefined;
111
111
  if (request.purpose === 'prod-execution') {
112
- const roots = entries.filter(({ task }) => purposeSteps['prod-execution'].includes(task.step ?? '')
112
+ const roots = entries.filter(({ task }) => deploymentPurpose(task) === 'prod-execution'
113
113
  && task.scope?.deployment && (task.scope.deployment as Record<string, unknown>).projectRoot === input.projectRoot
114
114
  && sameRelease((task.scope.deployment as Record<string, unknown>).releaseRef, request.releaseRef)).map(({ task }) => task.planKey);
115
115
  production = codec.projectDefinitions(text, { roots, mode: 'full' });
@@ -0,0 +1,85 @@
1
+ /** Allocate a round only after its concrete requirement revision is confirmed. */
2
+ import fs from 'node:fs';
3
+ import { randomBytes } from 'node:crypto';
4
+ import { parseCanonicalPlan, projectCanonicalDefinitions, deploymentPurpose } from './source';
5
+ import { projectRoot, deliveryProjectMarker, confinedFile, stat } from './project-files';
6
+ import { readInputBytes, assertUnambiguousHandoff } from './input-files';
7
+ import { withDevelopmentFileLock, atomicDevelopmentWrite, fileBytes } from './materialization';
8
+ import { exactObject, semanticHash, canonicalJson } from '../workflow/lib/canonicalData';
9
+ import { safeId, portablePath, object } from './protocol';
10
+
11
+ export interface DeploymentRequirementRef { planKey: string; rev: number }
12
+ export function parseDeploymentRequirementRef(raw: unknown): DeploymentRequirementRef {
13
+ const ref = exactObject(raw, ['planKey', 'rev'], 'requirementRef');
14
+ safeId(ref.planKey, 'requirementRef.planKey');
15
+ if (!Number.isSafeInteger(ref.rev) || (ref.rev as number) < 1) throw Error('Invalid requirement revision');
16
+ return { planKey: ref.planKey as string, rev: ref.rev as number };
17
+ }
18
+ export interface CreateDeliveryTaskOptions {
19
+ workspaceRoot: string; projectRoot: string; handoff: string; taskId: string;
20
+ requirementRef: DeploymentRequirementRef; businessSlug: string; referenceDeploymentId?: string;
21
+ }
22
+ /** A reservation creates metadata only. The deployment Agent supplies executable content afterwards. */
23
+ export async function createDeliveryTask(input: CreateDeliveryTaskOptions) {
24
+ object(input, 'create deployment task', ['workspaceRoot', 'projectRoot', 'handoff', 'taskId', 'requirementRef', 'businessSlug', 'referenceDeploymentId']);
25
+ const root = projectRoot(input.workspaceRoot, input.projectRoot), workspace = projectRoot(input.workspaceRoot, '.');
26
+ deliveryProjectMarker(root);
27
+ portablePath(input.handoff, 'handoff'); safeId(input.taskId, 'taskId');
28
+ const ref = parseDeploymentRequirementRef(input.requirementRef);
29
+ if (typeof input.businessSlug !== 'string' || !/^[a-z0-9][a-z0-9-]{0,63}$/.test(input.businessSlug)) throw Error('businessSlug must be a short lowercase business name');
30
+ if (input.referenceDeploymentId !== undefined) safeId(input.referenceDeploymentId, 'referenceDeploymentId');
31
+ return withDevelopmentFileLock(root, async () => {
32
+ const text = readInputBytes(workspace, input.handoff).toString(); assertUnambiguousHandoff(text);
33
+ const plan = parseCanonicalPlan(text);
34
+ if (plan.taskId !== input.taskId) throw Error('Requirement taskId mismatch');
35
+ const requirement = Object.values(plan.tasks).flat().find(t => t.planKey === ref.planKey);
36
+ if (!requirement || requirement.rev !== ref.rev || requirement.requirementConfirmation?.rev !== ref.rev
37
+ || requirement.status === 'cancelled' || deploymentPurpose(requirement) !== 'analysis'
38
+ || (requirement.scope?.deployment as any)?.projectRoot !== input.projectRoot) throw Error('Deployment requirement is unconfirmed or stale');
39
+ const d = requirement.scope!.deployment as any;
40
+ if (!d.requiredOperations?.length || !d.developmentNetwork || !Array.isArray(d.releaseTargetNetworks)) throw Error('Confirmed requirement scope is incomplete');
41
+ const identity = semanticHash({ taskId: input.taskId, projectRoot: input.projectRoot, requirementRef: ref });
42
+ const requirementHash = semanticHash(projectCanonicalDefinitions(text, { roots: [ref.planKey], mode: 'upstream' }).snapshot);
43
+ const registry = `.gate-delivery/deployment-requests/${identity}.json`;
44
+ const requestIdentity = { taskId: input.taskId, requirementRef: ref, requirementHash,
45
+ referenceDeploymentId: input.referenceDeploymentId ?? null };
46
+ let record: any;
47
+ const existing = fileBytes(root, registry);
48
+ if (existing !== null) {
49
+ record = JSON.parse(existing);
50
+ if (canonicalJson(record.requestIdentity) !== canonicalJson(requestIdentity)) throw Error('Confirmed requirement identity conflict');
51
+ safeId(record.deploymentId, 'reserved deploymentId');
52
+ } else {
53
+ const known = new Set(Object.values(plan.tasks).flat().map(t => (t.scope?.deployment as any)?.deploymentId).filter(Boolean));
54
+ const history = fileBytes(workspace, input.handoff.includes('/') ? `${input.handoff.slice(0, input.handoff.lastIndexOf('/'))}/handoff-ledger.jsonl` : 'handoff-ledger.jsonl');
55
+ if (history) for (const line of history.split('\n').filter(Boolean)) {
56
+ const item = JSON.parse(line);
57
+ for (const entry of item.tasks ?? []) { const id = entry.task?.scope?.deployment?.deploymentId; if (id) known.add(id); }
58
+ }
59
+ const date = new Date().toISOString().slice(0, 10).replaceAll('-', '');
60
+ let deploymentId: string;
61
+ do { deploymentId = `${input.businessSlug}-${date}-${randomBytes(4).toString('hex')}`; }
62
+ while (known.has(deploymentId) || stat(confinedFile(root, `scripts/tasks/${deploymentId}`, 'directory')));
63
+ record = { version: 1, deploymentId, releaseId: `${deploymentId}-release`, requestIdentity, state: 'reserved' };
64
+ // Publish reservation before creating the package, so a retry uses the same ID.
65
+ atomicDevelopmentWrite(root, registry, canonicalJson(record) + '\n');
66
+ }
67
+ const businessRoot = `scripts/tasks/${record.deploymentId}`;
68
+ const directory = confinedFile(root, businessRoot, 'directory');
69
+ const marker = `${businessRoot}/.request.json`;
70
+ const markerBytes = canonicalJson({ identity }) + '\n';
71
+ const previousMarker = fileBytes(root, marker);
72
+ if (stat(directory) && previousMarker !== markerBytes && fs.readdirSync(directory).length) throw Error('Reserved deployment directory is occupied; refusing to overwrite');
73
+ if (previousMarker !== null && previousMarker !== markerBytes) throw Error('Deployment reservation ownership mismatch');
74
+ if (previousMarker === null) atomicDevelopmentWrite(root, marker, markerBytes);
75
+ const metadata = { version: 1, id: record.deploymentId, requirementRef: ref,
76
+ developmentNetwork: d.developmentNetwork, releaseTargetNetworks: d.releaseTargetNetworks,
77
+ ...(input.referenceDeploymentId ? { referenceDeploymentId: input.referenceDeploymentId } : {}) };
78
+ const taskPath = `${businessRoot}/task.yaml`, bytes = canonicalJson(metadata) + '\n';
79
+ const previous = fileBytes(root, taskPath);
80
+ if (previous !== null && previous !== bytes) throw Error('Reserved task metadata changed; refusing to overwrite');
81
+ if (previous === null) atomicDevelopmentWrite(root, taskPath, bytes);
82
+ if (record.state !== 'complete') atomicDevelopmentWrite(root, registry, canonicalJson({ ...record, state: 'complete' }) + '\n');
83
+ return { status: 'created' as const, deploymentId: record.deploymentId as string, releaseId: record.releaseId as string, businessRoot, specPath: taskPath, requirementRef: ref };
84
+ });
85
+ }
@@ -0,0 +1,48 @@
1
+ import { compilerDependencyPins } from './compiler-dependency-pins';
2
+
3
+ /** Reviewed compiler adapter dependency selections; payload checks remain authoritative.
4
+ * Range-scoped entries preserve distinct dependency majors. Setup never overrides a conflicting project choice. */
5
+ export const REVIEWED_DELIVERY_OVERRIDES: Record<string, string> = {
6
+ "axios": "1.20.0",
7
+ "@aws-sdk/client-lambda": "3.1152.0",
8
+ "@aws-sdk/core": "3.978.3",
9
+ "@aws-sdk/credential-provider-env": "3.972.74",
10
+ "@aws-sdk/credential-provider-http": "3.972.76",
11
+ "@aws-sdk/credential-provider-ini": "3.973.19",
12
+ "@aws-sdk/credential-provider-login": "3.972.81",
13
+ "@aws-sdk/credential-provider-node": "3.972.86",
14
+ "@aws-sdk/credential-provider-process": "3.972.74",
15
+ "@aws-sdk/credential-provider-sso": "3.973.18",
16
+ "@aws-sdk/credential-provider-web-identity": "3.972.80",
17
+ "@aws-sdk/nested-clients": "3.997.48",
18
+ "@aws-sdk/signature-v4-multi-region": "3.996.48",
19
+ "@aws-sdk/token-providers": "3.1150.0",
20
+ "@aws-sdk/types": "3.974.6",
21
+ "@smithy/types": "4.19.0",
22
+ "@smithy/signature-v4": "5.7.4",
23
+ "@smithy/fetch-http-handler": "5.8.0",
24
+ "@smithy/credential-provider-imds": "4.5.2",
25
+ "@smithy/core": "3.36.0",
26
+ "@smithy/node-http-handler": "4.12.1",
27
+ "bowser": "2.14.1",
28
+ "follow-redirects": "1.16.1",
29
+ "undici@>=5 <6": "5.29.0",
30
+ "undici@>=6 <7": "6.29.0",
31
+ "tslib@>=1 <2": "1.14.1",
32
+ "tslib@>=2 <3": "2.7.0",
33
+ "semver@>=5 <6": "5.7.2",
34
+ "semver@>=6 <7": "6.3.1",
35
+ "semver@>=7 <8": "7.8.5",
36
+ "ansi-regex@>=6 <7": "6.4.0"
37
+ };
38
+
39
+ // OZ's compiler adapter follows floating AWS/Smithy ranges. Freeze that reviewed
40
+ // family closure so a fresh npm resolution cannot select unqualified payloads.
41
+ // Other project dependencies keep their original constraints and payload checks.
42
+ for (const key of Object.keys(compilerDependencyPins)) {
43
+ if (!key.startsWith('@aws-sdk/') && !key.startsWith('@smithy/')) continue;
44
+ const at = key.lastIndexOf('@'), name = key.slice(0, at), version = key.slice(at + 1);
45
+ const existing = REVIEWED_DELIVERY_OVERRIDES[name];
46
+ if (existing && existing !== version) throw new Error('Ambiguous reviewed compiler dependency: ' + name);
47
+ REVIEWED_DELIVERY_OVERRIDES[name] = version;
48
+ }
@@ -118,13 +118,16 @@ export function createDeliveryValidation(
118
118
  const args = first
119
119
  ? (first.constructorArgs ?? [])
120
120
  : step.kind === "deploy"
121
- ? (step.args ?? [])
121
+ ? (proxy ? (proxy.constructorArgs ?? []) : (step.args ?? []))
122
122
  : (step.constructorArgs ??
123
123
  (typeof proxy === "object"
124
124
  ? proxy?.constructorArgs
125
125
  : undefined) ??
126
126
  []);
127
127
  await argumentsFor(name as string, null, args, true);
128
+ if (step.kind === "deploy" && proxy?.kind === "transparent" && proxy.initializer !== false) {
129
+ await argumentsFor(name as string, String(proxy.initializer), step.args ?? [], true);
130
+ }
128
131
  const init = (first?.call ?? step.call) as
129
132
  | Record<string, unknown>
130
133
  | undefined;
@@ -169,7 +172,9 @@ export function createDeliveryValidation(
169
172
  true,
170
173
  )
171
174
  : declaredCreate2;
172
- if (step.kind === "deploy" && create2) {
175
+ // Transparent proxy prediction depends on the prepared implementation salt/address.
176
+ // Its actual constructor and policies are independently checked by preparation semantics.
177
+ if (step.kind === "deploy" && create2 && proxy?.kind !== "transparent") {
173
178
  const a = await read(first ? ERC1967_PROXY : (name as string));
174
179
  const constructor = resolve(
175
180
  first