@telora/daemon 0.20.28 → 0.20.53

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 (231) hide show
  1. package/build-info.json +2 -2
  2. package/dist/agent-state.d.ts +4 -6
  3. package/dist/agent-state.d.ts.map +1 -1
  4. package/dist/agent-state.js +4 -10
  5. package/dist/agent-state.js.map +1 -1
  6. package/dist/auto-update.d.ts +87 -0
  7. package/dist/auto-update.d.ts.map +1 -1
  8. package/dist/auto-update.js +142 -8
  9. package/dist/auto-update.js.map +1 -1
  10. package/dist/branch-status.d.ts +25 -3
  11. package/dist/branch-status.d.ts.map +1 -1
  12. package/dist/branch-status.js +130 -59
  13. package/dist/branch-status.js.map +1 -1
  14. package/dist/completion/completion-decision.d.ts +29 -3
  15. package/dist/completion/completion-decision.d.ts.map +1 -1
  16. package/dist/completion/completion-decision.js +15 -3
  17. package/dist/completion/completion-decision.js.map +1 -1
  18. package/dist/completion/event-entry-phases.d.ts +57 -0
  19. package/dist/completion/event-entry-phases.d.ts.map +1 -0
  20. package/dist/completion/event-entry-phases.js +205 -0
  21. package/dist/completion/event-entry-phases.js.map +1 -0
  22. package/dist/completion/event-phases.d.ts +14 -42
  23. package/dist/completion/event-phases.d.ts.map +1 -1
  24. package/dist/completion/event-phases.js +63 -190
  25. package/dist/completion/event-phases.js.map +1 -1
  26. package/dist/completion/event.d.ts +11 -1
  27. package/dist/completion/event.d.ts.map +1 -1
  28. package/dist/completion/event.js +5 -2
  29. package/dist/completion/event.js.map +1 -1
  30. package/dist/completion/index.d.ts +0 -3
  31. package/dist/completion/index.d.ts.map +1 -1
  32. package/dist/completion/index.js +0 -3
  33. package/dist/completion/index.js.map +1 -1
  34. package/dist/completion/review-exit-phase.d.ts +2 -1
  35. package/dist/completion/review-exit-phase.d.ts.map +1 -1
  36. package/dist/completion/review-exit-phase.js +41 -1
  37. package/dist/completion/review-exit-phase.js.map +1 -1
  38. package/dist/completion/status-advance-phase.d.ts +2 -0
  39. package/dist/completion/status-advance-phase.d.ts.map +1 -1
  40. package/dist/completion/status-advance-phase.js +14 -28
  41. package/dist/completion/status-advance-phase.js.map +1 -1
  42. package/dist/completion/team-completion.js +1 -1
  43. package/dist/completion/team-completion.js.map +1 -1
  44. package/dist/completion/terminated-work-reconcile.d.ts.map +1 -1
  45. package/dist/completion/terminated-work-reconcile.js +10 -0
  46. package/dist/completion/terminated-work-reconcile.js.map +1 -1
  47. package/dist/constants.d.ts +0 -8
  48. package/dist/constants.d.ts.map +1 -1
  49. package/dist/constants.js +0 -8
  50. package/dist/constants.js.map +1 -1
  51. package/dist/delivery-close-actions.d.ts +39 -0
  52. package/dist/delivery-close-actions.d.ts.map +1 -0
  53. package/dist/delivery-close-actions.js +53 -0
  54. package/dist/delivery-close-actions.js.map +1 -0
  55. package/dist/delivery-lifecycle.d.ts +11 -0
  56. package/dist/delivery-lifecycle.d.ts.map +1 -1
  57. package/dist/delivery-lifecycle.js +13 -14
  58. package/dist/delivery-lifecycle.js.map +1 -1
  59. package/dist/delivery-reconciler.d.ts +18 -4
  60. package/dist/delivery-reconciler.d.ts.map +1 -1
  61. package/dist/delivery-reconciler.js +18 -4
  62. package/dist/delivery-reconciler.js.map +1 -1
  63. package/dist/directive-executor.d.ts +1 -1
  64. package/dist/directive-executor.js +1 -1
  65. package/dist/discovery-fetch.d.ts +76 -0
  66. package/dist/discovery-fetch.d.ts.map +1 -0
  67. package/dist/discovery-fetch.js +206 -0
  68. package/dist/discovery-fetch.js.map +1 -0
  69. package/dist/discovery-poll.d.ts +1 -51
  70. package/dist/discovery-poll.d.ts.map +1 -1
  71. package/dist/discovery-poll.js +10 -192
  72. package/dist/discovery-poll.js.map +1 -1
  73. package/dist/drain-teardown.d.ts +11 -6
  74. package/dist/drain-teardown.d.ts.map +1 -1
  75. package/dist/drain-teardown.js +3 -2
  76. package/dist/drain-teardown.js.map +1 -1
  77. package/dist/focus-branch-ahead.d.ts +42 -0
  78. package/dist/focus-branch-ahead.d.ts.map +1 -0
  79. package/dist/focus-branch-ahead.js +45 -0
  80. package/dist/focus-branch-ahead.js.map +1 -0
  81. package/dist/focus-engine.d.ts.map +1 -1
  82. package/dist/focus-engine.js +21 -43
  83. package/dist/focus-engine.js.map +1 -1
  84. package/dist/focus-executor.js +2 -2
  85. package/dist/focus-executor.js.map +1 -1
  86. package/dist/focus-lifecycle.d.ts.map +1 -1
  87. package/dist/focus-lifecycle.js +32 -3
  88. package/dist/focus-lifecycle.js.map +1 -1
  89. package/dist/focus-loop-registry.d.ts.map +1 -1
  90. package/dist/focus-loop-registry.js +27 -0
  91. package/dist/focus-loop-registry.js.map +1 -1
  92. package/dist/focus-loop.d.ts +34 -12
  93. package/dist/focus-loop.d.ts.map +1 -1
  94. package/dist/focus-loop.js +78 -15
  95. package/dist/focus-loop.js.map +1 -1
  96. package/dist/focus-merge.d.ts.map +1 -1
  97. package/dist/focus-merge.js +6 -1
  98. package/dist/focus-merge.js.map +1 -1
  99. package/dist/focus-phase.d.ts +18 -3
  100. package/dist/focus-phase.d.ts.map +1 -1
  101. package/dist/focus-phase.js +85 -31
  102. package/dist/focus-phase.js.map +1 -1
  103. package/dist/focus-prompt-builder.d.ts.map +1 -1
  104. package/dist/focus-prompt-builder.js +13 -1
  105. package/dist/focus-prompt-builder.js.map +1 -1
  106. package/dist/focus-provisioning.d.ts.map +1 -1
  107. package/dist/focus-provisioning.js +4 -0
  108. package/dist/focus-provisioning.js.map +1 -1
  109. package/dist/focus-stage-lifecycle/planning-release.d.ts +35 -17
  110. package/dist/focus-stage-lifecycle/planning-release.d.ts.map +1 -1
  111. package/dist/focus-stage-lifecycle/planning-release.js +53 -22
  112. package/dist/focus-stage-lifecycle/planning-release.js.map +1 -1
  113. package/dist/focus-worktree-state.d.ts +17 -6
  114. package/dist/focus-worktree-state.d.ts.map +1 -1
  115. package/dist/focus-worktree-state.js +21 -11
  116. package/dist/focus-worktree-state.js.map +1 -1
  117. package/dist/guard-engine.d.ts +1 -2
  118. package/dist/guard-engine.d.ts.map +1 -1
  119. package/dist/guard-engine.js +1 -2
  120. package/dist/guard-engine.js.map +1 -1
  121. package/dist/health-events.d.ts +10 -0
  122. package/dist/health-events.d.ts.map +1 -0
  123. package/dist/health-events.js +10 -0
  124. package/dist/health-events.js.map +1 -0
  125. package/dist/heartbeat.d.ts.map +1 -1
  126. package/dist/heartbeat.js +98 -21
  127. package/dist/heartbeat.js.map +1 -1
  128. package/dist/host-control/catalog.d.ts.map +1 -1
  129. package/dist/host-control/catalog.js +4 -1
  130. package/dist/host-control/catalog.js.map +1 -1
  131. package/dist/host-control/client.d.ts +3 -4
  132. package/dist/host-control/client.d.ts.map +1 -1
  133. package/dist/host-control/client.js +4 -5
  134. package/dist/host-control/client.js.map +1 -1
  135. package/dist/listener-auto-advance.d.ts +2 -1
  136. package/dist/listener-auto-advance.d.ts.map +1 -1
  137. package/dist/listener-auto-advance.js +36 -40
  138. package/dist/listener-auto-advance.js.map +1 -1
  139. package/dist/listener.d.ts +2 -7
  140. package/dist/listener.d.ts.map +1 -1
  141. package/dist/listener.js +11 -9
  142. package/dist/listener.js.map +1 -1
  143. package/dist/operator-hold.d.ts +66 -0
  144. package/dist/operator-hold.d.ts.map +1 -0
  145. package/dist/operator-hold.js +99 -0
  146. package/dist/operator-hold.js.map +1 -0
  147. package/dist/poll-trigger.d.ts +28 -0
  148. package/dist/poll-trigger.d.ts.map +1 -0
  149. package/dist/poll-trigger.js +31 -0
  150. package/dist/poll-trigger.js.map +1 -0
  151. package/dist/prompt-listing.d.ts +25 -0
  152. package/dist/prompt-listing.d.ts.map +1 -1
  153. package/dist/prompt-listing.js +67 -0
  154. package/dist/prompt-listing.js.map +1 -1
  155. package/dist/prompt-sections/execution-sections.d.ts.map +1 -1
  156. package/dist/prompt-sections/execution-sections.js +24 -0
  157. package/dist/prompt-sections/execution-sections.js.map +1 -1
  158. package/dist/queries/context-lock-queries.d.ts.map +1 -1
  159. package/dist/queries/context-lock-queries.js +4 -1
  160. package/dist/queries/context-lock-queries.js.map +1 -1
  161. package/dist/queries/deliveries.d.ts +17 -0
  162. package/dist/queries/deliveries.d.ts.map +1 -1
  163. package/dist/queries/deliveries.js.map +1 -1
  164. package/dist/queries/issues.d.ts +98 -0
  165. package/dist/queries/issues.d.ts.map +1 -1
  166. package/dist/queries/issues.js +135 -0
  167. package/dist/queries/issues.js.map +1 -1
  168. package/dist/queries/schemas.d.ts +3 -3
  169. package/dist/security-scan-engine.d.ts +9 -1
  170. package/dist/security-scan-engine.d.ts.map +1 -1
  171. package/dist/security-scan-engine.js +25 -2
  172. package/dist/security-scan-engine.js.map +1 -1
  173. package/dist/spawn/worktree-session.d.ts.map +1 -1
  174. package/dist/spawn/worktree-session.js +2 -0
  175. package/dist/spawn/worktree-session.js.map +1 -1
  176. package/dist/spawner/index.d.ts +7 -9
  177. package/dist/spawner/index.d.ts.map +1 -1
  178. package/dist/spawner/index.js +13 -11
  179. package/dist/spawner/index.js.map +1 -1
  180. package/dist/spawner/lifecycle.d.ts +1 -18
  181. package/dist/spawner/lifecycle.d.ts.map +1 -1
  182. package/dist/spawner/lifecycle.js +1 -54
  183. package/dist/spawner/lifecycle.js.map +1 -1
  184. package/dist/spawner/liveness.d.ts +5 -14
  185. package/dist/spawner/liveness.d.ts.map +1 -1
  186. package/dist/spawner/liveness.js +5 -67
  187. package/dist/spawner/liveness.js.map +1 -1
  188. package/dist/spawner/state.d.ts +8 -20
  189. package/dist/spawner/state.d.ts.map +1 -1
  190. package/dist/spawner/state.js +8 -34
  191. package/dist/spawner/state.js.map +1 -1
  192. package/dist/staleness-sensor.d.ts +153 -0
  193. package/dist/staleness-sensor.d.ts.map +1 -0
  194. package/dist/staleness-sensor.js +308 -0
  195. package/dist/staleness-sensor.js.map +1 -0
  196. package/dist/types/focus.d.ts +9 -0
  197. package/dist/types/focus.d.ts.map +1 -1
  198. package/dist/types/session.d.ts +0 -44
  199. package/dist/types/session.d.ts.map +1 -1
  200. package/dist/unified-shell.d.ts.map +1 -1
  201. package/dist/unified-shell.js +19 -0
  202. package/dist/unified-shell.js.map +1 -1
  203. package/dist/verification-engine.d.ts +6 -4
  204. package/dist/verification-engine.d.ts.map +1 -1
  205. package/dist/verification-engine.js +9 -43
  206. package/dist/verification-engine.js.map +1 -1
  207. package/dist/verification-feedback.d.ts +42 -0
  208. package/dist/verification-feedback.d.ts.map +1 -1
  209. package/dist/verification-feedback.js +93 -0
  210. package/dist/verification-feedback.js.map +1 -1
  211. package/dist/version-check.d.ts +6 -0
  212. package/dist/version-check.d.ts.map +1 -1
  213. package/dist/version-check.js +1 -1
  214. package/dist/version-check.js.map +1 -1
  215. package/package.json +2 -3
  216. package/dist/completion/agent-completion.d.ts +0 -48
  217. package/dist/completion/agent-completion.d.ts.map +0 -1
  218. package/dist/completion/agent-completion.js +0 -205
  219. package/dist/completion/agent-completion.js.map +0 -1
  220. package/dist/delivery-guards.d.ts +0 -41
  221. package/dist/delivery-guards.d.ts.map +0 -1
  222. package/dist/delivery-guards.js +0 -200
  223. package/dist/delivery-guards.js.map +0 -1
  224. package/dist/spawner/spawn-team.d.ts +0 -20
  225. package/dist/spawner/spawn-team.d.ts.map +0 -1
  226. package/dist/spawner/spawn-team.js +0 -19
  227. package/dist/spawner/spawn-team.js.map +0 -1
  228. package/dist/spawner/timeout.d.ts +0 -32
  229. package/dist/spawner/timeout.d.ts.map +0 -1
  230. package/dist/spawner/timeout.js +0 -126
  231. package/dist/spawner/timeout.js.map +0 -1
@@ -7,42 +7,67 @@
7
7
  * 3. Each focus worktree vs integration
8
8
  *
9
9
  * Results ride in the heartbeat metadata field (no new tables).
10
+ *
11
+ * Multi-product: computeBranchStatus is called once per configured product
12
+ * with a product-scoped config (configForProduct). The focus worktree map
13
+ * spans all products, so this module scopes it by each entry's productId and
14
+ * runs git against the entry's own repoPath — evaluating a worktree against
15
+ * a repository that does not own it is unrepresentable here. All caches are
16
+ * keyed per product so one product's tick cannot evict another's state.
17
+ *
18
+ * Failure semantics (two distinct kinds, deliberately kept apart):
19
+ * - TRANSIENT git failures (lock contention, mid-rebase, timeouts) fall
20
+ * back to the last good cached status without raising anything — this
21
+ * tolerance predates this module split and prevents UI flicker.
22
+ * - PERMANENT failures (unknown revision, not a git repository, bad
23
+ * object) mean the branch we believe exists cannot be resolved where we
24
+ * looked: an attribution error, not contention. These are surfaced via
25
+ * a healthEvent + error log (once per focus per daemon run) instead of
26
+ * silently rendering identically to "no worktree". A worktree entry in
27
+ * the map IS the claim that its branch should exist; a legitimately
28
+ * deleted branch is removed from the map (removeFocusWorktree) before
29
+ * ever being evaluated here, so ordinary deletions raise no events.
10
30
  */
11
31
  import { runGitSync } from './git/index.js';
12
32
  import { getDefaultBranch } from './git/index.js';
13
33
  import { getAllFocusWorktrees } from './focus-worktree-state.js';
14
34
  import { getActiveTeams } from './focus-team-state.js';
35
+ import { healthEvents } from './health-events.js';
36
+ import { createLogger } from './log.js';
37
+ const log = createLogger({ module: 'branch-status' });
15
38
  /** Short timeout for git commands to avoid blocking the heartbeat. */
16
39
  const BRANCH_STATUS_GIT_TIMEOUT_MS = 5_000;
40
+ const cachesByProduct = new Map();
17
41
  /**
18
- * Cache of last successful integration branch status.
19
- * Reused when a transient git failure (lock contention, mid-rebase)
20
- * prevents computing fresh status, avoiding UI flicker.
21
- */
22
- let lastGoodIntegrationStatus = null;
23
- /**
24
- * Cache of last successful focus branch status per focus ID.
25
- * Reused when a transient git failure (lock contention, mid-rebase)
26
- * prevents computing fresh status, avoiding UI flicker.
42
+ * Focus IDs whose permanent-failure health event has already been emitted
43
+ * this daemon run one event per focus, not one per heartbeat tick.
27
44
  */
28
- const lastGoodFocusStatus = new Map();
29
- /**
30
- * Cache of last successful remote branch status per remote ref.
31
- * Reused when a transient git failure prevents computing fresh status.
32
- */
33
- const lastGoodRemoteStatus = new Map();
34
- /** Reset the cache. Exported for tests only. */
45
+ const permanentFailureEmitted = new Set();
46
+ function cacheForProduct(key) {
47
+ let cache = cachesByProduct.get(key);
48
+ if (!cache) {
49
+ cache = { integration: null, focus: new Map(), remote: new Map() };
50
+ cachesByProduct.set(key, cache);
51
+ }
52
+ return cache;
53
+ }
54
+ /** Reset all caches. Exported for tests only. */
35
55
  export function resetBranchStatusCache() {
36
- lastGoodIntegrationStatus = null;
37
- lastGoodFocusStatus.clear();
38
- lastGoodRemoteStatus.clear();
56
+ cachesByProduct.clear();
57
+ permanentFailureEmitted.clear();
39
58
  }
40
59
  // ── Helpers ──────────────────────────────────────────────────────────
41
60
  const gitOpts = { timeoutMs: BRANCH_STATUS_GIT_TIMEOUT_MS };
61
+ /**
62
+ * Git stderr patterns that mean the ref/repository itself is unresolvable —
63
+ * a permanent condition no retry will fix, as opposed to contention.
64
+ */
65
+ const PERMANENT_GIT_FAILURE_RE = /unknown revision|bad revision|ambiguous argument|not a git repository|bad object|invalid ref/i;
42
66
  /**
43
67
  * Count commits in A that are not in B: `git rev-list --count B..A`.
44
- * Returns null on any failure so callers can distinguish "actually zero"
45
- * from "git was busy" and fall back to cached data.
68
+ * Returns a null count on failure, classified as transient (git was busy —
69
+ * fall back to cached data) or permanent (the ref cannot resolve where we
70
+ * looked — an attribution error to surface, not to swallow).
46
71
  *
47
72
  * @param noMerges - When true, adds `--no-merges` to skip merge commits.
48
73
  * Useful for remote monitors where "Merge main into qa" commits are
@@ -54,24 +79,51 @@ function revListCount(refA, refB, cwd, noMerges) {
54
79
  args.push('--no-merges');
55
80
  args.push(`${refB}..${refA}`);
56
81
  const result = runGitSync(args, cwd, gitOpts);
57
- if (!result.success)
58
- return null;
82
+ if (!result.success) {
83
+ return PERMANENT_GIT_FAILURE_RE.test(result.error)
84
+ ? { count: null, failure: 'permanent', message: result.error }
85
+ : { count: null, failure: 'transient' };
86
+ }
59
87
  const n = parseInt(result.output, 10);
60
- return Number.isNaN(n) ? null : n;
88
+ return Number.isNaN(n) ? { count: null, failure: 'transient' } : { count: n };
89
+ }
90
+ /**
91
+ * Surface a permanent branch-resolution failure for a focus: error log plus
92
+ * a healthEvent (rides in heartbeat metadata), emitted once per focus per
93
+ * daemon run. This is the channel that distinguishes "could not determine"
94
+ * from "no worktree" — the payload entry falls back to cache (or is omitted),
95
+ * but the failure is never silent.
96
+ */
97
+ function surfacePermanentFocusFailure(focusId, branch, repoPath, productId, message) {
98
+ log.error(`Permanent branch-status failure for focus ${focusId}: ` +
99
+ `cannot resolve ${branch} in ${repoPath}: ${message}`);
100
+ if (permanentFailureEmitted.has(focusId))
101
+ return;
102
+ permanentFailureEmitted.add(focusId);
103
+ healthEvents.emit({
104
+ severity: 'warn',
105
+ source: 'branch-status',
106
+ code: 'branch_status.attribution_error',
107
+ message: `Branch ${branch} for focus ${focusId} cannot be resolved in ${repoPath}: ${message}`,
108
+ productId,
109
+ });
61
110
  }
62
111
  // ── Main ─────────────────────────────────────────────────────────────
63
112
  /**
64
- * Compute branch status for all three tiers.
113
+ * Compute branch status for all three tiers of ONE product.
65
114
  *
66
115
  * Safe to call from the heartbeat loop: uses short git timeouts
67
116
  * and catches all errors so a single failure skips that entry
68
117
  * rather than failing the entire heartbeat.
69
118
  *
70
- * @param config - Daemon config (provides repoPath, integrationBranch)
119
+ * @param config - Product-scoped daemon config (configForProduct); provides
120
+ * productId, repoPath, integrationBranch. Only worktrees owned by
121
+ * config.productId are evaluated, each against its own repoPath.
71
122
  * @param options - Optional overrides for mainBranch and branchMonitors from the product record
72
123
  */
73
124
  export function computeBranchStatus(config, options) {
74
- const { repoPath, integrationBranch } = config;
125
+ const { repoPath, integrationBranch, productId } = config;
126
+ const cache = cacheForProduct(productId || repoPath);
75
127
  const mainBranch = options?.mainBranch || getDefaultBranch(repoPath);
76
128
  const monitors = options?.branchMonitors?.length
77
129
  ? options.branchMonitors
@@ -86,31 +138,31 @@ export function computeBranchStatus(config, options) {
86
138
  // not new code. Without this, integration perpetually shows as "ahead".
87
139
  const aheadOfMain = revListCount(integrationBranch, mainBranch, repoPath, true);
88
140
  const behindMain = revListCount(mainBranch, integrationBranch, repoPath);
89
- if (aheadOfMain === null || behindMain === null) {
141
+ if (aheadOfMain.count === null || behindMain.count === null) {
90
142
  // Transient git failure (lock contention, mid-rebase) — use cached status
91
- integration = lastGoodIntegrationStatus;
143
+ integration = cache.integration;
92
144
  }
93
145
  else {
94
146
  let health = 'clean';
95
- if (aheadOfMain > 0 && behindMain > 0) {
147
+ if (aheadOfMain.count > 0 && behindMain.count > 0) {
96
148
  health = 'conflict'; // truly diverged — both directions have commits
97
149
  }
98
- else if (aheadOfMain > 0 || behindMain > 0) {
150
+ else if (aheadOfMain.count > 0 || behindMain.count > 0) {
99
151
  health = 'dirty';
100
152
  }
101
153
  integration = {
102
154
  branch: integrationBranch,
103
155
  health,
104
- aheadOfMain,
105
- behindMain,
156
+ aheadOfMain: aheadOfMain.count,
157
+ behindMain: behindMain.count,
106
158
  };
107
- lastGoodIntegrationStatus = integration;
159
+ cache.integration = integration;
108
160
  }
109
161
  }
110
162
  }
111
163
  catch {
112
164
  // Non-fatal: use cached integration status if available
113
- integration = lastGoodIntegrationStatus;
165
+ integration = cache.integration;
114
166
  }
115
167
  // ── Remote branch monitors ──────────────────────────────────────
116
168
  const remotes = [];
@@ -123,61 +175,78 @@ export function computeBranchStatus(config, options) {
123
175
  const aheadOfMain = revListCount(monitor.ref, mainBranch, repoPath, true);
124
176
  // behindMain: commits in main not in remote (remote is behind)
125
177
  const behindMain = revListCount(mainBranch, monitor.ref, repoPath);
126
- if (aheadOfMain === null || behindMain === null) {
178
+ if (aheadOfMain.count === null || behindMain.count === null) {
127
179
  // Transient git failure — use cached status
128
- const cached = lastGoodRemoteStatus.get(monitor.ref);
180
+ const cached = cache.remote.get(monitor.ref);
129
181
  remotes.push(cached ?? { ref: monitor.ref, label: monitor.label, aheadOfMain: null, behindMain: null });
130
182
  }
131
183
  else {
132
184
  const entry = {
133
185
  ref: monitor.ref,
134
186
  label: monitor.label,
135
- aheadOfMain,
136
- behindMain,
187
+ aheadOfMain: aheadOfMain.count,
188
+ behindMain: behindMain.count,
137
189
  };
138
- lastGoodRemoteStatus.set(monitor.ref, entry);
190
+ cache.remote.set(monitor.ref, entry);
139
191
  remotes.push(entry);
140
192
  }
141
193
  }
142
194
  else {
143
195
  // Ref doesn't exist — use cached if available, otherwise emit grey sentinel
144
- const cached = lastGoodRemoteStatus.get(monitor.ref);
196
+ const cached = cache.remote.get(monitor.ref);
145
197
  remotes.push(cached ?? { ref: monitor.ref, label: monitor.label, aheadOfMain: null, behindMain: null });
146
198
  }
147
199
  }
148
200
  catch {
149
201
  // Non-fatal: use cached status if available, otherwise emit grey sentinel
150
- const cached = lastGoodRemoteStatus.get(monitor.ref);
202
+ const cached = cache.remote.get(monitor.ref);
151
203
  remotes.push(cached ?? { ref: monitor.ref, label: monitor.label, aheadOfMain: null, behindMain: null });
152
204
  }
153
205
  }
154
206
  // Evict remote cache entries for monitors no longer configured
155
207
  const monitorRefs = new Set(monitors.map(m => m.ref));
156
- for (const cachedRef of lastGoodRemoteStatus.keys()) {
208
+ for (const cachedRef of cache.remote.keys()) {
157
209
  if (!monitorRefs.has(cachedRef)) {
158
- lastGoodRemoteStatus.delete(cachedRef);
210
+ cache.remote.delete(cachedRef);
159
211
  }
160
212
  }
161
213
  // ── Focus worktree statuses ───────────────────────────────────
162
214
  const focuses = [];
163
215
  const worktrees = getAllFocusWorktrees();
164
216
  const teams = getActiveTeams();
217
+ const ownFocusIds = new Set();
165
218
  for (const [focusId, info] of worktrees) {
219
+ // The worktree map is cross-product; only evaluate worktrees this
220
+ // product owns, and evaluate them against the entry's OWN repo.
221
+ if (info.productId !== productId)
222
+ continue;
223
+ ownFocusIds.add(focusId);
224
+ const focusRepoPath = info.repoPath || repoPath;
166
225
  try {
167
226
  const headResult = runGitSync(['rev-parse', 'HEAD'], info.worktreePath, gitOpts);
168
227
  if (!headResult.success) {
169
228
  // Transient failure — use cached status if available
170
- const cached = lastGoodFocusStatus.get(focusId);
229
+ const cached = cache.focus.get(focusId);
171
230
  if (cached)
172
231
  focuses.push(cached);
173
232
  continue;
174
233
  }
175
234
  const headSha = headResult.output;
176
- const aheadOfIntegration = revListCount(info.branchName, integrationBranch, repoPath, true);
177
- const behindIntegration = revListCount(integrationBranch, info.branchName, repoPath);
178
- if (aheadOfIntegration === null || behindIntegration === null) {
179
- // Transient git failure on rev-list use cached status
180
- const cached = lastGoodFocusStatus.get(focusId);
235
+ const aheadOfIntegration = revListCount(info.branchName, integrationBranch, focusRepoPath, true);
236
+ const behindIntegration = revListCount(integrationBranch, info.branchName, focusRepoPath);
237
+ if (aheadOfIntegration.count === null || behindIntegration.count === null) {
238
+ const permanent = aheadOfIntegration.failure === 'permanent' ? aheadOfIntegration :
239
+ behindIntegration.failure === 'permanent' ? behindIntegration :
240
+ null;
241
+ if (permanent) {
242
+ // The branch this worktree entry claims exists cannot be resolved
243
+ // in its own repository: an attribution error, not contention.
244
+ surfacePermanentFocusFailure(focusId, info.branchName, focusRepoPath, productId, permanent.message ?? 'unknown git error');
245
+ }
246
+ // Either way, fall back to cached status (transient tolerance for
247
+ // contention; last-known-good rather than a wrong fresh value for
248
+ // permanent failures — the healthEvent above carries the error).
249
+ const cached = cache.focus.get(focusId);
181
250
  if (cached)
182
251
  focuses.push(cached);
183
252
  continue;
@@ -189,7 +258,7 @@ export function computeBranchStatus(config, options) {
189
258
  if (isConflicting) {
190
259
  health = 'conflict';
191
260
  }
192
- else if (aheadOfIntegration > 0) {
261
+ else if (aheadOfIntegration.count > 0) {
193
262
  health = 'dirty';
194
263
  }
195
264
  const entry = {
@@ -197,23 +266,25 @@ export function computeBranchStatus(config, options) {
197
266
  branch: info.branchName,
198
267
  headSha,
199
268
  health,
200
- aheadOfIntegration,
201
- behindIntegration,
269
+ aheadOfIntegration: aheadOfIntegration.count,
270
+ behindIntegration: behindIntegration.count,
202
271
  };
203
- lastGoodFocusStatus.set(focusId, entry);
272
+ cache.focus.set(focusId, entry);
204
273
  focuses.push(entry);
205
274
  }
206
275
  catch {
207
276
  // Transient failure — use cached status if available
208
- const cached = lastGoodFocusStatus.get(focusId);
277
+ const cached = cache.focus.get(focusId);
209
278
  if (cached)
210
279
  focuses.push(cached);
211
280
  }
212
281
  }
213
- // Evict cache entries for worktrees that no longer exist
214
- for (const cachedId of lastGoodFocusStatus.keys()) {
215
- if (!worktrees.has(cachedId)) {
216
- lastGoodFocusStatus.delete(cachedId);
282
+ // Evict cache entries for THIS product's worktrees that no longer exist.
283
+ // (Other products' focuses never enter this cache — it is per-product.)
284
+ for (const cachedId of cache.focus.keys()) {
285
+ if (!ownFocusIds.has(cachedId)) {
286
+ cache.focus.delete(cachedId);
287
+ permanentFailureEmitted.delete(cachedId);
217
288
  }
218
289
  }
219
290
  return { integration, remotes, focuses };
@@ -1 +1 @@
1
- {"version":3,"file":"branch-status.js","sourceRoot":"","sources":["../src/branch-status.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"branch-status.js","sourceRoot":"","sources":["../src/branch-status.ts"],"names":[],"mappings":"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"}
@@ -12,10 +12,16 @@
12
12
  * and terminate
13
13
  * 2. team has NO actionable work -> terminate cleanly (daemon/review-
14
14
  * managed states move the remaining deliveries)
15
- * 3. no-progress counter crossed the limit -> escalate and terminate
16
- * 4. actionable deliveries carry open issues -> mid-focus handoff with
15
+ * 3. team is blocked on an unanswered DIRECTED escalation (needs_intent /
16
+ * needs_clarification) anchored to a delivery it is working -> hold: do
17
+ * NOT escalate, do NOT re-engage. It is waiting on a human, not stalling.
18
+ * This precedes the no-progress and handoff/re-engage branches so a
19
+ * blocked team is never counted as a stall (its own park is the signal a
20
+ * human already sees).
21
+ * 4. no-progress counter crossed the limit -> escalate and terminate
22
+ * 5. actionable deliveries carry open issues -> mid-focus handoff with
17
23
  * the new work
18
- * 5. otherwise (planning deliveries remain) -> re-engagement nudge
24
+ * 6. otherwise (planning deliveries remain) -> re-engagement nudge
19
25
  */
20
26
  /** Facts the decision is made from. All computed post-self-heal-advance. */
21
27
  export interface CompletionDecisionFacts {
@@ -45,6 +51,16 @@ export interface CompletionDecisionFacts {
45
51
  noProgressLimit: number;
46
52
  /** At least one agent-actionable delivery carries an open issue. */
47
53
  hasActionableOpenIssues: boolean;
54
+ /**
55
+ * An agent-actionable delivery the team is working carries an OPEN, unanswered
56
+ * DIRECTED escalation (disposition needs_intent / needs_clarification). The
57
+ * team is blocked on a human answer, not stalling. Computed fail-OPEN: a
58
+ * lookup error resolves to false, so a genuine stall is never masked by a
59
+ * failed check. Only consulted on the teamHasActionableWork path (a team with
60
+ * nothing to do is handled by the terminate branches above, where a block is
61
+ * moot).
62
+ */
63
+ blockedOnDirectedEscalation: boolean;
48
64
  }
49
65
  /** The action handleCompletionEvent executes for this cycle. */
50
66
  export type CompletionAction =
@@ -67,6 +83,16 @@ export type CompletionAction =
67
83
  /** Planning deliveries remain: send a re-engagement nudge to scope them. */
68
84
  | {
69
85
  kind: 'reengage';
86
+ }
87
+ /**
88
+ * Team is blocked on an unanswered directed escalation: hold in place. No
89
+ * escalation filed, no wake message sent, no termination -- the open question
90
+ * is the single signal a human needs, and re-engaging would only burn model
91
+ * spend rediscovering it. The team resumes when the escalation is answered
92
+ * (the answer read-back path re-engages it).
93
+ */
94
+ | {
95
+ kind: 'hold_blocked_on_directed_escalation';
70
96
  };
71
97
  /**
72
98
  * Whether the (async, workflow-fetching) non-advanceability lookup should run
@@ -1 +1 @@
1
- {"version":3,"file":"completion-decision.d.ts","sourceRoot":"","sources":["../../src/completion/completion-decision.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,4EAA4E;AAC5E,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,qBAAqB,EAAE,OAAO,CAAC;IAC/B;;;;;OAKG;IACH,iBAAiB,EAAE,OAAO,CAAC;IAC3B;;;;;OAKG;IACH,sBAAsB,EAAE,OAAO,CAAC;IAChC,wEAAwE;IACxE,gBAAgB,EAAE,MAAM,CAAC;IACzB,yEAAyE;IACzE,eAAe,EAAE,MAAM,CAAC;IACxB,oEAAoE;IACpE,uBAAuB,EAAE,OAAO,CAAC;CAClC;AAED,gEAAgE;AAChE,MAAM,MAAM,gBAAgB;AAC1B,6EAA6E;AAC3E;IAAE,IAAI,EAAE,wCAAwC,CAAA;CAAE;AACpD,0EAA0E;GACxE;IAAE,IAAI,EAAE,8BAA8B,CAAA;CAAE;AAC1C,0EAA0E;GACxE;IAAE,IAAI,EAAE,oCAAoC,CAAA;CAAE;AAChD,qEAAqE;GACnE;IAAE,IAAI,EAAE,kBAAkB,CAAA;CAAE;AAC9B,4EAA4E;GAC1E;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAEzB;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,IAAI,CAAC,uBAAuB,EAAE,uBAAuB,GAAG,mBAAmB,CAAC,GAClF,OAAO,CAET;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,uBAAuB,GAAG,gBAAgB,CAcvF"}
1
+ {"version":3,"file":"completion-decision.d.ts","sourceRoot":"","sources":["../../src/completion/completion-decision.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,4EAA4E;AAC5E,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,qBAAqB,EAAE,OAAO,CAAC;IAC/B;;;;;OAKG;IACH,iBAAiB,EAAE,OAAO,CAAC;IAC3B;;;;;OAKG;IACH,sBAAsB,EAAE,OAAO,CAAC;IAChC,wEAAwE;IACxE,gBAAgB,EAAE,MAAM,CAAC;IACzB,yEAAyE;IACzE,eAAe,EAAE,MAAM,CAAC;IACxB,oEAAoE;IACpE,uBAAuB,EAAE,OAAO,CAAC;IACjC;;;;;;;;OAQG;IACH,2BAA2B,EAAE,OAAO,CAAC;CACtC;AAED,gEAAgE;AAChE,MAAM,MAAM,gBAAgB;AAC1B,6EAA6E;AAC3E;IAAE,IAAI,EAAE,wCAAwC,CAAA;CAAE;AACpD,0EAA0E;GACxE;IAAE,IAAI,EAAE,8BAA8B,CAAA;CAAE;AAC1C,0EAA0E;GACxE;IAAE,IAAI,EAAE,oCAAoC,CAAA;CAAE;AAChD,qEAAqE;GACnE;IAAE,IAAI,EAAE,kBAAkB,CAAA;CAAE;AAC9B,4EAA4E;GAC1E;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE;AACtB;;;;;;GAMG;GACD;IAAE,IAAI,EAAE,qCAAqC,CAAA;CAAE,CAAC;AAEpD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,IAAI,CAAC,uBAAuB,EAAE,uBAAuB,GAAG,mBAAmB,CAAC,GAClF,OAAO,CAET;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,uBAAuB,GAAG,gBAAgB,CAoBvF"}
@@ -12,10 +12,16 @@
12
12
  * and terminate
13
13
  * 2. team has NO actionable work -> terminate cleanly (daemon/review-
14
14
  * managed states move the remaining deliveries)
15
- * 3. no-progress counter crossed the limit -> escalate and terminate
16
- * 4. actionable deliveries carry open issues -> mid-focus handoff with
15
+ * 3. team is blocked on an unanswered DIRECTED escalation (needs_intent /
16
+ * needs_clarification) anchored to a delivery it is working -> hold: do
17
+ * NOT escalate, do NOT re-engage. It is waiting on a human, not stalling.
18
+ * This precedes the no-progress and handoff/re-engage branches so a
19
+ * blocked team is never counted as a stall (its own park is the signal a
20
+ * human already sees).
21
+ * 4. no-progress counter crossed the limit -> escalate and terminate
22
+ * 5. actionable deliveries carry open issues -> mid-focus handoff with
17
23
  * the new work
18
- * 5. otherwise (planning deliveries remain) -> re-engagement nudge
24
+ * 6. otherwise (planning deliveries remain) -> re-engagement nudge
19
25
  */
20
26
  /**
21
27
  * Whether the (async, workflow-fetching) non-advanceability lookup should run
@@ -37,6 +43,12 @@ export function decideCompletionAction(facts) {
37
43
  }
38
44
  return { kind: 'terminate_no_actionable_work' };
39
45
  }
46
+ // A team parked on its own unanswered directed escalation is blocked, not
47
+ // stalled: hold ahead of the no-progress and handoff/re-engage branches so it
48
+ // is neither escalated nor re-engaged while the question is open.
49
+ if (facts.blockedOnDirectedEscalation) {
50
+ return { kind: 'hold_blocked_on_directed_escalation' };
51
+ }
40
52
  if (facts.noProgressCycles >= facts.noProgressLimit) {
41
53
  return { kind: 'escalate_no_progress_and_terminate' };
42
54
  }
@@ -1 +1 @@
1
- {"version":3,"file":"completion-decision.js","sourceRoot":"","sources":["../../src/completion/completion-decision.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AA6CH;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CACvC,KAAmF;IAEnF,OAAO,CAAC,KAAK,CAAC,qBAAqB,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC;AAClE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAA8B;IACnE,IAAI,CAAC,KAAK,CAAC,qBAAqB,EAAE,CAAC;QACjC,IAAI,CAAC,KAAK,CAAC,iBAAiB,IAAI,KAAK,CAAC,sBAAsB,EAAE,CAAC;YAC7D,OAAO,EAAE,IAAI,EAAE,wCAAwC,EAAE,CAAC;QAC5D,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,8BAA8B,EAAE,CAAC;IAClD,CAAC;IACD,IAAI,KAAK,CAAC,gBAAgB,IAAI,KAAK,CAAC,eAAe,EAAE,CAAC;QACpD,OAAO,EAAE,IAAI,EAAE,oCAAoC,EAAE,CAAC;IACxD,CAAC;IACD,IAAI,KAAK,CAAC,uBAAuB,EAAE,CAAC;QAClC,OAAO,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC;IACtC,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;AAC9B,CAAC"}
1
+ {"version":3,"file":"completion-decision.js","sourceRoot":"","sources":["../../src/completion/completion-decision.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AA+DH;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CACvC,KAAmF;IAEnF,OAAO,CAAC,KAAK,CAAC,qBAAqB,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC;AAClE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAA8B;IACnE,IAAI,CAAC,KAAK,CAAC,qBAAqB,EAAE,CAAC;QACjC,IAAI,CAAC,KAAK,CAAC,iBAAiB,IAAI,KAAK,CAAC,sBAAsB,EAAE,CAAC;YAC7D,OAAO,EAAE,IAAI,EAAE,wCAAwC,EAAE,CAAC;QAC5D,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,8BAA8B,EAAE,CAAC;IAClD,CAAC;IACD,0EAA0E;IAC1E,8EAA8E;IAC9E,kEAAkE;IAClE,IAAI,KAAK,CAAC,2BAA2B,EAAE,CAAC;QACtC,OAAO,EAAE,IAAI,EAAE,qCAAqC,EAAE,CAAC;IACzD,CAAC;IACD,IAAI,KAAK,CAAC,gBAAgB,IAAI,KAAK,CAAC,eAAe,EAAE,CAAC;QACpD,OAAO,EAAE,IAAI,EAAE,oCAAoC,EAAE,CAAC;IACxD,CAAC;IACD,IAAI,KAAK,CAAC,uBAAuB,EAAE,CAAC;QAClC,OAAO,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC;IACtC,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Entry phases of the completion-event pipeline -- the three that run BEFORE
3
+ * any factual picture is computed, each able to short-circuit the pipeline:
4
+ *
5
+ * 1. applyPlanningRefresh planning-team delivery discovery / failure
6
+ * 2. routeReviewWindowCompletion review routing (review pass vs coding pass)
7
+ * 3. runWakeCycleSelfHeal pre-guard advanceDeliveryStatuses self-heal
8
+ *
9
+ * Split out of event-phases.ts (which kept phases 4-6: the factual picture,
10
+ * the advancement watchdog, and action side effects) purely to hold both
11
+ * files under the 800-line daemon module limit. Behavior is unchanged: same
12
+ * reads, same order, same log lines, same early returns, and delivery
13
+ * execution_status transition semantics remain owned by the single-writer
14
+ * reconciler.
15
+ */
16
+ import type { FocusDeliveryInfo, FocusIssueInfo } from '../types.js';
17
+ import type { CompletionEventContext, CompletionEventDeps } from './event.js';
18
+ /**
19
+ * Wake-cycle refresh (Option A): planning teams spawn with knownDeliveryIds
20
+ * empty. The MCP-driven planning turn writes deliveries to the DB, so we
21
+ * re-snapshot them here before any downstream merge/completion logic looks
22
+ * at the set. WHY Option A: keeps the refresh on the existing wake path
23
+ * instead of polling, so it runs exactly when new deliveries become visible.
24
+ *
25
+ * Returns true when the team was terminated (planning produced nothing).
26
+ */
27
+ export declare function applyPlanningRefresh(ctx: CompletionEventContext, deps: CompletionEventDeps, currentDeliveries: FocusDeliveryInfo[]): Promise<boolean>;
28
+ export type ReviewWindowOutcome = 'terminated' | 'leave_running' | 'not_in_review';
29
+ /**
30
+ * Review-window handling. Resolves review_requested_at FRESH because it can
31
+ * be set/cleared between spawn and this event.
32
+ *
33
+ * - A completing REVIEW pass routes verify deliveries deterministically
34
+ * (runReviewExitHandler) and terminates -> 'terminated'.
35
+ * - A completing CODING pass during a review window is left alive so the
36
+ * review's own completion closes the focus -> 'leave_running'.
37
+ * - Otherwise -> 'not_in_review' and the pipeline continues.
38
+ */
39
+ export declare function routeReviewWindowCompletion(ctx: CompletionEventContext, deps: CompletionEventDeps, currentDeliveries: FocusDeliveryInfo[]): Promise<ReviewWindowOutcome>;
40
+ /**
41
+ * Self-heal BEFORE the no-progress guard. When actionable deliveries exist
42
+ * but none carry open issues, the team has nothing left to code. The common
43
+ * cause is a review that bounced a delivery to verify_failed while all its
44
+ * issues are already Done. The daemon's transparent
45
+ * verify_failed -> coding -> verify stepping (advanceDeliveryStatuses) clears
46
+ * that. Running it here -- before snapshotting -- means a benign "no work to
47
+ * do" cycle either terminates the team cleanly (all deliveries now terminal)
48
+ * or shows up as real progress (the delivery status moved), instead of being
49
+ * counted as coder no-progress. Either way it can no longer accrue toward a
50
+ * spurious team_failure escalation. (Previously this advance ran only AFTER
51
+ * the guard, so the counter could reach the limit and escalate first.)
52
+ */
53
+ export declare function runWakeCycleSelfHeal(ctx: CompletionEventContext, deps: CompletionEventDeps, currentDeliveries: FocusDeliveryInfo[], currentIssues: FocusIssueInfo[]): Promise<{
54
+ terminated: boolean;
55
+ effectiveDeliveries: FocusDeliveryInfo[];
56
+ }>;
57
+ //# sourceMappingURL=event-entry-phases.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-entry-phases.d.ts","sourceRoot":"","sources":["../../src/completion/event-entry-phases.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAMrE,OAAO,KAAK,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAO9E;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,sBAAsB,EAC3B,IAAI,EAAE,mBAAmB,EACzB,iBAAiB,EAAE,iBAAiB,EAAE,GACrC,OAAO,CAAC,OAAO,CAAC,CA8BlB;AAID,MAAM,MAAM,mBAAmB,GAAG,YAAY,GAAG,eAAe,GAAG,eAAe,CAAC;AAEnF;;;;;;;;;GASG;AACH,wBAAsB,2BAA2B,CAC/C,GAAG,EAAE,sBAAsB,EAC3B,IAAI,EAAE,mBAAmB,EACzB,iBAAiB,EAAE,iBAAiB,EAAE,GACrC,OAAO,CAAC,mBAAmB,CAAC,CA+F9B;AAID;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,sBAAsB,EAC3B,IAAI,EAAE,mBAAmB,EACzB,iBAAiB,EAAE,iBAAiB,EAAE,EACtC,aAAa,EAAE,cAAc,EAAE,GAC9B,OAAO,CAAC;IAAE,UAAU,EAAE,OAAO,CAAC;IAAC,mBAAmB,EAAE,iBAAiB,EAAE,CAAA;CAAE,CAAC,CAiD5E"}