feat(queue): add thurbox to the auto-merge set - #64
Merged
Conversation
`AUTO_MERGE_REPOS` now names `github.com/Thurbeen/thurbox` alongside fleet and thurview, host-qualified like its neighbours. It joins on the stated test rather than on the fleet having work there: thurbox carries its own `.no-mistakes.yaml` — `just lint` plus a rustdoc build with warnings denied — and four CI workflows, so the attestation gate has a pipeline behind it and the checks gate has checks behind it. The comment above the set records that, in the same terms the thurview paragraph uses. No gate is loosened. `queue-selftest.sh`'s new section 9i drives the shepherd over two thurbox pull requests through the existing fake GitHub: the attested, green one is squash-merged unattended, the one nothing vetted is still handed back, and a bare `Thurbeen/thurbox` in `FLEET_AUTO_MERGE_REPOS` is refused rather than matched against the slug — the host-qualification rule this addition could quietly weaken. Claude-Session: https://claude.ai/code/session_01EuJuuMUd9NjJKCDHecNQ3Y
LeTuR
added a commit
that referenced
this pull request
Sep 11, 2026
## Intent Let fleet's shepherd merge pull requests in github.com/LeTuR/mazet, now that the remote takes squash. Add exactly one entry — github.com/LeTuR/mazet, host-qualified — to AUTO_MERGE_REPOS in scripts/lib/queue.py, and make every place that states the set agree with the code: .agents/skills/fleet-queue/SKILL.md names all three repositories in prose and must now name four. AGENTS.md and FLEET.md were checked and refer to the set generically with a format example rather than enumerating it, so they deliberately stay untouched. The remote was the blocker and is not any more: mazet allowed rebase merging only until 2026-09-11, and MERGE_METHOD is squash, so every shepherd pass would have produced a recorded refusal rather than a merge. It now reports allow_squash_merge true with rebase and merge-commit both false, delete_branch_on_merge true, and PR_TITLE/PR_BODY as the squash commit title and message — the same shape as fleet's own remotes. Its .no-mistakes.yaml and three CI workflows were verified against the live repository, which is what the code comment's stated test for adding an entry asks for. Deliberate constraints from the task, so a reviewer does not read them as omissions: - Nothing else in the merge gate may move. MERGE_METHOD, the no-mistakes attestation gate for the current head, the head-branch check, the pusher check and the checks-passed condition are all untouched; this widens the allowlist by one entry and nothing else. - Entries stay host-qualified. A bare LeTuR/mazet must keep being refused rather than matched against a slug. - FLEET_AUTO_MERGE_REPOS keeps REPLACING the set rather than adding to it. - scripts/queue.sh stays the only writer over the queue's records. Testing was written first and observed to fail for the right reason before the allowlist changed (the shepherd printed 'fleet does not merge in LeTuR/mazet on github.com; this one is yours'). The new queue-selftest.sh section 9j extends what 9i already asserts rather than adding a parallel check: an attested, green mazet pull request is merged by squash through the stubbed forge, an unvetted one is still handed back, a bare LeTuR/mazet in FLEET_AUTO_MERGE_REPOS is refused, and the default set is read back through auto_merge_repos() and every entry put through forge.RepoId.parse. That last assertion exists because the literal in queue.py is never parsed at runtime — only the environment override is — so a bare slug written into the set would match nothing, refuse nothing, and otherwise fail no test. ./scripts/check.sh was run to completion locally and exited 0, including the queue and skills checks. Repository convention note: CONTRIBUTING.md says pull request titles are conventional and scopeless, but the whole recent history is scoped and the direct precedent for this change is 'feat(queue): add thurbox to the auto-merge set (#64)'. The scoped form was chosen to match the history. A previous run of this same change (01M28VSQMRZCP0PFYGKMW6XBS9) passed intent, rebase, review and test, then failed at the document step because the pipeline agent exited 1 on a usage limit. Nothing was pushed and its rebased head is no longer reachable as an object, so this is a resubmission of the identical commit, not new work. ## What Changed - `AUTO_MERGE_REPOS` in `scripts/lib/queue.py` gains one host-qualified entry, `github.com/LeTuR/mazet`, so `queue.sh shepherd` merges there instead of recording a refusal; the comment above the set records why the remote was the blocker (it allowed rebase only, against a squash `MERGE_METHOD`) and no other gate moved. - `queue-selftest.sh` grows section 9j: against the stubbed forge, an attested green mazet pull request is merged with `--squash --delete-branch`, an unattested one is handed back unmerged, a bare `LeTuR/mazet` in `FLEET_AUTO_MERGE_REPOS` is refused rather than matched, and the whole set is read back through `auto_merge_repos()` with every entry put through `forge.RepoId.parse` — the literal in `queue.py` is never parsed at runtime, so an unqualified slug there would otherwise fail no test. - Section 14 no longer asserts the merge set by enumerating its members; it now checks only that discovering a GitLab instance added nothing to it, and the fleet-queue skill's prose naming the set lists four repositories instead of three. ## Risk Assessment ✅ Low: The behavioral change is a single host-qualified entry added to an existing allowlist with every merge gate untouched, backed by a new selftest section that mirrors the precedent set by the previous addition; the only issues found are minor weaknesses in test assertion strength. ## Testing The configured `./scripts/check.sh` baseline had already passed; on top of it I re-ran the queue check and the queue selftest directly (both exit 0, with the nine new section 9j assertions and the five reworked section 14 assertions green), then drove `./scripts/queue.sh shepherd` end-to-end three times against throwaway queues with a stand-in forge CLI to capture reviewer-readable transcripts: the before-state where mazet is handed back, the after-state where an attested green mazet pull request is squash-merged with the branch deleted and `publish.state = merged` persisted onto the task, and an adversarial pass showing the stale-attestation, no-push-access, failed-checks and fork gates all still refusing on the newly allowlisted repo. The bare-slug override is refused and merges nothing, and the environment override still replaces the shipped set. The change has no UI surface, so the evidence is CLI transcripts and persisted queue state rather than screenshots. Two things were not driven live: a merge against the live repository, which would irreversibly merge a real pull request (its premise — squash-only merging, delete-on-merge, PR_TITLE/PR_BODY, a `.no-mistakes.yaml` and three active workflows — was instead confirmed read-only against the real remote); and the agreement between the documentation that enumerates the set and the code, which was read rather than exercised and therefore carries no live result. - Live validation: ✅ go - 9 of 11 scenarios driven live against the product | Scenario | Result | Live | Evidence | | --- | --- | --- | --- | | An attested, green pull request on github.com/LeTuR/mazet is squash-merged unattended by the shepherd, with the branch deleted | ✅ pass | live | `./scripts/queue.sh shepherd --topic mazet-live` against a throwaway queue; the row reads `merged: squash-merged, branch deleted`, the shepherd issued `gh pr merge https://github.com/LeTuR/mazet/pull/… | | Before the entry existed the same pull request was handed back, not merged (the regression this change fixes) | ✅ pass | live | Same queue, same pull request, run with `FLEET_AUTO_MERGE_REPOS='github.com/Thurbeen/fleet github.com/Thurbeen/thurbox github.com/Thurbeen/thurview'`: the row reads `ready: fleet does not merge in LeT… | | An unattested mazet pull request is still handed back and given a fixer rather than merged | ✅ pass | live | PR 302 in the same pass: `policy: the body carries no no-mistakes attestation` then `dispatched: Re-open PR #302 through the pipeline`, recorded as `publish.state = unattested`; the merge log names on… | | Adversarial: a bare LeTuR/mazet naming no forge is refused rather than matched against the slug | ✅ pass | live | `FLEET_AUTO_MERGE_REPOS='LeTuR/mazet' ./scripts/queue.sh shepherd --dry-run` prints `ignoring 'LeTuR/mazet' — an auto-merge entry must name its forge`, the mazet pull request stays `ready: fleet does… | | FLEET_AUTO_MERGE_REPOS still replaces the shipped set rather than adding to it | ✅ pass | live | With the override naming the three older repos, the pass's own `Merging is limited to` line names exactly those three and mazet is excluded despite being in the shipped literal; with no override the l… | | Adversarial: every other merge gate still refuses on the newly allowlisted repo | ✅ pass | live | `./scripts/queue.sh shepherd --topic mazet-gates` over five mazet pull requests: an attestation for an earlier head is `policy` and gets a fixer, an author with no push access is `not-merged`, failing… | | The shepherd tells the operator the set is four repositories, every entry host-qualified | ✅ pass | live | The pass's closing line reads `Merging is limited to github.com/LeTuR/mazet, github.com/Thurbeen/fleet, github.com/Thurbeen/thurbox, github.com/Thurbeen/thurview`; queue-selftest section 9j reads the… | | A discovered second forge adds nothing to the merge set, and the reworked section 14 assertion would catch it if it did | ✅ pass | live | queue-selftest section 14 (real GitLab adapter over recorded glab output) is green on all five assertions including `discovering the instance put nothing of it on that set`; driving the same line with… | | The remote is genuinely no longer the blocker: github.com/LeTuR/mazet allows squash and only squash | ✅ pass | live | Read-only against the live repository: `gh api repos/LeTuR/mazet` returns allow_squash_merge true, allow_rebase_merge false, allow_merge_commit false, delete_branch_on_merge true, PR_TITLE/PR_BODY; it… | | Every place that states the set agrees with the code after the change | ⏸️ untested | no | This was established by reading tracked files with `git grep`, not by driving the running product, so the prior payload records no live result for it. Documentation consistency has no runtime surface… | | A real squash merge performed on the live github.com/LeTuR/mazet repository | ⏸️ untested | no | Driving this needs a genuinely open, attested, green pull request on the public github.com/LeTuR/mazet and authority to merge it; the merge is irreversible and outward-facing, and a test phase should… | <details> <summary>Evidence: Shepherd transcript: mazet before and after the allowlist entry</summary> ```text ======================================================================== A. BEFORE-STATE: the allowlist as it was, three repos, mazet not on it $ FLEET_AUTO_MERGE_REPOS='github.com/Thurbeen/fleet github.com/Thurbeen/thurbox github.com/Thurbeen/thurview' \ ./scripts/queue.sh shepherd --topic mazet-live ======================================================================== shepherd: 3 open pull request(s) on LeTuR/mazet on github.com, someone-else/their-repo on github.com — what it did: mazet-live/01-attested https://github.com/LeTuR/mazet/pull/301 ready: the pipeline attests 00000000, which is this head; checks green, mergeable, and the branch is ours ready: fleet does not merge in LeTuR/mazet on github.com; this one is yours mazet-live/02-unvetted https://github.com/LeTuR/mazet/pull/302 policy: the body carries no no-mistakes attestation, so nothing but its own prose says the pipeline ever ran dispatched: Re-open PR #302 through the pipeline -> f1xe4000-0000-0000-0000-000000000001 mazet-live/03-elsewhere https://github.com/someone-else/their-repo/pull/401 foreign: its head branch is in LeTuR's repository, not someone-else/their-repo on github.com — fleet neither merges nor sends an agent at a pull request that is not ours left-alone: not ours; fleet only merges and only fixes its own shepherd: 1 dispatched, 1 left-alone, 1 ready Fixers are working in place on the existing branches; nothing forked. Merging is limited to github.com/Thurbeen/fleet, github.com/Thurbeen/thurbox, github.com/Thurbeen/thurview, and only for a pull request whose head branch is in that repo, that someone who can push there opened, that carries a no-mistakes attestation for its CURRENT head, whose checks passed, and that the forge itself calls mergeable. run log updated: /tmp/tmp.QBeX93I65r/runs/2026-09-11-mazet-live.md --- what the forge was asked to merge: (nothing) ======================================================================== B. ADVERSARIAL: a bare LeTuR/mazet in the override, no forge named $ FLEET_AUTO_MERGE_REPOS='LeTuR/mazet' ./scripts/queue.sh shepherd --topic mazet-live --dry-run ======================================================================== FLEET_AUTO_MERGE_REPOS: ignoring 'LeTuR/mazet' — an auto-merge entry must name its forge, as in github.com/owner/repo FLEET_AUTO_MERGE_REPOS: ignoring 'LeTuR/mazet' — an auto-merge entry must name its forge, as in github.com/owner/repo shepherd: 3 open pull request(s) on LeTuR/mazet on github.com, someone-else/their-repo on github.com — what it would do: mazet-live/01-attested https://github.com/LeTuR/mazet/pull/301 ready: the pipeline attests 00000000, which is this head; checks green, mergeable, and the branch is ours ready: fleet does not merge in LeTuR/mazet on github.com; this one is yours mazet-live/02-unvetted https://github.com/LeTuR/mazet/pull/302 policy: the body carries no no-mistakes attestation, so nothing but its own prose says the pipeline ever ran would-dispatch: Re-open PR #302 through the pipeline (a fresh session on the branch) mazet-live/03-elsewhere https://github.com/someone-else/their-repo/pull/401 foreign: its head branch is in LeTuR's repository, not someone-else/their-repo on github.com — fleet neither merges nor sends an agent at a pull request that is not ours left-alone: not ours; fleet only merges and only fixes its own shepherd: 1 left-alone, 1 ready, 1 would-dispatch Merging is limited to , and only for a pull request whose head branch is in that repo, that someone who can push there opened, that carries a no-mistakes attestation for its CURRENT head, whose checks passed, and that the forge itself calls mergeable. ======================================================================== C. THE CHANGE: the default allowlist $ ./scripts/queue.sh shepherd --topic mazet-live ======================================================================== shepherd: 3 open pull request(s) on LeTuR/mazet on github.com, someone-else/their-repo on github.com — what it did: mazet-live/01-attested https://github.com/LeTuR/mazet/pull/301 ready: the pipeline attests 00000000, which is this head; checks green, mergeable, and the branch is ours merged: squash-merged, branch deleted mazet-live/02-unvetted https://github.com/LeTuR/mazet/pull/302 policy: the body carries no no-mistakes attestation, so nothing but its own prose says the pipeline ever ran dispatched: Re-open PR #302 through the pipeline -> f1xe4000-0000-0000-0000-000000000001 mazet-live/03-elsewhere https://github.com/someone-else/their-repo/pull/401 foreign: its head branch is in LeTuR's repository, not someone-else/their-repo on github.com — fleet neither merges nor sends an agent at a pull request that is not ours left-alone: not ours; fleet only merges and only fixes its own shepherd: 1 dispatched, 1 left-alone, 1 merged Fixers are working in place on the existing branches; nothing forked. Merging is limited to github.com/LeTuR/mazet, github.com/Thurbeen/fleet, github.com/Thurbeen/thurbox, github.com/Thurbeen/thurview, and only for a pull request whose head branch is in that repo, that someone who can push there opened, that carries a no-mistakes attestation for its CURRENT head, whose checks passed, and that the forge itself calls mergeable. run log updated: /tmp/tmp.QBeX93I65r/runs/2026-09-11-mazet-live.md --- what the forge was asked to merge (pull request numbers): 301 --- the merge command the shepherd issued: gh pr merge https://github.com/LeTuR/mazet/pull/301 --squash --delete-branch --- what the queue wrote onto each task: 01-attested state=done outcome=shipped publish.at = 2026-09-11T21:34:09+00:00 publish.by = shepherd publish.detail = squash-merged, branch deleted publish.how = run `/no-mistakes --yes` publish.method = no-mistakes publish.state = merged 02-unvetted state=queued outcome=None publish.at = 2026-09-11T21:34:09+00:00 publish.by = shepherd publish.detail = the body carries no no-mistakes attestation, so nothing but its own prose says the pipeline ever ran publish.how = run `/no-mistakes --yes` publish.method = no-mistakes publish.state = unattested 03-elsewhere state=done outcome=shipped publish.at = 2026-09-11T21:34:10+00:00 publish.by = shepherd publish.detail = its head branch is in LeTuR's repository, not someone-else/their-repo on github.com — fleet neither merges nor sends an agent at a pull request that is not ours publish.how = run `/no-mistakes --yes` publish.method = no-mistakes publish.state = unknown ``` </details> <details> <summary>Evidence: Shepherd transcript: every merge gate exercised on the new repo</summary> ```text ======================================================================== Every merge gate, on github.com/LeTuR/mazet — the newly allowlisted repo $ ./scripts/queue.sh shepherd --topic mazet-gates ======================================================================== shepherd: 5 open pull request(s) on LeTuR/mazet on github.com — what it did: mazet-gates/01-stale-attestation https://github.com/LeTuR/mazet/pull/311 policy: the no-mistakes attestation is for 00000000, and the head is 00000000 — it attests a push that is no longer what would merge dispatched: Re-open PR #311 through the pipeline -> f1xe4000-0000-0000-0000-000000000001 mazet-gates/02-stranger https://github.com/LeTuR/mazet/pull/312 ready: the pipeline attests 00000000, which is this head; checks green, mergeable, and the branch is ours not-merged: stranger has no access to LeTuR/mazet on github.com — fleet merges unattended only what someone who can push here opened mazet-gates/03-checks-failed https://github.com/LeTuR/mazet/pull/313 checks-failed: failed checks: CI dispatched: Fix the failing checks on PR #313 -> f1xe4000-0000-0000-0000-000000000001 mazet-gates/04-fork https://github.com/LeTuR/mazet/pull/314 foreign: its head branch is in someone-else's fork, not LeTuR/mazet on github.com — fleet neither merges nor sends an agent at a pull request that is not ours left-alone: not ours; fleet only merges and only fixes its own mazet-gates/05-good https://github.com/LeTuR/mazet/pull/315 ready: the pipeline attests 00000000, which is this head; checks green, mergeable, and the branch is ours merged: squash-merged, branch deleted shepherd: 2 dispatched, 1 left-alone, 1 merged, 1 not-merged Fixers are working in place on the existing branches; nothing forked. Merging is limited to github.com/LeTuR/mazet, github.com/Thurbeen/fleet, github.com/Thurbeen/thurbox, github.com/Thurbeen/thurview, and only for a pull request whose head branch is in that repo, that someone who can push there opened, that carries a no-mistakes attestation for its CURRENT head, whose checks passed, and that the forge itself calls mergeable. run log updated: /tmp/tmp.N6cvVamM6I/runs/2026-09-11-mazet-gates.md --- pull requests the forge was actually asked to merge: 315 --- every merge command issued: gh pr merge https://github.com/LeTuR/mazet/pull/315 --squash --delete-branch ``` </details> <details> <summary>Evidence: Live read-only check of the github.com/LeTuR/mazet remote</summary> ```text # The premise of the change, read live off github.com/LeTuR/mazet (read-only) $ gh api repos/LeTuR/mazet --jq "{merge settings}" {"allow_merge_commit":false,"allow_rebase_merge":false,"allow_squash_merge":true,"delete_branch_on_merge":true,"squash_merge_commit_message":"PR_BODY","squash_merge_commit_title":"PR_TITLE"} # fleet only adds a repo whose own pipeline gates it — its .no-mistakes.yaml and CI $ gh api repos/LeTuR/mazet/contents/.no-mistakes.yaml --jq .content | base64 -d # The no-mistakes gate for mazet. # # `commands.*` are spelled out rather than left for the agent to detect. A gate # step has to be deterministic about what it executes: an empty key does not # mean "run something small", it means the agent decides what running the tests # looks like, and two runs of the same gate can then check different things. # # These keys are read from the DEFAULT BRANCH, so an edit here takes effect on # the change after the one that makes it. commands: # The whole lint surface CI enforces, in the order that fails cheapest first. # The rustdoc check is part of it: a broken intra-doc link is a CI failure # like any other, and catching it here is the round-trip this step exists to # prevent. lint: >- cargo fmt --all -- --check && cargo clippy --all-targets --all-features -- -D warnings && RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features # Run before the push step commits agent fixes, so formatting never reaches # lint dirty and costs an extra auto-fix round. format: cargo fmt --all # The suite, named explicitly. `--all-features` so it matches what clippy and # CI compile; the crate is small enough that the build is warm by the time # this runs. test: cargo test --all-features # Generated, not authored: reviewing it reviews the resolver, not a decision. ignore_patterns: - "Cargo.lock" # Review findings park for a human decision rather than being auto-applied, so # this repository does not inherit an operator's global override. auto_fix: review: 0 # ci.yml sets `cancel-in-progress: true`, so a cancelled check here almost # always means a newer push superseded it rather than provider flakiness. # Rerunning would restart work that was stopped on purpose. ci: rerun_transient: 0 $ gh api repos/LeTuR/mazet/actions/workflows --jq ".workflows[] | .name + \" (\" + .path + \", \" + .state + \")\"" Release (.github/workflows/cd.yml, active) CI (.github/workflows/ci.yml, active) PR Title (.github/workflows/pr-title.yml, active) ``` </details> <details> <summary>Evidence: Queue selftest: section 9j and section 14 assertions</summary> ```text $ ./scripts/queue-selftest.sh (exit 0 — final line: "queue-selftest: every claim holds") --- section 9j assertions (the new entry) --- 310: �[32mok�[0m and by the same squash fleet's own are merged by 333: �[32mok�[0m the shepherd reaches mazet at all 334: �[32mok�[0m an attested, green mazet pull request is merged unattended 335: �[32mok�[0m and by the same squash fleet's own are merged by 336: �[32mok�[0m the second addition loosens no gate either: an unattested one is not merged 337: �[32mok�[0m a bare LeTuR/mazet is refused, not matched against the slug 338: �[32mok�[0m and nothing in mazet would be merged under it 339: �[32mok�[0m the allowlist is the four repositories fleet may merge in 340: �[32mok�[0m and every entry in it names its forge, so none can match a bare slug --- section 14 assertions (a discovered second forge adds nothing to the set) --- 715: �[32mok�[0m shepherd lists what is open on the discovered instance 716: �[32mok�[0m and a mergeable, attested one there is handed back, not merged 717: �[32mok�[0m and the pass says what it limits merging to 718: �[32mok�[0m because discovering the instance put nothing of it on that set 719: �[32mok�[0m so nothing on a discovered host was merged �[32mqueue-selftest: every claim holds�[0m ``` </details> <details> <summary>Evidence: Section 14's narrowed assertion is sensitive, not vacuous</summary> ```text --- the set as shipped (what section 14 checks against) --- Merging is limited to github.com/LeTuR/mazet, github.com/Thurbeen/fleet, github.com/Thurbeen/thurbox, github.com/Thurbeen/thurview, and only for a pull request whose --- the same line with a gitlab.example.com repository put on the set --- Merging is limited to github.com/LeTuR/mazet, gitlab.example.com/acme/group/widgets, and only for a pull request whose ``` </details> <details> <summary>Evidence: Every tracked place that enumerates the auto-merge set</summary> ```text # Every tracked place that enumerates the auto-merge set $ git grep -n -l "Thurbeen/thurview" -- "*.md" "*.py" "*.sh" .agents/skills/fleet-queue/SKILL.md scripts/lib/queue.py scripts/queue-selftest.sh $ git grep -n "Thurbeen/thurview" -- "*.md" .agents/skills/fleet-queue/SKILL.md:827:`github.com/Thurbeen/thurview` — and only when **all** of these hold. Entries # does any of them still name three repositories without mazet? $ git grep -n "LeTuR/mazet" -- "*.md" "*.py" "*.sh" .agents/skills/fleet-queue/SKILL.md:825:`scripts/lib/queue.py` — `github.com/LeTuR/mazet`, scripts/lib/queue.py:4334:# `LeTuR/mazet` was added on the same instruction and is the first entry under scripts/lib/queue.py:4346: "github.com/LeTuR/mazet", scripts/queue-selftest.sh:2573:# here about `github.com/LeTuR/mazet`, because they are claims about an ENTRY scripts/queue-selftest.sh:2576:# HOST-QUALIFIED, so `LeTuR/mazet` is refused rather than matched against the scripts/queue-selftest.sh:2592:artifact: https://github.com/LeTuR/mazet/pull/301 scripts/queue-selftest.sh:2615: "url": f"https://github.com/LeTuR/mazet/pull/{n}", scripts/queue-selftest.sh:2634:expect "the shepherd reaches mazet at all" "LeTuR/mazet" "$out" scripts/queue-selftest.sh:2642: "pr merge https://github.com/LeTuR/mazet/pull/301 --squash --delete-branch" \ scripts/queue-selftest.sh:2653:out="$(env PATH="$shep/bin:$base_path" FLEET_AUTO_MERGE_REPOS="LeTuR/mazet" \ scripts/queue-selftest.sh:2655:expect "a bare LeTuR/mazet is refused, not matched against the slug" \ scripts/queue-selftest.sh:2673: "entries=github.com/LeTuR/mazet github.com/Thurbeen/fleet github.com/Thurbeen/thurbox github.com/Thurbeen/thurview" \ ``` </details> <details> <summary>Evidence: The merge the shepherd performs on mazet, and what it wrote down</summary> ```text mazet-live/01-attested https://github.com/LeTuR/mazet/pull/301 ready: the pipeline attests 00000000, which is this head; checks green, mergeable, and the branch is ours merged: squash-merged, branch deleted --- the merge command the shepherd issued: gh pr merge https://github.com/LeTuR/mazet/pull/301 --squash --delete-branch --- what the queue wrote onto the task: 01-attested state=done outcome=shipped publish.state = merged publish.by = shepherd publish.detail = squash-merged, branch deleted ``` </details> ## Pipeline Updates from [git push no-mistakes](https://github.com/kunchenguid/no-mistakes) <!-- no-mistakes-pipeline-attestation:v1 {"head_sha":"41128d38747cb85e4b4135c70501db282ba96222","steps":[{"step":"intent","status":"completed"},{"step":"rebase","status":"completed"},{"step":"review","status":"completed"},{"step":"test","status":"completed"},{"step":"document","status":"completed"},{"step":"lint","status":"completed"},{"step":"push","status":"completed"},{"step":"pr","status":"running"},{"step":"ci","status":"pending"}],"live_validation":{"verdict":"go","live":9,"total":11}} --> <details> <summary>✅ **intent** - passed</summary> ✅ No issues found. </details> <details> <summary>✅ **Rebase** - passed</summary> ✅ No issues found. </details> <details> <summary>⚠️ **Review** - 2 infos</summary> -⚠️ `scripts/queue-selftest.sh:5409` - §14 still asserts "because the merge set is exactly the three repos it always was" against the literal "github.com/Thurbeen/fleet, github.com/Thurbeen/thurbox, github.com/Thurbeen/thurview", and it was not updated with the allowlist. The intent requires "make every place that states the set agree with the code"; this is such a place and it no longer does. Concrete trace: scripts/lib/queue.py:5371 prints "Merging is limited to " + ", ".join(sorted(auto_merge_repos())); sorted() now yields github.com/LeTuR/mazet first ('L' < 'T'), so the printed line is "…limited to github.com/LeTuR/mazet, github.com/Thurbeen/fleet, github.com/Thurbeen/thurbox, github.com/Thurbeen/thurview, …" and expect()'s grep -qF still finds the stale three-repo substring. The test therefore passes while asserting a set that is wrong by one entry — a wrong label that never fails. It is also silently fragile: an entry sorting between fleet and thurbox would make this expect fail for a reason unrelated to what §14 is about. Smallest remedy: put github.com/LeTuR/mazet at the head of the expected string and say four in the label, or narrow the assertion to what §14 actually proves (that acme/group/widgets on the discovered GitLab host is absent from the printed set). Flagged ask-user rather than auto-fix because it is the intent's "every place that states the set" criterion that is unmet, so the author should confirm which of the two forms they want. - ℹ️ `scripts/queue-selftest.sh:2672` - The allowlist is now spelled out verbatim in four places: scripts/lib/queue.py:4345, .agents/skills/fleet-queue/SKILL.md:825, the new entries= expectation here, and the §14 expectation at line 5409. The readback assertion here is worth keeping — without an exact-membership check, "unqualified=none" would also pass on an empty set — but noting the cost, which is exactly what produced the §14 miss above: a fifth entry means editing four literals, and only one of them fails loudly when it is forgotten. - ℹ️ `scripts/queue-selftest.sh:2585` - §9j reassigns mtopic, which §9h (line 2456) already used for the many-prs pagination topic. Nothing after §9j reads the old value today, so there is no current failure, but any assertion later appended about the §9h topic would silently target the mazet topic instead — the neighbouring sections deliberately use distinct names (stopic, ttopic, gdtopic). Rename to something like ztopic/maztopic. 🔧 Fix applied. 2 infos still open: - ℹ️ `scripts/queue-selftest.sh:2672` - The set readback asserts exact membership with a substring match, so it does not actually pin the set for the most likely future addition. `expect` greps with `grep -qF` (scripts/queue-selftest.sh:172), and the needle is `entries=github.com/LeTuR/mazet github.com/Thurbeen/fleet github.com/Thurbeen/thurbox github.com/Thurbeen/thurview` with nothing after it. Concrete trace: add `github.com/acme/widgets` to AUTO_MERGE_REPOS. `sorted()` compares `github.com/` then 'a' (97) against 'T' (84), so the new entry lands LAST and the printed line becomes `entries=...thurview github.com/acme/widgets` — which still contains the needle verbatim, so the assertion passes while its own label says "the four repositories fleet may merge in". Any owner whose name sorts after `Thurbeen` (every lowercase one) slips through. The `unqualified=none` assertion beside it is unaffected and still catches a bare slug wherever it sorts, so this is a weakened label rather than a hole in the parse claim the intent asked for. Smallest remedy is mechanical: emit a terminator the needle includes, e.g. `print("entries=" + " ".join(repos) + " .")` and end the expected string with `thurview .`. (A trailing newline cannot be used — `grep -F` treats a newline in the pattern as an alternation, which would make the assertion weaker still.) - ℹ️ `scripts/queue-selftest.sh:5410` - In the fix round's §14 rewrite, `limited` is defined as the output of `grep 'Merging is limited to'`, and the very next line asserts that `limited` contains `Merging is limited to`. That assertion can only fail when grep matched nothing, i.e. it is a non-empty check written circularly; the claim §14 actually makes is carried entirely by the `refute` on `gitlab.example.com` that follows. Not a defect — the pair still fails correctly if the shepherd stops printing the line (limited is empty, expect fails) — but the expect reads as if it verifies content it cannot. Noting it rather than asking for a change. </details> <details> <summary>✅ **Test** - passed</summary> ✅ No issues found. - Live validation: ✅ go - 9 of 11 scenarios driven live against the product | Scenario | Result | Live | Evidence | | --- | --- | --- | --- | | An attested, green pull request on github.com/LeTuR/mazet is squash-merged unattended by the shepherd, with the branch deleted | ✅ pass | live | `./scripts/queue.sh shepherd --topic mazet-live` against a throwaway queue; the row reads `merged: squash-merged, branch deleted`, the shepherd issued `gh pr merge https://github.com/LeTuR/mazet/pull/… | | Before the entry existed the same pull request was handed back, not merged (the regression this change fixes) | ✅ pass | live | Same queue, same pull request, run with `FLEET_AUTO_MERGE_REPOS='github.com/Thurbeen/fleet github.com/Thurbeen/thurbox github.com/Thurbeen/thurview'`: the row reads `ready: fleet does not merge in LeT… | | An unattested mazet pull request is still handed back and given a fixer rather than merged | ✅ pass | live | PR 302 in the same pass: `policy: the body carries no no-mistakes attestation` then `dispatched: Re-open PR #302 through the pipeline`, recorded as `publish.state = unattested`; the merge log names on… | | Adversarial: a bare LeTuR/mazet naming no forge is refused rather than matched against the slug | ✅ pass | live | `FLEET_AUTO_MERGE_REPOS='LeTuR/mazet' ./scripts/queue.sh shepherd --dry-run` prints `ignoring 'LeTuR/mazet' — an auto-merge entry must name its forge`, the mazet pull request stays `ready: fleet does… | | FLEET_AUTO_MERGE_REPOS still replaces the shipped set rather than adding to it | ✅ pass | live | With the override naming the three older repos, the pass's own `Merging is limited to` line names exactly those three and mazet is excluded despite being in the shipped literal; with no override the l… | | Adversarial: every other merge gate still refuses on the newly allowlisted repo | ✅ pass | live | `./scripts/queue.sh shepherd --topic mazet-gates` over five mazet pull requests: an attestation for an earlier head is `policy` and gets a fixer, an author with no push access is `not-merged`, failing… | | The shepherd tells the operator the set is four repositories, every entry host-qualified | ✅ pass | live | The pass's closing line reads `Merging is limited to github.com/LeTuR/mazet, github.com/Thurbeen/fleet, github.com/Thurbeen/thurbox, github.com/Thurbeen/thurview`; queue-selftest section 9j reads the… | | A discovered second forge adds nothing to the merge set, and the reworked section 14 assertion would catch it if it did | ✅ pass | live | queue-selftest section 14 (real GitLab adapter over recorded glab output) is green on all five assertions including `discovering the instance put nothing of it on that set`; driving the same line with… | | The remote is genuinely no longer the blocker: github.com/LeTuR/mazet allows squash and only squash | ✅ pass | live | Read-only against the live repository: `gh api repos/LeTuR/mazet` returns allow_squash_merge true, allow_rebase_merge false, allow_merge_commit false, delete_branch_on_merge true, PR_TITLE/PR_BODY; it… | | Every place that states the set agrees with the code after the change | ⏸️ untested | no | This was established by reading tracked files with `git grep`, not by driving the running product, so the prior payload records no live result for it. Documentation consistency has no runtime surface… | | A real squash merge performed on the live github.com/LeTuR/mazet repository | ⏸️ untested | no | Driving this needs a genuinely open, attested, green pull request on the public github.com/LeTuR/mazet and authority to merge it; the merge is irreversible and outward-facing, and a test phase should… | - `./scripts/check.sh` - <code>`./scripts/check.sh queue` (queue selftest through the repo's own gate, exit 0)</code> - <code>`./scripts/queue-selftest.sh` (direct run for per-assertion output; all §9j and §14 assertions green, exit 0)</code> - <code>Manual end-to-end drive of `./scripts/queue.sh shepherd --topic <topic>` under `FLEET_AUTO_MERGE_REPOS='github.com/Thurbeen/fleet github.com/Thurbeen/thurbox github.com/Thurbeen/thurview'` (before-state) and under the shipped set (after-state)</code> - <code>Manual drive of `./scripts/queue.sh shepherd` over five mazet pull requests exercising each merge gate: stale attestation, author without push access, failed checks, fork head branch, and a clean control</code> - <code>`FLEET_AUTO_MERGE_REPOS='LeTuR/mazet' ./scripts/queue.sh shepherd --topic <topic> --dry-run` (bare slug, adversarial)</code> - <code>`FLEET_AUTO_MERGE_REPOS='github.com/LeTuR/mazet gitlab.example.com/acme/group/widgets' ./scripts/queue.sh shepherd --dry-run` (sensitivity of section 14's narrowed assertion)</code> - <code>`gh api repos/LeTuR/mazet`, `gh api repos/LeTuR/mazet/contents/.no-mistakes.yaml`, `gh api repos/LeTuR/mazet/actions/workflows` (read-only, live remote)</code> - <code>`git grep -n 'Thurbeen/thurview' -- '*.md' '*.py' '*.sh'` to confirm every place that enumerates the set now names four repositories</code> </details> <details> <summary>✅ **Document** - passed</summary> ✅ No issues found. </details> <details> <summary>✅ **Lint** - passed</summary> ✅ No issues found. </details> <details> <summary>✅ **Push** - passed</summary> ✅ No issues found. </details>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Allow auto merge for thurbox. The operator asked, in exactly those words, for github.com/Thurbeen/thurbox to join fleet's AUTO_MERGE_REPOS allowlist in scripts/lib/queue.py, so queue.sh shepherd will squash-merge thurbox pull requests unattended the way it already does fleet's and thurview's.
Scope and deliberate decisions, so a reviewer reading only the diff does not flag them as mistakes:
The entry is HOST-QUALIFIED (github.com/Thurbeen/thurbox), like its two neighbours. That is not decoration: forge.RepoId.parse refuses an entry naming no host, deliberately, because a bare Thurbeen/thurbox is a different repository on github.com than on a self-hosted instance and this is the one list where matching the wrong one means acting on somebody else's code.
The set was reformatted from a one-line literal to a three-line braced set purely because a third entry no longer fits the line. No membership other than the addition changed.
The comment above the set is the file's own argument for who is on the list, and it states the test for adding a repo: not whether the fleet has work there, but whether the repo carries its own .no-mistakes.yaml and CI so the attestation and checks gates mean something. thurbox was checked against that test before the task was written — it has a 24KB .no-mistakes.yaml whose commands.lint is 'just lint && RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features', and four workflows (ci.yml, cd.yml, pages.yml, pr-title.yml). A new paragraph records that in the same style the thurview paragraph uses, because an entry that appears without an argument erodes the comment.
NO GATE WAS LOOSENED, and that was a hard constraint of the task. thurbox joins on exactly the same five gates: head branch in the repo, no-mistakes attestation for the CURRENT head, all checks concluded and passed, forge calls it mergeable, author can push. Nothing in classify, shepherd_pr, publish_word or author_can_push was touched.
AUTO_MERGE_ENV (FLEET_AUTO_MERGE_REPOS) was deliberately NOT touched. That variable REPLACES the set rather than adding to it, which is intentional — a fleet driving somebody else's repositories is a different fleet.
Tests were written FIRST and watched fail for the right reason before the constant changed: the new section 9i printed 'ready: fleet does not merge in Thurbeen/thurbox on github.com; this one is yours' until thurbox was added. It reuses section 9's existing fake gh stub and its perms fixture rather than building a third harness. Three claims, and the third is the one the task named as the thing this addition could quietly weaken:
The unattested PR (202) is deliberately recorded by NO task, so it is classified and left rather than dispatching a fixer — that keeps 9i from perturbing section 9's fixer counts, and it exercises the unlinked-PR path at the same time.
.agents/skills/fleet-queue/SKILL.md enumerates the allowlist in prose, so it now names thurbox too. FLEET.md and AGENTS.md were checked and deliberately left alone: both use github.com/Thurbeen/fleet as an example of the host-qualified FORM, not as an exhaustive list.
The branch was fast-forwarded from 47b236e to origin/main (bd8aca6) before any work, per the queue policy's rebase-first rule — the worktree was many commits behind and AUTO_MERGE_REPOS had changed shape (host-qualification, the forge seam) in the interim.
./scripts/check.sh — the repo's whole gate — is green in full on this commit: shell, markdown, yaml, profiles, queue, reconcile, status, skills, pane and voice.
What Changed
github.com/Thurbeen/thurboxentry toAUTO_MERGE_REPOSinscripts/lib/queue.py, reformatting the set from a one-line literal to a three-line braced set, and added a comment paragraph arguing thurbox meets the list's existing test (its own.no-mistakes.yamland CI, so the attestation and checks gates mean something).scripts/queue-selftest.sh, reusing section 9's fakeghstub and permissions fixture, asserting: an attested green thurbox PR is squash-merged unattended with the expectedpr merge --squash --delete-branchcall; an unattested-but-otherwise-green thurbox PR is left unmerged and reported; and a bareThurbeen/thurbox(no host) inFLEET_AUTO_MERGE_REPOSis refused rather than matched..agents/skills/fleet-queue/SKILL.mdto name thurbox alongside fleet and thurview in the prose description of the auto-merge allowlist.Risk Assessment
✅ Low: The change is a minimal, precisely-scoped addition of one host-qualified entry to AUTO_MERGE_REPOS plus a matching documentation update and a new selftest section reusing existing test infrastructure; it touches no gating logic (classify/shepherd_pr/publish_word/author_can_push), matches every constraint in the stated intent, and the new test exercises the real shepherd command against a faithful fake gh stub with concrete behavioral assertions rather than source-text matching.
Testing
Baseline ./scripts/check.sh had already passed. I additionally ran scripts/queue-selftest.sh directly (the targeted behavioral test for the queue subsystem this change touches, since check.sh's 'queue' check is exactly this script and it isn't subdividable into a smaller runnable subset — the new section 9i shares fixtures with earlier sections). The script exited 0 with the summary 'queue-selftest: every claim holds' and zero FAIL lines. The new section 9i's 7 assertions all passed, exercising the three claims the user intent named as load-bearing: (1) an attested, green thurbox PR (#201) is squash-merged unattended via the exact 'pr merge <url> --squash --delete-branch' command, matching how fleet's and thurview's PRs are merged; (2) an unattested-but-green thurbox PR (#202) is left unmerged and reported for lacking a no-mistakes attestation, proving the allowlist addition didn't loosen any gate; (3) a bare, non-host-qualified 'Thurbeen/thurbox' in FLEET_AUTO_MERGE_REPOS is refused with 'must name its forge' rather than matched against the slug. The worktree was left clean after the run (git status --porcelain empty), confirming no stray artifacts.Evidence: scripts/queue-selftest.sh output for section 9i (thurbox allowlist) and final summary
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
✅ **Review** - passed
✅ No issues found.
✅ **Test** - passed
✅ No issues found.
./scripts/check.sh./scripts/queue-selftest.sh (full run, includes new section 9i: 'thurbox is on the allowlist, on the same gates as fleet')✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.