diff --git a/.claude/skills/sync-docs/SKILL.md b/.claude/skills/sync-docs/SKILL.md index c2d76ac..80449b6 100644 --- a/.claude/skills/sync-docs/SKILL.md +++ b/.claude/skills/sync-docs/SKILL.md @@ -33,7 +33,7 @@ The skill runs through 5 phases. No user interaction. | Phase | Name | What happens | | ----- | ------------------ | -------------------------------------------------------------------------------------------------------- | | 1 | **Preflight** | Verify the repo (`.claude-plugin/plugin.json` exists, `skills/` is a directory); parse `--check` | -| 2 | **Enumerate** | List every directory under `skills/` (14 today); never include `.claude/skills/*` | +| 2 | **Enumerate** | List every directory under `skills/` (15 today); never include `.claude/skills/*` | | 3 | **Render** | Write per-skill MDX, README block, CLAUDE.md block into `.yoke/sync-docs-tmp/` | | 4 | **Sentinel check** | Verify exactly one `start` and one `end` marker in each of `README.md` and `CLAUDE.md`; start < end | | 5 | **Write or diff** | Write mode → copy tmp tree over live; check mode → diff and exit non-green on drift | @@ -68,8 +68,8 @@ include anything under `.claude/skills/` — `yoke-create`, `yoke-release`, and `yoke-validate` are local-only tools and must not appear in the public catalog. -The shipped catalog today is 14 skills: -`bootstrap, do, gca, gp, grill, grill-docs, handoff, help, issues, +The shipped catalog today is 15 skills: +`bootstrap, do, draft, gca, gp, grill, grill-docs, handoff, help, issues, journal, merge, pr, prd, review`. ## Phase 3 — Render @@ -201,7 +201,7 @@ When the live tree matches the tmp tree byte-for-byte → exit zero. ## Rules - Catalog membership: every directory under `skills/` that contains a - `SKILL.md` (14 today). Never include + `SKILL.md` (15 today). Never include `.claude/skills/*` skills (`yoke-create`, `yoke-release`, `yoke-validate`). - Sentinels are required. Refuse to write when they are missing or unbalanced. Never auto-insert. @@ -228,7 +228,7 @@ When the live tree matches the tmp tree byte-for-byte → exit zero. /sync-docs ``` -→ Writes `site/src/content/docs/skills/.mdx` for all 14 skills, +→ Writes `site/src/content/docs/skills/.mdx` for all 15 skills, regenerates the README and CLAUDE.md catalog blocks. ``` diff --git a/.yoke/ai/32-draft-marking-step/32-draft-marking-step-plan.md b/.yoke/ai/32-draft-marking-step/32-draft-marking-step-plan.md new file mode 100644 index 0000000..cf4c630 --- /dev/null +++ b/.yoke/ai/32-draft-marking-step/32-draft-marking-step-plan.md @@ -0,0 +1,342 @@ +# Draft marking step (#32) — implementation plan + +**Task:** https://github.com/yokeloop/yoke/issues/32 (PRD: `.yoke/ai/draft-marking-step/draft-marking-step-prd.md`) +**Complexity:** medium +**Mode:** sub-agents +**Parallel:** true + +A pure markdown-skill task: no application code, no manifest edits, no version bump. The glossary +(`.yoke/context.md`) and `.yoke/adr/0011-draft-optional-marking-step.md` are already written — do not touch them. +Every authoring task uses the glossary vocabulary verbatim — **Draft**, **Markup**, **Marker**, **Draft PR**, +**Draft execution** — in English, prettier-formatted (printWidth 120, proseWrap preserve). + +## Design decisions + +### DD-1: `/draft` is a separate shipped skill, not a `/do --draft` flag + +**Decision:** New `skills/draft/` skill; `/do` gains a distinct **Draft execution** mode that consumes the Draft PR. +**Rationale:** PRD Implementation Decision #1 + ADR-0011: `do`'s contract is "drive to a ready PR" +(`skills/do/SKILL.md:12-14`); a flag would invert its semantics. Draft mirrors `do`'s architecture +(router → mode references → finish) and reuses `do`'s finish the way `do` reuses gca/gp conventions. +**Alternative:** `/do --draft` mode — inverts `do`'s "ends at PR" contract, easy to forget (ADR-0011). + +### DD-2: `/draft` produces Markup in-session (orchestrator), no new implementer agent + +**Decision:** `/draft` runs `do`'s Plan pipeline (investigate + architect sub-agents, by citation) to write the plan, +then the orchestrator itself writes the Markup (Markers + skeleton) per the plan's tasks. No marking sub-agent. +**Rationale:** `skills/do/agents/task-executor.md:154,173` mandates deleting `TODO/FIXME` — reusing it to _write_ +Markers would erase the very Markup. Marking is a lightweight mechanical projection needing no isolated sub-agent +context. +**Alternative:** a new `marker-writer` agent — adds a component whose context isolation buys nothing for +comment/stub writing, and risks "implementing" instead of "marking." + +### DD-3: One PR, draft → ready, driven through the existing finish + pr mechanics + +**Decision:** `/draft` finishes each touched repo through `finish.md` §3 but passes `--draft` to the pr-skill create +call. `/do` Draft execution finds the PR already open → pr mechanics UPDATE it (draft state preserved, +`skills/pr/SKILL.md:63`) → `/do` then flips it with `gh pr ready `. Never a second PR. +**Rationale:** PRD Implementation Decision #6; `skills/pr/SKILL.md:43,68` already parameterizes `--draft` on create +and leaves draft state unchanged on update. Flipping an existing PR to ready still "ends at PR" (ADR-0006 compat). +**Alternative:** a fresh implementation PR — review comments would detach from the code they anchor to (ADR-0011). + +### DD-4: Router ordering — draft signals match before the sub-agents rung + +**Decision:** In `skills/do/SKILL.md`, the Draft execution rung(s) resolve a PR URL (contains `/pull/`) and a bare +`` whose `.yoke/ai//` holds a draft artifact **before** the existing issue-URL/slug sub-agents rung. +**Rationale:** `skills/do/SKILL.md:44` matches "a single issue URL, a bare ``". A bare slug is ambiguous; the +draft artifact's presence is the discriminator. Wrong order sends Draft PR URLs into sub-agents mode. +**Alternative:** in-body draft detection inside the sub-agents rung — hides the decision; a dedicated first-match +rung is explicit. + +### DD-5: Read draft state ad hoc, do not extend `lib/pr-collect.sh` + +**Decision:** Draft execution reads `gh pr view --json isDraft,number,url` directly; no `IS_DRAFT` field in +`pr-collect.sh`. +**Rationale:** The mode is selected because the input is a draft; a one-off `gh pr view` covers the idempotence +guard. `lib/pr-collect.sh:30-46` is shared by the `pr` skill — leaving it untouched avoids regression risk. +**Alternative:** extending `pr-collect.sh` with `IS_DRAFT` — unnecessary shared-lib change for a single ad-hoc read. + +### DD-6: Draft artifact `-draft.md` records the Draft PR, branch, and repo set + +**Decision:** `/draft` writes `.yoke/ai//-draft.md` holding the Draft PR URL(s), branch(es), +touched-repo set, and a pointer to `-plan.md`. `do`'s router tests for this file; Draft execution reads it. +**Rationale:** PRD Implementation Decision #7 enables `/do ` from a fresh session. A fixed filename keeps the +three touch points (write in mode-draft, detect in do/SKILL.md, read in mode-draft-execution) consistent. +**Alternative:** re-deriving the PR from the branch each time — fragile across sessions and multi-repo. + +### DD-7: Grep gate wording excludes doc mentions of the literal Marker string + +**Decision:** The final gate greps the target project's **source** for `TODO(yoke):`, scoped to exclude `.yoke/` +artifacts and skill prose. +**Rationale:** In this repo `markup-format.md`/`mode-draft*.md`/`docs/draft.md` contain the literal string as +documentation — expected, not a leftover. `grep -rn "TODO(yoke)"` over shipped `skills/`+`lib/` returns nothing +today; the gate must stay collision-free by scoping. +**Alternative:** an unscoped repo-wide grep — would flag the skill's own documentation of the Marker. + +## Tasks + +### Task 1: Write the shared Markup contract `markup-format.md` + +- **Files:** `skills/draft/reference/markup-format.md` (create) +- **Depends on:** none +- **Scope:** M +- **What:** Author the single source of truth for what Markup is, cited by both `/draft` (writes it) and `/do` + Draft execution (consumes/deletes it). +- **How:** Define (1) the **Marker** — one comment in the unified format `TODO(yoke): `, + optionally carrying the plan step reference; (2) the **skeleton** — real new files, signatures, and types whose + bodies are compilable stubs, with per-language examples (`throw new Error('TODO')`, `raise NotImplementedError`, + Go `panic("TODO")`); (3) the invariant "the skeleton must compile / type-check; red tests are acceptable, a broken + build is not"; (4) "Draft does not implement logic — a fully typed scaffold is explicitly out"; (5) the **grep + gate** prefix `TODO(yoke):` and its scoping rule per DD-7. +- **Context:** `.yoke/ai/draft-marking-step/draft-marking-step-prd.md` (Implementation Decisions "Markup = markers + + compilable skeleton", User Stories 3-5, 14); `.yoke/context.md` Draft section (quote Markup/Marker definitions); + `skills/do/agents/task-executor.md:154,173`. +- **Verify:** `grep -n "TODO(yoke):" skills/draft/reference/markup-format.md` shows the literal defined; + `pnpm exec prettier --check skills/draft/reference/markup-format.md` clean. + +### Task 2: Write the marking procedure `mode-draft.md` + +- **Files:** `skills/draft/reference/mode-draft.md` (create) +- **Depends on:** Task 1, Task 6 +- **Scope:** L +- **What:** The full `/draft` procedure for both fresh marking and iteration. +- **How:** Phases: **0 Resolve** — input + flow map (`finish.md` §1) + SLUG/TICKET_ID + worktree entry (`finish.md` + §2). **1 Plan** — reuse `mode-sub-agents.md` Phase 1 by citation (task-investigator → plan-architect → write + `.yoke/ai//-plan.md`); do not re-derive (cf. `mode-team.md:47`). **2 Mark** — the orchestrator writes + Markup in-session per `markup-format.md` (DD-2), walking the plan's tasks: `TODO(yoke):` Markers in existing + files, compilable skeleton for new structure; commit per + `${CLAUDE_PLUGIN_ROOT}/skills/gca/reference/commit-convention.md`. **3 Draft artifact** — write + `.yoke/ai//-draft.md` (DD-6): Draft PR URL(s), branch(es), touched-repo set, plan pointer. **4 + Finish** — `finish.md` §3 per-repo with `--draft` forced on the pr create call, §5 ticket comment, §7 notify + `--skill draft` with the Draft PR URL; one Draft PR per repo (multi-repo per §4). State "Draft never pauses — the + Draft PR is the pause." **Iteration** section: on re-run against an existing Draft (slug with `-draft.md`, + or a Draft PR URL) read the PR review comments (`gh api repos/{owner}/{repo}/pulls/{pr}/comments`), redraw the + Markup in the same branch, push, and reply in each thread + (`gh api --method POST repos/{owner}/{repo}/pulls/{pr}/comments -f body=... -F in_reply_to=`); any number of + rounds. +- **Context:** `skills/do/reference/mode-sub-agents.md:27-104`; `skills/do/reference/finish.md`; + `skills/do/reference/plan-format.md`; `skills/draft/reference/markup-format.md` (Task 1); PRD Solution + User + Stories 1-9, 16-17; `deprecated/fix/SKILL.md:264-273` (thread-reply endpoint prior art). +- **Verify:** prettier clean; the file cites `mode-sub-agents.md`, `finish.md`, `markup-format.md`, and names + `-draft.md`. + +### Task 3: Write the `/draft` orchestrator `SKILL.md` + +- **Files:** `skills/draft/SKILL.md` (create) +- **Depends on:** Task 1, Task 2 +- **Scope:** M +- **What:** The lean model-invoked entry point that routes to `reference/mode-draft.md`. +- **How:** YAML frontmatter: `name: draft`; `description` whose first sentence is a clean one-liner (it becomes the + README/CLAUDE catalog line), followed by quoted trigger phrases ("draft", "mark the code", "mark up the plan", + "draft pr", "разметь код"). Body: same **Input** contract as `do` (empty / chat description / issue URL / bare + slug / `*-task.md`); a 2-way **Router** (fresh marking vs iteration — iteration when the input is a Draft PR URL + or a slug with `-draft.md`); **Principles** (never pauses — the Draft PR is the pause; marks, never + implements; artifacts under `.yoke/`; commits by convention; ends at the Draft PR); pointers to + `reference/mode-draft.md` and `reference/markup-format.md`. Keep to ~`skills/pr/SKILL.md` length. +- **Context:** `skills/do/SKILL.md`; `skills/pr/SKILL.md`; `.claude/skills/sync-docs/SKILL.md:75-112` (how the + description first sentence is consumed); `.yoke/context.md` Draft section. +- **Verify:** `head -1 skills/draft/SKILL.md` is `---`; frontmatter parses as YAML; prettier clean. + +### Task 4: Write `/do`'s Draft execution mode `mode-draft-execution.md` + +- **Files:** `skills/do/reference/mode-draft-execution.md` (create) +- **Depends on:** Task 1, Task 6 +- **Scope:** L +- **What:** The `/do` mode that implements a reviewed Draft PR and flips it to ready. +- **How:** **Resolve** — the Draft PR URL (or slug → `.yoke/ai//-draft.md`); read + `gh pr view --json isDraft,number,headRefName,url` (DD-5); check out the Draft branch (worktree per + `finish.md` §2); read the plan artifact, the Markers in code (grep the `TODO(yoke):` prefix), and the PR review + comments. State the **priority of voices: PR comments > Markers > plan artifact**; a comment that overturns the + architecture (not a local correction) stops the run with AskUserQuestion instead of silently rewriting the plan. + **Implement** — each Marker is a checklist item: build a task (What/How/Files/Verify) from the Marker + plan step + + overriding comments and dispatch `agents/task-executor.md` verbatim, deleting each Marker together with its + implementation; statuses and review loop per `status-protocol.md`. Multi-repo: pick up every Draft PR from the + draft artifact, finish each per `finish.md` §4. **Reply** — in every inline comment thread describe what was done + - commit (`gh api repos/{owner}/{repo}/pulls/{pr}/comments` list, then `--method POST ... -F in_reply_to=`); + thread resolution stays the user's. **Grep gate** (per `markup-format.md`, DD-7) — `TODO(yoke):` must return + nothing in the implemented source before finishing; a leftover Marker blocks the ready flip. **Finish** — validate + - format per `mode-sub-agents.md` Phase 4, report per Phase 6 (`report-format.md`), then `finish.md` §3 (the pr + mechanics UPDATE the existing Draft PR — never a second PR), `gh pr ready ` (ADR-0006 compat: still ends + at PR), ticket comment §5, notify §7. +- **Context:** `skills/do/reference/mode-sub-agents.md:138-255`; `skills/do/reference/finish.md:49-79,116-131`; + `skills/do/reference/status-protocol.md`; `skills/do/reference/report-format.md`; + `skills/do/agents/task-executor.md:1-8,150-173`; `skills/draft/reference/markup-format.md` (Task 1); PRD User + Stories 10-15; `deprecated/fix/SKILL.md:264-273`. +- **Verify:** prettier clean; the file cites `task-executor.md`, `finish.md`, `markup-format.md`; contains + `gh pr ready` and the `in_reply_to` reply call. + +### Task 5: Wire the Draft execution rung into `do/SKILL.md` + +- **Files:** `skills/do/SKILL.md:20-64` (edit) +- **Depends on:** Task 4 +- **Scope:** M +- **What:** Add the input shape, router rung(s), and Modes-table row so drafts route to + `reference/mode-draft-execution.md`. +- **How:** In **Input** add a bullet: a Draft PR URL, or a bare `` whose `.yoke/ai//` records a Draft + (draft execution). In **Router** add, ahead of the current issue-URL/slug rung (DD-4): `$ARGUMENTS` is a GitHub + PR URL (contains `/pull/`, not `/issues/`) → Draft execution → read and follow + `reference/mode-draft-execution.md`; and: `$ARGUMENTS` is a bare `` and `.yoke/ai//-draft.md` + exists → Draft execution. Keep first-match-wins; the `-plan.md` rung stays first among path forms. In **Modes** + table add a **Draft execution** row: "Draft PR URL / drafted `` → implement the Markup (comments > markers > + plan), reply in threads, flip the PR to ready." +- **Context:** `skills/do/SKILL.md:20-64`; `.yoke/context.md` do modes ("Draft execution" label); Task 4 file name. +- **Verify:** `grep -n "Draft execution" skills/do/SKILL.md` and `grep -n "mode-draft-execution" skills/do/SKILL.md` + both present; prettier clean. + +### Task 6: Add the draft-aware note to `finish.md` §3 + +- **Files:** `skills/do/reference/finish.md:49-79` (edit) +- **Depends on:** none +- **Scope:** S +- **What:** Teach the `pr` finish policy the two draft variants without disturbing the common path. +- **How:** Under the §3 `pr` bullet add a compact paragraph: for a `/draft` run, pass `--draft` to the pr-skill + create call (the PR opens as a GitHub Draft PR); for a `/do` Draft execution the PR already exists — the pr + mechanics UPDATE it (draft state preserved) and the run then flips it with `gh pr ready ` — never create + a second PR. Note ADR-0006 compat explicitly: flipping to ready still ends the run at the PR. +- **Context:** `skills/do/reference/finish.md:49-79`; `skills/pr/SKILL.md:43,63,68`; ADR-0011. +- **Verify:** `grep -n "gh pr ready" skills/do/reference/finish.md` and `grep -n -- "--draft"` both present; + prettier clean. + +### Task 7: Write `docs/draft.md` + +- **Files:** `docs/draft.md` (create) +- **Depends on:** Task 2, Task 3, Task 4 +- **Scope:** M +- **What:** The long-form doc, table-styled like `docs/do.md`/`docs/pr.md`, carrying the `**Output:**` line + sync-docs reads. +- **How:** Sections: intro (the optional marking step between grill and do); **Input** (same contract as `/do`); + **Flow** (fresh: Plan → Mark → Draft PR; iteration: re-read comments → re-mark → reply); the draft→ready + lifecycle across `/draft` and `/do`; an `**Output:**` line — Draft PR link(s) + `.yoke/ai//-draft.md` + \+ plan artifact; **Connections** (`/grill → /draft → PR review → /do → ready PR`). Mirror `docs/do.md` headings + and tables. +- **Context:** `docs/do.md`; `docs/pr.md`; PRD Solution; Tasks 2-4 outputs. +- **Verify:** `grep -n "^\*\*Output:\*\*" docs/draft.md` present; prettier clean. + +### Task 8: Add the Draft execution row to `docs/do.md` + +- **Files:** `docs/do.md` (edit) +- **Depends on:** Task 5 +- **Scope:** S +- **What:** Document the new mode in `do`'s long-form doc. +- **How:** Add a **Draft execution** row to the Modes table matching the SKILL.md wording; add a line in + **Connections** noting `/draft` feeds `/do` a reviewed Draft PR that `/do` implements and flips to ready. +- **Context:** `docs/do.md` Modes + Connections sections; Task 5 wording. +- **Verify:** `grep -n "Draft execution" docs/do.md` present; prettier clean. + +### Task 9: Add draft rows to `docs/notify.md` + +- **Files:** `docs/notify.md` (edit) +- **Depends on:** Task 3 +- **Scope:** S +- **What:** Record the `/draft` notification point in the trigger map. +- **How:** Add a row `draft | Finish | STAGE_COMPLETE | : Draft PR ready — Draft PR URL as payload` to the + map table; note that a `/do` Draft execution reuses the existing `do | Finish | STAGE_COMPLETE` row when it flips + the PR to ready, and a `/draft` iteration re-fires the draft STAGE_COMPLETE after pushing the redrawn Markup. +- **Context:** `docs/notify.md` map table; `finish.md` §7; Task 2 notify call. +- **Verify:** `grep -n "| draft" docs/notify.md` present; prettier clean. + +### Task 10: Add `/draft` to `help/SKILL.md` + +- **Files:** `skills/help/SKILL.md` (edit) +- **Depends on:** Task 3 +- **Scope:** M +- **What:** List `/draft` in the help catalog and the Full cycle, as an optional step (no restructuring of + grill → do → PR). +- **How:** Add a `### /draft` section (Input/Output/example, style of the neighboring `/do` block) in flow order + between grill and do. In **Full cycle** add one optional line: + `/yoke:draft # optional: mark the code, open a Draft PR to review before implementing`, + positioned between grill and do, flagged optional. Do not alter the canonical grill → do → PR wording. +- **Context:** `skills/help/SKILL.md` (skill list + Full cycle); PRD Out of Scope (draft stays optional); + `.yoke/context.md` Flow. +- **Verify:** `grep -n "draft" skills/help/SKILL.md` shows the new section + Full cycle line; prettier clean. + +### Task 11: README mermaid + prose (non-sentinel) + +- **Files:** `README.md` (edit — mermaid diagram + "How to use" prose only) +- **Depends on:** Task 3 +- **Scope:** S +- **What:** Show the optional Draft step in the diagram and prose without touching the sentinel catalog table. +- **How:** In the mermaid add an optional `draft` node between `grill` and `do` on a dotted link (match the + existing `-.->` syntax; keep the default `grill → do → pr → merge` path intact). In "How to use" add one + sentence: `/yoke:draft` optionally projects the plan onto the code as a Draft PR to review before `/do` + implements it. Do not edit anything between `` and ``. +- **Context:** `README.md` head; commit b47bbd3 (mermaid dotted-link syntax); PRD Solution. +- **Verify:** dotted-link syntax matches existing lines; sentinel block unchanged; prettier clean. + +### Task 12: CLAUDE.md prose (non-sentinel) + +- **Files:** `CLAUDE.md` (edit — "Implemented skills" prose only) +- **Depends on:** Task 3 +- **Scope:** S +- **What:** Mention the optional `/draft` marking step in the "Implemented skills" prose paragraph. +- **How:** Extend the `/do`/`/merge` summary paragraph with one or two sentences: `/draft` is the optional marking + step between grill and do — it projects the plan onto the code as Markup and opens a Draft PR for remote review; + `/do` later implements the reviewed draft and flips it to ready. Do not edit the sentinel bullet list. +- **Context:** `CLAUDE.md` Implemented skills section; `.yoke/context.md` Draft + Flow. +- **Verify:** `grep -n "/draft" CLAUDE.md` shows the prose mention; sentinel block unchanged; prettier clean. + +### Task 13: Regenerate the catalog (sync-docs counts + run sync) + +- **Files:** `.claude/skills/sync-docs/SKILL.md` (edit); regenerate `README.md` sentinel table, `CLAUDE.md` + sentinel bullets, `site/src/content/docs/skills/draft.mdx` +- **Depends on:** Task 3, Task 7, Task 11, Task 12 +- **Scope:** M +- **What:** Update sync-docs' descriptive counts/list, then regenerate the catalog so `/draft` appears. +- **How:** In `.claude/skills/sync-docs/SKILL.md` bump the skill count (14 → 15) where stated and add `draft` to + the enumerated list (alphabetical). Then perform the sync-docs regeneration per its SKILL.md (Phase 3/5): render + `site/src/content/docs/skills/draft.mdx`, rewrite the sentinel blocks in `README.md` and `CLAUDE.md` — sentinel + bytes only, preserving Task 11/12 prose. Prettier-write the changed files. +- **Context:** `.claude/skills/sync-docs/SKILL.md` + `.claude/skills/sync-docs/reference/sync-spec.md`; Task 3 + description text; Task 7 `**Output:**` line. +- **Verify:** README sentinel table has a `draft` row; CLAUDE.md sentinel list has a `/draft` bullet; + `site/src/content/docs/skills/draft.mdx` exists; prose outside sentinels intact; `pnpm run format:check` clean. + +### Task 14: Validation + +- **Files:** — +- **Depends on:** all +- **Scope:** M +- **What:** Run every structural gate the PRD Testing Decisions name. +- **How:** `pnpm run format` then `pnpm run format:check`; JSON manifest sanity + (`python3 -c "import json; json.load(open('.claude-plugin/plugin.json')); json.load(open('.claude-plugin/marketplace.json')); print('OK')"`); + frontmatter check `head -1 skills/*/SKILL.md` (every line `---`); yoke-validate conventions pass over + `skills/draft/SKILL.md` and `skills/do/SKILL.md` (Strunk prose + plugin-dev structure); sync-docs drift check; + DD-7 sanity: `grep -rn "TODO(yoke)" skills/ lib/` returns only intentional documentation occurrences under + `skills/draft/reference/` and `skills/do/reference/mode-draft-execution.md`. +- **Context:** PRD Testing Decisions; repo `CLAUDE.md` Validation section. +- **Verify:** `pnpm run format:check` && manifest OK && no sync drift — all green. + +## Execution + +- **Mode:** sub-agents +- **Parallel:** true +- **Reasoning:** 14 tasks with clear parallel groups in a single codebase; cross-referential skill texts benefit + from the per-task review loop. +- **Order:** + Group 1 (parallel): Task 1, Task 6 + ─── barrier ─── + Group 2 (parallel): Task 2, Task 4 + ─── barrier ─── + Group 3 (parallel): Task 3, Task 5 + ─── barrier ─── + Group 4 (parallel): Task 7, Task 8, Task 9, Task 10, Task 11, Task 12 + ─── barrier ─── + Group 5 (sequential): Task 13 + ─── barrier ─── + Group 6 (sequential): Task 14 + +## Verification + +- grill → draft produces a Draft PR containing only Markers + compilable stubs (no implemented logic). +- Comment on the Draft PR → `/draft` re-run updates Markup and replies in threads. +- `/do ` implements, replies in threads, leaves zero Markers (grep gate), flips the same PR to ready. +- A conflicting comment beats a Marker; an architecture-overturning comment stops with a question. +- Structural gates: `pnpm run format:check`, manifest JSON parse, SKILL.md frontmatter, catalog sync, no stray + `TODO(yoke)` outside intentional docs. + +## Materials + +- PRD: `.yoke/ai/draft-marking-step/draft-marking-step-prd.md` (issue #32) +- ADR: `.yoke/adr/0011-draft-optional-marking-step.md` +- Glossary: `.yoke/context.md` (Draft, Flow, do modes) +- Video origin: https://www.youtube.com/watch?v=Aie0nYktsNA diff --git a/.yoke/ai/32-draft-marking-step/32-draft-marking-step-report.md b/.yoke/ai/32-draft-marking-step/32-draft-marking-step-report.md new file mode 100644 index 0000000..2a29e31 --- /dev/null +++ b/.yoke/ai/32-draft-marking-step/32-draft-marking-step-report.md @@ -0,0 +1,93 @@ +# Report: 32-draft-marking-step + +**Plan:** `.yoke/ai/32-draft-marking-step/32-draft-marking-step-plan.md` +**Mode:** sub-agents +**Status:** ✅ complete + +## Tasks + +| # | Task | Status | Commit | Concerns | +| --- | ---------------------------------------------------- | ------- | --------- | -------- | +| 1 | Markup contract `markup-format.md` | ✅ DONE | `4d22d1f` | — | +| 6 | Draft variants in `finish.md` §3 | ✅ DONE | `c5c131a` | — | +| 2 | Marking procedure `mode-draft.md` | ✅ DONE | `09f3e76` | — | +| 4 | `/do` mode `mode-draft-execution.md` | ✅ DONE | `bb50def` | — | +| 3 | `/draft` entry point `SKILL.md` | ✅ DONE | `2e73b0d` | — | +| 5 | Draft execution rung in `do/SKILL.md` | ✅ DONE | `d44dd98` | — | +| 7 | Long-form `docs/draft.md` | ✅ DONE | `020f2fb` | — | +| 8 | Draft execution row in `docs/do.md` | ✅ DONE | `a363640` | — | +| 9 | Draft rows in `docs/notify.md` | ✅ DONE | `9eb1d93` | — | +| 10 | `/draft` in `help/SKILL.md` | ✅ DONE | `b348548` | — | +| 11 | README mermaid + prose | ✅ DONE | `721e5a6` | — | +| 12 | CLAUDE.md prose | ✅ DONE | `08576a3` | — | +| 13 | Catalog regeneration (sync-docs counts + MDX/blocks) | ✅ DONE | `8631ecd` | — | +| 14 | Validation | ✅ DONE | `589afe7` | — | + +Every task passed the task-reviewer loop; review findings (all Minor/Important) were fixed in +`2171592`, `1aae3f6`, `df8200c`, and `589afe7`. + +## Post-implementation + +| Step | Status | Commit | +| ------------- | ----------------------------------- | --------- | +| Validate | ✅ pass | — | +| Documentation | ✅ done (in-plan tasks 7-13) | see above | +| Format | ✅ pass (prettier clean, hook + CI) | — | + +## Validation + +- `prettier --check "**/*.{md,json}"` ✅ +- JSON manifests (`plugin.json`, `marketplace.json`) parse ✅ +- `head -1 skills/*/SKILL.md` — every file starts with `---` ✅ +- yoke-validate lenses (Strunk + plugin-dev) over draft/do/help SKILL.md ✅ (2 LOW findings fixed in `589afe7`, 2 INFO accepted) +- MDX `
` blocks byte-match their SKILL.md sources (do, help, draft) ✅ +- `TODO(yoke)` grep — only intentional documentation occurrences ✅ + +## Changes summary + +| File | Action | Description | +| ------------------------------------------- | -------- | -------------------------------------------------------- | +| skills/draft/SKILL.md | created | `/draft` entry point: input, router, principles | +| skills/draft/reference/mode-draft.md | created | Marking procedure: Plan → Mark → Draft PR + Iteration | +| skills/draft/reference/markup-format.md | created | Markup contract: Marker, skeleton, build invariant, gate | +| skills/do/reference/mode-draft-execution.md | created | Draft execution: voices, checklist, replies, ready flip | +| skills/do/SKILL.md | modified | Input shape, router rung 2, Modes row | +| skills/do/reference/finish.md | modified | §3 Draft variants: `--draft` create / `gh pr ready` flip | +| docs/draft.md | created | Long-form doc with `**Output:**` line | +| docs/do.md | modified | Draft execution row + Connections line | +| docs/notify.md | modified | draft STAGE_COMPLETE row + note | +| skills/help/SKILL.md | modified | `/draft` section + Full cycle optional line | +| README.md | modified | Mermaid draft node, prose, catalog row (sentinel) | +| CLAUDE.md | modified | `/draft` prose + catalog bullet (sentinel) | +| .claude/skills/sync-docs/SKILL.md | modified | Catalog count 14 → 15, list + draft | +| site/src/content/docs/skills/draft.mdx | created | Generated catalog page | +| site/src/content/docs/skills/do.mdx | modified | Regenerated (input bullet + details) | +| site/src/content/docs/skills/help.mdx | modified | Regenerated (details) | + +## Commits + +- `c47d81d` docs: implementation plan +- `c5c131a` feat: finish contract Draft variants +- `4d22d1f` feat: markup format contract +- `2171592` refactor: review polish (quote style, phrasing) +- `09f3e76` feat: /draft marking procedure +- `bb50def` feat: do draft-execution mode +- `1aae3f6` fix: fill all task-executor template fields +- `d44dd98` feat: route drafts to draft execution +- `2e73b0d` feat: /draft skill entry point +- `9eb1d93` docs: draft notification points +- `08576a3` docs: CLAUDE.md draft mention +- `020f2fb` docs: long-form draft doc +- `b348548` docs: /draft in help +- `a363640` docs: draft execution in do doc +- `721e5a6` docs: README flow +- `df8200c` refactor: review polish (payload wording, drafted slug) +- `6aaf52c` chore: sync-docs count 15 +- `8631ecd` docs: regenerate skill catalog +- `589afe7` fix: ADR citation + post-run actor + +## Finish + +| repo | branch | PR URL / published version | +| ------------- | -------------------------------- | ---------------------------------------- | +| yokeloop/yoke | `worktree-32-draft-marking-step` | https://github.com/yokeloop/yoke/pull/33 | diff --git a/CLAUDE.md b/CLAUDE.md index 6e10846..d53f985 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -72,10 +72,13 @@ Skills write their artifacts under `.yoke/` in the target project: `/do` is the universal execution tool and now finishes at the PR. It auto-detects mode — no args → inline; an issue URL → sub-agents (plan, pausing only on a cold start); a PRD with sub-issues → team of parallel agents — then drives the run to a ready pull request (worktree, per-task commits, push, PR, ticket comment, notify) and stops. It never merges, except an explicit up-front "straight to main". `/merge` is the user-triggered finisher: once the user approves the PR on GitHub, it runs the post-PR tail per `.yoke/flow.md` (merge, cascade, deploy/release, ticket transition, worktree cleanup). `/task` and `/plan` are deprecated and have moved to `deprecated/`. +`/draft` is the optional marking step between grill and do: a do-shaped run that projects the agreed plan onto the code as Markup (`TODO(yoke):` Markers plus a compilable skeleton) and opens a GitHub Draft PR for remote review, instead of implementing. `/do ` (or the drafted ``) later implements the reviewed Draft per comments > markers > plan and flips the same PR to ready. + - `/bootstrap` — Prepares a project for the yoke flow — stack detection, scaffolding the `.yoke/` layout, and generation of CLAUDE.md, `.yoke/yoke-context.md`, and `.yoke/flow.md`. - `/do` — Executes a task per plan. +- `/draft` — Projects the agreed plan onto the code as Markup — TODO markers plus a compilable skeleton — and opens a Draft PR for review, instead of implementing. - `/gca` — Git staging and commit with smart file grouping. - `/gp` — Git push with checks and report. - `/grill` — Interviews the user one interactive question at a time about a plan or design, walking each branch of the decision tree to a shared understanding; every question offers a recommended answer. diff --git a/README.md b/README.md index c99e8fc..26f1b63 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ flowchart TD bootstrap["/yoke:bootstrap — detect stack, write .yoke/flow.md + context (once)"] grill["/yoke:grill or /yoke:grill-docs — discuss the plan"] + draft["/yoke:draft — mark plan onto code, open Draft PR"] do["/yoke:do — plan, execute, open the PR"] pr(["PR on GitHub — you review, comment, approve"]) merge["/yoke:merge — merge, cascade, deploy, transition, clean up"] @@ -11,6 +12,7 @@ flowchart TD bootstrap --> grill --> do --> pr -->|approved| merge bootstrap -.->|flow.md + context| do bootstrap -.->|flow.md| merge + grill -.->|optional: mark + Draft PR| draft -.-> do ``` A marketplace of skills and commands for Claude Code, inspired by: @@ -43,28 +45,29 @@ Run `/yoke:bootstrap` once to prepare the project — it detects the stack and w /yoke:merge # run the post-PR tail from flow.md: merge, cascade, deploy, clean up ``` -`/yoke:do` drives every run to a ready pull request and stops there — the merge decision stays yours, made on GitHub. `/yoke:grill-docs` is `/yoke:grill` plus a maintained glossary and ADRs. For larger, trackable work, spec it first with `/yoke:prd` + `/yoke:issues`, then hand the epic or sub-task URL to `/yoke:do`. See **Full cycle** below for the complete pipeline. +`/yoke:do` drives every run to a ready pull request and stops there — the merge decision stays yours, made on GitHub. `/yoke:draft` optionally projects the agreed plan onto the code as Markup and opens a Draft PR to review and comment before `/do` implements it. `/yoke:grill-docs` is `/yoke:grill` plus a maintained glossary and ADRs. For larger, trackable work, spec it first with `/yoke:prd` + `/yoke:issues`, then hand the epic or sub-task URL to `/yoke:do`. See **Full cycle** below for the complete pipeline. ## Skills -| Command | What it does | Output | -| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -| `/yoke:bootstrap` | Prepares a project for the yoke flow — stack detection, scaffolding the `.yoke/` layout, and generation of CLAUDE.md, `.yoke/yoke-context.md`, and `.yoke/flow.md`. | — | -| `/yoke:do` | Executes a task per plan. | ready PR link(s), report at `.yoke/ai//-report.md`, ticket comment, STAGE_COMPLETE notify | -| `/yoke:gca` | Git staging and commit with smart file grouping. | — | -| `/yoke:gp` | Git push with checks and report. | — | -| `/yoke:grill` | Interviews the user one interactive question at a time about a plan or design, walking each branch of the decision tree to a shared understanding; every question offers a recommended answer. | — | -| `/yoke:grill-docs` | Docs-aware grilling: interrogates the user's plan one question at a time AND maintains the domain glossary (.yoke/context.md) and architecture decision records (.yoke/adr/) inline as decisions crystallise. | — | -| `/yoke:handoff` | Saves the live state of the current conversation to `.yoke/handoff/` so a fresh session resumes where this one stopped, referencing existing artifacts instead of duplicating them. | — | -| `/yoke:help` | Explains how to use yoke and lists the available skills; also greets new users. | — | -| `/yoke:issues` | Breaks a plan, spec, or PRD into independently-grabbable GitHub issues using vertical slices (tracer bullets), publishes them in dependency order, and saves a local index in .yoke/ai. | — | -| `/yoke:journal` | Appends a concise, newest-first entry to `.yoke/journal.md` summarizing the session's real work and linking the relevant `.yoke/ai//` artifacts — the first layer of yoke's connected memory. | — | -| `/yoke:merge` | The user-triggered finisher that executes the post-PR tail per `.yoke/flow.md`: merges the task's PR(s), runs cascade merges, runs deploy/release commands, moves the ticket to its target state, cleans up worktrees, and returns to the default branch. | merged PR(s), cascade merges, deploy/release runs, ticket transition, cleaned worktrees | -| `/yoke:pr` | Creates or updates a GitHub Pull Request. | — | -| `/yoke:prd` | Turns the current conversation and codebase understanding into a PRD, publishes it as a GitHub issue, and saves a local copy in .yoke/ai. | — | -| `/yoke:review` | Finds problems in code, fixes them and produces a report. | — | +| Command | What it does | Output | +| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `/yoke:bootstrap` | Prepares a project for the yoke flow — stack detection, scaffolding the `.yoke/` layout, and generation of CLAUDE.md, `.yoke/yoke-context.md`, and `.yoke/flow.md`. | — | +| `/yoke:do` | Executes a task per plan. | ready PR link(s), report at `.yoke/ai//-report.md`, ticket comment, STAGE_COMPLETE notify | +| `/yoke:draft` | Projects the agreed plan onto the code as Markup — TODO markers plus a compilable skeleton — and opens a Draft PR for review, instead of implementing. | Draft PR link(s), Draft artifact at `.yoke/ai//-draft.md`, plan at `.yoke/ai//-plan.md`, ticket comment, STAGE_COMPLETE notify | +| `/yoke:gca` | Git staging and commit with smart file grouping. | — | +| `/yoke:gp` | Git push with checks and report. | — | +| `/yoke:grill` | Interviews the user one interactive question at a time about a plan or design, walking each branch of the decision tree to a shared understanding; every question offers a recommended answer. | — | +| `/yoke:grill-docs` | Docs-aware grilling: interrogates the user's plan one question at a time AND maintains the domain glossary (.yoke/context.md) and architecture decision records (.yoke/adr/) inline as decisions crystallise. | — | +| `/yoke:handoff` | Saves the live state of the current conversation to `.yoke/handoff/` so a fresh session resumes where this one stopped, referencing existing artifacts instead of duplicating them. | — | +| `/yoke:help` | Explains how to use yoke and lists the available skills; also greets new users. | — | +| `/yoke:issues` | Breaks a plan, spec, or PRD into independently-grabbable GitHub issues using vertical slices (tracer bullets), publishes them in dependency order, and saves a local index in .yoke/ai. | — | +| `/yoke:journal` | Appends a concise, newest-first entry to `.yoke/journal.md` summarizing the session's real work and linking the relevant `.yoke/ai//` artifacts — the first layer of yoke's connected memory. | — | +| `/yoke:merge` | The user-triggered finisher that executes the post-PR tail per `.yoke/flow.md`: merges the task's PR(s), runs cascade merges, runs deploy/release commands, moves the ticket to its target state, cleans up worktrees, and returns to the default branch. | merged PR(s), cascade merges, deploy/release runs, ticket transition, cleaned worktrees | +| `/yoke:pr` | Creates or updates a GitHub Pull Request. | — | +| `/yoke:prd` | Turns the current conversation and codebase understanding into a PRD, publishes it as a GitHub issue, and saves a local copy in .yoke/ai. | — | +| `/yoke:review` | Finds problems in code, fixes them and produces a report. | — | diff --git a/docs/do.md b/docs/do.md index b8f9554..f885106 100644 --- a/docs/do.md +++ b/docs/do.md @@ -12,6 +12,7 @@ the former `/task` and `/plan` skills (now in `deprecated/`). - nothing / a plain task description → **inline** - a single issue URL, a ``, or a `*-task.md` path → **sub-agents** +- a Draft PR URL, or a `` whose draft artifacts exist → **draft execution** - a PRD issue that has GitHub sub-issues → **team** - an existing `*-plan.md` path → **sub-agents** (back-compat; executes it directly) @@ -26,11 +27,12 @@ the former `/task` and `/plan` skills (now in `deprecated/`). `/do` reads its mode from the **input shape**, then reads the matching `reference/mode-*.md` body: -| Mode | When | Behavior | -| -------------- | ----------------------------------- | --------------------------------------------------------------------------------------------------------------- | -| **inline** | empty / plain chat description | Brief plan in chat, execute in-session, no pause, no plan file; still finishes at a PR. | -| **sub-agents** | a single issue / slug / task / plan | Write `.yoke/ai//-plan.md`, pause on cold start only, then run the sub-agent pipeline. | -| **team** | a PRD ticket with sub-issues | Write the plan, pause on cold start, then dispatch the sub-agents pipeline per sub-issue (TeamCreate deferred). | +| Mode | When | Behavior | +| ------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | +| **inline** | empty / plain chat description | Brief plan in chat, execute in-session, no pause, no plan file; still finishes at a PR. | +| **sub-agents** | a single issue / slug / task / plan | Write `.yoke/ai//-plan.md`, pause on cold start only, then run the sub-agent pipeline. | +| **draft execution** | Draft PR URL / drafted `` | Implement the Markup per the review (comments > markers > plan), reply in the threads, flip the PR to ready, then finish. | +| **team** | a PRD ticket with sub-issues | Write the plan, pause on cold start, then dispatch the sub-agents pipeline per sub-issue (TeamCreate deferred). | The cold-start confirmation pause in sub-agents/team modes catches a wrong mode guess, so auto-detection never triggers an unreviewed costly run. @@ -105,3 +107,6 @@ create/update, and notify into its Finish, so it needs no separate `/gp` or `/pr user approves on GitHub, `/yoke:merge` runs the post-PR tail (merge, cascade, deploy, transition, cleanup). `/review` optionally audits the diff before the PR. Upstream, `/grill`, `/grill-docs`, `/prd`, and `/issues` formalise _what_ to build before `/do`. + +`/draft` feeds `/do` a reviewed Draft PR — `/do` implements it and flips it to ready (never a +second PR). diff --git a/docs/draft.md b/docs/draft.md new file mode 100644 index 0000000..0a1d2c6 --- /dev/null +++ b/docs/draft.md @@ -0,0 +1,89 @@ +# Skill /draft + +The optional marking step between grill and do (ADR-0011). A do-shaped run — the same +inputs and the same finish machinery as `/do` — that marks instead of implementing: it +projects the agreed plan onto the code as Markup (`TODO(yoke):` Markers plus a +compilable skeleton) and opens a GitHub Draft PR for remote review. `/draft` never +pauses — the Draft PR is the pause. With it the flow becomes +**grill → draft → PR review → do**; grill → do stays the default path. + +## Input + +`$ARGUMENTS` — the same contract as `/do`, plus the iteration shapes: + +| Input shape | Run | +| -------------------------------------------------------------------- | ----------------- | +| nothing / a plain task description | **fresh marking** | +| a single issue URL, a bare ``, or a `*-task.md` path | **fresh marking** | +| a Draft PR URL, or a `` with `.yoke/ai//-draft.md` | **iteration** | + +``` +/yoke:draft https://github.com/org/repo/issues/42 # fresh marking from an issue +/yoke:draft https://github.com/org/repo/pull/57 # iteration against the Draft PR +``` + +## Flow + +Fresh marking: + +| Phase | Name | What happens | +| ----- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| 0 | **Resolve** | Detect fresh vs iteration, read the flow map, derive slug + ticket ID, enter a worktree per touched repo immediately — there is no confirmed-plan moment to defer it to. | +| 1 | **Plan** | Dispatch `task-investigator` then `plan-architect` per `/do`'s Plan phase; write `.yoke/ai//-plan.md`. No confirmation pause follows — the Draft PR review replaces the gate. | +| 2 | **Mark** | The orchestrator writes the Markup in-session: a `TODO(yoke):` Marker at every change site in existing files, a compilable skeleton for new structure. The build stays green; tests may be red; no implemented logic anywhere. | +| 3 | **Draft artifact** | Write `.yoke/ai//-draft.md` — Draft PR URL(s), branch(es), touched-repo set, plan pointer. | +| 4 | **Finish** | `/do`'s finish contract with `--draft` forced on the pr call: push, one Draft PR per repo, ticket comment, one STAGE_COMPLETE notify carrying the Draft PR link(s). | + +Iteration — a re-run against an existing Draft, still without pauses: + +1. Read the Draft artifact and the plan; enter the recorded branch(es). +2. Fetch the PR comments — inline review threads and top-level conversation. +3. Redraw the Markup in the same branch — comments outrank the existing Markers and the + plan; the build stays green; the Draft PR updates in place, never a second PR. +4. Reply in every inline review thread with what changed and where; thread resolution + stays the user's. +5. Re-fire the STAGE_COMPLETE notify. + +Any number of rounds. + +## The draft → ready lifecycle + +One PR carries the whole history from Markup to ready, across the two skills: + +| Step | Actor | What happens | +| ---- | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | `/draft` | Marks the code and opens the Draft PR (one per touched repo). | +| 2 | user | Reviews the Draft PR on GitHub and comments; re-runs `/draft` to re-mark per the comments — any number of rounds. | +| 3 | `/do ` (or ``) | Draft execution: implements per comments > Markers > plan, deletes every Marker (the grep gate blocks the flip on any leftover), replies in threads, flips the **same** PR to ready — never a second PR. | + +`/draft` never flips the PR to ready and never merges — the flip belongs to `/do` Draft +execution, the merge to `/merge`. + +## Output + +**Output:** Draft PR link(s), Draft artifact at `.yoke/ai//-draft.md`, plan at `.yoke/ai//-plan.md`, ticket comment, STAGE_COMPLETE notify + +File `.yoke/ai//-draft.md` — the record a fresh `/do ` session uses to find the Draft: + +- **Draft PR URL(s)** — one per touched repo +- **Branch(es)** — the Markup branch in each touched repo +- **Touched-repo set** — the repos from the flow map this Draft marks +- **Plan pointer** — the path to `-plan.md` + +## Example + +``` +/yoke:draft https://github.com/org/repo/issues/42 +``` + +## Connections + +``` +/grill → /yoke:draft → PR review → /yoke:do → ready PR +``` + +`/draft` reuses `/do`'s finish contract (worktree, push, PR per repo, ticket comment, +notify) and the pr skill's mechanics with `--draft` forced on. Downstream, `/do` +consumes the Draft via its Draft execution mode; `/merge` runs only after the PR is +ready and approved. The Markup contract — Marker format, skeleton rules, the grep-gate +scope — lives in `skills/draft/reference/markup-format.md`. diff --git a/docs/notify.md b/docs/notify.md index b4d0966..d8b6cc6 100644 --- a/docs/notify.md +++ b/docs/notify.md @@ -82,6 +82,7 @@ Any type not in the list is silently suppressed. | bootstrap | Complete | STAGE_COMPLETE | Bootstrap complete | | do | Execute | ALERT | Task blocked | | do | Finish | STAGE_COMPLETE | `: PR ready` — PR URL(s) as the payload | +| draft | Finish | STAGE_COMPLETE | `: Draft PR ready` — Draft PR URL(s) as the payload | | merge | Finish | STAGE_COMPLETE | `: merged` — merged / cascade / deploy / transition summary | | pr | Decide | ACTION_REQUIRED | Choose PR type (draft/ready) | | pr | Complete | STAGE_COMPLETE | PR created or updated | @@ -94,6 +95,12 @@ not from the Finalize phase — the PR link(s) are the payload the developer ret fires its own STAGE_COMPLETE from the merge procedure (`skills/merge/reference/merge-procedure.md` §7) once the post-PR tail is done. +`/draft` fires its STAGE_COMPLETE from `skills/draft/reference/mode-draft.md` Phase 4 §7 once the +Draft PR exists; a `/draft` iteration re-fires the same STAGE_COMPLETE after pushing the redrawn +Markup (mode-draft.md Iteration §7). A `/do` draft execution uses the existing +`do | Finish | STAGE_COMPLETE` point when it flips the PR to ready — no separate notify point for +that transition. + --- ## Example call diff --git a/site/src/content/docs/skills/do.mdx b/site/src/content/docs/skills/do.mdx index acbde78..21fef0a 100644 --- a/site/src/content/docs/skills/do.mdx +++ b/site/src/content/docs/skills/do.mdx @@ -28,6 +28,7 @@ Activates when the user writes: - nothing / a plain task description → **inline** - a single issue URL, a ``, or a `*-task.md` path → **sub-agents** +- a Draft PR URL, or a `` whose draft artifacts exist → **draft execution** - a PRD issue that has GitHub sub-issues → **team** - an existing `*-plan.md` path → **sub-agents** (back-compat; executes it directly) @@ -71,6 +72,7 @@ deliverable. - **a single issue URL**, a bare ``, or a `*-task.md` path (sub-agents) - **a `*-plan.md` path** — a pre-built plan (sub-agents, back-compat) - **a PRD issue that has GitHub sub-issues** (team) +- **a Draft PR URL**, or a bare `` whose `.yoke/ai//-draft.md` exists (draft execution) Optional flag `--update-docs` enables the documentation step. Without it, /do skips docs unless the plan's frontmatter sets `update_docs: true`. @@ -86,12 +88,17 @@ Detect the mode from `$ARGUMENTS`. First match wins: back-compat — an `agent-team` header maps to **team** mode instead. Then read and follow `reference/mode-sub-agents.md` (or `reference/mode-team.md` when the header says `agent-team`). -2. **`$ARGUMENTS` is a single issue URL, a bare ``, or a `*-task.md` +2. **`$ARGUMENTS` is a GitHub pull-request URL (path contains `/pull/`), or a + bare `` for which `.yoke/ai//-draft.md` exists** → + **draft execution** mode: a `/draft` run marked the code and opened the + Draft PR; implement it per the review. Read and follow + `reference/mode-draft-execution.md`. +3. **`$ARGUMENTS` is a single issue URL, a bare ``, or a `*-task.md` path** → **sub-agents** mode (investigate → plan → pause → execute). Read and follow `reference/mode-sub-agents.md`. -3. **`$ARGUMENTS` points at a PRD issue that HAS sub-issues** (detect via +4. **`$ARGUMENTS` points at a PRD issue that HAS sub-issues** (detect via `gh api`) → **team** mode. Read and follow `reference/mode-team.md`. -4. **empty / a plain chat description / no ticket** → **inline** mode. Read and +5. **empty / a plain chat description / no ticket** → **inline** mode. Read and follow `reference/mode-inline.md`. Each mode's full procedure lives in its reference file. Read only the one this @@ -101,11 +108,12 @@ ladder selects, then execute it. ## Modes -| Mode | Input | Behavior | -| -------------- | ------------------------------------------------ | ----------------------------------------------------------------------------------------- | -| **inline** | empty / plain chat description | Brief plan in chat, execute in-session, then finish per `reference/finish.md`. | -| **sub-agents** | issue URL / `` / `*-task.md` / `*-plan.md` | Write the plan, pause only on cold start, executor → reviewer → validator, then finish. | -| **team** | PRD issue with sub-issues | Write the plan, pause only on cold start, dispatch sub-agents per sub-issue, then finish. | +| Mode | Input | Behavior | +| ------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- | +| **inline** | empty / plain chat description | Brief plan in chat, execute in-session, then finish per `reference/finish.md`. | +| **sub-agents** | issue URL / `` / `*-task.md` / `*-plan.md` | Write the plan, pause only on cold start, executor → reviewer → validator, then finish. | +| **draft execution** | Draft PR URL / drafted `` | Implement the Markup per the review (comments > markers > plan), reply in the threads, flip the PR to ready, then finish. | +| **team** | PRD issue with sub-issues | Write the plan, pause only on cold start, dispatch sub-agents per sub-issue, then finish. | --- diff --git a/site/src/content/docs/skills/draft.mdx b/site/src/content/docs/skills/draft.mdx new file mode 100644 index 0000000..04f97c7 --- /dev/null +++ b/site/src/content/docs/skills/draft.mdx @@ -0,0 +1,129 @@ +--- +title: /yoke:draft +description: "Projects the agreed plan onto the code as Markup — TODO markers plus a compilable skeleton — and opens a Draft PR for review, instead of implementing." +--- + +Projects the agreed plan onto the code as Markup — TODO markers plus a compilable skeleton — and opens a Draft PR for review, instead of implementing. + +## Triggers + +Activates when the user writes: + +- `draft` +- `mark the code` +- `mark up the plan` +- `make a draft` +- `draft pr` + +## Use it + +``` +/yoke:draft https://github.com/org/repo/issues/42 # fresh marking from an issue +/yoke:draft https://github.com/org/repo/pull/57 # iteration against the Draft PR +``` + +## Inputs and outputs + +**Input:** `$ARGUMENTS` — the same contract as `/do`, plus the iteration shapes: + +| Input shape | Run | +| -------------------------------------------------------------------- | ----------------- | +| nothing / a plain task description | **fresh marking** | +| a single issue URL, a bare ``, or a `*-task.md` path | **fresh marking** | +| a Draft PR URL, or a `` with `.yoke/ai//-draft.md` | **iteration** | + +``` +/yoke:draft https://github.com/org/repo/issues/42 # fresh marking from an issue +/yoke:draft https://github.com/org/repo/pull/57 # iteration against the Draft PR +``` + +**Output:** Draft PR link(s), Draft artifact at `.yoke/ai//-draft.md`, plan at `.yoke/ai//-plan.md`, ticket comment, STAGE_COMPLETE notify + +
+Full instructions + +```markdown +--- +name: draft +description: >- + Projects the agreed plan onto the code as Markup — TODO markers plus a + compilable skeleton — and opens a Draft PR for review, instead of + implementing. Triggered when the user writes "draft", "mark the code", + "mark up the plan", "make a draft", "draft pr". +--- + +# Mark the code per plan + +The optional marking step between grill and do (ADR-0011). A do-shaped run — the same +inputs and the same finish machinery as `/do` — that marks instead of +implementing: it projects the plan onto the code as Markup and opens a GitHub +Draft PR for remote review. `/draft` NEVER pauses — the Draft PR is the pause. +The flow becomes **grill → draft → PR review → do**; grill → do stays the +default. + +--- + +## Input + +`$ARGUMENTS` — one of: + +- **empty** — no input; work from the current conversation +- **a plain task description** — chat text, no ticket +- **a single issue URL**, a bare ``, or a `*-task.md` path + +All of the above → fresh marking. Plus the iteration shapes: + +- **a Draft PR URL**, or **a bare ``** whose + `.yoke/ai//-draft.md` exists → iteration against the existing + Draft + +--- + +## Router + +Detect the run from `$ARGUMENTS`. First match wins: + +1. **Input is a Draft PR URL, or a `` with an existing + `.yoke/ai//-draft.md`** → **iteration**. Read and follow + `reference/mode-draft.md` § Iteration. +2. **Anything else** → **fresh marking**. Read and follow + `reference/mode-draft.md` from Phase 0. + +The full procedure lives in `reference/mode-draft.md`. Read it, then execute. + +--- + +## Principles + +These hold for every run: + +- **Never pauses.** No cold-start gate, no confirmation, no mid-run question — + the Draft PR is the pause. +- **Marks, never implements.** The Markup contract is + `reference/markup-format.md`: `TODO(yoke):` Markers plus a compilable + skeleton. The build stays green; tests may be red. +- **Ends at the Draft PR.** Never flips it to ready, never merges — `/do` + executes the Draft; `/merge` finishes after approval. +- **Worktree on default branch + finish machinery** per + `${CLAUDE_PLUGIN_ROOT}/skills/do/reference/finish.md`. +- **Artifacts under `.yoke/`.** `-plan.md` and `-draft.md` live in + `.yoke/ai//`. +- **Commits by convention** per + `${CLAUDE_PLUGIN_ROOT}/skills/gca/reference/commit-convention.md`. +- Language: match the ticket/input language, or follow the project-level + definition in CLAUDE.md / AGENTS.md. + +--- + +## After the run + +The user reviews the Draft PR on GitHub and comments on it. A re-run of +`/draft` re-marks per the comments; `/do ` (or `/do `) +implements the Markers and flips the PR to ready. +``` + +
+ +## Source + +[View `SKILL.md` on GitHub →](https://github.com/yokeloop/yoke/blob/main/skills/draft/SKILL.md) diff --git a/site/src/content/docs/skills/help.mdx b/site/src/content/docs/skills/help.mdx index c18604b..fd61086 100644 --- a/site/src/content/docs/skills/help.mdx +++ b/site/src/content/docs/skills/help.mdx @@ -152,6 +152,17 @@ Same grilling, plus it maintains the glossary `.yoke/context.md` and ADRs in `.y /yoke:grill-docs design the order cancellation flow ``` +### /draft — optional marking step between grill and do + +A do-shaped run that marks instead of implementing: it projects the agreed plan onto the code as Markup (`TODO(yoke):` Markers plus a compilable skeleton) and opens a GitHub Draft PR for remote review. Never pauses — the Draft PR is the pause. Comment on the Draft PR and re-run `/yoke:draft` to re-mark, or run `/yoke:do ` to implement the Markers and flip the PR to ready. + +**Input:** ticket URL, description, or nothing — fresh marking; a Draft PR URL or a drafted `` — iteration → **Output:** a GitHub Draft PR carrying the Markup + `.yoke/ai//-draft.md` + +``` +/yoke:draft https://github.com/owner/repo/issues/86 +/yoke:draft https://github.com/owner/repo/pull/90 +``` + ### /prd — PRD from context Synthesizes the current conversation into a PRD, publishes it as a GitHub issue (`ready-for-agent`), and saves a local copy. No interview. @@ -200,6 +211,7 @@ The everyday loop is short: **grill → do → PR on GitHub → merge**. `do` ca ``` /yoke:bootstrap # prepare the project (first run) — writes .yoke/flow.md /yoke:grill # stress-test the idea (grill-docs also captures terms + ADRs) +/yoke:draft # optional: mark the code, open a Draft PR to review before implementing /yoke:do # execute end to end → a ready pull request # → review the PR on GitHub, comment, approve /yoke:merge # merge, cascade, deploy/release, transition the ticket, clean up diff --git a/skills/do/SKILL.md b/skills/do/SKILL.md index 6bf5f7a..f5f2f85 100644 --- a/skills/do/SKILL.md +++ b/skills/do/SKILL.md @@ -26,6 +26,7 @@ deliverable. - **a single issue URL**, a bare ``, or a `*-task.md` path (sub-agents) - **a `*-plan.md` path** — a pre-built plan (sub-agents, back-compat) - **a PRD issue that has GitHub sub-issues** (team) +- **a Draft PR URL**, or a bare `` whose `.yoke/ai//-draft.md` exists (draft execution) Optional flag `--update-docs` enables the documentation step. Without it, /do skips docs unless the plan's frontmatter sets `update_docs: true`. @@ -41,12 +42,17 @@ Detect the mode from `$ARGUMENTS`. First match wins: back-compat — an `agent-team` header maps to **team** mode instead. Then read and follow `reference/mode-sub-agents.md` (or `reference/mode-team.md` when the header says `agent-team`). -2. **`$ARGUMENTS` is a single issue URL, a bare ``, or a `*-task.md` +2. **`$ARGUMENTS` is a GitHub pull-request URL (path contains `/pull/`), or a + bare `` for which `.yoke/ai//-draft.md` exists** → + **draft execution** mode: a `/draft` run marked the code and opened the + Draft PR; implement it per the review. Read and follow + `reference/mode-draft-execution.md`. +3. **`$ARGUMENTS` is a single issue URL, a bare ``, or a `*-task.md` path** → **sub-agents** mode (investigate → plan → pause → execute). Read and follow `reference/mode-sub-agents.md`. -3. **`$ARGUMENTS` points at a PRD issue that HAS sub-issues** (detect via +4. **`$ARGUMENTS` points at a PRD issue that HAS sub-issues** (detect via `gh api`) → **team** mode. Read and follow `reference/mode-team.md`. -4. **empty / a plain chat description / no ticket** → **inline** mode. Read and +5. **empty / a plain chat description / no ticket** → **inline** mode. Read and follow `reference/mode-inline.md`. Each mode's full procedure lives in its reference file. Read only the one this @@ -56,11 +62,12 @@ ladder selects, then execute it. ## Modes -| Mode | Input | Behavior | -| -------------- | ------------------------------------------------ | ----------------------------------------------------------------------------------------- | -| **inline** | empty / plain chat description | Brief plan in chat, execute in-session, then finish per `reference/finish.md`. | -| **sub-agents** | issue URL / `` / `*-task.md` / `*-plan.md` | Write the plan, pause only on cold start, executor → reviewer → validator, then finish. | -| **team** | PRD issue with sub-issues | Write the plan, pause only on cold start, dispatch sub-agents per sub-issue, then finish. | +| Mode | Input | Behavior | +| ------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- | +| **inline** | empty / plain chat description | Brief plan in chat, execute in-session, then finish per `reference/finish.md`. | +| **sub-agents** | issue URL / `` / `*-task.md` / `*-plan.md` | Write the plan, pause only on cold start, executor → reviewer → validator, then finish. | +| **draft execution** | Draft PR URL / drafted `` | Implement the Markup per the review (comments > markers > plan), reply in the threads, flip the PR to ready, then finish. | +| **team** | PRD issue with sub-issues | Write the plan, pause only on cold start, dispatch sub-agents per sub-issue, then finish. | --- diff --git a/skills/do/reference/finish.md b/skills/do/reference/finish.md index a7481f4..d84af2d 100644 --- a/skills/do/reference/finish.md +++ b/skills/do/reference/finish.md @@ -62,6 +62,16 @@ After implementation and per-task commits, finish each repo by its `finish` poli steps only. The pr skill's own terminal notify and print are superseded by the run-level notify in §7 — do not fire them here. + Draft variants: + - A `/draft` run passes `--draft` to the pr skill's create call + (`IS_DRAFT: true`), so the PR opens as a GitHub **Draft PR**. + - A `/do` Draft execution run finds the Draft PR already open: the pr + mechanics UPDATE it (the update path keeps the draft state), then the run + flips it with `gh pr ready `. Never create a second PR for the + same branch. + - ADR-0006 stands: flipping an existing Draft PR to ready still ends the run + at a PR — it is not a merge and does not violate `do`'s never-merge rule. + - **`direct-push`** — commit to the repo's default branch, push, run the declared `publish` command, then bump the published version in each repo named in `consumers` — as part of that consumer's own change set (i.e. inside the diff --git a/skills/do/reference/mode-draft-execution.md b/skills/do/reference/mode-draft-execution.md new file mode 100644 index 0000000..4dad1f4 --- /dev/null +++ b/skills/do/reference/mode-draft-execution.md @@ -0,0 +1,154 @@ +# Mode: draft execution + +The mode that consumes a **Draft**. `/draft` projected the plan onto the code as Markup — `TODO(yoke):` Markers plus a compilable skeleton — and opened a GitHub Draft PR; the user reviewed it and left comments. This mode implements the Markup per that review, replies in the threads, and flips the **same** PR to ready. One PR carries the whole history from markup to ready — never a second PR (ADR-0011). ADR-0006 stands: the run still ends at a PR; flipping draft → ready is not a merge. + +The router (`skills/do/SKILL.md`) delegates here when the input is a Draft PR URL or a slug whose artifacts record a Draft. The Markup contract — Marker format, skeleton rules, grep-gate scope — lives in `${CLAUDE_PLUGIN_ROOT}/skills/draft/reference/markup-format.md`; read it before Phase 1. + +**Flow:** + +``` +0. Resolve → Draft artifact + gh pr view (isDraft guard) → worktree on the Draft branch (finish.md §2) +1. Gather → three voices: plan artifact + Markers in code + PR review comments (comments win) +2. Execute → each Marker = a checklist item → task-executor per Marker, review loop per status-protocol.md +3. Reply → answer every inline review thread + one summary comment; never resolve threads +4. Grep gate → grep source for TODO(yoke): — any hit blocks the ready flip +5. Validate → validator + formatter (mode-sub-agents.md Phase 4) → report (its Phase 6, report-format.md) +6. Finish → finish.md §3: UPDATE the same Draft PR, then gh pr ready → ticket comment §5 → notify §7 +``` + +Track every phase in TodoWrite. + +--- + +## Phase 0 — Resolve + +Accept one input from the router: a **Draft PR URL** (contains `/pull/`) or a bare `` whose `.yoke/ai//-draft.md` exists — the router already discriminated. + +**1. Read the Draft artifact** `.yoke/ai//-draft.md`: the Draft PR URL(s), branch(es), repo set, and the plan pointer. With a PR URL input, derive the slug from the head branch, then read the same artifact. + +**2. Inspect the PR:** + +```bash +gh pr view --json isDraft,number,headRefName,url +``` + +If `isDraft` is already `false`, warn the user and continue as a plain update run — the flip already happened; a re-run stays idempotent. + +**3. Check out the Draft branch.** Enter the worktree per `reference/finish.md` §2 — the branch already exists, so enter or attach a worktree on it. Never work on the default branch. + +**4.** Derive `SLUG` and `TICKET_ID` per `${CLAUDE_PLUGIN_ROOT}/skills/gca/reference/commit-convention.md`. + +**Transition:** Draft resolved, worktree entered → Phase 1. + +--- + +## Phase 1 — Gather the three voices + +Collect the three inputs that define the work: + +- **(a) The plan artifact** — `.yoke/ai//-plan.md`: design decisions, task decomposition, Verify criteria. +- **(b) The Markers in code** — `grep -rn "TODO(yoke):"` over the repo source. Scope per + `${CLAUDE_PLUGIN_ROOT}/skills/draft/reference/markup-format.md`: exclude `.yoke/` and documentation that mentions + the literal. +- **(c) The PR review comments** — inline threads: `gh api repos/{owner}/{repo}/pulls/{pr}/comments`; top-level: `gh pr view --comments`. + +**Priority of voices: PR comments > Markers > plan artifact.** A comment is the user's latest will and wins silently over a Marker or a plan step — do not ask, do not reconcile in chat. + +**Exception — a comment that overturns the plan's architecture.** Not a local correction but a structural reversal ("different module boundary", "drop the whole approach"): stop and ask via AskUserQuestion instead of silently rewriting the plan: + +1. **Re-draft per the comment (Recommended)** — end this run; the user re-runs `/draft` so the Markup is redrawn per the comment. +2. **Proceed as commented** — implement per the comment, treating it as the new plan. +3. **Cancel** — stop; no code changes. + +This is the mode's only possible pause. + +**Transition:** voices gathered, conflicts resolved by priority → Phase 2. + +--- + +## Phase 2 — Execute the checklist + +Read `reference/status-protocol.md` — statuses, the review loop via `agents/task-reviewer.md`, model escalation, parallel dispatch. Do not duplicate its rules here. + +Each Marker — adjusted by any overriding comment — is one checklist item. For each, build a task and dispatch `agents/task-executor.md` verbatim: + +- **What** = the Marker text + the relevant plan step + the overriding comment, when one exists. +- **How** = the plan step's How, adjusted by the overriding comment. +- **Files** = the Marker's file and its skeleton counterparts. +- **Context** = the Marker's file plus the plan step's Context — only this task's files, never the whole plan. +- **Constraints** = from the plan. +- **Verify** = from the plan. +- **COMMIT_MESSAGE** per `${CLAUDE_PLUGIN_ROOT}/skills/gca/reference/commit-convention.md` — one commit per task. + +The executor deletes each Marker together with its implementation — a Marker is consumed, never left behind. + +Dispatch parallel groups when Markers touch disjoint files, sequentially otherwise — per `reference/status-protocol.md`. + +**Multi-repo.** Pick up every Draft PR from the Draft artifact; run the checklist per repo, finish order per `reference/finish.md` §4. + +**Transition:** checklist done (or BLOCKED recorded) → Phase 3. + +--- + +## Phase 3 — Thread replies + +After implementing, reply in **every** inline review thread describing what was done and in which commit: + +```bash +gh api --method POST repos/{owner}/{repo}/pulls/{pr}/comments \ + -f body="" -F in_reply_to= +``` + +Address top-level PR comments in one summary comment (`gh pr comment`). + +Thread resolution stays the user's — **never resolve threads**. + +**Transition:** every thread answered → Phase 4. + +--- + +## Phase 4 — Grep gate (hard block) + +Before finishing, grep the source for `TODO(yoke):` — scope per `${CLAUDE_PLUGIN_ROOT}/skills/draft/reference/markup-format.md` (exclude `.yoke/` and docs mentioning the literal). + +**Any hit = unfinished work.** Implement it or mark the task BLOCKED. The ready flip is blocked until the grep is clean — this gate is hard, with no override. + +**Transition:** grep clean → Phase 5. + +--- + +## Phase 5 — Validate + report + +Run `reference/mode-sub-agents.md` Phase 4: validator + formatter in parallel. Then its Phase 6: write `.yoke/ai//-report.md` per `reference/report-format.md`. Reuse both by citation — do not restate them here. + +**Transition:** validated, report written → Phase 6. + +--- + +## Phase 6 — Finish (flip to ready) + +Execute `reference/finish.md` §3: the pr mechanics **UPDATE the existing Draft PR** — never create a second one; the update path keeps the draft state. Then flip: + +```bash +gh pr ready +``` + +- **Ticket comment (§5)** — when a tracker is configured, one short comment: what was done + the now-ready PR URL. +- **Finish block + notify (§7)** — append the per-repo table to the report and commit it; send the **single** STAGE_COMPLETE notification, title `: PR ready`, body = the now-ready PR URL(s). +- **Mark the Draft consumed.** Update the status line in `.yoke/ai//-draft.md` to executed and commit it, so a router re-run treats the slug as consumed. The artifact stays for history. + +Print the PR link(s) and stop. + +--- + +## Rules + +- **PR comments > Markers > plan.** The user's latest will wins silently. +- **One pause only.** An architecture-overturning comment (Phase 1); everything else runs without stops. +- **Every Marker deleted with its implementation.** A Marker is consumed, never left behind. +- **The grep gate blocks the ready flip.** A clean `TODO(yoke):` grep is a hard precondition for `gh pr ready`. +- **Never a second PR.** Implement in the same branch and same Draft PR (ADR-0011). +- **Never merge.** Flipping draft → ready ends the run at a PR; it is not a merge (ADR-0006). +- **All artifacts under `.yoke/`.** The Draft artifact, plan, and report live in `.yoke/ai//`. +- **Context isolation.** A task-executor receives only its own task text, not the whole plan or comment set. +- Language: match the ticket/input language, or follow the project-level definition in CLAUDE.md / AGENTS.md. diff --git a/skills/draft/SKILL.md b/skills/draft/SKILL.md new file mode 100644 index 0000000..2566dd9 --- /dev/null +++ b/skills/draft/SKILL.md @@ -0,0 +1,77 @@ +--- +name: draft +description: >- + Projects the agreed plan onto the code as Markup — TODO markers plus a + compilable skeleton — and opens a Draft PR for review, instead of + implementing. Triggered when the user writes "draft", "mark the code", + "mark up the plan", "make a draft", "draft pr". +--- + +# Mark the code per plan + +The optional marking step between grill and do (ADR-0011). A do-shaped run — the same +inputs and the same finish machinery as `/do` — that marks instead of +implementing: it projects the plan onto the code as Markup and opens a GitHub +Draft PR for remote review. `/draft` NEVER pauses — the Draft PR is the pause. +The flow becomes **grill → draft → PR review → do**; grill → do stays the +default. + +--- + +## Input + +`$ARGUMENTS` — one of: + +- **empty** — no input; work from the current conversation +- **a plain task description** — chat text, no ticket +- **a single issue URL**, a bare ``, or a `*-task.md` path + +All of the above → fresh marking. Plus the iteration shapes: + +- **a Draft PR URL**, or **a bare ``** whose + `.yoke/ai//-draft.md` exists → iteration against the existing + Draft + +--- + +## Router + +Detect the run from `$ARGUMENTS`. First match wins: + +1. **Input is a Draft PR URL, or a `` with an existing + `.yoke/ai//-draft.md`** → **iteration**. Read and follow + `reference/mode-draft.md` § Iteration. +2. **Anything else** → **fresh marking**. Read and follow + `reference/mode-draft.md` from Phase 0. + +The full procedure lives in `reference/mode-draft.md`. Read it, then execute. + +--- + +## Principles + +These hold for every run: + +- **Never pauses.** No cold-start gate, no confirmation, no mid-run question — + the Draft PR is the pause. +- **Marks, never implements.** The Markup contract is + `reference/markup-format.md`: `TODO(yoke):` Markers plus a compilable + skeleton. The build stays green; tests may be red. +- **Ends at the Draft PR.** Never flips it to ready, never merges — `/do` + executes the Draft; `/merge` finishes after approval. +- **Worktree on default branch + finish machinery** per + `${CLAUDE_PLUGIN_ROOT}/skills/do/reference/finish.md`. +- **Artifacts under `.yoke/`.** `-plan.md` and `-draft.md` live in + `.yoke/ai//`. +- **Commits by convention** per + `${CLAUDE_PLUGIN_ROOT}/skills/gca/reference/commit-convention.md`. +- Language: match the ticket/input language, or follow the project-level + definition in CLAUDE.md / AGENTS.md. + +--- + +## After the run + +The user reviews the Draft PR on GitHub and comments on it. A re-run of +`/draft` re-marks per the comments; `/do ` (or `/do `) +implements the Markers and flips the PR to ready. diff --git a/skills/draft/reference/markup-format.md b/skills/draft/reference/markup-format.md new file mode 100644 index 0000000..1c0a25b --- /dev/null +++ b/skills/draft/reference/markup-format.md @@ -0,0 +1,82 @@ +# Markup Format + +The contract for **Markup** — what `/draft` writes into the code and what `/do` Draft execution consumes and deletes. From the glossary (`.yoke/context.md`): + +> **Markup** — the draft's product in code: markers in existing files plus a skeleton (new files, signatures, types) with compilable stub bodies. A temporary artifact living only between draft and do; none of it survives into the ready PR. + +> **Marker** — a single markup comment (`TODO(yoke): …`) naming what will be written at that spot. `do` implements markers as a checklist, deleting each with its implementation; a leftover marker blocks the finish. + +--- + +## Marker + +One comment in the unified format: + +``` +TODO(yoke): +``` + +Optionally carrying the plan step reference: + +``` +TODO(yoke): [task 3] parse the retry config; returns RetryPolicy +``` + +One Marker = one unit of future work at that exact spot. Use the host language's comment syntax (`// TODO(yoke): …`, `# TODO(yoke): …`, ``). Describe the future work — what the code will do, what it returns, what it touches — not the current state. Place the Marker on the line where the code will be written, not at the file header. Two units of work get two Markers. + +## Skeleton + +New structure appears as real files: modules, signatures, and types that will exist after implementation. Bodies are compilable stubs. + +TypeScript/JS: + +```typescript +export function parseRetryConfig(raw: unknown): RetryPolicy { + // TODO(yoke): [task 3] parse the retry config; validate bounds + throw new Error("TODO"); +} +``` + +Python: + +```python +def parse_retry_config(raw: dict) -> RetryPolicy: + # TODO(yoke): [task 3] parse the retry config; validate bounds + raise NotImplementedError +``` + +Go: + +```go +func ParseRetryConfig(raw map[string]any) RetryPolicy { + // TODO(yoke): [task 3] parse the retry config; validate bounds + panic("TODO") +} +``` + +## Build invariant + +The skeleton must compile / type-check. A working build keeps the LSP alive: the reviewer navigates signatures and types on the Draft PR instead of reading dead text. Red tests on a Draft PR are acceptable; a broken build is not. + +## Boundary + +Draft does not implement logic. Markers plus signatures show _where_ and _what_; every body stays a stub. A fully typed scaffold with contracts everywhere is explicitly out — that is half the implementation accepted blind, the exact thing Draft exists to prevent. When torn between a stub and a partial implementation, write the stub and a Marker. + +## Grep gate + +The prefix `TODO(yoke):` is the checklist key. + +- `/do` Draft execution walks the Markers as a checklist, deleting each Marker together with its implementation. +- Before the finish, grep the project's source for `TODO(yoke):` — any hit means unfinished work and blocks the ready flip. +- Scope: the gate greps source code only. Exclude `.yoke/` artifacts and documentation that mentions the literal string (like this file). + +--- + +## Format rules + +- One Marker = one unit of future work at that exact spot. +- The Marker prefix is always the literal `TODO(yoke):` — the grep gate depends on it. +- Skeleton files are real: correct paths, imports, exports, types. +- Stub bodies only: `throw new Error("TODO")`, `raise NotImplementedError`, `panic("TODO")`, or the language's equivalent. +- The build stays green; tests may be red. +- No implemented logic anywhere in Markup. diff --git a/skills/draft/reference/mode-draft.md b/skills/draft/reference/mode-draft.md new file mode 100644 index 0000000..125fadb --- /dev/null +++ b/skills/draft/reference/mode-draft.md @@ -0,0 +1,134 @@ +# Mode: draft + +`/draft` is a do-shaped run — the same inputs as `/do`, the same finish machinery — that marks instead of implementing (ADR-0011). It projects the plan onto the code as Markup — `TODO(yoke):` Markers in existing files plus a compilable skeleton for new structure — and opens a GitHub Draft PR for remote review. **`/draft` NEVER pauses: the Draft PR is the pause.** No cold-start confirmation, no AskUserQuestion, no mid-run question — the run always drives to the Draft PR and the notify. + +**Flow:** + +``` +0. Resolve → input shape + flow map + SLUG/TICKET_ID + worktree (iteration input → Iteration) +1. Plan → investigate + architect per do's Phase 1 → write -plan.md; NO confirmation pause +2. Mark → orchestrator writes the Markup in-session per markup-format.md; build stays green; commit +3. Draft artifact → write -draft.md (Draft PR URLs, branches, repo set, plan pointer) +4. Finish → finish.md §3-§5, §7 with --draft: push, one Draft PR per repo, ticket comment, one notify +``` + +--- + +## Phase 0 — Resolve input & slug + +Accept the same input shapes as `/do`: empty input, a plain chat description, an issue URL, a bare ``, or a `*-task.md` path. + +**Detect iteration first.** When the input is a **Draft PR URL**, or a `` whose `.yoke/ai//-draft.md` exists, this is a re-run against an existing Draft — skip Phases 1–4 and go to **Iteration** below. + +**Read the flow map** per `${CLAUDE_PLUGIN_ROOT}/skills/do/reference/finish.md` §1 (cited below as finish.md). Run the flow-map read once at the project root; hold the repos, finish policies, tracker, and commit language for the marking and the finish. + +**Derive `SLUG` and `TICKET_ID`** per `${CLAUDE_PLUGIN_ROOT}/skills/gca/reference/commit-convention.md`: issue URL → fetch the issue, build the slug from its number + title; `` → use directly; `*-task.md` path → take the slug from the `.yoke/ai//` directory in the path; chat description → build a slug from the task essence. + +**Enter the worktree** per finish.md §2 **immediately** — before any planning output touches disk. `/draft` never pauses, so there is no confirmed-plan moment to defer the entry to; isolate here, one worktree per repo the task will touch. + +**Transition:** input resolved → Phase 1 (or → Iteration). + +--- + +## Phase 1 — Plan + +Run the **Plan phase of `${CLAUDE_PLUGIN_ROOT}/skills/do/reference/mode-sub-agents.md`** (Phase 1): dispatch `task-investigator` to map the change area, then `plan-architect` to design and decompose, then write `.yoke/ai//-plan.md` per `${CLAUDE_PLUGIN_ROOT}/skills/do/reference/plan-format.md` and auto-commit the artifact with the escape-hatch. Reuse that machinery — do not re-derive it here. + +**No confirmation pause follows.** Where sub-agents mode gates on a cold start, `/draft` goes straight to marking: the Draft PR review replaces the gate. The result is safe — Markup only, no implementation — and the user steers on GitHub, not in chat. + +**Transition:** plan written and committed → Phase 2. + +--- + +## Phase 2 — Mark + +The orchestrator writes the Markup **in-session** — no sub-agents. A `task-executor` is trained to delete the very `TODO(yoke):` markers it would here be asked to write; marking is orchestrator work by design. + +Walk the plan's tasks in order and project each onto the code per `reference/markup-format.md`: + +- **Existing files** → a `TODO(yoke):` Marker at every change site, optionally carrying the plan step reference (`TODO(yoke): [task 3] …`). One Marker = one unit of future work at that exact spot. +- **New structure** → a compilable skeleton: real files with correct paths, imports, exports, signatures, and types; every body a stub (`throw new Error("TODO")`, `raise NotImplementedError`, `panic("TODO")`, or the language's equivalent) carrying its own Marker. + +**The build stays green.** Run the project's type-check/build and fix stubs until it compiles — a working build keeps the LSP alive for the reviewer. Red tests are acceptable; a broken build is not. No implemented logic anywhere — when torn between a stub and a partial implementation, write the stub and a Marker. + +Commit the Markup per `${CLAUDE_PLUGIN_ROOT}/skills/gca/reference/commit-convention.md`, type `feat` — e.g. `#86 feat(): mark up for implementation`. Group commits by plan task or area; NO colon after the ticket. + +**Transition:** Markup committed, build green → Phase 3. + +--- + +## Phase 3 — Draft artifact + +Write `.yoke/ai//-draft.md` — the record a fresh `/do ` session uses to find the Draft. It holds: + +- **Draft PR URL(s)** — one per touched repo. Phase 4 creates them, so write the file now with the URLs pending, then update it once the PRs exist. +- **Branch(es)** — the Markup branch in each touched repo. +- **Touched-repo set** — the repos from the flow map this Draft marks. +- **Plan pointer** — the path to `-plan.md`. + +Commit it with the run artifacts (escape-hatch: `.yoke/` gitignored → tell the user and skip the commit). + +**Transition:** Draft artifact written → Phase 4. + +--- + +## Phase 4 — Finish (drive to Draft PR) + +Hand off to finish.md **§3–§5 and §7**, with `--draft` forced on the pr create call — finish.md §3's "Draft variants" block covers it (`IS_DRAFT: true`, so the PR opens as a GitHub **Draft PR**): + +- **Per-repo finish (§3).** For each touched repo: commit remaining run artifacts (including the updated `-draft.md` once the PR URL exists), push the branch, create the PR **as a draft** through the pr skill's mechanics. +- **Multi-repo order (§4).** Libraries first, then apps; aggregate every Draft PR URL. +- **Ticket comment (§5).** When the tracker ≠ `none`, post one short comment (what was marked + Draft PR links) to the task's ticket. +- **Run-level notify (§7).** Send **one** STAGE_COMPLETE notification, with `--skill draft` and the Draft PR link(s) as the payload: + + ```bash + bash ${CLAUDE_PLUGIN_ROOT}/lib/notify.sh --type STAGE_COMPLETE --skill draft \ + --title ": Draft PR ready" --body "" + ``` + +- **Print the Draft PR link(s)** and stop. + +`/draft` never merges and never flips a PR to ready — flipping to ready is `/do` Draft execution's job, after the Markers are implemented and the grep gate passes. + +--- + +## Iteration + +A re-run against an existing Draft: the input is a Draft PR URL, or a `` whose `.yoke/ai//-draft.md` exists (detected in Phase 0). The user commented on the Draft PR; redraw the Markup per the comments. Still no pause. + +1. **Read the Draft artifact and the plan** — `-draft.md` for the PR(s), branch(es), and repo set; `-plan.md` for the decomposition. Enter the recorded branch(es) per finish.md §2. +2. **Fetch the PR comments** — both kinds: + + ```bash + gh api repos/{owner}/{repo}/pulls/{pr}/comments # inline review comments, with ids for replies + gh pr view --comments # top-level conversation comments + ``` + +3. **Redraw the Markup in the same branch.** Comments outrank the existing Markers and the plan — the user's latest word wins. Move, rewrite, add, or delete Markers and skeleton per each comment; keep the build green per `reference/markup-format.md`. +4. **Update the plan artifact** when a comment changes the decomposition — `-plan.md` and the Markup stay one whole. Re-commit it. +5. **Commit and push to the same branch.** The Draft PR updates in place; the pr skill's update path preserves the draft state — never open a second PR. +6. **Reply in every inline review thread** with what changed and where: + + ```bash + gh api --method POST repos/{owner}/{repo}/pulls/{pr}/comments \ + -f body="" -F in_reply_to= + ``` + + Thread resolution stays the user's. + +7. **Re-fire the notify** — the same STAGE_COMPLETE call as Phase 4, `--skill draft`, title `: Draft PR ready`. + +Any number of rounds. When the user is ready, `/do ` (or `/do `) executes the Draft — implements the Markers, replies in threads, flips the PR to ready. + +--- + +## Rules + +- **Never pause.** No confirmation gate, no AskUserQuestion — the Draft PR is the pause. +- **Mark, never implement.** No logic anywhere in Markup — Markers plus compilable stubs only, per `reference/markup-format.md`. +- **The build stays green.** Type-check/build must pass on every commit; tests may be red. +- **All artifacts under `.yoke/`.** Plan and Draft artifact both live in `.yoke/ai//`. +- **Commits by convention.** Format and ticket ID from `${CLAUDE_PLUGIN_ROOT}/skills/gca/reference/commit-convention.md`. +- **Glossary vocabulary.** Draft, Markup, Marker, Draft PR — use the `.yoke/context.md` terms verbatim. +- **Never merge, never flip to ready.** `/draft` ends at the Draft PR; `/do` Draft execution flips it. +- Language: match the ticket/input language, or follow the project-level definition in CLAUDE.md / AGENTS.md. diff --git a/skills/help/SKILL.md b/skills/help/SKILL.md index 183f5f5..c8368ed 100644 --- a/skills/help/SKILL.md +++ b/skills/help/SKILL.md @@ -112,6 +112,17 @@ Same grilling, plus it maintains the glossary `.yoke/context.md` and ADRs in `.y /yoke:grill-docs design the order cancellation flow ``` +### /draft — optional marking step between grill and do + +A do-shaped run that marks instead of implementing: it projects the agreed plan onto the code as Markup (`TODO(yoke):` Markers plus a compilable skeleton) and opens a GitHub Draft PR for remote review. Never pauses — the Draft PR is the pause. Comment on the Draft PR and re-run `/yoke:draft` to re-mark, or run `/yoke:do ` to implement the Markers and flip the PR to ready. + +**Input:** ticket URL, description, or nothing — fresh marking; a Draft PR URL or a drafted `` — iteration → **Output:** a GitHub Draft PR carrying the Markup + `.yoke/ai//-draft.md` + +``` +/yoke:draft https://github.com/owner/repo/issues/86 +/yoke:draft https://github.com/owner/repo/pull/90 +``` + ### /prd — PRD from context Synthesizes the current conversation into a PRD, publishes it as a GitHub issue (`ready-for-agent`), and saves a local copy. No interview. @@ -160,6 +171,7 @@ The everyday loop is short: **grill → do → PR on GitHub → merge**. `do` ca ``` /yoke:bootstrap # prepare the project (first run) — writes .yoke/flow.md /yoke:grill # stress-test the idea (grill-docs also captures terms + ADRs) +/yoke:draft # optional: mark the code, open a Draft PR to review before implementing /yoke:do # execute end to end → a ready pull request # → review the PR on GitHub, comment, approve /yoke:merge # merge, cascade, deploy/release, transition the ticket, clean up