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
1 change: 1 addition & 0 deletions quest/m0/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ ownership-manifest design:

## Required

- [Merge through a host gate](/quest/m0/host-land/README.md) - inline merge picks, small batches landed from the maintainer's host, and a Codex fixer instead of bisection
- [Codex cloud off](/quest/m0/codex-cloud-off.md) - automatic Codex cloud reviews stop once no open PR relies on them
- [Review reports an expired login](/quest/m0/review-login.md) - `quest review` says to log in again instead of failing with a 401
- [Live sandbox test](/quest/m0/review-sandbox.md) - the real reviewer CLIs run nothing a reviewed head plants
Expand Down
8 changes: 8 additions & 0 deletions quest/m0/helpers/land-adopt.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,11 @@ What remains is the fork path.
quest is done only once a fork PR that allows maintainer edits lands
through the gate and shows as merged; any fix it needs lands here. GitHub
offers maintainer edits only on forks a user owns, not an organization.
- **Host gate (user, 2026-10-30).** The gate moves to the maintainer's host
([host daemon](/quest/m0/host-land/daemon.md)), which pushes with moq-bot's
App key instead of the `token.moq.dev` exchange above, and land.yml goes
away. Verify the fork path on the host gate.

## Required

- [Host daemon](/quest/m0/host-land/daemon.md) - the gate the fork path is verified on
86 changes: 86 additions & 0 deletions quest/m0/host-land/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Merge through a host gate

## Goal

Picking a PR to merge starts no long-lived agent. `/quest-merge` queues it
inline only when a counted review names its head, or the head is trivial;
otherwise `/quest-iterate` runs first. A gate on the maintainer's host lands
small batches: a base PR plus up to floor(log₂ n) others that merge cleanly,
checked once on the chain's tip and pushed as one squash commit per PR. A
conflict on the base PR or a failing batch ejects the PRs and hands them to an
asynchronous Codex fixer, which makes only mechanical fixes and requeues the
healthy PRs. Bisection goes away.

Non-goals: other repositories adopting the gate (moq-dev/moq, moq-dev/moq.pro
plan their own; moq.pro needs only `allow_auto_merge` and the ruleset, since
moq-dev is on GitHub Team), and changing the review policy beyond the
mechanical-fix exemption.

## Plan

Decided 2026-10-30 (user, /quest-plan). Per-PR `/quest-merge` sub-agents were
wasteful: each one stayed alive to fix conflicts and failures that the gate
can hand off instead.

- Goal, as stated above:
- ✅ Yes, as stated
- Also include moq adoption
- Narrower: only the skill changes
- Where the gate runs. Keeping it in GitHub Actions was recommended, since it
is live and isolates the push credential; the user chose the host.
- Keep GitHub Actions
- ✅ Move to this host
- Architecture, once on the host:
- Host orchestrates, CI on Actions
- ✅ Everything on this host: the worker runs the check locally through
`quest gate`, pushes, and starts Codex. No Actions involved in landing.
- Everything stays in Actions
- Queue signal. The user asked for a check nobody reports, so PRs stay in
auto-merge until the host reaches them; `main`'s ruleset already requires
the unreported `quest land` check. GitHub keeps auto-merge across a
writer's push, so the gate compares the head to the pin and ejects
`head_moved`.
- ✅ Pinned auto-merge (`quest merge --land`) plus `quest:merge`
- Label only, with the label's time against the last push
- Retry cap for the fixer:
- 2 attempts
- ✅ 1 attempt
- The review-round checkpoint
- Push credential:
- Your gh auth through the admin bypass, check sandboxed
- ✅ A moq-bot App key on this host, check sandboxed
- Your gh auth, no sandbox
- Runtime. A one-pass systemd timer was recommended:
- systemd timer, one pass per run
- ✅ A long-running daemon
- Review of the fixer's changes:
- Claude reviews them through `quest review`
- ✅ None: Codex makes only mechanical fixes; anything that would need a
review is ejected and handed back
- Mechanical fixes:
- ✅ No behavior change, recorded in `## Review`
- Tool-verifiable only
- Batch:
- ✅ The longest-queued PR as the base, plus the next PRs in queue order
that merge cleanly onto the chain, up to floor(log₂ n)
- Quest priority order
- Open PRs: land
[moq-dev/quest#289](https://github.com/moq-dev/quest/pull/289) now, as it
fixes live wrong ejections until the host gate replaces that code; close
[moq-dev/quest#277](https://github.com/moq-dev/quest/pull/277), since an
ejection now removes `quest:merge` and the fixer adds it back.
- This epic ranks first in m0. It replaces the hook-started kix fixer that
[moq-dev/quest#276](https://github.com/moq-dev/quest/pull/276) proposes
(`kix/eject-fix`).
- The epic finishes with an end-to-end run on moq-dev/quest: a batch with one
PR that fails a check, one that conflicts with the base, and one healthy
PR. The healthy PR lands after the requeue, the mechanical one lands after
its fix, and the other is handed back. `CONTRIBUTING.md` and the README's
landing section describe the host gate.

## Required

- [Inline merge](/quest/m0/host-land/inline-merge.md) - `/quest-merge` queues inline or recommends `/quest-iterate`; no per-PR merge sub-agents
- [moq-bot's App key](/quest/m0/host-land/bot-key.md) - condition: the maintainer places the key on the gate host
- [Host daemon](/quest/m0/host-land/daemon.md) - `quest land serve` lands batches and ejects without bisecting
- [Codex fixer](/quest/m0/host-land/fixer.md) - ejected batches get one mechanical fix attempt and healthy PRs are requeued
19 changes: 19 additions & 0 deletions quest/m0/host-land/bot-key.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# [XS] moq-bot's App key on the gate host

## Goal

The maintainer's gate host can mint moq-bot installation tokens for
moq-dev/quest from moq-bot's App private key, kept readable only by the user
that runs the gate. Check it by minting a token there and reading the
repository with it. This waits on the maintainer placing the key.

## Plan

Decided 2026-10-30 (user, /quest-plan): the host gate pushes as moq-bot,
which `main`'s ruleset lets bypass the `quest land` check. Today moq-bot's
token comes only from `token.moq.dev` through land.yml's GitHub ID token, which
a host cannot present.

- Accept a key file path or a 1Password `op://` reference, as
`QUEST_API_KEYS` does.
- Never expose the key or a token to the sandboxed check.
42 changes: 42 additions & 0 deletions quest/m0/host-land/daemon.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# [L] Land batches from a host daemon

## Goal

`quest land serve` runs on the maintainer's host as a long-running daemon and
replaces the Land workflow. It reads the queue (PRs auto-merging with a
`quest merge --land` pin), builds a batch, checks the chain's tip once, and
fast-forwards `main` as moq-bot when it passes, one squash commit per PR.
When the base PR conflicts with `main` or the batch fails, it ejects the batch
and starts the fixer. It never bisects.

## Plan

Decided 2026-10-30 (user, /quest-plan); see the
[epic](/quest/m0/host-land/README.md).

- **Batch.** The base is the longest-queued PR. Add the next PRs in queue
order that merge cleanly onto the chain with the quest merge driver, up to
floor(log₂ n) for n queued PRs. A PR that conflicts with the chain is
skipped and stays queued. Only the base's own conflict ejects it.
- **Check.** Run the repository's check (`just check` and `just test` here)
on the tip through `quest gate`, in a sandbox holding no GitHub token,
`gh` config, SSH agent, or the bot key. Reuse the runner's sandbox where it
fits.
- **Eject.** On a failing tip, eject every PR in the batch: disable
auto-merge, remove `quest:merge`, and comment with the reason, keeping the
hidden marker `quest status` reads. Keep the resolve-time ejections
(`head_moved`, `not_pinned`, review and check states).
- **Delete** land.yml, `quest land check`'s bisection and `--budget`, and the
three-phase split that existed to keep the credential away from CI. Drop
the ID-token guard in `test/workflows.test.ts`. `token.moq.dev`'s land
endpoint lives in moq-dev/moq; suggest its removal there as a follow-up.
- **Daemon.** One process per repository checkout. It reacts to the queue by
reading GitHub's state cheaply between batches, holds a lock so two never
run, and resumes cleanly after a restart. Keep its code repository-agnostic
so other repositories can adopt it.
- Test the batch selection, a base conflict, a skipped conflicting PR, a
failing tip ejecting the whole batch, a moved head, and a restart mid-batch.

## Required

- [moq-bot's App key](/quest/m0/host-land/bot-key.md) - the host can push as moq-bot
36 changes: 36 additions & 0 deletions quest/m0/host-land/fixer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# [M] Fix ejected batches with Codex

## Goal

When the host gate ejects a batch, it starts `codex exec` on the batch in the
background and keeps landing other work. Codex reads the failure, requeues
every PR it finds healthy unchanged, makes mechanical fixes to the rest and
requeues them, and hands back anything else. Each ejection gets one attempt.

## Plan

Decided 2026-10-30 (user, /quest-plan); see the
[epic](/quest/m0/host-land/README.md).

- **Mechanical only.** A fix may not change behavior: resolving a conflict
while keeping both sides' intent, formatting and lint fixes, regenerating
lockfiles or generated files, following a rename the base made, or
requeueing unchanged after a flaky failure. Codex adds a line to the PR's
`## Review` record, `mechanical fix by Codex: <reason>`, naming the new
head, and requeues with `quest merge --land`.
- **Guide.** Add that exemption to the guide's Reviews section beside the
conflict-free base merge and the reviewer's patch. Anything that would
need a review is not mechanical.
- **Hand back.** Anything else, or a PR ejected again after its one attempt,
stays unqueued with a comment giving Codex's diagnosis and a
recommendation. `/quest-complete` asks about it again, recommending
`/quest-iterate`. Count the attempt from the ejection comments since the
maintainer's last pick.
- A flaky failure the fixer requeues becomes a suggested follow-up in its
comment.
- Codex runs with the maintainer's own Codex login and a write credential
for pushing to the PR branch and requeueing, never the bot key.

## Required

- [Host daemon](/quest/m0/host-land/daemon.md) - ejects batches and starts the fixer
30 changes: 30 additions & 0 deletions quest/m0/host-land/inline-merge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# [S] Merge inline from the coordinator

## Goal

`/quest-complete` and `/quest-spawn` merge a picked PR inline, without a
sub-agent. `/quest-merge` reads the PR with `quest status`, and when a
`## Review` record the guide counts names the head (a recorded skip for a
trivial change included), it queues that head with `quest merge --land` and
reports. Otherwise it recommends `/quest-iterate`, which runs the review and
any changes, and queues afterwards. `/quest-spawn` and `/quest-complete`
recommend `/quest-iterate` for every PR whose head has no counted review.

## Plan

Decided 2026-10-30 (user, /quest-plan); see the
[epic](/quest/m0/host-land/README.md).

- `/quest-merge` no longer fixes conflicts, failing checks, or review
findings, and no longer runs `quest check --base` or waits: the gate's
check covers `quest check`, and its fixer owns conflicts and failures.
Posted review findings that need changes make it recommend
`/quest-iterate` instead of queueing.
- Drop the skills' re-dispatch of `/quest-merge` after a `merge_conflict` or
`failed_checks` ejection; the fixer requeues those or hands them back,
and a handed-back PR is asked about again.
- This works on today's land.yml gate too, so it can land before the host
gate.
- Reconcile with [moq-dev/quest#288](https://github.com/moq-dev/quest/pull/288)
and [moq-dev/quest#276](https://github.com/moq-dev/quest/pull/276), which
also rewrite these skills, whichever lands first.
Loading