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
4 changes: 3 additions & 1 deletion quest/m0/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ ownership-manifest design:

## Required

- [Lifecycle EBUSY](/quest/m0/lifecycle-ebusy.md) - the Windows lifecycle check stops failing at random while removing its temp directory
- [Lifecycle flakes](/quest/m0/lifecycle-flakes.md) - lifecycle CI jobs stop failing on Windows `EBUSY` and unstarted macOS jobs
- [Worker tests](/quest/m0/worker-tests.md) - every Worker test passes alone and in any order
- [Gate bench](/quest/m0/gate-bench.md) - measure headroom admission on an idle host
- [Agent lifecycle integration](/quest/m0/worktree-agents.md) - reclaim completed and suspended checkouts through their harness
- [Agent workflow helpers](/quest/m0/helpers/README.md) - CLI commands for CI waits, PR status, claims, quest moves, and serialized merges

Expand Down
25 changes: 25 additions & 0 deletions quest/m0/gate-bench.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# [XS] Measure gate headroom on an idle host

## Goal

The gate's idle-host behaviour is measured: `scripts/gate-bench.sh gated 8`
and `ungated 8` run on an otherwise idle host, and the results are recorded
in a PR. A gated burst that starts together, close to the ungated makespan,
confirms headroom admission; anything else becomes a follow-up.

## Plan

Decided 2026-10-22 (user) as a follow-up of
[kixelated/quest#189](https://github.com/kixelated/quest/pull/189), whose
benchmarks ran while other agents kept the host's load at 19-42 on 24 CPUs,
so they measured the busy-host path, not the idle burst the quest was for.
The earlier baseline, from
[kixelated/quest#177](https://github.com/kixelated/quest/pull/177), was 104 s
gated against 19 s ungated for a burst of 8.

- Run on a host with no other agents or builds; record the 1-minute load
before each run alongside the results.
- Delete this quest in the PR that records the results.
- Dropped (user): asking Bun upstream to make `os.userInfo().homedir` ignore
`$HOME` (the child-process lookup costs about 10 ms), and handling a macOS
hostname that changes with the network, until it is seen in practice.
2 changes: 2 additions & 0 deletions quest/m0/helpers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ commands from Sep-Oct. Session counts in each child come from that window.

## Required

- [Merge rules](/quest/m0/helpers/merge-rules.md) - squash merges only, and no merge with changes no review covered
- [Complete loop](/quest/m0/helpers/complete-loop.md) - `/quest-complete` re-scans PRs, keeps picks and holds, and counts rounds per PR
- [Status holds](/quest/m0/helpers/status-holds.md) - `quest status` shows a PR's `quest:*` hold
- [Headless agents](/quest/m0/helpers/headless-agents.md) - `/quest-spawn api` launches, resumes, and stops billed agents through one command auto mode allows

## Related
Expand Down
39 changes: 39 additions & 0 deletions quest/m0/helpers/merge-rules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# [XS] Land squash merges, and review the final head

## Goal

Pull requests in this repository land as squash merges, and no pull request
merges with changes no review covered, other than conflict-free merges from
its base or a reviewer's own suggested patch applied unchanged.

## Plan

Decided 2026-10-22 (user) from a merge wave in which
[kixelated/quest#189](https://github.com/kixelated/quest/pull/189) landed as
a merge commit, and [#183](https://github.com/kixelated/quest/pull/183),
[#185](https://github.com/kixelated/quest/pull/185),
[#188](https://github.com/kixelated/quest/pull/188),
[#189](https://github.com/kixelated/quest/pull/189), and
[#190](https://github.com/kixelated/quest/pull/190) merged with fixes pushed
after their last review, up to about 150 lines and including #188's security
rework. The user asked for these root-instruction, guide, and setting changes
through this plan.

- **Squash (user).** Add a line to this repository's root `AGENTS.md` saying
pull requests land as squash merges; the merge skill picks
`quest merge --land --squash` from it. Also set the repository to allow
only squash merges (`allow_merge_commit` and `allow_rebase_merge` false,
through `gh api`), approved by the user on 2026-10-22, so a wrong method
fails instead of landing. Rejected: either one alone.
- **Re-review (user).** Tighten the guide's Reviews section in
`assets/AGENTS.md`: "trivial changes since the last review" means only
conflict-free merges from the base or a reviewer's suggested patch applied
unchanged. A base merge that needed a hand-resolved conflict is reviewed
like any other change (narrowed by the user from Codex's review of
[#195](https://github.com/kixelated/quest/pull/195)). Any other change
waits for a review of the head; if none arrives within the merge skill's
wait bound, the agent asks the user instead of merging. Rejected:
re-review on every head, exempting every base merge, and leaving
"trivial" to the agent.
- Ranked first in the epic: prose and one setting, and it stops unreviewed
merges now.
20 changes: 20 additions & 0 deletions quest/m0/helpers/status-holds.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# [XS] Show PR holds in quest status

## Goal

`quest status <pr>` shows whether a `quest:*` hold is on the PR: its label,
how long ago it was taken, and the hold's timeline event, so `/quest-complete`
can skip PRs another session holds without a separate label read.

## Plan

Decided 2026-10-22 (user) as a follow-up of
[kixelated/quest#185](https://github.com/kixelated/quest/pull/185), which
added the holds:

- Read the hold the same way the state commands do, through the shared
GitHub client, and report a draft its starter still holds the same way.
Comment on lines +15 to +16

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Page the hold timeline before promising its event

On a PR with more than 100 relevant timeline events after a hold was taken, reusing the state-command reader cannot provide the promised age or event: src/cli/hold.ts:25 requests only timelineItems(last: 100), and holder() deliberately omits those details when the label-add event is absent. Require pagination (or a direct event lookup) here so quest status satisfies the stated output on long-lived PRs.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disagree for this quest. The reader in src/cli/hold.ts filters the timeline to label, auto-merge, and merge-queue events, so falling off its last 100 needs 100 such events after the hold was taken, which no PR here comes close to. quest status deliberately shares that reader, so if paging is ever needed it belongs in the shared reader and fixes the state commands too, rather than in this quest.

(Written by Claude Opus 5.5)

- Update the `complete` skill to read holds from `quest status`, and the
README's status example.
- Ranked after the [complete loop](/quest/m0/helpers/complete-loop.md), which
also edits `complete`.
2 changes: 2 additions & 0 deletions quest/m0/kix/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ fixes what it finds:

## Required

- [Runner hardening](/quest/m0/kix/runner-hardening.md) - one runner per home, and `context` reads every review thread
- [Deploy kix.quest](/quest/m0/kix/deploy.md) - the operator registers the App and deploys the Worker with GitHub sign-in at kix.quest
- [Operator setup](/quest/m0/kix/operator-setup.md) - fork namespace, pilot installations, and a verified test PR
- [Per-project forks](/quest/m0/kix/forks.md) - each project publishes through its own fork, recorded by repository ID
Expand All @@ -119,5 +120,6 @@ fixes what it finds:
- [Agent activity](/quest/m0/kix/activity.md) - agent cards and map highlights built from checkpoint summaries
- [Web planning](/quest/m0/kix/planning.md) - issue-to-quest interviews produce draft planning PRs
- [Web execution](/quest/m0/kix/execution.md) - spawn and iterate through the UI, ending in contribution PRs
- [Seeded GitHub fake](/quest/m0/kix/github-fake.md) - the local server runs publication end to end, and tests share its fake
- [Onboarding guide](/quest/m0/kix/guide.md) - a complete maintainer path, from runner setup through a reviewed PR
- [Merged claims](/quest/m0/kix/merged-claims.md) - the board ignores branches whose pull request merged, as the CLI does
19 changes: 19 additions & 0 deletions quest/m0/kix/github-fake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# [S] Run publication end to end against the seeded fake GitHub

## Goal

The seeded local server's fake GitHub (`cloudflare/dev/github.ts`) models
commits, fast-forward ref updates, and pull request creation, so the local
server can run a job's publication end to end, and publication tests use the
same fake instead of their own.

## Plan

Decided 2026-10-22 (user) as a follow-up of
[kixelated/quest#190](https://github.com/kixelated/quest/pull/190):

- `cloudflare/test/publish.test.ts` keeps its own stateful GitHub fake, while
`dev/github.ts` models only what the inbox flows need. Merge the two into
`dev/github.ts` and delete the test-local copy.
- The epic's end-to-end test starts from the seeded fake before the live
rehearsal, so this ranks before the onboarding guide.
5 changes: 5 additions & 0 deletions quest/m0/kix/operator-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ and a bounded test PR verify the integration before contributors are invited.
background reconcile from
[kixelated/quest#170](https://github.com/kixelated/quest/pull/170) only
tests against the fake.
- Check what GitHub does to an open pull request when "Start over" resets
its service-fork head branch to the base, which
[kixelated/quest#190](https://github.com/kixelated/quest/pull/190) handles
either way (adopt it if open, open a new one if closed) but tests only
against the fake. Added 2026-10-22 (user).
- Rehearse on the operator's own runner and an explicitly selected
operator account.
- Record nonsecret setup/run instructions and deployment identifiers.
Expand Down
34 changes: 34 additions & 0 deletions quest/m0/kix/runner-hardening.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# [S] Fix the runner's post-merge review findings

## Goal

Two `quest runner` processes never work in the same runner home at once, and
the `context` tool returns every unresolved review thread of a pull request,
however many threads it has.

## Plan

Decided 2026-10-22 (user) from Codex's post-merge review of
[kixelated/quest#188](https://github.com/kixelated/quest/pull/188)
([review](https://github.com/kixelated/quest/pull/188#pullrequestreview-5618747276)),
which covered rework that merged without a review:

- **One runner per home (user).** `quest runner run` takes an exclusive lock
on its runner home and refuses to start while another process holds it.
The per-repository lock in `src/runner/workspace.ts` serializes only within
one process, so a second runner on the same home could reuse and modify a
job worktree while the first one's agents are still stopping after the hub
reassigns their jobs
([P1](https://github.com/kixelated/quest/pull/188#discussion_r4351848499)).
Rejected: inter-process locks per repository and worktree, which allow
several runners per home at more complexity. The lock must release when its
holder dies, on Linux and macOS.
- **Page review threads.** The context query in
`cloudflare/src/github/service.ts` reads only the first 100 review threads
before filtering unresolved ones, so a newer unresolved thread on a busy PR
is silently omitted
([P2](https://github.com/kixelated/quest/pull/188#discussion_r4351848505)).
Follow `pageInfo` cursors until every thread is examined.
- Ranked first in the epic, since both fix merged code. Test a second runner
refused on a held home, a lock released after a crash, and a pull request
with more than 100 review threads.
21 changes: 0 additions & 21 deletions quest/m0/lifecycle-ebusy.md

This file was deleted.

30 changes: 30 additions & 0 deletions quest/m0/lifecycle-flakes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# [S] Stop the lifecycle CI jobs failing at random

## Goal

The lifecycle CI jobs fail only when the code under test is broken: the
Windows check never fails with `EBUSY` while removing its temporary
directory, and a macOS job that never gets a runner does not show as a
failed check.

## Plan

Decided 2026-10-22 (user) as follow-ups of
[kixelated/quest#192](https://github.com/kixelated/quest/pull/192) and
[kixelated/quest#191](https://github.com/kixelated/quest/pull/191):

- **Windows `EBUSY`.** The Windows arm64 Release job failed after its own
checks passed, in the final `rmSync(work, { recursive: true, force: true })`
of `scripts/lifecycle-check.mjs`, on #192 and on the `quest/m0/worktree`
branch (run 39679528766). A rerun passed both times. Find which process or
handle still holds the directory (for example a child process the check
started, or a file it left open) and fix that cause. No retries, sleeps, or
ignored errors. Reproduce it on a native Windows runner before fixing.
- **macOS queue timeout.** On #191 and
[kixelated/quest#185](https://github.com/kixelated/quest/pull/185), the
optional `lifecycle (macos-14)` job waited 15 minutes for a hosted runner
during a GitHub macOS capacity notice, was cancelled without running, and
showed as failed. Decide from the workflow (`.github/workflows/check.yml`)
whether to shorten its queue limit, report it as skipped, or drop it from
pull request runs, keeping macOS covered somewhere.
- Keep both fixes covered by the existing lifecycle jobs.
22 changes: 22 additions & 0 deletions quest/m0/worker-tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# [S] Make every Worker test pass on its own

## Goal

Each Worker test (`cloudflare/test/`) passes when run alone, in any order, or
in the full suite, because no test depends on D1 state another test left
behind.

## Plan

Decided 2026-10-22 (user) as a follow-up of
[kixelated/quest#188](https://github.com/kixelated/quest/pull/188):

- A test in `cloudflare/test/publish.test.ts` passed in the full suite but
failed alone with a foreign-key error until it inserted its second user
itself, so D1 state leaks between tests in a full run.
- Find how state is shared (per-file or per-suite storage, seeded rows,
module-level fixtures) and make each test set up what it needs, rather than
fixing tests one at a time as they surface.
- Prove it by running each Worker test case alone (not just each file, since
tests in one file share state too) and the suite in a shuffled order, and
keep a check in CI that would catch a new order dependence.
1 change: 1 addition & 0 deletions quest/m1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ additional login providers. This milestone does not gate the first release.
- [ChatGPT hosted runs](/quest/m1/chatgpt-hosted.md) - conditional on provider approval and current terms
- [ChatGPT approval](/quest/m1/chatgpt-waitlist.md) - resolve hosted-use approval before implementation
- [Batched inbox reads](/quest/m1/inbox-reads.md) - a fixed number of D1 queries per project on each inbox load
- [Incremental history](/quest/m1/history-pass.md) - each history pass reads only what changed since the last
22 changes: 22 additions & 0 deletions quest/m1/history-pass.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# [S] Read only what changed in each history pass

## Goal

A history pass over a project reads only the issues and pull requests that
changed since the last pass, and fetches pull request bodies only where the
board needs them, instead of paging every entity each time.

## Plan

Decided 2026-10-22 (user) as a follow-up of
[kixelated/quest#182](https://github.com/kixelated/quest/pull/182):

- Each history page now fetches up to 50 pull request bodies, and a full pass
still pages every entity: about 126 pages on moq-dev/moq.
- Page by update time from the last pass's high-water mark, and read bodies
only for open drafts, whose `## Decisions needed` section decides whether
the board shows them as claimed or handed back.
- m1, next to [batched inbox reads](/quest/m1/inbox-reads.md): m0 pilots are
small enough that full passes are affordable.
- Dropped (user): caching installation tokens across an inbox load, until
pilots show slow inboxes.
Loading