Skip to content

feat(queue): add thurbox to the auto-merge set - #64

Merged
LeTuR merged 1 commit into
mainfrom
feat/automerge-thurbox
Sep 10, 2026
Merged

feat(queue): add thurbox to the auto-merge set#64
LeTuR merged 1 commit into
mainfrom
feat/automerge-thurbox

Conversation

@LeTuR

@LeTuR LeTuR commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

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:

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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:

  • an attested, green thurbox PR is squash-merged unattended, and the assertion names the exact 'pr merge --squash --delete-branch' the stub logged;
  • a thurbox PR that is green in every way the forge can see but carries no attestation is NOT merged, and is reported for what it lacks — the proof that joining the allowlist adds a repository and not a looser rule;
  • a bare 'Thurbeen/thurbox' in FLEET_AUTO_MERGE_REPOS is refused with 'must name its forge' rather than matched against the slug, and nothing under it would be merged. Section 13e proves that for a forge that is not GitHub; 9i proves it for the repo just added, where the bare slug is the plausible typo since it is how the operator wrote it.
    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.
  1. .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.

  2. 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

  • Added the host-qualified github.com/Thurbeen/thurbox entry to AUTO_MERGE_REPOS in scripts/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.yaml and CI, so the attestation and checks gates mean something).
  • Added section 9i to scripts/queue-selftest.sh, reusing section 9's fake gh stub and permissions fixture, asserting: an attested green thurbox PR is squash-merged unattended with the expected pr merge --squash --delete-branch call; an unattested-but-otherwise-green thurbox PR is left unmerged and reported; and a bare Thurbeen/thurbox (no host) in FLEET_AUTO_MERGE_REPOS is refused rather than matched.
  • Updated .agents/skills/fleet-queue/SKILL.md to 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
ok the shepherd reaches thurbox at all
ok an attested, green thurbox pull request is merged unattended
ok and by the same squash fleet's own are merged by
ok joining the allowlist loosens no gate: an unattested one is not merged
ok and it is named for what it lacks, not passed over
ok a bare Thurbeen/thurbox is refused, not matched against the slug
ok and nothing in thurbox would be merged under it
...
queue-selftest: every claim holds

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.

`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
LeTuR merged commit 35fc400 into main Sep 10, 2026
10 checks passed
@LeTuR
LeTuR deleted the feat/automerge-thurbox branch September 10, 2026 07:10
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=&#39;github.com/Thurbeen/fleet
github.com/Thurbeen/thurbox github.com/Thurbeen/thurview&#39;`: 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=&#39;LeTuR/mazet&#39; ./scripts/queue.sh
shepherd --dry-run` prints `ignoring &#39;LeTuR/mazet&#39; — 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&#39;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&#39;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&#39;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 &#34;because
the merge set is exactly the three repos it always was&#34; against the
literal &#34;github.com/Thurbeen/fleet, github.com/Thurbeen/thurbox,
github.com/Thurbeen/thurview&#34;, and it was not updated with the
allowlist. The intent requires &#34;make every place that states the set
agree with the code&#34;; this is such a place and it no longer does.
Concrete trace: scripts/lib/queue.py:5371 prints &#34;Merging is limited
to &#34; + &#34;, &#34;.join(sorted(auto_merge_repos())); sorted() now
yields github.com/LeTuR/mazet first (&#39;L&#39; &lt; &#39;T&#39;), so
the printed line is &#34;…limited to github.com/LeTuR/mazet,
github.com/Thurbeen/fleet, github.com/Thurbeen/thurbox,
github.com/Thurbeen/thurview, …&#34; and expect()&#39;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&#39;s &#34;every place that
states the set&#34; 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,
&#34;unqualified=none&#34; 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 &#39;a&#39;
(97) against &#39;T&#39; (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 &#34;the four repositories fleet may merge in&#34;.
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(&#34;entries=&#34; + &#34; &#34;.join(repos) + &#34; .&#34;)` 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&#39;s §14
rewrite, `limited` is defined as the output of `grep &#39;Merging is
limited to&#39;`, 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=&#39;github.com/Thurbeen/fleet
github.com/Thurbeen/thurbox github.com/Thurbeen/thurview&#39;`: 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=&#39;LeTuR/mazet&#39; ./scripts/queue.sh
shepherd --dry-run` prints `ignoring &#39;LeTuR/mazet&#39; — 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&#39;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&#39;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&#39;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
&lt;topic&gt;` under
`FLEET_AUTO_MERGE_REPOS=&#39;github.com/Thurbeen/fleet
github.com/Thurbeen/thurbox github.com/Thurbeen/thurview&#39;`
(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=&#39;LeTuR/mazet&#39; ./scripts/queue.sh
shepherd --topic &lt;topic&gt; --dry-run` (bare slug,
adversarial)</code>
- <code>`FLEET_AUTO_MERGE_REPOS=&#39;github.com/LeTuR/mazet
gitlab.example.com/acme/group/widgets&#39; ./scripts/queue.sh shepherd
--dry-run` (sensitivity of section 14&#39;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 &#39;Thurbeen/thurview&#39; -- &#39;*.md&#39;
&#39;*.py&#39; &#39;*.sh&#39;` 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant