@ngockhoale/ukit 1.4.4 → 1.5.1

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
@@ -2,6 +2,29 @@
2
2
 
3
3
  All notable changes to UKit are documented here.
4
4
 
5
+ ## 1.5.0 - 2026-05-24
6
+
7
+ ### Fixed
8
+
9
+ - Switched safe-patch release regressions to `spawnSync`-based helpers so advisory-mode assertions capture `stderr` correctly even when the hook exits `0`.
10
+ - Raised the packed artifact size budget slightly to preserve the shipped canvas font lane and recent runtime/router surfaces without failing release smoke on a 625-byte overage.
11
+
12
+ ### Changed
13
+
14
+ - Bumped package and shared runtime version metadata to `1.5.0`.
15
+
16
+ ## 1.4.5 - 2026-05-24
17
+
18
+ ### Fixed
19
+
20
+ - Stopped safe-patch hooks (`stale-spec-check`, `post-edit-verify`) from hard-blocking tool calls when configured via the new `safePatch.advisoryOnly` flag or the `UKIT_SAFE_PATCH_ADVISORY=1` env. Removes the mid-task "stop and wait for continue" stalls that hit shared-risk files in `.claude/`, `templates/`, `scripts/`, etc., while preserving the diagnostic message so Claude/Codex can self-correct instead of stalling.
21
+ - Default behavior unchanged (`advisoryOnly: false`): pre-edit corruption guards (shebang-bom, non-text, whole-file Write to shared-risk) and the `protect-files` / `block-dangerous` hooks still hard-block.
22
+
23
+ ### Tests
24
+
25
+ - Added regression coverage for advisory-mode exit code and stderr in `tests/hooks/safePatchProtocol.test.js`.
26
+ - Added default + validation assertions for `safePatch.advisoryOnly` in `tests/core/runtimeConfig.test.js`.
27
+
5
28
  ## 1.4.4 - 2026-05-11
6
29
 
7
30
  ### Fixed
@@ -84,7 +84,7 @@ items:
84
84
  requires:
85
85
  - docs-project
86
86
  - docs-memory
87
- mergeStrategy: skip
87
+ mergeStrategy: overwrite_with_backup
88
88
  variables:
89
89
  - project.name
90
90
  - project.root
@@ -107,7 +107,7 @@ items:
107
107
  requires:
108
108
  - docs-project
109
109
  - docs-memory
110
- mergeStrategy: skip
110
+ mergeStrategy: overwrite_with_backup
111
111
  variables:
112
112
  - project.name
113
113
  - project.stack
@@ -1302,6 +1302,15 @@ items:
1302
1302
  packs:
1303
1303
  - core
1304
1304
 
1305
+ - id: multi-antigravity-agents-link
1306
+ type: link
1307
+ sourceTemplate: .claude/agents
1308
+ targetPath: .antigravity/agents
1309
+ requires: []
1310
+ enabledByDefault: true
1311
+ packs:
1312
+ - core
1313
+
1305
1314
  - id: multi-antigravity-rules
1306
1315
  type: config
1307
1316
  sourceTemplate: adapter-presets/antigravity/rules.md
@@ -1349,6 +1358,15 @@ items:
1349
1358
  packs:
1350
1359
  - core
1351
1360
 
1361
+ - id: multi-codex-agents-link
1362
+ type: link
1363
+ sourceTemplate: .claude/agents
1364
+ targetPath: .codex/agents
1365
+ requires: []
1366
+ enabledByDefault: true
1367
+ packs:
1368
+ - core
1369
+
1352
1370
  - id: multi-codex-readme
1353
1371
  type: config
1354
1372
  sourceTemplate: .codex/README.md
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ngockhoale/ukit",
3
- "version": "1.4.4",
3
+ "version": "1.5.1",
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",
@@ -7,12 +7,14 @@ export const OPTIONAL_ADAPTERS = [
7
7
  'multi-antigravity-ukit-link',
8
8
  'multi-antigravity-rules',
9
9
  'multi-antigravity-readme',
10
+ 'multi-antigravity-agents-link',
10
11
  ],
11
12
  managedPaths: [
12
13
  '.antigravity/skills',
13
14
  '.antigravity/ukit',
14
15
  '.antigravity/rules/rules.md',
15
16
  '.antigravity/README.md',
17
+ '.antigravity/agents',
16
18
  ],
17
19
  },
18
20
  {
@@ -24,6 +26,7 @@ export const OPTIONAL_ADAPTERS = [
24
26
  'multi-codex-readme',
25
27
  'multi-codex-settings-json',
26
28
  'multi-codex-settings-local',
29
+ 'multi-codex-agents-link',
27
30
  ],
28
31
  managedPaths: [
29
32
  '.codex/skills',
@@ -31,6 +34,7 @@ export const OPTIONAL_ADAPTERS = [
31
34
  '.codex/README.md',
32
35
  '.codex/settings.json',
33
36
  '.codex/settings.local.json',
37
+ '.codex/agents',
34
38
  ],
35
39
  },
36
40
  {
@@ -2,6 +2,16 @@ import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import { writeFileAtomic, copyFileSafe, createDirectoryLink, removeLinkOnly } from './fileOps.js';
4
4
 
5
+ const TCC_PROTECTED_PREFIXES = ['.codex/', '.antigravity/'];
6
+
7
+ function isTccProtectedPath(filePath) {
8
+ const normalized = filePath.replace(/\\/g, '/');
9
+ return TCC_PROTECTED_PREFIXES.some((prefix) => {
10
+ const idx = normalized.indexOf(`/${prefix}`);
11
+ return idx !== -1 || normalized.startsWith(prefix);
12
+ });
13
+ }
14
+
5
15
  export async function applyDiffResults(diffResults, { backupRoot, projectRoot } = {}) {
6
16
  const writes = [];
7
17
  let skippedUpdates = 0;
@@ -12,14 +22,9 @@ export async function applyDiffResults(diffResults, { backupRoot, projectRoot }
12
22
  }
13
23
 
14
24
  if (entry.type === 'link') {
15
- // Remove existing symlink before recreating.
16
- // Use removeLinkOnly — NOT removeLinkOrDir — to protect real directories that may
17
- // contain user content. If the path is not a symlink, skip and warn instead of
18
- // recursively deleting it.
19
25
  if (entry.action === 'update') {
20
26
  const removed = await removeLinkOnly(entry.targetPath);
21
27
  if (!removed) {
22
- // Determine what actually exists at this path for a precise warning message.
23
28
  let existingKind = 'unknown path';
24
29
  try {
25
30
  const stat = await fs.lstat(entry.targetPath);
@@ -34,7 +39,18 @@ export async function applyDiffResults(diffResults, { backupRoot, projectRoot }
34
39
  continue;
35
40
  }
36
41
  }
37
- await createDirectoryLink(entry.linkTarget, entry.targetPath);
42
+ try {
43
+ await createDirectoryLink(entry.linkTarget, entry.targetPath);
44
+ } catch (linkError) {
45
+ if (linkError.code === 'EPERM' || linkError.code === 'EACCES') {
46
+ console.warn(
47
+ `[UKit] Warning: skipping link creation for ${entry.targetPath} — permission denied. Run 'ukit install' from within the target tool to create it.`,
48
+ );
49
+ skippedUpdates += 1;
50
+ continue;
51
+ }
52
+ throw linkError;
53
+ }
38
54
  writes.push({
39
55
  id: entry.id,
40
56
  targetPath: entry.targetPath,
@@ -54,7 +70,18 @@ export async function applyDiffResults(diffResults, { backupRoot, projectRoot }
54
70
  const relPath = path.relative(projectRoot, entry.targetPath);
55
71
  const timestamp = Date.now();
56
72
  const backupPath = path.join(backupRoot, `${relPath}.${timestamp}.bak`);
57
- await copyFileSafe(entry.targetPath, backupPath);
73
+ try {
74
+ await copyFileSafe(entry.targetPath, backupPath);
75
+ } catch (backupError) {
76
+ if (backupError.code === 'EPERM' || backupError.code === 'EACCES') {
77
+ console.warn(
78
+ `[UKit] Warning: skipping backup for ${entry.targetPath} — permission denied.`,
79
+ );
80
+ skippedUpdates += 1;
81
+ continue;
82
+ }
83
+ throw backupError;
84
+ }
58
85
  }
59
86
 
60
87
  const binaryEntry = Buffer.isBuffer(entry.renderedContent);
@@ -73,7 +100,21 @@ export async function applyDiffResults(diffResults, { backupRoot, projectRoot }
73
100
  )
74
101
  : entry.renderedContent;
75
102
 
76
- await writeFileAtomic(entry.targetPath, nextContent);
103
+ try {
104
+ await writeFileAtomic(entry.targetPath, nextContent);
105
+ } catch (writeError) {
106
+ if (
107
+ (writeError.code === 'EPERM' || writeError.code === 'EACCES') &&
108
+ isTccProtectedPath(entry.targetPath)
109
+ ) {
110
+ console.warn(
111
+ `[UKit] Warning: skipping write for ${entry.targetPath} — permission denied (macOS TCC). Run 'ukit install' from within the owning tool to update it.`,
112
+ );
113
+ skippedUpdates += 1;
114
+ continue;
115
+ }
116
+ throw writeError;
117
+ }
77
118
  if (typeof entry.mode === 'number') {
78
119
  await fs.chmod(entry.targetPath, entry.mode);
79
120
  }
@@ -49,7 +49,7 @@ export function buildDefaultRuntimeConfig(overrides = {}) {
49
49
  const safeOverrides = isPlainObject(overrides) ? overrides : {};
50
50
 
51
51
  return mergeObjects({
52
- version: '1.4.4',
52
+ version: '1.5.1',
53
53
  agent: 'claude-code',
54
54
  autonomy: {
55
55
  level: 'balanced',
@@ -183,6 +183,7 @@ export function buildDefaultRuntimeConfig(overrides = {}) {
183
183
  safePatch: {
184
184
  enabled: true,
185
185
  strictSharedRisk: true,
186
+ advisoryOnly: false,
186
187
  largeFileLineThreshold: 800,
187
188
  largeFileByteThreshold: 200_000,
188
189
  backupEnabled: true,
@@ -368,6 +369,7 @@ export function validateRuntimeConfig(config) {
368
369
  } else {
369
370
  pushBooleanError(errors, config.safePatch.enabled, 'safePatch.enabled');
370
371
  pushBooleanError(errors, config.safePatch.strictSharedRisk, 'safePatch.strictSharedRisk');
372
+ pushBooleanError(errors, config.safePatch.advisoryOnly, 'safePatch.advisoryOnly');
371
373
  pushPositiveNumberError(errors, config.safePatch.largeFileLineThreshold, 'safePatch.largeFileLineThreshold');
372
374
  pushPositiveNumberError(errors, config.safePatch.largeFileByteThreshold, 'safePatch.largeFileByteThreshold');
373
375
  pushBooleanError(errors, config.safePatch.backupEnabled, 'safePatch.backupEnabled');
@@ -3,11 +3,13 @@ export const OPTIONAL_ADAPTER_ITEM_IDS = new Set([
3
3
  'multi-antigravity-ukit-link',
4
4
  'multi-antigravity-rules',
5
5
  'multi-antigravity-readme',
6
+ 'multi-antigravity-agents-link',
6
7
  'multi-codex-skills-link',
7
8
  'multi-codex-ukit-link',
8
9
  'multi-codex-readme',
9
10
  'multi-codex-settings-json',
10
11
  'multi-codex-settings-local',
12
+ 'multi-codex-agents-link',
11
13
  'multi-opencode-config',
12
14
  ]);
13
15
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: ukit-small-task-maintainer
3
3
  description: "Internal UKit maintenance subagent for low-risk, reversible UKit decisions. Use proactively when UKit needs to decide or perform safe cleanup such as pruning docs/TASKS.md, classifying queued work, choosing whether compact/summarization is appropriate, summarizing local docs/status, or maintaining small UKit runtime queues. Do not use for product implementation, security, release/publish, data-loss, architecture, or risky/shared code changes."
4
- model: inherit
4
+ model: unic-lite
5
5
  color: cyan
6
6
  tools: ["Read", "Grep", "Glob", "Edit", "Write"]
7
7
  ---
@@ -2,7 +2,7 @@ import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
4
  import { analyzeTextBuffer, analyzeTextFile, publicTextProfile } from '../runtime/text-profile.mjs';
5
- import { classifySafePatchRisk, parseJsonInput, pathExists, readRuntimeSafePatchConfig, resolveProjectFile } from '../runtime/safe-patch-core.mjs';
5
+ import { classifySafePatchRisk, isSafePatchAdvisoryOnly, parseJsonInput, pathExists, readRuntimeSafePatchConfig, resolveProjectFile } from '../runtime/safe-patch-core.mjs';
6
6
 
7
7
  async function readStdin() {
8
8
  return await new Promise((resolve) => {
@@ -183,8 +183,10 @@ async function main() {
183
183
  process.stdout.write(json ? `${JSON.stringify({ help: text })}\n` : `${text}\n`);
184
184
  return;
185
185
  }
186
+ const projectRoot = process.env.CLAUDE_PROJECT_DIR || process.cwd();
187
+ const runtimeConfig = await readRuntimeSafePatchConfig(projectRoot);
186
188
  const result = await verifyPostEdit({
187
- projectRoot: process.env.CLAUDE_PROJECT_DIR || process.cwd(),
189
+ projectRoot,
188
190
  payload: parseJsonInput(await readStdin(), {}),
189
191
  });
190
192
  if (json) {
@@ -193,7 +195,14 @@ async function main() {
193
195
  process.stdout.write(`[ukit-safe-patch] ${result.message}\n`);
194
196
  }
195
197
  if (result.status === 'blocked') {
196
- process.stderr.write(`[ukit-safe-patch] ${result.message}\n`);
198
+ const advisory = isSafePatchAdvisoryOnly(runtimeConfig);
199
+ const prefix = advisory ? 'ADVISORY' : 'BLOCKED';
200
+ const message = String(result.message || '').replace(/^BLOCKED:/, `${prefix}:`);
201
+ process.stderr.write(`[ukit-safe-patch] ${message}\n`);
202
+ if (advisory) {
203
+ process.stderr.write('[ukit-safe-patch] advisoryOnly=true — change is already written; continue planned follow-up without stopping.\n');
204
+ return;
205
+ }
197
206
  process.exit(2);
198
207
  }
199
208
  }
@@ -4,6 +4,7 @@ import path from 'node:path';
4
4
  import {
5
5
  classifySafePatchRisk,
6
6
  countOccurrences,
7
+ isSafePatchAdvisoryOnly,
7
8
  lineNumberForIndex,
8
9
  parseJsonInput,
9
10
  pathExists,
@@ -169,7 +170,9 @@ async function main() {
169
170
  return;
170
171
  }
171
172
  const payload = parseJsonInput(await readStdin(), {});
172
- const result = await checkStaleSpec({ projectRoot: process.env.CLAUDE_PROJECT_DIR || process.cwd(), payload });
173
+ const projectRoot = process.env.CLAUDE_PROJECT_DIR || process.cwd();
174
+ const runtimeConfig = await readRuntimeSafePatchConfig(projectRoot);
175
+ const result = await checkStaleSpec({ projectRoot, payload });
173
176
  if (args.json) {
174
177
  process.stdout.write(`${JSON.stringify(result)}\n`);
175
178
  } else if (result.status === 'ok') {
@@ -179,7 +182,14 @@ async function main() {
179
182
  }
180
183
 
181
184
  if (result.status === 'blocked') {
182
- process.stderr.write(`[ukit-safe-patch] ${result.message}\n`);
185
+ const advisory = isSafePatchAdvisoryOnly(runtimeConfig);
186
+ const prefix = advisory ? 'ADVISORY' : 'BLOCKED';
187
+ const message = String(result.message || '').replace(/^BLOCKED:/, `${prefix}:`);
188
+ process.stderr.write(`[ukit-safe-patch] ${message}\n`);
189
+ if (advisory) {
190
+ process.stderr.write('[ukit-safe-patch] advisoryOnly=true — continue with corrected old_string; do not stop and ask the user.\n');
191
+ return;
192
+ }
183
193
  process.exit(2);
184
194
  }
185
195
  }
@@ -4,6 +4,7 @@ import path from 'node:path';
4
4
  export const DEFAULT_SAFE_PATCH_CONFIG = {
5
5
  enabled: true,
6
6
  strictSharedRisk: true,
7
+ advisoryOnly: false,
7
8
  largeFileLineThreshold: 800,
8
9
  largeFileByteThreshold: 200_000,
9
10
  backupEnabled: true,
@@ -13,6 +14,15 @@ export const DEFAULT_SAFE_PATCH_CONFIG = {
13
14
  deltaMaxDiffCells: 2_000_000,
14
15
  };
15
16
 
17
+ // When advisoryOnly is true (via config or env UKIT_SAFE_PATCH_ADVISORY=1),
18
+ // safe-patch hooks downgrade exit 2 (block) to exit 0 + WARNING. This keeps
19
+ // Claude/Codex from stalling mid-task on stale/ambiguous spec or delta-budget
20
+ // trips without losing the diagnostic message.
21
+ export function isSafePatchAdvisoryOnly(config = DEFAULT_SAFE_PATCH_CONFIG) {
22
+ if (process.env.UKIT_SAFE_PATCH_ADVISORY === '1') return true;
23
+ return Boolean(config?.advisoryOnly);
24
+ }
25
+
16
26
  const SHARED_RISK_PATTERNS = [
17
27
  /^\.claude\/hooks\//,
18
28
  /^\.claude\/ukit\//,
@@ -5,66 +5,121 @@ Auto-generated by UKit for OpenAI Codex.
5
5
  - Packs: {{project.stack}}
6
6
  - Package manager: {{runtime.packageManager}}
7
7
 
8
- ## Team Workflow (Highest Priority)
8
+ ## Core UKit Rule
9
9
 
10
- - Teammates should only need to remember **`ukit install`**.
11
- - After `ukit install`, open Claude/Codex and ask naturally.
12
- - Do not make end users memorize skill names, helper scripts, or routing internals unless they are debugging UKit itself.
13
- - **Treat helper commands as internal orchestration. Do not ask end users to run them.**
10
+ - Human-facing workflow should optimize for one remembered command: `ukit install`.
11
+ - After install, normal work should feel natural inside **Claude/Codex/OpenCode** (and Antigravity when installed).
12
+ - **Quality first, then speed, then token discipline**: do not waste reads, logs, or repeated helper output.
13
+ - **Never stop after read-only steps.** For implement/apply/fix requests, continue to actual Edit/Write and verification in the same turn.
14
14
 
15
- ## UKit v1.4.3 Shared Runtime
15
+ ## Fast Task Classification
16
16
 
17
- - Shared runtime state lives in `.ukit/storage/`.
18
- - Treat `.ukit/storage/config.json` as the source of compact, token-pipeline, router, memory, validation, and Safe Patch guardrail toggles.
19
- - Reuse `.ukit/storage/memory/` before asking users to restate prior decisions.
20
- - For non-trivial work, prefer `ukit memory recall "<current task>"` before widening docs.
21
- - Reusable cache state lives in `.ukit/storage/cache/prompt-cache.json`, `.ukit/storage/cache/compact-history.json`, `.ukit/storage/cache/compact-pressure.json`, `.ukit/storage/cache/output-history.json`, and preserved raw tool outputs under `.ukit/storage/cache/tee/`.
22
- - If an older repo still has a visible `ukit/` runtime root, rerun `ukit install`; UKit should migrate the shared runtime into hidden `.ukit/` when safe.
23
- - Maintainers can inspect runtime state with `ukit status` and `ukit memory export`.
24
- - Reuse compact `previous-context` / `recent-output` route snapshots before replaying raw history.
25
- - Threshold-based compact pressure is internal orchestration; Codex users should not need to manage it manually.
26
- - UKit keeps Claude PreCompact/reinject and OpenCode native auto/prune compaction intact. For Codex Desktop long sessions, UKit can use `subagents.smallTaskModel` through `ukit-small-task-maintainer` to decide soft auto-compact handoffs. Default `compact.codexContext.compactTarget=150` means about 150 compact handoff lines (120-150 preferred, hard max 170), not 150 app-context tokens.
27
- - Safe Patch Protocol is internal: for risky file edits, prefer current-file anchors and exact specs, avoid whole-file rewrites, and preserve multilingual/BOM/newline profiles. Do not ask normal users to run helper commands.
17
+ - **Trivial** typo, label, rename nhỏ, spacing, toggle flag, obvious config change.
18
+ - Act directly. No doc reads. No planning. No index.
19
+ - **Simple** 1-2 files, clear scope, existing pattern.
20
+ - Handle directly. Pull only the smallest useful context via resolver or targeted read.
21
+ - **Non-trivial / Risky** auth, security, migration, uninstall, shared runtime, race/flaky, data-loss.
22
+ - Read deeper, verify harder, and avoid shortcuts.
23
+ - Use index-first loop, then skill activation, then targeted verification.
28
24
 
29
- ## Speed / Reading Contract
25
+ ## Execution Contract (mandatory)
30
26
 
31
- - **Trivial**: no docs.
32
- - **Simple**: `docs/MEMORY.md` only.
33
- - **Non-trivial**: `docs/MEMORY.md` + `docs/PROJECT.md` + `docs/CODE_MAP.md`.
34
- - `docs/STATUS.md`: read for open-ended status/continue prompts or meaningful continuation context; stale status is orientation only.
35
- - `docs/TASKS.md`: read only for queued-task prompts or when status points at queued work; safely clean exact duplicates/completed overflow by default without deleting unfinished human-authored tasks.
36
- - Read `docs/WORKLOG.md` only when recent continuation/debug context matters.
37
- - Source is truth; if docs are stale, update docs and continue.
27
+ - For explicit implement/apply/fix requests, **continue until the actual edit is made** or a real blocker is found.
28
+ - Do NOT stop after a read-only inspection step (Read/Grep/Glob/search).
29
+ - If routed state says `pull-indexed-context`, treat it as internal continuation — after the bounded read, **continue to edit/verify in the same turn** when safe.
30
+ - If routed state shows `continuation required` or a stuck-lane rescue mode, finish the named milestone before widening reads or repeating analysis.
31
+ - **Do NOT say "done", "applied", or "fixed" after Read/Grep/analysis alone.** Completion wording requires concrete Edit/Write evidence in the current turn, and verification when the scope is risky.
32
+
33
+ ## Index-First Loop
38
34
 
39
- ## Index-First Loop (for Codex)
35
+ For any task that needs code context:
40
36
 
41
- 1. Refresh/build the index only when needed:
37
+ 1. Check if index is fresh (`.cache/index/` artifacts). If stale or missing, refresh:
42
38
  - `node .codex/ukit/index/refresh-index.mjs`
43
39
  - fallback: `node .codex/ukit/index/build-index.mjs`
44
40
  2. Query likely files:
45
41
  - `node .codex/ukit/index/query-index.mjs "<error|symbol|path>"`
46
42
  3. For bug signatures:
47
43
  - `node .codex/ukit/index/triage.mjs "<error signature>"`
48
- 4. Open only the top 1-3 suspect files first, then widen if needed.
44
+ 4. Open only the **top 1-3 suspect files first**, then widen if needed.
45
+ 5. For analog/reuse patterns, check if `resolve-context` returns related existing patterns.
49
46
 
50
- For clearly non-code specialist lanes, avoid dragging the source-code index into the route unless the target is actually code.
47
+ For clearly non-code specialist lanes (docs-only, status, task queue), skip the source-code index.
51
48
 
52
- ## Automatic Skill Activation
49
+ ## Automatic Skill Activation (mandatory)
53
50
 
54
51
  - End users should not need to know skill names.
55
- - For every non-trivial task — and again after the first meaningful tool calls — inspect installed project-local skills and **auto-activate the matching skill immediately**.
52
+ - For every non-trivial task — and again after the first relevant tool calls — inspect installed project-local skills and **auto-activate the matching skill immediately**.
56
53
  - Match from prompt wording plus tool/file evidence.
57
- - Use the smallest useful set, usually 1-2 skills.
54
+ - Use the smallest effective set, usually 1-2 skills.
58
55
  - If docs work is detected, prefer `.codex/skills/docs-quality/SKILL.md`.
59
- - For open-ended what next?” / continue / project-status / queued-task prompts, prefer `.codex/skills/next-step/SKILL.md` and show a status freshness cue when status is used.
56
+ - For open-ended "what next?" / "continue" / project-status / queued-task prompts, prefer `.codex/skills/next-step/SKILL.md` and show a status freshness cue when status is used.
60
57
  - For explicit handoff/wrap-up/status updates, prefer `.codex/skills/update-status/SKILL.md`.
61
58
  - Concrete debug/implementation/review prompts beat open-ended wording; do not let `next-step` replace the concrete workflow.
62
59
  - If routing is complex or ambiguous, prefer `node .codex/ukit/index/route-task.mjs "<prompt>" [--tool-command <cmd>] [--target <file>]`.
63
- - That helper should keep shared route memory in `.claude/ukit/skill-router-state.json` so Claude and Codex continue from the same compact route state.
60
+ - Shared route memory in `.claude/ukit/skill-router-state.json` is shared across Claude and Codex.
64
61
  - When route memory already includes `previous-context` or `recent-output`, reuse it before widening reads or logs.
65
62
  - After routing, prefer `node .codex/ukit/index/resolve-context.mjs ...` for context and `node .codex/ukit/index/verify-context.mjs ...` for verification.
66
63
  - Follow routed verification policy: targeted first, widen only when scope/risk justifies it, ask before blanket broad runs.
67
64
 
65
+ ### Common skill triggers
66
+
67
+ - review / audit / diff / PR feedback → `.codex/skills/code-review/SKILL.md`
68
+ - bug / error / crash / triage / failing path → `.codex/skills/debugging-toolkit/SKILL.md`
69
+ - test / spec / coverage / fixture → `.codex/skills/testing-quality/SKILL.md`
70
+ - docs / README / changelog / handoff / editing `docs/` → `.codex/skills/docs-quality/SKILL.md`
71
+ - open-ended next step / project status / continue → `.codex/skills/next-step/SKILL.md`
72
+ - explicit handoff / wrap up / update `docs/STATUS.md` → `.codex/skills/update-status/SKILL.md`
73
+ - auth / security / token / permission / validation → `.codex/skills/discover-security/SKILL.md`
74
+ - stale workspace / reinstall / cleanup → `.codex/skills/repo-maintenance/SKILL.md`
75
+
76
+ ## Internal Helper Routing
77
+
78
+ - If routing is complex or ambiguous, prefer `node .codex/ukit/index/route-task.mjs "<prompt>" [--tool-command <cmd>] [--target <file>]`.
79
+ - If context is needed, prefer `node .codex/ukit/index/resolve-context.mjs ...`.
80
+ - If verification is needed, prefer `node .codex/ukit/index/verify-context.mjs ...`.
81
+ - **Treat helper commands as internal orchestration.** Run them yourself when needed; never ask end users to run them.
82
+
83
+ ## UKit v1.5.0 Shared Runtime
84
+
85
+ - Shared runtime state lives in `.ukit/storage/`.
86
+ - Treat `.ukit/storage/config.json` as the source of compact, token-pipeline, router, memory, validation, and Safe Patch guardrail toggles.
87
+ - Reuse `.ukit/storage/memory/` before asking users to restate prior decisions.
88
+ - For non-trivial work, prefer `ukit memory recall "<current task>"` before widening doc reads.
89
+ - Reusable cache state lives in `.ukit/storage/cache/prompt-cache.json`, `.ukit/storage/cache/compact-history.json`, `.ukit/storage/cache/compact-pressure.json`, `.ukit/storage/cache/output-history.json`, and preserved raw tool outputs under `.ukit/storage/cache/tee/`.
90
+ - Shared route memory lives in `.claude/ukit/skill-router-state.json` (shared across Claude and Codex).
91
+ - If an older repo still has a visible `ukit/` runtime root, rerun `ukit install`; UKit should migrate the shared runtime into hidden `.ukit/` when safe.
92
+ - Maintainers can inspect runtime state with `ukit status` and `ukit memory export`.
93
+ - Reuse compact `previous-context` / `recent-output` route snapshots before replaying raw history.
94
+ - Threshold-based compact pressure is internal orchestration; Codex users should not need to manage it manually.
95
+ - For Codex Desktop long sessions, UKit can use soft auto-compact handoffs. Default `compact.codexContext.compactTarget=150` means about 150 compact handoff lines (120-150 preferred, hard max 170), not 150 tokens.
96
+
97
+ ## Context + Verification Budget
98
+
99
+ - **Trivial**: no docs.
100
+ - **Simple**: `docs/MEMORY.md` only.
101
+ - **Non-trivial**: `docs/MEMORY.md` + `docs/PROJECT.md` + `docs/CODE_MAP.md`.
102
+ - `docs/STATUS.md`: read for open-ended status/continue prompts or meaningful continuation context; stale status is orientation only.
103
+ - `docs/TASKS.md`: read only for queued-task prompts or when status points at queued work; safely clean exact duplicates/completed overflow by default without deleting unfinished human-authored tasks.
104
+ - Read `docs/WORKLOG.md` only when recent continuation/debug context matters.
105
+ - Source is truth; if docs are stale, update docs and continue.
106
+
107
+ ## Living Status Workflow
108
+
109
+ - `docs/STATUS.md` is compact current state, not a transcript and not source truth.
110
+ - When the user asks "what next?", "continue", without a concrete target, use the `next-step` skill and show a freshness cue (fresh / possibly stale / stale / missing).
111
+ - Concrete debug/implementation/review prompts beat open-ended wording; use the concrete skill first and only use status as background.
112
+ - After meaningful work, use `update-status` to record state, verification, blockers, and next candidates; skip trivial/no-state-change tasks.
113
+ - `docs/TASKS.md` is a local AI task queue: prefer `Ready for AI` when asked to pick queued work, and clean duplicates/prune `Done Recently` safely.
114
+
115
+ ## Small-Task Maintainer (internal)
116
+
117
+ - UKit may route low-risk internal decisions to the `ukit-small-task-maintainer` subagent using `subagents.smallTaskModel` (default `unic-lite`).
118
+ - Use it for safe/reversible UKit chores: dọn `docs/TASKS.md`, queued-task classification, fast-vs-slow/safe-vs-risky lane decisions, skill-routing/step-budget hints, compact/summary decisions, docs/status summarization, auto-triage, queue maintenance, and small workspace cleanup.
119
+ - Run it as a sidecar/parallel lane only; do not block, replace, or slow the user task.
120
+ - If the small-task lane sees security, risky/shared code, release/publish, data-loss, architecture, deep-reasoning risk, weak context, or quality risk, it hands back to the main model.
121
+ - Always preserve the CoDev priority: quality > safety > speed > token discipline.
122
+
68
123
  ## Selective Subagent Usage (internal only)
69
124
 
70
125
  - Stay direct for trivial/simple work or tightly coupled code already localized by the index.
@@ -72,6 +127,12 @@ For clearly non-code specialist lanes, avoid dragging the source-code index into
72
127
  - Good triggers: noisy side lanes, 3+ independent investigations, long-running background work, or explicit plan/batch execution.
73
128
  - End users still only need `ukit install`; subagent choice is internal orchestration.
74
129
 
130
+ ## Safe Patch Protocol
131
+
132
+ - For risky/shared/large edits, prefer unique current-file anchors over line numbers or stale pasted blocks.
133
+ - Do not silently merge stale specs: if `old_string` is missing or ambiguous, re-read current source and ask whether to apply as-is, adapt, or skip.
134
+ - Preserve UTF-8 BOM/no-BOM and LF/CRLF for existing multilingual/user-authored files.
135
+
75
136
  ## Docs Discipline
76
137
 
77
138
  After significant work, update only what changed:
@@ -82,18 +143,29 @@ After significant work, update only what changed:
82
143
  - `docs/CODE_MAP.md`
83
144
  - `docs/PROJECT.md`
84
145
 
85
- ## Execution Contract
146
+ ## Adaptive Autonomy
86
147
 
87
- - For explicit implement/apply/fix requests, continue until the actual edit is made or a real blocker is found; do not stop after a read-only inspection step.
88
- - If routed state still says `pull-indexed-context`, treat it as an internal continuation step, not a stopping point; after the bounded read, continue to edit/verify in the same turn when safe.
89
- - If routed state shows `continuation required` or a stuck-lane rescue mode, finish the named milestone before widening reads or repeating the same partial analysis.
90
- - Do not say “done”, “applied”, or “fixed” after Read/Grep/analysis alone. Completion wording requires concrete Edit/Write evidence in the current turn, and verification when the scope is risky.
148
+ - `autonomy.level` in `.ukit/storage/config.json` controls how much UKit acts without asking first: `conservative` (ask more), `balanced` (default), `free-run` (auto-run more).
149
+ - End users should not need to change this; maintainers may tune it per-project.
91
150
 
92
151
  ## Skills
93
152
 
94
153
  Skills are shared from `.claude/skills/` via symlink at `.codex/skills/`.
95
154
 
155
+ ## Team Workflow Safety
156
+
157
+ - Do not teach normal contributors `ukit doctor`, `ukit diff`, `ukit uninstall`, or `ukit index ...` unless they are explicitly debugging UKit itself.
158
+ - If the workspace needs a refresh, prefer telling them to rerun `ukit install`.
159
+ - Keep scope tight, prefer the smallest correct change set, reuse existing code, and update docs when source changes.
160
+
96
161
  ## Codex Rulebase
97
162
 
98
163
  - `.codex/settings.json` — project-shared Codex safe-auto baseline
99
164
  - `.codex/settings.local.json` — machine-local overrides (kept on reinstall)
165
+
166
+ ## Completion Checklist
167
+
168
+ - Requirements implemented
169
+ - No unrelated changes
170
+ - Verification executed and reported
171
+ - Docs updated when source truth changed
@@ -4,16 +4,42 @@
4
4
 
5
5
  - Human-facing workflow should optimize for one remembered command: `ukit install`.
6
6
  - After install, normal work should feel natural inside **Claude/Codex/OpenCode** (and Antigravity when installed).
7
- - Quality first, then speed, then token discipline: do not waste reads, logs, or repeated helper output.
7
+ - **Quality first, then speed, then token discipline**: do not waste reads, logs, or repeated helper output.
8
+ - **Never stop after read-only steps.** For implement/apply/fix requests, continue to actual Edit/Write and verification in the same turn.
8
9
 
9
10
  ## Fast Task Classification
10
11
 
11
12
  - **Trivial** — typo, label, rename nhỏ, spacing, toggle flag, obvious config change.
12
- - Act directly. No doc reads. No planning.
13
+ - Act directly. No doc reads. No planning. No index.
13
14
  - **Simple** — 1-2 files, clear scope, existing pattern.
14
- - Handle directly. Pull only the smallest useful context.
15
+ - Handle directly. Pull only the smallest useful context via resolver or targeted read.
15
16
  - **Non-trivial / Risky** — auth, security, migration, uninstall, shared runtime, race/flaky, data-loss.
16
17
  - Read deeper, verify harder, and avoid shortcuts.
18
+ - Use index-first loop, then skill activation, then targeted verification.
19
+
20
+ ## Execution Contract (mandatory)
21
+
22
+ - For explicit implement/apply/fix requests, **continue until the actual edit is made** or a real blocker is found.
23
+ - Do NOT stop after a read-only inspection step (Read/Grep/Glob/search).
24
+ - If routed state says `pull-indexed-context`, treat it as internal continuation — after the bounded read, **continue to edit/verify in the same turn** when safe.
25
+ - If routed state shows `continuation required` or a stuck-lane rescue mode, finish the named milestone before widening reads or repeating analysis.
26
+ - **Do NOT say "done", "applied", or "fixed" after Read/Grep/analysis alone.** Completion wording requires concrete Edit/Write evidence in the current turn, and verification when the scope is risky.
27
+
28
+ ## Index-First Loop
29
+
30
+ For any task that needs code context:
31
+
32
+ 1. Check if index is fresh (`.cache/index/` artifacts). If stale or missing, refresh:
33
+ - `node .claude/ukit/index/refresh-index.mjs`
34
+ - fallback: `node .claude/ukit/index/build-index.mjs`
35
+ 2. Query likely files:
36
+ - `node .claude/ukit/index/query-index.mjs "<error|symbol|path>"`
37
+ 3. For bug signatures:
38
+ - `node .claude/ukit/index/triage.mjs "<error signature>"`
39
+ 4. Open only the **top 1-3 suspect files first**, then widen if needed.
40
+ 5. For analog/reuse patterns, check if `resolve-context` returns related existing patterns.
41
+
42
+ For clearly non-code specialist lanes (docs-only, status, task queue), skip the source-code index.
17
43
 
18
44
  ## Automatic Skill Activation (mandatory)
19
45
 
@@ -21,7 +47,6 @@
21
47
  - For every non-trivial task — and again after the first relevant tool calls — inspect installed project-local skills and **auto-activate the matching skill immediately**.
22
48
  - Match from both prompt wording and tool/file evidence.
23
49
  - Use the smallest effective set, usually 1-2 skills.
24
- - If the prompt/tool signals point to docs work, use `.claude/skills/docs-quality/SKILL.md` when present.
25
50
  - If evidence becomes more specific than the original prompt, upgrade the active skill choice immediately.
26
51
  - Prefer routed, compact context before widening manual reads.
27
52
 
@@ -43,18 +68,20 @@
43
68
  - If a concrete verification lane is needed, prefer `node .claude/ukit/index/verify-context.mjs ...`.
44
69
  - These helper/index commands are internal orchestration. Run them yourself when needed; never turn them into required end-user workflow.
45
70
 
46
- ## UKit v1.3.1 Shared Runtime
71
+ ## UKit v1.5.1 Shared Runtime
47
72
 
48
73
  - Shared runtime state lives in `.ukit/storage/`.
49
74
  - Treat `.ukit/storage/config.json` as the source of runtime toggles for compact, token pipeline, router, memory, validation, and Safe Patch behavior.
50
75
  - Reuse `.ukit/storage/memory/` before asking users to restate prior decisions.
51
76
  - For non-trivial work, prefer `ukit memory recall "<current task>"` before widening doc reads.
52
- - Reusable runtime cache lives in `.ukit/storage/cache/prompt-cache.json`, `.ukit/storage/cache/compact-history.json`, and `.ukit/storage/cache/output-history.json`.
77
+ - Reusable runtime cache lives in `.ukit/storage/cache/prompt-cache.json`, `.ukit/storage/cache/compact-history.json`, `.ukit/storage/cache/compact-pressure.json`, `.ukit/storage/cache/output-history.json`, and preserved raw tool outputs under `.ukit/storage/cache/tee/`.
53
78
  - Shared route memory lives in `.claude/ukit/skill-router-state.json`.
54
79
  - If shared route state already includes compact `previous-context` or `recent-output` lines, reuse those first before rescanning memory or replaying noisy logs.
55
80
  - If an older repo still has a visible `ukit/` runtime root, rerun `ukit install`; UKit should migrate the shared runtime into hidden `.ukit/` when safe.
56
81
  - Maintainers can inspect runtime state with `ukit status` and `ukit memory export`, but normal teammates should still only need `ukit install`.
57
82
  - If runtime files are missing/corrupt, tell maintainers to rerun `ukit install`.
83
+ - Threshold-based compact pressure is internal orchestration; do not expose it to users.
84
+ - For Codex Desktop long sessions, UKit can use soft auto-compact handoffs. Default `compact.codexContext.compactTarget=150` means about 150 compact handoff lines (120-150 preferred, hard max 170), not 150 tokens.
58
85
 
59
86
  ## Context + Verification Budget
60
87
 
@@ -69,19 +96,19 @@
69
96
  ## Living Status Workflow
70
97
 
71
98
  - `docs/STATUS.md` is compact current state, not a transcript and not source truth.
72
- - When the user asks what next?”, continue”, or project đang ở đâu?” without a concrete target, use the `next-step` skill and show a freshness cue (fresh / possibly stale / stale / missing).
99
+ - When the user asks "what next?", "continue", or "project đang ở đâu?" without a concrete target, use the `next-step` skill and show a freshness cue (fresh / possibly stale / stale / missing).
73
100
  - Concrete debug/implementation/review prompts beat open-ended wording; use the concrete skill first and only use status as background.
74
101
  - After meaningful work, use `update-status` to record state, verification, blockers, and next candidates; skip trivial/no-state-change tasks.
75
102
  - `docs/TASKS.md` is a local AI task queue: prefer `Ready for AI` when asked to pick queued work, and clean duplicates/prune `Done Recently` safely when reading/updating it.
76
- - Detailed task context files such as `docs/context/<slug>.md` are a future extension, not required baseline workflow.
77
-
78
103
 
79
104
  ## Small-Task Maintainer (internal)
80
105
 
81
106
  - UKit may route low-risk internal decisions to the `ukit-small-task-maintainer` subagent using `subagents.smallTaskModel` (default `unic-lite`).
82
107
  - Use it for safe/reversible UKit chores: dọn `docs/TASKS.md`, queued-task classification, fast-vs-slow/safe-vs-risky lane decisions, skill-routing/step-budget hints, agent context-budget decisions, compact/summary decisions, docs/status summarization, auto-triage, queue maintenance, and small workspace cleanup.
83
- - Run it as a sidecar/parallel lane only; do not block, replace, or slow the user task. Do not block the main AI flow: if the small-task lane sees security, risky/shared code, release/publish, data-loss, architecture, deep-reasoning risk, weak context, or quality risk, it hands back to the main model instead of asking the end user to decide.
84
- - This is optional internal orchestration config from `.ukit/storage/config.json`; never turn it into an end-user workflow. End users still only need `ukit install` and natural-language product work. Always preserve the CoDev priority: quality > safety > speed > token discipline. Keep Claude PreCompact/reinject and OpenCode native auto/prune compaction enabled. For Codex Desktop long sessions, `compact.codexContext.compactTarget` defaults to 150 compact handoff lines (120-150 preferred, hard max 170), decided internally by the small-task maintainer.
108
+ - Run it as a sidecar/parallel lane only; do not block, replace, or slow the user task.
109
+ - If the small-task lane sees security, risky/shared code, release/publish, data-loss, architecture, deep-reasoning risk, weak context, or quality risk, it hands back to the main model.
110
+ - This is optional internal orchestration config from `.ukit/storage/config.json`; never turn it into an end-user workflow.
111
+ - Always preserve the CoDev priority: quality > safety > speed > token discipline.
85
112
 
86
113
  ## Subagent Policy (internal only)
87
114
 
@@ -100,16 +127,28 @@
100
127
  - Safe Patch is internal orchestration: normal users still only need `ukit install` and natural language.
101
128
  - For risky/shared/large edits, prefer unique current-file anchors over line numbers or stale pasted blocks.
102
129
  - Do not silently merge stale specs: if `old_string` is missing or ambiguous, re-read current source and ask whether to apply as-is, adapt, or skip.
103
- - Preserve UTF-8 BOM/no-BOM and LF/CRLF for existing multilingual/user-authored files; use UKit safe patch helpers internally when normal Edit/Write may normalize bytes.
130
+ - Preserve UTF-8 BOM/no-BOM and LF/CRLF for existing multilingual/user-authored files.
131
+ - Use `node .claude/ukit/index/safe-patch.mjs` internally when normal Edit/Write may normalize bytes or when anchor-based matching is needed.
104
132
 
105
133
  ## Team Workflow Safety
106
134
 
107
135
  - Do not teach normal contributors `ukit doctor`, `ukit diff`, `ukit uninstall`, or `ukit index ...` unless they are explicitly debugging UKit itself.
108
136
  - If the workspace needs a refresh, prefer telling them to rerun `ukit install`.
109
137
  - Keep scope tight, prefer the smallest correct change set, reuse existing code, and update docs when source changes.
110
- - For explicit implement/apply/fix work, if routed state still says `pull-indexed-context`, treat it as internal continuation, not a stopping point; continue through the bounded read into edit/verify when safe.
111
- - If routed state shows `continuation required` or a stuck-lane rescue mode, finish the named milestone before widening reads or repeating a partial progress report.
112
- - Never end with “done/applied/fixed” language while write/verification evidence is still missing unless there is a real blocker.
138
+
139
+ ## Adaptive Autonomy
140
+
141
+ - `autonomy.level` in `.ukit/storage/config.json` controls how much UKit acts without asking first: `conservative` (ask more), `balanced` (default), `free-run` (auto-run more).
142
+ - End users should not need to change this; maintainers may tune it per-project.
143
+
144
+ ## Session Start — OpenCode
145
+
146
+ At the start of every OpenCode session, before working on the first task:
147
+ 1. Check `.claude/ukit/skill-router-state.json` — if `line` has route hints matching the current task, reuse them instead of re-routing from scratch.
148
+ 2. Note which skills are installed by scanning `.claude/skills/` (directory listing only); read the full SKILL.md only when a task triggers it.
149
+ 3. For every non-trivial task: run `/ukit-route <task summary>` immediately to get skill + context hints **before** writing any code.
150
+ 4. If the route result points to a skill, read that SKILL.md before acting — do not skip this step.
151
+ 5. If `.ukit/storage/config.json` has `router.enabled: true`, prefer the router's output over ad-hoc guessing.
113
152
 
114
153
  ## Environment Snapshot
115
154
 
@@ -123,8 +162,8 @@
123
162
  ## Skills
124
163
 
125
164
  - Canonical skills live in `.claude/skills/`.
126
- - Adapter mirrors may also exist, for example `.antigravity/skills/`.
127
- - OpenCode reads `AGENTS.md` plus the canonical `.claude/skills/` tree, so UKit keeps the OpenCode adapter lean and avoids a duplicate `.opencode/skills/` mirror.
165
+ - Adapter mirrors may also exist, for example `.codex/skills/` → `.claude/skills/` (symlink) and `.antigravity/skills/`.
166
+ - **OpenCode**: reads `AGENTS.md` at session start only — it does NOT auto-load `.claude/skills/`. The model must explicitly read the triggered SKILL.md (see Session Start section above).
128
167
  - If `opencode.json` ships `ukit-*` commands, treat them as internal helper entrypoints only and **never ask end users to run them**; humans should still only need `ukit install`.
129
168
 
130
169
  ## DuraOne Skill — Conditional Activation
@@ -4,7 +4,8 @@
4
4
 
5
5
  - Human-facing UKit workflow should collapse to one remembered command: `ukit install`.
6
6
  - After install, default to natural-language work inside Claude/Codex.
7
- - Optimize for output quality first, then speed, then token discipline.
7
+ - **Quality first, then speed, then token discipline.**
8
+ - **Never stop after read-only steps.** For implement/apply/fix requests, continue to actual Edit/Write and verification in the same turn.
8
9
 
9
10
  ## Fast Classification
10
11
 
@@ -12,6 +13,29 @@
12
13
  - **Simple**: keep scope tight; use the smallest useful context.
13
14
  - **Non-trivial / Risky**: read deeper, verify harder, and avoid shortcuts.
14
15
 
16
+ ## Execution Contract (mandatory)
17
+
18
+ - For explicit implement/apply/fix requests, **continue until the actual edit is made** or a real blocker is found.
19
+ - Do NOT stop after a read-only inspection step (Read/Grep/Glob/search).
20
+ - If routed state says `pull-indexed-context`, treat it as internal continuation — after the bounded read, **continue to edit/verify in the same turn** when safe.
21
+ - If routed state shows `continuation required` or a stuck-lane rescue mode, finish the named milestone before widening reads or repeating analysis.
22
+ - **Do NOT say "done", "applied", or "fixed" after Read/Grep/analysis alone.** Completion wording requires concrete Edit/Write evidence in the current turn, and verification when the scope is risky.
23
+
24
+ ## Index-First Loop
25
+
26
+ For any task that needs code context:
27
+
28
+ 1. Check if index is fresh (`.cache/index/` artifacts). If stale or missing, refresh:
29
+ - `node .claude/ukit/index/refresh-index.mjs`
30
+ - fallback: `node .claude/ukit/index/build-index.mjs`
31
+ 2. Query likely files:
32
+ - `node .claude/ukit/index/query-index.mjs "<error|symbol|path>"`
33
+ 3. For bug signatures:
34
+ - `node .claude/ukit/index/triage.mjs "<error signature>"`
35
+ 4. Open only the **top 1-3 suspect files first**, then widen if needed.
36
+
37
+ For clearly non-code specialist lanes (docs-only, status, task queue), skip the source-code index.
38
+
15
39
  ## Automatic Skill Activation (mandatory)
16
40
 
17
41
  - End users should not need to know skill names.
@@ -42,24 +66,28 @@
42
66
  - **Do not ask normal contributors to run internal helper commands**; run them yourself or tell them to rerun `ukit install`.
43
67
  - Do not ask normal contributors to memorize `ukit doctor`, `ukit diff`, `ukit uninstall`, or `ukit index ...` unless they explicitly need maintainer/debug help.
44
68
 
45
- ## UKit v1.4.2 Shared Runtime
69
+ ## UKit v1.5.1 Shared Runtime
46
70
 
47
71
  - Shared runtime state lives in `.ukit/storage/`.
48
72
  - Treat `.ukit/storage/config.json` as the source of runtime toggles for compact, token pipeline, router, memory, validation, and Safe Patch behavior.
49
73
  - Reuse `.ukit/storage/memory/` before asking users to restate decisions.
50
74
  - For non-trivial work, prefer `ukit memory recall "<current task>"` before widening doc reads.
51
- - Reusable cache/compact/output state lives in `.ukit/storage/cache/prompt-cache.json`, `.ukit/storage/cache/compact-history.json`, and `.ukit/storage/cache/output-history.json`.
75
+ - Reusable cache/compact/output state lives in `.ukit/storage/cache/prompt-cache.json`, `.ukit/storage/cache/compact-history.json`, `.ukit/storage/cache/compact-pressure.json`, and `.ukit/storage/cache/output-history.json`.
76
+ - Shared route memory lives in `.claude/ukit/skill-router-state.json`.
77
+ - If shared route state already includes compact `previous-context` or `recent-output`, reuse those first.
52
78
  - If an older repo still has a visible `ukit/` runtime root, rerun `ukit install`; UKit should migrate the shared runtime into hidden `.ukit/` when safe.
53
79
  - Maintainers can inspect runtime state with `ukit status` and `ukit memory export`.
54
80
  - If runtime files are missing or corrupt, tell maintainers to rerun `ukit install`.
55
-
81
+ - Threshold-based compact pressure is internal orchestration; do not expose it to users.
82
+ - For Codex Desktop long sessions, UKit can use soft auto-compact handoffs. Default `compact.codexContext.compactTarget=150` means about 150 compact handoff lines (120-150 preferred, hard max 170), not 150 tokens.
56
83
 
57
84
  ## Safe Patch Protocol
58
85
 
59
86
  - Safe Patch is internal orchestration: normal users still only need `ukit install` and natural language.
60
87
  - For risky/shared/large edits, prefer unique current-file anchors over line numbers or stale pasted blocks.
61
88
  - Do not silently merge stale specs: if `old_string` is missing or ambiguous, re-read current source and ask whether to apply as-is, adapt, or skip.
62
- - Preserve UTF-8 BOM/no-BOM and LF/CRLF for existing multilingual/user-authored files; use UKit safe patch helpers internally when normal Edit/Write may normalize bytes.
89
+ - Preserve UTF-8 BOM/no-BOM and LF/CRLF for existing multilingual/user-authored files.
90
+ - Use `node .claude/ukit/index/safe-patch.mjs` internally when normal Edit/Write may normalize bytes or when anchor-based matching is needed.
63
91
 
64
92
  ## Context + Verification Budget
65
93
 
@@ -75,18 +103,19 @@
75
103
 
76
104
  - `docs/STATUS.md` captures compact current state, active work, debug threads, blockers, verification, and next candidates.
77
105
  - It is not source truth and must not replace source/index-first investigation.
78
- - For what next?” / continue prompts without a concrete target, use `next-step` and show a freshness cue before relying on the status file.
106
+ - For "what next?" / "continue" prompts without a concrete target, use `next-step` and show a freshness cue before relying on the status file.
79
107
  - For concrete debug/implementation/review prompts, keep the concrete workflow primary even if the user asks for an approach or next step.
80
108
  - After meaningful work, use `update-status`; skip trivial/no-state-change tasks and avoid transcript-style noise.
81
109
  - `docs/TASKS.md` is a local AI task queue: prefer `Ready for AI` when asked to pick queued work, and clean duplicates/prune `Done Recently` safely when reading/updating it.
82
110
 
83
-
84
111
  ## Small-Task Maintainer (internal)
85
112
 
86
113
  - UKit may route low-risk internal decisions to the `ukit-small-task-maintainer` subagent using `subagents.smallTaskModel` (default `unic-lite`).
87
114
  - Use it for safe/reversible UKit chores: dọn `docs/TASKS.md`, queued-task classification, fast-vs-slow/safe-vs-risky lane decisions, skill-routing/step-budget hints, agent context-budget decisions, compact/summary decisions, docs/status summarization, auto-triage, queue maintenance, and small workspace cleanup.
88
- - Run it as a sidecar/parallel lane only; do not block, replace, or slow the user task. Do not block the main AI flow: if the small-task lane sees security, risky/shared code, release/publish, data-loss, architecture, deep-reasoning risk, weak context, or quality risk, it hands back to the main model instead of asking the end user to decide.
89
- - This is optional internal orchestration config from `.ukit/storage/config.json`; never turn it into an end-user workflow. End users still only need `ukit install` and natural-language product work. Always preserve the CoDev priority: quality > safety > speed > token discipline. Keep Claude PreCompact/reinject and OpenCode native auto/prune compaction enabled. For Codex Desktop long sessions, `compact.codexContext.compactTarget` defaults to 150 compact handoff lines (120-150 preferred, hard max 170), decided internally by the small-task maintainer.
115
+ - Run it as a sidecar/parallel lane only; do not block, replace, or slow the user task.
116
+ - If the small-task lane sees security, risky/shared code, release/publish, data-loss, architecture, deep-reasoning risk, weak context, or quality risk, it hands back to the main model.
117
+ - This is optional internal orchestration config from `.ukit/storage/config.json`; never turn it into an end-user workflow.
118
+ - Always preserve the CoDev priority: quality > safety > speed > token discipline.
90
119
 
91
120
  ## Selective Subagent Policy (internal only)
92
121
 
@@ -97,10 +126,7 @@
97
126
 
98
127
  ## Adaptive Autonomy
99
128
 
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.
129
+ - `autonomy.level` in `.ukit/storage/config.json` controls how much UKit acts without asking first: `conservative` (ask more), `balanced` (default), `free-run` (auto-run more).
104
130
  - End users should not need to change this; maintainers may tune it per-project.
105
131
 
106
132
  ## Project Snapshot
@@ -114,9 +140,9 @@
114
140
  - Keep scope tight.
115
141
  - Reuse existing code.
116
142
  - For explicit implement/apply/fix requests, keep working until the actual edit is made or a real blocker is found; do not stop after a read-only inspection step.
117
- - If routed state still says `pull-indexed-context`, treat it as an internal continuation step, not a stopping point; after the bounded read, continue to edit/verify in the same turn when safe.
143
+ - If routed state still says `pull-indexed-context`, treat it as an internal continuation step, not a stopping point.
118
144
  - If routed state shows `continuation required` or a stuck-lane rescue mode, finish the named milestone before widening reads or rephrasing the same partial status.
119
- - Never claim done”, applied”, or fixed after Read/Grep/analysis alone. Completion language requires concrete Edit/Write evidence in the current turn, plus verification when the change is risky.
145
+ - Never claim "done", "applied", or "fixed" after Read/Grep/analysis alone. Completion language requires concrete Edit/Write evidence in the current turn, plus verification when the change is risky.
120
146
  - Update `docs/WORKLOG.md` after significant work.
121
147
  - If source contradicts docs, update docs immediately.
122
148
  - Use `{{runtime.packageManager}}`.
@@ -1 +1 @@
1
- {"$schema":"https://opencode.ai/config.json","default_agent":"build","share":"disabled","compaction":{"auto":true,"prune":true,"reserved":10000},"watcher":{"ignore":[".git/**","node_modules/**",".cache/**",".claude/ukit/.ukit/**",".claude/ukit/permission-usage.json",".claude/ukit/permission-audit.log"]},"permission":{"doom_loop":"deny"},"command":{"ukit-route":{"description":"Internal shared UKit route.","agent":"build","template":"Run `node .claude/ukit/index/route-task.mjs \"<task>\" --adapter opencode`; reuse `.claude/ukit/skill-router-state.json`."},"ukit-context":{"description":"Internal UKit context.","agent":"build","template":"Run `node .claude/ukit/index/resolve-context.mjs \"<intent>\" [--target <file>]`."},"ukit-verify":{"description":"Internal UKit verify lane.","agent":"build","template":"Run `node .claude/ukit/index/verify-context.mjs \"<intent>\" [--target <file>]`."},"ukit-triage":{"description":"Internal UKit triage.","agent":"build","template":"Run `node .claude/ukit/index/triage.mjs \"<error>\"`."},"ukit-query":{"description":"Internal UKit query.","agent":"build","template":"Run `node .claude/ukit/index/query-index.mjs \"<error|symbol|path>\"`."},"ukit-index":{"description":"Internal UKit index.","agent":"build","template":"Run `node .claude/ukit/index/refresh-index.mjs` (fallback: `node .claude/ukit/index/build-index.mjs`)."}},"agent":{"build":{"description":"UKit coding agent; keep internal helpers hidden, users only need ukit install.","permission":{"edit":"allow","task":"allow","skill":"allow","bash":{"*":"ask","pwd":"allow","ls":"allow","ls *":"allow","find *":"allow","rg *":"allow","grep *":"allow","cat *":"allow","sed *":"allow","head *":"allow","tail *":"allow","wc *":"allow","git status":"allow","git status *":"allow","git diff":"allow","git diff *":"allow","git log":"allow","git log *":"allow","git show *":"allow","git grep *":"allow","git rev-parse *":"allow","node .claude/ukit/index/*":"allow","{{runtime.packageManager}} test":"allow","{{runtime.packageManager}} test *":"allow","{{runtime.packageManager}} lint":"allow","{{runtime.packageManager}} lint *":"allow","{{runtime.packageManager}} typecheck":"allow","{{runtime.packageManager}} typecheck *":"allow","{{runtime.packageManager}} build":"allow","{{runtime.packageManager}} build *":"allow","npm run test":"allow","npm run test *":"allow","npm run lint":"allow","npm run lint *":"allow","npm run typecheck":"allow","npm run typecheck *":"allow","npm run build":"allow","npm run build *":"allow","git commit":"ask","git commit *":"ask","git push":"ask","git push *":"ask","git clean":"deny","git clean *":"deny","git reset":"deny","git reset *":"deny","rm *":"deny"}}},"plan":{"permission":{"edit":"ask","bash":"ask"}}}}
1
+ {"$schema":"https://opencode.ai/config.json","default_agent":"build","share":"disabled","compaction":{"auto":true,"prune":true,"reserved":10000},"watcher":{"ignore":[".git/**","node_modules/**",".cache/**",".ukit/**",".claude/ukit/permission-usage.json",".claude/ukit/permission-audit.log"]},"permission":{"doom_loop":"deny"},"command":{"ukit-route":{"description":"Internal shared UKit route. Run at the start of every non-trivial task to get skill and context hints before writing code.","agent":"build","template":"Run `node .claude/ukit/index/route-task.mjs \"<task>\" --adapter opencode`; reuse `.claude/ukit/skill-router-state.json`."},"ukit-context":{"description":"Internal UKit context.","agent":"build","template":"Run `node .claude/ukit/index/resolve-context.mjs \"<intent>\" [--target <file>]`."},"ukit-verify":{"description":"Internal UKit verify lane.","agent":"build","template":"Run `node .claude/ukit/index/verify-context.mjs \"<intent>\" [--target <file>]`."},"ukit-triage":{"description":"Internal UKit triage.","agent":"build","template":"Run `node .claude/ukit/index/triage.mjs \"<error>\"`."},"ukit-query":{"description":"Internal UKit query.","agent":"build","template":"Run `node .claude/ukit/index/query-index.mjs \"<error|symbol|path>\"`."},"ukit-index":{"description":"Internal UKit index.","agent":"build","template":"Run `node .claude/ukit/index/refresh-index.mjs` (fallback: `node .claude/ukit/index/build-index.mjs`)."}},"agent":{"build":{"description":"UKit build agent. Follow AGENTS.md. For every non-trivial task: run /ukit-route first, use index-first loop, activate matching skill, never claim done after read-only steps. Keep internal ukit-* helpers hidden; users only need ukit install.","permission":{"edit":"allow","task":"allow","skill":"allow","bash":{"*":"ask","pwd":"allow","ls":"allow","ls *":"allow","find *":"allow","rg *":"allow","grep *":"allow","cat *":"allow","sed *":"allow","head *":"allow","tail *":"allow","wc *":"allow","echo *":"allow","printf *":"allow","awk *":"allow","tr *":"allow","cut *":"allow","sort *":"allow","uniq *":"allow","diff *":"allow","jq *":"allow","stat *":"allow","file *":"allow","which *":"allow","date *":"allow","basename *":"allow","dirname *":"allow","realpath *":"allow","xargs *":"allow","mkdir *":"allow","touch *":"allow","cp *":"allow","vitest *":"allow","jest *":"allow","git status":"allow","git status *":"allow","git diff":"allow","git diff *":"allow","git log":"allow","git log *":"allow","git show *":"allow","git grep *":"allow","git rev-parse *":"allow","git branch *":"allow","git stash list":"allow","git ls-files *":"allow","git tag *":"allow","node .claude/ukit/index/*":"allow","node .claude/ukit/runtime/*":"allow","{{runtime.packageManager}} test":"allow","{{runtime.packageManager}} test *":"allow","{{runtime.packageManager}} lint":"allow","{{runtime.packageManager}} lint *":"allow","{{runtime.packageManager}} typecheck":"allow","{{runtime.packageManager}} typecheck *":"allow","{{runtime.packageManager}} build":"allow","{{runtime.packageManager}} build *":"allow","npm run test":"allow","npm run test *":"allow","npm run lint":"allow","npm run lint *":"allow","npm run typecheck":"allow","npm run typecheck *":"allow","npm run build":"allow","npm run build *":"allow","pnpm test":"allow","pnpm test *":"allow","pnpm lint":"allow","pnpm lint *":"allow","pnpm typecheck":"allow","pnpm typecheck *":"allow","pnpm build":"allow","pnpm build *":"allow","pnpm run test":"allow","pnpm run test *":"allow","pnpm run lint":"allow","pnpm run lint *":"allow","pnpm run typecheck":"allow","pnpm run typecheck *":"allow","pnpm run build":"allow","pnpm run build *":"allow","bun test":"allow","bun test *":"allow","bun run test":"allow","bun run test *":"allow","bun run lint":"allow","bun run lint *":"allow","bun run typecheck":"allow","bun run typecheck *":"allow","bun run build":"allow","bun run build *":"allow","git commit":"ask","git commit *":"ask","git push":"ask","git push *":"ask","git clean":"deny","git clean *":"deny","git reset":"deny","git reset *":"deny","rm *":"deny"}}},"plan":{"permission":{"edit":"ask","bash":"ask"}}}}
@@ -1,6 +1,6 @@
1
1
  # UKit Shared Runtime
2
2
 
3
- This folder stores shared UKit runtime state for v1.4.4 features.
3
+ This folder stores shared UKit runtime state for v1.5.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,5 +1,5 @@
1
1
  {
2
- "version": "1.4.4",
2
+ "version": "1.5.1",
3
3
  "agent": "claude-code",
4
4
  "autonomy": {
5
5
  "level": "balanced",
@@ -147,6 +147,7 @@
147
147
  "safePatch": {
148
148
  "enabled": true,
149
149
  "strictSharedRisk": true,
150
+ "advisoryOnly": false,
150
151
  "largeFileLineThreshold": 800,
151
152
  "largeFileByteThreshold": 200000,
152
153
  "backupEnabled": true,
@@ -365,6 +366,7 @@
365
366
  "safePatch": {
366
367
  "enabled": "Bật Safe Patch Protocol: UKit âm thầm chặn patch stale/ambiguous trên file rủi ro và giữ an toàn encoding khi helper nội bộ sửa file.",
367
368
  "strictSharedRisk": "Nếu true, file runtime/shared-risk như .claude/hooks hoặc .claude/ukit sẽ bị guard chặt hơn; người dùng vẫn không cần nhớ command mới.",
369
+ "advisoryOnly": "Nếu true (hoặc env UKIT_SAFE_PATCH_ADVISORY=1), guard chỉ in WARNING thay vì exit 2 — tránh Claude/Codex dừng giữa chừng chờ user 'continue'. Vẫn giữ message để model tự retry.",
368
370
  "largeFileLineThreshold": "Số dòng từ đó file được xem là lớn và cần anchor/spec guard kỹ hơn.",
369
371
  "largeFileByteThreshold": "Kích thước byte từ đó file được xem là lớn/rủi ro khi agent edit.",
370
372
  "backupEnabled": "Nếu true, UKit tạo rollback bytes dưới .ukit/storage/backups cho edit rủi ro.",