@ngockhoale/ukit 3.4.67 → 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.
- package/CHANGELOG.md +12 -0
- package/manifests/documentation.yaml +33 -0
- package/manifests/instructionRules.yaml +10 -0
- package/manifests/platform.full.yaml +67 -0
- package/package.json +1 -1
- package/src/core/applyPlan.js +111 -2
- package/src/core/buildPlan.js +3 -1
- package/src/core/diffPlan.js +49 -1
- package/src/core/executionContracts.js +49 -8
- package/src/core/metadata.js +45 -0
- package/src/core/runInstallPipeline.js +30 -2
- package/src/core/uninstall.js +106 -2
- package/src/manifest/validateManifest.js +25 -1
- package/template_project/.claude/agents/code-reviewer.md +22 -9
- package/template_project/.claude/agents/handoff-planner.md +97 -8
- package/template_project/.claude/commands/ukit/handoff-create.md +114 -19
- package/template_project/.claude/commands/ukit/handoff-fullstack.md +247 -79
- package/template_project/.claude/commands/ukit/handoff-implement.md +75 -40
- package/template_project/.claude/commands/ukit/handoff-review.md +14 -10
- package/template_project/.claude/hooks/auto-allow-bash.sh +73 -12
- package/template_project/.claude/hooks/auto-prune-bash.sh +10 -0
- package/template_project/.claude/hooks/delegation-gate.mjs +21 -0
- package/template_project/.claude/hooks/handoff-model-guard.sh +22 -6
- package/template_project/.claude/hooks/handoff-resume.sh +141 -1
- package/template_project/.claude/hooks/record-execution.mjs +140 -9
- package/template_project/.claude/hooks/skill-router.sh +173 -8
- package/template_project/.claude/settings.json +2 -2
- package/template_project/.claude/skills/advisor-plan/REFERENCE.md +10 -0
- package/template_project/.claude/skills/advisor-plan/SKILL.md +2 -2
- package/template_project/.claude/ukit/index/allocate-task-worktree.mjs +15 -0
- package/template_project/.claude/ukit/index/amend-guard.mjs +116 -0
- package/template_project/.claude/ukit/index/cleanup-task-worktree.mjs +1 -1
- package/template_project/.claude/ukit/index/land-worktree.mjs +243 -21
- package/template_project/.claude/ukit/index/plan-count.mjs +115 -0
- package/template_project/.claude/ukit/index/ready-gate.mjs +170 -0
- package/template_project/.claude/ukit/index/reset-auto-permissions.mjs +293 -4
- package/template_project/.claude/ukit/index/route-resolver.mjs +48 -8
- package/template_project/.claude/ukit/index/route-task.mjs +180 -11
- package/template_project/.claude/ukit/index/source-snapshot.mjs +172 -0
- package/template_project/.claude/ukit/index/task-budget-validator.mjs +109 -3
- package/template_project/.claude/ukit/runtime/execution-ledger.mjs +20 -3
- package/template_project/.claude/ukit/runtime/handoff-task-scope.mjs +205 -0
- package/template_project/.claude/ukit/runtime/loop-state.mjs +3 -1
- package/template_project/.claude/ukit/runtime/plan-dispatch.mjs +32 -5
- package/template_project/.claude/ukit/runtime/resumable-run.mjs +310 -21
- package/template_project/.claude/ukit/runtime/stop-coordinator.mjs +405 -105
- package/template_project/.claude/ukit/runtime/task-record-reconciliation.mjs +46 -0
- package/template_project/.claude/ukit/runtime/task-watchdog.mjs +28 -2
- package/template_project/.claude/ukit/runtime/worktree-allocation.mjs +75 -0
- package/template_project/.codex/README.md +25 -0
- package/template_project/.omp/RULES.md +22 -22
- package/template_project/.omp/agents/code-reviewer.md +22 -9
- package/template_project/.omp/agents/handoff-planner.md +102 -12
- package/template_project/.omp/hooks/pre/ukit-bridge.js +1 -1
- package/template_project/AGENTS.md +5 -1
- package/template_project/CLAUDE.md +1 -1
- package/template_project/docs/AI_HANDOFF/RULES.md +8 -0
- package/template_project/docs/AI_HANDOFF/tasks/_TEMPLATE.md +8 -1
- package/template_project/instructions/core.md +5 -1
- package/template_project/instructions/layout.yaml +2 -0
- package/template_project/instructions/overlays/omp-rules.md +22 -22
- package/template_project/ukit/storage/config.json +1 -1
|
@@ -74,7 +74,12 @@ resumable. If compaction does happen, the run resumes from the cursor automatica
|
|
|
74
74
|
### Run cursor — write after every step
|
|
75
75
|
|
|
76
76
|
Maintain `docs/AI_HANDOFF/RUN.md`. Rewrite it (whole file — the fixed field block below,
|
|
77
|
-
exactly as many lines as the fields in play) immediately after every numbered step completes
|
|
77
|
+
exactly as many lines as the fields in play) immediately after every numbered step completes.
|
|
78
|
+
Before dispatching any mutating worker (including blueprint folding), write and read back the
|
|
79
|
+
P0/P1 cursor with the actual phase, frozen scope, next action and known job references. Do not
|
|
80
|
+
defer cursor creation until P2; omit ExitPredicate until P2 pins it, never invent a satisfied one.
|
|
81
|
+
Reconcile partial writes and existing jobs from that cursor on interruption; never restart the fold blindly.
|
|
82
|
+
|
|
78
83
|
|
|
79
84
|
```
|
|
80
85
|
Command: handoff-fullstack
|
|
@@ -92,6 +97,8 @@ RetryFingerprint: <stable id of the failing step> # optional; retry-loop ident
|
|
|
92
97
|
RetryCount: <n> # optional; consecutive attempts of that fingerprint
|
|
93
98
|
ScopePlans: <slug[,slug...]> | none # optional; history/archive/Ready-for-AI items the invocation authorized
|
|
94
99
|
ScopeQueue: <slug[,slug...]> | none # optional; the queued blueprints frozen into this run at P2
|
|
100
|
+
TaskScope: cycle-<NN>/TASK-001 = queue:<slug> # repeat per imported task; cycle-qualified key (TASK ids are reused across cycles); plan:<ScopePlans entry> for an authorized plan
|
|
101
|
+
TaskScope: cycle-<NN>/TASK-001-R1 = repair:TASK-001 # unqualified parent = same cycle; repair:cycle-<NN>/TASK-xxx pins an explicit older-cycle parent
|
|
95
102
|
Authorization: <one line — who authorized the scope and from which invocation> # optional
|
|
96
103
|
LateCreate: <slug> — <disposition> # optional; a create that arrived mid-run, never auto-folded
|
|
97
104
|
```
|
|
@@ -104,7 +111,29 @@ session boundaries; they never replace INDEX.md or RUN.md authority.
|
|
|
104
111
|
|
|
105
112
|
**Late creates do not expand scope.** A blueprint or Ready-for-AI item that appears mid-run and is
|
|
106
113
|
not in `ScopeQueue`/`ScopePlans` is recorded as `LateCreate:` with disposition `Backlog`. A late create does not expand scope and is never silently folded in. Repairs of work already assigned to this run
|
|
107
|
-
still continue.
|
|
114
|
+
still continue. When folding a blueprint or authorized plan into INDEX, stamp a repeated
|
|
115
|
+
`TaskScope:` line for every assigned task in RUN.md. A repair/replan stamps `repair:<original task>`
|
|
116
|
+
(unqualified parent resolves in the same cycle) or `repair:cycle-<NN>/<original task>` (explicit
|
|
117
|
+
older-cycle parent) and inherits that task's scope, including across repair chains — never
|
|
118
|
+
unrelated late scope.
|
|
119
|
+
|
|
120
|
+
**Task ids are reused across cycles — qualify scope keys.** Stamp every new `TaskScope:` mapping
|
|
121
|
+
cycle-qualified (`cycle-<NN>/TASK-001`, same spelling the run's `Cycle:` field and claim cycles
|
|
122
|
+
normalize to). A task id reused in a later cycle never overwrites or inherits an earlier cycle's
|
|
123
|
+
scope or repair chain: the current cycle's mapping governs the live INDEX evaluation and each
|
|
124
|
+
archive cycle's mapping governs its ARCHIVE snapshot. Preserve ALL mapping lines on disk across
|
|
125
|
+
compaction, resume and cycle transition — retain the original mapping even after its task closes;
|
|
126
|
+
never rewrite or drop an older cycle's lines when opening the next cycle. Legacy unqualified
|
|
127
|
+
mappings stay honored only while no other cycle qualified the same id; an unqualified mapping that
|
|
128
|
+
collides with a cycle-qualified one is ambiguous and keeps the run in reconciliation instead of
|
|
129
|
+
guessing the old cycle. Completion, blocked and archive predicates use the same membership
|
|
130
|
+
selector: exclude only a task mapped to a different cycle/queue than the one being evaluated, and
|
|
131
|
+
refuse completion while any in-scope mapping is unresolved — unknown, conflicting, malformed,
|
|
132
|
+
cyclic or ambiguous mappings remain included and require reconciliation against the source before
|
|
133
|
+
declaring completion; never guess away unmapped obligations. The resume hook prints a bounded
|
|
134
|
+
slice of the frozen map (the current cycle plus the CurrentTask repair chain, hard-capped); the
|
|
135
|
+
full map is never truncated on disk — read `docs/AI_HANDOFF/RUN.md` for the remainder. Legacy runs
|
|
136
|
+
without frozen scope retain all INDEX rows. The eight-column INDEX format is unchanged.
|
|
108
137
|
|
|
109
138
|
**Compact-carry fields.** `Acceptance`, `CurrentTask`, `RetryFingerprint` and `RetryCount`
|
|
110
139
|
are what a compacted session carries forward — these four lines plus `Goal`/`Next:`, never
|
|
@@ -175,11 +204,13 @@ skipped silently.
|
|
|
175
204
|
|
|
176
205
|
`Phase: blocked` is terminal for the run — the machinery (Stop gate, hooks, stop-coordinator)
|
|
177
206
|
all treats it as closed. It is *paused*, not abandoned: an explicit `/ukit:handoff-fullstack`
|
|
178
|
-
re-invocation resumes it as a continuation; `ukit handoff-clear`
|
|
207
|
+
re-invocation resumes it as a continuation; `ukit handoff-clear` pauses it (`Paused: yes`, backlog and scope kept, no completion minted). Only when
|
|
179
208
|
`RUN.md` is absent or `Phase: done` does a new request start a fresh cycle.
|
|
180
209
|
|
|
181
210
|
### Explicit invocation reacquires ownership
|
|
182
211
|
|
|
212
|
+
An explicit `/ukit:handoff-fullstack` also lifts a liveness pause: the resume hook rewrites `Paused: yes` to `Paused: no` in `RUN.md`, reads it back, and keeps `Phase:`, scope, and the queue untouched. Ordinary prompts, startup, and clear never lift it.
|
|
213
|
+
|
|
183
214
|
`/ukit:handoff-create` is planning-only and makes a session's handoff intent *planning* — so
|
|
184
215
|
while the human is planning, neither the Stop gate nor the SessionStart compact/resume hook
|
|
185
216
|
forces a paused run back into implementation. This command is the explicit counter-action:
|
|
@@ -226,6 +257,57 @@ Never stop at `recap: ... Next: ...` while unfinished work remains — the Stop
|
|
|
226
257
|
bounces that stop straight back into the pipeline, so stopping is not even restful; it
|
|
227
258
|
just costs a round-trip.
|
|
228
259
|
|
|
260
|
+
### Pre-stop reconciliation — decide the stop, never rely on the bounce
|
|
261
|
+
|
|
262
|
+
The Stop gate is the **backstop, never the plan**. Before ANY turn ends — mid-wave or at
|
|
263
|
+
the end of the pipeline — reconcile the run once, explicitly, against this checklist and
|
|
264
|
+
then choose the ending yourself:
|
|
265
|
+
|
|
266
|
+
1. **Tasks** — every in-scope task is `done`/`cancelled_superseded`, or its real phase and
|
|
267
|
+
next step are in the cursor. Nothing is left "almost done" without a record.
|
|
268
|
+
2. **Acceptance** — every done task's acceptance criteria carry verification evidence on
|
|
269
|
+
disk (command + output). Never waived, never assumed.
|
|
270
|
+
3. **Findings** — every review/plan finding is dispositioned: fixed, or recorded as
|
|
271
|
+
`changes_requested`/`needs_breakdown` with its open signature. Nothing silently open.
|
|
272
|
+
4. **Jobs** — every spawned agent/background job is awaited through the host's own
|
|
273
|
+
mechanics (agent task result, background-shell output) and its report is consumed into
|
|
274
|
+
run state before the next step. NEVER spawn a second job for work a live job is
|
|
275
|
+
already doing — await the live one and consume its result.
|
|
276
|
+
5. **Independent work** — a blocked or waiting branch never strands independent tasks:
|
|
277
|
+
they ran first (Autonomy Contract).
|
|
278
|
+
6. **Integration** — landed work is committed (scoped `--only` commits); worktrees and
|
|
279
|
+
branches are cleaned, or every survivor is named in the retained-reason report.
|
|
280
|
+
7. **Release** — the run's single push (R5) happened, or the reason it did not is named.
|
|
281
|
+
8. **Consumer** — when a task or the goal names consumer/release evidence, it is recorded;
|
|
282
|
+
a missing consumer gate is work remaining, not a stop.
|
|
283
|
+
9. **Pause** — a pause (`Paused: yes`, set via `ukit handoff-clear` or an explicit user
|
|
284
|
+
instruction) releases the session: the backlog is retained, completion is never
|
|
285
|
+
minted, and nothing resumes until an explicit instruction lifts the pause.
|
|
286
|
+
10. **Blocker** — `HANDOFF FULLSTACK BLOCKED` only when every remaining task shares one
|
|
287
|
+
valid external blocker, evidence and attempted fixes are recorded, and no safe local
|
|
288
|
+
work exists.
|
|
289
|
+
|
|
290
|
+
**Turn wait ≠ run done.** If reconciliation leaves a live job running, a host async
|
|
291
|
+
result pending, or any checklist item open, the correct outcome is a **turn wait**: bound
|
|
292
|
+
the wait with the host's own mechanics, write the CHECKPOINT block above (cursor updated:
|
|
293
|
+
YES), and keep the run alive. A turn wait is never `Phase: done` and never claims
|
|
294
|
+
completion. If the wait ends in a compaction, the cursor plus the SessionStart resume
|
|
295
|
+
hook continue the run — never a manual `/compact` instruction loop. If Ready independent
|
|
296
|
+
work exists, select and run it first; a turn wait is only for an actual pending host event
|
|
297
|
+
with no runnable independent scope. **Pause** (`Paused: yes`) and **cancel** are releases,
|
|
298
|
+
not completion: they emit no terminal line and mint nothing. **Blocked** is a terminal
|
|
299
|
+
release, not done: `HANDOFF FULLSTACK BLOCKED` is emitted only when no safe local work
|
|
300
|
+
remains. **Run done** is only §0's `HANDOFF FULLSTACK COMPLETE` after F4, with the checklist
|
|
301
|
+
green item by item. The Final Report states scope-complete and correct termination as two
|
|
302
|
+
separate facts.
|
|
303
|
+
|
|
304
|
+
**Completed runs are not restarted by their own echo.** If this session is re-invoked (a
|
|
305
|
+
stale watchdog job, a repeated prompt, a queued wakeup) and `RUN.md` still reads
|
|
306
|
+
`Phase: done` with its ExitPredicate satisfied, the invocation is a **no-op**: re-verify
|
|
307
|
+
the predicate cheaply, re-emit the completion report if one is due, disarm the stale
|
|
308
|
+
watchdog job, and stop. A new cycle starts ONLY from a new explicit user request — never
|
|
309
|
+
from the run's own completion echo.
|
|
310
|
+
|
|
229
311
|
---
|
|
230
312
|
|
|
231
313
|
## Phase 0 — Sweep & Inventory (before planning)
|
|
@@ -256,7 +338,15 @@ work, not only the current plan:
|
|
|
256
338
|
so it is folded in here like any legacy blueprint and is never silently excluded.
|
|
257
339
|
Backlog items do not count toward `index:all-done` / `ExitPredicate`, so they never block completion. Only
|
|
258
340
|
an explicit slug in the invocation drains one (one blueprint per invocation). The
|
|
259
|
-
create phase of this command applies the same advisor intake as `/ukit:handoff-create
|
|
341
|
+
create phase of this command applies the same advisor intake as `/ukit:handoff-create`
|
|
342
|
+
— including the SOURCE snapshot (`node .claude/ukit/index/source-snapshot.mjs
|
|
343
|
+
<original-path> docs/AI_HANDOFF/SOURCE.md`, or `source snapshot MISSING` stated in
|
|
344
|
+
PLAN/LEDGER when it cannot run) and the plan-count rule: an owner-stated plan count is
|
|
345
|
+
delivered as that many real plans (the first under the planning root, each further one
|
|
346
|
+
its own `docs/AI_HANDOFF/queued/<slug>/` blueprint with its own SPEC.md/PLAN.md/tasks/;
|
|
347
|
+
labels inside one PLAN never satisfy a stated count; verify mechanically with
|
|
348
|
+
`node .claude/ukit/index/plan-count.mjs docs/AI_HANDOFF <N>` → `PLAN_COUNT: ok (<found>/<N>)`;
|
|
349
|
+
if impossible, record an explicit owner-decision item).
|
|
260
350
|
6. `git status` / `git diff` — uncommitted work-in-progress that must be finished or
|
|
261
351
|
checkpointed, never silently dropped.
|
|
262
352
|
|
|
@@ -264,10 +354,19 @@ The inventory feeds P2: the planner either schedules every discovered item or re
|
|
|
264
354
|
it is out of scope (§1/§2 of PLAN.md). Silent omission is a plan defect — a queued
|
|
265
355
|
blueprint dropped without either scheduling or a recorded reason is exactly that defect.
|
|
266
356
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
357
|
+
**Resume gates before planning.** If INDEX.md has `needs_breakdown` rows and PLAN.md has no
|
|
358
|
+
`PLAN_REVIEW: Approved`, a previous planning run died before both gates completed: do NOT
|
|
359
|
+
re-intake the request, do NOT re-run the advisor chain, do NOT rewrite SPEC/PLAN/tasks, and
|
|
360
|
+
never overwrite the existing plan on this path. Run only the missing gates on the existing
|
|
361
|
+
plan — the per-task validator (`--record`, P2 step 5) for tasks lacking a recorded
|
|
362
|
+
`Validator:` line, and the P2.5 independent review — then flip per the ready gate and
|
|
363
|
+
continue from P3. If a gate cannot run, leave the statuses as they are and name the missing
|
|
364
|
+
gate in INDEX.md and ACTIVE.md.
|
|
365
|
+
|
|
366
|
+
> **Never overwrite a live run to consume a queued blueprint.** Fold only through P2's
|
|
367
|
+
> normal plan-write path. On Resume, continue an already-authorized fold recorded in the
|
|
368
|
+
> cursor's frozen scope and `Next:`; reconcile partial writes and existing jobs first.
|
|
369
|
+
> Do not admit unrelated queued blueprints: leave those untouched for the next cycle.
|
|
271
370
|
|
|
272
371
|
**Recovery rule — stuck task records.** For every `pending`, stale `in_progress`, or
|
|
273
372
|
`blocked` task whose record cannot be cleanly resumed (invalid state, orphaned worktree
|
|
@@ -294,10 +393,12 @@ The run must keep itself alive without the human watching.
|
|
|
294
393
|
(`handoff.fullstack.stopGateMaxStalledBlocks`, default 12) releases the session if the
|
|
295
394
|
cursor has genuinely stopped advancing — the escape hatch, not the norm — and its
|
|
296
395
|
release advisory reports the predicate state, so a plateau is visible, not silent.
|
|
297
|
-
- **Scheduled wakeup (when the harness offers one):**
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
396
|
+
- **Scheduled wakeup (when the harness offers one):** use the supported host event wait, not
|
|
397
|
+
a polling job. Do not create a duplicate job: arm at most one resume wakeup while a real
|
|
398
|
+
host event is pending, and cancel it on pause, cancel, blocker, or completion
|
|
399
|
+
(`Phase: done` / `blocked` / `Paused: yes`). Claude Code's supported mechanics are the
|
|
400
|
+
Stop gate and SessionStart resume hook; `CronCreate` is used only when the harness offers no
|
|
401
|
+
event wait.
|
|
301
402
|
- **Harnesses with neither:** treat EVERY activation as a watchdog recovery turn — read
|
|
302
403
|
RUN.md first, rescan the inventory, continue `Next:`.
|
|
303
404
|
|
|
@@ -335,14 +436,20 @@ Return a compact summary. Do NOT write any files yet.
|
|
|
335
436
|
The planner agent does the following (use P1 summary — do NOT re-read files):
|
|
336
437
|
|
|
337
438
|
1. **Guard — check INDEX statuses:**
|
|
338
|
-
-
|
|
439
|
+
- **Resume gates — `needs_breakdown` rows and PLAN.md without `PLAN_REVIEW: Approved`:**
|
|
440
|
+
a previous planning run died before both gates. Never re-intake and never rewrite
|
|
441
|
+
SPEC/PLAN/tasks, never overwrite the existing plan. Run only the missing gates on the
|
|
442
|
+
existing plan — the per-task validator (`--record`, step 5 below) for tasks lacking a
|
|
443
|
+
recorded `Validator:` line and the P2.5 independent review — flip per the ready gate,
|
|
444
|
+
and report; the orchestrator continues from P3.
|
|
445
|
+
- All tasks are `ready` (planning only) → **only an explicit amendment may overwrite**: when the human explicitly names this plan to amend, 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>/` (scan existing rev dirs, take max+1, never reuse one). Then run the mechanical guard ONCE — `node .claude/ukit/index/amend-guard.mjs docs/AI_HANDOFF PLAN.md SPEC.md`, naming every file about to be rewritten — and proceed only on `AMEND_GUARD: ok` (the checker is mechanical; its invocation is prose). 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** is NOT an amendment: write its plan under `docs/AI_HANDOFF/queued/<slug>/` (the queued lane, see Phase 0) and never overwrite the existing canonical plan.
|
|
339
446
|
- Any task has status `pending_review`, `changes_requested`, `merge_conflict`, or `blocked` → **do not overwrite, and do not stop either.** Mid-flight work exists. Skip the rest of P2 entirely, write the run cursor with `Phase: I1`, and hand control back to the orchestrator to resume from Phase 3 with the surviving tasks (see Resume in the Autonomy Contract). Overwriting is what is unsafe here — stopping is not required.
|
|
340
447
|
- No tasks → fresh cycle, proceed.
|
|
341
448
|
|
|
342
|
-
2. **Resolve base branch:**
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
449
|
+
2. **Resolve base branch:** run ONE simple command — `git symbolic-ref --short HEAD` — and
|
|
450
|
+
use the printed branch name as a literal (`<base-branch>`) in ACTIVE.md's `Base:` line
|
|
451
|
+
and in every later command (worktree creation, final push). No assignment, no command
|
|
452
|
+
substitution, no compound.
|
|
346
453
|
|
|
347
454
|
3. **Write `docs/AI_HANDOFF/SPEC.md`** — the detailed implementation spec, from
|
|
348
455
|
`template_project/docs/AI_HANDOFF/SPEC.md`'s section list (or RULES.md §Spec). It must be
|
|
@@ -370,16 +477,36 @@ The planner agent does the following (use P1 summary — do NOT re-read files):
|
|
|
370
477
|
Every task MUST have:
|
|
371
478
|
- Spec references (SPEC.md section IDs this task implements)
|
|
372
479
|
- Target Files (exact paths — no two tasks in same wave share a file)
|
|
373
|
-
- Dependencies (`TASK-xxx` or `none` — wave structure inferred from this)
|
|
374
|
-
- Test Cases (Type | Name | Expected — ≥1 happy + ≥2 edge cases of different kinds)
|
|
480
|
+
- Dependencies (`TASK-xxx` or `none` — wave structure inferred from this; a source delivery-order qualifier like "after import works" IS a dependency, name its source line)
|
|
481
|
+
- Test Cases (Type | Name | Expected — ≥1 happy + ≥2 edge cases of different kinds; every Expected is ONE deterministic outcome, never "X or nothing")
|
|
375
482
|
- Test Files (exact paths)
|
|
376
|
-
- Verification Commands (runnable shell commands)
|
|
483
|
+
- Verification Commands (runnable shell commands that run the tests — grepping a doc for a literal line such as `Coverage: N/N` is not evidence)
|
|
377
484
|
- Acceptance Criteria (verifiable checklist)
|
|
378
485
|
Missing any field → status `needs_breakdown`, never `ready`.
|
|
379
|
-
|
|
380
|
-
|
|
486
|
+
Write every task file `Status: needs_breakdown` — `ready` is a verdict, not a default —
|
|
487
|
+
and run the task-budget validator on each file as ONE simple command per task, from the
|
|
488
|
+
project root, literal path, no `cd`, no loop, no shell variables, no pipes, no compound:
|
|
489
|
+
```
|
|
490
|
+
node .claude/ukit/index/task-budget-validator.mjs docs/AI_HANDOFF/tasks/TASK-001.md
|
|
491
|
+
```
|
|
492
|
+
Repeat the command per task file (eight tasks = eight separate calls). `VERDICT:
|
|
493
|
+
needs_breakdown` → split further, or record a one-line dismissal in the task's
|
|
494
|
+
`## Discussion`. Nothing is `ready` until P2.5 returns `Approved`.
|
|
495
|
+
Right after each `VERDICT: ok`, record it from the tool itself with ONE simple command
|
|
496
|
+
per task — `node .claude/ukit/index/task-budget-validator.mjs --record docs/AI_HANDOFF/tasks/TASK-001.md` — which re-validates and appends
|
|
497
|
+
`Validator: ok <YYYY-MM-DD> <tool-version>` to that task's `## Discussion` thread
|
|
498
|
+
(atomic temp-file + rename, existing BOM and line endings preserved, idempotent — a
|
|
499
|
+
second run never duplicates the line — and it refuses a non-ok verdict, so a
|
|
500
|
+
`needs_breakdown` file is never recorded). A dismissal stays a hand-written one-liner:
|
|
501
|
+
`Validator: dismissed <YYYY-MM-DD> — <reason>`. Verdicts live on disk, not in session
|
|
502
|
+
memory: compaction must not erase a gate.
|
|
503
|
+
|
|
504
|
+
6. **Update `docs/AI_HANDOFF/INDEX.md`** — one row per task, starting
|
|
505
|
+
`status=needs_breakdown`; P2.5's `Approved` verdict is what sets `ready` (every
|
|
381
506
|
unfinished item from the Phase 0 sweep is either a row here or superseded by a
|
|
382
|
-
`-R<n>` recovery row.
|
|
507
|
+
`-R<n>` recovery row). If the run ends before both gates completed (budget exhausted,
|
|
508
|
+
command denied, interruption), the rows stay `needs_breakdown`, and INDEX.md and
|
|
509
|
+
ACTIVE.md must say which gate is missing.
|
|
383
510
|
Then **verify the write** (read back the new rows).
|
|
384
511
|
|
|
385
512
|
7. **Update `docs/AI_HANDOFF/ACTIVE.md`:**
|
|
@@ -390,6 +517,10 @@ The planner agent does the following (use P1 summary — do NOT re-read files):
|
|
|
390
517
|
Tasks: <N> total
|
|
391
518
|
Status: planning_done — ready for executor
|
|
392
519
|
```
|
|
520
|
+
When the gates have not all passed, write the honest state instead:
|
|
521
|
+
`Status: planning_incomplete — tasks not ready: <validator | plan review>` (a
|
|
522
|
+
human-readable ACTIVE.md marker only — machine readers parse INDEX.md rows and
|
|
523
|
+
task-file `- Status:` lines, never write `planning_incomplete` into those).
|
|
393
524
|
Then **verify the write** (read back the `Status:` line).
|
|
394
525
|
|
|
395
526
|
8. **Write `ExitPredicate:` into `docs/AI_HANDOFF/RUN.md`** — the mechanical definition of
|
|
@@ -419,9 +550,9 @@ The gate still does its job: two independent opus passes plus one escalation pas
|
|
|
419
550
|
|
|
420
551
|
**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.
|
|
421
552
|
|
|
422
|
-
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 diff, no executor report). 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, and 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
|
|
553
|
+
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 diff, no executor report). 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, and 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 returns its verdict block; the planner appends it with `Edit` to PLAN.md's `## Plan Review Log` (new round entry, prior rounds kept).
|
|
423
554
|
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.
|
|
424
|
-
3. `Approved` → append `PLAN_REVIEW: Approved by <reviewer model>` to PLAN.md's `## Planner Report` footer,
|
|
555
|
+
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 — `node .claude/ukit/index/ready-gate.mjs docs/AI_HANDOFF` — and require `READY_GATE: ok`; any `tasks not ready: …` / `index/task mismatch …` line names the exact gap to fix and re-run, and no task flips while it fails. That verdict is the second readiness gate: 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` — P3 and the I-phase only ever collect `ready` tasks, so a skipped flip stalls the whole run. Then proceed to P3.
|
|
425
556
|
|
|
426
557
|
> **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 P2, paste PLAN.md, review using the Spec/Plan Review checklist in `.claude/agents/code-reviewer.md`.
|
|
427
558
|
|
|
@@ -515,11 +646,20 @@ leaves worktrees behind. Batching only ever narrows a wave, never reorders acros
|
|
|
515
646
|
|
|
516
647
|
For each wave:
|
|
517
648
|
|
|
518
|
-
**3a — Create worktrees** (one per task, from
|
|
649
|
+
**3a — Create worktrees** (one per task, from the `<base-branch>` literal recorded at P2 — ACTIVE.md `Base:`):
|
|
650
|
+
Under `Worktree-Policy: existing-only`, raw worktree mutation and Agent isolation remain forbidden.
|
|
651
|
+
Only an explicit owner-authorized RUN.md entry such as
|
|
652
|
+
`Worktree-Allow: TASK-003 handoff/task-003 .worktrees/task-003 owner-20261025`
|
|
653
|
+
permits that frozen task through `node .claude/ukit/index/allocate-task-worktree.mjs <absolute-project-root> TASK-003`.
|
|
654
|
+
The helper exclusively records task/branch/path/claim/base before allocation under the claims lock;
|
|
655
|
+
an existing intent refuses reallocation even after failure. Resume only that task's verified retained
|
|
656
|
+
worktree; never repurpose/delete a tree, allocate reviewer/investigator trees, or infer cleanup permission.
|
|
657
|
+
Without this restricted policy, use the normal command:
|
|
519
658
|
```bash
|
|
520
|
-
git worktree add -b handoff/task-xxx .worktrees/task-xxx
|
|
521
|
-
# (omit -b if branch already exists)
|
|
659
|
+
git worktree add -b handoff/task-xxx .worktrees/task-xxx <base-branch>
|
|
522
660
|
```
|
|
661
|
+
(Omit `-b` when the branch already exists. One simple command per worktree — no variable,
|
|
662
|
+
no compound.)
|
|
523
663
|
|
|
524
664
|
**3b — Run the batch in parallel** — one code-model agent per task in the batch (at most `handoff.maxParallelAgents`), each in its own worktree. Each agent:
|
|
525
665
|
```
|
|
@@ -527,12 +667,12 @@ Read docs/AI_HANDOFF/tasks/TASK-xxx.md
|
|
|
527
667
|
|
|
528
668
|
TDD — mandatory:
|
|
529
669
|
1. Write tests from §Test Cases
|
|
530
|
-
|
|
670
|
+
run <test command> from the worktree root (your cwd IS .worktrees/task-xxx — no cd)
|
|
531
671
|
Confirm RED — paste the actual failing output, don't just assert it happened
|
|
532
672
|
(immediately GREEN → test is wrong — flag this)
|
|
533
673
|
2. Implement → run → confirm GREEN
|
|
534
674
|
3. Run §Verification Commands inside the worktree:
|
|
535
|
-
|
|
675
|
+
run <each verification command> from the worktree root — no cd, no compound
|
|
536
676
|
Paste full output.
|
|
537
677
|
|
|
538
678
|
Milestone commits INSIDE your own worktree (e.g. `handoff/task-xxx`) are REQUIRED by the
|
|
@@ -570,45 +710,67 @@ run mid-pipeline.
|
|
|
570
710
|
|
|
571
711
|
Landing is **task-scoped, base-relative and receipt-backed** — never an ad-hoc cp loop.
|
|
572
712
|
`land-worktree.mjs` snapshots the source worktree's FINAL content against the immutable
|
|
573
|
-
|
|
713
|
+
`<base-branch>` head (committed milestone + staged + unstaged + nonignored untracked), so committed and
|
|
574
714
|
staged work is never dropped, deletions and rename origins are applied, and binary /
|
|
575
715
|
executable / symlink semantics and unusual filenames (space / newline / literal backslash)
|
|
576
716
|
survive. The helper refuses on any destination conflict, scope drift or identity drift
|
|
577
717
|
**before mutating anything** and writes no receipt on refusal.
|
|
578
718
|
|
|
579
719
|
For **PASS + EXECUTOR_MODEL present:**
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
720
|
+
|
|
721
|
+
1. Write the scope file with the **Write tool** (never a shell heredoc, no variable) to
|
|
722
|
+
`docs/AI_HANDOFF/benchmark/TASK-xxx-scope.json` — every field a literal. Get each value with ONE simple
|
|
723
|
+
command and paste the printed output: `git rev-parse <base-branch>` (baseCommit),
|
|
724
|
+
`git -C .worktrees/task-xxx rev-parse --show-toplevel` (sourceRoot),
|
|
725
|
+
`git rev-parse --show-toplevel` (destinationRoot),
|
|
726
|
+
`git -C .worktrees/task-xxx rev-parse HEAD` (sourceHead), `git rev-parse HEAD`
|
|
727
|
+
(destinationHead).
|
|
728
|
+
```json
|
|
729
|
+
{
|
|
730
|
+
"schemaVersion": 1,
|
|
731
|
+
"taskId": "TASK-xxx",
|
|
732
|
+
"baseCommit": "<base-branch head sha>",
|
|
733
|
+
"sourceRoot": "<absolute worktree root>",
|
|
734
|
+
"destinationRoot": "<absolute project root>",
|
|
735
|
+
"sourceHead": "<worktree HEAD sha>",
|
|
736
|
+
"destinationHead": "<project HEAD sha>",
|
|
737
|
+
"targetPaths": ["<each approved path>"]
|
|
738
|
+
}
|
|
739
|
+
```
|
|
740
|
+
Scope = the exact task-approved target paths (both rename endpoints); the file is
|
|
741
|
+
written outside the source worktree AND outside the target set. This is coordinator metadata,
|
|
742
|
+
not task implementation: keep it in the docs benchmark directory so the main-session
|
|
743
|
+
ownership guard remains intact.
|
|
744
|
+
2. Land with ONE simple command, literal paths:
|
|
745
|
+
`node .claude/ukit/index/land-worktree.mjs --scope docs/AI_HANDOFF/benchmark/TASK-xxx-scope.json --receipt docs/AI_HANDOFF/benchmark/TASK-xxx-landing.json`
|
|
746
|
+
— exit 0 → landed (receipt written); exit 2 → refused, both repos untouched; exit 1 →
|
|
747
|
+
apply/receipt failure, source retained, never a success claim. Landing is self-fencing: it reads the destination claims store under the claims lock held through apply+receipt, and exits 2 `worker-not-terminated` while any delegated worker claim for the task remains (handback must release it; lease expiry does not), or `claims-unreadable`/`claims-busy` (fail closed). Never fabricate a claim or receipt to pass.
|
|
748
|
+
3. After each exit-0 landing, checkpoint-commit the landed paths (receipt stays outside
|
|
749
|
+
the target set) BEFORE landing the next task: the helper refuses a destination with
|
|
750
|
+
tracked modifications (destination-dirty), so uncommitted landed work would block every
|
|
751
|
+
later task in the wave.
|
|
752
|
+
```bash
|
|
753
|
+
git add -- <landed paths>
|
|
754
|
+
git commit --only -m "checkpoint: TASK-xxx landed" -- <landed paths>
|
|
755
|
+
```
|
|
756
|
+
4. Update INDEX.md: status → pending_review (the orchestrator writes it; agents never do).
|
|
757
|
+
|
|
758
|
+
**Already-applied / divergent-history recovery:** normal landing steps above do not turn
|
|
759
|
+
all exit-0 helper results into landed status. `--adopt-applied` requires complete source
|
|
760
|
+
snapshot blob+mode equality. Where preserved task-record history differs, do not repeat a
|
|
761
|
+
known-failing adoption, copy metadata, omit scope, or fabricate a landed receipt. Explicit
|
|
762
|
+
owner-authorized recovery uses `--reconcile-metadata <proof-json> --preflight --scope
|
|
763
|
+
<scope-json> --receipt <new-json>` for ALL affected full scopes first, then the same command
|
|
764
|
+
without `--preflight`. File evidence is hash-pinned and colocated with the proof in its audit
|
|
765
|
+
directory; independently audit semantic provenance, which hashes alone cannot establish.
|
|
766
|
+
Consume `receiptKind: metadata-reconciliation`, `status: reconciled` only with
|
|
767
|
+
`completion:false`, `cleanupEligible:false` and matching current HEAD/snapshot/scope.
|
|
768
|
+
It resolves specifically verified integration-history debt, NOT task completion or normal
|
|
769
|
+
landing. Retain blocked status until independent current-source review and missing gates
|
|
770
|
+
justify progression; continue those gates on destination source without another equality
|
|
771
|
+
adoption attempt. No automatic pending_review/done, cleanup, archive or completion authority
|
|
772
|
+
comes from reconciliation. Preserve both histories and source worktrees; separate acceptance,
|
|
773
|
+
archive and cleanup gates and owner prohibitions remain binding.
|
|
612
774
|
|
|
613
775
|
For **FAIL:**
|
|
614
776
|
```bash
|
|
@@ -701,10 +863,9 @@ git status # should show modified/new files, no handoff branches/worktrees
|
|
|
701
863
|
git diff --stat # summary of all changes
|
|
702
864
|
```
|
|
703
865
|
|
|
704
|
-
Because 3d commits each wave, the changes under review are in **commits since the plan commit**, not only in the working tree. Resolve the review range once and use
|
|
866
|
+
Because 3d commits each wave, the changes under review are in **commits since the plan commit**, not only in the working tree. Resolve the review range once: run ONE simple command — `git log --format=%H --grep='^handoff: plan' -n 1` — and use the printed hash as a literal (`<plan-commit>`) everywhere below:
|
|
705
867
|
```bash
|
|
706
|
-
|
|
707
|
-
git diff $PLAN_COMMIT # all handoff changes: committed waves + anything uncommitted
|
|
868
|
+
git diff <plan-commit> # all handoff changes: committed waves + anything uncommitted
|
|
708
869
|
```
|
|
709
870
|
|
|
710
871
|
Classify the review by what the diff can show — an empty diff is NOT automatically "implement incomplete":
|
|
@@ -720,7 +881,7 @@ Never make fake edits or fake tests to satisfy an empty diff, and never lower ac
|
|
|
720
881
|
|
|
721
882
|
**Batch the review set — mandatory.** Read `handoff.maxParallelAgents` from `.ukit/storage/config.json`. If more `pending_review` tasks exist than that, split into consecutive batches of at most that many; finish one batch's verdicts (R2–R4, appended to each task file) before starting the next. The cap counts child workers of ONE batch/review set, summed across roles (implementers and reviewers together); the main session is outside it, and it is not a session-wide limit. It is prompt-level guidance: no hook counts children, and the host's own concurrency limit is separate.
|
|
722
883
|
|
|
723
|
-
**Claude Code — MANDATORY, do this before anything else in R2–R4:** for each batch, call the Agent tool once per `pending_review` task **in parallel** (at most `handoff.maxParallelAgents`), each with `subagent_type: "code-reviewer"` (omp: the `task` tool with `agent: "code-reviewer"`, likewise invoked once per task in the batch, not once per wave).
|
|
884
|
+
**Claude Code — MANDATORY, do this before anything else in R2–R4:** for each batch, call the Agent tool once per `pending_review` task **in parallel** (at most `handoff.maxParallelAgents`), each with `subagent_type: "code-reviewer"` (omp: the `task` tool with `agent: "code-reviewer"`, likewise invoked once per task in the batch, not once per wave). Reviewers return the complete verdict block (≤30 lines), without shell writes; the orchestrator appends it with `Edit` to the task file, preserving prior rounds, before aggregation or status updates. No reviewer writes INDEX or task files; serial persistence avoids shared-write races. Do NOT review the diff yourself in the current session — this step is contracted to the strong tier (opus/unic-smart) and MUST differ from the executor's model, which only the spawned agent's frontmatter model guarantees.
|
|
724
885
|
|
|
725
886
|
The spawned reviewer agent reads `EXECUTOR_MODEL` from each task file `## Executor Report`:
|
|
726
887
|
|
|
@@ -742,7 +903,7 @@ If any command fails → `VERDICT: CRITICAL` (`NEXT_STATUS_FOR_INDEX: critical_b
|
|
|
742
903
|
### R4 — Review unified diff + append verdict (strong model)
|
|
743
904
|
|
|
744
905
|
```bash
|
|
745
|
-
git diff
|
|
906
|
+
git diff <plan-commit> # every handoff change: committed waves + working tree
|
|
746
907
|
git status # overview of modified/new/deleted files
|
|
747
908
|
```
|
|
748
909
|
|
|
@@ -750,7 +911,7 @@ Review as one unified diff — correctness, regression risk, security, edge case
|
|
|
750
911
|
|
|
751
912
|
Stage gate (unic-decision): reviewers still generate findings; when `decisionPlane.families.review.stage` is not `off`, the emitted verdict goes through `node .claude/ukit/index/review-verdict.mjs` (`review.verdict.v1`; `--panel` for `review.panel-verdict.v1`/`review.finding-bucket.v1`) — the deterministic severity aggregate stays authoritative at `off` or on adapter failure.
|
|
752
913
|
|
|
753
|
-
|
|
914
|
+
Return the verdict for orchestrator persistence to each task file:
|
|
754
915
|
```
|
|
755
916
|
## Reviewer Verdict
|
|
756
917
|
VERDICT: APPROVED | APPROVED-WITH-MINOR | CHANGES-REQUESTED | CRITICAL
|
|
@@ -758,6 +919,10 @@ REVIEWER_MODEL: <your exact model ID>
|
|
|
758
919
|
EXECUTOR_MODEL: <from Executor Report>
|
|
759
920
|
REVIEW_KIND: product | integration-evidence | status-only
|
|
760
921
|
VERIFICATION_RERUN: PASS | FAIL | NOT_RUN | N/A
|
|
922
|
+
command: <exact command, or ->
|
|
923
|
+
result: <actual pass/fail counts or NOT_RUN/N/A with reason>
|
|
924
|
+
TEST_PLAN_COVERAGE: all-followed | partial — <gaps> | missing — <gaps>
|
|
925
|
+
NOTES: <acceptance limitations, or none>
|
|
761
926
|
FINDINGS:
|
|
762
927
|
critical: <file:line — what fails> | none
|
|
763
928
|
important: <file:line — risk> | none
|
|
@@ -767,7 +932,7 @@ NEXT_STATUS_FOR_INDEX: approved | approved_minor | changes_requested | critical_
|
|
|
767
932
|
|
|
768
933
|
`VERDICT:` uses the aggregator's canonical hyphen vocabulary — underscore spellings (`changes_requested`, `critical_block`, `approved_with_minor`) parse to the same verdicts, so a blocking reviewer is never dropped as unparsed. `NOT_RUN` = the required re-run never executed in your session; `FAIL` = it executed and failed; either blocks approval. `N/A` is legitimate only when this review has no executable required checks (`command: -` or none) — an `N/A` beside a declared executable `command:` counts as `NOT_RUN`. `REVIEW_KIND` comes from the R1 classification; it scopes only the implementation-TDD evidence (new tests + RED_OUTPUT) — required executable checks and the task's original acceptance criteria are never waived, and approving an evidence review never marks product acceptance met.
|
|
769
934
|
|
|
770
|
-
|
|
935
|
+
Return this routing header followed by the complete verdict block above; the orchestrator persists the block with `Edit` before reading it back and advancing R4.5:
|
|
771
936
|
```
|
|
772
937
|
TASK: TASK-xxx
|
|
773
938
|
VERDICT: approved | approved_minor | changes_requested | critical_block
|
|
@@ -776,7 +941,7 @@ VERIFICATION_RERUN: PASS | FAIL | NOT_RUN | N/A (+ one-line reason)
|
|
|
776
941
|
BLOCKING: <one line per critical/important finding, or "none">
|
|
777
942
|
```
|
|
778
943
|
The return `VERDICT:` carries the NEXT_STATUS_FOR_INDEX vocabulary; the on-disk block's `VERDICT:` field uses the canonical hyphen vocabulary above.
|
|
779
|
-
|
|
944
|
+
Return actionable findings inside the bounded block, not the diff or raw verification logs.
|
|
780
945
|
|
|
781
946
|
### R4.5 — Auto-fix loop (max 2 rounds)
|
|
782
947
|
|
|
@@ -824,12 +989,14 @@ once — this is the run's only push:
|
|
|
824
989
|
```bash
|
|
825
990
|
git add -- <run-owned paths>
|
|
826
991
|
git commit --only -m "handoff: implement <goal>" -- <run-owned paths> # skip if nothing left to commit
|
|
827
|
-
git push origin
|
|
992
|
+
git push origin <base-branch>
|
|
828
993
|
```
|
|
829
994
|
|
|
830
|
-
Replace `<goal>` with the one-sentence goal from ACTIVE.md. Push
|
|
831
|
-
|
|
832
|
-
|
|
995
|
+
Replace `<goal>` with the one-sentence goal from ACTIVE.md. Push only when the user's explicit
|
|
996
|
+
delivery scope authorizes it, and only within the host's permissions. A settings `allow` entry
|
|
997
|
+
is host configuration, not user authorization to publish, so it never licenses a push by itself.
|
|
998
|
+
Without explicit delivery scope the run commits locally and records "not pushed" in the Final
|
|
999
|
+
Report. Force-push stays denied, so any push can only fast-forward.
|
|
833
1000
|
|
|
834
1001
|
**If some tasks are `blocked`:** still push. The approved work is reviewed, tested, and
|
|
835
1002
|
committed; withholding it helps no one, and the per-wave commits make any subset revertible.
|
|
@@ -977,10 +1144,11 @@ fixes, local work completed, and the recovery instructions for the next session.
|
|
|
977
1144
|
|
|
978
1145
|
Then, as the last line of the run:
|
|
979
1146
|
|
|
980
|
-
> Cycle finished.
|
|
981
|
-
> the
|
|
1147
|
+
> Cycle finished. State is in git, `INDEX.md` and `RUN.md`; the next cycle continues from
|
|
1148
|
+
> the cursor (a `/compact` is optional and never required, and never asked while assigned
|
|
1149
|
+
> queue work remains).
|
|
982
1150
|
|
|
983
|
-
|
|
984
|
-
boundary costs nothing: all state is in git, `INDEX.md` and `RUN.md`, so a compacted or
|
|
1151
|
+
Do not make a manual `/compact` mandatory at the cycle boundary; compaction is a host choice.
|
|
1152
|
+
Asking at a cycle boundary costs nothing: all state is in git, `INDEX.md` and `RUN.md`, so a compacted or
|
|
985
1153
|
brand-new session picks the next cycle up with no loss. Asking mid-cycle is forbidden — see
|
|
986
1154
|
the Autonomy Contract.
|