From b3ecefb3f819793be2c7e7e43dd62a18e8faefde Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Tue, 20 Oct 2026 19:37:36 -0700 Subject: [PATCH 1/5] docs(guide): let fork PRs claim quests A claim was only a quest branch pushed upstream, so contributors without push access had no way to claim and their fork PRs went unseen. Any open PR whose head branch is the quest's branch now counts, and contributors without push access claim by opening a draft PR from their fork. Co-Authored-By: Claude Opus 5.5 --- README.md | 3 ++- assets/AGENTS.md | 12 ++++++++---- assets/skills/spawn.md | 2 +- assets/skills/start.md | 4 ++-- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 70ce515a..de47a028 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,8 @@ in Git history, beside the code that completed it. Work is taken through a live runner lock or an open change on the forge. kix.quest records each active job in its database and reassigns a job whose runner goes offline. On GitHub, a pushed quest -branch claims the work. These states stay out of the plan file. +branch or an open PR from one, including from a fork, claims the work. These +states stay out of the plan file. ## Try it diff --git a/assets/AGENTS.md b/assets/AGENTS.md index 783e3fff..2c167019 100644 --- a/assets/AGENTS.md +++ b/assets/AGENTS.md @@ -105,10 +105,14 @@ kix.quest records each active job in its database and reassigns a job whose runner goes offline. Check those locks and open changes before starting. These states stay out of the quest file. -On GitHub, if you have push access, make an empty commit and push a branch to -the remote. -The remote branch claims the quest so other agents skip it. -Check for its branch and any open PR before starting. +On GitHub, a quest is claimed by its branch on the upstream repository or by any +open PR whose head branch has that name, including PRs from forks +(`gh pr list --head `). +Check both before starting; in a fork's clone, `origin` is usually the fork. +To claim a quest, make an empty commit on its branch. +With push access, push it upstream. +Without, push it to your fork and open a draft PR from it right away; that PR +becomes the quest's PR. If a branch looks stale (old, with no open PR), offer the user to take it over. A quest's branch is its path without `.md`. diff --git a/assets/skills/spawn.md b/assets/skills/spawn.md index e1b83f33..7fbf7a48 100644 --- a/assets/skills/spawn.md +++ b/assets/skills/spawn.md @@ -10,7 +10,7 @@ Run `quest unblocked --json` for ready candidates in milestone priority, descend The count is distinct transitive dependents; other prerequisites may still remain. Use that order when dispatching, and recompute after the quest tree changes. An explicit argument takes precedence: filter to the selected quests/epics and honor their requested order. -Ranking does not establish that work is unclaimed: verify live locks, open changes, and remote branch claims before starting. +Ranking does not establish that work is unclaimed: verify live locks, open changes (including PRs from forks), and remote branch claims before starting. For a quest waiting on an outside condition, check whether it has cleared before recommending. Start every quest you would recommend starting, without asking: well planned, with no blockers or conflicts with quests already started. diff --git a/assets/skills/start.md b/assets/skills/start.md index 5acb583c..93f160f2 100644 --- a/assets/skills/start.md +++ b/assets/skills/start.md @@ -10,10 +10,10 @@ The argument is the quest to work on. If you are unsure on the best course of action, ask the user for direction. Update your checkout, run `quest ready`, then confirm the quest is still ready and unclaimed. -Check the forge for a live runner lock or an open change; on GitHub, check the quest's remote branch and open PRs. +Check the forge for a live runner lock or an open change; on GitHub, check the quest's upstream branch and open PRs from any fork. Confirm you can write in your worktree; if you cannot, stop and report without claiming. Claim it as `quest guide` describes. -Release work you cannot finish; on GitHub, delete its branch claim and your isolated worktree. +Release work you cannot finish; on GitHub, delete its branch claim, close any claim PR, and remove your isolated worktree. Implement the quest until it is complete, or some blocker is hit, then create a PR. Never write to or clean up a directory other agents share, such as a session scratchpad. From b620adb3ddf72c49c19a6ee483bd466b985220d0 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Wed, 21 Oct 2026 07:58:52 -0700 Subject: [PATCH 2/5] docs(guide): check claim PRs upstream and break fork claim races Co-Authored-By: Claude Opus 5.5 --- assets/AGENTS.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/assets/AGENTS.md b/assets/AGENTS.md index 2c167019..43b74187 100644 --- a/assets/AGENTS.md +++ b/assets/AGENTS.md @@ -107,12 +107,15 @@ starting. These states stay out of the quest file. On GitHub, a quest is claimed by its branch on the upstream repository or by any open PR whose head branch has that name, including PRs from forks -(`gh pr list --head `). -Check both before starting; in a fork's clone, `origin` is usually the fork. +(`gh pr list --repo --head `). +Check both before starting, against the upstream repository; in a fork's clone, +`origin` is usually the fork. To claim a quest, make an empty commit on its branch. With push access, push it upstream. Without, push it to your fork and open a draft PR from it right away; that PR becomes the quest's PR. +Fork pushes never collide, so recheck after opening: the earliest open PR holds +the claim, and a later one closes and stops. If a branch looks stale (old, with no open PR), offer the user to take it over. A quest's branch is its path without `.md`. From a111f8249f45c5ad1f59bed52a97fb2470fd7641 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Wed, 21 Oct 2026 08:39:43 -0700 Subject: [PATCH 3/5] docs(guide): claim every quest with a draft PR A branch push and a fork PR could both claim a quest at once. Every claimant now opens a draft PR right away and rechecks, so the earliest open PR decides the claim. Finishing marks that PR ready instead of opening a new one. Co-Authored-By: Claude Opus 5.5 --- README.md | 4 ++-- assets/AGENTS.md | 29 +++++++++++++++-------------- assets/skills/spawn.md | 2 +- assets/skills/start.md | 4 ++-- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index de47a028..6e7d8390 100644 --- a/README.md +++ b/README.md @@ -58,8 +58,8 @@ in Git history, beside the code that completed it. Work is taken through a live runner lock or an open change on the forge. kix.quest records each active job in its database and reassigns a job whose -runner goes offline. On GitHub, a pushed quest -branch or an open PR from one, including from a fork, claims the work. These +runner goes offline. On GitHub, a draft PR +opened from the quest's branch, including from a fork, claims the work. These states stay out of the plan file. ## Try it diff --git a/assets/AGENTS.md b/assets/AGENTS.md index 43b74187..c071251a 100644 --- a/assets/AGENTS.md +++ b/assets/AGENTS.md @@ -105,18 +105,19 @@ kix.quest records each active job in its database and reassigns a job whose runner goes offline. Check those locks and open changes before starting. These states stay out of the quest file. -On GitHub, a quest is claimed by its branch on the upstream repository or by any -open PR whose head branch has that name, including PRs from forks -(`gh pr list --repo --head `). -Check both before starting, against the upstream repository; in a fork's clone, -`origin` is usually the fork. -To claim a quest, make an empty commit on its branch. -With push access, push it upstream. -Without, push it to your fork and open a draft PR from it right away; that PR -becomes the quest's PR. -Fork pushes never collide, so recheck after opening: the earliest open PR holds -the claim, and a later one closes and stops. -If a branch looks stale (old, with no open PR), offer the user to take it over. +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 +(`gh pr list --repo --head `), or by that branch +upstream while its PR is being opened. +Check both against the upstream repository; in a fork's clone, `origin` is +usually the fork. +To claim a quest, push an empty commit to its branch, upstream if you have push +access and otherwise on your fork, then open a draft PR from it right away. +That PR becomes the quest's PR. +Then recheck: the earliest open PR holds the claim, and a later one closes and +stops. +If an upstream branch looks stale (old, with no open PR), offer the user to take +it over. A quest's branch is its path without `.md`. For example, `quest/m1/foo/bar.md` is branch `quest/m1/foo/bar`. @@ -124,8 +125,8 @@ For example, `quest/m1/foo/bar.md` is branch `quest/m1/foo/bar`. Push claims and updates with an explicit refspec: `git push refs/heads/:refs/heads/`. A bare branch name can push to the base branch instead, for example under `push.default=upstream` when the quest branch tracks it. -When a quest is complete with no open decisions, open its PR ready for review. -Otherwise open a draft and list its open decisions, or what remains unfinished, in the body. +When a quest is complete with no open decisions, mark its PR ready for review. +Otherwise keep it a draft and list its open decisions, or what remains unfinished, in the body. A draft suggests `/quest-iterate`; a PR ready for review suggests `/quest-merge`. Include a summary of the changes made and suggest follow-up quests based on issues encountered. Add a closing keyword for every issue under `Closes`. diff --git a/assets/skills/spawn.md b/assets/skills/spawn.md index 7fbf7a48..cb8f7b62 100644 --- a/assets/skills/spawn.md +++ b/assets/skills/spawn.md @@ -30,7 +30,7 @@ Each agent reports back only when done or blocked. Limit the number of active agents to the physical CPU core count. Other sessions share this machine: hold new agents while the load average exceeds the core count. -When done, each agent opens a PR, a draft if decisions or unfinished work remain. +When done, each agent's claim PR holds its work, still a draft if decisions or unfinished work remain. Its report lists every open decision and suggested follow-up with a recommendation. Report each sub-agent's final status, staying silent on interim notifications, but do not monitor their PRs. diff --git a/assets/skills/start.md b/assets/skills/start.md index 93f160f2..7b9fa00b 100644 --- a/assets/skills/start.md +++ b/assets/skills/start.md @@ -13,9 +13,9 @@ Update your checkout, run `quest ready`, then confirm the quest is still ready a Check the forge for a live runner lock or an open change; on GitHub, check the quest's upstream branch and open PRs from any fork. Confirm you can write in your worktree; if you cannot, stop and report without claiming. Claim it as `quest guide` describes. -Release work you cannot finish; on GitHub, delete its branch claim, close any claim PR, and remove your isolated worktree. +Release work you cannot finish; on GitHub, close its claim PR, delete its branch, and remove your isolated worktree. -Implement the quest until it is complete, or some blocker is hit, then create a PR. +Implement the quest until it is complete, or some blocker is hit, then push to its PR and update the description. Never write to or clean up a directory other agents share, such as a session scratchpad. When done, explain the result in a few lines and summarize any issues encountered. From 9c56a394884763936e3694235bd3de8285399640 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Wed, 21 Oct 2026 10:22:04 -0700 Subject: [PATCH 4/5] docs(home): describe draft PR claims in the hosted lifecycle Co-Authored-By: Claude Opus 5.5 --- cloudflare/src/home.tsx | 11 +++++++++-- design/theme.md | 3 ++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/cloudflare/src/home.tsx b/cloudflare/src/home.tsx index dca1f907..15e3cfbe 100644 --- a/cloudflare/src/home.tsx +++ b/cloudflare/src/home.tsx @@ -139,7 +139,11 @@ export function Home(props: { setup: string; board: Board }) {
  • Accepted by @agent

    -

    A live runner lock takes active work. On GitHub, pushing the quest's branch claims it.

    +

    + A live runner lock takes active work. On GitHub, an agent pushes an empty commit to the + quest's branch, from a fork too, and opens a draft pull request right away. The earliest + open pull request holds the claim. +

  • @@ -148,7 +152,10 @@ export function Home(props: { setup: string; board: Board }) { Ready to turn in

    -

    The work arrives as a draft pull request, plan and code reviewed together.

    +

    + The work lands on that pull request, marked ready for review, plan and code reviewed + together. +

  • Quest complete

    diff --git a/design/theme.md b/design/theme.md index 23e289e2..e2f0b831 100644 --- a/design/theme.md +++ b/design/theme.md @@ -56,7 +56,8 @@ blocked and `Required:`), with the markers and size colours. A quest shows its most advanced state: Ready to turn in, then Accepted by, then Available or Requires. Accepted by comes from a live runner lock: an active job in kix.quest's database, which moves when its runner goes offline; open changes -carry Ready to turn in. GitHub uses the pushed quest branch to claim work. +carry Ready to turn in. On GitHub, a draft PR from the quest branch, opened +right away and from a fork too, claims work. None of these states adds a section to the quest file. Tokens are display only: a run's spend and donated tokens show with an amber From 482f7edcda633db70ce173b7be8e7a770be02847 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Wed, 21 Oct 2026 10:31:02 -0700 Subject: [PATCH 5/5] docs(getting-started): check claims upstream, including fork PRs Co-Authored-By: Claude Opus 5.5 --- docs/getting-started.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index 44cf8e7d..7c17a3d3 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -53,7 +53,8 @@ pull request; `/quest-spawn` sends several agents out in parallel when your session supports them. Use `$quest-start` and `$quest-spawn` in Codex. Check the forge for a live runner lock or an open change before starting. kix.quest records each active job in its database and reassigns a job whose -runner goes offline. On GitHub, check the quest's remote branch and open PRs. `quest ready` +runner goes offline. On GitHub, check the upstream repository for the quest's +branch and for open PRs from it, including PRs from forks. `quest ready` reads dependencies in the quest tree; it does not look for these live states. You review each change: `/quest-ready` takes a draft to review, and