@telora/daemon 0.21.98 → 0.21.134

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 (226) hide show
  1. package/build-info.json +6 -3
  2. package/dist/audit/audit-hooks.d.ts +106 -0
  3. package/dist/audit/audit-hooks.d.ts.map +1 -1
  4. package/dist/audit/audit-hooks.js +149 -17
  5. package/dist/audit/audit-hooks.js.map +1 -1
  6. package/dist/ci/ci-sensor-loop.d.ts +6 -0
  7. package/dist/ci/ci-sensor-loop.d.ts.map +1 -1
  8. package/dist/ci/ci-sensor-loop.js +50 -3
  9. package/dist/ci/ci-sensor-loop.js.map +1 -1
  10. package/dist/completion/coverage-drift-state.d.ts +29 -2
  11. package/dist/completion/coverage-drift-state.d.ts.map +1 -1
  12. package/dist/completion/coverage-drift-state.js +42 -2
  13. package/dist/completion/coverage-drift-state.js.map +1 -1
  14. package/dist/completion/coverage-stabilized.d.ts +58 -0
  15. package/dist/completion/coverage-stabilized.d.ts.map +1 -0
  16. package/dist/completion/coverage-stabilized.js +84 -0
  17. package/dist/completion/coverage-stabilized.js.map +1 -0
  18. package/dist/completion/delivery-advancement-guard.d.ts +21 -0
  19. package/dist/completion/delivery-advancement-guard.d.ts.map +1 -1
  20. package/dist/completion/delivery-advancement-guard.js +31 -3
  21. package/dist/completion/delivery-advancement-guard.js.map +1 -1
  22. package/dist/completion/event-escalations.d.ts +15 -0
  23. package/dist/completion/event-escalations.d.ts.map +1 -1
  24. package/dist/completion/event-escalations.js +42 -4
  25. package/dist/completion/event-escalations.js.map +1 -1
  26. package/dist/completion/event-phases.d.ts.map +1 -1
  27. package/dist/completion/event-phases.js +5 -2
  28. package/dist/completion/event-phases.js.map +1 -1
  29. package/dist/completion/machine-remediable-demotion.d.ts +74 -0
  30. package/dist/completion/machine-remediable-demotion.d.ts.map +1 -0
  31. package/dist/completion/machine-remediable-demotion.js +147 -0
  32. package/dist/completion/machine-remediable-demotion.js.map +1 -0
  33. package/dist/completion/review-exit-phase.d.ts.map +1 -1
  34. package/dist/completion/review-exit-phase.js +10 -6
  35. package/dist/completion/review-exit-phase.js.map +1 -1
  36. package/dist/completion/settle-injection-sweep.d.ts +55 -0
  37. package/dist/completion/settle-injection-sweep.d.ts.map +1 -0
  38. package/dist/completion/settle-injection-sweep.js +88 -0
  39. package/dist/completion/settle-injection-sweep.js.map +1 -0
  40. package/dist/completion/state-cascade.d.ts.map +1 -1
  41. package/dist/completion/state-cascade.js +41 -0
  42. package/dist/completion/state-cascade.js.map +1 -1
  43. package/dist/completion/status-advance-phase.d.ts.map +1 -1
  44. package/dist/completion/status-advance-phase.js +18 -1
  45. package/dist/completion/status-advance-phase.js.map +1 -1
  46. package/dist/completion/team-lifecycle.d.ts +42 -0
  47. package/dist/completion/team-lifecycle.d.ts.map +1 -1
  48. package/dist/completion/team-lifecycle.js +71 -0
  49. package/dist/completion/team-lifecycle.js.map +1 -1
  50. package/dist/delivery/delivery-lifecycle.d.ts +19 -33
  51. package/dist/delivery/delivery-lifecycle.d.ts.map +1 -1
  52. package/dist/delivery/delivery-lifecycle.js +19 -147
  53. package/dist/delivery/delivery-lifecycle.js.map +1 -1
  54. package/dist/delivery/delivery-merge-ops.d.ts +46 -0
  55. package/dist/delivery/delivery-merge-ops.d.ts.map +1 -0
  56. package/dist/delivery/delivery-merge-ops.js +154 -0
  57. package/dist/delivery/delivery-merge-ops.js.map +1 -0
  58. package/dist/delivery/delivery-reconciler-apply.d.ts +28 -0
  59. package/dist/delivery/delivery-reconciler-apply.d.ts.map +1 -1
  60. package/dist/delivery/delivery-reconciler-apply.js +30 -0
  61. package/dist/delivery/delivery-reconciler-apply.js.map +1 -1
  62. package/dist/delivery/delivery-reconciler.d.ts +7 -2
  63. package/dist/delivery/delivery-reconciler.d.ts.map +1 -1
  64. package/dist/delivery/delivery-reconciler.js +34 -5
  65. package/dist/delivery/delivery-reconciler.js.map +1 -1
  66. package/dist/delivery/external-hold-surface.d.ts +32 -0
  67. package/dist/delivery/external-hold-surface.d.ts.map +1 -0
  68. package/dist/delivery/external-hold-surface.js +67 -0
  69. package/dist/delivery/external-hold-surface.js.map +1 -0
  70. package/dist/delivery/external-hold.d.ts +21 -0
  71. package/dist/delivery/external-hold.d.ts.map +1 -1
  72. package/dist/delivery/external-hold.js +40 -5
  73. package/dist/delivery/external-hold.js.map +1 -1
  74. package/dist/delivery/paused-revival.d.ts +140 -0
  75. package/dist/delivery/paused-revival.d.ts.map +1 -0
  76. package/dist/delivery/paused-revival.js +229 -0
  77. package/dist/delivery/paused-revival.js.map +1 -0
  78. package/dist/delivery/wait-reachability.d.ts.map +1 -1
  79. package/dist/delivery/wait-reachability.js +11 -0
  80. package/dist/delivery/wait-reachability.js.map +1 -1
  81. package/dist/directive/close-loop-dispatcher.d.ts +16 -263
  82. package/dist/directive/close-loop-dispatcher.d.ts.map +1 -1
  83. package/dist/directive/close-loop-dispatcher.js +21 -259
  84. package/dist/directive/close-loop-dispatcher.js.map +1 -1
  85. package/dist/directive/directive-dispatch.d.ts +19 -0
  86. package/dist/directive/directive-dispatch.d.ts.map +1 -1
  87. package/dist/directive/directive-dispatch.js +18 -0
  88. package/dist/directive/directive-dispatch.js.map +1 -1
  89. package/dist/directive/directive-executor.d.ts +1 -3
  90. package/dist/directive/directive-executor.d.ts.map +1 -1
  91. package/dist/directive/directive-executor.js +23 -21
  92. package/dist/directive/directive-executor.js.map +1 -1
  93. package/dist/directive/phase-sync.d.ts +28 -15
  94. package/dist/directive/phase-sync.d.ts.map +1 -1
  95. package/dist/directive/phase-sync.js +28 -36
  96. package/dist/directive/phase-sync.js.map +1 -1
  97. package/dist/directive/resolver-dispatch.d.ts +19 -92
  98. package/dist/directive/resolver-dispatch.d.ts.map +1 -1
  99. package/dist/directive/resolver-dispatch.js +19 -65
  100. package/dist/directive/resolver-dispatch.js.map +1 -1
  101. package/dist/focus/focus-engine.d.ts.map +1 -1
  102. package/dist/focus/focus-engine.js +26 -0
  103. package/dist/focus/focus-engine.js.map +1 -1
  104. package/dist/focus/focus-executor.d.ts.map +1 -1
  105. package/dist/focus/focus-executor.js +290 -256
  106. package/dist/focus/focus-executor.js.map +1 -1
  107. package/dist/focus/focus-loop-registry.d.ts.map +1 -1
  108. package/dist/focus/focus-loop-registry.js +43 -1
  109. package/dist/focus/focus-loop-registry.js.map +1 -1
  110. package/dist/focus/focus-respawn-guard.d.ts.map +1 -1
  111. package/dist/focus/focus-respawn-guard.js +11 -2
  112. package/dist/focus/focus-respawn-guard.js.map +1 -1
  113. package/dist/focus/focus-team-state.d.ts +11 -0
  114. package/dist/focus/focus-team-state.d.ts.map +1 -1
  115. package/dist/focus/focus-team-state.js +17 -0
  116. package/dist/focus/focus-team-state.js.map +1 -1
  117. package/dist/focus/listener-auto-advance.d.ts +13 -1
  118. package/dist/focus/listener-auto-advance.d.ts.map +1 -1
  119. package/dist/focus/listener-auto-advance.js +103 -22
  120. package/dist/focus/listener-auto-advance.js.map +1 -1
  121. package/dist/focus/listener.d.ts.map +1 -1
  122. package/dist/focus/listener.js +125 -75
  123. package/dist/focus/listener.js.map +1 -1
  124. package/dist/focus/tick-deadline.d.ts +55 -0
  125. package/dist/focus/tick-deadline.d.ts.map +1 -0
  126. package/dist/focus/tick-deadline.js +91 -0
  127. package/dist/focus/tick-deadline.js.map +1 -0
  128. package/dist/focus-stage-lifecycle/index.d.ts +18 -25
  129. package/dist/focus-stage-lifecycle/index.d.ts.map +1 -1
  130. package/dist/focus-stage-lifecycle/index.js +26 -38
  131. package/dist/focus-stage-lifecycle/index.js.map +1 -1
  132. package/dist/focus-stage-lifecycle/wedge-cause-arbiter.d.ts +52 -0
  133. package/dist/focus-stage-lifecycle/wedge-cause-arbiter.d.ts.map +1 -0
  134. package/dist/focus-stage-lifecycle/wedge-cause-arbiter.js +94 -0
  135. package/dist/focus-stage-lifecycle/wedge-cause-arbiter.js.map +1 -0
  136. package/dist/focus-stage-lifecycle/wedge-watchdog.d.ts +18 -1
  137. package/dist/focus-stage-lifecycle/wedge-watchdog.d.ts.map +1 -1
  138. package/dist/focus-stage-lifecycle/wedge-watchdog.js +57 -7
  139. package/dist/focus-stage-lifecycle/wedge-watchdog.js.map +1 -1
  140. package/dist/guard/condition-evaluators.d.ts +9 -0
  141. package/dist/guard/condition-evaluators.d.ts.map +1 -1
  142. package/dist/guard/condition-evaluators.js +15 -0
  143. package/dist/guard/condition-evaluators.js.map +1 -1
  144. package/dist/guard/guard-evaluator.d.ts +17 -1
  145. package/dist/guard/guard-evaluator.d.ts.map +1 -1
  146. package/dist/guard/guard-evaluator.js +61 -2
  147. package/dist/guard/guard-evaluator.js.map +1 -1
  148. package/dist/guard/trigger-executor.d.ts +30 -18
  149. package/dist/guard/trigger-executor.d.ts.map +1 -1
  150. package/dist/guard/trigger-executor.js +55 -31
  151. package/dist/guard/trigger-executor.js.map +1 -1
  152. package/dist/prompt/team-prompt-base.d.ts +1 -1
  153. package/dist/prompt/team-prompt-base.d.ts.map +1 -1
  154. package/dist/prompt/team-prompt-base.js +1 -1
  155. package/dist/prompt/team-prompt-base.js.map +1 -1
  156. package/dist/prompt-sections/persona-sections.d.ts +0 -32
  157. package/dist/prompt-sections/persona-sections.d.ts.map +1 -1
  158. package/dist/prompt-sections/persona-sections.js +19 -88
  159. package/dist/prompt-sections/persona-sections.js.map +1 -1
  160. package/dist/queries/deliveries.d.ts +23 -0
  161. package/dist/queries/deliveries.d.ts.map +1 -1
  162. package/dist/queries/deliveries.js +6 -0
  163. package/dist/queries/deliveries.js.map +1 -1
  164. package/dist/queries/focuses.d.ts +36 -0
  165. package/dist/queries/focuses.d.ts.map +1 -1
  166. package/dist/queries/focuses.js +45 -0
  167. package/dist/queries/focuses.js.map +1 -1
  168. package/dist/queries/guards.d.ts +10 -0
  169. package/dist/queries/guards.d.ts.map +1 -1
  170. package/dist/queries/guards.js +14 -1
  171. package/dist/queries/guards.js.map +1 -1
  172. package/dist/queries/issues.d.ts +65 -1
  173. package/dist/queries/issues.d.ts.map +1 -1
  174. package/dist/queries/issues.js +135 -2
  175. package/dist/queries/issues.js.map +1 -1
  176. package/dist/queries/schemas.d.ts +51 -0
  177. package/dist/queries/schemas.d.ts.map +1 -1
  178. package/dist/queries/schemas.js +34 -0
  179. package/dist/queries/schemas.js.map +1 -1
  180. package/dist/queries/verification.d.ts +5 -6
  181. package/dist/queries/verification.d.ts.map +1 -1
  182. package/dist/queries/verification.js +5 -6
  183. package/dist/queries/verification.js.map +1 -1
  184. package/dist/resolvers/loop-persona.d.ts +1 -11
  185. package/dist/resolvers/loop-persona.d.ts.map +1 -1
  186. package/dist/resolvers/loop-persona.js +2 -16
  187. package/dist/resolvers/loop-persona.js.map +1 -1
  188. package/dist/shell/unified-shell-provisioning.d.ts +40 -0
  189. package/dist/shell/unified-shell-provisioning.d.ts.map +1 -1
  190. package/dist/shell/unified-shell-provisioning.js +72 -0
  191. package/dist/shell/unified-shell-provisioning.js.map +1 -1
  192. package/dist/shell/unified-shell.d.ts.map +1 -1
  193. package/dist/shell/unified-shell.js +18 -1
  194. package/dist/shell/unified-shell.js.map +1 -1
  195. package/dist/spawn/helpers.d.ts.map +1 -1
  196. package/dist/spawn/helpers.js +6 -1
  197. package/dist/spawn/helpers.js.map +1 -1
  198. package/dist/spawn/process-spawn.d.ts.map +1 -1
  199. package/dist/spawn/process-spawn.js +7 -0
  200. package/dist/spawn/process-spawn.js.map +1 -1
  201. package/dist/spawn/spawn-cooldown.d.ts +41 -7
  202. package/dist/spawn/spawn-cooldown.d.ts.map +1 -1
  203. package/dist/spawn/spawn-cooldown.js +47 -0
  204. package/dist/spawn/spawn-cooldown.js.map +1 -1
  205. package/dist/spawn/spawn-decision.d.ts.map +1 -1
  206. package/dist/spawn/spawn-decision.js +33 -1
  207. package/dist/spawn/spawn-decision.js.map +1 -1
  208. package/dist/verify/stall-detectors.d.ts +20 -8
  209. package/dist/verify/stall-detectors.d.ts.map +1 -1
  210. package/dist/verify/stall-detectors.js +27 -46
  211. package/dist/verify/stall-detectors.js.map +1 -1
  212. package/dist/workflow/gate-failure-policy.d.ts +48 -0
  213. package/dist/workflow/gate-failure-policy.d.ts.map +1 -0
  214. package/dist/workflow/gate-failure-policy.js +57 -0
  215. package/dist/workflow/gate-failure-policy.js.map +1 -0
  216. package/dist/workflow/pipeline-config.d.ts +2 -2
  217. package/dist/workflow/pipeline-config.js +2 -2
  218. package/package.json +1 -1
  219. package/dist/directive/close-loop-stage.d.ts +0 -50
  220. package/dist/directive/close-loop-stage.d.ts.map +0 -1
  221. package/dist/directive/close-loop-stage.js +0 -210
  222. package/dist/directive/close-loop-stage.js.map +0 -1
  223. package/dist/focus-stage-lifecycle/review-convergence.d.ts +0 -133
  224. package/dist/focus-stage-lifecycle/review-convergence.d.ts.map +0 -1
  225. package/dist/focus-stage-lifecycle/review-convergence.js +0 -237
  226. package/dist/focus-stage-lifecycle/review-convergence.js.map +0 -1
@@ -1,64 +1,20 @@
1
1
  /**
2
- * Close-loop stage dispatcher.
2
+ * Focus injection-sweep primitives.
3
3
  *
4
- * Handles focuses entering the `close_loop` workflow stage. Three asymmetric
5
- * checks are delegated to the spawned bookkeeper team via the assembled
6
- * directive; the dispatcher itself is responsible for the deterministic
7
- * pre- and post-conditions:
4
+ * Formerly the close-loop dispatcher's pure helpers. The machine-driven
5
+ * close_loop/done stage-writing family has been removed (the focus lifecycle
6
+ * collapsed to a single derived phase terminating at winding_down); these
7
+ * pure primitives are all that remains, retained for
8
+ * `completion/settle-injection-sweep.ts`, which runs the same anchored-injection
9
+ * sweep at the derived winding_down settle (writing NO focus stage).
8
10
  *
9
- * - **Short-circuit on no anchors.** If the focus has no anchoring
10
- * injections, close_loop is a no-op: the dispatcher advances the focus
11
- * directly to `done`. No team is spawned. This matches the
12
- * `no_anchoring_injections_short_circuit` soft guard on
13
- * `verify -> close_loop` in the focus workflow.
14
- *
15
- * - **Otherwise, spawn a fresh bookkeeper team** (Sonnet model, fresh
16
- * session) with the close_loop assembly recipe:
17
- * loop.persona(variant=close_loop)
18
- * focus.context
19
- * focus.anchoring_injections
20
- * git.diff_against_base
21
- * delivery.acceptance_criteria
22
- * review.outcomes
23
- * The team handles the per-injection sweep (verified | escalated, no
24
- * third option), the incomplete-planning check, and the tree-drift
25
- * check skeleton (D5 wires `focus.description` through into the
26
- * drift-check prompt section).
27
- *
28
- * - **Monitor termination.** Once every anchored injection has reached a
29
- * terminal state (`verified` or has an open `injection_unverified`
30
- * escalation), the dispatcher advances the focus to `done`. While any
31
- * injection is still non-terminal, the focus stays at `close_loop`.
32
- *
33
- * The dispatcher is intentionally split into small pure helpers so each
34
- * deterministic check (terminal classification, short-circuit detection,
35
- * directive composition) is unit-testable without DB or process spawning.
11
+ * The sweep realizes anchored injections whose anchoring deliveries closed
12
+ * successfully but whose injection status has not yet flipped to 'verified',
13
+ * so the reality tree settles to reflect what was built. Split into small pure
14
+ * helpers so each check (anchor filtering, sweep planning, sweep execution) is
15
+ * unit-testable without DB or process spawning.
36
16
  */
37
- import type { DaemonConfig, StageDirective } from '../types/index.js';
38
17
  import type { FocusDeliveryInfo } from '../types/index.js';
39
- /**
40
- * Model used by close_loop bookkeeper teams. Sonnet because the bookkeeper
41
- * is a careful, deterministic role (sweep injections, file escalations);
42
- * Opus would be overkill and slower.
43
- */
44
- export declare const CLOSE_LOOP_MODEL = "claude-sonnet-4-6";
45
- /**
46
- * Assembly recipe for the close_loop stage. Composed in dispatcher when
47
- * the close_loop directive is synthesized. Persisted nowhere -- the
48
- * stage's stored `agent_directive` (if any) is ignored in favor of this
49
- * canonical recipe so the bookkeeper framing is deterministic regardless
50
- * of how the workflow stage row was seeded.
51
- */
52
- export declare const CLOSE_LOOP_ASSEMBLY_RECIPE: readonly string[];
53
- /**
54
- * Terminal injection statuses for close_loop. An injection is considered
55
- * terminal when it is either verified (the bookkeeper called
56
- * reality_tree_injection_verify) or has an `injection_unverified`
57
- * escalation filed against it. The first is detected by `injectionStatus`;
58
- * the second is detected by walking the agent_escalations table -- see
59
- * `isInjectionEscalated`.
60
- */
61
- export declare const TERMINAL_INJECTION_STATUSES: readonly string[];
62
18
  /**
63
19
  * Return the deliveries in the focus that anchor an injection.
64
20
  *
@@ -68,49 +24,6 @@ export declare const TERMINAL_INJECTION_STATUSES: readonly string[];
68
24
  * reality_tree_nodes row.
69
25
  */
70
26
  export declare function getAnchoringDeliveries(deliveries: FocusDeliveryInfo[]): FocusDeliveryInfo[];
71
- /**
72
- * Pure short-circuit predicate -- "does this focus have any anchoring
73
- * injections?". If false, close_loop is a no-op and the focus can advance
74
- * directly to `done`.
75
- */
76
- export declare function shouldShortCircuitToDone(deliveries: FocusDeliveryInfo[]): boolean;
77
- /**
78
- * Per-injection summary used by termination checks. The dispatcher composes
79
- * one of these per anchored injection from a snapshot of:
80
- *
81
- * - the injection node's `injectionStatus` (from reality_tree_nodes)
82
- * - whether there is an open `injection_unverified` escalation with
83
- * metadata.injection_id == this injection id (from agent_escalations)
84
- */
85
- export interface InjectionTerminalState {
86
- injectionId: string;
87
- /** From reality_tree_nodes.injection_status (or null for non-injection nodes). */
88
- injectionStatus: string | null;
89
- /** Whether an open injection_unverified escalation targets this injection. */
90
- hasOpenUnverifiedEscalation: boolean;
91
- }
92
- /**
93
- * Pure classifier. An injection is terminal for close_loop when:
94
- *
95
- * - injectionStatus is `verified`, OR
96
- * - there is an open `injection_unverified` escalation for it
97
- * (this is the "escalated" outcome -- the bookkeeper filed the
98
- * escalation and the focus is now blocked on a human).
99
- *
100
- * The "open escalation" case keeps the focus at close_loop (status='pending'
101
- * or 'in_review') -- this function classifies the escalation as terminal
102
- * for the dispatcher's perspective so the daemon does not loop forever
103
- * re-spawning the bookkeeper. A human must resolve or dismiss the
104
- * escalation; once resolved, the bookkeeper can be re-triggered.
105
- */
106
- export declare function isInjectionTerminal(state: InjectionTerminalState): boolean;
107
- /**
108
- * Pure aggregate predicate -- "are ALL anchored injections terminal?".
109
- * Returns true on an empty list (the short-circuit branch handles the
110
- * empty case separately, but this is safe to call after the short-circuit
111
- * filter).
112
- */
113
- export declare function allInjectionsTerminal(states: InjectionTerminalState[]): boolean;
114
27
  /**
115
28
  * One entry in the planned sweep: an injection that should be verified and
116
29
  * the evidence text to persist with the verify call.
@@ -144,8 +57,8 @@ export declare function planInjectionSweep(anchored: FocusDeliveryInfo[], status
144
57
  * I/O so tests can pass a stub.
145
58
  *
146
59
  * `ok === true` means every entry verified; `ok === false` means the loop
147
- * stopped at `failedAt.injectionId`. The dispatcher MUST NOT advance the
148
- * focus to 'done' when `ok` is false -- a partial sweep means the tree is
60
+ * stopped at `failedAt.injectionId`. The caller MUST NOT treat the sweep as
61
+ * complete when `ok` is false -- a partial sweep means the tree is
149
62
  * still in an inconsistent state and the next poll cycle should retry.
150
63
  */
151
64
  export interface SweepRunOutcome {
@@ -158,168 +71,8 @@ export interface SweepRunOutcome {
158
71
  }
159
72
  /**
160
73
  * Execute a planned sweep in order. Short-circuits on the first failure --
161
- * the dispatcher returns the original `advance_to_done` decision without
162
- * calling `updateFocusStage`, so the failed verify is retried on the next
163
- * close_loop poll cycle.
74
+ * the caller holds the focus and retries the failed verify on the next
75
+ * settle cycle.
164
76
  */
165
77
  export declare function executeSweep(entries: readonly InjectionSweepEntry[], verify: (injectionId: string, evidence: string) => Promise<void>): Promise<SweepRunOutcome>;
166
- /**
167
- * Dependencies for advancing a focus from close_loop -> done with a
168
- * preceding injection sweep. Both are owned by callers so tests can stub
169
- * them without mocking the daemon's I/O layer.
170
- */
171
- export interface AdvanceToDoneDeps {
172
- verify: (injectionId: string, evidence: string) => Promise<void>;
173
- updateFocusStage: (focusId: string, stage: 'done') => Promise<void>;
174
- }
175
- /**
176
- * Outcome of `advanceFocusToDoneWithSweep`. The dispatcher reads this to
177
- * decide whether to clear the bookkeeper-spawned flag (which is cleared
178
- * only when the focus actually leaves close_loop, success or terminal
179
- * failure).
180
- *
181
- * - `advanced=true` -- updateFocusStage was called and returned
182
- * - `sweepFailure` set -- the sweep failed; updateFocusStage was NOT
183
- * called; the focus is held at close_loop for the next poll cycle to
184
- * retry. This is the explicit "focus does not advance" semantics from
185
- * AC-6 of the focus-closure-correctness focus.
186
- * - `advanceError` set -- the sweep succeeded (or was empty) but
187
- * updateFocusStage threw. The focus did not advance, but the failure
188
- * is on the stage-update side, not the sweep side.
189
- */
190
- export interface AdvanceToDoneOutcome {
191
- advanced: boolean;
192
- verifiedCount: number;
193
- planSize: number;
194
- sweepFailure?: {
195
- injectionId: string;
196
- error: Error;
197
- };
198
- advanceError?: Error;
199
- }
200
- /**
201
- * Run the close_loop sweep, then advance the focus to `done`. Pure with
202
- * respect to side effects -- callers inject `verify` and
203
- * `updateFocusStage` via `deps`.
204
- *
205
- * Order of operations is part of the contract:
206
- * 1. Build the sweep plan from `anchored` + `statusByInjectionId`.
207
- * 2. If non-empty, run the sweep. On failure: log + return early WITHOUT
208
- * calling `deps.updateFocusStage`. This is the "focus does not
209
- * advance" invariant — the failed verify is retried on the next poll
210
- * cycle when the focus is re-evaluated.
211
- * 3. On sweep success (or empty plan), call `deps.updateFocusStage`.
212
- *
213
- * The dispatcher (`dispatchCloseLoopStage`) delegates the entire
214
- * advance_to_done branch to this function so the sweep-failure path is
215
- * unit-testable without DB or process mocking.
216
- */
217
- export declare function advanceFocusToDoneWithSweep(focus: {
218
- focus_id: string;
219
- focus_name: string;
220
- }, anchored: FocusDeliveryInfo[], statusByInjectionId: ReadonlyMap<string, string | null>, deps: AdvanceToDoneDeps): Promise<AdvanceToDoneOutcome>;
221
- /**
222
- * Compose the synthetic close_loop StageDirective. Used by the dispatcher
223
- * to seed the pending spawn directive map; pure for testability.
224
- */
225
- export declare function buildCloseLoopDirective(): StageDirective;
226
- /**
227
- * Query: are there any pending or in_review injection_unverified escalations
228
- * for the given injection ids? Returns the set of injection ids that have
229
- * an open escalation.
230
- *
231
- * Looks at agent_escalations with:
232
- * - escalation_kind = 'injection_unverified'
233
- * - status IN ('pending', 'in_review')
234
- * - metadata->>'injection_id' IN (...)
235
- *
236
- * The dispatcher uses this to classify "escalated" injections as terminal
237
- * for advancement purposes.
238
- */
239
- export interface OpenInjectionEscalationLookup {
240
- (params: {
241
- organizationId: string;
242
- injectionIds: string[];
243
- }): Promise<Set<string>>;
244
- }
245
- /**
246
- * Top-level result of inspecting a focus for close_loop termination.
247
- * Tells the caller exactly what to do: short-circuit, spawn, advance to
248
- * done, or hold.
249
- */
250
- export type CloseLoopDecision = {
251
- kind: 'short_circuit_to_done';
252
- } | {
253
- kind: 'spawn_bookkeeper';
254
- directive: StageDirective;
255
- } | {
256
- kind: 'advance_to_done';
257
- } | {
258
- kind: 'hold';
259
- reason: string;
260
- };
261
- /**
262
- * Compute the close_loop decision for a focus given a snapshot of its
263
- * deliveries and the terminal state of each anchored injection.
264
- *
265
- * Pure -- no DB access. Tests pass snapshots in.
266
- *
267
- * Semantics:
268
- *
269
- * - No anchored injections -> short_circuit_to_done
270
- * - Anchored injections, none yet sweeped -> spawn_bookkeeper
271
- * - All anchored injections terminal -> advance_to_done
272
- * - Some terminal, some not -> hold (waiting on bookkeeper)
273
- *
274
- * The "spawn_bookkeeper" branch is gated on "no sweep has happened yet"
275
- * which the caller communicates via `bookkeeperHasRun`. Without this gate
276
- * every poll cycle would respawn the bookkeeper while it's still working
277
- * (or before a stuck injection's escalation is filed).
278
- */
279
- export declare function decideCloseLoop(deliveries: FocusDeliveryInfo[], injectionStates: InjectionTerminalState[], bookkeeperHasRun: boolean): CloseLoopDecision;
280
- /**
281
- * Sentinel returned by the dispatcher when no action was taken (focus is
282
- * not in close_loop stage, or already processed this cycle). Caller can
283
- * log it but should not act on it.
284
- */
285
- export interface CloseLoopDispatchOutcome {
286
- decision: CloseLoopDecision;
287
- /** Anchored injection ids that were inspected (empty on short-circuit). */
288
- anchoredInjectionIds: string[];
289
- }
290
- /**
291
- * Re-exported constant set so tests can assert the kind names used by the
292
- * dispatcher in the agent_escalations rows. Keeps the kind string under
293
- * a single source of truth in daemon-core.
294
- */
295
- export declare const CLOSE_LOOP_ESCALATION_KINDS: {
296
- readonly INJECTION_UNVERIFIED: "injection_unverified";
297
- readonly TREE_DRIFT: "tree_drift";
298
- readonly INCOMPLETE_PLANNING: "incomplete_planning";
299
- };
300
- /**
301
- * Configuration knobs accepted by the dispatcher entry point. Exposed so
302
- * tests can inject a no-op spawner.
303
- */
304
- export interface CloseLoopDispatcherDeps {
305
- /**
306
- * Set the pending spawn directive for the focus so the next spawn cycle
307
- * delivers the close_loop directive. In production this is the export
308
- * from directive-executor; in tests this is a stub.
309
- */
310
- setPendingSpawnDirective: (focusId: string, directive: {
311
- message: string;
312
- model: string | null;
313
- sessionType: 'coding' | 'review';
314
- contentHash: string;
315
- }) => void;
316
- /** Advance the focus stage on product_focuses.stage. */
317
- updateFocusStage: (focusId: string, stage: string) => Promise<void>;
318
- /** Lookup open injection_unverified escalations. */
319
- lookupOpenInjectionEscalations: OpenInjectionEscalationLookup;
320
- /** Build the directive content (assembly resolution + prompt). */
321
- assembleDirectiveContent: (config: DaemonConfig, focusId: string, directive: StageDirective, worktreePath: string | null) => Promise<string>;
322
- /** Compute the content hash for the synthesized directive. */
323
- computeDirectiveHash: (directive: StageDirective) => string;
324
- }
325
78
  //# sourceMappingURL=close-loop-dispatcher.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"close-loop-dispatcher.d.ts","sourceRoot":"","sources":["../../src/directive/close-loop-dispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAW3D;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,sBAAsB,CAAC;AAEpD;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,EAAE,SAAS,MAAM,EAOvD,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,EAAE,SAAS,MAAM,EAAiB,CAAC;AAM3E;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,iBAAiB,EAAE,GAAG,iBAAiB,EAAE,CAI3F;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAEjF;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,kFAAkF;IAClF,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,8EAA8E;IAC9E,2BAA2B,EAAE,OAAO,CAAC;CACtC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAQ1E;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,sBAAsB,EAAE,GAAG,OAAO,CAE/E;AA8BD;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,iBAAiB,EAAE,EAC7B,mBAAmB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,GACtD,mBAAmB,EAAE,CA6BvB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC;CAClD;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,SAAS,mBAAmB,EAAE,EACvC,MAAM,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAC/D,OAAO,CAAC,eAAe,CAAC,CAe1B;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,gBAAgB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrE;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC;IACrD,YAAY,CAAC,EAAE,KAAK,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,2BAA2B,CAC/C,KAAK,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,EAC/C,QAAQ,EAAE,iBAAiB,EAAE,EAC7B,mBAAmB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EACvD,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,oBAAoB,CAAC,CA6C/B;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,cAAc,CAgCxD;AAMD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,6BAA6B;IAC5C,CAAC,MAAM,EAAE;QACP,cAAc,EAAE,MAAM,CAAC;QACvB,YAAY,EAAE,MAAM,EAAE,CAAC;KACxB,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;CAC1B;AAED;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,uBAAuB,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,SAAS,EAAE,cAAc,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,iBAAiB,CAAA;CAAE,GAC3B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAErC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,iBAAiB,EAAE,EAC/B,eAAe,EAAE,sBAAsB,EAAE,EACzC,gBAAgB,EAAE,OAAO,GACxB,iBAAiB,CAmBnB;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,2EAA2E;IAC3E,oBAAoB,EAAE,MAAM,EAAE,CAAC;CAChC;AAED;;;;GAIG;AACH,eAAO,MAAM,2BAA2B;;;;CAI9B,CAAC;AAEX;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,wBAAwB,EAAE,CACxB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE;QACT,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,WAAW,EAAE,QAAQ,GAAG,QAAQ,CAAC;QACjC,WAAW,EAAE,MAAM,CAAC;KACrB,KACE,IAAI,CAAC;IACV,wDAAwD;IACxD,gBAAgB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,oDAAoD;IACpD,8BAA8B,EAAE,6BAA6B,CAAC;IAC9D,kEAAkE;IAClE,wBAAwB,EAAE,CACxB,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,cAAc,EACzB,YAAY,EAAE,MAAM,GAAG,IAAI,KACxB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,8DAA8D;IAC9D,oBAAoB,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,MAAM,CAAC;CAC7D"}
1
+ {"version":3,"file":"close-loop-dispatcher.d.ts","sourceRoot":"","sources":["../../src/directive/close-loop-dispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAM3D;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,iBAAiB,EAAE,GAAG,iBAAiB,EAAE,CAI3F;AA2BD;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,iBAAiB,EAAE,EAC7B,mBAAmB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,GACtD,mBAAmB,EAAE,CA6BvB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC;CAClD;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,SAAS,mBAAmB,EAAE,EACvC,MAAM,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAC/D,OAAO,CAAC,eAAe,CAAC,CAe1B"}
@@ -1,75 +1,19 @@
1
1
  /**
2
- * Close-loop stage dispatcher.
3
- *
4
- * Handles focuses entering the `close_loop` workflow stage. Three asymmetric
5
- * checks are delegated to the spawned bookkeeper team via the assembled
6
- * directive; the dispatcher itself is responsible for the deterministic
7
- * pre- and post-conditions:
8
- *
9
- * - **Short-circuit on no anchors.** If the focus has no anchoring
10
- * injections, close_loop is a no-op: the dispatcher advances the focus
11
- * directly to `done`. No team is spawned. This matches the
12
- * `no_anchoring_injections_short_circuit` soft guard on
13
- * `verify -> close_loop` in the focus workflow.
14
- *
15
- * - **Otherwise, spawn a fresh bookkeeper team** (Sonnet model, fresh
16
- * session) with the close_loop assembly recipe:
17
- * loop.persona(variant=close_loop)
18
- * focus.context
19
- * focus.anchoring_injections
20
- * git.diff_against_base
21
- * delivery.acceptance_criteria
22
- * review.outcomes
23
- * The team handles the per-injection sweep (verified | escalated, no
24
- * third option), the incomplete-planning check, and the tree-drift
25
- * check skeleton (D5 wires `focus.description` through into the
26
- * drift-check prompt section).
27
- *
28
- * - **Monitor termination.** Once every anchored injection has reached a
29
- * terminal state (`verified` or has an open `injection_unverified`
30
- * escalation), the dispatcher advances the focus to `done`. While any
31
- * injection is still non-terminal, the focus stays at `close_loop`.
32
- *
33
- * The dispatcher is intentionally split into small pure helpers so each
34
- * deterministic check (terminal classification, short-circuit detection,
35
- * directive composition) is unit-testable without DB or process spawning.
36
- */
37
- import { ESCALATION_KINDS } from '@telora/daemon-core';
38
- import { createLogger } from '../shell/log.js';
39
- const log = createLogger({ module: 'close-loop-dispatcher' });
40
- // ---------------------------------------------------------------------------
41
- // Constants
42
- // ---------------------------------------------------------------------------
43
- /**
44
- * Model used by close_loop bookkeeper teams. Sonnet because the bookkeeper
45
- * is a careful, deterministic role (sweep injections, file escalations);
46
- * Opus would be overkill and slower.
47
- */
48
- export const CLOSE_LOOP_MODEL = 'claude-sonnet-4-6';
49
- /**
50
- * Assembly recipe for the close_loop stage. Composed in dispatcher when
51
- * the close_loop directive is synthesized. Persisted nowhere -- the
52
- * stage's stored `agent_directive` (if any) is ignored in favor of this
53
- * canonical recipe so the bookkeeper framing is deterministic regardless
54
- * of how the workflow stage row was seeded.
2
+ * Focus injection-sweep primitives.
3
+ *
4
+ * Formerly the close-loop dispatcher's pure helpers. The machine-driven
5
+ * close_loop/done stage-writing family has been removed (the focus lifecycle
6
+ * collapsed to a single derived phase terminating at winding_down); these
7
+ * pure primitives are all that remains, retained for
8
+ * `completion/settle-injection-sweep.ts`, which runs the same anchored-injection
9
+ * sweep at the derived winding_down settle (writing NO focus stage).
10
+ *
11
+ * The sweep realizes anchored injections whose anchoring deliveries closed
12
+ * successfully but whose injection status has not yet flipped to 'verified',
13
+ * so the reality tree settles to reflect what was built. Split into small pure
14
+ * helpers so each check (anchor filtering, sweep planning, sweep execution) is
15
+ * unit-testable without DB or process spawning.
55
16
  */
56
- export const CLOSE_LOOP_ASSEMBLY_RECIPE = [
57
- 'loop.persona(variant=close_loop)',
58
- 'focus.context',
59
- 'focus.anchoring_injections',
60
- 'git.diff_against_base',
61
- 'delivery.acceptance_criteria',
62
- 'review.outcomes',
63
- ];
64
- /**
65
- * Terminal injection statuses for close_loop. An injection is considered
66
- * terminal when it is either verified (the bookkeeper called
67
- * reality_tree_injection_verify) or has an `injection_unverified`
68
- * escalation filed against it. The first is detected by `injectionStatus`;
69
- * the second is detected by walking the agent_escalations table -- see
70
- * `isInjectionEscalated`.
71
- */
72
- export const TERMINAL_INJECTION_STATUSES = ['verified'];
73
17
  // ---------------------------------------------------------------------------
74
18
  // Helpers (pure)
75
19
  // ---------------------------------------------------------------------------
@@ -84,56 +28,13 @@ export const TERMINAL_INJECTION_STATUSES = ['verified'];
84
28
  export function getAnchoringDeliveries(deliveries) {
85
29
  return deliveries.filter((d) => typeof d.injectionId === 'string' && d.injectionId.length > 0);
86
30
  }
87
- /**
88
- * Pure short-circuit predicate -- "does this focus have any anchoring
89
- * injections?". If false, close_loop is a no-op and the focus can advance
90
- * directly to `done`.
91
- */
92
- export function shouldShortCircuitToDone(deliveries) {
93
- return getAnchoringDeliveries(deliveries).length === 0;
94
- }
95
- /**
96
- * Pure classifier. An injection is terminal for close_loop when:
97
- *
98
- * - injectionStatus is `verified`, OR
99
- * - there is an open `injection_unverified` escalation for it
100
- * (this is the "escalated" outcome -- the bookkeeper filed the
101
- * escalation and the focus is now blocked on a human).
102
- *
103
- * The "open escalation" case keeps the focus at close_loop (status='pending'
104
- * or 'in_review') -- this function classifies the escalation as terminal
105
- * for the dispatcher's perspective so the daemon does not loop forever
106
- * re-spawning the bookkeeper. A human must resolve or dismiss the
107
- * escalation; once resolved, the bookkeeper can be re-triggered.
108
- */
109
- export function isInjectionTerminal(state) {
110
- if (state.injectionStatus && TERMINAL_INJECTION_STATUSES.includes(state.injectionStatus)) {
111
- return true;
112
- }
113
- if (state.hasOpenUnverifiedEscalation) {
114
- return true;
115
- }
116
- return false;
117
- }
118
- /**
119
- * Pure aggregate predicate -- "are ALL anchored injections terminal?".
120
- * Returns true on an empty list (the short-circuit branch handles the
121
- * empty case separately, but this is safe to call after the short-circuit
122
- * filter).
123
- */
124
- export function allInjectionsTerminal(states) {
125
- return states.every(isInjectionTerminal);
126
- }
127
31
  // ---------------------------------------------------------------------------
128
- // Focus-level injection sweep (close_loop -> done)
32
+ // Focus-level injection sweep
129
33
  //
130
- // The terminal-injection classifier above gates whether close_loop -> done is
131
- // even considered. Once the gate permits the advance, the daemon still has
132
- // one bookkeeping step to perform: anchored injections whose status is not
133
- // yet 'verified' but whose anchoring deliveries closed successfully (via a
134
- // path other than the per-delivery verify gate -- e.g. a delivery that
135
- // finished its review and routed straight to 'done') should be realized in
136
- // the reality tree before the focus advances.
34
+ // Anchored injections whose status is not yet 'verified' but whose anchoring
35
+ // deliveries closed successfully (via a path other than the per-delivery verify
36
+ // gate -- e.g. a delivery that finished its review and routed straight to
37
+ // 'done') should be realized in the reality tree at focus settle.
137
38
  //
138
39
  // Without this sweep, the FRT overlays for those injections stay frozen in
139
40
  // their pre-close state and the focus completes with a stale reality tree.
@@ -200,9 +101,8 @@ export function planInjectionSweep(anchored, statusByInjectionId) {
200
101
  }
201
102
  /**
202
103
  * Execute a planned sweep in order. Short-circuits on the first failure --
203
- * the dispatcher returns the original `advance_to_done` decision without
204
- * calling `updateFocusStage`, so the failed verify is retried on the next
205
- * close_loop poll cycle.
104
+ * the caller holds the focus and retries the failed verify on the next
105
+ * settle cycle.
206
106
  */
207
107
  export async function executeSweep(entries, verify) {
208
108
  const verified = [];
@@ -221,142 +121,4 @@ export async function executeSweep(entries, verify) {
221
121
  }
222
122
  return { ok: true, verified };
223
123
  }
224
- /**
225
- * Run the close_loop sweep, then advance the focus to `done`. Pure with
226
- * respect to side effects -- callers inject `verify` and
227
- * `updateFocusStage` via `deps`.
228
- *
229
- * Order of operations is part of the contract:
230
- * 1. Build the sweep plan from `anchored` + `statusByInjectionId`.
231
- * 2. If non-empty, run the sweep. On failure: log + return early WITHOUT
232
- * calling `deps.updateFocusStage`. This is the "focus does not
233
- * advance" invariant — the failed verify is retried on the next poll
234
- * cycle when the focus is re-evaluated.
235
- * 3. On sweep success (or empty plan), call `deps.updateFocusStage`.
236
- *
237
- * The dispatcher (`dispatchCloseLoopStage`) delegates the entire
238
- * advance_to_done branch to this function so the sweep-failure path is
239
- * unit-testable without DB or process mocking.
240
- */
241
- export async function advanceFocusToDoneWithSweep(focus, anchored, statusByInjectionId, deps) {
242
- const plan = planInjectionSweep(anchored, statusByInjectionId);
243
- if (plan.length > 0) {
244
- const sweepResult = await executeSweep(plan, deps.verify);
245
- if (!sweepResult.ok) {
246
- const { injectionId, error } = sweepResult.failedAt;
247
- log.warn(`[close-loop-dispatcher] Injection sweep FAILED for focus ${focus.focus_id.slice(0, 8)} ` +
248
- `at injection ${injectionId.slice(0, 8)}: ${error.message}. ` +
249
- `${sweepResult.verified.length}/${plan.length} injection(s) verified before failure. ` +
250
- `Holding focus at close_loop -- next poll cycle will retry.`);
251
- return {
252
- advanced: false,
253
- verifiedCount: sweepResult.verified.length,
254
- planSize: plan.length,
255
- sweepFailure: { injectionId, error },
256
- };
257
- }
258
- if (sweepResult.verified.length > 0) {
259
- log.info(`[close-loop-dispatcher] Focus "${focus.focus_name}" -- close-loop sweep verified ` +
260
- `${sweepResult.verified.length} anchored injection(s) before advancing to done`);
261
- }
262
- }
263
- try {
264
- await deps.updateFocusStage(focus.focus_id, 'done');
265
- log.info(`[close-loop-dispatcher] Focus "${focus.focus_name}" -- all anchored injections terminal; ` +
266
- `advancing close_loop -> done`);
267
- return { advanced: true, verifiedCount: plan.length, planSize: plan.length };
268
- }
269
- catch (err) {
270
- log.warn(`[close-loop-dispatcher] Failed to advance focus ${focus.focus_id.slice(0, 8)} to done: ` +
271
- `${err.message}`);
272
- return {
273
- advanced: false,
274
- verifiedCount: plan.length,
275
- planSize: plan.length,
276
- advanceError: err,
277
- };
278
- }
279
- }
280
- /**
281
- * Compose the synthetic close_loop StageDirective. Used by the dispatcher
282
- * to seed the pending spawn directive map; pure for testability.
283
- */
284
- export function buildCloseLoopDirective() {
285
- return {
286
- execution: 'spawn',
287
- compact: null,
288
- assembly: [...CLOSE_LOOP_ASSEMBLY_RECIPE],
289
- tools: null,
290
- prompt: [
291
- 'You are the close-loop bookkeeper for this focus. Run the three',
292
- 'asymmetric checks in order:',
293
- '',
294
- '1. **Per-injection sweep.** For each anchored injection, decide:',
295
- ' verified or escalated. No third option. Use',
296
- ' telora_reality_tree_injection_verify(injectionId, evidence) for',
297
- ' verified; file an `injection_unverified` escalation otherwise.',
298
- '',
299
- '2. **incomplete_planning check.** Walk the focus deliveries and the',
300
- ' git diff. Any delivery that shipped without an anchoring injection,',
301
- ' or any "injection-shaped" residual work the focus did not declare,',
302
- ' gets one `incomplete_planning` escalation per gap.',
303
- '',
304
- '3. **tree_drift check.** Compare residual UDEs in the focus tree to',
305
- ' the focus.description (the implicit apex). Drift gets a `tree_drift`',
306
- ' escalation; in-scope but unresolved UDEs do too. See the',
307
- ' "Tree-Focus Apex Drift Check" section of the role framework for',
308
- ' the procedure.',
309
- '',
310
- 'You do not advance the focus stage. The daemon advances close_loop',
311
- 'to done automatically once every anchored injection is terminal',
312
- '(verified or has an open injection_unverified escalation).',
313
- ].join('\n'),
314
- model: CLOSE_LOOP_MODEL,
315
- };
316
- }
317
- /**
318
- * Compute the close_loop decision for a focus given a snapshot of its
319
- * deliveries and the terminal state of each anchored injection.
320
- *
321
- * Pure -- no DB access. Tests pass snapshots in.
322
- *
323
- * Semantics:
324
- *
325
- * - No anchored injections -> short_circuit_to_done
326
- * - Anchored injections, none yet sweeped -> spawn_bookkeeper
327
- * - All anchored injections terminal -> advance_to_done
328
- * - Some terminal, some not -> hold (waiting on bookkeeper)
329
- *
330
- * The "spawn_bookkeeper" branch is gated on "no sweep has happened yet"
331
- * which the caller communicates via `bookkeeperHasRun`. Without this gate
332
- * every poll cycle would respawn the bookkeeper while it's still working
333
- * (or before a stuck injection's escalation is filed).
334
- */
335
- export function decideCloseLoop(deliveries, injectionStates, bookkeeperHasRun) {
336
- if (shouldShortCircuitToDone(deliveries)) {
337
- return { kind: 'short_circuit_to_done' };
338
- }
339
- if (allInjectionsTerminal(injectionStates)) {
340
- return { kind: 'advance_to_done' };
341
- }
342
- if (!bookkeeperHasRun) {
343
- return { kind: 'spawn_bookkeeper', directive: buildCloseLoopDirective() };
344
- }
345
- const total = injectionStates.length;
346
- const terminal = injectionStates.filter(isInjectionTerminal).length;
347
- return {
348
- kind: 'hold',
349
- reason: `${terminal}/${total} anchored injections terminal (verified or escalated); waiting on bookkeeper`,
350
- };
351
- }
352
- /**
353
- * Re-exported constant set so tests can assert the kind names used by the
354
- * dispatcher in the agent_escalations rows. Keeps the kind string under
355
- * a single source of truth in daemon-core.
356
- */
357
- export const CLOSE_LOOP_ESCALATION_KINDS = {
358
- INJECTION_UNVERIFIED: ESCALATION_KINDS.INJECTION_UNVERIFIED,
359
- TREE_DRIFT: ESCALATION_KINDS.TREE_DRIFT,
360
- INCOMPLETE_PLANNING: ESCALATION_KINDS.INCOMPLETE_PLANNING,
361
- };
362
124
  //# sourceMappingURL=close-loop-dispatcher.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"close-loop-dispatcher.js","sourceRoot":"","sources":["../../src/directive/close-loop-dispatcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"close-loop-dispatcher.js","sourceRoot":"","sources":["../../src/directive/close-loop-dispatcher.ts"],"names":[],"mappings":"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"}