@davidahmann/mill 0.1.4 → 0.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 (249) hide show
  1. package/README.md +141 -32
  2. package/dist/audit/repository.d.ts.map +1 -1
  3. package/dist/audit/repository.js +2 -0
  4. package/dist/audit/repository.js.map +1 -1
  5. package/dist/cli-program.d.ts.map +1 -1
  6. package/dist/cli-program.js +189 -0
  7. package/dist/cli-program.js.map +1 -1
  8. package/dist/contracts/schemas.d.ts +467 -2
  9. package/dist/contracts/schemas.d.ts.map +1 -1
  10. package/dist/contracts/schemas.js +211 -1
  11. package/dist/contracts/schemas.js.map +1 -1
  12. package/dist/index.d.ts +7 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +7 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/planning/closure.d.ts +24 -0
  17. package/dist/planning/closure.d.ts.map +1 -0
  18. package/dist/planning/closure.js +68 -0
  19. package/dist/planning/closure.js.map +1 -0
  20. package/dist/planning/outcomes.d.ts +6 -0
  21. package/dist/planning/outcomes.d.ts.map +1 -0
  22. package/dist/planning/outcomes.js +36 -0
  23. package/dist/planning/outcomes.js.map +1 -0
  24. package/dist/planning/tasks.d.ts +32 -0
  25. package/dist/planning/tasks.d.ts.map +1 -0
  26. package/dist/planning/tasks.js +305 -0
  27. package/dist/planning/tasks.js.map +1 -0
  28. package/dist/repository/intelligence.d.ts +78 -0
  29. package/dist/repository/intelligence.d.ts.map +1 -0
  30. package/dist/repository/intelligence.js +537 -0
  31. package/dist/repository/intelligence.js.map +1 -0
  32. package/dist/repository/native-adoption.d.ts +36 -0
  33. package/dist/repository/native-adoption.d.ts.map +1 -0
  34. package/dist/repository/native-adoption.js +146 -0
  35. package/dist/repository/native-adoption.js.map +1 -0
  36. package/dist/repository/scan.d.ts.map +1 -1
  37. package/dist/repository/scan.js +4 -0
  38. package/dist/repository/scan.js.map +1 -1
  39. package/dist/runtime/authority-plans.d.ts +43 -0
  40. package/dist/runtime/authority-plans.d.ts.map +1 -0
  41. package/dist/runtime/authority-plans.js +173 -0
  42. package/dist/runtime/authority-plans.js.map +1 -0
  43. package/dist/runtime/codex.d.ts.map +1 -1
  44. package/dist/runtime/codex.js +24 -5
  45. package/dist/runtime/codex.js.map +1 -1
  46. package/dist/runtime/context.d.ts.map +1 -1
  47. package/dist/runtime/context.js +36 -0
  48. package/dist/runtime/context.js.map +1 -1
  49. package/dist/runtime/delivery.d.ts +8 -1
  50. package/dist/runtime/delivery.d.ts.map +1 -1
  51. package/dist/runtime/delivery.js +187 -74
  52. package/dist/runtime/delivery.js.map +1 -1
  53. package/dist/runtime/effect-boundary.d.ts +38 -0
  54. package/dist/runtime/effect-boundary.d.ts.map +1 -0
  55. package/dist/runtime/effect-boundary.js +59 -0
  56. package/dist/runtime/effect-boundary.js.map +1 -0
  57. package/dist/runtime/github.d.ts +24 -0
  58. package/dist/runtime/github.d.ts.map +1 -1
  59. package/dist/runtime/github.js +117 -2
  60. package/dist/runtime/github.js.map +1 -1
  61. package/dist/runtime/inputs.js.map +1 -1
  62. package/dist/runtime/lifecycle.d.ts +5 -0
  63. package/dist/runtime/lifecycle.d.ts.map +1 -1
  64. package/dist/runtime/lifecycle.js +60 -16
  65. package/dist/runtime/lifecycle.js.map +1 -1
  66. package/dist/runtime/merge.d.ts +73 -0
  67. package/dist/runtime/merge.d.ts.map +1 -0
  68. package/dist/runtime/merge.js +299 -0
  69. package/dist/runtime/merge.js.map +1 -0
  70. package/dist/runtime/public-metadata.d.ts +3 -0
  71. package/dist/runtime/public-metadata.d.ts.map +1 -0
  72. package/dist/runtime/public-metadata.js +15 -0
  73. package/dist/runtime/public-metadata.js.map +1 -0
  74. package/dist/runtime/repair.d.ts +12 -0
  75. package/dist/runtime/repair.d.ts.map +1 -0
  76. package/dist/runtime/repair.js +34 -0
  77. package/dist/runtime/repair.js.map +1 -0
  78. package/dist/runtime/repository.d.ts +18 -0
  79. package/dist/runtime/repository.d.ts.map +1 -1
  80. package/dist/runtime/repository.js +114 -2
  81. package/dist/runtime/repository.js.map +1 -1
  82. package/dist/runtime/state.d.ts +42 -1
  83. package/dist/runtime/state.d.ts.map +1 -1
  84. package/dist/runtime/state.js +324 -11
  85. package/dist/runtime/state.js.map +1 -1
  86. package/dist/runtime/usage.d.ts +12 -0
  87. package/dist/runtime/usage.d.ts.map +1 -0
  88. package/dist/runtime/usage.js +45 -0
  89. package/dist/runtime/usage.js.map +1 -0
  90. package/dist/runtime/verifier.d.ts.map +1 -1
  91. package/dist/runtime/verifier.js +12 -0
  92. package/dist/runtime/verifier.js.map +1 -1
  93. package/dist/runtime/worker.d.ts +1 -0
  94. package/dist/runtime/worker.d.ts.map +1 -1
  95. package/dist/runtime/worker.js.map +1 -1
  96. package/dist/version.d.ts +1 -1
  97. package/dist/version.js +1 -1
  98. package/dist/workflows/founder.d.ts.map +1 -1
  99. package/dist/workflows/founder.js +5 -0
  100. package/dist/workflows/founder.js.map +1 -1
  101. package/node_modules/typescript/LICENSE.txt +55 -0
  102. package/node_modules/typescript/README.md +50 -0
  103. package/node_modules/typescript/SECURITY.md +39 -0
  104. package/node_modules/typescript/ThirdPartyNoticeText.txt +193 -0
  105. package/node_modules/typescript/bin/tsc +2 -0
  106. package/node_modules/typescript/bin/tsserver +2 -0
  107. package/node_modules/typescript/lib/_tsc.js +134465 -0
  108. package/node_modules/typescript/lib/_tsserver.js +659 -0
  109. package/node_modules/typescript/lib/_typingsInstaller.js +222 -0
  110. package/node_modules/typescript/lib/cs/diagnosticMessages.generated.json +2129 -0
  111. package/node_modules/typescript/lib/de/diagnosticMessages.generated.json +2125 -0
  112. package/node_modules/typescript/lib/es/diagnosticMessages.generated.json +2129 -0
  113. package/node_modules/typescript/lib/fr/diagnosticMessages.generated.json +2129 -0
  114. package/node_modules/typescript/lib/it/diagnosticMessages.generated.json +2125 -0
  115. package/node_modules/typescript/lib/ja/diagnosticMessages.generated.json +2129 -0
  116. package/node_modules/typescript/lib/ko/diagnosticMessages.generated.json +2129 -0
  117. package/node_modules/typescript/lib/lib.d.ts +20 -0
  118. package/node_modules/typescript/lib/lib.decorators.d.ts +382 -0
  119. package/node_modules/typescript/lib/lib.decorators.legacy.d.ts +20 -0
  120. package/node_modules/typescript/lib/lib.dom.asynciterable.d.ts +18 -0
  121. package/node_modules/typescript/lib/lib.dom.d.ts +45125 -0
  122. package/node_modules/typescript/lib/lib.dom.iterable.d.ts +18 -0
  123. package/node_modules/typescript/lib/lib.es2015.collection.d.ts +150 -0
  124. package/node_modules/typescript/lib/lib.es2015.core.d.ts +595 -0
  125. package/node_modules/typescript/lib/lib.es2015.d.ts +26 -0
  126. package/node_modules/typescript/lib/lib.es2015.generator.d.ts +75 -0
  127. package/node_modules/typescript/lib/lib.es2015.iterable.d.ts +603 -0
  128. package/node_modules/typescript/lib/lib.es2015.promise.d.ts +79 -0
  129. package/node_modules/typescript/lib/lib.es2015.proxy.d.ts +126 -0
  130. package/node_modules/typescript/lib/lib.es2015.reflect.d.ts +142 -0
  131. package/node_modules/typescript/lib/lib.es2015.symbol.d.ts +44 -0
  132. package/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts +324 -0
  133. package/node_modules/typescript/lib/lib.es2016.array.include.d.ts +114 -0
  134. package/node_modules/typescript/lib/lib.es2016.d.ts +19 -0
  135. package/node_modules/typescript/lib/lib.es2016.full.d.ts +21 -0
  136. package/node_modules/typescript/lib/lib.es2016.intl.d.ts +29 -0
  137. package/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts +19 -0
  138. package/node_modules/typescript/lib/lib.es2017.d.ts +24 -0
  139. package/node_modules/typescript/lib/lib.es2017.date.d.ts +29 -0
  140. package/node_modules/typescript/lib/lib.es2017.full.d.ts +21 -0
  141. package/node_modules/typescript/lib/lib.es2017.intl.d.ts +42 -0
  142. package/node_modules/typescript/lib/lib.es2017.object.d.ts +47 -0
  143. package/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts +133 -0
  144. package/node_modules/typescript/lib/lib.es2017.string.d.ts +43 -0
  145. package/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts +51 -0
  146. package/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts +75 -0
  147. package/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts +51 -0
  148. package/node_modules/typescript/lib/lib.es2018.d.ts +22 -0
  149. package/node_modules/typescript/lib/lib.es2018.full.d.ts +22 -0
  150. package/node_modules/typescript/lib/lib.es2018.intl.d.ts +81 -0
  151. package/node_modules/typescript/lib/lib.es2018.promise.d.ts +28 -0
  152. package/node_modules/typescript/lib/lib.es2018.regexp.d.ts +35 -0
  153. package/node_modules/typescript/lib/lib.es2019.array.d.ts +77 -0
  154. package/node_modules/typescript/lib/lib.es2019.d.ts +22 -0
  155. package/node_modules/typescript/lib/lib.es2019.full.d.ts +22 -0
  156. package/node_modules/typescript/lib/lib.es2019.intl.d.ts +21 -0
  157. package/node_modules/typescript/lib/lib.es2019.object.d.ts +31 -0
  158. package/node_modules/typescript/lib/lib.es2019.string.d.ts +35 -0
  159. package/node_modules/typescript/lib/lib.es2019.symbol.d.ts +22 -0
  160. package/node_modules/typescript/lib/lib.es2020.bigint.d.ts +763 -0
  161. package/node_modules/typescript/lib/lib.es2020.d.ts +25 -0
  162. package/node_modules/typescript/lib/lib.es2020.date.d.ts +40 -0
  163. package/node_modules/typescript/lib/lib.es2020.full.d.ts +22 -0
  164. package/node_modules/typescript/lib/lib.es2020.intl.d.ts +472 -0
  165. package/node_modules/typescript/lib/lib.es2020.number.d.ts +26 -0
  166. package/node_modules/typescript/lib/lib.es2020.promise.d.ts +45 -0
  167. package/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts +97 -0
  168. package/node_modules/typescript/lib/lib.es2020.string.d.ts +42 -0
  169. package/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts +39 -0
  170. package/node_modules/typescript/lib/lib.es2021.d.ts +21 -0
  171. package/node_modules/typescript/lib/lib.es2021.full.d.ts +22 -0
  172. package/node_modules/typescript/lib/lib.es2021.intl.d.ts +164 -0
  173. package/node_modules/typescript/lib/lib.es2021.promise.d.ts +46 -0
  174. package/node_modules/typescript/lib/lib.es2021.string.d.ts +31 -0
  175. package/node_modules/typescript/lib/lib.es2021.weakref.d.ts +76 -0
  176. package/node_modules/typescript/lib/lib.es2022.array.d.ts +119 -0
  177. package/node_modules/typescript/lib/lib.es2022.d.ts +23 -0
  178. package/node_modules/typescript/lib/lib.es2022.error.d.ts +73 -0
  179. package/node_modules/typescript/lib/lib.es2022.full.d.ts +22 -0
  180. package/node_modules/typescript/lib/lib.es2022.intl.d.ts +143 -0
  181. package/node_modules/typescript/lib/lib.es2022.object.d.ts +24 -0
  182. package/node_modules/typescript/lib/lib.es2022.regexp.d.ts +37 -0
  183. package/node_modules/typescript/lib/lib.es2022.string.d.ts +23 -0
  184. package/node_modules/typescript/lib/lib.es2023.array.d.ts +922 -0
  185. package/node_modules/typescript/lib/lib.es2023.collection.d.ts +19 -0
  186. package/node_modules/typescript/lib/lib.es2023.d.ts +20 -0
  187. package/node_modules/typescript/lib/lib.es2023.full.d.ts +22 -0
  188. package/node_modules/typescript/lib/lib.es2023.intl.d.ts +62 -0
  189. package/node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts +63 -0
  190. package/node_modules/typescript/lib/lib.es2024.collection.d.ts +27 -0
  191. package/node_modules/typescript/lib/lib.es2024.d.ts +24 -0
  192. package/node_modules/typescript/lib/lib.es2024.full.d.ts +22 -0
  193. package/node_modules/typescript/lib/lib.es2024.object.d.ts +27 -0
  194. package/node_modules/typescript/lib/lib.es2024.promise.d.ts +33 -0
  195. package/node_modules/typescript/lib/lib.es2024.regexp.d.ts +23 -0
  196. package/node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts +66 -0
  197. package/node_modules/typescript/lib/lib.es2024.string.d.ts +27 -0
  198. package/node_modules/typescript/lib/lib.es2025.collection.d.ts +94 -0
  199. package/node_modules/typescript/lib/lib.es2025.d.ts +23 -0
  200. package/node_modules/typescript/lib/lib.es2025.float16.d.ts +443 -0
  201. package/node_modules/typescript/lib/lib.es2025.full.d.ts +22 -0
  202. package/node_modules/typescript/lib/lib.es2025.intl.d.ts +200 -0
  203. package/node_modules/typescript/lib/lib.es2025.iterator.d.ts +146 -0
  204. package/node_modules/typescript/lib/lib.es2025.promise.d.ts +32 -0
  205. package/node_modules/typescript/lib/lib.es2025.regexp.d.ts +30 -0
  206. package/node_modules/typescript/lib/lib.es5.d.ts +4599 -0
  207. package/node_modules/typescript/lib/lib.es6.d.ts +21 -0
  208. package/node_modules/typescript/lib/lib.esnext.array.d.ts +33 -0
  209. package/node_modules/typescript/lib/lib.esnext.collection.d.ts +47 -0
  210. package/node_modules/typescript/lib/lib.esnext.d.ts +27 -0
  211. package/node_modules/typescript/lib/lib.esnext.date.d.ts +21 -0
  212. package/node_modules/typescript/lib/lib.esnext.decorators.d.ts +26 -0
  213. package/node_modules/typescript/lib/lib.esnext.disposable.d.ts +191 -0
  214. package/node_modules/typescript/lib/lib.esnext.error.d.ts +22 -0
  215. package/node_modules/typescript/lib/lib.esnext.full.d.ts +22 -0
  216. package/node_modules/typescript/lib/lib.esnext.intl.d.ts +107 -0
  217. package/node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts +23 -0
  218. package/node_modules/typescript/lib/lib.esnext.temporal.d.ts +485 -0
  219. package/node_modules/typescript/lib/lib.esnext.typedarrays.d.ts +90 -0
  220. package/node_modules/typescript/lib/lib.scripthost.d.ts +320 -0
  221. package/node_modules/typescript/lib/lib.webworker.asynciterable.d.ts +18 -0
  222. package/node_modules/typescript/lib/lib.webworker.d.ts +15606 -0
  223. package/node_modules/typescript/lib/lib.webworker.importscripts.d.ts +21 -0
  224. package/node_modules/typescript/lib/lib.webworker.iterable.d.ts +18 -0
  225. package/node_modules/typescript/lib/pl/diagnosticMessages.generated.json +2129 -0
  226. package/node_modules/typescript/lib/pt-br/diagnosticMessages.generated.json +2129 -0
  227. package/node_modules/typescript/lib/ru/diagnosticMessages.generated.json +2125 -0
  228. package/node_modules/typescript/lib/tr/diagnosticMessages.generated.json +2129 -0
  229. package/node_modules/typescript/lib/tsc.js +8 -0
  230. package/node_modules/typescript/lib/tsserver.js +8 -0
  231. package/node_modules/typescript/lib/tsserverlibrary.d.ts +17 -0
  232. package/node_modules/typescript/lib/tsserverlibrary.js +21 -0
  233. package/node_modules/typescript/lib/typesMap.json +497 -0
  234. package/node_modules/typescript/lib/typescript.d.ts +11448 -0
  235. package/node_modules/typescript/lib/typescript.js +201039 -0
  236. package/node_modules/typescript/lib/typingsInstaller.js +8 -0
  237. package/node_modules/typescript/lib/watchGuard.js +53 -0
  238. package/node_modules/typescript/lib/zh-cn/diagnosticMessages.generated.json +2129 -0
  239. package/node_modules/typescript/lib/zh-tw/diagnosticMessages.generated.json +2125 -0
  240. package/node_modules/typescript/package.json +118 -0
  241. package/package.json +7 -4
  242. package/schemas/audit-report.schema.json +1 -0
  243. package/schemas/change-request.schema.json +189 -0
  244. package/schemas/context-manifest.schema.json +50 -0
  245. package/schemas/delivery-record.schema.json +109 -0
  246. package/schemas/mill-config.schema.json +50 -2
  247. package/schemas/repository-intelligence.schema.json +200 -0
  248. package/schemas/review-result.schema.json +21 -0
  249. package/schemas/task-packet.schema.json +12 -0
@@ -1,12 +1,14 @@
1
+ import { assertEffectAllowsNewWork, assertNoUnresolvedEffect, reconcilableDraftEffect, maximumRemoteEffectAttempts, } from "./effect-boundary.js";
2
+ import { parse as parseYaml } from "yaml";
1
3
  import { canonicalDigest } from "../contracts/canonical.js";
2
- import { deliveryRecordSchema, reviewResultSchema, validationEvidenceSchema, } from "../contracts/schemas.js";
4
+ import { deliveryRecordSchema, millConfigSchema, reviewResultSchema, validationEvidenceSchema, } from "../contracts/schemas.js";
3
5
  import { ExitCode, MillError, asMillError } from "../errors.js";
4
6
  import { createGitHubAdapter, } from "./github.js";
5
7
  import { loadRuntimeInputs } from "./inputs.js";
6
8
  import { assertRunBindings } from "./lifecycle.js";
7
- import { commonGitDirectory, repositoryRemoteUrl } from "./repository.js";
9
+ import { publicPullRequestTitle } from "./public-metadata.js";
10
+ import { commonGitDirectory, captureReviewScope, readCommittedFile, repositoryRemoteUrl, } from "./repository.js";
8
11
  import { acquireWriterLease, publicRunRecord, StateStore, } from "./state.js";
9
- const maximumRemoteEffectAttempts = 2;
10
12
  function operationDeadline(config) {
11
13
  return Date.now() + config.pollTimeoutSeconds * 1000;
12
14
  }
@@ -69,35 +71,27 @@ function setRunBlocker(store, run, code, eventType, details = {}) {
69
71
  : store.transition(run.id, "blocked", eventType, { code, ...details });
70
72
  }
71
73
  function reconcileAbsentEffect(store, run, delivery, effectValue) {
72
- if (cancellationRequested(store, run.id)) {
73
- stopCancelledDelivery(store, run.id, delivery);
74
- }
75
- if (effectValue.attemptCount >= maximumRemoteEffectAttempts) {
76
- const blocked = persistDelivery(store, run.id, {
77
- ...upsertEffect(delivery, {
78
- ...effectValue,
79
- status: "blocked",
80
- errorCode: "REMOTE_EFFECT_RETRY_EXHAUSTED",
81
- updatedAt: new Date().toISOString(),
82
- }),
83
- state: "blocked",
84
- lastErrorCode: "REMOTE_EFFECT_RETRY_EXHAUSTED",
85
- }, "delivery.retry_exhausted", { effectId: effectValue.id });
86
- const blockedRun = setRunBlocker(store, run, "REMOTE_EFFECT_RETRY_EXHAUSTED", "delivery.blocked");
87
- return { run: publicRunRecord(blockedRun), delivery: blocked };
88
- }
89
- const retryable = persistDelivery(store, run.id, {
74
+ const exhausted = effectValue.attemptCount >= maximumRemoteEffectAttempts;
75
+ const errorCode = exhausted ? "REMOTE_EFFECT_RETRY_EXHAUSTED" : null;
76
+ return completeDraftReconciliation(store, run, {
90
77
  ...upsertEffect(delivery, {
91
78
  ...effectValue,
92
- status: "retryable_absent",
93
- errorCode: null,
79
+ status: exhausted ? "blocked" : "retryable_absent",
80
+ errorCode,
94
81
  updatedAt: new Date().toISOString(),
95
82
  }),
96
- state: "proposing",
97
- lastErrorCode: null,
98
- }, "delivery.effect_absent", { effectId: effectValue.id, attemptCount: effectValue.attemptCount });
99
- const retryableRun = store.transition(run.id, "proposing", "delivery.retry_authorized");
100
- return { run: publicRunRecord(retryableRun), delivery: retryable };
83
+ state: exhausted ? "blocked" : "proposing",
84
+ lastErrorCode: errorCode,
85
+ });
86
+ }
87
+ function completeDraftReconciliation(store, run, delivery) {
88
+ if (run.deliveryJson === undefined)
89
+ throw new MillError("DELIVERY_PLAN_MISSING", "The journal disappeared during readback.", ExitCode.data);
90
+ const settled = store.settleDraftEffect(run.id, run.deliveryJson, JSON.stringify(deliveryRecordSchema.parse(delivery)));
91
+ const journal = storedDelivery(settled);
92
+ if (journal.state === "cancelled")
93
+ throw new MillError("OPERATOR_CANCELLED", "The effect was reconciled; cancellation prevents further mutation.", ExitCode.temporary);
94
+ return { run: publicRunRecord(settled), delivery: journal };
101
95
  }
102
96
  async function assertReviewedCandidate(root, run, inputs) {
103
97
  if (run.status !== "reviewed" && run.status !== "proposing") {
@@ -122,8 +116,31 @@ async function assertReviewedCandidate(root, run, inputs) {
122
116
  throw new MillError("LOCAL_EVIDENCE_STALE", "Validation and local review must pass on the exact candidate head.", ExitCode.configuration);
123
117
  }
124
118
  const candidate = await assertRunBindings(root, run, inputs);
119
+ const expectedScope = await captureReviewScope(candidate.worktree, review.scope?.baseCommit ??
120
+ (inputs.config.propose === undefined
121
+ ? run.baseCommit
122
+ : `refs/heads/${inputs.config.propose.baseBranch}`), candidate.commit);
123
+ if (review.scope?.digest !== expectedScope.digest) {
124
+ throw new MillError("REVIEW_SCOPE_STALE", "Delivery requires a fresh complete base-to-candidate review, including preparatory commits.", ExitCode.configuration);
125
+ }
125
126
  return { commit: candidate.commit, tree: candidate.tree };
126
127
  }
128
+ async function assertProviderReviewScope(run, config, adapter, deadlineMs) {
129
+ const base = await adapter.readBranch({
130
+ config,
131
+ branch: config.baseBranch,
132
+ deadlineMs,
133
+ });
134
+ if (base === null ||
135
+ run.candidateCommit === undefined ||
136
+ run.worktreePath === undefined)
137
+ throw new MillError("REVIEW_BASE_UNAVAILABLE", "The authoritative PR base and local candidate must be available.", ExitCode.configuration);
138
+ const review = reviewResultSchema.parse(JSON.parse(run.reviewJson ?? "null"));
139
+ const scope = await captureReviewScope(run.worktreePath, base, run.candidateCommit);
140
+ if (review.scope?.digest !== scope.digest)
141
+ throw new MillError("REVIEW_SCOPE_STALE", "The reviewed diff differs from GitHub's actual PR base. Before any remote attempt, use attended review --refresh --base with the exact locally available provider commit, then plan delivery again. Do not change frozen refs.", ExitCode.configuration);
142
+ // Reading the provider SHA never fetches or changes local refs implicitly.
143
+ }
127
144
  function expectedRemoteUrls(config, cloneUrl) {
128
145
  return new Set([
129
146
  cloneUrl,
@@ -164,6 +181,17 @@ function target(config, binding) {
164
181
  actorId: binding.actorId,
165
182
  };
166
183
  }
184
+ function postMergeRequiredChecks(config) {
185
+ return config.postMergeRequiredChecks ?? config.requiredChecks;
186
+ }
187
+ function postMergePolicySource(config) {
188
+ return config.postMergeRequiredChecks === undefined
189
+ ? "implicit_default"
190
+ : "configured";
191
+ }
192
+ function isCheckSubset(candidate, required) {
193
+ return candidate.every((check) => required.includes(check));
194
+ }
167
195
  function proposalDigest(input) {
168
196
  return canonicalDigest({
169
197
  schemaVersion: "1",
@@ -176,6 +204,10 @@ function proposalDigest(input) {
176
204
  branchName: input.branchName,
177
205
  approvalExpiresAt: input.approvalExpiresAt,
178
206
  requiredChecks: input.config.requiredChecks,
207
+ ...(input.config.checkProducers === undefined
208
+ ? {}
209
+ : { checkProducers: input.config.checkProducers }),
210
+ postMergeRequiredChecks: postMergeRequiredChecks(input.config),
179
211
  reviewPolicy: input.config.reviewPolicy,
180
212
  allowedMergeMethods: input.config.allowedMergeMethods,
181
213
  allowedMergerLogins: input.config.allowedMergerLogins,
@@ -240,10 +272,54 @@ function assertPushBoundaryPullRequest(pullRequest, delivery, expectedOldCommit)
240
272
  throw new MillError("PULL_REQUEST_IDENTITY_MISMATCH", "The recorded pull request is no longer the expected open draft at the observed branch head.", ExitCode.configuration);
241
273
  }
242
274
  }
243
- function assertDeliveryContinuity(input) {
275
+ async function candidateUsedImplicitPostMergePolicy(root, delivery) {
276
+ let source;
277
+ try {
278
+ source = await readCommittedFile(root, delivery.candidateCommit, "mill.yaml");
279
+ }
280
+ catch (error) {
281
+ throw new MillError("LEGACY_POST_MERGE_POLICY_SOURCE_UNAVAILABLE", "The reviewed candidate's mill.yaml cannot be read to prove an implicit post-merge policy.", ExitCode.configuration, { cause: String(error) });
282
+ }
283
+ let raw;
284
+ try {
285
+ raw = parseYaml(source);
286
+ }
287
+ catch (error) {
288
+ throw new MillError("LEGACY_POST_MERGE_POLICY_SOURCE_INVALID", "The reviewed candidate's mill.yaml is not valid YAML.", ExitCode.configuration, { cause: String(error) });
289
+ }
290
+ const parsed = millConfigSchema.safeParse(raw);
291
+ if (!parsed.success) {
292
+ throw new MillError("LEGACY_POST_MERGE_POLICY_SOURCE_INVALID", "The reviewed candidate's mill.yaml does not satisfy the Mill configuration contract.", ExitCode.configuration);
293
+ }
294
+ return parsed.data.propose?.postMergeRequiredChecks === undefined;
295
+ }
296
+ async function assertDeliveryContinuity(input) {
244
297
  const { run, inputs, config, delivery, binding } = input;
298
+ const configuredPostMergeChecks = postMergeRequiredChecks(config);
299
+ const configuredLegacyPolicy = input.allowLegacyPostMergePolicy === true &&
300
+ delivery.postMergePolicySource === undefined &&
301
+ delivery.postMergeRequiredChecks !== undefined &&
302
+ delivery.legacyPostMergePolicyConfigDigest === undefined &&
303
+ config.postMergeRequiredChecks !== undefined &&
304
+ isCheckSubset(config.postMergeRequiredChecks, delivery.requiredChecks) &&
305
+ JSON.stringify(delivery.postMergeRequiredChecks) ===
306
+ JSON.stringify(delivery.requiredChecks) &&
307
+ (await candidateUsedImplicitPostMergePolicy(input.root, delivery));
308
+ const bindLegacyPostMergePolicy = input.allowLegacyPostMergePolicy === true &&
309
+ (delivery.postMergeRequiredChecks === undefined ||
310
+ configuredLegacyPolicy) &&
311
+ delivery.legacyPostMergePolicyConfigDigest === undefined &&
312
+ config.postMergeRequiredChecks !== undefined &&
313
+ isCheckSubset(config.postMergeRequiredChecks, delivery.requiredChecks);
314
+ const hasBoundLegacyPostMergePolicy = input.allowLegacyPostMergePolicy === true &&
315
+ delivery.postMergeRequiredChecks !== undefined &&
316
+ delivery.postMergePolicySource === "legacy_migrated" &&
317
+ delivery.legacyPostMergePolicyConfigDigest === inputs.configDigest;
318
+ const configDigestMatches = bindLegacyPostMergePolicy ||
319
+ hasBoundLegacyPostMergePolicy ||
320
+ run.configDigest === inputs.configDigest;
245
321
  if (run.taskDigest !== inputs.taskDigest ||
246
- run.configDigest !== inputs.configDigest ||
322
+ !configDigestMatches ||
247
323
  delivery.runId !== run.id ||
248
324
  delivery.candidateCommit !== run.candidateCommit ||
249
325
  delivery.candidateTree !== run.candidateTree ||
@@ -258,6 +334,15 @@ function assertDeliveryContinuity(input) {
258
334
  delivery.target.cloneUrl !== binding.cloneUrl ||
259
335
  JSON.stringify(delivery.requiredChecks) !==
260
336
  JSON.stringify(config.requiredChecks) ||
337
+ canonicalDigest(delivery.checkProducers ?? {}) !==
338
+ canonicalDigest(config.checkProducers ?? {}) ||
339
+ (delivery.postMergeRequiredChecks !== undefined &&
340
+ !bindLegacyPostMergePolicy &&
341
+ !hasBoundLegacyPostMergePolicy &&
342
+ JSON.stringify(delivery.postMergeRequiredChecks) !==
343
+ JSON.stringify(configuredPostMergeChecks)) ||
344
+ (delivery.legacyPostMergePolicyConfigDigest !== undefined &&
345
+ !hasBoundLegacyPostMergePolicy) ||
261
346
  JSON.stringify(delivery.reviewPolicy) !==
262
347
  JSON.stringify(config.reviewPolicy) ||
263
348
  JSON.stringify(delivery.allowedMergerLogins) !==
@@ -266,13 +351,21 @@ function assertDeliveryContinuity(input) {
266
351
  JSON.stringify(config.allowedMergeMethods)) {
267
352
  throw new MillError("DELIVERY_AUTHORITY_DRIFT", "The task, configuration, candidate, actor, or repository changed after delivery approval.", ExitCode.configuration);
268
353
  }
354
+ return { bindLegacyPostMergePolicy };
269
355
  }
270
- function checkDecision(required, checks) {
356
+ export function checkDecision(required, checks, producers, phase = "pull_request", headSha) {
271
357
  const missing = [];
272
358
  const failed = [];
273
359
  let pending = false;
274
360
  for (const name of required) {
275
- const matching = checks.filter((check) => check.name === name);
361
+ const producer = producers?.[name];
362
+ const matching = checks.filter((check) => check.name === name &&
363
+ (producers === undefined ||
364
+ (producer !== undefined &&
365
+ check.appId === producer.appId &&
366
+ check.workflowPath === producer.workflowPath &&
367
+ check.event === phase &&
368
+ check.headSha === headSha)));
276
369
  if (matching.length === 0) {
277
370
  missing.push(name);
278
371
  pending = true;
@@ -292,14 +385,14 @@ function checkDecision(required, checks) {
292
385
  failed,
293
386
  };
294
387
  }
295
- function actionableFeedback(observation, reviewPolicy, candidateCommit) {
388
+ export function actionableFeedback(observation, reviewPolicy, candidateCommit) {
296
389
  if (reviewPolicy.mode !== "github_required")
297
390
  return [];
298
391
  return observation.feedback.filter((item) => item.commitId === candidateCommit &&
299
392
  reviewPolicy.requiredReviewerLogins.includes(item.actorLogin) &&
300
393
  item.priority !== "P3");
301
394
  }
302
- function reviewsPassed(observation, reviewPolicy, candidateCommit) {
395
+ export function reviewsPassed(observation, reviewPolicy, candidateCommit) {
303
396
  if (reviewPolicy.mode === "local_only")
304
397
  return true;
305
398
  return reviewPolicy.requiredReviewerLogins.every((login) => {
@@ -353,6 +446,7 @@ export async function planDraftPr(input) {
353
446
  try {
354
447
  lease = await acquireWriterLease(store);
355
448
  const run = store.getRun(input.runId);
449
+ assertEffectAllowsNewWork(run);
356
450
  const candidate = await assertReviewedCandidate(input.root, run, inputs);
357
451
  const adapter = input.adapter ?? createGitHubAdapter(input.root);
358
452
  const binding = await adapter.inspect({
@@ -361,6 +455,7 @@ export async function planDraftPr(input) {
361
455
  ...(input.signal === undefined ? {} : { signal: input.signal }),
362
456
  });
363
457
  await assertBinding(input.root, config, binding);
458
+ await assertProviderReviewScope(run, config, adapter, operationDeadline(config));
364
459
  const plannedBranch = branchName(config, run);
365
460
  const approvalExpiresAt = new Date(Date.now() + config.approvalTtlSeconds * 1000).toISOString();
366
461
  const plannedTarget = target(config, binding);
@@ -393,6 +488,11 @@ export async function planDraftPr(input) {
393
488
  candidateCommit: candidate.commit,
394
489
  candidateTree: candidate.tree,
395
490
  requiredChecks: config.requiredChecks,
491
+ ...(config.checkProducers === undefined
492
+ ? {}
493
+ : { checkProducers: config.checkProducers }),
494
+ postMergeRequiredChecks: postMergeRequiredChecks(config),
495
+ postMergePolicySource: postMergePolicySource(config),
396
496
  reviewPolicy: config.reviewPolicy,
397
497
  allowedMergerLogins: config.allowedMergerLogins,
398
498
  allowedMergeMethods: config.allowedMergeMethods,
@@ -452,6 +552,7 @@ export async function openDraftPr(input) {
452
552
  if (run.status !== "proposing") {
453
553
  throw new MillError("DELIVERY_NOT_APPLICABLE", "Draft-PR open requires an approved plan with no unknown external effect.", ExitCode.configuration);
454
554
  }
555
+ assertEffectAllowsNewWork(run);
455
556
  const candidate = await assertReviewedCandidate(input.root, run, inputs);
456
557
  let delivery = storedDelivery(run);
457
558
  assertRemoteMutationNotCancelled(store, run.id, delivery);
@@ -469,6 +570,7 @@ export async function openDraftPr(input) {
469
570
  ...(input.signal === undefined ? {} : { signal: input.signal }),
470
571
  });
471
572
  await assertBinding(input.root, config, binding);
573
+ await assertProviderReviewScope(run, config, adapter, deadlineMs);
472
574
  const liveDigest = proposalDigest({
473
575
  run,
474
576
  candidate,
@@ -495,10 +597,6 @@ export async function openDraftPr(input) {
495
597
  readback.branchSha !== delivery.remoteHeadCommit) {
496
598
  throw new MillError("REMOTE_BRANCH_CONFLICT", "The Mill delivery branch moved outside the exact expected-head precondition.", ExitCode.configuration);
497
599
  }
498
- if (push !== undefined &&
499
- (push.status === "call_started" || push.status === "effect_unknown")) {
500
- markUnknown(store, run, delivery, push, "GITHUB_PUSH_OUTCOME_UNKNOWN");
501
- }
502
600
  if (push?.status === "verified") {
503
601
  throw new MillError("REMOTE_BRANCH_CONFLICT", "A previously verified Mill branch no longer has its bound candidate head.", ExitCode.configuration);
504
602
  }
@@ -529,6 +627,7 @@ export async function openDraftPr(input) {
529
627
  throw new MillError("REMOTE_BRANCH_CONFLICT", "The Mill delivery branch changed after push intent and before the mutation boundary.", ExitCode.configuration);
530
628
  }
531
629
  assertPushBoundaryPullRequest(readback.pullRequest, delivery, push.expectedOldCommit);
630
+ await assertProviderReviewScope(run, config, adapter, deadlineMs);
532
631
  push = {
533
632
  ...push,
534
633
  status: "call_started",
@@ -618,11 +717,6 @@ export async function openDraftPr(input) {
618
717
  throw new MillError("PULL_REQUEST_DISAPPEARED", "The recorded pull request cannot be found by immutable delivery identity.", ExitCode.configuration);
619
718
  }
620
719
  if (pullRequest === null) {
621
- if (prEffect !== undefined &&
622
- (prEffect.status === "call_started" ||
623
- prEffect.status === "effect_unknown")) {
624
- markUnknown(store, run, delivery, prEffect, "GITHUB_PR_OUTCOME_UNKNOWN");
625
- }
626
720
  if (prEffect?.status === "verified" || delivery.pullRequest !== null) {
627
721
  throw new MillError("PULL_REQUEST_DISAPPEARED", "A previously verified pull request cannot be found by immutable delivery identity.", ExitCode.configuration);
628
722
  }
@@ -642,6 +736,7 @@ export async function openDraftPr(input) {
642
736
  updatedAt: new Date().toISOString(),
643
737
  };
644
738
  delivery = persistDelivery(store, run.id, upsertEffect(delivery, prEffect), "delivery.pull_request_intent", { effectId: prEffect.id });
739
+ await assertProviderReviewScope(run, config, adapter, deadlineMs);
645
740
  prEffect = {
646
741
  ...prEffect,
647
742
  status: "call_started",
@@ -654,7 +749,7 @@ export async function openDraftPr(input) {
654
749
  pullRequest = await adapter.createDraftPullRequest({
655
750
  config,
656
751
  branch: delivery.branchName,
657
- title: inputs.task.commit.message.slice(0, 240),
752
+ title: publicPullRequestTitle(inputs.task.commit.message),
658
753
  body: `${deliveryMarker(delivery.deliveryKey)}\n\nGenerated by Mill from an attended, locally validated and reviewed run. The current candidate identity is the pull-request head; configured human merge authority remains external.`,
659
754
  deadlineMs,
660
755
  ...(input.signal === undefined ? {} : { signal: input.signal }),
@@ -738,11 +833,9 @@ export async function reconcileDraftPr(input) {
738
833
  let lease;
739
834
  try {
740
835
  lease = await acquireWriterLease(store);
741
- let run = store.getRun(input.runId);
742
- if (run.status !== "effect_unknown") {
743
- throw new MillError("RECONCILIATION_NOT_REQUIRED", "The run has no unknown GitHub effect to reconcile.", ExitCode.configuration);
744
- }
745
- let delivery = storedDelivery(run);
836
+ const run = store.getRun(input.runId);
837
+ const unknownEffect = reconcilableDraftEffect(run);
838
+ const delivery = storedDelivery(run);
746
839
  const adapter = input.adapter ?? createGitHubAdapter(input.root);
747
840
  const deadlineMs = operationDeadline(config);
748
841
  const binding = await adapter.inspect({
@@ -751,7 +844,14 @@ export async function reconcileDraftPr(input) {
751
844
  ...(input.signal === undefined ? {} : { signal: input.signal }),
752
845
  });
753
846
  await assertBinding(input.root, config, binding);
754
- assertDeliveryContinuity({ run, inputs, config, delivery, binding });
847
+ await assertDeliveryContinuity({
848
+ root: input.root,
849
+ run,
850
+ inputs,
851
+ config,
852
+ delivery,
853
+ binding,
854
+ });
755
855
  const readback = await reconcileReadback({
756
856
  adapter,
757
857
  config,
@@ -759,14 +859,6 @@ export async function reconcileDraftPr(input) {
759
859
  deadlineMs,
760
860
  ...(input.signal === undefined ? {} : { signal: input.signal }),
761
861
  });
762
- const unknownEffects = delivery.effects.filter((item) => item.status === "effect_unknown");
763
- if (unknownEffects.length !== 1) {
764
- throw new MillError("GITHUB_RECONCILIATION_STATE_INVALID", "Exactly one external effect must be unknown before reconciliation.", ExitCode.data);
765
- }
766
- const unknownEffect = unknownEffects[0];
767
- if (unknownEffect === undefined) {
768
- throw new MillError("GITHUB_RECONCILIATION_STATE_INVALID", "The unknown external effect could not be identified.", ExitCode.data);
769
- }
770
862
  if (unknownEffect.kind === "push" &&
771
863
  (readback.branchSha === unknownEffect.expectedOldCommit ||
772
864
  readback.branchSha === delivery.candidateCommit)) {
@@ -787,7 +879,7 @@ export async function reconcileDraftPr(input) {
787
879
  if (unknownEffect.kind === "push" &&
788
880
  readback.branchSha === delivery.candidateCommit &&
789
881
  readback.pullRequest === null) {
790
- delivery = persistDelivery(store, run.id, {
882
+ return completeDraftReconciliation(store, run, {
791
883
  ...upsertEffect(delivery, {
792
884
  ...unknownEffect,
793
885
  status: "verified",
@@ -797,10 +889,7 @@ export async function reconcileDraftPr(input) {
797
889
  state: "proposing",
798
890
  remoteHeadCommit: readback.branchSha,
799
891
  lastErrorCode: null,
800
- }, "delivery.push_reconciled", { effectId: unknownEffect.id });
801
- assertRemoteMutationNotCancelled(store, run.id, delivery);
802
- run = store.transition(run.id, "proposing", "delivery.reconciled");
803
- return { run: publicRunRecord(run), delivery };
892
+ });
804
893
  }
805
894
  if (readback.branchSha !== delivery.candidateCommit) {
806
895
  throw new MillError("REMOTE_BRANCH_CONFLICT", "Authoritative readback found a branch head outside the reconciled effect precondition.", ExitCode.configuration);
@@ -809,7 +898,7 @@ export async function reconcileDraftPr(input) {
809
898
  throw new MillError("GITHUB_RECONCILIATION_STATE_INVALID", "Reconciliation could not classify the pull-request effect.", ExitCode.data);
810
899
  }
811
900
  assertExactPullRequest(readback.pullRequest, delivery, true);
812
- delivery = persistDelivery(store, run.id, {
901
+ return completeDraftReconciliation(store, run, {
813
902
  ...delivery,
814
903
  state: "awaiting_ci",
815
904
  remoteHeadCommit: readback.branchSha,
@@ -827,10 +916,7 @@ export async function reconcileDraftPr(input) {
827
916
  }
828
917
  : item),
829
918
  lastErrorCode: null,
830
- }, "delivery.reconciled", { pullRequestNumber: readback.pullRequest.number });
831
- assertRemoteMutationNotCancelled(store, run.id, delivery);
832
- run = store.transition(run.id, "awaiting_ci", "delivery.awaiting_ci");
833
- return { run: publicRunRecord(run), delivery };
919
+ });
834
920
  }
835
921
  finally {
836
922
  try {
@@ -868,10 +954,12 @@ export async function observeDraftPr(input) {
868
954
  ["REMOTE_CHECKS_FAILED", "REMOTE_REVIEW_FINDINGS"].includes(run.blockCode ?? ""))) {
869
955
  throw new MillError("DELIVERY_NOT_OBSERVABLE", "Run has no draft pull request awaiting policy observation.", ExitCode.configuration);
870
956
  }
957
+ assertEffectAllowsNewWork(run);
871
958
  let delivery = storedDelivery(run);
872
959
  if (delivery.pullRequest === null) {
873
960
  throw new MillError("PULL_REQUEST_IDENTITY_MISSING", "Delivery has no verified pull request identity.", ExitCode.configuration);
874
961
  }
962
+ const pullRequest = delivery.pullRequest;
875
963
  const adapter = input.adapter ?? createGitHubAdapter(input.root);
876
964
  const deadlineMs = operationDeadline(config);
877
965
  const binding = await adapter.inspect({
@@ -880,15 +968,22 @@ export async function observeDraftPr(input) {
880
968
  ...(input.signal === undefined ? {} : { signal: input.signal }),
881
969
  });
882
970
  await assertBinding(input.root, config, binding);
883
- assertDeliveryContinuity({ run, inputs, config, delivery, binding });
971
+ await assertDeliveryContinuity({
972
+ root: input.root,
973
+ run,
974
+ inputs,
975
+ config,
976
+ delivery,
977
+ binding,
978
+ });
884
979
  const observation = await adapter.observe({
885
980
  config,
886
- pullRequestNumber: delivery.pullRequest.number,
981
+ pullRequestNumber: pullRequest.number,
887
982
  deadlineMs,
888
983
  ...(input.signal === undefined ? {} : { signal: input.signal }),
889
984
  });
890
985
  assertObservationIdentity(observation, delivery, false);
891
- const checks = checkDecision(delivery.requiredChecks, observation.checks);
986
+ const checks = checkDecision(delivery.requiredChecks, observation.checks, delivery.checkProducers, "pull_request", delivery.candidateCommit);
892
987
  const feedback = actionableFeedback(observation, delivery.reviewPolicy, delivery.candidateCommit);
893
988
  const observationRecord = {
894
989
  headSha: observation.pullRequest.headSha,
@@ -974,10 +1069,12 @@ export async function finalizeDraftPr(input) {
974
1069
  !(run.status === "blocked" && run.blockCode === "POST_MERGE_CHECKS_FAILED")) {
975
1070
  throw new MillError("DELIVERY_NOT_FINALIZABLE", "Run is not awaiting human merge or post-merge verification.", ExitCode.configuration);
976
1071
  }
1072
+ assertNoUnresolvedEffect(run);
977
1073
  let delivery = storedDelivery(run);
978
1074
  if (delivery.pullRequest === null) {
979
1075
  throw new MillError("PULL_REQUEST_IDENTITY_MISSING", "Delivery has no verified pull request identity.", ExitCode.configuration);
980
1076
  }
1077
+ const pullRequest = delivery.pullRequest;
981
1078
  const adapter = input.adapter ?? createGitHubAdapter(input.root);
982
1079
  const deadlineMs = operationDeadline(config);
983
1080
  const binding = await adapter.inspect({
@@ -986,10 +1083,18 @@ export async function finalizeDraftPr(input) {
986
1083
  ...(input.signal === undefined ? {} : { signal: input.signal }),
987
1084
  });
988
1085
  await assertBinding(input.root, config, binding);
989
- assertDeliveryContinuity({ run, inputs, config, delivery, binding });
1086
+ const continuity = await assertDeliveryContinuity({
1087
+ root: input.root,
1088
+ run,
1089
+ inputs,
1090
+ config,
1091
+ delivery,
1092
+ binding,
1093
+ allowLegacyPostMergePolicy: true,
1094
+ });
990
1095
  const observation = await adapter.observe({
991
1096
  config,
992
- pullRequestNumber: delivery.pullRequest.number,
1097
+ pullRequestNumber: pullRequest.number,
993
1098
  deadlineMs,
994
1099
  ...(input.signal === undefined ? {} : { signal: input.signal }),
995
1100
  });
@@ -1021,6 +1126,14 @@ export async function finalizeDraftPr(input) {
1021
1126
  if (mergeCommit.tree !== delivery.candidateTree) {
1022
1127
  throw new MillError("MERGE_TREE_REVALIDATION_REQUIRED", "The merged tree differs from the reviewed candidate and requires a fresh exact-tree validation before closure.", ExitCode.configuration);
1023
1128
  }
1129
+ if (continuity.bindLegacyPostMergePolicy) {
1130
+ delivery = persistDelivery(store, run.id, {
1131
+ ...delivery,
1132
+ postMergeRequiredChecks: postMergeRequiredChecks(config),
1133
+ postMergePolicySource: "legacy_migrated",
1134
+ legacyPostMergePolicyConfigDigest: inputs.configDigest,
1135
+ }, "delivery.legacy_post_merge_policy_bound", { checks: postMergeRequiredChecks(config).length });
1136
+ }
1024
1137
  delivery = persistDelivery(store, run.id, {
1025
1138
  ...delivery,
1026
1139
  state: "merged",
@@ -1041,7 +1154,7 @@ export async function finalizeDraftPr(input) {
1041
1154
  if (run.status !== "merged" && run.status !== "post_merge_verified") {
1042
1155
  run = store.transition(run.id, "merged", "delivery.merged");
1043
1156
  }
1044
- const checks = checkDecision(delivery.requiredChecks, observation.mergeChecks);
1157
+ const checks = checkDecision(delivery.postMergeRequiredChecks ?? delivery.requiredChecks, observation.mergeChecks, delivery.checkProducers, "push", observation.mergeCommit.sha);
1045
1158
  if (checks.status === "pending") {
1046
1159
  return { run: publicRunRecord(run), delivery };
1047
1160
  }