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
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -510,8 +510,12 @@ The wrapper starts an ephemeral container and runs `quest land fix <log> <prs...
there, exposing that repository read/write and the log read-only at the given paths.
It supplies a fresh HOME, `OPENAI_BASE_URL` (the OpenAI-compatible Responses
endpoint, including `/v1`) and `OPENAI_API_KEY` (the gate's proxy client key).
The daemon never supplies these or any Git/GitHub credential; the wrapper must
restrict network access to the model proxy. Codex login stays on CLIProxyAPI.
The daemon never supplies these or any Git/GitHub credential, and the wrapper
must keep every other credential out of the container. Its network must reach the
model proxy and, so the fixer can build and test its fix, the package registries
and `github.com`/`codeload.github.com` that the repository's dependencies come from.
The prompt allows only those dependency fetches: no GitHub API, no push, no other
host. Codex login stays on CLIProxyAPI.
The wrapper waits for the payload, returns its exit status, and tears down its
container on exit or SIGTERM. On timeout the daemon sends SIGTERM, allows at
least 10 seconds for container cleanup, then sends SIGKILL on a later collection. The payload defaults
Expand Down
13 changes: 13 additions & 0 deletions assets/land-fix.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,19 @@ the base's own changes to those paths: that is allowed when they come out exactl
a plain `git merge` of the base leaves them, with no conflict there for you to edit. Never push or contact
GitHub. Anything needing behavior changes or review must be handed back.

Build tools may fetch the dependencies the repository's manifests and lockfiles
name: from their package registries, such as crates.io, npm, PyPI, and the Go
module proxy, and from `github.com` and `codeload.github.com` for git
dependencies. Do not build with `--offline` to avoid them. These fetches are the
only GitHub contact allowed: never call GitHub's API yourself (`gh`,
`api.github.com`), push, or reach any other host.

Before reporting `fixed` or `requeue`, build and test the packages the PR and your
fix touch, including whatever the failure log shows failing, and name the commands
you ran in the reason. A PR you cannot get passing mechanically, or whose build or
tests you cannot run, goes back as a handback quoting the command and the output
line that shows why in the diagnosis.

Write `quest-land-result.json` in the repository root: a JSON array with exactly
one entry per supplied PR, no extra fields. Use one of:
{"number":123,"action":"requeue","reason":"healthy; flaky test"}
Expand Down
6 changes: 4 additions & 2 deletions quest/m0/host-land/fixer.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ as untrusted and hands back attempts to redirect its task.

The quest CLI implements `quest land fix`, durable collection, validation,
lease-pushes, Review records, and one attempt per maintainer pick. Host work
remains in kixelated/nixos: allow the ephemeral fixer container network access
only to CLIProxyAPI, provide `OPENAI_BASE_URL` and the gate's `OPENAI_API_KEY`,
remains in kixelated/nixos: the ephemeral fixer container (`qland-fix`) reaches
CLIProxyAPI and, like the check containers, the public internet without private
ranges (`modules/ci-egress.nix`), so its builds fetch dependencies;
`assets/land-fix.md` limits the fixer to those fetches. Provide `OPENAI_BASE_URL` and the gate's `OPENAI_API_KEY`,
and log the maintainer's Codex account into CLIProxyAPI. The wrapper runs with
the supplied repository as cwd, receives `<log> <PR numbers...>`, exposes the
log read-only, waits for `quest land fix`, preserves its exit status, and returns
Expand Down
12 changes: 9 additions & 3 deletions quest/m0/land-fixer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ moq-dev/rust2, moq-dev/rind and moq-dev/quest.
| ~75 | "requeued unchanged": collateral of a batch another PR broke | [Batch triage](/quest/m0/land-fixer/triage.md) |
| 36 | picked again while fixing; the newer pick is kept, so nothing is lost | not planned |
| 17 | conflicts in protected paths (`flake.nix`, `.github/`), mostly mechanical; resolved by hand on moq-dev/moq#7344, #7315, #7318 | [Protected edits](/quest/m0/land-fixer/protected.md) |
| 17 of the last 40 jobs | `cargo` fails offline ("failed to get `uniffi`"), so Rust fixes were requeued uncompiled: moq-dev/moq#7357 sank three batches, and #6985's lockfile could not be regenerated | [Registry network](/quest/m0/land-fixer/network.md) |
| 17 of the last 40 jobs | `cargo` fails offline ("failed to get `uniffi`"), so Rust fixes were requeued uncompiled: moq-dev/moq#7357 sank three batches, and #6985's lockfile could not be regenerated | fixed by [moq-dev/quest#356](https://github.com/moq-dev/quest/pull/356): the prompt allows dependency fetches and requires a build and test |
| 2 | GitHub refused the push to a fork because the merge touches workflows: moq-dev/moq#7439, #7467 | [Fork commits](/quest/m0/land-fixer/fork-commit.md) |
| several batches | a flaky ffmpeg timeout ([moq-dev/moq#7480](https://github.com/moq-dev/moq/pull/7480)) ejected whole batches | [Flaky tests](/quest/m0/land-fixer/flaky.md) |
| ~15 | design conflicts, correctly handed back | none |
Expand All @@ -48,7 +48,14 @@ Decision prompts, selected options marked ✅:
and [Local mergeability](/quest/m0/land-fixer/mergeability.md) into
this epic
- How attempts count: see [Attempt budget](/quest/m0/land-fixer/attempts.md).
- How the fixer gets dependencies: see [Registry network](/quest/m0/land-fixer/network.md).
- How the fixer gets dependencies:
- Host prefetches the job's lockfile dependencies and mounts them read-only
- ✅ Allow registry network. The host already gave the fixer container
public egress; `assets/land-fix.md`'s "never contact GitHub" made it
build `--offline`. [moq-dev/quest#356](https://github.com/moq-dev/quest/pull/356)
allows fetches from package registries and `github.com`/`codeload.github.com`
and makes the fixer build and test what it reports.
- Leave it
- Protected paths: see [Protected edits](/quest/m0/land-fixer/protected.md).
- Fork pushes GitHub refuses: see [Fork commits](/quest/m0/land-fixer/fork-commit.md).
- Flaky tests: see [Flaky tests](/quest/m0/land-fixer/flaky.md).
Expand All @@ -67,7 +74,6 @@ resolves itself and what it hands back; that docs update finishes the epic.
## Required

- [Attempt budget](/quest/m0/land-fixer/attempts.md) - only a fix that fails again spends a pick's single attempt
- [Registry network](/quest/m0/land-fixer/network.md) - the fixer fetches dependencies, so it builds and tests what it requeues
- [Batch triage](/quest/m0/land-fixer/triage.md) - the fixer blames the failing PR before ejection, and a red base halts the queue
- [Flaky tests](/quest/m0/land-fixer/flaky.md) - the gate reruns a failed module, disables a flaky test in the next batch, and files a follow-up
- [Local mergeability](/quest/m0/land-fixer/mergeability.md) - `quest land` merges with the quest driver instead of ejecting on GitHub's conflict flag
Expand Down
46 changes: 0 additions & 46 deletions quest/m0/land-fixer/network.md

This file was deleted.

12 changes: 12 additions & 0 deletions test/land.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2174,6 +2174,18 @@ ${requeueScript}
])
expect(fixerPrompt).toContain(text);
});
test("lets the fixer fetch dependencies and requires it to verify what it reports", () => {
for (const text of [
"from `github.com` and `codeload.github.com` for git",
"Do not build with `--offline`",
"never call GitHub's API yourself",
"or reach any other host",
"Before reporting `fixed` or `requeue`, build and test",
"name the commands",
"quoting the command and the output",
])
expect(fixerPrompt).toContain(text);
});
test.each(["deleted branch", "gitfile", "symlink", "corrupt objects", "oversized"])(
"hands back %s and keeps collection usable",
async (kind) => {
Expand Down
Loading