@on-par/factory-core 0.9.28-next.9 → 0.9.28

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 (273) hide show
  1. package/dist/checkers/app-smoke.d.ts.map +1 -1
  2. package/dist/checkers/app-smoke.js +4 -1
  3. package/dist/checkers/app-smoke.js.map +1 -1
  4. package/dist/checkers/evidence-plan.d.ts +2 -0
  5. package/dist/checkers/evidence-plan.d.ts.map +1 -1
  6. package/dist/checkers/evidence-plan.js +13 -6
  7. package/dist/checkers/evidence-plan.js.map +1 -1
  8. package/dist/checkers/evidence-selector.d.ts +2 -0
  9. package/dist/checkers/evidence-selector.d.ts.map +1 -1
  10. package/dist/checkers/evidence-selector.js +13 -10
  11. package/dist/checkers/evidence-selector.js.map +1 -1
  12. package/dist/checkers/evidence-workspace.d.ts +21 -0
  13. package/dist/checkers/evidence-workspace.d.ts.map +1 -0
  14. package/dist/checkers/evidence-workspace.js +118 -0
  15. package/dist/checkers/evidence-workspace.js.map +1 -0
  16. package/dist/checkers/index.js +1 -1
  17. package/dist/checkers/index.js.map +1 -1
  18. package/dist/checkers/internal-exports.d.ts +3 -1
  19. package/dist/checkers/internal-exports.d.ts.map +1 -1
  20. package/dist/checkers/internal-exports.js +3 -1
  21. package/dist/checkers/internal-exports.js.map +1 -1
  22. package/dist/checkers/resolve-commands.d.ts.map +1 -1
  23. package/dist/checkers/resolve-commands.js +5 -1
  24. package/dist/checkers/resolve-commands.js.map +1 -1
  25. package/dist/config/example.d.ts.map +1 -1
  26. package/dist/config/example.js +5 -2
  27. package/dist/config/example.js.map +1 -1
  28. package/dist/config/index.d.ts +6 -32
  29. package/dist/config/index.d.ts.map +1 -1
  30. package/dist/config/index.js +17 -32
  31. package/dist/config/index.js.map +1 -1
  32. package/dist/config/merge-policy.d.ts +36 -0
  33. package/dist/config/merge-policy.d.ts.map +1 -0
  34. package/dist/config/merge-policy.js +31 -0
  35. package/dist/config/merge-policy.js.map +1 -0
  36. package/dist/config/repo.js +1 -1
  37. package/dist/config/repo.js.map +1 -1
  38. package/dist/config/run-config-env.d.ts +5 -0
  39. package/dist/config/run-config-env.d.ts.map +1 -0
  40. package/dist/config/run-config-env.js +11 -0
  41. package/dist/config/run-config-env.js.map +1 -0
  42. package/dist/config/run-config-ladder.d.ts +18 -0
  43. package/dist/config/run-config-ladder.d.ts.map +1 -0
  44. package/dist/config/run-config-ladder.js +110 -0
  45. package/dist/config/run-config-ladder.js.map +1 -0
  46. package/dist/config/run-config-source.d.ts +6 -6
  47. package/dist/config/run-config-source.d.ts.map +1 -1
  48. package/dist/config/run-config-source.js +16 -15
  49. package/dist/config/run-config-source.js.map +1 -1
  50. package/dist/constitutions/index.d.ts.map +1 -1
  51. package/dist/constitutions/index.js +8 -0
  52. package/dist/constitutions/index.js.map +1 -1
  53. package/dist/environment/process-groups.d.ts +5 -0
  54. package/dist/environment/process-groups.d.ts.map +1 -1
  55. package/dist/environment/process-groups.js +19 -0
  56. package/dist/environment/process-groups.js.map +1 -1
  57. package/dist/events/config-traits.d.ts +1 -1
  58. package/dist/events/config-traits.d.ts.map +1 -1
  59. package/dist/events/config-traits.js +2 -0
  60. package/dist/events/config-traits.js.map +1 -1
  61. package/dist/events/queue-traits.d.ts +1 -1
  62. package/dist/events/queue-traits.d.ts.map +1 -1
  63. package/dist/events/queue-traits.js +8 -1
  64. package/dist/events/queue-traits.js.map +1 -1
  65. package/dist/events/rotation.js +1 -1
  66. package/dist/events/rotation.js.map +1 -1
  67. package/dist/fakes/octokit.d.ts +13 -1
  68. package/dist/fakes/octokit.d.ts.map +1 -1
  69. package/dist/fakes/octokit.js +13 -0
  70. package/dist/fakes/octokit.js.map +1 -1
  71. package/dist/filing/redact.d.ts +1 -0
  72. package/dist/filing/redact.d.ts.map +1 -1
  73. package/dist/filing/redact.js +1 -1
  74. package/dist/filing/redact.js.map +1 -1
  75. package/dist/harness/opencode-version.d.ts +2 -2
  76. package/dist/harness/opencode-version.d.ts.map +1 -1
  77. package/dist/harness/opencode-version.js +3 -3
  78. package/dist/harness/opencode-version.js.map +1 -1
  79. package/dist/internal.d.ts +13 -1
  80. package/dist/internal.d.ts.map +1 -1
  81. package/dist/internal.js +14 -0
  82. package/dist/internal.js.map +1 -1
  83. package/dist/kpis/index.d.ts.map +1 -1
  84. package/dist/kpis/index.js +2 -1
  85. package/dist/kpis/index.js.map +1 -1
  86. package/dist/kpis/park.d.ts.map +1 -1
  87. package/dist/kpis/park.js +2 -1
  88. package/dist/kpis/park.js.map +1 -1
  89. package/dist/kpis/phase.d.ts.map +1 -1
  90. package/dist/kpis/phase.js +1 -0
  91. package/dist/kpis/phase.js.map +1 -1
  92. package/dist/land/changelog.d.ts +8 -0
  93. package/dist/land/changelog.d.ts.map +1 -0
  94. package/dist/land/changelog.js +90 -0
  95. package/dist/land/changelog.js.map +1 -0
  96. package/dist/land/sync.d.ts.map +1 -1
  97. package/dist/land/sync.js +93 -32
  98. package/dist/land/sync.js.map +1 -1
  99. package/dist/phases/check-evidence.d.ts.map +1 -1
  100. package/dist/phases/check-evidence.js +5 -1
  101. package/dist/phases/check-evidence.js.map +1 -1
  102. package/dist/phases/ship-approval.d.ts +17 -0
  103. package/dist/phases/ship-approval.d.ts.map +1 -0
  104. package/dist/phases/ship-approval.js +21 -0
  105. package/dist/phases/ship-approval.js.map +1 -0
  106. package/dist/phases/ship-branch-push.d.ts +17 -0
  107. package/dist/phases/ship-branch-push.d.ts.map +1 -0
  108. package/dist/phases/ship-branch-push.js +77 -0
  109. package/dist/phases/ship-branch-push.js.map +1 -0
  110. package/dist/phases/ship-evidence-comment.d.ts +14 -0
  111. package/dist/phases/ship-evidence-comment.d.ts.map +1 -0
  112. package/dist/phases/ship-evidence-comment.js +31 -0
  113. package/dist/phases/ship-evidence-comment.js.map +1 -0
  114. package/dist/phases/ship-existing-pr.d.ts +11 -0
  115. package/dist/phases/ship-existing-pr.d.ts.map +1 -0
  116. package/dist/phases/ship-existing-pr.js +36 -0
  117. package/dist/phases/ship-existing-pr.js.map +1 -0
  118. package/dist/phases/ship-finish.d.ts +15 -0
  119. package/dist/phases/ship-finish.d.ts.map +1 -0
  120. package/dist/phases/ship-finish.js +69 -0
  121. package/dist/phases/ship-finish.js.map +1 -0
  122. package/dist/phases/ship-git-detail.d.ts +31 -0
  123. package/dist/phases/ship-git-detail.d.ts.map +1 -0
  124. package/dist/phases/ship-git-detail.js +71 -0
  125. package/dist/phases/ship-git-detail.js.map +1 -0
  126. package/dist/phases/ship-git-remote.d.ts +51 -0
  127. package/dist/phases/ship-git-remote.d.ts.map +1 -0
  128. package/dist/phases/ship-git-remote.js +70 -0
  129. package/dist/phases/ship-git-remote.js.map +1 -0
  130. package/dist/phases/ship-git.d.ts +4 -79
  131. package/dist/phases/ship-git.d.ts.map +1 -1
  132. package/dist/phases/ship-git.js +2 -135
  133. package/dist/phases/ship-git.js.map +1 -1
  134. package/dist/phases/ship-main-sync.d.ts +18 -0
  135. package/dist/phases/ship-main-sync.d.ts.map +1 -0
  136. package/dist/phases/ship-main-sync.js +34 -0
  137. package/dist/phases/ship-main-sync.js.map +1 -0
  138. package/dist/phases/ship-open-pr.d.ts +24 -0
  139. package/dist/phases/ship-open-pr.d.ts.map +1 -0
  140. package/dist/phases/ship-open-pr.js +75 -0
  141. package/dist/phases/ship-open-pr.js.map +1 -0
  142. package/dist/phases/ship-options.d.ts +81 -0
  143. package/dist/phases/ship-options.d.ts.map +1 -0
  144. package/dist/phases/ship-options.js +4 -0
  145. package/dist/phases/ship-options.js.map +1 -0
  146. package/dist/phases/ship-reentry.d.ts +20 -0
  147. package/dist/phases/ship-reentry.d.ts.map +1 -0
  148. package/dist/phases/ship-reentry.js +47 -0
  149. package/dist/phases/ship-reentry.js.map +1 -0
  150. package/dist/phases/ship.d.ts +4 -76
  151. package/dist/phases/ship.d.ts.map +1 -1
  152. package/dist/phases/ship.js +40 -297
  153. package/dist/phases/ship.js.map +1 -1
  154. package/dist/phases/stack-order.d.ts +9 -0
  155. package/dist/phases/stack-order.d.ts.map +1 -1
  156. package/dist/phases/stack-order.js +13 -0
  157. package/dist/phases/stack-order.js.map +1 -1
  158. package/dist/queue/comment-rework-trigger.d.ts +24 -0
  159. package/dist/queue/comment-rework-trigger.d.ts.map +1 -0
  160. package/dist/queue/comment-rework-trigger.js +128 -0
  161. package/dist/queue/comment-rework-trigger.js.map +1 -0
  162. package/dist/queue/github-queue.d.ts +4 -2
  163. package/dist/queue/github-queue.d.ts.map +1 -1
  164. package/dist/queue/github-queue.js.map +1 -1
  165. package/dist/queue/internal-exports.d.ts +3 -0
  166. package/dist/queue/internal-exports.d.ts.map +1 -1
  167. package/dist/queue/internal-exports.js +2 -0
  168. package/dist/queue/internal-exports.js.map +1 -1
  169. package/dist/queue/lane-discovery-interval.d.ts +6 -0
  170. package/dist/queue/lane-discovery-interval.d.ts.map +1 -0
  171. package/dist/queue/lane-discovery-interval.js +9 -0
  172. package/dist/queue/lane-discovery-interval.js.map +1 -0
  173. package/dist/queue/linear-queue-backend.d.ts +17 -0
  174. package/dist/queue/linear-queue-backend.d.ts.map +1 -0
  175. package/dist/queue/linear-queue-backend.js +42 -0
  176. package/dist/queue/linear-queue-backend.js.map +1 -0
  177. package/dist/queue/linear-queue.d.ts +4 -2
  178. package/dist/queue/linear-queue.d.ts.map +1 -1
  179. package/dist/queue/linear-queue.js +79 -2
  180. package/dist/queue/linear-queue.js.map +1 -1
  181. package/dist/queue/prerequisite-stack.d.ts +47 -0
  182. package/dist/queue/prerequisite-stack.d.ts.map +1 -0
  183. package/dist/queue/prerequisite-stack.js +41 -0
  184. package/dist/queue/prerequisite-stack.js.map +1 -0
  185. package/dist/queue/queue-backend.d.ts +11 -5
  186. package/dist/queue/queue-backend.d.ts.map +1 -1
  187. package/dist/queue/queue-backend.js +8 -3
  188. package/dist/queue/queue-backend.js.map +1 -1
  189. package/dist/queue/review-rework-trigger.d.ts +7 -2
  190. package/dist/queue/review-rework-trigger.d.ts.map +1 -1
  191. package/dist/queue/review-rework-trigger.js +16 -8
  192. package/dist/queue/review-rework-trigger.js.map +1 -1
  193. package/dist/reports/pr-body.d.ts +5 -2
  194. package/dist/reports/pr-body.d.ts.map +1 -1
  195. package/dist/reports/pr-body.js +21 -10
  196. package/dist/reports/pr-body.js.map +1 -1
  197. package/dist/run/ci-rework-loop.d.ts.map +1 -1
  198. package/dist/run/ci-rework-loop.js +5 -1
  199. package/dist/run/ci-rework-loop.js.map +1 -1
  200. package/dist/run/feedback-github.d.ts +50 -0
  201. package/dist/run/feedback-github.d.ts.map +1 -0
  202. package/dist/run/feedback-github.js +87 -0
  203. package/dist/run/feedback-github.js.map +1 -0
  204. package/dist/run/feedback-round-hooks.d.ts +19 -0
  205. package/dist/run/feedback-round-hooks.d.ts.map +1 -0
  206. package/dist/run/feedback-round-hooks.js +106 -0
  207. package/dist/run/feedback-round-hooks.js.map +1 -0
  208. package/dist/run/feedback-round.d.ts +97 -0
  209. package/dist/run/feedback-round.d.ts.map +1 -0
  210. package/dist/run/feedback-round.js +275 -0
  211. package/dist/run/feedback-round.js.map +1 -0
  212. package/dist/run/linear-run.d.ts +23 -0
  213. package/dist/run/linear-run.d.ts.map +1 -0
  214. package/dist/run/linear-run.js +18 -0
  215. package/dist/run/linear-run.js.map +1 -0
  216. package/dist/run/park-comment.d.ts +9 -0
  217. package/dist/run/park-comment.d.ts.map +1 -1
  218. package/dist/run/park-comment.js +12 -0
  219. package/dist/run/park-comment.js.map +1 -1
  220. package/dist/run/ports.d.ts +10 -0
  221. package/dist/run/ports.d.ts.map +1 -1
  222. package/dist/run/ports.js +12 -0
  223. package/dist/run/ports.js.map +1 -1
  224. package/dist/run/pr-run-state.d.ts +99 -0
  225. package/dist/run/pr-run-state.d.ts.map +1 -0
  226. package/dist/run/pr-run-state.js +235 -0
  227. package/dist/run/pr-run-state.js.map +1 -0
  228. package/dist/run/prerequisite-restack.d.ts +39 -0
  229. package/dist/run/prerequisite-restack.d.ts.map +1 -0
  230. package/dist/run/prerequisite-restack.js +79 -0
  231. package/dist/run/prerequisite-restack.js.map +1 -0
  232. package/dist/run/review-rework-cap.d.ts +3 -1
  233. package/dist/run/review-rework-cap.d.ts.map +1 -1
  234. package/dist/run/review-rework-cap.js +2 -1
  235. package/dist/run/review-rework-cap.js.map +1 -1
  236. package/dist/run/review-rework.d.ts +17 -2
  237. package/dist/run/review-rework.d.ts.map +1 -1
  238. package/dist/run/review-rework.js +99 -33
  239. package/dist/run/review-rework.js.map +1 -1
  240. package/dist/run/run-issue.d.ts +5 -1
  241. package/dist/run/run-issue.d.ts.map +1 -1
  242. package/dist/run/run-issue.js +35 -28
  243. package/dist/run/run-issue.js.map +1 -1
  244. package/dist/run/stack-rebase.d.ts +28 -0
  245. package/dist/run/stack-rebase.d.ts.map +1 -0
  246. package/dist/run/stack-rebase.js +79 -0
  247. package/dist/run/stack-rebase.js.map +1 -0
  248. package/dist/run/stack-restack.d.ts.map +1 -1
  249. package/dist/run/stack-restack.js +21 -49
  250. package/dist/run/stack-restack.js.map +1 -1
  251. package/dist/utils/command-runner.d.ts.map +1 -1
  252. package/dist/utils/command-runner.js +4 -1
  253. package/dist/utils/command-runner.js.map +1 -1
  254. package/dist/utils/exec.d.ts.map +1 -1
  255. package/dist/utils/exec.js +4 -1
  256. package/dist/utils/exec.js.map +1 -1
  257. package/dist/utils/in-place.d.ts +24 -0
  258. package/dist/utils/in-place.d.ts.map +1 -0
  259. package/dist/utils/in-place.js +105 -0
  260. package/dist/utils/in-place.js.map +1 -0
  261. package/dist/work/internal-exports.d.ts +3 -0
  262. package/dist/work/internal-exports.d.ts.map +1 -0
  263. package/dist/work/internal-exports.js +4 -0
  264. package/dist/work/internal-exports.js.map +1 -0
  265. package/dist/work/ticket-writeback.d.ts +22 -0
  266. package/dist/work/ticket-writeback.d.ts.map +1 -0
  267. package/dist/work/ticket-writeback.js +73 -0
  268. package/dist/work/ticket-writeback.js.map +1 -0
  269. package/dist/work/work-key.d.ts +2 -0
  270. package/dist/work/work-key.d.ts.map +1 -1
  271. package/dist/work/work-key.js +4 -0
  272. package/dist/work/work-key.js.map +1 -1
  273. package/package.json +5 -5
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ship-approval.d.ts","sourceRoot":"","sources":["../../src/phases/ship-approval.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAiB,KAAK,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAElE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,wBAAsB,mBAAmB,CAAC,GAAG,EAAE;IAC7C,YAAY,EAAE,YAAY,CAAC;IAC3B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,aAAa,CAAC;IACnB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,GAAG,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC;CAC9B,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAmBlC"}
@@ -0,0 +1,21 @@
1
+ // packages/core/src/phases/ship-approval.ts — SHIP approval gate request
2
+ import { issueNumberOf } from '../work/work-key.js';
3
+ import { computeDiffStat } from './ship-diff-stat.js';
4
+ export async function requestShipApproval(ctx) {
5
+ const { approvalGate, issue, branch, worktree, base, run, checkSummary, log } = ctx;
6
+ // Log a 'ship'-typed event before anything else so the TUI's activePhase
7
+ // advances to SHIP first — otherwise a denial reports failedPhase as
8
+ // whichever phase (CHECK/BUILD) last logged, which is misleading.
9
+ log('ship', `Starting ship phase for ${branch}`);
10
+ const diffStat = await computeDiffStat(run, worktree, base);
11
+ log('approval_requested', `awaiting approval to ship ${branch}${checkSummary ? ` (checks: ${checkSummary.passes} pass, ${checkSummary.failures} fail, ${checkSummary.skips} skip)` : ''}`);
12
+ const response = await approvalGate({ issue: issueNumberOf(issue), branch, worktree, diffStat, checkSummary });
13
+ if (!response.approved) {
14
+ const reason = response.reason ?? 'denied';
15
+ log('ship_denied', `ship denied for ${branch}: ${reason}`);
16
+ return { ok: false, denied: true, deniedReason: reason };
17
+ }
18
+ log('approval_granted', `approval granted for ${branch}`);
19
+ return undefined;
20
+ }
21
+ //# sourceMappingURL=ship-approval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ship-approval.js","sourceRoot":"","sources":["../../src/phases/ship-approval.ts"],"names":[],"mappings":"AAAA,yEAAyE;AAIzE,OAAO,EAAE,aAAa,EAAgB,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAKtD,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,GASzC;IACC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC;IACpF,yEAAyE;IACzE,qEAAqE;IACrE,kEAAkE;IAClE,GAAG,CAAC,MAAM,EAAE,2BAA2B,MAAM,EAAE,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC5D,GAAG,CACD,oBAAoB,EACpB,6BAA6B,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,aAAa,YAAY,CAAC,MAAM,UAAU,YAAY,CAAC,QAAQ,UAAU,YAAY,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAChK,CAAC;IACF,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC;IAC/G,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC;QAC3C,GAAG,CAAC,aAAa,EAAE,mBAAmB,MAAM,KAAK,MAAM,EAAE,CAAC,CAAC;QAC3D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;IAC3D,CAAC;IACD,GAAG,CAAC,kBAAkB,EAAE,wBAAwB,MAAM,EAAE,CAAC,CAAC;IAC1D,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { Octokit } from '@octokit/rest';
2
+ import type { WorkKey } from '../work/work-key.js';
3
+ import { type CommandRunner } from './ship-git.js';
4
+ import type { ShipPhaseOptions } from './ship-options.js';
5
+ import type { ShipResult } from './ship-types.js';
6
+ export declare function pushNewBranch(ctx: {
7
+ run: CommandRunner;
8
+ worktree: string;
9
+ branch: string;
10
+ issue: WorkKey | undefined;
11
+ octokit: Octokit;
12
+ owner: string;
13
+ repoName: string;
14
+ recordedRemoteSha?: string;
15
+ log: ShipPhaseOptions['log'];
16
+ }): Promise<ShipResult | undefined>;
17
+ //# sourceMappingURL=ship-branch-push.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ship-branch-push.d.ts","sourceRoot":"","sources":["../../src/phases/ship-branch-push.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAG7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,KAAK,aAAa,EAAgD,MAAM,eAAe,CAAC;AACjG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,wBAAsB,aAAa,CAAC,GAAG,EAAE;IACvC,GAAG,EAAE,aAAa,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,GAAG,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC;CAC9B,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAqElC"}
@@ -0,0 +1,77 @@
1
+ // packages/core/src/phases/ship-branch-push.ts — SHIP push of a new branch before PR creation
2
+ import { shellEscape } from '../utils/index.js';
3
+ import { pushAndVerifyRemoteHead, readRemoteBranchSha } from './ship-git.js';
4
+ import { recoverOrStop } from './ship-recovery.js';
5
+ export async function pushNewBranch(ctx) {
6
+ const { run, worktree, branch, issue, octokit, owner, repoName, log } = ctx;
7
+ const stop = await recoverOrStop({
8
+ run,
9
+ worktree,
10
+ branch,
11
+ issue,
12
+ octokit,
13
+ owner,
14
+ repoName,
15
+ log,
16
+ });
17
+ if (stop)
18
+ return stop;
19
+ // Push branch. A rejected push means the remote head does not contain this run's
20
+ // commits — opening a PR against it would advertise work that is not there, so the
21
+ // ship fails closed here rather than continuing to PR creation (#734).
22
+ let pushCmd = `git push -u origin ${shellEscape(branch)}`;
23
+ const recorded = ctx.recordedRemoteSha;
24
+ let leased = false;
25
+ if (recorded) {
26
+ // A retry rebuilds the branch from origin/main, so an earlier run's push is stale. Replace it
27
+ // only while the remote is still exactly what was recorded at worktree creation (#1869).
28
+ const current = await readRemoteBranchSha(run, worktree, branch);
29
+ if (current.status === 'unreadable') {
30
+ const reason = `could not read origin/${branch} to check recorded SHA ${recorded} (${current.detail})`;
31
+ log('ship', `${reason} — aborting before push`);
32
+ return { ok: false, reason };
33
+ }
34
+ if (current.sha === null) {
35
+ log('ship', `origin/${branch} recorded @ ${recorded} no longer exists — nothing to replace, plain push`);
36
+ }
37
+ else if (current.sha !== recorded) {
38
+ const reason = `origin/${branch} moved since it was recorded: recorded ${recorded}, current ${current.sha}`;
39
+ log('ship', `${reason} — aborting before push`);
40
+ return { ok: false, reason };
41
+ }
42
+ else {
43
+ pushCmd = `git push ${shellEscape(`--force-with-lease=${branch}:${recorded}`)} -u origin ${shellEscape(branch)}`;
44
+ leased = true;
45
+ log('ship', `replacing stale origin/${branch} @ ${recorded} with a leased push`);
46
+ }
47
+ }
48
+ // A zero-exit push is not proof the remote branch actually carries this run's commits — a
49
+ // concurrent push or an update that silently applied nothing leaves the remote head elsewhere,
50
+ // and a PR opened against it advertises work that is not there (#735). Fail closed, like the
51
+ // push-failure abort (#734).
52
+ const pushed = await pushAndVerifyRemoteHead(run, worktree, branch, pushCmd);
53
+ if (pushed.status === 'push-failed') {
54
+ const pushReason = `git push failed (${pushed.kind}): ${pushed.detail}`;
55
+ log('ship', `${pushReason} — aborting before PR creation`);
56
+ if (leased) {
57
+ return {
58
+ ok: false,
59
+ reason: `leased push of ${branch} over recorded ${recorded} was rejected (${pushed.kind})`,
60
+ };
61
+ }
62
+ return { ok: false, reason: pushReason };
63
+ }
64
+ if (pushed.status === 'mismatch') {
65
+ const reason = `remote head ${pushed.remoteSha} does not match local HEAD ${pushed.localSha} for ${branch}`;
66
+ log('ship', `${reason} — aborting before PR creation`);
67
+ return { ok: false, reason };
68
+ }
69
+ if (pushed.status === 'unreadable') {
70
+ const reason = `could not verify the remote head for ${branch} (${pushed.detail}); local HEAD ${pushed.localSha ?? 'unknown'}`;
71
+ log('ship', `${reason} — aborting before PR creation`);
72
+ return { ok: false, reason };
73
+ }
74
+ log('ship', `remote head ${pushed.remoteSha} matches local HEAD ${pushed.localSha} for ${branch}`);
75
+ return undefined;
76
+ }
77
+ //# sourceMappingURL=ship-branch-push.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ship-branch-push.js","sourceRoot":"","sources":["../../src/phases/ship-branch-push.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { CommandRunner } from './ship-git.js';
2
+ import type { ShipPhaseOptions } from './ship-options.js';
3
+ import type { lazyWalkthrough } from './ship-walkthrough.js';
4
+ export declare function postEvidenceComment(ctx: {
5
+ opts: ShipPhaseOptions;
6
+ run: CommandRunner;
7
+ owner: string;
8
+ repoName: string;
9
+ prNumber: number;
10
+ walkthrough: ReturnType<typeof lazyWalkthrough>;
11
+ /** The commit CHECK ran on, when SHIP merged main after it; unset reads HEAD. */
12
+ checkedSha?: string;
13
+ }): Promise<void>;
14
+ //# sourceMappingURL=ship-evidence-comment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ship-evidence-comment.d.ts","sourceRoot":"","sources":["../../src/phases/ship-evidence-comment.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,wBAAsB,mBAAmB,CAAC,GAAG,EAAE;IAC7C,IAAI,EAAE,gBAAgB,CAAC;IACvB,GAAG,EAAE,aAAa,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;IAChD,iFAAiF;IACjF,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBhB"}
@@ -0,0 +1,31 @@
1
+ // packages/core/src/phases/ship-evidence-comment.ts — SHIP evidence-pack PR comment
2
+ import { gatherEvidencePack } from '../reports/evidence-pack.js';
3
+ export async function postEvidenceComment(ctx) {
4
+ const { opts, run, owner, repoName, prNumber, walkthrough } = ctx;
5
+ const { issue, octokit, worktree, checkSummary, log } = opts;
6
+ try {
7
+ let checkedSha = ctx.checkedSha;
8
+ if (!checkedSha)
9
+ try {
10
+ checkedSha = (await run('git rev-parse HEAD', { cwd: worktree })).stdout.trim() || undefined;
11
+ }
12
+ catch { }
13
+ const body = gatherEvidencePack({
14
+ issue,
15
+ checkSummary,
16
+ reworkRounds: opts.reworkRounds,
17
+ specPath: opts.specPath,
18
+ eventsFile: opts.eventsFile,
19
+ startedAt: opts.startedAt,
20
+ logsDir: opts.logsDir,
21
+ reviewRouting: opts.reviewRouting,
22
+ pinNotes: opts.pinNotes,
23
+ headSha: checkedSha,
24
+ walkthrough: await walkthrough.walkthrough(),
25
+ });
26
+ await octokit.rest.issues.createComment({ owner, repo: repoName, issue_number: prNumber, body });
27
+ log('evidence', `posted evidence pack to PR #${prNumber}`);
28
+ }
29
+ catch { }
30
+ }
31
+ //# sourceMappingURL=ship-evidence-comment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ship-evidence-comment.js","sourceRoot":"","sources":["../../src/phases/ship-evidence-comment.ts"],"names":[],"mappings":"AAAA,oFAAoF;AAEpF,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAKjE,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,GASzC;IACC,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,GAAG,CAAC;IAClE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC7D,IAAI,CAAC;QACH,IAAI,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC;QAChC,IAAI,CAAC,UAAU;YACb,IAAI,CAAC;gBACH,UAAU,GAAG,CAAC,MAAM,GAAG,CAAC,oBAAoB,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,SAAS,CAAC;YAC/F,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QACZ,MAAM,IAAI,GAAG,kBAAkB,CAAC;YAC9B,KAAK;YACL,YAAY;YACZ,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,OAAO,EAAE,UAAU;YACnB,WAAW,EAAE,MAAM,WAAW,CAAC,WAAW,EAAE;SAC7C,CAAC,CAAC;QACH,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACjG,GAAG,CAAC,UAAU,EAAE,+BAA+B,QAAQ,EAAE,CAAC,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;AACZ,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { type CommandRunner } from './ship-git.js';
2
+ import type { ShipPhaseOptions } from './ship-options.js';
3
+ import type { ShipResult } from './ship-types.js';
4
+ export declare function syncExistingPr(ctx: {
5
+ run: CommandRunner;
6
+ worktree: string;
7
+ branch: string;
8
+ prNumber: number;
9
+ log: ShipPhaseOptions['log'];
10
+ }): Promise<ShipResult | undefined>;
11
+ //# sourceMappingURL=ship-existing-pr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ship-existing-pr.d.ts","sourceRoot":"","sources":["../../src/phases/ship-existing-pr.ts"],"names":[],"mappings":"AAGA,OAAO,EAAyB,KAAK,aAAa,EAA6C,MAAM,eAAe,CAAC;AACrH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,wBAAsB,cAAc,CAAC,GAAG,EAAE;IACxC,GAAG,EAAE,aAAa,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC;CAC9B,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAmClC"}
@@ -0,0 +1,36 @@
1
+ // packages/core/src/phases/ship-existing-pr.ts — SHIP sync of an already-open PR's branch
2
+ import { shellEscape } from '../utils/index.js';
3
+ import { checkRemoteIsAncestor, pushAndVerifyRemoteHead, verifyRemoteHead } from './ship-git.js';
4
+ export async function syncExistingPr(ctx) {
5
+ const { run, worktree, branch, prNumber, log } = ctx;
6
+ // Rework commits made after BUILD's push must reach the open PR before evidence or ready (#1813).
7
+ const current = await verifyRemoteHead(run, worktree, branch);
8
+ if (current.status === 'match') {
9
+ log('ship', `remote head ${current.remoteSha} matches local HEAD ${current.localSha} for ${branch} — already in sync, not pushing`);
10
+ }
11
+ else {
12
+ if (current.status === 'mismatch') {
13
+ const ancestry = await checkRemoteIsAncestor(run, worktree, current.remoteSha, current.localSha);
14
+ if (ancestry.status !== 'ancestor') {
15
+ const reason = ancestry.status === 'diverged'
16
+ ? `origin/${branch} @ ${current.remoteSha} has diverged from local HEAD ${current.localSha} (remote has commits local HEAD lacks) on open PR #${prNumber} — not force-pushing`
17
+ : `could not confirm origin/${branch} @ ${current.remoteSha} is an ancestor of local HEAD ${current.localSha} on open PR #${prNumber} (${ancestry.detail})`;
18
+ log('ship', `${reason} — aborting before evidence`);
19
+ return { ok: false, prNumber, reason };
20
+ }
21
+ }
22
+ const pushed = await pushAndVerifyRemoteHead(run, worktree, branch, `git push -u origin ${shellEscape(branch)}`);
23
+ if (pushed.status !== 'pushed') {
24
+ const reason = pushed.status === 'push-failed'
25
+ ? `push of ${branch} to open PR #${prNumber} failed (${pushed.kind}): ${pushed.detail}`
26
+ : pushed.status === 'mismatch'
27
+ ? `remote head ${pushed.remoteSha} does not match local HEAD ${pushed.localSha} for ${branch} after push to open PR #${prNumber}`
28
+ : `could not verify the remote head for ${branch} after push to open PR #${prNumber} (${pushed.detail})`;
29
+ log('ship', `${reason} — aborting before evidence`);
30
+ return { ok: false, prNumber, reason };
31
+ }
32
+ log('ship', `remote head ${pushed.remoteSha} matches local HEAD ${pushed.localSha} for ${branch}`);
33
+ }
34
+ return undefined;
35
+ }
36
+ //# sourceMappingURL=ship-existing-pr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ship-existing-pr.js","sourceRoot":"","sources":["../../src/phases/ship-existing-pr.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAE1F,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAsB,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAIrH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,GAMpC;IACC,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC;IACrD,kGAAkG;IAClG,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC9D,IAAI,OAAO,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QAC/B,GAAG,CACD,MAAM,EACN,eAAe,OAAO,CAAC,SAAS,uBAAuB,OAAO,CAAC,QAAQ,QAAQ,MAAM,iCAAiC,CACvH,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,IAAI,OAAO,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAClC,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;YACjG,IAAI,QAAQ,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;gBACnC,MAAM,MAAM,GACV,QAAQ,CAAC,MAAM,KAAK,UAAU;oBAC5B,CAAC,CAAC,UAAU,MAAM,MAAM,OAAO,CAAC,SAAS,iCAAiC,OAAO,CAAC,QAAQ,sDAAsD,QAAQ,sBAAsB;oBAC9K,CAAC,CAAC,4BAA4B,MAAM,MAAM,OAAO,CAAC,SAAS,iCAAiC,OAAO,CAAC,QAAQ,gBAAgB,QAAQ,KAAK,QAAQ,CAAC,MAAM,GAAG,CAAC;gBAChK,GAAG,CAAC,MAAM,EAAE,GAAG,MAAM,6BAA6B,CAAC,CAAC;gBACpD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;YACzC,CAAC;QACH,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,sBAAsB,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACjH,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC/B,MAAM,MAAM,GACV,MAAM,CAAC,MAAM,KAAK,aAAa;gBAC7B,CAAC,CAAC,WAAW,MAAM,gBAAgB,QAAQ,YAAY,MAAM,CAAC,IAAI,MAAM,MAAM,CAAC,MAAM,EAAE;gBACvF,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,UAAU;oBAC5B,CAAC,CAAC,eAAe,MAAM,CAAC,SAAS,8BAA8B,MAAM,CAAC,QAAQ,QAAQ,MAAM,2BAA2B,QAAQ,EAAE;oBACjI,CAAC,CAAC,wCAAwC,MAAM,2BAA2B,QAAQ,KAAK,MAAM,CAAC,MAAM,GAAG,CAAC;YAC/G,GAAG,CAAC,MAAM,EAAE,GAAG,MAAM,6BAA6B,CAAC,CAAC;YACpD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;QACzC,CAAC;QACD,GAAG,CAAC,MAAM,EAAE,eAAe,MAAM,CAAC,SAAS,uBAAuB,MAAM,CAAC,QAAQ,QAAQ,MAAM,EAAE,CAAC,CAAC;IACrG,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { InfraRerunOutcome } from '../utils/ci-watch.js';
2
+ import type { CommandRunner } from './ship-git.js';
3
+ import type { ShipPhaseOptions } from './ship-options.js';
4
+ import type { ShipResult } from './ship-types.js';
5
+ export declare function finishShip(ctx: {
6
+ opts: ShipPhaseOptions;
7
+ run: CommandRunner;
8
+ owner: string;
9
+ repoName: string;
10
+ prNumber: number;
11
+ headSha?: string;
12
+ ciOutcome?: InfraRerunOutcome;
13
+ ciWatchError?: string;
14
+ }): Promise<ShipResult>;
15
+ //# sourceMappingURL=ship-finish.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ship-finish.d.ts","sourceRoot":"","sources":["../../src/phases/ship-finish.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,wBAAsB,UAAU,CAAC,GAAG,EAAE;IACpC,IAAI,EAAE,gBAAgB,CAAC;IACvB,GAAG,EAAE,aAAa,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,UAAU,CAAC,CAgEtB"}
@@ -0,0 +1,69 @@
1
+ // packages/core/src/phases/ship-finish.ts — SHIP preview gate, ready flip and final result
2
+ import { publishPreviewReceipt } from '../checkers/preview-receipt.js';
3
+ import { previewFailureReason, runPreviewGate } from './ship-preview.js';
4
+ import { markPrReadyWithRetry } from './ship-ready.js';
5
+ export async function finishShip(ctx) {
6
+ const { opts, run, owner, repoName, prNumber, headSha, ciOutcome, ciWatchError } = ctx;
7
+ const { octokit, worktree, log } = opts;
8
+ const ciPending = ciOutcome === 'timeout' || ciWatchError !== undefined;
9
+ let previewCheck;
10
+ if (opts.previewGate) {
11
+ const sha = headSha ?? (await run('git rev-parse HEAD', { cwd: worktree })).stdout.trim();
12
+ const publish = (n, r) => publishPreviewReceipt(octokit, owner, repoName, n, r);
13
+ const gateCtx = { log, ciPending, publish, ...(opts.logsDir ? { logsDir: opts.logsDir } : {}) };
14
+ previewCheck = await runPreviewGate(opts.previewGate, { prNumber, headSha: sha }, gateCtx);
15
+ if (previewCheck.status !== 'pass') {
16
+ return {
17
+ ok: false,
18
+ prNumber,
19
+ reason: previewFailureReason(prNumber, previewCheck),
20
+ previewCheck,
21
+ headSha: sha,
22
+ ...(ciOutcome ? { ciOutcome } : {}),
23
+ ...(ciPending ? { ciPending: true, draft: true } : {}),
24
+ };
25
+ }
26
+ }
27
+ if (ciWatchError !== undefined) {
28
+ const reason = `CI unknown for PR #${prNumber}: the CI watch failed (${ciWatchError}); leaving PR as draft`;
29
+ log('ship', reason);
30
+ return { ok: false, prNumber, reason, ciPending: true, draft: true, ...(headSha ? { headSha } : {}) };
31
+ }
32
+ // Mark ready for review (if draft). REST pulls.update ignores `draft`;
33
+ // undrafting requires the markPullRequestReadyForReview GraphQL mutation.
34
+ if (opts.draft || ciPending) {
35
+ try {
36
+ const { data: pr } = await octokit.rest.pulls.get({ owner, repo: repoName, pull_number: prNumber });
37
+ if (!pr.draft)
38
+ log('ship', `PR #${prNumber} is already open and not a draft; draft mode leaves it as is`);
39
+ }
40
+ catch { }
41
+ }
42
+ else {
43
+ const flip = await markPrReadyWithRetry(octokit, owner, repoName, prNumber);
44
+ if (!flip.ok) {
45
+ const reason = `could not mark PR #${prNumber} ready for review after one retry: ${flip.detail}`;
46
+ log('warn', reason);
47
+ return {
48
+ ok: false,
49
+ prNumber,
50
+ reason,
51
+ ...(ciOutcome === undefined ? {} : { ciOutcome }),
52
+ ...(headSha ? { headSha } : {}),
53
+ };
54
+ }
55
+ }
56
+ const noChecks = ciOutcome === 'no-checks' ? ' (CI skipped: no checks found)' : '';
57
+ const readyLabel = opts.draft || ciPending ? `left as draft${ciPending ? ' (CI pending)' : ''}` : 'ready for review';
58
+ log('ready', `PR #${prNumber} ${readyLabel}${noChecks}`);
59
+ return {
60
+ ok: true,
61
+ prNumber,
62
+ ...(ciOutcome === undefined ? {} : { ciOutcome }),
63
+ ...(headSha ? { headSha } : {}),
64
+ ...(opts.draft || ciPending ? { draft: true } : {}),
65
+ ...(ciPending ? { ciPending: true } : {}),
66
+ ...(previewCheck ? { previewCheck } : {}),
67
+ };
68
+ }
69
+ //# sourceMappingURL=ship-finish.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ship-finish.js","sourceRoot":"","sources":["../../src/phases/ship-finish.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ export type CommandRunner = (command: string, options?: {
2
+ cwd?: string;
3
+ timeout?: number;
4
+ }) => Promise<{
5
+ stdout: string;
6
+ }>;
7
+ /** Why a `git push` was refused, as far as git's own stderr says (#733). */
8
+ export type PushFailureKind = 'non-fast-forward' | 'network' | 'unknown';
9
+ /**
10
+ * The real reason a push failed, from git's own stderr when the runner exposes it
11
+ * (node's promisified `exec` rejection carries `stderr`), else the Error message, else the
12
+ * value's string form. Flattened to one line and bounded so a single event row stays
13
+ * greppable in `.factory/events.ndjson`.
14
+ */
15
+ export declare function describePushFailure(err: unknown): {
16
+ kind: PushFailureKind;
17
+ detail: string;
18
+ };
19
+ /** Prefer stderr, then stdout, before the error fallback; keep details flattened and bounded. */
20
+ export declare function shortDetail(err: unknown): string;
21
+ /** Whether origin's head is an ancestor of local HEAD, i.e. a plain push is a fast-forward (#1815). */
22
+ export type RemoteAncestry = {
23
+ status: 'ancestor';
24
+ } | {
25
+ status: 'diverged';
26
+ } | {
27
+ status: 'unreadable';
28
+ detail: string;
29
+ };
30
+ export declare function checkRemoteIsAncestor(run: CommandRunner, worktree: string, remoteSha: string, localSha: string): Promise<RemoteAncestry>;
31
+ //# sourceMappingURL=ship-git-detail.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ship-git-detail.d.ts","sourceRoot":"","sources":["../../src/phases/ship-git-detail.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,aAAa,GAAG,CAC1B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,KACzC,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEjC,4EAA4E;AAC5E,MAAM,MAAM,eAAe,GAAG,kBAAkB,GAAG,SAAS,GAAG,SAAS,CAAC;AA8BzE;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAM3F;AAKD,iGAAiG;AACjG,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAQhD;AAED,uGAAuG;AACvG,MAAM,MAAM,cAAc,GAAG;IAAE,MAAM,EAAE,UAAU,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,UAAU,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAIxH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,aAAa,EAClB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,cAAc,CAAC,CAYzB"}
@@ -0,0 +1,71 @@
1
+ // packages/core/src/phases/ship-git-detail.ts — command runner type and push-failure description for SHIP
2
+ import { shellEscape } from '../utils/index.js';
3
+ /** Bound on the failure text copied into one NDJSON event row. */
4
+ const MAX_PUSH_ERROR_DETAIL = 400;
5
+ const NON_FAST_FORWARD_MARKERS = [
6
+ 'non-fast-forward',
7
+ '! [rejected]',
8
+ 'fetch first',
9
+ 'updates were rejected',
10
+ 'stale info',
11
+ ];
12
+ const NETWORK_MARKERS = [
13
+ 'could not resolve host',
14
+ 'failed to connect',
15
+ 'connection timed out',
16
+ 'connection refused',
17
+ 'network is unreachable',
18
+ 'operation timed out',
19
+ 'the remote end hung up unexpectedly',
20
+ ];
21
+ function classifyPushFailure(text) {
22
+ const t = text.toLowerCase();
23
+ if (NON_FAST_FORWARD_MARKERS.some((m) => t.includes(m)))
24
+ return 'non-fast-forward';
25
+ if (NETWORK_MARKERS.some((m) => t.includes(m)))
26
+ return 'network';
27
+ return 'unknown';
28
+ }
29
+ /**
30
+ * The real reason a push failed, from git's own stderr when the runner exposes it
31
+ * (node's promisified `exec` rejection carries `stderr`), else the Error message, else the
32
+ * value's string form. Flattened to one line and bounded so a single event row stays
33
+ * greppable in `.factory/events.ndjson`.
34
+ */
35
+ export function describePushFailure(err) {
36
+ const raw = err?.stderr;
37
+ const stderr = typeof raw === 'string' ? raw : '';
38
+ const text = stderr.trim() || (err instanceof Error ? err.message : String(err));
39
+ const detail = text.replace(/\s+/g, ' ').trim().slice(0, MAX_PUSH_ERROR_DETAIL);
40
+ return { kind: classifyPushFailure(detail), detail: detail || 'no error output' };
41
+ }
42
+ /** Bound on the ls-remote failure text copied into one NDJSON event row (#735). */
43
+ const MAX_REMOTE_HEAD_DETAIL = 200;
44
+ /** Prefer stderr, then stdout, before the error fallback; keep details flattened and bounded. */
45
+ export function shortDetail(err) {
46
+ const output = err;
47
+ const rawStderr = output?.stderr;
48
+ const rawStdout = output?.stdout;
49
+ const stderr = typeof rawStderr === 'string' ? rawStderr.trim() : '';
50
+ const stdout = typeof rawStdout === 'string' ? rawStdout.trim() : '';
51
+ const text = stderr || stdout || (err instanceof Error ? err.message : String(err));
52
+ return text.replace(/\s+/g, ' ').trim().slice(0, MAX_REMOTE_HEAD_DETAIL) || 'no error output';
53
+ }
54
+ const MISSING_OBJECT_MARKERS = ['not a valid object name', 'not a valid commit', 'bad object', 'unknown revision'];
55
+ export async function checkRemoteIsAncestor(run, worktree, remoteSha, localSha) {
56
+ try {
57
+ await run(`git merge-base --is-ancestor ${shellEscape(remoteSha)} ${shellEscape(localSha)}`, { cwd: worktree });
58
+ return { status: 'ancestor' };
59
+ }
60
+ catch (err) {
61
+ // Exit 1 is git's documented "not an ancestor"; other non-zero statuses are errors.
62
+ if (err?.code === 1)
63
+ return { status: 'diverged' };
64
+ const detail = shortDetail(err);
65
+ // A remote commit absent from the local object store cannot be contained in local HEAD.
66
+ if (MISSING_OBJECT_MARKERS.some((marker) => detail.toLowerCase().includes(marker)))
67
+ return { status: 'diverged' };
68
+ return { status: 'unreadable', detail };
69
+ }
70
+ }
71
+ //# sourceMappingURL=ship-git-detail.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ship-git-detail.js","sourceRoot":"","sources":["../../src/phases/ship-git-detail.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import { type CommandRunner, type PushFailureKind } from './ship-git-detail.js';
2
+ /** The result of comparing the pushed branch's remote head against local HEAD (#735). */
3
+ type RemoteHeadCheck = {
4
+ status: 'match';
5
+ localSha: string;
6
+ remoteSha: string;
7
+ } | {
8
+ status: 'mismatch';
9
+ localSha: string;
10
+ remoteSha: string;
11
+ } | {
12
+ status: 'unreadable';
13
+ localSha?: string;
14
+ remoteSha?: string;
15
+ detail: string;
16
+ };
17
+ /** origin/<branch>'s current SHA, `null` when the branch is absent, or the failure detail (#1869). */
18
+ export declare function readRemoteBranchSha(run: CommandRunner, worktree: string, branch: string): Promise<{
19
+ status: 'ok';
20
+ sha: string | null;
21
+ } | {
22
+ status: 'unreadable';
23
+ detail: string;
24
+ }>;
25
+ /**
26
+ * A zero-exit push is not proof the remote branch actually carries this run's commits — a
27
+ * concurrent push or an update that silently applied nothing leaves the remote head elsewhere,
28
+ * and a PR opened against it would advertise work that is not there (#735).
29
+ */
30
+ export declare function verifyRemoteHead(run: CommandRunner, worktree: string, branch: string): Promise<RemoteHeadCheck>;
31
+ /** Outcome of one push followed by a remote-head check, the single verified push site for SHIP (#734/#735/#1813). */
32
+ export type VerifiedPush = {
33
+ status: 'pushed';
34
+ localSha: string;
35
+ remoteSha: string;
36
+ } | {
37
+ status: 'push-failed';
38
+ kind: PushFailureKind;
39
+ detail: string;
40
+ } | {
41
+ status: 'mismatch';
42
+ localSha: string;
43
+ remoteSha: string;
44
+ } | {
45
+ status: 'unreadable';
46
+ localSha?: string;
47
+ detail: string;
48
+ };
49
+ export declare function pushAndVerifyRemoteHead(run: CommandRunner, worktree: string, branch: string, pushCmd: string): Promise<VerifiedPush>;
50
+ export {};
51
+ //# sourceMappingURL=ship-git-remote.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ship-git-remote.d.ts","sourceRoot":"","sources":["../../src/phases/ship-git-remote.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,aAAa,EAAuB,KAAK,eAAe,EAAe,MAAM,sBAAsB,CAAC;AAElH,yFAAyF;AACzF,KAAK,eAAe,GAChB;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACxD;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAapF,sGAAsG;AACtG,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,aAAa,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAO1F;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAuBrH;AAED,qHAAqH;AACrH,MAAM,MAAM,YAAY,GACpB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAChE;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhE,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,aAAa,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,YAAY,CAAC,CAUvB"}
@@ -0,0 +1,70 @@
1
+ // packages/core/src/phases/ship-git-remote.ts — remote-head verification and verified push for SHIP
2
+ import { shellEscape } from '../utils/index.js';
3
+ import { describePushFailure, shortDetail } from './ship-git-detail.js';
4
+ /** The SHA on the `refs/heads/<branch>` line of `git ls-remote` output. `--heads origin <branch>`
5
+ * is a suffix pattern, so it can list more than one ref — match the ref name exactly rather than
6
+ * trusting the first line. */
7
+ function parseRemoteHeadSha(stdout, branch) {
8
+ for (const line of stdout.split('\n')) {
9
+ const [sha, ref] = line.trim().split(/\s+/);
10
+ if (ref === `refs/heads/${branch}` && sha)
11
+ return sha;
12
+ }
13
+ return undefined;
14
+ }
15
+ /** origin/<branch>'s current SHA, `null` when the branch is absent, or the failure detail (#1869). */
16
+ export async function readRemoteBranchSha(run, worktree, branch) {
17
+ try {
18
+ const { stdout } = await run(`git ls-remote --heads origin ${shellEscape(branch)}`, { cwd: worktree });
19
+ return { status: 'ok', sha: parseRemoteHeadSha(stdout, branch) ?? null };
20
+ }
21
+ catch (err) {
22
+ return { status: 'unreadable', detail: shortDetail(err) };
23
+ }
24
+ }
25
+ /**
26
+ * A zero-exit push is not proof the remote branch actually carries this run's commits — a
27
+ * concurrent push or an update that silently applied nothing leaves the remote head elsewhere,
28
+ * and a PR opened against it would advertise work that is not there (#735).
29
+ */
30
+ export async function verifyRemoteHead(run, worktree, branch) {
31
+ let localSha;
32
+ try {
33
+ const { stdout } = await run('git rev-parse HEAD', { cwd: worktree });
34
+ localSha = stdout.trim();
35
+ }
36
+ catch (err) {
37
+ return { status: 'unreadable', detail: shortDetail(err) };
38
+ }
39
+ if (!localSha)
40
+ return { status: 'unreadable', detail: 'git rev-parse HEAD produced no SHA' };
41
+ let listing;
42
+ try {
43
+ const { stdout } = await run(`git ls-remote --heads origin ${shellEscape(branch)}`, { cwd: worktree });
44
+ listing = stdout;
45
+ }
46
+ catch (err) {
47
+ return { status: 'unreadable', localSha, detail: shortDetail(err) };
48
+ }
49
+ const remoteSha = parseRemoteHeadSha(listing, branch);
50
+ if (!remoteSha)
51
+ return { status: 'unreadable', localSha, detail: `no refs/heads/${branch} on origin` };
52
+ return remoteSha === localSha
53
+ ? { status: 'match', localSha, remoteSha }
54
+ : { status: 'mismatch', localSha, remoteSha };
55
+ }
56
+ export async function pushAndVerifyRemoteHead(run, worktree, branch, pushCmd) {
57
+ try {
58
+ await run(pushCmd, { cwd: worktree });
59
+ }
60
+ catch (err) {
61
+ return { status: 'push-failed', ...describePushFailure(err) };
62
+ }
63
+ const head = await verifyRemoteHead(run, worktree, branch);
64
+ if (head.status === 'match')
65
+ return { status: 'pushed', localSha: head.localSha, remoteSha: head.remoteSha };
66
+ if (head.status === 'mismatch')
67
+ return head;
68
+ return { status: 'unreadable', localSha: head.localSha, detail: head.detail };
69
+ }
70
+ //# sourceMappingURL=ship-git-remote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ship-git-remote.js","sourceRoot":"","sources":["../../src/phases/ship-git-remote.ts"],"names":[],"mappings":"AAAA,oGAAoG;AAEpG,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAsB,mBAAmB,EAAwB,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAQlH;;+BAE+B;AAC/B,SAAS,kBAAkB,CAAC,MAAc,EAAE,MAAc;IACxD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5C,IAAI,GAAG,KAAK,cAAc,MAAM,EAAE,IAAI,GAAG;YAAE,OAAO,GAAG,CAAC;IACxD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,sGAAsG;AACtG,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,GAAkB,EAClB,QAAgB,EAChB,MAAc;IAEd,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,gCAAgC,WAAW,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QACvG,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;IAC3E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;IAC5D,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,GAAkB,EAAE,QAAgB,EAAE,MAAc;IACzF,IAAI,QAA4B,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,oBAAoB,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QACtE,QAAQ,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC3B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;IAC5D,CAAC;IACD,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,oCAAoC,EAAE,CAAC;IAE7F,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,gCAAgC,WAAW,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QACvG,OAAO,GAAG,MAAM,CAAC;IACnB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;IACtE,CAAC;IAED,MAAM,SAAS,GAAG,kBAAkB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACtD,IAAI,CAAC,SAAS;QAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,iBAAiB,MAAM,YAAY,EAAE,CAAC;IACvG,OAAO,SAAS,KAAK,QAAQ;QAC3B,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE;QAC1C,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;AAClD,CAAC;AASD,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,GAAkB,EAClB,QAAgB,EAChB,MAAc,EACd,OAAe;IAEf,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,mBAAmB,CAAC,GAAG,CAAC,EAAE,CAAC;IAChE,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC3D,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO;QAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;IAC7G,IAAI,IAAI,CAAC,MAAM,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IAC5C,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;AAChF,CAAC"}