@telora/daemon 0.15.31 → 0.15.33

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 (51) hide show
  1. package/build-info.json +2 -2
  2. package/dist/assembly-resolvers.d.ts.map +1 -1
  3. package/dist/assembly-resolvers.js +170 -2
  4. package/dist/assembly-resolvers.js.map +1 -1
  5. package/dist/close-loop-dispatcher.d.ts +218 -0
  6. package/dist/close-loop-dispatcher.d.ts.map +1 -0
  7. package/dist/close-loop-dispatcher.js +207 -0
  8. package/dist/close-loop-dispatcher.js.map +1 -0
  9. package/dist/directive-executor.d.ts +70 -3
  10. package/dist/directive-executor.d.ts.map +1 -1
  11. package/dist/directive-executor.js +233 -8
  12. package/dist/directive-executor.js.map +1 -1
  13. package/dist/focus-executor.d.ts.map +1 -1
  14. package/dist/focus-executor.js +3 -0
  15. package/dist/focus-executor.js.map +1 -1
  16. package/dist/focus-stage-lifecycle.d.ts +158 -0
  17. package/dist/focus-stage-lifecycle.d.ts.map +1 -0
  18. package/dist/focus-stage-lifecycle.js +293 -0
  19. package/dist/focus-stage-lifecycle.js.map +1 -0
  20. package/dist/heartbeat.d.ts.map +1 -1
  21. package/dist/heartbeat.js +1 -0
  22. package/dist/heartbeat.js.map +1 -1
  23. package/dist/listener.d.ts.map +1 -1
  24. package/dist/listener.js +8 -0
  25. package/dist/listener.js.map +1 -1
  26. package/dist/queries/deliveries.d.ts +14 -0
  27. package/dist/queries/deliveries.d.ts.map +1 -1
  28. package/dist/queries/deliveries.js +2 -0
  29. package/dist/queries/deliveries.js.map +1 -1
  30. package/dist/queries/focuses.d.ts +24 -0
  31. package/dist/queries/focuses.d.ts.map +1 -1
  32. package/dist/queries/focuses.js +35 -0
  33. package/dist/queries/focuses.js.map +1 -1
  34. package/dist/queries/schemas.d.ts +13 -0
  35. package/dist/queries/schemas.d.ts.map +1 -1
  36. package/dist/queries/schemas.js +15 -0
  37. package/dist/queries/schemas.js.map +1 -1
  38. package/dist/queries/shared.d.ts.map +1 -1
  39. package/dist/queries/shared.js +2 -0
  40. package/dist/queries/shared.js.map +1 -1
  41. package/dist/team-prompt-base.d.ts +65 -0
  42. package/dist/team-prompt-base.d.ts.map +1 -1
  43. package/dist/team-prompt-base.js +152 -0
  44. package/dist/team-prompt-base.js.map +1 -1
  45. package/dist/trigger-executor.d.ts +9 -15
  46. package/dist/trigger-executor.d.ts.map +1 -1
  47. package/dist/trigger-executor.js +15 -38
  48. package/dist/trigger-executor.js.map +1 -1
  49. package/dist/types/focus.d.ts +12 -0
  50. package/dist/types/focus.d.ts.map +1 -1
  51. package/package.json +1 -1
@@ -0,0 +1,218 @@
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 type { DaemonConfig, StageDirective } from './types.js';
38
+ import type { FocusDeliveryInfo } from './types.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
+ /**
63
+ * Return the deliveries in the focus that anchor an injection.
64
+ *
65
+ * A delivery anchors an injection when `injection_id` (a column on
66
+ * org_nodes rows of type='delivery', see migration
67
+ * 20260510152110_add_injection_id_to_product_deliveries.sql) points at a
68
+ * reality_tree_nodes row.
69
+ */
70
+ 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
+ /**
115
+ * Compose the synthetic close_loop StageDirective. Used by the dispatcher
116
+ * to seed the pending spawn directive map; pure for testability.
117
+ */
118
+ export declare function buildCloseLoopDirective(): StageDirective;
119
+ /**
120
+ * Query: are there any pending or in_review injection_unverified escalations
121
+ * for the given injection ids? Returns the set of injection ids that have
122
+ * an open escalation.
123
+ *
124
+ * Looks at agent_escalations with:
125
+ * - escalation_kind = 'injection_unverified'
126
+ * - status IN ('pending', 'in_review')
127
+ * - metadata->>'injection_id' IN (...)
128
+ *
129
+ * The dispatcher uses this to classify "escalated" injections as terminal
130
+ * for advancement purposes.
131
+ */
132
+ export interface OpenInjectionEscalationLookup {
133
+ (params: {
134
+ organizationId: string;
135
+ injectionIds: string[];
136
+ }): Promise<Set<string>>;
137
+ }
138
+ /**
139
+ * Top-level result of inspecting a focus for close_loop termination.
140
+ * Tells the caller exactly what to do: short-circuit, spawn, advance to
141
+ * done, or hold.
142
+ */
143
+ export type CloseLoopDecision = {
144
+ kind: 'short_circuit_to_done';
145
+ } | {
146
+ kind: 'spawn_bookkeeper';
147
+ directive: StageDirective;
148
+ } | {
149
+ kind: 'advance_to_done';
150
+ } | {
151
+ kind: 'hold';
152
+ reason: string;
153
+ };
154
+ /**
155
+ * Compute the close_loop decision for a focus given a snapshot of its
156
+ * deliveries and the terminal state of each anchored injection.
157
+ *
158
+ * Pure -- no DB access. Tests pass snapshots in.
159
+ *
160
+ * Semantics:
161
+ *
162
+ * - No anchored injections -> short_circuit_to_done
163
+ * - Anchored injections, none yet sweeped -> spawn_bookkeeper
164
+ * - All anchored injections terminal -> advance_to_done
165
+ * - Some terminal, some not -> hold (waiting on bookkeeper)
166
+ *
167
+ * The "spawn_bookkeeper" branch is gated on "no sweep has happened yet"
168
+ * which the caller communicates via `bookkeeperHasRun`. Without this gate
169
+ * every poll cycle would respawn the bookkeeper while it's still working
170
+ * (or before a stuck injection's escalation is filed).
171
+ */
172
+ export declare function decideCloseLoop(deliveries: FocusDeliveryInfo[], injectionStates: InjectionTerminalState[], bookkeeperHasRun: boolean): CloseLoopDecision;
173
+ /**
174
+ * Sentinel returned by the dispatcher when no action was taken (focus is
175
+ * not in close_loop stage, or already processed this cycle). Caller can
176
+ * log it but should not act on it.
177
+ */
178
+ export interface CloseLoopDispatchOutcome {
179
+ decision: CloseLoopDecision;
180
+ /** Anchored injection ids that were inspected (empty on short-circuit). */
181
+ anchoredInjectionIds: string[];
182
+ }
183
+ /**
184
+ * Re-exported constant set so tests can assert the kind names used by the
185
+ * dispatcher in the agent_escalations rows. Keeps the kind string under
186
+ * a single source of truth in daemon-core.
187
+ */
188
+ export declare const CLOSE_LOOP_ESCALATION_KINDS: {
189
+ readonly INJECTION_UNVERIFIED: "injection_unverified";
190
+ readonly TREE_DRIFT: "tree_drift";
191
+ readonly INCOMPLETE_PLANNING: "incomplete_planning";
192
+ };
193
+ /**
194
+ * Configuration knobs accepted by the dispatcher entry point. Exposed so
195
+ * tests can inject a no-op spawner.
196
+ */
197
+ export interface CloseLoopDispatcherDeps {
198
+ /**
199
+ * Set the pending spawn directive for the focus so the next spawn cycle
200
+ * delivers the close_loop directive. In production this is the export
201
+ * from directive-executor; in tests this is a stub.
202
+ */
203
+ setPendingSpawnDirective: (focusId: string, directive: {
204
+ message: string;
205
+ model: string | null;
206
+ sessionType: 'coding' | 'review';
207
+ contentHash: string;
208
+ }) => void;
209
+ /** Advance the focus stage on product_focuses.stage. */
210
+ updateFocusStage: (focusId: string, stage: string) => Promise<void>;
211
+ /** Lookup open injection_unverified escalations. */
212
+ lookupOpenInjectionEscalations: OpenInjectionEscalationLookup;
213
+ /** Build the directive content (assembly resolution + prompt). */
214
+ assembleDirectiveContent: (config: DaemonConfig, focusId: string, directive: StageDirective, worktreePath: string | null) => Promise<string>;
215
+ /** Compute the content hash for the synthesized directive. */
216
+ computeDirectiveHash: (directive: StageDirective) => string;
217
+ }
218
+ //# sourceMappingURL=close-loop-dispatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"close-loop-dispatcher.d.ts","sourceRoot":"","sources":["../src/close-loop-dispatcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,207 @@
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
+ // ---------------------------------------------------------------------------
39
+ // Constants
40
+ // ---------------------------------------------------------------------------
41
+ /**
42
+ * Model used by close_loop bookkeeper teams. Sonnet because the bookkeeper
43
+ * is a careful, deterministic role (sweep injections, file escalations);
44
+ * Opus would be overkill and slower.
45
+ */
46
+ export const CLOSE_LOOP_MODEL = 'claude-sonnet-4-6';
47
+ /**
48
+ * Assembly recipe for the close_loop stage. Composed in dispatcher when
49
+ * the close_loop directive is synthesized. Persisted nowhere -- the
50
+ * stage's stored `agent_directive` (if any) is ignored in favor of this
51
+ * canonical recipe so the bookkeeper framing is deterministic regardless
52
+ * of how the workflow stage row was seeded.
53
+ */
54
+ export const CLOSE_LOOP_ASSEMBLY_RECIPE = [
55
+ 'loop.persona(variant=close_loop)',
56
+ 'focus.context',
57
+ 'focus.anchoring_injections',
58
+ 'git.diff_against_base',
59
+ 'delivery.acceptance_criteria',
60
+ 'review.outcomes',
61
+ ];
62
+ /**
63
+ * Terminal injection statuses for close_loop. An injection is considered
64
+ * terminal when it is either verified (the bookkeeper called
65
+ * reality_tree_injection_verify) or has an `injection_unverified`
66
+ * escalation filed against it. The first is detected by `injectionStatus`;
67
+ * the second is detected by walking the agent_escalations table -- see
68
+ * `isInjectionEscalated`.
69
+ */
70
+ export const TERMINAL_INJECTION_STATUSES = ['verified'];
71
+ // ---------------------------------------------------------------------------
72
+ // Helpers (pure)
73
+ // ---------------------------------------------------------------------------
74
+ /**
75
+ * Return the deliveries in the focus that anchor an injection.
76
+ *
77
+ * A delivery anchors an injection when `injection_id` (a column on
78
+ * org_nodes rows of type='delivery', see migration
79
+ * 20260510152110_add_injection_id_to_product_deliveries.sql) points at a
80
+ * reality_tree_nodes row.
81
+ */
82
+ export function getAnchoringDeliveries(deliveries) {
83
+ return deliveries.filter((d) => typeof d.injectionId === 'string' && d.injectionId.length > 0);
84
+ }
85
+ /**
86
+ * Pure short-circuit predicate -- "does this focus have any anchoring
87
+ * injections?". If false, close_loop is a no-op and the focus can advance
88
+ * directly to `done`.
89
+ */
90
+ export function shouldShortCircuitToDone(deliveries) {
91
+ return getAnchoringDeliveries(deliveries).length === 0;
92
+ }
93
+ /**
94
+ * Pure classifier. An injection is terminal for close_loop when:
95
+ *
96
+ * - injectionStatus is `verified`, OR
97
+ * - there is an open `injection_unverified` escalation for it
98
+ * (this is the "escalated" outcome -- the bookkeeper filed the
99
+ * escalation and the focus is now blocked on a human).
100
+ *
101
+ * The "open escalation" case keeps the focus at close_loop (status='pending'
102
+ * or 'in_review') -- this function classifies the escalation as terminal
103
+ * for the dispatcher's perspective so the daemon does not loop forever
104
+ * re-spawning the bookkeeper. A human must resolve or dismiss the
105
+ * escalation; once resolved, the bookkeeper can be re-triggered.
106
+ */
107
+ export function isInjectionTerminal(state) {
108
+ if (state.injectionStatus && TERMINAL_INJECTION_STATUSES.includes(state.injectionStatus)) {
109
+ return true;
110
+ }
111
+ if (state.hasOpenUnverifiedEscalation) {
112
+ return true;
113
+ }
114
+ return false;
115
+ }
116
+ /**
117
+ * Pure aggregate predicate -- "are ALL anchored injections terminal?".
118
+ * Returns true on an empty list (the short-circuit branch handles the
119
+ * empty case separately, but this is safe to call after the short-circuit
120
+ * filter).
121
+ */
122
+ export function allInjectionsTerminal(states) {
123
+ return states.every(isInjectionTerminal);
124
+ }
125
+ /**
126
+ * Compose the synthetic close_loop StageDirective. Used by the dispatcher
127
+ * to seed the pending spawn directive map; pure for testability.
128
+ */
129
+ export function buildCloseLoopDirective() {
130
+ return {
131
+ execution: 'spawn',
132
+ compact: null,
133
+ assembly: [...CLOSE_LOOP_ASSEMBLY_RECIPE],
134
+ tools: null,
135
+ prompt: [
136
+ 'You are the close-loop bookkeeper for this focus. Run the three',
137
+ 'asymmetric checks in order:',
138
+ '',
139
+ '1. **Per-injection sweep.** For each anchored injection, decide:',
140
+ ' verified or escalated. No third option. Use',
141
+ ' telora_reality_tree_injection_verify(injectionId, evidence) for',
142
+ ' verified; file an `injection_unverified` escalation otherwise.',
143
+ '',
144
+ '2. **incomplete_planning check.** Walk the focus deliveries and the',
145
+ ' git diff. Any delivery that shipped without an anchoring injection,',
146
+ ' or any "injection-shaped" residual work the focus did not declare,',
147
+ ' gets one `incomplete_planning` escalation per gap.',
148
+ '',
149
+ '3. **tree_drift check.** Compare residual UDEs in the focus tree to',
150
+ ' the focus.description (the implicit apex). Drift gets a `tree_drift`',
151
+ ' escalation; in-scope but unresolved UDEs do too. See the',
152
+ ' "Tree-Focus Apex Drift Check" section of the role framework for',
153
+ ' the procedure.',
154
+ '',
155
+ 'You do not advance the focus stage. The daemon advances close_loop',
156
+ 'to done automatically once every anchored injection is terminal',
157
+ '(verified or has an open injection_unverified escalation).',
158
+ ].join('\n'),
159
+ model: CLOSE_LOOP_MODEL,
160
+ };
161
+ }
162
+ /**
163
+ * Compute the close_loop decision for a focus given a snapshot of its
164
+ * deliveries and the terminal state of each anchored injection.
165
+ *
166
+ * Pure -- no DB access. Tests pass snapshots in.
167
+ *
168
+ * Semantics:
169
+ *
170
+ * - No anchored injections -> short_circuit_to_done
171
+ * - Anchored injections, none yet sweeped -> spawn_bookkeeper
172
+ * - All anchored injections terminal -> advance_to_done
173
+ * - Some terminal, some not -> hold (waiting on bookkeeper)
174
+ *
175
+ * The "spawn_bookkeeper" branch is gated on "no sweep has happened yet"
176
+ * which the caller communicates via `bookkeeperHasRun`. Without this gate
177
+ * every poll cycle would respawn the bookkeeper while it's still working
178
+ * (or before a stuck injection's escalation is filed).
179
+ */
180
+ export function decideCloseLoop(deliveries, injectionStates, bookkeeperHasRun) {
181
+ if (shouldShortCircuitToDone(deliveries)) {
182
+ return { kind: 'short_circuit_to_done' };
183
+ }
184
+ if (allInjectionsTerminal(injectionStates)) {
185
+ return { kind: 'advance_to_done' };
186
+ }
187
+ if (!bookkeeperHasRun) {
188
+ return { kind: 'spawn_bookkeeper', directive: buildCloseLoopDirective() };
189
+ }
190
+ const total = injectionStates.length;
191
+ const terminal = injectionStates.filter(isInjectionTerminal).length;
192
+ return {
193
+ kind: 'hold',
194
+ reason: `${terminal}/${total} anchored injections terminal (verified or escalated); waiting on bookkeeper`,
195
+ };
196
+ }
197
+ /**
198
+ * Re-exported constant set so tests can assert the kind names used by the
199
+ * dispatcher in the agent_escalations rows. Keeps the kind string under
200
+ * a single source of truth in daemon-core.
201
+ */
202
+ export const CLOSE_LOOP_ESCALATION_KINDS = {
203
+ INJECTION_UNVERIFIED: ESCALATION_KINDS.INJECTION_UNVERIFIED,
204
+ TREE_DRIFT: ESCALATION_KINDS.TREE_DRIFT,
205
+ INCOMPLETE_PLANNING: ESCALATION_KINDS.INCOMPLETE_PLANNING,
206
+ };
207
+ //# sourceMappingURL=close-loop-dispatcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"close-loop-dispatcher.js","sourceRoot":"","sources":["../src/close-loop-dispatcher.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,7 @@
8
8
  */
9
9
  import type { DaemonConfig, StageDirective } from './types.js';
10
10
  import './assembly-resolvers.js';
11
+ import { type CloseLoopDecision } from './close-loop-dispatcher.js';
11
12
  import { createEscalation } from './queries/issues.js';
12
13
  /** Seed the last-processed stage for a focus (used on daemon startup). */
13
14
  export declare function seedLastProcessedStage(focusId: string, stageId: string): void;
@@ -83,9 +84,33 @@ export declare function getPendingSpawnFocusIds(): string[];
83
84
  */
84
85
  export declare function assembleDirectiveContent(config: DaemonConfig, focusId: string, directive: StageDirective, worktreePath: string | null): Promise<string>;
85
86
  /**
86
- * Derive the focus's execution phase from its delivery aggregate and
87
- * update product_focuses.current_workflow_stage_id if the derived phase
88
- * differs from what's recorded.
87
+ * Decide which workflow stage name a focus should be in.
88
+ *
89
+ * Pure helper, exported for testing. The selection rule is:
90
+ * 1. If `focus.stage` is one of the new lifecycle stage names
91
+ * (`queued`/`verify`/`review`/`close_loop`/`done`), use it directly.
92
+ * The denormalized stage is the authoritative signal under the new
93
+ * workflow.
94
+ * 2. Otherwise, fall back to the legacy phase derived from the delivery
95
+ * aggregate (kickoff/coding/verifying/reviewing/winding_down/blocked).
96
+ *
97
+ * Note: `review_requested_at` is still read by the legacy derivation for
98
+ * back-compat -- but on the new lifecycle path the `review` stage transition
99
+ * is driven by writes to `product_focuses.stage`, not by writes to
100
+ * `review_requested_at`. This is the Issue 1 contract.
101
+ */
102
+ export declare function resolveFocusStageName(input: {
103
+ focusStage: string | null | undefined;
104
+ deliveries: Array<{
105
+ executionStatus: string | null;
106
+ }>;
107
+ reviewRequestedAt: string | null;
108
+ }): string;
109
+ /**
110
+ * Synchronize `product_focuses.current_workflow_stage_id` with the focus's
111
+ * authoritative stage. The authoritative stage is taken from `focus.stage`
112
+ * when it names one of the new lifecycle stages (Issue 1); otherwise the
113
+ * legacy delivery-aggregate phase derivation applies.
89
114
  *
90
115
  * Returns the stage ID the focus should be in (post-sync). Falls back to
91
116
  * the recorded stage id on error so callers don't have to handle a third
@@ -95,6 +120,12 @@ export declare function syncFocusPhase(focus: {
95
120
  focus_id: string;
96
121
  current_workflow_stage_id: string | null;
97
122
  review_requested_at: string | null;
123
+ /**
124
+ * Denormalized lifecycle stage from product_focuses.stage. Optional for
125
+ * back-compat with old API responses; absence is treated as "fall back to
126
+ * the legacy phase derivation".
127
+ */
128
+ stage?: string | null;
98
129
  }): Promise<string | null>;
99
130
  /**
100
131
  * Result of a bounded-retry attempt to run a directive. The retry is on
@@ -145,6 +176,42 @@ export declare function escalateDirectiveFailure(params: {
145
176
  }, deps?: {
146
177
  createEscalation: typeof createEscalation;
147
178
  }): Promise<void>;
179
+ /** Test helper: clear the bookkeeper-spawned set. */
180
+ export declare function __resetCloseLoopStateForTesting(): void;
181
+ /**
182
+ * Inspect open escalations and return the set of injection ids that have
183
+ * an active `injection_unverified` escalation (status pending or
184
+ * in_review). Used by the close_loop dispatcher to classify "escalated"
185
+ * injections as terminal.
186
+ *
187
+ * The `metadata.injection_id` field is set by the bookkeeper persona when
188
+ * filing the escalation -- see the close_loop directive prompt.
189
+ */
190
+ export declare function getOpenInjectionUnverifiedEscalationIds(): Promise<Set<string>>;
191
+ /**
192
+ * Dispatch the close_loop stage for one focus.
193
+ *
194
+ * Reads the focus's anchored deliveries + injection statuses + open
195
+ * escalations, then runs the pure `decideCloseLoop` to determine whether
196
+ * to short-circuit, spawn a bookkeeper, advance to done, or hold.
197
+ *
198
+ * Returns the decision so the caller (or a test) can log/assert.
199
+ *
200
+ * Idempotent across poll cycles -- the `closeLoopBookkeeperSpawned` set
201
+ * ensures the bookkeeper is spawned at most once per focus visit to
202
+ * close_loop. Tests reset this via `__resetCloseLoopStateForTesting`.
203
+ */
204
+ export declare function dispatchCloseLoopStage(config: DaemonConfig, focus: {
205
+ focus_id: string;
206
+ focus_name: string;
207
+ }): Promise<CloseLoopDecision>;
208
+ /**
209
+ * Pure helper exported for tests: build the close_loop directive and verify
210
+ * it carries the expected assembly + model. The buildCloseLoopDirective
211
+ * function in close-loop-dispatcher.ts already does this; this is a
212
+ * dispatcher-side smoke export so the tests can grep through it.
213
+ */
214
+ export declare function getCloseLoopDirectiveForTesting(): StageDirective;
148
215
  /**
149
216
  * Check all active focuses for stage changes with directives.
150
217
  *
@@ -1 +1 @@
1
- {"version":3,"file":"directive-executor.d.ts","sourceRoot":"","sources":["../src/directive-executor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"directive-executor.d.ts","sourceRoot":"","sources":["../src/directive-executor.ts"],"names":[],"mappings":"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"}