@telora/daemon 0.24.29 → 0.24.38

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 (239) hide show
  1. package/build-info.json +5 -3
  2. package/dist/backends/index.js +1 -1
  3. package/dist/ci/gate-job-conclusion.d.ts +88 -0
  4. package/dist/ci/gate-job-conclusion.d.ts.map +1 -0
  5. package/dist/ci/gate-job-conclusion.js +207 -0
  6. package/dist/ci/gate-job-conclusion.js.map +1 -0
  7. package/dist/ci/gate-ref.d.ts +12 -0
  8. package/dist/ci/gate-ref.d.ts.map +1 -1
  9. package/dist/ci/gate-ref.js +2 -0
  10. package/dist/ci/gate-ref.js.map +1 -1
  11. package/dist/completion/completion-event/detector.d.ts.map +1 -1
  12. package/dist/completion/completion-event/detector.js +1 -0
  13. package/dist/completion/completion-event/detector.js.map +1 -1
  14. package/dist/completion/completion-event/event.d.ts +7 -0
  15. package/dist/completion/completion-event/event.d.ts.map +1 -1
  16. package/dist/completion/completion-event/event.js +1 -0
  17. package/dist/completion/completion-event/event.js.map +1 -1
  18. package/dist/completion/team-outcome/apply-turn.d.ts.map +1 -1
  19. package/dist/completion/team-outcome/apply-turn.js +11 -6
  20. package/dist/completion/team-outcome/apply-turn.js.map +1 -1
  21. package/dist/completion/team-outcome/decide-turn-entry-rows.js +1 -1
  22. package/dist/completion/team-outcome/decide-turn-entry-rows.js.map +1 -1
  23. package/dist/completion/team-outcome/exit-pipeline-state.d.ts +6 -0
  24. package/dist/completion/team-outcome/exit-pipeline-state.d.ts.map +1 -1
  25. package/dist/completion/team-outcome/exit-pipeline-state.js.map +1 -1
  26. package/dist/completion/team-outcome/work-facts.d.ts +8 -1
  27. package/dist/completion/team-outcome/work-facts.d.ts.map +1 -1
  28. package/dist/completion/team-outcome/work-facts.js +10 -5
  29. package/dist/completion/team-outcome/work-facts.js.map +1 -1
  30. package/dist/completion/team-progress/team-progress-measure.d.ts.map +1 -1
  31. package/dist/completion/team-progress/team-progress-measure.js +1 -0
  32. package/dist/completion/team-progress/team-progress-measure.js.map +1 -1
  33. package/dist/composition/completion-event-context.d.ts.map +1 -1
  34. package/dist/composition/completion-event-context.js +3 -0
  35. package/dist/composition/completion-event-context.js.map +1 -1
  36. package/dist/composition/execution-spawn-context.d.ts.map +1 -1
  37. package/dist/composition/execution-spawn-context.js +4 -0
  38. package/dist/composition/execution-spawn-context.js.map +1 -1
  39. package/dist/composition/execution-spawn-process-context.js +1 -1
  40. package/dist/composition/execution-spawn-process-context.js.map +1 -1
  41. package/dist/composition/runtime-delivery-advance-context.js +1 -1
  42. package/dist/composition/runtime-delivery-advance-context.js.map +1 -1
  43. package/dist/composition/runtime-spawn-pass-context.d.ts.map +1 -1
  44. package/dist/composition/runtime-spawn-pass-context.js +5 -2
  45. package/dist/composition/runtime-spawn-pass-context.js.map +1 -1
  46. package/dist/composition/tower-escalation-context.d.ts +3 -0
  47. package/dist/composition/tower-escalation-context.d.ts.map +1 -1
  48. package/dist/composition/tower-escalation-context.js +26 -12
  49. package/dist/composition/tower-escalation-context.js.map +1 -1
  50. package/dist/composition/verification-context.d.ts.map +1 -1
  51. package/dist/composition/verification-context.js +13 -2
  52. package/dist/composition/verification-context.js.map +1 -1
  53. package/dist/composition/verify-probe-context.d.ts +15 -1
  54. package/dist/composition/verify-probe-context.d.ts.map +1 -1
  55. package/dist/composition/verify-probe-context.js +45 -4
  56. package/dist/composition/verify-probe-context.js.map +1 -1
  57. package/dist/daemon-state/focus-team-state.js +1 -1
  58. package/dist/delivery/operator-hold.d.ts.map +1 -1
  59. package/dist/delivery/operator-hold.js +5 -3
  60. package/dist/delivery/operator-hold.js.map +1 -1
  61. package/dist/focus/ready-focus-team-work.d.ts +11 -0
  62. package/dist/focus/ready-focus-team-work.d.ts.map +1 -1
  63. package/dist/focus/ready-focus-team-work.js +8 -1
  64. package/dist/focus/ready-focus-team-work.js.map +1 -1
  65. package/dist/prompt/focus-prompt-builder.d.ts +7 -1
  66. package/dist/prompt/focus-prompt-builder.d.ts.map +1 -1
  67. package/dist/prompt/focus-prompt-builder.js +36 -11
  68. package/dist/prompt/focus-prompt-builder.js.map +1 -1
  69. package/dist/prompt-sections/ci-failed-step-section.d.ts +16 -0
  70. package/dist/prompt-sections/ci-failed-step-section.d.ts.map +1 -0
  71. package/dist/prompt-sections/ci-failed-step-section.js +20 -0
  72. package/dist/prompt-sections/ci-failed-step-section.js.map +1 -0
  73. package/dist/prompt-sections/prompt-listing.d.ts +3 -0
  74. package/dist/prompt-sections/prompt-listing.d.ts.map +1 -1
  75. package/dist/prompt-sections/prompt-listing.js +11 -1
  76. package/dist/prompt-sections/prompt-listing.js.map +1 -1
  77. package/dist/prompt-sections/routing-decider-sections.d.ts +7 -0
  78. package/dist/prompt-sections/routing-decider-sections.d.ts.map +1 -1
  79. package/dist/prompt-sections/routing-decider-sections.js +22 -0
  80. package/dist/prompt-sections/routing-decider-sections.js.map +1 -1
  81. package/dist/prompt-sections/session-constraints-section.d.ts.map +1 -1
  82. package/dist/prompt-sections/session-constraints-section.js +12 -2
  83. package/dist/prompt-sections/session-constraints-section.js.map +1 -1
  84. package/dist/queries/api-client/shared.js +1 -1
  85. package/dist/queries/delivery-gate-state/delivery-gate-holds.d.ts.map +1 -1
  86. package/dist/queries/delivery-gate-state/delivery-gate-holds.js +2 -1
  87. package/dist/queries/delivery-gate-state/delivery-gate-holds.js.map +1 -1
  88. package/dist/queries/delivery-gate-state/delivery-gate-state.d.ts +13 -0
  89. package/dist/queries/delivery-gate-state/delivery-gate-state.d.ts.map +1 -1
  90. package/dist/queries/delivery-gate-state/delivery-gate-state.js +3 -1
  91. package/dist/queries/delivery-gate-state/delivery-gate-state.js.map +1 -1
  92. package/dist/queries/escalations/filing-observation.d.ts +24 -1
  93. package/dist/queries/escalations/filing-observation.d.ts.map +1 -1
  94. package/dist/queries/escalations/filing-observation.js +27 -2
  95. package/dist/queries/escalations/filing-observation.js.map +1 -1
  96. package/dist/queries/escalations/tower-escalations.d.ts +21 -0
  97. package/dist/queries/escalations/tower-escalations.d.ts.map +1 -1
  98. package/dist/queries/escalations/tower-escalations.js +24 -0
  99. package/dist/queries/escalations/tower-escalations.js.map +1 -1
  100. package/dist/queries/focus-review/review-criterion-verdicts.d.ts.map +1 -1
  101. package/dist/queries/focus-review/review-criterion-verdicts.js +3 -0
  102. package/dist/queries/focus-review/review-criterion-verdicts.js.map +1 -1
  103. package/dist/queries/focus-review/review-summary-verdicts.d.ts +50 -0
  104. package/dist/queries/focus-review/review-summary-verdicts.d.ts.map +1 -0
  105. package/dist/queries/focus-review/review-summary-verdicts.js +117 -0
  106. package/dist/queries/focus-review/review-summary-verdicts.js.map +1 -0
  107. package/dist/queries/focuses/focuses.d.ts.map +1 -1
  108. package/dist/queries/focuses/focuses.js +2 -0
  109. package/dist/queries/focuses/focuses.js.map +1 -1
  110. package/dist/queries/reality-tree/reality-tree.d.ts.map +1 -1
  111. package/dist/queries/reality-tree/reality-tree.js +1 -0
  112. package/dist/queries/reality-tree/reality-tree.js.map +1 -1
  113. package/dist/queries/reality-tree/shortfall-node-bindings.d.ts +42 -0
  114. package/dist/queries/reality-tree/shortfall-node-bindings.d.ts.map +1 -0
  115. package/dist/queries/reality-tree/shortfall-node-bindings.js +42 -0
  116. package/dist/queries/reality-tree/shortfall-node-bindings.js.map +1 -0
  117. package/dist/queries/tower-decisions/tower-decisions.d.ts +3 -1
  118. package/dist/queries/tower-decisions/tower-decisions.d.ts.map +1 -1
  119. package/dist/queries/tower-decisions/tower-decisions.js +1 -0
  120. package/dist/queries/tower-decisions/tower-decisions.js.map +1 -1
  121. package/dist/spawn/helpers.d.ts.map +1 -1
  122. package/dist/spawn/helpers.js +1 -0
  123. package/dist/spawn/helpers.js.map +1 -1
  124. package/dist/spawn/idle-work-stamp.d.ts +8 -0
  125. package/dist/spawn/idle-work-stamp.d.ts.map +1 -1
  126. package/dist/spawn/idle-work-stamp.js +2 -1
  127. package/dist/spawn/idle-work-stamp.js.map +1 -1
  128. package/dist/spawn/lead-continuation.d.ts +8 -0
  129. package/dist/spawn/lead-continuation.d.ts.map +1 -1
  130. package/dist/spawn/lead-continuation.js +14 -5
  131. package/dist/spawn/lead-continuation.js.map +1 -1
  132. package/dist/supervision/holds.d.ts +78 -15
  133. package/dist/supervision/holds.d.ts.map +1 -1
  134. package/dist/supervision/holds.js +167 -87
  135. package/dist/supervision/holds.js.map +1 -1
  136. package/dist/supervision/operator-held-work.d.ts +48 -0
  137. package/dist/supervision/operator-held-work.d.ts.map +1 -0
  138. package/dist/supervision/operator-held-work.js +33 -0
  139. package/dist/supervision/operator-held-work.js.map +1 -0
  140. package/dist/supervision/stop-rows-delivery.d.ts.map +1 -1
  141. package/dist/supervision/stop-rows-delivery.js +3 -1
  142. package/dist/supervision/stop-rows-delivery.js.map +1 -1
  143. package/dist/supervision/team-work.d.ts +32 -1
  144. package/dist/supervision/team-work.d.ts.map +1 -1
  145. package/dist/supervision/team-work.js +44 -4
  146. package/dist/supervision/team-work.js.map +1 -1
  147. package/dist/templates/agents-md.d.ts.map +1 -1
  148. package/dist/templates/agents-md.js +1 -0
  149. package/dist/templates/agents-md.js.map +1 -1
  150. package/dist/templates/claude-md.d.ts +1 -1
  151. package/dist/templates/claude-md.d.ts.map +1 -1
  152. package/dist/templates/claude-md.js +11 -1
  153. package/dist/templates/claude-md.js.map +1 -1
  154. package/dist/testing/fixtures/api-client.js +1 -1
  155. package/dist/testing/fixtures/completion-event-deps.d.ts.map +1 -1
  156. package/dist/testing/fixtures/completion-event-deps.js +4 -1
  157. package/dist/testing/fixtures/completion-event-deps.js.map +1 -1
  158. package/dist/testing/fixtures/index.js +1 -1
  159. package/dist/testing/fixtures/tower-shortfall-7bac4c82.d.ts +38 -0
  160. package/dist/testing/fixtures/tower-shortfall-7bac4c82.d.ts.map +1 -0
  161. package/dist/testing/fixtures/tower-shortfall-7bac4c82.js +67 -0
  162. package/dist/testing/fixtures/tower-shortfall-7bac4c82.js.map +1 -0
  163. package/dist/testing/fixtures/tower-shortfall-cd32119b.d.ts +79 -0
  164. package/dist/testing/fixtures/tower-shortfall-cd32119b.d.ts.map +1 -0
  165. package/dist/testing/fixtures/tower-shortfall-cd32119b.js +142 -0
  166. package/dist/testing/fixtures/tower-shortfall-cd32119b.js.map +1 -0
  167. package/dist/testing/fixtures/verification-deps.d.ts.map +1 -1
  168. package/dist/testing/fixtures/verification-deps.js +3 -0
  169. package/dist/testing/fixtures/verification-deps.js.map +1 -1
  170. package/dist/testing/fixtures/verification-feedback-deps.js +1 -1
  171. package/dist/tower/tower-escalation-gather.d.ts +24 -0
  172. package/dist/tower/tower-escalation-gather.d.ts.map +1 -1
  173. package/dist/tower/tower-escalation-gather.js +29 -1
  174. package/dist/tower/tower-escalation-gather.js.map +1 -1
  175. package/dist/tower/tower-escalation-prompt.d.ts +26 -1
  176. package/dist/tower/tower-escalation-prompt.d.ts.map +1 -1
  177. package/dist/tower/tower-escalation-prompt.js +76 -8
  178. package/dist/tower/tower-escalation-prompt.js.map +1 -1
  179. package/dist/tower/tower-escalation-routing.d.ts +27 -1
  180. package/dist/tower/tower-escalation-routing.d.ts.map +1 -1
  181. package/dist/tower/tower-escalation-routing.js +32 -3
  182. package/dist/tower/tower-escalation-routing.js.map +1 -1
  183. package/dist/tower/tower-escalation-session.d.ts +29 -6
  184. package/dist/tower/tower-escalation-session.d.ts.map +1 -1
  185. package/dist/tower/tower-escalation-session.js +27 -9
  186. package/dist/tower/tower-escalation-session.js.map +1 -1
  187. package/dist/tower/tower-escalation-shortfall.d.ts +158 -0
  188. package/dist/tower/tower-escalation-shortfall.d.ts.map +1 -0
  189. package/dist/tower/tower-escalation-shortfall.js +452 -0
  190. package/dist/tower/tower-escalation-shortfall.js.map +1 -0
  191. package/dist/tower/tower-supervisor-session.d.ts.map +1 -1
  192. package/dist/tower/tower-supervisor-session.js +1 -0
  193. package/dist/tower/tower-supervisor-session.js.map +1 -1
  194. package/dist/types/index.js +1 -1
  195. package/dist/verify/ci-gate/ci-gate-dispatch.d.ts +41 -0
  196. package/dist/verify/ci-gate/ci-gate-dispatch.d.ts.map +1 -1
  197. package/dist/verify/ci-gate/ci-gate-dispatch.js +148 -7
  198. package/dist/verify/ci-gate/ci-gate-dispatch.js.map +1 -1
  199. package/dist/verify/ci-gate/ci-gate-pin-publish.d.ts +101 -0
  200. package/dist/verify/ci-gate/ci-gate-pin-publish.d.ts.map +1 -0
  201. package/dist/verify/ci-gate/ci-gate-pin-publish.js +238 -0
  202. package/dist/verify/ci-gate/ci-gate-pin-publish.js.map +1 -0
  203. package/dist/verify/deterministic-gate/verification-deterministic.d.ts +3 -1
  204. package/dist/verify/deterministic-gate/verification-deterministic.d.ts.map +1 -1
  205. package/dist/verify/deterministic-gate/verification-deterministic.js.map +1 -1
  206. package/dist/verify/gate-verdicts/commit-verdict-record.d.ts +2 -0
  207. package/dist/verify/gate-verdicts/commit-verdict-record.d.ts.map +1 -1
  208. package/dist/verify/gate-verdicts/commit-verdict-record.js +10 -1
  209. package/dist/verify/gate-verdicts/commit-verdict-record.js.map +1 -1
  210. package/dist/verify/install-probe/in-repo-publish.d.ts +10 -0
  211. package/dist/verify/install-probe/in-repo-publish.d.ts.map +1 -1
  212. package/dist/verify/install-probe/in-repo-publish.js +15 -0
  213. package/dist/verify/install-probe/in-repo-publish.js.map +1 -1
  214. package/dist/verify/install-probe/install-probe-tick.d.ts +7 -0
  215. package/dist/verify/install-probe/install-probe-tick.d.ts.map +1 -1
  216. package/dist/verify/install-probe/install-probe-tick.js +4 -1
  217. package/dist/verify/install-probe/install-probe-tick.js.map +1 -1
  218. package/dist/verify/outcome-routing/verification-feedback.d.ts +5 -1
  219. package/dist/verify/outcome-routing/verification-feedback.d.ts.map +1 -1
  220. package/dist/verify/outcome-routing/verification-feedback.js +7 -1
  221. package/dist/verify/outcome-routing/verification-feedback.js.map +1 -1
  222. package/dist/verify/outcome-routing/verification-rework-messages.d.ts.map +1 -1
  223. package/dist/verify/outcome-routing/verification-rework-messages.js +7 -2
  224. package/dist/verify/outcome-routing/verification-rework-messages.js.map +1 -1
  225. package/dist/verify/shortfalls/shortfall-park-escalation.d.ts +9 -2
  226. package/dist/verify/shortfalls/shortfall-park-escalation.d.ts.map +1 -1
  227. package/dist/verify/shortfalls/shortfall-park-escalation.js +13 -1
  228. package/dist/verify/shortfalls/shortfall-park-escalation.js.map +1 -1
  229. package/dist/verify/shortfalls/shortfall-rulings.d.ts.map +1 -1
  230. package/dist/verify/shortfalls/shortfall-rulings.js +4 -0
  231. package/dist/verify/shortfalls/shortfall-rulings.js.map +1 -1
  232. package/dist/worktree/focus-worktree-state.d.ts.map +1 -1
  233. package/dist/worktree/focus-worktree-state.js +1 -0
  234. package/dist/worktree/focus-worktree-state.js.map +1 -1
  235. package/dist/worktree/verify-hold-facts.d.ts +3 -1
  236. package/dist/worktree/verify-hold-facts.d.ts.map +1 -1
  237. package/dist/worktree/verify-hold-facts.js +1 -0
  238. package/dist/worktree/verify-hold-facts.js.map +1 -1
  239. package/package.json +2 -2
@@ -0,0 +1,158 @@
1
+ import type { ReviewVerdictRecord } from '../queries/focus-review/review-criterion-verdicts.js';
2
+ import type { ShortfallNodeBinding } from '../queries/reality-tree/shortfall-node-bindings.js';
3
+ /** The act the supervisor rules through (telora_agent action). */
4
+ export declare const SHORTFALL_RULING_ACT = "escalation_rule_shortfall";
5
+ /** How many verdict-bearing reviews under the arm the record reads. */
6
+ export declare const SHORTFALL_REVIEWS_READ = 10;
7
+ /** A gate verdict gate_state records. */
8
+ export interface ShortfallGateVerdict {
9
+ outcome: 'passed' | 'failed';
10
+ sha: string;
11
+ failedStage: string | null;
12
+ /** The gate_state key that carried it. */
13
+ from: string;
14
+ }
15
+ /** One shortfall node, what names it, and what the tree says binds a verdict to it. */
16
+ export interface ShortfallNode {
17
+ nodeId: string;
18
+ /** The outcome the injection declares for it (from the shortfall judgment), when recorded. */
19
+ declared: string | null;
20
+ namedBy: string[];
21
+ /** Whether the tree read found it among the focus's active nodes (false also when the read failed). */
22
+ inTree: boolean;
23
+ /** Its declared future (frt_statement) as the tree holds it; null when it declares none or was not found. */
24
+ future: string | null;
25
+ /** The active effects it is a `sufficient` cause of (N -> E). */
26
+ sufficientEffectIds: string[];
27
+ }
28
+ /** How a review verdict binds to a shortfall node (module header, THE BINDING RULE). */
29
+ export type ShortfallBindingVia = 'tree_verdict_on_node' | 'declared_future' | 'sufficient_effect';
30
+ /** One review verdict the record shows. */
31
+ export interface ShortfallReviewVerdict {
32
+ /** The criterion verbatim, as the review named it: what the act is passed. */
33
+ criterion: string;
34
+ nodeId: string | null;
35
+ /** A tree verdict (keyed to nodeId), or a verdict on one of this delivery's declared criteria. */
36
+ source: 'tree' | 'delivery_criterion';
37
+ verdict: 'met' | 'not_met' | 'excused';
38
+ evidence: string[];
39
+ /** True when only criterion_verdicts carried it (the summary section did not): no evidence is readable. */
40
+ storedOnly: boolean;
41
+ /** True when the stored row and the summary disagree on this verdict. */
42
+ disagrees: boolean;
43
+ /** The shortfall nodes it binds to, and how; [] when it binds none (shown, never counted). */
44
+ binds: Array<{
45
+ nodeId: string;
46
+ via: ShortfallBindingVia;
47
+ }>;
48
+ }
49
+ /** One verdict-bearing review under the arm. */
50
+ export interface ShortfallReview {
51
+ reviewId: string;
52
+ completedAt: string;
53
+ outcome: string;
54
+ reviewedSha: string | null;
55
+ verdicts: ShortfallReviewVerdict[];
56
+ }
57
+ /** What the supervisor is shown about a delivery-anchored escalation's shortfall. */
58
+ export interface ShortfallRecord {
59
+ deliveryId: string;
60
+ deliveryName: string;
61
+ judgedCommit: {
62
+ sha: string;
63
+ source: 'judged_commit' | 'shortfall_reconciliation';
64
+ } | null;
65
+ /** The verdict about the judged commit (a failed one wins); null when none is about it. */
66
+ gateVerdict: ShortfallGateVerdict | null;
67
+ /** Verdicts gate_state carries about OTHER commits (shown, never counted). */
68
+ otherCommitVerdicts: ShortfallGateVerdict[];
69
+ nodes: ShortfallNode[];
70
+ /** The delivery's own acceptance criteria, verbatim. */
71
+ deliveryCriteria: string[];
72
+ /** Newest first; [] when none (or unreadable: see reviewsReadable). */
73
+ reviews: ShortfallReview[];
74
+ reviewsReadable: boolean;
75
+ /** False when the tree read that binds verdicts to the nodes failed. */
76
+ bindingsReadable: boolean;
77
+ }
78
+ /** One node the standing supports ruling met, on the ONE verdict bound to it. */
79
+ export interface ShortfallRuling {
80
+ nodeId: string;
81
+ criterion: string;
82
+ reviewId: string;
83
+ evidence: string[];
84
+ via: ShortfallBindingVia;
85
+ /** The tree node the bound verdict is keyed to (the node itself, or the effect it sustains); null for a declared criterion. */
86
+ verdictNodeId: string | null;
87
+ }
88
+ /** What the standing says, and on what. */
89
+ export type ShortfallStanding = {
90
+ standing: 'rule';
91
+ rulings: ShortfallRuling[];
92
+ unasked: string[];
93
+ } | {
94
+ standing: 'defer';
95
+ reasons: string[];
96
+ unasked: string[];
97
+ };
98
+ /** Pure: the judged commit and the verdicts about it (module header). */
99
+ export declare function judgedGateOf(gateState: unknown): Pick<ShortfallRecord, 'judgedCommit' | 'gateVerdict' | 'otherCommitVerdicts'>;
100
+ /** Pure: the node ids a filing's structured shortfall-ruling ask names (metadata.human_act.shortfall_ruling.node_ids), tolerantly. */
101
+ export declare function filingShortfallNodeIds(metadata: Record<string, unknown>): string[];
102
+ /** How a node the filing's structured ask names is labelled in namedBy. */
103
+ export declare const NAMED_BY_FILING = "the filing";
104
+ /** Pure: the shortfall nodes gate_state and the filing name, each with what names it. */
105
+ export declare function shortfallNodesOf(gateState: unknown, metadata: Record<string, unknown>): ShortfallNode[];
106
+ /** Pure: the shortfall nodes a verdict binds to, by THE BINDING RULE (module header). */
107
+ export declare function bindsOf(v: {
108
+ criterion: string;
109
+ nodeId: string | null;
110
+ }, nodes: readonly ShortfallNode[]): ShortfallReviewVerdict['binds'];
111
+ /**
112
+ * Pure: one review's verdicts the record shows -- tree verdicts that bind a
113
+ * shortfall node, and verdicts on this delivery's declared criteria (each
114
+ * carrying the nodes it binds, possibly none).
115
+ */
116
+ export declare function shortfallReviewOf(r: ReviewVerdictRecord, nodes: readonly ShortfallNode[], deliveryKeys: ReadonlySet<string>): ShortfallReview;
117
+ /** What the record is built from. */
118
+ export interface ShortfallRecordInput {
119
+ delivery: {
120
+ id: string;
121
+ name: string;
122
+ gateState: unknown;
123
+ acceptanceCriteria: string | null;
124
+ };
125
+ metadata: Record<string, unknown>;
126
+ /** The focus's verdict-bearing reviews under the arm, newest first; null when the read failed. */
127
+ reviews: readonly ReviewVerdictRecord[] | null;
128
+ /** The tree's bindings of the shortfall nodes (queries/reality-tree/shortfall-node-bindings.ts); null when the read failed. */
129
+ bindings: readonly ShortfallNodeBinding[] | null;
130
+ }
131
+ /** Pure: the shortfall nodes with what the tree read says binds a verdict to each. */
132
+ export declare function withBindings(nodes: readonly ShortfallNode[], bindings: readonly ShortfallNodeBinding[] | null): ShortfallNode[];
133
+ /** Pure: the shortfall record. */
134
+ export declare function buildShortfallRecord(input: ShortfallRecordInput): ShortfallRecord;
135
+ /** Pure: the act text a filing's structured human act names (metadata.human_act.act), or null. */
136
+ export declare function filingActOf(metadata: Record<string, unknown>): string | null;
137
+ /** What the excusal check reads: the ask (helpNeeded) and the filing's structured act. */
138
+ export interface ShortfallAsk {
139
+ helpNeeded: string | null;
140
+ /** metadata.human_act.act (filingActOf); null or absent when the filing names no structured act. */
141
+ act?: string | null;
142
+ }
143
+ /** Pure: whether the text asks to EXCUSE or waive a criterion (module header, DECISION). */
144
+ export declare function askExcuses(helpNeeded: string | null): boolean;
145
+ /**
146
+ * Pure: the nodes this ask is a ruling on (module header, THE RULING SCOPE) --
147
+ * the filing's structured nodes when it names any, else every recorded node --
148
+ * and the recorded nodes outside that scope (shown, never counted).
149
+ */
150
+ export declare function rulingScopeOf(record: ShortfallRecord): {
151
+ scope: ShortfallNode[];
152
+ unasked: string[];
153
+ };
154
+ /** Pure: whether the record supports the supervisor's shortfall ruling (module header). */
155
+ export declare function computeShortfallStanding(record: ShortfallRecord, ask: ShortfallAsk): ShortfallStanding;
156
+ /** Pure: the shortfall section of the escalation prompt. */
157
+ export declare function renderShortfallSection(record: ShortfallRecord, standing: ShortfallStanding): string[];
158
+ //# sourceMappingURL=tower-escalation-shortfall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tower-escalation-shortfall.d.ts","sourceRoot":"","sources":["../../src/tower/tower-escalation-shortfall.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,452 @@
1
+ // PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
2
+ // Pinned by: packages/daemon/src/completion/state-cascade/failed-verdict-stranded-filing.test.ts,
3
+ // packages/daemon/src/tower/tower-escalation-gather.test.ts,
4
+ // packages/daemon/src/tower/tower-escalation-io-cases.test.ts,
5
+ // packages/daemon/src/tower/tower-escalation-prompt.test.ts,
6
+ // packages/daemon/src/verify/shortfalls/shortfall-park-escalation.test.ts
7
+ // PINNED-BY-END
8
+ /**
9
+ * THE SHORTFALL RECORD the Tower supervisor's escalation prompt shows for a
10
+ * delivery-anchored escalation, and the STANDING it computes from it: whether
11
+ * the record supports the supervisor ruling the delivery's verify-shortfall
12
+ * nodes met (telora_agent action "escalation_rule_shortfall") or does not, so
13
+ * it defers.
14
+ *
15
+ * WHY. A delivery can sit parked on a verify shortfall whose node a review
16
+ * under the current arm has already judged met, with evidence, at a commit the
17
+ * gate passed -- waiting on an operator to write down what the record already
18
+ * says (the shape of the io case cd32119b; fixture
19
+ * testing/fixtures/tower-shortfall-cd32119b.ts). A ruling admitted only on a
20
+ * passing gate verdict and a met-with-evidence review does not lower the bar;
21
+ * this module puts that record in front of the supervisor and says, definitely,
22
+ * whether it holds.
23
+ *
24
+ * THE RECORD (pure, from what the gathering read; tower-escalation-gather.ts):
25
+ * - the JUDGED COMMIT: gate_state.verificationHistory.judgedCommit.sha, or --
26
+ * only when no judged commit is stamped at all -- the live
27
+ * shortfallReconciliation's gate-verdict sha (the server gate's fallback,
28
+ * product-api supervisor-shortfall-ruling-evidence.ts evaluateGateEvidence);
29
+ * - its GATE VERDICT: every verdict gate_state carries about exactly that sha
30
+ * (judgedCommit, shortfallReconciliation, verification,
31
+ * evidenceUnavailable); any failed one wins over a passed one;
32
+ * - the SHORTFALL NODES: the standing park, the last (or live) shortfall
33
+ * judgment, and the filing's structured metadata.human_act.shortfall_ruling
34
+ * .node_ids (read tolerantly: absent on most filings);
35
+ * - per shortfall node, what the reality tree says binds a verdict to it: its
36
+ * declared future (frt_statement) and the effects it is an ACTIVE
37
+ * `sufficient` cause of (queries/reality-tree/shortfall-node-bindings.ts);
38
+ * - the REVIEW VERDICTS under the current arm, newest first, that are tree
39
+ * verdicts on those nodes or on those effects, or verdicts on this
40
+ * delivery's own acceptance criteria, each with its verdict, evidence
41
+ * references, criterion text verbatim and the shortfall node(s) it BINDS to
42
+ * -- evidence read from the summary's verdict section, the only place it
43
+ * lives.
44
+ *
45
+ * THE BINDING RULE (the server enforces the same one; keep them identical). A
46
+ * review verdict V binds to shortfall node N only when:
47
+ * (a) V is a TREE verdict keyed to N itself; or
48
+ * (b) V is a verdict on one of THIS delivery's declared criteria (as
49
+ * enumerateCriteria segments them: list numbering such as "3. "
50
+ * stripped) whose text, normalized (normalizeCriterion), EQUALS N's
51
+ * declared future normalized the same way; or
52
+ * (c) V is a TREE verdict keyed to an effect E with an active `sufficient`
53
+ * edge N -> E: an effect sustained by sufficient causes clears only when
54
+ * every one of them holds, so E judged met is evidence N holds.
55
+ * Nothing else binds -- not an `and`, derived_from or targets edge, not a
56
+ * delivery criterion that paraphrases the future, not a met criterion that is
57
+ * merely the delivery's. A node with no bound met-with-evidence verdict
58
+ * defers. The LATEST review carrying a bound verdict decides (a later not_met
59
+ * or excused withdraws an earlier met), and the ruling line proposes the BOUND
60
+ * verdict's criterion verbatim, since the server refuses any other.
61
+ *
62
+ * THE STANDING mirrors the server's admission rules so the prompt never tells
63
+ * the supervisor to make an act the server would refuse. A record it cannot
64
+ * read (the reviews, or the tree that binds them) never rules. The server
65
+ * remains the authority: a refused act names why, and the supervisor then
66
+ * defers.
67
+ *
68
+ * THE RULING SCOPE is what the filing asks for. When the filing names nodes
69
+ * structurally (metadata.human_act.shortfall_ruling.node_ids), only those are
70
+ * ruled and only those must carry evidence: another node on the delivery's
71
+ * shortfall record that the filing does not ask about is shown, never counted,
72
+ * so an unrequested, unevidenced node does not send an evidenced ask to the
73
+ * operator. A filing that names none (the cd32119b shape: a team reporting a
74
+ * re-held shortfall in prose) is scoped to every node the record holds.
75
+ *
76
+ * DECISION (reversible) -- an ask to EXCUSE. No structured field says a filing
77
+ * asks for an excusal, so it is read from the ask's text -- helpNeeded AND the
78
+ * structured act itself (metadata.human_act.act, filingActOf): ANY excuse
79
+ * or waiver word is an excuse ask, including a team's own "met or excused" --
80
+ * the alternative is explicit and the supervisor never takes it, so the ask
81
+ * defers. The only text stripped first is the daemon's OWN ruling offer, by its
82
+ * exact shape: "met or excused" followed by a parenthetical naming the
83
+ * shortfall_rule action (verify/shortfalls/shortfall-park-escalation.ts and
84
+ * completion/state-cascade/failed-verdict-stranded-filing.ts write it; their
85
+ * tests pin that it is recognised). It errs toward deferring, the safe direction.
86
+ *
87
+ * @module tower/tower-escalation-shortfall
88
+ */
89
+ import { readLastShortfallJudgment, readShortfallPark } from '../queries/delivery-gate-state/delivery-gate-state.js';
90
+ import { enumerateCriteria, normalizeCriterion, parseSummaryVerdicts } from '../queries/focus-review/review-summary-verdicts.js';
91
+ /** The act the supervisor rules through (telora_agent action). */
92
+ export const SHORTFALL_RULING_ACT = 'escalation_rule_shortfall';
93
+ /** How many verdict-bearing reviews under the arm the record reads. */
94
+ export const SHORTFALL_REVIEWS_READ = 10;
95
+ const FULL_SHA_RE = /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/;
96
+ function asObject(value) {
97
+ return value !== null && typeof value === 'object' && !Array.isArray(value) ? value : null;
98
+ }
99
+ function fullSha(raw) {
100
+ if (typeof raw !== 'string')
101
+ return null;
102
+ const sha = raw.trim().toLowerCase();
103
+ return FULL_SHA_RE.test(sha) ? sha : null;
104
+ }
105
+ function short(sha) {
106
+ return sha.slice(0, 12);
107
+ }
108
+ function parseVerdict(raw, from) {
109
+ const r = asObject(raw);
110
+ const sha = fullSha(r?.sha);
111
+ if (!r || sha === null || (r.outcome !== 'passed' && r.outcome !== 'failed'))
112
+ return null;
113
+ return { outcome: r.outcome, sha, failedStage: typeof r.failedStage === 'string' && r.failedStage !== '' ? r.failedStage : null, from };
114
+ }
115
+ /** Pure: the judged commit and the verdicts about it (module header). */
116
+ export function judgedGateOf(gateState) {
117
+ const gate = asObject(gateState);
118
+ const judgedRaw = asObject(asObject(gate?.verificationHistory)?.judgedCommit);
119
+ const sha = judgedRaw !== null ? fullSha(judgedRaw.sha) : fullSha(asObject(asObject(gate?.shortfallReconciliation)?.gateVerdict)?.sha);
120
+ const judgedCommit = sha === null ? null : { sha, source: judgedRaw !== null ? 'judged_commit' : 'shortfall_reconciliation' };
121
+ const verdicts = [
122
+ [judgedRaw?.gateVerdict, 'verificationHistory.judgedCommit'],
123
+ [asObject(gate?.shortfallReconciliation)?.gateVerdict, 'shortfallReconciliation'],
124
+ [asObject(gate?.verification)?.gateVerdict, 'verification'],
125
+ [asObject(gate?.evidenceUnavailable)?.gateVerdict, 'evidenceUnavailable'],
126
+ ].flatMap(([raw, from]) => parseVerdict(raw, from) ?? []);
127
+ const onJudged = verdicts.filter((v) => v.sha === sha);
128
+ const gateVerdict = onJudged.find((v) => v.outcome === 'failed') ?? onJudged.find((v) => v.outcome === 'passed') ?? null;
129
+ return { judgedCommit, gateVerdict, otherCommitVerdicts: verdicts.filter((v) => v.sha !== sha) };
130
+ }
131
+ /** Pure: the node ids a filing's structured shortfall-ruling ask names (metadata.human_act.shortfall_ruling.node_ids), tolerantly. */
132
+ export function filingShortfallNodeIds(metadata) {
133
+ const ids = asObject(asObject(asObject(metadata.human_act)?.shortfall_ruling))?.node_ids;
134
+ return Array.isArray(ids) ? ids.filter((id) => typeof id === 'string' && id.trim() !== '').map((id) => id.trim().toLowerCase()) : [];
135
+ }
136
+ /** How a node the filing's structured ask names is labelled in namedBy. */
137
+ export const NAMED_BY_FILING = 'the filing';
138
+ /** Pure: the shortfall nodes gate_state and the filing name, each with what names it. */
139
+ export function shortfallNodesOf(gateState, metadata) {
140
+ const nodes = new Map();
141
+ const add = (rawId, by, declared = null) => {
142
+ const nodeId = rawId.trim().toLowerCase();
143
+ const n = nodes.get(nodeId) ?? { nodeId, declared: null, namedBy: [], inTree: false, future: null, sufficientEffectIds: [] };
144
+ if (!n.namedBy.includes(by))
145
+ n.namedBy.push(by);
146
+ if (n.declared === null && declared)
147
+ n.declared = declared;
148
+ nodes.set(nodeId, n);
149
+ };
150
+ const live = asObject(asObject(gateState)?.shortfallReconciliation) !== null;
151
+ for (const n of readLastShortfallJudgment(gateState)?.nodes ?? []) {
152
+ add(n.nodeId, live ? 'the live shortfall hold' : 'the last shortfall judgment', n.declared);
153
+ }
154
+ for (const id of readShortfallPark(gateState)?.nodeIds ?? [])
155
+ add(id, 'the shortfall park');
156
+ for (const id of filingShortfallNodeIds(metadata))
157
+ add(id, NAMED_BY_FILING);
158
+ return [...nodes.values()];
159
+ }
160
+ function keyOf(criterion, nodeId) {
161
+ return nodeId ? `node:${nodeId.toLowerCase()}` : `text:${normalizeCriterion(criterion)}`;
162
+ }
163
+ /** Pure: the shortfall nodes a verdict binds to, by THE BINDING RULE (module header). */
164
+ export function bindsOf(v, nodes) {
165
+ if (v.nodeId) {
166
+ const id = v.nodeId.toLowerCase();
167
+ return nodes.flatMap((n) => {
168
+ if (n.nodeId === id)
169
+ return [{ nodeId: n.nodeId, via: 'tree_verdict_on_node' }];
170
+ if (n.sufficientEffectIds.includes(id))
171
+ return [{ nodeId: n.nodeId, via: 'sufficient_effect' }];
172
+ return [];
173
+ });
174
+ }
175
+ const text = normalizeCriterion(v.criterion);
176
+ return nodes.filter((n) => n.future !== null && normalizeCriterion(n.future) === text).map((n) => ({ nodeId: n.nodeId, via: 'declared_future' }));
177
+ }
178
+ /**
179
+ * Pure: one review's verdicts the record shows -- tree verdicts that bind a
180
+ * shortfall node, and verdicts on this delivery's declared criteria (each
181
+ * carrying the nodes it binds, possibly none).
182
+ */
183
+ export function shortfallReviewOf(r, nodes, deliveryKeys) {
184
+ const shown = (criterion, nodeId) => {
185
+ const binds = bindsOf({ criterion, nodeId }, nodes);
186
+ if (nodeId)
187
+ return binds.length > 0 ? { source: 'tree', binds } : null;
188
+ return deliveryKeys.has(normalizeCriterion(criterion)) ? { source: 'delivery_criterion', binds } : null;
189
+ };
190
+ const stored = new Map(r.criterionVerdicts.map((v) => [keyOf(v.criterion, v.nodeId), v]));
191
+ const verdicts = [];
192
+ const seen = new Set();
193
+ for (const v of parseSummaryVerdicts(r.summary) ?? []) {
194
+ const key = keyOf(v.criterion, v.nodeId);
195
+ const how = shown(v.criterion, v.nodeId);
196
+ if (how === null || seen.has(key))
197
+ continue;
198
+ seen.add(key);
199
+ const s = stored.get(key);
200
+ verdicts.push({ ...v, ...how, storedOnly: false, disagrees: s !== undefined && s.verdict !== v.verdict });
201
+ }
202
+ for (const [key, v] of stored) {
203
+ const how = shown(v.criterion, v.nodeId);
204
+ if (how === null || seen.has(key))
205
+ continue;
206
+ seen.add(key);
207
+ verdicts.push({ criterion: v.criterion, nodeId: v.nodeId, ...how, verdict: v.verdict, evidence: [], storedOnly: true, disagrees: false });
208
+ }
209
+ return { reviewId: r.reviewId, completedAt: r.completedAt, outcome: r.outcome, reviewedSha: r.reviewedSha ?? null, verdicts };
210
+ }
211
+ /** Pure: the shortfall nodes with what the tree read says binds a verdict to each. */
212
+ export function withBindings(nodes, bindings) {
213
+ const byId = new Map((bindings ?? []).map((b) => [b.nodeId.toLowerCase(), b]));
214
+ return nodes.map((n) => {
215
+ const b = byId.get(n.nodeId);
216
+ return b ? { ...n, inTree: true, future: b.frtStatement, sufficientEffectIds: b.sufficientEffectIds.map((id) => id.toLowerCase()) } : n;
217
+ });
218
+ }
219
+ /** Pure: the shortfall record. */
220
+ export function buildShortfallRecord(input) {
221
+ const { delivery } = input;
222
+ const nodes = withBindings(shortfallNodesOf(delivery.gateState, input.metadata), input.bindings);
223
+ const deliveryCriteria = enumerateCriteria(delivery.acceptanceCriteria);
224
+ const deliveryKeys = new Set(deliveryCriteria.map(normalizeCriterion));
225
+ return {
226
+ deliveryId: delivery.id,
227
+ deliveryName: delivery.name,
228
+ ...judgedGateOf(delivery.gateState),
229
+ nodes,
230
+ deliveryCriteria,
231
+ reviews: (input.reviews ?? []).map((r) => shortfallReviewOf(r, nodes, deliveryKeys)),
232
+ reviewsReadable: input.reviews !== null,
233
+ bindingsReadable: input.bindings !== null,
234
+ };
235
+ }
236
+ // ─── Standing ─────────────────────────────────────────────────────
237
+ /**
238
+ * The daemon's OWN ruling offer, by its exact shape (module header, DECISION):
239
+ * "met or excused", optionally "on the delivery" / "with a rationale", then a
240
+ * parenthetical that names the shortfall_rule action. A team's own "met or
241
+ * excused" is not followed by one, so it stays an excuse ask.
242
+ */
243
+ const DAEMON_RULING_OFFER_RE = /\bmet or excused(?: on the delivery)?(?: with a rationale)? \((?:[a-z_]+ action )?shortfall_rule\b[^)]*\)/gi;
244
+ /** Pure: the act text a filing's structured human act names (metadata.human_act.act), or null. */
245
+ export function filingActOf(metadata) {
246
+ const act = asObject(metadata.human_act)?.act;
247
+ return typeof act === 'string' && act.trim() !== '' ? act : null;
248
+ }
249
+ /** Pure: whether the text asks to EXCUSE or waive a criterion (module header, DECISION). */
250
+ export function askExcuses(helpNeeded) {
251
+ if (!helpNeeded)
252
+ return false;
253
+ const stripped = helpNeeded.replace(DAEMON_RULING_OFFER_RE, '');
254
+ return /\b(?:excus\w*|waiv\w*)\b/i.test(stripped);
255
+ }
256
+ /**
257
+ * Pure: the nodes this ask is a ruling on (module header, THE RULING SCOPE) --
258
+ * the filing's structured nodes when it names any, else every recorded node --
259
+ * and the recorded nodes outside that scope (shown, never counted).
260
+ */
261
+ export function rulingScopeOf(record) {
262
+ const asked = record.nodes.filter((n) => n.namedBy.includes(NAMED_BY_FILING));
263
+ if (asked.length === 0)
264
+ return { scope: record.nodes, unasked: [] };
265
+ return { scope: asked, unasked: record.nodes.filter((n) => !asked.includes(n)).map((n) => n.nodeId) };
266
+ }
267
+ function unmetReason(review, v) {
268
+ const what = `criterion "${v.criterion}" (review ${review.reviewId})`;
269
+ if (v.disagrees)
270
+ return `${what}: the stored verdict and the summary disagree`;
271
+ if (v.verdict === 'not_met')
272
+ return `${what}: the latest review verdict is not_met`;
273
+ if (v.verdict === 'excused')
274
+ return `${what}: the latest review verdict is excused, which is not evidence it was met`;
275
+ if (v.evidence.length === 0)
276
+ return `${what}: judged met with no evidence reference${v.storedOnly ? ' readable' : ''}`;
277
+ return null;
278
+ }
279
+ /** Which bound verdict a node's ruling line proposes when one review binds several: the node's own first. */
280
+ const VIA_ORDER = ['tree_verdict_on_node', 'declared_future', 'sufficient_effect'];
281
+ function nodeStanding(record, node) {
282
+ const label = `node ${node.nodeId}`;
283
+ if (!node.inTree) {
284
+ return { ok: false, reasons: [`${label}: it is not among the focus's active reality-tree nodes, so no review verdict can be bound to it`] };
285
+ }
286
+ // The LATEST review that carries a verdict bound to this node decides.
287
+ for (const review of record.reviews) {
288
+ const bound = review.verdicts.flatMap((verdict) => verdict.binds.filter((b) => b.nodeId === node.nodeId).map((b) => ({ verdict, via: b.via })));
289
+ if (bound.length === 0)
290
+ continue;
291
+ const reasons = bound.flatMap((b) => unmetReason(review, b.verdict) ?? []).map((r) => `${label}: ${r}`);
292
+ if (reasons.length > 0)
293
+ return { ok: false, reasons };
294
+ const pick = [...bound].sort((a, b) => VIA_ORDER.indexOf(a.via) - VIA_ORDER.indexOf(b.via))[0];
295
+ return {
296
+ ok: true,
297
+ ruling: {
298
+ nodeId: node.nodeId, criterion: pick.verdict.criterion, reviewId: review.reviewId, evidence: pick.verdict.evidence,
299
+ via: pick.via, verdictNodeId: pick.verdict.nodeId,
300
+ },
301
+ };
302
+ }
303
+ return {
304
+ ok: false,
305
+ reasons: [
306
+ `${label}: no review verdict identifies this node's criterion (none under the arm is a tree verdict on the node, ` +
307
+ `this delivery's criterion stating its declared future${node.future === null ? ' (it declares none)' : ''}, ` +
308
+ 'or a tree verdict on an effect it is a sufficient cause of)',
309
+ ],
310
+ };
311
+ }
312
+ function gateReasons(record) {
313
+ if (record.judgedCommit === null)
314
+ return ['no judged commit is recorded on the delivery, so no gate verdict can be about it'];
315
+ const sha = short(record.judgedCommit.sha);
316
+ if (record.gateVerdict === null)
317
+ return [`no gate verdict is recorded for the judged commit ${sha}`];
318
+ if (record.gateVerdict.outcome === 'failed') {
319
+ return [`the gate verdict for the judged commit ${sha} is failed${record.gateVerdict.failedStage ? ` (stage ${record.gateVerdict.failedStage})` : ''}`];
320
+ }
321
+ return [];
322
+ }
323
+ /** Pure: whether the record supports the supervisor's shortfall ruling (module header). */
324
+ export function computeShortfallStanding(record, ask) {
325
+ const reasons = [];
326
+ if (askExcuses(ask.helpNeeded) || askExcuses(ask.act ?? null)) {
327
+ reasons.push('the ask would excuse a criterion; an excuse is never a supervisor act');
328
+ }
329
+ reasons.push(...gateReasons(record));
330
+ const { scope, unasked } = rulingScopeOf(record);
331
+ if (scope.length === 0)
332
+ reasons.push('no verify shortfall node is recorded on this delivery');
333
+ if (!record.reviewsReadable)
334
+ reasons.push('the review verdicts under the arm could not be read');
335
+ if (!record.bindingsReadable)
336
+ reasons.push('the reality tree that binds review verdicts to the shortfall nodes could not be read');
337
+ const rulings = [];
338
+ for (const node of record.reviewsReadable && record.bindingsReadable ? scope : []) {
339
+ const s = nodeStanding(record, node);
340
+ if (s.ok)
341
+ rulings.push(s.ruling);
342
+ else
343
+ reasons.push(...s.reasons);
344
+ }
345
+ return reasons.length > 0 ? { standing: 'defer', reasons, unasked } : { standing: 'rule', rulings, unasked };
346
+ }
347
+ // ─── Rendering ────────────────────────────────────────────────────
348
+ function gateLines(record) {
349
+ const out = [];
350
+ const jc = record.judgedCommit;
351
+ out.push(jc === null
352
+ ? '- Judged commit: none recorded.'
353
+ : `- Judged commit: ${jc.sha} (from ${jc.source === 'judged_commit' ? 'verificationHistory.judgedCommit' : 'the live shortfall hold\'s gate verdict'}).`);
354
+ const gv = record.gateVerdict;
355
+ out.push(gv === null
356
+ ? '- Gate verdict for the judged commit: NONE recorded.'
357
+ : `- Gate verdict for the judged commit: ${gv.outcome.toUpperCase()}${gv.failedStage ? ` at stage ${gv.failedStage}` : ''} (${gv.from}).`);
358
+ for (const o of record.otherCommitVerdicts)
359
+ out.push(` - (about another commit, not counted: ${o.outcome} at ${short(o.sha)}, ${o.from})`);
360
+ return out;
361
+ }
362
+ function reviewLines(record) {
363
+ if (!record.reviewsReadable)
364
+ return ['(The review verdicts could not be read.)'];
365
+ const withVerdicts = record.reviews.filter((r) => r.verdicts.length > 0);
366
+ if (withVerdicts.length === 0)
367
+ return ['(No review under the arm rendered a verdict bound to these nodes or on this delivery\'s criteria.)'];
368
+ const out = [];
369
+ for (const r of withVerdicts) {
370
+ out.push(`- review ${r.reviewId} (${r.outcome}, completed ${r.completedAt}${r.reviewedSha ? `, at ${r.reviewedSha}` : ''}):`);
371
+ for (const v of r.verdicts) {
372
+ const on = v.source === 'tree' ? `tree node ${v.nodeId}` : 'delivery criterion';
373
+ const binds = v.binds.length === 0
374
+ ? 'binds NO shortfall node'
375
+ : v.binds.map((b) => `binds node ${b.nodeId} as ${VIA_LABEL[b.via]}`).join(', ');
376
+ const flags = [binds, v.storedOnly ? 'stored only, no summary entry' : '', v.disagrees ? 'stored row DISAGREES with the summary' : ''].filter(Boolean);
377
+ out.push(` - ${v.verdict} (${on}; ${flags.join('; ')}): criterion (verbatim, as a JSON string): ${JSON.stringify(v.criterion)}`);
378
+ out.push(` evidence: ${v.evidence.length > 0 ? v.evidence.join(' | ') : '(none)'}`);
379
+ }
380
+ }
381
+ return out;
382
+ }
383
+ /** How each binding reads in the prompt. */
384
+ const VIA_LABEL = {
385
+ tree_verdict_on_node: 'a tree verdict on the node itself',
386
+ declared_future: 'this delivery\'s criterion stating the node\'s declared future',
387
+ sufficient_effect: 'a tree verdict on an effect the node is a sufficient cause of',
388
+ };
389
+ function unaskedLines(standing) {
390
+ if (standing.unasked.length === 0)
391
+ return [];
392
+ return [
393
+ `Recorded on the delivery but NOT asked for by the filing (not ruled, and not counted for or against this ask): ` +
394
+ `node(s) ${standing.unasked.join(', ')}.`,
395
+ ];
396
+ }
397
+ function standingLines(standing) {
398
+ if (standing.standing === 'defer') {
399
+ return [
400
+ `**The record does NOT support a ruling: ${standing.reasons.join('; ')}. DEFER.**`,
401
+ `Do not call ${SHORTFALL_RULING_ACT}: an ask for a shortfall ruling on this delivery is deferred. ` +
402
+ '(An ask for anything else is judged by the answer-or-defer steps.)',
403
+ ...unaskedLines(standing),
404
+ ];
405
+ }
406
+ const out = [
407
+ '**The record SUPPORTS ruling these node(s) met**: the judged commit\'s gate verdict passed and the latest review under',
408
+ 'the arm that judged each node\'s criterion -- by a verdict BOUND to that node -- judged it met with evidence.',
409
+ `If the ask is a shortfall ruling, RULE with ${SHORTFALL_RULING_ACT}, one ruling per node, passing exactly this criterion:`,
410
+ ];
411
+ for (const r of standing.rulings) {
412
+ out.push(`- nodeId "${r.nodeId}", criterion ${JSON.stringify(r.criterion)} (bound as ${VIA_LABEL[r.via]}` +
413
+ `${r.via === 'sufficient_effect' && r.verdictNodeId ? ` ${r.verdictNodeId}` : ''}; review ${r.reviewId}; evidence ${r.evidence.join(' | ')})`);
414
+ }
415
+ out.push('The server refuses any other criterion for that node: a verdict not bound to the node is not evidence it holds.');
416
+ out.push(...unaskedLines(standing));
417
+ return out;
418
+ }
419
+ function nodeLine(n) {
420
+ const parts = [`- node ${n.nodeId} (named by ${n.namedBy.join(', ')})`];
421
+ if (n.declared)
422
+ parts.push(`declared outcome: ${JSON.stringify(n.declared)}`);
423
+ if (!n.inTree)
424
+ parts.push('NOT found among the focus\'s active reality-tree nodes');
425
+ else {
426
+ parts.push(n.future === null ? 'declares no future (frt_statement)' : `declared future (frt_statement): ${JSON.stringify(n.future)}`);
427
+ parts.push(n.sufficientEffectIds.length === 0
428
+ ? 'a sufficient cause of no active effect'
429
+ : `a sufficient cause of effect(s) ${n.sufficientEffectIds.join(', ')}`);
430
+ }
431
+ return parts.join('; ');
432
+ }
433
+ /** Pure: the shortfall section of the escalation prompt. */
434
+ export function renderShortfallSection(record, standing) {
435
+ const out = [
436
+ `## The verify shortfall record of "${record.deliveryName}" (deliveryId ${record.deliveryId})`,
437
+ '',
438
+ ...gateLines(record),
439
+ '',
440
+ 'Shortfall nodes:',
441
+ ];
442
+ if (record.nodes.length === 0)
443
+ out.push('(none recorded)');
444
+ if (!record.bindingsReadable)
445
+ out.push('(The reality tree that binds review verdicts to these nodes could not be read.)');
446
+ for (const n of record.nodes)
447
+ out.push(nodeLine(n));
448
+ out.push('', 'Review verdicts under the current arm bound to these nodes, and on this delivery\'s criteria (newest first). A verdict', 'binds a node only as a tree verdict on the node itself, as this delivery\'s criterion whose text IS the node\'s declared', 'future, or as a tree verdict on an effect the node is a sufficient cause of; nothing else is evidence the node holds:', ...reviewLines(record));
449
+ out.push('', ...standingLines(standing), '');
450
+ return out;
451
+ }
452
+ //# sourceMappingURL=tower-escalation-shortfall.js.map