@telora/daemon 0.22.208 → 0.22.226

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 (212) hide show
  1. package/build-info.json +2 -2
  2. package/dist/backends/index.d.ts.map +1 -1
  3. package/dist/backends/index.js +3 -1
  4. package/dist/backends/index.js.map +1 -1
  5. package/dist/completion/advancement-stall-watchdog.d.ts.map +1 -1
  6. package/dist/completion/advancement-stall-watchdog.js +6 -2
  7. package/dist/completion/advancement-stall-watchdog.js.map +1 -1
  8. package/dist/completion/completion-decision.d.ts +10 -1
  9. package/dist/completion/completion-decision.d.ts.map +1 -1
  10. package/dist/completion/completion-decision.js +1 -1
  11. package/dist/completion/completion-decision.js.map +1 -1
  12. package/dist/completion/delivery-advancement-guard.d.ts +31 -16
  13. package/dist/completion/delivery-advancement-guard.d.ts.map +1 -1
  14. package/dist/completion/delivery-advancement-guard.js +22 -37
  15. package/dist/completion/delivery-advancement-guard.js.map +1 -1
  16. package/dist/completion/detector.d.ts.map +1 -1
  17. package/dist/completion/detector.js +3 -1
  18. package/dist/completion/detector.js.map +1 -1
  19. package/dist/completion/event-phases.d.ts +19 -8
  20. package/dist/completion/event-phases.d.ts.map +1 -1
  21. package/dist/completion/event-phases.js +67 -88
  22. package/dist/completion/event-phases.js.map +1 -1
  23. package/dist/completion/event.d.ts +12 -9
  24. package/dist/completion/event.d.ts.map +1 -1
  25. package/dist/completion/event.js +6 -3
  26. package/dist/completion/event.js.map +1 -1
  27. package/dist/completion/index.js +1 -1
  28. package/dist/completion/progress-snapshot.d.ts +13 -9
  29. package/dist/completion/progress-snapshot.d.ts.map +1 -1
  30. package/dist/completion/progress-snapshot.js +16 -13
  31. package/dist/completion/progress-snapshot.js.map +1 -1
  32. package/dist/completion/reengagement-redrive.d.ts +8 -1
  33. package/dist/completion/reengagement-redrive.d.ts.map +1 -1
  34. package/dist/completion/reengagement-redrive.js +16 -2
  35. package/dist/completion/reengagement-redrive.js.map +1 -1
  36. package/dist/completion/state-cascade.d.ts.map +1 -1
  37. package/dist/completion/state-cascade.js +11 -19
  38. package/dist/completion/state-cascade.js.map +1 -1
  39. package/dist/completion/team-progress-measure.d.ts +70 -0
  40. package/dist/completion/team-progress-measure.d.ts.map +1 -0
  41. package/dist/completion/team-progress-measure.js +285 -0
  42. package/dist/completion/team-progress-measure.js.map +1 -0
  43. package/dist/completion/team-stillness.d.ts +76 -0
  44. package/dist/completion/team-stillness.d.ts.map +1 -0
  45. package/dist/completion/team-stillness.js +96 -0
  46. package/dist/completion/team-stillness.js.map +1 -0
  47. package/dist/completion/worker-wait.d.ts +84 -0
  48. package/dist/completion/worker-wait.d.ts.map +1 -0
  49. package/dist/completion/worker-wait.js +89 -0
  50. package/dist/completion/worker-wait.js.map +1 -0
  51. package/dist/delivery/delivery-advance-block.d.ts.map +1 -1
  52. package/dist/delivery/delivery-advance-block.js +1 -2
  53. package/dist/delivery/delivery-advance-block.js.map +1 -1
  54. package/dist/focus/focus-lifecycle.d.ts.map +1 -1
  55. package/dist/focus/focus-lifecycle.js +7 -1
  56. package/dist/focus/focus-lifecycle.js.map +1 -1
  57. package/dist/focus/focus-team-state.js +1 -1
  58. package/dist/focus/focus-worktree-state.d.ts.map +1 -1
  59. package/dist/focus/focus-worktree-state.js +2 -1
  60. package/dist/focus/focus-worktree-state.js.map +1 -1
  61. package/dist/git/focus-integration-sync.d.ts +42 -4
  62. package/dist/git/focus-integration-sync.d.ts.map +1 -1
  63. package/dist/git/focus-integration-sync.js +53 -9
  64. package/dist/git/focus-integration-sync.js.map +1 -1
  65. package/dist/git/types.d.ts.map +1 -1
  66. package/dist/git/types.js +4 -2
  67. package/dist/git/types.js.map +1 -1
  68. package/dist/merge/merge-back-loop.d.ts.map +1 -1
  69. package/dist/merge/merge-back-loop.js +0 -1
  70. package/dist/merge/merge-back-loop.js.map +1 -1
  71. package/dist/queries/deliveries.d.ts.map +1 -1
  72. package/dist/queries/deliveries.js +3 -1
  73. package/dist/queries/deliveries.js.map +1 -1
  74. package/dist/queries/delivery-gate-state.js +1 -1
  75. package/dist/queries/escalation-suppression.js +1 -1
  76. package/dist/queries/focus-integration-conflict.d.ts +7 -4
  77. package/dist/queries/focus-integration-conflict.d.ts.map +1 -1
  78. package/dist/queries/focus-integration-conflict.js +6 -3
  79. package/dist/queries/focus-integration-conflict.js.map +1 -1
  80. package/dist/queries/schemas.d.ts +15 -0
  81. package/dist/queries/schemas.d.ts.map +1 -1
  82. package/dist/queries/schemas.js +12 -1
  83. package/dist/queries/schemas.js.map +1 -1
  84. package/dist/queries/shortfall-park-record.d.ts +6 -1
  85. package/dist/queries/shortfall-park-record.d.ts.map +1 -1
  86. package/dist/queries/shortfall-park-record.js.map +1 -1
  87. package/dist/queries/shortfall-rulings.d.ts +14 -2
  88. package/dist/queries/shortfall-rulings.d.ts.map +1 -1
  89. package/dist/queries/shortfall-rulings.js +17 -3
  90. package/dist/queries/shortfall-rulings.js.map +1 -1
  91. package/dist/queries/verification.js +1 -1
  92. package/dist/queries/verify-own-holds.d.ts.map +1 -1
  93. package/dist/queries/verify-own-holds.js +1 -0
  94. package/dist/queries/verify-own-holds.js.map +1 -1
  95. package/dist/spawn/helpers.d.ts.map +1 -1
  96. package/dist/spawn/helpers.js +9 -1
  97. package/dist/spawn/helpers.js.map +1 -1
  98. package/dist/spawn/lead-continuation.d.ts +10 -2
  99. package/dist/spawn/lead-continuation.d.ts.map +1 -1
  100. package/dist/spawn/lead-continuation.js +39 -22
  101. package/dist/spawn/lead-continuation.js.map +1 -1
  102. package/dist/spawn/one-shot-model.d.ts.map +1 -1
  103. package/dist/spawn/one-shot-model.js +1 -0
  104. package/dist/spawn/one-shot-model.js.map +1 -1
  105. package/dist/spawn/worktree-session.d.ts.map +1 -1
  106. package/dist/spawn/worktree-session.js +11 -1
  107. package/dist/spawn/worktree-session.js.map +1 -1
  108. package/dist/testing/fixtures/conflicting-repo.d.ts +17 -0
  109. package/dist/testing/fixtures/conflicting-repo.d.ts.map +1 -1
  110. package/dist/testing/fixtures/conflicting-repo.js +31 -0
  111. package/dist/testing/fixtures/conflicting-repo.js.map +1 -1
  112. package/dist/testing/fixtures/index.d.ts.map +1 -1
  113. package/dist/testing/fixtures/index.js +1 -2
  114. package/dist/testing/fixtures/index.js.map +1 -1
  115. package/dist/types/focus.d.ts +59 -26
  116. package/dist/types/focus.d.ts.map +1 -1
  117. package/dist/types/index.js +1 -1
  118. package/dist/verify/commit-verdict-pull.d.ts +28 -3
  119. package/dist/verify/commit-verdict-pull.d.ts.map +1 -1
  120. package/dist/verify/commit-verdict-pull.js +160 -23
  121. package/dist/verify/commit-verdict-pull.js.map +1 -1
  122. package/dist/verify/credit-rearm.d.ts.map +1 -1
  123. package/dist/verify/credit-rearm.js +72 -17
  124. package/dist/verify/credit-rearm.js.map +1 -1
  125. package/dist/verify/default-on-guards.d.ts +54 -8
  126. package/dist/verify/default-on-guards.d.ts.map +1 -1
  127. package/dist/verify/default-on-guards.js +132 -17
  128. package/dist/verify/default-on-guards.js.map +1 -1
  129. package/dist/verify/explicit-rearm.d.ts.map +1 -1
  130. package/dist/verify/explicit-rearm.js +1 -0
  131. package/dist/verify/explicit-rearm.js.map +1 -1
  132. package/dist/verify/explicit-row-selection.d.ts +47 -0
  133. package/dist/verify/explicit-row-selection.d.ts.map +1 -0
  134. package/dist/verify/explicit-row-selection.js +37 -0
  135. package/dist/verify/explicit-row-selection.js.map +1 -0
  136. package/dist/verify/gate-run-registry.d.ts.map +1 -1
  137. package/dist/verify/gate-run-registry.js +2 -0
  138. package/dist/verify/gate-run-registry.js.map +1 -1
  139. package/dist/verify/parked-shortfall-reuse.d.ts +194 -0
  140. package/dist/verify/parked-shortfall-reuse.d.ts.map +1 -0
  141. package/dist/verify/parked-shortfall-reuse.js +310 -0
  142. package/dist/verify/parked-shortfall-reuse.js.map +1 -0
  143. package/dist/verify/reselection-log.d.ts +22 -0
  144. package/dist/verify/reselection-log.d.ts.map +1 -0
  145. package/dist/verify/reselection-log.js +87 -0
  146. package/dist/verify/reselection-log.js.map +1 -0
  147. package/dist/verify/shortfall-park.d.ts +8 -1
  148. package/dist/verify/shortfall-park.d.ts.map +1 -1
  149. package/dist/verify/shortfall-park.js +17 -3
  150. package/dist/verify/shortfall-park.js.map +1 -1
  151. package/dist/verify/shortfall-repeat.d.ts.map +1 -1
  152. package/dist/verify/shortfall-repeat.js +7 -2
  153. package/dist/verify/shortfall-repeat.js.map +1 -1
  154. package/dist/verify/shortfall-rulings.d.ts +93 -6
  155. package/dist/verify/shortfall-rulings.d.ts.map +1 -1
  156. package/dist/verify/shortfall-rulings.js +69 -12
  157. package/dist/verify/shortfall-rulings.js.map +1 -1
  158. package/dist/verify/stall-detector-config.d.ts.map +1 -1
  159. package/dist/verify/stall-detector-config.js +2 -1
  160. package/dist/verify/stall-detector-config.js.map +1 -1
  161. package/dist/verify/stall-detectors.d.ts +6 -4
  162. package/dist/verify/stall-detectors.d.ts.map +1 -1
  163. package/dist/verify/stall-detectors.js +9 -6
  164. package/dist/verify/stall-detectors.js.map +1 -1
  165. package/dist/verify/stalled-team-backstop.d.ts +8 -2
  166. package/dist/verify/stalled-team-backstop.d.ts.map +1 -1
  167. package/dist/verify/stalled-team-backstop.js +15 -11
  168. package/dist/verify/stalled-team-backstop.js.map +1 -1
  169. package/dist/verify/team-stall-reapers.d.ts +28 -0
  170. package/dist/verify/team-stall-reapers.d.ts.map +1 -0
  171. package/dist/verify/team-stall-reapers.js +23 -0
  172. package/dist/verify/team-stall-reapers.js.map +1 -0
  173. package/dist/verify/verification-attribution-deps.d.ts +1 -1
  174. package/dist/verify/verification-attribution-deps.d.ts.map +1 -1
  175. package/dist/verify/verification-attribution-deps.js +20 -1
  176. package/dist/verify/verification-attribution-deps.js.map +1 -1
  177. package/dist/verify/verification-boundary-env.d.ts.map +1 -1
  178. package/dist/verify/verification-boundary-env.js +23 -9
  179. package/dist/verify/verification-boundary-env.js.map +1 -1
  180. package/dist/verify/verification-checkout.d.ts +1 -1
  181. package/dist/verify/verification-checkout.d.ts.map +1 -1
  182. package/dist/verify/verification-checkout.js.map +1 -1
  183. package/dist/verify/verification-commit-sharing.d.ts.map +1 -1
  184. package/dist/verify/verification-commit-sharing.js +14 -3
  185. package/dist/verify/verification-commit-sharing.js.map +1 -1
  186. package/dist/verify/verification-config.d.ts.map +1 -1
  187. package/dist/verify/verification-config.js +1 -20
  188. package/dist/verify/verification-config.js.map +1 -1
  189. package/dist/verify/verification-default-on.d.ts +4 -1
  190. package/dist/verify/verification-default-on.d.ts.map +1 -1
  191. package/dist/verify/verification-default-on.js +29 -2
  192. package/dist/verify/verification-default-on.js.map +1 -1
  193. package/dist/verify/verification-deps-default.d.ts.map +1 -1
  194. package/dist/verify/verification-deps-default.js +13 -0
  195. package/dist/verify/verification-deps-default.js.map +1 -1
  196. package/dist/verify/verification-deps.d.ts +38 -0
  197. package/dist/verify/verification-deps.d.ts.map +1 -1
  198. package/dist/verify/verification-deps.js +2 -1
  199. package/dist/verify/verification-deps.js.map +1 -1
  200. package/dist/verify/verification-engine.d.ts.map +1 -1
  201. package/dist/verify/verification-engine.js +44 -15
  202. package/dist/verify/verification-engine.js.map +1 -1
  203. package/dist/verify/verification-feedback.d.ts.map +1 -1
  204. package/dist/verify/verification-feedback.js +1 -19
  205. package/dist/verify/verification-feedback.js.map +1 -1
  206. package/dist/verify/verify-restatement.d.ts.map +1 -1
  207. package/dist/verify/verify-restatement.js +5 -1
  208. package/dist/verify/verify-restatement.js.map +1 -1
  209. package/dist/worktree/provision.d.ts.map +1 -1
  210. package/dist/worktree/provision.js +3 -1
  211. package/dist/worktree/provision.js.map +1 -1
  212. package/package.json +1 -1
@@ -1,6 +1,8 @@
1
1
  // PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
2
2
  // Pinned by: packages/daemon/src/integration/held-route-pull-dispatch.test.ts,
3
- // packages/daemon/src/verify/commit-verdict-pull.test.ts
3
+ // packages/daemon/src/verify/commit-verdict-pull.test.ts,
4
+ // packages/daemon/src/verify/reselection-log.test.ts,
5
+ // packages/daemon/src/verify/verification-default-on.test.ts
4
6
  // PINNED-BY-END
5
7
  /**
6
8
  * A held route PULLS the gate run for the commit it awaits.
@@ -39,22 +41,72 @@
39
41
  * asks again next poll. Pulling a run for an unknown commit would judge
40
42
  * whatever HEAD happens to be.
41
43
  * - **No second run.** Not while a run that may judge the commit is selected or
42
- * in flight (verify/gate-run-registry.ts), and at most once per (delivery,
43
- * sha) in this process. A dispatch that renders nothing releases its own run
44
- * mark and records no pass, so the scan selects the delivery again on its own
45
- * -- the pull mark suppresses nothing that would otherwise run.
44
+ * in flight (verify/gate-run-registry.ts), and once per (delivery, sha) in
45
+ * this process until the verdict reads back (next rule). A dispatch that
46
+ * renders nothing records no pass, and ordinarily releases its own run mark,
47
+ * so the scan selects the delivery again on its own -- the pull mark
48
+ * suppresses nothing that would otherwise run. The exception is a
49
+ * checkout- or model-unavailable attempt on a STANDING park: it keeps a run
50
+ * mark naming no commit (verify/default-on-guards.ts noteDefaultOnResult
51
+ * declines that un-mark), so nothing else re-selects it -- and the next rule
52
+ * is what recognises that settled attempt and pulls again.
53
+ * - **A pull is not spent until its verdict reads back.** The per-commit record
54
+ * write is BEST-EFFORT (verify/commit-verdict-record.ts writeCommitVerdict
55
+ * returns false and the recorder discards it), so the run a pull caused can
56
+ * render on the held sha and still leave the release reading 'pending'. A
57
+ * commit already pulled for is pulled AGAIN once the attempt it caused has
58
+ * SETTLED -- a run mark exists again (a dispatch was attempted) and the
59
+ * gate-run registry holds no run selected or in flight -- and the release
60
+ * pass's own read (below) still returns a readable 'pending'. Two settled
61
+ * outcomes qualify, and the re-pull's log line names which one it saw: a
62
+ * run that JUDGED the held sha (its mark names it) whose write did not land,
63
+ * and an attempt that RENDERED NOTHING (its mark names no commit) -- a
64
+ * checkout-less retry on a standing park, whose preserved mark is the only
65
+ * trace it ran; requiring the mark to name the sha would strand the route
66
+ * there. 'passed' is answered;
67
+ * 'failed' is the gate's answer; an unreadable read waits for the next scan
68
+ * rather than paying a run on an unknown. Each re-pull costs one run and
69
+ * only after the previous one ended, so a store that stays down costs one
70
+ * run per scan, and a store that recovers is written by the next one.
46
71
  * - **The failure guard stays authoritative.** Only the run mark and the
47
72
  * recorded PASS are dropped. A recorded failure at the held commit means the
48
73
  * gate already answered; verification feedback routes the delivery to
49
74
  * verify_failed, and re-running the same commit would answer the same way.
50
75
  *
51
- * What it deliberately does NOT do: ask whether a verdict for the sha already
52
- * exists. That question needs the delivery's CommitVerdictGate resolved
53
- * (verify/commit-gate-configured.ts, async and config-reading) inside an
54
- * otherwise cheap scan seam, and it would duplicate a rule that already has one
55
- * home -- verify/verification-commit-sharing.ts reuses a recorded verdict instead
56
- * of running the gate, so a pull whose commit is already judged costs one
57
- * dispatch that reuses and routes, not a suite. Same shape as credit-rearm.ts.
76
+ * - **A parked delivery at the held commit is not pulled -- when the verdict
77
+ * is READABLE.** The pull DECLINES, and says so, only when all three hold:
78
+ * this process already judged the delivery ON the held sha (its run mark
79
+ * names it); the shortfall park that judgement left stands on an unchanged
80
+ * commit set and unchanged rulings (verify/parked-shortfall-reuse.ts
81
+ * parkHoldsOnUnchangedFacts); and the release pass's OWN verdict read
82
+ * (readHeldCommitVerdictState -- completion/review-exit-verdict-gate.ts
83
+ * readGateVerdictState, the read completion/commit-verdict-release.ts
84
+ * releases on) returns 'passed' for that sha. Then a re-selection is neither
85
+ * a new ruling nor a new commit and is not needed: the release replays from
86
+ * the record with no run.
87
+ *
88
+ * The third condition is not implied by the first two. The per-commit
89
+ * record write is BEST-EFFORT (verify/commit-verdict-record.ts
90
+ * writeCommitVerdict returns false and the recorder discards it), so a
91
+ * passing run can park a delivery while leaving no verdict behind. Declining
92
+ * there would leave the release reading 'pending' forever -- a wedge. So the
93
+ * pull asks the reader the release asks, and anything but 'passed' pulls:
94
+ * the run it causes writes the record again. A mark on another commit, no
95
+ * mark (a restart), no product id, no reader, or any unknown fact pulls as
96
+ * before -- this may only remove a pull it can prove is pointless.
97
+ *
98
+ * THE VERDICT READ, and what it is not. Two rules above -- the park decline and
99
+ * the re-pull -- ask the release pass's OWN verdict reader
100
+ * (readHeldCommitVerdictState: completion/review-exit-verdict-gate.ts
101
+ * readGateVerdictState over the delivery's resolved CommitVerdictGate,
102
+ * verify/commit-gate-configured.ts), and they ask it only for a delivery this
103
+ * process already dispatched for the held sha. They ask whether the route's wait is
104
+ * OVER, never whether a run may be skipped: a first pull on a commit is not
105
+ * declined because a verdict exists -- only where the park ALSO stands on
106
+ * unchanged facts, so a re-selection could change nothing. Reusing a recorded verdict instead
107
+ * of running the gate has one home -- verify/verification-commit-sharing.ts --
108
+ * so a pull whose commit is already judged costs one dispatch that reuses and
109
+ * routes, not a suite. Same shape as credit-rearm.ts.
58
110
  *
59
111
  * Wrapper shape follows the two existing re-arm seams (verify/credit-rearm.ts
60
112
  * withCreditRearm, verify/shortfall-rulings.ts withShortfallRulingRearm): wrap the
@@ -67,16 +119,80 @@ import { DELIVERY_STATUS } from '@telora/daemon-core';
67
119
  import { readCommitVerdictHold } from '../delivery/commit-verdict-hold.js';
68
120
  import { hasPendingGateRun, isGateRunSelected } from './gate-run-registry.js';
69
121
  import { defaultResolveFocusHeadSha } from './verification-default-on.js';
70
- import { forgetRecordedPass, releaseDefaultOnMark } from './default-on-guards.js';
122
+ import { forgetRecordedPass, hasDefaultOnRunMark, judgedShaOfRunMark, releaseDefaultOnMark } from './default-on-guards.js';
123
+ import { parkHoldsOnUnchangedFacts } from './parked-shortfall-reuse.js';
124
+ import { logReselection } from './reselection-log.js';
71
125
  import { createLogger } from '../shell/log.js';
72
126
  const log = createLogger({ module: 'verification' });
73
127
  const defaultPullDeps = {
74
128
  resolveFocusHeadSha: defaultResolveFocusHeadSha,
75
129
  hasPendingGateRun,
76
130
  isGateRunSelected,
77
- releaseRunMark: releaseDefaultOnMark,
131
+ // Names itself, so the guard's fallback line does not also speak: the pull's own
132
+ // line below is the one that says why (verify/reselection-log.ts).
133
+ releaseRunMark: (deliveryId) => releaseDefaultOnMark(deliveryId, 'commit-verdict-pull'),
78
134
  forgetRecordedPass,
79
135
  };
136
+ /**
137
+ * The two answers that read the held verdict through the release pass's own
138
+ * reader, when the caller can supply it and the product to key it by.
139
+ *
140
+ * parkAnswersHeldCommit is TRUE only where this process already judged the
141
+ * delivery ON the held commit (its run mark names it), the park the judgement
142
+ * left stands on unchanged facts, and the held verdict reads 'passed'. Every
143
+ * other case -- no mark (a restart), a mark on another commit, no injection, a
144
+ * verdict that did not persist, any unknown -- answers false, and the pull fires.
145
+ *
146
+ * heldVerdictStillAwaited is TRUE only where the attempt the pull caused has
147
+ * SETTLED (a run mark exists again, and no run is selected or in flight -- the
148
+ * caller asks the gate-run registry first) and the held verdict reads a
149
+ * readable 'pending': the write that run owed did not land, or the attempt
150
+ * rendered nothing (no checkout). 'passed' is
151
+ * answered, 'failed' is the gate's answer (re-running would repeat it), and an
152
+ * unreadable read waits for the next scan rather than paying a run on an unknown.
153
+ */
154
+ function heldAnswersFrom(deps, productId) {
155
+ const readHeld = deps.readHeldCommitVerdictState;
156
+ if (!readHeld || !productId)
157
+ return {};
158
+ const heldState = async (focusId, d, sha) => {
159
+ try {
160
+ return await readHeld({
161
+ productId, focusId, focusReadOnly: false, deliveryId: d.id, injectionId: d.injectionId ?? null, gateState: d.gateState,
162
+ }, sha);
163
+ }
164
+ catch {
165
+ return null; // unreadable: an unknown, never a decline and never a paid run
166
+ }
167
+ };
168
+ return {
169
+ // A mark means a dispatch was attempted since the pull dropped it; the caller
170
+ // has already refused a run that is selected or in flight (the gate-run
171
+ // registry), so the attempt SETTLED -- whether it judged the sha, or named no
172
+ // commit at all (a checkout-less retry the park declined to un-mark).
173
+ heldVerdictStillAwaited: async (focusId, d, sha) => hasDefaultOnRunMark(d.id) && await heldState(focusId, d, sha) === 'pending',
174
+ ...(deps.readDeliveryGateRecord ? {
175
+ parkAnswersHeldCommit: async (focusId, d, sha) => {
176
+ if (judgedShaOfRunMark(d.id) !== sha || !d.injectionId)
177
+ return false;
178
+ const parked = await parkHoldsOnUnchangedFacts({
179
+ deliveryId: d.id,
180
+ deliveryName: d.name ?? d.id,
181
+ productId: null,
182
+ focusId,
183
+ injectionNodeId: d.injectionId,
184
+ verificationMethod: 'deterministic',
185
+ verificationConfig: null,
186
+ verificationOutcome: null,
187
+ verificationLastRunAt: null,
188
+ gitState: d.gitState ?? null,
189
+ mergeCommitSha: d.mergeCommitSha ?? null,
190
+ }, sha, deps);
191
+ return parked && await heldState(focusId, d, sha) === 'passed';
192
+ },
193
+ } : {}),
194
+ };
195
+ }
80
196
  /** The commit each delivery was last pulled for in this process. */
81
197
  const pulledAt = new Map();
82
198
  /** Test-only: forget every pull this process made. */
@@ -90,7 +206,7 @@ export function __resetCommitVerdictPullForTests() {
90
206
  * selects the delivery, and the ordinary dispatch runs the gate under the same
91
207
  * semaphore and cap and records the verdict under the same per-commit record.
92
208
  */
93
- export function pullHeldCommitVerdicts(focusId, deliveries, deps = defaultPullDeps) {
209
+ export async function pullHeldCommitVerdicts(focusId, deliveries, deps = defaultPullDeps) {
94
210
  const pulled = [];
95
211
  let head;
96
212
  const readHead = () => (head ??= { sha: deps.resolveFocusHeadSha(focusId) }).sha;
@@ -101,20 +217,34 @@ export function pullHeldCommitVerdicts(focusId, deliveries, deps = defaultPullDe
101
217
  // No hold, or a hold whose judged commit was unreadable: nothing to aim a run at.
102
218
  if (hold === null || hold.sha === null)
103
219
  continue;
104
- if (pulledAt.get(d.id) === hold.sha)
105
- continue;
106
220
  // A run that may judge the commit is already coming; a second would answer the same question.
107
221
  if (deps.isGateRunSelected(d.id) || deps.hasPendingGateRun(focusId, hold.sha))
108
222
  continue;
109
223
  // A run judges the worktree HEAD, so a hold naming another commit cannot be served by one.
110
224
  if (readHead() !== hold.sha)
111
225
  continue;
226
+ const again = pulledAt.get(d.id) === hold.sha;
227
+ // Asked for this sha already: spent only once the verdict reads back, never before.
228
+ if (again && !(deps.heldVerdictStillAwaited && await deps.heldVerdictStillAwaited(focusId, d, hold.sha)))
229
+ continue;
230
+ if (!again && deps.parkAnswersHeldCommit && await deps.parkAnswersHeldCommit(focusId, d, hold.sha)) {
231
+ pulledAt.set(d.id, hold.sha); // answered for this sha; asked once, like a pull
232
+ logReselection('commit-verdict-pull', d.id, `DECLINED for ${hold.sha.slice(0, 8)}: its dispatch already judged that commit, its shortfall park stands on ` +
233
+ 'an unchanged commit set and unchanged rulings, and the passing verdict the held route awaits reads back; ' +
234
+ 'only a new ruling or a new commit re-selects it', `park-declined@${hold.sha}`);
235
+ continue;
236
+ }
237
+ // Read before the release below drops it: which settled outcome this re-pull answers.
238
+ const priorJudged = again ? judgedShaOfRunMark(d.id) : null;
112
239
  pulledAt.set(d.id, hold.sha);
113
240
  deps.releaseRunMark(d.id);
114
241
  deps.forgetRecordedPass(d.id);
115
242
  pulled.push(d.id);
116
- log.info(`[verification] commit-verdict pull: re-arming delivery "${d.name ?? d.id}" (${d.id}) for ${hold.sha.slice(0, 8)} -- ` +
117
- `its ${hold.route ?? 'done'} route has been held since ${hold.heldAt} for a verdict on that commit`);
243
+ logReselection('commit-verdict-pull', d.id, `re-armed for ${hold.sha.slice(0, 8)} -- delivery "${d.name ?? d.id}"'s ${hold.route ?? 'done'} route has been ` +
244
+ `held since ${hold.heldAt} for a verdict on that commit` +
245
+ (!again ? '' : priorJudged === hold.sha
246
+ ? '; the run that answered the last pull judged it, but its verdict does not read back'
247
+ : '; the attempt the last pull caused rendered nothing (no checkout or no verdict), and no verdict reads back'));
118
248
  }
119
249
  return pulled;
120
250
  }
@@ -130,13 +260,20 @@ export function pullHeldCommitVerdicts(focusId, deliveries, deps = defaultPullDe
130
260
  * only when the hold names HEAD -- is only as sound as its agreeing with the
131
261
  * selection that follows it.
132
262
  */
133
- export function withCommitVerdictPull(deps, pullDeps = deps.resolveFocusHeadSha
134
- ? { ...defaultPullDeps, resolveFocusHeadSha: deps.resolveFocusHeadSha }
135
- : defaultPullDeps) {
263
+ export function withCommitVerdictPull(deps, explicitPullDeps,
264
+ /** The product the scan runs over; the held verdict is keyed by it. Absent: the pull never declines. */
265
+ productId) {
266
+ const pullDeps = explicitPullDeps ?? {
267
+ ...defaultPullDeps,
268
+ ...(deps.resolveFocusHeadSha ? { resolveFocusHeadSha: deps.resolveFocusHeadSha } : {}),
269
+ // The park is asked through the SAME deps the dispatch reads it with, so the
270
+ // pull and the dispatch cannot answer differently about one park.
271
+ ...heldAnswersFrom(deps, productId),
272
+ };
136
273
  const getFocusDeliveriesPulling = async (focusId) => {
137
274
  const deliveries = await deps.getFocusDeliveries(focusId);
138
275
  try {
139
- pullHeldCommitVerdicts(focusId, deliveries, pullDeps);
276
+ await pullHeldCommitVerdicts(focusId, deliveries, pullDeps);
140
277
  }
141
278
  catch (err) {
142
279
  log.debug(`[verification] commit-verdict pull check failed for focus ${focusId.slice(0, 8)}:`, err.message);
@@ -1 +1 @@
1
- {"version":3,"file":"commit-verdict-pull.js","sourceRoot":"","sources":["../../src/verify/commit-verdict-pull.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"commit-verdict-pull.js","sourceRoot":"","sources":["../../src/verify/commit-verdict-pull.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"credit-rearm.d.ts","sourceRoot":"","sources":["../../src/verify/credit-rearm.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAU/D,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IACvF,OAAO,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAOD,4DAA4D;AAC5D,wBAAgB,0BAA0B,IAAI,IAAI,CAEjD;AAED,6FAA6F;AAC7F,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EAAE,EACrE,IAAI,GAAE,eAAkC,GACvC,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED,6GAA6G;AAC7G,wBAAgB,eAAe,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EACtF,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,EACvC,IAAI,GAAE,eAAkC,GACvC,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,CAUnC"}
1
+ {"version":3,"file":"credit-rearm.d.ts","sourceRoot":"","sources":["../../src/verify/credit-rearm.ts"],"names":[],"mappings":"AAuCA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AA+B/D,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IACvF,OAAO,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AASD,4DAA4D;AAC5D,wBAAgB,0BAA0B,IAAI,IAAI,CAEjD;AAED,6FAA6F;AAC7F,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EAAE,EACrE,IAAI,GAAE,eAAkC,GACvC,OAAO,CAAC,IAAI,CAAC,CAgCf;AAED,6GAA6G;AAC7G,wBAAgB,eAAe,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EACtF,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,EACvC,IAAI,GAAE,eAAkC,GACvC,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,CAUnC"}
@@ -1,5 +1,7 @@
1
1
  // PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
2
- // Pinned by: packages/daemon/src/verify/credit-rearm.test.ts
2
+ // Pinned by: packages/daemon/src/verify/credit-rearm.test.ts,
3
+ // packages/daemon/src/verify/reselection-log.test.ts,
4
+ // packages/daemon/src/verify/verification-default-on.test.ts
3
5
  // PINNED-BY-END
4
6
  /**
5
7
  * A new commit credit re-arms the focus's deliveries sitting in verify.
@@ -11,23 +13,62 @@
11
13
  * diagnosis, which stops re-queuing -- would never be re-judged with the credit.
12
14
  *
13
15
  * This watches each focus's credit set as the verification scan reads the
14
- * focus's deliveries. When the set differs from the one last seen, every
15
- * delivery of the focus in verify has its run mark released, so the next scan
16
- * judges it again at the same commit (the per-commit gate verdict is reused, so
17
- * no suite re-runs; only the evidence and reconciliation are re-read). The first
18
- * sighting of a focus only records the set: after a restart nothing is marked.
19
- * An unreadable credit read changes nothing.
16
+ * focus's deliveries. The run mark is released for a delivery whose OWN credited
17
+ * commits changed, so the next scan judges it again at the same commit (the
18
+ * per-commit gate verdict is reused, so no suite re-runs; only the evidence and
19
+ * reconciliation are re-read). The first sighting of a focus only records the
20
+ * set: after a restart nothing is marked. An unreadable credit read changes
21
+ * nothing.
22
+ *
23
+ * PER DELIVERY, NOT PER FOCUS -- and that distinction is the whole correctness
24
+ * of this module. It used to compare one fingerprint of the focus's WHOLE credit
25
+ * set and then release EVERY in-verify delivery when it moved, so attributing a
26
+ * commit to delivery A re-armed parked sibling B, whose own evidence had not
27
+ * changed at all. On 2026-09-24 that was one of the paths re-selecting a parked
28
+ * delivery at an unchanged HEAD: the declared rule is that only a new ruling or
29
+ * a new commit re-selects it, and a SIBLING's new commit is neither. A credit
30
+ * set is per-delivery data; reading it as a focus-wide scalar threw away exactly
31
+ * the attribution that makes it answerable.
32
+ *
33
+ * So the question asked here is "did THIS delivery's evidence change", which
34
+ * needs no park read and no extra IO: the credit map already carries the
35
+ * attribution, and a delivery whose own credits are unchanged is left alone.
20
36
  */
21
37
  import { DELIVERY_STATUS } from '@telora/daemon-core';
22
38
  import { getCommitAttributionsForFocus } from '../queries/commit-attributions.js';
23
39
  import { releaseDefaultOnMark } from './default-on-guards.js';
40
+ import { logReselection } from './reselection-log.js';
24
41
  import { createLogger } from '../shell/log.js';
25
42
  const log = createLogger({ module: 'verification' });
26
- /** Focus id -> fingerprint of the credit set last seen. */
43
+ /** Focus id -> each of its deliveries' own credit fingerprint, as last seen. */
27
44
  const seenCredits = new Map();
45
+ /**
46
+ * Each delivery's OWN credited commits, fingerprinted. The credit map is keyed by
47
+ * sha and VALUED by delivery, so the attribution is already there to be read --
48
+ * this only groups it the way the question is asked. Pure.
49
+ *
50
+ * A delivery credited nothing has no entry, which compares equal to '' below, so
51
+ * "no credits" and "no entry" are one state rather than a spurious change.
52
+ */
53
+ function creditsByDelivery(credits) {
54
+ const shas = new Map();
55
+ for (const [sha, deliveryId] of credits) {
56
+ const list = shas.get(deliveryId);
57
+ if (list)
58
+ list.push(sha);
59
+ else
60
+ shas.set(deliveryId, [sha]);
61
+ }
62
+ const out = new Map();
63
+ for (const [deliveryId, list] of shas)
64
+ out.set(deliveryId, list.sort().join(','));
65
+ return out;
66
+ }
28
67
  const defaultRearmDeps = {
29
68
  readCredits: getCommitAttributionsForFocus,
30
- release: releaseDefaultOnMark,
69
+ // Names itself, so the guard's own fallback line does not also speak: the
70
+ // per-delivery line below is the one that says why (verify/reselection-log.ts).
71
+ release: (deliveryId) => releaseDefaultOnMark(deliveryId, 'credit-rearm'),
31
72
  };
32
73
  /** Test-only: forget every focus's last-seen credit set. */
33
74
  export function __resetCreditRearmForTests() {
@@ -41,17 +82,31 @@ export async function rearmOnCreditChange(focusId, deliveries, deps = defaultRea
41
82
  const lookup = await deps.readCredits(focusId);
42
83
  if (lookup.state === 'undetermined')
43
84
  return;
44
- const fingerprint = lookup.state === 'found'
45
- ? [...lookup.value].map(([sha, deliveryId]) => `${sha}:${deliveryId}`).sort().join(',')
46
- : '';
85
+ const current = creditsByDelivery(lookup.state === 'found' ? lookup.value : new Map());
47
86
  const previous = seenCredits.get(focusId);
48
- seenCredits.set(focusId, fingerprint);
49
- if (previous === undefined || previous === fingerprint)
50
- return;
51
- for (const d of inVerify)
87
+ seenCredits.set(focusId, current);
88
+ if (previous === undefined)
89
+ return; // first sighting records only
90
+ const rearmed = [];
91
+ for (const d of inVerify) {
92
+ const before = previous.get(d.id) ?? '';
93
+ const now = current.get(d.id) ?? '';
94
+ // A SIBLING's credit is not this delivery's evidence, so it does not re-arm it.
95
+ if (before === now)
96
+ continue;
52
97
  deps.release(d.id);
98
+ rearmed.push(d.id);
99
+ // PER DELIVERY, not only per focus: the focus line below cannot be matched to
100
+ // the delivery a later dispatch names, which is exactly what the 2026-09-24
101
+ // re-dispatch investigation needed (verify/reselection-log.ts).
102
+ logReselection('credit-rearm', d.id, `its OWN commit credits on focus ${focusId} changed (${before === '' ? 'none' : before} -> `
103
+ + `${now === '' ? 'none' : now}), so its evidence is re-read at the same commit`);
104
+ }
105
+ if (rearmed.length === 0)
106
+ return;
53
107
  log.info(`[verification] commit credits changed on focus ${focusId.slice(0, 8)}: re-judging ` +
54
- `${inVerify.length} delivery(ies) in verify at the current commit`);
108
+ `${rearmed.length} of ${inVerify.length} delivery(ies) in verify at the current commit ` +
109
+ '(only those whose own credits moved)');
55
110
  }
56
111
  /** Wrap a focus-deliveries read so every read also checks the focus's credits. Never throws on the check. */
57
112
  export function withCreditRearm(read, deps = defaultRearmDeps) {
@@ -1 +1 @@
1
- {"version":3,"file":"credit-rearm.js","sourceRoot":"","sources":["../../src/verify/credit-rearm.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,6DAA6D;AAC7D,gBAAgB;AAEhB;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,6BAA6B,EAAE,MAAM,mCAAmC,CAAC;AAClF,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;AAErD,2DAA2D;AAC3D,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;AAO9C,MAAM,gBAAgB,GAAoB;IACxC,WAAW,EAAE,6BAA6B;IAC1C,OAAO,EAAE,oBAAoB;CAC9B,CAAC;AAEF,4DAA4D;AAC5D,MAAM,UAAU,0BAA0B;IACxC,WAAW,CAAC,KAAK,EAAE,CAAC;AACtB,CAAC;AAED,6FAA6F;AAC7F,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,OAAe,EACf,UAAqE,EACrE,OAAwB,gBAAgB;IAExC,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,KAAK,eAAe,CAAC,MAAM,CAAC,CAAC;IACxF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAClC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC/C,IAAI,MAAM,CAAC,KAAK,KAAK,cAAc;QAAE,OAAO;IAC5C,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,KAAK,OAAO;QAC1C,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,UAAU,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC;QACvF,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC1C,WAAW,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACtC,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,WAAW;QAAE,OAAO;IAC/D,KAAK,MAAM,CAAC,IAAI,QAAQ;QAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC7C,GAAG,CAAC,IAAI,CACN,kDAAkD,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,eAAe;QACpF,GAAG,QAAQ,CAAC,MAAM,gDAAgD,CACnE,CAAC;AACJ,CAAC;AAED,6GAA6G;AAC7G,MAAM,UAAU,eAAe,CAC7B,IAAuC,EACvC,OAAwB,gBAAgB;IAExC,OAAO,KAAK,EAAE,OAAO,EAAE,EAAE;QACvB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC;YACH,MAAM,mBAAmB,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,KAAK,CAAC,uDAAuD,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,EAAG,GAAa,CAAC,OAAO,CAAC,CAAC;QACnH,CAAC;QACD,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"credit-rearm.js","sourceRoot":"","sources":["../../src/verify/credit-rearm.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,33 @@
1
+ import { type ReselectionPath } from './reselection-log.js';
1
2
  /** Test-only: reset the default-on re-run guards (status- and HEAD-keyed). */
2
3
  export declare function __resetDefaultOnGuardForTests(): void;
3
4
  /** Test-only: snapshot of the default-on re-run guard (delivery id -> the commit its dispatch judged). */
4
5
  export declare function __getDefaultOnGuardForTests(): ReadonlyMap<string, string | null>;
5
6
  /** Mark a delivery as already run this verify-entry (dispatch-time bookkeeping; the judged commit is noted after). */
6
7
  export declare function markDefaultOnRan(deliveryId: string): void;
8
+ /**
9
+ * The commit the delivery's run mark says its dispatch judged; null when there is
10
+ * no mark, the dispatch is in flight, or it named no commit -- all "unknown".
11
+ */
12
+ export declare function judgedShaOfRunMark(deliveryId: string): string | null;
13
+ /**
14
+ * Whether the delivery carries a run mark at all -- a dispatch was attempted
15
+ * since the mark was last dropped -- whatever commit (if any) it names.
16
+ */
17
+ export declare function hasDefaultOnRunMark(deliveryId: string): boolean;
7
18
  /** Test-only alias for markDefaultOnRan. */
8
19
  export declare function __markDefaultOnRanForTests(deliveryId: string): void;
9
- /** Drop a delivery's run mark so the next tick selects it again (its dispatch rendered nothing it may keep). */
10
- export declare function releaseDefaultOnMark(deliveryId: string): void;
20
+ /**
21
+ * Drop a delivery's run mark so the next tick selects it again (its dispatch
22
+ * rendered nothing it may keep).
23
+ *
24
+ * `releasedBy` names the re-selection path for the log. A caller that passes one
25
+ * logs its OWN line at its own call site (where the reason is known), so this
26
+ * stays silent for it; a caller that names none gets the fallback
27
+ * 'run-mark-release' line. Either way nothing is logged when there was no mark to
28
+ * drop: a release that suppressed nothing re-selected nothing.
29
+ */
30
+ export declare function releaseDefaultOnMark(deliveryId: string, releasedBy?: ReselectionPath): void;
11
31
  /**
12
32
  * Drop a delivery's recorded pass, so the pass guard no longer suppresses it.
13
33
  * The demand pull (verify/commit-verdict-pull.ts) calls this for a delivery whose
@@ -24,6 +44,13 @@ export interface DefaultOnResultFacts {
24
44
  checkoutUnavailable?: boolean;
25
45
  /** The reconciliation could not run (model unavailable): no verdict exists to guard. */
26
46
  modelUnavailable?: boolean;
47
+ /**
48
+ * A shortfall park stands on this delivery and EVERY fact behind it is
49
+ * unchanged (verify/parked-shortfall-reuse.ts parkHoldsOnUnchangedFacts).
50
+ * Absent/false means no park, moved facts, or an unknown -- all of which
51
+ * re-select. Read only on the two un-marks (checkout- and model-unavailable).
52
+ */
53
+ parkHolds?: boolean;
27
54
  }
28
55
  /**
29
56
  * Dispatch-result bookkeeping for a default-on run:
@@ -38,6 +65,17 @@ export interface DefaultOnResultFacts {
38
65
  * forget any recorded pass;
39
66
  * - a pass -> forget any recorded failure and, at a known judged sha, remember
40
67
  * the pass so that commit is not re-verified either.
68
+ *
69
+ * A PASS DEMOTED TO 'failed' BY THE RECONCILIATION records neither: judgedFailedSha
70
+ * requires a non-zero gate exit and the gate exited 0, and the outcome is no longer
71
+ * 'passed'. That is deliberate and it is NOT a hole -- the run mark still carries
72
+ * the commit the run judged (the line above keeps it), so the delivery is not
73
+ * re-selected while a readable focus HEAD equals it, and a new commit re-arms it
74
+ * exactly once. Recording it as a failed sha instead would be wrong twice over: the
75
+ * gate did not fail, and failedAtSha is DURABLE (gate_state), so it would suppress
76
+ * the commit across a restart while the shortfall park -- which owns this state and
77
+ * is released by an operator ruling -- would have nothing to release. Pinned by
78
+ * verification-default-on.test.ts ("a pass demoted by a shortfall ...").
41
79
  */
42
80
  export declare function noteDefaultOnResult(deliveryId: string, result: DefaultOnResultFacts): void;
43
81
  /**
@@ -64,14 +102,22 @@ export declare function failedOnCurrentHead(delivery: {
64
102
  */
65
103
  export declare function ranOnCurrentHead(deliveryId: string, readHead: () => string | null): boolean;
66
104
  /**
67
- * Prune the guards of every delivery no longer observed in verify. The run mark
68
- * and the recorded PASS both go: a genuine verify_failed -> coding -> verify
69
- * re-entry is the ONLY thing that re-arms a passed delivery, so this sweep IS
70
- * that rule -- without it a delivery would keep a pass earned on the code before
71
- * its fix commits, which is the one way the narrowed rule could lower the bar.
105
+ * Prune the guards of every delivery THIS PRODUCT'S scan no longer observed in
106
+ * verify. The run mark and the recorded PASS both go: a genuine verify_failed ->
107
+ * coding -> verify re-entry is the ONLY thing that re-arms a passed delivery, so
108
+ * this sweep IS that rule -- without it a delivery would keep a pass earned on the
109
+ * code before its fix commits, which is the one way the narrowed rule could lower
110
+ * the bar.
111
+ *
112
+ * `productId` is the product the observation was taken over (config.productId of
113
+ * the scan's product-scoped config), and it BOUNDS the conclusion: an entry
114
+ * claimed by another product is left alone, because this scan never looked for it
115
+ * (module header, incident 2026-09-24). Pass `undefined` only from a caller whose
116
+ * single observation IS the whole view. Every observed id is claimed for
117
+ * `productId` here, so the claim and the prune come from one read.
72
118
  *
73
119
  * failedAtSha is deliberately NOT pruned: a recorded failure is durable in
74
120
  * gate_state and survives the round trip on purpose, unchanged.
75
121
  */
76
- export declare function pruneGuardsOutsideVerify(observedInVerify: ReadonlySet<string>): void;
122
+ export declare function pruneGuardsOutsideVerify(observedInVerify: ReadonlySet<string>, productId?: string): void;
77
123
  //# sourceMappingURL=default-on-guards.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"default-on-guards.d.ts","sourceRoot":"","sources":["../../src/verify/default-on-guards.ts"],"names":[],"mappings":"AAwKA,8EAA8E;AAC9E,wBAAgB,6BAA6B,IAAI,IAAI,CAKpD;AAED,0GAA0G;AAC1G,wBAAgB,2BAA2B,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAEhF;AAED,sHAAsH;AACtH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAEzD;AAED,4CAA4C;AAC5C,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAEnE;AAED,gHAAgH;AAChH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAE7D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAE3D;AAED,4EAA4E;AAC5E,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,wFAAwF;IACxF,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,IAAI,CAc1F;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAYzD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,EAAE,QAAQ,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,OAAO,CAoBzH;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,OAAO,CAY3F;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CAOpF"}
1
+ {"version":3,"file":"default-on-guards.d.ts","sourceRoot":"","sources":["../../src/verify/default-on-guards.ts"],"names":[],"mappings":"AAsDA,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAqJ5E,8EAA8E;AAC9E,wBAAgB,6BAA6B,IAAI,IAAI,CAMpD;AAED,0GAA0G;AAC1G,wBAAgB,2BAA2B,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAEhF;AAED,sHAAsH;AACtH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAEzD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEpE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAE/D;AAED,4CAA4C;AAC5C,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAEnE;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,eAAe,GAAG,IAAI,CAS3F;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAE3D;AAED,4EAA4E;AAC5E,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,wFAAwF;IACxF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,IAAI,CA0C1F;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAYzD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,EAAE,QAAQ,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,OAAO,CAoBzH;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,OAAO,CAY3F;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,wBAAwB,CAAC,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAuBxG"}