@telora/daemon 0.18.40 → 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.
- package/build-info.json +4 -3
- package/dist/completion/advanceability.d.ts +66 -0
- package/dist/completion/advanceability.d.ts.map +1 -0
- package/dist/completion/advanceability.js +112 -0
- package/dist/completion/advanceability.js.map +1 -0
- package/dist/completion/event.d.ts +28 -52
- package/dist/completion/event.d.ts.map +1 -1
- package/dist/completion/event.js +79 -99
- package/dist/completion/event.js.map +1 -1
- package/dist/completion/progress-snapshot.d.ts +15 -4
- package/dist/completion/progress-snapshot.d.ts.map +1 -1
- package/dist/completion/progress-snapshot.js +20 -4
- package/dist/completion/progress-snapshot.js.map +1 -1
- package/dist/crash-recovery.d.ts +48 -0
- package/dist/crash-recovery.d.ts.map +1 -1
- package/dist/crash-recovery.js +166 -30
- package/dist/crash-recovery.js.map +1 -1
- package/dist/delivery-advance-block.d.ts +17 -1
- package/dist/delivery-advance-block.d.ts.map +1 -1
- package/dist/delivery-advance-block.js +31 -8
- package/dist/delivery-advance-block.js.map +1 -1
- package/dist/escalation-provenance.d.ts +5 -1
- package/dist/escalation-provenance.d.ts.map +1 -1
- package/dist/escalation-provenance.js +46 -4
- package/dist/escalation-provenance.js.map +1 -1
- package/dist/focus-executor.d.ts.map +1 -1
- package/dist/focus-executor.js +1 -0
- package/dist/focus-executor.js.map +1 -1
- package/dist/git-activity.d.ts +15 -0
- package/dist/git-activity.d.ts.map +1 -1
- package/dist/git-activity.js +24 -0
- package/dist/git-activity.js.map +1 -1
- package/dist/loop-engine-types.d.ts +40 -0
- package/dist/loop-engine-types.d.ts.map +1 -0
- package/dist/loop-engine-types.js +11 -0
- package/dist/loop-engine-types.js.map +1 -0
- package/dist/loop-engine.d.ts +52 -0
- package/dist/loop-engine.d.ts.map +1 -1
- package/dist/loop-engine.js +91 -10
- package/dist/loop-engine.js.map +1 -1
- package/dist/loop-llm-flag.d.ts +32 -0
- package/dist/loop-llm-flag.d.ts.map +1 -0
- package/dist/loop-llm-flag.js +35 -0
- package/dist/loop-llm-flag.js.map +1 -0
- package/dist/loop-operational-block.d.ts +44 -0
- package/dist/loop-operational-block.d.ts.map +1 -0
- package/dist/loop-operational-block.js +47 -0
- package/dist/loop-operational-block.js.map +1 -0
- package/dist/merge-back-loop.d.ts.map +1 -1
- package/dist/merge-back-loop.js +1 -0
- package/dist/merge-back-loop.js.map +1 -1
- package/dist/nexus-intake.d.ts +26 -3
- package/dist/nexus-intake.d.ts.map +1 -1
- package/dist/nexus-intake.js +62 -10
- package/dist/nexus-intake.js.map +1 -1
- package/dist/types/focus.d.ts +24 -0
- package/dist/types/focus.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/crash-recovery-cleanup.d.ts +0 -21
- package/dist/crash-recovery-cleanup.d.ts.map +0 -1
- package/dist/crash-recovery-cleanup.js +0 -205
- package/dist/crash-recovery-cleanup.js.map +0 -1
- package/dist/crash-recovery-scan.d.ts +0 -19
- package/dist/crash-recovery-scan.d.ts.map +0 -1
- package/dist/crash-recovery-scan.js +0 -145
- package/dist/crash-recovery-scan.js.map +0 -1
- package/dist/crash-recovery-types.d.ts +0 -49
- package/dist/crash-recovery-types.d.ts.map +0 -1
- package/dist/crash-recovery-types.js +0 -13
- package/dist/crash-recovery-types.js.map +0 -1
package/dist/nexus-intake.js
CHANGED
|
@@ -23,7 +23,48 @@
|
|
|
23
23
|
* wiring is testable with mocks. Mirrors nexus-incoming.ts.
|
|
24
24
|
*/
|
|
25
25
|
import { callApi } from './queries/shared.js';
|
|
26
|
+
import { getAgentRoles } from './queries/roles.js';
|
|
26
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
|
+
}
|
|
27
68
|
/**
|
|
28
69
|
* Default staleness window for an in-flight scoping spawn (20 minutes).
|
|
29
70
|
*
|
|
@@ -79,11 +120,20 @@ export function defaultNexusIntakeDeps(config) {
|
|
|
79
120
|
return (res.requests ?? []).filter((r) => !r.materializedFocusId);
|
|
80
121
|
},
|
|
81
122
|
resolveIntakeRoleId: async () => {
|
|
82
|
-
//
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
|
|
86
|
-
|
|
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
|
+
});
|
|
87
137
|
},
|
|
88
138
|
markIntakeScoping: async (requestId) => {
|
|
89
139
|
await callApi('product_request_mark_intake_scoping', { requestId });
|
|
@@ -136,12 +186,14 @@ export async function checkIntakePendingRequests(config, deps = defaultNexusInta
|
|
|
136
186
|
return;
|
|
137
187
|
}
|
|
138
188
|
if (!roleId) {
|
|
139
|
-
// No role -> no spawn.
|
|
140
|
-
//
|
|
141
|
-
//
|
|
142
|
-
//
|
|
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.
|
|
143
195
|
log(`[nexus-intake] ${spawnable.length} intake-pending request(s) for ${productId} but ` +
|
|
144
|
-
`
|
|
196
|
+
`no intake role resolved (no product nexus_intake_role_id and no org 'Developer' role) -- skipping`);
|
|
145
197
|
return;
|
|
146
198
|
}
|
|
147
199
|
for (const req of batch) {
|
package/dist/nexus-intake.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nexus-intake.js","sourceRoot":"","sources":["../src/nexus-intake.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,IAAI,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAExF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEtD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC;AAoB7C;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,GAAyB,EACzB,KAAa,EACb,UAAkB,uBAAuB;IAEzC,IAAI,GAAG,CAAC,MAAM,KAAK,UAAU;QAAE,OAAO,MAAM,CAAC;IAC7C,IAAI,GAAG,CAAC,mBAAmB;QAAE,OAAO,MAAM,CAAC;IAC3C,MAAM,SAAS,GAAG,GAAG,CAAC,sBAAsB,CAAC;IAC7C,IAAI,CAAC,SAAS;QAAE,OAAO,OAAO,CAAC;IAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACxC,gFAAgF;IAChF,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC;QAAE,OAAO,OAAO,CAAC;IAC5C,OAAO,KAAK,GAAG,SAAS,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC;AAC9D,CAAC;
|
|
1
|
+
{"version":3,"file":"nexus-intake.js","sourceRoot":"","sources":["../src/nexus-intake.ts"],"names":[],"mappings":"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"}
|
package/dist/types/focus.d.ts
CHANGED
|
@@ -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.
|
|
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.
|
|
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"}
|
|
@@ -1,145 +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 { existsSync, readdirSync, statSync } from 'node:fs';
|
|
8
|
-
import { join, resolve } from 'node:path';
|
|
9
|
-
import { runGitSync } from './git.js';
|
|
10
|
-
import { defaultDeps } from './crash-recovery-types.js';
|
|
11
|
-
// ── Helpers ──────────────────────────────────────────────────────
|
|
12
|
-
/**
|
|
13
|
-
* Extract the focus ID prefix (last 8 hex chars) from a worktree directory name.
|
|
14
|
-
* Focus worktree directories follow: agent-{role}-{name}-{8-char-id}
|
|
15
|
-
*/
|
|
16
|
-
function extractFocusIdPrefix(dirName) {
|
|
17
|
-
const match = dirName.match(/-([0-9a-f]{8})$/);
|
|
18
|
-
return match ? match[1] : null;
|
|
19
|
-
}
|
|
20
|
-
// ── Worktree scanning ────────────────────────────────────────────
|
|
21
|
-
/**
|
|
22
|
-
* Parse `git worktree list --porcelain` to build a map of
|
|
23
|
-
* worktree path -> branch name for all registered worktrees.
|
|
24
|
-
*/
|
|
25
|
-
export function parseWorktreeList(repoPath) {
|
|
26
|
-
const result = runGitSync(['worktree', 'list', '--porcelain'], repoPath);
|
|
27
|
-
const map = new Map();
|
|
28
|
-
if (!result.success)
|
|
29
|
-
return map;
|
|
30
|
-
let currentPath = null;
|
|
31
|
-
for (const line of result.output.split('\n')) {
|
|
32
|
-
if (line.startsWith('worktree ')) {
|
|
33
|
-
currentPath = line.slice('worktree '.length);
|
|
34
|
-
}
|
|
35
|
-
else if (line.startsWith('branch refs/heads/') && currentPath) {
|
|
36
|
-
map.set(currentPath, line.slice('branch refs/heads/'.length));
|
|
37
|
-
currentPath = null;
|
|
38
|
-
}
|
|
39
|
-
else if (line === '') {
|
|
40
|
-
currentPath = null;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
return map;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Scan the worktree directory and reconcile against active DB sessions
|
|
47
|
-
* to classify each worktree as active or orphaned.
|
|
48
|
-
*/
|
|
49
|
-
export async function detectOrphanedWorktrees(config, deps = defaultDeps) {
|
|
50
|
-
const { worktreeDir, repoPath } = config;
|
|
51
|
-
// 1. Read all subdirectories in worktreeDir
|
|
52
|
-
if (!existsSync(worktreeDir))
|
|
53
|
-
return [];
|
|
54
|
-
const entries = readdirSync(worktreeDir);
|
|
55
|
-
const subdirs = entries.filter((entry) => {
|
|
56
|
-
const fullPath = join(worktreeDir, entry);
|
|
57
|
-
try {
|
|
58
|
-
return statSync(fullPath).isDirectory();
|
|
59
|
-
}
|
|
60
|
-
catch (e) {
|
|
61
|
-
console.debug(`[crash-recovery] Failed to stat ${fullPath} (may have been deleted):`, e.message);
|
|
62
|
-
return false;
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
if (subdirs.length === 0)
|
|
66
|
-
return [];
|
|
67
|
-
// 2. Parse git worktree list to map paths -> branch names
|
|
68
|
-
const worktreeMap = parseWorktreeList(repoPath);
|
|
69
|
-
// Build a reverse lookup: resolve worktree paths so we can match
|
|
70
|
-
const pathToBranch = new Map();
|
|
71
|
-
for (const [wtPath, branch] of worktreeMap) {
|
|
72
|
-
pathToBranch.set(resolve(wtPath), branch);
|
|
73
|
-
}
|
|
74
|
-
// 3. Query active sessions from DB
|
|
75
|
-
let activeSessions = [];
|
|
76
|
-
try {
|
|
77
|
-
activeSessions = await deps.getActiveSessions();
|
|
78
|
-
}
|
|
79
|
-
catch (err) {
|
|
80
|
-
console.warn(`[crash-recovery] Failed to query active sessions from DB: ${err instanceof Error ? err.message : String(err)}. ` +
|
|
81
|
-
`Treating all worktrees as orphaned.`);
|
|
82
|
-
}
|
|
83
|
-
// Build set of branch names with active sessions
|
|
84
|
-
const activeBranches = new Set(activeSessions.map((s) => s.branch_name));
|
|
85
|
-
// Build map of branch -> session for linking
|
|
86
|
-
const branchToSession = new Map();
|
|
87
|
-
for (const session of activeSessions) {
|
|
88
|
-
branchToSession.set(session.branch_name, session);
|
|
89
|
-
}
|
|
90
|
-
// 3b. Query active focuses to preserve persistent worktrees
|
|
91
|
-
const activeFocusIdPrefixes = new Set();
|
|
92
|
-
try {
|
|
93
|
-
const activeFocuses = await deps.getActiveFocuses(config.organizationId, config.productId);
|
|
94
|
-
for (const s of activeFocuses) {
|
|
95
|
-
activeFocusIdPrefixes.add(s.focus_id.slice(0, 8));
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
catch (err) {
|
|
99
|
-
console.warn(`[crash-recovery] Failed to query active focuses: ${err instanceof Error ? err.message : String(err)}. ` +
|
|
100
|
-
`Persistent focus worktrees may be incorrectly classified as orphaned.`);
|
|
101
|
-
}
|
|
102
|
-
// 4. Classify each worktree subdirectory
|
|
103
|
-
const orphans = [];
|
|
104
|
-
for (const subdir of subdirs) {
|
|
105
|
-
const fullPath = resolve(join(worktreeDir, subdir));
|
|
106
|
-
const branchName = pathToBranch.get(fullPath);
|
|
107
|
-
if (!branchName) {
|
|
108
|
-
// Directory exists but no git worktree entry -- likely a stale directory.
|
|
109
|
-
// Check if it belongs to an active focus before classifying as orphan.
|
|
110
|
-
const idPrefix = extractFocusIdPrefix(subdir);
|
|
111
|
-
if (idPrefix && activeFocusIdPrefixes.has(idPrefix)) {
|
|
112
|
-
console.log(`[crash-recovery] Worktree belongs to active focus (persistent, no git entry): ${fullPath}`);
|
|
113
|
-
continue;
|
|
114
|
-
}
|
|
115
|
-
// Try to infer branch from directory name (agent-role-delivery pattern).
|
|
116
|
-
console.log(`[crash-recovery] Worktree directory has no git entry: ${fullPath}`);
|
|
117
|
-
orphans.push({
|
|
118
|
-
worktreePath: fullPath,
|
|
119
|
-
branchName: subdir.replace(/-/g, '/').replace(/^agent\//, 'agent/'),
|
|
120
|
-
session: null,
|
|
121
|
-
});
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
if (activeBranches.has(branchName)) {
|
|
125
|
-
// Active session exists -- leave alone
|
|
126
|
-
console.log(`[crash-recovery] Worktree is active (has DB session): ${fullPath} [${branchName}]`);
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
// Check if this worktree belongs to an active focus (persistent worktree)
|
|
130
|
-
const idPrefix = extractFocusIdPrefix(subdir);
|
|
131
|
-
if (idPrefix && activeFocusIdPrefixes.has(idPrefix)) {
|
|
132
|
-
console.log(`[crash-recovery] Worktree belongs to active focus (persistent): ${fullPath} [${branchName}]`);
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
// No active session and no active focus -- orphaned
|
|
136
|
-
const session = branchToSession.get(branchName) ?? null;
|
|
137
|
-
orphans.push({
|
|
138
|
-
worktreePath: fullPath,
|
|
139
|
-
branchName,
|
|
140
|
-
session,
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
return orphans;
|
|
144
|
-
}
|
|
145
|
-
//# sourceMappingURL=crash-recovery-scan.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"crash-recovery-scan.js","sourceRoot":"","sources":["../src/crash-recovery-scan.ts"],"names":[],"mappings":"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"}
|