@deftai/directive-content 0.96.0 → 0.98.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/.agents/skills/deft-directive-portfolio-priority/SKILL.md +11 -0
- package/Taskfile.yml +6 -0
- package/UPGRADING.md +9 -6
- package/commands.md +17 -2
- package/contracts/test-boundary.md +18 -0
- package/docs/consumer-check-contract.md +64 -0
- package/docs/deft-directive-disable.md +6 -0
- package/docs/delivery-attempt.md +173 -0
- package/docs/openclaw-agent-host.md +36 -1
- package/docs/operator-log-hygiene-checklist.md +57 -0
- package/docs/operator-log-hygiene-consumer-pack-stub.md +75 -0
- package/docs/scope-provenance.md +54 -0
- package/docs/test-boundary.md +43 -0
- package/main.md +46 -0
- package/meta/philosophy.md +10 -0
- package/package.json +1 -1
- package/packs/patterns/patterns-pack-0.1.json +10 -0
- package/packs/skills/skills-pack-0.1.json +22 -5
- package/patterns/operator-log-hygiene.md +130 -0
- package/scm/github.md +26 -0
- package/skills/deft-directive-article-review/SKILL.md +17 -6
- package/skills/deft-directive-build/SKILL.md +41 -0
- package/skills/deft-directive-portfolio-priority/SKILL.md +144 -0
- package/skills/deft-directive-release/SKILL.md +22 -5
- package/skills/deft-directive-review-cycle/SKILL.md +150 -0
- package/skills/deft-directive-swarm/SKILL.md +14 -0
- package/skills/deft-directive-swarm/references/core-ops.md +14 -2
- package/skills/deft-directive-swarm/references/core-phase-0.md +34 -1
- package/skills/deft-directive-swarm/references/core-phase-3.md +6 -0
- package/skills/deft-directive-swarm/references/core-phase-4.md +21 -2
- package/skills/deft-directive-swarm/references/core-phase-5-6.md +17 -0
- package/skills/deft-directive-swarm/references/host-openclaw.md +4 -0
- package/tasks/engine-invoke.cjs +22 -17
- package/tasks/engine-invoke.test.cjs +30 -0
- package/tasks/verify.yml +30 -0
- package/templates/agent-prompt-preamble.md +8 -0
- package/templates/agents-entry.md +10 -0
- package/templates/swarm-greptile-poller-prompt.md +4 -2
|
@@ -190,6 +190,26 @@ Babysit and review-cycle are **not** a second unbounded implementation mandate.
|
|
|
190
190
|
⊗ Expand active story scope past xBRIEF AC mid-babysit without follow-up or consented amend (#2881).
|
|
191
191
|
⊗ Treat confidence-only holds as authorization to invent new subsystems in-tree.
|
|
192
192
|
|
|
193
|
+
|
|
194
|
+
### Dual stop — review fix loops (#2442)
|
|
195
|
+
|
|
196
|
+
Review fix cycles are multi-iteration work and MUST carry dual stop (`main.md` `## Dual Stop Rule (#2442)`). Single-turn re-checks are exempt.
|
|
197
|
+
|
|
198
|
+
**Defaults for this skill (override only with an explicit operator envelope):**
|
|
199
|
+
|
|
200
|
+
| Loop class | Success stop | Default failure stop |
|
|
201
|
+
|------------|--------------|----------------------|
|
|
202
|
+
| Greptile / bot fix batch (Step 3 → re-review) | No P0/P1 on current HEAD; confidence meets `minGreptileConfidence` | **max 3** fix-batch iterations across the whole review ownership (do **not** reset the counter on push when the same primary fingerprint remains) **or** **2** consecutive re-reviews with the same primary P0/P1 fingerprint and no material fix |
|
|
203
|
+
| Confidence-only hold (0 P0/P1, score below floor) | Confidence meets floor, or operator chooses document/accept path | **max 1** optional polish pass, then stop (do not redesign unbounded — see confidence-only holds above) |
|
|
204
|
+
|
|
205
|
+
**On failure stop:**
|
|
206
|
+
|
|
207
|
+
- ! Halt automatic re-fix. Prefer `BLOCKED:` with PR number, HEAD SHA, blocker class (`review_cycle_cap` / `greptile_p0_p1` / `no_progress`), what was tried, and human decision needed (preamble §11 / #2843).
|
|
208
|
+
- ⊗ Continue silent fix rounds after the envelope is exhausted.
|
|
209
|
+
- ⊗ Reset the fix-batch counter solely by re-pushing, empty-committing, or swapping workers when the same primary finding fingerprint remains (poll-wait timer MAY reset for a new HEAD; the dual-stop fix-batch counter MUST NOT).
|
|
210
|
+
|
|
211
|
+
**Enforcement note:** skill defaults are behavioral. Durable delivery/acceptance circuit breaker: **#3143** packages/core/src/delivery-attempt/ (valuatePreDispatch). Docs: docs/delivery-attempt.md.
|
|
212
|
+
|
|
193
213
|
### Step 3: Fix all findings in ONE batch commit
|
|
194
214
|
|
|
195
215
|
! Apply [`coding/review.md`](../../coding/review.md) single-batch, cross-file grep, and local structured-data validation rules. Land **all** in-scope fixes in one commit (or one intentional batch), never per-finding pushes.
|
|
@@ -297,6 +317,94 @@ Remediation:
|
|
|
297
317
|
|
|
298
318
|
⊗ Use `--skip-ci` / merge-with-pending because CI is capacity-stalled — the failover path is the unblock; skip-ci is an incident-only release escape hatch (#2652), not a runner-capacity remedy.
|
|
299
319
|
|
|
320
|
+
### CI weather reason codes + thrash caps (#3167)
|
|
321
|
+
|
|
322
|
+
`pr:watch` / `pr:merge-ready` expose machine-distinguishable `ci_ready_state` values (also `--json`) so agents stop conflating Actions weather with product test failure:
|
|
323
|
+
|
|
324
|
+
| `ci_ready_state` / verdict | Meaning | Agent action |
|
|
325
|
+
|----------------------------|---------|--------------|
|
|
326
|
+
| `ci_never_scheduled` / `CI_NEVER_SCHEDULED` | No CI workflow check-run for HEAD (empty or bots-only: Greptile/SLizard) | Cap re-triggers; then **BLOCKED** — do not multi-hour empty-commit thrash |
|
|
327
|
+
| `runner_capacity_stall` / `RUNNER_CAPACITY_STALL` | Required still `queued`, no runner past budget (#2672) | Wait auto-failover; ⊗ `--skip-ci` |
|
|
328
|
+
| `ci_failures` / `CI_BLOCKED` | Completed `failure` / `timed_out` with product evidence (#2688) | Own like Greptile P0 — fix or escalate |
|
|
329
|
+
| `ci_cancelled_no_failover` / `CI_CANCELLED_NO_FAILOVER` | Primary `cancelled` and no green required sibling (failover skipped/not armed; workflow sibling **#3168**) | Cap re-triggers; then **BLOCKED** |
|
|
330
|
+
| Greptile CLEAN fields / `greptile_pending` | Existing Step 6 / SHA / confidence | Unchanged |
|
|
331
|
+
|
|
332
|
+
! **Thrash caps (MUST):** Under stable `ci_never_scheduled`, `ci_cancelled_no_failover`, or repeated capacity stall after failover wait budget, limit **CI re-trigger attempts** (empty-commit push, close/reopen, rebase-for-enqueue) to **at most 2** total across the ownership span. On the **2nd** failed re-trigger (or immediately when the weather code is stable and Greptile Step 6 is already clean), stop automatic re-push and emit a structured **BLOCKED** handoff.
|
|
333
|
+
|
|
334
|
+
### Platform status probe + outage attribution (#3180)
|
|
335
|
+
|
|
336
|
+
! When `ci_ready_state` is weather-class (`ci_never_scheduled`, `runner_capacity_stall`, `ci_cancelled_no_failover`, `ci_failures`), CI never starts for HEAD, or many PRs share an empty-check pattern: **MUST probe public status pages** before workflow thrash or drive-by edits. Gates surface static URLs in `pr:watch` / `pr:merge-ready` JSON and human output (v1: no network fetch required).
|
|
337
|
+
|
|
338
|
+
1. ! **GitHub Status** (Actions, Webhooks): https://www.githubstatus.com/
|
|
339
|
+
2. ! **Blacksmith Status**: https://status.blacksmith.sh/
|
|
340
|
+
|
|
341
|
+
**Attribution table:**
|
|
342
|
+
|
|
343
|
+
| Observation | `attribution` | Agent action |
|
|
344
|
+
|-------------|---------------|--------------|
|
|
345
|
+
| GH Actions and/or Webhooks major/partial outage | `platform` | Platform incident; ⊗ workflow drive-by edits; ⊗ empty-commit thrash past thrash caps; wait + re-check HEAD runs + local `task check` |
|
|
346
|
+
| Blacksmith red while GH Actions green | `capacity` | Runner-provider incident; failover doctrine (#2672 / #3168) |
|
|
347
|
+
| Both green + still `ci_never_scheduled` on this PR only | `repo_config` | Workflow paths, branch filters, required-check names, Actions disabled / org policy |
|
|
348
|
+
| Unclear / mixed | `unknown` | Cap thrash; BLOCKED with both status URLs; operator decision |
|
|
349
|
+
|
|
350
|
+
! **Anti-thrash during attributed platform outage:** After thrash caps, stop automatic re-push loops. Remediation is wait + re-probe HEAD check-runs, not inventing workflow edits for a global outage.
|
|
351
|
+
|
|
352
|
+
⊗ Merge or `--skip-ci` solely because a status page is red — status is attribution for wait/thrash policy, not a second branch-protection oracle.
|
|
353
|
+
⊗ Blame Blacksmith when GH Actions/Webhooks are the red components and Blacksmith runners are operational.
|
|
354
|
+
⊗ Edit workflows / empty-commit thrash to "fix" a documented global Actions/webhook outage without a status-page probe.
|
|
355
|
+
|
|
356
|
+
Cross-links: #3167 (weather codes), #3168 (failover arms), #2672 (capacity stall), #2688 (Greptile CLEAN + CI holdout).
|
|
357
|
+
|
|
358
|
+
! **BLOCKED handoff template (CI weather):**
|
|
359
|
+
|
|
360
|
+
```text
|
|
361
|
+
BLOCKED: ci_weather
|
|
362
|
+
PR: <N>
|
|
363
|
+
HEAD: <sha>
|
|
364
|
+
REASON: ci_never_scheduled|ci_cancelled_no_failover|runner_capacity_stall
|
|
365
|
+
GREPTILE: CLEAN|P0/P1|pending (Step 6 fields)
|
|
366
|
+
CI: <ci_ready_state from pr:watch --json>
|
|
367
|
+
platform_status_github: https://www.githubstatus.com/
|
|
368
|
+
platform_status_blacksmith: https://status.blacksmith.sh/
|
|
369
|
+
incident_url: <optional status-page incident URL or n/a>
|
|
370
|
+
attribution: platform|capacity|repo_config|unknown
|
|
371
|
+
ATTEMPTS: empty-commit=<0-2> close-reopen=<0-2>
|
|
372
|
+
REMEDIATION: wait for platform recovery | capacity failover (#3168) | repo config fix | human admin-merge playbook below | operator decision
|
|
373
|
+
REDISPATCH_OK: yes|no
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
! Ownership of Greptile CLEAN + CI holdout is still real (#2688) — **ownership ≠ infinite wait**. After thrash caps, hand off; do not burn multi-hour `gh run watch` / empty-commit loops when Greptile is already CLEAN.
|
|
377
|
+
|
|
378
|
+
! **Envelope selection under CI weather (#3153):** Prefer deliberate `stop-at: pr-open` implement + this skill as the partner merge-path babysit when known capacity/outage weather dominates; see swarm Envelope selection SLA and partner merge-path section above. Cross-link only — do not re-spec the tree here.
|
|
379
|
+
|
|
380
|
+
⊗ Multi-hour empty-commit / close-reopen / rebase thrash after thrash caps when `ci_ready_state` is `ci_never_scheduled` or `ci_cancelled_no_failover`.
|
|
381
|
+
⊗ Treat `ci_never_scheduled` as ordinary Greptile latency (`sha_match` / `terminal_check_run` only).
|
|
382
|
+
⊗ Silent `--skip-ci` / admin merge without the outage playbook audit trail below.
|
|
383
|
+
|
|
384
|
+
### SLizard advisory-only for merge-ready wait (#3167)
|
|
385
|
+
|
|
386
|
+
! Required bot for **merge-ready wait** / Step 6 exit ownership is **Greptile**. SLizard (Gemini Verify) is **advisory only**: timeouts, retries, missing check, or flaky SLizard conclusions MUST NOT gate the review-cycle wait loop or authorize unbounded re-push.
|
|
387
|
+
|
|
388
|
+
! `task pr:merge-ready` may still surface SLizard structure when present (#2189); agents MUST NOT idle-poll or thrash solely for SLizard when Greptile Step 6 is clean. Prefer continue / BLOCKED on CI weather / human decision.
|
|
389
|
+
|
|
390
|
+
⊗ Block merge-ready babysit on SLizard alone when Greptile Step 6 all-of is satisfied on HEAD.
|
|
391
|
+
|
|
392
|
+
### Outage admin-merge playbook (opt-in / human, #3167)
|
|
393
|
+
|
|
394
|
+
When GitHub Actions is in a **documented major outage** (or multi-hour `ci_never_scheduled` / `ci_cancelled_no_failover` after thrash caps) and product + Greptile are ready:
|
|
395
|
+
|
|
396
|
+
! Admin / human merge is **opt-in**, never the autonomous agent default. Preconditions:
|
|
397
|
+
|
|
398
|
+
1. ! Greptile Step 6 fail-closed all-of on current HEAD (dogfood conf floor / `minGreptileConfidence`).
|
|
399
|
+
2. ! Evidence of local or prior green `task check` / merge-gate when available.
|
|
400
|
+
3. ! PR comment **audit note** naming the weather code, HEAD SHA, and who authorized override.
|
|
401
|
+
4. ? Optional explicit env/policy for bot merge (`DEFT_ALLOW_BOT_MERGE` / `task policy:allow-bot-merge`) — **opt-in**, never silent default skip-ci.
|
|
402
|
+
|
|
403
|
+
⊗ Autonomous `--skip-ci` / `--admin` merge as the default under ordinary CI weather.
|
|
404
|
+
⊗ Replace branch protection with Greptile-only merge on normal days.
|
|
405
|
+
|
|
406
|
+
Workflow failover arming (Blacksmith cancelled → GH-hosted lane) is sibling issue **#3168** — this skill owns agent thrash caps and reason codes only.
|
|
407
|
+
|
|
300
408
|
### Stall Detection Rubric (#564)
|
|
301
409
|
|
|
302
410
|
! Track per poll: `startedAt` (timestamp of the first observation of the IN_PROGRESS check run for the current commit) and `commit.oid` (head SHA being reviewed). Both fields MUST be re-recorded every time the head SHA changes -- the rubric measures elapsed time on a single commit, not across the whole review cycle.
|
|
@@ -360,6 +468,38 @@ Remediation:
|
|
|
360
468
|
|
|
361
469
|
! **Swarm monitor must not self-implement (#2843 / Gap C):** When a cohort monitor receives `BLOCKED` or DONE-with-blockers from a `drive-to: merge-ready` implementation leaf, the monitor MUST NOT enter the review/fix loop inline on Tier 1 — background-dispatch ONE continuation leaf scoped `drive-to: merge-ready` on the same worktree. Monitor-inline review-cycle is permitted only on Tier 3 or with explicit operator consent (see `skills/deft-directive-swarm/SKILL.md` Phase 5 completion-notification decision tree).
|
|
362
470
|
|
|
471
|
+
### Partner merge-path when implement stops at PR-open (#3153)
|
|
472
|
+
|
|
473
|
+
! This skill is the **required partner** for the swarm **Envelope selection SLA** (`skills/deft-directive-swarm/references/core-phase-0.md` / Phase 3). When an implement leaf was deliberately scoped **`stop-at: pr-open`** (or a merge-ready leaf failed thin DONE and recovery chose babysit ownership), the parent/monitor MUST **not** leave the open PR without a merge-path owner.
|
|
474
|
+
|
|
475
|
+
! **First-class merge-path ownership (MUST, same turn as PR ground-truth):**
|
|
476
|
+
|
|
477
|
+
1. ! Spawn **or** retain **exactly one** review-cycle owner for the open PR:
|
|
478
|
+
- **Approach 1** review-monitor (`worker_role: review-monitor`) with sticky `<!-- deft:review-owner -->` lease (#3090 / #3044 / dual-invoke `review-monitor:register` when available), **or**
|
|
479
|
+
- A continuation leaf scoped **`drive-to: merge-ready`** on that PR/worktree that owns babysit → merge-ready in its tool loop, **or**
|
|
480
|
+
- Documented **parent-retained** ownership (`review_cycle: in_progress:<pr>#parent-retained`) with an explicit next poll/fix action — never silent hold.
|
|
481
|
+
2. ! Route through **this skill** — ⊗ Cursor global babysit (`#2261`), freestyle main-session poll, or dual parallel monitors (`#3044`).
|
|
482
|
+
3. ! Apply Owner Continuity Gate (#3090) and Single review-monitor lease (#3044) without exception: one sticky lease; force-takeover only when the prior owner is dead.
|
|
483
|
+
4. ! **Post-merge `scope:complete` (#2321 / Gap C):** When the implement leaf stopped at pr-open, it MUST NOT have run `task scope:complete`. After the PR **merges**, the merge-path owner (or swarm Phase 6 `task swarm:finalize-cohort` / `task swarm:complete-cohort` / monitor) MUST run `task scope:complete` or `task scope:cancel`. `task verify:orphan-active` fails closed on stranded active briefs.
|
|
484
|
+
5. ! **Human-merge / CLEAN-before-merge ownership (#3153 / #1193 / #2321):** When `plan.policy.requireHumanMerge` (or missing bot-merge authority) means the review owner reaches Greptile CLEAN / merge-ready but **cannot** squash-merge, lifecycle ownership is **not** complete. Prefer **durable** ownership (not a prose-only promise):
|
|
485
|
+
- **Preferred:** Parent/monitor **retains** ownership (`review_cycle: in_progress:<pr>#parent-retained` or sticky lease held by the long-lived monitor) until human merge lands, then runs `scope:complete` (or Phase 6 `task swarm:finalize-cohort` / `task swarm:complete-cohort`).
|
|
486
|
+
- **Allowed handoff:** Only to a **long-lived** parent/monitor / Phase 6 closer — same turn: (1) re-claim sticky `<!-- deft:review-owner -->` lease for the **recipient** (register/force as needed), (2) structured handback with PR, HEAD, `awaiting-human-merge`, and explicit post-merge `scope:complete` duty, (3) recipient acknowledges with `review_cycle: in_progress:<pr>#…` before the giving agent exits.
|
|
487
|
+
- ! Cohort through-merge: the **swarm monitor** is the default durable post-merge `scope:complete` owner for every `stop-at: pr-open` story (#2321) — do not rely on a review leaf that exits at CLEAN.
|
|
488
|
+
- ! **Post-CLEAN wake path (MUST):** After CLEAN under human-merge, the durable owner MUST keep a **reachable observe path** until the PR is `MERGED` (or closed without merge → `scope:cancel` / operator decision). Concrete options (pick one, same ownership):
|
|
489
|
+
1. **Background poller** (Approach 1 preferred when Tier 1): spawn/retain a review-monitor or short poll loop that probes `gh api repos/<owner>/<repo>/pulls/<N>` for `merged` / `state` on adaptive cadence (or host merge webhook when available), then runs post-merge verification + `scope:complete`.
|
|
490
|
+
2. **Parent-retained yield-with-wake:** parent keeps `review_cycle: in_progress:<pr>#parent-retained` and re-enters on the next operator message / scheduled re-invocation (Approach 2) with an explicit first action of "check merge state → if merged, `scope:complete`".
|
|
491
|
+
3. **Phase 6 cohort closer:** for swarm, record the PR as `awaiting-human-merge` in the monitor checkpoint and **require** the Phase 6 pre-sweep merge re-poll (`skills/deft-directive-swarm/references/core-phase-5-6.md` § Human-merge observe path / Step 1.5) before `task swarm:complete-cohort` / finalize — never skip `scope:complete` solely because Greptile was CLEAN earlier.
|
|
492
|
+
⊗ Keep only a sticky lease with no poller, no parent re-entry plan, and no Phase 6 re-poll checklist — that is ownership-in-name-only and still strands `scope:complete`.
|
|
493
|
+
⊗ Handoff to a short-lived leaf that exits at CLEAN without lease transfer.
|
|
494
|
+
⊗ Emit terminal `DONE` / stand down at CLEAN when merge authority is human-only and no **reachable** durable owner (sticky lease + live parent/monitor/cohort closer **with an observe path above**) remains for post-merge `scope:complete`.
|
|
495
|
+
6. ! **Thin DONE recovery (#2943 / #3153):** A failed `drive-to: merge-ready` leaf that only opened a PR is **not** success. After ground truth, hand merge path to **one** of the owners above — never improvise a second lease or re-dispatch implement + babysit in parallel without releasing the first.
|
|
496
|
+
|
|
497
|
+
! **Cohort through-merge intent is unchanged:** stories still land on master. Envelope selection only assigns **who owns implement vs who owns Greptile/CI/merge** under capacity stall, conf floors, wall-clock budgets, or large multi-gate stories. Happy-path single `drive-to: merge-ready` leaves remain the default and do not use this partner handoff.
|
|
498
|
+
|
|
499
|
+
! **Does not authorize:** lowering `minGreptileConfidence`, `--skip-ci` for capacity stalls, or unbounded redesign on conf-only holds (#2881 / #2672 / #3095).
|
|
500
|
+
|
|
501
|
+
Cross-links: swarm decision tree `skills/deft-directive-swarm/references/core-phase-0.md` § Envelope selection SLA; Phase 3 Gap C `skills/deft-directive-swarm/references/core-phase-3.md`; thin SKILL pointer `skills/deft-directive-swarm/SKILL.md` § Envelope selection SLA.
|
|
502
|
+
|
|
363
503
|
|
|
364
504
|
|
|
365
505
|
! Select the monitoring approach based on runtime capability detection (the matrix in `skills/deft-directive-swarm/SKILL.md` Phase 3 Step 1, extended per #1342 slices 1-2 for `spawn_subagent` / "grok-build", per #1877 for Cursor as first-class Tier-1 tiers, per #2876 for OpenClaw `sessions_spawn`, and per #3134 for Claude Code `claude-code` / `claude-agent`). Probe the environment (tool set + env vars) to obtain the stable platform descriptor (`grok-build`, `warp-orchestrated`, `warp-manual`, `cursor-composer`, `cursor-cloud-agent`, `claude-code`, `openclaw`, etc.) from the launch adapter / `get_platform_capabilities` and map the descriptor to the appropriate tier + dispatch primitive (`start_agent`, `spawn_subagent`, the Cursor `Task` tool, Claude Code `Agent` / `claude-agent`, or OpenClaw `sessions_spawn`). The descriptor (not hard-coded tool presence) is the single source of truth for both launch and review monitoring.
|
|
@@ -637,6 +777,16 @@ task lifecycle:event -- emit plan:approved \
|
|
|
637
777
|
|
|
638
778
|
## Anti-Patterns
|
|
639
779
|
|
|
780
|
+
- ⊗ Multi-hour empty-commit / close-reopen thrash after CI weather thrash caps when `ci_never_scheduled` or `ci_cancelled_no_failover` (#3167)
|
|
781
|
+
- ⊗ Workflow thrash or empty-commit spam during attributed platform outage without status-page probe (#3180)
|
|
782
|
+
- ⊗ Merge or `--skip-ci` solely because a status page is red without check-run evidence (#3180)
|
|
783
|
+
- ⊗ Block merge-ready wait on SLizard alone when Greptile Step 6 is clean (#3167)
|
|
784
|
+
- ⊗ Silent admin / `--skip-ci` merge under Actions outage without audit comment and opt-in authority (#3167)
|
|
785
|
+
- ⊗ Leave a deliberate `stop-at: pr-open` (or thin-DONE recovery) open PR without spawning/retaining one review-cycle babysit owner + lease continuity and post-merge `scope:complete` plan (#3153)
|
|
786
|
+
- ⊗ Stand down at CLEAN under human-merge policy without a durable owner (sticky lease + live parent/monitor/Phase 6 closer) **and** a post-CLEAN observe path (poller / parent wake / Phase 6 re-poll) for post-merge `scope:complete` (#3153 / #1193 / #2321)
|
|
787
|
+
- ⊗ Handoff human-merge cleanup to a short-lived leaf that exits at CLEAN without re-claiming the sticky lease (#3153)
|
|
788
|
+
- ⊗ Retain only a sticky lease after CLEAN with no poller, no parent re-entry, and no Phase 6 merge re-poll — ownership-in-name-only (#3153)
|
|
789
|
+
- ⊗ Dual-lease or freestyle Cursor global babysit for the partner merge-path after implement stops at PR-open (#3153 / #2261 / #3044)
|
|
640
790
|
- ⊗ End owning turn with 0 children, no sticky lease, and no finish after drive-to-merge / babysit / shepherd claim — silent hold (#3090)
|
|
641
791
|
- ⊗ Emit freeform `review_cycle: started` / `pending` / `initiated` or L4 `status: pass` without `done` or verifiable `in_progress:<pr>#…` lease/parent-retained (#3090)
|
|
642
792
|
- ⊗ Treat check-run SUCCESS alone as CLEAN / merge-ready while dual-source P0/P1 remain (#3090)
|
|
@@ -127,6 +127,19 @@ Large multi-host skills use a **host-neutral core** plus **one** per-host adapte
|
|
|
127
127
|
|
|
128
128
|
! After the parent emits **one** user/caller-visible consolidate for a child `runId` / settle batch, **identical or equivalent completion replay** for the same key MUST be **silent** (no tools, no re-QC, no second final; host silent token when defined, e.g. OpenClaw `NO_REPLY`). Re-open only on new `runId`/batch, principal explicit reopen, or materially new evidence (new HEAD, new blocker class). Replay storms: at most one fail-loud note, then silent. Full MUST: `templates/agent-prompt-preamble.md` §11.5. Depth: `references/core-phase-5-6.md`. Orthogonal to empty settle ≠ done (#3044).
|
|
129
129
|
|
|
130
|
+
### Dual stop — repair and monitor loops (#2442)
|
|
131
|
+
|
|
132
|
+
! Multi-iteration swarm **repair** and **monitor** loops MUST carry dual stop: success (goal/AC/clean gate) **and** a failure/budget stop. Single-turn probes (one status check, one heartbeat read) are exempt. Principle: `main.md` `## Dual Stop Rule (#2442)`. Defaults and halt-report shape live in [`references/core-phase-4.md`](references/core-phase-4.md) (monitor / takeover) and [`references/core-ops.md`](references/core-ops.md) (prompts + anti-patterns).
|
|
133
|
+
|
|
134
|
+
! Default failure envelope for repair/monitor class work (unless the operator or xBRIEF names a stricter one):
|
|
135
|
+
- **max iterations:** 3 monitor repair actions (re-dispatch, takeover complete, re-trigger review) for the same leaf/PR failure class, **or**
|
|
136
|
+
- **no-progress:** same error / same Greptile P0-P1 fingerprint / same idle state **3+** times with no material worktree or review change (composes with Phase 4 "stuck in an error loop" takeover trigger), **or**
|
|
137
|
+
- **budget:** existing poll caps (`pr:watch` max-wait, Greptile service-error single retry + escalate) count as budget stops -- do not invent a second unbounded poll loop outside them.
|
|
138
|
+
|
|
139
|
+
! On failure stop: halt automatic continuation; emit an operator-visible report (what was tried, what is missing, what human decision is needed). ⊗ Silent re-dispatch or infinite monitor continuation after the envelope is exhausted.
|
|
140
|
+
|
|
141
|
+
! Composes with minimal-subgraph repair guidance (#2439): keep repairs minimal **and** bounded by dual-stop -- minimal repair is not a license to thrash. Durable delivery/acceptance circuit-breaker: **#3143** `packages/core/src/delivery-attempt/` (`evaluatePreDispatch`, unit ledger). Docs: `docs/delivery-attempt.md`. Skill defaults remain behavioral; mechanical gate lives in core.
|
|
142
|
+
|
|
130
143
|
## Runtime Capability Detection (summary)
|
|
131
144
|
|
|
132
145
|
! Before selecting a launch method, probe the environment. Full probe text: [`references/core-phase-3.md`](references/core-phase-3.md).
|
|
@@ -174,5 +187,6 @@ Large multi-host skills use a **host-neutral core** plus **one** per-host adapte
|
|
|
174
187
|
- ⊗ Skip Phase 0 approval before Phase 1
|
|
175
188
|
- ⊗ Misclassify OpenClaw `sessions_spawn` as `grok-build` or `generic-terminal` (#2875)
|
|
176
189
|
- ⊗ Misclassify Claude Code as `cursor-composer` / `generic-terminal` (#3134)
|
|
190
|
+
- ⊗ Run multi-iteration repair/monitor loops without a failure stop or with silent continuation after the envelope is exhausted (#2442)
|
|
177
191
|
|
|
178
192
|
Full anti-pattern list: [`references/core-ops.md`](references/core-ops.md).
|
|
@@ -44,7 +44,8 @@ TASK: You must complete N [type] fixes on this branch ([branch-name]) in the def
|
|
|
44
44
|
This is a git worktree. Do NOT just read files and stop — you must implement all changes,
|
|
45
45
|
run iteration-lane validation during implement/fix loops, full task check before push,
|
|
46
46
|
commit, push, create a PR, and run the review cycle.
|
|
47
|
-
|
|
47
|
+
Drive every step to completion, subject to dual-stop (#2442): if a multi-iteration fix/repair
|
|
48
|
+
loop hits its failure/budget stop, halt with BLOCKED (operator-visible report) — do not thrash past the envelope.
|
|
48
49
|
|
|
49
50
|
STEP 1 — Read directives: Read AGENTS.md, vbrief/vbrief.md, and the assigned xBRIEF(s) from xbrief/active/.
|
|
50
51
|
Read skills/deft-directive-review-cycle/SKILL.md.
|
|
@@ -75,16 +76,21 @@ CONSTRAINTS:
|
|
|
75
76
|
- Use conventional commits: type(scope): description
|
|
76
77
|
- Iteration commits: affected/static fast lane only; full task check required before push (#1704)
|
|
77
78
|
- Never force-push
|
|
79
|
+
- Dual stop (#2442): multi-iteration fix/repair loops need success + failure/budget stop (build defaults: max 5 quality-fix iters or 3 identical no-progress; pre-PR: max 3 polish passes). On halt: operator-visible report (tried / missing / human decision). Single-turn work is exempt. Delivery/acceptance mechanical ledger is #3143 (`packages/core/src/delivery-attempt/` / `docs/delivery-attempt.md`).
|
|
78
80
|
```
|
|
79
81
|
|
|
80
82
|
### Template Rules
|
|
81
83
|
|
|
82
84
|
- ! First line MUST start with `TASK:` followed by an imperative statement
|
|
83
|
-
- ! Include
|
|
85
|
+
- ! Include a drive-to-completion instruction that is **subordinate to dual-stop** (#2442): complete all steps unless a multi-iteration failure/budget envelope is exhausted — then `BLOCKED` with an operator-visible report (do not use unconditional "DO NOT STOP" language that overrides the failure stop)
|
|
84
86
|
- ! Each task MUST include its xBRIEF filename and origin issue number
|
|
85
87
|
- ! CONSTRAINTS section MUST list files the agent must not touch (other agents' scope)
|
|
86
88
|
- ! Review cycle step MUST reference `skills/deft-directive-review-cycle/SKILL.md` explicitly
|
|
89
|
+
- ! Multi-iteration prompts MUST name dual-stop defaults (or point at `main.md` / build skill #2442) so workers do not thrash without a failure envelope
|
|
90
|
+
- ! **Unit-of-work envelope (#3153 / Gap C):** The prompt MUST declare `drive-to: merge-ready` **or** `stop-at: pr-open` (default merge-ready for story work). When `stop-at: pr-open`, state that the parent/monitor owns review-cycle babysit + post-merge `scope:complete` (worker MUST NOT `scope:complete` at exit). Selection tree: `references/core-phase-0.md` Envelope selection SLA.
|
|
87
91
|
- ⊗ Start the prompt with context ("You are working in...") — agents treat this as passive setup and may stop after reading
|
|
92
|
+
- ⊗ Write unconditional `DO NOT STOP until all steps are complete` without a dual-stop exception — that conflicts with the failure stop and causes thrash (#2442)
|
|
93
|
+
- ⊗ Omit the unit-of-work envelope line or leave merge-path ownership ambiguous after a deliberate `stop-at: pr-open` (#3153)
|
|
88
94
|
|
|
89
95
|
## Push Autonomy
|
|
90
96
|
|
|
@@ -144,5 +150,11 @@ CONSTRAINTS:
|
|
|
144
150
|
- ⊗ Multi-sentence progress-only first response after leaf completion announce (`subagent_announce` / parent-push) with zero tools / yield — tool-first ground-truth batch, host yield, or one short non-repeated answer only (#2943 text-repetition hang)
|
|
145
151
|
- ⊗ N>2 near-identical assistant sentences in one turn with no tool_use / yield — FC14 hard-stop (`evaluateParentTurnShape` in `packages/core/src/parent-turn-shape/`; soft prose not sole mitigation) (#3131 / #2943)
|
|
146
152
|
- ⊗ Treat thin DONE (completion without PR URL / merge evidence) as success — re-dispatch or take over after ground truth (#2943)
|
|
153
|
+
- ⊗ Treat a `drive-to: merge-ready` exit with PR open but no merge-ready evidence as a designed handoff — it is FAILED thin DONE; recover with **one** continuation or review-cycle babysit owner, never dual lease (#3153 / #2943 / #3044)
|
|
154
|
+
- ⊗ Dispatch `stop-at: pr-open` without a named review-cycle partner merge-path owner (babysit / Approach 1 monitor + sticky lease + post-merge `scope:complete` plan) (#3153)
|
|
155
|
+
- ⊗ Freestyle Cursor global babysit or a second parallel review-monitor when recovering thin DONE or owning a stop-at:pr-open handoff (#2261 / #3044 / #3153)
|
|
147
156
|
- ⊗ Second+ user-visible consolidate / final for the same child `runId` / settle batch without new evidence or principal reopen — completion latch silent-replay path (`templates/agent-prompt-preamble.md` §11.5 / #3092)
|
|
148
157
|
- ⊗ Full dual-source re-QC solely because the harness re-delivered the same settle event (#3092)
|
|
158
|
+
- ⊗ Run multi-iteration repair, monitor, or implement-fix loops without a dual-stop failure envelope (max iterations and/or no-progress and/or budget) (#2442)
|
|
159
|
+
- ⊗ Silently continue, re-dispatch, or open another identical attempt after the failure stop fires — halt with an operator-visible report (what was tried, what is missing, what human decision is needed) (#2442)
|
|
160
|
+
- ⊗ Treat dual-stop skill defaults as a durable delivery-attempt ledger — mechanical cross-revision circuit breaker is #3143 (`packages/core/src/delivery-attempt/`), not prompt-only thrashing control (#2442)
|
|
@@ -6,10 +6,43 @@
|
|
|
6
6
|
|
|
7
7
|
### Through-merge / N=1 still uses the launch path (#3032)
|
|
8
8
|
|
|
9
|
-
! When operator intent is **through merge**, **drive to merge**, **land/ship issue**, or explicit **drive-to: merge-ready** for story work, the parent (monitor) conversation MUST NOT implement product code or own the implementation PR as the leaf. Parent MUST run this skill's launch path: worktree isolation when available, worker envelope with `drive-to: merge-ready
|
|
9
|
+
! When operator intent is **through merge**, **drive to merge**, **land/ship issue**, or explicit **drive-to: merge-ready** for story work, the parent (monitor) conversation MUST NOT implement product code or own the implementation PR as the leaf. Parent MUST run this skill's launch path: worktree isolation when available, worker envelope with the unit-of-work boundary selected below (`drive-to: merge-ready` default, or deliberate `stop-at: pr-open` per the envelope selection SLA), xBRIEF preflight, pre-pr + review-cycle, then merge/`scope:complete` per #1880 Gap C.
|
|
10
10
|
! **Cohort size N=1 is still a cohort for dispatch.** Solo through-merge uses the same swarm/solo-worker launch path as multi-story (`dispatch_kind: solo` or a one-story swarm-cohort). Do not treat "only one issue" as permission for the parent to code.
|
|
11
11
|
⊗ Parent implements, babysits product fix loops, or skips worktree + worker dispatch for through-merge / drive-to:merge-ready work when background subagent/worktree dispatch is available (#3032).
|
|
12
12
|
|
|
13
|
+
### Envelope selection SLA — `drive-to: merge-ready` vs `stop-at: pr-open` (#3153)
|
|
14
|
+
|
|
15
|
+
! **Cohort through-merge intent still means stories land on master.** Choosing `stop-at: pr-open` changes **who owns which mile** (implement leaf vs review-cycle babysit owner), not whether the cohort ships. Happy-path single-leaf ownership remains valid; this SLA does **not** replace Gap C with "always split."
|
|
16
|
+
|
|
17
|
+
! **Default for story / through-merge dispatch:** `drive-to: merge-ready` — the implementation leaf owns implement → pre-pr → push → PR → Greptile review-cycle → CI → merge-ready (and `scope:complete` when the envelope includes that step) as **one** unit (#1880 Gap C / #3032).
|
|
18
|
+
|
|
19
|
+
! **Select the envelope at Phase 0 allocation / Phase 3 dispatch prep** (before spawn). Record the choice in the worker prompt unit-of-work line. Re-evaluate only when a leaf returns `BLOCKED` / thin DONE and a **new** continuation is planned — never re-label a live `drive-to: merge-ready` leaf as if it had been `stop-at: pr-open`.
|
|
20
|
+
|
|
21
|
+
#### Decision tree (concrete triggers)
|
|
22
|
+
|
|
23
|
+
| Trigger | Envelope | Notes |
|
|
24
|
+
|---------|----------|--------|
|
|
25
|
+
| Happy path / short story / green CI expected / no wall-clock budget stated | **`drive-to: merge-ready`** (default) | One leaf owns full path; silent PR-open handback remains forbidden |
|
|
26
|
+
| Operator (or xBRIEF) states a wall-clock / context budget that is likely shorter than CI + conf-floor wait | **`stop-at: pr-open` recommended** | Parent/monitor **must** spawn or retain one review-cycle babysit owner on the open PR (partner contract: `skills/deft-directive-review-cycle/SKILL.md` § Partner merge-path) |
|
|
27
|
+
| Known or observed **runner capacity stall** (`ci_ready_state=runner_capacity_stall` / #2672) dominating wall clock before implement finishes | **`stop-at: pr-open` recommended** | Do not lower conf floors or `--skip-ci`; split so implement leaf does not burn host budget waiting on runners; babysit owns failover wait |
|
|
28
|
+
| Large multi-gate story (many required checks, multi-round Greptile, dogfood conf floor, expected multi-hour non-impl wait) | **`stop-at: pr-open` recommended** | Keeps implement leaf focused; merge path owned by review-cycle babysit with sticky lease (#3090 / #3044) |
|
|
29
|
+
| **Conf-only residual** after implement: 0 P0/P1, score below `minGreptileConfidence`, product AC met (#2881 / #3095) | Prefer **`drive-to: merge-ready`** leaf to exit **`BLOCKED`** (not thin DONE) **or** deliberate **`stop-at: pr-open`** + babysit if the split was pre-declared | Confidence-only holds are **not** a mandate to redesign; babysit offers document/accept/minimal polish — not unbounded redesign |
|
|
30
|
+
| Host leaf cannot nest a review-monitor (Cursor Task / Claude Code nested-spawn limits #2797 / #3134) **and** Approach 1 sibling is desired | **`stop-at: pr-open` required** for the implement leaf | Orchestrator spawns sibling review-monitor + lease; same as existing leaf-boundary rules |
|
|
31
|
+
| Explicit operator override | Honor operator | Still declare envelope in dispatch; partner ownership rules still apply |
|
|
32
|
+
|
|
33
|
+
#### Thin DONE and recovery (fail-closed)
|
|
34
|
+
|
|
35
|
+
! A `drive-to: merge-ready` leaf that exits with PR URL but **no** merge / merge-ready evidence is **FAILED thin DONE** (#2943 / preamble §11) — not success and not a designed handoff.
|
|
36
|
+
! Recovery: parent/monitor ground-truths once, then backgrounds **exactly one** continuation owner scoped `drive-to: merge-ready` on the same worktree/PR **or** one review-cycle babysit owner with sticky `<!-- deft:review-owner -->` lease. ⊗ Dual lease / parallel babysit (#3044). ⊗ Cursor global babysit freestyle (#2261).
|
|
37
|
+
! A **deliberate** `stop-at: pr-open` exit (PR open + structured handback) is **not** thin DONE — it is a designed handoff that **requires** the review-cycle partner merge-path contract immediately (same turn tool dispatch or registered owner).
|
|
38
|
+
! Under human-merge policy, the partner owner (or an explicit handoff recipient) remains responsible through merge + `scope:complete` — CLEAN alone is not lifecycle complete (review-cycle partner merge-path / #1193 / #2321).
|
|
39
|
+
|
|
40
|
+
⊗ Re-scope a live `drive-to: merge-ready` worker mid-flight to "PR-open is enough" without a new dispatch envelope.
|
|
41
|
+
⊗ Choose `stop-at: pr-open` without a named babysit / review-monitor owner plan (silent drop of merge path).
|
|
42
|
+
⊗ Lower Greptile floors, skip CI, or use `--skip-ci` as the alternative to envelope selection (#2672 / #3095).
|
|
43
|
+
|
|
44
|
+
Cross-links: Phase 3 Worker-owns-lifecycle (`references/core-phase-3.md`), review-cycle partner merge-path (`skills/deft-directive-review-cycle/SKILL.md`), preamble Gap C (`templates/agent-prompt-preamble.md` § Orchestrator dispatch doctrine).
|
|
45
|
+
|
|
13
46
|
### Headless cohort fast-path: low-ceremony launch (C1 / #1387)
|
|
14
47
|
|
|
15
48
|
! When the operator supplies a **pre-approved cohort** via the **C1** `task swarm:launch` CLI, Phase 0 runs in headless / low-ceremony mode: the per-phase interactive approval gates (the Step 0c promote-fill prompts, the Step 0.5 lifecycle-bridge approval, and the Step 4/5 allocation approval) collapse into a SINGLE consent -- the `## Allocation context` token (#1378) carried in the dispatch envelope. The interactive promote-fill loop (Step 0a -- 0d below) is SKIPPED.
|
|
@@ -126,12 +126,18 @@ Cross-references: `packages/core/src/swarm/routing.ts` (`SWARM_WORKER_ROLES`), `
|
|
|
126
126
|
|
|
127
127
|
! **Worker-owns-lifecycle (Gap C):** Every implementation-worker dispatch prompt MUST declare the unit-of-work boundary: `stop-at: pr-open` OR `drive-to: merge-ready` (default for story xBRIEF work). Workers scoped `drive-to: merge-ready` own pre-PR, push, PR open, Greptile review-cycle poll/fix, and the #1259 Step 6 fail-closed exit as ONE dispatch — they spawn their own review poller per `skills/deft-directive-review-cycle/SKILL.md` monitoring tiers. The monitor MUST NOT plan a separate post-PR review leaf for a worker already scoped merge-ready.
|
|
128
128
|
|
|
129
|
+
! **Envelope selection at launch (#3153):** Choose the unit-of-work boundary using the Phase 0 **Envelope selection SLA** decision tree (`references/core-phase-0.md`) before spawn. Default remains `drive-to: merge-ready`. When the tree recommends or requires `stop-at: pr-open` (capacity stall, wall-clock budget, large multi-gate, host nested-monitor limits), the monitor MUST pre-plan the **partner merge-path owner** (review-cycle babysit / Approach 1 review-monitor) and dispatch or retain that owner when the implement leaf hands back — same turn as ground-truth of PR open, not improvised thin-DONE recovery. Cohort through-merge still means land on master; only mile ownership splits.
|
|
130
|
+
|
|
131
|
+
! **Deliberate `stop-at: pr-open` is not silent Gap C handback:** Silent PR-open handback for a worker whose envelope already said `drive-to: merge-ready` remains **forbidden**. A **pre-declared** `stop-at: pr-open` plus an immediately owned review-cycle babysit path is the supported alternative under the #3153 SLA. Partner contract depth: `skills/deft-directive-review-cycle/SKILL.md` § Partner merge-path when implement stops at PR-open.
|
|
132
|
+
|
|
129
133
|
! **Post-merge scope lifecycle (#2321 / Gap C):** Workers scoped `stop-at: pr-open` MUST NOT run `task scope:complete` before exit — their activation checkpoint rides into master on merge. The monitor (or Phase 6 `task swarm:finalize-cohort` / `task swarm:complete-cohort` on the headless path) MUST run `task scope:complete` or `task scope:cancel` for each shipped story xBRIEF after its PR merges. Workers scoped `drive-to: merge-ready` (or `drive-to: merge`) MUST include `task scope:complete` on their active xBRIEF as part of the same unit of work (after merge when appropriate). `task verify:orphan-active` fails closed when active/running briefs remain after their issues close or PR merges.
|
|
130
134
|
|
|
131
135
|
! **Background / independent dispatch (Gap D):** Dispatch implementation, fix, and review-cycle workers independently / in the background when the platform supports it. On Cursor, use the Task tool background path (`run_in_background: true`); on Claude Code, use the `Agent` tool with `run_in_background: true` (or host equivalent) (#3134); on OpenClaw, use `sessions_spawn` with the host's non-blocking / background session flags so the monitor conversation stays interactive. Foreground dispatch is for short tasks (<~3 min) only.
|
|
132
136
|
|
|
133
137
|
⊗ Hand back at PR-open and re-dispatch separate review-monitor or fix leaf agents for a worker whose envelope scoped `drive-to: merge-ready` (#1880 Gap C).
|
|
134
138
|
|
|
139
|
+
⊗ Dispatch `stop-at: pr-open` without a named review-cycle babysit / merge-path owner plan — that drops the merge mile (#3153).
|
|
140
|
+
|
|
135
141
|
⊗ Foreground/blocking dispatch for long-running implementation, fix, or review-cycle workers when background dispatch is available (#1880 Gap D).
|
|
136
142
|
|
|
137
143
|
|
|
@@ -60,6 +60,25 @@ tools: explore=0 commit=3 verify=0 coordinate=0 unknown=1 | anomalies: commit-wi
|
|
|
60
60
|
~ Pair the status line with worktree git checks and `task pr:merge-ready` so operators see progress **and** tool mix without reading raw tool logs.
|
|
61
61
|
⊗ Treat raw “ran N tools” as a structured mix — always bucket when events are available (#2967).
|
|
62
62
|
|
|
63
|
+
### Dual stop on monitor and repair loops (#2442)
|
|
64
|
+
|
|
65
|
+
! Phase 4 monitoring is multi-iteration work. It MUST obey dual stop (`main.md` `## Dual Stop Rule (#2442)`): **success** (leaf DONE with PR/merge evidence, or clean gate) **and** a **failure/budget** stop. One-shot status probes are exempt.
|
|
66
|
+
|
|
67
|
+
**Default failure envelope (monitor / repair class):**
|
|
68
|
+
|
|
69
|
+
| Stop | Default |
|
|
70
|
+
|------|---------|
|
|
71
|
+
| max iterations | **3** repair actions for the same leaf/PR failure class (resume prompt, takeover complete-remaining-steps, re-dispatch replacement, review re-trigger) |
|
|
72
|
+
| no-progress | same error / same Greptile finding class / same idle stage **3+** times with no material worktree or review change |
|
|
73
|
+
| budget | honor `pr:watch` / poll max-wait and Greptile service-error single-retry+escalate caps; do not nest an unbounded poll outside them |
|
|
74
|
+
|
|
75
|
+
! When the failure stop fires: **halt** automatic repair/re-dispatch; emit an **operator-visible halt report** (what was tried, current stage, missing evidence, human decision needed). Prefer `BLOCKED:` over thin `DONE` when the unit cannot reach merge-ready inside the envelope.
|
|
76
|
+
|
|
77
|
+
! Composes with minimal-subgraph repair (#2439): repairs stay minimal **and** dual-stop bounded. Mechanical delivery/acceptance circuit breaker: **#3143** `packages/core/src/delivery-attempt/` (`evaluatePreDispatch`). Docs: `docs/delivery-attempt.md`.
|
|
78
|
+
|
|
79
|
+
⊗ Silently continue the monitor repair loop after the envelope is exhausted.
|
|
80
|
+
⊗ Count a worker swap or session handoff as a fresh unlimited budget when the same failure class remains.
|
|
81
|
+
|
|
63
82
|
### Takeover Triggers
|
|
64
83
|
|
|
65
84
|
! **Pre-spawn verification:** Before spawning a replacement agent, verify the original is truly unresponsive by waiting for an idle/blocked lifecycle event — verified via worktree state (`git status`, `git log --oneline -3`) and sub-agent lifecycle signals showing no in-flight work (for grok-build / spawn_subagent agents: polling is via worktree state + `get_command_or_subagent_output` rather than tab observation; for openclaw / sessions_spawn agents: worktree state + parent completion announce / heartbeat records, not Grok Build poll output). Do NOT spawn a replacement based solely on message timing, absence of recent commits, or a perceived delay — original agents (Warp tabs, spawn_subagent processes, or OpenClaw sessions) can resume after apparent failure, and spawning a new agent creates two concurrent agents on the same worktree (see Duplicate-Tab Failure Mode below).
|
|
@@ -69,9 +88,9 @@ tools: explore=0 commit=3 verify=0 coordinate=0 unknown=1 | anomalies: commit-wi
|
|
|
69
88
|
- Agent process has exited and PR has not been created
|
|
70
89
|
- Agent process has exited and Greptile review cycle was not started
|
|
71
90
|
- Agent is idle for >5 minutes after PR creation with no review activity
|
|
72
|
-
- Agent is stuck in an error loop (same error 3+ times)
|
|
91
|
+
- Agent is stuck in an error loop (same error 3+ times) — this is a dual-stop no-progress signal (#2442); after takeover, remaining repair actions still count against the default failure envelope above
|
|
73
92
|
|
|
74
|
-
When taking over: read the agent's current state (git log, diff, PR comments), complete remaining steps manually following the same deft process.
|
|
93
|
+
When taking over: read the agent's current state (git log, diff, PR comments), complete remaining steps manually following the same deft process. If takeover itself cannot clear the failure class within the dual-stop envelope, halt with the operator-visible report rather than thrashing.
|
|
75
94
|
|
|
76
95
|
### Duplicate-Agent Failure Mode (a.k.a. Duplicate-Tab Failure Mode)
|
|
77
96
|
|
|
@@ -39,6 +39,21 @@ For each agent's PR:
|
|
|
39
39
|
|
|
40
40
|
! **Completion latch after first consolidate (#3092):** After the parent has emitted **one** user/caller-visible consolidate for a child `runId` / settle batch (accept or reject), **identical or equivalent completion replay** for the same key MUST be **silent** (no tools, no re-QC, no second final; host silent token when defined, e.g. OpenClaw `NO_REPLY`). Re-open only on new `runId`/batch, principal explicit reopen, or **materially new** evidence (new HEAD, new blocker class) — not fat re-embeds of the same rollup. Replay storms: at most one fail-loud note, then silent. Full MUST + anti-patterns: `templates/agent-prompt-preamble.md` §11.5. Orthogonal to empty settle ≠ done (#3044).
|
|
41
41
|
|
|
42
|
+
### Human-merge observe path for `stop-at: pr-open` (#3153)
|
|
43
|
+
|
|
44
|
+
! When any cohort story was dispatched **`stop-at: pr-open`** (or thin-DONE recovery handed merge path to babysit) **and** merge authority is human-only (`requireHumanMerge` / no bot merge), the monitor is the **default durable owner** of post-merge `scope:complete` (review-cycle partner merge-path). Greptile CLEAN alone is **not** lifecycle complete.
|
|
45
|
+
|
|
46
|
+
! **Required observe path before declaring the cohort closed:**
|
|
47
|
+
|
|
48
|
+
1. ! Keep a machine-checkable list of open cohort PRs marked `awaiting-human-merge` (PR number, HEAD, story xBRIEF path) in the monitor checkpoint.
|
|
49
|
+
2. ! Until each listed PR is `MERGED` (or closed without merge → cancel path), the monitor MUST use one of:
|
|
50
|
+
- **Background merge observer** (preferred on Tier 1): Approach 1 poller or short sub-agent that probes `gh api repos/<owner>/<repo>/pulls/<N>` for `merged == true` / `state`, then signals the parent; parent runs Step 1.5 sweep for that story.
|
|
51
|
+
- **Parent-retained re-entry:** parent keeps `review_cycle: in_progress:<pr>#parent-retained` and **MUST** re-check merge state on every re-invocation / next tool turn until merged — first tool action on re-entry is the merge-state probe.
|
|
52
|
+
- **Phase 6 Step 1 pre-sweep re-poll (always):** Immediately before Step 1.5 `task swarm:complete-cohort` / `task swarm:finalize-cohort`, re-poll **every** cohort PR via REST `pulls/<N>` and refuse the sweep while any `awaiting-human-merge` PR is still open. ⊗ Run the completion sweep solely because Greptile was CLEAN earlier.
|
|
53
|
+
3. ! After merge is observed: run post-merge verification (closing keywords) then Step 1.5 sweep / `task scope:complete` for the story.
|
|
54
|
+
|
|
55
|
+
Cross-link: `skills/deft-directive-review-cycle/SKILL.md` § Partner merge-path / Post-CLEAN wake path. ⊗ Ownership-in-name-only (sticky lease with no observer).
|
|
56
|
+
|
|
42
57
|
### Complete xBRIEFs
|
|
43
58
|
|
|
44
59
|
! The cohort's story xBRIEFs are completed by the deterministic **cohort completion sweep** in Phase 6 (`task swarm:complete-cohort`, Phase 6 Step 1.5 below), which runs AFTER the merge cascade. Do NOT move story xBRIEFs out of `xbrief/active/` before their PRs merge — a pre-merge move creates premature state if the merge cascade fails. This section is where the monitor records, per story, what the post-merge sweep will finalize:
|
|
@@ -215,6 +230,8 @@ This is defense in depth -- run it even when the pre-merge inspection above pass
|
|
|
215
230
|
|
|
216
231
|
! **REQUIRED.** Once the cohort's PRs are merged (Step 1 complete), the monitor MUST run the deterministic cohort completion sweep so the finished swarm leaves NO stranded xBRIEFs. This step closes the gap where a completed cohort left its story xBRIEFs in `xbrief/active/` and their decompose-created epic parents in `xbrief/pending/` -- nothing in the swarm flow swept them to `completed/` (observed in the 2026-06-03 swarm: after the cohort's PRs merged, the child story xBRIEFs stayed in `active/` and their epic parents stayed in `pending/`).
|
|
217
232
|
|
|
233
|
+
! **Pre-sweep merge re-poll for human-merge / `stop-at: pr-open` (#3153):** Before invoking `task swarm:complete-cohort` or `task swarm:finalize-cohort`, re-read each cohort PR's merge state via REST. If any PR marked `awaiting-human-merge` is still open, **halt** the sweep, keep durable ownership, and continue the observe path (Phase 5 human-merge section) until merge or operator cancel. ⊗ Sweep on Greptile CLEAN alone while a human-merge PR is still open.
|
|
234
|
+
|
|
218
235
|
```pwsh path=null start=null
|
|
219
236
|
# Sweep the whole cohort by glob (typical close-out)...
|
|
220
237
|
task swarm:complete-cohort -- --cohort 'xbrief/active/*.xbrief.json'
|
|
@@ -35,6 +35,10 @@ Live miss: operator said “use review skill” + URL; agent stayed on host free
|
|
|
35
35
|
|
|
36
36
|
Package install alone does not put always-pins into `~/.openclaw/workspace/skills`. Operators / agents SHOULD run `deft doctor` (detect) and `deft doctor --fix` (symlink or copy the four pins) when main-workspace pins are missing. Multi-seat only with `--openclaw-all-agents`. Operator steps: [`../../docs/openclaw-agent-host.md`](../../docs/openclaw-agent-host.md) § Wire skills into OpenClaw workspace.
|
|
37
37
|
|
|
38
|
+
### Soft post-compact AGENTS re-bind (#3171)
|
|
39
|
+
|
|
40
|
+
OpenClaw does **not** claim file-host PreCompact hard re-arm alone. Soft re-bind is a **required** durable skill (`deft-directive-post-compact-rebind`) deposited by `deft doctor --fix` / init when OpenClaw is detected — same checklist SoT as Cursor/Claude/Grok. After deposit, restart gateway or start a new session. Full dual-surface matrix: [`../../docs/openclaw-agent-host.md`](../../docs/openclaw-agent-host.md) § Soft post-compact AGENTS re-bind; `commands.md` compact + soft section.
|
|
41
|
+
|
|
38
42
|
## Hard isolation before spawn (#2929)
|
|
39
43
|
|
|
40
44
|
! For **parallel** OpenClaw leaves (cohort size > 1):
|
package/tasks/engine-invoke.cjs
CHANGED
|
@@ -113,12 +113,13 @@ function main() {
|
|
|
113
113
|
// stdio inherit (not pipe): piped stdout/stderr deadlocks when the child emits
|
|
114
114
|
// more than the OS pipe buffer before exit — observed as greenfield smoke
|
|
115
115
|
// hanging then CI SIGTERM exit 143 with no output (#2554 / #2547).
|
|
116
|
+
// shell:false is a literal at the call site (not plan.shell) so static
|
|
117
|
+
// analyzers see a non-shell spawn; win32 global still uses a quoted cmd.exe
|
|
118
|
+
// wrapper inside buildSpawnPlan, never shell:true (#2911 / #3175).
|
|
116
119
|
const result = spawnSync(plan.command, plan.args, {
|
|
117
120
|
stdio: "inherit",
|
|
118
121
|
env: childEnv,
|
|
119
|
-
|
|
120
|
-
// win32 .cmd shim is reached through a tightly quoted cmd.exe wrapper below.
|
|
121
|
-
shell: plan.shell,
|
|
122
|
+
shell: false,
|
|
122
123
|
// CREATE_NO_WINDOW: hide console windows from Cursor Task / nested shells (#2563).
|
|
123
124
|
windowsHide: true,
|
|
124
125
|
});
|
|
@@ -135,6 +136,11 @@ function main() {
|
|
|
135
136
|
* quoted so metacharacters stay inside a single argv token — aligned with
|
|
136
137
|
* tasks/engine-pm-run.cjs executeAllowlisted().
|
|
137
138
|
*
|
|
139
|
+
* Vendored vs global branches are deliberately disjoint (#3175 / CodeQL alert
|
|
140
|
+
* #74): process.execPath (AbsolutePathSource) is only the vendored non-shell
|
|
141
|
+
* command and must never flow into the win32 cmd.exe `/c` string, where it
|
|
142
|
+
* would be shell-interpreted as part of a constructed command line.
|
|
143
|
+
*
|
|
138
144
|
* @param {string} mode
|
|
139
145
|
* @param {string} target
|
|
140
146
|
* @param {string[]} argv
|
|
@@ -143,26 +149,25 @@ function main() {
|
|
|
143
149
|
*/
|
|
144
150
|
function buildSpawnPlan(mode, target, argv, opts = {}) {
|
|
145
151
|
const platform = opts.platform || process.platform;
|
|
146
|
-
const nodePath = opts.nodePath || process.execPath;
|
|
147
152
|
|
|
148
|
-
let execPath;
|
|
149
|
-
let execArgv;
|
|
150
153
|
if (mode === "vendored") {
|
|
151
|
-
execPath
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
} else {
|
|
157
|
-
return null;
|
|
154
|
+
// Non-shell: Node binary + script path + operator argv. process.execPath is
|
|
155
|
+
// only used here as the executable name with shell:false — never joined into
|
|
156
|
+
// a cmd.exe command line (CodeQL js/shell-command-injection-from-environment).
|
|
157
|
+
const nodePath = opts.nodePath || process.execPath;
|
|
158
|
+
return { command: nodePath, args: [target, ...argv], shell: false };
|
|
158
159
|
}
|
|
159
160
|
|
|
160
|
-
if (mode === "global"
|
|
161
|
-
|
|
162
|
-
|
|
161
|
+
if (mode === "global") {
|
|
162
|
+
if (platform === "win32") {
|
|
163
|
+
// Only the global shim name/path and operator argv — no process.execPath.
|
|
164
|
+
const commandLine = [target, ...argv].map(quoteWin32Arg).join(" ");
|
|
165
|
+
return { command: "cmd.exe", args: ["/d", "/s", "/c", commandLine], shell: false };
|
|
166
|
+
}
|
|
167
|
+
return { command: target, args: argv, shell: false };
|
|
163
168
|
}
|
|
164
169
|
|
|
165
|
-
return
|
|
170
|
+
return null;
|
|
166
171
|
}
|
|
167
172
|
|
|
168
173
|
if (require.main === module) {
|
|
@@ -186,3 +186,33 @@ describe("buildSpawnPlan — other paths keep shell:false", () => {
|
|
|
186
186
|
assert.equal(buildSpawnPlan("bogus", "deft", ["release"], WIN32), null);
|
|
187
187
|
});
|
|
188
188
|
});
|
|
189
|
+
|
|
190
|
+
describe("buildSpawnPlan — CodeQL absolute-path isolation (#3175 / alert #74)", () => {
|
|
191
|
+
it("never places nodePath/process.execPath into the win32 cmd.exe command line", () => {
|
|
192
|
+
const evilNode = String.raw`C:\Program Files\nodejs\node.exe`;
|
|
193
|
+
const plan = buildSpawnPlan("global", "deft", ["release", "--summary", "ok"], {
|
|
194
|
+
platform: "win32",
|
|
195
|
+
nodePath: evilNode,
|
|
196
|
+
});
|
|
197
|
+
assert.equal(plan.shell, false);
|
|
198
|
+
assert.equal(plan.command, "cmd.exe");
|
|
199
|
+
assert.deepEqual(plan.args.slice(0, 3), ["/d", "/s", "/c"]);
|
|
200
|
+
// Global win32 must only join target + operator argv — not the Node binary.
|
|
201
|
+
assert.equal(plan.args[3].includes(evilNode), false);
|
|
202
|
+
assert.equal(plan.args[3].includes("Program Files"), false);
|
|
203
|
+
assert.equal(plan.args[3].includes("node.exe"), false);
|
|
204
|
+
assert.deepEqual(splitCmdTokens(plan.args[3]), ["deft", "release", "--summary", "ok"]);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it("uses nodePath only as the non-shell vendored command (never cmd.exe)", () => {
|
|
208
|
+
const nodePath = String.raw`C:\Program Files\nodejs\node.exe`;
|
|
209
|
+
const plan = buildSpawnPlan("vendored", String.raw`C:\repo\packages\cli\dist\bin.js`, ["session:start"], {
|
|
210
|
+
platform: "win32",
|
|
211
|
+
nodePath,
|
|
212
|
+
});
|
|
213
|
+
assert.equal(plan.shell, false);
|
|
214
|
+
assert.equal(plan.command, nodePath);
|
|
215
|
+
assert.notEqual(plan.command, "cmd.exe");
|
|
216
|
+
assert.deepEqual(plan.args, [String.raw`C:\repo\packages\cli\dist\bin.js`, "session:start"]);
|
|
217
|
+
});
|
|
218
|
+
});
|
package/tasks/verify.yml
CHANGED
|
@@ -210,6 +210,36 @@ tasks:
|
|
|
210
210
|
vars:
|
|
211
211
|
ENGINE_CMD: 'verify:forward-coverage --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
|
|
212
212
|
|
|
213
|
+
test-boundary:
|
|
214
|
+
desc: "Test/source boundary gate (#3145): reject recognized test artifacts under production roots and production references to test/fixture roots unless allowlisted or classified production-liveness. Policy from .deft/test-boundary.policy.json or plan.policy.testBoundary; defaults are warn-only (migration). Flags: --enforce / --warn / --policy <path> / --quiet. Three-state exit (0 clean or warn / 1 violation / 2 config)."
|
|
215
|
+
dir: '{{.USER_WORKING_DIR}}'
|
|
216
|
+
deps:
|
|
217
|
+
- task: :engine:_ts-build
|
|
218
|
+
cmds:
|
|
219
|
+
- task: :engine:invoke
|
|
220
|
+
vars:
|
|
221
|
+
ENGINE_CMD: 'verify:test-boundary --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
|
|
222
|
+
|
|
223
|
+
scope-provenance:
|
|
224
|
+
desc: "Approved-scope provenance gate (#3145): same-PR active xBRIEF file_scope expansion cannot self-authorize new paths. Compares against .deft/approved-scope/<plan-id>.json digests; requires renewed human approval for expansion. Missing digests warn by default; pass --enforce to fail closed. Flags: --base-ref / --enforce / --quiet. Three-state exit (0 clean or warn / 1 self-auth / 2 config)."
|
|
225
|
+
dir: '{{.USER_WORKING_DIR}}'
|
|
226
|
+
deps:
|
|
227
|
+
- task: :engine:_ts-build
|
|
228
|
+
cmds:
|
|
229
|
+
- task: :engine:invoke
|
|
230
|
+
vars:
|
|
231
|
+
ENGINE_CMD: 'verify:scope-provenance --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
|
|
232
|
+
|
|
233
|
+
consumer-check-contract:
|
|
234
|
+
desc: "Consumer check-composition contract (#3145): fail when tasks/verify.yml or check aggregate omit required enforcement gates (verify:test-boundary, verify:scope-provenance, verify:consumer-check-contract). CI omissions warn by default. Flags: --framework-source / --enforce / --warn / --quiet. Three-state exit (0 clean or warn / 1 missing / 2 config)."
|
|
235
|
+
dir: '{{.USER_WORKING_DIR}}'
|
|
236
|
+
deps:
|
|
237
|
+
- task: :engine:_ts-build
|
|
238
|
+
cmds:
|
|
239
|
+
- task: :engine:invoke
|
|
240
|
+
vars:
|
|
241
|
+
ENGINE_CMD: 'verify:consumer-check-contract --project-root "{{.USER_WORKING_DIR}}" {{.CLI_ARGS}}'
|
|
242
|
+
|
|
213
243
|
vbrief-conformance:
|
|
214
244
|
desc: "Detect bare non-conformant vBRIEF keys (#1620). Scans tracked vbrief/**/*.vbrief.json and flags any document/plan/item key that is not 0.6 spec-core, x-directive/-namespaced, or x-vbrief/-namespaced. plan.policy + plan.completedNote carry a TEMPORARY allow-list pending vBRIEF #12. Defaults to --all; pass --staged for the pre-commit invocation."
|
|
215
245
|
dir: '{{.USER_WORKING_DIR}}'
|
|
@@ -461,11 +461,13 @@ These rules bind **orchestrators** dispatching implementation, fix, or review-cy
|
|
|
461
461
|
**Worker-owns-lifecycle (Gap C):**
|
|
462
462
|
|
|
463
463
|
- ! When dispatching an implementation worker, the dispatch envelope MUST declare the unit-of-work boundary explicitly: `stop-at: pr-open` (worker opens PR and exits) OR `drive-to: merge-ready` (worker owns PR + Greptile review cycle + fix batches through merge-ready as ONE unit of work, spawning its own review poller per `skills/deft-directive-review-cycle/SKILL.md` monitoring tiers). Default for story implementation dispatches is `drive-to: merge-ready`.
|
|
464
|
+
- ! **Envelope selection SLA (#3153):** Choose the boundary before spawn using the swarm decision tree (`skills/deft-directive-swarm/references/core-phase-0.md` — capacity stall, conf-only residual, wall-clock budget, large multi-gate, host nest limits). Happy-path default remains `drive-to: merge-ready`. A **deliberate** `stop-at: pr-open` is valid only with an immediate partner merge-path owner per `skills/deft-directive-review-cycle/SKILL.md` § Partner merge-path (babysit / Approach 1 lease / parent-retained — not freestyle global babysit). Under human-merge policy, that owner (or an explicit handoff recipient) remains responsible through merge + `scope:complete` — do not stand down at CLEAN alone. Consumer pin: `templates/agents-entry.md` § Envelope selection SLA. Silent PR-open handback for a worker already scoped merge-ready remains **forbidden**.
|
|
464
465
|
- ! **Cursor Task ownership split (#2797 / #2814):** A Cursor `Task` implementation leaf MUST NOT spawn another Cursor `Task` review-monitor: nested Task (leaf spawning leaf) is unsupported/unreliable. A Cursor `drive-to: merge-ready` leaf instead owns a blocking `task pr:watch -- <N>` in its own process. To use an Approach 1 monitor, scope the leaf `stop-at: pr-open`; the orchestrator that owns the Task primitive then launches the sibling monitor and runs `task review-monitor:register -- --pr <N> --monitor-agent-id <id> --platform-primitive cursor-task` (GitHub sticky `<!-- deft:review-owner -->` lease — not local JSON).
|
|
465
466
|
- ⊗ Let a Cursor leaf background `task pr:watch` and claim review monitoring is active. The process dies with the leaf and has no GitHub review-owner lease; treat that claim as a regression/eval failure and let `task verify:review-monitor -- --pr <N>` fail closed.
|
|
466
467
|
- ! **Post-merge scope lifecycle (#2321 / Gap C):** Workers scoped `stop-at: pr-open` MUST NOT run `task scope:complete` before exit — their activation checkpoint rides into master on merge. The **orchestrator** (or Phase 6 `task swarm:finalize-cohort` / `task swarm:complete-cohort` on the headless path) MUST run `task scope:complete` or `task scope:cancel` for each shipped story xBRIEF after its PR merges. Workers scoped `drive-to: merge-ready` (or `drive-to: merge`) MUST include `task scope:complete` on their active xBRIEF as part of the same unit of work (after merge when appropriate).
|
|
467
468
|
- ! Workers scoped `drive-to: merge-ready` MUST drive to merge-ready in their own tool loop — pre-PR, push, PR open, review-cycle poll/fix loop, and the #1259 Step 6 fail-closed exit — without handing back at PR-open for the orchestrator to re-dispatch separate leaf agents for review or fixes.
|
|
468
469
|
- ⊗ Re-dispatch a separate review-monitor or fix agent after an implementation worker exits at PR-open when the original envelope scoped `drive-to: merge-ready` — that split recreates cross-agent state-handoff hazards and terminal lifecycle gaps (#1878 / Gap C).
|
|
470
|
+
- ⊗ Dispatch `stop-at: pr-open` without a named review-cycle partner merge-path owner plan (#3153).
|
|
469
471
|
- ⊗ Leave an `xbrief/active/` brief with `plan.status == running` on master after the story's issue is closed or its PR merged — `task verify:orphan-active` fails closed on that signature (#2321).
|
|
470
472
|
|
|
471
473
|
**Background / independent dispatch (Gap D):**
|
|
@@ -526,6 +528,12 @@ The parent monitor watches the heartbeat file directly (three-state exit 0 ok /
|
|
|
526
528
|
- Monitors run `task verify:subagent-alive -- --require-agent <agent-id> [--scratch-dir <worktree>/.deft-scratch/subagent-status]` each poll iteration.
|
|
527
529
|
- Workers run `task agent:monitor` (raw sweep) or the gate verb above; both wrap `subagent-monitor` (#1365).
|
|
528
530
|
|
|
531
|
+
## 10.6 Dual stop for multi-iteration worker loops (#2442)
|
|
532
|
+
|
|
533
|
+
Multi-iteration implement, pre-PR, repair, and monitor loops require **two** stops: **success** (goal / AC / checker met) and **failure or budget** (max iterations, no-progress, or time/token budget). Single-turn tasks are exempt. Principle and defaults: `main.md` `## Dual Stop Rule (#2442)`; build skill dual-stop table; swarm Phase 4 / core-ops.
|
|
534
|
+
|
|
535
|
+
! On failure stop: halt; emit an operator-visible report (what was tried, what is missing, what human decision is needed). Prefer `BLOCKED:` over silent retry. ⊗ Thrash past the envelope. Durable delivery/acceptance mechanical enforcement is **#3143** (`packages/core/src/delivery-attempt/`; not prompt-only).
|
|
536
|
+
|
|
529
537
|
## 11. Mandatory DONE message even on early exit
|
|
530
538
|
|
|
531
539
|
Every worker MUST send a final status message before exiting its tool loop, regardless of outcome:
|