crewly 1.8.5 → 1.8.6

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orc-delivery-enforcer.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/orc/orc-delivery-enforcer.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AAgBH;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,cAAc,CAAC;IACpB,wFAAwF;IACxF,cAAc,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,cAAc,EAAE,MAAM,CAAC;IACvB,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,MAAM,EAAE;IAC1C,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACd,KAAK,IAAI,CAAC;AAEX,MAAM,WAAW,0BAA0B;IACzC,2EAA2E;IAC3E,YAAY,EAAE,oBAAoB,CAAC;IACnC,mCAAmC;IACnC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,qBAAa,0BAA0B;IACrC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA2C;IAClE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAuB;IACpD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,KAAK,CAA+B;IAC5C,wCAAwC;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsC;gBAElD,IAAI,EAAE,0BAA0B;IAM5C,MAAM,CAAC,WAAW,IAAI,0BAA0B,GAAG,IAAI;IAIvD,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,0BAA0B,GAAG,IAAI,GAAG,IAAI;IAKjE,2CAA2C;IAC3C,KAAK,IAAI,IAAI;IAUb,IAAI,IAAI,IAAI;IAQZ;;;;;OAKG;IACH,mBAAmB,CAAC,KAAK,EAAE;QACzB,cAAc,EAAE,MAAM,CAAC;QACvB,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;KACd,GAAG,IAAI;IAyBR;;;OAGG;IACH,aAAa,CAAC,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI;IAY3E,sDAAsD;IACtD,YAAY,IAAI,eAAe,EAAE;IAIjC;;;OAGG;IACH,IAAI,CAAC,GAAG,GAAE,MAAmB,GAAG;QAAE,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE;IA8CtD,OAAO,CAAC,cAAc;CAevB;AAMD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAI3D;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,cAAc,EAAE,MAAM,GACrB,cAAc,GAAG,IAAI,CAyBvB"}
@@ -0,0 +1,265 @@
1
+ /**
2
+ * OrcDeliveryEnforcerService
3
+ *
4
+ * **Why this exists** (2026-05-23 incident, the "affiliate research" case):
5
+ *
6
+ * Steve asked the team to research affiliate programs at 12:59 PM. ORC
7
+ * acknowledged at 1:00 PM with "Atlas + Sage/Kai 派出去了, ETA 30-40min".
8
+ * Sage finished Phase 1 at 1:15, Kai finished Phase 2 at 1:28 — but
9
+ * Steve never saw the result. ORC's terminal logs claimed the pipeline
10
+ * was "closed" and the result "already routed to Steve at Slack thread
11
+ * ...", but there were zero `/api/slack/send` calls all day. ORC's
12
+ * internal mental model believed delivery happened; the actual skill
13
+ * call didn't.
14
+ *
15
+ * Root cause: ORC's prompt has a HARD pre-yield gate ("any `[CHAT:slack-…]`
16
+ * MUST have a `reply-slack` before yielding"). But for a long-running
17
+ * delegation, the user-visible deliverable comes from the *agent* via
18
+ * `[DONE]`-style status reports — long AFTER ORC's initial ack. ORC
19
+ * reads the agent's `[DONE]` as internal team chatter, narrates "pipeline
20
+ * closed", and yields without delivering to Steve. The prompt rule
21
+ * doesn't catch this case because the prompt looks for `[CHAT:slack-…]`
22
+ * (user-originating) not `[DONE]` (agent-originating).
23
+ *
24
+ * **What this service does:**
25
+ *
26
+ * 1. When a worker agent posts `[DONE]` / `[COMPLETED]` to a
27
+ * slack-prefixed conversation (chat.controller's "Agent status
28
+ * routed to orchestrator" path), call {@link markPendingDelivery}.
29
+ * The service records a pending delivery with `dueBy = now + 3 min`.
30
+ *
31
+ * 2. When ORC successfully posts via `/api/slack/send` to the same
32
+ * thread, call {@link markDelivered}. Pending delivery cleared.
33
+ *
34
+ * 3. A timer scans every 30 s. For any pending delivery whose `dueBy`
35
+ * has passed AND ORC hasn't replied, enqueue a `[DELIVER_REQUIRED]`
36
+ * system message to ORC via MessageQueueService. ORC's prompt
37
+ * treats `[DELIVER_REQUIRED]` exactly like `[CHAT:slack-…]` for
38
+ * the pre-yield gate.
39
+ *
40
+ * 4. Exponential backoff between reminders for the same thread, to
41
+ * avoid spamming ORC if it's genuinely stuck or rate-limited.
42
+ * First reminder at 3 min, then 10 min, then 30 min, then stop.
43
+ *
44
+ * Fire-and-forget on all writes — a fault in the enforcer MUST NOT
45
+ * block chat or slack flow.
46
+ *
47
+ * @module services/orc/orc-delivery-enforcer.service
48
+ */
49
+ import { LoggerService } from '../core/logger.service.js';
50
+ /** Reminder cadence (ms): first reminder at 3 min, then 10 min, then 30 min, then stop. */
51
+ const REMINDER_CADENCE_MS = [
52
+ 3 * 60 * 1000,
53
+ 10 * 60 * 1000,
54
+ 30 * 60 * 1000,
55
+ ];
56
+ const DEFAULT_TICK_INTERVAL_MS = 30 * 1000;
57
+ /** Markers in agent output that indicate user-facing delivery is ready. */
58
+ const DELIVERY_MARKERS = ['[DONE]', '[COMPLETED]', '[DELIVERED]'];
59
+ /**
60
+ * Singleton scope — there's one ORC, one queue of pending deliveries.
61
+ */
62
+ export class OrcDeliveryEnforcerService {
63
+ static instance = null;
64
+ logger;
65
+ reminderSink;
66
+ tickIntervalMs;
67
+ timer = null;
68
+ /** key = `${channelId}::${threadTs}` */
69
+ pending = new Map();
70
+ constructor(opts) {
71
+ this.logger = LoggerService.getInstance().createComponentLogger('OrcDeliveryEnforcer');
72
+ this.reminderSink = opts.reminderSink;
73
+ this.tickIntervalMs = opts.tickIntervalMs ?? DEFAULT_TICK_INTERVAL_MS;
74
+ }
75
+ static getInstance() {
76
+ return this.instance;
77
+ }
78
+ static setInstance(next) {
79
+ if (this.instance && this.instance !== next)
80
+ this.instance.stop();
81
+ this.instance = next;
82
+ }
83
+ /** Start the periodic scan. Idempotent. */
84
+ start() {
85
+ if (this.timer)
86
+ return;
87
+ this.timer = setInterval(() => this.tick(), this.tickIntervalMs);
88
+ this.timer.unref?.();
89
+ this.logger.info('OrcDeliveryEnforcer started', {
90
+ tickIntervalMs: this.tickIntervalMs,
91
+ cadenceMinutes: REMINDER_CADENCE_MS.map((n) => Math.round(n / 60000)),
92
+ });
93
+ }
94
+ stop() {
95
+ if (this.timer) {
96
+ clearInterval(this.timer);
97
+ this.timer = null;
98
+ this.logger.info('OrcDeliveryEnforcer stopped');
99
+ }
100
+ }
101
+ /**
102
+ * Call this from `chat.controller` when an agent posts a `[DONE]`-style
103
+ * status to a slack-prefixed conversation. Safe to call multiple times
104
+ * for the same thread — the most recent agent message wins (we
105
+ * surface only the latest deliverable summary in the reminder).
106
+ */
107
+ markPendingDelivery(input) {
108
+ if (!isAgentDeliveryMarker(input.text))
109
+ return;
110
+ const key = parseSlackConversationId(input.conversationId);
111
+ if (!key)
112
+ return; // not a slack thread — ignore
113
+ const k = serializeKey(key);
114
+ const now = Date.now();
115
+ const summary = input.text.slice(0, 200);
116
+ this.pending.set(k, {
117
+ key,
118
+ conversationId: input.conversationId,
119
+ agentSender: input.agentSender,
120
+ deliverableSummary: summary,
121
+ doneAt: now,
122
+ remindersFired: 0,
123
+ nextDueAt: now + REMINDER_CADENCE_MS[0],
124
+ });
125
+ this.logger.info('OrcDeliveryEnforcer pending delivery recorded', {
126
+ conversationId: input.conversationId,
127
+ agentSender: input.agentSender,
128
+ summaryPreview: summary.slice(0, 80),
129
+ firstReminderInSec: REMINDER_CADENCE_MS[0] / 1000,
130
+ });
131
+ }
132
+ /**
133
+ * Call this from `slack.controller` after a successful `/api/slack/send`.
134
+ * Cleared regardless of which agent originated the underlying deliverable.
135
+ */
136
+ markDelivered(input) {
137
+ if (!input.channelId || !input.threadTs)
138
+ return;
139
+ const k = serializeKey({ channelId: input.channelId, threadTs: input.threadTs });
140
+ const had = this.pending.delete(k);
141
+ if (had) {
142
+ this.logger.info('OrcDeliveryEnforcer delivery cleared by reply-slack', {
143
+ channelId: input.channelId,
144
+ threadTs: input.threadTs,
145
+ });
146
+ }
147
+ }
148
+ /** Test affordance — peek at the in-memory ledger. */
149
+ _peekPending() {
150
+ return [...this.pending.values()];
151
+ }
152
+ /**
153
+ * Public for tests + the manual-trigger endpoint. Otherwise driven by
154
+ * the internal timer.
155
+ */
156
+ tick(now = Date.now()) {
157
+ const firedFor = [];
158
+ for (const [k, item] of this.pending) {
159
+ if (now < item.nextDueAt)
160
+ continue;
161
+ if (item.remindersFired >= REMINDER_CADENCE_MS.length) {
162
+ // Out of reminder budget — drop the entry so we stop spamming.
163
+ this.pending.delete(k);
164
+ this.logger.warn('OrcDeliveryEnforcer reminder budget exhausted — giving up', {
165
+ conversationId: item.conversationId,
166
+ remindersFired: item.remindersFired,
167
+ });
168
+ continue;
169
+ }
170
+ const text = this.formatReminder(item);
171
+ try {
172
+ this.reminderSink({
173
+ conversationId: item.conversationId,
174
+ text,
175
+ });
176
+ firedFor.push(item.conversationId);
177
+ this.logger.info('OrcDeliveryEnforcer reminder fired', {
178
+ conversationId: item.conversationId,
179
+ agentSender: item.agentSender,
180
+ reminderIndex: item.remindersFired,
181
+ minutesSinceDone: Math.round((now - item.doneAt) / 60000),
182
+ });
183
+ }
184
+ catch (err) {
185
+ this.logger.warn('OrcDeliveryEnforcer reminderSink threw (swallowed)', {
186
+ error: err.message,
187
+ conversationId: item.conversationId,
188
+ });
189
+ }
190
+ item.remindersFired += 1;
191
+ const nextOffset = REMINDER_CADENCE_MS[item.remindersFired];
192
+ if (nextOffset === undefined) {
193
+ // Final reminder fired — drop the entry now so we don't keep
194
+ // re-evaluating it on every tick.
195
+ this.pending.delete(k);
196
+ }
197
+ else {
198
+ item.nextDueAt = now + nextOffset;
199
+ }
200
+ }
201
+ return { firedFor };
202
+ }
203
+ formatReminder(item) {
204
+ const minutes = Math.round((Date.now() - item.doneAt) / 60000);
205
+ return [
206
+ `[DELIVER_REQUIRED] Steve is waiting on a deliverable in Slack thread ${item.conversationId}.`,
207
+ ``,
208
+ `Agent \`${item.agentSender}\` posted [DONE] ${minutes} min ago with this content (preview):`,
209
+ `> ${item.deliverableSummary.slice(0, 200)}${item.deliverableSummary.length > 200 ? '…' : ''}`,
210
+ ``,
211
+ `Action required: call reply-slack now with the deliverable. Treat this`,
212
+ `the same as a [CHAT:slack-...] message — do NOT yield the turn until`,
213
+ `the reply lands on the thread. If the agent's output isn't the final`,
214
+ `deliverable yet (e.g. it's "Phase 1 done" out of 2), send Steve a status`,
215
+ `update via reply-slack saying so + revised ETA, then continue waiting.`,
216
+ ].join('\n');
217
+ }
218
+ }
219
+ // =============================================================================
220
+ // Helpers (exported for testing)
221
+ // =============================================================================
222
+ export function isAgentDeliveryMarker(text) {
223
+ if (!text)
224
+ return false;
225
+ const upper = text.toUpperCase();
226
+ return DELIVERY_MARKERS.some((m) => upper.includes(m));
227
+ }
228
+ /**
229
+ * Parse a chat-v2 conversation id of the form `slack-<channelId>-<ts>`
230
+ * into { channelId, threadTs }. Returns null for non-slack ids. Mirrors
231
+ * the regex in `request-sla.subscriber` so the enforcer agrees with the
232
+ * SLA layer on what "the same thread" means.
233
+ */
234
+ export function parseSlackConversationId(conversationId) {
235
+ if (!conversationId || !conversationId.startsWith('slack-'))
236
+ return null;
237
+ // Strip any per-message suffix (`-msg-<ts>`) so we key on thread root.
238
+ const stripped = conversationId.replace(/-msg-\d+\.\d+$/, '');
239
+ const rest = stripped.slice('slack-'.length);
240
+ const lastDash = rest.lastIndexOf('-');
241
+ if (lastDash < 1)
242
+ return null;
243
+ const channelId = rest.slice(0, lastDash);
244
+ let threadTs = rest.slice(lastDash + 1);
245
+ // Some producers serialize ts as `1779555555-588569` (dash) or
246
+ // `1779555555.588569` (dot). Normalize to dotted form to match
247
+ // Slack-API ts shape.
248
+ if (/^\d+$/.test(threadTs)) {
249
+ // No fractional segment in URL form — try one more split.
250
+ const beforeRest = rest.slice(0, lastDash);
251
+ const prevDash = beforeRest.lastIndexOf('-');
252
+ if (prevDash > 0) {
253
+ const candidate = `${beforeRest.slice(prevDash + 1)}.${threadTs}`;
254
+ if (/^\d+\.\d+$/.test(candidate)) {
255
+ return { channelId: beforeRest.slice(0, prevDash), threadTs: candidate };
256
+ }
257
+ }
258
+ }
259
+ // If threadTs already contains a dot (dotted form), keep as-is.
260
+ return { channelId, threadTs };
261
+ }
262
+ function serializeKey(k) {
263
+ return `${k.channelId}::${k.threadTs}`;
264
+ }
265
+ //# sourceMappingURL=orc-delivery-enforcer.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orc-delivery-enforcer.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/orc/orc-delivery-enforcer.service.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "crewly",
3
- "version": "1.8.5",
3
+ "version": "1.8.6",
4
4
  "type": "module",
5
5
  "description": "Multi-agent orchestration platform for AI coding teams — coordinates Claude Code, Gemini CLI, and Codex agents with a real-time web dashboard",
6
6
  "workspaces": [