@kognai/orchestrator-core 0.1.3 → 0.1.4
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/index.d.ts +1 -0
- package/dist/index.js +3 -0
- package/dist/lib/build-triage.d.ts +27 -0
- package/dist/lib/build-triage.js +202 -0
- package/dist/lib/engine-orchestrator.d.ts +2 -0
- package/dist/lib/engine-orchestrator.js +210 -134
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export * from './lib/trust-score-updater';
|
|
|
23
23
|
export * from './lib/citizenship';
|
|
24
24
|
export * from './lib/agent-registry';
|
|
25
25
|
export * from './lib/sprint-state';
|
|
26
|
+
export * from './lib/build-triage';
|
|
26
27
|
export * as ksl from './lib/ksl';
|
|
27
28
|
export * from './lib/wallet-state';
|
|
28
29
|
export * from './lib/ceo-wallet';
|
package/dist/index.js
CHANGED
|
@@ -82,6 +82,9 @@ __exportStar(require("./lib/citizenship"), exports);
|
|
|
82
82
|
__exportStar(require("./lib/agent-registry"), exports);
|
|
83
83
|
// TICKET-098 sprint runtime-state split (committed defs vs gitignored status).
|
|
84
84
|
__exportStar(require("./lib/sprint-state"), exports);
|
|
85
|
+
// TICKET-234 build triage seam — classifyBuildPath (ceremony-depth axis) +
|
|
86
|
+
// logBuildTriage. Consumed by the orchestrator run loop AND by kognai-build.
|
|
87
|
+
__exportStar(require("./lib/build-triage"), exports);
|
|
85
88
|
// Phase 3b-3 Wave B: KSL capture cluster (session records + error log + tap).
|
|
86
89
|
// Namespaced ('ksl.tapAttempt', 'ksl.writeRecord', 'ksl.record', …) to keep the
|
|
87
90
|
// generic 'record' export off the package's flat public surface.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type BuildPath = 'regulated' | 'fast';
|
|
2
|
+
export interface BuildTriageResult {
|
|
3
|
+
path: BuildPath;
|
|
4
|
+
reason: string;
|
|
5
|
+
triggers: string[];
|
|
6
|
+
sensitive: boolean;
|
|
7
|
+
sovereign: boolean;
|
|
8
|
+
complexity: 'low' | 'medium' | 'high';
|
|
9
|
+
taskCount: number;
|
|
10
|
+
codeFileCount: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Classify a build into a ceremony-depth path. Pure + synchronous: it only reads
|
|
14
|
+
* the sprint JSON + task list, so it adds negligible cost relative to the
|
|
15
|
+
* ceremony it gates. Default-to-regulated on uncertainty.
|
|
16
|
+
*
|
|
17
|
+
* @param sprint the raw sprint object (may carry regulated/strict/fast_track/sovereign flags)
|
|
18
|
+
* @param tasks the loaded task list (each with deliverables/context/type)
|
|
19
|
+
*/
|
|
20
|
+
export declare function classifyBuildPath(sprint: any, tasks: any[]): BuildTriageResult;
|
|
21
|
+
/**
|
|
22
|
+
* Append the triage decision to logs/routing/triage.jsonl (location-independent
|
|
23
|
+
* via engine-paths). Best-effort: never throws into the run loop. This is the
|
|
24
|
+
* audit trail required by the ticket — evidence that triage routes correctly and
|
|
25
|
+
* the means to audit any fast-tracked build later.
|
|
26
|
+
*/
|
|
27
|
+
export declare function logBuildTriage(sprintId: string, result: BuildTriageResult): void;
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.classifyBuildPath = classifyBuildPath;
|
|
4
|
+
exports.logBuildTriage = logBuildTriage;
|
|
5
|
+
/**
|
|
6
|
+
* build-triage.ts — TICKET-234: pre-orchestrator build triage (ceremony-depth axis).
|
|
7
|
+
*
|
|
8
|
+
* The orchestrator historically ran the SAME full ceremony for every build
|
|
9
|
+
* regardless of complexity or sensitivity (CEO assessment → execution →
|
|
10
|
+
* dual-supervisor review → CTO data analysis → CEO proposal cycle → post-sprint
|
|
11
|
+
* + agent minting). A 3-line `addTwo` cost 171s + the entire ceremony.
|
|
12
|
+
*
|
|
13
|
+
* This module adds a cheap classifier that runs BEFORE the orchestrator hands
|
|
14
|
+
* off to the swarm and routes the build to one of two execution paths:
|
|
15
|
+
*
|
|
16
|
+
* - REGULATED (full ceremony) — CEO · CTO governance gate · dual-supervisor
|
|
17
|
+
* review · reconciliation · the full CTO/CEO proposal cycle. Templates apply
|
|
18
|
+
* on this path only. For sensitive / sovereign / complex builds.
|
|
19
|
+
*
|
|
20
|
+
* - FAST — coder → single-supervisor review → the minimum safety/security/
|
|
21
|
+
* quality gate (QA gate: typecheck/compile/no-secrets, always on). No
|
|
22
|
+
* dual-supervisor, no CTO/CEO post-sprint ceremony, no templates. For
|
|
23
|
+
* simple, low-stakes, single-file, non-sensitive builds.
|
|
24
|
+
*
|
|
25
|
+
* It is the CEREMONY-DEPTH axis. It composes WITH `assessTaskComplexity`
|
|
26
|
+
* (engine-helpers), which scores the MODEL-ROUTING axis — they are orthogonal:
|
|
27
|
+
* a fast-tracked build can still route to a cloud model, and a regulated build
|
|
28
|
+
* can still run local. This stays a PURE HEURISTIC (no LLM call) so the triage
|
|
29
|
+
* never reintroduces the overhead it removes.
|
|
30
|
+
*
|
|
31
|
+
* Safety invariant: DEFAULT TO REGULATED on any uncertainty. `fast` is returned
|
|
32
|
+
* only when the build is provably simple AND non-sensitive AND non-sovereign.
|
|
33
|
+
* A `fast_track` opt-in never lowers the safety floor — sensitivity/complexity
|
|
34
|
+
* still force REGULATED.
|
|
35
|
+
*/
|
|
36
|
+
const fs_1 = require("fs");
|
|
37
|
+
const path_1 = require("path");
|
|
38
|
+
const engine_paths_1 = require("./engine-paths");
|
|
39
|
+
// Sensitivity keywords — PHI/PII, payments/financial, auth/secrets/credentials,
|
|
40
|
+
// crypto/on-chain/contracts, destructive or privileged operations. A match in a
|
|
41
|
+
// deliverable path, task context, or sprint goal forces REGULATED.
|
|
42
|
+
const SENSITIVE_KEYWORDS = [
|
|
43
|
+
// auth / secrets / credentials
|
|
44
|
+
'auth', 'secret', 'credential', 'password', 'passwd', 'api[_-]?key', 'apikey',
|
|
45
|
+
'access[_-]?token', 'private[_-]?key', 'privatekey', 'seed[_-]?phrase', 'mnemonic',
|
|
46
|
+
'oauth', 'jwt', 'session[_-]?token', 'vault',
|
|
47
|
+
// payments / financial
|
|
48
|
+
'payment', 'billing', 'invoice', 'payout', 'stripe', 'paypal', 'charge', 'refund',
|
|
49
|
+
'kyc', 'ledger', 'wallet', 'pricing',
|
|
50
|
+
// crypto / on-chain / contracts
|
|
51
|
+
'x402', 'crypto', 'on[_-]?chain', 'onchain', 'blockchain', 'smart[_-]?contract',
|
|
52
|
+
'erc20', 'erc-20', 'usdc', '\\$kog', 'viem', 'web3',
|
|
53
|
+
// PHI / PII / regulated data
|
|
54
|
+
'\\bphi\\b', '\\bpii\\b', 'gdpr', 'hipaa', 'personal[_-]?data', 'health[_-]?record',
|
|
55
|
+
// schema / data migrations (high-blast-radius, hard to roll back)
|
|
56
|
+
'migration', 'prisma/migrations', 'drop[_-]?table', 'alter[_-]?table',
|
|
57
|
+
];
|
|
58
|
+
// Destructive / privileged operations — context-level matches force REGULATED.
|
|
59
|
+
const DESTRUCTIVE_KEYWORDS = [
|
|
60
|
+
'rm\\s+-rf', 'drop\\s+table', 'delete\\s+from', 'truncate\\s+table',
|
|
61
|
+
'force[_-]?push', '--force', 'chmod\\s+777', 'sudo\\b', 'kill\\s+-9',
|
|
62
|
+
];
|
|
63
|
+
// Sensitive directories — a deliverable under one of these forces REGULATED.
|
|
64
|
+
const SENSITIVE_DIRS = [
|
|
65
|
+
'banks/', 'wallet', 'ceo-wallet', 'gates/', 'policy/', 'contracts/', 'omel/',
|
|
66
|
+
'x402-base/', 'prisma/', 'credential', '.env', 'auth/', 'secrets/',
|
|
67
|
+
];
|
|
68
|
+
// Architectural / cross-cutting keywords — a match means the change is not a
|
|
69
|
+
// simple single-concern build → REGULATED.
|
|
70
|
+
const ARCHITECTURAL_KEYWORDS = [
|
|
71
|
+
'architect', 'refactor', 'migrate', 'cross[_-]?cutting', 'system[_-]?wide',
|
|
72
|
+
'redesign', 'database', 'schema', 'infrastructure', 'orchestrat', 'pipeline',
|
|
73
|
+
'framework', 'breaking[_-]?change', 'rewrite',
|
|
74
|
+
];
|
|
75
|
+
function compile(words) {
|
|
76
|
+
return new RegExp(`(${words.join('|')})`, 'i');
|
|
77
|
+
}
|
|
78
|
+
const SENSITIVE_RE = compile(SENSITIVE_KEYWORDS);
|
|
79
|
+
const DESTRUCTIVE_RE = compile(DESTRUCTIVE_KEYWORDS);
|
|
80
|
+
const ARCH_RE = compile(ARCHITECTURAL_KEYWORDS);
|
|
81
|
+
function asBool(v) {
|
|
82
|
+
return v === true || v === 'true' || v === 1 || v === '1';
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Classify a build into a ceremony-depth path. Pure + synchronous: it only reads
|
|
86
|
+
* the sprint JSON + task list, so it adds negligible cost relative to the
|
|
87
|
+
* ceremony it gates. Default-to-regulated on uncertainty.
|
|
88
|
+
*
|
|
89
|
+
* @param sprint the raw sprint object (may carry regulated/strict/fast_track/sovereign flags)
|
|
90
|
+
* @param tasks the loaded task list (each with deliverables/context/type)
|
|
91
|
+
*/
|
|
92
|
+
function classifyBuildPath(sprint, tasks) {
|
|
93
|
+
const triggers = [];
|
|
94
|
+
const taskList = Array.isArray(tasks) ? tasks : [];
|
|
95
|
+
const taskCount = taskList.length;
|
|
96
|
+
// Gather all the text we scan for sensitivity/architecture signals.
|
|
97
|
+
const deliverablePaths = [];
|
|
98
|
+
const codeFiles = [];
|
|
99
|
+
for (const t of taskList) {
|
|
100
|
+
const d = (t && t.deliverables) || {};
|
|
101
|
+
const code = Array.isArray(d.code) ? d.code : [];
|
|
102
|
+
const tests = Array.isArray(d.tests) ? d.tests : [];
|
|
103
|
+
const docs = Array.isArray(d.docs) ? d.docs : [];
|
|
104
|
+
codeFiles.push(...code);
|
|
105
|
+
deliverablePaths.push(...code, ...tests, ...docs);
|
|
106
|
+
}
|
|
107
|
+
const codeFileCount = new Set(codeFiles).size;
|
|
108
|
+
const contextText = taskList
|
|
109
|
+
.map((t) => `${(t && (t.context || t.title || t.id)) || ''} ${(t && (t.type || t.task_type)) || ''}`)
|
|
110
|
+
.join(' ');
|
|
111
|
+
const goalText = `${sprint?.name || sprint?.title || ''} ${sprint?.goal || sprint?.description || ''}`;
|
|
112
|
+
const pathText = deliverablePaths.join(' ');
|
|
113
|
+
const haystack = `${goalText} ${contextText} ${pathText}`;
|
|
114
|
+
// ── Explicit flags ────────────────────────────────────────────────────────
|
|
115
|
+
const forcedRegulated = asBool(sprint?.regulated) || asBool(sprint?.strict) || asBool(process.env.KOGNAI_FORCE_REGULATED);
|
|
116
|
+
const requestedFast = asBool(sprint?.fast_track) || asBool(sprint?.fast);
|
|
117
|
+
if (forcedRegulated)
|
|
118
|
+
triggers.push('explicit:regulated');
|
|
119
|
+
// ── Sensitivity ───────────────────────────────────────────────────────────
|
|
120
|
+
let sensitive = false;
|
|
121
|
+
if (SENSITIVE_RE.test(haystack)) {
|
|
122
|
+
sensitive = true;
|
|
123
|
+
triggers.push(`sensitive:keyword(${(haystack.match(SENSITIVE_RE) || [])[1]})`);
|
|
124
|
+
}
|
|
125
|
+
if (DESTRUCTIVE_RE.test(haystack)) {
|
|
126
|
+
sensitive = true;
|
|
127
|
+
triggers.push(`sensitive:destructive(${(haystack.match(DESTRUCTIVE_RE) || [])[1]})`);
|
|
128
|
+
}
|
|
129
|
+
const dirHit = SENSITIVE_DIRS.find((dir) => pathText.toLowerCase().includes(dir.toLowerCase()));
|
|
130
|
+
if (dirHit) {
|
|
131
|
+
sensitive = true;
|
|
132
|
+
triggers.push(`sensitive:path(${dirHit})`);
|
|
133
|
+
}
|
|
134
|
+
// ── Sovereign / regulated domain ──────────────────────────────────────────
|
|
135
|
+
const sovereign = asBool(sprint?.sovereign) || asBool(sprint?.regulated_domain);
|
|
136
|
+
if (sovereign)
|
|
137
|
+
triggers.push('sovereign');
|
|
138
|
+
// ── Complexity (ceremony-depth, NOT model routing) ────────────────────────
|
|
139
|
+
const estimated = String(sprint?.estimated_complexity || '').toLowerCase();
|
|
140
|
+
const archHit = ARCH_RE.test(haystack);
|
|
141
|
+
if (archHit)
|
|
142
|
+
triggers.push(`complex:architectural(${(haystack.match(ARCH_RE) || [])[1]})`);
|
|
143
|
+
if (taskCount > 1)
|
|
144
|
+
triggers.push(`complex:multi-task(${taskCount})`);
|
|
145
|
+
if (codeFileCount > 1)
|
|
146
|
+
triggers.push(`complex:multi-file(${codeFileCount})`);
|
|
147
|
+
if (estimated === 'high')
|
|
148
|
+
triggers.push('complex:estimated-high');
|
|
149
|
+
let complexity = 'low';
|
|
150
|
+
if (archHit || taskCount > 2 || codeFileCount > 2 || estimated === 'high')
|
|
151
|
+
complexity = 'high';
|
|
152
|
+
else if (taskCount > 1 || codeFileCount > 1 || estimated === 'medium')
|
|
153
|
+
complexity = 'medium';
|
|
154
|
+
// ── Decision (default-to-regulated) ───────────────────────────────────────
|
|
155
|
+
// A build is FAST-eligible only if it is provably simple AND nothing sensitive
|
|
156
|
+
// / sovereign / forced fired. Anything ambiguous → REGULATED.
|
|
157
|
+
const isSimple = taskCount === 1 && codeFileCount <= 1 && !archHit && estimated !== 'high';
|
|
158
|
+
const blockFast = forcedRegulated || sensitive || sovereign || !isSimple;
|
|
159
|
+
let path;
|
|
160
|
+
let reason;
|
|
161
|
+
if (blockFast) {
|
|
162
|
+
path = 'regulated';
|
|
163
|
+
reason =
|
|
164
|
+
forcedRegulated ? 'explicit --regulated/--strict flag'
|
|
165
|
+
: sensitive ? `sensitive build (${triggers.filter((t) => t.startsWith('sensitive')).join(', ')})`
|
|
166
|
+
: sovereign ? 'sovereign / regulated-domain build'
|
|
167
|
+
: `complexity above fast-track threshold (${triggers.filter((t) => t.startsWith('complex')).join(', ') || 'multi-concern'})`;
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
path = 'fast';
|
|
171
|
+
reason = requestedFast
|
|
172
|
+
? 'fast-track opt-in; simple non-sensitive single-file build'
|
|
173
|
+
: 'simple non-sensitive single-file build → fast track';
|
|
174
|
+
}
|
|
175
|
+
return { path, reason, triggers, sensitive, sovereign, complexity, taskCount, codeFileCount };
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Append the triage decision to logs/routing/triage.jsonl (location-independent
|
|
179
|
+
* via engine-paths). Best-effort: never throws into the run loop. This is the
|
|
180
|
+
* audit trail required by the ticket — evidence that triage routes correctly and
|
|
181
|
+
* the means to audit any fast-tracked build later.
|
|
182
|
+
*/
|
|
183
|
+
function logBuildTriage(sprintId, result) {
|
|
184
|
+
try {
|
|
185
|
+
const file = (0, path_1.join)((0, engine_paths_1.resolveEnginePaths)().logs, 'routing', 'triage.jsonl');
|
|
186
|
+
(0, fs_1.mkdirSync)((0, path_1.dirname)(file), { recursive: true });
|
|
187
|
+
const row = {
|
|
188
|
+
sprint_id: sprintId,
|
|
189
|
+
path: result.path,
|
|
190
|
+
reason: result.reason,
|
|
191
|
+
triggers: result.triggers,
|
|
192
|
+
sensitive: result.sensitive,
|
|
193
|
+
sovereign: result.sovereign,
|
|
194
|
+
complexity: result.complexity,
|
|
195
|
+
task_count: result.taskCount,
|
|
196
|
+
code_file_count: result.codeFileCount,
|
|
197
|
+
logged_at: new Date().toISOString(),
|
|
198
|
+
};
|
|
199
|
+
(0, fs_1.appendFileSync)(file, JSON.stringify(row) + '\n');
|
|
200
|
+
}
|
|
201
|
+
catch { /* non-fatal — audit log must never break a run */ }
|
|
202
|
+
}
|
|
@@ -36,6 +36,7 @@ const engine_agents_1 = require("./engine-agents");
|
|
|
36
36
|
const engine_coding_agent_1 = require("./engine-coding-agent");
|
|
37
37
|
const engine_loaders_1 = require("./engine-loaders");
|
|
38
38
|
const orchestrate_engine_1 = require("./orchestrate-engine");
|
|
39
|
+
const build_triage_1 = require("./build-triage");
|
|
39
40
|
class Orchestrator {
|
|
40
41
|
spawnGate;
|
|
41
42
|
ceo;
|
|
@@ -44,6 +45,11 @@ class Orchestrator {
|
|
|
44
45
|
supervisor2;
|
|
45
46
|
agents = new Map();
|
|
46
47
|
tasks = [];
|
|
48
|
+
// TICKET-234: ceremony-depth path for this run. 'regulated' = full ceremony
|
|
49
|
+
// (default, safe); 'fast' = coder → single-supervisor → QA safety floor only.
|
|
50
|
+
// Set in run() by classifyBuildPath after tasks load. Defaults to regulated.
|
|
51
|
+
buildPath = 'regulated';
|
|
52
|
+
triage = null;
|
|
47
53
|
stats = { tasksExecuted: 0, approved: 0, rejected: 0, totalTokens: 0, conflicts: 0, escalations: 0 };
|
|
48
54
|
// Per-task structured run records — written to swarm run report at end of sprint
|
|
49
55
|
taskRuns = [];
|
|
@@ -219,6 +225,13 @@ class Orchestrator {
|
|
|
219
225
|
// Normalize priority: sprint JSON may omit it
|
|
220
226
|
if (!task.priority)
|
|
221
227
|
task.priority = 'medium';
|
|
228
|
+
// Normalize status: sprint JSON may omit it. Without a status the task is
|
|
229
|
+
// silently skipped in Phase 2 (`if (task.status !== 'pending') continue`),
|
|
230
|
+
// so the full ceremony runs but executes 0 tasks. Default a MISSING status
|
|
231
|
+
// to 'pending'; explicit terminal states (done/skipped/rejected/approved)
|
|
232
|
+
// are preserved so re-runs don't re-execute finished work.
|
|
233
|
+
if (!task.status)
|
|
234
|
+
task.status = 'pending';
|
|
222
235
|
// Fix: task_target used as file path (e.g., 'scripts/lib/foo.ts') must be cleared
|
|
223
236
|
// so it doesn't confuse the routing switch which expects: local|cloud-code|cloud-exec|cloud-post
|
|
224
237
|
const VALID_ROUTING_TARGETS = ['local', 'cloud-code', 'cloud-exec', 'cloud-post'];
|
|
@@ -404,17 +417,23 @@ ONLY output the JSON array. No markdown, no explanation.`;
|
|
|
404
417
|
monotask_state_machine_1.MonotaskSM.release(subtask.agent, subtask.id, `no files: ${inferred.slice(0, 60)}`);
|
|
405
418
|
return false;
|
|
406
419
|
}
|
|
407
|
-
//
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
this.
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
this.
|
|
420
|
+
// Supervisor review. TICKET-234: fast track → single supervisor; regulated → dual.
|
|
421
|
+
let review;
|
|
422
|
+
if (this.buildPath === 'fast') {
|
|
423
|
+
review = await this.supervisor.reviewTask(subtask, result.files);
|
|
424
|
+
}
|
|
425
|
+
else {
|
|
426
|
+
const [review1, review2] = await Promise.all([
|
|
427
|
+
this.supervisor.reviewTask(subtask, result.files),
|
|
428
|
+
this.supervisor2.reviewTask(subtask, result.files),
|
|
429
|
+
]);
|
|
430
|
+
const dualResult = await (0, engine_agents_1.reconcileSupervisorReviews)(review1, review2, subtask, this.ceo);
|
|
431
|
+
review = dualResult.finalReview;
|
|
432
|
+
if (!dualResult.consensus)
|
|
433
|
+
this.stats.conflicts++;
|
|
434
|
+
if (dualResult.escalatedToCEO)
|
|
435
|
+
this.stats.escalations++;
|
|
436
|
+
}
|
|
418
437
|
lastReview = review;
|
|
419
438
|
// TICKET-214: instrument SUB-TASK attempts. The MAIN task loop already taps KSL +
|
|
420
439
|
// records reputation, but the split sub-task loop did neither — so split sprints
|
|
@@ -787,18 +806,28 @@ ONLY output the JSON array. No markdown, no explanation.`;
|
|
|
787
806
|
return;
|
|
788
807
|
}
|
|
789
808
|
(0, engine_primitives_1.log)(engine_primitives_1.c.gray, ` [QA-gate] PASS — ${qaResult.reason}`);
|
|
790
|
-
//
|
|
809
|
+
// Supervisor review. TICKET-234: fast track runs ONE supervisor (no dual
|
|
810
|
+
// review / reconcile / CEO escalation); regulated runs the dual-supervisor
|
|
811
|
+
// ceremony. The QA gate above already enforced the safety floor
|
|
812
|
+
// (typecheck/compile/no-secrets) on both paths.
|
|
791
813
|
task.status = 'review';
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
this.
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
814
|
+
let review;
|
|
815
|
+
if (this.buildPath === 'fast') {
|
|
816
|
+
review = await this.supervisor.reviewTask(task, result.files);
|
|
817
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.gray, ' [fast-track] single-supervisor review (dual-supervisor skipped)');
|
|
818
|
+
}
|
|
819
|
+
else {
|
|
820
|
+
const [review1, review2] = await Promise.all([
|
|
821
|
+
this.supervisor.reviewTask(task, result.files),
|
|
822
|
+
this.supervisor2.reviewTask(task, result.files),
|
|
823
|
+
]);
|
|
824
|
+
const dualResult = await (0, engine_agents_1.reconcileSupervisorReviews)(review1, review2, task, this.ceo);
|
|
825
|
+
review = dualResult.finalReview;
|
|
826
|
+
if (!dualResult.consensus)
|
|
827
|
+
this.stats.conflicts++;
|
|
828
|
+
if (dualResult.escalatedToCEO)
|
|
829
|
+
this.stats.escalations++;
|
|
830
|
+
}
|
|
802
831
|
lastReview = review;
|
|
803
832
|
task.output = { files: result.files, commit: '', model: result.model, review };
|
|
804
833
|
// CTO-006 telemetry-blackout hotfix (2026-05-29, Slice A of TICKET-135):
|
|
@@ -1050,6 +1079,28 @@ ONLY output the JSON array. No markdown, no explanation.`;
|
|
|
1050
1079
|
await mc.disconnect().catch(() => { });
|
|
1051
1080
|
return;
|
|
1052
1081
|
}
|
|
1082
|
+
// ── BUILD TRIAGE — TICKET-234 (ceremony-depth routing) ─────────────────
|
|
1083
|
+
// Classify the build BEFORE the swarm ceremony: simple, non-sensitive,
|
|
1084
|
+
// single-file builds take the FAST path (single-supervisor + QA safety
|
|
1085
|
+
// floor, no CTO/CEO post-sprint ceremony, no templates); everything
|
|
1086
|
+
// sensitive/sovereign/complex/ambiguous takes the REGULATED full ceremony.
|
|
1087
|
+
// Pure heuristic — negligible cost vs the ceremony it gates. SOVEREIGN_MODE
|
|
1088
|
+
// always forces regulated: a sovereign build is regulated by definition.
|
|
1089
|
+
{
|
|
1090
|
+
const triageSprint = JSON.parse((0, fs_1.readFileSync)(process.argv[2] || 'sprints/current.json', 'utf-8'));
|
|
1091
|
+
this.triage = (0, build_triage_1.classifyBuildPath)(triageSprint, this.tasks);
|
|
1092
|
+
if (engine_primitives_1.SOVEREIGN_MODE && this.triage.path === 'fast') {
|
|
1093
|
+
this.triage = { ...this.triage, path: 'regulated', reason: 'sovereign mode → regulated by definition', triggers: [...this.triage.triggers, 'sovereign:mode'], sovereign: true };
|
|
1094
|
+
}
|
|
1095
|
+
this.buildPath = this.triage.path;
|
|
1096
|
+
(0, build_triage_1.logBuildTriage)(_evtSprintId, this.triage);
|
|
1097
|
+
const col = this.buildPath === 'fast' ? engine_primitives_1.c.green : engine_primitives_1.c.magenta;
|
|
1098
|
+
(0, engine_primitives_1.log)(col, `\n--- Build Triage: ${this.buildPath.toUpperCase()} ---`);
|
|
1099
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.gray, ` ${this.triage.reason}`);
|
|
1100
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.gray, ` complexity=${this.triage.complexity} tasks=${this.triage.taskCount} code-files=${this.triage.codeFileCount}${this.triage.triggers.length ? ` · triggers: ${this.triage.triggers.join(', ')}` : ''}`);
|
|
1101
|
+
if (this.buildPath === 'fast')
|
|
1102
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.gray, ' Fast track: single-supervisor + QA safety floor; skipping dual-supervisor, CTO/CEO post-sprint ceremony, and templates.');
|
|
1103
|
+
}
|
|
1053
1104
|
// ── CTO APPROVAL GATE — Exec Protocol §17 ──────────────────────────────
|
|
1054
1105
|
// Every autonomous sprint must be approved by the CTO agent before execution.
|
|
1055
1106
|
// Human-submitted sprints (source: 'human') are auto-approved.
|
|
@@ -1100,8 +1151,14 @@ ONLY output the JSON array. No markdown, no explanation.`;
|
|
|
1100
1151
|
}
|
|
1101
1152
|
// ── End CTO Gate ────────────────────────────────────────────────────────
|
|
1102
1153
|
// 2. CEO initial assessment (B.14: once per sprint, not once per conflict)
|
|
1103
|
-
|
|
1104
|
-
|
|
1154
|
+
// TICKET-234: regulated path only — the fast track skips the CEO ceremony.
|
|
1155
|
+
if (this.buildPath === 'regulated') {
|
|
1156
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.magenta, '\n--- Phase 1: CEO Initial Assessment ---');
|
|
1157
|
+
await this.ceo.reviewSprintProgress(this.tasks);
|
|
1158
|
+
}
|
|
1159
|
+
else {
|
|
1160
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.gray, '\n--- Phase 1: CEO Initial Assessment — SKIPPED (fast track) ---');
|
|
1161
|
+
}
|
|
1105
1162
|
const _ceoIntentDone = true; // flag for Phase 5: only re-run if ≥2 rejected
|
|
1106
1163
|
// 3. Execute coding tasks with review loop
|
|
1107
1164
|
(0, engine_primitives_1.log)(engine_primitives_1.c.blue, '\n--- Phase 2: Sprint Execution ---');
|
|
@@ -1220,79 +1277,91 @@ ONLY output the JSON array. No markdown, no explanation.`;
|
|
|
1220
1277
|
}
|
|
1221
1278
|
}
|
|
1222
1279
|
// 4. CTO data-driven analysis + CMO reports
|
|
1223
|
-
|
|
1280
|
+
// TICKET-234: Phases 3–6 (CTO/CEO governance ceremony + agent minting +
|
|
1281
|
+
// daily report) run on the REGULATED path only. Fast track ships after the
|
|
1282
|
+
// per-task review + QA safety floor; the financial telemetry below (wallet
|
|
1283
|
+
// burn + budget freeze/warning) still runs on both paths.
|
|
1224
1284
|
let ctoReport = { summary: '', proposals: [], metrics_reviewed: [] };
|
|
1225
1285
|
let ctoDecisions = '';
|
|
1226
1286
|
let cmoReports = '';
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
(0,
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
(0,
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
(0,
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
(0,
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
if (
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1287
|
+
if (this.buildPath === 'regulated') {
|
|
1288
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.cyan, '\n--- Phase 3: CTO Data-Driven Analysis + CMO Reports ---');
|
|
1289
|
+
try {
|
|
1290
|
+
ctoReport = await this.cto.analyze();
|
|
1291
|
+
// Load CMO reports (produced independently by Manus AI runner)
|
|
1292
|
+
cmoReports = (0, engine_loaders_1.loadCMOReports)();
|
|
1293
|
+
if (cmoReports) {
|
|
1294
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.magenta, ' CMO reports found — will include in CEO review');
|
|
1295
|
+
}
|
|
1296
|
+
else {
|
|
1297
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.gray, ' No CMO reports available yet');
|
|
1298
|
+
}
|
|
1299
|
+
// Load CTO tech-watch reports (produced independently by run-cto-techwatch.ts)
|
|
1300
|
+
const ctoTechWatch = (0, engine_loaders_1.loadCTOTechWatchReports)();
|
|
1301
|
+
if (ctoTechWatch) {
|
|
1302
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.cyan, ' CTO tech-watch reports found — will include in CEO review');
|
|
1303
|
+
cmoReports = cmoReports ? cmoReports + '\n\n' + ctoTechWatch : ctoTechWatch;
|
|
1304
|
+
}
|
|
1305
|
+
else {
|
|
1306
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.gray, ' No CTO tech-watch reports available yet');
|
|
1307
|
+
}
|
|
1308
|
+
// Load Grok intelligence feed (Grok AI monitors X/Twitter for OpenClaw news)
|
|
1309
|
+
const grokFeed = (0, engine_loaders_1.loadGrokFeed)();
|
|
1310
|
+
if (grokFeed) {
|
|
1311
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.magenta, ' Grok intelligence feed found — will include in CEO review');
|
|
1312
|
+
cmoReports = cmoReports ? cmoReports + '\n\n' + grokFeed : grokFeed;
|
|
1313
|
+
}
|
|
1314
|
+
else {
|
|
1315
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.gray, ' No Grok feed reports available');
|
|
1316
|
+
}
|
|
1317
|
+
// Load Owner Directives (highest priority — always included)
|
|
1318
|
+
const ownerDirectives = (0, engine_loaders_1.loadOwnerDirectives)();
|
|
1319
|
+
if (ownerDirectives) {
|
|
1320
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.magenta, " Owner directives found — will include in CEO review (highest priority)");
|
|
1321
|
+
cmoReports = ownerDirectives + (cmoReports ? "\n\n" + cmoReports : "");
|
|
1322
|
+
}
|
|
1323
|
+
// 5. CEO reviews CTO proposals + CMO reports
|
|
1324
|
+
if (ctoReport.proposals.length > 0 || cmoReports) {
|
|
1325
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.magenta, '\n--- Phase 4: CEO Reviews CTO Proposals + CMO Reports ---');
|
|
1326
|
+
ctoDecisions = await this.ceo.reviewCTOProposals(ctoReport);
|
|
1327
|
+
// Persist CEO decisions for CTO feedback loop + approved proposals tracking
|
|
1328
|
+
(0, orchestrate_engine_1.persistCEODecisions)(ctoDecisions, ctoReport);
|
|
1329
|
+
// Handle approved new_agent proposals
|
|
1330
|
+
const agentCreator = new engine_agents_1.AgentCreator(this.spawnGate);
|
|
1331
|
+
for (const proposal of ctoReport.proposals) {
|
|
1332
|
+
if (proposal.category === 'new_agent' && proposal.agent_spec) {
|
|
1333
|
+
// Check if CEO approved this specific proposal
|
|
1334
|
+
if (ctoDecisions.includes(proposal.id) && ctoDecisions.toUpperCase().includes('APPROVED')) {
|
|
1335
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.green, `\n 🤖 CEO approved new agent: ${proposal.agent_spec.name}`);
|
|
1336
|
+
agentCreator.createAgent(proposal.agent_spec);
|
|
1337
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.green, ` Agent will be loaded on next orchestrator run.`);
|
|
1338
|
+
}
|
|
1339
|
+
else {
|
|
1340
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.yellow, ` CEO did not approve agent: ${proposal.agent_spec.name}`);
|
|
1341
|
+
}
|
|
1279
1342
|
}
|
|
1280
1343
|
}
|
|
1281
1344
|
}
|
|
1345
|
+
else {
|
|
1346
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.cyan, ' No proposals from CTO — stack is current and optimized');
|
|
1347
|
+
ctoDecisions = 'No proposals to review.';
|
|
1348
|
+
}
|
|
1282
1349
|
}
|
|
1283
|
-
|
|
1284
|
-
(0, engine_primitives_1.log)(engine_primitives_1.c.
|
|
1285
|
-
ctoDecisions = '
|
|
1350
|
+
catch (error) {
|
|
1351
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.yellow, ` CTO/CEO review cycle skipped: ${error.message}`);
|
|
1352
|
+
ctoDecisions = 'CTO analysis was not performed this run.';
|
|
1286
1353
|
}
|
|
1287
1354
|
}
|
|
1288
|
-
|
|
1289
|
-
(0, engine_primitives_1.log)(engine_primitives_1.c.
|
|
1290
|
-
ctoDecisions = 'CTO analysis was not performed this run.';
|
|
1355
|
+
else {
|
|
1356
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.gray, '\n--- Phases 3–4: CTO/CEO Governance Ceremony — SKIPPED (fast track) ---');
|
|
1291
1357
|
}
|
|
1292
1358
|
// 6. CEO final assessment — B.14: only runs if ≥2 tasks rejected (skips if sprint went well)
|
|
1293
1359
|
const rejectedCount = this.tasks.filter(t => t.status === 'rejected').length;
|
|
1294
1360
|
(0, engine_primitives_1.log)(engine_primitives_1.c.magenta, '\n--- Phase 5: CEO Final Assessment ---');
|
|
1295
|
-
if (
|
|
1361
|
+
if (this.buildPath === 'fast') {
|
|
1362
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.gray, ' Fast track — skipping CEO final assessment');
|
|
1363
|
+
}
|
|
1364
|
+
else if (rejectedCount >= 2) {
|
|
1296
1365
|
(0, engine_primitives_1.log)(engine_primitives_1.c.magenta, ` ${rejectedCount} tasks rejected — CEO reviewing...`);
|
|
1297
1366
|
await this.ceo.reviewSprintProgress(this.tasks);
|
|
1298
1367
|
}
|
|
@@ -1309,63 +1378,68 @@ ONLY output the JSON array. No markdown, no explanation.`;
|
|
|
1309
1378
|
(0, event_bus_publisher_1.publishBudgetWarning)(_evtSprintId, _ws.burnPct, _ws.spentThisMonth, _ws.monthlyBudget).catch(() => { });
|
|
1310
1379
|
}
|
|
1311
1380
|
catch { /* wallet state unavailable */ }
|
|
1312
|
-
// 6b. CTO autonomous post-sprint analysis
|
|
1313
|
-
(0, engine_primitives_1.log)(engine_primitives_1.c.cyan, '\n--- Phase 5b: CTO Post-Sprint Analysis (Autonomous) ---');
|
|
1381
|
+
// 6b. CTO autonomous post-sprint analysis — regulated path only (TICKET-234)
|
|
1314
1382
|
let postSprintReport = '';
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1383
|
+
if (this.buildPath === 'regulated') {
|
|
1384
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.cyan, '\n--- Phase 5b: CTO Post-Sprint Analysis (Autonomous) ---');
|
|
1385
|
+
try {
|
|
1386
|
+
postSprintReport = await this.cto.postSprintAnalysis(this.tasks, this.stats);
|
|
1387
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.cyan, ' Post-sprint analysis saved to reports/cto/');
|
|
1388
|
+
// Extract proposals from post-sprint analysis and feed into CEO review
|
|
1389
|
+
const jsonMatch = postSprintReport.match(/```json\s*([\s\S]*?)```/);
|
|
1390
|
+
if (jsonMatch) {
|
|
1391
|
+
try {
|
|
1392
|
+
const parsed = JSON.parse(jsonMatch[1].trim());
|
|
1393
|
+
const postSprintProposals = parsed.proposals || [];
|
|
1394
|
+
if (postSprintProposals.length > 0) {
|
|
1395
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.cyan, ` Found ${postSprintProposals.length} proposals — sending to CEO for autonomous review`);
|
|
1396
|
+
// Build CTOReport for CEO review
|
|
1397
|
+
const postSprintCTOReport = {
|
|
1398
|
+
summary: parsed.summary || 'Post-sprint analysis proposals',
|
|
1399
|
+
proposals: postSprintProposals.map((p) => ({
|
|
1400
|
+
id: p.id,
|
|
1401
|
+
title: p.title,
|
|
1402
|
+
category: p.category,
|
|
1403
|
+
description: p.description,
|
|
1404
|
+
estimated_impact: p.estimated_impact || '',
|
|
1405
|
+
risk_level: p.risk_level || 'medium',
|
|
1406
|
+
implementation_steps: p.implementation_steps || [],
|
|
1407
|
+
})),
|
|
1408
|
+
metrics_reviewed: ['sprint_results', 'failure_patterns', 'trend_analysis'],
|
|
1409
|
+
};
|
|
1410
|
+
// Phase 5c: CEO autonomously reviews post-sprint proposals
|
|
1411
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.magenta, '\n--- Phase 5c: CEO Reviews Post-Sprint Proposals (Autonomous) ---');
|
|
1412
|
+
const postSprintDecisions = await this.ceo.reviewCTOProposals(postSprintCTOReport);
|
|
1413
|
+
// Persist CEO decisions + update approved-proposals tracker
|
|
1414
|
+
(0, orchestrate_engine_1.persistCEODecisions)(postSprintDecisions, postSprintCTOReport);
|
|
1415
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.magenta, ' CEO post-sprint proposal review complete');
|
|
1416
|
+
}
|
|
1417
|
+
else {
|
|
1418
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.cyan, ' No proposals in post-sprint analysis');
|
|
1419
|
+
}
|
|
1346
1420
|
}
|
|
1347
|
-
|
|
1348
|
-
(0, engine_primitives_1.log)(engine_primitives_1.c.
|
|
1421
|
+
catch (parseErr) {
|
|
1422
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.yellow, ` Could not parse post-sprint proposals JSON: ${parseErr.message}`);
|
|
1349
1423
|
}
|
|
1350
1424
|
}
|
|
1351
|
-
catch (parseErr) {
|
|
1352
|
-
(0, engine_primitives_1.log)(engine_primitives_1.c.yellow, ` Could not parse post-sprint proposals JSON: ${parseErr.message}`);
|
|
1353
|
-
}
|
|
1354
1425
|
}
|
|
1426
|
+
catch (error) {
|
|
1427
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.yellow, ` Post-sprint analysis skipped: ${error.message}`);
|
|
1428
|
+
}
|
|
1429
|
+
// 7. CEO generates daily report
|
|
1430
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.magenta, '\n--- Phase 6: Daily Report Generation ---');
|
|
1431
|
+
const ctoReportStr = `Summary: ${ctoReport.summary}\nProposals: ${ctoReport.proposals.length}\n${ctoReport.proposals.map(p => `- [${p.category}] ${p.title} (${p.risk_level})`).join('\n')}`;
|
|
1432
|
+
const grokSection = (0, engine_loaders_1.loadGrokFeed)();
|
|
1433
|
+
const cmoSection = cmoReports
|
|
1434
|
+
? '\n\n## CMO Activity (Manus AI)\n' + cmoReports.substring(0, 2000)
|
|
1435
|
+
: '\n\nCMO: No reports available this cycle.';
|
|
1436
|
+
const grokForReport = grokSection ? '\n\n## Grok Intelligence Feed\nGrok AI reports available — included in CTO/CEO analysis.' : '\n\nGrok: No feed reports this cycle.';
|
|
1437
|
+
const postSprintSection = postSprintReport ? '\n\n## CTO Post-Sprint Analysis\n' + postSprintReport.substring(0, 2000) : '';
|
|
1438
|
+
await this.ceo.generateDailyReport(this.tasks, this.stats, ctoReportStr + cmoSection + grokForReport + postSprintSection, ctoDecisions);
|
|
1355
1439
|
}
|
|
1356
|
-
|
|
1357
|
-
(0, engine_primitives_1.log)(engine_primitives_1.c.
|
|
1440
|
+
else {
|
|
1441
|
+
(0, engine_primitives_1.log)(engine_primitives_1.c.gray, '\n--- Phases 5b–6: Post-Sprint Ceremony + Daily Report — SKIPPED (fast track) ---');
|
|
1358
1442
|
}
|
|
1359
|
-
// 7. CEO generates daily report
|
|
1360
|
-
(0, engine_primitives_1.log)(engine_primitives_1.c.magenta, '\n--- Phase 6: Daily Report Generation ---');
|
|
1361
|
-
const ctoReportStr = `Summary: ${ctoReport.summary}\nProposals: ${ctoReport.proposals.length}\n${ctoReport.proposals.map(p => `- [${p.category}] ${p.title} (${p.risk_level})`).join('\n')}`;
|
|
1362
|
-
const grokSection = (0, engine_loaders_1.loadGrokFeed)();
|
|
1363
|
-
const cmoSection = cmoReports
|
|
1364
|
-
? '\n\n## CMO Activity (Manus AI)\n' + cmoReports.substring(0, 2000)
|
|
1365
|
-
: '\n\nCMO: No reports available this cycle.';
|
|
1366
|
-
const grokForReport = grokSection ? '\n\n## Grok Intelligence Feed\nGrok AI reports available — included in CTO/CEO analysis.' : '\n\nGrok: No feed reports this cycle.';
|
|
1367
|
-
const postSprintSection = postSprintReport ? '\n\n## CTO Post-Sprint Analysis\n' + postSprintReport.substring(0, 2000) : '';
|
|
1368
|
-
await this.ceo.generateDailyReport(this.tasks, this.stats, ctoReportStr + cmoSection + grokForReport + postSprintSection, ctoDecisions);
|
|
1369
1443
|
// 8. Save updated sprint state
|
|
1370
1444
|
const sprintFile = process.argv[2] || 'sprints/current.json';
|
|
1371
1445
|
(0, fs_1.writeFileSync)(sprintFile, JSON.stringify({ tasks: this.tasks }, null, 2));
|
|
@@ -1412,6 +1486,8 @@ ONLY output the JSON array. No markdown, no explanation.`;
|
|
|
1412
1486
|
git_head_before: gitHeadBefore,
|
|
1413
1487
|
git_head_after: gitHeadAfter,
|
|
1414
1488
|
sovereign_mode: engine_primitives_1.SOVEREIGN_MODE,
|
|
1489
|
+
build_path: this.buildPath, // TICKET-234: 'regulated' | 'fast'
|
|
1490
|
+
triage: this.triage, // TICKET-234: classifier reason + triggers
|
|
1415
1491
|
summary: {
|
|
1416
1492
|
total_tasks: this.tasks.length,
|
|
1417
1493
|
done: this.tasks.filter(t => t.status === 'done').length,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kognai/orchestrator-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
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",
|