@telora/daemon 0.22.91 → 0.22.97

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 (120) hide show
  1. package/build-info.json +6 -3
  2. package/dist/completion/event-phases.js +5 -5
  3. package/dist/completion/event-phases.js.map +1 -1
  4. package/dist/completion/event.d.ts +7 -0
  5. package/dist/completion/event.d.ts.map +1 -1
  6. package/dist/completion/event.js.map +1 -1
  7. package/dist/completion/review-exit-phase.d.ts.map +1 -1
  8. package/dist/completion/review-exit-phase.js +2 -1
  9. package/dist/completion/review-exit-phase.js.map +1 -1
  10. package/dist/delivery/external-hold.js +1 -1
  11. package/dist/delivery/external-hold.js.map +1 -1
  12. package/dist/delivery/operator-hold.d.ts +14 -0
  13. package/dist/delivery/operator-hold.d.ts.map +1 -1
  14. package/dist/delivery/operator-hold.js +31 -1
  15. package/dist/delivery/operator-hold.js.map +1 -1
  16. package/dist/directive/directive-dispatch.js +2 -2
  17. package/dist/directive/directive-dispatch.js.map +1 -1
  18. package/dist/directive/directive-executor.d.ts.map +1 -1
  19. package/dist/directive/directive-executor.js +2 -1
  20. package/dist/directive/directive-executor.js.map +1 -1
  21. package/dist/directive/directive-verify-hold-gate.d.ts +32 -8
  22. package/dist/directive/directive-verify-hold-gate.d.ts.map +1 -1
  23. package/dist/directive/directive-verify-hold-gate.js +20 -21
  24. package/dist/directive/directive-verify-hold-gate.js.map +1 -1
  25. package/dist/focus/focus-engine.d.ts.map +1 -1
  26. package/dist/focus/focus-engine.js +6 -9
  27. package/dist/focus/focus-engine.js.map +1 -1
  28. package/dist/focus/listener-spawn.d.ts +31 -0
  29. package/dist/focus/listener-spawn.d.ts.map +1 -1
  30. package/dist/focus/listener-spawn.js +44 -22
  31. package/dist/focus/listener-spawn.js.map +1 -1
  32. package/dist/focus/listener.d.ts.map +1 -1
  33. package/dist/focus/listener.js +4 -0
  34. package/dist/focus/listener.js.map +1 -1
  35. package/dist/focus/team-actionable-work.d.ts +76 -20
  36. package/dist/focus/team-actionable-work.d.ts.map +1 -1
  37. package/dist/focus/team-actionable-work.js +85 -20
  38. package/dist/focus/team-actionable-work.js.map +1 -1
  39. package/dist/nexus/incoming.js +1 -1
  40. package/dist/nexus/incoming.js.map +1 -1
  41. package/dist/nexus/pending-returns.d.ts +124 -0
  42. package/dist/nexus/pending-returns.d.ts.map +1 -0
  43. package/dist/nexus/pending-returns.js +194 -0
  44. package/dist/nexus/pending-returns.js.map +1 -0
  45. package/dist/nexus/return-routing.d.ts +89 -0
  46. package/dist/nexus/return-routing.d.ts.map +1 -0
  47. package/dist/nexus/return-routing.js +148 -0
  48. package/dist/nexus/return-routing.js.map +1 -0
  49. package/dist/nexus/return.d.ts +66 -89
  50. package/dist/nexus/return.d.ts.map +1 -1
  51. package/dist/nexus/return.js +116 -279
  52. package/dist/nexus/return.js.map +1 -1
  53. package/dist/prompt/focus-prompt-builder.d.ts.map +1 -1
  54. package/dist/prompt/focus-prompt-builder.js +1 -0
  55. package/dist/prompt/focus-prompt-builder.js.map +1 -1
  56. package/dist/queries/delivery-gate-state.d.ts +23 -0
  57. package/dist/queries/delivery-gate-state.d.ts.map +1 -1
  58. package/dist/queries/delivery-gate-state.js +31 -4
  59. package/dist/queries/delivery-gate-state.js.map +1 -1
  60. package/dist/queries/focus-discovery.d.ts +7 -1
  61. package/dist/queries/focus-discovery.d.ts.map +1 -1
  62. package/dist/queries/focus-discovery.js +9 -3
  63. package/dist/queries/focus-discovery.js.map +1 -1
  64. package/dist/queries/requests.d.ts +51 -3
  65. package/dist/queries/requests.d.ts.map +1 -1
  66. package/dist/queries/requests.js +63 -10
  67. package/dist/queries/requests.js.map +1 -1
  68. package/dist/queries/shared.js +1 -1
  69. package/dist/queries/verification.d.ts.map +1 -1
  70. package/dist/queries/verification.js +1 -0
  71. package/dist/queries/verification.js.map +1 -1
  72. package/dist/spawn/prompt-assembly.js +1 -1
  73. package/dist/spawn/prompt-assembly.js.map +1 -1
  74. package/dist/spawn/respawn-cycle-escalation.d.ts.map +1 -1
  75. package/dist/spawn/respawn-cycle-escalation.js +11 -3
  76. package/dist/spawn/respawn-cycle-escalation.js.map +1 -1
  77. package/dist/spawn/review-hold-park.d.ts +31 -0
  78. package/dist/spawn/review-hold-park.d.ts.map +1 -0
  79. package/dist/spawn/review-hold-park.js +120 -0
  80. package/dist/spawn/review-hold-park.js.map +1 -0
  81. package/dist/spawn/spawn-cooldown.d.ts +27 -4
  82. package/dist/spawn/spawn-cooldown.d.ts.map +1 -1
  83. package/dist/spawn/spawn-cooldown.js +88 -3
  84. package/dist/spawn/spawn-cooldown.js.map +1 -1
  85. package/dist/spawn/spawn-decision.d.ts.map +1 -1
  86. package/dist/spawn/spawn-decision.js +6 -0
  87. package/dist/spawn/spawn-decision.js.map +1 -1
  88. package/dist/types/index.js +1 -1
  89. package/dist/update/auto-update-idle.d.ts.map +1 -1
  90. package/dist/update/auto-update-idle.js +2 -1
  91. package/dist/update/auto-update-idle.js.map +1 -1
  92. package/dist/verify/failure-signature.d.ts.map +1 -1
  93. package/dist/verify/failure-signature.js +1 -0
  94. package/dist/verify/failure-signature.js.map +1 -1
  95. package/dist/verify/verification-checkout.d.ts +58 -0
  96. package/dist/verify/verification-checkout.d.ts.map +1 -0
  97. package/dist/verify/verification-checkout.js +266 -0
  98. package/dist/verify/verification-checkout.js.map +1 -0
  99. package/dist/verify/verification-default-on.d.ts +27 -3
  100. package/dist/verify/verification-default-on.d.ts.map +1 -1
  101. package/dist/verify/verification-default-on.js +98 -5
  102. package/dist/verify/verification-default-on.js.map +1 -1
  103. package/dist/verify/verification-deps.d.ts +11 -0
  104. package/dist/verify/verification-deps.d.ts.map +1 -1
  105. package/dist/verify/verification-deterministic.d.ts +22 -1
  106. package/dist/verify/verification-deterministic.d.ts.map +1 -1
  107. package/dist/verify/verification-deterministic.js +6 -7
  108. package/dist/verify/verification-deterministic.js.map +1 -1
  109. package/dist/verify/verification-engine.d.ts.map +1 -1
  110. package/dist/verify/verification-engine.js +10 -8
  111. package/dist/verify/verification-engine.js.map +1 -1
  112. package/dist/verify/verification-feedback.d.ts +3 -0
  113. package/dist/verify/verification-feedback.d.ts.map +1 -1
  114. package/dist/verify/verification-feedback.js +5 -2
  115. package/dist/verify/verification-feedback.js.map +1 -1
  116. package/dist/worktree/verify-interlock.d.ts +9 -1
  117. package/dist/worktree/verify-interlock.d.ts.map +1 -1
  118. package/dist/worktree/verify-interlock.js +40 -3
  119. package/dist/worktree/verify-interlock.js.map +1 -1
  120. package/package.json +2 -2
@@ -0,0 +1,194 @@
1
+ // PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
2
+ // Pinned by: packages/daemon/src/nexus/nexus-pending-returns-paging.test.ts,
3
+ // packages/daemon/src/nexus/nexus-pending-returns.test.ts,
4
+ // packages/daemon/src/nexus/nexus-return-path-e2e.test.ts,
5
+ // packages/daemon/src/nexus/nexus-return-routing.test.ts,
6
+ // packages/daemon/src/spawn/build-spawn-prompt.test.ts
7
+ // PINNED-BY-END
8
+ /**
9
+ * Nexus pending returns on the REQUESTING focus: what that focus is waiting on
10
+ * across products, and what came back.
11
+ *
12
+ * A pending return (product_request_pending_returns) is one return -- a
13
+ * discovery, question or findings entry the requested team sent, or the
14
+ * request's close / decline -- carried on the requesting focus until the
15
+ * requesting team acknowledges it. This module owns the READ + RENDER half:
16
+ *
17
+ * - resolveNexusReturnsSection: loads the focus's unacknowledged returns and
18
+ * the open outgoing requests the focus waits on (filed from the focus OR
19
+ * from one of its deliveries), and renders ONE prompt section with every
20
+ * return's FULL content (never truncated). The spawn path folds it into the
21
+ * carried section every pass receives -- fresh coding, scoping, resume and
22
+ * review -- so no pass on the focus misses a return.
23
+ * - buildNexusReturnHandOff: the message handed to a LIVE team when a new
24
+ * return arrives mid-session (nexus/return-routing.ts decides when).
25
+ *
26
+ * Leaf module: imports only query helpers, never the return / routing passes,
27
+ * so both the spawn path and the poll pass can import it without a cycle.
28
+ */
29
+ import { callApi } from '../queries/shared.js';
30
+ import { listAllOutgoingRequests } from '../queries/requests.js';
31
+ import { createLogger } from '../shell/log.js';
32
+ const log = createLogger({ module: 'nexus/pending-returns' });
33
+ /** Rows per pending-return page (the product-api's max `limit`). */
34
+ export const PENDING_RETURNS_PAGE_SIZE = 500;
35
+ /**
36
+ * Read EVERY pending return matching the filter, oldest first. One list call
37
+ * serves at most a page, so a burst larger than a page would otherwise leave
38
+ * returns out of a prompt or out of an engagement pass. Walks the keyset cursor
39
+ * (the last row's createdAt + id) until a page comes back shorter than the limit
40
+ * the server applied (it echoes `limit`), so an earlier return acknowledged
41
+ * mid-walk never shifts a later one out of the read and a server cap below the
42
+ * requested page never ends the walk early. A full page that does not advance
43
+ * the cursor THROWS (no partial list read as complete). THROWS on a hard API
44
+ * error. `deps.callApi` is the test seam.
45
+ */
46
+ export async function listAllPendingReturns(filter, deps = {}) {
47
+ const call = deps.callApi ?? callApi;
48
+ const all = [];
49
+ let cursor = null;
50
+ for (;;) {
51
+ const params = { ...filter, limit: PENDING_RETURNS_PAGE_SIZE, ...(cursor ?? {}) };
52
+ const res = await call('product_request_list_pending_returns', params);
53
+ const rows = res.pendingReturns ?? [];
54
+ all.push(...rows);
55
+ const served = typeof res.limit === 'number' && res.limit > 0 ? Math.min(res.limit, PENDING_RETURNS_PAGE_SIZE) : PENDING_RETURNS_PAGE_SIZE;
56
+ if (rows.length < served)
57
+ return all;
58
+ const last = rows[rows.length - 1];
59
+ if (cursor && cursor.afterCreatedAt === last.createdAt && cursor.afterId === last.id) {
60
+ throw new Error(`listAllPendingReturns: the page after ${last.id} did not advance; refusing a partial read`);
61
+ }
62
+ cursor = { afterCreatedAt: last.createdAt, afterId: last.id };
63
+ }
64
+ }
65
+ /**
66
+ * Request statuses in which an outgoing request is still open: the requesting
67
+ * work waits on it. Single definition shared with the source-delivery gate
68
+ * (nexus/return.ts).
69
+ */
70
+ export const WAITING_REQUEST_STATUSES = new Set(['open', 'accepted', 'in_progress', 'delivered']);
71
+ /**
72
+ * Pure: the open outgoing requests a focus waits on -- filed from the focus
73
+ * itself (with or without a source delivery) or from one of its deliveries.
74
+ */
75
+ export function selectWaitingOnRequests(outgoing, focusId, deliveryIds) {
76
+ return outgoing.filter((r) => {
77
+ if (!r.status || !WAITING_REQUEST_STATUSES.has(r.status))
78
+ return false;
79
+ if (r.sourceFocusId === focusId)
80
+ return true;
81
+ return !!r.sourceDeliveryId && deliveryIds.has(r.sourceDeliveryId);
82
+ });
83
+ }
84
+ /** The acknowledge instruction, shared by the spawn section and the live hand-off. */
85
+ function acknowledgeInstructionLines() {
86
+ return [
87
+ 'For each return:',
88
+ '1. Act on it in this pass. Fold a discovery or findings into your plan. Answer a question by',
89
+ ' updating the request or filing a follow-up request. A CLOSED request releases the work that',
90
+ ' waited on it. A DECLINED request hands that work back to you to re-plan: re-scope the waiting',
91
+ ' delivery, or file a different request.',
92
+ '2. Acknowledge it once handled: `telora_product_request` (action: "acknowledge_return",',
93
+ ' pendingReturnId: "<id>", note: "<what you did>"). An acknowledged return stops appearing in',
94
+ ' your prompts and never re-engages this focus.',
95
+ ];
96
+ }
97
+ /** Pure: one return rendered in full (its content is never truncated). */
98
+ export function renderPendingReturnBlock(ret) {
99
+ const title = ret.requestTitle ? `"${ret.requestTitle}"` : `request ${ret.requestId}`;
100
+ const anchor = ret.sourceDeliveryId ? ` (for delivery ${ret.sourceDeliveryId})` : '';
101
+ return [
102
+ `#### [${ret.returnKind}] ${title}${anchor} -- ${ret.createdAt}`,
103
+ `pendingReturnId: ${ret.id}`,
104
+ '',
105
+ ret.content,
106
+ '',
107
+ ];
108
+ }
109
+ /**
110
+ * Pure: the Nexus section for a focus's prompt. Empty (no lines) when the focus
111
+ * waits on nothing and has no pending return.
112
+ */
113
+ export function buildNexusReturnsSection(args) {
114
+ const { waitingOn, pendingReturns } = args;
115
+ if (waitingOn.length === 0 && pendingReturns.length === 0)
116
+ return '';
117
+ const lines = ['## Nexus: cross-product requests this focus waits on, and what came back', ''];
118
+ if (waitingOn.length > 0) {
119
+ lines.push('### Waiting on another product', '', 'This focus filed these requests and they are still open, so the work that asked for them is', 'waiting on another product\'s team. Do not build around the dependency. Plan the work that does', 'not need it, and act on the returns below as they arrive.', '');
120
+ for (const r of waitingOn) {
121
+ const origin = r.sourceDeliveryId ? `filed by delivery ${r.sourceDeliveryId}` : 'filed by this focus';
122
+ lines.push(`- "${r.title ?? r.id}" (request ${r.id}, status: ${r.status ?? 'unknown'}; ${origin})`);
123
+ }
124
+ lines.push('');
125
+ }
126
+ if (pendingReturns.length > 0) {
127
+ lines.push('### Returns pending your acknowledgement', '', 'The requested products sent these back on this focus\'s requests, or the request closed or was', 'declined. Each is kept here, in full, in every pass on this focus until you acknowledge it.', '', ...acknowledgeInstructionLines(), '');
128
+ for (const ret of pendingReturns)
129
+ lines.push(...renderPendingReturnBlock(ret));
130
+ }
131
+ return lines.join('\n').trimEnd();
132
+ }
133
+ /** Pure: the message handed to a live team when new returns arrive mid-session. */
134
+ export function buildNexusReturnHandOff(returns) {
135
+ const lines = [
136
+ '## Nexus return arrived while you are working',
137
+ '',
138
+ `${returns.length} new return(s) arrived on this focus's cross-product request(s).`,
139
+ '',
140
+ ...acknowledgeInstructionLines(),
141
+ '',
142
+ ];
143
+ for (const ret of returns)
144
+ lines.push(...renderPendingReturnBlock(ret));
145
+ return lines.join('\n').trimEnd();
146
+ }
147
+ /** The production reads over a product-api client (`apiDeps.callApi` is the test seam). */
148
+ export function nexusReturnsSectionDeps(apiDeps = {}) {
149
+ return {
150
+ listFocusPendingReturns: (focusId) => listAllPendingReturns({ focusId }, apiDeps),
151
+ listOutgoing: (productId) => listAllOutgoingRequests(productId, apiDeps),
152
+ };
153
+ }
154
+ export const defaultNexusReturnsSectionDeps = nexusReturnsSectionDeps();
155
+ /**
156
+ * Load + render the focus's Nexus section. Best-effort: each read degrades to
157
+ * empty on failure (logged) and never blocks a spawn.
158
+ */
159
+ export async function resolveNexusReturnsSection(args, deps = defaultNexusReturnsSectionDeps) {
160
+ const { focusId, productId, deliveryIds } = args;
161
+ const [returnsResult, outgoingResult] = await Promise.allSettled([
162
+ deps.listFocusPendingReturns(focusId),
163
+ productId ? deps.listOutgoing(productId) : Promise.resolve([]),
164
+ ]);
165
+ if (returnsResult.status === 'rejected') {
166
+ log.warn(`nexus pending returns read failed for focus ${focusId.slice(0, 8)}: ${returnsResult.reason.message}`);
167
+ }
168
+ if (outgoingResult.status === 'rejected') {
169
+ log.warn(`nexus outgoing requests read failed for focus ${focusId.slice(0, 8)}: ${outgoingResult.reason.message}`);
170
+ }
171
+ const pendingReturns = returnsResult.status === 'fulfilled' ? returnsResult.value : [];
172
+ const outgoing = outgoingResult.status === 'fulfilled' ? outgoingResult.value : [];
173
+ return buildNexusReturnsSection({
174
+ waitingOn: selectWaitingOnRequests(outgoing, focusId, new Set(deliveryIds)),
175
+ pendingReturns,
176
+ });
177
+ }
178
+ /**
179
+ * Fold the focus's Nexus section into the section every spawn shape carries
180
+ * (the answered-escalations carrier: appended to fresh directive + legacy
181
+ * prompts, the scoping message and the resume delta, for coding AND review
182
+ * passes). Ids are untouched: they name escalations to consume, not returns --
183
+ * a return is consumed only by the team's acknowledgement.
184
+ */
185
+ export async function foldNexusReturnsSection(carried, args, deps = defaultNexusReturnsSectionDeps) {
186
+ const nexusSection = await resolveNexusReturnsSection(args, deps);
187
+ if (!nexusSection)
188
+ return carried;
189
+ return {
190
+ ids: carried.ids,
191
+ section: [carried.section, nexusSection].filter((s) => s.trim()).join('\n\n'),
192
+ };
193
+ }
194
+ //# sourceMappingURL=pending-returns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pending-returns.js","sourceRoot":"","sources":["../../src/nexus/pending-returns.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Nexus return routing: every return reaches the REQUESTING focus within one
3
+ * poll, whatever pass that focus is in, and engages it at most once.
4
+ *
5
+ * Runs per product in the poll loop (listener runNexusPasses), right after the
6
+ * resolve pass so a close decided this tick routes this tick, and BEFORE the
7
+ * spawn pass so a re-armed focus spawns the same tick.
8
+ *
9
+ * 1. ROUTE -- product_request_route_returns materializes every not-yet-routed
10
+ * return of the product's outgoing requests (new entries, closes, declines)
11
+ * into pending returns on the requesting focus. Set-based over EVERY
12
+ * outgoing request, idempotent by dedupe key, so it is safe each tick and no
13
+ * request's end goes unread however many requests the product has.
14
+ * 2. ENGAGE -- each not-yet-engaged return is engaged ONCE, by focus state:
15
+ * live team -> 'handed': the return is written to the lead's stdin
16
+ * now, without waiting for a respawn;
17
+ * armed, no team -> 'rearmed': the focus's re-arm signal is set (the
18
+ * escalation-answer path), so it spawns once for it
19
+ * even with no actionable delivery;
20
+ * un-armed -> left pending: visible on the focus, no spawn. It is
21
+ * engaged if and when the focus is armed.
22
+ * A stamp is written only once its engagement is PROVEN, so no return is
23
+ * ever marked engaged with nothing carrying it:
24
+ * handed -- the hand-off is written to stdin FIRST; only a landed write
25
+ * is stamped. A write that did not land stamps nothing and is
26
+ * retried next poll; a stamp that fails after a landed write
27
+ * re-hands next poll (at-least-once to a live team, never lost).
28
+ * rearmed -- the stamp and the re-arm signal are one transaction
29
+ * (engage_product_request_returns): no signal, no stamp. It
30
+ * writes a fresh signal value per engaged batch, and the spawn
31
+ * side clears only the value it spawned for, so a batch engaged
32
+ * after a spawn rendered its prompt gets its own spawn.
33
+ * Every unengaged return is read (paged) and engaged in batches of at most
34
+ * ENGAGE_BATCH_SIZE, so a burst of any size is engaged in one poll. A stamp
35
+ * covers only returns not already engaged or acknowledged, so one return is
36
+ * handed / re-arms at most once -- the billed-respawn-loop hazard cannot form
37
+ * around an unconsumed input.
38
+ *
39
+ * Every pass that spawns on the focus renders the unacknowledged returns in full
40
+ * (nexus/pending-returns.ts), and the requesting team's acknowledgement
41
+ * (telora_product_request acknowledge_return) is the durable consumed state.
42
+ *
43
+ * This replaces the nexus_request_resolved / nexus_clarification_requested
44
+ * escalations the return path used to file: those reached an agent only inside a
45
+ * coding spawn, truncated findings to the escalation cap, and spawned nothing.
46
+ */
47
+ import type { Writable } from 'node:stream';
48
+ import type { DaemonConfig } from '../types/index.js';
49
+ import { type CallApiDeps } from '../queries/shared.js';
50
+ import { type PendingReturn } from './pending-returns.js';
51
+ /** Ids per engage call (the product-api's per-call cap). */
52
+ export declare const ENGAGE_BATCH_SIZE = 200;
53
+ /** How a not-yet-engaged return is engaged this tick. */
54
+ export type ReturnEngagementDecision = 'handed' | 'rearmed' | 'leave_pending';
55
+ /** Pure: the engagement a return gets from its requesting focus's state. */
56
+ export declare function decideReturnEngagement(state: {
57
+ hasLiveTeam: boolean;
58
+ armed: boolean;
59
+ }): ReturnEngagementDecision;
60
+ /** Pure: group returns by requesting focus; a return with no focus has no team to engage. */
61
+ export declare function groupReturnsByFocus(returns: readonly PendingReturn[]): Map<string, PendingReturn[]>;
62
+ export interface NexusReturnRoutingDeps {
63
+ /** Route the product's not-yet-routed returns; returns how many were created. */
64
+ routeReturns: (productId: string) => Promise<number>;
65
+ /** The product's pending returns no team has been engaged for yet. */
66
+ listUnengagedReturns: (productId: string) => Promise<PendingReturn[]>;
67
+ /** focusId -> armed (active + assigned agent role), for the product's active focuses. */
68
+ listFocusArmState: (productId: string) => Promise<Map<string, boolean>>;
69
+ /** The live team lead's stdin for a focus, or null when no team is live. */
70
+ getLiveTeamStdin: (focusId: string) => Writable | null;
71
+ /** Stamp returns engaged (only not-yet-engaged ones); returns the ids actually stamped. */
72
+ engageReturns: (focusId: string, pendingReturnIds: string[], engagement: 'handed' | 'rearmed') => Promise<string[]>;
73
+ /** Write a message to a live team's stdin; false when the write did not land. */
74
+ handToLiveTeam: (focusId: string, stdin: Writable, message: string) => boolean;
75
+ log?: (msg: string) => void;
76
+ }
77
+ /**
78
+ * The production deps. `apiDeps.callApi` replaces the product-api client for
79
+ * every API-backed dep (route, list, engage), so an end-to-end test drives this
80
+ * exact wiring over one shared fake API.
81
+ */
82
+ export declare function defaultNexusReturnRoutingDeps(apiDeps?: CallApiDeps): NexusReturnRoutingDeps;
83
+ /**
84
+ * Poll one product: route its returns, then engage each requesting focus once.
85
+ * Best-effort throughout: a route failure still engages already-routed returns,
86
+ * and one focus's failure never aborts the others.
87
+ */
88
+ export declare function routeNexusReturns(config: DaemonConfig, deps?: NexusReturnRoutingDeps): Promise<void>;
89
+ //# sourceMappingURL=return-routing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"return-routing.d.ts","sourceRoot":"","sources":["../../src/nexus/return-routing.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAW,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAIjE,OAAO,EAAkD,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAK1G,4DAA4D;AAC5D,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC,yDAAyD;AACzD,MAAM,MAAM,wBAAwB,GAAG,QAAQ,GAAG,SAAS,GAAG,eAAe,CAAC;AAE9E,4EAA4E;AAC5E,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAAE,WAAW,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,wBAAwB,CAIhH;AAED,6FAA6F;AAC7F,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC,CASnG;AAED,MAAM,WAAW,sBAAsB;IACrC,iFAAiF;IACjF,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,sEAAsE;IACtE,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IACtE,yFAAyF;IACzF,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACxE,4EAA4E;IAC5E,gBAAgB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,QAAQ,GAAG,IAAI,CAAC;IACvD,2FAA2F;IAC3F,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,QAAQ,GAAG,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACpH,iFAAiF;IACjF,cAAc,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAC/E,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,GAAE,WAAgB,GAAG,sBAAsB,CA4B/F;AA4CD;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,YAAY,EACpB,IAAI,GAAE,sBAAwD,GAC7D,OAAO,CAAC,IAAI,CAAC,CAqCf"}
@@ -0,0 +1,148 @@
1
+ // PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
2
+ // Pinned by: packages/daemon/src/nexus/nexus-return-path-e2e.test.ts,
3
+ // packages/daemon/src/nexus/nexus-return-routing.test.ts
4
+ // PINNED-BY-END
5
+ import { sendMessage } from '@telora/daemon-core';
6
+ import { callApi } from '../queries/shared.js';
7
+ import { getActiveFocuses } from '../queries/focus-discovery.js';
8
+ import { getActiveTeams } from '../focus/focus-team-state.js';
9
+ import { recordStdinMessageSent } from '../completion/stdin-turn-tracker.js';
10
+ import { buildNexusReturnHandOff, listAllPendingReturns } from './pending-returns.js';
11
+ import { createLogger } from '../shell/log.js';
12
+ const dlog = createLogger({ module: 'nexus/return-routing' });
13
+ /** Ids per engage call (the product-api's per-call cap). */
14
+ export const ENGAGE_BATCH_SIZE = 200;
15
+ /** Pure: the engagement a return gets from its requesting focus's state. */
16
+ export function decideReturnEngagement(state) {
17
+ if (state.hasLiveTeam)
18
+ return 'handed';
19
+ if (state.armed)
20
+ return 'rearmed';
21
+ return 'leave_pending';
22
+ }
23
+ /** Pure: group returns by requesting focus; a return with no focus has no team to engage. */
24
+ export function groupReturnsByFocus(returns) {
25
+ const byFocus = new Map();
26
+ for (const ret of returns) {
27
+ if (!ret.sourceFocusId)
28
+ continue;
29
+ const list = byFocus.get(ret.sourceFocusId);
30
+ if (list)
31
+ list.push(ret);
32
+ else
33
+ byFocus.set(ret.sourceFocusId, [ret]);
34
+ }
35
+ return byFocus;
36
+ }
37
+ /**
38
+ * The production deps. `apiDeps.callApi` replaces the product-api client for
39
+ * every API-backed dep (route, list, engage), so an end-to-end test drives this
40
+ * exact wiring over one shared fake API.
41
+ */
42
+ export function defaultNexusReturnRoutingDeps(apiDeps = {}) {
43
+ const call = apiDeps.callApi ?? callApi;
44
+ return {
45
+ routeReturns: async (productId) => {
46
+ const res = await call('product_request_route_returns', { productId });
47
+ return res.routed ?? 0;
48
+ },
49
+ listUnengagedReturns: (productId) => listAllPendingReturns({ productId, unengagedOnly: true }, apiDeps),
50
+ listFocusArmState: async (productId) => {
51
+ const focuses = await getActiveFocuses('', productId);
52
+ return new Map(focuses.map((f) => [f.focus_id, f.status === 'active' && !!f.assigned_agent_role_id]));
53
+ },
54
+ getLiveTeamStdin: (focusId) => getActiveTeams().get(focusId)?.leadStdin ?? null,
55
+ engageReturns: async (focusId, pendingReturnIds, engagement) => {
56
+ const res = await call('product_request_engage_returns', {
57
+ focusId,
58
+ pendingReturnIds,
59
+ engagement,
60
+ });
61
+ return res.engagedIds ?? [];
62
+ },
63
+ handToLiveTeam: (focusId, stdin, message) => {
64
+ const sent = sendMessage(stdin, message);
65
+ if (sent)
66
+ recordStdinMessageSent(focusId);
67
+ return sent;
68
+ },
69
+ log: (msg) => dlog.info(msg),
70
+ };
71
+ }
72
+ /** Stamp ids in batches the engage call accepts; returns every id actually stamped. */
73
+ async function engageInBatches(focusId, ids, engagement, deps) {
74
+ const stamped = [];
75
+ for (let i = 0; i < ids.length; i += ENGAGE_BATCH_SIZE) {
76
+ stamped.push(...(await deps.engageReturns(focusId, ids.slice(i, i + ENGAGE_BATCH_SIZE), engagement)));
77
+ }
78
+ return stamped;
79
+ }
80
+ /** Engage one focus's not-yet-engaged returns per its state; a stamp follows proof. */
81
+ async function engageFocusReturns(focusId, returns, armed, deps, log) {
82
+ const stdin = deps.getLiveTeamStdin(focusId);
83
+ const decision = decideReturnEngagement({ hasLiveTeam: stdin !== null, armed });
84
+ if (decision === 'leave_pending')
85
+ return;
86
+ const ids = returns.map((r) => r.id);
87
+ if (decision === 'rearmed') {
88
+ const engagedIds = await engageInBatches(focusId, ids, 'rearmed', deps);
89
+ if (engagedIds.length > 0) {
90
+ log(`[nexus] re-armed focus ${focusId.slice(0, 8)} for ${engagedIds.length} pending return(s)`);
91
+ }
92
+ return;
93
+ }
94
+ const landed = stdin !== null && deps.handToLiveTeam(focusId, stdin, buildNexusReturnHandOff(returns));
95
+ if (!landed) {
96
+ log(`[nexus] live hand-off to focus ${focusId.slice(0, 8)} did not land; ${ids.length} return(s) stay unengaged and are retried next poll`);
97
+ return;
98
+ }
99
+ const engagedIds = await engageInBatches(focusId, ids, 'handed', deps);
100
+ log(`[nexus] handed ${ids.length} pending return(s) to the live team on focus ${focusId.slice(0, 8)} (${engagedIds.length} stamped)`);
101
+ }
102
+ /**
103
+ * Poll one product: route its returns, then engage each requesting focus once.
104
+ * Best-effort throughout: a route failure still engages already-routed returns,
105
+ * and one focus's failure never aborts the others.
106
+ */
107
+ export async function routeNexusReturns(config, deps = defaultNexusReturnRoutingDeps()) {
108
+ const productId = config.productId;
109
+ if (!productId)
110
+ return;
111
+ const log = deps.log ?? ((msg) => dlog.info(msg));
112
+ try {
113
+ const routed = await deps.routeReturns(productId);
114
+ if (routed > 0)
115
+ log(`[nexus] routed ${routed} new return(s) to requesting focuses for ${productId}`);
116
+ }
117
+ catch (err) {
118
+ log(`[nexus] failed to route returns for ${productId}: ${err.message}`);
119
+ }
120
+ let unengaged = [];
121
+ try {
122
+ unengaged = await deps.listUnengagedReturns(productId);
123
+ }
124
+ catch (err) {
125
+ log(`[nexus] failed to list unengaged returns for ${productId}: ${err.message}`);
126
+ return;
127
+ }
128
+ const byFocus = groupReturnsByFocus(unengaged);
129
+ if (byFocus.size === 0)
130
+ return;
131
+ let armState = new Map();
132
+ try {
133
+ armState = await deps.listFocusArmState(productId);
134
+ }
135
+ catch (err) {
136
+ // Unknown arm state: a live team is still handed its returns; nothing re-arms.
137
+ log(`[nexus] failed to read focus arm state for ${productId}: ${err.message}`);
138
+ }
139
+ for (const [focusId, returns] of byFocus) {
140
+ try {
141
+ await engageFocusReturns(focusId, returns, armState.get(focusId) === true, deps, log);
142
+ }
143
+ catch (err) {
144
+ log(`[nexus] failed to engage returns on focus ${focusId.slice(0, 8)}: ${err.message}`);
145
+ }
146
+ }
147
+ }
148
+ //# sourceMappingURL=return-routing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"return-routing.js","sourceRoot":"","sources":["../../src/nexus/return-routing.ts"],"names":[],"mappings":"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"}