@telora/daemon 0.15.1 → 0.15.3
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/README.md +11 -11
- package/build-info.json +2 -2
- package/dist/assembly-engine.d.ts +1 -1
- package/dist/assembly-engine.d.ts.map +1 -1
- package/dist/assembly-resolvers.js +41 -41
- package/dist/assembly-resolvers.js.map +1 -1
- package/dist/branch-status.d.ts +4 -4
- package/dist/branch-status.d.ts.map +1 -1
- package/dist/branch-status.js +23 -23
- package/dist/branch-status.js.map +1 -1
- package/dist/cli/connect.js +1 -1
- package/dist/cli/connect.js.map +1 -1
- package/dist/completion-detector.d.ts +1 -1
- package/dist/completion-detector.js +1 -1
- package/dist/completion-handler.d.ts +1 -1
- package/dist/completion-handler.js +4 -4
- package/dist/completion-handler.js.map +1 -1
- package/dist/condition-evaluators.js +4 -4
- package/dist/condition-evaluators.js.map +1 -1
- package/dist/control-state.d.ts +6 -6
- package/dist/control-state.d.ts.map +1 -1
- package/dist/control-state.js +43 -43
- package/dist/control-state.js.map +1 -1
- package/dist/crash-recovery-scan.d.ts +1 -1
- package/dist/crash-recovery-scan.js +20 -20
- package/dist/crash-recovery-scan.js.map +1 -1
- package/dist/crash-recovery-types.d.ts +3 -3
- package/dist/crash-recovery-types.d.ts.map +1 -1
- package/dist/crash-recovery-types.js +2 -2
- package/dist/crash-recovery-types.js.map +1 -1
- package/dist/crash-recovery.d.ts +3 -3
- package/dist/crash-recovery.d.ts.map +1 -1
- package/dist/crash-recovery.js +21 -21
- package/dist/crash-recovery.js.map +1 -1
- package/dist/daemon-process.d.ts +1 -1
- package/dist/daemon-process.d.ts.map +1 -1
- package/dist/dag-validator.d.ts +6 -6
- package/dist/dag-validator.d.ts.map +1 -1
- package/dist/dag-validator.js +2 -2
- package/dist/dag-validator.js.map +1 -1
- package/dist/delivery-guards.d.ts +1 -1
- package/dist/delivery-guards.js +1 -1
- package/dist/delivery-lifecycle.d.ts +5 -5
- package/dist/delivery-lifecycle.d.ts.map +1 -1
- package/dist/delivery-lifecycle.js +12 -12
- package/dist/delivery-lifecycle.js.map +1 -1
- package/dist/delivery-merge.js +1 -1
- package/dist/delivery-merge.js.map +1 -1
- package/dist/dependency-resolver.d.ts +7 -7
- package/dist/dependency-resolver.d.ts.map +1 -1
- package/dist/dependency-resolver.js.map +1 -1
- package/dist/directive-executor.d.ts +15 -15
- package/dist/directive-executor.d.ts.map +1 -1
- package/dist/directive-executor.js +76 -76
- package/dist/directive-executor.js.map +1 -1
- package/dist/evaluation-context.d.ts +2 -2
- package/dist/evaluation-context.d.ts.map +1 -1
- package/dist/evaluation-context.js +4 -4
- package/dist/evaluation-context.js.map +1 -1
- package/dist/focus-completion-event.d.ts +97 -0
- package/dist/focus-completion-event.d.ts.map +1 -0
- package/dist/focus-completion-event.js +257 -0
- package/dist/focus-completion-event.js.map +1 -0
- package/dist/focus-completion.d.ts +85 -0
- package/dist/focus-completion.d.ts.map +1 -0
- package/dist/focus-completion.js +459 -0
- package/dist/focus-completion.js.map +1 -0
- package/dist/focus-engine.d.ts +47 -0
- package/dist/focus-engine.d.ts.map +1 -0
- package/dist/focus-engine.js +421 -0
- package/dist/focus-engine.js.map +1 -0
- package/dist/focus-executor.d.ts +55 -0
- package/dist/focus-executor.d.ts.map +1 -0
- package/dist/focus-executor.js +549 -0
- package/dist/focus-executor.js.map +1 -0
- package/dist/focus-lifecycle.d.ts +61 -0
- package/dist/focus-lifecycle.d.ts.map +1 -0
- package/dist/focus-lifecycle.js +544 -0
- package/dist/focus-lifecycle.js.map +1 -0
- package/dist/focus-merge.d.ts +77 -0
- package/dist/focus-merge.d.ts.map +1 -0
- package/dist/focus-merge.js +378 -0
- package/dist/focus-merge.js.map +1 -0
- package/dist/focus-prompt-builder.d.ts +35 -0
- package/dist/focus-prompt-builder.d.ts.map +1 -0
- package/dist/focus-prompt-builder.js +138 -0
- package/dist/focus-prompt-builder.js.map +1 -0
- package/dist/focus-provisioning.d.ts +16 -0
- package/dist/focus-provisioning.d.ts.map +1 -0
- package/dist/focus-provisioning.js +119 -0
- package/dist/focus-provisioning.js.map +1 -0
- package/dist/focus-spawn-helpers.d.ts +67 -0
- package/dist/focus-spawn-helpers.d.ts.map +1 -0
- package/dist/focus-spawn-helpers.js +160 -0
- package/dist/focus-spawn-helpers.js.map +1 -0
- package/dist/focus-team-lifecycle.d.ts +50 -0
- package/dist/focus-team-lifecycle.d.ts.map +1 -0
- package/dist/focus-team-lifecycle.js +256 -0
- package/dist/focus-team-lifecycle.js.map +1 -0
- package/dist/focus-team-state.d.ts +24 -0
- package/dist/focus-team-state.d.ts.map +1 -0
- package/dist/focus-team-state.js +43 -0
- package/dist/focus-team-state.js.map +1 -0
- package/dist/focus-worktree-state.d.ts +47 -0
- package/dist/focus-worktree-state.d.ts.map +1 -0
- package/dist/focus-worktree-state.js +104 -0
- package/dist/focus-worktree-state.js.map +1 -0
- package/dist/git-merge.d.ts +5 -5
- package/dist/git-merge.d.ts.map +1 -1
- package/dist/git-merge.js +5 -5
- package/dist/git-merge.js.map +1 -1
- package/dist/git-state-detector.d.ts +1 -1
- package/dist/git-state-detector.js +9 -9
- package/dist/git-state-detector.js.map +1 -1
- package/dist/git-utils.d.ts +1 -1
- package/dist/git-utils.js +1 -1
- package/dist/git.d.ts +2 -2
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +3 -3
- package/dist/git.js.map +1 -1
- package/dist/heartbeat.d.ts +4 -4
- package/dist/heartbeat.d.ts.map +1 -1
- package/dist/heartbeat.js +7 -7
- package/dist/heartbeat.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +10 -10
- package/dist/index.js.map +1 -1
- package/dist/listener-auto-advance.d.ts +2 -2
- package/dist/listener-auto-advance.js +21 -21
- package/dist/listener-auto-advance.js.map +1 -1
- package/dist/listener.d.ts +12 -12
- package/dist/listener.d.ts.map +1 -1
- package/dist/listener.js +80 -75
- package/dist/listener.js.map +1 -1
- package/dist/loop-engine.d.ts +20 -20
- package/dist/loop-engine.d.ts.map +1 -1
- package/dist/loop-engine.js +82 -82
- package/dist/loop-engine.js.map +1 -1
- package/dist/loop-event-bus.d.ts +5 -5
- package/dist/loop-event-bus.d.ts.map +1 -1
- package/dist/loop-event-bus.js +3 -3
- package/dist/loop-llm-client.d.ts +1 -1
- package/dist/loop-llm-client.js +1 -1
- package/dist/loop-variance.d.ts +1 -1
- package/dist/loop-variance.js +1 -1
- package/dist/merge-detector.d.ts +6 -6
- package/dist/merge-detector.d.ts.map +1 -1
- package/dist/merge-detector.js +47 -47
- package/dist/merge-detector.js.map +1 -1
- package/dist/otlp-log-parser.js +2 -2
- package/dist/otlp-log-parser.js.map +1 -1
- package/dist/otlp-metric-parser.js +1 -1
- package/dist/otlp-metric-parser.js.map +1 -1
- package/dist/otlp-receiver.d.ts +1 -1
- package/dist/otlp-receiver.js +7 -7
- package/dist/otlp-receiver.js.map +1 -1
- package/dist/otlp-types.d.ts +1 -1
- package/dist/otlp-types.d.ts.map +1 -1
- package/dist/otlp-types.js +3 -3
- package/dist/otlp-types.js.map +1 -1
- package/dist/output-monitor.d.ts +6 -6
- package/dist/output-monitor.d.ts.map +1 -1
- package/dist/output-monitor.js +11 -11
- package/dist/output-monitor.js.map +1 -1
- package/dist/planning-prompt-builder.d.ts +17 -15
- package/dist/planning-prompt-builder.d.ts.map +1 -1
- package/dist/planning-prompt-builder.js +34 -32
- package/dist/planning-prompt-builder.js.map +1 -1
- package/dist/pm/mitigation-correlator.d.ts +7 -7
- package/dist/pm/mitigation-correlator.d.ts.map +1 -1
- package/dist/pm/mitigation-correlator.js +33 -33
- package/dist/pm/mitigation-correlator.js.map +1 -1
- package/dist/pm-engine.js +1 -1
- package/dist/pm-engine.js.map +1 -1
- package/dist/prompt-builder.d.ts +1 -1
- package/dist/prompt-builder.js +9 -9
- package/dist/prompt-builder.js.map +1 -1
- package/dist/prompts/starter-prompt.d.ts +2 -2
- package/dist/prompts/starter-prompt.d.ts.map +1 -1
- package/dist/prompts/starter-prompt.js +6 -6
- package/dist/qa-crash-recovery.d.ts +10 -10
- package/dist/qa-crash-recovery.d.ts.map +1 -1
- package/dist/qa-crash-recovery.js +32 -32
- package/dist/qa-crash-recovery.js.map +1 -1
- package/dist/qa-dev-server.d.ts +3 -3
- package/dist/qa-dev-server.d.ts.map +1 -1
- package/dist/qa-dev-server.js +3 -3
- package/dist/qa-dev-server.js.map +1 -1
- package/dist/qa-orchestrator.d.ts +18 -18
- package/dist/qa-orchestrator.d.ts.map +1 -1
- package/dist/qa-orchestrator.js +47 -47
- package/dist/qa-orchestrator.js.map +1 -1
- package/dist/qa-provisioner.d.ts +3 -3
- package/dist/qa-provisioner.d.ts.map +1 -1
- package/dist/qa-provisioner.js +14 -14
- package/dist/qa-provisioner.js.map +1 -1
- package/dist/qa-state.d.ts +10 -10
- package/dist/qa-state.d.ts.map +1 -1
- package/dist/qa-state.js +11 -11
- package/dist/qa-state.js.map +1 -1
- package/dist/queries/control-state.d.ts +5 -5
- package/dist/queries/control-state.d.ts.map +1 -1
- package/dist/queries/control-state.js +4 -4
- package/dist/queries/control-state.js.map +1 -1
- package/dist/queries/deliveries.d.ts +28 -24
- package/dist/queries/deliveries.d.ts.map +1 -1
- package/dist/queries/deliveries.js +32 -28
- package/dist/queries/deliveries.js.map +1 -1
- package/dist/queries/focuses.d.ts +97 -0
- package/dist/queries/focuses.d.ts.map +1 -0
- package/dist/queries/focuses.js +136 -0
- package/dist/queries/focuses.js.map +1 -0
- package/dist/queries/index.d.ts +3 -3
- package/dist/queries/index.d.ts.map +1 -1
- package/dist/queries/index.js +2 -2
- package/dist/queries/index.js.map +1 -1
- package/dist/queries/qa.d.ts +16 -16
- package/dist/queries/qa.d.ts.map +1 -1
- package/dist/queries/qa.js +22 -22
- package/dist/queries/qa.js.map +1 -1
- package/dist/queries/schemas.d.ts +40 -34
- package/dist/queries/schemas.d.ts.map +1 -1
- package/dist/queries/schemas.js +31 -26
- package/dist/queries/schemas.js.map +1 -1
- package/dist/queries/sessions.d.ts +1 -1
- package/dist/queries/sessions.d.ts.map +1 -1
- package/dist/queries/sessions.js +2 -2
- package/dist/queries/sessions.js.map +1 -1
- package/dist/queries/shared.js +10 -10
- package/dist/queries/shared.js.map +1 -1
- package/dist/queries/workflows.d.ts +1 -1
- package/dist/queries/workflows.js +1 -1
- package/dist/queries/worktrees.d.ts +7 -7
- package/dist/queries/worktrees.d.ts.map +1 -1
- package/dist/queries/worktrees.js +7 -7
- package/dist/queries/worktrees.js.map +1 -1
- package/dist/review-defect-detector.d.ts +125 -0
- package/dist/review-defect-detector.d.ts.map +1 -0
- package/dist/review-defect-detector.js +289 -0
- package/dist/review-defect-detector.js.map +1 -0
- package/dist/session-lifecycle.d.ts +17 -17
- package/dist/session-lifecycle.d.ts.map +1 -1
- package/dist/session-lifecycle.js +82 -82
- package/dist/session-lifecycle.js.map +1 -1
- package/dist/spawn-cooldown.d.ts +8 -8
- package/dist/spawn-cooldown.d.ts.map +1 -1
- package/dist/spawn-cooldown.js +15 -15
- package/dist/spawn-cooldown.js.map +1 -1
- package/dist/spawn-environment.d.ts +2 -2
- package/dist/spawn-environment.d.ts.map +1 -1
- package/dist/spawn-environment.js +3 -3
- package/dist/spawn-environment.js.map +1 -1
- package/dist/spawner-lifecycle.d.ts +2 -2
- package/dist/spawner-lifecycle.d.ts.map +1 -1
- package/dist/spawner-lifecycle.js +3 -3
- package/dist/spawner-lifecycle.js.map +1 -1
- package/dist/spawner-resolution.d.ts +3 -3
- package/dist/spawner-resolution.d.ts.map +1 -1
- package/dist/spawner-resolution.js +4 -4
- package/dist/spawner-resolution.js.map +1 -1
- package/dist/spawner-stream-handlers.js +2 -2
- package/dist/spawner-stream-handlers.js.map +1 -1
- package/dist/spawner.d.ts +1 -1
- package/dist/spawner.d.ts.map +1 -1
- package/dist/spawner.js +6 -6
- package/dist/spawner.js.map +1 -1
- package/dist/stage-classifier.d.ts +1 -1
- package/dist/stage-classifier.js +1 -1
- package/dist/state-cascade.d.ts +25 -25
- package/dist/state-cascade.d.ts.map +1 -1
- package/dist/state-cascade.js +89 -89
- package/dist/state-cascade.js.map +1 -1
- package/dist/strategy-completion-event.d.ts +37 -3
- package/dist/strategy-completion-event.d.ts.map +1 -1
- package/dist/strategy-completion-event.js +78 -9
- package/dist/strategy-completion-event.js.map +1 -1
- package/dist/strategy-completion.d.ts +11 -0
- package/dist/strategy-completion.d.ts.map +1 -1
- package/dist/strategy-completion.js +22 -1
- package/dist/strategy-completion.js.map +1 -1
- package/dist/strategy-executor.d.ts.map +1 -1
- package/dist/strategy-executor.js +46 -14
- package/dist/strategy-executor.js.map +1 -1
- package/dist/strategy-merge.d.ts.map +1 -1
- package/dist/strategy-merge.js +4 -0
- package/dist/strategy-merge.js.map +1 -1
- package/dist/strategy-team-lifecycle.d.ts.map +1 -1
- package/dist/strategy-team-lifecycle.js +3 -0
- package/dist/strategy-team-lifecycle.js.map +1 -1
- package/dist/supabase.d.ts +4 -4
- package/dist/supabase.d.ts.map +1 -1
- package/dist/supabase.js +5 -5
- package/dist/supabase.js.map +1 -1
- package/dist/task-converter.d.ts +4 -4
- package/dist/task-converter.d.ts.map +1 -1
- package/dist/task-converter.js +1 -1
- package/dist/task-converter.js.map +1 -1
- package/dist/team-prompt-base.d.ts +59 -19
- package/dist/team-prompt-base.d.ts.map +1 -1
- package/dist/team-prompt-base.js +206 -25
- package/dist/team-prompt-base.js.map +1 -1
- package/dist/team-spawner.d.ts +9 -9
- package/dist/team-spawner.d.ts.map +1 -1
- package/dist/team-spawner.js +87 -83
- package/dist/team-spawner.js.map +1 -1
- package/dist/telemetry-writer.d.ts +2 -2
- package/dist/telemetry-writer.d.ts.map +1 -1
- package/dist/templates/claude-md.js +8 -8
- package/dist/templates/claude-settings.d.ts +1 -1
- package/dist/templates/claude-settings.js +2 -2
- package/dist/templates/claude-settings.js.map +1 -1
- package/dist/trigger-executor.d.ts +4 -4
- package/dist/trigger-executor.d.ts.map +1 -1
- package/dist/trigger-executor.js +11 -11
- package/dist/trigger-executor.js.map +1 -1
- package/dist/types/dag.d.ts +1 -1
- package/dist/types/delivery.d.ts +3 -3
- package/dist/types/delivery.d.ts.map +1 -1
- package/dist/types/focus.d.ts +214 -0
- package/dist/types/focus.d.ts.map +1 -0
- package/dist/types/focus.js +5 -0
- package/dist/types/focus.js.map +1 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/merge.d.ts +1 -1
- package/dist/types/session.d.ts +2 -2
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/strategy.d.ts +7 -0
- package/dist/types/strategy.d.ts.map +1 -1
- package/dist/unified-engine-lifecycle.js +11 -11
- package/dist/unified-engine-lifecycle.js.map +1 -1
- package/dist/unified-init.d.ts +1 -1
- package/dist/unified-init.js +9 -9
- package/dist/unified-init.js.map +1 -1
- package/dist/unified-shell-config.d.ts +4 -4
- package/dist/unified-shell-config.d.ts.map +1 -1
- package/dist/unified-shell-config.js +5 -5
- package/dist/unified-shell-config.js.map +1 -1
- package/dist/unified-shell-status.js +3 -3
- package/dist/unified-shell-status.js.map +1 -1
- package/dist/unified-shell.d.ts +1 -1
- package/dist/unified-shell.js +4 -4
- package/dist/unified-shell.js.map +1 -1
- package/dist/workflow-engine.d.ts +1 -1
- package/dist/workflow-engine.d.ts.map +1 -1
- package/dist/worktree-focus.d.ts +69 -0
- package/dist/worktree-focus.d.ts.map +1 -0
- package/dist/worktree-focus.js +214 -0
- package/dist/worktree-focus.js.map +1 -0
- package/dist/worktree.d.ts +10 -10
- package/dist/worktree.d.ts.map +1 -1
- package/dist/worktree.js +39 -39
- package/dist/worktree.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Focus team lifecycle management - terminate, wait, detect deactivated.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from focus-executor.ts. These functions manage the lifecycle
|
|
5
|
+
* of running focus teams (shutdown, deactivation detection, merge checks).
|
|
6
|
+
*/
|
|
7
|
+
import { getReadyFocuses, } from './supabase.js';
|
|
8
|
+
import { sendMessage } from '@telora/daemon-core';
|
|
9
|
+
import { clearNarration } from './heartbeat.js';
|
|
10
|
+
import { getActiveTeams } from './focus-team-state.js';
|
|
11
|
+
import { mergeFocusBranch, escalateMergeConflict } from './focus-merge.js';
|
|
12
|
+
import { mergeIntegrationToMain } from './git-merge.js';
|
|
13
|
+
import { reportGitState } from './supabase.js';
|
|
14
|
+
import { isStatusAgentActionable, isStatusBlocking, isStatusExcludedFromCascade } from './stage-classifier.js';
|
|
15
|
+
import { getFocusDeliveries } from './queries/focuses.js';
|
|
16
|
+
import { configForProduct, findProduct } from './config.js';
|
|
17
|
+
// ── Team lifecycle ──────────────────────────────────────────────────────
|
|
18
|
+
/**
|
|
19
|
+
* Terminate a focus team.
|
|
20
|
+
*
|
|
21
|
+
* Sends a deactivation message via stdin (if open) before SIGTERM
|
|
22
|
+
* to allow the team lead to process the shutdown gracefully.
|
|
23
|
+
*/
|
|
24
|
+
export function terminateTeam(focusId) {
|
|
25
|
+
const activeTeams = getActiveTeams();
|
|
26
|
+
const team = activeTeams.get(focusId);
|
|
27
|
+
if (!team || !team.leadPid)
|
|
28
|
+
return false;
|
|
29
|
+
// Warn if terminating while conflict resolution is in progress
|
|
30
|
+
if (team.resolvingMergeConflict) {
|
|
31
|
+
console.warn(`[focus-executor] Terminating team "${team.focusName}" while merge conflict resolution is in progress`);
|
|
32
|
+
}
|
|
33
|
+
console.log(`[focus-executor] Terminating team for focus "${team.focusName}" (phase: ${team.phase})`);
|
|
34
|
+
team.phase = 'shutting_down';
|
|
35
|
+
clearNarration(focusId);
|
|
36
|
+
try {
|
|
37
|
+
// Send a deactivation message first to let the team lead process it
|
|
38
|
+
if (team.leadStdin) {
|
|
39
|
+
sendMessage(team.leadStdin, 'Pipeline deactivated. Exit now.');
|
|
40
|
+
// Close stdin after a short delay to let the message be processed
|
|
41
|
+
setTimeout(() => {
|
|
42
|
+
try {
|
|
43
|
+
team.leadStdin?.end();
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
console.debug('[focus-executor] stdin.end() failed (may already be closed):', e.message);
|
|
47
|
+
}
|
|
48
|
+
}, 5000);
|
|
49
|
+
}
|
|
50
|
+
// SIGTERM to the lead process -- it should clean up workers
|
|
51
|
+
process.kill(team.leadPid, 'SIGTERM');
|
|
52
|
+
// Escalate to SIGKILL after timeout
|
|
53
|
+
setTimeout(() => {
|
|
54
|
+
if (activeTeams.has(focusId) && team.leadPid) {
|
|
55
|
+
try {
|
|
56
|
+
process.kill(team.leadPid, 'SIGKILL');
|
|
57
|
+
}
|
|
58
|
+
catch (e) {
|
|
59
|
+
console.debug('[focus-executor] SIGKILL failed (process may have exited):', e.message);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}, 30000);
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
console.debug(`[focus-executor] terminateTeam: process may have already exited:`, e.message);
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Wait for a team's process to exit (leave activeTeams).
|
|
72
|
+
*
|
|
73
|
+
* Polls activeTeams until the focus is no longer present,
|
|
74
|
+
* which happens when handleTeamCompletion runs on the 'close' event.
|
|
75
|
+
* If the timeout expires, sends SIGKILL and waits briefly.
|
|
76
|
+
*
|
|
77
|
+
* @param focusId - Focus to wait for
|
|
78
|
+
* @param timeoutMs - Max wait time in ms (default 30s)
|
|
79
|
+
* @returns true if team exited within timeout, false if forced
|
|
80
|
+
*/
|
|
81
|
+
export async function waitForTeamExit(focusId, timeoutMs = 30000) {
|
|
82
|
+
const activeTeams = getActiveTeams();
|
|
83
|
+
const team = activeTeams.get(focusId);
|
|
84
|
+
if (!team)
|
|
85
|
+
return true; // Already gone
|
|
86
|
+
const deadline = Date.now() + timeoutMs;
|
|
87
|
+
const pollMs = 500;
|
|
88
|
+
while (Date.now() < deadline) {
|
|
89
|
+
if (!activeTeams.has(focusId))
|
|
90
|
+
return true;
|
|
91
|
+
await new Promise(resolve => setTimeout(resolve, pollMs));
|
|
92
|
+
}
|
|
93
|
+
// Timeout expired — escalate to SIGKILL
|
|
94
|
+
if (team.leadPid) {
|
|
95
|
+
console.warn(`[focus-executor] Team "${team.focusName}" did not exit within ${timeoutMs}ms, sending SIGKILL`);
|
|
96
|
+
try {
|
|
97
|
+
process.kill(team.leadPid, 'SIGKILL');
|
|
98
|
+
}
|
|
99
|
+
catch { /* process may already be gone */ }
|
|
100
|
+
// Brief wait for SIGKILL to take effect
|
|
101
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
102
|
+
}
|
|
103
|
+
return !activeTeams.has(focusId);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Terminate all active teams.
|
|
107
|
+
*/
|
|
108
|
+
export function terminateAllTeams() {
|
|
109
|
+
const activeTeams = getActiveTeams();
|
|
110
|
+
for (const focusId of activeTeams.keys()) {
|
|
111
|
+
terminateTeam(focusId);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Detect focuses that have been deactivated (agent role removed)
|
|
116
|
+
* and shut down their active teams.
|
|
117
|
+
*/
|
|
118
|
+
export async function detectDeactivatedFocuses(config) {
|
|
119
|
+
const activeTeams = getActiveTeams();
|
|
120
|
+
if (activeTeams.size === 0)
|
|
121
|
+
return;
|
|
122
|
+
try {
|
|
123
|
+
// Aggregate ready focuses across all configured products
|
|
124
|
+
const allReadyFocuses = [];
|
|
125
|
+
for (const product of config.products) {
|
|
126
|
+
const focuses = await getReadyFocuses(config.organizationId, product.id);
|
|
127
|
+
allReadyFocuses.push(...focuses);
|
|
128
|
+
}
|
|
129
|
+
const activeFocusIds = new Set(allReadyFocuses.map(s => s.focus_id));
|
|
130
|
+
for (const [focusId, team] of activeTeams) {
|
|
131
|
+
if (!activeFocusIds.has(focusId) && team.phase !== 'shutting_down' && team.phase !== 'terminated') {
|
|
132
|
+
console.log(`[focus-executor] Focus "${team.focusName}" deactivated -- shutting down team`);
|
|
133
|
+
// Mark the shutdown reason so handleTeamCompletion can skip the merge
|
|
134
|
+
// attempt cleanly when a planning team is cancelled mid-flight.
|
|
135
|
+
team.shutdownReason = 'deactivated';
|
|
136
|
+
terminateTeam(focusId);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
console.warn(`[focus-executor] Failed to check for deactivated focuses:`, err.message);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Check active teams for newly completed deliveries and merge
|
|
146
|
+
* the focus branch to integration incrementally.
|
|
147
|
+
*
|
|
148
|
+
* Called from the poll loop. For each active team, queries delivery
|
|
149
|
+
* statuses and triggers a merge when any delivery reaches verify/done
|
|
150
|
+
* that hasn't already been merged mid-flight.
|
|
151
|
+
*
|
|
152
|
+
* After processing merges, checks if ALL active deliveries are terminal
|
|
153
|
+
* and merged. If so, terminates the team proactively since no more work
|
|
154
|
+
* remains. The focus stays active in the DB -- if new deliveries
|
|
155
|
+
* arrive later, the next poll cycle spawns a fresh team.
|
|
156
|
+
*/
|
|
157
|
+
export async function checkAndMergeCompletedDeliveries(config) {
|
|
158
|
+
const activeTeams = getActiveTeams();
|
|
159
|
+
if (activeTeams.size === 0)
|
|
160
|
+
return;
|
|
161
|
+
for (const [focusId, team] of activeTeams) {
|
|
162
|
+
// Only check teams that are actively executing
|
|
163
|
+
if (team.phase !== 'executing')
|
|
164
|
+
continue;
|
|
165
|
+
// Skip merge attempts while team lead is resolving a merge conflict
|
|
166
|
+
if (team.resolvingMergeConflict) {
|
|
167
|
+
console.log(`[focus-executor] Skipping merge check for "${team.focusName}" -- conflict resolution in progress`);
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
// Use product-scoped config for this team's merge operations
|
|
171
|
+
const teamProduct = findProduct(config, team.productId);
|
|
172
|
+
const teamConfig = teamProduct ? configForProduct(config, teamProduct) : config;
|
|
173
|
+
try {
|
|
174
|
+
const deliveries = await getFocusDeliveries(focusId);
|
|
175
|
+
// Find deliveries in verify/done that we haven't merged for yet
|
|
176
|
+
const newlyCompleted = deliveries.filter(d => !isStatusAgentActionable(d.executionStatus ?? '') && !isStatusBlocking(d.executionStatus ?? '')
|
|
177
|
+
&& !team.mergedDeliveryIds.has(d.id));
|
|
178
|
+
if (newlyCompleted.length > 0) {
|
|
179
|
+
const completedNames = newlyCompleted.map(d => d.name).join(', ');
|
|
180
|
+
console.log(`[focus-executor] ${newlyCompleted.length} delivery(ies) completed mid-flight for "${team.focusName}": ${completedNames} -- merging to integration`);
|
|
181
|
+
// One merge covers all completed deliveries (same branch).
|
|
182
|
+
// Pass the newly-completed IDs so git state is recorded only for
|
|
183
|
+
// these — never for queued/planning deliveries on the same branch.
|
|
184
|
+
const mergeResult = await mergeFocusBranch(teamConfig, team, team.leadSessionId ?? '', team.branchName, newlyCompleted.map(d => d.id));
|
|
185
|
+
if (mergeResult.mergeSucceeded) {
|
|
186
|
+
// Track merged deliveries (git state already reported by mergeFocusBranch)
|
|
187
|
+
for (const d of newlyCompleted) {
|
|
188
|
+
team.mergedDeliveryIds.add(d.id);
|
|
189
|
+
}
|
|
190
|
+
// ── Eager CI: merge integration → main when all deliveries are merged ──
|
|
191
|
+
// Don't wait for team exit — run CI as soon as all work reaches integration.
|
|
192
|
+
if (team.pipelineConfig?.ci?.enabled) {
|
|
193
|
+
const activeDeliveries = deliveries.filter(d => !isStatusExcludedFromCascade(d.executionStatus ?? ''));
|
|
194
|
+
const allMerged = activeDeliveries.length > 0 && activeDeliveries.every(d => team.mergedDeliveryIds.has(d.id));
|
|
195
|
+
if (allMerged) {
|
|
196
|
+
const pushToRemote = team.pipelineConfig?.cd?.enabled ?? false;
|
|
197
|
+
const ciLabel = pushToRemote ? 'CI+CD' : 'CI';
|
|
198
|
+
console.log(`[${ciLabel}] All deliveries merged for "${team.focusName}" -- merging integration to main${pushToRemote ? ' (will push to remote)' : ''}`);
|
|
199
|
+
try {
|
|
200
|
+
const ciResult = await mergeIntegrationToMain({
|
|
201
|
+
config: teamConfig,
|
|
202
|
+
focusName: team.focusName,
|
|
203
|
+
pushToRemote,
|
|
204
|
+
});
|
|
205
|
+
if (ciResult.success) {
|
|
206
|
+
console.log(`[${ciLabel}] Successfully merged integration to main for "${team.focusName}"`);
|
|
207
|
+
for (const d of activeDeliveries) {
|
|
208
|
+
const newState = pushToRemote ? 'pushed_to_remote' : 'merged_to_main';
|
|
209
|
+
reportGitState(d.id, newState).catch(err => console.warn(`[${ciLabel}] reportGitState ${newState} failed for ${d.id}:`, err.message));
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
console.error(`[${ciLabel}] Failed to merge integration to main for "${team.focusName}": ${ciResult.error}`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
catch (err) {
|
|
217
|
+
console.error(`[${ciLabel}] Error merging integration to main for "${team.focusName}":`, err.message);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
console.warn(`[focus-executor] Mid-flight merge failed for "${team.focusName}": ${mergeResult.exitReason}`);
|
|
224
|
+
// Escalate merge conflict for each unmerged delivery
|
|
225
|
+
for (const d of newlyCompleted) {
|
|
226
|
+
escalateMergeConflict({
|
|
227
|
+
organizationId: team.organizationId,
|
|
228
|
+
sessionId: team.leadSessionId ?? '',
|
|
229
|
+
deliveryId: d.id,
|
|
230
|
+
deliveryName: d.name,
|
|
231
|
+
branchName: team.branchName,
|
|
232
|
+
integrationBranch: config.integrationBranch,
|
|
233
|
+
mergeError: mergeResult.exitReason,
|
|
234
|
+
}).catch(err => console.warn(`[focus-executor] escalateMergeConflict failed for ${d.id}:`, err.message));
|
|
235
|
+
}
|
|
236
|
+
// Don't mark as merged -- will retry next poll. Team continues working.
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
// ── All-done detection ──────────────────────────────────────
|
|
240
|
+
// If any delivery is queued or running, the team still has work.
|
|
241
|
+
// Otherwise the team is idle, waiting for the daemon to push new work.
|
|
242
|
+
const teamWork = deliveries.filter(d => isStatusAgentActionable(d.executionStatus ?? ''));
|
|
243
|
+
if (teamWork.length > 0) {
|
|
244
|
+
console.log(`[focus-executor] ${teamWork.length} delivery(ies) still queued/running for "${team.focusName}" -- team continues`);
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
// No queued/running deliveries -- team is idle, completion detector
|
|
248
|
+
// handles the actual idle transition. Log for observability.
|
|
249
|
+
console.log(`[focus-executor] All deliveries complete for "${team.focusName}" -- team is idle`);
|
|
250
|
+
}
|
|
251
|
+
catch (err) {
|
|
252
|
+
console.warn(`[focus-executor] Failed to check completed deliveries for "${team.focusName}":`, err.message);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
//# sourceMappingURL=focus-team-lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"focus-team-lifecycle.js","sourceRoot":"","sources":["../src/focus-team-lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Focus team state management.
|
|
3
|
+
*
|
|
4
|
+
* Tracks active focus teams in memory and provides
|
|
5
|
+
* query/mutation helpers for the active teams map.
|
|
6
|
+
*/
|
|
7
|
+
import type { FocusTeamState, FocusExecutionConfig, PipelineConfig } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Get all active focus teams.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getActiveTeams(): Map<string, FocusTeamState>;
|
|
12
|
+
/**
|
|
13
|
+
* Check if a focus already has an active team.
|
|
14
|
+
*/
|
|
15
|
+
export declare function hasActiveTeam(focusId: string): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Get count of active teams.
|
|
18
|
+
*/
|
|
19
|
+
export declare function getActiveTeamCount(): number;
|
|
20
|
+
/**
|
|
21
|
+
* Derive execution config from focus pipeline config.
|
|
22
|
+
*/
|
|
23
|
+
export declare function deriveExecutionConfig(_pipelineConfig: PipelineConfig | null): FocusExecutionConfig;
|
|
24
|
+
//# sourceMappingURL=focus-team-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"focus-team-state.d.ts","sourceRoot":"","sources":["../src/focus-team-state.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACpB,cAAc,EACf,MAAM,YAAY,CAAC;AAOpB;;GAEG;AACH,wBAAgB,cAAc,IAAI,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAE5D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAUD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,eAAe,EAAE,cAAc,GAAG,IAAI,GAAG,oBAAoB,CAKlG"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Focus team state management.
|
|
3
|
+
*
|
|
4
|
+
* Tracks active focus teams in memory and provides
|
|
5
|
+
* query/mutation helpers for the active teams map.
|
|
6
|
+
*/
|
|
7
|
+
// ── Active teams tracking ────────────────────────────────────────────
|
|
8
|
+
/** Active focus teams: focusId -> FocusTeamState */
|
|
9
|
+
const activeTeams = new Map();
|
|
10
|
+
/**
|
|
11
|
+
* Get all active focus teams.
|
|
12
|
+
*/
|
|
13
|
+
export function getActiveTeams() {
|
|
14
|
+
return activeTeams;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Check if a focus already has an active team.
|
|
18
|
+
*/
|
|
19
|
+
export function hasActiveTeam(focusId) {
|
|
20
|
+
return activeTeams.has(focusId);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get count of active teams.
|
|
24
|
+
*/
|
|
25
|
+
export function getActiveTeamCount() {
|
|
26
|
+
return activeTeams.size;
|
|
27
|
+
}
|
|
28
|
+
// ── Default execution config ─────────────────────────────────────────
|
|
29
|
+
const DEFAULT_EXECUTION_CONFIG = {
|
|
30
|
+
maxWorkers: 3,
|
|
31
|
+
idlePollIntervalMs: 30000,
|
|
32
|
+
activePollIntervalMs: 60000,
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Derive execution config from focus pipeline config.
|
|
36
|
+
*/
|
|
37
|
+
export function deriveExecutionConfig(_pipelineConfig) {
|
|
38
|
+
// For now, use defaults. The teams.enabled flag in pipelineConfig
|
|
39
|
+
// is deprecated — teams are always the execution model.
|
|
40
|
+
// Future: pipelineConfig could specify maxWorkers or parallelism level.
|
|
41
|
+
return { ...DEFAULT_EXECUTION_CONFIG };
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=focus-team-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"focus-team-state.js","sourceRoot":"","sources":["../src/focus-team-state.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,wEAAwE;AAExE,oDAAoD;AACpD,MAAM,WAAW,GAAG,IAAI,GAAG,EAA0B,CAAC;AAEtD;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,OAAO,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,WAAW,CAAC,IAAI,CAAC;AAC1B,CAAC;AAED,wEAAwE;AAExE,MAAM,wBAAwB,GAAyB;IACrD,UAAU,EAAE,CAAC;IACb,kBAAkB,EAAE,KAAK;IACzB,oBAAoB,EAAE,KAAK;CAC5B,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,eAAsC;IAC1E,kEAAkE;IAClE,wDAAwD;IACxD,wEAAwE;IACxE,OAAO,EAAE,GAAG,wBAAwB,EAAE,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Focus worktree state management — write-through cache.
|
|
3
|
+
*
|
|
4
|
+
* Tracks persistent focus worktrees using a local Map as the
|
|
5
|
+
* synchronous read cache, backed by the focus_worktrees DB table.
|
|
6
|
+
*
|
|
7
|
+
* Read path: all get/has/getAll calls are synchronous (Map lookup).
|
|
8
|
+
* Write path: update Map immediately, then fire async DB write.
|
|
9
|
+
* Startup: hydrateFromDb() loads all records from DB into the Map.
|
|
10
|
+
*
|
|
11
|
+
* The Map is authoritative during runtime. The DB is authoritative
|
|
12
|
+
* across restarts. Async DB writes are fire-and-forget with logging.
|
|
13
|
+
*/
|
|
14
|
+
import type { FocusWorktreeInfo } from './types.js';
|
|
15
|
+
/**
|
|
16
|
+
* Hydrate the in-memory cache from the database.
|
|
17
|
+
*
|
|
18
|
+
* Call once during daemon startup, BEFORE rebuildFocusWorktreeState.
|
|
19
|
+
* Stores the productId for subsequent write-through operations.
|
|
20
|
+
*/
|
|
21
|
+
export declare function hydrateFromDb(productId: string): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Get a single focus worktree by focus ID.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getFocusWorktree(focusId: string): FocusWorktreeInfo | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Add or update a focus worktree entry.
|
|
28
|
+
*
|
|
29
|
+
* Updates the Map synchronously, then fires an async DB upsert.
|
|
30
|
+
*/
|
|
31
|
+
export declare function setFocusWorktree(focusId: string, info: FocusWorktreeInfo): void;
|
|
32
|
+
/**
|
|
33
|
+
* Remove a focus worktree entry.
|
|
34
|
+
* Returns whether the entry existed.
|
|
35
|
+
*
|
|
36
|
+
* Deletes from Map synchronously, then fires an async DB remove.
|
|
37
|
+
*/
|
|
38
|
+
export declare function removeFocusWorktree(focusId: string): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Get all focus worktrees.
|
|
41
|
+
*/
|
|
42
|
+
export declare function getAllFocusWorktrees(): Map<string, FocusWorktreeInfo>;
|
|
43
|
+
/**
|
|
44
|
+
* Check if a focus has a persistent worktree.
|
|
45
|
+
*/
|
|
46
|
+
export declare function hasFocusWorktree(focusId: string): boolean;
|
|
47
|
+
//# sourceMappingURL=focus-worktree-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"focus-worktree-state.d.ts","sourceRoot":"","sources":["../src/focus-worktree-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAgBpD;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BpE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAE/E;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAgB/E;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAc5D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAErE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEzD"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Focus worktree state management — write-through cache.
|
|
3
|
+
*
|
|
4
|
+
* Tracks persistent focus worktrees using a local Map as the
|
|
5
|
+
* synchronous read cache, backed by the focus_worktrees DB table.
|
|
6
|
+
*
|
|
7
|
+
* Read path: all get/has/getAll calls are synchronous (Map lookup).
|
|
8
|
+
* Write path: update Map immediately, then fire async DB write.
|
|
9
|
+
* Startup: hydrateFromDb() loads all records from DB into the Map.
|
|
10
|
+
*
|
|
11
|
+
* The Map is authoritative during runtime. The DB is authoritative
|
|
12
|
+
* across restarts. Async DB writes are fire-and-forget with logging.
|
|
13
|
+
*/
|
|
14
|
+
import { upsertWorktreeRecord, removeWorktreeRecord, listWorktreeRecords, } from './queries/worktrees.js';
|
|
15
|
+
// ── Module-level config ──────────────────────────────────────────────
|
|
16
|
+
let configuredProductId = null;
|
|
17
|
+
// ── Persistent worktree tracking ─────────────────────────────────────
|
|
18
|
+
/** Persistent focus worktrees: focusId -> FocusWorktreeInfo */
|
|
19
|
+
const focusWorktrees = new Map();
|
|
20
|
+
/**
|
|
21
|
+
* Hydrate the in-memory cache from the database.
|
|
22
|
+
*
|
|
23
|
+
* Call once during daemon startup, BEFORE rebuildFocusWorktreeState.
|
|
24
|
+
* Stores the productId for subsequent write-through operations.
|
|
25
|
+
*/
|
|
26
|
+
export async function hydrateFromDb(productId) {
|
|
27
|
+
configuredProductId = productId;
|
|
28
|
+
let records;
|
|
29
|
+
try {
|
|
30
|
+
records = await listWorktreeRecords(productId);
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
console.warn(`[worktree-state] Failed to hydrate from DB, starting with empty cache:`, err.message);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
let hydrated = 0;
|
|
37
|
+
for (const record of records) {
|
|
38
|
+
focusWorktrees.set(record.focusId, {
|
|
39
|
+
focusId: record.focusId,
|
|
40
|
+
focusName: '', // Not stored in DB — rebuilt by callers
|
|
41
|
+
worktreePath: record.worktreePath,
|
|
42
|
+
branchName: record.branchName,
|
|
43
|
+
createdAt: new Date(record.createdAt),
|
|
44
|
+
hasQaDevServer: false, // Runtime-only state
|
|
45
|
+
});
|
|
46
|
+
hydrated++;
|
|
47
|
+
}
|
|
48
|
+
if (hydrated > 0) {
|
|
49
|
+
console.log(`[worktree-state] Hydrated ${hydrated} worktree(s) from DB`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get a single focus worktree by focus ID.
|
|
54
|
+
*/
|
|
55
|
+
export function getFocusWorktree(focusId) {
|
|
56
|
+
return focusWorktrees.get(focusId);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Add or update a focus worktree entry.
|
|
60
|
+
*
|
|
61
|
+
* Updates the Map synchronously, then fires an async DB upsert.
|
|
62
|
+
*/
|
|
63
|
+
export function setFocusWorktree(focusId, info) {
|
|
64
|
+
focusWorktrees.set(focusId, info);
|
|
65
|
+
// Write-through: async DB upsert (fire-and-forget)
|
|
66
|
+
upsertWorktreeRecord({
|
|
67
|
+
focusId,
|
|
68
|
+
productId: configuredProductId,
|
|
69
|
+
worktreePath: info.worktreePath,
|
|
70
|
+
branchName: info.branchName,
|
|
71
|
+
status: 'active',
|
|
72
|
+
}).catch((err) => {
|
|
73
|
+
console.warn(`[worktree-state] DB upsert failed for focus ${focusId}:`, err.message);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Remove a focus worktree entry.
|
|
78
|
+
* Returns whether the entry existed.
|
|
79
|
+
*
|
|
80
|
+
* Deletes from Map synchronously, then fires an async DB remove.
|
|
81
|
+
*/
|
|
82
|
+
export function removeFocusWorktree(focusId) {
|
|
83
|
+
const existed = focusWorktrees.delete(focusId);
|
|
84
|
+
if (existed) {
|
|
85
|
+
// Write-through: async DB remove (fire-and-forget)
|
|
86
|
+
removeWorktreeRecord(focusId).catch((err) => {
|
|
87
|
+
console.warn(`[worktree-state] DB remove failed for focus ${focusId}:`, err.message);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return existed;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get all focus worktrees.
|
|
94
|
+
*/
|
|
95
|
+
export function getAllFocusWorktrees() {
|
|
96
|
+
return focusWorktrees;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Check if a focus has a persistent worktree.
|
|
100
|
+
*/
|
|
101
|
+
export function hasFocusWorktree(focusId) {
|
|
102
|
+
return focusWorktrees.has(focusId);
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=focus-worktree-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"focus-worktree-state.js","sourceRoot":"","sources":["../src/focus-worktree-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,wBAAwB,CAAC;AAEhC,wEAAwE;AAExE,IAAI,mBAAmB,GAAkB,IAAI,CAAC;AAE9C,wEAAwE;AAExE,+DAA+D;AAC/D,MAAM,cAAc,GAAG,IAAI,GAAG,EAA6B,CAAC;AAE5D;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,SAAiB;IACnD,mBAAmB,GAAG,SAAS,CAAC;IAEhC,IAAI,OAAO,CAAC;IACZ,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,mBAAmB,CAAC,SAAS,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CACV,wEAAwE,EACvE,GAAa,CAAC,OAAO,CACvB,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE;YACjC,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,SAAS,EAAE,EAAE,EAAE,wCAAwC;YACvD,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,SAAS,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;YACrC,cAAc,EAAE,KAAK,EAAE,qBAAqB;SAC7C,CAAC,CAAC;QACH,QAAQ,EAAE,CAAC;IACb,CAAC;IAED,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,6BAA6B,QAAQ,sBAAsB,CAAC,CAAC;IAC3E,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,OAAO,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACrC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe,EAAE,IAAuB;IACvE,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAElC,mDAAmD;IACnD,oBAAoB,CAAC;QACnB,OAAO;QACP,SAAS,EAAE,mBAAmB;QAC9B,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,MAAM,EAAE,QAAQ;KACjB,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACf,OAAO,CAAC,IAAI,CACV,+CAA+C,OAAO,GAAG,EACxD,GAAa,CAAC,OAAO,CACvB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAe;IACjD,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAE/C,IAAI,OAAO,EAAE,CAAC;QACZ,mDAAmD;QACnD,oBAAoB,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YAC1C,OAAO,CAAC,IAAI,CACV,+CAA+C,OAAO,GAAG,EACxD,GAAa,CAAC,OAAO,CACvB,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB;IAClC,OAAO,cAAc,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,OAAO,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACrC,CAAC"}
|
package/dist/git-merge.d.ts
CHANGED
|
@@ -60,15 +60,15 @@ export interface MergeToIntegrationParams {
|
|
|
60
60
|
export declare function mergeToIntegration(params: MergeToIntegrationParams): Promise<MergeResult>;
|
|
61
61
|
export interface MergeIntegrationToMainParams {
|
|
62
62
|
config: DaemonConfig;
|
|
63
|
-
/**
|
|
64
|
-
|
|
63
|
+
/** Focus name for logging/commit messages. */
|
|
64
|
+
focusName: string;
|
|
65
65
|
/** Whether to also push main to remote (CD). */
|
|
66
66
|
pushToRemote: boolean;
|
|
67
67
|
}
|
|
68
68
|
/**
|
|
69
69
|
* Merge the integration branch into the default (main) branch.
|
|
70
70
|
*
|
|
71
|
-
* Called when a
|
|
71
|
+
* Called when a focus completes with CI enabled. Optionally pushes
|
|
72
72
|
* to remote when CD is also enabled.
|
|
73
73
|
*
|
|
74
74
|
* Uses the merge worktree and merge lock (same as mergeToIntegration)
|
|
@@ -76,7 +76,7 @@ export interface MergeIntegrationToMainParams {
|
|
|
76
76
|
*/
|
|
77
77
|
export declare function mergeIntegrationToMain(params: MergeIntegrationToMainParams): Promise<MergeResult>;
|
|
78
78
|
export interface MergeBackFromIntegrationParams {
|
|
79
|
-
/** Path to the
|
|
79
|
+
/** Path to the focus/delivery worktree. */
|
|
80
80
|
worktreePath: string;
|
|
81
81
|
/** Name of the integration branch (e.g., 'integration'). */
|
|
82
82
|
integrationBranch: string;
|
|
@@ -85,7 +85,7 @@ export interface MergeBackFromIntegrationParams {
|
|
|
85
85
|
* Merge the latest integration HEAD into the current branch of a worktree.
|
|
86
86
|
*
|
|
87
87
|
* This is the "prevent conflicts" layer: by syncing integration changes into
|
|
88
|
-
* the
|
|
88
|
+
* the focus branch before merging to integration, we guarantee the final
|
|
89
89
|
* merge will be conflict-free (or surface conflicts early for agent resolution).
|
|
90
90
|
*
|
|
91
91
|
* On conflict: does NOT abort -- leaves conflict markers in the worktree
|
package/dist/git-merge.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-merge.d.ts","sourceRoot":"","sources":["../src/git-merge.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,EAAc,KAAK,WAAW,EAAE,KAAK,aAAa,EAAwB,MAAM,gBAAgB,CAAC;AACxG,OAAO,EAAyC,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAmCpG,UAAU,yBAAyB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAC;CAC1D;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,yBAAyB,GAAG,WAAW,CAoD5F;AA0HD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,GACpB,WAAW,CA8Cb;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,aAAa,GACtB,WAAW,CAmBb;AAID,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,oBAAoB,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAC9G;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,wBAAwB,GAC/B,OAAO,CAAC,WAAW,CAAC,CA4GtB;AAID,MAAM,WAAW,4BAA4B;IAC3C,MAAM,EAAE,YAAY,CAAC;IACrB,
|
|
1
|
+
{"version":3,"file":"git-merge.d.ts","sourceRoot":"","sources":["../src/git-merge.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,EAAc,KAAK,WAAW,EAAE,KAAK,aAAa,EAAwB,MAAM,gBAAgB,CAAC;AACxG,OAAO,EAAyC,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAmCpG,UAAU,yBAAyB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAC;CAC1D;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,yBAAyB,GAAG,WAAW,CAoD5F;AA0HD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,GACpB,WAAW,CA8Cb;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,aAAa,GACtB,WAAW,CAmBb;AAID,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,oBAAoB,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAC9G;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,wBAAwB,GAC/B,OAAO,CAAC,WAAW,CAAC,CA4GtB;AAID,MAAM,WAAW,4BAA4B;IAC3C,MAAM,EAAE,YAAY,CAAC;IACrB,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,4BAA4B,GACnC,OAAO,CAAC,WAAW,CAAC,CAwFtB;AAID,MAAM,WAAW,8BAA8B;IAC7C,2CAA2C;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,8BAA8B,GACrC,OAAO,CAAC,eAAe,CAAC,CAgE1B"}
|
package/dist/git-merge.js
CHANGED
|
@@ -330,14 +330,14 @@ export function mergeToIntegration(params) {
|
|
|
330
330
|
/**
|
|
331
331
|
* Merge the integration branch into the default (main) branch.
|
|
332
332
|
*
|
|
333
|
-
* Called when a
|
|
333
|
+
* Called when a focus completes with CI enabled. Optionally pushes
|
|
334
334
|
* to remote when CD is also enabled.
|
|
335
335
|
*
|
|
336
336
|
* Uses the merge worktree and merge lock (same as mergeToIntegration)
|
|
337
337
|
* to avoid concurrent merge conflicts.
|
|
338
338
|
*/
|
|
339
339
|
export function mergeIntegrationToMain(params) {
|
|
340
|
-
const { config,
|
|
340
|
+
const { config, focusName, pushToRemote } = params;
|
|
341
341
|
return withMergeLock(async () => {
|
|
342
342
|
const mwt = getMergeWorktreePath(config);
|
|
343
343
|
const mainBranch = getDefaultBranch(config.repoPath);
|
|
@@ -362,7 +362,7 @@ export function mergeIntegrationToMain(params) {
|
|
|
362
362
|
}
|
|
363
363
|
// Save pre-merge state for rollback
|
|
364
364
|
const preMergeRef = runGitSync(['rev-parse', 'HEAD'], mwt);
|
|
365
|
-
const commitMessage = `Merge integration: ${
|
|
365
|
+
const commitMessage = `Merge integration: ${focusName} [CI]`;
|
|
366
366
|
// Try fast-forward first, fall back to merge commit
|
|
367
367
|
let result = tryFastForwardMerge(mwt, config.integrationBranch);
|
|
368
368
|
if (!result.success) {
|
|
@@ -411,13 +411,13 @@ export function mergeIntegrationToMain(params) {
|
|
|
411
411
|
commitSha: result.commitSha,
|
|
412
412
|
preMergeRef: preMergeRef.success ? preMergeRef.output : undefined,
|
|
413
413
|
};
|
|
414
|
-
}, `mergeIntegrationToMain:${
|
|
414
|
+
}, `mergeIntegrationToMain:${focusName}`);
|
|
415
415
|
}
|
|
416
416
|
/**
|
|
417
417
|
* Merge the latest integration HEAD into the current branch of a worktree.
|
|
418
418
|
*
|
|
419
419
|
* This is the "prevent conflicts" layer: by syncing integration changes into
|
|
420
|
-
* the
|
|
420
|
+
* the focus branch before merging to integration, we guarantee the final
|
|
421
421
|
* merge will be conflict-free (or surface conflicts early for agent resolution).
|
|
422
422
|
*
|
|
423
423
|
* On conflict: does NOT abort -- leaves conflict markers in the worktree
|