@ngockhoale/ukit 3.1.9 → 3.3.0
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/CHANGELOG.md +27 -0
- package/package.json +1 -1
- package/src/cli/commands/memory.js +11 -87
- package/src/cli/commands/selfImprove.js +55 -0
- package/src/cli/commands/telemetry.js +45 -3
- package/src/cli/index.js +7 -0
- package/src/core/agentRuntime/adapters.js +177 -0
- package/src/core/agentRuntime/contract.js +77 -0
- package/src/core/agentRuntime/diagnostics.js +343 -42
- package/src/core/agentRuntime/eventStore.js +139 -0
- package/src/core/agentRuntime/planCompiler.js +45 -6
- package/src/core/agentRuntime/planLibrary.js +43 -7
- package/src/core/agentRuntime/plans/bugfix-loop.json +1 -0
- package/src/core/agentRuntime/plans/flag-promotion.json +138 -0
- package/src/core/agentRuntime/plans/handoff-review-batch.json +1 -0
- package/src/core/agentRuntime/plans/release-check.json +2 -1
- package/src/core/agentRuntime/promotion.js +147 -9
- package/src/core/agentRuntime/runtimeSupport.js +18 -0
- package/src/core/agentRuntime/supervisor.js +44 -2
- package/src/core/agentRuntime/telemetry.js +123 -0
- package/src/core/agentRuntime/vmEngine.js +51 -10
- package/src/core/memory/episodes.js +168 -0
- package/src/core/metadata.js +21 -0
- package/src/core/runInstallPipeline.js +6 -1
- package/src/core/runtimeConfig.js +71 -40
- package/src/decision/client.js +4 -5
- package/src/decision/runtimeDecide.js +183 -5
- package/src/learning/selfImprove.js +205 -0
- package/src/learning/tunedOverlay.js +112 -0
- package/template_project/.claude/hooks/session-episode.sh +35 -15
- package/template_project/.claude/ukit/index/route-task.mjs +13 -0
- package/template_project/.claude/ukit/index/unic-decision.mjs +1 -2
- package/template_project/.claude/ukit/runtime/self-improve-trigger.mjs +98 -0
- package/template_project/ukit/storage/config.json +68 -17
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// self-improve-trigger.mjs — fire-and-forget launcher for `ukit self-improve`.
|
|
2
|
+
//
|
|
3
|
+
// Called from every engine's natural lifecycle point:
|
|
4
|
+
// * Claude Code — SessionEnd (session-episode.sh)
|
|
5
|
+
// * omp — session_stop (same script via ukit-bridge.js)
|
|
6
|
+
// * Codex — route-task.mjs, the helperCommand Codex runs per task
|
|
7
|
+
// (Codex has no hook lifecycle)
|
|
8
|
+
//
|
|
9
|
+
// Contract:
|
|
10
|
+
// * NEVER blocks the caller: the CLI runs detached (own process group,
|
|
11
|
+
// stdio ignored, unref'd); this module returns in a few ms.
|
|
12
|
+
// * NEVER throws; every failure is a silent no-op — self-improvement is
|
|
13
|
+
// background work and must not add noise to a user's session.
|
|
14
|
+
// * Cheap gates first: config opt-out (learning.selfImprove.enabled:false),
|
|
15
|
+
// the pass's own rate-limit stamp, and the CLI locator. The locator
|
|
16
|
+
// (.ukit/storage/cli.json, written by `ukit install`) holds absolute
|
|
17
|
+
// node + bin paths, so GUI-launched hosts without nvm on PATH still work;
|
|
18
|
+
// without it there is no trusted CLI to launch and the trigger no-ops.
|
|
19
|
+
//
|
|
20
|
+
// CLI: node self-improve-trigger.mjs [projectRoot]
|
|
21
|
+
|
|
22
|
+
import fs from 'node:fs';
|
|
23
|
+
import path from 'node:path';
|
|
24
|
+
import { spawn } from 'node:child_process';
|
|
25
|
+
import { fileURLToPath } from 'node:url';
|
|
26
|
+
|
|
27
|
+
export const MIN_INTERVAL_MS = 10 * 60 * 1000;
|
|
28
|
+
|
|
29
|
+
function readJson(filePath) {
|
|
30
|
+
try {
|
|
31
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
32
|
+
} catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// The locator is a project file: never trust it blindly. `bin` must be the
|
|
38
|
+
// `bin/ukit` of a directory whose package.json names @ngockhoale/ukit, and
|
|
39
|
+
// `node` must be a node executable — a committed/forged cli.json cannot turn
|
|
40
|
+
// the trigger into an arbitrary-binary launcher.
|
|
41
|
+
export function resolveCliLocator(projectRoot) {
|
|
42
|
+
const locator = readJson(path.join(projectRoot, '.ukit', 'storage', 'cli.json'));
|
|
43
|
+
if (!locator || typeof locator.node !== 'string' || typeof locator.bin !== 'string') return null;
|
|
44
|
+
if (!/^node(\.exe)?$/i.test(path.basename(locator.node))) return null;
|
|
45
|
+
if (path.basename(locator.bin) !== 'ukit' || path.basename(path.dirname(locator.bin)) !== 'bin') return null;
|
|
46
|
+
const pkg = readJson(path.join(path.dirname(locator.bin), '..', 'package.json'));
|
|
47
|
+
if (pkg?.name !== '@ngockhoale/ukit') return null;
|
|
48
|
+
if (!fs.existsSync(locator.node) || !fs.existsSync(locator.bin)) return null;
|
|
49
|
+
return { node: locator.node, bin: locator.bin };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function selfImproveDue(projectRoot, now = Date.now()) {
|
|
53
|
+
const config = readJson(path.join(projectRoot, '.ukit', 'storage', 'config.json'));
|
|
54
|
+
if (config?.learning?.selfImprove?.enabled === false) return false;
|
|
55
|
+
const stamp = readJson(path.join(projectRoot, '.ukit', 'storage', 'learning', 'self-improve.json'));
|
|
56
|
+
const lastRunAt = Date.parse(stamp?.lastRunAt ?? '');
|
|
57
|
+
return !(Number.isFinite(lastRunAt) && now - lastRunAt < MIN_INTERVAL_MS);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Returns true when a pass was launched.
|
|
61
|
+
export function triggerSelfImprove({ projectRoot, now = Date.now(), spawnImpl = spawn } = {}) {
|
|
62
|
+
try {
|
|
63
|
+
if (typeof projectRoot !== 'string' || projectRoot.length === 0) return false;
|
|
64
|
+
const root = path.resolve(projectRoot);
|
|
65
|
+
if (!selfImproveDue(root, now)) return false;
|
|
66
|
+
const cli = resolveCliLocator(root);
|
|
67
|
+
if (!cli) return false;
|
|
68
|
+
const env = { ...process.env };
|
|
69
|
+
// Hook self-deadlines must not leak into a background pass.
|
|
70
|
+
delete env.UKIT_HOOK_DEADLINE_MS;
|
|
71
|
+
const child = spawnImpl(cli.node, [cli.bin, 'self-improve', '--if-due', '--quiet'], {
|
|
72
|
+
cwd: root,
|
|
73
|
+
env,
|
|
74
|
+
detached: true,
|
|
75
|
+
stdio: 'ignore',
|
|
76
|
+
windowsHide: true,
|
|
77
|
+
});
|
|
78
|
+
child.on?.('error', () => {});
|
|
79
|
+
child.unref?.();
|
|
80
|
+
return true;
|
|
81
|
+
} catch {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function isMainModule() {
|
|
87
|
+
try {
|
|
88
|
+
const self = fs.realpathSync(fileURLToPath(import.meta.url));
|
|
89
|
+
const invoked = process.argv[1] ? fs.realpathSync(process.argv[1]) : '';
|
|
90
|
+
return self === invoked;
|
|
91
|
+
} catch {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (isMainModule()) {
|
|
97
|
+
triggerSelfImprove({ projectRoot: process.argv[2] || process.env.CLAUDE_PROJECT_DIR || process.cwd() });
|
|
98
|
+
}
|
|
@@ -85,16 +85,16 @@
|
|
|
85
85
|
},
|
|
86
86
|
"routing": {
|
|
87
87
|
"routeSchema": {
|
|
88
|
-
"stage": "
|
|
88
|
+
"stage": "default"
|
|
89
89
|
},
|
|
90
90
|
"rigor": {
|
|
91
|
-
"stage": "
|
|
91
|
+
"stage": "default"
|
|
92
92
|
},
|
|
93
93
|
"fastPath": {
|
|
94
|
-
"stage": "
|
|
94
|
+
"stage": "default"
|
|
95
95
|
},
|
|
96
96
|
"escalation": {
|
|
97
|
-
"stage": "
|
|
97
|
+
"stage": "default"
|
|
98
98
|
}
|
|
99
99
|
},
|
|
100
100
|
"decisionPlane": {
|
|
@@ -316,7 +316,20 @@
|
|
|
316
316
|
},
|
|
317
317
|
"recall": {
|
|
318
318
|
"maxRecords": 8
|
|
319
|
-
}
|
|
319
|
+
},
|
|
320
|
+
"eligibility": {
|
|
321
|
+
"stage": "default"
|
|
322
|
+
},
|
|
323
|
+
"writer": {
|
|
324
|
+
"stage": "default"
|
|
325
|
+
},
|
|
326
|
+
"index": {
|
|
327
|
+
"stage": "default"
|
|
328
|
+
},
|
|
329
|
+
"decision": {
|
|
330
|
+
"stage": "default"
|
|
331
|
+
},
|
|
332
|
+
"killSwitch": false
|
|
320
333
|
},
|
|
321
334
|
"memory": {
|
|
322
335
|
"enabled": true,
|
|
@@ -346,31 +359,69 @@
|
|
|
346
359
|
},
|
|
347
360
|
"tuning": {
|
|
348
361
|
"enabled": true,
|
|
349
|
-
"applyMode": "
|
|
362
|
+
"applyMode": "auto"
|
|
363
|
+
},
|
|
364
|
+
"selfImprove": {
|
|
365
|
+
"enabled": true
|
|
350
366
|
},
|
|
351
367
|
"candidates": {
|
|
352
|
-
"stage": "
|
|
368
|
+
"stage": "default",
|
|
353
369
|
"minOccurrences": 3
|
|
354
370
|
},
|
|
355
371
|
"overlays": {
|
|
356
|
-
"stage": "
|
|
372
|
+
"stage": "default"
|
|
357
373
|
}
|
|
358
374
|
},
|
|
359
375
|
"continuity": {
|
|
360
376
|
"resumableRun": {
|
|
361
|
-
"stage": "
|
|
377
|
+
"stage": "default"
|
|
362
378
|
}
|
|
363
379
|
},
|
|
364
380
|
"experiments": {
|
|
365
381
|
"deliberation": {
|
|
366
|
-
"enabled":
|
|
382
|
+
"enabled": true
|
|
367
383
|
},
|
|
368
384
|
"dynamicWorkflow": {
|
|
369
|
-
"enabled":
|
|
385
|
+
"enabled": true,
|
|
370
386
|
"maxAttemptsPerFailure": 2,
|
|
371
387
|
"noProgressCap": 3
|
|
372
388
|
}
|
|
373
389
|
},
|
|
390
|
+
"decisionRuntime": {
|
|
391
|
+
"contract": {
|
|
392
|
+
"stage": "shadow"
|
|
393
|
+
},
|
|
394
|
+
"supervisor": {
|
|
395
|
+
"stage": "shadow"
|
|
396
|
+
},
|
|
397
|
+
"scheduler": {
|
|
398
|
+
"stage": "shadow"
|
|
399
|
+
},
|
|
400
|
+
"vm": {
|
|
401
|
+
"stage": "shadow"
|
|
402
|
+
},
|
|
403
|
+
"adapters": {
|
|
404
|
+
"stage": "shadow"
|
|
405
|
+
},
|
|
406
|
+
"context": {
|
|
407
|
+
"stage": "shadow"
|
|
408
|
+
},
|
|
409
|
+
"completion": {
|
|
410
|
+
"stage": "shadow"
|
|
411
|
+
},
|
|
412
|
+
"quality": {
|
|
413
|
+
"stage": "shadow"
|
|
414
|
+
},
|
|
415
|
+
"promotion": {
|
|
416
|
+
"stage": "shadow"
|
|
417
|
+
},
|
|
418
|
+
"resourcePolicy": {
|
|
419
|
+
"stage": "shadow"
|
|
420
|
+
},
|
|
421
|
+
"diagnostics": {
|
|
422
|
+
"stage": "default"
|
|
423
|
+
}
|
|
424
|
+
},
|
|
374
425
|
"safePatch": {
|
|
375
426
|
"enabled": true,
|
|
376
427
|
"strictSharedRisk": true,
|
|
@@ -600,15 +651,15 @@
|
|
|
600
651
|
},
|
|
601
652
|
"tu_ghi_episode_ket_thuc_session": {
|
|
602
653
|
"field": "learning.episodes.autoWrite",
|
|
603
|
-
"mac_dinh":
|
|
604
|
-
"y_nghia": "
|
|
605
|
-
"khi_nao_bat": "Ch\u1ec9
|
|
654
|
+
"mac_dinh": true,
|
|
655
|
+
"y_nghia": "B\u1eadt m\u1eb7c \u0111\u1ecbnh: UKit t\u1ef1 ghi episode v\u00e0o memory v2 cho m\u1ed7i session \u0111\u00e3 k\u1ebft th\u00fac (hook SessionEnd/session_stop + chu k\u1ef3 self-improve qu\u00e9t exec-ledger, ch\u1ea1y \u0111\u01b0\u1ee3c c\u1ea3 tr\u00ean Codex). D\u1eef li\u1ec7u n\u1eb1m local trong .ukit/storage.",
|
|
656
|
+
"khi_nao_bat": "Ch\u1ec9 t\u1eaft (false) khi kh\u00f4ng mu\u1ed1n UKit l\u01b0u episode."
|
|
606
657
|
},
|
|
607
658
|
"tat_goi_y_tuning": {
|
|
608
659
|
"field": "learning.tuning.applyMode",
|
|
609
|
-
"mac_dinh": "
|
|
610
|
-
"y_nghia": "
|
|
611
|
-
"khuyen_nghi": "Gi\u1eef
|
|
660
|
+
"mac_dinh": "auto",
|
|
661
|
+
"y_nghia": "auto (m\u1eb7c \u0111\u1ecbnh) = chu k\u1ef3 self-improve t\u1ef1 \u00e1p d\u1ee5ng thay \u0111\u1ed5i tuning t\u1eebng b\u01b0\u1edbc nh\u1ecf, c\u00f3 gi\u1edbi h\u1ea1n (retriever weights, escalation.debugLoopThreshold) v\u00e0o .ukit/storage/learning/tuned.json. manual = ch\u1ec9 ghi g\u1ee3i \u00fd v\u00e0o suggestions.json. off = kh\u00f4ng t\u00ednh.",
|
|
662
|
+
"khuyen_nghi": "Gi\u1eef auto. Rollback: xo\u00e1 .ukit/storage/learning/tuned.json ho\u1eb7c \u0111\u1eb7t manual."
|
|
612
663
|
}
|
|
613
664
|
},
|
|
614
665
|
"version": "Phi\u00ean b\u1ea3n config runtime \u0111i k\u00e8m package UKit.",
|