diff --git a/quest/m0/README.md b/quest/m0/README.md index bf047680..ecb45caf 100644 --- a/quest/m0/README.md +++ b/quest/m0/README.md @@ -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? @@ -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 diff --git a/quest/m0/gate-load-wording.md b/quest/m0/gate-load-wording.md new file mode 100644 index 00000000..351fca4d --- /dev/null +++ b/quest/m0/gate-load-wording.md @@ -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. diff --git a/quest/m0/kix/README.md b/quest/m0/kix/README.md index 77b8e28a..25d30587 100644 --- a/quest/m0/kix/README.md +++ b/quest/m0/kix/README.md @@ -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 diff --git a/quest/m0/kix/runner-review.md b/quest/m0/kix/runner-review.md new file mode 100644 index 00000000..c0eed1ed --- /dev/null +++ b/quest/m0/kix/runner-review.md @@ -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. diff --git a/quest/m0/queue-watcher/README.md b/quest/m0/queue-watcher/README.md index fe52a3b1..a822dbe2 100644 --- a/quest/m0/queue-watcher/README.md +++ b/quest/m0/queue-watcher/README.md @@ -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 @@ -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 @@ -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 diff --git a/quest/m0/queue-watcher/flaky-verdicts.md b/quest/m0/queue-watcher/flaky-verdicts.md new file mode 100644 index 00000000..8bccc8eb --- /dev/null +++ b/quest/m0/queue-watcher/flaky-verdicts.md @@ -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. diff --git a/quest/m0/review-test-load.md b/quest/m0/review-test-load.md new file mode 100644 index 00000000..d634733e --- /dev/null +++ b/quest/m0/review-test-load.md @@ -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. diff --git a/quest/m1/README.md b/quest/m1/README.md index f92bd2d3..2a897ce1 100644 --- a/quest/m1/README.md +++ b/quest/m1/README.md @@ -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 @@ -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 diff --git a/quest/m0/bun-efault.md b/quest/m1/bun-efault.md similarity index 100% rename from quest/m0/bun-efault.md rename to quest/m1/bun-efault.md diff --git a/quest/m1/git-env.md b/quest/m1/git-env.md new file mode 100644 index 00000000..2337ca27 --- /dev/null +++ b/quest/m1/git-env.md @@ -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 ` 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. diff --git a/quest/m1/kix/guide.md b/quest/m1/kix/guide.md index 03d9cacc..87e48e96 100644 --- a/quest/m1/kix/guide.md +++ b/quest/m1/kix/guide.md @@ -26,6 +26,16 @@ how the service works. decision flow. - Extend the guide when cloud runners, API-key funding, and donations ship; do not advertise them as available before then. +- Explain read-only pull-request CI (`cloudflare/GITHUB.md`) and what the + setup page's CI panel checks: repository settings, not workflow files. + Point maintainers at a workflow linter such as zizmor, which moq-dev/moq + already runs, for jobs that request write `permissions:`, use secrets + outside an environment, or check out a PR head under `pull_request_target` + or `workflow_run`. Decided 2026-11-03 (coordinator, /quest-complete + follow-ups) instead of parsing workflows in the Worker, which + [moq-dev/quest#434](https://github.com/moq-dev/quest/pull/434) suggested: + none of the pilots' pull-request jobs can write, and the linter covers + every case it named. - Validate the guide against the running UI and a real pilot repository. ## Required diff --git a/quest/m1/release.md b/quest/m1/release.md index f5aa26df..87db4e2a 100644 --- a/quest/m1/release.md +++ b/quest/m1/release.md @@ -35,5 +35,13 @@ Work: 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. +- Check that the Install check (`.github/workflows/install-check.yml`, which + Release calls) passes all 12 jobs on the new tag. Against v0.1.0 its 4 + Windows jobs fail because that release has no Windows assets ("No matching + asset found for platform windows-x64", and a 404 for the archive): + [run 40144909978](https://github.com/moq-dev/quest/actions/runs/40144909978) + and [run 41660575051](https://github.com/moq-dev/quest/actions/runs/41660575051), + as [moq-dev/quest#430](https://github.com/moq-dev/quest/pull/430) + noted (coordinator, /quest-complete follow-ups, 2026-11-03). - Decide in the PR how later releases are cut, such as a step in the release checklist or a recurring quest through `/quest-recurring`. diff --git a/quest/m1/review-harness.md b/quest/m1/review-harness.md index 3fda8987..5125ac0a 100644 --- a/quest/m1/review-harness.md +++ b/quest/m1/review-harness.md @@ -21,6 +21,15 @@ was [moq-dev/quest#426](https://github.com/moq-dev/quest/pull/426). premium Fable tier (`claude-fable-5-1`); `gpt-6.1-sol` is Codex's first-listed "latest workhorse" in `~/.codex/models_cache.json`, beside the frontier `gpt-6-astra`. Neither pin changed. + - Check that the pinned Claude Code maps the Claude id to each cloud + provider. `quest review` keeps Bedrock, Vertex and Foundry routing + ([moq-dev/quest#424](https://github.com/moq-dev/quest/pull/424)) but + strips `ANTHROPIC_MODEL`, so the pin must resolve on each route. + Claude Code 2.1.316's model catalog lists `claude-opus-5-5` with + `provider_ids` (Bedrock `us.anthropic.claude-opus-5-5`; Vertex and + Foundry `claude-opus-5-5`). Find the new pin's entry the same way, and + plan a quest if a provider has none (coordinator, /quest-complete + follow-ups, 2026-11-03). - Run the live sandbox test, `just review-sandbox`, with the CLIs installed at the time, through `quest gate`, and plan a quest for any failure. - Check first: diff --git a/quest/m1/windows-suite.md b/quest/m1/windows-suite.md new file mode 100644 index 00000000..e3ac085b --- /dev/null +++ b/quest/m1/windows-suite.md @@ -0,0 +1,77 @@ +# [S] The native Windows suite passes nightly + +## Goal + +Check's `native Windows` jobs run nightly against `main` and on +`workflow_dispatch`, not on pull requests or in the merge group, and they +pass on both `windows-2022` and `windows-11-arm`. A Windows regression may +land; the next nightly run catches it, and GitHub's notification for a +failed scheduled run is the signal. + +## 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. +The user chose to land [moq-dev/quest#437](https://github.com/moq-dev/quest/pull/437) +and fix these failures separately. + +Decided 2026-11-03 (user, /quest-complete, on +[moq-dev/quest#455](https://github.com/moq-dev/quest/pull/455)), moving it +from m0 to m1 since Windows isn't a priority: + +- How should a Windows regression be caught before it lands? + - Run on ready PRs (recommended), not picked + - Require in the merge group, not picked + - Main only, cancelling in progress only on PRs, not picked + - ✅ Other: "I don't really care about windows, it's fine if we catch + issues nightly." + +Evidence, gathered 2026-11-03: + +- `main`'s Check has failed on every completed push since `ef8c4b50` + (15:45Z), only in its native Windows jobs. The latest, + [run 41696344037](https://github.com/moq-dev/quest/actions/runs/41696344037) + on `ee96a82e`, has 7 failures: + - `test/runner.test.ts` › "pick the other vendor…": the test expects a + `:`-joined `PATH`, while `reviewerFor` correctly joins with + `path.delimiter` (`src/runner/review.ts:51`). From + [moq-dev/quest#417](https://github.com/moq-dev/quest/pull/417). + - `test/move.test.ts` › three `quest check --fix` tests expect LF where + Windows writes CRLF. From + [moq-dev/quest#427](https://github.com/moq-dev/quest/pull/427). + - `test/worktree.test.ts` › "initializes nested submodules…" and "ignores + inherited Git location variables…" expect `original\n` and read + `original\r\n`. "fails explicitly without a supported backend" calls + the synchronous `run` helper for `worktree create`, which is now async + ("use await main for asynchronous CLI commands"). The test skips on + Linux, and only Windows runs the suite elsewhere. All three first fail + on `ee96a82e`, after + [moq-dev/quest#445](https://github.com/moq-dev/quest/pull/445) and + [#437](https://github.com/moq-dev/quest/pull/437). +- Today the Windows jobs run on every push to `main` and on dispatch + (`if: github.event_name != 'pull_request'` in + `.github/workflows/check.yml`). Check's `cancel-in-progress` cancels most + of those pushes in a busy hour, so a failure surfaces only on the last + push of a burst. The queue build (`.github/workflows/queue-build.yml`) + runs on Linux only. +- Install check's Windows jobs failing against v0.1.0 is a different cause: + v0.1.0 has no Windows assets. The next release covers it + ([Release with worktree hooks](/quest/m1/release.md)). + +Work: + +- Fix the 7 failures where each one's cause lies, so the first nightly run + starts green: compare text with line endings normalized wherever Git or + Quest may write CRLF on Windows, use `path.delimiter` in the `PATH` + expectation, and await `main` for `worktree create`. Keep each test's + assertion; never skip a test on Windows to pass. +- Run the Windows jobs on a nightly `schedule` against `main` and on + `workflow_dispatch`. Prefer nightly only, dropping them from pushes to + `main`, as the simpler and cheaper choice; keep push runs only if the + work finds a concrete reason. Whether they stay in `check.yml` or move to + a workflow of their own is this quest's call, whichever keeps the + triggers simplest. +- Rely on GitHub's failure notification for scheduled runs, which goes to + whoever last changed the workflow's cron. Add no issue filing, chat + alert, or other reporting. +- Dispatch the Windows jobs on the PR's head and record that both pass.