crewly 1.20.147 → 1.20.148

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 (86) hide show
  1. package/config/roles/developer/prompt.md +2 -1
  2. package/config/roles/orchestrator/prompt.md +3 -2
  3. package/config/roles/product-manager/prompt.md +2 -1
  4. package/config/roles/team-leader/tl-addon.md +11 -2
  5. package/config/skills/team-leader/set-member-model/SKILL.md +60 -0
  6. package/config/skills/team-leader/set-member-model/execute.sh +55 -0
  7. package/config/skills/team-leader/set-member-model/execute.test.sh +76 -0
  8. package/dist/backend/backend/src/constants.d.ts +56 -0
  9. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  10. package/dist/backend/backend/src/constants.js +56 -0
  11. package/dist/backend/backend/src/constants.js.map +1 -1
  12. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts.map +1 -1
  13. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js +21 -0
  14. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js.map +1 -1
  15. package/dist/backend/backend/src/index.d.ts.map +1 -1
  16. package/dist/backend/backend/src/index.js +29 -10
  17. package/dist/backend/backend/src/index.js.map +1 -1
  18. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +9 -6
  19. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  20. package/dist/backend/backend/src/services/agent/agent-registration.service.js +22 -16
  21. package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
  22. package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.d.ts +248 -0
  23. package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.d.ts.map +1 -0
  24. package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.js +572 -0
  25. package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.js.map +1 -0
  26. package/dist/backend/backend/src/services/agent/runtime-session-recovery.d.ts +8 -0
  27. package/dist/backend/backend/src/services/agent/runtime-session-recovery.d.ts.map +1 -1
  28. package/dist/backend/backend/src/services/agent/runtime-session-recovery.js +12 -1
  29. package/dist/backend/backend/src/services/agent/runtime-session-recovery.js.map +1 -1
  30. package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.d.ts +10 -0
  31. package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.d.ts.map +1 -1
  32. package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js +41 -3
  33. package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js.map +1 -1
  34. package/dist/backend/backend/src/services/session/session-state-persistence.d.ts +9 -0
  35. package/dist/backend/backend/src/services/session/session-state-persistence.d.ts.map +1 -1
  36. package/dist/backend/backend/src/services/session/session-state-persistence.js +20 -0
  37. package/dist/backend/backend/src/services/session/session-state-persistence.js.map +1 -1
  38. package/dist/backend/backend/src/services/skill/skill-permission.service.d.ts.map +1 -1
  39. package/dist/backend/backend/src/services/skill/skill-permission.service.js +1 -0
  40. package/dist/backend/backend/src/services/skill/skill-permission.service.js.map +1 -1
  41. package/dist/backend/backend/src/services/v3/tl-auto-verify.service.d.ts +25 -1
  42. package/dist/backend/backend/src/services/v3/tl-auto-verify.service.d.ts.map +1 -1
  43. package/dist/backend/backend/src/services/v3/tl-auto-verify.service.js +82 -2
  44. package/dist/backend/backend/src/services/v3/tl-auto-verify.service.js.map +1 -1
  45. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.d.ts +27 -0
  46. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.d.ts.map +1 -1
  47. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js +48 -2
  48. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js.map +1 -1
  49. package/dist/backend/backend/src/types/settings.types.d.ts +8 -0
  50. package/dist/backend/backend/src/types/settings.types.d.ts.map +1 -1
  51. package/dist/backend/backend/src/types/settings.types.js +4 -0
  52. package/dist/backend/backend/src/types/settings.types.js.map +1 -1
  53. package/dist/backend/backend/src/utils/member-default-model.utils.d.ts +66 -0
  54. package/dist/backend/backend/src/utils/member-default-model.utils.d.ts.map +1 -0
  55. package/dist/backend/backend/src/utils/member-default-model.utils.js +95 -0
  56. package/dist/backend/backend/src/utils/member-default-model.utils.js.map +1 -0
  57. package/dist/backend/backend/src/utils/trigger-workitem-dedupe.utils.d.ts +53 -0
  58. package/dist/backend/backend/src/utils/trigger-workitem-dedupe.utils.d.ts.map +1 -0
  59. package/dist/backend/backend/src/utils/trigger-workitem-dedupe.utils.js +75 -0
  60. package/dist/backend/backend/src/utils/trigger-workitem-dedupe.utils.js.map +1 -0
  61. package/dist/backend/build-info.json +2 -2
  62. package/dist/cli/backend/src/constants.d.ts +56 -0
  63. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  64. package/dist/cli/backend/src/constants.js +56 -0
  65. package/dist/cli/backend/src/constants.js.map +1 -1
  66. package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts +9 -6
  67. package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  68. package/dist/cli/backend/src/services/agent/agent-registration.service.js +22 -16
  69. package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
  70. package/dist/cli/backend/src/services/agent/runtime-session-recovery.d.ts +8 -0
  71. package/dist/cli/backend/src/services/agent/runtime-session-recovery.d.ts.map +1 -1
  72. package/dist/cli/backend/src/services/agent/runtime-session-recovery.js +12 -1
  73. package/dist/cli/backend/src/services/agent/runtime-session-recovery.js.map +1 -1
  74. package/dist/cli/backend/src/services/session/session-state-persistence.d.ts +9 -0
  75. package/dist/cli/backend/src/services/session/session-state-persistence.d.ts.map +1 -1
  76. package/dist/cli/backend/src/services/session/session-state-persistence.js +20 -0
  77. package/dist/cli/backend/src/services/session/session-state-persistence.js.map +1 -1
  78. package/dist/cli/backend/src/types/settings.types.d.ts +8 -0
  79. package/dist/cli/backend/src/types/settings.types.d.ts.map +1 -1
  80. package/dist/cli/backend/src/types/settings.types.js +4 -0
  81. package/dist/cli/backend/src/types/settings.types.js.map +1 -1
  82. package/dist/cli/backend/src/utils/member-default-model.utils.d.ts +66 -0
  83. package/dist/cli/backend/src/utils/member-default-model.utils.d.ts.map +1 -0
  84. package/dist/cli/backend/src/utils/member-default-model.utils.js +95 -0
  85. package/dist/cli/backend/src/utils/member-default-model.utils.js.map +1 -0
  86. package/package.json +1 -1
@@ -0,0 +1,572 @@
1
+ /**
2
+ * Fresh Task Conversation Service
3
+ *
4
+ * Claude Code agents keep one conversation forever, so a small new task
5
+ * re-reads hundreds of thousands of tokens of unrelated history on every
6
+ * turn (81% of measured usage came from turns over 300k context). This
7
+ * service starts a fresh conversation when a team member is handed a task
8
+ * whose ROOT differs from the last one it was given:
9
+ *
10
+ * 1. The old conversation is saved server-side — a handover file under
11
+ * `<CREWLY_HOME>/handover/` (same format the orchestrator uses at
12
+ * restart) and a concise copy through the memory `remember` path, which
13
+ * mirrors into the wiki. No agent turn is spent on it.
14
+ * 2. `/clear` is written to the PTY the same way context compaction writes
15
+ * its command (Escape, 200 ms, command + CR), then a short pause for the
16
+ * prompt to come back.
17
+ * 3. The dispatch goes on with a one-line note pointing at the handover.
18
+ * 4. In the background the new transcript Claude Code starts is found and
19
+ * its id stored, so a restart resumes the NEW conversation; if it cannot
20
+ * be found the stored id is cleared so a restart starts fresh instead of
21
+ * resuming the huge pre-clear one.
22
+ *
23
+ * Retries, verifications and reviews of the same task share its root
24
+ * (`<id>:retry:N`, `<id>:verify:<id>`, `<id>:review:…`), so they keep their
25
+ * context. Never the orchestrator, only Claude Code, only when the agent is
26
+ * idle and nobody else just wrote to it; any failure falls back to plain
27
+ * delivery — nothing here throws into dispatch.
28
+ *
29
+ * @module services/agent/fresh-task-conversation.service
30
+ */
31
+ import * as fs from 'fs';
32
+ import * as path from 'path';
33
+ import { LoggerService } from '../core/logger.service.js';
34
+ import { getCrewlyHomePath } from '../core/crewly-home.utils.js';
35
+ import { CREWLY_CONSTANTS, FRESH_TASK_CONVERSATION_CONSTANTS, ORC_CONVERSATION_CONSTANTS, ORCHESTRATOR_SESSION_NAME, RUNTIME_TYPES, } from '../../constants.js';
36
+ import { buildHandoverSummary, claudeTranscriptPath, lastTurnContextTokens } from './runtime-session-recovery.js';
37
+ import { getSessionStatePersistence } from '../session/session-state-persistence.js';
38
+ import { getSessionBackendSync } from '../session/session-backend.factory.js';
39
+ import { PtyActivityTrackerService } from './pty-activity-tracker.service.js';
40
+ // ---------------------------------------------------------------------------
41
+ // Pure helpers
42
+ // ---------------------------------------------------------------------------
43
+ /**
44
+ * The root task id of a work item: its id with any follow-up suffix
45
+ * (`:retry:N`, `:verify:…`, `:review:…`) removed, so every follow-up of one
46
+ * task maps to the same root.
47
+ *
48
+ * @param workItemId - WorkItem id
49
+ * @returns The root id
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * rootWorkItemId('abc:retry:2'); // 'abc'
54
+ * rootWorkItemId('abc:verify:abc'); // 'abc'
55
+ * rootWorkItemId('abc:retry:1:retry:2'); // 'abc'
56
+ * ```
57
+ */
58
+ export function rootWorkItemId(workItemId) {
59
+ let cut = workItemId.length;
60
+ for (const marker of FRESH_TASK_CONVERSATION_CONSTANTS.ROOT_SUFFIX_MARKERS) {
61
+ const i = workItemId.indexOf(marker);
62
+ if (i > 0 && i < cut)
63
+ cut = i;
64
+ }
65
+ return workItemId.slice(0, cut);
66
+ }
67
+ /**
68
+ * Whether the feature is switched on by the environment.
69
+ *
70
+ * @param env - Environment (tests)
71
+ * @returns False when CREWLY_FRESH_TASK_CONVERSATION is 0 / false / off / no
72
+ */
73
+ export function freshTaskConversationEnvEnabled(env = process.env) {
74
+ const raw = env[FRESH_TASK_CONVERSATION_CONSTANTS.ENV_TOGGLE];
75
+ if (raw === undefined)
76
+ return true;
77
+ return !['0', 'false', 'off', 'no'].includes(raw.trim().toLowerCase());
78
+ }
79
+ /**
80
+ * Decide whether to start a fresh conversation before delivering a task.
81
+ *
82
+ * @param input - Decision inputs
83
+ * @returns The decision
84
+ */
85
+ export function decideFreshConversation(input) {
86
+ if (input.sessionName === ORCHESTRATOR_SESSION_NAME)
87
+ return { clear: false, reason: 'orchestrator' };
88
+ if (input.runtimeType !== RUNTIME_TYPES.CLAUDE_CODE)
89
+ return { clear: false, reason: 'not claude-code' };
90
+ if (!input.enabled)
91
+ return { clear: false, reason: 'disabled' };
92
+ if (!input.previousRoot)
93
+ return { clear: false, reason: 'first task' };
94
+ if (input.previousRoot === input.newRoot)
95
+ return { clear: false, reason: 'same task' };
96
+ if (input.busy)
97
+ return { clear: false, reason: 'busy' };
98
+ if (input.recentDelivery)
99
+ return { clear: false, reason: 'recent delivery' };
100
+ if (input.alreadyStarted)
101
+ return { clear: false, reason: 'already working on it' };
102
+ if (input.otherActiveRoots.some((r) => r !== input.newRoot))
103
+ return { clear: false, reason: 'other work in progress' };
104
+ return { clear: true, reason: 'new task' };
105
+ }
106
+ /**
107
+ * The line put in front of the task text after a fresh start.
108
+ *
109
+ * @param handoverPath - Handover file written for the old conversation
110
+ * @returns One line
111
+ */
112
+ export function freshConversationNote(handoverPath) {
113
+ return `Fresh conversation for this task — your earlier work is in ${handoverPath} and your wiki; read them only if this task needs it.`;
114
+ }
115
+ /** Statuses that mean the agent is actively on a work item. */
116
+ const ACTIVE_STATUSES = new Set(['running', 'accepted', 'proposed']);
117
+ /**
118
+ * Default collaborators. Heavy services are imported lazily so importing this
119
+ * module (from the dispatch subscriber, the terminal controller) stays cheap.
120
+ *
121
+ * @returns Deps bound to the running backend
122
+ */
123
+ function defaultDeps() {
124
+ const getPersistence = () => {
125
+ try {
126
+ return getSessionStatePersistence();
127
+ }
128
+ catch {
129
+ return null;
130
+ }
131
+ };
132
+ return {
133
+ getSessionInfo: (sessionName) => {
134
+ const meta = getPersistence()?.getSessionMetadata(sessionName);
135
+ if (!meta)
136
+ return null;
137
+ return { runtimeType: meta.runtimeType, cwd: meta.cwd, sessionId: meta.claudeSessionId };
138
+ },
139
+ getClaimedSessionIds: (sessionName) => {
140
+ const p = getPersistence();
141
+ const ids = new Set();
142
+ if (!p)
143
+ return ids;
144
+ for (const name of p.getRegisteredSessions()) {
145
+ const id = p.getSessionId(name);
146
+ if (id && name !== sessionName)
147
+ ids.add(id);
148
+ }
149
+ return ids;
150
+ },
151
+ updateSessionId: (sessionName, id) => getPersistence()?.updateSessionId(sessionName, id),
152
+ clearSessionId: (sessionName) => getPersistence()?.clearSessionId(sessionName),
153
+ isBusy: async (sessionName) => {
154
+ const { StorageService } = await import('../core/storage.service.js');
155
+ const info = await StorageService.getInstance().findMemberBySessionName(sessionName).catch(() => null);
156
+ if (info?.member.workingStatus === CREWLY_CONSTANTS.WORKING_STATUSES.IN_PROGRESS)
157
+ return true;
158
+ const tracker = PtyActivityTrackerService.getInstance();
159
+ return tracker.hasActivity(sessionName) && tracker.getIdleTimeMs(sessionName) < FRESH_TASK_CONVERSATION_CONSTANTS.MIN_QUIET_MS;
160
+ },
161
+ settingEnabled: async () => {
162
+ try {
163
+ const { getSettingsService } = await import('../settings/settings.service.js');
164
+ return (await getSettingsService().getSettings()).general.freshConversationPerTask !== false;
165
+ }
166
+ catch {
167
+ return true;
168
+ }
169
+ },
170
+ getActiveItems: async (sessionName) => {
171
+ const { TaskPoolService } = await import('../task-pool/task-pool.service.js');
172
+ const all = await TaskPoolService.getInstance().getAllItems();
173
+ return all.filter((wi) => wi.target === sessionName && ACTIVE_STATUSES.has(wi.status));
174
+ },
175
+ writeToSession: (sessionName, data) => {
176
+ const session = getSessionBackendSync()?.getSession(sessionName);
177
+ if (!session)
178
+ return false;
179
+ session.write(data);
180
+ return true;
181
+ },
182
+ remember: async ({ agentId, projectPath, content, title }) => {
183
+ const { MemoryService } = await import('../memory/memory.service.js');
184
+ return MemoryService.getInstance().remember({
185
+ agentId,
186
+ projectPath,
187
+ content,
188
+ category: 'fact',
189
+ scope: 'agent',
190
+ metadata: { title },
191
+ });
192
+ },
193
+ crewlyHome: getCrewlyHomePath,
194
+ now: () => Date.now(),
195
+ sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
196
+ env: process.env,
197
+ };
198
+ }
199
+ /**
200
+ * Singleton that starts a fresh Claude Code conversation per new task.
201
+ */
202
+ export class FreshTaskConversationService {
203
+ static instance = null;
204
+ logger;
205
+ deps;
206
+ state = null;
207
+ /** Per-session in-flight prepare (serialises prepares; waited on by terminal writes) */
208
+ inFlight = new Map();
209
+ /** Last time a message was written to a session (terminal write / deliver) */
210
+ lastDelivery = new Map();
211
+ constructor(deps) {
212
+ this.logger = LoggerService.getInstance().createComponentLogger('FreshTaskConversation');
213
+ this.deps = { ...defaultDeps(), ...(deps ?? {}) };
214
+ }
215
+ /**
216
+ * @returns The singleton
217
+ */
218
+ static getInstance() {
219
+ if (!FreshTaskConversationService.instance) {
220
+ FreshTaskConversationService.instance = new FreshTaskConversationService();
221
+ }
222
+ return FreshTaskConversationService.instance;
223
+ }
224
+ /**
225
+ * Replace the singleton with one using the given collaborators (tests).
226
+ *
227
+ * @param deps - Overrides for the default deps
228
+ * @returns The new singleton
229
+ */
230
+ static createForTesting(deps) {
231
+ FreshTaskConversationService.instance = new FreshTaskConversationService(deps);
232
+ return FreshTaskConversationService.instance;
233
+ }
234
+ /** Drop the singleton (tests). */
235
+ static resetInstance() {
236
+ FreshTaskConversationService.instance = null;
237
+ }
238
+ /**
239
+ * Record that a message is being written to a session. A clear right after
240
+ * would wipe it before the agent reads it, so {@link prepareForTask} skips
241
+ * clearing for a short window (this includes the dispatcher's own briefs,
242
+ * so two tasks dispatched back to back never clear each other).
243
+ *
244
+ * @param sessionName - Session written to
245
+ */
246
+ noteDelivery(sessionName) {
247
+ this.lastDelivery.set(sessionName, this.deps.now());
248
+ }
249
+ /**
250
+ * Wait (bounded) while a prepare — possibly a `/clear` — is running for the
251
+ * session, so a message written now is not wiped by it.
252
+ *
253
+ * @param sessionName - Session about to be written to
254
+ * @param maxMs - Upper bound on the wait
255
+ */
256
+ async waitIfClearing(sessionName, maxMs = FRESH_TASK_CONVERSATION_CONSTANTS.WAIT_IF_CLEARING_MAX_MS) {
257
+ const pending = this.inFlight.get(sessionName);
258
+ if (!pending)
259
+ return;
260
+ let timer;
261
+ await Promise.race([
262
+ pending.catch(() => undefined),
263
+ new Promise((resolve) => {
264
+ timer = setTimeout(resolve, maxMs);
265
+ timer.unref?.();
266
+ }),
267
+ ]);
268
+ if (timer)
269
+ clearTimeout(timer);
270
+ }
271
+ /**
272
+ * Root of the last task delivered to a session.
273
+ *
274
+ * @param sessionName - Session
275
+ * @returns Root id or null
276
+ */
277
+ getLastRoot(sessionName) {
278
+ return this.loadState().sessions[sessionName]?.root ?? null;
279
+ }
280
+ /**
281
+ * Called right before a task is written to an agent. Starts a fresh
282
+ * conversation when the task's root differs from the previous one and it
283
+ * is safe to; always records the new root. Never throws.
284
+ *
285
+ * @param sessionName - Target session
286
+ * @param workItem - Task being delivered
287
+ * @returns Whether it cleared, and the handover file when it did
288
+ */
289
+ async prepareForTask(sessionName, workItem) {
290
+ const previous = this.inFlight.get(sessionName);
291
+ const run = (async () => {
292
+ if (previous)
293
+ await previous.catch(() => undefined);
294
+ try {
295
+ return await this.doPrepare(sessionName, workItem);
296
+ }
297
+ catch (err) {
298
+ this.logger.warn('Fresh-conversation prepare failed — delivering without clearing', {
299
+ sessionName,
300
+ workItemId: workItem.id,
301
+ error: err instanceof Error ? err.message : String(err),
302
+ });
303
+ return { cleared: false };
304
+ }
305
+ })();
306
+ this.inFlight.set(sessionName, run);
307
+ try {
308
+ return await run;
309
+ }
310
+ finally {
311
+ if (this.inFlight.get(sessionName) === run)
312
+ this.inFlight.delete(sessionName);
313
+ }
314
+ }
315
+ // -------------------------------------------------------------------------
316
+ // Internals
317
+ // -------------------------------------------------------------------------
318
+ async doPrepare(sessionName, workItem) {
319
+ const newRoot = rootWorkItemId(workItem.id);
320
+ const previousRoot = this.getLastRoot(sessionName);
321
+ const info = this.deps.getSessionInfo(sessionName);
322
+ // Cheap checks first; the async ones only when a clear is still possible.
323
+ let decision = decideFreshConversation({
324
+ sessionName,
325
+ runtimeType: info?.runtimeType,
326
+ previousRoot,
327
+ newRoot,
328
+ enabled: true,
329
+ busy: false,
330
+ recentDelivery: false,
331
+ otherActiveRoots: [],
332
+ });
333
+ if (decision.clear) {
334
+ const enabled = freshTaskConversationEnvEnabled(this.deps.env) && (await this.deps.settingEnabled());
335
+ const busy = enabled ? await this.deps.isBusy(sessionName).catch(() => true) : false;
336
+ const last = this.lastDelivery.get(sessionName);
337
+ const recentDelivery = last !== undefined && this.deps.now() - last < FRESH_TASK_CONVERSATION_CONSTANTS.RECENT_DELIVERY_MS;
338
+ const active = enabled && !busy ? await this.deps.getActiveItems(sessionName).catch(() => null) : [];
339
+ decision = decideFreshConversation({
340
+ sessionName,
341
+ runtimeType: info?.runtimeType,
342
+ previousRoot,
343
+ newRoot,
344
+ enabled,
345
+ busy: busy || active === null,
346
+ recentDelivery,
347
+ otherActiveRoots: (active ?? []).filter((wi) => wi.id !== workItem.id).map((wi) => rootWorkItemId(wi.id)),
348
+ alreadyStarted: (active ?? []).some((wi) => rootWorkItemId(wi.id) === newRoot &&
349
+ !!wi.startedAt &&
350
+ this.deps.now() - Date.parse(wi.startedAt) > FRESH_TASK_CONVERSATION_CONSTANTS.ALREADY_STARTED_MS),
351
+ });
352
+ }
353
+ this.recordRoot(sessionName, newRoot);
354
+ if (!decision.clear) {
355
+ if (previousRoot && previousRoot !== newRoot) {
356
+ this.logger.debug('New task — keeping the current conversation', { sessionName, newRoot, previousRoot, reason: decision.reason });
357
+ }
358
+ return { cleared: false };
359
+ }
360
+ if (!info?.cwd || !info.sessionId) {
361
+ this.logger.info('New task but the conversation id is unknown — not clearing', { sessionName, newRoot });
362
+ return { cleared: false };
363
+ }
364
+ const transcript = claudeTranscriptPath({ sessionId: info.sessionId, cwd: info.cwd, claudeHome: this.deps.claudeHome });
365
+ if (!fs.existsSync(transcript)) {
366
+ this.logger.info('New task but the transcript is missing — not clearing', { sessionName, transcript });
367
+ return { cleared: false };
368
+ }
369
+ // 1. Save the conversation (server-side, no agent turn).
370
+ const summary = buildHandoverSummary(transcript);
371
+ const handoverPath = this.writeHandover(sessionName, info.sessionId, transcript, previousRoot, summary);
372
+ const memoryText = this.conciseHandover(sessionName, previousRoot, handoverPath, summary);
373
+ void this.deps
374
+ .remember({
375
+ agentId: sessionName,
376
+ projectPath: info.cwd,
377
+ content: memoryText,
378
+ title: `Conversation handover — ${sessionName} — task ${previousRoot}`,
379
+ })
380
+ .catch((err) => {
381
+ this.logger.debug('Handover memory write failed (non-fatal; the file is on disk)', {
382
+ sessionName,
383
+ error: err instanceof Error ? err.message : String(err),
384
+ });
385
+ });
386
+ // 2. Clear, exactly as context compaction writes its command.
387
+ const clearAt = this.deps.now();
388
+ if (!this.deps.writeToSession(sessionName, '\x1b')) {
389
+ this.logger.info('Session not found — not clearing', { sessionName });
390
+ return { cleared: false };
391
+ }
392
+ await this.deps.sleep(FRESH_TASK_CONVERSATION_CONSTANTS.ESCAPE_DELAY_MS);
393
+ this.deps.writeToSession(sessionName, `${FRESH_TASK_CONVERSATION_CONSTANTS.CLEAR_COMMAND}\r`);
394
+ await this.deps.sleep(FRESH_TASK_CONVERSATION_CONSTANTS.POST_CLEAR_READY_MS);
395
+ this.logger.info('Started a fresh conversation for a new task', {
396
+ sessionName,
397
+ previousRoot,
398
+ newRoot,
399
+ oldSessionId: info.sessionId,
400
+ handover: handoverPath,
401
+ });
402
+ // 3. Learn the new conversation id in the background.
403
+ void this.trackNewConversation(sessionName, info.cwd, info.sessionId, clearAt);
404
+ return { cleared: true, handoverPath };
405
+ }
406
+ /**
407
+ * Write the handover file (same shape as the orchestrator's restart handover).
408
+ *
409
+ * @returns Its path
410
+ */
411
+ writeHandover(sessionName, oldSessionId, transcript, previousRoot, body) {
412
+ const dir = path.join(this.deps.crewlyHome(), ORC_CONVERSATION_CONSTANTS.HANDOVER_DIR);
413
+ fs.mkdirSync(dir, { recursive: true });
414
+ const stamp = new Date(this.deps.now()).toISOString().replace(/[:.]/g, '-');
415
+ const file = path.join(dir, `${sessionName}-${stamp}.md`);
416
+ const tokens = lastTurnContextTokens(transcript);
417
+ fs.writeFileSync(file, [
418
+ `# Handover from your previous conversation`,
419
+ ``,
420
+ `Your previous conversation (${oldSessionId}) was closed when you were given a new task; its last task was ${previousRoot}.` +
421
+ (tokens !== null ? ` It had grown to ${tokens.toLocaleString('en-US')} tokens per turn.` : ''),
422
+ `Everything Crewly tracks — tasks, teams, OKRs, wiki — is still there; this file keeps only the end of what was said.`,
423
+ `The full transcript: ${transcript}`,
424
+ ``,
425
+ body || '_Nothing readable was found at the end of the old conversation._',
426
+ ``,
427
+ ].join('\n'), 'utf-8');
428
+ return file;
429
+ }
430
+ /**
431
+ * The capped text stored through memory: where the handover is plus the
432
+ * newest part of what was said.
433
+ */
434
+ conciseHandover(sessionName, previousRoot, handoverPath, summary) {
435
+ const head = `${sessionName} finished its conversation on task ${previousRoot}; full handover: ${handoverPath}\n\n`;
436
+ const room = Math.max(0, FRESH_TASK_CONVERSATION_CONSTANTS.MEMORY_MAX_CHARS - head.length);
437
+ const tail = summary.length > room ? `…${summary.slice(summary.length - room + 1)}` : summary;
438
+ return head + (tail || '(nothing readable at the end of the conversation)');
439
+ }
440
+ /**
441
+ * After `/clear`, find the transcript Claude Code starts for this agent and
442
+ * store its id; if none shows up in time, clear the stored id so a restart
443
+ * starts fresh rather than resuming the pre-clear conversation.
444
+ *
445
+ * A candidate is a `.jsonl` in the agent's transcript directory, modified
446
+ * since the clear, not the old id, not claimed by another session, and
447
+ * mentioning this session's name (the dispatch text written right after the
448
+ * clear carries it) — several agents can share one cwd.
449
+ */
450
+ async trackNewConversation(sessionName, cwd, oldId, clearAt) {
451
+ try {
452
+ const dir = path.dirname(claudeTranscriptPath({ sessionId: oldId, cwd, claudeHome: this.deps.claudeHome }));
453
+ const deadline = clearAt + FRESH_TASK_CONVERSATION_CONSTANTS.NEW_SESSION_DETECT_MS;
454
+ while (this.deps.now() <= deadline) {
455
+ const found = this.findNewTranscript(dir, sessionName, oldId, clearAt);
456
+ if (found) {
457
+ this.deps.updateSessionId(sessionName, found);
458
+ this.logger.info('Recorded the conversation id started by /clear', { sessionName, sessionId: found });
459
+ return;
460
+ }
461
+ await this.deps.sleep(FRESH_TASK_CONVERSATION_CONSTANTS.NEW_SESSION_POLL_MS);
462
+ }
463
+ this.deps.clearSessionId(sessionName);
464
+ this.logger.warn('New conversation id not found after /clear — cleared the stored id so a restart starts fresh', {
465
+ sessionName,
466
+ oldSessionId: oldId,
467
+ });
468
+ }
469
+ catch (err) {
470
+ this.logger.warn('New conversation id tracking failed — clearing the stored id', {
471
+ sessionName,
472
+ error: err instanceof Error ? err.message : String(err),
473
+ });
474
+ try {
475
+ this.deps.clearSessionId(sessionName);
476
+ }
477
+ catch {
478
+ // nothing more to do
479
+ }
480
+ }
481
+ }
482
+ /**
483
+ * One scan of the transcript directory.
484
+ *
485
+ * @returns The new conversation id, or null
486
+ */
487
+ findNewTranscript(dir, sessionName, oldId, clearAt) {
488
+ let entries;
489
+ try {
490
+ entries = fs.readdirSync(dir).filter((f) => f.endsWith('.jsonl'));
491
+ }
492
+ catch {
493
+ return null;
494
+ }
495
+ const claimed = this.deps.getClaimedSessionIds(sessionName);
496
+ const candidates = [];
497
+ for (const name of entries) {
498
+ const id = name.slice(0, -'.jsonl'.length);
499
+ if (id === oldId || claimed.has(id))
500
+ continue;
501
+ const file = path.join(dir, name);
502
+ let mtime;
503
+ try {
504
+ mtime = fs.statSync(file).mtimeMs;
505
+ }
506
+ catch {
507
+ continue;
508
+ }
509
+ // One second of slack for filesystem timestamp granularity.
510
+ if (mtime < clearAt - 1_000)
511
+ continue;
512
+ if (!this.fileMentions(file, sessionName))
513
+ continue;
514
+ candidates.push({ id, mtime });
515
+ }
516
+ candidates.sort((a, b) => b.mtime - a.mtime);
517
+ return candidates[0]?.id ?? null;
518
+ }
519
+ /** Whether the start of a transcript mentions the session name. */
520
+ fileMentions(file, needle) {
521
+ const MAX_BYTES = 256 * 1024;
522
+ try {
523
+ const fd = fs.openSync(file, 'r');
524
+ try {
525
+ const buf = Buffer.alloc(Math.min(MAX_BYTES, fs.fstatSync(fd).size));
526
+ fs.readSync(fd, buf, 0, buf.length, 0);
527
+ return buf.toString('utf-8').includes(needle);
528
+ }
529
+ finally {
530
+ fs.closeSync(fd);
531
+ }
532
+ }
533
+ catch {
534
+ return false;
535
+ }
536
+ }
537
+ statePath() {
538
+ return path.join(this.deps.crewlyHome(), FRESH_TASK_CONVERSATION_CONSTANTS.STATE_FILE);
539
+ }
540
+ loadState() {
541
+ if (this.state)
542
+ return this.state;
543
+ try {
544
+ const parsed = JSON.parse(fs.readFileSync(this.statePath(), 'utf-8'));
545
+ this.state = { version: 1, sessions: parsed && typeof parsed.sessions === 'object' && parsed.sessions ? parsed.sessions : {} };
546
+ }
547
+ catch {
548
+ this.state = { version: 1, sessions: {} };
549
+ }
550
+ return this.state;
551
+ }
552
+ recordRoot(sessionName, root) {
553
+ const state = this.loadState();
554
+ if (state.sessions[sessionName]?.root === root)
555
+ return;
556
+ state.sessions[sessionName] = { root, at: new Date(this.deps.now()).toISOString() };
557
+ try {
558
+ const file = this.statePath();
559
+ fs.mkdirSync(path.dirname(file), { recursive: true });
560
+ const tmp = `${file}.${process.pid}.tmp`;
561
+ fs.writeFileSync(tmp, JSON.stringify(state, null, 2), 'utf-8');
562
+ fs.renameSync(tmp, file);
563
+ }
564
+ catch (err) {
565
+ this.logger.debug('Could not persist the last task root (non-fatal)', {
566
+ sessionName,
567
+ error: err instanceof Error ? err.message : String(err),
568
+ });
569
+ }
570
+ }
571
+ }
572
+ //# sourceMappingURL=fresh-task-conversation.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fresh-task-conversation.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/agent/fresh-task-conversation.service.ts"],"names":[],"mappings":"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"}
@@ -221,4 +221,12 @@ export declare function buildHandoverSummary(filePath: string): string;
221
221
  * @returns Tokens
222
222
  */
223
223
  export declare function orcFreshContextTokens(env?: NodeJS.ProcessEnv): number;
224
+ /**
225
+ * The threshold at which a team member (not the orchestrator) starts a fresh
226
+ * conversation at launch instead of resuming its old one.
227
+ *
228
+ * @param env - Environment (tests)
229
+ * @returns Tokens
230
+ */
231
+ export declare function memberFreshContextTokens(env?: NodeJS.ProcessEnv): number;
224
232
  //# sourceMappingURL=runtime-session-recovery.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-session-recovery.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/agent/runtime-session-recovery.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runtime-session-recovery.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/agent/runtime-session-recovery.ts"],"names":[],"mappings":"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"}
@@ -31,7 +31,7 @@ import * as fs from 'fs';
31
31
  import * as os from 'os';
32
32
  import * as path from 'path';
33
33
  import { randomUUID } from 'crypto';
34
- import { ANTIGRAVITY_CONSTANTS, RUNTIME_TYPES, ORC_CONVERSATION_CONSTANTS } from '../../constants.js';
34
+ import { ANTIGRAVITY_CONSTANTS, RUNTIME_TYPES, ORC_CONVERSATION_CONSTANTS, FRESH_TASK_CONVERSATION_CONSTANTS } from '../../constants.js';
35
35
  import { getAntigravityConfigDir } from '../../utils/antigravity-settings.utils.js';
36
36
  /**
37
37
  * Env vars set by a running Claude Code session for its children. An agent
@@ -602,4 +602,15 @@ export function orcFreshContextTokens(env = process.env) {
602
602
  const raw = Number(env['CREWLY_ORC_FRESH_CONTEXT_TOKENS']);
603
603
  return Number.isFinite(raw) && raw > 0 ? raw : ORC_CONVERSATION_CONSTANTS.FRESH_CONTEXT_TOKENS;
604
604
  }
605
+ /**
606
+ * The threshold at which a team member (not the orchestrator) starts a fresh
607
+ * conversation at launch instead of resuming its old one.
608
+ *
609
+ * @param env - Environment (tests)
610
+ * @returns Tokens
611
+ */
612
+ export function memberFreshContextTokens(env = process.env) {
613
+ const raw = Number(env['CREWLY_MEMBER_FRESH_CONTEXT_TOKENS']);
614
+ return Number.isFinite(raw) && raw > 0 ? raw : FRESH_TASK_CONVERSATION_CONSTANTS.MEMBER_FRESH_CONTEXT_TOKENS;
615
+ }
605
616
  //# sourceMappingURL=runtime-session-recovery.js.map