diff --git a/.agents/skills/quest-afk/SKILL.md b/.agents/skills/quest-afk/SKILL.md new file mode 100644 index 00000000..dfb76ed9 --- /dev/null +++ b/.agents/skills/quest-afk/SKILL.md @@ -0,0 +1,7 @@ +--- +name: quest-afk +description: Keep quest work moving while the user is away, leaving every decision for their return. +--- + +Run `quest skill afk` and follow its output. +If `quest` is not installed, follow https://github.com/kixelated/quest/blob/main/SETUP.md first. diff --git a/.claude/skills/quest-afk/SKILL.md b/.claude/skills/quest-afk/SKILL.md new file mode 100644 index 00000000..dfb76ed9 --- /dev/null +++ b/.claude/skills/quest-afk/SKILL.md @@ -0,0 +1,7 @@ +--- +name: quest-afk +description: Keep quest work moving while the user is away, leaving every decision for their return. +--- + +Run `quest skill afk` and follow its output. +If `quest` is not installed, follow https://github.com/kixelated/quest/blob/main/SETUP.md first. diff --git a/README.md b/README.md index e4355494..d0db8c15 100644 --- a/README.md +++ b/README.md @@ -514,15 +514,13 @@ the version you pin decides what your agents follow: | `quest-ready` | Mark a draft PR ready for review, wait for an automated review, then decide whether to merge. | | `quest-merge` | Merge a quest's PR once CI and reviews pass, completing the quest. | | `quest-complete` | Decide which open PRs to merge, then merge them in parallel. | +| `quest-afk` | Keep starting agreed work while you are away, leaving every decision for your return. | | `quest-delete` | Abandon a quest, deleting it in its own PR. | Use `/quest-plan` in Claude Code or `$quest-plan` in Codex. Skills coordinate within your agent session. A started quest stops at a pull request; merging is a separate invocation, so you review every change. -Before stepping away, add `afk` to `/quest-spawn` or `/quest-complete`: the -agent acts on its own recommendations and asks only before merging or deleting. - To bill spawned agents to API keys instead of your agent's account, export `QUEST_API_KEYS` with one or more whitespace-separated keys and run `/quest-spawn api`. Entries may be secret references such as 1Password `op://` diff --git a/assets/AGENTS.md b/assets/AGENTS.md index 53fdf31b..b7568f6b 100644 --- a/assets/AGENTS.md +++ b/assets/AGENTS.md @@ -82,6 +82,8 @@ A sub-agent's brief carries the quest or PR, the user's picks, and the scope; it A background agent reports any decision needing user input, with context and a recommendation, to the foreground agent instead of prompting the user itself. Honor explicit instructions to proceed unattended within their scope; do not ask a question and then silently choose its answer. +End every quest skill with a final summary in sections, such as the PRs and their states, the open decisions with recommendations, and suggested follow-ups, so a user returning to the session first sees what needs them. + ## Creation Quests are created in PRs and reviewed. diff --git a/assets/skills/afk.md b/assets/skills/afk.md new file mode 100644 index 00000000..5b3d857a --- /dev/null +++ b/assets/skills/afk.md @@ -0,0 +1,23 @@ +--- +description: Keep quest work moving while the user is away, leaving every decision for their return. +--- + +Before you begin, run `quest guide`, `quest skill spawn`, and `quest skill complete`, and read their output completely. + +The user has stepped away and will not answer. +Your goal is to keep the work they already agreed to moving, asking nothing, until only work that needs a decision remains. +Dispatch, limit, and clean up agents as those skills describe. +This skill takes no arguments: it filters no quests or PRs and bills agents to this session's account. + +Make no decisions, not even by acting on your own recommendation; skip each one and leave it for the user: + +- Start every ready quest that `/quest-spawn` starts without asking; leave each quest it would ask about unstarted. +- Carry on each action the user already picked, such as a `/quest-merge` pick, until it lands or needs the user again. +- Pick no skip, `/quest-ready`, `/quest-iterate`, `/quest-merge`, or `/quest-delete` for a PR the user has not, so nothing merges or is deleted on your judgment. A started agent still runs `/quest-ready` itself when its quest finishes with no decisions, as `/quest-start` describes. +- Answer no decision an agent reports. Its PR stays a draft whose `## Decisions needed` section lists the decision with a recommendation. +- Hold `/quest-plan` sessions, stale claims, and suggested follow-ups for the user. + +As merges land, recompute the ready quests and start any that newly qualify. +Finish once every agent has reported, every picked action has landed or needs the user, and no quest remains that starts without asking. + +Write the final summary so a new session can act on it without this one's context, letting the user start fresh on their return: link each quest and PR, give each skipped decision with its options and your recommendation, and describe every follow-up the agents suggested fully enough to hand to `/quest-plan`. diff --git a/assets/skills/complete.md b/assets/skills/complete.md index 44944eae..652d911c 100644 --- a/assets/skills/complete.md +++ b/assets/skills/complete.md @@ -43,12 +43,3 @@ Dispatch already selected actions before asking the next question; background wo Once every sub-agent has finished, remove 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; list those in your summary. - -## Unattended - -With an `afk` argument, the user has stepped away: your recommendation stands in for their pick of skip, `/quest-ready`, or `/quest-iterate`, so dispatch it without asking. -It also answers each simple decision a sub-agent reports. -Still ask about each `/quest-merge` and `/quest-delete` you recommend, as one simple question with your recommendation first. -Skip a PR or reported decision that is not simple, noting why in the summary instead of asking. -Hold suggested `/quest-plan` follow-ups for the summary, since planning is an interview. -The rest of the argument still filters the PRs in scope. diff --git a/assets/skills/spawn.md b/assets/skills/spawn.md index b7346ee8..9952cba3 100644 --- a/assets/skills/spawn.md +++ b/assets/skills/spawn.md @@ -51,15 +51,6 @@ Run selected `/quest-plan` sessions in the foreground. Once every sub-agent has finished, remove 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; list those in your summary. -## Unattended - -With an `afk` argument, the user has stepped away: your recommendation stands in for their pick of `/quest-start`, skip, `/quest-ready`, or `/quest-iterate`, so act on it without asking. -It also answers each simple decision an agent reports, including when you resume a headless agent. -Still ask about each `/quest-merge` and `/quest-delete` you recommend, as one simple question with your recommendation first. -Skip a quest, PR, or reported decision that is not simple, noting why in the summary instead of asking. -Hold `/quest-plan` sessions, including deprioritizing and suggested follow-ups, for the summary, since planning is an interview. -The rest of the argument still filters the quests in scope. - ## API keys With an `api` argument, bill agents to API keys instead of this session's account: run each as a headless agent through `quest agent` rather than as a sub-agent. diff --git a/quest/m0/helpers/README.md b/quest/m0/helpers/README.md index 2ffc5ace..7f63ce59 100644 --- a/quest/m0/helpers/README.md +++ b/quest/m0/helpers/README.md @@ -56,7 +56,6 @@ commands from Sep-Oct. Session counts in each child come from that window. ## Required -- [Unattended work](/quest/m0/helpers/afk.md) - `/quest-afk` replaces the `afk` argument: it skips every decision and keeps starting agreed work; every skill ends with a summary - [PR state commands](/quest/m0/helpers/pr-states.md) - `quest iterate`, `ready`, `merge`, and `release` label the one owner of a PR - [Complete loop](/quest/m0/helpers/complete-loop.md) - `/quest-complete` re-scans PRs, keeps picks and holds, and counts rounds per PR - [Headless agents](/quest/m0/helpers/headless-agents.md) - `/quest-spawn api` launches, resumes, and stops billed agents through one command auto mode allows diff --git a/quest/m0/helpers/afk.md b/quest/m0/helpers/afk.md deleted file mode 100644 index b7e7ab0d..00000000 --- a/quest/m0/helpers/afk.md +++ /dev/null @@ -1,56 +0,0 @@ -# [S] Keep working unattended with /quest-afk - -## Goal - -`/quest-afk` keeps quest work moving while the user is away and asks -nothing: it skips every decision instead of choosing one, leaves each skipped -decision on its PR, and keeps starting agents and PRs for work the user -already agreed to. Every quest skill ends with a final summary, so returning -starts with what needs the user. This replaces the steering the user typed in -about 20 moq sessions ("I'm going to bed", "you don't need to decide -everything, only when blocked", "I'm back, what decisions need to be made") -and the one-line global `/afk` and repository `/recommended` skills. - -Non-goals: a wind-down mode that stops dispatching ("just make the PRs then -stop"), and noticing the user's return; the final summary covers it. - -## Plan - -Decided 2026-10-21 (user), replacing the 2026-10-19 `afk` argument on -`/quest-complete` and `/quest-spawn`, from an audit of a month of moq -maintainer transcripts. That argument landed the same day in -[kixelated/quest#166](https://github.com/kixelated/quest/pull/166) as an -`## Unattended` section in `assets/skills/complete.md` and -`assets/skills/spawn.md`, plus a README sentence. It acts on its own -recommendations, answers simple decisions agents report, and still asks about -each merge and delete. This quest replaces it: - -- A skill of its own, `/quest-afk`, not an argument on two skills. Delete - both `## Unattended` sections and the README's `afk` sentence in the same - PR. At the user's request the old skills were removed the same day, ahead - of this quest, so the user types those instructions by hand until it - lands: the global `/afk` link in kixelated/dotfiles, the `afk` skill in - [kixelated/skills#8](https://github.com/kixelated/skills/pull/8), and the - `/recommended` links in - [moq-dev/moq#6200](https://github.com/moq-dev/moq/pull/6200) and - moq-dev/moq.pro. -- It makes no decisions. Every question a quest skill would ask is skipped, - not answered with its recommendation: the PR stays a draft listing the - decision with a recommendation, a quest that would need asking is left - unstarted and listed, and suggested follow-ups wait for `/quest-plan`. - Unlike the landed argument, it picks no skip, `/quest-ready`, or - `/quest-iterate` for a PR the user has not picked, answers no reported - decision, and asks nothing about merges or deletes: it never merges or - deletes on its own judgment. -- It keeps going as far as already agreed work allows: it starts ready - quests that `/quest-spawn` starts without asking, and carries on the actions - the user already picked, until nothing is left that needs no decision. -- Decided (user): every quest skill ends with a final summary in sections, - such as its PRs and their states, the open decisions, and suggested - follow-ups. Don't fix the exact shape. State this once in the guide rather - than in each skill. -- Write `assets/skills/afk.md` following `PROMPTING.md`, reusing the spawn - and complete skills' dispatch rules instead of restating them. Register it - in `src/cli/skills.ts` and the README's skill table; existing - repositories get its `quest-afk` stub by rerunning `quest init`. The user - asked for the skill and guide edits through this plan. diff --git a/quest/m0/helpers/complete-loop.md b/quest/m0/helpers/complete-loop.md index a63eddfd..a3e9758f 100644 --- a/quest/m0/helpers/complete-loop.md +++ b/quest/m0/helpers/complete-loop.md @@ -28,4 +28,3 @@ edits through this plan. ## Related - [PR state commands](/quest/m0/helpers/pr-states.md) - also rewrites how `complete` dispatches and skips held PRs -- [Unattended work](/quest/m0/helpers/afk.md) - carries on picks the user already made diff --git a/src/cli/skills.ts b/src/cli/skills.ts index 97f8b296..e2af2166 100644 --- a/src/cli/skills.ts +++ b/src/cli/skills.ts @@ -6,6 +6,7 @@ // upgrading never rewrites repository files. import guide from "../../assets/AGENTS.md"; +import afk from "../../assets/skills/afk.md"; import audit from "../../assets/skills/audit.md"; import complete from "../../assets/skills/complete.md"; import del from "../../assets/skills/delete.md"; @@ -65,6 +66,7 @@ export class Skill { /** Every skill, sorted by name. */ export const SKILLS: readonly Skill[] = Object.entries({ + afk, audit, complete, delete: del, diff --git a/test/cli.test.ts b/test/cli.test.ts index dd281ce0..f8ea1b28 100644 --- a/test/cli.test.ts +++ b/test/cli.test.ts @@ -82,7 +82,7 @@ test("skill lists every skill", () => { test("skill rejects an unknown name", () => { const out = run("skill", "nope"); expect(out.code).toBe(1); - expect(out.stderr).toMatch(/^quest: no skill named nope \(have: audit, /); + expect(out.stderr).toMatch(/^quest: no skill named nope \(have: afk, audit, /); }); test("usage errors exit 2", () => {