Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions quest/m0/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,21 @@ web app with push notifications, and their own Linux and macOS runners do
the work through Claude Code and opencode inside each project's Nix
devShell. The GitHub App bot publishes ordinary PRs. The standalone CLI
(v0.1.0 shipped on 2026-10-07) keeps serving the same repositories locally on
macOS, Linux, and native Windows.
macOS and Linux.

Work that only third-party repositories need, and the public launch, belong
to [m1](/quest/m1/README.md).
Work that only third-party repositories need, native Windows, and the public
launch belong to [m1](/quest/m1/README.md).

## Plan

Decided 2026-11-03 (user, /quest-complete, on
[moq-dev/quest#455](https://github.com/moq-dev/quest/pull/455)), after the
native Windows suite moved to m1 with nightly-only coverage:

- Should m0's Goal drop native Windows?
- ✅ Narrow m0's Goal (recommended)
- Leave it

Decided 2026-10-30 (user, /quest-plan), replacing "First public release":

- Should m0 serve moq-dev's repositories before third parties?
Expand Down Expand Up @@ -85,14 +93,15 @@ ownership-manifest design:
- [Land through the merge queue with an async fixer](/quest/m0/queue-watcher/README.md) - GitHub's merge queue lands one PR at a time, and a host watcher fixes and re-enqueues each PR it drops
- [Merge through a host gate](/quest/m0/host-land/README.md) - the host's fixer containers, and the frozen batched gate for the repositories not yet switched
- [The land fixer resolves every mechanical failure](/quest/m0/land-fixer/README.md) - workflow pushes and the PR's own CI as context
- [Split the rejected-login review test](/quest/m0/review-test-load.md) - each rejected-login variant is its own test, within the default limit under load
- [Reviewer usage limits](/quest/m0/review-quota.md) - `quest review` exits distinctly on a reviewer's quota and prints the reset time
- [Drafts in quest waiting](/quest/m0/waiting-drafts.md) - `quest waiting` lists open draft PRs' `## Waiting` items beside the tree's
- [Rejected options in decision records](/quest/m0/decision-records.md) - grill and plan label rejected options so no one reads them as qualifiers
- [Kix decision UI](/quest/m0/kix/README.md) - planning and implementation through prompts and summaries, run on the maintainer's own runners
- [Codex cloud off](/quest/m0/codex-cloud-off.md) - automatic Codex cloud reviews stop once no open PR relies on them
- [Bun EFAULT report](/quest/m0/bun-efault.md) - report concurrent `rmSync` `EFAULT` on Windows, and drop the workaround once Bun fixes it
- [Codex project-config skip](/quest/m0/codex-project-config.md) - once Codex keeps a supported way to skip a project's `.codex/` layer, reviews keep the user's config
- [Gate bench](/quest/m0/gate-bench.md) - measure headroom admission on an idle host
- [Gate load wording](/quest/m0/gate-load-wording.md) - stop naming Spotlight as the cause of a fresh macOS runner's load
- [Agent workflow helpers](/quest/m0/helpers/README.md) - CLI commands for CI waits, PR status, claims, quest moves, and serialized merges
- [Worktree hooks here](/quest/m0/worktree-hooks.md) - `quest` reaches Claude Code's hooks and the merge driver in this repository, then `quest init` installs the hooks
- [Remote control worktrees](/quest/m0/worktree-routes.md) - live-check `claude remote-control --spawn worktree` against the hooks, from a session spawned on claude.ai
Expand Down
35 changes: 35 additions & 0 deletions quest/m0/gate-load-wording.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# [XS] Stop blaming Spotlight for a fresh macOS runner's load

## Goal

The gate's docs, comments and tests describe a freshly booted hosted macOS
runner's load without naming Spotlight's index as its cause, since
measurements ruled that out. The gate's behavior is unchanged.

## Plan

Decided 2026-11-03 (coordinator, /quest-complete follow-ups, under the
user's 2026-11-02 instruction to decide follow-ups from evidence): plan it,
[XS], m0.

Evidence, gathered 2026-11-03:

- [moq-dev/quest#430](https://github.com/moq-dev/quest/pull/430) turned
Spotlight indexing off for whole macOS jobs, and the load stayed high or
rose: Release x86_64 ran at 33.18 / 39.10 (1- and 5-minute load) against
10.94 / 20.17 before. Something other than Spotlight's index keeps a
freshly booted runner loaded. The quest was dropped and the workflow
change reverted.
- The Spotlight explanation is still on `main` in
`.github/workflows/check.yml:70`, `.github/workflows/release.yml:126`,
`test/gate.test.ts:131`, `src/cli/gate.ts:373` and `README.md:940`
("Gate expensive commands").

Work:

- Reword each place to say that a freshly booted hosted macOS runner's load
stays above its CPU count for the whole job, from work outside the job
that the gate can't wait out. Name no cause. Keep the reason each
check or test exists.
- `README.md` is user-facing: keep its example of a host where load comes
from outside the gate.
1 change: 1 addition & 0 deletions quest/m0/kix/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,5 @@ fixes what it finds:
- [Operator setup](/quest/m0/kix/operator-setup.md) - pilot installations and a verified test PR on moq-dev/moq and moq-dev/quest
- [Private repositories](/quest/m0/kix/private.md) - moq-dev/moq.pro enrolls, visible only to signed-in users who can read it
- [Job sandbox](/quest/m0/kix/sandbox/README.md) - head approval for kix-pushed heads, and opencode sandboxed
- [Runner reviews](/quest/m0/kix/runner-review.md) - a runner's review fetches without blocking it, under the workspace lock, with a pinned Codex
- [Web execution](/quest/m0/kix/execution.md) - spawn and iterate through the UI, ending in contribution PRs
49 changes: 49 additions & 0 deletions quest/m0/kix/runner-review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# [S] Runner reviews never block the runner, and Codex is pinned

## Goal

A runner's review of a published head never blocks the runner process.
Its `git fetch` and `ls-remote` run asynchronously, under the workspace lock
that guards the shared clone. The runner package pins a Codex CLI, so any
runner user with a Codex login can review a Claude Code job.

## Plan

Decided 2026-11-03 (coordinator, /quest-complete follow-ups, under the
user's 2026-11-02 instruction to decide follow-ups from evidence): plan it,
[S], in the kix epic. Both items come from
[moq-dev/quest#417](https://github.com/moq-dev/quest/pull/417)'s
follow-ups. The 2026-11-02 follow-up review sent them to that PR as
[a comment](https://github.com/moq-dev/quest/pull/417#issuecomment-6596307686),
and #417 merged without them. Its third follow-up, cancelling a running
review with its job, was fixed in #417's own first review round: the
attempt's abort signal kills the reviewer CLI (`src/runner/review.ts`).

Evidence, gathered 2026-11-03 on `main`:

- `reviewHead` (`src/runner/review.ts:68`) runs `quest review`'s `review()`
in the runner process. `review()` runs `git ls-remote --symref`
(`src/cli/review.ts:807`) and `git fetch` (`:888`) through `gitOutput`
(`src/cli/claims.ts`), which is `execFileSync`. The review checkout's
`origin` is the GitHub URL (`src/runner/workspace.ts:102`), so each
network call stalls the runner's WebSocket and its other jobs. It also
fetches into the shared clone outside `locked()` (`workspace.ts:414`),
which every other fetch there holds.
- `flake.nix` pins `QUEST_RUNNER_CLAUDE`, `QUEST_RUNNER_OPENCODE` and
`QUEST_RUNNER_SRT`, but no Codex. `reviewerFor` reviews a Claude Code job
with whatever `codex` is on the runner user's `PATH`. Without one, the
review fails and the head falls back to waiting on a person's approval.
nixpkgs' codex 0.164.0 accepted every flag `quest review` passes, checked
2026-11-02.

Work:

- Make the review's git calls async (`review()` already is), or prefetch the
base in `reviewCheckout` under the lock and pass `--base` so `review()`
needs no network. Prefer the prefetch, which keeps `quest review` itself
unchanged. Test that a slow fetch doesn't block a concurrent runner
message.
- Add `--set-default QUEST_RUNNER_CODEX ${getExe pkgs.codex}` to the runner
wrapper. In `reviewerFor`, put that binary's directory first on `PATH`, as
for Claude Code. The user still brings their own Codex login.
- Note the pin in the runner docs, beside the Claude Code and opencode pins.
13 changes: 10 additions & 3 deletions quest/m0/queue-watcher/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ batching host gate (`quest land serve`) is then retired.

The epic finishes with an end-to-end run on moq-dev/moq: a PR the queue drops
for a failing build is fixed and re-enqueued, a PR dropped for a conflict is
resolved and re-enqueued, a flaky failure is re-enqueued unchanged, and a
design conflict is handed back. The README's landing section describes the
watcher.
resolved and re-enqueued, a flaky failure is re-enqueued unchanged, a test
seen flaking twice is disabled by a PR that lands through moq's queue with its
`quest/m0/flaky/` epic passing `quest check`, and a design conflict is handed
back. The README's landing section describes the watcher.

Non-goals: moq's own switch (its ruleset, its `merge_group` workflow, the
runner label, and retiring its `quest land` requirement). moq-dev/moq plans
Expand Down Expand Up @@ -79,6 +80,11 @@ Decision prompts, selected options marked ✅:
- ✅ The fixer re-enqueues them unchanged, and a test seen flaking twice is
disabled in a separate PR with a follow-up quest; the rerun before blame
(#375) is dropped. Done in [moq-dev/quest#406](https://github.com/moq-dev/quest/pull/406).
Refined 2026-11-03 (coordinator, /quest-complete follow-ups): a failure
that reproduces on the base or comes from the runner is not a flaky
verdict ([Genuine flakes only](/quest/m0/queue-watcher/flaky-verdicts.md)).
The end-to-end run covers the first disable PR, and the host gate gets
no flaky record, since its work is frozen until it is retired.
- Pick record (decided 2026-11-02, replacing "Picks GitHub refuses to
enqueue: ✅ The watcher fixes them"):
- ✅ GitHub's records only. Drop the comment and `pick.ts`. The watcher
Expand Down Expand Up @@ -131,6 +137,7 @@ Shared shape, for the children to follow:

- [The other repositories follow](/quest/m0/queue-watcher/follow.md) - quest, rind and rust2 are cut over and landing; waits for a fork PR to land through one of their queues
- [Harden the queue runners](/quest/m0/queue-watcher/runners.md) - each queue runner runs only its repository's queue workflow, and every outside fork PR needs approval
- [Genuine flakes only](/quest/m0/queue-watcher/flaky-verdicts.md) - a failure on the base or from the runner never counts toward disabling a test
- [Retire the batching gate](/quest/m0/queue-watcher/retire.md) - once no repository lands through `quest land serve`, its batching code and host units go

## Related
Expand Down
54 changes: 54 additions & 0 deletions quest/m0/queue-watcher/flaky-verdicts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# [S] Only genuine flakes count toward disabling a test

## Goal

`quest land watch` records a flaky verdict only for a failure that comes and
goes with no cause in the PR, the base, or the runner. A failure that
reproduces on the base or comes from the runner's environment is requeued
without counting toward a disable. Two such failures can never auto-disable
a real test.

## Plan

Decided 2026-11-03 (coordinator, /quest-complete follow-ups, under the
user's 2026-11-02 instruction to decide follow-ups from evidence): plan it,
[S], in this epic. The 2026-11-02 follow-up review sent this to
[moq-dev/quest#406](https://github.com/moq-dev/quest/pull/406) as
[a comment](https://github.com/moq-dev/quest/pull/406#issuecomment-6596308277).
#406 merged without it.

Evidence, gathered 2026-11-03 on `main`:

- `src/cli/land-watch-fix.ts:516-523` labels every unchanged requeue of a
failed build `flaky`, and `recordFlaky` (`src/cli/land-watch-flaky.ts`)
counts each one toward the two verdicts that take a `disable`. Its PR is
enqueued with no person's pick.
- `assets/land-fix.md`'s `## Flaky tests` defines flaky as "no cause in the
PR or the base". It gives no action for a failure that reproduces on the
base or comes from the runner, so the fixer can only requeue those
unchanged or hand them back. A requeue then counts as a flaky verdict.
- Earlier rounds that were requeued as flaky but weren't:
[moq-dev/quest#324](https://github.com/moq-dev/quest/pull/324#issuecomment-6593076398)
(EROFS on `cgroup.kill`, a runner gap fixed in kixelated/nixos#19),
[#324 again](https://github.com/moq-dev/quest/pull/324#issuecomment-6593268009)
(missing `flock`/`script`, where the fixer itself wrote "environment
dependency issue, not a flaky test"), and
[moq-dev/moq#7560](https://github.com/moq-dev/moq/pull/7560#issuecomment-6572579456)
and [moq-dev/moq#7221](https://github.com/moq-dev/moq/pull/7221), where
an unused import already on `main` was requeued twice under signatures
that differed only by backticks.
- No disable PR has opened on moq-dev/moq yet: it has no `quest/m0/flaky/`
and no `quest-land/flaky-*` PR. Nothing needs undoing.

Work:

- Let a requeue name its cause: flaky, the base, or the environment. The
watcher records only flaky ones in `flaky.json`. The other causes still
requeue at the back and still count as rounds for the stop rules.
- Tell the fixer in `assets/land-fix.md`: a failure that reproduces on
`base`, or one that comes from the runner (a missing tool, a read-only
path, a full disk), is not flaky. Name its cause, never `disable`.
- Normalize a `failure` signature before matching it (strip backticks and
quotes, collapse whitespace), so one test's verdicts aren't split.
- Tests: a base failure requeued twice takes no disable, and two flaky
verdicts whose signatures differ only in quoting do.
32 changes: 32 additions & 0 deletions quest/m0/review-test-load.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# [XS] Split the rejected-login review test

## Goal

`test/review.test.ts` › "a login the API rejects fails as logged out,
whatever the status check said" passes within the default 5 s test limit
under full-suite load, because each rejected-login variant is its own test.

## Plan

Decided 2026-11-03 (coordinator, /quest-complete follow-ups, under the
user's 2026-11-02 instruction to decide follow-ups from evidence): plan it,
[XS], m0, since a test that times out under load can be judged flaky and
disabled by the land watcher ([Genuine flakes only](/quest/m0/queue-watcher/flaky-verdicts.md)).

Evidence, gathered 2026-11-03:

- The test loops over 5 variants, building a fixture and running
`quest review` against the fake reviewers for each, all inside one test.
- The land fixer's full-suite run on
[moq-dev/quest#408](https://github.com/moq-dev/quest/pull/408#issuecomment-6607816976)
timed out on it after 5,388 ms. The file took 33 s for 24 tests there. It
passed alone, and the whole suite passed with `--testTimeout=15000`.

Work:

- Turn the loop into `fakes.each` over the variants, keeping every
assertion, so each test runs `quest review` once.
- Check the rest of the file for other tests that run `quest review` more
than twice, and split them the same way.
- Don't raise the timeout: the repository's rule is to fix the cause, not
mask it with timeouts.
8 changes: 6 additions & 2 deletions quest/m1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

kix.quest opens to any maintainer: a third-party repository onboards itself,
contributor PR heads run safely on runners, and the themed site and launch
material announce it. Nothing here is needed for moq-dev's own repositories,
which m0 serves first.
material announce it. The standalone CLI runs on native Windows, whose suite
passes nightly rather than on every pull request. Nothing here is needed for
moq-dev's own repositories, which m0 serves first.

## Plan

Expand All @@ -23,9 +24,12 @@ earlier "Later work" milestone became m2.

- [Open kix.quest](/quest/m1/open.md) - the Worker moves to kix.quest and any owner may enroll
- [Release with worktree hooks](/quest/m1/release.md) - tag a release that has `quest worktree hook`, so SETUP.md's release routes work
- [Git location variables](/quest/m1/git-env.md) - every Git call on an explicit path ignores a hook's inherited `GIT_DIR` and index
- [Kix for any repository](/quest/m1/kix/README.md) - onboarding, read-only CI checks, contributor sandboxing, and the maintainer guide
- [Quest log theme](/quest/m1/theme/README.md) - an MMO-style identity, copy, board, landing page, and CLI output for the demo and launch
- [Launch material](/quest/m1/launch.md) - README, quickstart, demo, comparison, and launch-post drafts
- [Workers in a 5-minute cache](/quest/m1/worker-cache.md) - re-plan #276's worker/coordinator split and gate tickets, after confirming the cache premise
- [Retire Decisions needed](/quest/m1/decisions-needed.md) - only `## Waiting` hands a draft back, once no open draft uses the old heading
- [Native Windows suite](/quest/m1/windows-suite.md) - the native Windows jobs pass, running nightly and on dispatch instead of on every push
- [Bun EFAULT report](/quest/m1/bun-efault.md) - report concurrent `rmSync` `EFAULT` on Windows, and drop the workaround once Bun fixes it
- [Review harness check](/quest/m1/review-harness.md) - recurring each milestone: newest pinned review models, and the live sandbox test passes
File renamed without changes.
60 changes: 60 additions & 0 deletions quest/m1/git-env.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# [S] Every Git call ignores inherited repository location

## Goal

Every Git subprocess the CLI runs on an explicit path finds that path's
repository, even when `quest` runs from a Git hook or
`git submodule foreach`. They share one helper that drops the
repository-local variables (`GIT_DIR`, `GIT_WORK_TREE`, `GIT_INDEX_FILE`
and the rest of `git rev-parse --local-env-vars`) and keeps `-c` config,
as Git itself does when it enters another repository. The command that
`quest worktree run` starts in a reserved checkout gets the same treatment.

## Plan

Decided 2026-11-03 (coordinator, /quest-complete follow-ups, under the
user's 2026-11-02 instruction to decide follow-ups from evidence): plan it,
[S], m1. No moq-dev repository runs `quest` from a Git hook (none has
lefthook, pre-commit, husky or a hooks directory), so only adopters with
such hooks reach it.

Decided 2026-11-03 (user, /quest-complete, on
[moq-dev/quest#455](https://github.com/moq-dev/quest/pull/455)):

- Should `quest worktree run` drop inherited Git location variables from the
user's command? Today it hands the command Quest's own environment, so a
command started from a hook in one checkout acts on that checkout's
repository, not the reserved one it runs in.
- ✅ Drop them, keeping `-c` config (recommended): the command runs in a
different checkout, where an inherited location names the wrong
repository
- Pass the environment through unchanged, as now

Evidence, gathered 2026-11-03:

- [moq-dev/quest#445](https://github.com/moq-dev/quest/pull/445) hit it in
the worktree hook: with an inherited `GIT_DIR` naming a submodule, the
hook created the checkout inside the submodule. It fixed only
`src/cli/worktree.ts` and `worktree-hook.ts`, through `discoveryEnv()`.
- A probe on 2026-11-03: a `pre-commit` hook gets `GIT_INDEX_FILE` in every
checkout, and `GIT_DIR` too in a linked worktree. A merge driver gets
neither in a main checkout.
- The other helpers pass the environment through:
`gitOutput` (`src/cli/claims.ts`), `git` in `src/cli/move.ts`,
`src/cli/github.ts`, `src/cli/tree.ts` and `src/cli/landed.ts`,
`spawnDirectory` (`src/cli/agent.ts`) and the call in `src/cli/start.ts`.
`tree.ts` runs Git in a submodule to resolve links into it, so a
`quest check` from a hook reads the superproject there.

Work:

- Move `discoveryEnv()` from `src/cli/worktree.ts` to a shared module.
Have every `git -C <path>` helper above use it. Fold the near-duplicate
`git` helpers into it where their error handling allows, rather than
patching each one.
- Leave `src/runner/` as it is: the runner process isn't started by Git.
- Test `quest check` with links into a submodule, run under an inherited
`GIT_DIR` and `GIT_INDEX_FILE`.
- Have `quest worktree run` drop the same variables from the user's
command, keeping `-c` config (`src/cli/supervise.ts:339` hands it Quest's
own environment today), and test it from a hook-like environment.
Loading