@ngockhoale/ukit 1.5.2 → 1.5.5
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 +57 -5
- package/README.md +2 -2
- package/manifests/platform.full.yaml +2 -2
- package/package.json +1 -1
- package/src/cli/commands/doctor.js +14 -2
- package/src/cli/commands/install.js +2 -2
- package/src/cli/commands/uninstall.js +1 -1
- package/src/index/taskRouting.js +117 -1
- package/templates/.claude/agents/bug-debugger.md +48 -19
- package/templates/.claude/agents/code-reviewer.md +86 -0
- package/templates/.claude/agents/feature-implementer.md +59 -18
- package/templates/.claude/hooks/skill-router.sh +1 -1
- package/templates/.claude/hooks/verification-guard.sh +1 -1
- package/templates/.claude/skills/next-step/SKILL.md +1 -1
- package/templates/.claude/ukit/index/post-edit-verify.mjs +3 -2
- package/templates/.claude/ukit/index/route-task.mjs +8 -4
- package/templates/.claude/ukit/runtime/output-compression.mjs +37 -1
- package/templates/AGENTS.md +7 -0
- package/templates/CLAUDE.md +8 -1
- package/templates/docs/AI_HANDOFF/ACTIVE.md +9 -0
- package/templates/docs/AI_HANDOFF/HISTORY.md +4 -0
- package/templates/docs/AI_HANDOFF/INDEX.md +13 -0
- package/templates/docs/AI_HANDOFF/PLAN.md +75 -0
- package/templates/docs/AI_HANDOFF/RULES.md +127 -0
- package/templates/docs/AI_HANDOFF/archive/.gitkeep +0 -0
- package/templates/docs/AI_HANDOFF/tasks/.gitkeep +0 -0
- package/templates/docs/AI_HANDOFF/tasks/_TEMPLATE.md +72 -0
- package/templates/docs/INSTALL.md +2 -2
- package/templates/docs/PROJECT.md +1 -1
- package/templates/docs/UKIT_USAGE_GUIDE.md +1 -1
- package/templates/docs/WORKLOG.md +11 -0
- package/templates/ukit/storage/config.json +93 -1
- package/templates/docs/AI_HANDOFF.md +0 -118
|
@@ -8,48 +8,89 @@ tools: ["Read", "Edit", "Write", "Grep", "Glob", "Bash", "TodoWrite"]
|
|
|
8
8
|
|
|
9
9
|
Implement requested behavior with minimal scope drift.
|
|
10
10
|
|
|
11
|
+
**Two modes — auto-detect at start:**
|
|
12
|
+
- **Daily/ad-hoc mode** (DEFAULT): task didn't come from `docs/AI_HANDOFF/` → use the original lightweight workflow. Tests only when touched code already has coverage. No reviewer trigger.
|
|
13
|
+
- **Handoff mode**: task file is `docs/AI_HANDOFF/tasks/TASK-xxx.md` OR user explicitly invokes handoff (e.g. "execute task TASK-001") → activate full Quality Gate: test-first → green → reviewer.
|
|
14
|
+
|
|
15
|
+
If unsure, ask the user. Don't apply Handoff mode rules to a quick one-off fix.
|
|
16
|
+
|
|
11
17
|
## Workflow
|
|
12
18
|
|
|
13
19
|
### 1. Understand (< 30 seconds)
|
|
14
20
|
|
|
15
|
-
- Infer intent directly from user request (build/test/docs flow)
|
|
21
|
+
- Infer intent directly from user request (build/test/docs flow).
|
|
16
22
|
- Apply graduated doc budget:
|
|
17
23
|
- trivial: no docs
|
|
18
24
|
- simple: `docs/MEMORY.md` only
|
|
19
25
|
- non-trivial: `docs/MEMORY.md` + `docs/PROJECT.md` + `docs/CODE_MAP.md`
|
|
20
|
-
- Identify target files and existing patterns
|
|
21
|
-
- If
|
|
26
|
+
- Identify target files and existing patterns.
|
|
27
|
+
- If task came from handoff, read `tasks/TASK-xxx.md` and locate its **Test Plan** + **Verification Commands**.
|
|
28
|
+
- If confidence is low or risk is high, ask one short clarifying question before deeper analysis.
|
|
22
29
|
|
|
23
30
|
### 2. Plan Approach (< 1 minute)
|
|
24
31
|
|
|
25
|
-
- List files to create/modify (max diff)
|
|
26
|
-
-
|
|
32
|
+
- List files to create/modify (max diff).
|
|
33
|
+
- **Handoff mode only:** if no Test Plan exists in the task file and task is not `trivial`, write one inline before implementing (happy + ≥1 edge case; regression test if fixing a bug). In daily mode, skip this step.
|
|
34
|
+
|
|
35
|
+
### 3. Test First (RED) — Handoff mode
|
|
36
|
+
|
|
37
|
+
- Write the test(s) from §2 / from task Test Plan.
|
|
38
|
+
- Run them: must FAIL for the expected reason. Capture output.
|
|
39
|
+
- If test passes immediately → test is wrong or behavior already exists. Fix the test or stop and report.
|
|
40
|
+
- **Daily mode**: skip this step unless touched code already has tests (then follow original rule).
|
|
27
41
|
|
|
28
|
-
### 3. Implement
|
|
29
42
|
|
|
30
|
-
|
|
31
|
-
- Reuse existing code before creating new
|
|
32
|
-
- No unrelated changes or speculative refactors
|
|
33
|
-
- Follow project conventions (check `.claude/skills/` for patterns)
|
|
43
|
+
### 4. Implement (GREEN)
|
|
34
44
|
|
|
35
|
-
|
|
45
|
+
- Smallest correct change set to make the test pass.
|
|
46
|
+
- Reuse existing code before creating new.
|
|
47
|
+
- No unrelated changes or speculative refactors.
|
|
48
|
+
- Follow project conventions (check `.claude/skills/` for patterns).
|
|
36
49
|
|
|
37
|
-
|
|
38
|
-
- For SQL changes: verify with `EXPLAIN ANALYZE` on non-trivial queries
|
|
39
|
-
- Check no lint errors introduced
|
|
50
|
+
### 5. Verify (REQUIRED before DONE in Handoff mode; targeted in Daily mode)
|
|
40
51
|
|
|
41
|
-
|
|
52
|
+
- **Handoff mode**: run the task's Verification Commands fresh in this turn. Capture full output. If ANY test fails → status is `PARTIAL` or `BLOCKED`, never `DONE`.
|
|
53
|
+
- **Daily mode**: run existing tests if touched behavior has coverage; lint clean; targeted verification only.
|
|
54
|
+
- For SQL changes: verify with `EXPLAIN ANALYZE` on non-trivial queries.
|
|
55
|
+
- Check no lint errors introduced.
|
|
56
|
+
|
|
57
|
+
### 6. Report
|
|
42
58
|
|
|
43
59
|
```
|
|
44
60
|
STATUS: DONE | BLOCKED | PARTIAL
|
|
61
|
+
EXECUTOR_TOOL: [claude-code | kilo-code | codex | opencode | other]
|
|
62
|
+
EXECUTOR_MODEL: [exact model name you are running as — e.g. unic-code, claude-sonnet-4-5, gpt-5-mini. If you truly cannot tell, write "unknown" — reviewer treats unknown as suspicious and asks the human to confirm.]
|
|
63
|
+
EXECUTOR_SUBAGENT: [name of the subagent you are, if your host has multiple — e.g. "Kilo:code", "Claude:feature-implementer". Otherwise "-".]
|
|
45
64
|
SUMMARY: [1-2 sentences of what was implemented]
|
|
65
|
+
TEST_PLAN_FOLLOWED: [task §4 / inline / N/A — reason]
|
|
46
66
|
FILES_CHANGED:
|
|
47
67
|
- [file path]: [what changed]
|
|
48
|
-
|
|
68
|
+
TESTS_ADDED:
|
|
69
|
+
- [test file]: [test names]
|
|
70
|
+
VERIFICATION:
|
|
71
|
+
command: [exact command run]
|
|
72
|
+
result: [N pass / M fail / exit code]
|
|
73
|
+
output_excerpt: |
|
|
74
|
+
[last 5-10 lines of test output]
|
|
49
75
|
ISSUES: [any problems or edge cases, or "none"]
|
|
50
|
-
|
|
76
|
+
HANDOFF_TO_REVIEWER: yes | no — reason
|
|
77
|
+
NEXT: [follow-up needed, or "ready for review"]
|
|
51
78
|
```
|
|
52
79
|
|
|
80
|
+
> **Self-report rule:** UKit cannot force any tool/host to use a specific model. Your self-reported `EXECUTOR_MODEL` is how the reviewer (in another tool or subagent) knows what to compare against its own model. Misreporting → reviewer refuses and asks the human to confirm.
|
|
81
|
+
|
|
82
|
+
### 7. Trigger Reviewer — Handoff mode ONLY
|
|
83
|
+
|
|
84
|
+
- Daily mode: skip this step entirely. Just report and stop.
|
|
85
|
+
- Handoff mode + `STATUS: DONE` + `handoff.reviewer.enabled=true`:
|
|
86
|
+
- Set task status to `pending_review` in `docs/AI_HANDOFF/INDEX.md`.
|
|
87
|
+
- The next AI session (any tool, model from `handoff.reviewer.model`, MUST differ from executor) will pick `pending_review` task and run review.
|
|
88
|
+
- Do NOT dispatch reviewer in-process unless your host explicitly supports it AND can guarantee a different model — file-based handoff is the default.
|
|
89
|
+
|
|
53
90
|
## Rules
|
|
54
91
|
|
|
55
|
-
-
|
|
92
|
+
- **Iron law (Handoff mode):** no `DONE` without fresh PASS output in the current turn.
|
|
93
|
+
- **Daily mode:** original rule — add tests only when touched behavior already has coverage.
|
|
94
|
+
- If Handoff Test Plan says `N/A`, document why in the report and ensure manual verification ran.
|
|
95
|
+
- Never silently skip reviewer phase in Handoff mode; if disabled, say so explicitly in NEXT.
|
|
96
|
+
- Detection rule: if the task came from `docs/AI_HANDOFF/tasks/`, you are in Handoff mode. Otherwise Daily mode.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# Used from UserPromptSubmit and PreToolUse so end users do not need to name skills.
|
|
4
4
|
|
|
5
5
|
INPUT=$(cat)
|
|
6
|
-
PROJECT_ROOT="${CLAUDE_PROJECT_DIR:-$
|
|
6
|
+
PROJECT_ROOT="${CLAUDE_PROJECT_DIR:-$PWD}"
|
|
7
7
|
STATE_FILE="$PROJECT_ROOT/.claude/ukit/skill-router-state.json"
|
|
8
8
|
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
9
9
|
THRESHOLD_SCRIPT="$HOOK_DIR/../ukit/runtime/compact-threshold.mjs"
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# and does not jump to blanket verification when targeted evidence already exists.
|
|
4
4
|
|
|
5
5
|
INPUT=$(cat)
|
|
6
|
-
PROJECT_ROOT="${CLAUDE_PROJECT_DIR:-$
|
|
6
|
+
PROJECT_ROOT="${CLAUDE_PROJECT_DIR:-$PWD}"
|
|
7
7
|
STATE_FILE="$PROJECT_ROOT/.claude/ukit/skill-router-state.json"
|
|
8
8
|
ROUTE_CACHE_FILE="$PROJECT_ROOT/.claude/ukit/route-cache.json"
|
|
9
9
|
PROGRESS_FILE="$PROJECT_ROOT/.claude/ukit/verification-progress.json"
|
|
@@ -44,7 +44,7 @@ If stale or missing, downgrade confidence and verify with the smallest current t
|
|
|
44
44
|
## Input Order
|
|
45
45
|
|
|
46
46
|
Read only what is needed:
|
|
47
|
-
1. `docs/AI_HANDOFF.md` first when the prompt explicitly names handoff / `ukit:handoff` / brainstorm-to-task flow
|
|
47
|
+
1. `docs/AI_HANDOFF/ACTIVE.md` first when the prompt explicitly names handoff / `ukit:handoff` / brainstorm-to-task flow
|
|
48
48
|
2. `docs/STATUS.md` (or existing root `STATUS.md` fallback) for normal status/continue prompts
|
|
49
49
|
3. `docs/TASKS.md` only for queued-task prompts, “continue” with no active status, or when status points at queued work
|
|
50
50
|
4. `docs/CODE_MAP.md` only when navigation is needed
|
|
@@ -18,7 +18,8 @@ function getFilePath(payload = {}) {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
function isHandoffAuthoringFile(relativePath) {
|
|
21
|
-
return relativePath === 'docs/AI_HANDOFF.md'
|
|
21
|
+
return relativePath === 'docs/AI_HANDOFF.md'
|
|
22
|
+
|| relativePath.startsWith('docs/AI_HANDOFF/');
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
async function listManifestPaths(backupsRoot) {
|
|
@@ -200,7 +201,7 @@ async function main() {
|
|
|
200
201
|
process.stdout.write(`[ukit-safe-patch] ${result.message}\n`);
|
|
201
202
|
} else if (result.status === 'advisory') {
|
|
202
203
|
process.stderr.write(`[ukit-safe-patch] ${result.message}\n`);
|
|
203
|
-
process.stderr.write('[ukit-safe-patch] handoff authoring advisory — change is already written; continue updating docs/AI_HANDOFF
|
|
204
|
+
process.stderr.write('[ukit-safe-patch] handoff authoring advisory — change is already written; continue updating docs/AI_HANDOFF/.\n');
|
|
204
205
|
}
|
|
205
206
|
if (result.status === 'blocked') {
|
|
206
207
|
const advisory = isSafePatchAdvisoryOnly(runtimeConfig);
|
|
@@ -481,6 +481,7 @@ function formatDisplayRouteSummary(routeSummary = null, routingContext = {}) {
|
|
|
481
481
|
|
|
482
482
|
const segments = [
|
|
483
483
|
taskSegment,
|
|
484
|
+
extractRouteLineSegment(line, 'handoff'),
|
|
484
485
|
extractRouteLineSegment(line, 'targets'),
|
|
485
486
|
extractRouteLineSegment(line, 'tests'),
|
|
486
487
|
extractRouteLineSegment(line, 'styles'),
|
|
@@ -831,14 +832,14 @@ function deriveIntentMode({ promptText = '', commandText = '', targetFile = null
|
|
|
831
832
|
const openEndedStatus = hasOpenEndedStatusSignal(lower, raw) || taskQueueNext;
|
|
832
833
|
const concreteTask = hasConcreteTaskSignal(lower, raw, targetFile, { taskQueueNext });
|
|
833
834
|
|
|
834
|
-
if (docsSpecific) {
|
|
835
|
-
return 'docs-specific';
|
|
836
|
-
}
|
|
837
|
-
|
|
838
835
|
if (hasHandoffSignal(lower, raw)) {
|
|
839
836
|
return 'handoff';
|
|
840
837
|
}
|
|
841
838
|
|
|
839
|
+
if (docsSpecific) {
|
|
840
|
+
return 'docs-specific';
|
|
841
|
+
}
|
|
842
|
+
|
|
842
843
|
if (statusUpdate) {
|
|
843
844
|
return 'status-update';
|
|
844
845
|
}
|
|
@@ -1350,8 +1351,10 @@ function buildRouteSummary({
|
|
|
1350
1351
|
),
|
|
1351
1352
|
);
|
|
1352
1353
|
const nextActionCommand = compactHelperLane ? null : nextAction?.command ?? null;
|
|
1354
|
+
const handoffFile = routingContext.intentMode === 'handoff' ? 'docs/AI_HANDOFF/ACTIVE.md' : null;
|
|
1353
1355
|
const line = [
|
|
1354
1356
|
routingContext.taskType ? `task=${routingContext.taskType}` : null,
|
|
1357
|
+
handoffFile ? `handoff=${handoffFile}` : null,
|
|
1355
1358
|
formatCompactSegment('targets', primaryTargets),
|
|
1356
1359
|
formatCompactSegment('tests', relatedTests),
|
|
1357
1360
|
formatCompactSegment('styles', styleFiles),
|
|
@@ -1374,6 +1377,7 @@ function buildRouteSummary({
|
|
|
1374
1377
|
completionState,
|
|
1375
1378
|
continuationState,
|
|
1376
1379
|
intentMode: routingContext.intentMode ?? null,
|
|
1380
|
+
handoffFile,
|
|
1377
1381
|
delegateHint: delegationRecommendation?.hint ?? null,
|
|
1378
1382
|
nextActionType: nextAction?.type ?? null,
|
|
1379
1383
|
nextActionCommand,
|
|
@@ -1082,7 +1082,11 @@ function normalizeOutputSummaryForDedupe(summary) {
|
|
|
1082
1082
|
return String(summary ?? '')
|
|
1083
1083
|
.split(/\r?\n/)
|
|
1084
1084
|
.map((line) => String(line ?? '').trim())
|
|
1085
|
-
.filter((line) => line
|
|
1085
|
+
.filter((line) => line
|
|
1086
|
+
&& !/^- Full output:\s+/i.test(line)
|
|
1087
|
+
&& !/^-\s*FAIL(?:ED)?\b/i.test(line)
|
|
1088
|
+
&& !/^-\s*PASS\b/i.test(line)
|
|
1089
|
+
&& !/^-\s*(?:Test Files|Tests|Duration|Start at)\b/i.test(line))
|
|
1086
1090
|
.join('\n');
|
|
1087
1091
|
}
|
|
1088
1092
|
|
|
@@ -1131,6 +1135,16 @@ async function appendOutputHistory(projectRoot, entry) {
|
|
|
1131
1135
|
return nextDocument;
|
|
1132
1136
|
}
|
|
1133
1137
|
|
|
1138
|
+
async function findOutputHistoryEntry(projectRoot, command, summary) {
|
|
1139
|
+
const runtimePaths = buildRuntimePaths(projectRoot);
|
|
1140
|
+
const current = normalizeOutputHistoryDocument(await readJson(runtimePaths.outputHistoryPath, { entries: [] }));
|
|
1141
|
+
const lookupKey = [
|
|
1142
|
+
String(command ?? '').trim(),
|
|
1143
|
+
normalizeOutputSummaryForDedupe(summary),
|
|
1144
|
+
].join('\n').trim().toLowerCase();
|
|
1145
|
+
return current.entries.find((candidate) => buildOutputHistoryDedupeKey(candidate) === lookupKey) ?? null;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1134
1148
|
function shouldCompress(config) {
|
|
1135
1149
|
return Boolean(config?.tokenPipeline?.outputCompression);
|
|
1136
1150
|
}
|
|
@@ -1244,6 +1258,28 @@ async function main() {
|
|
|
1244
1258
|
exitCode,
|
|
1245
1259
|
projectRoot,
|
|
1246
1260
|
});
|
|
1261
|
+
|
|
1262
|
+
const historyMatch = await findOutputHistoryEntry(projectRoot, result.command, result.summary);
|
|
1263
|
+
if (historyMatch?.summary) {
|
|
1264
|
+
await appendOutputHistory(projectRoot, {
|
|
1265
|
+
timestamp: Date.now(),
|
|
1266
|
+
command: historyMatch.command,
|
|
1267
|
+
profile: historyMatch.profile,
|
|
1268
|
+
summary: historyMatch.summary,
|
|
1269
|
+
tokensBefore: historyMatch.tokensBefore,
|
|
1270
|
+
tokensAfter: historyMatch.tokensAfter,
|
|
1271
|
+
savedTokens: historyMatch.savedTokens,
|
|
1272
|
+
exitCode,
|
|
1273
|
+
rawSaved: historyMatch.rawSaved,
|
|
1274
|
+
rawPath: historyMatch.rawPath,
|
|
1275
|
+
rawBytes: historyMatch.rawBytes,
|
|
1276
|
+
recoveryReason: historyMatch.recoveryReason,
|
|
1277
|
+
truncated: historyMatch.truncated,
|
|
1278
|
+
});
|
|
1279
|
+
process.stdout.write(String(historyMatch.summary));
|
|
1280
|
+
return;
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1247
1283
|
const recoveryReason = buildRawOutputRecoveryReason({
|
|
1248
1284
|
exitCode,
|
|
1249
1285
|
tokensBefore: result.tokensBefore,
|
package/templates/AGENTS.md
CHANGED
|
@@ -83,6 +83,13 @@ For clearly non-code specialist lanes (docs-only, status, task queue), skip the
|
|
|
83
83
|
- Threshold-based compact pressure is internal orchestration; do not expose it to users.
|
|
84
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.
|
|
85
85
|
|
|
86
|
+
## Handoff Quality Gate — OPT-IN
|
|
87
|
+
|
|
88
|
+
Activates ONLY when work goes through `docs/AI_HANDOFF/` (user says "execute task TASK-xxx" or target is `docs/AI_HANDOFF/tasks/*.md`). Daily prompts → unchanged lightweight flow, no test-first/reviewer overhead.
|
|
89
|
+
|
|
90
|
+
In Handoff mode: read `docs/AI_HANDOFF/RULES.md` for the 4-phase spec (Idea+Plan → Create Tasks → Implement+Test → Review+Test), state machine, comment thread, and self-reported model contract. Config: `.ukit/storage/config.json` → `handoff.*`.
|
|
91
|
+
|
|
92
|
+
|
|
86
93
|
## Context + Verification Budget
|
|
87
94
|
|
|
88
95
|
- **Trivial**: no docs, no index query unless the file target is unclear.
|
package/templates/CLAUDE.md
CHANGED
|
@@ -89,6 +89,13 @@ For clearly non-code specialist lanes (docs-only, status, task queue), skip the
|
|
|
89
89
|
- Preserve UTF-8 BOM/no-BOM and LF/CRLF for existing multilingual/user-authored files.
|
|
90
90
|
- Use `node .claude/ukit/index/safe-patch.mjs` internally when normal Edit/Write may normalize bytes or when anchor-based matching is needed.
|
|
91
91
|
|
|
92
|
+
## Handoff Quality Gate — OPT-IN
|
|
93
|
+
|
|
94
|
+
CHỈ kích hoạt khi task đi qua `docs/AI_HANDOFF/` (user nói "execute task TASK-xxx" hoặc target là `docs/AI_HANDOFF/tasks/*.md`). Daily prompt → KHÔNG đụng, flow cũ giữ nguyên.
|
|
95
|
+
|
|
96
|
+
Khi Handoff mode: đọc `docs/AI_HANDOFF/RULES.md` để biết 4 phase (Idea+Plan → Create Tasks → Implement+Test → Review+Test) + state machine + comment thread + self-report model. Config: `.ukit/storage/config.json` → `handoff.*`.
|
|
97
|
+
|
|
98
|
+
|
|
92
99
|
## Context + Verification Budget
|
|
93
100
|
|
|
94
101
|
- **Trivial**: no docs.
|
|
@@ -96,7 +103,7 @@ For clearly non-code specialist lanes (docs-only, status, task queue), skip the
|
|
|
96
103
|
- **Non-trivial**: `docs/MEMORY.md` + `docs/PROJECT.md` + `docs/CODE_MAP.md`.
|
|
97
104
|
- `docs/STATUS.md`: use for open-ended status/continue prompts or meaningful continuation context; stale status is orientation only.
|
|
98
105
|
- `docs/TASKS.md`: use 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.
|
|
99
|
-
- `docs/WORKLOG.md`: only recent relevant entries.
|
|
106
|
+
- `docs/WORKLOG.md`: only recent relevant entries. Follow the Budget Rules at the top of the file; archive oldest entries to `docs/WORKLOG_ARCHIVE.md` when over limits.
|
|
100
107
|
- Follow routed verification policy: targeted first, widen only when risk/shared scope justifies it, ask before blanket broad runs.
|
|
101
108
|
|
|
102
109
|
## Living Status Workflow
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Handoff Task Index
|
|
2
|
+
|
|
3
|
+
<!--
|
|
4
|
+
Status values (xem RULES.md §Status state machine):
|
|
5
|
+
ready | in_progress | pending_review | changes_requested | critical_block | approved | approved_minor | blocked | done
|
|
6
|
+
|
|
7
|
+
Owner = tool đang giữ task: claude-code | kilo-code | codex | opencode | -
|
|
8
|
+
-->
|
|
9
|
+
|
|
10
|
+
| ID | Title | Priority | Size | Status | Owner | Reviewer | File |
|
|
11
|
+
|----|-------|----------|------|--------|-------|----------|------|
|
|
12
|
+
|
|
13
|
+
Updated:
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Handoff Plan
|
|
2
|
+
|
|
3
|
+
Status: `empty`
|
|
4
|
+
|
|
5
|
+
<!--
|
|
6
|
+
File này CHỈ dùng cho luồng Handoff Quality Gate.
|
|
7
|
+
Daily prompt / quick fix → KHÔNG cần đụng vào đây, UKit vẫn chạy flow cũ bình thường.
|
|
8
|
+
|
|
9
|
+
Chỉ kích hoạt khi user explicit đẩy việc qua handoff (ví dụ: "đưa vào handoff", "gom ý tưởng X").
|
|
10
|
+
|
|
11
|
+
QUALITY GATE: mỗi task split ra phải kèm Test Plan (xem mục bên dưới).
|
|
12
|
+
Không có Test Plan → task không được phép chuyển sang status `ready`.
|
|
13
|
+
-->
|
|
14
|
+
|
|
15
|
+
## 1. Intent / Goal
|
|
16
|
+
|
|
17
|
+
<!-- 1-2 câu mô tả thứ user muốn đạt. Không paste lại nguyên prompt. -->
|
|
18
|
+
|
|
19
|
+
## 2. Scope
|
|
20
|
+
|
|
21
|
+
- In scope:
|
|
22
|
+
- Out of scope:
|
|
23
|
+
- Risk surface (file/module rủi ro share):
|
|
24
|
+
|
|
25
|
+
## 3. Approach
|
|
26
|
+
|
|
27
|
+
<!-- Cách làm ngắn gọn. Reuse code có sẵn trước khi tạo mới. -->
|
|
28
|
+
|
|
29
|
+
## 4. Test Plan (REQUIRED — TDD-style)
|
|
30
|
+
|
|
31
|
+
Liệt kê test sẽ viết TRƯỚC khi code. Mỗi test phải có:
|
|
32
|
+
|
|
33
|
+
| # | Loại | Tên test | File | Expect | Pre-state |
|
|
34
|
+
|---|------|----------|------|--------|-----------|
|
|
35
|
+
| 1 | unit / integration / regression / e2e | `<tên test mô tả hành vi>` | `<path/to/file.test.js>` | `<output kỳ vọng cụ thể>` | `<input/fixture>` |
|
|
36
|
+
|
|
37
|
+
Bắt buộc tối thiểu:
|
|
38
|
+
|
|
39
|
+
- **Happy path**: hành vi chính chạy đúng.
|
|
40
|
+
- **Edge case**: ít nhất 1 (null/empty/boundary/concurrent…).
|
|
41
|
+
- **Regression** (nếu fix bug): test fail-trước-khi-fix, pass-sau-khi-fix.
|
|
42
|
+
|
|
43
|
+
Nếu task không thể test (config-only, doc-only, prototype throw-away): ghi `Test plan: N/A — lý do: <…>` và đính kèm phương án verify thủ công.
|
|
44
|
+
|
|
45
|
+
## 5. Verification Commands
|
|
46
|
+
|
|
47
|
+
Lệnh chính xác executor sẽ chạy:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# ví dụ:
|
|
51
|
+
# yarn test path/to/file.test.js
|
|
52
|
+
# yarn test --run
|
|
53
|
+
# node scripts/smoke.mjs
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 6. Acceptance Criteria
|
|
57
|
+
|
|
58
|
+
- [ ] Tất cả test ở Test Plan PASS (kèm output trong report).
|
|
59
|
+
- [ ] Không có regression ở suite liên quan.
|
|
60
|
+
- [ ] Reviewer (model riêng) báo `APPROVED` hoặc `APPROVED-WITH-MINOR`.
|
|
61
|
+
- [ ] Docs/CHANGELOG cập nhật nếu user-facing.
|
|
62
|
+
|
|
63
|
+
## 7. Task Split (Phase 2 — TDD-embedded, MANDATORY)
|
|
64
|
+
|
|
65
|
+
Khi human approve plan, AI tạo từng `tasks/TASK-xxx.md` theo cấu trúc ở `tasks/_TEMPLATE.md`.
|
|
66
|
+
|
|
67
|
+
**Mỗi TASK file BẮT BUỘC có:**
|
|
68
|
+
- `## Test Cases` — bảng test (loại, tên, expected, fixture) cho slice của task. Tối thiểu happy + 1 edge + regression nếu fix bug.
|
|
69
|
+
- `## Test Files` — đường dẫn cụ thể file test sẽ tạo/sửa.
|
|
70
|
+
- `## Verification Commands` — lệnh executor + reviewer đều chạy fresh.
|
|
71
|
+
- `## Acceptance Criteria`.
|
|
72
|
+
|
|
73
|
+
Task không kèm Test Cases + Test Files cụ thể → đánh `needs_breakdown`, không cho status `ready`.
|
|
74
|
+
|
|
75
|
+
Update `INDEX.md`: thêm row cho mỗi task mới với `Status: ready`, `Owner: -`.
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Handoff Rules
|
|
2
|
+
|
|
3
|
+
## Token Budget (MANDATORY)
|
|
4
|
+
|
|
5
|
+
- **Combined handoff reads must stay under 200 lines per request.**
|
|
6
|
+
- Read order: `ACTIVE.md` (if needed) → `INDEX.md` (scan tasks) → single `tasks/TASK-xxx.md` (implement one task).
|
|
7
|
+
- Do NOT read `RULES.md` every request — only when you need flow clarification.
|
|
8
|
+
- Do NOT read multiple task files in one request.
|
|
9
|
+
- If ACTIVE.md + INDEX.md + task file would exceed budget, read only the task file.
|
|
10
|
+
- Auto-compact: if any **state file** (`ACTIVE.md`, `INDEX.md`, or any single `tasks/TASK-xxx.md`) exceeds 80 lines, trigger `clear handoff` / split task. `PLAN.md` and `RULES.md` are reference/spec — exempt.
|
|
11
|
+
|
|
12
|
+
## How Human Submits Ideas
|
|
13
|
+
|
|
14
|
+
- Natural language is enough: `ukit:handoff`, `gom ý tưởng`, `chia task`, `đưa vào handoff`.
|
|
15
|
+
- If request is already a concrete task (clear file/logic/output, small enough to do now), bypass handoff and execute directly.
|
|
16
|
+
- If request is broad/ambiguous/multi-step, use handoff.
|
|
17
|
+
|
|
18
|
+
## Hard rule — All work stays in `docs/AI_HANDOFF/`
|
|
19
|
+
|
|
20
|
+
Mọi giao tiếp giữa các AI trong handoff CHỈ qua file dưới `docs/AI_HANDOFF/`:
|
|
21
|
+
|
|
22
|
+
- `PLAN.md` — brainstorm + Test Plan tổng (Phase 1).
|
|
23
|
+
- `INDEX.md` — bảng task + status (mọi phase đọc/ghi).
|
|
24
|
+
- `tasks/TASK-xxx.md` — nơi sống của từng task: Goal + Test Cases + Verification + Executor Report + Reviewer Verdict + **Discussion thread**.
|
|
25
|
+
- `ACTIVE.md` — snapshot cycle hiện tại.
|
|
26
|
+
- `archive/` — cycle cũ.
|
|
27
|
+
|
|
28
|
+
**Cấm**: AI gửi câu hỏi/comment qua chat tool khác, qua commit message, hay qua file ngoài thư mục này. Lý do: cross-tool/cross-subagent chỉ đồng bộ được qua file. AI nào không đọc folder này = không tham gia handoff.
|
|
29
|
+
|
|
30
|
+
### Discussion thread (AI-to-AI comments)
|
|
31
|
+
|
|
32
|
+
Khi cần hỏi-lại / push-back / gợi ý cho phase khác, AI ghi vào `## Discussion` của task file (template ở `tasks/_TEMPLATE.md`). Format:
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
### <YYYY-MM-DD> · <role: planner|executor|reviewer> · <tool/model>
|
|
36
|
+
<nội dung — gửi @planner / @executor / @reviewer nếu có người nhận>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Phase kế tiếp PHẢI đọc Discussion trước khi tiếp tục — coi như inbox.
|
|
40
|
+
|
|
41
|
+
## Handoff Flow (tool-agnostic, file-based state machine)
|
|
42
|
+
|
|
43
|
+
UKit handoff hoạt động qua **file state**. Anh tự chọn tool nào cho từng phase — Claude Code / Kilo Code / Codex / OpenCode / tool mới sau này — đều được. UKit chỉ care về **role của model**, không care tool.
|
|
44
|
+
|
|
45
|
+
3 phase × 3 role model:
|
|
46
|
+
|
|
47
|
+
- **Plan** — model mạnh nhất anh có (reasoning model). Có thể chạy ở bất kỳ tool nào hỗ trợ planning tốt.
|
|
48
|
+
- **Execute** — model rẻ-mà-vẫn-thông-minh (code model). Có thể là subagent code của Kilo, hay agent build của OpenCode, hay feature-implementer của Claude Code.
|
|
49
|
+
- **Review** — **MODEL KHÁC executor** (reasoning model thường tốt hơn). Có thể là tool khác, hoặc cùng tool nhưng subagent khác model (ví dụ Kilo có subagent code và subagent review riêng).
|
|
50
|
+
|
|
51
|
+
Hai mô hình triển khai đều hợp lệ:
|
|
52
|
+
- **Cross-tool**: ví dụ Claude (plan) → Kilo (execute) → Claude (review). Bridge qua file.
|
|
53
|
+
- **Same-tool different-subagent**: ví dụ Kilo:plan → Kilo:code → Kilo:review, miễn 3 subagent dùng MODEL khác nhau ở role tương ứng.
|
|
54
|
+
|
|
55
|
+
Mỗi tool/subagent đọc cùng `INDEX.md` + `tasks/TASK-xxx.md` → chọn task theo `status` → cập nhật status khi xong.
|
|
56
|
+
|
|
57
|
+
> **Quan trọng — UKit không enforce model:** `handoff.executor.cheapSmartModelHint` và `handoff.reviewer.model` trong `.ukit/storage/config.json` chỉ là **nhãn** để anh biết MUỐN dùng gì. Tool nào dùng model nào là do anh chọn trong settings của tool đó. UKit enforce contract bằng cách bắt executor TỰ KHAI `EXECUTOR_MODEL` trong Executor Report; reviewer so với chính nó và refuse nếu trùng. Vì vậy nếu trong Kilo anh để cả code-subagent và review-subagent đều dùng cùng model → reviewer sẽ tự refuse, không silent-pass.
|
|
58
|
+
|
|
59
|
+
### Status state machine
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
brainstorm ──[plan approved]──▶ ready ──[executor pick]──▶ in_progress
|
|
63
|
+
├─[PASS]──▶ pending_review
|
|
64
|
+
└─[FAIL]──▶ blocked
|
|
65
|
+
pending_review ──[reviewer]──▶ approved | approved_minor ──▶ done
|
|
66
|
+
├▶ changes_requested ──[fix]──▶ in_progress
|
|
67
|
+
└▶ critical_block ──[fix]──▶ in_progress
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 4 Phases
|
|
71
|
+
|
|
72
|
+
**Phase 1 — Idea + Plan** (smart/reasoning model)
|
|
73
|
+
- Human submit ideas (natural language).
|
|
74
|
+
- AI ghi vào `PLAN.md`: §1 Intent, §2 Scope, §3 Approach, **§4 Test Plan (bắt buộc TDD-style)**, §5 Verification Commands, §6 Acceptance Criteria.
|
|
75
|
+
- Output: PLAN.md đầy đủ, chờ human approve.
|
|
76
|
+
|
|
77
|
+
**Phase 2 — Create Tasks (TDD-embedded, MANDATORY)** (smart/reasoning model, thường cùng phase 1)
|
|
78
|
+
- Human approve plan → AI split `PLAN.md §7` sang nhiều `tasks/TASK-xxx.md`.
|
|
79
|
+
- **Mỗi TASK file BẮT BUỘC có Test Plan của riêng nó**, không chỉ trỏ về PLAN.md. Cụ thể:
|
|
80
|
+
- `§ Test Cases`: bảng test (loại, tên test, expected) cho phần task này — happy + ≥1 edge case + regression (nếu fix bug).
|
|
81
|
+
- `§ Test Files`: đường dẫn cụ thể file test sẽ tạo/sửa (ví dụ `tests/auth/login.test.js`).
|
|
82
|
+
- `§ Verification Commands`: lệnh executor sẽ chạy để xác nhận PASS.
|
|
83
|
+
- `§ Acceptance Criteria`: checklist.
|
|
84
|
+
- Nếu split mà task nào không kèm được Test Cases + Test Files cụ thể → task đó chưa đủ `ready`, đánh `needs_breakdown`.
|
|
85
|
+
- Update `INDEX.md`: thêm row mỗi task với status `ready`.
|
|
86
|
+
- Đây là **điểm cắt human-approval**: phase này xong, executor được phép pick.
|
|
87
|
+
- Mục tiêu: executor (cheap-smart model) đọc task file là biết NGAY test gì cần viết trước, KHÔNG phải tự suy diễn.
|
|
88
|
+
|
|
89
|
+
**Phase 3 — Implement + Test** (cheap-smart/code model)
|
|
90
|
+
- User: "execute next task" / "làm TASK-001" / "implement task 1".
|
|
91
|
+
- Executor đọc `INDEX.md` → pick `ready` task → đổi `in_progress` → **viết test trước → RED → implement → GREEN** → chạy Verification Commands fresh trong turn → append `## Executor Report` (gồm `EXECUTOR_TOOL`/`EXECUTOR_MODEL`/`EXECUTOR_SUBAGENT` + verification output) vào cuối task file → đổi status `pending_review`.
|
|
92
|
+
- KHÔNG được claim DONE nếu chưa có PASS fresh.
|
|
93
|
+
|
|
94
|
+
**Phase 4 — Review + Test** (reviewer model — KHÁC model executor)
|
|
95
|
+
- User: "review pending tasks" / "review TASK-001".
|
|
96
|
+
- Reviewer đọc INDEX → pick `pending_review` → đọc task file + diff → **so model với `EXECUTOR_MODEL`, refuse nếu trùng/unknown** → **re-run Verification Commands fresh** (không tin executor) → áp `code-review` skill → append `## Reviewer Verdict` vào task file (verdict + findings + reviewer model dùng) → đổi status:
|
|
97
|
+
- `approved` / `approved_minor` → cho phép `done`.
|
|
98
|
+
- `changes_requested` → executor phải fix Important → lặp Phase 3-4.
|
|
99
|
+
- `critical_block` → executor PHẢI fix → lặp Phase 3-4.
|
|
100
|
+
|
|
101
|
+
Nếu `handoff.reviewer.enabled=false`, Phase 4 skip nhưng phải log lý do vào task — bỏ Phase 4 là bỏ lưới an toàn cuối.
|
|
102
|
+
|
|
103
|
+
## Task Gate
|
|
104
|
+
|
|
105
|
+
A task is `ready` only when it has:
|
|
106
|
+
- Clear target files
|
|
107
|
+
- Clear action
|
|
108
|
+
- Dependencies stated
|
|
109
|
+
- **Test Plan** (PLAN.md §4) — happy path + ≥1 edge case (+ regression test nếu fix bug); hoặc `N/A` kèm lý do
|
|
110
|
+
- Verification command (lệnh executor sẽ chạy)
|
|
111
|
+
- Acceptance criteria
|
|
112
|
+
|
|
113
|
+
Missing any → `needs_breakdown`, `blocked`, or `needs_human`.
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
## Clear Handoff
|
|
117
|
+
|
|
118
|
+
1. Archive current cycle → `archive/cycle-NNN.md`.
|
|
119
|
+
2. If archive > 3 files → delete oldest, append 1-line summary to `HISTORY.md`.
|
|
120
|
+
3. Reset `ACTIVE.md` to empty template.
|
|
121
|
+
4. Clear `INDEX.md`.
|
|
122
|
+
5. Delete all files in `tasks/`.
|
|
123
|
+
6. Clear `PLAN.md`.
|
|
124
|
+
|
|
125
|
+
## Docs Sync
|
|
126
|
+
|
|
127
|
+
After cycle, update affected docs only: `WORKLOG.md`, `PROJECT.md`, `CODE_MAP.md`, `CHANGELOG.md`.
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# TASK-XXX — <short title>
|
|
2
|
+
|
|
3
|
+
<!--
|
|
4
|
+
Template cho mỗi task. Planner copy file này khi split PLAN.md sang task riêng.
|
|
5
|
+
File này BẮT BUỘC giữ structure: Goal + Test Cases + Test Files + Verification + Acceptance.
|
|
6
|
+
Mọi AI (planner / executor / reviewer) đọc và ghi vào file NÀY. Không trao đổi ngoài file.
|
|
7
|
+
-->
|
|
8
|
+
|
|
9
|
+
- Status: `ready` <!-- ready | in_progress | pending_review | changes_requested | critical_block | approved | approved_minor | blocked | done -->
|
|
10
|
+
- Owner: `-` <!-- tool đang giữ task -->
|
|
11
|
+
- Reviewer: `-` <!-- model name reviewer dùng, set ở Phase 4 -->
|
|
12
|
+
- Parent plan: `docs/AI_HANDOFF/PLAN.md` §<section>
|
|
13
|
+
|
|
14
|
+
## Goal
|
|
15
|
+
|
|
16
|
+
<!-- 1-2 câu mô tả slice này làm gì. -->
|
|
17
|
+
|
|
18
|
+
## Target Files
|
|
19
|
+
|
|
20
|
+
- `<path/to/source.js>` — <what changes>
|
|
21
|
+
|
|
22
|
+
## Test Cases (REQUIRED — TDD)
|
|
23
|
+
|
|
24
|
+
| # | Loại | Tên test | Expected | Pre-state / Fixture |
|
|
25
|
+
|---|------|----------|----------|---------------------|
|
|
26
|
+
| 1 | unit | `<describe behavior>` | `<concrete expected>` | `<input>` |
|
|
27
|
+
| 2 | edge | `<null/empty/boundary>` | `<expected>` | `<input>` |
|
|
28
|
+
| 3 | regression (nếu bug fix) | `<reproduces bug>` | RED before fix, GREEN after | `<repro input>` |
|
|
29
|
+
|
|
30
|
+
## Test Files
|
|
31
|
+
|
|
32
|
+
- `<tests/path/to/file.test.js>` — chứa các test ở trên.
|
|
33
|
+
|
|
34
|
+
## Verification Commands
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
yarn test tests/path/to/file.test.js
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Acceptance Criteria
|
|
41
|
+
|
|
42
|
+
- [ ] Mọi test ở §Test Cases PASS.
|
|
43
|
+
- [ ] Không regression ở suite liên quan.
|
|
44
|
+
- [ ] Reviewer verdict APPROVED hoặc APPROVED-WITH-MINOR.
|
|
45
|
+
- [ ] Docs/CHANGELOG cập nhật nếu user-facing.
|
|
46
|
+
|
|
47
|
+
## Dependencies
|
|
48
|
+
|
|
49
|
+
- (none) <!-- hoặc TASK-xxx phải done trước -->
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Discussion
|
|
54
|
+
|
|
55
|
+
<!--
|
|
56
|
+
AI nói chuyện với nhau Ở ĐÂY, không nói qua tool khác.
|
|
57
|
+
Format mỗi comment:
|
|
58
|
+
|
|
59
|
+
### <date> · <role: planner|executor|reviewer> · <tool/model>
|
|
60
|
+
<nội dung — câu hỏi, lưu ý, đề xuất, đẩy ngược về phase trước>
|
|
61
|
+
|
|
62
|
+
Reply lùn 1 level (####). Ghi rõ "→ @planner" / "→ @executor" / "→ @reviewer" nếu có người nhận cụ thể.
|
|
63
|
+
-->
|
|
64
|
+
|
|
65
|
+
(chưa có comment)
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
<!--
|
|
70
|
+
Phase 3 executor append `## Executor Report` BÊN DƯỚI dấu phân cách này.
|
|
71
|
+
Phase 4 reviewer append `## Reviewer Verdict` BÊN DƯỚI Executor Report.
|
|
72
|
+
-->
|
|
@@ -47,7 +47,7 @@ End users do not need to manage any of that manually.
|
|
|
47
47
|
Complete these files before first serious use:
|
|
48
48
|
- `docs/PROJECT.md`
|
|
49
49
|
- `docs/MEMORY.md`
|
|
50
|
-
- `docs/AI_HANDOFF
|
|
50
|
+
- `docs/AI_HANDOFF/`
|
|
51
51
|
- `docs/WORKLOG.md`
|
|
52
52
|
|
|
53
53
|
### 4) Open your AI tool
|
|
@@ -97,7 +97,7 @@ ukit install
|
|
|
97
97
|
Check that the docs baseline files exist and are filled in:
|
|
98
98
|
- `docs/PROJECT.md`
|
|
99
99
|
- `docs/MEMORY.md`
|
|
100
|
-
- `docs/AI_HANDOFF
|
|
100
|
+
- `docs/AI_HANDOFF/`
|
|
101
101
|
- `docs/WORKLOG.md`
|
|
102
102
|
|
|
103
103
|
---
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
|
|
45
45
|
1. Run `ukit memory recall "<current task>"` for non-trivial work; reuse relevant `## Previous Context` before asking the user to restate prior decisions
|
|
46
46
|
2. Read `docs/MEMORY.md` — architecture decisions, active constraints, known bugs
|
|
47
|
-
3. Read `docs/AI_HANDOFF.md` when continuing cross-AI planning, task breakdown, or task implementation handoff work
|
|
47
|
+
3. Read `docs/AI_HANDOFF/ACTIVE.md` when continuing cross-AI planning, task breakdown, or task implementation handoff work
|
|
48
48
|
4. Read `docs/CODE_MAP.md` if it exists — structural navigation index
|
|
49
49
|
5. Use the installed source-code index / routed helpers to localize the smallest relevant file + test set first
|
|
50
50
|
6. Scan recent `docs/WORKLOG.md` entries if continuing prior work
|
|
@@ -138,7 +138,7 @@ Project đang ở đâu, làm gì tiếp?
|
|
|
138
138
|
|
|
139
139
|
Expected UKit behavior:
|
|
140
140
|
1. auto-load the hidden next-step lane
|
|
141
|
-
2. read `docs/AI_HANDOFF.md` when the team is passing planning, task breakdown, or implementation context between AIs
|
|
141
|
+
2. read `docs/AI_HANDOFF/ACTIVE.md` when the team is passing planning, task breakdown, or implementation context between AIs
|
|
142
142
|
3. verify the handoff against source/index before treating it as authoritative
|
|
143
143
|
4. suggest only a few actionable next candidates
|
|
144
144
|
5. if the prompt names a concrete bug/feature/review target, keep the concrete workflow primary instead of producing a global roadmap
|