@ngockhoale/ukit 1.4.2 → 1.4.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/CHANGELOG.md +18 -1
- package/package.json +1 -1
- package/src/core/runtimeConfig.js +1 -1
- package/src/index/routeCatalog.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-catalog.mjs +1 -1
- 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/.gitignore +0 -14
- package/templates/ukit/README.md +1 -1
- package/templates/ukit/storage/config.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to UKit are documented here.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 1.4.4 - 2026-05-11
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Removed shipped `.gitignore` negations that accidentally unignored installed `.claude/` and `.codex/` files in fresh repos, preventing large post-install `git status` noise.
|
|
10
|
+
- Kept the intended local-only ignores for `AGENTS.md`, `CLAUDE.md`, `docs/STATUS.md`, `docs/TASKS.md`, runtime cache, and adapter state intact.
|
|
11
|
+
|
|
12
|
+
### Tests
|
|
13
|
+
|
|
14
|
+
- Added install-pipeline regression coverage that initializes a fresh git repo, runs `ukit install`, and asserts managed UKit files stay ignored.
|
|
15
|
+
|
|
16
|
+
## 1.4.3 - 2026-05-10
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Tightened execute-first orchestration guidance so one clear safe path runs directly, while real user-choice or risk-confirmation moments still ask.
|
|
21
|
+
- Added compact route-audit coverage and repeated write-lane rescue bias to reduce stop-and-explain loops.
|
|
22
|
+
- Published patch `1.4.3` after fresh full-suite, release-verify, and registry-smoke validation.
|
|
6
23
|
|
|
7
24
|
## 1.4.2 - 2026-05-10
|
|
8
25
|
|
package/package.json
CHANGED
|
@@ -178,7 +178,7 @@ export const ROUTE_CATALOG = [
|
|
|
178
178
|
order: 20,
|
|
179
179
|
contextMode: 'standalone',
|
|
180
180
|
signals: [
|
|
181
|
-
{ type: 'prompt', regex: /\b(pdf
|
|
181
|
+
{ type: 'prompt', regex: /\b(pdf form|fillable pdf|fill (?:this )?pdf|merge pdfs?|split pdfs?|extract tables? from .*pdf|extract text from .*pdf|read (?:this |the |a )?pdf|open (?:this |the |a )?pdf|analy(?:s|z)e (?:this |the |a )?pdf|annotate (?:this |the |a )?pdf|create pdf|convert .*pdf|pdf extraction|pdf parser|pdf parsing)\b/i, score: 8 },
|
|
182
182
|
{ type: 'command', regex: /\b(pdftotext|qpdf|pypdf|pdfplumber|reportlab)\b/i, score: 5 },
|
|
183
183
|
{ type: 'file', regex: /\.pdf$/i, score: 5 },
|
|
184
184
|
],
|
package/src/index/taskRouting.js
CHANGED
|
@@ -59,13 +59,20 @@ export async function deriveTaskRoute({
|
|
|
59
59
|
intentMode,
|
|
60
60
|
taskType: inferredTaskType,
|
|
61
61
|
});
|
|
62
|
+
const executionCandidates = buildExecutionModeCandidates({
|
|
63
|
+
promptText: normalizedPrompt,
|
|
64
|
+
commandText: normalizedCommand,
|
|
65
|
+
targetFile: normalizedTarget,
|
|
66
|
+
intentMode,
|
|
67
|
+
executionScores,
|
|
68
|
+
});
|
|
62
69
|
const executionMode = deriveExecutionMode({
|
|
63
70
|
promptText: normalizedPrompt,
|
|
64
71
|
commandText: normalizedCommand,
|
|
65
72
|
targetFile: normalizedTarget,
|
|
66
73
|
intentMode,
|
|
67
|
-
taskType: inferredTaskType,
|
|
68
74
|
executionScores,
|
|
75
|
+
executionCandidates,
|
|
69
76
|
});
|
|
70
77
|
const preservedPrompt = normalizedPrompt || String(lastExplicitUserPromptText || '').trim();
|
|
71
78
|
const degradedWarnings = [];
|
|
@@ -144,6 +151,7 @@ export async function deriveTaskRoute({
|
|
|
144
151
|
intentMode,
|
|
145
152
|
autonomyLevel,
|
|
146
153
|
executionScores,
|
|
154
|
+
executionCandidates,
|
|
147
155
|
executionMode,
|
|
148
156
|
},
|
|
149
157
|
contextRecommendation,
|
|
@@ -164,6 +172,7 @@ export async function deriveTaskRoute({
|
|
|
164
172
|
intentMode,
|
|
165
173
|
autonomyLevel,
|
|
166
174
|
executionScores,
|
|
175
|
+
executionCandidates,
|
|
167
176
|
executionMode,
|
|
168
177
|
},
|
|
169
178
|
approachSelector,
|
|
@@ -209,9 +218,11 @@ export function buildRouteSummary({
|
|
|
209
218
|
&& contextRecommendation.command.trim();
|
|
210
219
|
const executionMode = routingContext.executionMode ?? null;
|
|
211
220
|
const executionScores = routingContext.executionScores ?? null;
|
|
221
|
+
const executionCandidates = routingContext.executionCandidates ?? null;
|
|
212
222
|
const approachSelector = buildApproachSelectorResult({
|
|
213
223
|
executionMode,
|
|
214
224
|
executionScores,
|
|
225
|
+
executionCandidates,
|
|
215
226
|
});
|
|
216
227
|
const executionContract = buildExecutionContract(executionMode);
|
|
217
228
|
const completionState = buildCompletionState({
|
|
@@ -250,6 +261,7 @@ export function buildRouteSummary({
|
|
|
250
261
|
editGuardHint,
|
|
251
262
|
executionMode,
|
|
252
263
|
executionScores,
|
|
264
|
+
executionCandidates,
|
|
253
265
|
approachSelector,
|
|
254
266
|
executionContract,
|
|
255
267
|
completionState,
|
|
@@ -284,6 +296,12 @@ function deriveExecutionScores({
|
|
|
284
296
|
const buildSignal = /\b(build|create|add|implement|feature)\b/.test(raw);
|
|
285
297
|
const debugSignal = intentMode === 'debug-specific' || /\b(root cause|debug|triage|flaky|investigate|why)\b/.test(raw);
|
|
286
298
|
const reviewSignal = intentMode === 'review-specific' || /\b(review|audit|verify|release readiness)\b/.test(raw);
|
|
299
|
+
const failureSignal = /\b(failing|failed|broken|error|crash|timeout|undefined|exception|eacces|trace)\b/.test(raw);
|
|
300
|
+
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);
|
|
301
|
+
const boundedEditSignal = /\b(one[- ]line|small|tiny|single|local|guard|log line|loading message|label)\b/.test(raw);
|
|
302
|
+
const implementSignal = /\b(implement|apply|update|modify|add|create|ship|deliver|fix)\b/.test(raw)
|
|
303
|
+
|| /\bchange\s+.+\s+to\s+.+\b/.test(raw);
|
|
304
|
+
const explicitTarget = Boolean(targetFile);
|
|
287
305
|
|
|
288
306
|
let editCertainty = 0;
|
|
289
307
|
if (directTransformSignal) {
|
|
@@ -297,7 +315,7 @@ function deriveExecutionScores({
|
|
|
297
315
|
let investigationNeed = 0;
|
|
298
316
|
if (debugSignal) {
|
|
299
317
|
investigationNeed = 3;
|
|
300
|
-
} else if (
|
|
318
|
+
} else if (failureSignal) {
|
|
301
319
|
investigationNeed = 2;
|
|
302
320
|
}
|
|
303
321
|
|
|
@@ -330,6 +348,17 @@ function deriveExecutionScores({
|
|
|
330
348
|
blastRadius,
|
|
331
349
|
verificationBurden,
|
|
332
350
|
ambiguity,
|
|
351
|
+
sharedRisk,
|
|
352
|
+
directTransformSignal,
|
|
353
|
+
smallFixSignal,
|
|
354
|
+
buildSignal,
|
|
355
|
+
debugSignal,
|
|
356
|
+
reviewSignal,
|
|
357
|
+
failureSignal,
|
|
358
|
+
impactSignal,
|
|
359
|
+
boundedEditSignal,
|
|
360
|
+
implementSignal,
|
|
361
|
+
explicitTarget,
|
|
333
362
|
};
|
|
334
363
|
}
|
|
335
364
|
|
|
@@ -339,40 +368,64 @@ function deriveExecutionMode({
|
|
|
339
368
|
targetFile = null,
|
|
340
369
|
intentMode = null,
|
|
341
370
|
executionScores = {},
|
|
371
|
+
executionCandidates = null,
|
|
342
372
|
} = {}) {
|
|
343
373
|
const raw = `${promptText ?? ''}\n${commandText ?? ''}`.toLowerCase();
|
|
344
374
|
const scores = executionScores;
|
|
375
|
+
const candidates = executionCandidates ?? buildExecutionModeCandidates({
|
|
376
|
+
promptText,
|
|
377
|
+
commandText,
|
|
378
|
+
targetFile,
|
|
379
|
+
intentMode,
|
|
380
|
+
executionScores,
|
|
381
|
+
});
|
|
345
382
|
const explicitReviewLead = /\b(review this|audit this|review\b.*\brelease readiness|verify\b.*\brelease readiness)\b/.test(raw);
|
|
383
|
+
const strongImpactLead = scores.sharedRisk
|
|
384
|
+
&& (scores.impactSignal || /\b(check all affected|map all affected|across all affected)\b/.test(raw));
|
|
385
|
+
const boundedLocalBuildCandidate = scores.buildSignal && scores.boundedEditSignal && scores.explicitTarget && !scores.sharedRisk;
|
|
346
386
|
|
|
347
|
-
if (intentMode === 'review-specific' || explicitReviewLead) {
|
|
387
|
+
if ((intentMode === 'review-specific' || explicitReviewLead) && !scores.implementSignal) {
|
|
348
388
|
return 'review-release';
|
|
349
389
|
}
|
|
350
390
|
|
|
351
|
-
if (scores.blastRadius >= 3 && (scores.ambiguity >= 2 || scores.investigationNeed >= 2)) {
|
|
391
|
+
if (strongImpactLead || (scores.blastRadius >= 3 && (scores.ambiguity >= 2 || scores.investigationNeed >= 2))) {
|
|
352
392
|
return 'map-impact';
|
|
353
393
|
}
|
|
354
394
|
|
|
355
|
-
if (scores.
|
|
395
|
+
if (scores.sharedRisk && scores.failureSignal && scores.investigationNeed >= 2 && !scores.impactSignal) {
|
|
356
396
|
return 'shared-edit';
|
|
357
397
|
}
|
|
358
398
|
|
|
359
|
-
if (scores.
|
|
399
|
+
if (scores.blastRadius >= 3 || scores.sharedRisk) {
|
|
400
|
+
return 'shared-edit';
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
if (scores.investigationNeed >= 3 || (scores.failureSignal && scores.investigationNeed >= 2)) {
|
|
360
404
|
return 'find-cause';
|
|
361
405
|
}
|
|
362
406
|
|
|
407
|
+
if (scores.directTransformSignal && !scores.explicitTarget && scores.investigationNeed === 0 && !scores.sharedRisk) {
|
|
408
|
+
return 'local-build';
|
|
409
|
+
}
|
|
410
|
+
|
|
363
411
|
if (
|
|
364
412
|
scores.editCertainty >= 3
|
|
365
|
-
&& scores.ambiguity
|
|
413
|
+
&& scores.ambiguity <= 1
|
|
366
414
|
&& scores.blastRadius === 0
|
|
367
415
|
&& scores.verificationBurden <= 1
|
|
368
416
|
) {
|
|
369
417
|
return 'tiny-fix';
|
|
370
418
|
}
|
|
371
419
|
|
|
420
|
+
if (boundedLocalBuildCandidate && scores.investigationNeed === 0) {
|
|
421
|
+
return 'local-fix';
|
|
422
|
+
}
|
|
423
|
+
|
|
372
424
|
if (
|
|
373
425
|
/\b(build|create|add|implement|feature|summary card)\b/.test(raw)
|
|
374
426
|
&& scores.investigationNeed === 0
|
|
375
427
|
&& scores.blastRadius < 3
|
|
428
|
+
&& !scores.boundedEditSignal
|
|
376
429
|
) {
|
|
377
430
|
return 'local-build';
|
|
378
431
|
}
|
|
@@ -381,7 +434,107 @@ function deriveExecutionMode({
|
|
|
381
434
|
return 'local-fix';
|
|
382
435
|
}
|
|
383
436
|
|
|
384
|
-
return 'local-build';
|
|
437
|
+
return applySafeUpwardBias(candidates, 'local-build');
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function buildExecutionModeCandidates({
|
|
441
|
+
promptText = '',
|
|
442
|
+
commandText = '',
|
|
443
|
+
targetFile = null,
|
|
444
|
+
intentMode = null,
|
|
445
|
+
executionScores = {},
|
|
446
|
+
} = {}) {
|
|
447
|
+
const scores = executionScores;
|
|
448
|
+
const raw = `${promptText ?? ''}\n${commandText ?? ''}`.toLowerCase();
|
|
449
|
+
const explicitReviewLead = (intentMode === 'review-specific' || /\b(review this|audit this|review\b.*\brelease readiness|verify\b.*\brelease readiness)\b/.test(raw))
|
|
450
|
+
&& !scores.implementSignal;
|
|
451
|
+
|
|
452
|
+
const modeScores = {
|
|
453
|
+
'tiny-fix': (
|
|
454
|
+
(scores.editCertainty * 4)
|
|
455
|
+
+ (scores.directTransformSignal ? 4 : 0)
|
|
456
|
+
+ (scores.explicitTarget ? 1 : 0)
|
|
457
|
+
- (scores.failureSignal ? 4 : 0)
|
|
458
|
+
- (scores.blastRadius * 4)
|
|
459
|
+
- (scores.ambiguity * 2)
|
|
460
|
+
),
|
|
461
|
+
'local-fix': (
|
|
462
|
+
(scores.editCertainty * 3)
|
|
463
|
+
+ (scores.boundedEditSignal ? 3 : 0)
|
|
464
|
+
+ (scores.explicitTarget ? 1 : 0)
|
|
465
|
+
- (scores.failureSignal ? 2 : 0)
|
|
466
|
+
- (scores.blastRadius * 4)
|
|
467
|
+
),
|
|
468
|
+
'local-build': (
|
|
469
|
+
(scores.buildSignal ? 6 : 0)
|
|
470
|
+
+ (scores.editCertainty * 1)
|
|
471
|
+
+ (scores.explicitTarget ? 1 : 0)
|
|
472
|
+
- (scores.boundedEditSignal ? 3 : 0)
|
|
473
|
+
- (scores.failureSignal ? 3 : 0)
|
|
474
|
+
- (scores.blastRadius * 4)
|
|
475
|
+
),
|
|
476
|
+
'find-cause': (
|
|
477
|
+
(scores.investigationNeed * 4)
|
|
478
|
+
+ (scores.failureSignal ? 3 : 0)
|
|
479
|
+
+ (scores.debugSignal ? 2 : 0)
|
|
480
|
+
- (scores.blastRadius >= 3 ? 1 : 0)
|
|
481
|
+
),
|
|
482
|
+
'shared-edit': (
|
|
483
|
+
(scores.sharedRisk ? 8 : 0)
|
|
484
|
+
+ (scores.editCertainty * 1)
|
|
485
|
+
+ (scores.buildSignal ? 1 : 0)
|
|
486
|
+
- (scores.impactSignal ? 2 : 0)
|
|
487
|
+
),
|
|
488
|
+
'map-impact': (
|
|
489
|
+
(scores.sharedRisk ? 7 : 0)
|
|
490
|
+
+ (scores.impactSignal ? 5 : 0)
|
|
491
|
+
+ (scores.ambiguity * 2)
|
|
492
|
+
+ scores.investigationNeed
|
|
493
|
+
),
|
|
494
|
+
'review-release': (
|
|
495
|
+
(explicitReviewLead ? 10 : 0)
|
|
496
|
+
+ (scores.reviewSignal ? 3 : 0)
|
|
497
|
+
- (scores.implementSignal ? 5 : 0)
|
|
498
|
+
),
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
return Object.entries(modeScores)
|
|
502
|
+
.map(([mode, score]) => ({ mode, score }))
|
|
503
|
+
.sort((a, b) => b.score - a.score || executionModeRank(a.mode) - executionModeRank(b.mode));
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
function applySafeUpwardBias(candidates = [], fallbackMode = 'local-build') {
|
|
507
|
+
const [topCandidate, competingCandidate] = candidates;
|
|
508
|
+
if (!topCandidate) {
|
|
509
|
+
return fallbackMode;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
if (!competingCandidate) {
|
|
513
|
+
return topCandidate.mode;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
const scoreGap = Number(topCandidate.score ?? 0) - Number(competingCandidate.score ?? 0);
|
|
517
|
+
const rankGap = executionModeRank(competingCandidate.mode) - executionModeRank(topCandidate.mode);
|
|
518
|
+
if (scoreGap <= 1 && rankGap === 1) {
|
|
519
|
+
return competingCandidate.mode;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
return topCandidate.mode;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
function executionModeRank(mode = '') {
|
|
526
|
+
const orderedModes = [
|
|
527
|
+
'tiny-fix',
|
|
528
|
+
'local-fix',
|
|
529
|
+
'local-build',
|
|
530
|
+
'find-cause',
|
|
531
|
+
'shared-edit',
|
|
532
|
+
'map-impact',
|
|
533
|
+
'review-release',
|
|
534
|
+
];
|
|
535
|
+
|
|
536
|
+
const index = orderedModes.indexOf(mode);
|
|
537
|
+
return index >= 0 ? index : orderedModes.length;
|
|
385
538
|
}
|
|
386
539
|
|
|
387
540
|
function buildExecutionContract(executionMode = null) {
|
|
@@ -453,6 +606,7 @@ function buildExecutionContract(executionMode = null) {
|
|
|
453
606
|
function buildApproachSelectorResult({
|
|
454
607
|
executionMode = null,
|
|
455
608
|
executionScores = null,
|
|
609
|
+
executionCandidates = null,
|
|
456
610
|
} = {}) {
|
|
457
611
|
if (!executionMode) {
|
|
458
612
|
return null;
|
|
@@ -501,6 +655,14 @@ function buildApproachSelectorResult({
|
|
|
501
655
|
contextPolicy: selectedPolicy.contextPolicy,
|
|
502
656
|
verificationPolicy: executionContract?.verificationPolicy ?? null,
|
|
503
657
|
completionRule: executionContract?.completionRule ?? null,
|
|
658
|
+
competingMode: executionCandidates?.[1]?.mode ?? null,
|
|
659
|
+
competingScoreGap: executionCandidates?.length >= 2
|
|
660
|
+
? Number(executionCandidates[0]?.score ?? 0) - Number(executionCandidates[1]?.score ?? 0)
|
|
661
|
+
: null,
|
|
662
|
+
candidateModes: (executionCandidates ?? []).slice(0, 3).map((entry) => ({
|
|
663
|
+
mode: entry.mode,
|
|
664
|
+
score: entry.score,
|
|
665
|
+
})),
|
|
504
666
|
};
|
|
505
667
|
}
|
|
506
668
|
|
|
@@ -588,6 +750,8 @@ function buildContinuationState({
|
|
|
588
750
|
repeatCount: reasons.length > 0 ? 1 : 0,
|
|
589
751
|
stuckRisk: null,
|
|
590
752
|
rescueMode: null,
|
|
753
|
+
wideningBlocked: false,
|
|
754
|
+
milestonePriority: reasons.length > 0 ? 'normal' : null,
|
|
591
755
|
};
|
|
592
756
|
}
|
|
593
757
|
|
|
@@ -749,7 +913,7 @@ function deriveIntentMode({ promptText = '', commandText = '', targetFile = null
|
|
|
749
913
|
}
|
|
750
914
|
|
|
751
915
|
if (concreteTask) {
|
|
752
|
-
if (/\b(bug|debug|error|crash|broken|failing|stack trace|triage|fix|
|
|
916
|
+
if (/\b(bug|debug|error|crash|broken|failing|stack trace|triage|fix|timeout)\b/.test(lower)) {
|
|
753
917
|
return 'debug-specific';
|
|
754
918
|
}
|
|
755
919
|
if (/\b(review|audit|diff|pr feedback|code review|kiem tra|soat)\b/.test(raw)) {
|