@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
|
@@ -273,7 +273,7 @@ const { pathToFileURL } = require('url');
|
|
|
273
273
|
}
|
|
274
274
|
|
|
275
275
|
if (concreteTask) {
|
|
276
|
-
if (/\b(bug|debug|error|crash|broken|failing|stack trace|triage|fix|
|
|
276
|
+
if (/\b(bug|debug|error|crash|broken|failing|stack trace|triage|fix|timeout)\b/.test(lower)) {
|
|
277
277
|
return 'debug-specific';
|
|
278
278
|
}
|
|
279
279
|
if (/\b(review|audit|diff|pr feedback|code review|kiem tra|soat)\b/.test(raw)) {
|
|
@@ -1307,9 +1307,11 @@ const { pathToFileURL } = require('url');
|
|
|
1307
1307
|
&& contextRecommendation.command.trim();
|
|
1308
1308
|
const executionMode = routingContext.executionMode || null;
|
|
1309
1309
|
const executionScores = routingContext.executionScores || null;
|
|
1310
|
+
const executionCandidates = routingContext.executionCandidates || null;
|
|
1310
1311
|
const approachSelector = buildApproachSelectorResult({
|
|
1311
1312
|
executionMode,
|
|
1312
1313
|
executionScores,
|
|
1314
|
+
executionCandidates,
|
|
1313
1315
|
});
|
|
1314
1316
|
const executionContract = buildExecutionContract(executionMode);
|
|
1315
1317
|
const completionState = buildCompletionState({
|
|
@@ -1345,6 +1347,7 @@ const { pathToFileURL } = require('url');
|
|
|
1345
1347
|
policyMode,
|
|
1346
1348
|
executionMode,
|
|
1347
1349
|
executionScores,
|
|
1350
|
+
executionCandidates,
|
|
1348
1351
|
approachSelector,
|
|
1349
1352
|
executionContract,
|
|
1350
1353
|
completionState,
|
|
@@ -1371,6 +1374,12 @@ const { pathToFileURL } = require('url');
|
|
|
1371
1374
|
const buildSignal = /\b(build|create|add|implement|feature)\b/.test(raw);
|
|
1372
1375
|
const debugSignal = intentMode === 'debug-specific' || /\b(root cause|debug|triage|flaky|investigate|why)\b/.test(raw);
|
|
1373
1376
|
const reviewSignal = intentMode === 'review-specific' || /\b(review|audit|verify|release readiness)\b/.test(raw);
|
|
1377
|
+
const failureSignal = /\b(failing|failed|broken|error|crash|timeout|undefined|exception|eacces|trace)\b/.test(raw);
|
|
1378
|
+
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);
|
|
1379
|
+
const boundedEditSignal = /\b(one[- ]line|small|tiny|single|local|guard|log line|loading message|label)\b/.test(raw);
|
|
1380
|
+
const implementSignal = /\b(implement|apply|update|modify|add|create|ship|deliver|fix)\b/.test(raw)
|
|
1381
|
+
|| /\bchange\s+.+\s+to\s+.+\b/.test(raw);
|
|
1382
|
+
const explicitTarget = Boolean(targetFile);
|
|
1374
1383
|
|
|
1375
1384
|
let editCertainty = 0;
|
|
1376
1385
|
if (directTransformSignal) {
|
|
@@ -1384,7 +1393,7 @@ const { pathToFileURL } = require('url');
|
|
|
1384
1393
|
let investigationNeed = 0;
|
|
1385
1394
|
if (debugSignal) {
|
|
1386
1395
|
investigationNeed = 3;
|
|
1387
|
-
} else if (
|
|
1396
|
+
} else if (failureSignal) {
|
|
1388
1397
|
investigationNeed = 2;
|
|
1389
1398
|
}
|
|
1390
1399
|
|
|
@@ -1417,6 +1426,17 @@ const { pathToFileURL } = require('url');
|
|
|
1417
1426
|
blastRadius,
|
|
1418
1427
|
verificationBurden,
|
|
1419
1428
|
ambiguity,
|
|
1429
|
+
sharedRisk,
|
|
1430
|
+
directTransformSignal,
|
|
1431
|
+
smallFixSignal,
|
|
1432
|
+
buildSignal,
|
|
1433
|
+
debugSignal,
|
|
1434
|
+
reviewSignal,
|
|
1435
|
+
failureSignal,
|
|
1436
|
+
impactSignal,
|
|
1437
|
+
boundedEditSignal,
|
|
1438
|
+
implementSignal,
|
|
1439
|
+
explicitTarget,
|
|
1420
1440
|
};
|
|
1421
1441
|
}
|
|
1422
1442
|
|
|
@@ -1426,40 +1446,64 @@ const { pathToFileURL } = require('url');
|
|
|
1426
1446
|
targetFile = null,
|
|
1427
1447
|
intentMode = null,
|
|
1428
1448
|
executionScores = {},
|
|
1449
|
+
executionCandidates = null,
|
|
1429
1450
|
} = {}) {
|
|
1430
1451
|
const raw = `${promptText || ''}\n${commandText || ''}`.toLowerCase();
|
|
1431
1452
|
const scores = executionScores;
|
|
1453
|
+
const candidates = executionCandidates ?? buildExecutionModeCandidates({
|
|
1454
|
+
promptText,
|
|
1455
|
+
commandText,
|
|
1456
|
+
targetFile,
|
|
1457
|
+
intentMode,
|
|
1458
|
+
executionScores,
|
|
1459
|
+
});
|
|
1432
1460
|
const explicitReviewLead = /\b(review this|audit this|review\b.*\brelease readiness|verify\b.*\brelease readiness)\b/.test(raw);
|
|
1461
|
+
const strongImpactLead = scores.sharedRisk
|
|
1462
|
+
&& (scores.impactSignal || /\b(check all affected|map all affected|across all affected)\b/.test(raw));
|
|
1463
|
+
const boundedLocalBuildCandidate = scores.buildSignal && scores.boundedEditSignal && scores.explicitTarget && !scores.sharedRisk;
|
|
1433
1464
|
|
|
1434
|
-
if (intentMode === 'review-specific' || explicitReviewLead) {
|
|
1465
|
+
if ((intentMode === 'review-specific' || explicitReviewLead) && !scores.implementSignal) {
|
|
1435
1466
|
return 'review-release';
|
|
1436
1467
|
}
|
|
1437
1468
|
|
|
1438
|
-
if (scores.blastRadius >= 3 && (scores.ambiguity >= 2 || scores.investigationNeed >= 2)) {
|
|
1469
|
+
if (strongImpactLead || (scores.blastRadius >= 3 && (scores.ambiguity >= 2 || scores.investigationNeed >= 2))) {
|
|
1439
1470
|
return 'map-impact';
|
|
1440
1471
|
}
|
|
1441
1472
|
|
|
1442
|
-
if (scores.
|
|
1473
|
+
if (scores.sharedRisk && scores.failureSignal && scores.investigationNeed >= 2 && !scores.impactSignal) {
|
|
1443
1474
|
return 'shared-edit';
|
|
1444
1475
|
}
|
|
1445
1476
|
|
|
1446
|
-
if (scores.
|
|
1477
|
+
if (scores.blastRadius >= 3 || scores.sharedRisk) {
|
|
1478
|
+
return 'shared-edit';
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
if (scores.investigationNeed >= 3 || (scores.failureSignal && scores.investigationNeed >= 2)) {
|
|
1447
1482
|
return 'find-cause';
|
|
1448
1483
|
}
|
|
1449
1484
|
|
|
1485
|
+
if (scores.directTransformSignal && !scores.explicitTarget && scores.investigationNeed === 0 && !scores.sharedRisk) {
|
|
1486
|
+
return 'local-build';
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1450
1489
|
if (
|
|
1451
1490
|
scores.editCertainty >= 3
|
|
1452
|
-
&& scores.ambiguity
|
|
1491
|
+
&& scores.ambiguity <= 1
|
|
1453
1492
|
&& scores.blastRadius === 0
|
|
1454
1493
|
&& scores.verificationBurden <= 1
|
|
1455
1494
|
) {
|
|
1456
1495
|
return 'tiny-fix';
|
|
1457
1496
|
}
|
|
1458
1497
|
|
|
1498
|
+
if (boundedLocalBuildCandidate && scores.investigationNeed === 0) {
|
|
1499
|
+
return 'local-fix';
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1459
1502
|
if (
|
|
1460
1503
|
/\b(build|create|add|implement|feature|summary card)\b/.test(raw)
|
|
1461
1504
|
&& scores.investigationNeed === 0
|
|
1462
1505
|
&& scores.blastRadius < 3
|
|
1506
|
+
&& !scores.boundedEditSignal
|
|
1463
1507
|
) {
|
|
1464
1508
|
return 'local-build';
|
|
1465
1509
|
}
|
|
@@ -1468,7 +1512,107 @@ const { pathToFileURL } = require('url');
|
|
|
1468
1512
|
return 'local-fix';
|
|
1469
1513
|
}
|
|
1470
1514
|
|
|
1471
|
-
return 'local-build';
|
|
1515
|
+
return applySafeUpwardBias(candidates, 'local-build');
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
function buildExecutionModeCandidates({
|
|
1519
|
+
promptText = '',
|
|
1520
|
+
commandText = '',
|
|
1521
|
+
targetFile = null,
|
|
1522
|
+
intentMode = null,
|
|
1523
|
+
executionScores = {},
|
|
1524
|
+
} = {}) {
|
|
1525
|
+
const scores = executionScores;
|
|
1526
|
+
const raw = `${promptText || ''}\n${commandText || ''}`.toLowerCase();
|
|
1527
|
+
const explicitReviewLead = (intentMode === 'review-specific' || /\b(review this|audit this|review\b.*\brelease readiness|verify\b.*\brelease readiness)\b/.test(raw))
|
|
1528
|
+
&& !scores.implementSignal;
|
|
1529
|
+
|
|
1530
|
+
const modeScores = {
|
|
1531
|
+
'tiny-fix': (
|
|
1532
|
+
(scores.editCertainty * 4)
|
|
1533
|
+
+ (scores.directTransformSignal ? 4 : 0)
|
|
1534
|
+
+ (scores.explicitTarget ? 1 : 0)
|
|
1535
|
+
- (scores.failureSignal ? 4 : 0)
|
|
1536
|
+
- (scores.blastRadius * 4)
|
|
1537
|
+
- (scores.ambiguity * 2)
|
|
1538
|
+
),
|
|
1539
|
+
'local-fix': (
|
|
1540
|
+
(scores.editCertainty * 3)
|
|
1541
|
+
+ (scores.boundedEditSignal ? 3 : 0)
|
|
1542
|
+
+ (scores.explicitTarget ? 1 : 0)
|
|
1543
|
+
- (scores.failureSignal ? 2 : 0)
|
|
1544
|
+
- (scores.blastRadius * 4)
|
|
1545
|
+
),
|
|
1546
|
+
'local-build': (
|
|
1547
|
+
(scores.buildSignal ? 6 : 0)
|
|
1548
|
+
+ (scores.editCertainty * 1)
|
|
1549
|
+
+ (scores.explicitTarget ? 1 : 0)
|
|
1550
|
+
- (scores.boundedEditSignal ? 3 : 0)
|
|
1551
|
+
- (scores.failureSignal ? 3 : 0)
|
|
1552
|
+
- (scores.blastRadius * 4)
|
|
1553
|
+
),
|
|
1554
|
+
'find-cause': (
|
|
1555
|
+
(scores.investigationNeed * 4)
|
|
1556
|
+
+ (scores.failureSignal ? 3 : 0)
|
|
1557
|
+
+ (scores.debugSignal ? 2 : 0)
|
|
1558
|
+
- (scores.blastRadius >= 3 ? 1 : 0)
|
|
1559
|
+
),
|
|
1560
|
+
'shared-edit': (
|
|
1561
|
+
(scores.sharedRisk ? 8 : 0)
|
|
1562
|
+
+ (scores.editCertainty * 1)
|
|
1563
|
+
+ (scores.buildSignal ? 1 : 0)
|
|
1564
|
+
- (scores.impactSignal ? 2 : 0)
|
|
1565
|
+
),
|
|
1566
|
+
'map-impact': (
|
|
1567
|
+
(scores.sharedRisk ? 7 : 0)
|
|
1568
|
+
+ (scores.impactSignal ? 5 : 0)
|
|
1569
|
+
+ (scores.ambiguity * 2)
|
|
1570
|
+
+ scores.investigationNeed
|
|
1571
|
+
),
|
|
1572
|
+
'review-release': (
|
|
1573
|
+
(explicitReviewLead ? 10 : 0)
|
|
1574
|
+
+ (scores.reviewSignal ? 3 : 0)
|
|
1575
|
+
- (scores.implementSignal ? 5 : 0)
|
|
1576
|
+
),
|
|
1577
|
+
};
|
|
1578
|
+
|
|
1579
|
+
return Object.entries(modeScores)
|
|
1580
|
+
.map(([mode, score]) => ({ mode, score }))
|
|
1581
|
+
.sort((a, b) => b.score - a.score || executionModeRank(a.mode) - executionModeRank(b.mode));
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
function applySafeUpwardBias(candidates = [], fallbackMode = 'local-build') {
|
|
1585
|
+
const [topCandidate, competingCandidate] = candidates;
|
|
1586
|
+
if (!topCandidate) {
|
|
1587
|
+
return fallbackMode;
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
if (!competingCandidate) {
|
|
1591
|
+
return topCandidate.mode;
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
const scoreGap = Number(topCandidate.score ?? 0) - Number(competingCandidate.score ?? 0);
|
|
1595
|
+
const rankGap = executionModeRank(competingCandidate.mode) - executionModeRank(topCandidate.mode);
|
|
1596
|
+
if (scoreGap <= 1 && rankGap === 1) {
|
|
1597
|
+
return competingCandidate.mode;
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1600
|
+
return topCandidate.mode;
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
function executionModeRank(mode = '') {
|
|
1604
|
+
const orderedModes = [
|
|
1605
|
+
'tiny-fix',
|
|
1606
|
+
'local-fix',
|
|
1607
|
+
'local-build',
|
|
1608
|
+
'find-cause',
|
|
1609
|
+
'shared-edit',
|
|
1610
|
+
'map-impact',
|
|
1611
|
+
'review-release',
|
|
1612
|
+
];
|
|
1613
|
+
|
|
1614
|
+
const index = orderedModes.indexOf(mode);
|
|
1615
|
+
return index >= 0 ? index : orderedModes.length;
|
|
1472
1616
|
}
|
|
1473
1617
|
|
|
1474
1618
|
function buildExecutionContract(executionMode = null) {
|
|
@@ -1540,6 +1684,7 @@ const { pathToFileURL } = require('url');
|
|
|
1540
1684
|
function buildApproachSelectorResult({
|
|
1541
1685
|
executionMode = null,
|
|
1542
1686
|
executionScores = null,
|
|
1687
|
+
executionCandidates = null,
|
|
1543
1688
|
} = {}) {
|
|
1544
1689
|
if (!executionMode) {
|
|
1545
1690
|
return null;
|
|
@@ -1588,6 +1733,14 @@ const { pathToFileURL } = require('url');
|
|
|
1588
1733
|
contextPolicy: selectedPolicy.contextPolicy,
|
|
1589
1734
|
verificationPolicy: executionContract?.verificationPolicy ?? null,
|
|
1590
1735
|
completionRule: executionContract?.completionRule ?? null,
|
|
1736
|
+
competingMode: executionCandidates?.[1]?.mode ?? null,
|
|
1737
|
+
competingScoreGap: executionCandidates?.length >= 2
|
|
1738
|
+
? Number(executionCandidates[0]?.score ?? 0) - Number(executionCandidates[1]?.score ?? 0)
|
|
1739
|
+
: null,
|
|
1740
|
+
candidateModes: (executionCandidates ?? []).slice(0, 3).map((entry) => ({
|
|
1741
|
+
mode: entry.mode,
|
|
1742
|
+
score: entry.score,
|
|
1743
|
+
})),
|
|
1591
1744
|
};
|
|
1592
1745
|
}
|
|
1593
1746
|
|
|
@@ -1675,6 +1828,8 @@ const { pathToFileURL } = require('url');
|
|
|
1675
1828
|
repeatCount: reasons.length > 0 ? 1 : 0,
|
|
1676
1829
|
stuckRisk: null,
|
|
1677
1830
|
rescueMode: null,
|
|
1831
|
+
wideningBlocked: false,
|
|
1832
|
+
milestonePriority: reasons.length > 0 ? 'normal' : null,
|
|
1678
1833
|
};
|
|
1679
1834
|
}
|
|
1680
1835
|
|
|
@@ -1689,6 +1844,8 @@ const { pathToFileURL } = require('url');
|
|
|
1689
1844
|
repeatCount: 0,
|
|
1690
1845
|
stuckRisk: null,
|
|
1691
1846
|
rescueMode: null,
|
|
1847
|
+
wideningBlocked: false,
|
|
1848
|
+
milestonePriority: null,
|
|
1692
1849
|
};
|
|
1693
1850
|
}
|
|
1694
1851
|
|
|
@@ -1717,15 +1874,45 @@ const { pathToFileURL } = require('url');
|
|
|
1717
1874
|
const stuckRisk = repeatCount >= 3
|
|
1718
1875
|
? 'high'
|
|
1719
1876
|
: (repeatCount === 2 ? 'elevated' : null);
|
|
1877
|
+
const wideningBlocked = repeatCount >= 2 && Boolean(rescueMode);
|
|
1878
|
+
const nextMilestone = repeatCount >= 2 && currentReasons.includes('missing-write-evidence')
|
|
1879
|
+
? 'finish-write-before-more-analysis'
|
|
1880
|
+
: (
|
|
1881
|
+
repeatCount >= 2 && currentReasons.includes('pending-bounded-context')
|
|
1882
|
+
? 'finish-current-milestone-before-more-reading'
|
|
1883
|
+
: continuationState.nextMilestone
|
|
1884
|
+
);
|
|
1720
1885
|
|
|
1721
1886
|
return {
|
|
1722
1887
|
...continuationState,
|
|
1888
|
+
nextMilestone,
|
|
1723
1889
|
repeatCount,
|
|
1724
1890
|
stuckRisk,
|
|
1725
1891
|
rescueMode,
|
|
1892
|
+
wideningBlocked,
|
|
1893
|
+
milestonePriority: wideningBlocked ? 'execute-current-milestone' : 'normal',
|
|
1726
1894
|
};
|
|
1727
1895
|
}
|
|
1728
1896
|
|
|
1897
|
+
function applyRescueBiasToRouteSummary(routeSummary = null) {
|
|
1898
|
+
if (!routeSummary || typeof routeSummary !== 'object') {
|
|
1899
|
+
return routeSummary;
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
const continuationState = routeSummary.continuationState;
|
|
1903
|
+
if (
|
|
1904
|
+
continuationState?.repeatCount >= 2
|
|
1905
|
+
&& continuationState?.wideningBlocked
|
|
1906
|
+
&& (continuationState.reasons ?? []).includes('missing-write-evidence')
|
|
1907
|
+
) {
|
|
1908
|
+
routeSummary.nextActionType = 'execute-current-milestone';
|
|
1909
|
+
routeSummary.nextActionCommand = null;
|
|
1910
|
+
routeSummary.helperHint = null;
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1913
|
+
return routeSummary;
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1729
1916
|
const SHARED_IMPACT_PATTERNS = [
|
|
1730
1917
|
/^\.claude\/hooks\//,
|
|
1731
1918
|
/^\.claude\/ukit\//,
|
|
@@ -1901,6 +2088,79 @@ const { pathToFileURL } = require('url');
|
|
|
1901
2088
|
};
|
|
1902
2089
|
}
|
|
1903
2090
|
|
|
2091
|
+
function buildRouteAuditEntry({
|
|
2092
|
+
routingContext = {},
|
|
2093
|
+
routeSummary = {},
|
|
2094
|
+
state = null,
|
|
2095
|
+
} = {}) {
|
|
2096
|
+
const candidateModes = Array.isArray(routeSummary?.approachSelector?.candidateModes)
|
|
2097
|
+
? routeSummary.approachSelector.candidateModes
|
|
2098
|
+
: [];
|
|
2099
|
+
|
|
2100
|
+
return {
|
|
2101
|
+
ts: Date.now(),
|
|
2102
|
+
source: state?.source || 'skill-router',
|
|
2103
|
+
requestKey: state?.requestKey || null,
|
|
2104
|
+
adapter: routingContext.adapter || 'claude',
|
|
2105
|
+
promptFingerprint: stableMachineDigest({
|
|
2106
|
+
prompt: routingContext.lastExplicitUserPromptText || '',
|
|
2107
|
+
adapter: routingContext.adapter || 'claude',
|
|
2108
|
+
}),
|
|
2109
|
+
targetFile: routingContext.targetFile || null,
|
|
2110
|
+
taskType: routingContext.taskType || null,
|
|
2111
|
+
executionMode: routeSummary.executionMode || null,
|
|
2112
|
+
competingMode: routeSummary?.approachSelector?.competingMode || null,
|
|
2113
|
+
competingScoreGap: routeSummary?.approachSelector?.competingScoreGap || null,
|
|
2114
|
+
candidateModes: candidateModes.slice(0, 3),
|
|
2115
|
+
nextActionType: routeSummary.nextActionType || null,
|
|
2116
|
+
nextMilestone: routeSummary?.continuationState?.nextMilestone || null,
|
|
2117
|
+
repeatCount: routeSummary?.continuationState?.repeatCount || null,
|
|
2118
|
+
rescueMode: routeSummary?.continuationState?.rescueMode || null,
|
|
2119
|
+
wideningBlocked: routeSummary?.continuationState?.wideningBlocked || null,
|
|
2120
|
+
};
|
|
2121
|
+
}
|
|
2122
|
+
|
|
2123
|
+
function appendRouteAuditEntry(filePath, entry) {
|
|
2124
|
+
if (!entry || typeof entry !== 'object') {
|
|
2125
|
+
return;
|
|
2126
|
+
}
|
|
2127
|
+
|
|
2128
|
+
let parsed = { entries: [] };
|
|
2129
|
+
if (fs.existsSync(filePath)) {
|
|
2130
|
+
try {
|
|
2131
|
+
parsed = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
2132
|
+
} catch {
|
|
2133
|
+
parsed = { entries: [] };
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
const entries = Array.isArray(parsed?.entries) ? parsed.entries : [];
|
|
2138
|
+
const dedupeKey = stableMachineDigest({
|
|
2139
|
+
requestKey: entry.requestKey,
|
|
2140
|
+
executionMode: entry.executionMode,
|
|
2141
|
+
nextActionType: entry.nextActionType,
|
|
2142
|
+
nextMilestone: entry.nextMilestone,
|
|
2143
|
+
repeatCount: entry.repeatCount,
|
|
2144
|
+
rescueMode: entry.rescueMode,
|
|
2145
|
+
});
|
|
2146
|
+
const filtered = entries.filter((item) => {
|
|
2147
|
+
const itemKey = stableMachineDigest({
|
|
2148
|
+
requestKey: item?.requestKey || null,
|
|
2149
|
+
executionMode: item?.executionMode || null,
|
|
2150
|
+
nextActionType: item?.nextActionType || null,
|
|
2151
|
+
nextMilestone: item?.nextMilestone || null,
|
|
2152
|
+
repeatCount: item?.repeatCount || null,
|
|
2153
|
+
rescueMode: item?.rescueMode || null,
|
|
2154
|
+
});
|
|
2155
|
+
return itemKey !== dedupeKey;
|
|
2156
|
+
});
|
|
2157
|
+
|
|
2158
|
+
ensureDir(filePath);
|
|
2159
|
+
fs.writeFileSync(filePath, JSON.stringify({
|
|
2160
|
+
entries: [entry, ...filtered].slice(0, 40),
|
|
2161
|
+
}));
|
|
2162
|
+
}
|
|
2163
|
+
|
|
1904
2164
|
function shouldIncludePreviousContext({ routingContext = {}, useIndexedContext = true } = {}) {
|
|
1905
2165
|
const taskType = String(routingContext?.taskType || '').trim();
|
|
1906
2166
|
const hasExplicitTarget = Boolean(String(routingContext?.targetFile || '').trim());
|
|
@@ -1999,6 +2259,7 @@ const { pathToFileURL } = require('url');
|
|
|
1999
2259
|
const projectRoot = process.env.PROJECT_ROOT || process.cwd();
|
|
2000
2260
|
const statePath = process.env.STATE_FILE || path.join(projectRoot, '.claude', 'ukit', 'skill-router-state.json');
|
|
2001
2261
|
const routeCachePath = path.join(projectRoot, '.claude', 'ukit', 'route-cache.json');
|
|
2262
|
+
const routeAuditPath = path.join(projectRoot, '.ukit', 'storage', 'cache', 'route-audit.json');
|
|
2002
2263
|
const cacheUtilsPath = path.join(projectRoot, '.claude', 'ukit', 'index', 'cache-utils.mjs');
|
|
2003
2264
|
const previous = readJson(statePath, {});
|
|
2004
2265
|
const runtimeConfig = loadRuntimeConfig(projectRoot);
|
|
@@ -2106,13 +2367,20 @@ const { pathToFileURL } = require('url');
|
|
|
2106
2367
|
intentMode,
|
|
2107
2368
|
taskType,
|
|
2108
2369
|
});
|
|
2370
|
+
const executionCandidates = buildExecutionModeCandidates({
|
|
2371
|
+
promptText,
|
|
2372
|
+
commandText,
|
|
2373
|
+
targetFile: filePath,
|
|
2374
|
+
intentMode,
|
|
2375
|
+
executionScores,
|
|
2376
|
+
});
|
|
2109
2377
|
const executionMode = deriveExecutionMode({
|
|
2110
2378
|
promptText,
|
|
2111
2379
|
commandText,
|
|
2112
2380
|
targetFile: filePath,
|
|
2113
2381
|
intentMode,
|
|
2114
|
-
taskType,
|
|
2115
2382
|
executionScores,
|
|
2383
|
+
executionCandidates,
|
|
2116
2384
|
});
|
|
2117
2385
|
const lastExplicitUserPromptText = promptText.trim()
|
|
2118
2386
|
|| previous?.routingContext?.lastExplicitUserPromptText
|
|
@@ -2126,6 +2394,7 @@ const { pathToFileURL } = require('url');
|
|
|
2126
2394
|
taskType,
|
|
2127
2395
|
intentMode,
|
|
2128
2396
|
executionScores,
|
|
2397
|
+
executionCandidates,
|
|
2129
2398
|
executionMode,
|
|
2130
2399
|
};
|
|
2131
2400
|
const useIndexedContext = shouldUseIndexedContext({
|
|
@@ -2193,6 +2462,9 @@ const { pathToFileURL } = require('url');
|
|
|
2193
2462
|
),
|
|
2194
2463
|
}
|
|
2195
2464
|
: null;
|
|
2465
|
+
if (rescuedRouteSummary) {
|
|
2466
|
+
applyRescueBiasToRouteSummary(rescuedRouteSummary);
|
|
2467
|
+
}
|
|
2196
2468
|
const reusedState = {
|
|
2197
2469
|
...cachedRouteState,
|
|
2198
2470
|
source: 'skill-router',
|
|
@@ -2208,6 +2480,9 @@ const { pathToFileURL } = require('url');
|
|
|
2208
2480
|
|
|
2209
2481
|
ensureDir(statePath);
|
|
2210
2482
|
fs.writeFileSync(statePath, JSON.stringify(reusedState));
|
|
2483
|
+
appendRouteAuditEntry(routeAuditPath, buildRouteAuditEntry({
|
|
2484
|
+
state: reusedState,
|
|
2485
|
+
}));
|
|
2211
2486
|
|
|
2212
2487
|
process.stdout.write(`[ukit-skill-router] Read skills: ${getActiveSkillPaths(reusedState.activeSkills || []).join(', ')}\n`);
|
|
2213
2488
|
process.stdout.write(`[ukit-skill-router] Route: ${formatDisplayRouteSummary(reusedState.routeSummary, reusedState.routingContext)}\n`);
|
|
@@ -2263,6 +2538,7 @@ const { pathToFileURL } = require('url');
|
|
|
2263
2538
|
routeSummary.continuationState,
|
|
2264
2539
|
previous?.routeSummary?.continuationState || null,
|
|
2265
2540
|
);
|
|
2541
|
+
applyRescueBiasToRouteSummary(routeSummary);
|
|
2266
2542
|
|
|
2267
2543
|
const fingerprint = buildRouteStateFingerprint({
|
|
2268
2544
|
activeSkills: selected,
|
|
@@ -2292,6 +2568,11 @@ const { pathToFileURL } = require('url');
|
|
|
2292
2568
|
routeSummary: compactRouteSummary(routeSummary),
|
|
2293
2569
|
};
|
|
2294
2570
|
fs.writeFileSync(statePath, JSON.stringify(sharedState));
|
|
2571
|
+
appendRouteAuditEntry(routeAuditPath, buildRouteAuditEntry({
|
|
2572
|
+
routingContext,
|
|
2573
|
+
routeSummary,
|
|
2574
|
+
state: sharedState,
|
|
2575
|
+
}));
|
|
2295
2576
|
if (typeof cacheUtils?.writeRecentCacheEntry === 'function') {
|
|
2296
2577
|
await cacheUtils.writeRecentCacheEntry(routeCachePath, compactRouteCacheState(sharedState), {
|
|
2297
2578
|
maxEntries: cacheUtils.DEFAULT_RECENT_CACHE_MAX_ENTRIES,
|