@telora/daemon 0.18.37 → 0.18.49

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 (81) hide show
  1. package/build-info.json +5 -3
  2. package/dist/completion/advanceability.d.ts +66 -0
  3. package/dist/completion/advanceability.d.ts.map +1 -0
  4. package/dist/completion/advanceability.js +112 -0
  5. package/dist/completion/advanceability.js.map +1 -0
  6. package/dist/completion/event.d.ts +28 -52
  7. package/dist/completion/event.d.ts.map +1 -1
  8. package/dist/completion/event.js +79 -99
  9. package/dist/completion/event.js.map +1 -1
  10. package/dist/completion/progress-snapshot.d.ts +15 -4
  11. package/dist/completion/progress-snapshot.d.ts.map +1 -1
  12. package/dist/completion/progress-snapshot.js +20 -4
  13. package/dist/completion/progress-snapshot.js.map +1 -1
  14. package/dist/crash-recovery.d.ts +48 -0
  15. package/dist/crash-recovery.d.ts.map +1 -1
  16. package/dist/crash-recovery.js +166 -30
  17. package/dist/crash-recovery.js.map +1 -1
  18. package/dist/delivery-advance-block.d.ts +17 -1
  19. package/dist/delivery-advance-block.d.ts.map +1 -1
  20. package/dist/delivery-advance-block.js +31 -8
  21. package/dist/delivery-advance-block.js.map +1 -1
  22. package/dist/escalation-provenance.d.ts +5 -1
  23. package/dist/escalation-provenance.d.ts.map +1 -1
  24. package/dist/escalation-provenance.js +46 -4
  25. package/dist/escalation-provenance.js.map +1 -1
  26. package/dist/focus-executor.d.ts.map +1 -1
  27. package/dist/focus-executor.js +1 -0
  28. package/dist/focus-executor.js.map +1 -1
  29. package/dist/git-activity.d.ts +15 -0
  30. package/dist/git-activity.d.ts.map +1 -1
  31. package/dist/git-activity.js +24 -0
  32. package/dist/git-activity.js.map +1 -1
  33. package/dist/listener.d.ts.map +1 -1
  34. package/dist/listener.js +5 -0
  35. package/dist/listener.js.map +1 -1
  36. package/dist/loop-engine-types.d.ts +40 -0
  37. package/dist/loop-engine-types.d.ts.map +1 -0
  38. package/dist/loop-engine-types.js +11 -0
  39. package/dist/loop-engine-types.js.map +1 -0
  40. package/dist/loop-engine.d.ts +52 -0
  41. package/dist/loop-engine.d.ts.map +1 -1
  42. package/dist/loop-engine.js +91 -10
  43. package/dist/loop-engine.js.map +1 -1
  44. package/dist/loop-llm-flag.d.ts +32 -0
  45. package/dist/loop-llm-flag.d.ts.map +1 -0
  46. package/dist/loop-llm-flag.js +35 -0
  47. package/dist/loop-llm-flag.js.map +1 -0
  48. package/dist/loop-operational-block.d.ts +44 -0
  49. package/dist/loop-operational-block.d.ts.map +1 -0
  50. package/dist/loop-operational-block.js +47 -0
  51. package/dist/loop-operational-block.js.map +1 -0
  52. package/dist/merge-back-loop.d.ts.map +1 -1
  53. package/dist/merge-back-loop.js +1 -0
  54. package/dist/merge-back-loop.js.map +1 -1
  55. package/dist/nexus-incoming.d.ts +8 -7
  56. package/dist/nexus-incoming.d.ts.map +1 -1
  57. package/dist/nexus-incoming.js +10 -12
  58. package/dist/nexus-incoming.js.map +1 -1
  59. package/dist/nexus-intake-spawn.d.ts +57 -0
  60. package/dist/nexus-intake-spawn.d.ts.map +1 -0
  61. package/dist/nexus-intake-spawn.js +158 -0
  62. package/dist/nexus-intake-spawn.js.map +1 -0
  63. package/dist/nexus-intake.d.ts +117 -0
  64. package/dist/nexus-intake.d.ts.map +1 -0
  65. package/dist/nexus-intake.js +212 -0
  66. package/dist/nexus-intake.js.map +1 -0
  67. package/dist/types/focus.d.ts +24 -0
  68. package/dist/types/focus.d.ts.map +1 -1
  69. package/package.json +2 -2
  70. package/dist/crash-recovery-cleanup.d.ts +0 -21
  71. package/dist/crash-recovery-cleanup.d.ts.map +0 -1
  72. package/dist/crash-recovery-cleanup.js +0 -205
  73. package/dist/crash-recovery-cleanup.js.map +0 -1
  74. package/dist/crash-recovery-scan.d.ts +0 -19
  75. package/dist/crash-recovery-scan.d.ts.map +0 -1
  76. package/dist/crash-recovery-scan.js +0 -145
  77. package/dist/crash-recovery-scan.js.map +0 -1
  78. package/dist/crash-recovery-types.d.ts +0 -49
  79. package/dist/crash-recovery-types.d.ts.map +0 -1
  80. package/dist/crash-recovery-types.js +0 -13
  81. package/dist/crash-recovery-types.js.map +0 -1
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Nexus intake poll: the target-product side of authoring work from an accepted
3
+ * cross-product request.
4
+ *
5
+ * An accepted Nexus request (status 'accepted', materialized_focus_id NULL) is
6
+ * "intake-pending": accepted, but not yet scoped into work. Authoring a focus
7
+ * from that request IS scoping work -- read the acceptanceContract, build a
8
+ * reality tree, decompose into injection-anchored deliveries -- which the
9
+ * row-stamping materialize edge handler structurally cannot do. So the TARGET
10
+ * product's agent team owns it: each poll cycle the daemon finds intake-pending
11
+ * requests and spawns a dedicated, short-lived nexus-intake SCOPING agent whose
12
+ * sole job is to create the per-request focus + reality tree + deliveries and
13
+ * stamp materialized_focus_id back.
14
+ *
15
+ * The in-flight guard is intake_scoping_started_at: stamped when a scoping agent
16
+ * is spawned so the same request is not re-spawned every poll while the run is in
17
+ * flight; the scoping agent stamping materialized_focus_id removes the request
18
+ * from the intake-pending set permanently; a STALE stamp (older than staleMs)
19
+ * lets the daemon re-spawn after a crashed scoping run.
20
+ *
21
+ * decideIntakeSpawn is a pure gate so it is unit-tested without any I/O; the side
22
+ * effects (list / role-resolve / mark / spawn) are injected as deps so the poll
23
+ * wiring is testable with mocks. Mirrors nexus-incoming.ts.
24
+ */
25
+ import { callApi } from './queries/shared.js';
26
+ import { getAgentRoles } from './queries/roles.js';
27
+ import { spawnScopingAgent as defaultSpawnScopingAgent } from './nexus-intake-spawn.js';
28
+ /**
29
+ * Name of the org's auto-seeded, full-codebase agent role. Every organization
30
+ * gets one on creation (migration seed_default_agent_roles: 'Developer',
31
+ * allowed_file_patterns ['**\/*']). It is the zero-config intake fallback so a
32
+ * product that auto-accepts can always resolve SOMEONE to scope the work.
33
+ */
34
+ export const DEFAULT_INTAKE_ROLE_NAME = 'Developer';
35
+ /**
36
+ * Layered intake-role resolution: the product's declared intake role wins, else
37
+ * the org's seeded Developer role, else null (skip). Mirrors the PRD per-entity
38
+ * role signal (prds.assigned_agent_role_id) that replaced the global
39
+ * TELORA_PRD_ARM_ROLE_ID env var -- intake no longer reads any global env var.
40
+ * Co-locating accept + scope on the product means opting into auto-accept also
41
+ * declares who fulfills it; the Developer fallback keeps it zero-config.
42
+ *
43
+ * Takes the two role readers as thunks so the full resolution policy -- the
44
+ * short-circuit (product role wins, the Developer reader is NOT consulted) AND
45
+ * the per-leg best-effort fall-through (a reader that throws degrades to the
46
+ * next leg rather than wedging the whole intake batch) -- lives here, in one
47
+ * unit-testable place, rather than in the production deps closure.
48
+ */
49
+ export async function resolveIntakeRoleLayered(readProductRole, readDeveloperRole, log) {
50
+ let productRoleId = null;
51
+ try {
52
+ productRoleId = await readProductRole();
53
+ }
54
+ catch (err) {
55
+ log?.(`[nexus-intake] product intake-role read failed, falling back to Developer role: ${err.message}`);
56
+ }
57
+ if (productRoleId)
58
+ return productRoleId;
59
+ let developerRoleId = null;
60
+ try {
61
+ developerRoleId = await readDeveloperRole();
62
+ }
63
+ catch (err) {
64
+ log?.(`[nexus-intake] Developer-role read failed, no intake role resolved: ${err.message}`);
65
+ }
66
+ return developerRoleId ?? null;
67
+ }
68
+ /**
69
+ * Default staleness window for an in-flight scoping spawn (20 minutes).
70
+ *
71
+ * MUST be strictly greater than the scoping spawn's kill timeout
72
+ * (INTAKE_SCOPING_TIMEOUT_MS, 15m) plus its SIGKILL grace (10s) so a healthy
73
+ * long-running scoping agent is never treated as stale and re-spawned while it
74
+ * is still finishing (or being torn down). If this equalled the kill timeout a
75
+ * run that legitimately took ~15m could cross the staleness threshold right as
76
+ * it materialized, double-spawning a second scoping agent.
77
+ */
78
+ export const DEFAULT_INTAKE_STALE_MS = 20 * 60 * 1000;
79
+ /**
80
+ * Max scoping agents spawned per poll cycle, per product. Each spawn is a full
81
+ * Claude Code process; an unbounded accepted backlog would otherwise fork a
82
+ * process per request in a single tick. The remainder stays intake-pending
83
+ * (unstamped) and drains on subsequent cycles -- nothing is dropped, only
84
+ * rate-limited. Surfaced via a log line so the cap is never silent.
85
+ */
86
+ export const MAX_INTAKE_SPAWNS_PER_CYCLE = 5;
87
+ /**
88
+ * Pure intake gate. A request needs a scoping spawn when it is accepted, not yet
89
+ * materialized, and either has never been spawned or its last spawn is stale.
90
+ * A recent in-flight stamp holds (no re-spawn). Anything else is skipped.
91
+ */
92
+ export function decideIntakeSpawn(req, nowMs, staleMs = DEFAULT_INTAKE_STALE_MS) {
93
+ if (req.status !== 'accepted')
94
+ return 'skip';
95
+ if (req.materializedFocusId)
96
+ return 'skip';
97
+ const startedAt = req.intakeScopingStartedAt;
98
+ if (!startedAt)
99
+ return 'spawn';
100
+ const startedMs = Date.parse(startedAt);
101
+ // Unparseable timestamp -> treat as no stamp (spawn) rather than wedge forever.
102
+ if (Number.isNaN(startedMs))
103
+ return 'spawn';
104
+ return nowMs - startedMs >= staleMs ? 'spawn' : 'in_flight';
105
+ }
106
+ /** Production deps backed by the product-api over callApi + the real spawn. */
107
+ export function defaultNexusIntakeDeps(config) {
108
+ return {
109
+ listIntakePending: async (productId) => {
110
+ // Pull the full accepted page (max limit), not the default 50, so a larger
111
+ // backlog is visible to the gate; per-cycle spawning is rate-limited by
112
+ // MAX_INTAKE_SPAWNS_PER_CYCLE rather than by an accidental page boundary.
113
+ const res = await callApi('product_request_list', {
114
+ productId,
115
+ direction: 'incoming',
116
+ status: 'accepted',
117
+ limit: 500,
118
+ });
119
+ // accepted + no materialized focus = intake-pending (not yet scoped).
120
+ return (res.requests ?? []).filter((r) => !r.materializedFocusId);
121
+ },
122
+ resolveIntakeRoleId: async () => {
123
+ // Layered resolve (no global env var): the target product's declared
124
+ // intake role wins, else the org's seeded Developer role, else null/skip.
125
+ // The policy (short-circuit + best-effort per-leg fall-through) lives in
126
+ // resolveIntakeRoleLayered; here we only supply the two role readers.
127
+ const productId = config.productId;
128
+ return resolveIntakeRoleLayered(async () => {
129
+ if (!productId)
130
+ return null;
131
+ const res = await callApi('get', { productId });
132
+ return res.product?.nexusIntakeRoleId ?? null;
133
+ }, async () => {
134
+ const roles = await getAgentRoles(config.organizationId ?? '');
135
+ return roles.find((r) => r.name === DEFAULT_INTAKE_ROLE_NAME)?.id ?? null;
136
+ });
137
+ },
138
+ markIntakeScoping: async (requestId) => {
139
+ await callApi('product_request_mark_intake_scoping', { requestId });
140
+ },
141
+ spawnScopingAgent: async (req, roleId) => {
142
+ await defaultSpawnScopingAgent(config, req, roleId);
143
+ },
144
+ };
145
+ }
146
+ /**
147
+ * Poll one product for intake-pending requests and spawn a scoping agent for
148
+ * each. Safe to call every poll cycle: it is a no-op when there is no
149
+ * intake-pending work, the intake role is resolved once per cycle (and skips the
150
+ * whole batch when unset), and individual request failures are logged without
151
+ * aborting the batch. The intake_scoping_started_at stamp is written BEFORE the
152
+ * spawn so a slow/failed spawn does not re-fire on the next tick.
153
+ */
154
+ export async function checkIntakePendingRequests(config, deps = defaultNexusIntakeDeps(config), staleMs = DEFAULT_INTAKE_STALE_MS) {
155
+ const productId = config.productId;
156
+ if (!productId)
157
+ return;
158
+ const log = deps.log ?? ((msg) => console.log(msg));
159
+ let requests;
160
+ try {
161
+ requests = await deps.listIntakePending(productId);
162
+ }
163
+ catch (err) {
164
+ log(`[nexus-intake] failed to list intake-pending requests for ${productId}: ${err.message}`);
165
+ return;
166
+ }
167
+ if (requests.length === 0)
168
+ return;
169
+ const nowMs = Date.now();
170
+ const spawnable = requests.filter((r) => decideIntakeSpawn(r, nowMs, staleMs) === 'spawn');
171
+ if (spawnable.length === 0)
172
+ return;
173
+ // Rate-limit spawns per cycle: each is a full process. The remainder stays
174
+ // unstamped (intake-pending) and is picked up next cycle. Never silent.
175
+ const batch = spawnable.slice(0, MAX_INTAKE_SPAWNS_PER_CYCLE);
176
+ if (spawnable.length > batch.length) {
177
+ log(`[nexus-intake] ${spawnable.length} spawnable request(s) for ${productId}; ` +
178
+ `capping to ${batch.length} this cycle (${spawnable.length - batch.length} deferred to next tick)`);
179
+ }
180
+ let roleId;
181
+ try {
182
+ roleId = await deps.resolveIntakeRoleId();
183
+ }
184
+ catch (err) {
185
+ log(`[nexus-intake] failed to resolve intake role for ${productId}: ${err.message}`);
186
+ return;
187
+ }
188
+ if (!roleId) {
189
+ // No role -> no spawn. With the layered resolve this only fires in the
190
+ // degenerate case where the product declares no nexus_intake_role_id AND the
191
+ // org has no seeded 'Developer' role -- normally one always resolves, so
192
+ // accepted requests never sit intake-pending. Surfacing it stays important
193
+ // (mirrors the PRD loop's skippedNoRole) so the rare degenerate case is not
194
+ // silent.
195
+ log(`[nexus-intake] ${spawnable.length} intake-pending request(s) for ${productId} but ` +
196
+ `no intake role resolved (no product nexus_intake_role_id and no org 'Developer' role) -- skipping`);
197
+ return;
198
+ }
199
+ for (const req of batch) {
200
+ try {
201
+ // Stamp BEFORE the spawn so a slow/failed spawn does not re-fire next tick;
202
+ // a stale stamp re-arms it after staleMs.
203
+ await deps.markIntakeScoping(req.id);
204
+ await deps.spawnScopingAgent(req, roleId);
205
+ log(`[nexus-intake] spawned scoping agent for accepted request ${req.id} (product ${productId})`);
206
+ }
207
+ catch (err) {
208
+ log(`[nexus-intake] failed to spawn scoping agent for request ${req.id}: ${err.message}`);
209
+ }
210
+ }
211
+ }
212
+ //# sourceMappingURL=nexus-intake.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nexus-intake.js","sourceRoot":"","sources":["../src/nexus-intake.ts"],"names":[],"mappings":"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"}
@@ -174,6 +174,19 @@ export interface FocusTeamState {
174
174
  * Escalates and terminates when it reaches SCOPE_COVERAGE_NO_PROGRESS_LIMIT.
175
175
  */
176
176
  noProgressCycles: number;
177
+ /**
178
+ * Re-wake (commit-nudge) attempts spent in the CURRENT dirty episode before
179
+ * the no-progress guard is allowed to terminate the team. When the no-progress
180
+ * watchdog is about to escalate+terminate a team that has produced
181
+ * uncommitted work (a dirty focus worktree) AND a live lead is still
182
+ * reachable, the daemon instead nudges the lead to commit -- keeping the
183
+ * producing team alive so it commits its own work and the delivery advances
184
+ * out of coding without a manual commit. This counter bounds those nudges by
185
+ * the auto-remediation budget so a team that will never commit still
186
+ * eventually escalates. Reset to 0 on any measurable progress, and whenever
187
+ * the worktree is observed clean (the episode is over).
188
+ */
189
+ commitNudgeAttempts: number;
177
190
  /**
178
191
  * SHA-256 hash of the last spawn directive consumed by this team
179
192
  * (computed over { prompt, assembly, model } -- not the assembled output
@@ -211,6 +224,17 @@ export interface ProgressSnapshot {
211
224
  * a moving count is forward motion the daemon drove, not a team stall.
212
225
  */
213
226
  deliveryIterations: Record<string, number>;
227
+ /**
228
+ * Git-activity dimension: the focus worktree's HEAD sha at snapshot time, or
229
+ * null when no worktree is registered / git could not be read. A moving HEAD
230
+ * on the focus branch is forward motion even when delivery/issue STATE is
231
+ * flat -- a team that wrote and committed real code this cycle produced
232
+ * progress the status/issue/gate axes cannot see. Including the head sha in
233
+ * snapshotsEqual makes a fresh commit reset the no-progress counter through
234
+ * the existing snapshot-comparison machinery, so a producing team is not
235
+ * killed as "idle" purely because no DB state moved this cycle.
236
+ */
237
+ focusHeadSha: string | null;
214
238
  }
215
239
  /**
216
240
  * Summary info about a delivery within the focus.
@@ -1 +1 @@
1
- {"version":3,"file":"focus.d.ts","sourceRoot":"","sources":["../../src/types/focus.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"focus.d.ts","sourceRoot":"","sources":["../../src/types/focus.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telora/daemon",
3
- "version": "0.18.37",
3
+ "version": "0.18.49",
4
4
  "description": "Agent orchestration daemon for Telora - spawns and manages Claude Code instances",
5
5
  "type": "module",
6
6
  "bin": {
@@ -37,7 +37,7 @@
37
37
  "//testRunner": "Uses Node.js built-in test runner (node:test) via tsx for TypeScript support. The root package uses Vitest; this is a deliberate choice for the daemon package to avoid framework dependencies. See src/__tests__/ for test files.",
38
38
  "dependencies": {
39
39
  "@telora/daemon-core": "^0.2.49",
40
- "@telora/mcp-products": "^0.22.80",
40
+ "@telora/mcp-products": "^0.22.82",
41
41
  "commander": "^14.0.3",
42
42
  "yaml": "^2.4.0",
43
43
  "zod": "^4.3.6"
@@ -1,21 +0,0 @@
1
- /**
2
- * Orphan cleanup and stale branch pruning for crash recovery.
3
- *
4
- * Processes orphaned worktrees (safety-commit, merge check, remove/preserve)
5
- * and prunes stale agent branches with no worktree and no unmerged commits.
6
- */
7
- import type { DaemonConfig } from './types.js';
8
- import type { OrphanedWorktree, CleanupAction, RecoveryDeps } from './crash-recovery-types.js';
9
- /**
10
- * Clean up all orphaned worktrees. Returns actions taken and
11
- * any preserved orphans that need escalation.
12
- */
13
- export declare function cleanupOrphanedWorktrees(orphans: OrphanedWorktree[], config: DaemonConfig, deps?: RecoveryDeps): Promise<CleanupAction[]>;
14
- /**
15
- * Prune stale agent branches that have no worktree and no unmerged commits.
16
- */
17
- export declare function pruneStaleAgentBranches(config: DaemonConfig): {
18
- pruned: string[];
19
- preserved: string[];
20
- };
21
- //# sourceMappingURL=crash-recovery-cleanup.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"crash-recovery-cleanup.d.ts","sourceRoot":"","sources":["../src/crash-recovery-cleanup.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAS/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAmG/F;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,gBAAgB,EAAE,EAC3B,MAAM,EAAE,YAAY,EACpB,IAAI,GAAE,YAA0B,GAC/B,OAAO,CAAC,aAAa,EAAE,CAAC,CA2E1B;AAgBD;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,YAAY,GACnB;IAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,CAwC3C"}
@@ -1,205 +0,0 @@
1
- /**
2
- * Orphan cleanup and stale branch pruning for crash recovery.
3
- *
4
- * Processes orphaned worktrees (safety-commit, merge check, remove/preserve)
5
- * and prunes stale agent branches with no worktree and no unmerged commits.
6
- */
7
- import { existsSync } from 'node:fs';
8
- import { runGitSync } from './git.js';
9
- import { worktreeHasUncommittedChanges, branchHasUnmergedCommits, safetyCommitWorktree, removeWorktree, } from './worktree.js';
10
- import { ESCALATION_REASONS, ESCALATION_DISPOSITIONS } from '@telora/daemon-core';
11
- import { defaultDeps } from './crash-recovery-types.js';
12
- import { parseWorktreeList } from './crash-recovery-scan.js';
13
- // ── Helpers ──────────────────────────────────────────────────────
14
- /**
15
- * Count unmerged commits on a branch relative to integration.
16
- */
17
- function countUnmergedCommits(branchName, integrationBranch, repoPath) {
18
- const result = runGitSync(['log', '--oneline', `${integrationBranch}..${branchName}`, '--'], repoPath);
19
- if (!result.success)
20
- return 0;
21
- const lines = result.output.trim();
22
- if (lines.length === 0)
23
- return 0;
24
- return lines.split('\n').length;
25
- }
26
- /**
27
- * Process a single orphaned worktree: safety-commit if dirty,
28
- * then remove if merged or preserve if unmerged.
29
- *
30
- * Returns the action taken.
31
- */
32
- function cleanupSingleOrphan(orphan, config) {
33
- const { worktreePath, branchName } = orphan;
34
- const { repoPath, integrationBranch } = config;
35
- let commitHash;
36
- // Step 1: Safety-commit if dirty
37
- if (existsSync(worktreePath) && worktreeHasUncommittedChanges(worktreePath)) {
38
- const deliveryName = branchName.split('/').slice(2).join('/') || 'unknown';
39
- console.log(`[crash-recovery] Safety-committing dirty worktree: ${worktreePath}`);
40
- const hash = safetyCommitWorktree(worktreePath, deliveryName);
41
- if (hash) {
42
- commitHash = hash.trim();
43
- console.log(`[crash-recovery] Safety commit created: ${commitHash.slice(0, 8)} on ${branchName}`);
44
- }
45
- else {
46
- console.warn(`[crash-recovery] Safety commit failed for ${worktreePath}, preserving as-is`);
47
- return {
48
- worktreePath,
49
- branchName,
50
- action: 'preserved',
51
- };
52
- }
53
- }
54
- // Step 2: Check if branch is already merged to integration
55
- const hasUnmerged = branchHasUnmergedCommits(branchName, integrationBranch, repoPath);
56
- if (!hasUnmerged) {
57
- // Fully merged -- safe to remove
58
- console.log(`[crash-recovery] Removing merged orphan: ${worktreePath} [${branchName}]`);
59
- removeWorktree(repoPath, worktreePath, {
60
- branchName,
61
- integrationBranch,
62
- mergeSucceeded: true,
63
- });
64
- // Also delete the branch since it's merged
65
- const deleteResult = runGitSync(['branch', '-d', branchName], repoPath);
66
- if (deleteResult.success) {
67
- console.log(`[crash-recovery] Deleted merged branch: ${branchName}`);
68
- }
69
- return {
70
- worktreePath,
71
- branchName,
72
- action: commitHash ? 'safety-committed-and-removed' : 'removed',
73
- commitHash,
74
- };
75
- }
76
- // Step 3: Unmerged commits -- preserve
77
- const unmergedCount = countUnmergedCommits(branchName, integrationBranch, repoPath);
78
- console.log(`[crash-recovery] Preserving orphan with ${unmergedCount} unmerged commit(s): ${worktreePath} [${branchName}]`);
79
- return {
80
- worktreePath,
81
- branchName,
82
- action: commitHash ? 'safety-committed' : 'preserved',
83
- commitHash,
84
- unmergedCommitCount: unmergedCount,
85
- };
86
- }
87
- // ── Orphan cleanup ───────────────────────────────────────────────
88
- /**
89
- * Clean up all orphaned worktrees. Returns actions taken and
90
- * any preserved orphans that need escalation.
91
- */
92
- export async function cleanupOrphanedWorktrees(orphans, config, deps = defaultDeps) {
93
- const actions = [];
94
- // Mark orphaned sessions as failed in DB
95
- for (const orphan of orphans) {
96
- if (orphan.session) {
97
- try {
98
- await deps.updateSession(orphan.session.id, {
99
- status: 'failed',
100
- exit_reason: 'Daemon crash recovery: session was active when daemon restarted',
101
- exit_category: 'recovery_cleanup',
102
- ended_at: new Date().toISOString(),
103
- });
104
- console.log(`[crash-recovery] Marked session ${orphan.session.id} as failed (crash recovery)`);
105
- }
106
- catch (err) {
107
- console.warn(`[crash-recovery] Failed to update session ${orphan.session.id}: ${err instanceof Error ? err.message : String(err)}`);
108
- }
109
- }
110
- }
111
- // Process each orphan
112
- for (const orphan of orphans) {
113
- try {
114
- const action = cleanupSingleOrphan(orphan, config);
115
- actions.push(action);
116
- }
117
- catch (err) {
118
- console.error(`[crash-recovery] Error cleaning up orphan ${orphan.worktreePath}: ${err instanceof Error ? err.message : String(err)}`);
119
- }
120
- }
121
- // Escalate preserved orphans
122
- const preserved = actions.filter((a) => a.action === 'preserved' || a.action === 'safety-committed');
123
- if (preserved.length > 0) {
124
- const lines = preserved.map((a) => `- ${a.branchName} (${a.worktreePath})` +
125
- (a.unmergedCommitCount ? ` -- ${a.unmergedCommitCount} unmerged commit(s)` : '') +
126
- (a.commitHash ? ` -- safety commit: ${a.commitHash.slice(0, 8)}` : ''));
127
- const description = `Daemon crash recovery found ${preserved.length} orphaned worktree(s) with unmerged work:\n\n` +
128
- lines.join('\n') +
129
- '\n\nThese worktrees have been preserved for manual inspection.';
130
- try {
131
- await deps.createEscalation({
132
- organizationId: config.organizationId,
133
- sessionId: preserved[0].branchName, // No session available, use branch as context
134
- issueId: null,
135
- reasonType: ESCALATION_REASONS.NEEDS_CLARIFICATION,
136
- // Operator triage: an operator inspects the preserved branches and
137
- // decides to merge or delete -- not an intent-owner decision.
138
- disposition: ESCALATION_DISPOSITIONS.NEEDS_OPERATOR,
139
- // Best-effort provenance from the preserved branch (resolved via a
140
- // session row carrying it, when one exists).
141
- anchor: { branch: preserved[0].branchName },
142
- description,
143
- whatWasTried: 'Daemon crash recovery scanned for orphaned worktrees and preserved those with unmerged commits.',
144
- helpNeeded: 'Inspect the preserved branches and either merge them to integration or delete them.',
145
- });
146
- console.log(`[crash-recovery] Created escalation for ${preserved.length} preserved orphan(s)`);
147
- }
148
- catch (err) {
149
- console.warn(`[crash-recovery] Failed to create escalation: ${err instanceof Error ? err.message : String(err)}`);
150
- }
151
- }
152
- return actions;
153
- }
154
- // ── Stale branch pruning ─────────────────────────────────────────
155
- /**
156
- * List all local branches matching the agent/* pattern.
157
- */
158
- function listAgentBranches(repoPath) {
159
- const result = runGitSync(['branch', '--list', 'agent/*'], repoPath);
160
- if (!result.success)
161
- return [];
162
- return result.output
163
- .split('\n')
164
- .map((line) => line.replace(/^[*+]?\s+/, '').trim())
165
- .filter(Boolean);
166
- }
167
- /**
168
- * Prune stale agent branches that have no worktree and no unmerged commits.
169
- */
170
- export function pruneStaleAgentBranches(config) {
171
- const { repoPath, integrationBranch } = config;
172
- const branches = listAgentBranches(repoPath);
173
- const pruned = [];
174
- const preserved = [];
175
- if (branches.length === 0) {
176
- console.log('[crash-recovery] No stale agent branches found');
177
- return { pruned, preserved };
178
- }
179
- // Get set of branches that have active worktrees
180
- const worktreeMap = parseWorktreeList(repoPath);
181
- const worktreeBranches = new Set(worktreeMap.values());
182
- for (const branch of branches) {
183
- // Skip branches with active worktrees
184
- if (worktreeBranches.has(branch))
185
- continue;
186
- // Check for unmerged commits
187
- if (branchHasUnmergedCommits(branch, integrationBranch, repoPath)) {
188
- console.log(`[crash-recovery] Preserving stale branch with unmerged commits: ${branch}`);
189
- preserved.push(branch);
190
- continue;
191
- }
192
- // Safe to delete
193
- const deleteResult = runGitSync(['branch', '-D', branch], repoPath);
194
- if (deleteResult.success) {
195
- console.log(`[crash-recovery] Pruned stale branch: ${branch}`);
196
- pruned.push(branch);
197
- }
198
- else {
199
- console.warn(`[crash-recovery] Failed to prune branch ${branch}: ${deleteResult.error}`);
200
- }
201
- }
202
- console.log(`[crash-recovery] Branch pruning: ${pruned.length} pruned, ${preserved.length} preserved with unmerged work`);
203
- return { pruned, preserved };
204
- }
205
- //# sourceMappingURL=crash-recovery-cleanup.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"crash-recovery-cleanup.js","sourceRoot":"","sources":["../src/crash-recovery-cleanup.ts"],"names":[],"mappings":"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"}
@@ -1,19 +0,0 @@
1
- /**
2
- * Worktree scanning for crash recovery.
3
- *
4
- * Parses `git worktree list` output and reconciles against DB sessions
5
- * and active focuses to classify worktrees as active or orphaned.
6
- */
7
- import type { DaemonConfig } from './types.js';
8
- import type { OrphanedWorktree, RecoveryDeps } from './crash-recovery-types.js';
9
- /**
10
- * Parse `git worktree list --porcelain` to build a map of
11
- * worktree path -> branch name for all registered worktrees.
12
- */
13
- export declare function parseWorktreeList(repoPath: string): Map<string, string>;
14
- /**
15
- * Scan the worktree directory and reconcile against active DB sessions
16
- * to classify each worktree as active or orphaned.
17
- */
18
- export declare function detectOrphanedWorktrees(config: DaemonConfig, deps?: RecoveryDeps): Promise<OrphanedWorktree[]>;
19
- //# sourceMappingURL=crash-recovery-scan.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"crash-recovery-scan.d.ts","sourceRoot":"","sources":["../src/crash-recovery-scan.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,YAAY,CAAC;AAE7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAgBhF;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAiBvE;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,YAAY,EACpB,IAAI,GAAE,YAA0B,GAC/B,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA+G7B"}