@ngockhoale/ukit 3.4.66 → 3.4.68

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 (62) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/manifests/documentation.yaml +33 -0
  3. package/manifests/instructionRules.yaml +10 -0
  4. package/manifests/platform.full.yaml +67 -0
  5. package/package.json +1 -1
  6. package/src/core/applyPlan.js +111 -2
  7. package/src/core/buildPlan.js +3 -1
  8. package/src/core/diffPlan.js +49 -1
  9. package/src/core/executionContracts.js +51 -10
  10. package/src/core/metadata.js +45 -0
  11. package/src/core/runInstallPipeline.js +30 -2
  12. package/src/core/uninstall.js +106 -2
  13. package/src/manifest/validateManifest.js +25 -1
  14. package/template_project/.claude/agents/code-reviewer.md +22 -9
  15. package/template_project/.claude/agents/handoff-planner.md +97 -8
  16. package/template_project/.claude/commands/ukit/handoff-create.md +114 -19
  17. package/template_project/.claude/commands/ukit/handoff-fullstack.md +247 -79
  18. package/template_project/.claude/commands/ukit/handoff-implement.md +75 -40
  19. package/template_project/.claude/commands/ukit/handoff-review.md +14 -10
  20. package/template_project/.claude/hooks/auto-allow-bash.sh +73 -12
  21. package/template_project/.claude/hooks/auto-prune-bash.sh +10 -0
  22. package/template_project/.claude/hooks/delegation-gate.mjs +21 -0
  23. package/template_project/.claude/hooks/handoff-model-guard.sh +22 -6
  24. package/template_project/.claude/hooks/handoff-resume.sh +141 -1
  25. package/template_project/.claude/hooks/record-execution.mjs +140 -9
  26. package/template_project/.claude/hooks/skill-router.sh +173 -8
  27. package/template_project/.claude/settings.json +2 -2
  28. package/template_project/.claude/skills/advisor-plan/REFERENCE.md +10 -0
  29. package/template_project/.claude/skills/advisor-plan/SKILL.md +2 -2
  30. package/template_project/.claude/ukit/index/allocate-task-worktree.mjs +15 -0
  31. package/template_project/.claude/ukit/index/amend-guard.mjs +116 -0
  32. package/template_project/.claude/ukit/index/cleanup-task-worktree.mjs +1 -1
  33. package/template_project/.claude/ukit/index/land-worktree.mjs +243 -21
  34. package/template_project/.claude/ukit/index/plan-count.mjs +115 -0
  35. package/template_project/.claude/ukit/index/ready-gate.mjs +170 -0
  36. package/template_project/.claude/ukit/index/reset-auto-permissions.mjs +293 -4
  37. package/template_project/.claude/ukit/index/route-resolver.mjs +50 -10
  38. package/template_project/.claude/ukit/index/route-task.mjs +180 -11
  39. package/template_project/.claude/ukit/index/source-snapshot.mjs +172 -0
  40. package/template_project/.claude/ukit/index/task-budget-validator.mjs +109 -3
  41. package/template_project/.claude/ukit/runtime/execution-ledger.mjs +20 -3
  42. package/template_project/.claude/ukit/runtime/handoff-task-scope.mjs +205 -0
  43. package/template_project/.claude/ukit/runtime/loop-state.mjs +3 -1
  44. package/template_project/.claude/ukit/runtime/plan-dispatch.mjs +32 -5
  45. package/template_project/.claude/ukit/runtime/resumable-run.mjs +310 -21
  46. package/template_project/.claude/ukit/runtime/stop-coordinator.mjs +405 -105
  47. package/template_project/.claude/ukit/runtime/task-record-reconciliation.mjs +46 -0
  48. package/template_project/.claude/ukit/runtime/task-watchdog.mjs +28 -2
  49. package/template_project/.claude/ukit/runtime/worktree-allocation.mjs +75 -0
  50. package/template_project/.codex/README.md +25 -0
  51. package/template_project/.omp/RULES.md +22 -22
  52. package/template_project/.omp/agents/code-reviewer.md +22 -9
  53. package/template_project/.omp/agents/handoff-planner.md +102 -12
  54. package/template_project/.omp/hooks/pre/ukit-bridge.js +1 -1
  55. package/template_project/AGENTS.md +5 -1
  56. package/template_project/CLAUDE.md +1 -1
  57. package/template_project/docs/AI_HANDOFF/RULES.md +8 -0
  58. package/template_project/docs/AI_HANDOFF/tasks/_TEMPLATE.md +8 -1
  59. package/template_project/instructions/core.md +5 -1
  60. package/template_project/instructions/layout.yaml +2 -0
  61. package/template_project/instructions/overlays/omp-rules.md +22 -22
  62. package/template_project/ukit/storage/config.json +1 -1
@@ -19,8 +19,12 @@ $ARGUMENTS
19
19
  `/ukit:handoff-create` produces **SPEC.md, PLAN.md, and decomposed task files under
20
20
  `docs/AI_HANDOFF/` — nothing else.** It never edits product code, never launches an
21
21
  executor, and never escalates itself into implementation. Long plans are simply
22
- **queued**: after Step 2.5 the command stops with the tasks in `status=ready`, and
23
- implementation waits for an explicit human action.
22
+ **queued**: after Step 2.5 the command stops with every task `ready` — which is a
23
+ verdict, not a default: tasks are born `needs_breakdown` and only flip to `ready` after
24
+ the task-budget validator (`VERDICT: ok`) AND the independent plan review (`Approved`)
25
+ both pass (see Step 2.5). If a gate never ran (budget, denial, interruption), the tasks
26
+ stay non-ready and the state files say so, and implementation still waits for an explicit
27
+ human action.
24
28
 
25
29
  This holds even when `docs/AI_HANDOFF/RUN.md` already carries an unfinished
26
30
  handoff-fullstack cursor. Running this command **makes the session's handoff intent
@@ -44,7 +48,7 @@ is **not** `done`/`blocked`, a fullstack run is live and owns the canonical plan
44
48
 
45
49
  **Explicit abandonment never overwrites an unfinished canonical run.** Only when the human
46
50
  explicitly says to abandon/clear the current run, first run `/ukit:handoff-clear`, which
47
- sets `Paused: yes` in `RUN.md` and keeps its actual phase and scope, recording the
51
+ sets `Paused: yes` in `RUN.md` and keeps its actual phase and scope; a later explicit `/ukit:handoff-fullstack` lifts it (`Paused: no`, read back, Phase/scope untouched). Recording the
48
52
  cancellation reason and next recovery action (it never sets `Phase: done` and never erases
49
53
  `RUN.md`). The paused canonical files are still unfinished: the new request is written under
50
54
  the queued root `docs/AI_HANDOFF/queued/<slug>/` and the canonical task files, INDEX, and
@@ -93,13 +97,35 @@ the document into a LEDGER, a bounded task set and a queue, and never implements
93
97
 
94
98
  - **Phase A — gather (lite tier):** chunk the document, extract candidate requirements, and
95
99
  collect feasibility evidence from the **current source** (index-first) plus `git log`,
96
- `git diff` and `git status` of the touched areas. Gatherers decide nothing.
100
+ `git diff` and `git status` of the touched areas. Gatherers decide nothing. Before
101
+ chunking, persist the source verbatim with ONE simple command, literal paths (no `cd`, no
102
+ compound):
103
+ `node .claude/ukit/index/source-snapshot.mjs <original-path> docs/AI_HANDOFF/SOURCE.md`
104
+ (under a queued root, pass that root's SOURCE.md path). It records the origin path, the
105
+ sha256 of the original bytes and a byte-identical copy, and refuses to overwrite an
106
+ existing snapshot. If it cannot run (denial, budget), `PLAN.md` and `LEDGER.md` must
107
+ state `source snapshot MISSING` explicitly — never cite only a mutable path as the source.
97
108
  - **Phase B — decide (smart tier):** write the LEDGER at `${OUTPUT_ROOT}LEDGER.md` — every
98
109
  requirement gets exactly one disposition (`feasible`/`adapted`/`deferred`/`blocker`); the
99
110
  footer reads `Coverage: N/N rows dispositioned`; note that
100
- disposition coverage is not implementation coverage. Draft 2-3 candidate plans, score them, pick the best and record
111
+ disposition coverage is not implementation coverage. Material the source itself marks as
112
+ proposal, example, or rejected (and explicit non-goals) is NOT `deferred` — `deferred`
113
+ means intentionally-later work with a queue entry. Those items are `NOTES.md` entries
114
+ with their kind (`proposal`/`example`/`rejected`), per the advisor-plan skill; forcing
115
+ them into `deferred` queues non-work as backlog. Draft 2-3 candidate plans, score them, pick the best and record
101
116
  the rejected ones in `PLAN.md`. Every task carries detailed TDD test cases (happy, edge,
102
117
  error with expected results) that prove it works.
118
+ - **Plan count is a deliverable.** When the owner source states a number of plans or
119
+ separate plans ("at least two plans", "plan A and plan B"), write that many real plan
120
+ units in the Handoff-supported layout: the first plan under `OUTPUT_ROOT` (canonical
121
+ SPEC.md/PLAN.md/tasks/, or the queued root when a run is live), each further plan as its
122
+ own `docs/AI_HANDOFF/queued/<slug>/` blueprint with its own SPEC.md, PLAN.md, INDEX.md
123
+ (rows `queued_blueprint`), HANDOFF.md and tasks/. Group labels ("group A/B") inside one
124
+ PLAN.md never satisfy a stated count. Verify the count mechanically before reporting:
125
+ `node .claude/ukit/index/plan-count.mjs docs/AI_HANDOFF <N>` (the planning root, the
126
+ stated count) must print `PLAN_COUNT: ok (<found>/<N>)`. If the layout genuinely cannot
127
+ carry the count, record an explicit owner-decision item (a `NOTES.md` `question` entry
128
+ naming the decision) instead of silently collapsing it.
103
129
  - **Phase C — review:** the independent plan review in Step 2.5.
104
130
  - **Phase D — implement (code tier, separate phase):** never in this session; it runs later
105
131
  under `/ukit:handoff-fullstack` or `/ukit:handoff-implement`.
@@ -147,10 +173,43 @@ Ending the turn on a question with no plan written is a failed create.
147
173
 
148
174
  After the batched call, run Steps 1–2.5 to completion without further questions.
149
175
 
176
+ ## Step 0.5 — Source snapshot (before Step 1, every run)
177
+
178
+ When the problem statement comes from — or references — an original document on disk,
179
+ persist the source verbatim with ONE simple command, literal paths, BEFORE Step 1 reads
180
+ anything:
181
+
182
+ ```
183
+ node .claude/ukit/index/source-snapshot.mjs <original-path> docs/AI_HANDOFF/SOURCE.md
184
+ ```
185
+
186
+ (under a queued root, pass that root's SOURCE.md path literally). The helper refuses to
187
+ overwrite an existing snapshot (exclusive create), so a re-run never clobbers the recorded
188
+ bytes. If it cannot run (denial, budget, no file), PLAN.md — and LEDGER.md on the advisor
189
+ path — must state `source snapshot MISSING` explicitly — never cite only a mutable path as
190
+ the source. Chat-only input needs no snapshot: the durable verbatim message origin stands in
191
+ for the file (Step 2.5 item 1 reads it).
192
+
150
193
  ---
151
194
 
195
+ ## Planning dispatch contract
196
+
197
+ For **all three planning dispatches** (context reader, planner, independent reviewer),
198
+ omit the `isolation` field entirely. Do not set it to `worktree`, `remote`, `null`, or
199
+ an empty string. Planning reads/writes belong to this checkout; it does not authorize
200
+ worktree allocation. This also applies to read-only context agents. On omp, omit the
201
+ corresponding isolation/worktree option; Codex without agents uses its existing
202
+ instruction-mediated path, not a new worktree.
203
+
204
+ Do not repeat or respawn a refused dispatch, change its writer, or manufacture a
205
+ fallback plan to satisfy Stop. Preserve the exact refusal and incomplete planning
206
+ state. A hook refusal is not a transient network error.
207
+
152
208
  ## Step 1 — Read context (lite model)
153
209
 
210
+ Before this first context-agent call, omit the `isolation` field entirely.
211
+ Do not repeat or respawn a refused dispatch.
212
+
154
213
  **Claude Code — MANDATORY, do this before anything else:** call the Agent tool with `subagent_type: "ukit-small-task-maintainer"` (omp: the `task` tool with `agent: "ukit-small-task-maintainer"`). Do NOT read these files yourself in the current session — this step is contracted to the lite tier (haiku/unic-lite), which only the spawned agent's frontmatter model guarantees. Ask the agent to:
155
214
 
156
215
  1. Read `docs/AI_HANDOFF/INDEX.md` → current tasks + statuses (or "empty")
@@ -183,14 +242,21 @@ The planner agent does the following (use Step 1 summary — do NOT re-read file
183
242
 
184
243
  1. Check INDEX.md task statuses (canonical root only — skip when the live-run guard routed
185
244
  you to the queued root):
186
- - All tasks are `ready` (planning only) → **only an explicit amendment may overwrite**: when the human names the existing plan to refine: first copy every prior file (PLAN.md, SPEC.md, LEDGER.md, NOTES.md, SOURCE.md, tasks/TASK-*.md, when present) to the next unused `amendments/rev-<NN>/` under the same root (scan existing rev dirs and take max+1; never reuse or overwrite an existing rev dir). Then compose the revised PLAN.md in full: carry the existing `## Amendment History` forward and append this amendment's entry (prior review rounds and verdicts; prior requirement, decision and task versions with what changed and why; each change's `invalidated` evidence: tasks, executor reports, verdicts that no longer hold). Write the revised PLAN.md only after that entry is in the composed text, so the overwrite can never drop the history. An **independent new request** (a different goal, even when the old tasks are all `ready`) is NOT an amendment: write it under the queued root `docs/AI_HANDOFF/queued/<slug>/` and never overwrite the existing canonical plan.
245
+ - **Resume gates — `needs_breakdown` rows and PLAN.md without `PLAN_REVIEW: Approved`:**
246
+ a previous create run ended before both gates passed. Never re-intake the request,
247
+ do NOT re-run the advisor chain, and never overwrite the existing SPEC/PLAN/tasks on
248
+ this path. Run only the missing gates on the existing plan: the per-task validator
249
+ (`--record`, step 5 below) for every task still lacking its recorded `Validator:` line,
250
+ and the Step 2.5 independent review. Flip per the ready gate only after both pass; if
251
+ a gate cannot run, leave the statuses as they are and name the missing gate in
252
+ INDEX.md and ACTIVE.md.
253
+ - All tasks are `ready` (planning only) → **only an explicit amendment may overwrite**: when the human names the existing plan to refine: first copy every prior file (PLAN.md, SPEC.md, LEDGER.md, NOTES.md, SOURCE.md, tasks/TASK-*.md, when present) to the next unused `amendments/rev-<NN>/` under the same root (scan existing rev dirs and take max+1; never reuse or overwrite an existing rev dir). Then run the mechanical guard ONCE, naming every file you are about to rewrite — `node .claude/ukit/index/amend-guard.mjs docs/AI_HANDOFF PLAN.md SPEC.md` — and only an `AMEND_GUARD: ok` line lets the rewrite proceed (a queued root passes its own root path). The checker is mechanical — it verifies the `amendments/rev-<NN>` copy exists on disk — but its invocation is prose: no host hook runs it for you, so run it yourself before composing the revision. Then compose the revised PLAN.md in full: carry the existing `## Amendment History` forward and append this amendment's entry (prior review rounds and verdicts; prior requirement, decision and task versions with what changed and why; each change's `invalidated` evidence: tasks, executor reports, verdicts that no longer hold). Write the revised PLAN.md only after that entry is in the composed text, so the overwrite can never drop the history. An **independent new request** (a different goal, even when the old tasks are all `ready`) is NOT an amendment: write it under the queued root `docs/AI_HANDOFF/queued/<slug>/` and never overwrite the existing canonical plan.
187
254
  - Any task is `pending_review`, `changes_requested`, `merge_conflict`, or `blocked` → **do not overwrite** the in-flight cycle: its task files carry executor reports and verdicts. An **independent new request** is still planned and written under the queued root `docs/AI_HANDOFF/queued/<slug>/` (it is never refused for this reason); report which tasks are in flight and point the human at `/ukit:handoff-review` (to finish the cycle) or `/ukit:handoff-clear` (to abandon it). Only an explicit amendment of the in-flight plan is refused, with that pointer.
188
255
  - No tasks → fresh cycle, proceed normally.
189
256
 
190
- 2. Resolve base branch:
191
- ```bash
192
- BASE=$(git symbolic-ref --short HEAD)
193
- ```
257
+ 2. Resolve base branch: run ONE simple command — `git symbolic-ref --short HEAD` — and use
258
+ the printed branch name as a literal (`<base-branch>`) in ACTIVE.md's `Base:` line and in
259
+ any later command. No assignment, no command substitution, no compound.
194
260
 
195
261
  3. Write `${OUTPUT_ROOT}SPEC.md` — the detailed implementation spec (BẮT BUỘC before tasks).
196
262
  Follow `docs/AI_HANDOFF/SPEC.md`'s template sections (or `template_project/docs/AI_HANDOFF/SPEC.md`
@@ -224,14 +290,37 @@ The planner agent does the following (use Step 1 summary — do NOT re-read file
224
290
  Every task MUST have:
225
291
  - Spec references (SPEC.md section IDs this task implements)
226
292
  - Target Files (exact paths — no two tasks in same wave share a file)
227
- - Dependencies (`TASK-xxx` or `none` — wave structure inferred from this, not stored separately)
228
- - Test Cases (Type | Name | Expected — ≥1 happy + ≥2 edge cases of different kinds)
293
+ - Dependencies (`TASK-xxx` or `none` — wave structure inferred from this, not stored separately; a source delivery-order qualifier like "after import works" IS a dependency, name its source line)
294
+ - Test Cases (Type | Name | Expected — ≥1 happy + ≥2 edge cases of different kinds; every Expected is ONE deterministic outcome, never "X or nothing")
229
295
  - Test Files (exact paths)
230
- - Verification Commands (runnable shell commands)
296
+ - Verification Commands (runnable shell commands that run the tests — grepping a doc for a literal line such as `Coverage: N/N` is not evidence)
231
297
  - Acceptance Criteria (verifiable checklist)
232
- Missing any field → status: `needs_breakdown`, never `ready`
233
-
234
- 6. Update `${OUTPUT_ROOT}INDEX.md` — one row per task. Canonical root: `status=ready`.
298
+ Missing any field → status: `needs_breakdown`, never `ready`.
299
+ Write every task file `Status: needs_breakdown` — `ready` is a verdict, not a default —
300
+ and run the task-budget validator on each file you just wrote as ONE simple command per
301
+ task, from the project root, literal path, no `cd`, no loop, no shell variables, no
302
+ pipes, no compound:
303
+ ```
304
+ node .claude/ukit/index/task-budget-validator.mjs docs/AI_HANDOFF/tasks/TASK-001.md
305
+ ```
306
+ Repeat the command per task file (eight tasks = eight separate calls). `VERDICT:
307
+ needs_breakdown` → split further, or record a one-line dismissal in the task's
308
+ `## Discussion`. Nothing is `ready` yet — the review gate in Step 2.5 still applies.
309
+ Right after each `VERDICT: ok`, record it from the tool itself with ONE simple command
310
+ per task — `node .claude/ukit/index/task-budget-validator.mjs --record docs/AI_HANDOFF/tasks/TASK-001.md` — which re-validates and appends
311
+ `Validator: ok <YYYY-MM-DD> <tool-version>` to that task's `## Discussion` thread
312
+ (atomic temp-file + rename, existing BOM and line endings preserved, idempotent — a
313
+ second run never duplicates the line — and it refuses a non-ok verdict, so a
314
+ `needs_breakdown` file is never recorded). A dismissal stays a hand-written one-liner:
315
+ `Validator: dismissed <YYYY-MM-DD> — <reason>`. Verdicts live on disk, not in session
316
+ memory: compaction must not erase a gate.
317
+
318
+ 6. Update `${OUTPUT_ROOT}INDEX.md` — one row per task. Canonical root: rows start
319
+ `status=needs_breakdown`; set `ready` only in Step 2.5, after the validator passed each
320
+ task (or a documented dismissal) AND the independent plan review returned `Approved`.
321
+ If the run ends before both gates completed (budget exhausted, command denied,
322
+ interruption), the rows stay `needs_breakdown`, and INDEX.md and ACTIVE.md must say
323
+ which gate is missing.
235
324
  **Queued root: a draft index with `status=queued_blueprint` rows, never `ready`.** The queued
236
325
  blueprint's own `INDEX.md` and `tasks/` are a draft only: they are not canonical runnable
237
326
  admission. The "first 10 active" rule applies to the canonical root alone; a blueprint's tasks
@@ -247,6 +336,10 @@ The planner agent does the following (use Step 1 summary — do NOT re-read file
247
336
  Tasks: <N> total
248
337
  Status: planning_done — ready for executor
249
338
  ```
339
+ When the gates have not all passed, write the honest state instead:
340
+ `Status: planning_incomplete — tasks not ready: <validator | plan review>` (a
341
+ human-readable ACTIVE.md marker only — machine readers parse INDEX.md rows and
342
+ task-file `- Status:` lines, never write `planning_incomplete` into those).
250
343
  Note: wave structure is inferred from task Dependencies fields — not stored here.
251
344
 
252
345
  8. Report: task IDs, dependency graph, any `needs_breakdown` + reason — and, when queued,
@@ -277,14 +370,16 @@ round gives one more fresh pass on anything still open. A stalled plan is never
277
370
 
278
371
  1. Reviewer reads `SPEC.md` + `PLAN.md` plus the plan's sources, starting from the original: `SOURCE.md` (the verbatim original bytes; verify the recorded sha256 against them; for chat input, the durable verbatim message origin stands in for the file), then `LEDGER.md` (classification of every requirement), `NOTES.md` (optional source-only notes, when present; a missing note is caught because the chain starts at SOURCE, not at NOTES), the `tasks/TASK-*.md` files of the plan, and the current source the plan's Target Files touch (no executor report, no diff). It compares the chain SOURCE → classification (LEDGER) → tasks (acceptance and verification), and NOTES are checked against the same chain. Each `feasible`/`adapted` row maps to a task with acceptance and a verification command. It checks that every `feasible`/`adapted` row and every requirement not explicitly deferred, blocked, or classified as rejected/proposal/example is covered by a task with acceptance and verification, that no feasible/adapted row lacks evidence, and 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).
279
372
  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`.
280
- 3. `Approved` → append `PLAN_REVIEW: Approved by <reviewer model>` to PLAN.md's `## Planner Report` footer, then proceed.
373
+ 3. `Approved` → append `PLAN_REVIEW: Approved by <reviewer model>` to PLAN.md's `## Planner Report` footer. Before any flip, run the mechanical ready gate ONCE on the output root — `node .claude/ukit/index/ready-gate.mjs ${OUTPUT_ROOT}` — and require `READY_GATE: ok` (every task marked `ready` carries a recorded `Validator:` line and PLAN.md carries `PLAN_REVIEW: Approved`; INDEX rows and task files agree). Any `tasks not ready: …` / `index/task mismatch …` line names the exact gap — fix it (re-run the validator with `--record`, finish the review, align the statuses) and re-run the gate; do not flip while it fails. This is the second of the two readiness gates: flip ONLY the tasks whose task file's `## Discussion` records `Validator: ok <date>` (or `Validator: dismissed <date> — <reason>`) to `Status: ready` in that task file and in `INDEX.md` — re-read each task file from disk to decide, never from session memory; a task without the recorded `Validator:` line stays `needs_breakdown` (a verdict held only in the session does not count) — and set ACTIVE.md to `Status: planning_done — ready for executor`.
281
374
 
282
375
  > **For the human operator, on a tool with no agent support (Codex) — not an instruction to the model:** manually switch to the strong model in a **separate** chat/session from Step 2, paste PLAN.md, review using the Spec/Plan Review checklist in `.claude/agents/code-reviewer.md`.
283
376
 
284
377
  ---
285
378
 
286
- **Next:** the plan is complete and every task is `ready` (queued — nothing has been
287
- implemented). To start implementation, the human runs `/ukit:handoff-implement` for the
379
+ **Next:** the plan is complete; every task is `ready` only when both gates passed (validator
380
+ `VERDICT: ok` per task + review `Approved`) — otherwise the tasks stay `needs_breakdown`
381
+ and INDEX/ACTIVE name the missing gate (nothing has been implemented either way). To start
382
+ implementation once the tasks are `ready`, the human runs `/ukit:handoff-implement` for the
288
383
  plan-only flow, or `/ukit:handoff-fullstack` to drive plan → implement → review as one
289
384
  one-shot pipeline. This command does not do either on its own.
290
385