diff --git a/quest/m0/land-fixer/README.md b/quest/m0/land-fixer/README.md index 260b84b3..3e93a473 100644 --- a/quest/m0/land-fixer/README.md +++ b/quest/m0/land-fixer/README.md @@ -16,9 +16,10 @@ result, so a maintainer sees only behavior and design decisions. chain before the sandbox, and pre-checks queued PRs against the base while a batch runs. Batch size follows the measured failure rate. - The fixer starts from the base with internet access and the batch's PRs and - head SHAs. It ignores instructions in their diffs, builds and tests its - fixes, and pushes them onto the PRs' branches. The daemon posts the - comments the fixer writes into its result. + head SHAs. It ignores instructions in their diffs, rebuilds a conflicted + lockfile from the base's copy, builds and tests its fixes, and pushes them + onto the PRs' branches. The daemon posts the comments the fixer writes into + its result. - The gate merges locally instead of trusting GitHub's mergeability, and reruns a failed module before blaming. A rerun-proven flaky test is disabled in a separate PR with a follow-up quest. @@ -108,10 +109,6 @@ Decision prompts, selected options marked ✅: a PR is parked while a fixer job holds it (`src/cli/land-park.ts`), and [Local mergeability](/quest/m0/land-fixer/mergeability.md) follows the same rule. - -The README's landing section and `CONTRIBUTING.md` list what the fixer -resolves itself and what it hands back; that docs update finishes the epic. - - Audit of the merge-queue plan, 2026-11-01 (an independent read-only agent; the maintainer then decided each point). On moq over 24 hours: 128 landed and 390 ejected; 66 of 138 sandbox checks failed; batches stayed at @@ -129,11 +126,20 @@ resolves itself and what it hands back; that docs update finishes the epic. right after triage; [the batch check](/quest/m0/land-fixer/batch-check.md); [pre-checks](/quest/m0/land-fixer/precheck.md); and [tuning](/quest/m0/land-fixer/tuning.md) +- Amended 2026-11-01 (maintainer, /quest-plan in moq-dev/moq): a fixer merge + on [moq-dev/moq#7318](https://github.com/moq-dev/moq/pull/7318) rebuilt + `bun.lock` from the PR's side and undid the base's advisory fix; see + [Lockfile merges](/quest/m0/land-fixer/lockfile.md). + +The README's landing section and `CONTRIBUTING.md` list what the fixer +resolves itself and what it hands back. That docs update is the epic's own +work, done once the Required quests below have merged. ## Required - [Workflow permission](/quest/m0/land-fixer/workflows-permission.md) - waits on the maintainer to grant moq-bot `workflows`, so pushes touching workflows are accepted - [Attempt budget](/quest/m0/land-fixer/attempts.md) - only a fix that fails again spends a pick's single attempt +- [Lockfile merges](/quest/m0/land-fixer/lockfile.md) - a conflicted lockfile is rebuilt from the base's copy, so a fix never reverts the base's dependency changes - [Batch quest check](/quest/m0/land-fixer/batch-check.md) - the daemon runs `quest check` on the batch's chain before spending a sandbox check - [Pre-check queued PRs](/quest/m0/land-fixer/precheck.md) - compile and lint the next PRs against the base while a batch runs, parking broken ones before they batch - [Throughput tuning](/quest/m0/land-fixer/tuning.md) - batch size from the failure rate, no wasted base-conflict rounds, rerere, a fixer cap, and an explicit reasoning effort diff --git a/quest/m0/land-fixer/lockfile.md b/quest/m0/land-fixer/lockfile.md new file mode 100644 index 00000000..f37fd547 --- /dev/null +++ b/quest/m0/land-fixer/lockfile.md @@ -0,0 +1,69 @@ +# [S] The fixer rebuilds a conflicted lockfile from the base's copy + +## Goal + +When the fixer resolves a lockfile while merging the base (`bun.lock`, +`Cargo.lock`, `uv.lock`, `go.sum`, and the like), it starts +from the base's copy and runs the package manager, so the result adds only +the PR's own dependency changes. A fixer merge never reverts a dependency +change the base made, such as a security bump. + +Non-goals: running `bun audit` or another advisory scan in a repository's +land check; that is each repository's CI choice. + +## Plan + +Decided 2026-11-01 (maintainer, /quest-plan in moq-dev/moq). After `quest land` +removed [moq-dev/moq#7318](https://github.com/moq-dev/moq/pull/7318) with +`merge_conflict`, the fixer pushed its own merge of main, +[229973492b](https://github.com/moq-dev/moq/commit/229973492ba403cd414161c69c98e67680907e23), +which rebuilt `bun.lock` from the PR's side instead of main's. That undid +[moq-dev/moq#7443](https://github.com/moq-dev/moq/pull/7443)'s glob/minimatch +advisory fix: `glob@10.5.0` (with `jackspeak` and `path-scurry@1.11.1`) and +`minimatch@9.0.9` came back, and `bun audit` reported two moderate advisories, +GHSA-3g3m-2fjr-6pw4 and GHSA-g3hv-75wg-m249. The land check missed it because +moq runs `bun audit` only in Nightly. Redoing the merge from main's `bun.lock` +plus `bun install` added only the PR's packages and audited clean +([evidence](https://github.com/moq-dev/moq/pull/7318#issuecomment-6558969580)). + +- ✅ Plan it: start from the base's lockfile and regenerate, size S, in this + epic (m0) + +The fixer's merge resolution is Codex following `assets/land-fix.md`, whose +only lockfile rule is "regenerate lockfiles/generated files"; nothing says +which side to start from. Replace it with a procedure: for each lockfile the +merge touches, check out the `base` branch's copy (`git checkout base -- +`), apply the PR's manifest changes (merged `package.json`, +`Cargo.toml`, and so on), and run the package manager's minimal resolve +(`bun install`, a `cargo` build or `cargo update --workspace`, `uv lock`, +`go mod tidy`; never `cargo generate-lockfile` or an unpinned update). Then +compare the result with the base's copy and the merged manifests: every +lockfile change, and any manifest change the package manager itself made +(such as `go mod tidy` editing `go.mod`), must trace to a dependency or import +change in the PR. The fix reason names the lockfiles it rebuilt. + +Hand back, quoting the command's output or the offending diff, instead of +taking either side's copy when: + +- the package manager cannot rebuild the lockfile; +- a change does not trace to the PR; +- the PR's manifest no longer admits a version the base moved to, such as a + pin below the base's security bump. Keeping either version is a behavior + decision, not a mechanical fix. + +The prompt already lets build tools fetch from package registries (from +[moq-dev/quest#356](https://github.com/moq-dev/quest/pull/356)), which +regeneration needs. `flake.lock` stays a protected path in `validateFix`, and +this quest does not open it: a fixer-written `flake.lock` comes back as a +ready commit through +[Protected edits as ready commits](/quest/m0/land-fixer/protected-commit.md), +and that edit follows the same rule, rebuilt from the base's copy with +`nix flake lock`. Both quests edit `assets/land-fix.md`, so whichever lands +second merges the other's wording. + +Cover the rule in `test/land.test.ts`, which already asserts the prompt's +contents. + +## Related + +- [Protected edits as ready commits](/quest/m0/land-fixer/protected-commit.md) - returns a fixer-written `flake.lock` as a ready commit, built by this quest's rule