diff --git a/.agents/skills/quest-complete/SKILL.md b/.agents/skills/quest-complete/SKILL.md index 59f863c3..f42c1270 100644 --- a/.agents/skills/quest-complete/SKILL.md +++ b/.agents/skills/quest-complete/SKILL.md @@ -1,6 +1,6 @@ --- name: quest-complete -description: Decide which open PRs to merge, then queue them. +description: Decide which open PRs to merge and settle what quests and drafts wait on, then queue the merges. --- Run `quest skill complete` and follow its output. diff --git a/.agents/skills/quest-unblock/SKILL.md b/.agents/skills/quest-unblock/SKILL.md deleted file mode 100644 index 725d29bd..00000000 --- a/.agents/skills/quest-unblock/SKILL.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -name: quest-unblock -description: Walk the maintainer through every quest and draft PR waiting on them, and clear waits that have resolved. ---- - -Run `quest skill unblock` and follow its output. -If `quest` is not installed, follow https://github.com/moq-dev/quest/blob/main/SETUP.md first. diff --git a/.claude/skills/quest-complete/SKILL.md b/.claude/skills/quest-complete/SKILL.md index 4da3e568..f0da986b 100644 --- a/.claude/skills/quest-complete/SKILL.md +++ b/.claude/skills/quest-complete/SKILL.md @@ -1,6 +1,6 @@ --- name: quest-complete -description: Decide which open PRs to merge, then queue them. +description: Decide which open PRs to merge and settle what quests and drafts wait on, then queue the merges. allowed-tools: Bash(quest skill complete) PowerShell(quest skill complete) --- diff --git a/.claude/skills/quest-unblock/SKILL.md b/.claude/skills/quest-unblock/SKILL.md deleted file mode 100644 index a54ed554..00000000 --- a/.claude/skills/quest-unblock/SKILL.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -name: quest-unblock -description: Walk the maintainer through every quest and draft PR waiting on them, and clear waits that have resolved. -allowed-tools: Bash(quest skill unblock) PowerShell(quest skill unblock) ---- - -!`quest skill unblock; echo "If quest skill unblock printed an error instead of instructions, install quest as https://github.com/moq-dev/quest/blob/main/SETUP.md describes, then run quest skill unblock and follow its output."` diff --git a/README.md b/README.md index 33904db8..efeaa5d1 100644 --- a/README.md +++ b/README.md @@ -206,7 +206,7 @@ the item; `--maintainer` keeps only the maintainer's, and `--json` prints party is the maintainer's. Drafts come from the upstream's open PRs, found as for `unblocked --unclaimed`; without the remote, off GitHub, or when GitHub cannot be read, it lists the tree's items -and warns that drafts were skipped. `/quest-unblock` walks you through them. +and warns that drafts were skipped. `/quest-complete` walks you through them. ## Claim a quest @@ -1841,10 +1841,9 @@ arrives with the guide sections and other skills it builds on, in one call: | `quest-iterate` | Iterate on an open PR to settle its open decisions, fix CI and review findings, and push. | | `quest-review` | Review a PR's branch locally with a model other than its latest writer, then mark it ready for review. | | `quest-merge` | Queue a PR to land, running `quest-iterate` first when it needs work. | -| `quest-complete` | Run only `quest-run`'s PR decisions: decide which open PRs to merge, then queue them. | +| `quest-complete` | Run only `quest-run`'s PR decisions and settle what quests and draft PRs wait on you: decide which open PRs to merge, clear resolved waits, then queue the merges. | | `quest-run` | Orchestrate a project from one session: start ready quests and take PRs to merge in a loop, until only your decisions remain. | | `quest-afk` | Keep a session such as `quest-run` going while you are away: it acts on its recommendations, defers merges, and walks you through the rest when you return. | -| `quest-unblock` | Settle what quests and draft PRs wait on you, and clear waits that have resolved. | | `quest-delete` | Abandon a quest, deleting it in its own PR. | Use `/quest-plan` in Claude Code or `$quest-plan` in Codex. Skills coordinate diff --git a/assets/AGENTS.md b/assets/AGENTS.md index e9a7d5c9..618216e2 100644 --- a/assets/AGENTS.md +++ b/assets/AGENTS.md @@ -100,16 +100,16 @@ End every quest skill with a final summary in sections, such as the PRs and thei ## Creation Quests are created in PRs and reviewed. -Search the tree and git history first before making a new quest. +Search the tree and git history before making a new quest. Split independently completable work into separate quests. Group related quests in an epic; its README holds the work no child owns. -Work found along the way that is worth a quest is a follow-up: add it to the PR that found it, as a new quest placed and sized by the rules here and the repository's, or as an edit to the quest that already owns the work; never as an agent-session task or a GitHub issue. +Work found along the way that is worth a quest is a follow-up: add it to the PR that found it, as a new quest placed and sized by these rules and the repository's, or an edit to the quest that owns the work; never as an agent-session task or a GitHub issue. Drop one you would call optional or worth doing only if it matters. Answer each of its decisions you can with your recommendation in its Plan, and list each you cannot as a `Maintainer:` decision item under its `Waiting`. The PR body's `## Follow-ups` section links each one with its open decisions, which neither keep the PR a draft nor stop its pick. -A PR that adds follow-ups lands only on the user's pick: the round that picks it to merge, in any client, also asks about each follow-up in questions of its own, apart from the pick and other follow-ups, in the Questions form: whether to keep it, and one question per open decision. +A PR that adds follow-ups lands only on the user's pick: the round that picks it to merge, in any client, also asks about each follow-up in questions of its own, apart from the pick and each other, in the Questions form: whether to keep it, and one per open decision. Before it lands, record each answer in its quest's Plan, removing that `Waiting` item, and remove each dropped follow-up, with `quest rm` for a new quest. A follow-up for work another repository's quest tree owns stays in `## Follow-ups` for `/quest-plan` there. @@ -119,36 +119,35 @@ So is anything waiting on an outside party or a human action (an upstream fix, a Its `Waiting` section names who acts, the condition, and how to check or advance it; it is deleted once the condition clears. Automate a step rather than leave it to a person whenever an agent can take it. A `Maintainer:` item says why an agent cannot take the step and what automation was considered. -Record a wait there, not in a draft PR that only holds evidence or steps for a person. -Unlike a blocked quest it stays ready, so it resurfaces every time ready work is triaged instead of stalling in the backlog. -`quest waiting` lists every waiting item, the maintainer's first, ranked by what each unblocks, and `/quest-unblock` walks the maintainer through them. +Record a wait there, not in a draft PR holding only evidence or steps for a person. +Unlike a blocked quest it stays ready, so it resurfaces whenever ready work is triaged instead of stalling in the backlog. +`quest waiting` lists every waiting item, the maintainer's first, ranked by what each unblocks, and `/quest-complete` walks the maintainer through them. ## Execution Start only ready quests. -First question whether the quest is still needed: its problem may no longer be real, or a later change may have made its plan the wrong solution. +First question whether the quest is still needed: its problem may no longer be real, or a later change may have made its plan wrong. If so, stop and propose rewriting or deleting it. -Before claiming, also check that no open PR already does its work: search open PRs whose title, body, or changed files name the quest's path or the files its Plan names, or read the matches a coordinator's brief lists. +Before claiming, check that no open PR already does its work: search open PRs whose title, body, or changed files name the quest's path or its Plan's files, or read the matches a coordinator's brief lists. Stop and report a PR that makes the same change; one that only touches the same files is no overlap. `quest unblocked` ranks the ready quests, and `quest unblocked ` prints what blocks one. With `--unclaimed`, it skips quests someone holds and lists them on stderr. -Work is taken when it has an open change on the forge. Check open changes -before starting. These states stay out of the quest file. +Work is taken when it has an open change on the forge, so check before starting; +these states stay out of the quest file. On GitHub, a quest is claimed by an open PR whose head branch is the quest's branch, from the upstream repository or a fork, or by that branch upstream while its PR is being opened. The earliest open PR holds the claim. Claim a quest with `quest start `: it checks both, pushes an empty -claim commit to the quest's branch, and opens a draft PR from it right away. -That PR becomes the quest's PR. +claim commit to the quest's branch, and opens a draft PR from it right away, which becomes the quest's PR. In a fork's clone, it pushes to the fork and opens the PR upstream; a fork whose parent keeps no quests is its own upstream. It exits 3 when the quest is blocked or someone else holds it; pick other work. `quest start --release ` gives back a claim before any work is pushed. If a claim looks stale, such as a draft without `## Waiting` or a -branch with no open PR that has been quiet a long time, offer the user to take +branch with no open PR quiet a long time, offer the user to take it over, saying how long ago it was last active. A quest's branch is its path without `.md`. @@ -160,14 +159,14 @@ Never rename an open PR's head branch either: GitHub closes the PR. Its warning that the quest's local branch already exists is not that refusal: the claim succeeded, and the branch holds an earlier attempt. Switch to it, merge the claim commit the warning names, and resume that attempt; stop and report only if another worktree has the branch checked out. -Push the quest branch as `quest context` describes for pull requests. The claim push from `quest start`, made before its draft PR exists, is exempt from confirming the PR is open. +Push the quest branch as `quest context` describes for pull requests. The claim push from `quest start`, made before its PR exists, is exempt from confirming it is open. -Prefer the exhaustive solution: a quest's PR handles every case of its problem, including those its reviews find, rather than landing part of it and splitting the rest into new quests. +Prefer the exhaustive solution: a quest's PR handles every case of its problem, including those its reviews find, instead of splitting the rest into new quests. Leave work for later only when it waits on an outside condition or a maintainer decision, or lies outside the quest's Goal. A quest's PR leaves its quest accurate when it merges. The PR that finishes a quest deletes its file and every link to it. -A PR that leaves work rewrites the quest to what remains, rather than noting it only in the PR body. +A PR that leaves work rewrites the quest to what remains, not just the PR body. `quest check --base ` flags a quest branch whose diff does neither. When a quest is complete, review it locally and mark its PR ready for review with `/quest-review`, even if you made choices without asking; list those choices in the PR body for review. @@ -188,16 +187,16 @@ Remove the `quest` label from issues no other quest tracks. ## Coordination Relay no interim report: resume a sub-agent that ended its turn on one, telling it to block until its work finishes. -A long-running coordinator lets compaction bound its context: it keeps what must outlast compaction in the forge and the quest tree, and reads a PR's state afresh before acting on it rather than trusting earlier turns. +A long-running coordinator lets compaction bound its context: what must outlast it lives in the forge and the quest tree, and a PR's state is read afresh before acting, not trusted from earlier turns. Start each sub-agent in the background with its own isolated worktree, since agents cannot write to a worktree their parent created. It reports only when done or blocked, and never waits on GitHub CI, reviews, or merges; stay silent on its interim notifications. As each reports, explain its result in a few lines: its PR, whether it is still a draft, and its open decisions with recommendations. -Once two agents report the same blocker, such as a check failure that reproduces on the base or a reviewer outage, name it with its evidence in the brief of each agent started after, and report it once. +Once two agents report the same blocker, such as a check failure that reproduces on the base or a reviewer outage, name it with its evidence in each later agent's brief, and report it once. -A report that is an API error, such as a rate limit or an overload, or a cancellation the user did not ask for, is not a result. +A report that is an API error such as a rate limit or overload, or a cancellation the user did not ask for, is not a result. Resume that agent by messaging it, or with `quest agent resume` for a headless one, so it keeps its context and checkout. -If it cannot be resumed, start a new one with the same brief plus its PR, its checkout, and the token of any hold it took, which `quest status ` shows, so it continues that work and keeps the hold. +If it cannot be resumed, start a new one with the same brief plus its PR, checkout, and the token of any hold it took (shown by `quest status `), so it continues and keeps the hold. While the error persists, such as a rate limit before its reset, resume and start nothing until it clears, and report it once. Answer these requests at any point, without stopping running agents: @@ -206,7 +205,7 @@ Answer these requests at any point, without stopping running agents: - "pause": start nothing new until the user says to resume; reports are handled as usual. - "status": a compact list of each agent with its quest or PR, state, and how long ago it started or last reported. -Once every sub-agent has finished, remove each agent checkout `quest worktree status` lists with `quest worktree remove`, since Claude never removes a subagent's checkout; it refuses one holding unpreserved work. +Once every sub-agent has finished, remove each agent checkout `quest worktree status` lists with `quest worktree remove`, since Claude never removes a subagent's checkout; it refuses one with unpreserved work. Remove other local worktrees and branches whose tip is the head of a merged PR; squash merges leave that tip off the base branch. Leave the worktree you are running in and any holding uncommitted work or refused removal; list those in your summary. @@ -214,24 +213,24 @@ Run each agent at an entry of `quest`'s ranked lists unless the repository's `AG Size each `/quest-iterate` you dispatch as a quest, by the work left on its PR, and name that size in its brief. Start it on the PR's writer, the model of its first `Implementer:` line, at the entry `quest models --writer ` prints, waiting out its usage limit so the other model can review; a PR whose writer no list names, such as `unknown` or a retired model, takes its size's first entry that can run. -`quest agent start --harness --model --effort --permission-mode ` runs a headless agent on that CLI's own login; start it as a background command in its own isolated worktree, so the harness reports its exit as it would a sub-agent's. +`quest agent start --harness --model --effort --permission-mode ` runs a headless agent on that CLI's own login; start it as a background command in its own isolated worktree, so the harness reports its exit like a sub-agent's. `--permission-mode` is Claude Code's permission mode, or Codex's sandbox mode. It prints the session id, then the outcome and the agent's final reply, and exits 3 at the account's usage limit, or 4 when the CLI is logged out, printing the login command. -Tell the agent that it cannot prompt, so it ends with its decisions and recommendations in its final reply, and that ending its turn kills its background commands, so it waits in the foreground. -Answer it in the background with `quest agent resume`, passing the same options, the worktree, the session id, and the answer. +Tell the agent it cannot prompt, so it ends with its decisions and recommendations in its final reply, and that ending its turn kills its background commands, so it waits in the foreground. +Answer it in the background with `quest agent resume`, passing the same options, worktree, session id, and the answer. Stop one with `quest agent stop `, and each you started that still runs before you finish; `--all` would stop other sessions' agents too. ## Questions Open each prompt with the context to answer it without opening the quest or PR: what the work is, the problem it hit, and what each option would change. -Name and explain anything the agent or its PR introduced, such as a new term, file, check, or credential, since the user may not have followed the work. +Name and explain anything the agent or its PR introduced, such as a new term, file, check, or credential, since the user may not have followed it. Then give your recommendation and ask synchronously with a blocking interactive question tool when available and allowed in the current mode. Recommend in every prompt, a multiple-choice list included: mark each option you recommend and give a one-line reason for each you would leave out. An answer such as "whatever you recommend" picks your recommendations; act on them without asking again. Do not use asynchronous question tools. If no blocking tool is available, or it returns without an answer, put the question and numbered choices in your final reply and end the turn. -Resume when the user answers; do not bury the question in a progress update or replace the wait with sleeps or timed polls. +Resume when the user answers; do not bury the question in a progress update or wait with sleeps or timed polls. Silence, elapsed time, and a preselected recommendation are not answers or approval. Do not advance the interview or act on an unanswered choice. Already authorized background work may continue while the foreground waits. diff --git a/assets/skills/afk.md b/assets/skills/afk.md index 9b8c3ee3..e8853b35 100644 --- a/assets/skills/afk.md +++ b/assets/skills/afk.md @@ -25,4 +25,4 @@ Carry on each pick the user already made until it lands or needs them again. When the work finishes, end with a final summary holding only the blockers, each linked, with its options and your recommendation, so a fresh session can act on it; the choices you took live in the PRs' bodies. A message that adds to these instructions, such as a newly granted merge or more work, amends them, and afk continues. -Any other message is the user's return: afk ends. Answer it, run `/quest-unblock` on the quests and drafts among the blockers, then resume the session's skill, which asks the questions it deferred. +Any other message is the user's return: afk ends. Answer it, run `/quest-complete` on the quests and drafts among the blockers, then resume the session's skill, which asks the questions it deferred. diff --git a/assets/skills/complete.md b/assets/skills/complete.md index 7c436838..ddebd449 100644 --- a/assets/skills/complete.md +++ b/assets/skills/complete.md @@ -1,8 +1,23 @@ --- -description: Decide which open PRs to merge, then queue them. -guide: Summaries +description: Decide which open PRs to merge and settle what quests and drafts wait on, then queue the merges. +guide: Format, Deletion, Summaries skills: run --- -Run only the Pull requests part of `/quest-run` below, with its loop's rounds: refresh the open PRs as sub-agents report, and stop once every PR in scope is decided and every sub-agent has reported. +Run only `/quest-run`'s Pull requests part below with its loop's rounds, plus the waits: refresh both as sub-agents report, and stop once all have reported and every PR and wait in scope is decided, skipped, or left to an outside party. Start no quests, and wait on no PR. +The skill argument, if any, filters the PRs and waits in scope. + +## Waits + +Take the quests' and drafts' `## Waiting` items from `quest waiting --json`, which ranks them; rerun it with GitHub access if it warns that drafts were skipped, and skip a draft another session holds, as for PRs. +Rewrite a quest that waits in prose, such as a Goal opening "Waiting on the maintainer", into a `## Waiting` section, and treat it like the rest. +Check each condition yourself, in parallel sub-agents. +An outside party's item that holds stays, asked about only when the user can advance it, such as by requesting an upstream release. +Ask each maintainer item left among the round's questions, in that order, saying what it unblocks; a skip stands for the session. +For an action only the user can take, give the exact steps and the check you will run once they report it done; take any secret through the host's secret prompt. + +Settle a draft's items with its PR, naming cleared ones in its `/quest-iterate` brief. +Remove a quest's cleared item, or its answered one after recording the answer and reason in its Plan as `Decided (maintainer, /quest-complete): ...`; `quest rm` a quest whose only purpose was that wait, editing the mentions it reports and recording why and any answer in the PR body's `## Decisions`, and drop the `quest` label from issues no other quest tracks. +Make these edits in one draft PR on a `quest-complete/` branch, run `quest check` on the edited tree, then `/quest-review`; it is then in scope like any PR. +The final summary lists the waits settled, cleared, or deleted, and each still held, with who acts and its check's result. diff --git a/assets/skills/run.md b/assets/skills/run.md index caf1c817..05cd5080 100644 --- a/assets/skills/run.md +++ b/assets/skills/run.md @@ -17,7 +17,7 @@ A brief gives the task, its reason and context, such as the quest or PR and the Starting quests asks the user nothing: each agent works headless, and its decisions surface in its PR. `quest unblocked --unclaimed --json` ranks the unclaimed ready quests, reading the upstream tree afresh; start them in that order, as many at once as the harness allows. -It lists each skipped claim on stderr with how long ago it was last active; name any that look stale in the summary, for the user to take over. +It lists each skipped claim on stderr, with how long ago it was last active when it has an open PR; name any that look stale in the summary, for the user to take over. Start every quest you would recommend: well planned, with no blockers, and no conflict with work already started. For one waiting on an outside condition, first check whether it has cleared. Skip the rest, such as one you doubt is worth doing at all or now, and list each in the summary with why and your recommendation between `/quest-plan`, which redesigns it or moves it down, and `/quest-delete`. @@ -34,7 +34,7 @@ Skip a quest whose list runs out, and report each harness's outage once. ## Pull requests Read each open PR, drafts included, with `quest status`, and skip one another session holds by its `hold` or `starter-hold` record, offering to take over only one that looks stale. -List a draft whose `## Waiting` holds no decision for the user, only outside conditions or actions, once in the summary, pointing to `/quest-unblock`. +List a draft whose `## Waiting` holds no decision for the user, only outside conditions or actions, once in the summary, pointing to `/quest-complete`. Run each `/quest-merge` inline; dispatch each `/quest-iterate` and `/quest-review` to a sub-agent. Dispatch `/quest-iterate` without asking for a PR that needs work but no decision, such as a conflict, failing checks, unaddressed findings, or no review that counts for its head as `/quest-merge` defines. diff --git a/assets/skills/unblock.md b/assets/skills/unblock.md deleted file mode 100644 index 28af1f8a..00000000 --- a/assets/skills/unblock.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -description: Walk the maintainer through every quest and draft PR waiting on them, and clear waits that have resolved. -guide: Format, Creation, Deletion, Coordination, Summaries -skills: grill, plan ---- - -The goal is to unblock the most work for each thing the maintainer settles, and to clear every wait whose condition has already resolved. -The skill argument, if any, filters the quests or PRs in scope. - -Gather what waits: - -- `quest waiting --json` lists each quest's `## Waiting` items and each draft PR's hand-back items, the maintainer's first, ranked by what each unblocks; a draft's entry carries its URL in `pr`. If it warns that drafts were skipped, restore GitHub access and rerun it rather than go on without them. Check each draft's holds with `quest status `, and skip one another session holds as `/quest-run` does. -- Quests that wait in prose without the section, such as a Goal opening "Waiting on the maintainer" or "Waits on moq-dev/moq". Rewrite each into a `## Waiting` section in this skill's PR, and treat it like the rest. - -Checking a condition is your job, never the user's. Check every item yourself, outside parties' and the maintainer's alike: run its check, or dispatch sub-agents to run several at once. -A condition that has cleared needs no question: remove its item, or delete a quest that only waited on it, with `quest rm`. -An outside party's item that still holds stays, unless the maintainer can advance it, such as by asking upstream for a release; then offer that as a question. - -Put every remaining maintainer item to the user with the grill skill's rounds, in `quest waiting`'s order. -Each question says what it unblocks, the context needed to answer without opening the quest or PR, and the options with your recommendation. -For an action only the user can take, such as opening an account or granting access, give the exact steps and the check you will run; when they report it done, run the check before treating it as cleared. -Collect any secret through the host's secret prompt, never in chat. -A skip stands for this session; leave that item as it is. - -Record each answer where its wait lives: - -- **Quest:** record the decision and its reason in the quest's Plan, as `Decided (maintainer, /quest-unblock): ...`, and remove the item. Delete a quest whose only purpose was the wait, and record its decision in this skill's PR body's `## Decisions` section instead. -- **PR:** dispatch `/quest-iterate` in a sub-agent with its own worktree, with the answers in its brief. It applies them, runs the PR's reviews, and leaves merging to `/quest-merge` or `/quest-run`. - -Make every quest edit in one PR on a `quest-unblock/` branch, run `quest check`, open it as a draft, and run `/quest-review` on it, which reviews the branch, marks the PR ready, and offers its merge picks; merging it waits on a `/quest-merge` pick, like any PR. - -End with the final summary the guide describes, covering: - -- what was settled, cleared, or deleted; -- the PRs and the sub-agents dispatched; -- each item still waiting, with who acts and what its check found. diff --git a/src/cli/skills.ts b/src/cli/skills.ts index e9329cea..db7e0b9b 100644 --- a/src/cli/skills.ts +++ b/src/cli/skills.ts @@ -26,7 +26,6 @@ import review from "../../assets/skills/review.md"; import run from "../../assets/skills/run.md"; import spawn from "../../assets/skills/spawn.md"; import start from "../../assets/skills/start.md"; -import unblock from "../../assets/skills/unblock.md"; /** The quest contract: the format, workflow, and rules every skill builds on. */ export const GUIDE: string = guide; @@ -185,7 +184,6 @@ export const SKILLS: readonly Skill[] = Object.entries({ run, spawn, start, - unblock, }).map(([name, text]) => new Skill(name, text)); /** The skill called `name`, if this version ships one. */