@kognai/orchestrator-core 0.2.3 → 0.2.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/lib/sprint-runner-engine.js +44 -7
- package/package.json +1 -1
- package/dist/lib/v2-decomposition-gate.types.d.ts +0 -80
- package/dist/lib/v2-decomposition-gate.types.js +0 -2
- package/dist/lib/v2-decomposition-gate.types.test.d.ts +0 -0
- package/dist/lib/v2-decomposition-gate.types.test.js +0 -3
|
@@ -886,15 +886,52 @@ async function runSprintCycle(opts) {
|
|
|
886
886
|
// overlapping orphans can't accumulate even if cron ever gets re-armed
|
|
887
887
|
const orchestratorTimeoutMs = PER_RUN_HARD_TIMEOUT_MIN * 60 * 1000;
|
|
888
888
|
log(`Spawning orchestrator with ${PER_RUN_HARD_TIMEOUT_MIN}-min hard timeout`);
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
889
|
+
// TICKET-347: spawnSync's `timeout` only SIGKILLs the DIRECT child (`npx`).
|
|
890
|
+
// Its `ts-node` child + the orchestrator grandchildren (and everything THEY
|
|
891
|
+
// spawn) get orphaned and keep running — reparented to init. A live incident
|
|
892
|
+
// (2026-06-13) had a "timed-out" run keep executing for ~2h after the runner
|
|
893
|
+
// declared it failed, burning ~1.3M tokens + attempting wallet settlements.
|
|
894
|
+
// Fix: spawn DETACHED so the child leads its own process group, then SIGKILL
|
|
895
|
+
// the WHOLE group (negative pid) on timeout — taking the entire subtree down.
|
|
896
|
+
const result = await new Promise((resolveRun) => {
|
|
897
|
+
const child = (0, child_process_1.spawn)('npx', ['ts-node', orchestratorPath, activePath], {
|
|
898
|
+
stdio: 'inherit',
|
|
899
|
+
cwd: ROOT,
|
|
900
|
+
env: { ...process.env },
|
|
901
|
+
detached: true, // new process group (setsid) → killable as a unit
|
|
902
|
+
});
|
|
903
|
+
let timedOut = false;
|
|
904
|
+
let settled = false;
|
|
905
|
+
const finish = (status) => {
|
|
906
|
+
if (settled)
|
|
907
|
+
return;
|
|
908
|
+
settled = true;
|
|
909
|
+
clearTimeout(timer);
|
|
910
|
+
resolveRun({ status, timedOut });
|
|
911
|
+
};
|
|
912
|
+
const timer = setTimeout(() => {
|
|
913
|
+
timedOut = true;
|
|
914
|
+
// Negative pid = signal the entire process group (the detached subtree).
|
|
915
|
+
try {
|
|
916
|
+
if (child.pid)
|
|
917
|
+
process.kill(-child.pid, 'SIGKILL');
|
|
918
|
+
}
|
|
919
|
+
catch { /* group already gone */ }
|
|
920
|
+
// Belt-and-braces: also target the direct child in case the group call missed.
|
|
921
|
+
try {
|
|
922
|
+
child.kill('SIGKILL');
|
|
923
|
+
}
|
|
924
|
+
catch { /* already dead */ }
|
|
925
|
+
}, orchestratorTimeoutMs);
|
|
926
|
+
child.on('error', (err) => { log(`Orchestrator spawn error: ${err.message}`); finish(1); });
|
|
927
|
+
child.on('exit', (code) => finish(code));
|
|
895
928
|
});
|
|
896
929
|
const elapsed = Math.round((Date.now() - start) / 60000);
|
|
897
|
-
const status = result.status === 0
|
|
930
|
+
const status = result.status === 0
|
|
931
|
+
? '✅ Completed'
|
|
932
|
+
: result.timedOut
|
|
933
|
+
? `⏱️ Killed — ${PER_RUN_HARD_TIMEOUT_MIN}-min hard timeout (process group SIGKILLed)`
|
|
934
|
+
: `❌ Failed (exit ${result.status})`;
|
|
898
935
|
log(`Orchestrator finished: ${status} (${elapsed} min)`);
|
|
899
936
|
// Founder directive 2026-05-26: on non-zero exit, write an incident record
|
|
900
937
|
// and emit an event for CTO + CEO to investigate autonomously. The swarm
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kognai/orchestrator-core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Kognai sovereign orchestrator — core engine (template-agnostic). Shared by all products (Kognai/coding, Voxight/market-intel, Invoica/fin-compliance); each supplies only its template. Replaces per-repo forks of orchestrate-agents-v2 / sprint-runner / lib.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "SkinGem",
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Defines the task kind for decomposition gate scoring.
|
|
3
|
-
* @category DecompositionGate
|
|
4
|
-
*/
|
|
5
|
-
export type TaskKind = 'MODIFY' | 'CREATE';
|
|
6
|
-
/**
|
|
7
|
-
* Represents an edit point in the task context.
|
|
8
|
-
* @property kind - The type of edit (e.g., 'import', 'function_body')
|
|
9
|
-
* @property location - The file path or symbol where the edit occurs
|
|
10
|
-
* @property description - Optional description of the edit
|
|
11
|
-
* @category DecompositionGate
|
|
12
|
-
*/
|
|
13
|
-
export interface EditPoint {
|
|
14
|
-
kind: 'import' | 'guard' | 'function_body' | 'export';
|
|
15
|
-
location: string;
|
|
16
|
-
description?: string;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Complexity score for a task before decomposition.
|
|
20
|
-
* @property editPointCount - Total number of edit points
|
|
21
|
-
* @property editPoints - Array of edit points
|
|
22
|
-
* @property estimatedLines - Estimated number of lines to modify
|
|
23
|
-
* @property taskKind - The kind of task (MODIFY or CREATE)
|
|
24
|
-
* @category DecompositionGate
|
|
25
|
-
*/
|
|
26
|
-
export interface ComplexityScore {
|
|
27
|
-
editPointCount: number;
|
|
28
|
-
editPoints: EditPoint[];
|
|
29
|
-
estimatedLines: number;
|
|
30
|
-
taskKind: TaskKind;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Decision outcome from the decomposition gate.
|
|
34
|
-
* @property accepted - Whether the task is accepted for decomposition
|
|
35
|
-
* @property reason - Reason for acceptance or rejection
|
|
36
|
-
* @property score - Complexity score of the task
|
|
37
|
-
* @property redecomposeFeedback - Optional feedback for redecomposing the task (if rejected)
|
|
38
|
-
* @category DecompositionGate
|
|
39
|
-
*/
|
|
40
|
-
export interface GateDecision {
|
|
41
|
-
accepted: boolean;
|
|
42
|
-
reason: string;
|
|
43
|
-
score: ComplexityScore;
|
|
44
|
-
redecomposeFeedback?: string;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Mode of the decomposition gate.
|
|
48
|
-
* @property shadow - Logs only (no hard rejection)
|
|
49
|
-
* @property enforce - Hard rejects tasks that exceed complexity limits
|
|
50
|
-
* @category DecompositionGate
|
|
51
|
-
*/
|
|
52
|
-
export type GateMode = 'shadow' | 'enforce';
|
|
53
|
-
/**
|
|
54
|
-
* Configuration for the decomposition gate.
|
|
55
|
-
* @property mode - Operation mode (shadow or enforce)
|
|
56
|
-
* @property maxEditPointsModify - Maximum edit points for modify tasks (default: 1)
|
|
57
|
-
* @property maxLinesCreate - Maximum lines for create tasks (default: 200)
|
|
58
|
-
* @category DecompositionGate
|
|
59
|
-
*/
|
|
60
|
-
export interface GateConfig {
|
|
61
|
-
mode: GateMode;
|
|
62
|
-
maxEditPointsModify: number;
|
|
63
|
-
maxLinesCreate: number;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Input for the decomposition gate scoring.
|
|
67
|
-
* @property id - Unique identifier for the task
|
|
68
|
-
* @property taskKind - The kind of task (MODIFY or CREATE)
|
|
69
|
-
* @property description - Description of the task
|
|
70
|
-
* @property targetFiles - List of target files for the task
|
|
71
|
-
* @property estimatedLines - Estimated number of lines (optional)
|
|
72
|
-
* @category DecompositionGate
|
|
73
|
-
*/
|
|
74
|
-
export interface TicketInput {
|
|
75
|
-
id: string;
|
|
76
|
-
taskKind: TaskKind;
|
|
77
|
-
description: string;
|
|
78
|
-
targetFiles: string[];
|
|
79
|
-
estimatedLines?: number;
|
|
80
|
-
}
|
|
File without changes
|