@ngockhoale/ukit 2.5.1 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/package.json +1 -1
- package/templates/.claude/agents/code-reviewer.md +12 -1
- package/templates/.claude/agents/feature-implementer.md +4 -2
- package/templates/.claude/agents/handoff-planner.md +36 -1
- package/templates/.claude/commands/ukit/handoff-clear.md +4 -0
- package/templates/.claude/commands/ukit/handoff-create.md +23 -7
- package/templates/.claude/commands/ukit/handoff-fullstack.md +172 -11
- package/templates/.claude/commands/ukit/handoff-implement.md +9 -2
- package/templates/.claude/commands/ukit/handoff-review.md +4 -1
- package/templates/.claude/commands/ukit/handoff-status.md +6 -2
- package/templates/.claude/hooks/handoff-model-guard.sh +24 -0
- package/templates/.claude/ukit/runtime/stop-coordinator.mjs +201 -11
- package/templates/.omp/RULES.md +9 -1
- package/templates/.omp/agents/code-reviewer.md +12 -1
- package/templates/.omp/agents/feature-implementer.md +4 -2
- package/templates/.omp/agents/handoff-planner.md +36 -1
- package/templates/AGENTS.md +14 -0
- package/templates/CLAUDE.md +14 -0
- package/templates/docs/AI_HANDOFF/RULES.md +37 -4
- package/templates/docs/AI_HANDOFF/SPEC.md +98 -0
- package/templates/docs/AI_HANDOFF/tasks/_TEMPLATE.md +4 -1
- package/templates/ukit/storage/config.json +47 -9
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to UKit are documented here.
|
|
4
4
|
|
|
5
|
+
## 2.6.0 - 2026-09-18
|
|
6
|
+
|
|
7
|
+
handoff-fullstack v2 — autonomous create→implement→review loop that runs to 100%
|
|
8
|
+
completion of all unfinished work, with a mandatory detailed SPEC gate.
|
|
9
|
+
|
|
10
|
+
- **Never-stall Stop gate**: `stop-coordinator.mjs` gained a `handoff-cursor` lane that
|
|
11
|
+
reads `docs/AI_HANDOFF/RUN.md` and blocks stop while `Phase:` is not `done`/`blocked`,
|
|
12
|
+
carrying the cursor's `Next:` step. Liveness breaker releases after
|
|
13
|
+
`handoff.fullstack.stopGateMaxStalledBlocks` (default 12) un-advancing blocks; the lane
|
|
14
|
+
is advisory-on-failure and `stopGateEnabled` disables it. This fixes the observed
|
|
15
|
+
stall where runs went idle after a recap.
|
|
16
|
+
- **Mandatory SPEC.md**: `handoff-create` now writes `docs/AI_HANDOFF/SPEC.md` — a
|
|
17
|
+
15-section template (FRs with Given/When/Then, fullstack scope, data model, API
|
|
18
|
+
contract, test matrix, acceptance criteria, migration, chosen defaults) — before task
|
|
19
|
+
files. Tasks carry `Spec references`; `handoff-model-guard.sh` hard-blocks fresh task
|
|
20
|
+
creation without a filled SPEC (`handoff.fullstack.specRequired=false` bypasses).
|
|
21
|
+
- **Autonomous loop contract**: only `HANDOFF FULLSTACK COMPLETE` / `HANDOFF FULLSTACK
|
|
22
|
+
BLOCKED` may end a run; `CHECKPOINT — WORK CONTINUING` replaces bare recaps. Phase 0
|
|
23
|
+
sweeps INDEX, task files, HISTORY/archive, `docs/TASKS.md` Ready-for-AI, and
|
|
24
|
+
uncommitted WIP. Stuck tasks recover via `cancelled_superseded` + `TASK-xxx-R<n>`
|
|
25
|
+
replacement tasks. `idleWatchdogMin` (default 5) scheduled wakeups keep the loop
|
|
26
|
+
alive off-Claude-Code; `quietScansRequired` (default 2) guards completion; Phase F
|
|
27
|
+
runs docs sync → `archive/cycle-NN/` → `Phase: done` → marker report.
|
|
28
|
+
- **Agent + command wiring**: `handoff-planner` gained legacy-sweep and SPEC-authoring
|
|
29
|
+
phases; `code-reviewer` reviews SPEC+PLAN against a 7-point spec quality gate;
|
|
30
|
+
`feature-implementer` treats `Spec references` as outranking task-file wording;
|
|
31
|
+
`handoff-implement`/`handoff-review` codify spec-is-the-contract and `-R<n>`
|
|
32
|
+
recovery. `handoff-clear` archives SPEC and must close RUN.md; `handoff-status`
|
|
33
|
+
reports run phase + spec presence.
|
|
34
|
+
- **Config**: `handoff.fullstack.*` keys (`stopGateEnabled`, `stopGateMaxStalledBlocks`,
|
|
35
|
+
`quietScansRequired`, `idleWatchdogMin`, `autoArchive`, `specRequired`) with `_help`
|
|
36
|
+
notes, in both config trees.
|
|
37
|
+
|
|
5
38
|
## 2.5.1 - 2026-09-18
|
|
6
39
|
|
|
7
40
|
Post-release fixes from C20 reviewer advisories.
|
package/package.json
CHANGED
|
@@ -127,17 +127,28 @@ Same model is the most common silent failure. Do not skip this check.
|
|
|
127
127
|
### Inputs you expect
|
|
128
128
|
|
|
129
129
|
- Path to the spec/plan document (e.g. `docs/plans/*.md`). No diff, no task file, no executor report — review the document itself.
|
|
130
|
+
- When invoked from the handoff pipeline you get BOTH `docs/AI_HANDOFF/SPEC.md` and `docs/AI_HANDOFF/PLAN.md`. Review them as one unit: the spec is the contract, the plan is the decomposition. Verdicts still append to PLAN.md's `## Plan Review Log`.
|
|
130
131
|
|
|
131
132
|
### Review order
|
|
132
133
|
|
|
133
134
|
| Category | What to look for |
|
|
134
135
|
|---|---|
|
|
135
136
|
| Completeness | TODO/TBD/placeholders, incomplete sections |
|
|
136
|
-
| Consistency | internal contradictions, conflicting requirements |
|
|
137
|
+
| Consistency | internal contradictions, conflicting requirements; SPEC and PLAN contradicting each other |
|
|
137
138
|
| Clarity | requirements ambiguous enough to cause a wrong build |
|
|
138
139
|
| Scope | focused enough for one plan, not silently covering multiple subsystems |
|
|
139
140
|
| YAGNI | unrequested features, over-engineering |
|
|
140
141
|
|
|
142
|
+
**Handoff spec quality gate** (only when reviewing `docs/AI_HANDOFF/SPEC.md`):
|
|
143
|
+
|
|
144
|
+
1. Every functional requirement is testable — Given/When/Then or a command, never "should work".
|
|
145
|
+
2. Every applicable fullstack layer is covered or explicitly `N/A` with a reason.
|
|
146
|
+
3. Every FR traces forward to plan scope; nothing in the plan is unbacked by the spec.
|
|
147
|
+
4. Dependencies between parts are explicit.
|
|
148
|
+
5. Legacy/unfinished work discovered by the Phase 0 sweep is either planned or recorded out-of-scope.
|
|
149
|
+
6. Rollback/migration impact is addressed when data or schema changes.
|
|
150
|
+
7. No vague instruction survives — "improve UI", "faster", "better UX" without defined behavior fails Clarity.
|
|
151
|
+
|
|
141
152
|
Only flag issues that would cause real problems during implementation planning. Approve unless there are serious gaps that would lead to a flawed plan.
|
|
142
153
|
|
|
143
154
|
### Output
|
|
@@ -19,8 +19,10 @@ reasoning to the parent agent so it can decide whether to re-route.
|
|
|
19
19
|
**In Handoff mode you are running unattended — ask nothing.** You were spawned by an
|
|
20
20
|
orchestrator driving a pipeline; there is no human in your conversation to answer, and a
|
|
21
21
|
question there is silently dropped while the run stalls. Resolve ambiguity in this order:
|
|
22
|
-
the task file → `
|
|
23
|
-
|
|
22
|
+
the task file → the `Spec references` sections of `SPEC.md` → `PLAN.md` → the surrounding
|
|
23
|
+
code's existing patterns → the choice you would recommend. The spec is the contract; if the
|
|
24
|
+
task file and spec disagree, implement the spec and note it in the task's `## Discussion`
|
|
25
|
+
thread. Record what you chose and why in that thread. Only a blocker
|
|
24
26
|
outside the repo (missing credential, unreachable service) justifies reporting `FAIL` early —
|
|
25
27
|
and even then, report it, don't ask about it.
|
|
26
28
|
|
|
@@ -55,6 +55,35 @@ Before writing any path or command into `PLAN.md` or a task file, verify it:
|
|
|
55
55
|
If something cannot be verified, say so in the task's `## Discussion` rather than guessing.
|
|
56
56
|
A stated unknown costs the executor one read; a wrong path costs it a round.
|
|
57
57
|
|
|
58
|
+
## Phase 0 — Legacy sweep (before writing anything)
|
|
59
|
+
|
|
60
|
+
The plan owns ALL unfinished work, not only the new request. Scan and fold in:
|
|
61
|
+
|
|
62
|
+
- `INDEX.md` rows that are not `done`/`cancelled_superseded`.
|
|
63
|
+
- Task files in stale `in_progress` / `blocked` / `changes_requested` /
|
|
64
|
+
`needs_executor_report` / `needs_breakdown` from dead sessions.
|
|
65
|
+
- `docs/AI_HANDOFF/HISTORY.md` + `archive/` — cycles closed with leftovers.
|
|
66
|
+
- `docs/TASKS.md` — `Ready for AI` items are newly-assigned work.
|
|
67
|
+
- `git status` — uncommitted work-in-progress (finish or checkpoint, never drop silently).
|
|
68
|
+
|
|
69
|
+
Every discovered item becomes either a task row in the new plan or an explicitly recorded
|
|
70
|
+
out-of-scope line in PLAN.md §2. Silent omission is a plan defect.
|
|
71
|
+
|
|
72
|
+
**Recovery:** a stuck task record that cannot be cleanly resumed (orphaned worktree,
|
|
73
|
+
contradicting reports, invalid state) is marked `cancelled_superseded` and replaced by
|
|
74
|
+
`TASK-xxx-R1` (`-R2`, …) carrying the same spec references, acceptance criteria and
|
|
75
|
+
verification — link both files' `## Discussion` threads.
|
|
76
|
+
|
|
77
|
+
## Phase 0.5 — Write SPEC.md
|
|
78
|
+
|
|
79
|
+
Write `docs/AI_HANDOFF/SPEC.md` from the template at `templates/docs/AI_HANDOFF/SPEC.md`
|
|
80
|
+
(15 sections). The spec is the contract executors implement against — concrete enough that
|
|
81
|
+
nothing is guessed: exact paths, module and API names, schemas, validation rules,
|
|
82
|
+
permissions, empty/error states, migration behavior, test expectations. Every section is
|
|
83
|
+
filled or marked `N/A — <reason>`; every open question is resolved to a chosen default
|
|
84
|
+
recorded in §14. A vague line ("improve UI", "make it faster" with no number) is a spec
|
|
85
|
+
defect — fix it before writing tasks.
|
|
86
|
+
|
|
58
87
|
## Phase 1 — Write PLAN.md
|
|
59
88
|
|
|
60
89
|
Write all 7 sections to `docs/AI_HANDOFF/PLAN.md`:
|
|
@@ -101,6 +130,7 @@ Use `_TEMPLATE.md` structure (from pre-read context or file).
|
|
|
101
130
|
|
|
102
131
|
| Field | Rule |
|
|
103
132
|
|-------|------|
|
|
133
|
+
| Spec references | SPEC.md section/FR IDs this task implements — every task traces to the spec |
|
|
104
134
|
| Target Files | Exact paths — no two tasks in same wave share a file |
|
|
105
135
|
| Dependencies | `TASK-xxx` or `none` — wave order is inferred from this |
|
|
106
136
|
| Test Cases | Type \| Test Name \| Expected — ≥1 happy + ≥2 edge cases of different kinds |
|
|
@@ -160,6 +190,7 @@ most chains are ordering preferences that a wide wave 1 would satisfy just as we
|
|
|
160
190
|
```
|
|
161
191
|
Cycle: <ID> Date: <YYYY-MM-DD> Base: <current HEAD branch>
|
|
162
192
|
Goal: <1 sentence>
|
|
193
|
+
Spec: docs/AI_HANDOFF/SPEC.md
|
|
163
194
|
Tasks: <N> total
|
|
164
195
|
Status: planning_done — ready for executor
|
|
165
196
|
```
|
|
@@ -179,6 +210,8 @@ catches it:
|
|
|
179
210
|
2. Does every task trace back to something in §1/§6? A task nothing asks for is scope creep — cut it.
|
|
180
211
|
3. Do the tasks together actually deliver §1's success definition, or only the easy part of it? State the gap if there is one.
|
|
181
212
|
4. Is the *unhappy* path planned — errors, empty input, permissions, migration of existing data — or only the feature?
|
|
213
|
+
4b. Does every task carry `Spec references` into SPEC.md, and does every SPEC.md FR trace to at least one task? A spec section no task implements is a silent hole.
|
|
214
|
+
4c. Did the Phase 0 sweep leave anything unplanned — stale tasks, legacy leftovers, Ready-for-AI items, uncommitted WIP — without a §2 out-of-scope line?
|
|
182
215
|
|
|
183
216
|
**Correctness — is anything wrong?**
|
|
184
217
|
5. Every `Target Files` path verified per Grounding? Any `(new)` file marked as such?
|
|
@@ -195,7 +228,7 @@ catches it:
|
|
|
195
228
|
Append the result to `PLAN.md`:
|
|
196
229
|
```
|
|
197
230
|
## Planner Self-Audit
|
|
198
|
-
Checklist:
|
|
231
|
+
Checklist: 14/14 pass
|
|
199
232
|
Fixed during audit: <what you changed, or "nothing">
|
|
200
233
|
Known gaps: <what you deliberately left out and why, or "none">
|
|
201
234
|
```
|
|
@@ -209,6 +242,8 @@ Keep the returned message under 25 lines — the caller may be an orchestrator w
|
|
|
209
242
|
budget is the constraint on the whole run. Detail belongs in `PLAN.md`, not in the reply.
|
|
210
243
|
|
|
211
244
|
- Task count + IDs
|
|
245
|
+
- Spec path + one-line coverage statement (`SPEC.md §5 FR-001→TASK-003`, …)
|
|
246
|
+
- Recovery/superseded pairs (`TASK-007 → TASK-007-R1`) | none
|
|
212
247
|
- Dependency graph (text form: TASK-001 → TASK-003, TASK-002 independent)
|
|
213
248
|
- Wave plan: `wave 1: N tasks | wave 2: M tasks` — flag it if the graph is mostly a chain
|
|
214
249
|
- Self-audit result + any `Known gaps`
|
|
@@ -37,6 +37,7 @@ Write `docs/AI_HANDOFF/archive/cycle-NNN.md` (if there is anything worth archivi
|
|
|
37
37
|
```
|
|
38
38
|
# Cycle NNN — <YYYY-MM-DD> — ABORTED
|
|
39
39
|
## Summary: cycle was cleared before completion
|
|
40
|
+
## Spec: <copy SPEC.md — or note its path if archived separately>
|
|
40
41
|
## Tasks: <copy INDEX.md table as-is>
|
|
41
42
|
```
|
|
42
43
|
If `archive/` has > 3 files → delete oldest, append 1-line summary to `HISTORY.md`.
|
|
@@ -45,8 +46,11 @@ If `archive/` has > 3 files → delete oldest, append 1-line summary to `HISTORY
|
|
|
45
46
|
|
|
46
47
|
```
|
|
47
48
|
PLAN.md → "# PLAN\n_(empty)_"
|
|
49
|
+
SPEC.md → restore the untouched template (keep section headings, clear content)
|
|
48
50
|
INDEX.md → empty table header only
|
|
49
51
|
ACTIVE.md → "# ACTIVE\n_(no active cycle)_"
|
|
52
|
+
RUN.md → set `Phase: done` (or delete) — a live non-done cursor makes the Stop gate
|
|
53
|
+
refuse the next session's stops; clearing a cycle MUST close the cursor.
|
|
50
54
|
tasks/TASK-*.md → delete all (keep _TEMPLATE.md)
|
|
51
55
|
```
|
|
52
56
|
|
|
@@ -69,7 +69,21 @@ The planner agent does the following (use Step 1 summary — do NOT re-read file
|
|
|
69
69
|
BASE=$(git symbolic-ref --short HEAD)
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
3. Write `docs/AI_HANDOFF/
|
|
72
|
+
3. Write `docs/AI_HANDOFF/SPEC.md` — the detailed implementation spec (BẮT BUỘC before tasks).
|
|
73
|
+
Follow `docs/AI_HANDOFF/SPEC.md`'s template sections (or `templates/docs/AI_HANDOFF/SPEC.md`
|
|
74
|
+
on a fresh tree): problem/context, goals, non-goals, user journeys, functional requirements
|
|
75
|
+
with Given/When/Then + error cases, fullstack scope (backend, schema/migrations, API
|
|
76
|
+
contract, UI+state, integration, security, performance, observability, deploy/rollback),
|
|
77
|
+
data model, edge cases, test matrix, acceptance criteria, migration steps, open questions
|
|
78
|
+
with chosen defaults, review checklist.
|
|
79
|
+
|
|
80
|
+
The spec must be concrete enough that an executor implements it WITHOUT guessing: exact
|
|
81
|
+
file paths, module names, API methods, statuses, schemas, validation rules, permissions,
|
|
82
|
+
empty/error states, migration behavior, and test expectations. Open questions are
|
|
83
|
+
resolved to a chosen default recorded inline — the plan phase is the only question
|
|
84
|
+
window, so anything left "TBD" becomes a guess downstream.
|
|
85
|
+
|
|
86
|
+
4. Write `docs/AI_HANDOFF/PLAN.md` — all 6 sections mandatory:
|
|
73
87
|
- §1 Intent — problem + success definition
|
|
74
88
|
- §2 Scope — in / out of scope. **Add a constraint**: same-wave tasks must not modify the same file (prevents merge conflicts). If two tasks need the same file, make one depend on the other.
|
|
75
89
|
- §3 Approach — solution, trade-offs, alternatives rejected
|
|
@@ -83,8 +97,9 @@ The planner agent does the following (use Step 1 summary — do NOT re-read file
|
|
|
83
97
|
PLANNER_MODEL: <your exact model ID>
|
|
84
98
|
```
|
|
85
99
|
|
|
86
|
-
|
|
100
|
+
5. Create `docs/AI_HANDOFF/tasks/TASK-001.md`, `TASK-002.md`... from `_TEMPLATE.md`
|
|
87
101
|
Every task MUST have:
|
|
102
|
+
- Spec references (SPEC.md section IDs this task implements)
|
|
88
103
|
- Target Files (exact paths — no two tasks in same wave share a file)
|
|
89
104
|
- Dependencies (`TASK-xxx` or `none` — wave structure inferred from this, not stored separately)
|
|
90
105
|
- Test Cases (Type | Name | Expected — ≥1 happy + ≥2 edge cases of different kinds)
|
|
@@ -93,18 +108,19 @@ The planner agent does the following (use Step 1 summary — do NOT re-read file
|
|
|
93
108
|
- Acceptance Criteria (verifiable checklist)
|
|
94
109
|
Missing any field → status: `needs_breakdown`, never `ready`
|
|
95
110
|
|
|
96
|
-
|
|
111
|
+
6. Update `INDEX.md` — one row per task, `status=ready`
|
|
97
112
|
|
|
98
|
-
|
|
113
|
+
7. Update `ACTIVE.md`:
|
|
99
114
|
```
|
|
100
115
|
Cycle: <ID> Date: <YYYY-MM-DD> Base: <BASE>
|
|
101
116
|
Goal: <1 sentence>
|
|
117
|
+
Spec: docs/AI_HANDOFF/SPEC.md
|
|
102
118
|
Tasks: <N> total
|
|
103
119
|
Status: planning_done — ready for executor
|
|
104
120
|
```
|
|
105
121
|
Note: wave structure is inferred from task Dependencies fields — not stored here.
|
|
106
122
|
|
|
107
|
-
|
|
123
|
+
8. Report: task IDs, dependency graph, any `needs_breakdown` + reason
|
|
108
124
|
|
|
109
125
|
> **For the human operator, on a tool with no agent support (Codex, OpenCode) — not an instruction to the model:** manually switch to the strong model, execute steps 1–7 above yourself.
|
|
110
126
|
|
|
@@ -121,9 +137,9 @@ The planner agent does the following (use Step 1 summary — do NOT re-read file
|
|
|
121
137
|
Two independent strong-model passes shape the plan before any code is written — that gate is
|
|
122
138
|
intact. What it no longer does is hand a stalled plan back and wait.
|
|
123
139
|
|
|
124
|
-
**Claude Code — MANDATORY, do this before anything else:** call the Agent tool with `subagent_type: "code-reviewer"` (omp: the `task` tool with `agent: "code-reviewer"`), passing `REVIEW_TARGET_TYPE=plan` and the
|
|
140
|
+
**Claude Code — MANDATORY, do this before anything else:** call the Agent tool with `subagent_type: "code-reviewer"` (omp: the `task` tool with `agent: "code-reviewer"`), passing `REVIEW_TARGET_TYPE=plan` and the paths to `docs/AI_HANDOFF/PLAN.md` AND `docs/AI_HANDOFF/SPEC.md`. This MUST be a separate agent invocation from Step 2's `handoff-planner` call (fresh context) — same-session self-review defeats the purpose of an independent gate.
|
|
125
141
|
|
|
126
|
-
1. Reviewer reads `PLAN.md`
|
|
142
|
+
1. Reviewer reads `SPEC.md` + `PLAN.md` (no diff, no task files, no executor report), checks Completeness / Consistency / Clarity / Scope / YAGNI plus the spec quality gate — every requirement testable, every fullstack layer covered, dependencies explicit, no vague instruction left — see `.claude/agents/code-reviewer.md` → Spec/Plan Review — and appends its verdict to PLAN.md's `## Plan Review Log` (new round entry, prior rounds kept).
|
|
127
143
|
2. `Issues Found` → route back to Step 2: planner revises `PLAN.md` and the affected `TASK-xxx.md` files to address every finding, then re-submit for another Step 2.5 review (this becomes the next round). Do NOT commit or hand off to executor on `Issues Found`.
|
|
128
144
|
3. `Approved` → append `PLAN_REVIEW: Approved by <reviewer model>` to PLAN.md's `## Planner Report` footer, then proceed.
|
|
129
145
|
|
|
@@ -66,9 +66,10 @@ numbered step completes:
|
|
|
66
66
|
Command: handoff-fullstack
|
|
67
67
|
Goal: <one sentence from the **Problem / feature** section above>
|
|
68
68
|
Base: <BASE branch>
|
|
69
|
-
Phase: <P1|P2|P2.5|P3|I1|I2|I3|I4|R1|R2|R3|R4|R5|done>
|
|
69
|
+
Phase: <P0|P1|P2|P2.5|P3|I1|I2|I3|I4|R1|R2|R3|R4|R4.5|R5|F|done|blocked>
|
|
70
70
|
Cursor: wave <N> batch <M> — <what just finished>
|
|
71
71
|
Next: <the exact next step to run>
|
|
72
|
+
QuietScans: <n>/<required> # only while sweeping for stragglers near the end
|
|
72
73
|
```
|
|
73
74
|
|
|
74
75
|
This file is the resume contract. It costs one small write per step and is what turns an
|
|
@@ -86,6 +87,89 @@ Only when `RUN.md` is absent or `Phase: done` does a new request start a fresh c
|
|
|
86
87
|
|
|
87
88
|
---
|
|
88
89
|
|
|
90
|
+
## §0 — Completion contract (terminal outputs)
|
|
91
|
+
|
|
92
|
+
This run has exactly **two** legal ways to end:
|
|
93
|
+
|
|
94
|
+
- `HANDOFF FULLSTACK COMPLETE` — the completion gate in Phase F passed. First line of the
|
|
95
|
+
final report, verbatim.
|
|
96
|
+
- `HANDOFF FULLSTACK BLOCKED` — every remaining task depends on the same external blocker
|
|
97
|
+
(missing credential, dead service, permission wall) AND no safe local work exists. Write
|
|
98
|
+
`Phase: blocked` to RUN.md before emitting it so the Stop gate releases the session.
|
|
99
|
+
|
|
100
|
+
Nothing else ends the run. A recap is a progress notification, not a stopping point. If you
|
|
101
|
+
emit a checkpoint it MUST use this shape and be followed by immediate work:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
CHECKPOINT — WORK CONTINUING
|
|
105
|
+
Cycle:
|
|
106
|
+
Completed since last checkpoint:
|
|
107
|
+
Currently executing:
|
|
108
|
+
Exact next action:
|
|
109
|
+
Verification status:
|
|
110
|
+
Run cursor updated: YES
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Never stop at `recap: ... Next: ...` while unfinished work remains — the Stop gate now
|
|
114
|
+
bounces that stop straight back into the pipeline, so stopping is not even restful; it
|
|
115
|
+
just costs a round-trip.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Phase 0 — Sweep & Inventory (before planning)
|
|
120
|
+
|
|
121
|
+
Before Phase 1, build the authoritative task inventory — the run owns **all** unfinished
|
|
122
|
+
work, not only the current plan:
|
|
123
|
+
|
|
124
|
+
1. `docs/AI_HANDOFF/INDEX.md` — every task not `done`/`cancelled_superseded`.
|
|
125
|
+
2. `docs/AI_HANDOFF/tasks/TASK-*.md` — stale `in_progress` from a dead session, `blocked`,
|
|
126
|
+
`changes_requested`, `needs_executor_report`, `needs_breakdown`.
|
|
127
|
+
3. Previous cycles — `docs/AI_HANDOFF/HISTORY.md` and `archive/` for cycles closed with
|
|
128
|
+
unfinished tasks; their leftovers join THIS cycle.
|
|
129
|
+
4. `docs/TASKS.md` — `Ready for AI` items are newly-assigned work; fold them into the plan.
|
|
130
|
+
5. `git status` / `git diff` — uncommitted work-in-progress that must be finished or
|
|
131
|
+
checkpointed, never silently dropped.
|
|
132
|
+
|
|
133
|
+
The inventory feeds P2: the planner either schedules every discovered item or records why
|
|
134
|
+
it is out of scope (§1/§2 of PLAN.md). Silent omission is a plan defect.
|
|
135
|
+
|
|
136
|
+
**Recovery rule — stuck task records.** For every `pending`, stale `in_progress`, or
|
|
137
|
+
`blocked` task whose record cannot be cleanly resumed (invalid state, orphaned worktree
|
|
138
|
+
gone, contradicting reports):
|
|
139
|
+
|
|
140
|
+
1. Inspect code/tests/git to see what is actually missing.
|
|
141
|
+
2. Recoverable → finish the original task in place.
|
|
142
|
+
3. Not recoverable → mark the old row `cancelled_superseded`, create `TASK-xxx-R1`
|
|
143
|
+
(`-R2`, …) with the same spec references, acceptance criteria and verification, link
|
|
144
|
+
both files' `## Discussion` threads, and execute the replacement in this cycle.
|
|
145
|
+
4. Never leave stranded work merely because a task record was pending.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Watchdog — surviving idle and new assignments
|
|
150
|
+
|
|
151
|
+
The run must keep itself alive without the human watching.
|
|
152
|
+
|
|
153
|
+
- **Stop gate (Claude Code, automatic):** while `RUN.md` `Phase:` is not `done`/`blocked`,
|
|
154
|
+
`completion-gate.sh` refuses the stop with the cursor's `Next:` step. Recaps and
|
|
155
|
+
premature stops cannot park the run. A stalled-cursor breaker
|
|
156
|
+
(`handoff.fullstack.stopGateMaxStalledBlocks`, default 12) releases the session if the
|
|
157
|
+
cursor has genuinely stopped advancing — the escape hatch, not the norm.
|
|
158
|
+
- **Scheduled wakeup (when the harness offers one):** arm it at run start — Claude Code:
|
|
159
|
+
`CronCreate` a ~`handoff.fullstack.idleWatchdogMin`-minute (default 5) session job with
|
|
160
|
+
prompt `Resume HANDOFF FULLSTACK from docs/AI_HANDOFF/RUN.md — continue the Next: step`;
|
|
161
|
+
`/loop`-style tools: the equivalent interval. Cancel/let it expire once `Phase: done`.
|
|
162
|
+
- **Harnesses with neither:** treat EVERY activation as a watchdog recovery turn — read
|
|
163
|
+
RUN.md first, rescan the inventory, continue `Next:`.
|
|
164
|
+
|
|
165
|
+
**Quiet-period rule.** The run may finish only after the backlog is empty AND
|
|
166
|
+
`handoff.fullstack.quietScansRequired` (default 2) consecutive watchdog scans find no new
|
|
167
|
+
assignment, no recoverable task, and no uncommitted intended change. Record each quiet
|
|
168
|
+
scan in RUN.md as `QuietScans: <n>/<required>`. A scan that finds anything resets the
|
|
169
|
+
counter and starts a new cycle automatically.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
89
173
|
## Phase 1+2 — Plan (strong model)
|
|
90
174
|
|
|
91
175
|
### P1 — Read context (lite model)
|
|
@@ -117,7 +201,15 @@ The planner agent does the following (use P1 summary — do NOT re-read files):
|
|
|
117
201
|
BASE=$(git symbolic-ref --short HEAD)
|
|
118
202
|
```
|
|
119
203
|
|
|
120
|
-
3. **Write `docs/AI_HANDOFF/
|
|
204
|
+
3. **Write `docs/AI_HANDOFF/SPEC.md`** — the detailed implementation spec, from
|
|
205
|
+
`templates/docs/AI_HANDOFF/SPEC.md`'s section list (or RULES.md §Spec). It must be
|
|
206
|
+
concrete enough that an executor implements without guessing: exact paths, module and
|
|
207
|
+
API names, schemas, validation rules, permissions, empty/error states, migration
|
|
208
|
+
behavior, and test expectations — every applicable section filled, open questions
|
|
209
|
+
resolved to chosen defaults recorded inline. Implementation begins from SPEC+PLAN,
|
|
210
|
+
never from the raw request.
|
|
211
|
+
|
|
212
|
+
4. **Write `docs/AI_HANDOFF/PLAN.md`** — all 6 sections mandatory:
|
|
121
213
|
- §1 Intent — problem + success definition
|
|
122
214
|
- §2 Scope — in / out of scope; same-wave tasks must not modify the same file (prevents merge conflicts)
|
|
123
215
|
- §3 Approach — solution, trade-offs, alternatives rejected
|
|
@@ -131,8 +223,9 @@ The planner agent does the following (use P1 summary — do NOT re-read files):
|
|
|
131
223
|
PLANNER_MODEL: <your exact model ID>
|
|
132
224
|
```
|
|
133
225
|
|
|
134
|
-
|
|
226
|
+
5. **Create `docs/AI_HANDOFF/tasks/TASK-001.md`, `TASK-002.md`...** from `_TEMPLATE.md`.
|
|
135
227
|
Every task MUST have:
|
|
228
|
+
- Spec references (SPEC.md section IDs this task implements)
|
|
136
229
|
- Target Files (exact paths — no two tasks in same wave share a file)
|
|
137
230
|
- Dependencies (`TASK-xxx` or `none` — wave structure inferred from this)
|
|
138
231
|
- Test Cases (Type | Name | Expected — ≥1 happy + ≥2 edge cases of different kinds)
|
|
@@ -141,17 +234,21 @@ The planner agent does the following (use P1 summary — do NOT re-read files):
|
|
|
141
234
|
- Acceptance Criteria (verifiable checklist)
|
|
142
235
|
Missing any field → status `needs_breakdown`, never `ready`.
|
|
143
236
|
|
|
144
|
-
|
|
237
|
+
6. **Update `docs/AI_HANDOFF/INDEX.md`** — one row per task, `status=ready`. Every
|
|
238
|
+
unfinished item from the Phase 0 sweep is either a row here or superseded by a
|
|
239
|
+
`-R<n>` recovery row.
|
|
145
240
|
|
|
146
|
-
|
|
241
|
+
7. **Update `docs/AI_HANDOFF/ACTIVE.md`:**
|
|
147
242
|
```
|
|
148
243
|
Cycle: <ID> Date: <YYYY-MM-DD> Base: <BASE>
|
|
149
244
|
Goal: <1 sentence>
|
|
245
|
+
Spec: docs/AI_HANDOFF/SPEC.md
|
|
150
246
|
Tasks: <N> total
|
|
151
247
|
Status: planning_done — ready for executor
|
|
152
248
|
```
|
|
153
249
|
|
|
154
|
-
|
|
250
|
+
8. **Report:** task IDs, dependency graph, recovery/superseded tasks, any
|
|
251
|
+
`needs_breakdown` tasks + reason.
|
|
155
252
|
|
|
156
253
|
### P2.5 — Independent plan review (strong model, separate agent)
|
|
157
254
|
|
|
@@ -164,9 +261,9 @@ The planner agent does the following (use P1 summary — do NOT re-read files):
|
|
|
164
261
|
The gate still does its job — two independent opus passes shape the plan before a line of code
|
|
165
262
|
is written. What it no longer does is hand a stalled plan back to a human who isn't there.
|
|
166
263
|
|
|
167
|
-
**Claude Code — MANDATORY, do this before anything else in P2.5:** call the Agent tool with `subagent_type: "code-reviewer"` (omp: the `task` tool with `agent: "code-reviewer"`), passing `REVIEW_TARGET_TYPE=plan` and the
|
|
264
|
+
**Claude Code — MANDATORY, do this before anything else in P2.5:** call the Agent tool with `subagent_type: "code-reviewer"` (omp: the `task` tool with `agent: "code-reviewer"`), passing `REVIEW_TARGET_TYPE=plan` and the paths to `docs/AI_HANDOFF/PLAN.md` AND `docs/AI_HANDOFF/SPEC.md`. This MUST be a separate agent invocation from P2's `handoff-planner` call (fresh context) — same-session self-review defeats the purpose of an independent gate.
|
|
168
265
|
|
|
169
|
-
1. Reviewer reads `PLAN.md` only (no diff, no task files, no executor report), checks Completeness / Consistency / Clarity / Scope / YAGNI — see `.claude/agents/code-reviewer.md` → Spec/Plan Review — and appends its verdict to PLAN.md's `## Plan Review Log` (new round entry, prior rounds kept).
|
|
266
|
+
1. Reviewer reads `SPEC.md` + `PLAN.md` only (no diff, no task files, no executor report), checks Completeness / Consistency / Clarity / Scope / YAGNI plus the spec quality gate — every requirement testable, every fullstack layer covered, dependencies explicit, legacy sweep included, no vague instruction left ("improve UI" without defined behavior fails) — see `.claude/agents/code-reviewer.md` → Spec/Plan Review — and appends its verdict to PLAN.md's `## Plan Review Log` (new round entry, prior rounds kept).
|
|
170
267
|
2. `Issues Found` → route back to P2: `handoff-planner` revises `PLAN.md` and the affected `TASK-xxx.md` files to address every finding, then re-submit for one more P2.5 review round — subject to the loop cap above.
|
|
171
268
|
3. `Approved` → append `PLAN_REVIEW: Approved by <reviewer model>` to PLAN.md's `## Planner Report` footer, then proceed to P3.
|
|
172
269
|
|
|
@@ -510,9 +607,50 @@ Force-push stays denied, so this can only ever fast-forward.
|
|
|
510
607
|
|
|
511
608
|
**If some tasks are `blocked`:** still push. The approved work is reviewed, tested, and
|
|
512
609
|
committed; withholding it helps no one, and the per-wave commits make any subset revertible.
|
|
513
|
-
Name the blocked tasks in the Final Report.
|
|
610
|
+
Name the blocked tasks in the Final Report. Tasks that stayed `blocked` only because their
|
|
611
|
+
record was unrecoverable get the Phase 0 recovery treatment — `cancelled_superseded` plus a
|
|
612
|
+
`-R<n>` replacement — before the run may close.
|
|
613
|
+
|
|
614
|
+
Do NOT set `Phase: done` yet — Phase F still has to close the books.
|
|
615
|
+
|
|
616
|
+
---
|
|
617
|
+
|
|
618
|
+
## Phase F — Finalize: quiet period, docs, archive
|
|
619
|
+
|
|
620
|
+
### F1 — Quiet-period scan
|
|
621
|
+
|
|
622
|
+
Run the sweep from Phase 0 again (INDEX, task files, `docs/TASKS.md`, git status).
|
|
623
|
+
`handoff.fullstack.quietScansRequired` (default 2) consecutive scans must each find:
|
|
624
|
+
no unfinished task, no new assignment, no uncommitted intended change. Record each scan
|
|
625
|
+
in RUN.md (`QuietScans: <n>/<required>`). Anything found resets the counter — fold it in
|
|
626
|
+
through the normal pipeline and keep going.
|
|
627
|
+
|
|
628
|
+
### F2 — Docs sync
|
|
629
|
+
|
|
630
|
+
Update only the docs the change actually touched: `docs/WORKLOG.md` (always — one entry
|
|
631
|
+
for the cycle), plus `docs/PROJECT.md` / `docs/CODE_MAP.md` / `docs/CHANGELOG.md` when the
|
|
632
|
+
cycle changed architecture, surface area, or shipped behavior. Record: behavior
|
|
633
|
+
implemented, API/schema/UI changes, migration steps, config changes, verification
|
|
634
|
+
evidence, rollback notes.
|
|
635
|
+
|
|
636
|
+
### F3 — Archive the cycle
|
|
514
637
|
|
|
515
|
-
|
|
638
|
+
When `handoff.fullstack.autoArchive` is true (default), archive per `handoff-clear`
|
|
639
|
+
conventions so a future session needs no transcript to understand the cycle:
|
|
640
|
+
|
|
641
|
+
1. Move the completed cycle's records (PLAN.md, SPEC.md, task files, ACTIVE.md snapshot)
|
|
642
|
+
into `docs/AI_HANDOFF/archive/cycle-<NN>/`.
|
|
643
|
+
2. If `archive/` holds more than 3 cycle folders → fold the oldest into a one-line
|
|
644
|
+
summary in `HISTORY.md` and remove it.
|
|
645
|
+
3. Reset `ACTIVE.md` to its empty template; clear `INDEX.md` rows to a fresh header;
|
|
646
|
+
remove `tasks/TASK-*.md`; clear `PLAN.md`/`SPEC.md` (templates stay).
|
|
647
|
+
4. Commit the docs + archive changes:
|
|
648
|
+
`git add -A && git commit -m "handoff: finalize + archive cycle <ID>"`
|
|
649
|
+
|
|
650
|
+
### F4 — Close the run
|
|
651
|
+
|
|
652
|
+
Set `Phase: done` in `docs/AI_HANDOFF/RUN.md`, disarm any watchdog job armed at the
|
|
653
|
+
start, and emit the Final Report below.
|
|
516
654
|
|
|
517
655
|
---
|
|
518
656
|
|
|
@@ -539,17 +677,40 @@ Re-run assertions after removal to confirm clean state.
|
|
|
539
677
|
|
|
540
678
|
## Final Report
|
|
541
679
|
|
|
680
|
+
The ONLY legal first lines are:
|
|
681
|
+
|
|
682
|
+
```
|
|
683
|
+
HANDOFF FULLSTACK COMPLETE
|
|
684
|
+
```
|
|
685
|
+
or, when every remaining task shares one external blocker and no safe local work exists
|
|
686
|
+
(RUN.md set to `Phase: blocked` first):
|
|
687
|
+
```
|
|
688
|
+
HANDOFF FULLSTACK BLOCKED
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
Then the body:
|
|
692
|
+
|
|
542
693
|
```
|
|
543
|
-
handoff-fullstack complete:
|
|
544
694
|
Cycle: <ID>
|
|
695
|
+
Spec: docs/AI_HANDOFF/SPEC.md
|
|
545
696
|
Tasks: <N> approved, <M> blocked
|
|
697
|
+
Recovery/superseded: <TASK-xxx→TASK-xxx-R1, …> | none
|
|
698
|
+
Newly assigned processed: <n> | none
|
|
699
|
+
Quiet scans: <n>/<required>
|
|
546
700
|
Fix rounds used: <0|1|2>
|
|
701
|
+
Verification: <commands + results>
|
|
547
702
|
Git: <K> wave commits + pushed to <branch>
|
|
703
|
+
Docs updated: <files>
|
|
704
|
+
Archive: docs/AI_HANDOFF/archive/cycle-<NN>/
|
|
548
705
|
Worktrees: all cleaned
|
|
549
706
|
Branches: all cleaned
|
|
707
|
+
Remaining tasks: NONE | <list>
|
|
550
708
|
Blocked (needs you): <TASK-xxx — one-line reason> | none
|
|
551
709
|
```
|
|
552
710
|
|
|
711
|
+
A blocked report additionally lists: blocked tasks, exact blocker + evidence, attempted
|
|
712
|
+
fixes, local work completed, and the recovery instructions for the next session.
|
|
713
|
+
|
|
553
714
|
Then, as the last line of the run:
|
|
554
715
|
|
|
555
716
|
> Cycle finished. Run `/compact` before starting the next cycle — this session is carrying
|
|
@@ -59,8 +59,12 @@ If this file already exists with `Phase:` not `done` when the command starts, th
|
|
|
59
59
|
|
|
60
60
|
Read `docs/AI_HANDOFF/ACTIVE.md` → get `Base: <BASE>`.
|
|
61
61
|
Read `docs/AI_HANDOFF/INDEX.md` → collect `ready` tasks (or the specific task named in the request above).
|
|
62
|
-
If there are no `ready` tasks, check for `changes_requested`/`blocked`
|
|
63
|
-
instead.
|
|
62
|
+
If there are no `ready` tasks, check for `changes_requested`/`blocked`/stale `in_progress`
|
|
63
|
+
ones and run those instead. A stuck record that cannot resume (orphaned worktree,
|
|
64
|
+
contradicting reports) gets the recovery treatment: mark it `cancelled_superseded`, create
|
|
65
|
+
`TASK-xxx-R1` with the same spec references/acceptance/verification, and run the
|
|
66
|
+
replacement — never leave stranded work just because a record was pending.
|
|
67
|
+
Only if nothing is actionable → report and stop.
|
|
64
68
|
|
|
65
69
|
Verify working tree state:
|
|
66
70
|
```bash
|
|
@@ -125,6 +129,9 @@ Each spawned agent works independently in its own worktree — **NO git commit,
|
|
|
125
129
|
|
|
126
130
|
```
|
|
127
131
|
Read docs/AI_HANDOFF/tasks/TASK-xxx.md
|
|
132
|
+
Read the SPEC.md sections named in the task's `Spec references` — the spec is the contract;
|
|
133
|
+
the task file is the slice. If they disagree, implement the spec and note it in the task's
|
|
134
|
+
## Discussion.
|
|
128
135
|
|
|
129
136
|
TDD — mandatory:
|
|
130
137
|
1. Write tests from §Test Cases
|
|
@@ -86,7 +86,10 @@ git status # overview of modified/new/deleted files
|
|
|
86
86
|
```
|
|
87
87
|
|
|
88
88
|
Review as one unified diff — correctness, regression risk, security, edge cases, maintainability.
|
|
89
|
-
Cross-reference
|
|
89
|
+
Cross-reference each task's intent in `docs/AI_HANDOFF/tasks/TASK-xxx.md` AND the
|
|
90
|
+
`Spec references` sections it names in `docs/AI_HANDOFF/SPEC.md` — spec compliance is the
|
|
91
|
+
primary correctness bar; a diff that drifts from the spec's contract fails even when it
|
|
92
|
+
matches the task file's wording.
|
|
90
93
|
|
|
91
94
|
### 2d — Append verdict to each task file
|
|
92
95
|
|
|
@@ -12,8 +12,10 @@ Read and display current handoff state. Do NOT modify any files.
|
|
|
12
12
|
|
|
13
13
|
1. `docs/AI_HANDOFF/ACTIVE.md` → cycle ID, goal, base branch
|
|
14
14
|
2. `docs/AI_HANDOFF/INDEX.md` → all tasks + statuses
|
|
15
|
-
3. `
|
|
16
|
-
4. `
|
|
15
|
+
3. `docs/AI_HANDOFF/RUN.md` → fullstack run cursor: `Phase:` ≠ `done`/`blocked` means a run is live and the Stop gate is holding the session to it
|
|
16
|
+
4. `docs/AI_HANDOFF/SPEC.md` → spec exists/fresh (one line)
|
|
17
|
+
5. `git worktree list` → open worktrees
|
|
18
|
+
6. `git branch | grep handoff/` → open handoff branches
|
|
17
19
|
|
|
18
20
|
## Report
|
|
19
21
|
|
|
@@ -21,6 +23,8 @@ Read and display current handoff state. Do NOT modify any files.
|
|
|
21
23
|
━━━ Handoff Status ━━━━━━━━━━━━━━━━━━━━━━━━
|
|
22
24
|
Cycle: <ID> Base: <branch> Date: <date>
|
|
23
25
|
Goal: <goal>
|
|
26
|
+
Run: <Phase — or "no live cursor">
|
|
27
|
+
Spec: <present | missing>
|
|
24
28
|
|
|
25
29
|
Tasks:
|
|
26
30
|
✅ done TASK-001 <name>
|
|
@@ -181,6 +181,30 @@ if (toolName === 'Write' || toolName === 'Edit') {
|
|
|
181
181
|
if (!plannerModel || tierOf(plannerModel) !== 'smart') {
|
|
182
182
|
block(`Cannot create ${taskId}.md — PLAN.md has no valid smart-tier PLANNER_MODEL yet. Run planning via Agent tool subagent_type: "handoff-planner" (opus/unic-smart) first.`);
|
|
183
183
|
}
|
|
184
|
+
|
|
185
|
+
// Spec gate (handoff-fullstack v2): tasks are decomposed FROM a detailed spec, so a
|
|
186
|
+
// fresh task file requires docs/AI_HANDOFF/SPEC.md to exist and to differ from the
|
|
187
|
+
// shipped template. Disable per project: handoff.fullstack.specRequired=false.
|
|
188
|
+
let specRequired = true;
|
|
189
|
+
try {
|
|
190
|
+
const cfg = JSON.parse(fs.readFileSync(path.join(projectRoot, '.ukit/storage/config.json'), 'utf8'));
|
|
191
|
+
if (cfg?.handoff?.fullstack?.specRequired === false) specRequired = false;
|
|
192
|
+
} catch {}
|
|
193
|
+
if (specRequired) {
|
|
194
|
+
let specOk = false;
|
|
195
|
+
try {
|
|
196
|
+
const specPath = path.join(projectRoot, 'docs/AI_HANDOFF/SPEC.md');
|
|
197
|
+
const specText = fs.readFileSync(specPath, 'utf8');
|
|
198
|
+
let templateText = null;
|
|
199
|
+
try {
|
|
200
|
+
templateText = fs.readFileSync(path.join(projectRoot, 'templates/docs/AI_HANDOFF/SPEC.md'), 'utf8');
|
|
201
|
+
} catch {}
|
|
202
|
+
specOk = specText.length > 500 && specText !== templateText;
|
|
203
|
+
} catch {}
|
|
204
|
+
if (!specOk) {
|
|
205
|
+
block(`Cannot create ${taskId}.md — docs/AI_HANDOFF/SPEC.md is missing or still the untouched template. handoff-create must write a detailed spec (15 sections) before tasks are created.`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
184
208
|
}
|
|
185
209
|
|
|
186
210
|
// A section already on disk only counts as validated when its model is real —
|