diff --git a/quest/m0/mistake-audit.md b/quest/m0/mistake-audit.md index 4e4f792c..68c88672 100644 --- a/quest/m0/mistake-audit.md +++ b/quest/m0/mistake-audit.md @@ -29,7 +29,7 @@ and `/reflect`): - Rejected: forge records only; transcripts through a script each run - What gates each run? - ✅ A week since the last run, the way - [the release cut](/quest/m1/release-cut.md) waits. The decision named a + the release cut waited. The decision named a `## Waiting` item because quests could not yet be held until a date; since `## Scheduled` exists, the run holds the date there (agent, 2026-11-11). diff --git a/quest/m0/pin-bumps/README.md b/quest/m0/pin-bumps/README.md new file mode 100644 index 00000000..59d80049 --- /dev/null +++ b/quest/m0/pin-bumps/README.md @@ -0,0 +1,51 @@ +# Every merge reaches every repository that pins quest + +## Goal + +A merge to quest's `main` that changes what ships becomes a release, and within the hour +every other repository with moq-bot installed whose flake locks quest through +exactly one root input gets a bump PR to that release, which lands on its own. No person or agent hand-bumps a +flake pin. Pins through mise or the installer stay out of scope: no moq-dev, +kixel-ai, or kixelated repository uses them. + +The epic finishes with an end-to-end run: a merge to `src/` cuts a release, +and the watcher opens and lands a bump to it in an enrolled repository whose +stubs that release changes, with `quest init`'s refreshed stubs in the PR. + +## Plan + +Decided 2026-11-12 (maintainer, /quest-plan), after moq-dev/moq sat on +`93c9c2ef` past [moq-dev/quest#646](https://github.com/moq-dev/quest/pull/646), +so quest spawns there kept writing XS quests on Haiku 5.5 xhigh and hit its +rate limits until a hand bump +([moq-dev/moq#8623](https://github.com/moq-dev/moq/pull/8623)). The bump pass +from [moq-dev/quest#550](https://github.com/moq-dev/quest/pull/550) never ran: +the host's watcher has no `--bump` flags, since its wiring sits in the stale +draft [kixelated/nixos#36](https://github.com/kixelated/nixos/pull/36). + +- What do consumers pin? ✅ A release, cut on every merge that changes what ships + (rejected: quest's `main`, which the bump pass follows today). +- What bumps them? ✅ The watcher's `--bump`, following the latest release + (rejected: Renovate with a stale-stub check, since hosted Renovate cannot run + `quest init` or `quest check --fix` and most bumps need them: 48 quest + commits touched skills from 2026-11-01 to 2026-11-12; Renovate with a + fixup workflow in each consumer; Kixel Code, which runs no host jobs until + its m1). Kixel Code retires the watcher later and takes bumps with it. +- Do bumps wait for a merge click? ✅ No, they land once checks pass, as the + bump pass does today (rejected: a click, which Kixel Code requires of + dependency bumps; a quest bump is the exception). +- Which repositories? ✅ Every other repository moq-bot is installed on whose + `flake.lock` locks quest through exactly one root input. quest's own + `quest-pinned` input, the merge driver's, stays on Dependabot's weekly nix + update (`flake.nix`); bumping it here would cut a release, since it changes + the flake, which would trigger another bump (rejected: a `--bump` list in the host's + configuration, since #36's list went stale within five days). + +Turning it on is the host's work, planned in kixelated/nixos's tree. + +## Waiting + +- kixelated/nixos: the quest watcher runs the bump pass, planned as + `quest/m0/quest-bump.md` there + ([kixelated/nixos#70](https://github.com/kixelated/nixos/pull/70)); check + that the `quest-land` journal on the maintainer's host shows a `bump` line. diff --git a/quest/m0/pin-bumps/discover.md b/quest/m0/pin-bumps/discover.md new file mode 100644 index 00000000..5e7deb04 --- /dev/null +++ b/quest/m0/pin-bumps/discover.md @@ -0,0 +1,30 @@ +# [S] The bump pass finds its own targets + +## Goal + +`quest land watch` bumps every repository its App is installed on whose +`flake.lock` locks the watched repository through exactly one root input, with no list of +repositories on the host: installing moq-bot on a repository enrolls it, and +uninstalling it stops its bumps. + +## Plan + +Decided 2026-11-12 (maintainer, /quest-plan; see the +[epic](/quest/m0/pin-bumps/README.md)): ✅ discover the targets (rejected: +`--bump ` flags in the host's configuration, which went stale). +Replace the repeatable `--bump ` with one switch; nothing is in +production, so drop the list form. + +A pass lists the App's installations and their repositories, reads each +default branch's `flake.lock`, and treats the repositories that lock the +watched repository through exactly one root input as targets, which is what +the bump needs (`questInput` in `src/cli/land-bump.ts`). Skip the watched repository itself. Rereading +every repository each pass costs API quota: keep it to what a pass needs, such +as only when the base moved. + +Update README.md's "Pin bumps" section and its examples to the switch, +matching `quest land watch --help`. + +Tests against a fake GitHub: a repository that locks quest is bumped, one +that doesn't is never cloned, and one dropped from the installation is not +bumped again. diff --git a/quest/m0/pin-bumps/follow-release.md b/quest/m0/pin-bumps/follow-release.md new file mode 100644 index 00000000..7580f1ba --- /dev/null +++ b/quest/m0/pin-bumps/follow-release.md @@ -0,0 +1,30 @@ +# [S] The bump pass follows the latest release + +## Goal + +A bump moves each target to the commit of the watched repository's latest +release instead of its base's head, so consumers run only released quest, and +the PR names the release it moves to. + +## Plan + +Decided 2026-11-12 (maintainer, /quest-plan; see the +[epic](/quest/m0/pin-bumps/README.md)): ✅ consumers pin releases (rejected: +quest's `main`). + +Keep the pin lock-only: `flake.nix` names no revision or tag, and +`flake.lock` locks the release's commit, so a bump stays a lock-only diff. +Today the pass detects and strips only a revision: `questInput` in +`src/cli/land-bump.ts` reads `original.rev`, while a tag pin is recorded as +`original.ref`. Detect and strip a tag too, or a later `nix flake update` +resolves the tag again and moves the pin back. A repository +that wants a slower cadence leaves moq-bot off and pins by hand. + +Key a target's recorded bump on the release it moved to, not the base head the +watcher passes in: otherwise a pass that runs before the Release workflow tags +the base records the target done, and the release that follows is skipped +until `main` moves again. Update README.md's "Pin bumps" section to match. + +## Required + +- [Release every merge that changes what ships](/quest/m0/pin-bumps/release.md) - the releases a bump follows diff --git a/quest/m0/pin-bumps/release.md b/quest/m0/pin-bumps/release.md new file mode 100644 index 00000000..b36b2a10 --- /dev/null +++ b/quest/m0/pin-bumps/release.md @@ -0,0 +1,67 @@ +# [M] Release every merge that changes what ships + +## Goal + +Each push to `main` that changes what ships publishes a new quest release +with no person involved: the Release workflow picks the next version, tags +it, and publishes the binaries, so the biweekly cut and the maintainer's tag +push are gone. `quest --version` names the release in its binaries, and a +flake build names its release or commit. + +## Plan + +Decided 2026-11-12 (maintainer, /quest-plan; see the +[epic](/quest/m0/pin-bumps/README.md)): ✅ the workflow cuts every release +(rejected: each user-facing PR bumps `package.json` and a merge-time workflow +tags it, since PRs racing through the merge queue would conflict on that +line). This replaces the biweekly cut decided 2026-11-09 on +[moq-dev/quest#587](https://github.com/moq-dev/quest/pull/587) and lifts +CONTRIBUTING.md's rule reserving release tags for the maintainer: no release +has shipped since v0.1.0, because v0.2.0's run failed and v0.2.1 was never +tagged. + +Decided 2026-11-12 (maintainer, at the review's design checkpoint): ✅ Release +reconciles `main` with the published releases, and tagging is its last step +(rejected: recovery steps for each way a run can fail, which review kept +finding new cases of; semantic-release, an added dependency that publishes +before the checks this needs to pass first). So: + +- Every run, on each push to `main` and on a daily schedule, compares `main` + with the latest published release and cuts one when that range touches + what ships: everything the binaries or the flake package build from, + `assets/` (bundled into the binary) and `nix/` included, plus every file + Release publishes, such as `scripts/installer.sh`. Release's pull request + path filter, which misses `assets/` and `nix/` today, uses the same + predicate, so the two cannot drift. A + cancelled or failed run then needs no recovery: the next run sees the same + unreleased range. Runs on `main` queue rather than cancel each other. +- A run builds every binary and passes the lifecycle and archive install + checks on those local artifacts before it tags. It then uploads every + asset to a draft release and publishes the draft, which creates the tag, so + no tag exists without its complete release; a run that fails before that + leaves only a draft, which the next run replaces. The next version is + greater than every existing tag, so the dead v0.2.0 tag is skipped (v0.2.1 + was never tagged): minor when the range holds a `!` subject, patch + otherwise. +- The checks that need a published release, mise and the installer's URL, + run after it and fail loudly; their fix ships as the next release. They + block no consumer, since the bump pass moves flake pins, which build from + source at the release's commit. +- The version comes from the tag: `package.json` stops carrying one, so no + release needs a PR. Everything that reads it moves to the build's input: + find them by searching for it, since they span the CLI (`src/cli/main.ts`, + `src/cli/hooks.ts`), `nix/package.nix`, `scripts/lifecycle-check.mjs`, the + tests, and the workflows' version checks and Windows fallback tag. A + release binary embeds its tag; a flake build, which cannot see tags, embeds + its commit, which `flake.nix` passes to `nix/package.nix`. It also builds + `quest-pinned` from that input's own, older `nix/package.nix`, so the new + argument must not break that call. +- Update CONTRIBUTING.md's Releases section and SETUP.md's pinning advice. +- The first automated release exists only after the implementing PR merges. + That PR rewrites this quest to its checks, with a `## Waiting` item on the + release, rather than deleting it: the Windows ZIPs SETUP.md expects, every + Install check job, and that a release binary has `quest worktree hook`, the + Goal of [the v0.2.1 cut](https://github.com/moq-dev/quest/blob/2a80c902/quest/m1/release.md). Then drop SETUP.md's v0.1.0 caveat and the "next release" + notes in README.md and docs/windows.md, and delete this quest. +- Milestone: ✅ m0 (rejected: m1), so those first-release checks, which the + deleted m1 quests held, move to m0 with it. diff --git a/quest/m1/release-cut.md b/quest/m1/release-cut.md deleted file mode 100644 index 40b35a77..00000000 --- a/quest/m1/release-cut.md +++ /dev/null @@ -1,53 +0,0 @@ -# [S] Cut a release - -## Goal - -Every two weeks, when `main` has user-facing changes since the last tag, a -new quest release ships with its version bumped, so adopters on the release, -mise, and installer routes stay current. Recurring; nothing ends it. - -## Plan - -Decided 2026-11-09 (maintainer, /quest-complete of -[moq-dev/quest#587](https://github.com/moq-dev/quest/pull/587)): - -- How are later releases cut? ✅ This recurring quest, every two weeks, when - `main` has user-facing changes (rejected: a step in CONTRIBUTING.md's - Releases section; ad hoc). A quest resurfaces each time ready work is - triaged; a checklist line doesn't. -- Where is the two-week gate? ✅ A `## Waiting` item (rejected: a Plan line). - Quests can't be held until a date, so a Plan line would let a spawn claim - the quest only to find it too early, while coordinators check outside - conditions before starting and `quest waiting` lists them. Each run's PR - resets the item to the new release's date when it recreates the quest. - -Each run: - -- If the commits from the last tag to `origin/main` hold no - user-facing change (only `quest/`, CI, tests, or chores), skip the cut and - recreate the next run. -- Bump `package.json` by semver's 0.x convention: minor when the range has a - breaking (`!`) commit, patch otherwise. List the user-facing changes in the - PR body. -- The tag push stays a maintainer step, since CONTRIBUTING.md reserves - release tags for the maintainer; agents cannot push them. The PR rewrites - this quest to the checks that follow the tag, with a `Maintainer:` item to - push `vX.Y.Z` from `main` after merge, checked with - `gh release view vX.Y.Z -R moq-dev/quest`. -- After the tag, check that the release has every archive SETUP.md names and - that the Install check (`.github/workflows/install-check.yml`) passed all - its jobs on the Release run. Plan a quest for any failure. -- The PR that finishes those checks deletes this run and creates the next at - this path, or at the same path in the lowest open milestone once m1 - completes. It carries forward the last tag, its date, and anything to check - first, and resets the `Waiting` item to two weeks after the new release. - -## Waiting - -- moq-dev/quest: two weeks pass since the last release (v0.2.1 once it - ships); check `gh release list -R moq-dev/quest --limit 1` - -## Required - -- [Cut a release with the worktree hooks](/quest/m1/release.md) - v0.2.1 is - the first release this cadence follows diff --git a/quest/m1/release.md b/quest/m1/release.md deleted file mode 100644 index 8650ca87..00000000 --- a/quest/m1/release.md +++ /dev/null @@ -1,30 +0,0 @@ -# [S] Cut a release with the worktree hooks - -## Goal - -A tagged quest release includes `quest worktree hook`, so SETUP.md's release, -mise, and installer routes give adopters a `quest` whose Claude Code hooks -work. Later releases follow [Cut a release](/quest/m1/release-cut.md). - -## Plan - -`package.json` is at 0.2.1. The v0.2.0 tag stays a tag with no release: its -Release run failed on macOS, which -[moq-dev/quest#624](https://github.com/moq-dev/quest/pull/624) fixed. - -Once the v0.2.1 release exists: - -- Check it has the Windows ZIPs SETUP.md expects, and that the Install check - (`.github/workflows/install-check.yml`, which Release calls) passes all 12 - jobs; against v0.1.0 its 4 Windows jobs failed for lack of Windows assets - ([run 40144909978](https://github.com/moq-dev/quest/actions/runs/40144909978) - and [run 41660575051](https://github.com/moq-dev/quest/actions/runs/41660575051)). -- Then drop SETUP.md's v0.1.0 caveat and the "next release" notes in - README.md and docs/windows.md. - -## Waiting - -- Maintainer: once this bump merges, tag `main` as `v0.2.1` and push the tag, - since CONTRIBUTING.md reserves release - tags for the maintainer, so no agent pushes one; check with - `gh release view v0.2.1 -R moq-dev/quest`