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
2 changes: 1 addition & 1 deletion quest/m0/mistake-audit.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
51 changes: 51 additions & 0 deletions quest/m0/pin-bumps/README.md
Original file line number Diff line number Diff line change
@@ -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.
30 changes: 30 additions & 0 deletions quest/m0/pin-bumps/discover.md
Original file line number Diff line number Diff line change
@@ -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 <owner/repo>` flags in the host's configuration, which went stale).
Replace the repeatable `--bump <owner/repo>` 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.
30 changes: 30 additions & 0 deletions quest/m0/pin-bumps/follow-release.md
Original file line number Diff line number Diff line change
@@ -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
67 changes: 67 additions & 0 deletions quest/m0/pin-bumps/release.md
Original file line number Diff line number Diff line change
@@ -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.
53 changes: 0 additions & 53 deletions quest/m1/release-cut.md

This file was deleted.

30 changes: 0 additions & 30 deletions quest/m1/release.md

This file was deleted.