@ngockhoale/ukit 1.4.0 → 1.4.2
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 +24 -0
- package/package.json +1 -1
- package/src/bug/triageBug.js +1 -33
- package/src/cli/commands/install.js +5 -10
- package/src/context/detectProjectContext.js +3 -24
- package/src/core/compact/index.js +19 -27
- package/src/core/ensureGitignore.js +1 -1
- package/src/core/fileOps.js +41 -2
- package/src/core/memory/hygiene.js +17 -1
- package/src/core/memory/store.js +14 -36
- package/src/core/metadata.js +5 -5
- package/src/core/output/index.js +20 -20
- package/src/core/packageManager.js +51 -0
- package/src/core/router/router.js +22 -6
- package/src/core/runInstallPipeline.js +1 -36
- package/src/core/runtimeConfig.js +71 -3
- package/src/core/token/index.js +21 -1
- package/src/core/uninstall.js +15 -38
- package/src/index/buildIndex.js +217 -49
- package/src/index/gitHooks.js +32 -7
- package/src/index/impactContext.js +16 -6
- package/src/index/importResolution.js +105 -28
- package/src/index/paths.js +29 -0
- package/src/index/queryIndex.js +20 -35
- package/src/index/relatedTests.js +15 -2
- package/src/index/routeCatalog.js +1 -1
- package/src/index/taskRouting.js +438 -18
- package/src/index/verificationPlan.js +2 -36
- package/templates/.claude/hooks/reinject-context.sh +2 -0
- package/templates/.claude/hooks/session-start.md +2 -0
- package/templates/.claude/hooks/skill-router.sh +657 -15
- package/templates/.claude/ukit/index/route-catalog.mjs +1 -1
- package/templates/.claude/ukit/index/route-task.mjs +475 -5
- package/templates/.claude/ukit/runtime/reinject-context.mjs +120 -3
- package/templates/.codex/README.md +8 -1
- package/templates/.codex/settings.json +53 -0
- package/templates/AGENTS.md +3 -0
- package/templates/CLAUDE.md +5 -1
- package/templates/ukit/README.md +1 -1
- package/templates/ukit/storage/config.json +61 -2
|
@@ -66,7 +66,7 @@ export const ROUTE_CATALOG = [
|
|
|
66
66
|
{
|
|
67
67
|
id: 'postgres',
|
|
68
68
|
path: '.claude/skills/postgres/SKILL.md',
|
|
69
|
-
order: 4,
|
|
69
|
+
order: 4.5,
|
|
70
70
|
signals: [
|
|
71
71
|
{ type: 'prompt', regex: /\b(sql|postgres|postgresql|migration|schema|table|view|index|trigger|function|stored procedure|materialized view|query plan|explain)\b/i, score: 5 },
|
|
72
72
|
{ type: 'command', regex: /\b(psql|prisma|drizzle|knex|sequelize|typeorm)\b/i, score: 4 },
|
|
@@ -138,12 +138,23 @@ async function main() {
|
|
|
138
138
|
requestKey,
|
|
139
139
|
});
|
|
140
140
|
if (cachedRouteState) {
|
|
141
|
+
const rescuedRouteSummary = cachedRouteState.routeSummary
|
|
142
|
+
? {
|
|
143
|
+
...cachedRouteState.routeSummary,
|
|
144
|
+
continuationState: advanceContinuationState(
|
|
145
|
+
cachedRouteState.routeSummary.continuationState ?? null,
|
|
146
|
+
cachedRouteState.routeSummary.continuationState ?? null,
|
|
147
|
+
),
|
|
148
|
+
}
|
|
149
|
+
: null;
|
|
141
150
|
const sharedState = {
|
|
142
151
|
...cachedRouteState,
|
|
143
152
|
source: 'task-route',
|
|
144
153
|
ts: Date.now(),
|
|
145
154
|
requestKey,
|
|
155
|
+
routeSummary: rescuedRouteSummary,
|
|
146
156
|
};
|
|
157
|
+
sharedState.fingerprint = buildRouteStateFingerprint(sharedState);
|
|
147
158
|
await writeJson(sharedStatePath, sharedState);
|
|
148
159
|
printRouteState(sharedState);
|
|
149
160
|
return;
|
|
@@ -166,6 +177,7 @@ async function main() {
|
|
|
166
177
|
useIndexedContext,
|
|
167
178
|
previousContextSnapshot,
|
|
168
179
|
recentOutputSnapshot,
|
|
180
|
+
previousRouteSummary: previousState?.routeSummary ?? null,
|
|
169
181
|
});
|
|
170
182
|
await seedHelperCaches({
|
|
171
183
|
rootDir,
|
|
@@ -255,6 +267,21 @@ async function prepareTaskRoute({
|
|
|
255
267
|
selectedIds,
|
|
256
268
|
targetFile: normalizedTarget,
|
|
257
269
|
});
|
|
270
|
+
const executionScores = deriveExecutionScores({
|
|
271
|
+
promptText: normalizedPrompt,
|
|
272
|
+
commandText: normalizedCommand,
|
|
273
|
+
targetFile: normalizedTarget,
|
|
274
|
+
intentMode,
|
|
275
|
+
taskType: inferredTaskType,
|
|
276
|
+
});
|
|
277
|
+
const executionMode = deriveExecutionMode({
|
|
278
|
+
promptText: normalizedPrompt,
|
|
279
|
+
commandText: normalizedCommand,
|
|
280
|
+
targetFile: normalizedTarget,
|
|
281
|
+
intentMode,
|
|
282
|
+
taskType: inferredTaskType,
|
|
283
|
+
executionScores,
|
|
284
|
+
});
|
|
258
285
|
const preservedPrompt = normalizedPrompt || String(lastExplicitUserPromptText || '').trim();
|
|
259
286
|
|
|
260
287
|
return {
|
|
@@ -269,6 +296,8 @@ async function prepareTaskRoute({
|
|
|
269
296
|
contextIntent,
|
|
270
297
|
taskType: inferredTaskType,
|
|
271
298
|
intentMode,
|
|
299
|
+
executionScores,
|
|
300
|
+
executionMode,
|
|
272
301
|
},
|
|
273
302
|
};
|
|
274
303
|
}
|
|
@@ -283,6 +312,7 @@ async function finalizeTaskRoute({
|
|
|
283
312
|
useIndexedContext = true,
|
|
284
313
|
previousContextSnapshot = null,
|
|
285
314
|
recentOutputSnapshot = null,
|
|
315
|
+
previousRouteSummary = null,
|
|
286
316
|
} = {}) {
|
|
287
317
|
const absoluteRoot = path.resolve(rootDir);
|
|
288
318
|
const activeSkills = preparedRoute?.activeSkills ?? [];
|
|
@@ -347,10 +377,16 @@ async function finalizeTaskRoute({
|
|
|
347
377
|
verificationRecommendation,
|
|
348
378
|
nextAction,
|
|
349
379
|
});
|
|
380
|
+
routeSummary.continuationState = advanceContinuationState(
|
|
381
|
+
routeSummary.continuationState,
|
|
382
|
+
previousRouteSummary?.continuationState ?? null,
|
|
383
|
+
);
|
|
384
|
+
const approachSelector = routeSummary?.approachSelector ?? null;
|
|
350
385
|
|
|
351
386
|
return {
|
|
352
387
|
activeSkills,
|
|
353
388
|
routingContext,
|
|
389
|
+
approachSelector,
|
|
354
390
|
previousContext: previousContextSnapshot,
|
|
355
391
|
recentOutput: recentOutputSnapshot,
|
|
356
392
|
contextRecommendation,
|
|
@@ -445,7 +481,11 @@ function formatDisplayNextAction(routeSummary = null) {
|
|
|
445
481
|
}
|
|
446
482
|
|
|
447
483
|
const nextActionType = String(routeSummary.nextActionType ?? '').trim();
|
|
448
|
-
if (
|
|
484
|
+
if (
|
|
485
|
+
!nextActionType
|
|
486
|
+
|| nextActionType === 'read-skill-instructions'
|
|
487
|
+
|| nextActionType === 'pull-indexed-context'
|
|
488
|
+
) {
|
|
449
489
|
return '';
|
|
450
490
|
}
|
|
451
491
|
|
|
@@ -492,6 +532,10 @@ function formatDisplayHelperHint(routeSummary = null, compactSummary = '') {
|
|
|
492
532
|
return '';
|
|
493
533
|
}
|
|
494
534
|
|
|
535
|
+
if (String(routeSummary.nextActionType ?? '').trim() === 'pull-indexed-context') {
|
|
536
|
+
return '';
|
|
537
|
+
}
|
|
538
|
+
|
|
495
539
|
let helperHint = String(routeSummary.helperHint ?? '').trim().replace(/\s+/g, ' ');
|
|
496
540
|
if (!helperHint) {
|
|
497
541
|
return '';
|
|
@@ -671,6 +715,10 @@ function shouldKeepRouteEntryForIntent(entry, intentMode) {
|
|
|
671
715
|
return false;
|
|
672
716
|
}
|
|
673
717
|
|
|
718
|
+
if (entry.id === 'code-review' && intentMode === 'implement-specific') {
|
|
719
|
+
return false;
|
|
720
|
+
}
|
|
721
|
+
|
|
674
722
|
return true;
|
|
675
723
|
}
|
|
676
724
|
|
|
@@ -710,6 +758,10 @@ function deriveSkillPriorityBoost(skillId, routeSignals = {}) {
|
|
|
710
758
|
routeSignals.commandRawText ?? '',
|
|
711
759
|
routeSignals.commandNormalizedText ?? '',
|
|
712
760
|
].join('\n');
|
|
761
|
+
const rawPromptSignals = [
|
|
762
|
+
routeSignals.promptRawText ?? '',
|
|
763
|
+
routeSignals.commandRawText ?? '',
|
|
764
|
+
].join('\n');
|
|
713
765
|
|
|
714
766
|
if (
|
|
715
767
|
skillId === 'testing-quality'
|
|
@@ -718,6 +770,14 @@ function deriveSkillPriorityBoost(skillId, routeSignals = {}) {
|
|
|
718
770
|
return 1;
|
|
719
771
|
}
|
|
720
772
|
|
|
773
|
+
if (
|
|
774
|
+
skillId === 'code-review'
|
|
775
|
+
&& /\b(implement|build|create|add|ship|deliver|refactor|integrate|integration|scaffold|feature|update|change|modify|inject|apply)\b/.test(rawPromptSignals)
|
|
776
|
+
&& !/\b(review|audit|diff|pr feedback|code review|kiem tra|soat)\b/.test(rawPromptSignals)
|
|
777
|
+
) {
|
|
778
|
+
return -4;
|
|
779
|
+
}
|
|
780
|
+
|
|
721
781
|
return 0;
|
|
722
782
|
}
|
|
723
783
|
|
|
@@ -771,10 +831,10 @@ function deriveIntentMode({ promptText = '', commandText = '', targetFile = null
|
|
|
771
831
|
if (/\b(bug|debug|error|crash|broken|failing|stack trace|triage|fix|login|timeout)\b/.test(lower)) {
|
|
772
832
|
return 'debug-specific';
|
|
773
833
|
}
|
|
774
|
-
if (/\b(review|audit|diff|pr feedback|code review|kiem tra|soat)\b/.test(
|
|
834
|
+
if (/\b(review|audit|diff|pr feedback|code review|kiem tra|soat)\b/.test(raw)) {
|
|
775
835
|
return 'review-specific';
|
|
776
836
|
}
|
|
777
|
-
if (/\b(implement|build|create|add|ship|deliver|refactor|integrate|integration|scaffold|feature)\b/.test(
|
|
837
|
+
if (/\b(implement|build|create|add|ship|deliver|refactor|integrate|integration|scaffold|feature|update|change|modify|inject|apply)\b/.test(raw)) {
|
|
778
838
|
return 'implement-specific';
|
|
779
839
|
}
|
|
780
840
|
}
|
|
@@ -806,7 +866,7 @@ function hasConcreteTaskSignal(lower, raw, targetFile, { taskQueueNext = false }
|
|
|
806
866
|
return true;
|
|
807
867
|
}
|
|
808
868
|
|
|
809
|
-
return /\b(bug|debug|error|crash|broken|failing|stack trace|triage|fix|implement|build|create|add|ship|deliver|refactor|integrate|integration|scaffold|feature|review|audit|diff|pr feedback|code review|auth|login|api|endpoint|test|spec)\b/.test(lower)
|
|
869
|
+
return /\b(bug|debug|error|crash|broken|failing|stack trace|triage|fix|implement|build|create|add|ship|deliver|refactor|integrate|integration|scaffold|feature|update|change|modify|inject|apply|review|audit|diff|pr feedback|code review|auth|login|api|endpoint|test|spec)\b/.test(lower)
|
|
810
870
|
|| /\b(sửa|fix|lỗi|bug|debug|implement|cài|thêm|review|kiểm tra|soát|đăng nhập)\b/.test(raw);
|
|
811
871
|
}
|
|
812
872
|
|
|
@@ -1225,6 +1285,21 @@ function buildRouteSummary({
|
|
|
1225
1285
|
const compactHelperLane = nextAction?.type === 'pull-indexed-context'
|
|
1226
1286
|
&& typeof contextRecommendation?.command === 'string'
|
|
1227
1287
|
&& contextRecommendation.command.trim();
|
|
1288
|
+
const executionMode = routingContext.executionMode ?? null;
|
|
1289
|
+
const executionScores = routingContext.executionScores ?? null;
|
|
1290
|
+
const approachSelector = buildApproachSelectorResult({
|
|
1291
|
+
executionMode,
|
|
1292
|
+
executionScores,
|
|
1293
|
+
});
|
|
1294
|
+
const executionContract = buildExecutionContract(executionMode);
|
|
1295
|
+
const completionState = buildCompletionState({
|
|
1296
|
+
executionMode,
|
|
1297
|
+
verificationRecommendation,
|
|
1298
|
+
});
|
|
1299
|
+
const continuationState = buildContinuationState({
|
|
1300
|
+
nextActionType: nextAction?.type ?? null,
|
|
1301
|
+
completionState,
|
|
1302
|
+
});
|
|
1228
1303
|
const helperHint = compactHelperHint(
|
|
1229
1304
|
compactHelperLane
|
|
1230
1305
|
? contextRecommendation?.command
|
|
@@ -1243,7 +1318,6 @@ function buildRouteSummary({
|
|
|
1243
1318
|
editGuardHint ? `editGuard=${editGuardHint}` : null,
|
|
1244
1319
|
delegationRecommendation?.hint ? `delegate=${delegationRecommendation.hint}` : null,
|
|
1245
1320
|
policyMode ? `policy=${policyMode}` : null,
|
|
1246
|
-
contextMode ? `mode=${contextMode}` : null,
|
|
1247
1321
|
].filter(Boolean).join(' | ');
|
|
1248
1322
|
|
|
1249
1323
|
return {
|
|
@@ -1252,6 +1326,12 @@ function buildRouteSummary({
|
|
|
1252
1326
|
preferredOrder,
|
|
1253
1327
|
policyMode,
|
|
1254
1328
|
editGuardHint,
|
|
1329
|
+
executionMode,
|
|
1330
|
+
executionScores,
|
|
1331
|
+
approachSelector,
|
|
1332
|
+
executionContract,
|
|
1333
|
+
completionState,
|
|
1334
|
+
continuationState,
|
|
1255
1335
|
intentMode: routingContext.intentMode ?? null,
|
|
1256
1336
|
delegateHint: delegationRecommendation?.hint ?? null,
|
|
1257
1337
|
nextActionType: nextAction?.type ?? null,
|
|
@@ -1268,6 +1348,375 @@ function deriveContextMode(taskType) {
|
|
|
1268
1348
|
return null;
|
|
1269
1349
|
}
|
|
1270
1350
|
|
|
1351
|
+
function deriveExecutionScores({
|
|
1352
|
+
promptText = '',
|
|
1353
|
+
commandText = '',
|
|
1354
|
+
targetFile = null,
|
|
1355
|
+
intentMode = null,
|
|
1356
|
+
taskType = null,
|
|
1357
|
+
} = {}) {
|
|
1358
|
+
const raw = `${promptText ?? ''}\n${commandText ?? ''}`.toLowerCase();
|
|
1359
|
+
const sharedRisk = isSharedImpactFile(targetFile);
|
|
1360
|
+
const directTransformSignal = /\b(change|replace|set|rename|convert|swap)\b/.test(raw) || /\bchange\s+.+\s+to\s+.+\b/.test(raw);
|
|
1361
|
+
const smallFixSignal = /\b(adjust|tweak|patch|fix|modify|update|apply)\b/.test(raw);
|
|
1362
|
+
const buildSignal = /\b(build|create|add|implement|feature)\b/.test(raw);
|
|
1363
|
+
const debugSignal = intentMode === 'debug-specific' || /\b(root cause|debug|triage|flaky|investigate|why)\b/.test(raw);
|
|
1364
|
+
const reviewSignal = intentMode === 'review-specific' || /\b(review|audit|verify|release readiness)\b/.test(raw);
|
|
1365
|
+
|
|
1366
|
+
let editCertainty = 0;
|
|
1367
|
+
if (directTransformSignal) {
|
|
1368
|
+
editCertainty = 3;
|
|
1369
|
+
} else if (smallFixSignal) {
|
|
1370
|
+
editCertainty = 2;
|
|
1371
|
+
} else if (buildSignal) {
|
|
1372
|
+
editCertainty = 1;
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
let investigationNeed = 0;
|
|
1376
|
+
if (debugSignal) {
|
|
1377
|
+
investigationNeed = 3;
|
|
1378
|
+
} else if (/\b(failing|broken|error|crash|timeout)\b/.test(raw)) {
|
|
1379
|
+
investigationNeed = 2;
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
let blastRadius = 0;
|
|
1383
|
+
if (sharedRisk) {
|
|
1384
|
+
blastRadius = 3;
|
|
1385
|
+
} else if (taskType === 'non-trivial' || taskType === 'shared-simple') {
|
|
1386
|
+
blastRadius = 2;
|
|
1387
|
+
} else if (!targetFile) {
|
|
1388
|
+
blastRadius = 1;
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
let verificationBurden = 1;
|
|
1392
|
+
if (reviewSignal || sharedRisk) {
|
|
1393
|
+
verificationBurden = 3;
|
|
1394
|
+
} else if (debugSignal || taskType === 'non-trivial') {
|
|
1395
|
+
verificationBurden = 2;
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
let ambiguity = 0;
|
|
1399
|
+
if (!targetFile) {
|
|
1400
|
+
ambiguity = 2;
|
|
1401
|
+
} else if (buildSignal && !directTransformSignal && !smallFixSignal) {
|
|
1402
|
+
ambiguity = 1;
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
return {
|
|
1406
|
+
editCertainty,
|
|
1407
|
+
investigationNeed,
|
|
1408
|
+
blastRadius,
|
|
1409
|
+
verificationBurden,
|
|
1410
|
+
ambiguity,
|
|
1411
|
+
};
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
function deriveExecutionMode({
|
|
1415
|
+
promptText = '',
|
|
1416
|
+
commandText = '',
|
|
1417
|
+
targetFile = null,
|
|
1418
|
+
intentMode = null,
|
|
1419
|
+
executionScores = {},
|
|
1420
|
+
} = {}) {
|
|
1421
|
+
const raw = `${promptText ?? ''}\n${commandText ?? ''}`.toLowerCase();
|
|
1422
|
+
const scores = executionScores;
|
|
1423
|
+
const explicitReviewLead = /\b(review this|audit this|review\b.*\brelease readiness|verify\b.*\brelease readiness)\b/.test(raw);
|
|
1424
|
+
|
|
1425
|
+
if (intentMode === 'review-specific' || explicitReviewLead) {
|
|
1426
|
+
return 'review-release';
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
if (scores.blastRadius >= 3 && (scores.ambiguity >= 2 || scores.investigationNeed >= 2)) {
|
|
1430
|
+
return 'map-impact';
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
if (scores.blastRadius >= 3 || isSharedImpactFile(targetFile)) {
|
|
1434
|
+
return 'shared-edit';
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
if (scores.investigationNeed >= 3) {
|
|
1438
|
+
return 'find-cause';
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
if (
|
|
1442
|
+
scores.editCertainty >= 3
|
|
1443
|
+
&& scores.ambiguity === 0
|
|
1444
|
+
&& scores.blastRadius === 0
|
|
1445
|
+
&& scores.verificationBurden <= 1
|
|
1446
|
+
) {
|
|
1447
|
+
return 'tiny-fix';
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
if (
|
|
1451
|
+
/\b(build|create|add|implement|feature|summary card)\b/.test(raw)
|
|
1452
|
+
&& scores.investigationNeed === 0
|
|
1453
|
+
&& scores.blastRadius < 3
|
|
1454
|
+
) {
|
|
1455
|
+
return 'local-build';
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
if (scores.editCertainty >= 2 && scores.investigationNeed === 0 && scores.blastRadius === 0) {
|
|
1459
|
+
return 'local-fix';
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
return 'local-build';
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
function buildExecutionContract(executionMode = null) {
|
|
1466
|
+
if (!executionMode) {
|
|
1467
|
+
return null;
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
const contracts = {
|
|
1471
|
+
'tiny-fix': {
|
|
1472
|
+
maxReadPasses: 0,
|
|
1473
|
+
maxContextPulls: 0,
|
|
1474
|
+
verificationPolicy: 'minimal-or-targeted',
|
|
1475
|
+
completionRule: 'never-claim-done-without-write',
|
|
1476
|
+
delegationPolicy: 'disallow',
|
|
1477
|
+
completionEvidence: ['write-evidence'],
|
|
1478
|
+
},
|
|
1479
|
+
'local-fix': {
|
|
1480
|
+
maxReadPasses: 1,
|
|
1481
|
+
maxContextPulls: 1,
|
|
1482
|
+
verificationPolicy: 'targeted-if-covered',
|
|
1483
|
+
completionRule: 'require-write',
|
|
1484
|
+
delegationPolicy: 'disallow',
|
|
1485
|
+
completionEvidence: ['write-evidence'],
|
|
1486
|
+
},
|
|
1487
|
+
'local-build': {
|
|
1488
|
+
maxReadPasses: 2,
|
|
1489
|
+
maxContextPulls: 1,
|
|
1490
|
+
verificationPolicy: 'targeted-if-covered',
|
|
1491
|
+
completionRule: 'require-write',
|
|
1492
|
+
delegationPolicy: 'disallow-by-default',
|
|
1493
|
+
completionEvidence: ['write-evidence'],
|
|
1494
|
+
},
|
|
1495
|
+
'find-cause': {
|
|
1496
|
+
maxReadPassesBeforeReassess: 3,
|
|
1497
|
+
verificationPolicy: 'root-cause-then-targeted',
|
|
1498
|
+
completionRule: 'never-claim-fixed-without-write-and-verification',
|
|
1499
|
+
delegationPolicy: 'allow-specialized-debug-lane',
|
|
1500
|
+
completionEvidence: ['write-evidence', 'verification-evidence'],
|
|
1501
|
+
},
|
|
1502
|
+
'shared-edit': {
|
|
1503
|
+
maxReadPasses: 2,
|
|
1504
|
+
maxContextPulls: 2,
|
|
1505
|
+
verificationPolicy: 'targeted-then-widen-on-risk',
|
|
1506
|
+
completionRule: 'require-write-and-verification',
|
|
1507
|
+
delegationPolicy: 'allow-qualified-sidecar',
|
|
1508
|
+
completionEvidence: ['write-evidence', 'verification-evidence'],
|
|
1509
|
+
mirrorConsistencyRequired: true,
|
|
1510
|
+
},
|
|
1511
|
+
'map-impact': {
|
|
1512
|
+
maxReadPasses: 3,
|
|
1513
|
+
maxContextPulls: 3,
|
|
1514
|
+
verificationPolicy: 'impact-first-then-targeted-then-widen-on-risk',
|
|
1515
|
+
completionRule: 'require-impact-evidence-before-edit-claim',
|
|
1516
|
+
delegationPolicy: 'allow-impact-sidecar',
|
|
1517
|
+
completionEvidence: ['impact-evidence', 'write-evidence', 'verification-evidence'],
|
|
1518
|
+
mirrorConsistencyRequired: true,
|
|
1519
|
+
},
|
|
1520
|
+
'review-release': {
|
|
1521
|
+
verificationPolicy: 'evidence-first',
|
|
1522
|
+
completionRule: 'report-findings-not-implementation',
|
|
1523
|
+
delegationPolicy: 'allow-review-sidecar',
|
|
1524
|
+
completionEvidence: ['verification-evidence'],
|
|
1525
|
+
},
|
|
1526
|
+
};
|
|
1527
|
+
|
|
1528
|
+
return contracts[executionMode] ? { ...contracts[executionMode] } : null;
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
function buildApproachSelectorResult({
|
|
1532
|
+
executionMode = null,
|
|
1533
|
+
executionScores = null,
|
|
1534
|
+
} = {}) {
|
|
1535
|
+
if (!executionMode) {
|
|
1536
|
+
return null;
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
const executionContract = buildExecutionContract(executionMode);
|
|
1540
|
+
const policyByMode = {
|
|
1541
|
+
'tiny-fix': {
|
|
1542
|
+
riskLevel: 'minimal',
|
|
1543
|
+
contextPolicy: 'confirm-target-only',
|
|
1544
|
+
},
|
|
1545
|
+
'local-fix': {
|
|
1546
|
+
riskLevel: 'local',
|
|
1547
|
+
contextPolicy: 'bounded-local',
|
|
1548
|
+
},
|
|
1549
|
+
'local-build': {
|
|
1550
|
+
riskLevel: 'local',
|
|
1551
|
+
contextPolicy: 'bounded-with-related-files',
|
|
1552
|
+
},
|
|
1553
|
+
'find-cause': {
|
|
1554
|
+
riskLevel: 'investigation',
|
|
1555
|
+
contextPolicy: 'trace-then-bounded-context',
|
|
1556
|
+
},
|
|
1557
|
+
'shared-edit': {
|
|
1558
|
+
riskLevel: 'shared',
|
|
1559
|
+
contextPolicy: 'bounded-with-related-tests',
|
|
1560
|
+
},
|
|
1561
|
+
'map-impact': {
|
|
1562
|
+
riskLevel: 'wide',
|
|
1563
|
+
contextPolicy: 'impact-map-first',
|
|
1564
|
+
},
|
|
1565
|
+
'review-release': {
|
|
1566
|
+
riskLevel: 'release',
|
|
1567
|
+
contextPolicy: 'evidence-review-only',
|
|
1568
|
+
},
|
|
1569
|
+
};
|
|
1570
|
+
const selectedPolicy = policyByMode[executionMode] ?? {
|
|
1571
|
+
riskLevel: 'local',
|
|
1572
|
+
contextPolicy: 'bounded-local',
|
|
1573
|
+
};
|
|
1574
|
+
|
|
1575
|
+
return {
|
|
1576
|
+
executionMode,
|
|
1577
|
+
executionScores: executionScores ? { ...executionScores } : null,
|
|
1578
|
+
riskLevel: selectedPolicy.riskLevel,
|
|
1579
|
+
contextPolicy: selectedPolicy.contextPolicy,
|
|
1580
|
+
verificationPolicy: executionContract?.verificationPolicy ?? null,
|
|
1581
|
+
completionRule: executionContract?.completionRule ?? null,
|
|
1582
|
+
};
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
function buildCompletionState({ executionMode = null, verificationRecommendation = null } = {}) {
|
|
1586
|
+
if (!executionMode) {
|
|
1587
|
+
return null;
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
const contract = buildExecutionContract(executionMode);
|
|
1591
|
+
const missingEvidence = [...(contract?.completionEvidence ?? [])];
|
|
1592
|
+
const requiresVerification = missingEvidence.includes('verification-evidence');
|
|
1593
|
+
if (
|
|
1594
|
+
requiresVerification
|
|
1595
|
+
&& verificationRecommendation
|
|
1596
|
+
&& !(verificationRecommendation.commands?.length || verificationRecommendation.fallbackCommands?.length)
|
|
1597
|
+
) {
|
|
1598
|
+
missingEvidence.push('verification-plan');
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
let reason = 'completion evidence is still required';
|
|
1602
|
+
if (['tiny-fix', 'local-fix', 'local-build', 'shared-edit'].includes(executionMode)) {
|
|
1603
|
+
reason = 'implement request has not produced an edit yet';
|
|
1604
|
+
} else if (executionMode === 'review-release') {
|
|
1605
|
+
reason = 'review/release evidence is still required before final claim';
|
|
1606
|
+
} else if (executionMode === 'map-impact') {
|
|
1607
|
+
reason = 'impact evidence is still required before safe completion claim';
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
return {
|
|
1611
|
+
claimAllowed: false,
|
|
1612
|
+
missingEvidence,
|
|
1613
|
+
reason,
|
|
1614
|
+
};
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
function buildContinuationState({
|
|
1618
|
+
nextActionType = null,
|
|
1619
|
+
completionState = null,
|
|
1620
|
+
} = {}) {
|
|
1621
|
+
const reasons = [];
|
|
1622
|
+
const missingEvidence = unique(completionState?.missingEvidence ?? []);
|
|
1623
|
+
|
|
1624
|
+
if (nextActionType === 'pull-indexed-context') {
|
|
1625
|
+
reasons.push('pending-bounded-context');
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1628
|
+
if (nextActionType === 'read-skill-instructions') {
|
|
1629
|
+
reasons.push('pending-skill-read');
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
if (missingEvidence.includes('write-evidence')) {
|
|
1633
|
+
reasons.push('missing-write-evidence');
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
if (missingEvidence.includes('verification-evidence') || missingEvidence.includes('verification-plan')) {
|
|
1637
|
+
reasons.push('missing-verification-evidence');
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
if (missingEvidence.includes('impact-evidence')) {
|
|
1641
|
+
reasons.push('missing-impact-evidence');
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1644
|
+
const nextMilestone = reasons.includes('pending-bounded-context')
|
|
1645
|
+
? 'complete-bounded-context-then-continue'
|
|
1646
|
+
: (
|
|
1647
|
+
reasons.includes('missing-write-evidence')
|
|
1648
|
+
? 'produce-write-evidence'
|
|
1649
|
+
: (
|
|
1650
|
+
reasons.includes('missing-verification-evidence')
|
|
1651
|
+
? 'produce-verification-evidence'
|
|
1652
|
+
: (
|
|
1653
|
+
reasons.includes('missing-impact-evidence')
|
|
1654
|
+
? 'produce-impact-evidence'
|
|
1655
|
+
: null
|
|
1656
|
+
)
|
|
1657
|
+
)
|
|
1658
|
+
);
|
|
1659
|
+
|
|
1660
|
+
return {
|
|
1661
|
+
required: reasons.length > 0,
|
|
1662
|
+
reasons,
|
|
1663
|
+
doneLanguageBlocked: reasons.length > 0,
|
|
1664
|
+
stopAllowedOnlyFor: reasons.length > 0 ? ['real-blocker'] : [],
|
|
1665
|
+
nextMilestone,
|
|
1666
|
+
repeatCount: reasons.length > 0 ? 1 : 0,
|
|
1667
|
+
stuckRisk: null,
|
|
1668
|
+
rescueMode: null,
|
|
1669
|
+
};
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
function advanceContinuationState(continuationState = null, previousContinuationState = null) {
|
|
1673
|
+
if (!continuationState || typeof continuationState !== 'object') {
|
|
1674
|
+
return continuationState;
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
if (!continuationState.required) {
|
|
1678
|
+
return {
|
|
1679
|
+
...continuationState,
|
|
1680
|
+
repeatCount: 0,
|
|
1681
|
+
stuckRisk: null,
|
|
1682
|
+
rescueMode: null,
|
|
1683
|
+
};
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1686
|
+
const currentReasons = unique(continuationState.reasons ?? []);
|
|
1687
|
+
const previousReasons = unique(previousContinuationState?.reasons ?? []);
|
|
1688
|
+
const sameMilestone = Boolean(
|
|
1689
|
+
previousContinuationState?.required
|
|
1690
|
+
&& continuationState.nextMilestone
|
|
1691
|
+
&& previousContinuationState.nextMilestone === continuationState.nextMilestone
|
|
1692
|
+
&& JSON.stringify(previousReasons) === JSON.stringify(currentReasons)
|
|
1693
|
+
);
|
|
1694
|
+
const repeatCount = sameMilestone
|
|
1695
|
+
? Math.max(1, Number(previousContinuationState?.repeatCount ?? 1) + 1)
|
|
1696
|
+
: 1;
|
|
1697
|
+
const rescueMode = repeatCount >= 2
|
|
1698
|
+
? (
|
|
1699
|
+
currentReasons.includes('pending-bounded-context')
|
|
1700
|
+
? 'finish-current-milestone-before-more-reading'
|
|
1701
|
+
: (
|
|
1702
|
+
currentReasons.includes('missing-write-evidence')
|
|
1703
|
+
? 'finish-write-before-more-analysis'
|
|
1704
|
+
: 'finish-required-milestone-before-widening'
|
|
1705
|
+
)
|
|
1706
|
+
)
|
|
1707
|
+
: null;
|
|
1708
|
+
const stuckRisk = repeatCount >= 3
|
|
1709
|
+
? 'high'
|
|
1710
|
+
: (repeatCount === 2 ? 'elevated' : null);
|
|
1711
|
+
|
|
1712
|
+
return {
|
|
1713
|
+
...continuationState,
|
|
1714
|
+
repeatCount,
|
|
1715
|
+
stuckRisk,
|
|
1716
|
+
rescueMode,
|
|
1717
|
+
};
|
|
1718
|
+
}
|
|
1719
|
+
|
|
1271
1720
|
function deriveExecutionPolicy({
|
|
1272
1721
|
taskType = 'simple',
|
|
1273
1722
|
mode = 'minimal',
|
|
@@ -1687,6 +2136,7 @@ function buildRouteRequestKey({
|
|
|
1687
2136
|
targetFile: routingContext.targetFile ?? '',
|
|
1688
2137
|
contextIntent: routingContext.contextIntent ?? '',
|
|
1689
2138
|
taskType: routingContext.taskType ?? '',
|
|
2139
|
+
executionMode: routingContext.executionMode ?? '',
|
|
1690
2140
|
});
|
|
1691
2141
|
}
|
|
1692
2142
|
|
|
@@ -1704,10 +2154,23 @@ function buildStructuredRouteFingerprintPayload(route = {}) {
|
|
|
1704
2154
|
previousContextIds: unique(route.previousContext?.selectedIds ?? []),
|
|
1705
2155
|
recentOutputLine: route.recentOutput?.line ?? null,
|
|
1706
2156
|
policyMode: routeSummary?.policyMode ?? null,
|
|
2157
|
+
executionMode: routeSummary?.executionMode ?? null,
|
|
2158
|
+
approachRiskLevel: routeSummary?.approachSelector?.riskLevel ?? null,
|
|
2159
|
+
approachContextPolicy: routeSummary?.approachSelector?.contextPolicy ?? null,
|
|
2160
|
+
approachVerificationPolicy: routeSummary?.approachSelector?.verificationPolicy ?? null,
|
|
2161
|
+
approachCompletionRule: routeSummary?.approachSelector?.completionRule ?? null,
|
|
2162
|
+
continuationRequired: routeSummary?.continuationState?.required ?? null,
|
|
2163
|
+
continuationReasons: unique(routeSummary?.continuationState?.reasons ?? []),
|
|
2164
|
+
continuationMilestone: routeSummary?.continuationState?.nextMilestone ?? null,
|
|
2165
|
+
continuationRepeatCount: routeSummary?.continuationState?.repeatCount ?? null,
|
|
2166
|
+
continuationStuckRisk: routeSummary?.continuationState?.stuckRisk ?? null,
|
|
2167
|
+
continuationRescueMode: routeSummary?.continuationState?.rescueMode ?? null,
|
|
1707
2168
|
delegateHint: routeSummary?.delegateHint ?? null,
|
|
1708
2169
|
nextActionType: routeSummary?.nextActionType ?? null,
|
|
1709
2170
|
nextActionCommand: routeSummary?.nextActionCommand ?? null,
|
|
1710
2171
|
helperHint: routeSummary?.helperHint ?? null,
|
|
2172
|
+
completionRule: routeSummary?.executionContract?.completionRule ?? null,
|
|
2173
|
+
completionMissingEvidence: unique(routeSummary?.completionState?.missingEvidence ?? []),
|
|
1711
2174
|
primaryCommands: unique(routeSummary?.primaryCommands ?? []),
|
|
1712
2175
|
fallbackCommands: unique(routeSummary?.fallbackCommands ?? []),
|
|
1713
2176
|
preferredOrder: unique(routeSummary?.preferredOrder ?? []),
|
|
@@ -1784,6 +2247,7 @@ function compactRoutingContext(routingContext = {}) {
|
|
|
1784
2247
|
lastExplicitUserPromptText: routingContext.lastExplicitUserPromptText ?? '',
|
|
1785
2248
|
taskType: routingContext.taskType ?? null,
|
|
1786
2249
|
intentMode: routingContext.intentMode ?? null,
|
|
2250
|
+
executionMode: routingContext.executionMode ?? null,
|
|
1787
2251
|
};
|
|
1788
2252
|
}
|
|
1789
2253
|
|
|
@@ -1846,6 +2310,12 @@ function compactRouteSummary(routeSummary = null) {
|
|
|
1846
2310
|
fallbackCommands: unique(routeSummary.fallbackCommands ?? []).slice(0, 3),
|
|
1847
2311
|
preferredOrder: unique(routeSummary.preferredOrder ?? []).slice(0, 5),
|
|
1848
2312
|
policyMode: routeSummary.policyMode ?? null,
|
|
2313
|
+
executionMode: routeSummary.executionMode ?? null,
|
|
2314
|
+
executionScores: routeSummary.executionScores ?? null,
|
|
2315
|
+
approachSelector: routeSummary.approachSelector ?? null,
|
|
2316
|
+
executionContract: routeSummary.executionContract ?? null,
|
|
2317
|
+
completionState: routeSummary.completionState ?? null,
|
|
2318
|
+
continuationState: routeSummary.continuationState ?? null,
|
|
1849
2319
|
delegateHint: routeSummary.delegateHint ?? null,
|
|
1850
2320
|
nextActionType: routeSummary.nextActionType ?? null,
|
|
1851
2321
|
nextActionCommand: routeSummary.nextActionCommand ?? null,
|