@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.
Files changed (33) hide show
  1. package/CHANGELOG.md +57 -5
  2. package/README.md +2 -2
  3. package/manifests/platform.full.yaml +2 -2
  4. package/package.json +1 -1
  5. package/src/cli/commands/doctor.js +14 -2
  6. package/src/cli/commands/install.js +2 -2
  7. package/src/cli/commands/uninstall.js +1 -1
  8. package/src/index/taskRouting.js +117 -1
  9. package/templates/.claude/agents/bug-debugger.md +48 -19
  10. package/templates/.claude/agents/code-reviewer.md +86 -0
  11. package/templates/.claude/agents/feature-implementer.md +59 -18
  12. package/templates/.claude/hooks/skill-router.sh +1 -1
  13. package/templates/.claude/hooks/verification-guard.sh +1 -1
  14. package/templates/.claude/skills/next-step/SKILL.md +1 -1
  15. package/templates/.claude/ukit/index/post-edit-verify.mjs +3 -2
  16. package/templates/.claude/ukit/index/route-task.mjs +8 -4
  17. package/templates/.claude/ukit/runtime/output-compression.mjs +37 -1
  18. package/templates/AGENTS.md +7 -0
  19. package/templates/CLAUDE.md +8 -1
  20. package/templates/docs/AI_HANDOFF/ACTIVE.md +9 -0
  21. package/templates/docs/AI_HANDOFF/HISTORY.md +4 -0
  22. package/templates/docs/AI_HANDOFF/INDEX.md +13 -0
  23. package/templates/docs/AI_HANDOFF/PLAN.md +75 -0
  24. package/templates/docs/AI_HANDOFF/RULES.md +127 -0
  25. package/templates/docs/AI_HANDOFF/archive/.gitkeep +0 -0
  26. package/templates/docs/AI_HANDOFF/tasks/.gitkeep +0 -0
  27. package/templates/docs/AI_HANDOFF/tasks/_TEMPLATE.md +72 -0
  28. package/templates/docs/INSTALL.md +2 -2
  29. package/templates/docs/PROJECT.md +1 -1
  30. package/templates/docs/UKIT_USAGE_GUIDE.md +1 -1
  31. package/templates/docs/WORKLOG.md +11 -0
  32. package/templates/ukit/storage/config.json +93 -1
  33. 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 confidence is low or risk is high, ask one short clarifying question before deeper analysis
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
- - Implement directly
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
- - Smallest correct change set
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
- ### 4. Verify
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
- - Run existing tests if touched behavior has coverage: `yarn test` or project-specific
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
- ### 5. Report
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
- VERIFIED: [test output / manual check result]
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
- NEXT: [follow-up needed, or "nothing task complete"]
76
+ HANDOFF_TO_REVIEWER: yes | noreason
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
- - Add/update tests only when touched behavior already has coverage
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:-$(pwd)}"
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:-$(pwd)}"
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.md.\n');
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 && !/^- Full output:\s+/i.test(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,
@@ -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.
@@ -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,9 @@
1
+ # Active Handoff Cycle
2
+
3
+ - Status: `ready_for_next_cycle`
4
+ - Phase: `cleared`
5
+ - Updated:
6
+ - Updated by:
7
+ - Human decision needed: `no`
8
+
9
+ <!-- Snapshot only. Rules in RULES.md. Tasks in tasks/. Plan brainstorm in PLAN.md. -->
@@ -0,0 +1,4 @@
1
+ # Handoff History
2
+
3
+ | Cycle | Date | Summary |
4
+ |-------|------|---------|
@@ -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.md`
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.md`
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