@ngockhoale/ukit 1.3.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,7 +4,31 @@ All notable changes to UKit are documented here.
4
4
 
5
5
  ## Unreleased
6
6
 
7
- ## 1.3.1 - 2026-05-06
7
+ ## 1.4.0 - 2026-05-09
8
+
9
+ ### Added
10
+
11
+ - Added Adaptive Autonomy runtime config (`autonomy`) with three levels: `conservative`, `balanced` (default), and `free-run`.
12
+ - `conservative`: asks before fallback verification and broad/risky escalation; suppresses non-essential delegation except explicit plan/batch execution and small-task maintainer.
13
+ - `balanced`: default behavior unchanged — targeted verification auto-runs, broad risky asks confirmation, delegation follows existing thresholds.
14
+ - `free-run`: auto-runs fallback verification, removes broad verification confirmation for escalation-only, lowers feature/debug delegation thresholds slightly.
15
+ - Added `autonomy.level`, `autonomy.affectVerification`, and `autonomy.affectDelegation` to runtime config defaults and validation.
16
+ - Added LITE/FULL context mode labels to stepBudgets (`trivial`/`simple` = LITE, `sharedSimple`/`nonTrivial` = FULL) for subagent model selection hints.
17
+ - Added `contextMode` (LITE/FULL) to route summary output and `mode=` segment in summary line.
18
+ - Added `autonomyLevel` to routing context and verification plan cache key for autonomy-aware plan reuse.
19
+
20
+ ### Changed
21
+
22
+ - `deriveTaskRoute`, `deriveVerificationPlan`, and `deriveExecutionPolicy` now accept `autonomyLevel` parameter.
23
+ - `deriveDelegationRecommendation` now respects `autonomyLevel`: conservative suppresses non-essential delegation; free-run relaxes bug-debugger and feature-implementer thresholds.
24
+ - Updated `CLAUDE.md`, `.codex/README.md`, and `ukit/README.md` templates with v1.4.0 version wording and Adaptive Autonomy policy.
25
+ - Added Vietnamese `_help` for autonomy config in `config.json` template.
26
+
27
+ ### Tests
28
+
29
+ - Added targeted tests for autonomy validation, conservative/free-run execution policy, and delegation behavior.
30
+
31
+ ## 1.4.0 - 2026-05-06
8
32
 
9
33
  ### Fixed
10
34
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ngockhoale/ukit",
3
- "version": "1.3.1",
3
+ "version": "1.4.0",
4
4
  "description": "Install/update an index-first AI workspace for Claude Code, Antigravity, OpenAI Codex, and OpenCode.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -49,8 +49,13 @@ export function buildDefaultRuntimeConfig(overrides = {}) {
49
49
  const safeOverrides = isPlainObject(overrides) ? overrides : {};
50
50
 
51
51
  return mergeObjects({
52
- version: '1.3.1',
52
+ version: '1.4.0',
53
53
  agent: 'claude-code',
54
+ autonomy: {
55
+ level: 'balanced',
56
+ affectVerification: true,
57
+ affectDelegation: true,
58
+ },
54
59
  compact: {
55
60
  enabled: true,
56
61
  tokenThreshold: 100_000,
@@ -174,9 +179,10 @@ export function buildDefaultRuntimeConfig(overrides = {}) {
174
179
  'summarize-docs-or-keep-detail',
175
180
  ],
176
181
  stepBudgets: {
177
- trivial: { maxSteps: 1, verification: 'skip-unless-risky' },
178
- simple: { maxSteps: 2, verification: 'targeted-if-covered' },
179
- nonTrivial: { maxSteps: 4, verification: 'targeted-then-widen-on-risk' },
182
+ trivial: { maxSteps: 1, verification: 'skip-unless-risky', label: 'LITE' },
183
+ simple: { maxSteps: 2, verification: 'targeted-if-covered', label: 'LITE' },
184
+ sharedSimple: { maxSteps: 3, verification: 'targeted-then-widen-on-risk', label: 'FULL' },
185
+ nonTrivial: { maxSteps: 4, verification: 'targeted-then-widen-on-risk', label: 'FULL' },
180
186
  },
181
187
  },
182
188
  },
@@ -194,6 +200,17 @@ export function validateRuntimeConfig(config) {
194
200
  errors.push('version must be a non-empty string.');
195
201
  }
196
202
 
203
+ const VALID_AUTONOMY_LEVELS = new Set(['conservative', 'balanced', 'free-run']);
204
+ if (!isPlainObject(config.autonomy)) {
205
+ errors.push('autonomy must be an object.');
206
+ } else {
207
+ if (!VALID_AUTONOMY_LEVELS.has(config.autonomy.level)) {
208
+ errors.push(`autonomy.level must be one of: ${[...VALID_AUTONOMY_LEVELS].join(', ')}.`);
209
+ }
210
+ pushBooleanError(errors, config.autonomy.affectVerification, 'autonomy.affectVerification');
211
+ pushBooleanError(errors, config.autonomy.affectDelegation, 'autonomy.affectDelegation');
212
+ }
213
+
197
214
  if (!VALID_AGENTS.has(config.agent)) {
198
215
  errors.push(`agent must be one of: ${[...VALID_AGENTS].join(', ')}.`);
199
216
  }
@@ -17,6 +17,7 @@ export async function deriveTaskRoute({
17
17
  taskType = null,
18
18
  lastExplicitUserPromptText = '',
19
19
  commandNamespace = '.claude',
20
+ autonomyLevel = 'balanced',
20
21
  } = {}) {
21
22
  const absoluteRoot = path.resolve(rootDir);
22
23
  const normalizedPrompt = String(promptText || '').trim();
@@ -79,6 +80,7 @@ export async function deriveTaskRoute({
79
80
  taskType: inferredTaskType,
80
81
  contextResult: enrichedContextResult,
81
82
  skillIds: selectedIds,
83
+ autonomyLevel,
82
84
  })
83
85
  : null;
84
86
 
@@ -109,6 +111,7 @@ export async function deriveTaskRoute({
109
111
  contextIntent,
110
112
  taskType: inferredTaskType,
111
113
  intentMode,
114
+ autonomyLevel,
112
115
  },
113
116
  contextRecommendation,
114
117
  verificationRecommendation,
@@ -125,6 +128,7 @@ export async function deriveTaskRoute({
125
128
  contextIntent,
126
129
  taskType: inferredTaskType,
127
130
  intentMode,
131
+ autonomyLevel,
128
132
  },
129
133
  contextRecommendation,
130
134
  verificationRecommendation,
@@ -140,11 +144,13 @@ export function buildRouteSummary({
140
144
  verificationRecommendation = null,
141
145
  nextAction = null,
142
146
  } = {}) {
147
+ const autonomyLevel = routingContext.autonomyLevel ?? 'balanced';
143
148
  const delegationRecommendation = deriveDelegationRecommendation({
144
149
  activeSkills,
145
150
  routingContext,
146
151
  contextRecommendation,
147
152
  verificationRecommendation,
153
+ autonomyLevel,
148
154
  });
149
155
  const preview = contextRecommendation?.preview ?? {};
150
156
  const primaryTargets = summarizeCompactList(preview.primaryTargets ?? [], 2);
@@ -158,6 +164,8 @@ export function buildRouteSummary({
158
164
  );
159
165
  const policyMode = verificationRecommendation?.executionPolicy?.policyMode ?? null;
160
166
  const editGuardHint = isSharedImpactFile(routingContext.targetFile) ? 'anchor-required' : null;
167
+ const taskType = routingContext.taskType ?? null;
168
+ const contextMode = deriveContextMode(taskType);
161
169
  const compactHelperLane = nextAction?.type === 'pull-indexed-context'
162
170
  && typeof contextRecommendation?.command === 'string'
163
171
  && contextRecommendation.command.trim();
@@ -179,6 +187,7 @@ export function buildRouteSummary({
179
187
  editGuardHint ? `editGuard=${editGuardHint}` : null,
180
188
  delegationRecommendation?.hint ? `delegate=${delegationRecommendation.hint}` : null,
181
189
  policyMode ? `policy=${policyMode}` : null,
190
+ contextMode ? `mode=${contextMode}` : null,
182
191
  ].filter(Boolean).join(' | ');
183
192
 
184
193
  return {
@@ -192,10 +201,17 @@ export function buildRouteSummary({
192
201
  nextActionType: nextAction?.type ?? null,
193
202
  nextActionCommand,
194
203
  helperHint,
204
+ contextMode,
195
205
  line: summaryLine || 'task=unknown',
196
206
  };
197
207
  }
198
208
 
209
+ function deriveContextMode(taskType) {
210
+ if (taskType === 'trivial' || taskType === 'simple') return 'LITE';
211
+ if (taskType === 'non-trivial' || taskType === 'shared-simple') return 'FULL';
212
+ return null;
213
+ }
214
+
199
215
  async function selectActiveSkills({ rootDir, promptText, commandText, targetFile, intentMode = null }) {
200
216
  const routeSignals = {
201
217
  promptRawText: String(promptText || '').toLowerCase(),
@@ -598,6 +614,7 @@ function deriveDelegationRecommendation({
598
614
  routingContext = {},
599
615
  contextRecommendation = null,
600
616
  verificationRecommendation = null,
617
+ autonomyLevel = 'balanced',
601
618
  } = {}) {
602
619
  const skillIds = activeSkills.map((item) => item.id);
603
620
  const lower = `${routingContext.promptText ?? ''}\n${routingContext.commandText ?? ''}`.toLowerCase();
@@ -622,6 +639,21 @@ function deriveDelegationRecommendation({
622
639
  return null;
623
640
  }
624
641
 
642
+ if (autonomyLevel === 'conservative') {
643
+ if (
644
+ skillIds.includes('executing-plans')
645
+ || /\b(execute this plan|follow this plan|implementation plan|rollout plan|controlled batches?|review checkpoints?|batch execution|execute in batches)\b/.test(lower)
646
+ ) {
647
+ return {
648
+ hint: 'subagent-driven-development',
649
+ when,
650
+ reason: 'Explicit plan/batch execution is separable enough for deliberate subagent passes.',
651
+ };
652
+ }
653
+
654
+ return null;
655
+ }
656
+
625
657
  if (
626
658
  skillIds.includes('executing-plans')
627
659
  || /\b(execute this plan|follow this plan|implementation plan|rollout plan|controlled batches?|review checkpoints?|batch execution|execute in batches)\b/.test(lower)
@@ -638,7 +670,8 @@ function deriveDelegationRecommendation({
638
670
  || /\b(debug|error|crash|stack(?: trace)?|failing|flake|flaky|timeout|triage|root cause)\b/.test(lower)
639
671
  || verificationRecommendation?.executionPolicy?.policyMode === 'confirm-then-broad'
640
672
  );
641
- if (noisyDebugLane && (!localizedIndexedLane || !hasRelatedTests || contextBreadth >= 4)) {
673
+ const debugDelegationThreshold = autonomyLevel === 'free-run' ? 3 : 4;
674
+ if (noisyDebugLane && (!localizedIndexedLane || !hasRelatedTests || contextBreadth >= debugDelegationThreshold)) {
642
675
  return {
643
676
  hint: 'bug-debugger',
644
677
  when,
@@ -649,11 +682,15 @@ function deriveDelegationRecommendation({
649
682
  const hasImplementationSkill = skillIds.some((id) => DELEGATABLE_IMPLEMENTATION_SKILL_IDS.has(id));
650
683
  const clearImplementationSignal = /\b(implement|build|create|add|ship|deliver|refactor|integrat(?:e|ion)|scaffold|feature)\b/.test(lower);
651
684
  const multiLaneSignal = /\b(multiple|several|parallel|independent|across files|across modules|batch)\b/.test(lower);
685
+ const featureDelegationTaskType = autonomyLevel === 'free-run'
686
+ ? (routingContext.taskType === 'non-trivial' || routingContext.taskType === 'simple')
687
+ : routingContext.taskType === 'non-trivial';
688
+ const featureDelegationBreadth = autonomyLevel === 'free-run' ? 3 : 4;
652
689
  if (
653
690
  hasImplementationSkill
654
691
  && clearImplementationSignal
655
- && routingContext.taskType === 'non-trivial'
656
- && (!localizedIndexedLane || !hasExplicitTarget || contextBreadth >= 4 || multiLaneSignal)
692
+ && featureDelegationTaskType
693
+ && (autonomyLevel === 'free-run' || !localizedIndexedLane || !hasExplicitTarget || contextBreadth >= featureDelegationBreadth || multiLaneSignal)
657
694
  ) {
658
695
  return {
659
696
  hint: 'feature-implementer',
@@ -25,6 +25,7 @@ export async function deriveVerificationPlan({
25
25
  contextResult = null,
26
26
  impactContext = null,
27
27
  skillIds = [],
28
+ autonomyLevel = 'balanced',
28
29
  } = {}) {
29
30
  const absoluteRoot = path.resolve(rootDir);
30
31
  const resolvedContext = contextResult ?? await resolveContext({
@@ -43,6 +44,7 @@ export async function deriveVerificationPlan({
43
44
  taskType: effectiveTaskType,
44
45
  skillIds,
45
46
  context,
47
+ autonomyLevel,
46
48
  });
47
49
 
48
50
  const cachedPlan = getRecentCacheEntry(VERIFICATION_PLAN_CACHE, verificationPlanCacheKey);
@@ -160,6 +162,7 @@ export async function deriveVerificationPlan({
160
162
  fallbackCommands: fallbackCommandList,
161
163
  reasons: reasonList,
162
164
  context,
165
+ autonomyLevel,
163
166
  }),
164
167
  context,
165
168
  };
@@ -354,6 +357,7 @@ function deriveExecutionPolicy({
354
357
  fallbackCommands = [],
355
358
  reasons = [],
356
359
  context = {},
360
+ autonomyLevel = 'balanced',
357
361
  } = {}) {
358
362
  const relatedTests = context.relatedTests ?? [];
359
363
  const sharedAbstractions = context.sharedAbstractions ?? [];
@@ -366,10 +370,12 @@ function deriveExecutionPolicy({
366
370
  const sharedScope = sharedAbstractions.length > 0;
367
371
  const noRelatedTests = relatedTests.length === 0;
368
372
  const broadOnlyPrimary = hasPrimaryCommands && !hasTargetedPrimaryCommands && noRelatedTests;
369
- const requiresHumanConfirmationForBroadOrRisky = risky && broadOnlyPrimary;
373
+ const isConservative = autonomyLevel === 'conservative';
374
+ const isFreeRun = autonomyLevel === 'free-run';
375
+ const requiresHumanConfirmationForBroadOrRisky = !isFreeRun && risky && broadOnlyPrimary;
370
376
  const shouldAutoRunPrimaryCommands = hasPrimaryCommands && !docsOnly && !requiresHumanConfirmationForBroadOrRisky;
371
377
  const shouldEscalateToFallbacks = !docsOnly && fallbackCommands.length > 0 && (risky || sharedScope);
372
- const shouldAutoRunFallbacks = shouldEscalateToFallbacks && !requiresHumanConfirmationForBroadOrRisky;
378
+ const shouldAutoRunFallbacks = shouldEscalateToFallbacks && !requiresHumanConfirmationForBroadOrRisky && !isConservative;
373
379
 
374
380
  let policyMode = 'recommend-only';
375
381
  if (docsOnly) {
@@ -409,6 +415,7 @@ function buildVerificationPlanCacheKey({
409
415
  taskType,
410
416
  skillIds = [],
411
417
  context = {},
418
+ autonomyLevel = 'balanced',
412
419
  } = {}) {
413
420
  return JSON.stringify({
414
421
  rootDir,
@@ -417,6 +424,7 @@ function buildVerificationPlanCacheKey({
417
424
  taskType: String(taskType || '').trim(),
418
425
  skillIds: unique(skillIds).sort(),
419
426
  context,
427
+ autonomyLevel: String(autonomyLevel || 'balanced').trim(),
420
428
  });
421
429
  }
422
430
 
@@ -945,10 +945,13 @@ const { pathToFileURL } = require('url');
945
945
  const sharedScope = sharedAbstractions.length > 0;
946
946
  const noRelatedTests = relatedTests.length === 0;
947
947
  const broadOnlyPrimary = hasPrimaryCommands && !hasTargetedPrimaryCommands && noRelatedTests;
948
- const requiresHumanConfirmationForBroadOrRisky = risky && broadOnlyPrimary;
948
+ const autonomyLevel = runtimeConfig?.autonomy?.level || 'balanced';
949
+ const isConservative = autonomyLevel === 'conservative';
950
+ const isFreeRun = autonomyLevel === 'free-run';
951
+ const requiresHumanConfirmationForBroadOrRisky = !isFreeRun && risky && broadOnlyPrimary;
949
952
  const shouldAutoRunPrimaryCommands = hasPrimaryCommands && !docsOnly && !requiresHumanConfirmationForBroadOrRisky;
950
953
  const shouldEscalateToFallbacks = !docsOnly && fallbackCommands.length > 0 && (risky || sharedScope);
951
- const shouldAutoRunFallbacks = shouldEscalateToFallbacks && !requiresHumanConfirmationForBroadOrRisky;
954
+ const shouldAutoRunFallbacks = shouldEscalateToFallbacks && !requiresHumanConfirmationForBroadOrRisky && !isConservative;
952
955
 
953
956
  let policyMode = 'recommend-only';
954
957
  if (docsOnly) {
@@ -1105,6 +1105,7 @@ function deriveDelegationRecommendation({
1105
1105
  routingContext = {},
1106
1106
  contextRecommendation = null,
1107
1107
  verificationRecommendation = null,
1108
+ autonomyLevel = 'balanced',
1108
1109
  } = {}) {
1109
1110
  const skillIds = activeSkills.map((item) => item.id);
1110
1111
  const lower = `${routingContext.promptText ?? ''}\n${routingContext.commandText ?? ''}`.toLowerCase();
@@ -1129,6 +1130,21 @@ function deriveDelegationRecommendation({
1129
1130
  return null;
1130
1131
  }
1131
1132
 
1133
+ if (autonomyLevel === 'conservative') {
1134
+ if (
1135
+ skillIds.includes('executing-plans')
1136
+ || /\b(execute this plan|follow this plan|implementation plan|rollout plan|controlled batches?|review checkpoints?|batch execution|execute in batches)\b/.test(lower)
1137
+ ) {
1138
+ return {
1139
+ hint: 'subagent-driven-development',
1140
+ when,
1141
+ reason: 'Explicit plan/batch execution is separable enough for deliberate subagent passes.',
1142
+ };
1143
+ }
1144
+
1145
+ return null;
1146
+ }
1147
+
1132
1148
  if (
1133
1149
  skillIds.includes('executing-plans')
1134
1150
  || /\b(execute this plan|follow this plan|implementation plan|rollout plan|controlled batches?|review checkpoints?|batch execution|execute in batches)\b/.test(lower)
@@ -1145,7 +1161,8 @@ function deriveDelegationRecommendation({
1145
1161
  || /\b(debug|error|crash|stack(?: trace)?|failing|flake|flaky|timeout|triage|root cause)\b/.test(lower)
1146
1162
  || verificationRecommendation?.executionPolicy?.policyMode === 'confirm-then-broad'
1147
1163
  );
1148
- if (noisyDebugLane && (!localizedIndexedLane || !hasRelatedTests || contextBreadth >= 4)) {
1164
+ const debugDelegationThreshold = autonomyLevel === 'free-run' ? 3 : 4;
1165
+ if (noisyDebugLane && (!localizedIndexedLane || !hasRelatedTests || contextBreadth >= debugDelegationThreshold)) {
1149
1166
  return {
1150
1167
  hint: 'bug-debugger',
1151
1168
  when,
@@ -1156,11 +1173,15 @@ function deriveDelegationRecommendation({
1156
1173
  const hasImplementationSkill = skillIds.some((id) => DELEGATABLE_IMPLEMENTATION_SKILL_IDS.has(id));
1157
1174
  const clearImplementationSignal = /\b(implement|build|create|add|ship|deliver|refactor|integrat(?:e|ion)|scaffold|feature)\b/.test(lower);
1158
1175
  const multiLaneSignal = /\b(multiple|several|parallel|independent|across files|across modules|batch)\b/.test(lower);
1176
+ const featureDelegationTaskType = autonomyLevel === 'free-run'
1177
+ ? (routingContext.taskType === 'non-trivial' || routingContext.taskType === 'simple')
1178
+ : routingContext.taskType === 'non-trivial';
1179
+ const featureDelegationBreadth = autonomyLevel === 'free-run' ? 3 : 4;
1159
1180
  if (
1160
1181
  hasImplementationSkill
1161
1182
  && clearImplementationSignal
1162
- && routingContext.taskType === 'non-trivial'
1163
- && (!localizedIndexedLane || !hasExplicitTarget || contextBreadth >= 4 || multiLaneSignal)
1183
+ && featureDelegationTaskType
1184
+ && (autonomyLevel === 'free-run' || !localizedIndexedLane || !hasExplicitTarget || contextBreadth >= featureDelegationBreadth || multiLaneSignal)
1164
1185
  ) {
1165
1186
  return {
1166
1187
  hint: 'feature-implementer',
@@ -1179,11 +1200,13 @@ function buildRouteSummary({
1179
1200
  verificationRecommendation = null,
1180
1201
  nextAction = null,
1181
1202
  } = {}) {
1203
+ const autonomyLevel = routingContext.autonomyLevel ?? 'balanced';
1182
1204
  const delegationRecommendation = deriveDelegationRecommendation({
1183
1205
  activeSkills,
1184
1206
  routingContext,
1185
1207
  contextRecommendation,
1186
1208
  verificationRecommendation,
1209
+ autonomyLevel,
1187
1210
  });
1188
1211
  const preview = contextRecommendation?.preview ?? {};
1189
1212
  const primaryTargets = summarizeCompactList(preview.primaryTargets ?? [], 2);
@@ -1197,6 +1220,8 @@ function buildRouteSummary({
1197
1220
  );
1198
1221
  const policyMode = verificationRecommendation?.executionPolicy?.policyMode ?? null;
1199
1222
  const editGuardHint = isSharedImpactFile(routingContext.targetFile) ? 'anchor-required' : null;
1223
+ const taskType = routingContext.taskType ?? null;
1224
+ const contextMode = deriveContextMode(taskType);
1200
1225
  const compactHelperLane = nextAction?.type === 'pull-indexed-context'
1201
1226
  && typeof contextRecommendation?.command === 'string'
1202
1227
  && contextRecommendation.command.trim();
@@ -1218,6 +1243,7 @@ function buildRouteSummary({
1218
1243
  editGuardHint ? `editGuard=${editGuardHint}` : null,
1219
1244
  delegationRecommendation?.hint ? `delegate=${delegationRecommendation.hint}` : null,
1220
1245
  policyMode ? `policy=${policyMode}` : null,
1246
+ contextMode ? `mode=${contextMode}` : null,
1221
1247
  ].filter(Boolean).join(' | ');
1222
1248
 
1223
1249
  return {
@@ -1231,10 +1257,17 @@ function buildRouteSummary({
1231
1257
  nextActionType: nextAction?.type ?? null,
1232
1258
  nextActionCommand,
1233
1259
  helperHint,
1260
+ contextMode,
1234
1261
  line: line || 'task=unknown',
1235
1262
  };
1236
1263
  }
1237
1264
 
1265
+ function deriveContextMode(taskType) {
1266
+ if (taskType === 'trivial' || taskType === 'simple') return 'LITE';
1267
+ if (taskType === 'non-trivial' || taskType === 'shared-simple') return 'FULL';
1268
+ return null;
1269
+ }
1270
+
1238
1271
  function deriveExecutionPolicy({
1239
1272
  taskType = 'simple',
1240
1273
  mode = 'minimal',
@@ -1242,6 +1275,7 @@ function deriveExecutionPolicy({
1242
1275
  fallbackCommands = [],
1243
1276
  reasons = [],
1244
1277
  context = {},
1278
+ autonomyLevel = 'balanced',
1245
1279
  } = {}) {
1246
1280
  const relatedTests = context.relatedTests ?? [];
1247
1281
  const sharedAbstractions = context.sharedAbstractions ?? [];
@@ -1254,10 +1288,12 @@ function deriveExecutionPolicy({
1254
1288
  const sharedScope = sharedAbstractions.length > 0;
1255
1289
  const noRelatedTests = relatedTests.length === 0;
1256
1290
  const broadOnlyPrimary = hasPrimaryCommands && !hasTargetedPrimaryCommands && noRelatedTests;
1257
- const requiresHumanConfirmationForBroadOrRisky = risky && broadOnlyPrimary;
1291
+ const isConservative = autonomyLevel === 'conservative';
1292
+ const isFreeRun = autonomyLevel === 'free-run';
1293
+ const requiresHumanConfirmationForBroadOrRisky = !isFreeRun && risky && broadOnlyPrimary;
1258
1294
  const shouldAutoRunPrimaryCommands = hasPrimaryCommands && !docsOnly && !requiresHumanConfirmationForBroadOrRisky;
1259
1295
  const shouldEscalateToFallbacks = !docsOnly && fallbackCommands.length > 0 && (risky || sharedScope);
1260
- const shouldAutoRunFallbacks = shouldEscalateToFallbacks && !requiresHumanConfirmationForBroadOrRisky;
1296
+ const shouldAutoRunFallbacks = shouldEscalateToFallbacks && !requiresHumanConfirmationForBroadOrRisky && !isConservative;
1261
1297
 
1262
1298
  let policyMode = 'recommend-only';
1263
1299
  if (docsOnly) {
@@ -23,6 +23,7 @@ const args = process.argv.slice(2);
23
23
  const rootDir = getRootDir(args);
24
24
  const targetFile = readFlagValue(args, '--target');
25
25
  const taskType = readFlagValue(args, '--type');
26
+ const autonomyLevel = readFlagValue(args, '--autonomy') ?? 'balanced';
26
27
  const intent = collectPositionalArgs(args, ['--root', '--target', '--type']);
27
28
  const effectiveIntent = deriveHelperIntent({ intent, targetFile });
28
29
 
@@ -42,6 +43,7 @@ if (!intent && !targetFile) {
42
43
  intent: effectiveIntent,
43
44
  targetFile,
44
45
  taskType,
46
+ autonomyLevel,
45
47
  });
46
48
  const cached = await readRecentCacheEntry(cachePath, requestKey, {
47
49
  maxEntries: DEFAULT_RECENT_CACHE_MAX_ENTRIES,
@@ -71,6 +73,7 @@ if (!intent && !targetFile) {
71
73
  contextResult: expandHelperContext(cachedContext?.result ?? null),
72
74
  fingerprintEntries: projectVerification.entries,
73
75
  pkg: projectVerification.pkg,
76
+ autonomyLevel,
74
77
  });
75
78
 
76
79
  if (!cached) {
@@ -122,6 +125,7 @@ async function deriveVerificationPlan({
122
125
  contextResult = null,
123
126
  fingerprintEntries = [],
124
127
  pkg = null,
128
+ autonomyLevel = 'balanced',
125
129
  } = {}) {
126
130
  const absoluteRoot = path.resolve(rootDir);
127
131
  const context = expandHelperContext(contextResult ?? await resolveContext({
@@ -223,6 +227,7 @@ async function deriveVerificationPlan({
223
227
  fallbackCommands: fallbackCommandList,
224
228
  reasons: reasonList,
225
229
  context: summarizedContext,
230
+ autonomyLevel,
226
231
  }),
227
232
  };
228
233
  }
@@ -614,6 +619,7 @@ function deriveExecutionPolicy({
614
619
  fallbackCommands = [],
615
620
  reasons = [],
616
621
  context = {},
622
+ autonomyLevel = 'balanced',
617
623
  } = {}) {
618
624
  const relatedTests = context.relatedTests ?? [];
619
625
  const sharedAbstractions = context.sharedAbstractions ?? [];
@@ -626,10 +632,12 @@ function deriveExecutionPolicy({
626
632
  const sharedScope = sharedAbstractions.length > 0;
627
633
  const noRelatedTests = relatedTests.length === 0;
628
634
  const broadOnlyPrimary = hasPrimaryCommands && !hasTargetedPrimaryCommands && noRelatedTests;
629
- const requiresHumanConfirmationForBroadOrRisky = risky && broadOnlyPrimary;
635
+ const isConservative = autonomyLevel === 'conservative';
636
+ const isFreeRun = autonomyLevel === 'free-run';
637
+ const requiresHumanConfirmationForBroadOrRisky = !isFreeRun && risky && broadOnlyPrimary;
630
638
  const shouldAutoRunPrimaryCommands = hasPrimaryCommands && !docsOnly && !requiresHumanConfirmationForBroadOrRisky;
631
639
  const shouldEscalateToFallbacks = !docsOnly && fallbackCommands.length > 0 && (risky || sharedScope);
632
- const shouldAutoRunFallbacks = shouldEscalateToFallbacks && !requiresHumanConfirmationForBroadOrRisky;
640
+ const shouldAutoRunFallbacks = shouldEscalateToFallbacks && !requiresHumanConfirmationForBroadOrRisky && !isConservative;
633
641
 
634
642
  let policyMode = 'recommend-only';
635
643
  if (docsOnly) {
@@ -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.3.1 Shared Runtime
15
+ ## UKit v1.4.0 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.
@@ -42,7 +42,7 @@
42
42
  - **Do not ask normal contributors to run internal helper commands**; run them yourself or tell them to rerun `ukit install`.
43
43
  - Do not ask normal contributors to memorize `ukit doctor`, `ukit diff`, `ukit uninstall`, or `ukit index ...` unless they explicitly need maintainer/debug help.
44
44
 
45
- ## UKit v1.3.1 Shared Runtime
45
+ ## UKit v1.4.0 Shared Runtime
46
46
 
47
47
  - Shared runtime state lives in `.ukit/storage/`.
48
48
  - Treat `.ukit/storage/config.json` as the source of runtime toggles for compact, token pipeline, router, memory, validation, and Safe Patch behavior.
@@ -95,6 +95,14 @@
95
95
  - Good delegation triggers: noisy research/log lanes, 3+ independent failures, explicit batch execution, or a broad debug/implementation lane with a clean handoff.
96
96
  - If route memory includes `delegate=<lane>`, treat it as an internal hint after any required indexed-context step.
97
97
 
98
+ ## Adaptive Autonomy
99
+
100
+ - `autonomy.level` in `.ukit/storage/config.json` controls how much UKit acts without asking first: `conservative` (ask more), `balanced` (default, current behavior), `free-run` (auto-run more).
101
+ - `conservative`: do not auto-run fallback verification; ask before broad/risky escalation; suppress non-essential delegation (except explicit plan/batch execution and small-task maintainer).
102
+ - `balanced`: default behavior unchanged — targeted verification auto-runs, broad risky asks confirmation, delegation follows existing thresholds.
103
+ - `free-run`: auto-run fallback verification; remove broad verification confirmation for escalation-only; lower feature/debug delegation thresholds slightly.
104
+ - End users should not need to change this; maintainers may tune it per-project.
105
+
98
106
  ## Project Snapshot
99
107
 
100
108
  - Project: {{project.name}} | Root: {{project.root}}
@@ -1,6 +1,6 @@
1
1
  # UKit Shared Runtime
2
2
 
3
- This folder stores shared UKit runtime state for v1.3.1 features.
3
+ This folder stores shared UKit runtime state for v1.4.0 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/`
@@ -1,6 +1,11 @@
1
1
  {
2
- "version": "1.3.1",
2
+ "version": "1.4.0",
3
3
  "agent": "claude-code",
4
+ "autonomy": {
5
+ "level": "balanced",
6
+ "affectVerification": true,
7
+ "affectDelegation": true
8
+ },
4
9
  "compact": {
5
10
  "enabled": true,
6
11
  "tokenThreshold": 100000,
@@ -141,15 +146,23 @@
141
146
  "stepBudgets": {
142
147
  "trivial": {
143
148
  "maxSteps": 1,
144
- "verification": "skip-unless-risky"
149
+ "verification": "skip-unless-risky",
150
+ "label": "LITE"
145
151
  },
146
152
  "simple": {
147
153
  "maxSteps": 2,
148
- "verification": "targeted-if-covered"
154
+ "verification": "targeted-if-covered",
155
+ "label": "LITE"
156
+ },
157
+ "sharedSimple": {
158
+ "maxSteps": 3,
159
+ "verification": "targeted-then-widen-on-risk",
160
+ "label": "FULL"
149
161
  },
150
162
  "nonTrivial": {
151
163
  "maxSteps": 4,
152
- "verification": "targeted-then-widen-on-risk"
164
+ "verification": "targeted-then-widen-on-risk",
165
+ "label": "FULL"
153
166
  }
154
167
  },
155
168
  "executionMode": "sidecar-parallel",
@@ -196,6 +209,11 @@
196
209
  },
197
210
  "version": "Phiên bản config runtime đi kèm package UKit.",
198
211
  "agent": "Adapter mặc định của workspace. Thường giữ nguyên theo lúc install.",
212
+ "autonomy": {
213
+ "level": "Mức tự chủ của UKit. conservative: hỏi trước khi fallback/escalate, không tự delegate. balanced: mặc định, hành vi hiện tại. free-run: tự chạy fallback, delegate tự nhiên hơn, bớt xác nhận.",
214
+ "affectVerification": "Nếu true, autonomy.level ảnh hưởng hành vi verification plan.",
215
+ "affectDelegation": "Nếu true, autonomy.level ảnh hưởng ngưỡng delegation."
216
+ },
199
217
  "compact": {
200
218
  "enabled": "Bật/tắt toàn bộ helper compact của UKit.",
201
219
  "tokenThreshold": "Ngưỡng token chung cho runtime compact dùng chung.",
@@ -282,7 +300,7 @@
282
300
  "maxSidecarWaitMs": "0 nghĩa là không chờ sidecar trước khi tiếp tục task chính.",
283
301
  "optimizeOrder": "Thứ tự ưu tiên khi ra quyết định nội bộ.",
284
302
  "decisions": "Nhóm quyết định sidecar được phép hỗ trợ.",
285
- "stepBudgets": "Gợi ý số bước planning tối đa theo độ lớn task trước khi reassess."
303
+ "stepBudgets": "Gợi ý số bước planning tối đa theo độ lớn task trước khi reassess. label LITE/FULL cho biết subagent dùng model nhỏ hay đầy đủ."
286
304
  }
287
305
  },
288
306
  "safePatch": {