@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 +23 -0
- package/manifests/platform.full.yaml +20 -2
- package/package.json +1 -1
- package/src/cli/adapters.js +4 -0
- package/src/core/applyPlan.js +49 -8
- package/src/core/runtimeConfig.js +3 -1
- package/src/manifest/selectItems.js +2 -0
- package/templates/.claude/agents/ukit-small-task-maintainer.md +1 -1
- package/templates/.claude/ukit/index/post-edit-verify.mjs +12 -3
- package/templates/.claude/ukit/index/stale-spec-check.mjs +12 -2
- package/templates/.claude/ukit/runtime/safe-patch-core.mjs +10 -0
- package/templates/.codex/README.md +111 -39
- package/templates/AGENTS.md +56 -17
- package/templates/CLAUDE.md +41 -15
- package/templates/adapter-presets/opencode/opencode.template.json +1 -1
- package/templates/ukit/README.md +1 -1
- package/templates/ukit/storage/config.json +3 -1
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:
|
|
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:
|
|
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
package/src/cli/adapters.js
CHANGED
|
@@ -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
|
{
|
package/src/core/applyPlan.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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:
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
##
|
|
8
|
+
## Core UKit Rule
|
|
9
9
|
|
|
10
|
-
-
|
|
11
|
-
- After
|
|
12
|
-
-
|
|
13
|
-
- **
|
|
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
|
-
##
|
|
15
|
+
## Fast Task Classification
|
|
16
16
|
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
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
|
-
##
|
|
25
|
+
## Execution Contract (mandatory)
|
|
30
26
|
|
|
31
|
-
- **
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
- `
|
|
35
|
-
-
|
|
36
|
-
|
|
37
|
-
-
|
|
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
|
-
|
|
35
|
+
For any task that needs code context:
|
|
40
36
|
|
|
41
|
-
1.
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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
|
-
-
|
|
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
|
-
##
|
|
146
|
+
## Adaptive Autonomy
|
|
86
147
|
|
|
87
|
-
-
|
|
88
|
-
-
|
|
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
|
package/templates/AGENTS.md
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
|
|
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.
|
|
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`,
|
|
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
|
|
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.
|
|
84
|
-
-
|
|
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
|
|
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
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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`
|
|
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
|
package/templates/CLAUDE.md
CHANGED
|
@@ -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
|
-
-
|
|
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.
|
|
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
|
|
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
|
|
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.
|
|
89
|
-
-
|
|
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
|
|
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
|
|
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
|
|
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/**",".
|
|
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"}}}}
|
package/templates/ukit/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# UKit Shared Runtime
|
|
2
2
|
|
|
3
|
-
This folder stores shared UKit runtime state for v1.
|
|
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.
|
|
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.",
|