@telora/factory 0.4.5
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/dist/audit.d.ts +69 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +376 -0
- package/dist/audit.js.map +1 -0
- package/dist/builder-completion.d.ts +35 -0
- package/dist/builder-completion.d.ts.map +1 -0
- package/dist/builder-completion.js +375 -0
- package/dist/builder-completion.js.map +1 -0
- package/dist/builder-spawner.d.ts +40 -0
- package/dist/builder-spawner.d.ts.map +1 -0
- package/dist/builder-spawner.js +493 -0
- package/dist/builder-spawner.js.map +1 -0
- package/dist/completion-gate.d.ts +52 -0
- package/dist/completion-gate.d.ts.map +1 -0
- package/dist/completion-gate.js +336 -0
- package/dist/completion-gate.js.map +1 -0
- package/dist/completion-report.d.ts +36 -0
- package/dist/completion-report.d.ts.map +1 -0
- package/dist/completion-report.js +348 -0
- package/dist/completion-report.js.map +1 -0
- package/dist/completion.d.ts +58 -0
- package/dist/completion.d.ts.map +1 -0
- package/dist/completion.js +287 -0
- package/dist/completion.js.map +1 -0
- package/dist/config.d.ts +16 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +57 -0
- package/dist/config.js.map +1 -0
- package/dist/context-manager.d.ts +152 -0
- package/dist/context-manager.d.ts.map +1 -0
- package/dist/context-manager.js +421 -0
- package/dist/context-manager.js.map +1 -0
- package/dist/crash-detection.d.ts +70 -0
- package/dist/crash-detection.d.ts.map +1 -0
- package/dist/crash-detection.js +123 -0
- package/dist/crash-detection.js.map +1 -0
- package/dist/crash-recovery.d.ts +83 -0
- package/dist/crash-recovery.d.ts.map +1 -0
- package/dist/crash-recovery.js +522 -0
- package/dist/crash-recovery.js.map +1 -0
- package/dist/crash-resolution.d.ts +34 -0
- package/dist/crash-resolution.d.ts.map +1 -0
- package/dist/crash-resolution.js +382 -0
- package/dist/crash-resolution.js.map +1 -0
- package/dist/escalation.d.ts +150 -0
- package/dist/escalation.d.ts.map +1 -0
- package/dist/escalation.js +352 -0
- package/dist/escalation.js.map +1 -0
- package/dist/execution-target.d.ts +31 -0
- package/dist/execution-target.d.ts.map +1 -0
- package/dist/execution-target.js +71 -0
- package/dist/execution-target.js.map +1 -0
- package/dist/execution-unit-init.d.ts +28 -0
- package/dist/execution-unit-init.d.ts.map +1 -0
- package/dist/execution-unit-init.js +115 -0
- package/dist/execution-unit-init.js.map +1 -0
- package/dist/execution.d.ts +17 -0
- package/dist/execution.d.ts.map +1 -0
- package/dist/execution.js +20 -0
- package/dist/execution.js.map +1 -0
- package/dist/factory-engine.d.ts +100 -0
- package/dist/factory-engine.d.ts.map +1 -0
- package/dist/factory-engine.js +243 -0
- package/dist/factory-engine.js.map +1 -0
- package/dist/gap-detection.d.ts +43 -0
- package/dist/gap-detection.d.ts.map +1 -0
- package/dist/gap-detection.js +149 -0
- package/dist/gap-detection.js.map +1 -0
- package/dist/gate-context.d.ts +23 -0
- package/dist/gate-context.d.ts.map +1 -0
- package/dist/gate-context.js +63 -0
- package/dist/gate-context.js.map +1 -0
- package/dist/gate-engine.d.ts +55 -0
- package/dist/gate-engine.d.ts.map +1 -0
- package/dist/gate-engine.js +191 -0
- package/dist/gate-engine.js.map +1 -0
- package/dist/gates/adversarial.d.ts +59 -0
- package/dist/gates/adversarial.d.ts.map +1 -0
- package/dist/gates/adversarial.js +426 -0
- package/dist/gates/adversarial.js.map +1 -0
- package/dist/gates/adversary-spawner.d.ts +35 -0
- package/dist/gates/adversary-spawner.d.ts.map +1 -0
- package/dist/gates/adversary-spawner.js +286 -0
- package/dist/gates/adversary-spawner.js.map +1 -0
- package/dist/gates/adversary-test-dir.d.ts +41 -0
- package/dist/gates/adversary-test-dir.d.ts.map +1 -0
- package/dist/gates/adversary-test-dir.js +150 -0
- package/dist/gates/adversary-test-dir.js.map +1 -0
- package/dist/gates/behavioral-parser.d.ts +32 -0
- package/dist/gates/behavioral-parser.d.ts.map +1 -0
- package/dist/gates/behavioral-parser.js +190 -0
- package/dist/gates/behavioral-parser.js.map +1 -0
- package/dist/gates/behavioral-runner.d.ts +36 -0
- package/dist/gates/behavioral-runner.d.ts.map +1 -0
- package/dist/gates/behavioral-runner.js +306 -0
- package/dist/gates/behavioral-runner.js.map +1 -0
- package/dist/gates/behavioral.d.ts +37 -0
- package/dist/gates/behavioral.d.ts.map +1 -0
- package/dist/gates/behavioral.js +485 -0
- package/dist/gates/behavioral.js.map +1 -0
- package/dist/gates/deterministic.d.ts +24 -0
- package/dist/gates/deterministic.d.ts.map +1 -0
- package/dist/gates/deterministic.js +186 -0
- package/dist/gates/deterministic.js.map +1 -0
- package/dist/git-factory.d.ts +59 -0
- package/dist/git-factory.d.ts.map +1 -0
- package/dist/git-factory.js +102 -0
- package/dist/git-factory.js.map +1 -0
- package/dist/guard-evaluation.d.ts +48 -0
- package/dist/guard-evaluation.d.ts.map +1 -0
- package/dist/guard-evaluation.js +416 -0
- package/dist/guard-evaluation.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/instance-completion.d.ts +34 -0
- package/dist/instance-completion.d.ts.map +1 -0
- package/dist/instance-completion.js +366 -0
- package/dist/instance-completion.js.map +1 -0
- package/dist/instance-lifecycle.d.ts +15 -0
- package/dist/instance-lifecycle.d.ts.map +1 -0
- package/dist/instance-lifecycle.js +18 -0
- package/dist/instance-lifecycle.js.map +1 -0
- package/dist/instance-phase-dispatch.d.ts +75 -0
- package/dist/instance-phase-dispatch.d.ts.map +1 -0
- package/dist/instance-phase-dispatch.js +674 -0
- package/dist/instance-phase-dispatch.js.map +1 -0
- package/dist/instance-poll-loop.d.ts +43 -0
- package/dist/instance-poll-loop.d.ts.map +1 -0
- package/dist/instance-poll-loop.js +360 -0
- package/dist/instance-poll-loop.js.map +1 -0
- package/dist/instance-state-machine.d.ts +52 -0
- package/dist/instance-state-machine.d.ts.map +1 -0
- package/dist/instance-state-machine.js +235 -0
- package/dist/instance-state-machine.js.map +1 -0
- package/dist/log-manager.d.ts +28 -0
- package/dist/log-manager.d.ts.map +1 -0
- package/dist/log-manager.js +71 -0
- package/dist/log-manager.js.map +1 -0
- package/dist/pipeline-evaluator.d.ts +61 -0
- package/dist/pipeline-evaluator.d.ts.map +1 -0
- package/dist/pipeline-evaluator.js +107 -0
- package/dist/pipeline-evaluator.js.map +1 -0
- package/dist/pipeline-metrics.d.ts +52 -0
- package/dist/pipeline-metrics.d.ts.map +1 -0
- package/dist/pipeline-metrics.js +40 -0
- package/dist/pipeline-metrics.js.map +1 -0
- package/dist/pipeline-traversal.d.ts +43 -0
- package/dist/pipeline-traversal.d.ts.map +1 -0
- package/dist/pipeline-traversal.js +68 -0
- package/dist/pipeline-traversal.js.map +1 -0
- package/dist/plan-parser.d.ts +76 -0
- package/dist/plan-parser.d.ts.map +1 -0
- package/dist/plan-parser.js +223 -0
- package/dist/plan-parser.js.map +1 -0
- package/dist/planning-phase.d.ts +52 -0
- package/dist/planning-phase.d.ts.map +1 -0
- package/dist/planning-phase.js +444 -0
- package/dist/planning-phase.js.map +1 -0
- package/dist/planning-prompt.d.ts +64 -0
- package/dist/planning-prompt.d.ts.map +1 -0
- package/dist/planning-prompt.js +251 -0
- package/dist/planning-prompt.js.map +1 -0
- package/dist/planning.d.ts +16 -0
- package/dist/planning.d.ts.map +1 -0
- package/dist/planning.js +17 -0
- package/dist/planning.js.map +1 -0
- package/dist/process-runner.d.ts +41 -0
- package/dist/process-runner.d.ts.map +1 -0
- package/dist/process-runner.js +81 -0
- package/dist/process-runner.js.map +1 -0
- package/dist/product-config.d.ts +34 -0
- package/dist/product-config.d.ts.map +1 -0
- package/dist/product-config.js +43 -0
- package/dist/product-config.js.map +1 -0
- package/dist/queries/cycle-evaluations.d.ts +23 -0
- package/dist/queries/cycle-evaluations.d.ts.map +1 -0
- package/dist/queries/cycle-evaluations.js +37 -0
- package/dist/queries/cycle-evaluations.js.map +1 -0
- package/dist/queries/escalations.d.ts +30 -0
- package/dist/queries/escalations.d.ts.map +1 -0
- package/dist/queries/escalations.js +42 -0
- package/dist/queries/escalations.js.map +1 -0
- package/dist/queries/execution-units.d.ts +76 -0
- package/dist/queries/execution-units.d.ts.map +1 -0
- package/dist/queries/execution-units.js +109 -0
- package/dist/queries/execution-units.js.map +1 -0
- package/dist/queries/gate-results.d.ts +32 -0
- package/dist/queries/gate-results.d.ts.map +1 -0
- package/dist/queries/gate-results.js +44 -0
- package/dist/queries/gate-results.js.map +1 -0
- package/dist/queries/instances.d.ts +51 -0
- package/dist/queries/instances.d.ts.map +1 -0
- package/dist/queries/instances.js +77 -0
- package/dist/queries/instances.js.map +1 -0
- package/dist/queries/sessions.d.ts +50 -0
- package/dist/queries/sessions.d.ts.map +1 -0
- package/dist/queries/sessions.js +81 -0
- package/dist/queries/sessions.js.map +1 -0
- package/dist/queries/shared.d.ts +38 -0
- package/dist/queries/shared.d.ts.map +1 -0
- package/dist/queries/shared.js +119 -0
- package/dist/queries/shared.js.map +1 -0
- package/dist/queries/specs.d.ts +12 -0
- package/dist/queries/specs.d.ts.map +1 -0
- package/dist/queries/specs.js +21 -0
- package/dist/queries/specs.js.map +1 -0
- package/dist/queries/strategies.d.ts +14 -0
- package/dist/queries/strategies.d.ts.map +1 -0
- package/dist/queries/strategies.js +18 -0
- package/dist/queries/strategies.js.map +1 -0
- package/dist/queries/work-units.d.ts +42 -0
- package/dist/queries/work-units.d.ts.map +1 -0
- package/dist/queries/work-units.js +57 -0
- package/dist/queries/work-units.js.map +1 -0
- package/dist/queries/workflows.d.ts +29 -0
- package/dist/queries/workflows.d.ts.map +1 -0
- package/dist/queries/workflows.js +103 -0
- package/dist/queries/workflows.js.map +1 -0
- package/dist/remediation-units.d.ts +40 -0
- package/dist/remediation-units.d.ts.map +1 -0
- package/dist/remediation-units.js +263 -0
- package/dist/remediation-units.js.map +1 -0
- package/dist/replanning.d.ts +72 -0
- package/dist/replanning.d.ts.map +1 -0
- package/dist/replanning.js +403 -0
- package/dist/replanning.js.map +1 -0
- package/dist/resource-limits.d.ts +62 -0
- package/dist/resource-limits.d.ts.map +1 -0
- package/dist/resource-limits.js +322 -0
- package/dist/resource-limits.js.map +1 -0
- package/dist/scheduler.d.ts +98 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +203 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/session-adapter.d.ts +89 -0
- package/dist/session-adapter.d.ts.map +1 -0
- package/dist/session-adapter.js +108 -0
- package/dist/session-adapter.js.map +1 -0
- package/dist/sop-generator.d.ts +29 -0
- package/dist/sop-generator.d.ts.map +1 -0
- package/dist/sop-generator.js +235 -0
- package/dist/sop-generator.js.map +1 -0
- package/dist/spec-profiles.d.ts +41 -0
- package/dist/spec-profiles.d.ts.map +1 -0
- package/dist/spec-profiles.js +131 -0
- package/dist/spec-profiles.js.map +1 -0
- package/dist/strategy-design-graph.d.ts +23 -0
- package/dist/strategy-design-graph.d.ts.map +1 -0
- package/dist/strategy-design-graph.js +205 -0
- package/dist/strategy-design-graph.js.map +1 -0
- package/dist/strategy-design-prompt.d.ts +28 -0
- package/dist/strategy-design-prompt.d.ts.map +1 -0
- package/dist/strategy-design-prompt.js +108 -0
- package/dist/strategy-design-prompt.js.map +1 -0
- package/dist/strategy-design-schema.d.ts +767 -0
- package/dist/strategy-design-schema.d.ts.map +1 -0
- package/dist/strategy-design-schema.js +126 -0
- package/dist/strategy-design-schema.js.map +1 -0
- package/dist/strategy-design.d.ts +69 -0
- package/dist/strategy-design.d.ts.map +1 -0
- package/dist/strategy-design.js +411 -0
- package/dist/strategy-design.js.map +1 -0
- package/dist/strategy-gating.d.ts +31 -0
- package/dist/strategy-gating.d.ts.map +1 -0
- package/dist/strategy-gating.js +276 -0
- package/dist/strategy-gating.js.map +1 -0
- package/dist/team-prompt-builder.d.ts +47 -0
- package/dist/team-prompt-builder.d.ts.map +1 -0
- package/dist/team-prompt-builder.js +362 -0
- package/dist/team-prompt-builder.js.map +1 -0
- package/dist/trace-engine.d.ts +40 -0
- package/dist/trace-engine.d.ts.map +1 -0
- package/dist/trace-engine.js +344 -0
- package/dist/trace-engine.js.map +1 -0
- package/dist/types.d.ts +612 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/unit-session-lifecycle.d.ts +78 -0
- package/dist/unit-session-lifecycle.d.ts.map +1 -0
- package/dist/unit-session-lifecycle.js +141 -0
- package/dist/unit-session-lifecycle.js.map +1 -0
- package/dist/unit-session.d.ts +30 -0
- package/dist/unit-session.d.ts.map +1 -0
- package/dist/unit-session.js +370 -0
- package/dist/unit-session.js.map +1 -0
- package/dist/watchdogs.d.ts +33 -0
- package/dist/watchdogs.d.ts.map +1 -0
- package/dist/watchdogs.js +170 -0
- package/dist/watchdogs.js.map +1 -0
- package/dist/work-unit-scheduler.d.ts +34 -0
- package/dist/work-unit-scheduler.d.ts.map +1 -0
- package/dist/work-unit-scheduler.js +91 -0
- package/dist/work-unit-scheduler.js.map +1 -0
- package/dist/workflow-transition.d.ts +90 -0
- package/dist/workflow-transition.d.ts.map +1 -0
- package/dist/workflow-transition.js +340 -0
- package/dist/workflow-transition.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory instance escalation and stuck detection.
|
|
3
|
+
*
|
|
4
|
+
* Handles escalation when resource limits are hit or the factory gets stuck.
|
|
5
|
+
* Pauses the instance and signals the human via the agent_escalations table.
|
|
6
|
+
*
|
|
7
|
+
* Stuck detection identifies when the same gate is failing N consecutive
|
|
8
|
+
* times with the same error pattern, indicating the builder is unable to
|
|
9
|
+
* make progress.
|
|
10
|
+
*
|
|
11
|
+
* Resume support: when a human resolves the escalation, the instance can
|
|
12
|
+
* transition from 'paused' back to 'building' via resumeInstance().
|
|
13
|
+
*/
|
|
14
|
+
import { updateInstanceStatus, updateInstanceWorkflowStage } from './queries/instances.js';
|
|
15
|
+
import { createFactoryEscalation } from './queries/escalations.js';
|
|
16
|
+
import { getGateResultsByInstance } from './queries/gate-results.js';
|
|
17
|
+
import { getOrResolveWorkflow, attemptTransition } from './workflow-transition.js';
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// Escalation trigger constants
|
|
20
|
+
// ============================================================================
|
|
21
|
+
/** Trigger fired when resource limits (token budget, wall clock, etc.) are exceeded. */
|
|
22
|
+
export const TRIGGER_RESOURCE_LIMIT_EXCEEDED = 'resource_limit_exceeded';
|
|
23
|
+
/** Trigger fired when a builder appears stuck (same gate failure repeated). */
|
|
24
|
+
export const TRIGGER_BUILDER_STUCK = 'builder_stuck';
|
|
25
|
+
/** Trigger fired when a work unit exhausts all gate retry iterations. */
|
|
26
|
+
export const TRIGGER_GATE_FAILURE_EXHAUSTED = 'gate_failure_exhausted';
|
|
27
|
+
/** Trigger fired when strategy-level gate evaluation fails. */
|
|
28
|
+
export const TRIGGER_STRATEGY_GATE_FAILED = 'strategy_gate_failed';
|
|
29
|
+
// ============================================================================
|
|
30
|
+
// Constants
|
|
31
|
+
// ============================================================================
|
|
32
|
+
/** Default number of consecutive same-pattern failures before stuck detection triggers. */
|
|
33
|
+
const DEFAULT_STUCK_THRESHOLD = 3;
|
|
34
|
+
/** Maximum length of error pattern to compare for stuck detection. */
|
|
35
|
+
const ERROR_PATTERN_MAX_LENGTH = 500;
|
|
36
|
+
/** Log prefix for all escalation messages. */
|
|
37
|
+
const LOG_PREFIX = '[escalation]';
|
|
38
|
+
// ============================================================================
|
|
39
|
+
// Escalation entry point
|
|
40
|
+
// ============================================================================
|
|
41
|
+
/**
|
|
42
|
+
* Escalate a factory instance.
|
|
43
|
+
*
|
|
44
|
+
* Sets the instance status to 'paused', records the escalation reason
|
|
45
|
+
* and message on the instance record, and creates an escalation entry
|
|
46
|
+
* in the agent_escalations table to signal the human.
|
|
47
|
+
*
|
|
48
|
+
* @param instanceId - The factory instance UUID.
|
|
49
|
+
* @param reason - Short reason for the escalation (e.g. "token_budget_exceeded").
|
|
50
|
+
* @param message - Detailed human-readable message describing the situation.
|
|
51
|
+
* @param config - Optional escalation configuration overrides.
|
|
52
|
+
* @param sessionId - Optional session ID to link the escalation to.
|
|
53
|
+
*/
|
|
54
|
+
export async function escalateInstance(instanceId, reason, message, config, sessionId) {
|
|
55
|
+
// config is available for future use (e.g., escalation routing rules)
|
|
56
|
+
void config;
|
|
57
|
+
const now = new Date().toISOString();
|
|
58
|
+
console.log(`${LOG_PREFIX} Escalating instance ${instanceId}: ${reason}`);
|
|
59
|
+
// Step 1: Update instance status to paused with escalation fields
|
|
60
|
+
await updateInstanceStatus(instanceId, 'paused', {
|
|
61
|
+
escalationReason: reason,
|
|
62
|
+
escalationMessage: message,
|
|
63
|
+
escalatedAt: now,
|
|
64
|
+
});
|
|
65
|
+
// Step 2: Create an escalation record for the human to review
|
|
66
|
+
await createFactoryEscalation(instanceId, reason, message, undefined, sessionId);
|
|
67
|
+
console.log(`${LOG_PREFIX} Instance ${instanceId} paused and escalation created. ` +
|
|
68
|
+
`Reason: ${reason}`);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Escalate a factory instance using its in-memory state.
|
|
72
|
+
*
|
|
73
|
+
* Attempts a workflow-governed transition from the current status to
|
|
74
|
+
* 'paused'. If the workflow allows it (or no workflow exists), updates
|
|
75
|
+
* in-memory state and persists the escalation.
|
|
76
|
+
*/
|
|
77
|
+
export async function escalateInstanceState(state, reason, message, config, sessionId) {
|
|
78
|
+
// Attempt workflow-governed transition to paused
|
|
79
|
+
const workflow = await getOrResolveWorkflow('factory_instance');
|
|
80
|
+
const ctx = buildEscalationEvalContext(state);
|
|
81
|
+
const transResult = await attemptTransition(workflow, state.status, 'paused', state.productId, 'factory_instance', state.instanceId, ctx);
|
|
82
|
+
if (!transResult.allowed) {
|
|
83
|
+
console.log(`${LOG_PREFIX} Instance ${state.instanceId} transition ${state.status} -> paused ` +
|
|
84
|
+
`blocked by workflow guards -- skipping escalation`);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
state.status = 'paused';
|
|
88
|
+
state.escalatedAt = new Date().toISOString();
|
|
89
|
+
if (transResult.newStageId) {
|
|
90
|
+
state.currentWorkflowStageId = transResult.newStageId;
|
|
91
|
+
await updateInstanceWorkflowStage(state.instanceId, transResult.newStageId, 'paused');
|
|
92
|
+
}
|
|
93
|
+
await escalateInstance(state.instanceId, reason, message, config, sessionId);
|
|
94
|
+
}
|
|
95
|
+
// ============================================================================
|
|
96
|
+
// Resume support
|
|
97
|
+
// ============================================================================
|
|
98
|
+
/**
|
|
99
|
+
* Resume a paused factory instance.
|
|
100
|
+
*
|
|
101
|
+
* Attempts a workflow-governed transition from 'paused' back to 'building'
|
|
102
|
+
* and clears the escalation fields. This is called when a human resolves
|
|
103
|
+
* the escalation and wants the factory to continue.
|
|
104
|
+
*
|
|
105
|
+
* @param instanceId - The factory instance UUID.
|
|
106
|
+
* @param state - The in-memory instance state (if available).
|
|
107
|
+
*/
|
|
108
|
+
export async function resumeInstance(instanceId, state) {
|
|
109
|
+
console.log(`${LOG_PREFIX} Resuming instance ${instanceId} from paused state`);
|
|
110
|
+
// Attempt workflow-governed transition: paused -> building
|
|
111
|
+
if (state) {
|
|
112
|
+
const workflow = await getOrResolveWorkflow('factory_instance');
|
|
113
|
+
const ctx = buildEscalationEvalContext(state);
|
|
114
|
+
const transResult = await attemptTransition(workflow, 'paused', 'building', state.productId, 'factory_instance', instanceId, ctx);
|
|
115
|
+
if (!transResult.allowed) {
|
|
116
|
+
console.log(`${LOG_PREFIX} Instance ${instanceId} transition paused -> building ` +
|
|
117
|
+
`blocked by workflow guards`);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (transResult.newStageId) {
|
|
121
|
+
state.currentWorkflowStageId = transResult.newStageId;
|
|
122
|
+
await updateInstanceWorkflowStage(instanceId, transResult.newStageId, 'building');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
await updateInstanceStatus(instanceId, 'building', {
|
|
126
|
+
escalationReason: null,
|
|
127
|
+
escalationMessage: null,
|
|
128
|
+
escalatedAt: null,
|
|
129
|
+
});
|
|
130
|
+
// Update in-memory state if provided
|
|
131
|
+
if (state) {
|
|
132
|
+
state.status = 'building';
|
|
133
|
+
}
|
|
134
|
+
console.log(`${LOG_PREFIX} Instance ${instanceId} resumed: paused -> building`);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Build a minimal EvaluationContext for escalation transitions.
|
|
138
|
+
*/
|
|
139
|
+
function buildEscalationEvalContext(state) {
|
|
140
|
+
const elapsedSeconds = Math.floor((Date.now() - state.startedAt.getTime()) / 1000);
|
|
141
|
+
return {
|
|
142
|
+
deliveryId: '',
|
|
143
|
+
openIssueCount: 0,
|
|
144
|
+
totalIssueCount: 0,
|
|
145
|
+
issuesByStatus: {},
|
|
146
|
+
issuesByPriority: {},
|
|
147
|
+
lastExitCode: 0,
|
|
148
|
+
sessionCount: state.activeBuilderSessions.size,
|
|
149
|
+
tokensUsed: state.tokensUsed,
|
|
150
|
+
tokenBudget: state.blueprint.maxTokenBudget,
|
|
151
|
+
cycleCount: state.completionGateIterations,
|
|
152
|
+
wallClockSeconds: elapsedSeconds,
|
|
153
|
+
wallClockLimitSeconds: state.blueprint.maxWallClockHours
|
|
154
|
+
? state.blueprint.maxWallClockHours * 3600
|
|
155
|
+
: null,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
// ============================================================================
|
|
159
|
+
// Escalation trigger routing
|
|
160
|
+
// ============================================================================
|
|
161
|
+
/**
|
|
162
|
+
* Check whether a given trigger name is configured in the blueprint's
|
|
163
|
+
* escalation triggers list.
|
|
164
|
+
*
|
|
165
|
+
* If the trigger is in the list, the scenario should cause a pause+escalate.
|
|
166
|
+
* If not, the scenario should cause an immediate failure.
|
|
167
|
+
*
|
|
168
|
+
* @param blueprint - The factory blueprint with escalationTriggers config.
|
|
169
|
+
* @param triggerName - The trigger name to check (e.g. TRIGGER_RESOURCE_LIMIT_EXCEEDED).
|
|
170
|
+
* @returns true if the trigger should cause an escalation.
|
|
171
|
+
*/
|
|
172
|
+
export function shouldEscalate(blueprint, triggerName) {
|
|
173
|
+
return blueprint.escalationTriggers.includes(triggerName);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Route an escalation-worthy event to either pause+escalate or immediate failure.
|
|
177
|
+
*
|
|
178
|
+
* If the trigger name is in the blueprint's escalationTriggers list, pauses
|
|
179
|
+
* the instance and creates an escalation. Otherwise, calls the onFail callback
|
|
180
|
+
* to fail the instance immediately.
|
|
181
|
+
*
|
|
182
|
+
* @param state - The in-memory instance state.
|
|
183
|
+
* @param triggerName - The trigger category (e.g. TRIGGER_RESOURCE_LIMIT_EXCEEDED).
|
|
184
|
+
* @param reason - Short reason for the escalation.
|
|
185
|
+
* @param message - Detailed human-readable message.
|
|
186
|
+
* @param onFail - Callback invoked when the trigger is not configured for escalation.
|
|
187
|
+
* @param config - Optional escalation configuration overrides.
|
|
188
|
+
*/
|
|
189
|
+
export async function escalateOrFail(state, triggerName, reason, message, onFail, config, sessionId) {
|
|
190
|
+
if (shouldEscalate(state.blueprint, triggerName)) {
|
|
191
|
+
await escalateInstanceState(state, reason, message, config, sessionId);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
console.log(`${LOG_PREFIX} Trigger "${triggerName}" not in escalationTriggers -- failing instead of escalating`);
|
|
195
|
+
await onFail();
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// ============================================================================
|
|
199
|
+
// Stuck detection
|
|
200
|
+
// ============================================================================
|
|
201
|
+
/**
|
|
202
|
+
* Detect whether any strategies in an instance appear to be stuck.
|
|
203
|
+
*
|
|
204
|
+
* A strategy is considered "stuck" when the same gate has failed N
|
|
205
|
+
* consecutive times (where N is the stuckThreshold) with the same
|
|
206
|
+
* error pattern. This indicates the builder is unable to make progress
|
|
207
|
+
* despite retries.
|
|
208
|
+
*
|
|
209
|
+
* Gate results are grouped by strategy_id and analyzed per-strategy.
|
|
210
|
+
*
|
|
211
|
+
* @param instanceState - The in-memory state of the factory instance.
|
|
212
|
+
* @param config - Optional escalation configuration overrides.
|
|
213
|
+
* @returns Array of stuck detection results (one per stuck strategy).
|
|
214
|
+
*/
|
|
215
|
+
export async function detectStuckStrategies(instanceState, config) {
|
|
216
|
+
const threshold = config?.stuckThreshold ?? DEFAULT_STUCK_THRESHOLD;
|
|
217
|
+
const allGateResults = await getGateResultsByInstance(instanceState.instanceId);
|
|
218
|
+
const results = [];
|
|
219
|
+
// Group gate results by strategy
|
|
220
|
+
const byStrategy = new Map();
|
|
221
|
+
for (const gr of allGateResults) {
|
|
222
|
+
if (!gr.strategyId)
|
|
223
|
+
continue;
|
|
224
|
+
const existing = byStrategy.get(gr.strategyId);
|
|
225
|
+
if (existing) {
|
|
226
|
+
existing.push(gr);
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
byStrategy.set(gr.strategyId, [gr]);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
for (const [strategyId, gateResults] of byStrategy) {
|
|
233
|
+
const stuckResult = analyzeGateResultsForStuck(strategyId, gateResults, threshold);
|
|
234
|
+
if (stuckResult.isStuck) {
|
|
235
|
+
results.push(stuckResult);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return results;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Check stuck detection and escalate or fail based on blueprint triggers.
|
|
242
|
+
*
|
|
243
|
+
* Convenience function that combines detectStuckStrategies() with
|
|
244
|
+
* escalateOrFail(). Returns true if the instance was escalated or failed.
|
|
245
|
+
*
|
|
246
|
+
* @param onFail - Callback invoked when TRIGGER_BUILDER_STUCK is not in
|
|
247
|
+
* escalationTriggers and the instance should fail instead.
|
|
248
|
+
*/
|
|
249
|
+
export async function checkAndEscalateIfStuck(state, onFail, config) {
|
|
250
|
+
const stuckStrategies = await detectStuckStrategies(state, config);
|
|
251
|
+
if (stuckStrategies.length === 0) {
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
// Build a detailed message from all stuck strategies
|
|
255
|
+
const details = stuckStrategies.map((s) => {
|
|
256
|
+
const pattern = s.errorPattern
|
|
257
|
+
? `: "${s.errorPattern.slice(0, 200)}${s.errorPattern.length > 200 ? '...' : ''}"`
|
|
258
|
+
: '';
|
|
259
|
+
return (`Strategy ${s.strategyId} stuck at ${s.gateType ?? 'unknown'} gate ` +
|
|
260
|
+
`(${s.consecutiveFailures} consecutive failures with same error pattern${pattern})`);
|
|
261
|
+
});
|
|
262
|
+
const reason = 'stuck_detected';
|
|
263
|
+
const message = `Factory instance is stuck. ${stuckStrategies.length} strategy(ies) are failing ` +
|
|
264
|
+
`repeatedly with the same error:\n\n${details.join('\n')}`;
|
|
265
|
+
await escalateOrFail(state, TRIGGER_BUILDER_STUCK, reason, message, onFail, config);
|
|
266
|
+
return true;
|
|
267
|
+
}
|
|
268
|
+
// ============================================================================
|
|
269
|
+
// Pure analysis helpers
|
|
270
|
+
// ============================================================================
|
|
271
|
+
/**
|
|
272
|
+
* Analyze gate results for a single strategy to detect stuck patterns.
|
|
273
|
+
*
|
|
274
|
+
* Looks at the most recent gate results in reverse chronological order.
|
|
275
|
+
* If N consecutive failed results have the same gate type and normalized
|
|
276
|
+
* error output, the strategy is considered stuck.
|
|
277
|
+
*/
|
|
278
|
+
export function analyzeGateResultsForStuck(strategyId, gateResults, threshold) {
|
|
279
|
+
const notStuck = {
|
|
280
|
+
isStuck: false,
|
|
281
|
+
strategyId,
|
|
282
|
+
gateType: null,
|
|
283
|
+
errorPattern: null,
|
|
284
|
+
consecutiveFailures: 0,
|
|
285
|
+
};
|
|
286
|
+
if (gateResults.length < threshold) {
|
|
287
|
+
return notStuck;
|
|
288
|
+
}
|
|
289
|
+
// Sort by creation time descending (most recent first)
|
|
290
|
+
const sorted = [...gateResults].sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
|
291
|
+
// Get the most recent failed results
|
|
292
|
+
const recentFailed = [];
|
|
293
|
+
for (const result of sorted) {
|
|
294
|
+
if (!result.passed) {
|
|
295
|
+
recentFailed.push(result);
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
// Stop at the first passing result -- the streak is broken
|
|
299
|
+
break;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
if (recentFailed.length < threshold) {
|
|
303
|
+
return notStuck;
|
|
304
|
+
}
|
|
305
|
+
// Check if the N most recent failures share the same gate type and error pattern
|
|
306
|
+
const referenceResult = recentFailed[0];
|
|
307
|
+
const referencePattern = normalizeErrorPattern(referenceResult.output);
|
|
308
|
+
const referenceGateType = referenceResult.gateType;
|
|
309
|
+
let consecutiveCount = 0;
|
|
310
|
+
for (const result of recentFailed) {
|
|
311
|
+
if (result.gateType !== referenceGateType) {
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
const pattern = normalizeErrorPattern(result.output);
|
|
315
|
+
if (pattern !== referencePattern) {
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
consecutiveCount++;
|
|
319
|
+
}
|
|
320
|
+
if (consecutiveCount >= threshold) {
|
|
321
|
+
return {
|
|
322
|
+
isStuck: true,
|
|
323
|
+
strategyId,
|
|
324
|
+
gateType: referenceGateType,
|
|
325
|
+
errorPattern: referencePattern,
|
|
326
|
+
consecutiveFailures: consecutiveCount,
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
return notStuck;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Normalize an error output string for pattern comparison.
|
|
333
|
+
*
|
|
334
|
+
* Applies the following normalizations:
|
|
335
|
+
* - Trims whitespace
|
|
336
|
+
* - Collapses multiple whitespace to single space
|
|
337
|
+
* - Truncates to ERROR_PATTERN_MAX_LENGTH characters
|
|
338
|
+
* - Returns empty string for null/undefined input
|
|
339
|
+
*
|
|
340
|
+
* This allows comparing error outputs that differ only in timestamps,
|
|
341
|
+
* line numbers, or minor formatting variations.
|
|
342
|
+
*/
|
|
343
|
+
export function normalizeErrorPattern(output) {
|
|
344
|
+
if (!output) {
|
|
345
|
+
return '';
|
|
346
|
+
}
|
|
347
|
+
return output
|
|
348
|
+
.trim()
|
|
349
|
+
.replace(/\s+/g, ' ')
|
|
350
|
+
.slice(0, ERROR_PATTERN_MAX_LENGTH);
|
|
351
|
+
}
|
|
352
|
+
//# sourceMappingURL=escalation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"escalation.js","sourceRoot":"","sources":["../src/escalation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builder execution target -- bridges TriggerExecutionTarget to a running builder.
|
|
3
|
+
*
|
|
4
|
+
* The BuilderExecutionTarget wraps a BuilderState (with its stdin handle) and
|
|
5
|
+
* implements TriggerExecutionTarget for sending stream-json messages to the
|
|
6
|
+
* builder process.
|
|
7
|
+
*
|
|
8
|
+
* Extracted from execution.ts for focused module boundaries.
|
|
9
|
+
*/
|
|
10
|
+
import type { BuilderState, FactoryInstanceState, TriggerExecutionTarget, ContextDirective } from './types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Wraps a BuilderState (with its stdin handle) as a TriggerExecutionTarget.
|
|
13
|
+
*
|
|
14
|
+
* Writes stream-json messages to the builder's stdin pipe.
|
|
15
|
+
* Handles edge cases: stdin already closed, write errors.
|
|
16
|
+
*/
|
|
17
|
+
export declare class BuilderExecutionTarget implements TriggerExecutionTarget {
|
|
18
|
+
private readonly builder;
|
|
19
|
+
constructor(builder: BuilderState);
|
|
20
|
+
injectPrompt(prompt: string): Promise<void>;
|
|
21
|
+
manageContext(directive: ContextDirective): Promise<void>;
|
|
22
|
+
setField(fieldName: string, fieldValue: unknown): Promise<void>;
|
|
23
|
+
notify(recipients: string[], message: string): Promise<void>;
|
|
24
|
+
private sendMessage;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Look up the active builder for a work unit and return it as a TriggerExecutionTarget.
|
|
28
|
+
* Returns null if no active builder exists for the given work unit.
|
|
29
|
+
*/
|
|
30
|
+
export declare function getBuilderTarget(state: FactoryInstanceState, workUnitId: string): TriggerExecutionTarget | null;
|
|
31
|
+
//# sourceMappingURL=execution-target.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution-target.d.ts","sourceRoot":"","sources":["../src/execution-target.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EACpB,sBAAsB,EACtB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAWpB;;;;;GAKG;AACH,qBAAa,sBAAuB,YAAW,sBAAsB;IACvD,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,YAAY;IAE5C,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C,aAAa,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IASzD,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/D,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlE,OAAO,CAAC,WAAW;CAcpB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,oBAAoB,EAC3B,UAAU,EAAE,MAAM,GACjB,sBAAsB,GAAG,IAAI,CAM/B"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builder execution target -- bridges TriggerExecutionTarget to a running builder.
|
|
3
|
+
*
|
|
4
|
+
* The BuilderExecutionTarget wraps a BuilderState (with its stdin handle) and
|
|
5
|
+
* implements TriggerExecutionTarget for sending stream-json messages to the
|
|
6
|
+
* builder process.
|
|
7
|
+
*
|
|
8
|
+
* Extracted from execution.ts for focused module boundaries.
|
|
9
|
+
*/
|
|
10
|
+
import { executeDirective } from './context-manager.js';
|
|
11
|
+
/** Log prefix for execution-target messages. */
|
|
12
|
+
const LOG_PREFIX = '[execution]';
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Builder execution target
|
|
15
|
+
// ============================================================================
|
|
16
|
+
/**
|
|
17
|
+
* Wraps a BuilderState (with its stdin handle) as a TriggerExecutionTarget.
|
|
18
|
+
*
|
|
19
|
+
* Writes stream-json messages to the builder's stdin pipe.
|
|
20
|
+
* Handles edge cases: stdin already closed, write errors.
|
|
21
|
+
*/
|
|
22
|
+
export class BuilderExecutionTarget {
|
|
23
|
+
builder;
|
|
24
|
+
constructor(builder) {
|
|
25
|
+
this.builder = builder;
|
|
26
|
+
}
|
|
27
|
+
async injectPrompt(prompt) {
|
|
28
|
+
this.sendMessage(prompt, 'inject_prompt');
|
|
29
|
+
}
|
|
30
|
+
async manageContext(directive) {
|
|
31
|
+
const message = executeDirective(directive);
|
|
32
|
+
if (message) {
|
|
33
|
+
this.sendMessage(message, 'manage_context');
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
console.log(`${LOG_PREFIX} manageContext directive '${directive.type}' produced no payload (handled externally or skipped)`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async setField(fieldName, fieldValue) {
|
|
40
|
+
console.log(`${LOG_PREFIX} setField("${fieldName}", ${JSON.stringify(fieldValue)}) on builder ${this.builder.sessionId} -- no-op for builder sessions`);
|
|
41
|
+
}
|
|
42
|
+
async notify(recipients, message) {
|
|
43
|
+
console.log(`${LOG_PREFIX} notify(${JSON.stringify(recipients)}, "${message}") on builder ${this.builder.sessionId}`);
|
|
44
|
+
}
|
|
45
|
+
sendMessage(content, action) {
|
|
46
|
+
const { stdin } = this.builder;
|
|
47
|
+
if (!stdin || stdin.destroyed) {
|
|
48
|
+
console.warn(`${LOG_PREFIX} Cannot send ${action} to builder ${this.builder.sessionId} -- stdin closed`);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const payload = JSON.stringify({ type: 'user', content });
|
|
53
|
+
stdin.write(payload + '\n');
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
console.warn(`${LOG_PREFIX} Failed to write ${action} to builder ${this.builder.sessionId}: ${err.message}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Look up the active builder for a work unit and return it as a TriggerExecutionTarget.
|
|
62
|
+
* Returns null if no active builder exists for the given work unit.
|
|
63
|
+
*/
|
|
64
|
+
export function getBuilderTarget(state, workUnitId) {
|
|
65
|
+
const builder = state.activeBuilderSessions.get(workUnitId);
|
|
66
|
+
if (!builder || !builder.stdin || builder.stdin.destroyed) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
return new BuilderExecutionTarget(builder);
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=execution-target.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution-target.js","sourceRoot":"","sources":["../src/execution-target.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AASH,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,gDAAgD;AAChD,MAAM,UAAU,GAAG,aAAa,CAAC;AAEjC,+EAA+E;AAC/E,2BAA2B;AAC3B,+EAA+E;AAE/E;;;;;GAKG;AACH,MAAM,OAAO,sBAAsB;IACJ;IAA7B,YAA6B,OAAqB;QAArB,YAAO,GAAP,OAAO,CAAc;IAAG,CAAC;IAEtD,KAAK,CAAC,YAAY,CAAC,MAAc;QAC/B,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,SAA2B;QAC7C,MAAM,OAAO,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAC5C,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;QAC9C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,GAAG,UAAU,6BAA6B,SAAS,CAAC,IAAI,uDAAuD,CAAC,CAAC;QAC/H,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,SAAiB,EAAE,UAAmB;QACnD,OAAO,CAAC,GAAG,CAAC,GAAG,UAAU,cAAc,SAAS,MAAM,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,gBAAgB,IAAI,CAAC,OAAO,CAAC,SAAS,gCAAgC,CAAC,CAAC;IAC1J,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,UAAoB,EAAE,OAAe;QAChD,OAAO,CAAC,GAAG,CAAC,GAAG,UAAU,WAAW,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,OAAO,iBAAiB,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IACxH,CAAC;IAEO,WAAW,CAAC,OAAe,EAAE,MAAc;QACjD,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC,GAAG,UAAU,gBAAgB,MAAM,eAAe,IAAI,CAAC,OAAO,CAAC,SAAS,kBAAkB,CAAC,CAAC;YACzG,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;YAC1D,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,GAAG,UAAU,oBAAoB,MAAM,eAAe,IAAI,CAAC,OAAO,CAAC,SAAS,KAAM,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1H,CAAC;IACH,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAA2B,EAC3B,UAAkB;IAElB,MAAM,OAAO,GAAG,KAAK,CAAC,qBAAqB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC5D,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;QAC1D,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execution unit initialization.
|
|
3
|
+
*
|
|
4
|
+
* Creates execution unit rows in the DB when a factory instance transitions
|
|
5
|
+
* to building. Each unit starts as 'idle', ready for strategy assignment
|
|
6
|
+
* by the scheduler.
|
|
7
|
+
*/
|
|
8
|
+
import type { FactoryInstanceState } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Initialize execution units for a factory instance entering the building phase.
|
|
11
|
+
*
|
|
12
|
+
* Creates N execution unit rows in the DB (N = blueprint.executionUnitCount)
|
|
13
|
+
* and populates the in-memory executionUnits map on the instance state.
|
|
14
|
+
* Each unit gets a sequential slot_index (0..N-1), starts as 'idle',
|
|
15
|
+
* and inherits the model from the blueprint's execution unit config.
|
|
16
|
+
*
|
|
17
|
+
* Called once when an instance transitions from planning to building.
|
|
18
|
+
*/
|
|
19
|
+
export declare function initializeExecutionUnits(state: FactoryInstanceState): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Restore execution units from DB into in-memory state.
|
|
22
|
+
*
|
|
23
|
+
* Used during daemon restart (adoptActiveInstance) to rebuild the
|
|
24
|
+
* executionUnits map from existing DB rows. Units that were 'running'
|
|
25
|
+
* are reset to 'idle' since their sessions are gone.
|
|
26
|
+
*/
|
|
27
|
+
export declare function restoreExecutionUnits(state: FactoryInstanceState): Promise<void>;
|
|
28
|
+
//# sourceMappingURL=execution-unit-init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution-unit-init.d.ts","sourceRoot":"","sources":["../src/execution-unit-init.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,oBAAoB,EAErB,MAAM,YAAY,CAAC;AAKpB;;;;;;;;;GASG;AACH,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,oBAAoB,GAC1B,OAAO,CAAC,IAAI,CAAC,CA6Cf;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,oBAAoB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAyDf"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execution unit initialization.
|
|
3
|
+
*
|
|
4
|
+
* Creates execution unit rows in the DB when a factory instance transitions
|
|
5
|
+
* to building. Each unit starts as 'idle', ready for strategy assignment
|
|
6
|
+
* by the scheduler.
|
|
7
|
+
*/
|
|
8
|
+
import { createExecutionUnit, getExecutionUnitsByInstance, updateExecutionUnit } from './queries/execution-units.js';
|
|
9
|
+
const LOG_PREFIX = '[factory-init]';
|
|
10
|
+
/**
|
|
11
|
+
* Initialize execution units for a factory instance entering the building phase.
|
|
12
|
+
*
|
|
13
|
+
* Creates N execution unit rows in the DB (N = blueprint.executionUnitCount)
|
|
14
|
+
* and populates the in-memory executionUnits map on the instance state.
|
|
15
|
+
* Each unit gets a sequential slot_index (0..N-1), starts as 'idle',
|
|
16
|
+
* and inherits the model from the blueprint's execution unit config.
|
|
17
|
+
*
|
|
18
|
+
* Called once when an instance transitions from planning to building.
|
|
19
|
+
*/
|
|
20
|
+
export async function initializeExecutionUnits(state) {
|
|
21
|
+
const { blueprint } = state;
|
|
22
|
+
const count = blueprint.executionUnitCount;
|
|
23
|
+
const unitConfig = blueprint.executionUnitConfig;
|
|
24
|
+
const defaultModel = unitConfig?.defaultModel ?? null;
|
|
25
|
+
console.log(`${LOG_PREFIX} Initializing ${count} execution unit(s) for instance ${state.instanceId} ` +
|
|
26
|
+
`(model: ${defaultModel ?? 'default'})`);
|
|
27
|
+
for (let i = 0; i < count; i++) {
|
|
28
|
+
const unit = await createExecutionUnit({
|
|
29
|
+
instanceId: state.instanceId,
|
|
30
|
+
slotIndex: i,
|
|
31
|
+
model: defaultModel,
|
|
32
|
+
config: unitConfig,
|
|
33
|
+
});
|
|
34
|
+
state.executionUnits.set(unit.id, {
|
|
35
|
+
unitId: unit.id,
|
|
36
|
+
instanceId: state.instanceId,
|
|
37
|
+
slotIndex: i,
|
|
38
|
+
status: 'idle',
|
|
39
|
+
pid: null,
|
|
40
|
+
stdin: null,
|
|
41
|
+
streamParser: null,
|
|
42
|
+
claudeSessionId: null,
|
|
43
|
+
assignedStrategyId: null,
|
|
44
|
+
assignedAt: null,
|
|
45
|
+
previousStrategyId: null,
|
|
46
|
+
activityTracker: null,
|
|
47
|
+
adapter: null,
|
|
48
|
+
startedAt: null,
|
|
49
|
+
dispatchedAt: null,
|
|
50
|
+
dispatchedWorkUnitIds: new Set(),
|
|
51
|
+
lastActivityAt: null,
|
|
52
|
+
tokensUsed: 0,
|
|
53
|
+
costUsed: 0,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
console.log(`${LOG_PREFIX} Created ${count} execution unit(s) for instance ${state.instanceId}`);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Restore execution units from DB into in-memory state.
|
|
60
|
+
*
|
|
61
|
+
* Used during daemon restart (adoptActiveInstance) to rebuild the
|
|
62
|
+
* executionUnits map from existing DB rows. Units that were 'running'
|
|
63
|
+
* are reset to 'idle' since their sessions are gone.
|
|
64
|
+
*/
|
|
65
|
+
export async function restoreExecutionUnits(state) {
|
|
66
|
+
const units = await getExecutionUnitsByInstance(state.instanceId);
|
|
67
|
+
if (units.length === 0) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
for (const unit of units) {
|
|
71
|
+
// If the unit was running or assigned when the daemon died, reset to idle.
|
|
72
|
+
// After a crash, sessions for assigned/running units are gone -- the
|
|
73
|
+
// scheduler will reassign them on the next cycle.
|
|
74
|
+
const needsReset = unit.status === 'running' || unit.status === 'assigned';
|
|
75
|
+
const status = needsReset ? 'idle' : unit.status;
|
|
76
|
+
// Also persist the reset to DB so the scheduler sees clean state
|
|
77
|
+
if (needsReset) {
|
|
78
|
+
try {
|
|
79
|
+
await updateExecutionUnit(unit.id, {
|
|
80
|
+
status: 'idle',
|
|
81
|
+
assignedStrategyId: null,
|
|
82
|
+
assignedAt: null,
|
|
83
|
+
claudeSessionId: null,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
console.warn(`${LOG_PREFIX} Failed to reset unit ${unit.id} in DB during restore: ` +
|
|
88
|
+
`${err instanceof Error ? err.message : String(err)}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
state.executionUnits.set(unit.id, {
|
|
92
|
+
unitId: unit.id,
|
|
93
|
+
instanceId: state.instanceId,
|
|
94
|
+
slotIndex: unit.slotIndex,
|
|
95
|
+
status,
|
|
96
|
+
pid: null,
|
|
97
|
+
stdin: null,
|
|
98
|
+
streamParser: null,
|
|
99
|
+
claudeSessionId: needsReset ? null : unit.claudeSessionId,
|
|
100
|
+
assignedStrategyId: needsReset ? null : unit.assignedStrategyId,
|
|
101
|
+
assignedAt: null,
|
|
102
|
+
previousStrategyId: null,
|
|
103
|
+
activityTracker: null,
|
|
104
|
+
adapter: null,
|
|
105
|
+
startedAt: null,
|
|
106
|
+
dispatchedAt: null,
|
|
107
|
+
dispatchedWorkUnitIds: new Set(),
|
|
108
|
+
lastActivityAt: null,
|
|
109
|
+
tokensUsed: 0,
|
|
110
|
+
costUsed: 0,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
console.log(`${LOG_PREFIX} Restored ${units.length} execution unit(s) for instance ${state.instanceId}`);
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=execution-unit-init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution-unit-init.js","sourceRoot":"","sources":["../src/execution-unit-init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory execution -- barrel re-export.
|
|
3
|
+
*
|
|
4
|
+
* The implementation has been split into focused modules:
|
|
5
|
+
* - builder-spawner.ts -- builder process spawning, env setup, stream handling
|
|
6
|
+
* - builder-completion.ts -- builder completion handling, execution cycle orchestration
|
|
7
|
+
* - execution-target.ts -- BuilderExecutionTarget (TriggerExecutionTarget impl)
|
|
8
|
+
* - work-unit-scheduler.ts -- DAG-aware work unit readiness, dependency maps
|
|
9
|
+
*
|
|
10
|
+
* This file preserves the original import path for consumers (index.ts, tests).
|
|
11
|
+
*/
|
|
12
|
+
export { findReadyWorkUnits } from './work-unit-scheduler.js';
|
|
13
|
+
export type { StrategyDependencyMap, StrategyStatusMap } from './work-unit-scheduler.js';
|
|
14
|
+
export { spawnBuilder, transitionWorkUnitStatus, DEFAULT_MAX_ITERATIONS, LOG_PREFIX, lastGateOutputByWorkUnit } from './builder-spawner.js';
|
|
15
|
+
export { handleBuilderCompletion, runExecutionCycle } from './builder-completion.js';
|
|
16
|
+
export { BuilderExecutionTarget, getBuilderTarget } from './execution-target.js';
|
|
17
|
+
//# sourceMappingURL=execution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution.d.ts","sourceRoot":"","sources":["../src/execution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,YAAY,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGzF,OAAO,EAAE,YAAY,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,UAAU,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAG5I,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAGrF,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
|