Repository navigation
quest: plan the 2026-11-02 spawn's follow-ups #444
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
b59e2a1
quest: plan the 2026-11-02 spawn's follow-ups
kixelated 158df7b
quest: answer CodeRabbit's findings on the spawn follow-ups
kixelated 8979639
quest: require the seccomp fix and #404's test before the Claude boun…
kixelated b832ad6
Merge origin/main into quest-plan/spawn-followups-2026-11-02
kixelated d895a83
quest land: merge tested base
0e1ba69
quest land: merge tested base
4610bda
quest land: merge tested base
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| # [XS] Report claude rm's unlock advice upstream | ||
|
|
||
| ## Goal | ||
|
|
||
| anthropics/claude-code has an issue asking `claude rm` to dispatch the | ||
| `WorktreeRemove` hook for a checkout a `WorktreeCreate` hook made, as remote | ||
| control already does, instead of telling the user to run | ||
| `git worktree unlock`, which breaks the hook's lock. Delete this quest once | ||
| the issue is filed, or abandon it if the maintainer declines. | ||
|
|
||
| ## Plan | ||
|
|
||
| Decided 2026-11-02 (coordinator, /quest-spawn follow-ups, after the user | ||
| asked the coordinator to decide follow-ups from evidence): plan it, [XS], | ||
| m0, waiting on the maintainer's approval to post. | ||
|
|
||
| - [moq-dev/quest#425](https://github.com/moq-dev/quest/pull/425)'s probe | ||
| with Claude Code 2.1.316: `claude rm` on an agent-view session's | ||
| hook-made checkout reports it "locked … by something other than Claude | ||
| Code" and suggests `git worktree unlock`. The README now tells users to | ||
| run `quest worktree remove` first. | ||
| - No upstream issue covers it (searched 2026-11-02). Related but different: | ||
| [anthropics/claude-code#79872](https://github.com/anthropics/claude-code/issues/79872) | ||
| (`claude agents` delete skips plugin `WorktreeRemove` hooks), | ||
| [#93676](https://github.com/anthropics/claude-code/issues/93676), | ||
| [#101283](https://github.com/anthropics/claude-code/issues/101283), and | ||
| [#99270](https://github.com/anthropics/claude-code/issues/99270). Link | ||
| them in the report. | ||
| - Include the Claude Code version, the minimal reproduction from #425's | ||
| scratch repository, and the expected behaviour. | ||
|
|
||
| ## Waiting | ||
|
|
||
| - Maintainer: approve posting on anthropics/claude-code, which is outside the kixelated and moq-dev orgs where agents may post without asking; check by a ✅ recorded in this quest's Plan |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| # [XS] Recorded decisions mark the rejected options | ||
|
|
||
| ## Goal | ||
|
|
||
| The grill and plan skills record each decision with the chosen option | ||
| marked and the rejected options labelled as rejected, such as | ||
| `✅ Yes, as stated (rejected: without the overlap check; drop it)`, so no | ||
| reader takes a rejected option for a qualifier of the chosen one. | ||
|
|
||
| ## Plan | ||
|
|
||
| Decided 2026-11-02 (user, /quest-spawn follow-ups): ✅ plan as stated | ||
| (rejected: drop it); ✅ m0 (rejected: m1, m2). | ||
|
|
||
| - Raised by [moq-dev/quest#416](https://github.com/moq-dev/quest/pull/416): | ||
| Codex read "✅ Yes, as stated; without the overlap check; drop it" as | ||
| dropping the overlap check, and the agent spent a review round refuting | ||
| it. | ||
| - Change the recording instruction in `assets/skills/grill.md` and | ||
| `assets/skills/plan.md`. Existing records stay as written. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| # [M] The Claude Code sandbox's boundary test runs in CI | ||
|
|
||
| ## Goal | ||
|
|
||
| Claude Code jobs get the same checked-in hostile-repository boundary test | ||
| that opencode jobs got in | ||
| [moq-dev/quest#404](https://github.com/moq-dev/quest/pull/404): a scripted | ||
| fake model, set as the account's endpoint in its home, drives the pinned | ||
| Claude Code through the runner's launch path on Linux CI, and every escape | ||
| attempt is refused. | ||
| A Claude Code bump that weakens the boundary fails CI before it lands. | ||
|
|
||
| ## Plan | ||
|
|
||
| Decided 2026-11-02 (coordinator, /quest-spawn follow-ups, after the user | ||
| asked the coordinator to decide follow-ups from evidence): plan it, [M], | ||
| in this epic after the seccomp fix. | ||
|
|
||
| Evidence, gathered 2026-11-02: | ||
|
|
||
| - The only Claude Code coverage is unit tests of its settings and | ||
| environment (`test/runner.test.ts`). The boundary was last checked by hand | ||
| ("verified live on Linux with Claude Code 2.1.291 and 2.1.305"), and | ||
| [moq-dev/quest#242](https://github.com/moq-dev/quest/pull/242) bumped the | ||
| pin without a rerun although 2.1.305 added `allowNestedUserNamespaces`. | ||
| - The opencode test found a real hole (the missing seccomp helper, see | ||
| [Unix sockets](/quest/m0/kix/sandbox/seccomp.md)), so these tests pay off. | ||
|
|
||
| Work: | ||
|
|
||
| - Reuse #404's attempts and layout: denied reads by path and symlink, | ||
| writes outside the checkout and job temp directory, planted project | ||
| settings and hooks, the network directly and through the proxy, and the | ||
| Unix-socket probe from the seccomp quest. | ||
| - Assert that `TMPDIR` inside a command is the job's private directory and | ||
| is writable. Reading Claude Code 2.1.305 says its strict policy exports | ||
| `TMPDIR=<CLAUDE_CODE_TMPDIR or os.tmpdir()>/claude-<uid>`, which the | ||
| runner's `TMPDIR` (`src/runner/claude.ts`) puts inside `allowWrite`; the | ||
| test confirms it instead of trusting the read. | ||
| - Point the account at the fake model in its home, as #404's `signIn` | ||
| configures opencode's provider: `ANTHROPIC_BASE_URL` in the `env` of | ||
| `$CLAUDE_CONFIG_DIR/settings.json`, which `--setting-sources user` loads. | ||
| An ambient `ANTHROPIC_BASE_URL` never reaches Claude Code, since | ||
| `jobEnvironment` (`src/runner/claude.ts`) keeps only `keptEnvironment`'s | ||
| allowlist (`src/runner/sandbox.ts`); leave that allowlist as it is. If | ||
| settings' `env` also reaches the commands, the fake key there is no | ||
| secret, so the unreadable-secret attempt reads a planted credential file | ||
| in the home instead. | ||
| - Like #404, each shell attempt first succeeds outside the sandbox, and the | ||
| test fails rather than skips on Linux when the sandbox can't start. | ||
|
|
||
| ## Required | ||
|
|
||
| - [No Unix sockets in opencode jobs](/quest/m0/kix/sandbox/seccomp.md) - the Unix-socket probe this test reuses | ||
| - [Boundary test in CI](/quest/m0/kix/sandbox/live-test.md) - #404's attempts and layout this test reuses |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| # [S] opencode jobs' commands can't reach Unix sockets | ||
|
|
||
| ## Goal | ||
|
|
||
| The sandbox-runtime (srt) that runs opencode jobs' commands applies its | ||
| seccomp filter, so a sandboxed command cannot create a Unix socket and so | ||
| cannot connect to one, the Nix daemon's included. The runner refuses to start an opencode job when | ||
| srt reports Unix-socket blocking disabled, and the boundary test probes the | ||
| daemon socket, so a package bump that drops the filter fails CI. srt's | ||
| always-writable `/tmp/claude` is denied too. | ||
|
|
||
| ## Plan | ||
|
|
||
| Decided 2026-11-02 (coordinator, /quest-spawn follow-ups, after the user | ||
| asked the coordinator to decide follow-ups from evidence): plan it, [S], | ||
| first in this epic, since it is a hole in a boundary the README says holds. | ||
|
|
||
| Evidence, gathered 2026-11-02: | ||
|
|
||
| - nixpkgs' `sandbox-runtime-0.0.81`, which `flake.nix` uses as is, ships | ||
| `vendor/seccomp/build.ts` but no compiled `apply-seccomp` helper. srt then | ||
| logs `apply-seccomp binary not available - unix socket blocking disabled` | ||
| (seen in [moq-dev/quest#435](https://github.com/moq-dev/quest/pull/435)'s | ||
| session on 2026-11-03T03:55Z). | ||
| - Run with the runner's `runtimeSettings` shape (reads of `/home` and `/tmp` | ||
| denied), `nix store ping --store daemon` inside srt answered | ||
| `Version: 2.35.2`. `nix config show trusted-users` is | ||
| `root kixelated github-runner`, so a job's command on this host could pass | ||
| the daemon root-level options. This contradicts the epic's "Commands have | ||
| no Nix daemon". No runner was deployed on the host yet. | ||
| - [moq-dev/quest#404](https://github.com/moq-dev/quest/pull/404)'s boundary | ||
| test passed because it probes no Unix socket. | ||
| - srt 0.0.81 lists `/tmp/claude` in `SANDBOX_OWN_WRITE_PATHS`, which it never | ||
| drops (`dist/sandbox/sandbox-utils.js`). The directory doesn't exist on | ||
| this host and a sandboxed `mkdir` lands on srt's private tmpfs, so it | ||
| matters only if something on the host creates it. Deny it anyway while | ||
| editing the same settings. | ||
|
|
||
| Work: | ||
|
|
||
| - Build `apply-seccomp` for the flake's `sandbox-runtime` (an override that | ||
| compiles it per `build.ts` against static libseccomp), or package the npm | ||
| tarball's prebuilt helper and pass `seccomp.applyPath`. Prefer the build | ||
| from source, matching how the flake pins the rest. | ||
| - The runner refuses an opencode account when srt reports Unix-socket | ||
| blocking disabled, with an error that names the missing helper. | ||
| - Add to [#404](https://github.com/moq-dev/quest/pull/404)'s boundary test, | ||
| in that PR if it is still open: connecting to the Nix daemon socket, and to a | ||
| socket the test opens outside the sandbox, are both refused. | ||
| - The filter blocks creating a Unix socket, not using one a command | ||
| inherits or receives over `SCM_RIGHTS`. Have the boundary test list the | ||
| command's open descriptors (`/proc/self/fd`) and fail on any Unix socket | ||
| other than its stdio's, so nothing the runner or opencode passes down | ||
| reaches a host socket. | ||
| - Add `/tmp/claude` to `denyWrite` if srt honours it over its own write | ||
| paths without leaving a placeholder behind; otherwise record why not. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| # [S] A job's head trust is rechecked when it queues | ||
|
|
||
| ## Goal | ||
|
|
||
| kix rechecks a PR job's head trust whenever the job becomes queued, after an | ||
| answer or when a runner's lease expires, not only when a runner has a free | ||
| slot. A job whose head is no longer trusted shows the "Head to approve" | ||
| decision at once instead of sitting as "Queued" until a slot frees. | ||
|
|
||
| ## Plan | ||
|
|
||
| Decided 2026-11-02 (user, /quest-spawn follow-ups): ✅ plan as stated | ||
| (rejected: drop it); ✅ m0 (rejected: m1, m2). | ||
|
|
||
| - Raised by [moq-dev/quest#402](https://github.com/moq-dev/quest/pull/402), | ||
| which added per-head approval and rechecks trust at job creation and at | ||
| assignment. Existing behaviour: a queued job's trust is reread only when a | ||
| runner slot frees, so a job resumed after kix pushed new commits looks | ||
| idle while it needs a maintainer. | ||
| - Reuse #402's trust classification; call it from every transition into | ||
| `queued`. Keep the recheck at assignment as the authority. | ||
| - Test a resume after kix pushed, and a lease expiry, each surfacing the | ||
| decision without a free runner slot. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # [S] quest review reports a reviewer's usage limit | ||
|
|
||
| ## Goal | ||
|
|
||
| When the reviewer CLI fails because its account hit a usage limit or quota, | ||
| `quest review` exits with a distinct status and prints the reset time, so an | ||
| agent records the outage as a `## Waiting` item without parsing the | ||
|
coderabbitai[bot] marked this conversation as resolved.
Resolved
|
||
| reviewer's error text. | ||
|
|
||
| ## Plan | ||
|
|
||
| Decided 2026-11-02 (user, /quest-spawn follow-ups): ✅ plan as stated | ||
| (rejected: drop it); ✅ m0 (rejected: m1, m2). | ||
|
|
||
| - Raised by [moq-dev/quest#411](https://github.com/moq-dev/quest/pull/411), | ||
| whose guide rule turns a reviewer's quota or login failure into a | ||
| `## Waiting` item naming when it resets. About 29 sessions between | ||
| 2026-10-30 and 11-01 ended on a reviewer's weekly quota. | ||
| - Reuse the matchers that exist: Claude Code's usage-limit `LIMIT` in | ||
| `src/runner/claude.ts` and `quest agent`'s `EXHAUSTED` in | ||
| `src/cli/agent.ts`. Move them where both and `quest review` import them, | ||
| rather than adding a third copy. | ||
| - The contract: `quest review` exits 3, which it uses for nothing else | ||
| (0 is a round, 1 a failure, 2 a usage error), and prints one stderr line, | ||
| `error: <harness> hit its usage limit; resets <time>`, where `<time>` is | ||
| the reset as an ISO 8601 UTC timestamp, or `unknown` when the CLI's | ||
| output names none. Claude Code reports the reset as `resetsAt` epoch | ||
| seconds (`src/runner/claude.ts`); take Codex's from its error if it gives | ||
| one. | ||
| - Document the contract in `quest review --help` and the README, and point | ||
| #411's rule at it, so all three say the same. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| # [M] A Claude session's checkout is released when the session ends | ||
|
|
||
| ## Goal | ||
|
|
||
| A checkout `quest worktree hook` made for a Claude Code session itself (not | ||
| a subagent), through `--worktree`, `--bg`, or agent view, is released when | ||
| the session ends and claimed again when it resumes, so session checkouts no | ||
| longer pile up the way Claude Code's own do. | ||
|
|
||
| ## Plan | ||
|
|
||
| Decided 2026-11-02 (coordinator, /quest-spawn follow-ups, after the user | ||
| asked the coordinator to decide follow-ups from evidence): plan it, [M], m0. | ||
|
|
||
| Evidence, gathered 2026-11-02: | ||
|
|
||
| - [moq-dev/quest#425](https://github.com/moq-dev/quest/pull/425)'s live | ||
| probes found session checkouts never released by any route. | ||
| - Claude Code's own session worktrees (not `agent-*`) already accumulate: | ||
| 32 registered in moq.pro, 21 in moq, and 3 in quest (2026-10-14 to | ||
| 10-27), beside 449, 124, and 26 `agent-*` worktrees. Once the hooks own | ||
| these checkouts the same backlog would build in the registry. | ||
|
|
||
| Work: | ||
|
|
||
| - Install `SessionEnd` and `SessionStart` hook entries through | ||
| `quest init`, recognised by `init` and `uninstall` like the others. | ||
| - `SessionEnd` releases (never removes) the session's checkout; | ||
| `SessionStart` claims it again on resume. `/clear` also fires | ||
| `SessionEnd`, so release is idempotent and the next `SessionStart` | ||
| reclaims it. An idle background session never ends; leave it held. | ||
|
kixelated marked this conversation as resolved.
Resolved
|
||
| - Claude Code bounds `SessionEnd` hooks by a short budget | ||
| (`CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS`) and does not wait past it. | ||
| Measure a release with scratch to delete, and set the entry's timeout to | ||
| cover it. A release that fails or is cut short leaves the checkout | ||
| reserved with its failure recorded, as `settle` does | ||
| (`src/cli/worktree.ts`), and the next `SessionStart` for that session, or | ||
| `quest worktree release` by hand, finishes it. Verify a killed release | ||
| this way too. | ||
| - Verify each route live as #425 did, from a session that is not itself | ||
| worktree-isolated. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| # [S] quest waiting lists draft PRs' Waiting items | ||
|
|
||
| ## Goal | ||
|
|
||
| `quest waiting` lists each open draft PR's `## Waiting` items beside the | ||
| quest tree's, ranked the same way with the maintainer's first, so one | ||
| command shows everything that waits on someone. `/quest-unblock` reads it | ||
| instead of gathering draft bodies with `gh` itself. | ||
|
|
||
| ## Plan | ||
|
|
||
| Decided 2026-11-02 (user, /quest-spawn follow-ups): ✅ plan as stated | ||
| (rejected: drop it); ✅ m0 (rejected: m1, m2). | ||
|
|
||
| - Raised by [moq-dev/quest#411](https://github.com/moq-dev/quest/pull/411): | ||
| a reviewer outage lives in the draft's `## Waiting`, which `quest waiting` | ||
| never reads. Drafts handed back for decisions carry theirs there too. | ||
| - Read drafts of the repository's own PRs, parsing `## Waiting` (and the | ||
| older `## Decisions needed` until | ||
| [its retirement](/quest/m1/decisions-needed.md)) with the claim code that | ||
| already detects the heading. Each item names its PR's URL. | ||
| - Keep `quest waiting` usable offline: without GitHub access it prints the | ||
| tree's items and says the drafts were skipped. | ||
| - Update `assets/skills/unblock.md` to read the command's output, keeping | ||
| its per-draft `quest status <pr>` hold check, so it still skips a draft | ||
| another session holds. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| # [S] Cut a release with the worktree hooks | ||
|
|
||
| ## Goal | ||
|
|
||
| A tagged quest release includes `quest worktree hook`, so SETUP.md's release, | ||
| mise, and installer routes give adopters a `quest` whose Claude Code hooks | ||
| work, and the release checklist says when the next one is due. | ||
|
|
||
| ## Plan | ||
|
|
||
| Decided 2026-11-02 (coordinator, /quest-spawn follow-ups, after the user | ||
| asked the coordinator to decide follow-ups from evidence): plan it, [S], m1, | ||
| since every moq-dev repository pins quest through a nix flake and only | ||
| third-party adopters take the release routes. | ||
|
|
||
| Evidence, gathered 2026-11-02: | ||
|
|
||
| - The only release, v0.1.0 (`4fbbb0c0`, 2026-10-07), is 323 commits behind | ||
| `main` and has no `worktree` command; the hook arrived in | ||
| [moq-dev/quest#350](https://github.com/moq-dev/quest/pull/350) on | ||
| 2026-11-01. `SETUP.md` still offers those routes, and `quest init` | ||
| installs hook entries that call it. | ||
| - No quest plans a release; m0's README only notes "v0.1.0 shipped". | ||
|
|
||
|
kixelated marked this conversation as resolved.
Resolved
|
||
| Work: | ||
|
|
||
| - First, before any release: `SETUP.md` does not yet say v0.1.0 lacks the | ||
| hook, so add that the release routes lack it and point at the flake | ||
| route until a release has it. | ||
| - Once the remaining worktree-hook work | ||
| ([moq-dev/quest#423](https://github.com/moq-dev/quest/pull/423); its | ||
| sibling [#425](https://github.com/moq-dev/quest/pull/425) landed on | ||
| 2026-11-03) has landed or been dropped, bump `package.json`'s `version` in a PR to `main`, then tag that | ||
| version from `main`; `.github/workflows/release.yml` publishes on the tag | ||
| push and fails when the tag and `package.json` differ. Check that the | ||
| release has the Windows archives SETUP.md expects, then drop the | ||
| `SETUP.md` caveat. | ||
| - Decide in the PR how later releases are cut, such as a step in the release | ||
| checklist or a recurring quest through `/quest-recurring`. | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.