diff --git a/.claude/agents/quality-mgr.md b/.claude/agents/quality-mgr.md index 842f4778..9c2e6f12 100644 --- a/.claude/agents/quality-mgr.md +++ b/.claude/agents/quality-mgr.md @@ -65,15 +65,18 @@ every reply to the assigner named in the assignment, never to a fixed name. wake-up, not a serialization rule: after handling it, list the queue again and pick up everything else that is open. - A task assignment is informational until `task_ready`; when it is ready, start - it with `atm task start ""`. The start event does not - close the task. + it with `atm task start ""`, then claim its matching + QA bead with `bd update --claim`. The start + event does not close either item. - Deliver each final verdict by closing its own task: `atm task close completed --template --vars - ` (the assignment names the templates). Close tasks in whatever + ` followed by `bd close ` (the + assignment names the templates). Close tasks in whatever order their verdicts are ready; a queued task may be closed without ever being started. A plain `atm send ` leaves the task open and keeps - later assignments queued. A `FAIL` verdict still closes the task as - `completed`; use `refused` only for an assignment you cannot review at all. + later assignments queued. A `FAIL` verdict still closes the task and bead as + `completed`; use `refused` only for an assignment you cannot review at all, + leaving the bead open with `bd update --notes ""`. ## Inputs @@ -142,7 +145,7 @@ TODO-specific rule: ## Workflow -1. Start immediately with `atm task start ""` when `task_ready` arrives, per `docs/team-protocol.md`. +1. Start immediately with `atm task start ""` and `bd update --claim` when `task_ready` arrives, per `docs/team-protocol.md`. 2. Validate that the task is XML rendered from the QA template. Reject any non-XML assignment from the lead immediately. 3. Read the task payload and determine the reviewer set. @@ -199,6 +202,10 @@ TODO-specific rule: 11. Report a final PASS, FAIL, or IN-FLIGHT gate to the lead, including deliverable completion as `X/Y (Z%)`. +When reporting QA findings, preserve their stable finding ids for +`/triaging-findings`; do not create or close Beads for those findings. The lead +creates and wires the resulting fix beads. + ## Default Reviewer Set For implementation QA-1 in this Rust repo: @@ -288,7 +295,7 @@ Reviewer ownership note: All ATM messages must follow the required sequence: 1. task start 2. in-flight status when reviewer launch or collection takes time -3. final QA verdict +3. final QA verdict and `bd close ` For PR updates: - install the templates with diff --git a/.claude/skills/codex-orchestration/SKILL.md b/.claude/skills/codex-orchestration/SKILL.md index 3eb6fc13..53a1d498 100644 --- a/.claude/skills/codex-orchestration/SKILL.md +++ b/.claude/skills/codex-orchestration/SKILL.md @@ -91,21 +91,63 @@ Before starting a sprint: 9. `.claude/agents/rust-best-practices-agent.md` and `.claude/skills/codex-orchestration/rust-best-practices-agent-assignment.json.j2` exist for first-pass boundary optimization review. +10. Every agent pane exports `BEADS_ACTOR` equal to its `ATM_IDENTITY` (the + pane name, not an alias), and bead assignee values use those same names. + +## Beads + +This is the one lifecycle contract for development, fix, and QA work. + +1. **Identity and dispatch.** Before dispatch, the lead creates one bead for + each task, sets its assignee to the recipient's ATM identity, and uses that + bead id everywhere: `bd update --assignee=`; + `atm task assign --task-id `; and template-vars + `task_id`. Release work is a child of its release epic (`bd create --parent + `). +2. **Assignee-owned tandem lifecycle.** First self-check `[ "$BEADS_ACTOR" = + "$ATM_IDENTITY" ]`. If it fails, stop and report to the lead rather than + claiming under the shared git user. Then start with `atm task start + ""` and `bd update --claim`; after successful validation, close + with `atm task close completed --stdin` and `bd close `. A refusal + runs `atm task close refused ""` and leaves the bead open with + a note (`bd update --notes ""`). A push or progress report + closes neither system. +3. **Dependency-driven flow.** Before the first dispatch, the lead creates an + epic chain with `bd dep add `; each QA bead depends on its + dev bead, and merge/release beads depend on the latest QA bead. After a QA + paired close, the lead reads the verdict before running `bd ready`: on + PASS, dispatch what opens; on FAIL, first create fix child beads and QA-2, + make QA-2 depend on every fix bead, and make merge depend on QA-2 (`bd dep + add `). Then `bd ready` must show the fixes, not merge. A + merge bead is dispatchable only when its latest QA bead closed PASS. An + assignee views its own work with `bd ready --assignee "$ATM_IDENTITY"`; the + lead uses unfiltered `bd ready` for dispatch. +4. **QA findings and rejected work.** After `/triaging-findings`, each promoted + finding is a child bead of the epic and its id is the fix task id. For a + failed QA round, every fix bead blocks its follow-up QA bead, which in turn + blocks merge; it never tries to block the already-closed QA bead. `quality-mgr` + reports stable finding ids but does not create beads. If a lead rejects + completed work, the lead reopens its bead or creates a child bead; the lead + never closes a bead on acceptance. ## Sprint Flow -1. the lead assigns development to a developer using `dev-template.xml.j2`. +1. the lead creates and wires the dev bead, then assigns development to its + assignee using `dev-template.xml.j2` with the bead id as `task_id`. Every dev assignment must include the sprint-plan document path as `sprint_doc`, and that sprint document is the authoritative source for the task. Assignment prose may summarize, but it must not replace or weaken the sprint doc. -2. the developer starts, implements, commits, pushes, and reports branch plus SHA. +2. the developer claims the bead in tandem with task start, then implements, + commits, pushes, reports branch plus SHA, and closes both task and bead + after validation. 3. Before QA-1, the developer performs a self-directed Rust best-practices sweep on the integration branch using the same `review_targets` planned for QA-1 and fixes all RBP findings found there. This is a developer cleanup step, not a QA surprise. 4. the lead opens or updates the PR. -5. the lead assigns QA to `quality-mgr` using `qa-template.xml.j2`. +5. after the dev bead closes, the lead runs `bd ready`, then assigns the + newly-ready QA bead to `quality-mgr` using `qa-template.xml.j2`. Every QA assignment must include `sprint_doc`, and `quality-mgr` must treat that sprint document as the authoritative QA scope source. 6. `quality-mgr` launches the full reviewer set on QA-1 (the sprint's first @@ -136,13 +178,20 @@ Before starting a sprint: triage-and-fix path. `rust-best-practices-agent`, `rust-best-practices-agent`, and `rust-service-hardening-agent` remain part of docs-only plan review and phase-ending review regardless of sprint round. -8. If QA passes and CI is green, merge may proceed. -9. After every QA round that reports any finding, at any severity, the lead +8. After a QA close, the lead reads the verdict before `bd ready`: PASS and + green CI permit the now-ready merge work; FAIL must not expose merge. +9. On any QA FAIL, the lead runs `/triaging-findings`, then creates a fix bead + for every promoted finding and a QA-2 bead that depends on every fix. The + merge bead depends on QA-2, so `bd ready` shows only fix work. Repeat this + rule for each failed follow-up QA round; merge becomes eligible only after + the latest QA bead closes PASS. +10. After every QA round that reports any finding, at any severity, the lead runs `/triaging-findings` (where the repository carries that skill) the same way: every finding is recorded, correlated across worktrees, and promoted to the current top layer of the stack. No finding is skipped, deferred, or left without a fix dispatch. -10. After triage completes, the lead routes concrete fixes to a developer of +11. After triage completes, the lead creates and wires finding child beads, + then routes concrete fixes to a developer of the tier the fix needs, using `fix-assignment.xml.j2`: easy fixes go to the fast tier for speed, not back to the sprint's developer by default. Fix assignments must also include `sprint_doc`, and the sprint document remains authoritative if the task @@ -292,4 +341,5 @@ Use the Rust assignment templates from: The sequence for every ATM task assignment — start, work, task close; the receiver never acks a close — is defined once in [`docs/team-protocol.md`](../../../docs/team-protocol.md) (Required Flow). -This skill adds nothing to it and restates none of it. +The Beads lifecycle is defined in this skill's **Beads** section; templates +carry its assignee commands. diff --git a/.claude/skills/codex-orchestration/dev-template.xml.j2 b/.claude/skills/codex-orchestration/dev-template.xml.j2 index 009e33cc..9dec4d30 100644 --- a/.claude/skills/codex-orchestration/dev-template.xml.j2 +++ b/.claude/skills/codex-orchestration/dev-template.xml.j2 @@ -68,13 +68,13 @@ metadata: - Start the task immediately with `atm task start {{ task_id }} ""`, then begin executing it in the same work session. Make reasonable assumptions and do not ask clarifying questions unless a real blocker prevents execution. + Start the task immediately with `atm task start {{ task_id }} ""`, then claim the matching bead with `bd update {{ task_id }} --claim` and begin executing in the same work session. Make reasonable assumptions and do not ask clarifying questions unless a real blocker prevents execution. Read `{{ sprint_doc }}` before coding. Treat it as the authoritative source for scope, deliverables, deletion targets, validation, and acceptance criteria. If this assignment summary and the sprint doc differ, the sprint doc wins and the mismatch must be reported. Before coding, update the worktree from the sprint target branch and include prior fixes already merged to that target. Honor ``: must-follow merge-forward trigger is parent dev push, not QA; merge parent → child before every round. PR-completion trigger is parent PR merge first. Stop if a parallel-safe relation intersects. As soon as the development changes are complete and the branch is pushable, commit and push immediately. Send branch name and commit hash right away to the assigner (the sender of this message) with a plain `atm send {{ lead }} --stdin` — a progress report, not a close; never close the task on a push. This lets PR work and QA preparation begin in parallel. {% if cc and cc != lead %}Copy a one-line summary to `{{ cc }}` with a plain `atm send {{ cc }} --stdin`.{% endif %} After the push report, run the required validation and tests. Do not wait for PR creation before starting validation. - After validation, fix findings and re-run checks until clean. Then close the task with the completion report as the body: `atm task close {{ task_id }} completed --stdin <<'EOF' … EOF` — the deliverable inventory and the exact gate output lines; for deletion or cleanup sprints, the before/after targeted symbol or code-path inventory (net LOC is secondary evidence). Only this close frees your queue: the next assignment stays queued and never starts until `{{ task_id }}` is closed, and a plain `atm send` report does not close it. Use `atm task close {{ task_id }} refused ""` only when the whole assignment cannot be done. {% if cc and cc != lead %}Copy a one-line summary to `{{ cc }}` with a plain `atm send {{ cc }} --stdin`.{% endif %} + After validation, fix findings and re-run checks until clean. Then close the task with the completion report as the body: `atm task close {{ task_id }} completed --stdin <<'EOF' … EOF`, followed by `bd close {{ task_id }}` — the deliverable inventory and the exact gate output lines; for deletion or cleanup sprints, the before/after targeted symbol or code-path inventory (net LOC is secondary evidence). Only this paired close frees the task and opens dependent Beads: a plain `atm send` report closes neither. Use `atm task close {{ task_id }} refused ""` only when the whole assignment cannot be done; leave its bead open and add `bd update {{ task_id }} --notes ""`. {% if cc and cc != lead %}Copy a one-line summary to `{{ cc }}` with a plain `atm send {{ cc }} --stdin`.{% endif %} After the close, read ATM again: the next queued task starts only now. diff --git a/.claude/skills/codex-orchestration/fix-assignment.xml.j2 b/.claude/skills/codex-orchestration/fix-assignment.xml.j2 index 9d38d870..91082121 100644 --- a/.claude/skills/codex-orchestration/fix-assignment.xml.j2 +++ b/.claude/skills/codex-orchestration/fix-assignment.xml.j2 @@ -78,7 +78,7 @@ metadata: - Start the task immediately with `atm task start {{ task_id }} ""`, then begin executing it in the same work session unless blocked. + Start the task immediately with `atm task start {{ task_id }} ""`, then claim the matching bead with `bd update {{ task_id }} --claim` and begin executing in the same work session unless blocked. Read `{{ sprint_doc }}` before editing. Treat it as the authoritative source for sprint scope, retained requirements, deletion targets, validation, and acceptance criteria. If this assignment summary and the sprint doc differ, the sprint doc wins and the mismatch must be reported. Update the assigned worktree from the target branch before editing. Include all earlier-sprint fixes already merged forward to that branch. Honor the `` block above: must-follow merge-forward trigger is parent dev push, not QA; merge parent → child before every round. PR-completion trigger is parent PR merge first. Stop if a parallel-safe relation intersects. @@ -86,7 +86,7 @@ metadata: Before fixing each finding, verify the defect it describes is still actually present at the cited file:line in this worktree's current state. If a finding does not reproduce — already fixed, superseded by other work, or the described code path no longer exists — refuse to perform speculative or invented work to "address" it. Do not edit unrelated code in its name. Note it in your push/validation report as `not-reproducible` with the file:line you checked instead, and skip it. This applies per-finding, not to the whole task — fix every finding that does reproduce as normal. Fix every promoted-branch occurrence in scope. Do not stop at the first location when the triage record marks the finding as repeatable. As soon as the branch is pushable, commit and push immediately. Send branch name and commit hash right away to the assigner (the sender of this message) with a plain `atm send {{ lead }} --stdin` — a progress report, not a close; never close the task on a push. This lets follow-up QA start in parallel. {% if cc and cc != lead %}Copy a one-line summary to `{{ cc }}` with a plain `atm send {{ cc }} --stdin`.{% endif %} - Run the required validation after the push report. While it is FAIL, keep fixing and report progress with plain `atm send`. When it is PASS, close the task with the validation report as the body: `atm task close {{ task_id }} completed --stdin <<'EOF' … EOF` — PASS plus the gate output lines and, per finding, fixed or `not-reproducible` with the file:line checked. Only this close frees your queue: the next assignment stays queued and never starts until `{{ task_id }}` is closed, and a plain `atm send` report does not close it. Use `atm task close {{ task_id }} refused ""` only when the whole assignment cannot be done. {% if cc and cc != lead %}Copy a one-line summary to `{{ cc }}` with a plain `atm send {{ cc }} --stdin`.{% endif %} + Run the required validation after the push report. While it is FAIL, keep fixing and report progress with plain `atm send`. When it is PASS, close the task with the validation report as the body: `atm task close {{ task_id }} completed --stdin <<'EOF' … EOF`, followed by `bd close {{ task_id }}` — PASS plus the gate output lines and, per finding, fixed or `not-reproducible` with the file:line checked. Only this paired close frees the task and opens dependent Beads: a plain `atm send` report closes neither. Use `atm task close {{ task_id }} refused ""` only when the whole assignment cannot be done; leave its bead open and add `bd update {{ task_id }} --notes ""`. {% if cc and cc != lead %}Copy a one-line summary to `{{ cc }}` with a plain `atm send {{ cc }} --stdin`.{% endif %} {% if triage_records and triage_records|trim %} Triage records are attached to this assignment. Use the `/closing-triage` skill to work them to zero before reporting: `{{ branch }}` is a stacked layer no phase structure declares, so its query runs as `python3 .claude/skills/closing-triage/scripts/query_open_findings.py --branch {{ branch }}{% if sprint_id %} --sprint {{ sprint_id }}{% endif %} --phase {{ phase }} --json` from your worktree. The finding ids it returns are the full scope of this assignment; fix every one in this pass. {% endif %} After the close, read ATM again: the next queued task starts only now. diff --git a/.claude/skills/codex-orchestration/qa-template.xml.j2 b/.claude/skills/codex-orchestration/qa-template.xml.j2 index b50dae39..551aac93 100644 --- a/.claude/skills/codex-orchestration/qa-template.xml.j2 +++ b/.claude/skills/codex-orchestration/qa-template.xml.j2 @@ -66,7 +66,7 @@ metadata: - Start the task immediately with `atm task start {{ task_id }} ""`, then begin the QA review in the same work session. + Start the task immediately with `atm task start {{ task_id }} ""`, then claim the matching QA bead with `bd update {{ task_id }} --claim` and begin the QA review in the same work session. Your queue runs in parallel: QA tasks never wait for each other. Right after the task start run `atm task list --json` and treat every open task assigned to quality-mgr as live now — its assignment body is the `description` field — and run each one concurrently with its own background reviewers. Close each task with its own `atm task close completed …` the moment that verdict is ready, in any order; a queued position is ordering, not a wait, and a task can be closed without ever being started. Reject the task immediately if the assignment is not an XML payload rendered from this template. Read `{{ sprint_doc }}` first and treat it as the authoritative source for QA scope. Render structured JSON assignments for `req-qa` and `arch-qa` using the templates in `.claude/skills/codex-orchestration/`. Do not send free-form reviewer prompts. Extract every deliverable, acceptance criterion, deletion requirement, required validation item, and expected artifact directly from `{{ sprint_doc }}`. @@ -78,7 +78,7 @@ metadata: When triage records are present, explicitly state whether each rechecked finding is still open, fixed on the reviewed branch, regressed, or requires a new triage pass because the scope changed. If a PR number is present, check stack and CI state with `gh stack view --json` from a worktree checked out on `{{ branch }}` (if it reports the branch is not part of a stack, run `gh stack checkout ` there first) and `gh pr checks {{ pr_number }} --json name,state,bucket`. Never use `gh pr checks --watch` or parse its text output. Report a PR with no CI run as conflicting or needs-rebase, with the `gh stack view --json` output. Install the daemon-readable templates with `mkdir -p ~/.atm/templates/quality-management-gh && cp .claude/skills/quality-management-gh/*.j2 ~/.atm/templates/quality-management-gh/`. Append the completed QA report to the PR whenever a PR exists: render `FAIL`/`IN-FLIGHT` with `atm compose --template ~/.atm/templates/quality-management-gh/findings-report.md.j2 --vars /qa--vars.json | gh pr comment --body-file -`, or `PASS` with the same command using `~/.atm/templates/quality-management-gh/quality-report.md.j2`. Build vars for this QA run from the selected template's `required_variables` frontmatter; never reuse a previous or sample report's vars. Write the vars file outside the repository working tree (in the session scratchpad or a temp directory); never commit or stage it, and delete it or let it expire after the send. The PR comment remains required. - Deliver the final QA verdict by closing this task with the rendered report as the body: `atm task close {{ task_id }} completed --template ~/.atm/templates/quality-management-gh/findings-report.md.j2 --vars /qa--vars.json` for `FAIL`/`IN-FLIGHT`, or `atm task close {{ task_id }} completed --template ~/.atm/templates/quality-management-gh/quality-report.md.j2 --vars /qa--vars.json` for `PASS`. The close delivers the report to the assigner (the sender of this message) and frees your queue; a plain `atm send {{ lead }}` leaves `{{ task_id }}` open and the next QA task never starts. A `FAIL` verdict still closes the task as `completed` — the QA round is the task, the code is not; use the same outside-repository scratchpad or temp vars file, never commit or stage it, and delete it or let it expire after the send. Include deliverable completion as `X/Y (Z%)`. PASS requires 100% deliverable completion, a PASS verdict from every required reviewer, an active PR for the branch, and no unresolved blocking findings. {% if cc and cc != lead %}Copy a one-line summary to `{{ cc }}` with a plain `atm send {{ cc }} --stdin`.{% endif %} + Deliver the final QA verdict by closing this task with the rendered report as the body: `atm task close {{ task_id }} completed --template ~/.atm/templates/quality-management-gh/findings-report.md.j2 --vars /qa--vars.json` for `FAIL`/`IN-FLIGHT`, or `atm task close {{ task_id }} completed --template ~/.atm/templates/quality-management-gh/quality-report.md.j2 --vars /qa--vars.json` for `PASS`, then run `bd close {{ task_id }}`. The paired close delivers the report and opens dependent Beads; a plain `atm send {{ lead }}` closes neither. A `FAIL` verdict still closes the task as `completed` — the QA round is the task, the code is not; use `refused` only for an assignment that cannot be reviewed, leave its bead open, and add `bd update {{ task_id }} --notes ""`. Use the same outside-repository scratchpad or temp vars file, never commit or stage it, and delete it or let it expire after the send. Include deliverable completion as `X/Y (Z%)`. PASS requires 100% deliverable completion, a PASS verdict from every required reviewer, an active PR for the branch, and no unresolved blocking findings. {% if cc and cc != lead %}Copy a one-line summary to `{{ cc }}` with a plain `atm send {{ cc }} --stdin`.{% endif %} {% if triage_records and triage_records|trim %} For every triage record in `{{ triage_records }}` (or any other `.triage/*/findings/*.ttl` record in scope for this round) that this round's reviewers confirm is fixed on the reviewed branch, update that record's `triage:status` to `"fixed"` and set `triage:closedAt`/`triage:closedBy "quality-mgr"` before sending the final verdict — per the triaging-findings skill's closure rule that quality-mgr, not {{ lead }}, owns finding closure once follow-up QA confirms the fix. Do not close a record that is still open, regressed, or unverified this round. List every record you closed (finding id + file) in the final verdict message so {{ lead }} can reconcile it. {% endif %} diff --git a/.claude/skills/phase-orchestration/SKILL.md b/.claude/skills/phase-orchestration/SKILL.md index 4b0e9289..d7027abd 100644 --- a/.claude/skills/phase-orchestration/SKILL.md +++ b/.claude/skills/phase-orchestration/SKILL.md @@ -36,6 +36,17 @@ Read the phase plan and identify: - parallel waves - merge order within each wave +Translate the dependency graph into Beads before the first dispatch: create an +epic chain with `bd dep add `, assign each bead to the +recipient's ATM identity, and use the bead id as the ATM task id. Each QA bead +depends on its dev bead; merge/release beads depend on QA; promoted QA fixes are +child beads that feed a follow-up QA bead; that QA bead blocks merge. After a +QA close, read its verdict before `bd ready`: PASS may dispatch what opened; +FAIL first creates fix beads, QA-2 depending on every fix, and a merge +dependency on QA-2. A merge bead is dispatchable only after its latest QA bead +closes PASS. The lead's dispatch view is unfiltered `bd ready`; an assignee +uses `bd ready --assignee "$ATM_IDENTITY"`. + ### 2. Execute sprints For each sprint, respecting dependency order: diff --git a/.claude/skills/team-lead/SKILL.md b/.claude/skills/team-lead/SKILL.md index c71ce870..55965558 100644 --- a/.claude/skills/team-lead/SKILL.md +++ b/.claude/skills/team-lead/SKILL.md @@ -182,21 +182,28 @@ work and nudges the agent. A plain send opens no task, so the agent cannot `atm task start` it and nothing re-nudges an agent that stops. - Include task scope, worktree, relevant docs and acceptance criteria. -- The assignee runs `atm task start ""` when `task_ready` - arrives, reports at meaningful milestones, and closes with a commit or PR - reference. +- Before dispatch, create and dependency-wire the bead, assign it to the + recipient's ATM identity, and use its id for `--task-id` and `task_id`. The + assignee runs `atm task start ""` and `bd update + --claim` when `task_ready` arrives, reports at + meaningful milestones, and closes with a commit or PR reference. - **Every task must be closed.** Write the close into the assignment itself: the body ends with the instruction to run - `atm task close completed` with the commit or PR as the report - when the work is done. The orchestration dispatch templates already end - this way; a hand-written assignment must too. An agent's queue releases - the next task only when the current one closes, so an open finished task - blocks everything behind it. -- When work is reported complete, verify the task is closed with - `atm task list --all`. If it is still open, close it yourself: - `atm task close completed ""`. - Do not spend a round trip asking the agent to close it. The assignee is - told the assigner closed the task, so put the real result in the reason. + `atm task close completed` plus `bd close ` with the + commit or PR as the report when the work is done. + The orchestration dispatch templates already end this way; a hand-written + assignment must too. An agent's queue releases the next task only when the + current task and bead close, so an open finished task blocks everything + behind it. +- When work is reported complete, verify the task and bead are closed with + `atm task list --all` and `bd show `. If rejected, reopen the bead + or create a child bead; do not close a bead on the assignee's behalf. +- After every paired close, use unfiltered `bd ready` for the lead's dispatch + view (an assignee uses `bd ready --assignee "$ATM_IDENTITY"`). After a QA + close, read its verdict first: PASS permits dispatch of what opened; FAIL + requires fix child beads plus a QA-2 bead depending on every fix, then a + merge dependency on QA-2, before `bd ready`. Merge is dispatchable only when + its latest QA bead closes PASS; never dispatch a blocked bead. ### Communication Rules diff --git a/.claude/skills/triaging-findings/SKILL.md b/.claude/skills/triaging-findings/SKILL.md index 52e0e181..602ae026 100644 --- a/.claude/skills/triaging-findings/SKILL.md +++ b/.claude/skills/triaging-findings/SKILL.md @@ -258,6 +258,16 @@ The per-finding `.ttl` record is canonical. Aggregation is derived. ### 4. Dispatch branch-scoped fix work to `clint` +For every promoted finding that needs a fix, the lead creates a child bead of +the phase epic before dispatch. Its bead id is the fix task id. After a failed +QA round, also create a QA-2 bead that depends on every fix bead and replace +the merge dependency with QA-2 (`bd dep add ` and `bd dep add + `). Do this before `bd ready`, so it shows fix beads rather +than merge. A merge bead is dispatchable only after its latest QA bead closes +PASS. Dispatch only when a fix bead is ready, assign it to the recipient's ATM +identity, and pass the id as `--task-id` / `task_id`. `quality-mgr` supplies +stable finding ids; it does not create these beads. + For each promoted branch with open work: 1. render `.claude/skills/codex-orchestration/fix-assignment.xml.j2` 2. include all findings promoted to that branch diff --git a/AGENTS.md b/AGENTS.md index d64730e3..d7402fa5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -58,6 +58,16 @@ just test These are complete aggregate gates, not advisory shortcuts. Use `just setup` when the product compatibility preflight needs to be checked or repaired. +## Task–Bead Lifecycle + +For every dev, fix, and QA task, create and dependency-wire a bead before ATM +dispatch; its id is the `--task-id` and template `task_id`. The lead assigns the +bead to the recipient's ATM identity. The assignee starts with `atm task start` +and `bd update --claim`, and completes with `atm task close` and `bd close +`. Refusal leaves the bead open with a note. After each paired close the lead runs `bd +ready` and dispatches only newly unblocked work; rejected completed work is +reopened or replaced by a child bead, never closed by the lead on acceptance. + ## Beads Issue Tracker diff --git a/CLAUDE.md b/CLAUDE.md index 8e844356..5d2b47f2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -67,6 +67,16 @@ Repo-local coordination and review skills: Use `docs/team-protocol.md` as the source of truth for required acknowledgement and completion behavior. +## Task–Bead Lifecycle + +For every dev, fix, and QA task, create and dependency-wire a bead before ATM +dispatch; its id is the `--task-id` and template `task_id`. The lead assigns the +bead to the recipient's ATM identity. The assignee starts with `atm task start` +and `bd update --claim`, and completes with `atm task close` and `bd close +`. Refusal leaves the bead open with a note. After each paired close the lead runs `bd +ready` and dispatches only newly unblocked work; rejected completed work is +reopened or replaced by a child bead, never closed by the lead on acceptance. + ## Beads Issue Tracker diff --git a/docs/plans/orchestration/lint-spx.5-orchestration-beads-lifecycle.md b/docs/plans/orchestration/lint-spx.5-orchestration-beads-lifecycle.md new file mode 100644 index 00000000..c23b84df --- /dev/null +++ b/docs/plans/orchestration/lint-spx.5-orchestration-beads-lifecycle.md @@ -0,0 +1,77 @@ +--- +sprint: lint-spx.5 +bead: lint-spx.5 +epic: lint-spx +status: complete +branch: chore/orchestration-beads-lifecycle +worktree: /Users/randlee/github/sc-lint-worktrees/chore/orchestration-beads-lifecycle +pr_target: chore/codex-orchestration-task-assign +closure_type: contract +--- + +# lint-spx.5 — Beads lifecycle for orchestration task assignment + +Layer 2 of the orchestration stack. Layer 1 (`lint-spx.1`, PR #166) is the +atm-core port with no Beads semantics. This layer adds them. Focus is **dev +task, fix task, and QA task assignment**; nothing else in this first round of +Beads integration. + +## The contract (state it once in SKILL.md, reference it elsewhere) + +1. **Identity.** Every dev, fix, and QA task is a bead created before + dispatch. Bead id == `atm task assign --task-id` == vars `task_id`. Release + work is a child of its release epic (`bd create --parent `). +2. **Tandem lifecycle, performed by the assignee.** + - start: `atm task start ""` and `bd update --claim` + - close: `atm task close completed --stdin` and `bd close ` + - refused: `atm task close refused ""`; the bead stays open + with a note (`bd update --notes`), it is not closed. + - A push or progress message never closes either. + - If the lead rejects closed work, the lead reopens the bead or files a new + child bead; there is no "lead closes the bead" step. +3. **Dependency-driven flow.** The lead plans an epic as a chain of beads + wired with `bd dep add ` before the first dispatch; each dev + bead is followed by its QA bead (`bd dep add `), and + merge/release beads depend on QA beads. Closing a bead is what opens the + next task: after every close the lead runs `bd ready` and immediately + dispatches each newly unblocked bead with `atm task assign`. A blocked bead + is never dispatched. +4. **QA findings.** After `/triaging-findings`, each promoted finding becomes + a child bead of the epic; that id is the fix task id, and the fix bead is + added as a blocker of the QA/merge bead it came from + (`bd dep add `). `quality-mgr` reports stable + finding ids; it does not create beads. + +## Deliverables + +1. `codex-orchestration/SKILL.md`: a "Beads" section with the contract above, + and Sprint Flow steps updated to say where beads are created, wired, + claimed, closed, and where `bd ready` drives the next dispatch. +2. `dev-template.xml.j2` and `fix-assignment.xml.j2`: workflow start step adds + `bd update {{ task_id }} --claim`; close step adds `bd close {{ task_id }}`; + refused path leaves the bead open. `qa-template.xml.j2`: same tandem + steps, so a QA bead that became ready when its dev or fix bead closed is + claimed and closed by `quality-mgr` the same way. +3. `docs/team-protocol.md` Required Flow, `CLAUDE.md` + `AGENTS.md` (mirrored) + contract paragraph, `triaging-findings/SKILL.md` (rule 4), + `quality-mgr.md` (finding-id handoff), `team-lead` / `phase-orchestration` + skills (rule 3): each references the one rule; no contradictory copy. +4. Sample vars use bead ids as `task_id`; installed templates under + `~/.atm/templates/codex-orchestration/` refreshed. + +## Acceptance criteria + +- `git diff chore/codex-orchestration-task-assign..HEAD` contains only the + Beads upgrade; layer 1 files are not otherwise reworked. +- No sentence anywhere says the lead closes beads on acceptance. +- Every template composes with its sample vars; composed dev and fix bodies + show the claim and close commands with the task id substituted. +- `just lint` passes. +- This doc's frontmatter is `status: complete` at closeout, and the assignee + claimed and closed `lint-spx.5` in tandem with the ATM task. + +## This sprint does not close + +- `review-template.xml.j2` and the reviewer-agent JSON assignment templates + (first round of Beads integration is dev, fix, and QA tasks only). +- Any Rust source change; re-dispatching in-flight QA on stack #165. diff --git a/docs/project-plan.md b/docs/project-plan.md index a4dd9e02..13d1f566 100644 --- a/docs/project-plan.md +++ b/docs/project-plan.md @@ -133,6 +133,10 @@ The scheduled sprint plans are: - Beads-backed ATM task-assignment orchestration - `docs/plans/orchestration/lint-spx.1-codex-orchestration-task-assign.md` +- `lint-spx.5` + - Assignee-owned Beads lifecycle for dev, fix, and QA task assignment + - `docs/plans/orchestration/lint-spx.5-orchestration-beads-lifecycle.md` + - `A.1a` - CLI bootstrap and contract definition - includes the A.1a exit-review checkpoint for Workstreams 4-7 diff --git a/docs/team-protocol.md b/docs/team-protocol.md index 25bb0a88..e38f8e16 100644 --- a/docs/team-protocol.md +++ b/docs/team-protocol.md @@ -4,14 +4,20 @@ This protocol is mandatory for all `sc-lint` ATM team communications. ## Required Flow -1. Read an actionable ATM assignment and immediately run `atm task start ""`. +1. Read an actionable ATM assignment and immediately run `atm task start ""`, then claim its matching bead with `bd update --claim`. 2. Execute the requested work. 3. Send a concise progress report after pushing. -4. After validation passes, close the ATM task with `atm task close completed --stdin`. +4. After validation passes, close the ATM task with `atm task close completed --stdin` and the matching bead with `bd close `. 5. No silent processing; report blockers promptly. Every assignment is dispatched as `atm task assign --task-id --template --vars `. Do not hand-render an assignment and send it with `atm send`. +For dev, fix, and QA work, the bead id is the ATM task id. The lead creates and +dependency-wires beads before dispatch, sets `--assignee` to the recipient's ATM +identity, and runs `bd ready` after each paired close to dispatch only newly +unblocked work. A refused ATM task leaves its bead open with a note; +if completed work is rejected, the lead reopens the bead or creates a child bead. + ## Messaging Rules - Use `atm send` for progress, blockers, and non-task information.