diff --git a/.project/STATUS.md b/.project/STATUS.md index aceea8c..7e9ed30 100644 --- a/.project/STATUS.md +++ b/.project/STATUS.md @@ -1,12 +1,12 @@ # artifact-driven-dev — Project Status +_Updated: 2026-07-30 (**collab status-refresh invariant implemented — delegated run landed on `feat/collab-status-refresh`** — `/ardd-implement` found nothing to execute: the one `ready` tasks file `tasks-feat-collab-status-refresh-18bc.md` was already `completed` 6/6 inside delegated worktree `agent-ab9b42b27448e8249`, which the pairwise matrix flagged `claimed` (step 1's hard same-file exclusion). Coordinator path instead: fast-forwarded `worktree-agent-ab9b42b27448e8249` (7 commits, T001–T006) into `feat/collab-status-refresh` — no conflicts, no merge commit — so the tasks file now reads `completed` 6/6 here. Landed edits: `skills/ardd-implement/SKILL.md` (collaborative report-back refreshes STATUS.md before push), `skills/ardd-plan/SKILL.md` (collaborative push waits for the terminal refresh), `skills/ardd-status/SKILL.md` (the no-`/ardd-status`-in-a-worktree prohibition scoped to delegated runs, collaborative norm named), plus `CLAUDE.md` and the three `docs/reference/skills/` bodies. `lint-project.sh` clean. No features bound (`features: []`), so no register flip; `completion-flip-check.sh` reports no orphans across every completed tasks file. `worktree-reap.sh` refused all three worktrees `reason=unmerged` — correct and expected in collaborative mode, where nothing reaches local `main` until the PR merges; nothing forced. `core.bare=false` and `core.hooksPath=hooks` both healthy — no `Agent` worktree side effects to restore. This very block is the refresh-before-push the landed invariant now mandates. Pushed to **PR #30** (open, *not* draft — it predates this run). CI green on `fec1938` — 52 checks pass, `deploy` skipped. **Stale base resolved, with the user's explicit approval for the rewrite:** PR #29 squash-merged to `main` as `f79abe9` on 2026-07-27, but `feat/complexity-model-routing` still existed on origin at `191bea3`, so #30 was stacked on a dead branch. Fixed by `git rebase --onto origin/main 191bea3` — dropping the 9 pre-squash commits, re-signing all 10 survivors with the on-disk key (1Password was locked, so the first attempt died on `failed to fill whole buffer` and was aborted cleanly; the retry passed the signing `-c` overrides explicitly) — then retargeting #30 to `main` and force-pushing with `--force-with-lease`. Verified: the rebased tree is byte-identical to the pre-rebase branch (`git diff` against a `backup-collab-status-refresh` safety ref is empty), every commit verifies `G`, and #30's diff against `main` is now the clean 11 files / +236/-25 rather than the 27-file / +827 pre-squash noise. Register: 0 backlogged · 0 planned · 0 tasked · 44 implemented · 1 retired · 1 rejected; 2 open feedback (`feedback-amend-path-for-skill-written-files-2187.md`, `feedback-repo-critique-6ad1.md` — the block below understates this as 0; 2 is the count derived from disk); 0 defects (last verified 2026-07-12). No `ready` tasks files remain — Work Queue empty. In flight: 3 worktrees (all `completed`/clean, unmerged against `main`) and PR #30. Recommended next step: review and merge PR #30.)_ + +_Updated: 2026-07-27 (**collab status-refresh invariant planned + tasked on `feat/collab-status-refresh` (stacked on PR #29's branch)** — `/ardd-plan` consumed `feedback-collab-status-refresh-before-pr-a28b.md` (F001 accepted `[x]`, file `planned`): drafted and approved `plan-feat-collab-status-refresh-2026-07-27-7811.md` — the invariant "in collaborative mode, no ArDD skill pushes a feature branch whose STATUS.md predates the state the push carries," implemented as prose edits scoping the delegated-no-`/ardd-status` rule to solo mode, adding the coordinator's refresh-before-push step to `/ardd-implement`'s collaborative report-back, and a terminal refresh to `/ardd-plan`'s collaborative endings (mid-run visibility pushes exempt, per the approved open-question default). Tasks `tasks-feat-collab-status-refresh-18bc.md` (`ready`, 0/6, `complexity: moderate` — the stamp's first dogfood) across 4 phases: implement wiring → plan wiring → status scoping → docs+verify. No features bound (`features: []` — the superseded `ci-status-refresh-on-main-coll` stays `rejected`). This very block is the plan-only-PR refresh the invariant mandates. Register: 0 backlogged · 0 planned · 0 tasked · 44 implemented · 1 retired · 1 rejected; 0 open feedback; 0 defects. In flight: PR #29 (ready for review) and this stacked branch. Recommended next step: review/merge PR #29, then `/ardd-implement` for the 18bc tasks file.)_ + _Updated: 2026-07-27 (**complexity+routing implemented (PR #29 ready) · ci-status-refresh researched, rejected, superseded by new feedback** — the delegated worktree run completed all 9 tasks of `tasks-feat-complexity-model-routing-884c.md` (`completed`, 9/9; test-ardd-state 158 ok, test-lint-project 29 ok at 43 expected findings, lint-project + lint-docs clean) and fast-forwarded into `feat/complexity-model-routing`; both bound features are `implemented` (rides this branch, lands when PR #29 merges — now ready for review, no longer draft). A delegated `/ardd-research` run vetted `ci-status-refresh-on-main-coll` (`research-ci-status-refresh-on-main-coll-2026-07-27-0c1d.md`, merged onto this branch): verdict reject — the CI shape reverses the STATUS.md single-writer decision and the 2026-07-06 mechanization non-goal, needs bot PRs under branch protection, and its PR-noise motivation mostly evaporated after `merge=ours` + `status_history_keep`; register entry flipped `rejected`. The surviving kernel is captured as new open feedback `feedback-collab-status-refresh-before-pr-a28b.md` (Reconsidered, F001): in collaborative mode every ArDD skill refreshes STATUS.md on the feature branch as the last step before a PR push — plan-only and implementation PRs alike — relaxing the over-broad delegated-no-/ardd-status rule (this very block is the invariant's first dogfood, fixing PR #29's stale `ready 0/9` report). Register: 0 backlogged · 0 planned · 0 tasked · 44 implemented · 1 retired · 1 rejected. 1 open feedback (the next `/ardd-plan`'s input); 0 defects (last verified 2026-07-12). Recommended next step: review/merge PR #29, then `/ardd-plan feedback-collab-status-refresh-before-pr-a28b.md`.)_ _Updated: 2026-07-26 (**slate bundle planned + tasked on `feat/complexity-model-routing` (draft PR #29)** — `/ardd-plan --slate` over the 3 backlogged items recommended one bundle (`plan-time-complexity-stamps` → `delegate-model-routing`: dependency edge — the routing map is keyed by the complexity stamp — plus shared validator files; both high confidence) and one solo-deferral (`ci-status-refresh-on-main-coll`: low — no code seam, collides with the single-writer rule and the STATUS.md-assembly mechanization non-goal; vet via `/ardd-research` before planning). The bundle run drafted and approved `plan-feat-complexity-model-routing-2026-07-25-fd96.md` (no artifact changes — workflow-field precedent; Open-Question defaults accepted: `haiku|sonnet|opus` tier aliases, absent complexity never routes down) and generated `tasks-feat-complexity-model-routing-884c.md` (`ready`, 0/9, phases: complexity stamp machinery → plan-side wiring → delegate_model grammar → dispatch resolution + docs → verification). Both features flipped `backlogged → tasked`; state committed and pushed, in-flight via draft PR #29. Work Queue: the one `ready` file, no pairs to relate. Register: 1 backlogged · 0 planned · 2 tasked · 44 implemented · 1 retired. 0 open feedback; 0 defects (last verified 2026-07-12). Recommended next step: `/ardd-implement` to execute the tasks file on this branch.)_ _Updated: 2026-07-25 (**PRs #24/#26 merged + reinstall at `541b283` + first live STATUS.md prune** — both feature PRs squash-merged to `main`: #24 (`/ardd-plan --slate` spans features + open feedback, with the review-hardened deterministic bucket precedence/transitive bundles/stable ordering) and #26 (`status_history_keep` keep-last-N STATUS.md pruning, with the review-hardened fail-closed `status-prune.sh`, the shared ≤4-digit validator contract, and the new `ardd-state.sh unstamp` return-to-unbounded path); the `status-md-trim-prune-history` register flip rode #26 (`implemented`, tasks `completed` 15/15). `/ardd-update` reinstalled from this self-hosted checkout at `541b283` (0d60d69 → 541b283; no migrations pending; `status-prune.sh` + `unstamp` now installed), and its backfill ask stamped `status_history_keep: 5` — this very entry's write is the field's first dogfood: the prune below cuts the chronology to its newest 5 blocks, with the full history in git (`git log -p .project/STATUS.md`). Current state on `main`: constitution stable ✅; 0 open defects (last verified 2026-07-12); 0 open feedback; register 3 backlogged · 0 planned · 0 tasked · 42 implemented · 1 retired; no ready/in-progress tasks; no worktrees; no orphaned flips. Recommended next step: merge this update PR, then `/ardd-plan --slate` over the 3 backlogged slugs (`ci-status-refresh-on-main-coll`, `delegate-model-routing`, `plan-time-complexity-stamps`).)_ -_Updated: 2026-07-24 (**implemented `ardd-plan-slate-mixed-feature` on branch `feat/ardd-plan-slate-mixed`** — `/ardd-implement` executed all 10 tasks of `tasks-ardd-plan-slate-mixed-feature-4469.md` (`status: completed`, 10/10) inline on this branch: `/ardd-plan --slate` now enumerates open feedback files alongside backlogged features (each feedback *file* is one slate item), grades/relates them on the same two axes, adds the `## Reconsidered`-vs-slated-feature dependency-edge heuristic, and emits mixed `/ardd-plan ` recommendations — all while staying read-only (slate never marks or flips feedback). Edits: `skills/ardd-plan/SKILL.md` (Usage `--slate` + slate steps 1–5 + next-step), `skills/ardd-feedback/SKILL.md` (Consumption note), `docs/reference/skills/ardd-plan.md` (hand-written body). No scripts or `lint-project.sh` enum changes — the scoped-run grammar already supported mixed calls. `lint-docs.sh` + `lint-project.sh` clean. Feature flipped `tasked → implemented` (rides this branch; lands when its PR merges). Sibling check: `all_complete=true`. This branch is one of two forked from `main` for the two independent features (the other, `feat/status-md-trim-prune`, carries `status-md-trim-prune-history` planning, still `tasked`). Recommended next step: push `feat/ardd-plan-slate-mixed` + open its draft PR (collaborative mode — awaiting user confirmation to push). Prior blocks preserved verbatim below.)_ - -_Updated: 2026-07-24 (**delegated `/ardd-implement` run — docs-sweep-feedback fixes completed on this branch (PR #19)** — all 6 tasks of `tasks-chore-docs-sweep-feedback-745e.md` are complete (`status: completed`, 6/6): T001-T005 fixed the five stale `docs/reference/skills/*.md` hand-written passages (`ardd-defects` reconciliation spot-check clause, `ardd-implement` Pre-flight four-path coverage + artifacts-dir ask, `ardd-init` overclaim-guard distinction, `ardd-plan` `plan_preview_editor` coverage, `ardd-update` Claude pre-`--harness` fallback note), T006 verified `lint-docs.sh` green. All 5 bound feedback files remain `planned` against `plan-chore-docs-sweep-feedback-2026-07-24-8c58.md`; no feature slugs (`features: []`), so no register flip. State rides this branch (`worktree-agent-a9ab51aacfd6ed53a`) per worktree-native state and lands when PR #19 merges — the `ready` copy of this tasks file on `chore/docs-sweep-feedback` (PR #20) reconciles to `completed` at that point. This entry refreshes the branch's stale pre-implementation STATUS.md at the user's request; the prior blocks below are preserved verbatim.)_ - diff --git a/.project/feedback/feedback-collab-status-refresh-before-pr-a28b.md b/.project/feedback/feedback-collab-status-refresh-before-pr-a28b.md index 4d802fd..1f9d3d8 100644 --- a/.project/feedback/feedback-collab-status-refresh-before-pr-a28b.md +++ b/.project/feedback/feedback-collab-status-refresh-before-pr-a28b.md @@ -1,7 +1,7 @@ --- -status: open # open -> planned +status: planned # open -> planned created: 2026-07-27 -plan: null +plan: plan-feat-collab-status-refresh-2026-07-27-7811.md --- # Feedback @@ -14,7 +14,7 @@ motivation mostly evaporated after `merge=ours` + `status_history_keep`). This item is the surviving kernel, reshaped per the user's direction. ## Reconsidered -- [ ] F001 In collaborative mode, the feature branch must always get a +- [x] F001 In collaborative mode, the feature branch must always get a STATUS.md refresh as the LAST step before a PR is pushed/opened — true for a plan-only PR (`/ardd-plan`'s collaborative path) and for an implementation PR (`/ardd-implement`, inline AND delegated), regardless diff --git a/.project/plans/plan-feat-collab-status-refresh-2026-07-27-7811.md b/.project/plans/plan-feat-collab-status-refresh-2026-07-27-7811.md new file mode 100644 index 0000000..7e7ef76 --- /dev/null +++ b/.project/plans/plan-feat-collab-status-refresh-2026-07-27-7811.md @@ -0,0 +1,117 @@ +--- +status: approved # draft -> approved -> superseded (schema-of-record: scripts/lint-project.sh) +branch: feat-collab-status-refresh +created: 2026-07-27 +features: [] +surfaced-defects: [] +--- + +# Plan: collaborative mode always refreshes STATUS.md before a PR push + +## Goal + +In collaborative mode, no ArDD skill pushes a feature branch whose STATUS.md predates the state the push carries — every plan-only and implementation PR gets a terminal `/ardd-status` refresh on the feature branch as the last step before the push. + +## Scope + +**In:** feedback F001 (`feedback-collab-status-refresh-before-pr-a28b.md`, +a Reconsidered item superseding the rejected +`ci-status-refresh-on-main-coll` register entry). Prose-only skill edits +to `/ardd-implement`, `/ardd-plan`, and `/ardd-status`, plus the doc/ +CLAUDE.md sync those skills' rules are mirrored in. Reverses two recorded +prose decisions: the blanket "a delegated subagent must never run +`/ardd-status`" rule (scoped down to solo mode), and `/ardd-plan`'s +refresh-free collaborative ending. + +**Out:** any CI regeneration of STATUS.md on the default branch (rejected +by the research doc — the register entry stays `rejected`); any change to +solo-mode behavior (inline terminal refresh and post-merge coordinator +refresh are already correct there); any new scripts (the refresh is the +existing `/ardd-status` procedure plus the already-landed +`status-prune.sh`). + +## Technical Approach + +- **One owner per path, coordinator-preferred.** The invariant needs + exactly one refresh per push, so each path names its owner explicitly: + - `/ardd-implement`, collaborative **delegated**: the **coordinator** + owns it. After the report-back and the fast-forward of the feature + branch onto the subagent-reported branch, the coordinator — a live + session in the primary checkout, now on the feature branch — runs + `/ardd-status` (refresh + `status-prune.sh` when `status_history_keep` + is set), commits it, and only then reaches the push/PR offer. The + delegated subagent itself stays out of the STATUS.md business (it + would have to re-derive the whole skill from prose mid-run); the rule + it currently violates is re-scoped rather than inverted. + - `/ardd-implement`, collaborative **inline**: already correct (step + 8's terminal refresh happens on the feature branch) — the edit just + states that this satisfies the invariant and that the push offer must + come after it, never before. + - `/ardd-plan`, collaborative: before the first push/draft-PR offer — + and again before any later push in the same run (e.g. the + post-approval tasking push) — run the terminal `/ardd-status` on the + feature branch so a plan-only PR's STATUS.md matches the plan/tasks + state it carries. +- **Re-scope the delegated-no-status rule, don't delete it.** The + trapped-write rationale is real in solo mode (an abandoned worktree + traps the report) — solo delegated runs keep the prohibition and the + post-merge coordinator refresh, unchanged. The prose in + `/ardd-implement` (step 3 note + step 8) and `/ardd-status` ("run only + from the primary checkout") gains the mode split: in collaborative + mode the coordinator's refresh happens on the feature branch in the + primary checkout — which is not the delegated-worktree case the + prohibition guards against — and the invariant sentence is stated in + all three skills verbatim: "in collaborative mode, no ArDD skill pushes + a feature branch whose STATUS.md predates the state the push carries." +- **Docs sync.** CLAUDE.md's two-modes section and single-writer note, + and the hand-written bodies of `docs/reference/skills/ardd-plan.md`, + `ardd-implement.md`, `ardd-status.md`, get the same mode-scoped rule; + `lint-docs.sh` green. No `lint-project.sh` changes — no new fields or + enums. + +## Phase Breakdown + +Phase lists are plan work-items, not live checklists — progress is +tracked in the linked tasks file. + +- **Phase 1 — `/ardd-implement` coordinator + inline wiring.** The + collaborative report-back sequence becomes: side-effect checks → + fast-forward feature branch → **status refresh + prune + commit** → + push/PR offer; the delegated-no-status rule gains its solo-only + scoping; inline step 8 gains the refresh-before-push ordering note. +- **Phase 2 — `/ardd-plan` collaborative ending.** Terminal refresh + before every push offer in the collaborative path (initial plan push + and post-tasking re-push). Depends on Phase 1 only for consistent + wording of the shared invariant sentence. +- **Phase 3 — `/ardd-status` scoping.** "Run only from the primary + checkout, never inside a delegated worktree" gains the collaborative + clarification (feature-branch runs in the primary checkout are the + required norm, not an exception) and the invariant sentence. + Depends on Phase 1's wording. +- **Phase 4 — docs + verification.** CLAUDE.md and the three reference + pages synced; `lint-docs.sh` + `lint-project.sh .` green. Depends on + Phases 1–3. + +## Complexity Tracking + +No justified deviations — prose-only edits to three skills plus doc +sync; no new mechanism (the refresh and prune already exist), per +Principle VI. + +## Open Questions + +None outstanding — the one question this plan opened was resolved at the +approval checkpoint. + +**Resolved (approved 2026-07-27): mid-run visibility pushes are exempt.** +`/ardd-implement`'s collaborative path may push after the *first* commit +(the draft-PR visibility offer) long before completion. The invariant +binds only pushes that carry *terminal* state — plan approved/tasked, +implementation completed — not incremental visibility pushes, since +refreshing STATUS.md on every mid-run push would spam the chronology. The +alternative considered and rejected was tightening it to +literally-every-push. Implemented as approved: see +`skills/ardd-implement/SKILL.md` (the exemption is stated at the +collaborative report-back step) and `skills/ardd-plan/SKILL.md` ("any +such push carrying this run's terminal state happens only after" the +refresh). diff --git a/.project/tasks/tasks-feat-collab-status-refresh-18bc.md b/.project/tasks/tasks-feat-collab-status-refresh-18bc.md new file mode 100644 index 0000000..1971ddc --- /dev/null +++ b/.project/tasks/tasks-feat-collab-status-refresh-18bc.md @@ -0,0 +1,22 @@ +--- +plan: plan-feat-collab-status-refresh-2026-07-27-7811.md +generated: 2026-07-27 +status: completed # generating -> ready -> in-progress -> completed (schema-of-record: scripts/lint-project.sh) +complexity: moderate +--- + +# Tasks + +## Phase 1: /ardd-implement coordinator + inline wiring +- [x] T001 Update `skills/ardd-implement/SKILL.md` step 3's collaborative-mode coordinator sequence: after the report-back side-effect checks and the fast-forward of the feature branch onto the subagent-reported branch, the coordinator MUST run `/ardd-status` on the feature branch in the primary checkout (refresh + `status-prune.sh` when `status_history_keep` is set) and commit it BEFORE the push/PR offer — the push never happens without it. Re-scope the "delegated subagent must never run `/ardd-status`" note to solo mode only, stating why (solo's abandoned-worktree trapped-write risk is real; in collaborative mode the coordinator's feature-branch refresh in the primary checkout is the required norm, and the subagent still never runs it — the coordinator owns the refresh). Mid-run visibility pushes (the first-commit draft-PR offer) are exempt: the invariant binds pushes carrying terminal state. Add the invariant sentence verbatim: "in collaborative mode, no ArDD skill pushes a feature branch whose STATUS.md predates the state the push carries." +- [x] T002 Update `skills/ardd-implement/SKILL.md` step 8's inline path: state that in collaborative mode the terminal `/ardd-status` on the feature branch is what satisfies the invariant, and any push/PR offer must come after that refresh, never before. Depends on T001 (same invariant wording). + +## Phase 2: /ardd-plan collaborative ending +- [x] T003 Update `skills/ardd-plan/SKILL.md`: in collaborative mode, before the run's terminal push/draft-PR offer — and before any later terminal-state push in the same run (the post-approval/tasking push) — run the terminal `/ardd-status` on the feature branch (refresh + prune) and commit it, so a plan-only PR's STATUS.md matches the plan/tasks state it carries. Keep step 15's existing analyze handoff as the mechanism; the edit pins its ordering relative to the push. Include the invariant sentence verbatim (same wording as T001). Depends on T001. + +## Phase 3: /ardd-status scoping +- [x] T004 Update `skills/ardd-status/SKILL.md`'s "Run only from the primary checkout, never inside a delegated worktree" passage: add the collaborative-mode clarification — running on a feature branch in the primary checkout is the required norm there (the refresh rides the branch and lands with the PR), and the prohibition's target remains delegated worktrees (all modes) plus solo-mode's trapped-write case. State the invariant sentence verbatim (same wording as T001). Depends on T001. + +## Phase 4: docs + verification +- [x] T005 Sync the mode-scoped rule into CLAUDE.md (the single-writer ownership note's `/ardd-status` line and the "Two operating modes" collaborative bullet) and into the hand-written bodies of `docs/reference/skills/ardd-implement.md`, `docs/reference/skills/ardd-plan.md`, and `docs/reference/skills/ardd-status.md` — same invariant, same solo/collaborative split, no contradicting leftover prose. Depends on T002, T003, T004. +- [x] T006 Run `scripts/lint-docs.sh` and `scripts/lint-project.sh .`; confirm both pass with no new findings. Depends on T005. diff --git a/CLAUDE.md b/CLAUDE.md index 68569be..28abb61 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -210,7 +210,12 @@ this is not enforceable by a hook, and that was verified, not assumed.** `/ardd-status` calls `scripts/status-prune.sh` after each prepend to keep only the newest N blocks in the live file — older history stays recoverable from git, so "durable re-entry chronology" is backed by git rather than - by file length + by file length. Never run by a delegated subagent in any mode — the + trapped-write rationale is solo-specific (an abandoned worktree traps + the write); in collaborative mode the coordinator's refresh on the + feature branch in the primary checkout is the required norm, upholding + the invariant that in collaborative mode, no ArDD skill pushes a + feature branch whose STATUS.md predates the state the push carries - `.project/DEFECTS.md` — written only by `/ardd-defects` - `.project/TRACKER.md` — written only by `/ardd-tracker` - `.project/audit.md` — written only by `/ardd-audit` @@ -403,7 +408,14 @@ re-asked afterward via `/ardd-update --reconfigure`): `origin/`, so plan/tasks files must have reached the remote before delegated implementation can see them — `/ardd-plan` carries a note about this; solo mode doesn't need one because `worktree-align.sh` - carries unpushed local commits in. + carries unpushed local commits in. Terminal-state pushes wait for the + status refresh: before `/ardd-plan` or `/ardd-implement` (inline + terminal step, or the coordinator's collaborative report-back sequence) + reaches a push/PR offer carrying terminal state, `/ardd-status` runs on + the feature branch and its commit rides the push — in collaborative + mode, no ArDD skill pushes a feature branch whose STATUS.md predates + the state the push carries (the first-commit draft-PR visibility push + is exempt). There is no custom script for the worktree-creation part itself — a hand-built one was tried and removed (Principle VIII; decision record diff --git a/docs/reference/skills/ardd-implement.md b/docs/reference/skills/ardd-implement.md index ec84937..5f6c60d 100644 --- a/docs/reference/skills/ardd-implement.md +++ b/docs/reference/skills/ardd-implement.md @@ -101,9 +101,12 @@ isolates state; backgrounding frees your session). The constitution's merge keeps the in-flight window short), then runs `worktree-reap.sh` to remove the landed worktree (refusals surfaced verbatim, never forced). -- A delegated subagent never runs `/ardd-status` — that write would be - trapped on the worktree branch. The terminal analyze handoff belongs to - the coordinator or the inline path. +- A delegated subagent never runs `/ardd-status` in any mode — the + coordinator owns the refresh. The trapped-write rationale is + solo-specific (an abandoned worktree would trap the write on the + worktree branch); in collaborative mode the coordinator refreshes on + the feature branch in the primary checkout instead. The terminal + analyze handoff belongs to the coordinator or the inline path. - If delegation ever misbehaves, the blessed fallback is a plain branch, inline: decline the offer, `git checkout -b `, same state model, same merge. @@ -113,7 +116,13 @@ branch. Work moves to a branch (worktree or plain), and after the first commit the skill offers to push and open a draft PR titled with the feature slug(s) — the mode's in-flight visibility channel. Merging goes through the PR; `merge_policy` is never consulted; pushes always require -explicit confirmation. +explicit confirmation. On a delegated report-back the coordinator +fast-forwards the feature branch onto the subagent-reported branch, runs +`/ardd-status` on it (refresh + prune) and commits, and only then offers +the push/PR — in collaborative mode, no ArDD skill pushes a feature +branch whose STATUS.md predates the state the push carries (the inline +path's terminal `/ardd-status` satisfies the same invariant; the +first-commit draft-PR visibility push is exempt). ## Reconcile mode (formerly the `ardd-converge` skill) diff --git a/docs/reference/skills/ardd-plan.md b/docs/reference/skills/ardd-plan.md index 1fc068c..5532231 100644 --- a/docs/reference/skills/ardd-plan.md +++ b/docs/reference/skills/ardd-plan.md @@ -167,7 +167,10 @@ All status mutations are script-performed via `ardd-state.sh` worktree branches from `origin/`, so the plan and tasks files must reach the remote before delegated implementation can see them. Solo mode needs nothing — `worktree-align.sh` carries unpushed local - commits in. + commits in. Any collaborative push carrying the run's terminal state + happens only after the terminal `/ardd-status` refresh is committed on + the feature branch — in collaborative mode, no ArDD skill pushes a + feature branch whose STATUS.md predates the state the push carries. - Re-tasking a plan that already has tasks files asks before generating a new one (a deliberate fork, never an overwrite) and offers to mark superseded non-completed siblings `abandoned`. diff --git a/docs/reference/skills/ardd-status.md b/docs/reference/skills/ardd-status.md index c56f6d6..30e6ed1 100644 --- a/docs/reference/skills/ardd-status.md +++ b/docs/reference/skills/ardd-status.md @@ -28,7 +28,13 @@ next-step prompt. Same "no writes of any kind" shape as `/ardd-plan check without touching `STATUS.md` or being asked anything. **Run only from the primary checkout, never inside a delegated worktree** — -that would trap the `STATUS.md` write on the worktree's branch. +in solo mode that would trap the `STATUS.md` write on the worktree's +branch. In collaborative mode, running on a feature branch in the primary +checkout is the required norm (the refresh rides the branch and lands +with the PR): in collaborative mode, no ArDD skill pushes a feature +branch whose STATUS.md predates the state the push carries. The +prohibition targets delegated worktrees (all modes) plus solo mode's +trapped-write case. ## Reads diff --git a/skills/ardd-implement/SKILL.md b/skills/ardd-implement/SKILL.md index 079b540..8b167f9 100644 --- a/skills/ardd-implement/SKILL.md +++ b/skills/ardd-implement/SKILL.md @@ -366,9 +366,16 @@ entering the normal flow. until it merges or the user deals with it by hand. Note: a delegated subagent must **never** run `/ardd-status` or write - `STATUS.md` — either would trap `STATUS.md` inside the worktree branch. - The terminal analyze handoff belongs to the coordinator (or the inline - path), never the delegated subagent. + `STATUS.md` — the coordinator owns the refresh in every mode. The + trapped-write rationale behind this rule is **solo-mode-specific**: in + solo mode an abandoned worktree would trap `STATUS.md` inside the + worktree branch, so the refresh waits for the coordinator's post-merge + step. In collaborative mode the risk profile is different but the + ownership is the same — the coordinator's `/ardd-status` refresh on the + feature branch in the primary checkout (see the collaborative + report-back sequence below) is the required norm, and the subagent + still never runs it. The terminal analyze handoff belongs to the + coordinator (or the inline path), never the delegated subagent. **Collaborative mode.** Nothing may be committed to the local default branch, ever — branch protection makes it unlandable anyway. If @@ -419,6 +426,23 @@ entering the normal flow. closable or absorbable into the merged one, since its state has already landed via the delegated branch's PR. + **Collaborative report-back sequence.** When a delegated subagent + reports back in collaborative mode, the coordinator runs, in order: + the same side-effect checks as solo mode (`core.bare`, + `core.hooksPath`); then a fast-forward of the feature branch onto the + **subagent-reported** branch (never an in-memory name), so the feature + branch carries the completed work and its state; then — **mandatory, + before any push/PR offer** — `/ardd-status` on the feature branch in + the primary checkout (the full refresh, including `status-prune.sh` + when the constitution sets `status_history_keep`), committing the + refreshed `STATUS.md` to the feature branch. Only then does the run + reach the push/PR offer — the push never happens without the refresh: + in collaborative mode, no ArDD skill pushes a feature branch whose + STATUS.md predates the state the push carries. Mid-run visibility + pushes (the first-commit draft-PR offer above) are exempt — the + invariant binds pushes carrying terminal state (a completed tasks + file, flipped features), not incremental visibility pushes. + 4. **Flip to `in-progress` (if needed), then find the next uncompleted task.** If the file's status is still `ready` (a first-task run on the inline path — the delegated path already flipped it in step 3's @@ -488,9 +512,15 @@ entering the normal flow. **On the inline (non-delegated) path, this is the run's terminal step:** once step 9 commits this final work, **run `/ardd-status` now** to refresh `STATUS.md` — don't rely on the next loop iteration's early-exit (step 2) - to discover completion after the fact. A delegated subagent must **not** + to discover completion after the fact. In collaborative mode this + terminal `/ardd-status` on the feature branch is what satisfies the + invariant — in collaborative mode, no ArDD skill pushes a feature + branch whose STATUS.md predates the state the push carries — so any + push/PR offer must come **after** this refresh (and its commit), never + before. A delegated subagent must **not** run it here (see the note in step 3); its `/ardd-status` runs on the - coordinator after the worktree branch merges. + coordinator after the worktree branch merges (solo) or as the + coordinator's collaborative report-back sequence (step 3). 9. **Commit** the work with a concise message referencing the task ID. diff --git a/skills/ardd-plan/SKILL.md b/skills/ardd-plan/SKILL.md index 31d4c73..cd25d99 100644 --- a/skills/ardd-plan/SKILL.md +++ b/skills/ardd-plan/SKILL.md @@ -152,6 +152,9 @@ drafts or writes a plan. implementation can pick them up. Solo mode needs nothing extra here: `worktree-align.sh` fast-forwards the local default branch's unpushed commits into the delegated worktree, so both are visible without pushing. + Any such push carrying this run's terminal state happens only after + step 15's terminal `/ardd-status` refresh on the feature branch (see + the collaborative-ordering note there). **Re-task mode:** if invoked with `--from `, do step 1, then skip directly to step 11 with `` as the chosen plan. Steps @@ -696,6 +699,17 @@ drafts or writes a plan. feature register, plan approval, and/or the feature-backlog flips in this run leave it stale otherwise. Don't wait for the user to ask. + **Collaborative ordering.** In collaborative mode this terminal + `/ardd-status` (the full refresh, including `status-prune.sh` when the + constitution sets `status_history_keep`) must run on the feature + branch and be committed **before** the run's terminal push/draft-PR + offer — and before any later terminal-state push in the same run + (e.g. the post-approval/tasking re-push) — so a plan-only PR's + STATUS.md matches the plan/tasks state it carries: in collaborative + mode, no ArDD skill pushes a feature branch whose STATUS.md predates + the state the push carries. The existing analyze handoff here is the + mechanism; this note pins its ordering relative to the push. + **Next-step prompt (opt-in).** If `.project/artifacts/constitution.md` frontmatter has `next_step_prompt: true` or `auto` (grep the frontmatter block; absent or `false` = the plain-text behavior above, unchanged), the diff --git a/skills/ardd-status/SKILL.md b/skills/ardd-status/SKILL.md index 27dd59e..2ce7855 100644 --- a/skills/ardd-status/SKILL.md +++ b/skills/ardd-status/SKILL.md @@ -26,11 +26,17 @@ immediately would just report a wall of expected draft-state noise) or anytime the user wants a fresh check outside those flows. **Run only from the primary checkout, never inside a delegated worktree.** -`/ardd-status` is the sole writer of `STATUS.md`; running it inside a -worktree would trap that write on the worktree's branch instead of the -default branch. Delegated `/ardd-implement` subagents are -told explicitly not to invoke it — the terminal analyze handoff belongs to -the coordinator or the inline path. +`/ardd-status` is the sole writer of `STATUS.md`; in solo mode, running it +inside a worktree would trap that write on the worktree's branch instead +of the default branch. Delegated `/ardd-implement` subagents are +told explicitly not to invoke it in any mode — the terminal analyze +handoff belongs to the coordinator or the inline path. In collaborative +mode, running on a **feature branch in the primary checkout** is not an +exception but the required norm: the refresh rides the branch and lands +with the PR, and it is what upholds the invariant that in collaborative +mode, no ArDD skill pushes a feature branch whose STATUS.md predates the +state the push carries. The prohibition's target remains delegated +worktrees (all modes) plus solo mode's trapped-write case. `/ardd-status --view` is a **read-only side door**: it runs steps 1–5 (discovery and the assembled report) unchanged, then prints that report