@ngockhoale/ukit 1.4.2 → 1.4.3
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 +6 -0
- package/package.json +1 -1
- package/src/core/runtimeConfig.js +1 -1
- package/src/index/taskRouting.js +173 -9
- package/templates/.claude/hooks/skill-router.sh +290 -9
- package/templates/.claude/ukit/index/route-task.mjs +277 -9
- package/templates/.claude/ukit/runtime/reinject-context.mjs +16 -5
- package/templates/.codex/README.md +1 -1
- package/templates/ukit/README.md +1 -1
- package/templates/ukit/storage/config.json +1 -1
|
@@ -49,6 +49,7 @@ async function main() {
|
|
|
49
49
|
const rootDir = getRootDir(args);
|
|
50
50
|
const sharedStatePath = path.join(rootDir, '.claude', 'ukit', 'skill-router-state.json');
|
|
51
51
|
const routeCachePath = path.join(rootDir, '.claude', 'ukit', 'route-cache.json');
|
|
52
|
+
const routeAuditPath = path.join(rootDir, '.ukit', 'storage', 'cache', 'route-audit.json');
|
|
52
53
|
const previousState = await readJson(sharedStatePath, {});
|
|
53
54
|
const targetFile = readFlagValue(args, '--target');
|
|
54
55
|
const taskType = readFlagValue(args, '--type');
|
|
@@ -147,6 +148,9 @@ async function main() {
|
|
|
147
148
|
),
|
|
148
149
|
}
|
|
149
150
|
: null;
|
|
151
|
+
if (rescuedRouteSummary) {
|
|
152
|
+
applyRescueBiasToRouteSummary(rescuedRouteSummary);
|
|
153
|
+
}
|
|
150
154
|
const sharedState = {
|
|
151
155
|
...cachedRouteState,
|
|
152
156
|
source: 'task-route',
|
|
@@ -156,6 +160,9 @@ async function main() {
|
|
|
156
160
|
};
|
|
157
161
|
sharedState.fingerprint = buildRouteStateFingerprint(sharedState);
|
|
158
162
|
await writeJson(sharedStatePath, sharedState);
|
|
163
|
+
await appendRouteAuditEntry(routeAuditPath, buildRouteAuditEntry({
|
|
164
|
+
state: sharedState,
|
|
165
|
+
}));
|
|
159
166
|
printRouteState(sharedState);
|
|
160
167
|
return;
|
|
161
168
|
}
|
|
@@ -194,6 +201,10 @@ async function main() {
|
|
|
194
201
|
indexGeneratedAtMs,
|
|
195
202
|
});
|
|
196
203
|
await writeJson(sharedStatePath, sharedState);
|
|
204
|
+
await appendRouteAuditEntry(routeAuditPath, buildRouteAuditEntry({
|
|
205
|
+
route,
|
|
206
|
+
state: sharedState,
|
|
207
|
+
}));
|
|
197
208
|
await writeRecentCacheEntry(routeCachePath, compactRouteCacheState(sharedState), {
|
|
198
209
|
maxEntries: DEFAULT_RECENT_CACHE_MAX_ENTRIES,
|
|
199
210
|
});
|
|
@@ -274,13 +285,20 @@ async function prepareTaskRoute({
|
|
|
274
285
|
intentMode,
|
|
275
286
|
taskType: inferredTaskType,
|
|
276
287
|
});
|
|
288
|
+
const executionCandidates = buildExecutionModeCandidates({
|
|
289
|
+
promptText: normalizedPrompt,
|
|
290
|
+
commandText: normalizedCommand,
|
|
291
|
+
targetFile: normalizedTarget,
|
|
292
|
+
intentMode,
|
|
293
|
+
executionScores,
|
|
294
|
+
});
|
|
277
295
|
const executionMode = deriveExecutionMode({
|
|
278
296
|
promptText: normalizedPrompt,
|
|
279
297
|
commandText: normalizedCommand,
|
|
280
298
|
targetFile: normalizedTarget,
|
|
281
299
|
intentMode,
|
|
282
|
-
taskType: inferredTaskType,
|
|
283
300
|
executionScores,
|
|
301
|
+
executionCandidates,
|
|
284
302
|
});
|
|
285
303
|
const preservedPrompt = normalizedPrompt || String(lastExplicitUserPromptText || '').trim();
|
|
286
304
|
|
|
@@ -297,6 +315,7 @@ async function prepareTaskRoute({
|
|
|
297
315
|
taskType: inferredTaskType,
|
|
298
316
|
intentMode,
|
|
299
317
|
executionScores,
|
|
318
|
+
executionCandidates,
|
|
300
319
|
executionMode,
|
|
301
320
|
},
|
|
302
321
|
};
|
|
@@ -381,6 +400,7 @@ async function finalizeTaskRoute({
|
|
|
381
400
|
routeSummary.continuationState,
|
|
382
401
|
previousRouteSummary?.continuationState ?? null,
|
|
383
402
|
);
|
|
403
|
+
applyRescueBiasToRouteSummary(routeSummary);
|
|
384
404
|
const approachSelector = routeSummary?.approachSelector ?? null;
|
|
385
405
|
|
|
386
406
|
return {
|
|
@@ -828,7 +848,7 @@ function deriveIntentMode({ promptText = '', commandText = '', targetFile = null
|
|
|
828
848
|
}
|
|
829
849
|
|
|
830
850
|
if (concreteTask) {
|
|
831
|
-
if (/\b(bug|debug|error|crash|broken|failing|stack trace|triage|fix|
|
|
851
|
+
if (/\b(bug|debug|error|crash|broken|failing|stack trace|triage|fix|timeout)\b/.test(lower)) {
|
|
832
852
|
return 'debug-specific';
|
|
833
853
|
}
|
|
834
854
|
if (/\b(review|audit|diff|pr feedback|code review|kiem tra|soat)\b/.test(raw)) {
|
|
@@ -1287,9 +1307,11 @@ function buildRouteSummary({
|
|
|
1287
1307
|
&& contextRecommendation.command.trim();
|
|
1288
1308
|
const executionMode = routingContext.executionMode ?? null;
|
|
1289
1309
|
const executionScores = routingContext.executionScores ?? null;
|
|
1310
|
+
const executionCandidates = routingContext.executionCandidates ?? null;
|
|
1290
1311
|
const approachSelector = buildApproachSelectorResult({
|
|
1291
1312
|
executionMode,
|
|
1292
1313
|
executionScores,
|
|
1314
|
+
executionCandidates,
|
|
1293
1315
|
});
|
|
1294
1316
|
const executionContract = buildExecutionContract(executionMode);
|
|
1295
1317
|
const completionState = buildCompletionState({
|
|
@@ -1328,6 +1350,7 @@ function buildRouteSummary({
|
|
|
1328
1350
|
editGuardHint,
|
|
1329
1351
|
executionMode,
|
|
1330
1352
|
executionScores,
|
|
1353
|
+
executionCandidates,
|
|
1331
1354
|
approachSelector,
|
|
1332
1355
|
executionContract,
|
|
1333
1356
|
completionState,
|
|
@@ -1362,6 +1385,12 @@ function deriveExecutionScores({
|
|
|
1362
1385
|
const buildSignal = /\b(build|create|add|implement|feature)\b/.test(raw);
|
|
1363
1386
|
const debugSignal = intentMode === 'debug-specific' || /\b(root cause|debug|triage|flaky|investigate|why)\b/.test(raw);
|
|
1364
1387
|
const reviewSignal = intentMode === 'review-specific' || /\b(review|audit|verify|release readiness)\b/.test(raw);
|
|
1388
|
+
const failureSignal = /\b(failing|failed|broken|error|crash|timeout|undefined|exception|eacces|trace)\b/.test(raw);
|
|
1389
|
+
const impactSignal = /\b(map impact|impact|blast radius|all affected|across (?:runtime|templates|helpers|adapters|mirrors)|affected adapters|affected mirrors|inspect impact)\b/.test(raw);
|
|
1390
|
+
const boundedEditSignal = /\b(one[- ]line|small|tiny|single|local|guard|log line|loading message|label)\b/.test(raw);
|
|
1391
|
+
const implementSignal = /\b(implement|apply|update|modify|add|create|ship|deliver|fix)\b/.test(raw)
|
|
1392
|
+
|| /\bchange\s+.+\s+to\s+.+\b/.test(raw);
|
|
1393
|
+
const explicitTarget = Boolean(targetFile);
|
|
1365
1394
|
|
|
1366
1395
|
let editCertainty = 0;
|
|
1367
1396
|
if (directTransformSignal) {
|
|
@@ -1375,7 +1404,7 @@ function deriveExecutionScores({
|
|
|
1375
1404
|
let investigationNeed = 0;
|
|
1376
1405
|
if (debugSignal) {
|
|
1377
1406
|
investigationNeed = 3;
|
|
1378
|
-
} else if (
|
|
1407
|
+
} else if (failureSignal) {
|
|
1379
1408
|
investigationNeed = 2;
|
|
1380
1409
|
}
|
|
1381
1410
|
|
|
@@ -1408,6 +1437,17 @@ function deriveExecutionScores({
|
|
|
1408
1437
|
blastRadius,
|
|
1409
1438
|
verificationBurden,
|
|
1410
1439
|
ambiguity,
|
|
1440
|
+
sharedRisk,
|
|
1441
|
+
directTransformSignal,
|
|
1442
|
+
smallFixSignal,
|
|
1443
|
+
buildSignal,
|
|
1444
|
+
debugSignal,
|
|
1445
|
+
reviewSignal,
|
|
1446
|
+
failureSignal,
|
|
1447
|
+
impactSignal,
|
|
1448
|
+
boundedEditSignal,
|
|
1449
|
+
implementSignal,
|
|
1450
|
+
explicitTarget,
|
|
1411
1451
|
};
|
|
1412
1452
|
}
|
|
1413
1453
|
|
|
@@ -1417,40 +1457,64 @@ function deriveExecutionMode({
|
|
|
1417
1457
|
targetFile = null,
|
|
1418
1458
|
intentMode = null,
|
|
1419
1459
|
executionScores = {},
|
|
1460
|
+
executionCandidates = null,
|
|
1420
1461
|
} = {}) {
|
|
1421
1462
|
const raw = `${promptText ?? ''}\n${commandText ?? ''}`.toLowerCase();
|
|
1422
1463
|
const scores = executionScores;
|
|
1464
|
+
const candidates = executionCandidates ?? buildExecutionModeCandidates({
|
|
1465
|
+
promptText,
|
|
1466
|
+
commandText,
|
|
1467
|
+
targetFile,
|
|
1468
|
+
intentMode,
|
|
1469
|
+
executionScores,
|
|
1470
|
+
});
|
|
1423
1471
|
const explicitReviewLead = /\b(review this|audit this|review\b.*\brelease readiness|verify\b.*\brelease readiness)\b/.test(raw);
|
|
1472
|
+
const strongImpactLead = scores.sharedRisk
|
|
1473
|
+
&& (scores.impactSignal || /\b(check all affected|map all affected|across all affected)\b/.test(raw));
|
|
1474
|
+
const boundedLocalBuildCandidate = scores.buildSignal && scores.boundedEditSignal && scores.explicitTarget && !scores.sharedRisk;
|
|
1424
1475
|
|
|
1425
|
-
if (intentMode === 'review-specific' || explicitReviewLead) {
|
|
1476
|
+
if ((intentMode === 'review-specific' || explicitReviewLead) && !scores.implementSignal) {
|
|
1426
1477
|
return 'review-release';
|
|
1427
1478
|
}
|
|
1428
1479
|
|
|
1429
|
-
if (scores.blastRadius >= 3 && (scores.ambiguity >= 2 || scores.investigationNeed >= 2)) {
|
|
1480
|
+
if (strongImpactLead || (scores.blastRadius >= 3 && (scores.ambiguity >= 2 || scores.investigationNeed >= 2))) {
|
|
1430
1481
|
return 'map-impact';
|
|
1431
1482
|
}
|
|
1432
1483
|
|
|
1433
|
-
if (scores.
|
|
1484
|
+
if (scores.sharedRisk && scores.failureSignal && scores.investigationNeed >= 2 && !scores.impactSignal) {
|
|
1434
1485
|
return 'shared-edit';
|
|
1435
1486
|
}
|
|
1436
1487
|
|
|
1437
|
-
if (scores.
|
|
1488
|
+
if (scores.blastRadius >= 3 || scores.sharedRisk) {
|
|
1489
|
+
return 'shared-edit';
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
if (scores.investigationNeed >= 3 || (scores.failureSignal && scores.investigationNeed >= 2)) {
|
|
1438
1493
|
return 'find-cause';
|
|
1439
1494
|
}
|
|
1440
1495
|
|
|
1496
|
+
if (scores.directTransformSignal && !scores.explicitTarget && scores.investigationNeed === 0 && !scores.sharedRisk) {
|
|
1497
|
+
return 'local-build';
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1441
1500
|
if (
|
|
1442
1501
|
scores.editCertainty >= 3
|
|
1443
|
-
&& scores.ambiguity
|
|
1502
|
+
&& scores.ambiguity <= 1
|
|
1444
1503
|
&& scores.blastRadius === 0
|
|
1445
1504
|
&& scores.verificationBurden <= 1
|
|
1446
1505
|
) {
|
|
1447
1506
|
return 'tiny-fix';
|
|
1448
1507
|
}
|
|
1449
1508
|
|
|
1509
|
+
if (boundedLocalBuildCandidate && scores.investigationNeed === 0) {
|
|
1510
|
+
return 'local-fix';
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1450
1513
|
if (
|
|
1451
1514
|
/\b(build|create|add|implement|feature|summary card)\b/.test(raw)
|
|
1452
1515
|
&& scores.investigationNeed === 0
|
|
1453
1516
|
&& scores.blastRadius < 3
|
|
1517
|
+
&& !scores.boundedEditSignal
|
|
1454
1518
|
) {
|
|
1455
1519
|
return 'local-build';
|
|
1456
1520
|
}
|
|
@@ -1459,7 +1523,107 @@ function deriveExecutionMode({
|
|
|
1459
1523
|
return 'local-fix';
|
|
1460
1524
|
}
|
|
1461
1525
|
|
|
1462
|
-
return 'local-build';
|
|
1526
|
+
return applySafeUpwardBias(candidates, 'local-build');
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
function buildExecutionModeCandidates({
|
|
1530
|
+
promptText = '',
|
|
1531
|
+
commandText = '',
|
|
1532
|
+
targetFile = null,
|
|
1533
|
+
intentMode = null,
|
|
1534
|
+
executionScores = {},
|
|
1535
|
+
} = {}) {
|
|
1536
|
+
const scores = executionScores;
|
|
1537
|
+
const raw = `${promptText ?? ''}\n${commandText ?? ''}`.toLowerCase();
|
|
1538
|
+
const explicitReviewLead = (intentMode === 'review-specific' || /\b(review this|audit this|review\b.*\brelease readiness|verify\b.*\brelease readiness)\b/.test(raw))
|
|
1539
|
+
&& !scores.implementSignal;
|
|
1540
|
+
|
|
1541
|
+
const modeScores = {
|
|
1542
|
+
'tiny-fix': (
|
|
1543
|
+
(scores.editCertainty * 4)
|
|
1544
|
+
+ (scores.directTransformSignal ? 4 : 0)
|
|
1545
|
+
+ (scores.explicitTarget ? 1 : 0)
|
|
1546
|
+
- (scores.failureSignal ? 4 : 0)
|
|
1547
|
+
- (scores.blastRadius * 4)
|
|
1548
|
+
- (scores.ambiguity * 2)
|
|
1549
|
+
),
|
|
1550
|
+
'local-fix': (
|
|
1551
|
+
(scores.editCertainty * 3)
|
|
1552
|
+
+ (scores.boundedEditSignal ? 3 : 0)
|
|
1553
|
+
+ (scores.explicitTarget ? 1 : 0)
|
|
1554
|
+
- (scores.failureSignal ? 2 : 0)
|
|
1555
|
+
- (scores.blastRadius * 4)
|
|
1556
|
+
),
|
|
1557
|
+
'local-build': (
|
|
1558
|
+
(scores.buildSignal ? 6 : 0)
|
|
1559
|
+
+ (scores.editCertainty * 1)
|
|
1560
|
+
+ (scores.explicitTarget ? 1 : 0)
|
|
1561
|
+
- (scores.boundedEditSignal ? 3 : 0)
|
|
1562
|
+
- (scores.failureSignal ? 3 : 0)
|
|
1563
|
+
- (scores.blastRadius * 4)
|
|
1564
|
+
),
|
|
1565
|
+
'find-cause': (
|
|
1566
|
+
(scores.investigationNeed * 4)
|
|
1567
|
+
+ (scores.failureSignal ? 3 : 0)
|
|
1568
|
+
+ (scores.debugSignal ? 2 : 0)
|
|
1569
|
+
- (scores.blastRadius >= 3 ? 1 : 0)
|
|
1570
|
+
),
|
|
1571
|
+
'shared-edit': (
|
|
1572
|
+
(scores.sharedRisk ? 8 : 0)
|
|
1573
|
+
+ (scores.editCertainty * 1)
|
|
1574
|
+
+ (scores.buildSignal ? 1 : 0)
|
|
1575
|
+
- (scores.impactSignal ? 2 : 0)
|
|
1576
|
+
),
|
|
1577
|
+
'map-impact': (
|
|
1578
|
+
(scores.sharedRisk ? 7 : 0)
|
|
1579
|
+
+ (scores.impactSignal ? 5 : 0)
|
|
1580
|
+
+ (scores.ambiguity * 2)
|
|
1581
|
+
+ scores.investigationNeed
|
|
1582
|
+
),
|
|
1583
|
+
'review-release': (
|
|
1584
|
+
(explicitReviewLead ? 10 : 0)
|
|
1585
|
+
+ (scores.reviewSignal ? 3 : 0)
|
|
1586
|
+
- (scores.implementSignal ? 5 : 0)
|
|
1587
|
+
),
|
|
1588
|
+
};
|
|
1589
|
+
|
|
1590
|
+
return Object.entries(modeScores)
|
|
1591
|
+
.map(([mode, score]) => ({ mode, score }))
|
|
1592
|
+
.sort((a, b) => b.score - a.score || executionModeRank(a.mode) - executionModeRank(b.mode));
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
function applySafeUpwardBias(candidates = [], fallbackMode = 'local-build') {
|
|
1596
|
+
const [topCandidate, competingCandidate] = candidates;
|
|
1597
|
+
if (!topCandidate) {
|
|
1598
|
+
return fallbackMode;
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
if (!competingCandidate) {
|
|
1602
|
+
return topCandidate.mode;
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
const scoreGap = Number(topCandidate.score ?? 0) - Number(competingCandidate.score ?? 0);
|
|
1606
|
+
const rankGap = executionModeRank(competingCandidate.mode) - executionModeRank(topCandidate.mode);
|
|
1607
|
+
if (scoreGap <= 1 && rankGap === 1) {
|
|
1608
|
+
return competingCandidate.mode;
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
return topCandidate.mode;
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
function executionModeRank(mode = '') {
|
|
1615
|
+
const orderedModes = [
|
|
1616
|
+
'tiny-fix',
|
|
1617
|
+
'local-fix',
|
|
1618
|
+
'local-build',
|
|
1619
|
+
'find-cause',
|
|
1620
|
+
'shared-edit',
|
|
1621
|
+
'map-impact',
|
|
1622
|
+
'review-release',
|
|
1623
|
+
];
|
|
1624
|
+
|
|
1625
|
+
const index = orderedModes.indexOf(mode);
|
|
1626
|
+
return index >= 0 ? index : orderedModes.length;
|
|
1463
1627
|
}
|
|
1464
1628
|
|
|
1465
1629
|
function buildExecutionContract(executionMode = null) {
|
|
@@ -1531,6 +1695,7 @@ function buildExecutionContract(executionMode = null) {
|
|
|
1531
1695
|
function buildApproachSelectorResult({
|
|
1532
1696
|
executionMode = null,
|
|
1533
1697
|
executionScores = null,
|
|
1698
|
+
executionCandidates = null,
|
|
1534
1699
|
} = {}) {
|
|
1535
1700
|
if (!executionMode) {
|
|
1536
1701
|
return null;
|
|
@@ -1579,6 +1744,14 @@ function buildApproachSelectorResult({
|
|
|
1579
1744
|
contextPolicy: selectedPolicy.contextPolicy,
|
|
1580
1745
|
verificationPolicy: executionContract?.verificationPolicy ?? null,
|
|
1581
1746
|
completionRule: executionContract?.completionRule ?? null,
|
|
1747
|
+
competingMode: executionCandidates?.[1]?.mode ?? null,
|
|
1748
|
+
competingScoreGap: executionCandidates?.length >= 2
|
|
1749
|
+
? Number(executionCandidates[0]?.score ?? 0) - Number(executionCandidates[1]?.score ?? 0)
|
|
1750
|
+
: null,
|
|
1751
|
+
candidateModes: (executionCandidates ?? []).slice(0, 3).map((entry) => ({
|
|
1752
|
+
mode: entry.mode,
|
|
1753
|
+
score: entry.score,
|
|
1754
|
+
})),
|
|
1582
1755
|
};
|
|
1583
1756
|
}
|
|
1584
1757
|
|
|
@@ -1666,6 +1839,8 @@ function buildContinuationState({
|
|
|
1666
1839
|
repeatCount: reasons.length > 0 ? 1 : 0,
|
|
1667
1840
|
stuckRisk: null,
|
|
1668
1841
|
rescueMode: null,
|
|
1842
|
+
wideningBlocked: false,
|
|
1843
|
+
milestonePriority: reasons.length > 0 ? 'normal' : null,
|
|
1669
1844
|
};
|
|
1670
1845
|
}
|
|
1671
1846
|
|
|
@@ -1680,6 +1855,8 @@ function advanceContinuationState(continuationState = null, previousContinuation
|
|
|
1680
1855
|
repeatCount: 0,
|
|
1681
1856
|
stuckRisk: null,
|
|
1682
1857
|
rescueMode: null,
|
|
1858
|
+
wideningBlocked: false,
|
|
1859
|
+
milestonePriority: null,
|
|
1683
1860
|
};
|
|
1684
1861
|
}
|
|
1685
1862
|
|
|
@@ -1708,15 +1885,45 @@ function advanceContinuationState(continuationState = null, previousContinuation
|
|
|
1708
1885
|
const stuckRisk = repeatCount >= 3
|
|
1709
1886
|
? 'high'
|
|
1710
1887
|
: (repeatCount === 2 ? 'elevated' : null);
|
|
1888
|
+
const wideningBlocked = repeatCount >= 2 && Boolean(rescueMode);
|
|
1889
|
+
const nextMilestone = repeatCount >= 2 && currentReasons.includes('missing-write-evidence')
|
|
1890
|
+
? 'finish-write-before-more-analysis'
|
|
1891
|
+
: (
|
|
1892
|
+
repeatCount >= 2 && currentReasons.includes('pending-bounded-context')
|
|
1893
|
+
? 'finish-current-milestone-before-more-reading'
|
|
1894
|
+
: continuationState.nextMilestone
|
|
1895
|
+
);
|
|
1711
1896
|
|
|
1712
1897
|
return {
|
|
1713
1898
|
...continuationState,
|
|
1899
|
+
nextMilestone,
|
|
1714
1900
|
repeatCount,
|
|
1715
1901
|
stuckRisk,
|
|
1716
1902
|
rescueMode,
|
|
1903
|
+
wideningBlocked,
|
|
1904
|
+
milestonePriority: wideningBlocked ? 'execute-current-milestone' : 'normal',
|
|
1717
1905
|
};
|
|
1718
1906
|
}
|
|
1719
1907
|
|
|
1908
|
+
function applyRescueBiasToRouteSummary(routeSummary = null) {
|
|
1909
|
+
if (!routeSummary || typeof routeSummary !== 'object') {
|
|
1910
|
+
return routeSummary;
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1913
|
+
const continuationState = routeSummary.continuationState;
|
|
1914
|
+
if (
|
|
1915
|
+
continuationState?.repeatCount >= 2
|
|
1916
|
+
&& continuationState?.wideningBlocked
|
|
1917
|
+
&& (continuationState.reasons ?? []).includes('missing-write-evidence')
|
|
1918
|
+
) {
|
|
1919
|
+
routeSummary.nextActionType = 'execute-current-milestone';
|
|
1920
|
+
routeSummary.nextActionCommand = null;
|
|
1921
|
+
routeSummary.helperHint = null;
|
|
1922
|
+
}
|
|
1923
|
+
|
|
1924
|
+
return routeSummary;
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1720
1927
|
function deriveExecutionPolicy({
|
|
1721
1928
|
taskType = 'simple',
|
|
1722
1929
|
mode = 'minimal',
|
|
@@ -2368,6 +2575,67 @@ function shouldIncludeRecentOutput({
|
|
|
2368
2575
|
return true;
|
|
2369
2576
|
}
|
|
2370
2577
|
|
|
2578
|
+
function buildRouteAuditEntry({ route = null, state = null } = {}) {
|
|
2579
|
+
const routingContext = route?.routingContext ?? state?.routingContext ?? {};
|
|
2580
|
+
const routeSummary = route?.routeSummary ?? state?.routeSummary ?? {};
|
|
2581
|
+
const candidateModes = Array.isArray(routeSummary?.approachSelector?.candidateModes)
|
|
2582
|
+
? routeSummary.approachSelector.candidateModes
|
|
2583
|
+
: [];
|
|
2584
|
+
|
|
2585
|
+
return {
|
|
2586
|
+
ts: Date.now(),
|
|
2587
|
+
source: state?.source ?? 'task-route',
|
|
2588
|
+
requestKey: state?.requestKey ?? null,
|
|
2589
|
+
adapter: routingContext.adapter ?? 'claude',
|
|
2590
|
+
promptFingerprint: stableMachineDigest({
|
|
2591
|
+
prompt: routingContext.lastExplicitUserPromptText ?? '',
|
|
2592
|
+
adapter: routingContext.adapter ?? 'claude',
|
|
2593
|
+
}),
|
|
2594
|
+
targetFile: route?.routingContext?.targetFile ?? null,
|
|
2595
|
+
taskType: routingContext.taskType ?? null,
|
|
2596
|
+
executionMode: routeSummary.executionMode ?? null,
|
|
2597
|
+
competingMode: routeSummary?.approachSelector?.competingMode ?? null,
|
|
2598
|
+
competingScoreGap: routeSummary?.approachSelector?.competingScoreGap ?? null,
|
|
2599
|
+
candidateModes: candidateModes.slice(0, 3),
|
|
2600
|
+
nextActionType: routeSummary.nextActionType ?? null,
|
|
2601
|
+
nextMilestone: routeSummary?.continuationState?.nextMilestone ?? null,
|
|
2602
|
+
repeatCount: routeSummary?.continuationState?.repeatCount ?? null,
|
|
2603
|
+
rescueMode: routeSummary?.continuationState?.rescueMode ?? null,
|
|
2604
|
+
wideningBlocked: routeSummary?.continuationState?.wideningBlocked ?? null,
|
|
2605
|
+
};
|
|
2606
|
+
}
|
|
2607
|
+
|
|
2608
|
+
async function appendRouteAuditEntry(filePath, entry) {
|
|
2609
|
+
if (!entry || typeof entry !== 'object') {
|
|
2610
|
+
return;
|
|
2611
|
+
}
|
|
2612
|
+
|
|
2613
|
+
const existing = await readJson(filePath, { entries: [] });
|
|
2614
|
+
const entries = Array.isArray(existing?.entries) ? existing.entries : [];
|
|
2615
|
+
const dedupeKey = stableMachineDigest({
|
|
2616
|
+
requestKey: entry.requestKey,
|
|
2617
|
+
executionMode: entry.executionMode,
|
|
2618
|
+
nextActionType: entry.nextActionType,
|
|
2619
|
+
nextMilestone: entry.nextMilestone,
|
|
2620
|
+
repeatCount: entry.repeatCount,
|
|
2621
|
+
rescueMode: entry.rescueMode,
|
|
2622
|
+
});
|
|
2623
|
+
const filtered = entries.filter((item) => {
|
|
2624
|
+
const itemKey = stableMachineDigest({
|
|
2625
|
+
requestKey: item?.requestKey ?? null,
|
|
2626
|
+
executionMode: item?.executionMode ?? null,
|
|
2627
|
+
nextActionType: item?.nextActionType ?? null,
|
|
2628
|
+
nextMilestone: item?.nextMilestone ?? null,
|
|
2629
|
+
repeatCount: item?.repeatCount ?? null,
|
|
2630
|
+
rescueMode: item?.rescueMode ?? null,
|
|
2631
|
+
});
|
|
2632
|
+
return itemKey !== dedupeKey;
|
|
2633
|
+
});
|
|
2634
|
+
await writeJson(filePath, {
|
|
2635
|
+
entries: [entry, ...filtered].slice(0, 40),
|
|
2636
|
+
});
|
|
2637
|
+
}
|
|
2638
|
+
|
|
2371
2639
|
async function readJson(filePath, fallback = null) {
|
|
2372
2640
|
try {
|
|
2373
2641
|
return JSON.parse(await fs.readFile(filePath, 'utf8'));
|
|
@@ -66,9 +66,12 @@ async function main() {
|
|
|
66
66
|
line.startsWith('- Recent routed lane:')
|
|
67
67
|
|| line.startsWith('- Current approach:')
|
|
68
68
|
|| line.startsWith('- Completion debt:')
|
|
69
|
+
|| line.startsWith('- Execution rule:')
|
|
69
70
|
|| line.startsWith('- Continuation required:')
|
|
70
71
|
|| line.startsWith('- Stuck-lane rescue:')
|
|
72
|
+
|| line.startsWith('- Rescue rule:')
|
|
71
73
|
|| line.startsWith('- Continue rule:')
|
|
74
|
+
|| line.startsWith('- Decision rule:')
|
|
72
75
|
|| line.startsWith('- Previous context:')
|
|
73
76
|
|| line.startsWith('- Recent command output:')
|
|
74
77
|
|| line.startsWith('- Recent delegation hint:')
|
|
@@ -113,9 +116,9 @@ async function main() {
|
|
|
113
116
|
compressEnabled
|
|
114
117
|
? compactContextBlock(bodyLines, {
|
|
115
118
|
maxTokens,
|
|
116
|
-
maxLines:
|
|
117
|
-
anchorLines: anchorLines.slice(0,
|
|
118
|
-
maxAnchors:
|
|
119
|
+
maxLines: 14,
|
|
120
|
+
anchorLines: anchorLines.slice(0, 6),
|
|
121
|
+
maxAnchors: 6,
|
|
119
122
|
})
|
|
120
123
|
: {
|
|
121
124
|
text: bodyLines.join('\n'),
|
|
@@ -284,7 +287,7 @@ function buildStaticGuidanceLines(state = {}, { compact = true } = {}) {
|
|
|
284
287
|
'- Simple: read docs/MEMORY.md; use context resolver for related files.',
|
|
285
288
|
'- Non-trivial: read docs/MEMORY.md + docs/PROJECT.md + docs/CODE_MAP.md.',
|
|
286
289
|
'- WORKLOG: read only for continuation/debugging.',
|
|
287
|
-
'- If
|
|
290
|
+
'- If one safe path is clear, execute it; ask only when choices or risk need a user decision.',
|
|
288
291
|
'- Reuse existing code. Use yarn. Run tests after code changes.',
|
|
289
292
|
'- Scope-based verification: match verify effort to change scope.',
|
|
290
293
|
'- Auto-activate matching project-local skills from prompt + tool/file signals.',
|
|
@@ -306,7 +309,7 @@ function buildStaticGuidanceLines(state = {}, { compact = true } = {}) {
|
|
|
306
309
|
return [
|
|
307
310
|
currentLaneLine,
|
|
308
311
|
'- WORKLOG: read only for continuation/debugging.',
|
|
309
|
-
'- If
|
|
312
|
+
'- If one safe path is clear, execute it; ask only when choices or risk need a user decision.',
|
|
310
313
|
'- Reuse existing code; use yarn; verify after changes with scope-matched effort.',
|
|
311
314
|
'- Auto-activate matching project-local skills from prompt + tool/file signals.',
|
|
312
315
|
];
|
|
@@ -560,6 +563,9 @@ function buildApproachSelectorLines(state = {}) {
|
|
|
560
563
|
|| null;
|
|
561
564
|
lines.push('- Completion debt: ' + missingEvidence.join(', ') + (completionRule ? ` | gate=${completionRule}` : ''));
|
|
562
565
|
lines.push('- Continue rule: while completion debt remains, do not end with done/applied/fixed language unless a real blocker is found.');
|
|
566
|
+
if (missingEvidence.includes('write-evidence')) {
|
|
567
|
+
lines.push('- Execution rule: execute the next safe milestone first; explain only if blocked or the risk changes.');
|
|
568
|
+
}
|
|
563
569
|
}
|
|
564
570
|
}
|
|
565
571
|
|
|
@@ -573,6 +579,9 @@ function buildApproachSelectorLines(state = {}) {
|
|
|
573
579
|
+ (continuationState.stuckRisk ? ` | risk=${continuationState.stuckRisk}` : '')
|
|
574
580
|
+ (continuationState.rescueMode ? ` | mode=${continuationState.rescueMode}` : ''));
|
|
575
581
|
}
|
|
582
|
+
if (continuationState.wideningBlocked) {
|
|
583
|
+
lines.push('- Rescue rule: do not widen reads yet; execute the current milestone before more analysis.');
|
|
584
|
+
}
|
|
576
585
|
if ((continuationState.reasons ?? []).includes('pending-bounded-context')) {
|
|
577
586
|
lines.push('- Continue rule: pull-indexed-context is an internal continuation step; after the bounded read, continue to edit/verify in the same turn when safe.');
|
|
578
587
|
}
|
|
@@ -639,6 +648,8 @@ function deriveContinuationState(state = {}) {
|
|
|
639
648
|
repeatCount: 1,
|
|
640
649
|
stuckRisk: null,
|
|
641
650
|
rescueMode: null,
|
|
651
|
+
wideningBlocked: false,
|
|
652
|
+
milestonePriority: 'normal',
|
|
642
653
|
};
|
|
643
654
|
}
|
|
644
655
|
|
|
@@ -12,7 +12,7 @@ Auto-generated by UKit for OpenAI Codex.
|
|
|
12
12
|
- Do not make end users memorize skill names, helper scripts, or routing internals unless they are debugging UKit itself.
|
|
13
13
|
- **Treat helper commands as internal orchestration. Do not ask end users to run them.**
|
|
14
14
|
|
|
15
|
-
## UKit v1.4.
|
|
15
|
+
## UKit v1.4.3 Shared Runtime
|
|
16
16
|
|
|
17
17
|
- Shared runtime state lives in `.ukit/storage/`.
|
|
18
18
|
- Treat `.ukit/storage/config.json` as the source of compact, token-pipeline, router, memory, validation, and Safe Patch guardrail toggles.
|
package/templates/ukit/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# UKit Shared Runtime
|
|
2
2
|
|
|
3
|
-
This folder stores shared UKit runtime state for v1.4.
|
|
3
|
+
This folder stores shared UKit runtime state for v1.4.3 features.
|
|
4
4
|
|
|
5
5
|
- `storage/config.json` — runtime feature flags and defaults
|
|
6
6
|
- `storage/cache/` — prompt-cache, compact history, compact pressure state, output summaries, and preserved raw tool outputs under `storage/cache/tee/`
|