@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,322 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource limit checking for factory instances.
|
|
3
|
+
*
|
|
4
|
+
* Enforces blueprint resource limits (token budget, wall-clock time,
|
|
5
|
+
* per-unit iterations, work unit count) and returns a structured result
|
|
6
|
+
* indicating whether any limit has been exceeded.
|
|
7
|
+
*
|
|
8
|
+
* Checks are designed to run after each session completion and gate
|
|
9
|
+
* evaluation. All checks are based on the blueprint configuration --
|
|
10
|
+
* null limits are treated as unlimited.
|
|
11
|
+
*/
|
|
12
|
+
import { getInstanceWorkUnits } from './queries/work-units.js';
|
|
13
|
+
import { getActiveSessionsForInstance } from './queries/sessions.js';
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// Main entry point
|
|
16
|
+
// ============================================================================
|
|
17
|
+
/**
|
|
18
|
+
* Check all resource limits for a factory instance.
|
|
19
|
+
*
|
|
20
|
+
* Evaluates four resource limits defined in the blueprint:
|
|
21
|
+
* 1. Token budget: aggregate tokens across all factory sessions
|
|
22
|
+
* 2. Wall-clock time: elapsed time since instance started
|
|
23
|
+
* 3. Iteration count: per-work-unit iteration limit
|
|
24
|
+
* 4. Work unit count: total work units vs max_work_units
|
|
25
|
+
*
|
|
26
|
+
* Returns immediately on the first exceeded limit found. All limits
|
|
27
|
+
* configured as null in the blueprint are treated as unlimited.
|
|
28
|
+
*
|
|
29
|
+
* @param instanceState - The in-memory state of the factory instance.
|
|
30
|
+
* @returns A result indicating whether any limit has been exceeded.
|
|
31
|
+
*/
|
|
32
|
+
export async function checkResourceLimits(instanceState) {
|
|
33
|
+
const blueprint = instanceState.blueprint;
|
|
34
|
+
const exceeded = [];
|
|
35
|
+
// Check 1: Token budget
|
|
36
|
+
const tokenResult = await checkTokenBudget(instanceState, blueprint);
|
|
37
|
+
if (tokenResult) {
|
|
38
|
+
exceeded.push(tokenResult);
|
|
39
|
+
}
|
|
40
|
+
// Check 1b: Cost budget
|
|
41
|
+
const costResult = checkCostBudget(instanceState, blueprint);
|
|
42
|
+
if (costResult) {
|
|
43
|
+
exceeded.push(costResult);
|
|
44
|
+
}
|
|
45
|
+
// Check 2: Wall-clock time
|
|
46
|
+
const wallClockResult = checkWallClockTime(instanceState, blueprint);
|
|
47
|
+
if (wallClockResult) {
|
|
48
|
+
exceeded.push(wallClockResult);
|
|
49
|
+
}
|
|
50
|
+
// Check 3: Per-work-unit iteration count
|
|
51
|
+
const iterationResults = await checkIterationLimits(instanceState, blueprint);
|
|
52
|
+
exceeded.push(...iterationResults);
|
|
53
|
+
// Check 4: Total work unit count
|
|
54
|
+
const workUnitCountResult = await checkWorkUnitCount(instanceState, blueprint);
|
|
55
|
+
if (workUnitCountResult) {
|
|
56
|
+
exceeded.push(workUnitCountResult);
|
|
57
|
+
}
|
|
58
|
+
// Check 5: Instance iteration limit (completion gate cycles)
|
|
59
|
+
const instanceIterResult = checkInstanceIterations(instanceState, blueprint);
|
|
60
|
+
if (instanceIterResult) {
|
|
61
|
+
exceeded.push(instanceIterResult);
|
|
62
|
+
}
|
|
63
|
+
if (exceeded.length === 0) {
|
|
64
|
+
return { exceeded: false, reason: '', details: [] };
|
|
65
|
+
}
|
|
66
|
+
// Build a combined reason string from all exceeded limits
|
|
67
|
+
const reasons = exceeded.map((d) => d.description);
|
|
68
|
+
return {
|
|
69
|
+
exceeded: true,
|
|
70
|
+
reason: reasons.join('; '),
|
|
71
|
+
details: exceeded,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
// ============================================================================
|
|
75
|
+
// Individual limit checks
|
|
76
|
+
// ============================================================================
|
|
77
|
+
/**
|
|
78
|
+
* Check whether the aggregate token usage across all sessions exceeds
|
|
79
|
+
* the blueprint's max_token_budget.
|
|
80
|
+
*
|
|
81
|
+
* Fetches active sessions for the instance and sums their token_count
|
|
82
|
+
* values. Sessions with null token_count are treated as 0.
|
|
83
|
+
*/
|
|
84
|
+
async function checkTokenBudget(instanceState, blueprint) {
|
|
85
|
+
if (blueprint.maxTokenBudget === null) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
const sessions = await getActiveSessionsForInstance(instanceState.instanceId);
|
|
89
|
+
const totalTokens = sumSessionTokens(sessions);
|
|
90
|
+
if (totalTokens > blueprint.maxTokenBudget) {
|
|
91
|
+
return {
|
|
92
|
+
limitType: 'token_budget',
|
|
93
|
+
currentValue: totalTokens,
|
|
94
|
+
maxValue: blueprint.maxTokenBudget,
|
|
95
|
+
description: `Token budget exceeded: ${totalTokens} tokens used ` +
|
|
96
|
+
`(limit: ${blueprint.maxTokenBudget})`,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Check whether the cumulative cost across all sessions exceeds
|
|
103
|
+
* the blueprint's max_cost_budget (denominated in dollars).
|
|
104
|
+
*
|
|
105
|
+
* Uses the in-memory costUsed counter which is updated after each
|
|
106
|
+
* session completes.
|
|
107
|
+
*/
|
|
108
|
+
function checkCostBudget(instanceState, blueprint) {
|
|
109
|
+
if (blueprint.maxCostBudget === null) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
const currentCost = instanceState.costUsed;
|
|
113
|
+
if (currentCost > blueprint.maxCostBudget) {
|
|
114
|
+
return {
|
|
115
|
+
limitType: 'cost_budget',
|
|
116
|
+
currentValue: Math.round(currentCost * 100) / 100,
|
|
117
|
+
maxValue: blueprint.maxCostBudget,
|
|
118
|
+
description: `Cost budget exceeded: $${currentCost.toFixed(2)} spent ` +
|
|
119
|
+
`(limit: $${blueprint.maxCostBudget.toFixed(2)})`,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Check whether the wall-clock elapsed time exceeds the blueprint's
|
|
126
|
+
* max_wall_clock_hours.
|
|
127
|
+
*
|
|
128
|
+
* Uses the in-memory startedAt timestamp for the instance. This avoids
|
|
129
|
+
* an extra API call since the lifecycle manager always sets startedAt
|
|
130
|
+
* when the instance is picked up.
|
|
131
|
+
*/
|
|
132
|
+
function checkWallClockTime(instanceState, blueprint) {
|
|
133
|
+
if (blueprint.maxWallClockHours === null) {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
const elapsedMs = Date.now() - instanceState.startedAt.getTime();
|
|
137
|
+
const elapsedHours = elapsedMs / (1000 * 60 * 60);
|
|
138
|
+
const maxHours = blueprint.maxWallClockHours;
|
|
139
|
+
if (elapsedHours > maxHours) {
|
|
140
|
+
return {
|
|
141
|
+
limitType: 'wall_clock',
|
|
142
|
+
currentValue: Math.round(elapsedHours * 100) / 100,
|
|
143
|
+
maxValue: maxHours,
|
|
144
|
+
description: `Wall-clock time exceeded: ${(elapsedHours).toFixed(2)} hours elapsed ` +
|
|
145
|
+
`(limit: ${maxHours} hours)`,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Check whether any work unit has exceeded the per-unit iteration limit
|
|
152
|
+
* defined in the blueprint's max_iterations_per_work_unit.
|
|
153
|
+
*
|
|
154
|
+
* Returns a detail entry for each work unit that has exceeded the limit.
|
|
155
|
+
*/
|
|
156
|
+
async function checkIterationLimits(instanceState, blueprint) {
|
|
157
|
+
if (blueprint.maxIterationsPerWorkUnit === null) {
|
|
158
|
+
return [];
|
|
159
|
+
}
|
|
160
|
+
const maxIterations = blueprint.maxIterationsPerWorkUnit;
|
|
161
|
+
const workUnits = await getInstanceWorkUnits(instanceState.instanceId);
|
|
162
|
+
const exceeded = [];
|
|
163
|
+
for (const unit of workUnits) {
|
|
164
|
+
if (unit.iterationCount >= maxIterations) {
|
|
165
|
+
exceeded.push({
|
|
166
|
+
limitType: 'iteration_count',
|
|
167
|
+
currentValue: unit.iterationCount,
|
|
168
|
+
maxValue: maxIterations,
|
|
169
|
+
description: `Work unit "${unit.title}" (${unit.id}) exceeded iteration limit: ` +
|
|
170
|
+
`${unit.iterationCount} iterations (limit: ${maxIterations})`,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return exceeded;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Check whether the total number of work units exceeds the blueprint's
|
|
178
|
+
* max_work_units limit.
|
|
179
|
+
*/
|
|
180
|
+
async function checkWorkUnitCount(instanceState, blueprint) {
|
|
181
|
+
if (blueprint.maxWorkUnits === null) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
const workUnits = await getInstanceWorkUnits(instanceState.instanceId);
|
|
185
|
+
const count = workUnits.length;
|
|
186
|
+
if (count > blueprint.maxWorkUnits) {
|
|
187
|
+
return {
|
|
188
|
+
limitType: 'work_unit_count',
|
|
189
|
+
currentValue: count,
|
|
190
|
+
maxValue: blueprint.maxWorkUnits,
|
|
191
|
+
description: `Work unit count exceeded: ${count} work units ` +
|
|
192
|
+
`(limit: ${blueprint.maxWorkUnits})`,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Check whether the instance has exceeded its completion gate iteration limit.
|
|
199
|
+
*
|
|
200
|
+
* Uses blueprint.maxInstanceIterations. Null means no limit (skip check).
|
|
201
|
+
* This ensures the instance escalates when iteration limits are hit, giving
|
|
202
|
+
* the human a chance to extend the limit or review progress.
|
|
203
|
+
*/
|
|
204
|
+
function checkInstanceIterations(instanceState, blueprint) {
|
|
205
|
+
const maxIterations = blueprint.maxInstanceIterations;
|
|
206
|
+
if (maxIterations === null)
|
|
207
|
+
return null;
|
|
208
|
+
if (instanceState.completionGateIterations >= maxIterations) {
|
|
209
|
+
return {
|
|
210
|
+
limitType: 'instance_iterations',
|
|
211
|
+
currentValue: instanceState.completionGateIterations,
|
|
212
|
+
maxValue: maxIterations,
|
|
213
|
+
description: `Instance iteration limit reached: ${instanceState.completionGateIterations} cycles ` +
|
|
214
|
+
`(limit: ${maxIterations})`,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
// ============================================================================
|
|
220
|
+
// Pure helpers
|
|
221
|
+
// ============================================================================
|
|
222
|
+
/**
|
|
223
|
+
* Sum token counts across a list of factory sessions.
|
|
224
|
+
* Sessions with null token_count are treated as 0.
|
|
225
|
+
*/
|
|
226
|
+
export function sumSessionTokens(sessions) {
|
|
227
|
+
return sessions.reduce((sum, s) => sum + (s.tokenCount ?? 0), 0);
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Check resource limits using pre-fetched data (no API calls).
|
|
231
|
+
*
|
|
232
|
+
* This is useful when the caller has already fetched work units and
|
|
233
|
+
* sessions and wants to avoid redundant API calls. Performs the same
|
|
234
|
+
* checks as checkResourceLimits but operates on provided data.
|
|
235
|
+
*/
|
|
236
|
+
export function checkResourceLimitsSync(instanceState, sessions, workUnits) {
|
|
237
|
+
const blueprint = instanceState.blueprint;
|
|
238
|
+
const exceeded = [];
|
|
239
|
+
// Check 1: Token budget
|
|
240
|
+
if (blueprint.maxTokenBudget !== null) {
|
|
241
|
+
const totalTokens = sumSessionTokens(sessions);
|
|
242
|
+
if (totalTokens > blueprint.maxTokenBudget) {
|
|
243
|
+
exceeded.push({
|
|
244
|
+
limitType: 'token_budget',
|
|
245
|
+
currentValue: totalTokens,
|
|
246
|
+
maxValue: blueprint.maxTokenBudget,
|
|
247
|
+
description: `Token budget exceeded: ${totalTokens} tokens used ` +
|
|
248
|
+
`(limit: ${blueprint.maxTokenBudget})`,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
// Check 1b: Cost budget
|
|
253
|
+
if (blueprint.maxCostBudget !== null) {
|
|
254
|
+
const currentCost = instanceState.costUsed;
|
|
255
|
+
if (currentCost > blueprint.maxCostBudget) {
|
|
256
|
+
exceeded.push({
|
|
257
|
+
limitType: 'cost_budget',
|
|
258
|
+
currentValue: Math.round(currentCost * 100) / 100,
|
|
259
|
+
maxValue: blueprint.maxCostBudget,
|
|
260
|
+
description: `Cost budget exceeded: $${currentCost.toFixed(2)} spent ` +
|
|
261
|
+
`(limit: $${blueprint.maxCostBudget.toFixed(2)})`,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
// Check 2: Wall-clock time
|
|
266
|
+
if (blueprint.maxWallClockHours !== null) {
|
|
267
|
+
const elapsedMs = Date.now() - instanceState.startedAt.getTime();
|
|
268
|
+
const elapsedHours = elapsedMs / (1000 * 60 * 60);
|
|
269
|
+
if (elapsedHours > blueprint.maxWallClockHours) {
|
|
270
|
+
exceeded.push({
|
|
271
|
+
limitType: 'wall_clock',
|
|
272
|
+
currentValue: Math.round(elapsedHours * 100) / 100,
|
|
273
|
+
maxValue: blueprint.maxWallClockHours,
|
|
274
|
+
description: `Wall-clock time exceeded: ${elapsedHours.toFixed(2)} hours elapsed ` +
|
|
275
|
+
`(limit: ${blueprint.maxWallClockHours} hours)`,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
// Check 3: Per-work-unit iteration count
|
|
280
|
+
if (blueprint.maxIterationsPerWorkUnit !== null) {
|
|
281
|
+
const maxIterations = blueprint.maxIterationsPerWorkUnit;
|
|
282
|
+
for (const unit of workUnits) {
|
|
283
|
+
if (unit.iterationCount >= maxIterations) {
|
|
284
|
+
exceeded.push({
|
|
285
|
+
limitType: 'iteration_count',
|
|
286
|
+
currentValue: unit.iterationCount,
|
|
287
|
+
maxValue: maxIterations,
|
|
288
|
+
description: `Work unit "${unit.title}" (${unit.id}) exceeded iteration limit: ` +
|
|
289
|
+
`${unit.iterationCount} iterations (limit: ${maxIterations})`,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
// Check 4: Total work unit count
|
|
295
|
+
if (blueprint.maxWorkUnits !== null) {
|
|
296
|
+
const count = workUnits.length;
|
|
297
|
+
if (count > blueprint.maxWorkUnits) {
|
|
298
|
+
exceeded.push({
|
|
299
|
+
limitType: 'work_unit_count',
|
|
300
|
+
currentValue: count,
|
|
301
|
+
maxValue: blueprint.maxWorkUnits,
|
|
302
|
+
description: `Work unit count exceeded: ${count} work units ` +
|
|
303
|
+
`(limit: ${blueprint.maxWorkUnits})`,
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// Check 5: Instance iteration limit (completion gate cycles)
|
|
308
|
+
const instanceIterResult = checkInstanceIterations(instanceState, blueprint);
|
|
309
|
+
if (instanceIterResult) {
|
|
310
|
+
exceeded.push(instanceIterResult);
|
|
311
|
+
}
|
|
312
|
+
if (exceeded.length === 0) {
|
|
313
|
+
return { exceeded: false, reason: '', details: [] };
|
|
314
|
+
}
|
|
315
|
+
const reasons = exceeded.map((d) => d.description);
|
|
316
|
+
return {
|
|
317
|
+
exceeded: true,
|
|
318
|
+
reason: reasons.join('; '),
|
|
319
|
+
details: exceeded,
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
//# sourceMappingURL=resource-limits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-limits.js","sourceRoot":"","sources":["../src/resource-limits.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DAG-aware execution unit scheduler.
|
|
3
|
+
*
|
|
4
|
+
* Each poll cycle, the scheduler examines the strategy DAG to determine
|
|
5
|
+
* which strategies have all upstream dependencies completed. For each
|
|
6
|
+
* ready strategy, it assigns an available (idle) execution unit.
|
|
7
|
+
*
|
|
8
|
+
* The core algorithm is a pure function (computeAssignments) for testability.
|
|
9
|
+
* The IO wrapper (runSchedulerCycle) handles DB queries and atomic updates.
|
|
10
|
+
*/
|
|
11
|
+
import type { ExecutionUnitStatus } from './types.js';
|
|
12
|
+
import type { PersistedStrategy, StrategyExecutionStatus } from './strategy-design.js';
|
|
13
|
+
/** Minimal strategy info needed by the scheduler. */
|
|
14
|
+
export interface SchedulerStrategy {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
executionStatus: StrategyExecutionStatus | null;
|
|
18
|
+
dependsOn: string[];
|
|
19
|
+
priorityRank: number;
|
|
20
|
+
}
|
|
21
|
+
/** Minimal execution unit info needed by the scheduler. */
|
|
22
|
+
export interface SchedulerUnit {
|
|
23
|
+
id: string;
|
|
24
|
+
slotIndex: number;
|
|
25
|
+
status: ExecutionUnitStatus;
|
|
26
|
+
assignedStrategyId: string | null;
|
|
27
|
+
}
|
|
28
|
+
/** A single assignment produced by the scheduler. */
|
|
29
|
+
export interface SchedulerAssignment {
|
|
30
|
+
unitId: string;
|
|
31
|
+
strategyId: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Compute strategy-to-unit assignments.
|
|
35
|
+
*
|
|
36
|
+
* Pure function -- no DB calls, no side effects. Takes the current state
|
|
37
|
+
* of strategies and execution units and returns the list of new assignments.
|
|
38
|
+
*
|
|
39
|
+
* Eligible strategies: executionStatus is 'pending' AND all dependsOn
|
|
40
|
+
* strategies have executionStatus 'completed'.
|
|
41
|
+
*
|
|
42
|
+
* Idle units: status is 'idle'.
|
|
43
|
+
*
|
|
44
|
+
* Matching: assign eligible strategies to idle units in priorityRank order
|
|
45
|
+
* (lower rank = higher priority). If more eligible strategies than idle units,
|
|
46
|
+
* only assign what fits.
|
|
47
|
+
*/
|
|
48
|
+
export declare function computeAssignments(strategies: SchedulerStrategy[], units: SchedulerUnit[]): SchedulerAssignment[];
|
|
49
|
+
/** Dependencies injected into runSchedulerCycle for testability. */
|
|
50
|
+
export interface SchedulerDeps {
|
|
51
|
+
getStrategies: (instanceId: string) => Promise<PersistedStrategy[]>;
|
|
52
|
+
getUnits: (instanceId: string) => Promise<SchedulerUnit[]>;
|
|
53
|
+
assignUnit: (unitId: string, strategyId: string) => Promise<{
|
|
54
|
+
id: string;
|
|
55
|
+
} | null>;
|
|
56
|
+
updateStrategyStatus: (strategyId: string, status: StrategyExecutionStatus) => Promise<void>;
|
|
57
|
+
}
|
|
58
|
+
/** Result of a single scheduler cycle. */
|
|
59
|
+
export interface SchedulerCycleResult {
|
|
60
|
+
/** Assignments that were successfully applied. */
|
|
61
|
+
assignments: SchedulerAssignment[];
|
|
62
|
+
/** Number of eligible strategies that couldn't be assigned (no idle units). */
|
|
63
|
+
waitingStrategies: number;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Run one scheduler cycle for a factory instance.
|
|
67
|
+
*
|
|
68
|
+
* Fetches strategies and execution units from DB, computes assignments,
|
|
69
|
+
* then applies each assignment using an atomic conditional update.
|
|
70
|
+
*
|
|
71
|
+
* If the conditional update returns null (unit was claimed by another cycle),
|
|
72
|
+
* the assignment is skipped and logged.
|
|
73
|
+
*/
|
|
74
|
+
export declare function runSchedulerCycle(instanceId: string, deps: SchedulerDeps): Promise<SchedulerCycleResult>;
|
|
75
|
+
/**
|
|
76
|
+
* Release the execution unit assigned to a strategy back to idle.
|
|
77
|
+
*
|
|
78
|
+
* Called when a strategy reaches a terminal state (completed via gates,
|
|
79
|
+
* or failed). Clears assignedStrategyId, sets status to 'idle' in both
|
|
80
|
+
* DB and in-memory state. Preserves claudeSessionId for potential resume.
|
|
81
|
+
*
|
|
82
|
+
* @returns true if a unit was found and released, false otherwise.
|
|
83
|
+
*/
|
|
84
|
+
export declare function releaseUnitForStrategy(state: {
|
|
85
|
+
executionUnits: Map<string, {
|
|
86
|
+
unitId: string;
|
|
87
|
+
assignedStrategyId: string | null;
|
|
88
|
+
assignedAt: Date | null;
|
|
89
|
+
status: ExecutionUnitStatus;
|
|
90
|
+
claudeSessionId: string | null;
|
|
91
|
+
}>;
|
|
92
|
+
}, strategyId: string): Promise<boolean>;
|
|
93
|
+
/**
|
|
94
|
+
* Create the default SchedulerDeps using real query functions.
|
|
95
|
+
* Used by the instance lifecycle to wire the scheduler.
|
|
96
|
+
*/
|
|
97
|
+
export declare function createSchedulerDeps(): SchedulerDeps;
|
|
98
|
+
//# sourceMappingURL=scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAQvF,qDAAqD;AACrD,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,uBAAuB,GAAG,IAAI,CAAC;IAChD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,2DAA2D;AAC3D,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,qDAAqD;AACrD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,iBAAiB,EAAE,EAC/B,KAAK,EAAE,aAAa,EAAE,GACrB,mBAAmB,EAAE,CAgCvB;AAMD,oEAAoE;AACpE,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACpE,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAC3D,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACnF,oBAAoB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,uBAAuB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9F;AAED,0CAA0C;AAC1C,MAAM,WAAW,oBAAoB;IACnC,kDAAkD;IAClD,WAAW,EAAE,mBAAmB,EAAE,CAAC;IACnC,+EAA+E;IAC/E,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,oBAAoB,CAAC,CAqF/B;AAMD;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE;IAAE,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;QAAC,MAAM,EAAE,mBAAmB,CAAC;QAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAA;CAAE,EACnL,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC,CAgClB;AAMD;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,aAAa,CAoBnD"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DAG-aware execution unit scheduler.
|
|
3
|
+
*
|
|
4
|
+
* Each poll cycle, the scheduler examines the strategy DAG to determine
|
|
5
|
+
* which strategies have all upstream dependencies completed. For each
|
|
6
|
+
* ready strategy, it assigns an available (idle) execution unit.
|
|
7
|
+
*
|
|
8
|
+
* The core algorithm is a pure function (computeAssignments) for testability.
|
|
9
|
+
* The IO wrapper (runSchedulerCycle) handles DB queries and atomic updates.
|
|
10
|
+
*/
|
|
11
|
+
const LOG_PREFIX = '[scheduler]';
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Pure scheduling algorithm
|
|
14
|
+
// ============================================================================
|
|
15
|
+
/**
|
|
16
|
+
* Compute strategy-to-unit assignments.
|
|
17
|
+
*
|
|
18
|
+
* Pure function -- no DB calls, no side effects. Takes the current state
|
|
19
|
+
* of strategies and execution units and returns the list of new assignments.
|
|
20
|
+
*
|
|
21
|
+
* Eligible strategies: executionStatus is 'pending' AND all dependsOn
|
|
22
|
+
* strategies have executionStatus 'completed'.
|
|
23
|
+
*
|
|
24
|
+
* Idle units: status is 'idle'.
|
|
25
|
+
*
|
|
26
|
+
* Matching: assign eligible strategies to idle units in priorityRank order
|
|
27
|
+
* (lower rank = higher priority). If more eligible strategies than idle units,
|
|
28
|
+
* only assign what fits.
|
|
29
|
+
*/
|
|
30
|
+
export function computeAssignments(strategies, units) {
|
|
31
|
+
// Build a status lookup for fast dependency checking
|
|
32
|
+
const statusById = new Map();
|
|
33
|
+
for (const s of strategies) {
|
|
34
|
+
statusById.set(s.id, s.executionStatus);
|
|
35
|
+
}
|
|
36
|
+
// Find eligible strategies: pending + all deps completed
|
|
37
|
+
const eligible = strategies
|
|
38
|
+
.filter((s) => {
|
|
39
|
+
if (s.executionStatus !== 'pending')
|
|
40
|
+
return false;
|
|
41
|
+
return s.dependsOn.every((depId) => statusById.get(depId) === 'completed');
|
|
42
|
+
})
|
|
43
|
+
.sort((a, b) => a.priorityRank - b.priorityRank);
|
|
44
|
+
// Find idle units, sorted by slot_index for deterministic assignment
|
|
45
|
+
const idle = units
|
|
46
|
+
.filter((u) => u.status === 'idle')
|
|
47
|
+
.sort((a, b) => a.slotIndex - b.slotIndex);
|
|
48
|
+
// Match eligible strategies to idle units
|
|
49
|
+
const assignments = [];
|
|
50
|
+
const assignCount = Math.min(eligible.length, idle.length);
|
|
51
|
+
for (let i = 0; i < assignCount; i++) {
|
|
52
|
+
assignments.push({
|
|
53
|
+
unitId: idle[i].id,
|
|
54
|
+
strategyId: eligible[i].id,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return assignments;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Run one scheduler cycle for a factory instance.
|
|
61
|
+
*
|
|
62
|
+
* Fetches strategies and execution units from DB, computes assignments,
|
|
63
|
+
* then applies each assignment using an atomic conditional update.
|
|
64
|
+
*
|
|
65
|
+
* If the conditional update returns null (unit was claimed by another cycle),
|
|
66
|
+
* the assignment is skipped and logged.
|
|
67
|
+
*/
|
|
68
|
+
export async function runSchedulerCycle(instanceId, deps) {
|
|
69
|
+
// Fetch current state
|
|
70
|
+
const strategies = await deps.getStrategies(instanceId);
|
|
71
|
+
const units = await deps.getUnits(instanceId);
|
|
72
|
+
// Map to scheduler types
|
|
73
|
+
const schedulerStrategies = strategies.map((s) => ({
|
|
74
|
+
id: s.id,
|
|
75
|
+
name: s.name,
|
|
76
|
+
executionStatus: s.executionStatus,
|
|
77
|
+
dependsOn: s.dependsOn,
|
|
78
|
+
priorityRank: s.priorityRank,
|
|
79
|
+
}));
|
|
80
|
+
const schedulerUnits = units.map((u) => ({
|
|
81
|
+
id: u.id,
|
|
82
|
+
slotIndex: u.slotIndex,
|
|
83
|
+
status: u.status,
|
|
84
|
+
assignedStrategyId: u.assignedStrategyId,
|
|
85
|
+
}));
|
|
86
|
+
// Compute assignments
|
|
87
|
+
const planned = computeAssignments(schedulerStrategies, schedulerUnits);
|
|
88
|
+
if (planned.length === 0) {
|
|
89
|
+
// Count how many strategies are eligible but can't be assigned
|
|
90
|
+
const eligibleCount = schedulerStrategies.filter((s) => {
|
|
91
|
+
if (s.executionStatus !== 'pending')
|
|
92
|
+
return false;
|
|
93
|
+
const statusById = new Map(schedulerStrategies.map((st) => [st.id, st.executionStatus]));
|
|
94
|
+
return s.dependsOn.every((depId) => statusById.get(depId) === 'completed');
|
|
95
|
+
}).length;
|
|
96
|
+
const idleCount = schedulerUnits.filter((u) => u.status === 'idle').length;
|
|
97
|
+
const waitingStrategies = Math.max(0, eligibleCount - idleCount);
|
|
98
|
+
return { assignments: [], waitingStrategies };
|
|
99
|
+
}
|
|
100
|
+
// Apply assignments atomically
|
|
101
|
+
const successfulAssignments = [];
|
|
102
|
+
const strategyNameById = new Map(strategies.map((s) => [s.id, s.name]));
|
|
103
|
+
for (const assignment of planned) {
|
|
104
|
+
const result = await deps.assignUnit(assignment.unitId, assignment.strategyId);
|
|
105
|
+
if (!result) {
|
|
106
|
+
// Unit was claimed by another cycle -- skip
|
|
107
|
+
console.log(`${LOG_PREFIX} Unit ${assignment.unitId} was already claimed -- skipping assignment ` +
|
|
108
|
+
`for strategy "${strategyNameById.get(assignment.strategyId) ?? assignment.strategyId}"`);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
// Update strategy execution_status to in_progress
|
|
112
|
+
try {
|
|
113
|
+
await deps.updateStrategyStatus(assignment.strategyId, 'in_progress');
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
console.error(`${LOG_PREFIX} Failed to update strategy ${assignment.strategyId} to in_progress: ` +
|
|
117
|
+
`${err.message}`);
|
|
118
|
+
// Assignment succeeded in DB but status update failed -- still count it
|
|
119
|
+
}
|
|
120
|
+
successfulAssignments.push(assignment);
|
|
121
|
+
console.log(`${LOG_PREFIX} Assigned strategy "${strategyNameById.get(assignment.strategyId) ?? assignment.strategyId}" ` +
|
|
122
|
+
`to unit ${assignment.unitId}`);
|
|
123
|
+
}
|
|
124
|
+
// Count waiting strategies
|
|
125
|
+
const assignedStrategyIds = new Set(successfulAssignments.map((a) => a.strategyId));
|
|
126
|
+
const eligibleAfter = schedulerStrategies.filter((s) => {
|
|
127
|
+
if (s.executionStatus !== 'pending')
|
|
128
|
+
return false;
|
|
129
|
+
if (assignedStrategyIds.has(s.id))
|
|
130
|
+
return false;
|
|
131
|
+
const statusById = new Map(schedulerStrategies.map((st) => [st.id, st.executionStatus]));
|
|
132
|
+
return s.dependsOn.every((depId) => statusById.get(depId) === 'completed');
|
|
133
|
+
}).length;
|
|
134
|
+
return {
|
|
135
|
+
assignments: successfulAssignments,
|
|
136
|
+
waitingStrategies: eligibleAfter,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
// ============================================================================
|
|
140
|
+
// Unit release
|
|
141
|
+
// ============================================================================
|
|
142
|
+
/**
|
|
143
|
+
* Release the execution unit assigned to a strategy back to idle.
|
|
144
|
+
*
|
|
145
|
+
* Called when a strategy reaches a terminal state (completed via gates,
|
|
146
|
+
* or failed). Clears assignedStrategyId, sets status to 'idle' in both
|
|
147
|
+
* DB and in-memory state. Preserves claudeSessionId for potential resume.
|
|
148
|
+
*
|
|
149
|
+
* @returns true if a unit was found and released, false otherwise.
|
|
150
|
+
*/
|
|
151
|
+
export async function releaseUnitForStrategy(state, strategyId) {
|
|
152
|
+
// Find the unit assigned to this strategy
|
|
153
|
+
let targetUnit = null;
|
|
154
|
+
for (const unit of state.executionUnits.values()) {
|
|
155
|
+
if (unit.assignedStrategyId === strategyId) {
|
|
156
|
+
targetUnit = unit;
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (!targetUnit) {
|
|
161
|
+
console.log(`${LOG_PREFIX} No execution unit found for strategy ${strategyId} -- skipping release`);
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
// Release in DB
|
|
165
|
+
const { releaseExecutionUnit } = await import('./queries/execution-units.js');
|
|
166
|
+
await releaseExecutionUnit(targetUnit.unitId);
|
|
167
|
+
// Update in-memory state
|
|
168
|
+
targetUnit.assignedStrategyId = null;
|
|
169
|
+
targetUnit.assignedAt = null;
|
|
170
|
+
targetUnit.status = 'idle';
|
|
171
|
+
console.log(`${LOG_PREFIX} Released unit ${targetUnit.unitId} (strategy ${strategyId} -> idle)` +
|
|
172
|
+
(targetUnit.claudeSessionId ? ` [session preserved for resume]` : ''));
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
// ============================================================================
|
|
176
|
+
// Default dependencies
|
|
177
|
+
// ============================================================================
|
|
178
|
+
/**
|
|
179
|
+
* Create the default SchedulerDeps using real query functions.
|
|
180
|
+
* Used by the instance lifecycle to wire the scheduler.
|
|
181
|
+
*/
|
|
182
|
+
export function createSchedulerDeps() {
|
|
183
|
+
// Lazy imports to avoid circular dependencies
|
|
184
|
+
return {
|
|
185
|
+
getStrategies: async (instanceId) => {
|
|
186
|
+
const { getStrategiesByFactoryInstance } = await import('./strategy-design.js');
|
|
187
|
+
return getStrategiesByFactoryInstance(instanceId);
|
|
188
|
+
},
|
|
189
|
+
getUnits: async (instanceId) => {
|
|
190
|
+
const { getExecutionUnitsByInstance } = await import('./queries/execution-units.js');
|
|
191
|
+
return getExecutionUnitsByInstance(instanceId);
|
|
192
|
+
},
|
|
193
|
+
assignUnit: async (unitId, strategyId) => {
|
|
194
|
+
const { assignExecutionUnit } = await import('./queries/execution-units.js');
|
|
195
|
+
return assignExecutionUnit(unitId, strategyId);
|
|
196
|
+
},
|
|
197
|
+
updateStrategyStatus: async (strategyId, status) => {
|
|
198
|
+
const { updateStrategyExecutionStatus } = await import('./queries/strategies.js');
|
|
199
|
+
await updateStrategyExecutionStatus(strategyId, status);
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"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"}
|