Repository navigation
feat!: epics list no children - #518
Conversation
Quest-Claim: 548a99dcabdca6a5
An epic's children are the quests in its directory, in path order, and an epic README's `Required` lists only what blocks it. Finishing a quest deletes its file and edits no README, so sibling PRs stop conflicting on milestone and epic READMEs. `quest check` flags an epic's `Required` link to a quest it holds and a quest in a directory without a README; `quest check --fix`, `quest rm`, and the land daemon's base merges strip those links, which migrates a tree whose epics still list their children. Path order replaces list order: a directory's README first, then names, with numbers by value so `m10` follows `m9`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…child-lists # Conflicts: # quest/m0/token-waste/README.md
A README's `Required` link to a mistyped path inside its own directory is a mistake for `quest check` to report, not a child link for `--fix` to drop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…child-lists # Conflicts: # quest/m0/queue-watcher/README.md
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed head: 75d43e0
Findings: No actionable defects found. Reviewed the 61-file diff and relevant consumers: directory membership, implicit cycle edges, blocker expansion, milestone completion, ranking, migration/removal behavior, CLI start checks, Worker board/map rendering, and the updated tests. The new model consistently keeps child membership separate from explicit prerequisites.
Direction: Keep the directory-based approach. Carry the documented quest check --fix migration in adopting repositories' pin bumps, and complete the required landing checks.
Verification limits: GitHub-only static review; no tests, builds, or UI sessions executed. The PR reports full suites on 73af3ae and just check on this head after Markdown-only base merges. The available Check and Queue runs are skipped, and Release is still running; this review does not establish a passing merge-group run.
(Written by unknown OpenAI model)
|
No actionable comments were generated in the recent review. WalkthroughEpic children now come from directory contents rather than Merge Risk:
|
…child-lists # Conflicts: # quest/m0/README.md # quest/m1/README.md
|
quest land watch: the merge queue removed this pull request at 0f832ae because it conflicts with The land fixer works on it in the background, and the watcher re-enqueues it at the back of the queue once it is fixed or judged flaky, or hands it back here with what it needs. (written by quest land watch) |
|
quest land watch: armed auto-merge on this pull request at 80253f4, so it joins the back of the merge queue once its required checks pass, with the land fixer's fix ( (written by quest land watch) |
|
quest land watch: the merge queue removed this pull request at 80253f4 because it conflicts with The land fixer works on it in the background, and the watcher re-enqueues it at the back of the queue once it is fixed or judged flaky, or hands it back here with what it needs. (written by quest land watch) |
|
quest land watch: armed auto-merge on this pull request at fa2879b, so it joins the back of the merge queue once its required checks pass, with the land fixer's fix ( (written by quest land watch) |
|
quest land watch: the merge queue removed this pull request at fa2879b because it conflicts with The land fixer works on it in the background, and the watcher re-enqueues it at the back of the queue once it is fixed or judged flaky, or hands it back here with what it needs. (written by quest land watch) |
|
codex, gpt-6.1-sol, medium effort land fixer note:
(written by codex, gpt-6.1-sol, medium effort) |
|
quest land watch: armed auto-merge on this pull request at caa32fc, so it joins the back of the merge queue once its required checks pass, with the land fixer's fix ( (written by quest land watch) |
|
quest land watch: the merge queue removed this pull request at caa32fc because its The land fixer works on it in the background, and the watcher re-enqueues it at the back of the queue once it is fixed or judged flaky, or hands it back here with what it needs.
…t listed in quest/m2/automation/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m2/automation/checks.md: not listed in quest/m2/automation/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m2/automation/review.md: not listed in quest/m2/automation/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m2/chatgpt-hosted.md: not listed in quest/m2/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m2/chatgpt-waitlist.md: not listed in quest/m2/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m2/cloud/README.md: not listed in quest/m2/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m2/cloud/README.md: quest title must be '# [XS|S|M|L|XL] Title'
quest: quest/m2/cloud/billing.md: not listed in quest/m2/cloud/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m2/cloud/donors.md: not listed in quest/m2/cloud/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m2/cloud/funding.md: not listed in quest/m2/cloud/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m2/cloud/runners.md: not listed in quest/m2/cloud/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m2/council.md: not listed in quest/m2/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m2/donor-isolation.md: not listed in quest/m2/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m2/donor-runner.md: not listed in quest/m2/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m2/hook-path-error.md: not listed in quest/m2/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m2/legacy-labels.md: not listed in quest/m2/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m2/mobile-app.md: not listed in quest/m2/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m2/review-harnesses.md: not listed in quest/m2/README.md's '## Required'; an unlisted quest is unreachable
##[error]Process completed with exit code 1.
Post job cleanup.
[command]/nix/store/lg46w7hrjx7kylsh6645c9l975i8h43b-git-2.55.0/bin/git version
git version 2.55.0
Temporarily overriding HOME='/var/cache/github-runner-work/_temp/e3728256-4859-4c5f-829e-9e301f13e060' before making global git config changes
Adding repository directory to the temporary git global config as a safe directory
[command]/nix/store/lg46w7hrjx7kylsh6645c9l975i8h43b-git-2.55.0/bin/git config --global --add safe.directory /var/cache/github-runner-work/quest/quest
Removing SSH command configuration
[command]/nix/store/lg46w7hrjx7kylsh6645c9l975i8h43b-git-2.55.0/bin/git config --local --name-only --get-regexp core\.sshCommand
[command]/nix/store/lg46w7hrjx7kylsh6645c9l975i8h43b-git-2.55.0/bin/git submodule foreach --recursive sh -c "git config --local --name-only --get-regexp 'core\.sshCommand' && git config --local --unset-all 'core.sshCommand' || :"
Removing HTTP extra header
[command]/nix/store/lg46w7hrjx7kylsh6645c9l975i8h43b-git-2.55.0/bin/git config --local --name-only --get-regexp http\.https\:\/\/github\.com\/\.extraheader
[command]/nix/store/lg46w7hrjx7kylsh6645c9l975i8h43b-git-2.55.0/bin/git submodule foreach --recursive sh -c "git config --local --name-only --get-regexp 'http\.https\:\/\/github\.com\/\.extraheader' && git config --local --unset-all 'http.https://github.com/.extraheader' || :"
Removing includeIf entries pointing to credentials config files
[command]/nix/store/lg46w7hrjx7kylsh6645c9l975i8h43b-git-2.55.0/bin/git config --local --name-only --get-regexp ^includeIf\.gitdir:
[command]/nix/store/lg46w7hrjx7kylsh6645c9l975i8h43b-git-2.55.0/bin/git submodule foreach --recursive git config --local --show-origin --name-only --get-regexp remote.origin.url
Post job cleanup.
[command]/nix/store/lg46w7hrjx7kylsh6645c9l975i8h43b-git-2.55.0/bin/git version
git version 2.55.0
Temporarily overriding HOME='/var/cache/github-runner-work/_temp/a92b245d-b2cc-426c-93f3-d8d829dce2ba' before making global git config changes
Adding repository directory to the temporary git global config as a safe directory
[command]/nix/store/lg46w7hrjx7kylsh6645c9l975i8h43b-git-2.55.0/bin/git config --global --add safe.directory /var/cache/github-runner-work/quest/quest
Removing SSH command configuration
[command]/nix/store/lg46w7hrjx7kylsh6645c9l975i8h43b-git-2.55.0/bin/git config --local --name-only --get-regexp core\.sshCommand
[command]/nix/store/lg46w7hrjx7kylsh6645c9l975i8h43b-git-2.55.0/bin/git submodule foreach --recursive sh -c "git config --local --name-only --get-regexp 'core\.sshCommand' && git config --local --unset-all 'core.sshCommand' || :"
Removing HTTP extra header
[command]/nix/store/lg46w7hrjx7kylsh6645c9l975i8h43b-git-2.55.0/bin/git config --local --name-only --get-regexp http\.https\:\/\/github\.com\/\.extraheader
[command]/nix/store/lg46w7hrjx7kylsh6645c9l975i8h43b-git-2.55.0/bin/git submodule foreach --recursive sh -c "git config --local --name-only --get-regexp 'http\.https\:\/\/github\.com\/\.extraheader' && git config --local --unset-all 'http.https://github.com/.extraheader' || :"
Removing includeIf entries pointing to credentials config files
[command]/nix/store/lg46w7hrjx7kylsh6645c9l975i8h43b-git-2.55.0/bin/git config --local --name-only --get-regexp ^includeIf\.gitdir:
[command]/nix/store/lg46w7hrjx7kylsh6645c9l975i8h43b-git-2.55.0/bin/git submodule foreach --recursive git config --local --show-origin --name-only --get-regexp remote.origin.url
A job completed hook has been configured by the self-hosted runner administrator
##[group]Run '/nix/store/gx2v6q84b0w43bafm0whkdx93qyxbpps-ci-cache-gc.sh/bin/ci-cache-gc.sh'
shell: /nix/store/1mv3qz005gkbalxfghk4y3s8ayv4d2dl-bash-interactive-5.3p15/bin/bash --noprofile --norc -e -o pipefail {0}
##[endgroup]
evicted 0 objects and 0 action results (0 B logical); 35.5 GiB logical remain
Cleaning up orphan processes
Current runner version: '2.338.2'
##[group]Runner Image Provisioner
Hosted Compute Agent
Version: 20261028.624
Commit: 54898b74c23fde5556c9b3c3a2290865feef0dfe
Build Date: 2026-10-28T21:51:42Z
Worker ID: {be45e5c4-3f51-4a22-9aff-29c4fafe000c}
Region: centralus
Cloud: Azure
##[endgroup]
##[group]Operating System
Ubuntu
24.04.5
LTS
##[endgroup]
##[group]Runner Image
Image: ubuntu-24.04
Version: 20261101.360.1
Included Software: https://github.com/actions/runner-images/blob/ubuntu24/20261101.360/images/ubuntu/Ubuntu2404-Readme.md
Image Release: https://github.com/actions/runner-images/releases/tag/ubuntu24%2F20261101.360
##[endgroup]
##[group]GITHUB_TOKEN Permissions
Contents: read
Metadata: read
PullRequests: read
##[endgroup]
Secret source: Actions
Cache mode: write
Prepare workflow directory
Prepare all required actions
Complete job name: Queue
##[group]Run [[ "$RESULT" == success ]] || { echo "::error::the queue build ended $RESULT" >&2; exit 1; }
�[36;1m[[ "$RESULT" == success ]] || { echo "::error::the queue build ended $RESULT" >&2; exit 1; }�[0m
shell: /usr/bin/bash -e {0}
env:
RESULT: failure
##[endgroup]
##[error]the queue build ended failure
##[error]Process completed with exit code 1.
Cleaning up orphan processes
(written by quest land watch) |
|
codex, gpt-6.1-sol, medium effort land fixer note:
(written by codex, gpt-6.1-sol, medium effort) |
|
codex, gpt-6.1-sol, medium effort land fixer: ##[group]Run # Build concurrency and group size are both one in main's ruleset.
�[36;1m# Build concurrency and group size are both one in main's ruleset.�[0m
�[36;1m[[ "$QUEUE_REF" =~ ^refs/heads/gh-readonly-queue/main/pr-([0-9]+)- ]] || { echo "::error::unexpected merge group ref" >&2; exit 1; }�[0m
�[36;1mhead_ref=$(gh api "repos/$REPO/pulls/${BASH_REMATCH[1]}" --jq .head.ref)�[0m
�[36;1m./quest-base/bin/quest --root "$GITHUB_WORKSPACE" check --base "$BASE" --branch "$head_ref"�[0m
shell: /nix/store/1mv3qz005gkbalxfghk4y3s8ayv4d2dl-bash-interactive-5.3p15/bin/bash -e {0}
env:
BASE: 1c3cf6a719c8ac8e98181475e27e25d25a5ebbc2
GH_TOKEN: ***
REPO: moq-dev/quest
QUEUE_REF: refs/heads/gh-readonly-queue/main/pr-518-1c3cf6a719c8ac8e98181475e27e25d25a5ebbc2
##[endgroup]
quest: quest/m0/README.md: not listed in quest/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m0/claude-rm-upstream.md: not listed in quest/m0/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m0/codex-cloud-off.md: not listed in quest/m0/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m0/codex-project-config.md: not listed in quest/m0/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m0/context-rules.md: not listed in quest/m0/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m0/flaky/README.md: not listed in quest/m0/README.md's '## Required'; an unlisted quest is unreachable
quest: quest/m0/flaky/README.md: quest title must be '# [XS|S|M|L|XL] Title'
(written by codex, gpt-6.1-sol, medium effort) |
The merge queue checks a PR with the CLI built from its base, which rejects a tree whose epics no longer list their children. Stage the change: this PR ships directory membership with a validator that accepts an epic's Required link to a quest it holds, counting it once as a child, and keeps this tree's child lists. Removing held links and enforcing their absence move to the follow-up that migrates the tree. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Design change: staged in 2 PRs (user decision, 2026-11-07; rejected: admin-bypass merge once, skip, delete). The merge queue checks this PR with the CLI built from base, and base's CLI rejected the migrated tree. This PR now ships directory membership with a validator that accepts both tree formats. An epic's The follow-up, Verified: (Written by Claude Opus 5.5 with high effort) |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A link to a deeper quest stays a blocker, as on a tree that listed children, so an invalid subtree cannot hide it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed head 9c48c20 against base d29a0d2, comparing branch-specific changes with previously reviewed head 75d43e0.
No new actionable findings in the staged-rollout changes. Existing direct-child links now count once as membership in requires(), blocker expansion and impact ranking. Deeper or missing targets remain explicit blockers, and ranking validates structural membership before using the graph. The updated tests cover listed/unlisted equivalence, the deeper-target case, and preservation of remaining child links when removing one quest.
The repository retains its child lists, while automatic stripping and strict rejection move to the follow-up quest. This addresses the base-built validator rollout constraint without migrating unrelated trees as a side effect of check --fix or removal.
Direction: proceed through the normal base-validator and merge-group checks. This updates my earlier migration recommendation: pin bumps to this compatibility stage need no child-list migration; migration belongs with the later strict-format change documented in the follow-up.
Verification limits: GitHub-only static diff and source/test inspection. I did not execute tests, build either CLI, or independently reproduce the reported base-validator run.
(Written by review (OpenAI))
Restore the stripping #518 staged out: remove() drops every epic's Required link to a quest it holds, so quest check --fix, quest rm, and the land daemon's base-merge prune migrate an old tree, and --fix runs with no history. quest check now errors on "requires X, which this epic holds". Migrate this tree with quest check --fix, and the land fixer no longer adds the flaky quest's link to quest/m0/flaky/README.md. BREAKING CHANGE: repositories migrate with quest check --fix on their pin bump past this commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Ships directory membership for quest/m0/token-waste/child-lists.md and rewrites that quest to the remaining step: migrating this tree and enforcing the format.
Problem
Every epic and milestone README listed its children in
## Required, so every PR that finished a quest edited its parent's README. Siblings conflicted there:quest/m1/README.mdwas touched by 33% of merged moq-dev/moq PRs, and GitHub's merge queue, which cannot run the quest merge driver, ejected 723 PRs for conflicts in 30 days.The first version of this PR also migrated the tree, and the merge queue dropped it. The queue runs
quest checkwith the CLI built from base, so a PR cannot loosen its own validator, and base's CLI rejects a README that does not list its children.Decisions
quest check --base ... --branch ...passes on the merge. The follow-up runsquest check --fixto migrate the tree and turnsrequires X, which this epic holdsinto an error.Behavior
Requiredlink to one of its children, as every README in a tree from before this change has, is allowed and counts once:quest unblockedneither scores it as a dependent nor prints it twice, and cycles and the Worker's map count it once. A link to a deeper quest stays a blocker, as on base.m10followsm9.quest unblockedandquest waitingstill rank by milestone, then downstream impact; path order is only the tiebreak, as list order was.quest checkaddssits in D, which has no README.mdfor a quest nothing reaches. It replacesnot listed in ...'s '## Required'.## Required.quest rm,quest check --fix, and the land daemon's base-merge prune still drop only links to deleted quests, so a finished quest's entry leaves its parent's list and its siblings stay.Public API
Quest format: additive. A tree that lists children and one that does not both pass
quest check, so other repositories (moq-dev/moq, moq.pro, rind, rust2) pass on a pin bump past this change without migrating. The follow-up makes child lists an error and is the breaking step.Breaking, core exports:
children(docs, doc)andisEpic(docs, doc)now take the document set. To migrate, pass the loaded documents.requires(docs, doc)is new.comparePathsnow orders README first and compares numbers by value.No CLI flags changed. The
unblocked,waiting,mv, andrmhelp text is updated.Changes
src/core: the directory model (doc.ts), its rules (rules.ts:membershipreplacesindex; milestone and cycle rules count directory children), readiness and tree order (ready.ts), and ranking (unblocked.ts), each counting an epic's link to its own child once.src/cli/main.ts: help text.assets/AGENTS.md), covering Model and Format: epics, milestones, andRequired./quest-plan(placement replaces rank),/quest-audit(no rank to change),/quest-spawn(path order), and/quest-recurring(no parent listing).quest/m0/token-waste/child-lists.mdis rewritten to the follow-up's work.Choices made without asking
remove()no longer strips held links in this PR.quest check --fixruns after every base merge, andquest rmand the land daemon's prune shareremove(). If it stripped them, the first unrelated PR to run any of these would migrate all 15 READMEs as a side effect. The follow-up restores it from caa32fc and migrates on purpose. So--fixalso needs history again, as on base.assets/land-fix.mdand the flaky quest keep base's wording: the fixer adds the flaky quest's link toquest/m0/flaky/README.md. That is valid under both validators, which matters while other repositories pin an olderquest. The follow-up drops it.m10followsm9.comparePathsitself changed, soquest check's finding order, the board, and tree order all agree.quest unblocked <epic>lists the epic's otherRequiredentries first, then its children. Each child that is an epic expands as before.Validation
just checkandjust testpass on 9c48c20 (root 1104 tests and 6 skipped, Worker 539, and both lifecycle checks), run throughquest gate.questfrom origin/main at 1c3cf6a withnix build .#quest, as.github/workflows/queue-build.ymldoes, and ranquest --root . check --base origin/main --branch quest/m0/token-waste/child-listson c5065a2 and again on 9c48c20 after merging origin/main at d29a0d2, which changed nosrc. Result:quest: 82 documents ok.quest checkpasses on this tree (82 documents, child lists kept) and onexamples/export(4 documents, no child lists).quest rmon a listed tree drops only the finished quest's entry; the root's listing of a finished milestone is kept.Models
Size: L
Implementer: Claude Code, claude-opus-5-5, xhigh effort
Implementer: Claude Code, claude-opus-5-5, high effort
Review
Rewritten by
quest reviewafter each round.01a1b760-8d4f-74f1-bc7e-72b42621e1fc, round 3No remaining findings: targeted checks and repository/example validation passed, while full suites were blocked by the read-only sandbox.src/core/ready.ts:100:[P2] Verify structural reachability before suppressing descendants;src/core/ready.ts:100 now suppresses only actual children, preserving the reproduced dependency behind a missing README, and ranking() rejects malformed trees without explicit links.Caused by
No single PR. Epics have listed their children since the format began.
Follow-ups
remove()from caa32fc, runsquest check --fixon this tree, makesrequires X, which this epic holdsan error, and drops the flaky epic link fromassets/land-fix.md. It is the breaking change, and it lands once this PR's validator is base, so the queue accepts the migrated tree.quest check --fixin the same PR, and both moq-dev pins, updated here to name the follow-up, and Repositories and hosts follow quest's main already require that.(Written by Claude Opus 5.5 with high effort)
🤖 Generated with Claude Code