Skip to content

fix(changeset): the two unreleased /packages-door notes enumerate all three filters that door reads - #19616

Merged
hotlong merged 1 commit into
mainfrom
claude/issue-19605-changeset-carriers-third-filter
Sep 22, 2026
Merged

hotlong merged 1 commit into
mainfrom
claude/issue-19605-changeset-carriers-third-filter

Conversation

@os-steve

Copy link
Copy Markdown
Collaborator

Fixes #19605

What changed

GET /api/v1/packages reads three query filters — status, type, enabled
(readEnabledFilter, packages/runtime/src/domains/packages.ts). Two pending changesets
enumerated two of them. Each gains enabled; nothing else moves.

file frontmatter the enumeration
.changeset/17667-packages-query-contract.md '@objectstack/spec': minor the serving door filters on `status` / `type``` → … status / type / `enabled```
.changeset/scoped-packages-dispatcher-door.md "@objectstack/runtime": minor this door applies its `status` / `type` filters → … `status` / `type` / `enabled` filters

3 lines changed, 2 files (+3 / -3). The second line of the first file's hunk is a re-wrap
only — that file is hard-wrapped at 80 columns and the twelve added characters pushed one
word onto the next line. Re-wrapping was contained to the two lines the sentence occupies,
so the paragraph below it is byte-identical.

Clause-②: no

Re-judged from this diff rather than inherited: this branch adds no key to any published
payload — it adds no key to anything. It edits prose inside two pending changesets and
ships no schema, no export and no wire field. The claim comment on #19605 declares the same
value, so there is no mismatch to report.

ROUTE 0 — read this before merging: Check Changeset is RED by design

This PR corrects two pending release notes and adds no changeset of its own. That is the
DELIBERATE CORRECTION class named in .github/workflows/pr-automation.yml's Check Changeset
step (route 0) and in scripts/check-empty-changeset.mjs. Both readings were taken locally,
exit codes captured before any pipe.

The route-0 discriminator, verbatim:

$ git diff --name-status 5c5b67fc4140f76ca3158acea9e0845d9eebfad8 HEAD -- '.changeset/*.md'
M	.changeset/17667-packages-query-contract.md
M	.changeset/scoped-packages-dispatcher-door.md

$ git diff --name-only --diff-filter=A 5c5b67fc4140f76ca3158acea9e0845d9eebfad8 HEAD -- '.changeset/*.md' | grep -v '/README\.md$' | wc -l
0

Every row is M, none is A, so the counting step reads added=0 and the verdict step fails.
scripts/check-empty-changeset.mjs --base origin/main classifies it independently — exit 1,
"present on the merge base and CHANGED by this PR". Of that gate's two classes this is
DELIBERATE CORRECTION, not COLLISION: the two filenames were drawn by other PRs
(#17667 and #16781), this branch drew neither, and restoring them from the merge base is the one
thing the gate tells you not to do here — it would put the short enumeration back.

The written confirmation route 0 asks for, naming the note and what changed under it:

  1. .changeset/17667-packages-query-contract.md — '@objectstack/spec': minor, the note for
    the limit / cursor retirement on ListInstalledPackagesRequestSchema. Under it, one
    sentence in the BREAKING paragraph gains the third filter. The removability argument, the
    .default(50) passage, the retiredKey() paragraph, the newly-declared-parameters table, the
    hasMore paragraph, the Clause-②: yes line and the ADR-0087 disposition marker are all
    untouched.
  2. .changeset/scoped-packages-dispatcher-door.md — "@objectstack/runtime": minor, the note
    for mounting the scoped /api/v1/environments/:id/packages* door. Under it, the hasMore
    bullet's enumeration gains the third filter. The door paragraph, the DELETE bullet and the
    route-ledger paragraph are untouched.

Neither note is made false by this branch's own code — this branch ships no code. Both were made
short by #19405, which landed the enabled leg, and both publish into the same 17.5.0
that carries the correction of that same sentence everywhere else (landed as #19595 for card
#19407). Repairing them here is a decision about a release, which is why the gate puts it in
front of a person rather than letting a label route around it.

⛔ skip-changeset is deliberately NOT applied and must not be applied. Maintainer ruling on
#18375 (ruling D, 2026-09-18): the label is never applied to a PR that edits an existing
changeset. It would be a false declaration — the notes rewritten here are releases that are
still pending — and it exempts the whole job, taking the refusal that names this class with it.
Check Changeset is not one of the seven required contexts, so this red blocks no merge; the
approver merges over it, and staying red is the point.

Does a .changeset/-only edit owe its own changeset?

No, and it must not have one. Two independent readings agree:

  • AGENTS.md Post-Task Checklist step 3 — "Add a changeset for anything that publishes." This
    branch publishes nothing: it adds no package version, moves no files[] payload and touches no
    packages/ source. pnpm check:published-files exit 0.
  • Route 0 above is stronger than that: it forbids both remaining routes. Adding a changeset of
    this branch's own would be route 1, declaring a release this branch does not make; the label
    would be route 2, refused by name for this class.

So the correct shape is: no changeset, no label, a red Check Changeset, and this paragraph.

Does editing an unconsumed changeset's prose need anything regenerated?

No. Measured rather than assumed:

  • pnpm --filter @objectstack/spec check:generated — exit 0, "All 15 generated artifacts are
    up to date", run against a dist this branch built (pnpm --filter @objectstack/spec build,
    exit 0, under the shared verify lock). Nothing in packages/spec/scripts/ reads .changeset/
    content — the three hits for that path are prose in file headers, not reads.
  • node scripts/check-changeset-fixed.mjs — exit 0, the .changeset/config.json "fixed"
    group still in sync with 70 public workspace packages. This is the one artifact-roster gate
    whose roster lives under a directory this diff is in, so its silence would not have been
    evidence either way; it was run rather than assumed.
  • node scripts/check-adr-0087-registration.mjs --base origin/main — exit 0. The first file
    is a declared-breaking changeset and its ADR-0087 disposition marker is intact.

The one artifact these two files do feed is the generated CHANGELOG.md on the changesets
release PR, and that artifact regenerates itself — see below.

⛔ Do not edit PR #17076, and nothing here does

PR #17076 chore: version packages is the bot's standing release PR. Read at
3b8ebe9a2dec9fa6fea7c3a131f4fa72fc005fec, it carries packages/spec and packages/runtime at
17.5.0 and both stale sentences are already written into its generated changelogs
(packages/spec/CHANGELOG.md, packages/runtime/CHANGELOG.md), with the three-filter form absent
from both. Nothing in this PR touches that branch, its files, its body or its labels. When this
lands on main the bot regenerates that PR and the corrected sentences replace the stale ones.
Prime Directive #15 also applies to it: no agent seat merges, queues or arms auto-merge on it.

Is the edit semantically right?

The sentence was incomplete, not false, and only the enumeration moves. Its load-bearing claim
— no page was ever withheld and no continuation token was ever minted — stays true, because
enabled filters rows and does not paginate. The surrounding argument is unrewritten; a probe for
that claim still counts 1 in the first file after the edit.

Evidence

Exit codes captured before any pipe (cmd > file 2>&1; EXIT=$?).

Premise, re-verified at 5c5b67fc41 with a whitespace-normalised whole-file probe. A
line-wise git grep for the first sentence returns a false zero — it wraps, "the serving door
filters on" ends one line and the backticked filters begin the next. Before the edit: carrier 1
two-filter count 1 / three-filter 0; carrier 2 two-filter 1 / three-filter 0. Lit control ("no page
was ever withheld") true in file 1; dark control ("zzznotasentence") false in both. After the edit:
two-filter 0 / three-filter 1 in each, lit control still 1, dark control still 0.

The destination, read directly from the release branch (fetched into a ref this branch owns, no
write): on 3b8ebe9a2d, packages/spec/CHANGELOG.md carries the first stale sentence (count 1) and
packages/runtime/CHANGELOG.md the second (count 1), the three-filter form counts 0 in both,
and both packages read 17.5.0. That is the byte-level confirmation that these two .changeset/
files are the sources of those two changelog lines.

Gate families. node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack
derived 19 commands from this tree at 7bd01a6d88; all 19 were run and reconciled with
--ran (19 derived, 19 run, 0 NOT-MEASURED, 0 UNRUN, every row carrying an exit code), plus 2 run
beyond the derivation. 18 exit 0; the single exit 1 is check-empty-changeset.mjs --base origin/main, the designed route-0 red documented above. Included:
check-changeset-no-major 0, check-adr-0087-registration 0, check:nul-bytes 0,
check:published-files 0, check:pm-changeset-deadline-census 0, check:objectui-changeset 0,
check-closing-keyword-parity 0, check-issue-citations --base origin/main 0 (0 issue citations
added — no bare card number lands on an added line).

pnpm lint, narrowed and the narrowing proven. eslint.config.mjs carries seven
files-bearing config objects and every one of them is a TypeScript/JavaScript glob
(**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs} and narrower); a grep of that file for a markdown glob or
for this diff's directory returns exit 1, zero hits. npx eslint --no-inline-config --format json
over exactly the two changed files reports 2 results, 0 errors, each carrying "File ignored
because no matching configuration was supplied". This diff adds and removes no config object and
touches no .ts/.js file, so no untouched file's verdict can move. The repo-wide scan is CI's;
its verdict is invariant under this diff.

Build/test tiers: this diff touches no workspace package, so there is no affected-package closure
and no package test / typecheck is owed. The packages/spec build above was run only to give
check:generated a real dist to read.

Acceptance notes

  • .changeset/19407-packages-list-tombstone-third-filter.md also matches the two-filter pattern.
    It is the FROM side of that note's own before/after block, with the corrected TO two lines
    below it. Quoting the old sentence to show what moved is the point of the block, so it is left
    exactly as it stands — a naive re-run of the probe returns three lines and the third is a
    deliberate quotation, not a fourth carrier.
  • packages/runtime/src/domains/packages.ts already enumerates all three filters correctly and is
    outside this PR's declared file surface (.changeset/ and nothing else).
  • ListInstalledPackagesResponseSchema.nextCursor remains declared and never emitted. Named in
    card [finding] two unreleased changesets publish the /packages list door's filter set as two-of-three into 17.5.0 — the same release that carries the repair #19605 as deliberately left by the retirement; no card is opened for it here.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AmH9bKvGoLjiY86Q4Z3og2


Generated by Claude Code

… three filters that door reads

`GET /api/v1/packages` reads three query filters — `status`, `type` and
`enabled` (`readEnabledFilter`, `packages/runtime/src/domains/packages.ts`).
Two pending changesets still enumerate two of them, and both publish into the
same release that carries the correction of that same sentence.

Incomplete, not wrong, and only the enumeration moves: the load-bearing claim —
no page was ever withheld and no continuation token was ever minted — stays
true, because `enabled` filters rows and does not paginate. The surrounding
argument is byte-identical.

Claude-Session: https://claude.ai/code/session_01AmH9bKvGoLjiY86Q4Z3og2
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/xs documentation Improvements or additions to documentation tooling labels Sep 21, 2026

Copy link
Copy Markdown
Collaborator Author

Seat confirmation for the DELIBERATE CORRECTION refusal — the two notes are named and the rewrite is confirmed, 2026-09-21T18:13Z

check-empty-changeset.mjs refuses this PR by name because it modifies two .changeset/*.md that exist on
the merge base and were not added by it
. The refusal names two classes with opposite remedies, and this PR
is the second one. Quoted from the gate's own source, ⛔ not paraphrased:

COLLISION -> rename yours; restore theirs from base
DELIBERATE CORRECTION -> do NOT restore it; get it confirmed on the PR

and the remedy string itself, scripts/check-empty-changeset.mjs:551:

do NOT restore it -- say so on the PR and get it confirmed

This comment is the confirmation half. The seat that dispatched this card has read both hunks and confirms
them below. ⛔ This is not an approval of the PR and ⛔ it clears no gate — the red stands, by design.

The two notes, and what changed under each

note what it said what it says now
.changeset/17667-packages-query-contract.md ('@objectstack/spec': minor) 「the serving door filters on status / type and then returns every remaining row」 「… on status / type / enabled and then returns every remaining row」
.changeset/scoped-packages-dispatcher-door.md ("@objectstack/runtime": minor) 「this door applies its status / type filters and returns every remaining row」 「… applies its status / type / enabled filters and returns every remaining row」

⇒ +3/−3 over 2 files, one of the three lines being an 80-column re-wrap in a hard-wrapped file.

Why restoring from base is the wrong remedy here — which is the whole point of the two-class split

Both notes are PENDING: they publish into @objectstack/spec / @objectstack/runtime 17.5.0, and the
release PR that consumes them is open right now with both sentences already generated into its changelogs.
Restoring them from base would put the short enumeration back into a release that is one merge from
publishing it.

⚠️ And this is ⛔ not the COLLISION class, measured rather than asserted: the two filenames were drawn by
#17667 and #16781 respectively, and this branch drew neither — it added no changeset of its own, which is
exactly why the counting step reads added=0.

The sentences were incomplete, ⛔ not false — so only the enumeration moved

GET /api/v1/packages reads three filters; the notes enumerated two. The load-bearing claim of both —
no page was ever withheld and no continuation token was ever minted — stays true, because enabled
filters rows and does not paginate. Verified after the edit: the two-filter form counts 0 and the
three-filter form counts 1 in each file, while the lit control 「no page was ever withheld」 still counts 1
and the dark control counts 0.

⛔ Two things this PR deliberately did NOT do

  1. ⛔ skip-changeset was not applied, and ⛔ must not be: the maintainer's ruling D on [finding] the skip-changeset label suppresses the DELIBERATE-CORRECTION refusal whose own text says 「no label and no diff shape makes that safe」 — declared contract against enforced behaviour #18375
    (2026-09-18) refuses that label for exactly this class — the notes rewritten here are releases still
    pending, so the label would be a false declaration and it exempts the whole job.
  2. ⛔ The release PR was not touched — no branch, file, body or label write of any kind. It regenerates
    from main on the next push, which is the mechanism this repair depends on.

⚠️ One thing this seat could NOT measure, stated rather than assumed

Whether Check Changeset is a required context on main is NOT MEASURED here:
GET /branches/main/protection answers 403 「Resource not accessible by integration」 for this seat, and
the gate's motivating instance ed7243d52 predates the gate (2026-09-08 vs the 2026-09-13 ruling), so it
carries 0 Check Changeset runs and is no precedent for landing red. A scan of the 25 most recently
updated merged PRs found 0 that merged with a red latest Check Changeset — a weak reading with a small
radius, ⛔ not a proof either way.

⇒ the seat will read it off mergeable_state once this PR leaves draft — unstable says the red is
advisory, blocked says it is not — and will ⛔ not arm this PR on an assumption about which.


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 7bd01a6d884a08e376033204a76a33ef7bd64527

① Derived judgments

Read at 2026-09-21T18:23Z. Every reading below is from GitHub or from the checkout at 5c5b67fc41 (= the
declared base), ⛔ not from the PR body. Exit codes captured before any pipe. ⚠️ The line-wise trap
was avoided throughout: in 17667-packages-query-contract.md the sentence wraps across lines
14–15, so every probe here is a whitespace-normalised whole-file probe, and every zero is paired
with a lit control.

The diff is what it claims. Commit 7bd01a6d88, single commit, parent 5c5b67fc41 — the
declared base. 2 files, +3/−3, both under .changeset/; no file outside it. The declared file
surface (.changeset/ and nothing else) holds.

The third line is a re-wrap, not an edit — measured, not accepted. A word-level diff of each
file whole and whitespace-normalised returns exactly one opcode per file, and in both it is the
same insert:

file the only delta, base → head
17667-packages-query-contract.md 「the serving door filters on status / type」 gains / `enabled` — inserted between `type` and 「and then returns every remaining row」
scoped-packages-dispatcher-door.md 「this door applies its status / type」 gains / `enabled` — inserted between `type` and 「filters and returns every remaining row」

Nothing else in either file differs by so much as a word. The 12 added characters pushed was ever
onto the next line: base 15/16 are 75/71 columns, head 15/16 are 78/80, and the set of lines
over 80 columns is identical in base and head (5, 24, 27, 55, 56, 57 — frontmatter title and a
table, neither touched). Line 17 down is byte-identical. The re-wrap is contained to the two lines
the sentence occupies.

The repair is right, and bounded. The door reads exactly three query keys on this route —
read from packages/runtime/src/domains/packages.ts, ⛔ not from the card: enabled (:828, via
readEnabledFilter), status (:837), type (:840). Dark control query?.limit / query?.cursor
counts 0 in that file, grep exit 1 — the instrument fires, the target is genuinely absent. The
other query?. reads (:1035 overwrite, :1721 version, :1864 keepData) are other routes,
outside the parts.length === 0 && m === 'GET' branch. ListInstalledPackagesRequestSchema
(packages/spec/src/api/package-api.zod.ts:235-257) agrees exactly: three live filters
status / enabled / type, plus limit / cursor as retiredKey() tombstones. The door's own
comment at :873 already writes the corrected sentence — the two notes were the last carriers of
the short one.

The sentences were incomplete, not false, and the load-bearing claim survives untouched. Lit
control 「no page was ever withheld and no continuation token was ever minted」 counts 1 in
17667-… before and after; dark control counts 0 in both files, both sides. Two-filter form
1 → 0, three-filter form 0 → 1, in each file. The removability passage, the .default(50)
passage and the hasMore passage are byte-identical — the single-opcode diff above is the proof, not
an assurance.

The carrier set is closed. Whitespace-normalised sweep over all 569 .changeset/*.md at
5c5b67fc41: the two-filter form lives in 3 files — the 2 this PR repairs, and
19407-packages-list-tombstone-third-filter.md, correctly untouched. ⚠️ One refinement to the
acceptance note: that file carries two two-filter occurrences, not one — :9 (「that prescription
enumerated the serving door's filters as status / type」, the note reciting what it is replacing)
and :23 (the FROM side, with TO at :27). Both are deliberate records of what moved; editing
either would destroy it. ⛔ No change requested — recorded only so a future sweep does not read :9
as a missed carrier. ListInstalledPackagesResponseSchema.nextCursor stays declared
(package-api.zod.ts:269) and never emitted; untouched here, as intended.

Clause-②: no is true — judged from the diff, ⛔ not from the path surface. Clause ② asks whether
this PR puts a new key on a published payload (check-changeset-no-major.mjs:1903: 「this PR puts no
new key on a published payload」). The whole diff is the two-word insert above: no schema key, no
export, no wire field, no manifest, no exports entry. And the key the prose now names was already
declared (package-api.zod.ts:240) and already read at the base — #19405 landed that leg. The card's
claim comment (5765016512) declares the same value; no mismatch.

② Semver level

No changeset of its own is correct, and adding one would be wrong. Editing two pending
changesets' prose publishes nothing that owes a level:

  • The frontmatter of both notes is untouched — '@objectstack/spec': minor and
    "@objectstack/runtime": minor — so the releases those notes already declare are unchanged in
    level. This PR creates no release; it edits the text of two that already exist.
  • check:published-files — self-test exit 0, main exit 0 (70 publishable packages). Its
    invariants read package manifests (files, exports, entry points), ⛔ never changeset prose. The
    one invariant that reads a changeset at all is ANNOUNCED, and it fires only when a package's
    resolvable surface narrows against the merge base. This diff touches no package.json, no
    dist, no exports — nothing can narrow, so that arm has no input.
  • AGENTS.md step 3 — 「Add a changeset for anything that publishes」. This branch touches no
    packages/ source and moves no version. It publishes nothing.

The destination confirms these two notes are genuinely pending. At the release PR's head
3b8ebe9a2d, packages/spec/CHANGELOG.md and packages/runtime/CHANGELOG.md each carry the
two-filter form ×1 and the three-filter form ×0, and both top out at 17.5.0 (dark
control 0 in both). So the short enumeration is one merge away from publishing, and these two files
are the sources of those two lines.

③ Boundary flags

⭐ The Check Changeset red is the DELIBERATE CORRECTION class, and the remedy was followed.
Established from the gate, not the narration. scripts/check-empty-changeset.mjs names two classes
with opposite remedies — FOREIGN_REMEDY (:538) 「rename yours; restore theirs from base」 vs
FOREIGN_CORRECTION_REMEDY (:551) 「do NOT restore it -- say so on the PR and get it confirmed」,
rendered together at FOREIGN_TWO_CLASS_LINES (:559-563). The live annotation on the failing run
(106456881287) states this PR's case by name:

This PR adds no changeset. FIRST: if its only .changeset rows are CHANGED, not added, this PR
corrects somebody else's pending release note -- do NOT apply 'skip-changeset'; write the
confirmation on the PR, naming the note and what changed under it, and leave this check red (#18375).

COLLISION is structurally impossible here, measured rather than argued: the head commit's file
list is 2 modified, 0 added — this branch drew no changeset filename at all, so there is
nothing of its own that could have overwritten anyone's. And the COLLISION remedy is provably the
wrong act: git checkout <merge-base> -- … would restore the two-filter enumeration into the
same 17.5.0 whose changelogs still carry it, contradicting both the door (packages.ts:828/837/840)
and the schema.

ℹ️ One honest nuance, stated rather than smoothed: the correction class is narrated as 「your change
may have made this PENDING release note false, and you rewrote it in the same stroke」. This branch
ships no code, so the notes were made short by #19405, not by this branch, and they are
incomplete rather than false. The class holds by remedy — which is the operative question the
two-class split exists to answer — and the gate is diff-shape-blind by design, which is why it asks a
person. ⛔ Not a defect; no change requested.

The confirmation comment exists and does what the remedy asks. Comment 5765290088 (2026-09-21T18:13Z).
It names each note and what changed under it: a table carrying both paths with their frontmatter
('@objectstack/spec': minor, "@objectstack/runtime": minor) and the before → after sentence for
each, plus +3/−3 over 2 files with one line flagged as an 80-column re-wrap. It states it clears no
gate and that the red stands.

⚠️ One precision gap in that comment, for the record only. Ruling ② B asks the confirmation carry
its provenance as 「who / what / where (the decision batch and its chat reply)」. The comment cites the
ruling as 「#18375 (2026-09-18)」 — issue and date, but not decision batch #158 item 1 nor the
maintainer's 「同意」 at 2026-09-18T11:14Z. It satisfies the gate's own remedy text and ② B's
「naming the note and what changed under it」. ⛔ Not a merge blocker and ⛔ no re-post requested.

⛔ skip-changeset is absent, and the cited ruling exists and says so. Verified by reading
#18375's comments: 5729188290, hotlong, 2026-09-18T11:14:12Z — 「Ruling: batch #158 item 1 ·
② B, ① D … ⛔ skip-changeset is not applied to a PR that edits an existing changeset」, maintainer
「同意」 at 2026-09-18T11:14Z. The ruling exists, is dated as cited, and refuses the label for exactly
this class. ℹ️ Precisely, the batch is ② B + ① D: ① D is the arm that carries the one-line rule
(「label never applied to a PR that edits an existing changeset」) into the workflow step text and the
agent text — and that text is what the live annotation above now prints, so ① D has landed — while ②
B is the written-confirmation channel. The PR body's 「ruling D」 lands on the right arm. Label
events on this PR: size/xs, documentation, tooling (bot) and needs:contract-review (os-steve)
— skip-changeset was never applied and never removed.

⛔ Release PR #17076 was not touched. Its timeline carries one commit, 3b8ebe9a2d, authored
by github-actions[bot] at 2026-09-21T12:21:12Z, with updated_at 2026-09-21T12:21:19Z — both before this
PR existed
(created 2026-09-21T18:07:48Z). No labels. Nothing on this branch reached it.

Nothing else moved. The commit's file list is exactly the two .changeset/ files; no packages/
source, no manifest, no workflow.

ℹ️ Two readings the PM may want, with their radii.
① Check Changeset is not one of the repo's pinned required contexts: REQUIRED_CONTEXTS in
scripts/check-required-contexts.mjs holds 7 entries — Lint & Repo Gates,
TypeScript Type Check, Test Core, Dogfood Regression Gate, Build Core,
Temporal Conformance (live PG + MySQL), Governed Surface Queue Guard —
and Check Changeset is absent. That is a repo-source
reading; the live Settings ruleset stays unread here too — GET /branches/main/protection answers
403 「Resource not accessible by integration」 for this seat, with a lit control (GET /repos/… →
200). So the seat's NOT-MEASURED was honest about the settings surface, and this answers it from
the repo side only.
② At review time Lint & Repo Gates — a required context — was still in_progress, and the PR is
still a draft (mergeable_state: blocked is the draft state, ⛔ not a gate verdict).

Implemented-by: claude/issue-19605-changeset-carriers-third-filter
Reviewed-by: session_01AmH9bKvGoLjiY86Q4Z3og2

VERDICT: PASS


Generated by Claude Code

@os-steve
os-steve marked this pull request as ready for review September 21, 2026 18:24

Copy link
Copy Markdown
Collaborator Author

⛔ Seat correction — comment 5765290088 is NOT the ruling's confirmation channel, and this PR is NOT landable on it, 2026-09-21T18:26Z

Read the ruling after writing that comment, ⛔ which is the wrong order. Ruling on #18375, batch #158 item 1
(5729188290, director seat, maintainer 「同意」 2026-09-18T11:14Z), ② B, quoted:

the confirmation is text on the PR: the maintainer's word, verbatim, with who / what / where (the
decision batch and its chat reply), naming the note and what changed under it.
The gate stays advisory
red; the approver (or the queue) merges over it.

and the channel, from the same ruling's head line:

the maintainer's own word, or the director / a seat carrying it with 出处三件

⇒ comment 5765290088 supplies one half — it names each note and what changed under it. It supplies
none of the other half: there is no maintainer word about this correction, because none has been
given. A seat may carry the maintainer's word with 出处三件 (谁的指令 / 原话 / 在哪说); it may ⛔ not
originate the confirmation on its own authority. That is what that comment did.

⇒ this PR waits for the maintainer's word. ⛔ Not armed, ⛔ not enqueued, and ⛔ the seat will not merge
over the red on its own reading.

What is NOT the blocker, measured — so the wait is not mistaken for a gate problem

Check Changeset red is advisory and blocks nothing, and three independent instruments agree:

instrument reading
scripts/check-required-contexts.mjs — the repo's own REQUIRED_CONTEXTS Check Changeset absent: grep exit 1, 0 lines. Lit control Lint & Repo Gates: 24 hits
the ruling's own text 「Check Changeset is not one of the seven REQUIRED_CONTEXTS, so its red is advisory and blocks nothing」
⭐ GitHub's computed mergeable_state, this PR, out of draft with the red final unstable, mergeable: true — ⛔ not blocked. A required check failing reads blocked; unstable is the non-required reading

⭐ The third one matters beyond this PR: GET /branches/main/protection answers 403 for this seat, so the
live ruleset is unreadable — but mergeable_state is computed from that ruleset, so reading it after
leaving draft is an indirect read of the surface the 403 hides. The registry is the repo's declaration;
this is its effect.

⇒ the red is settled and permanent (route 0 never clears, and ⛔ no commit clears it). It is ⛔ not what
this PR is waiting on.

What the PR is waiting on, precisely

One sentence from the maintainer confirming the correction of these two pending release notes — which
the seat will then carry back here with 谁的指令 / 原话 / 在哪说, per ② B. The notes and their before/after
are already set out in 5765290088 and need no restating.

⚠️ ⛔ skip-changeset stays unapplied and is ⛔ not an alternative: the same ruling refuses it by name for
exactly this class, and records that the one prior instance (#18765) applied it 「on the maintainer's
authority」 as surplus to the written confirmation, ⛔ not as the channel.

⏱️ Stated without pressure, because the maintainer decides the pace: release PR #17076 is open at 17.5.0
with both stale sentences already generated into its changelogs, and it regenerates from main on the next
push. Whatever lands first is what publishes.


Generated by Claude Code

@hotlong
hotlong merged commit cf1e2c2 into main Sep 22, 2026
32 of 35 checks passed
@hotlong
hotlong deleted the claude/issue-19605-changeset-carriers-third-filter branch September 22, 2026 02:46

Copy link
Copy Markdown
Collaborator Author

The DELIBERATE CORRECTION was confirmed by the maintainer's own merge, 2026-09-22T02:50Z

check-empty-changeset.mjs's FOREIGN_CORRECTION_REMEDY (scripts/check-empty-changeset.mjs:551) asks that a foreign note NOT be restored and that the correction be said on the PR and confirmed. Comment 5765290088 was my own confirmation; I retracted it in 5765464809, because ruling #18375 ② B reserves that channel for the maintainer and lets a seat only carry their word with who / what / where.

The confirmation arrived as an act, not as text. Carried here with its three sources:

The two notes, and what changed under each as merged:

  • .changeset/17667-packages-query-contract.md (+2 −2) — «the serving door filters on status / type and then returns every remaining row» → the same sentence naming all three filters the door reads, status / type / enabled.
  • .changeset/scoped-packages-dispatcher-door.md (+1 −1) — the same two-filter sentence in the GET /packages hasMore row, likewise widened to three.

Both sentences now read three filters on main, verified by reading the merged files out of origin/main, not out of this diff.

⚠️ For the record's sake, stated rather than papered over: this is an act-record, not the verbatim word the ruling's letter asks for. No text on this thread names, in the maintainer's own words, which notes were confirmed; what the merge says is that all three lines of this diff were accepted by the authority the ruling names. A later reader who needs the word itself has this provenance and the diff, not a quotation.

Check Changeset was still advisory red at merge time — the clause-② carrier axis (scripts/check-changeset-no-major.mjs:1576), which is not one of the seven REQUIRED_CONTEXTS (scripts/check-required-contexts.mjs:40). That is why the PR read mergeable_state: unstable rather than blocked, and why no admin bypass was needed to land it.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/xs tooling

Projects

None yet

3 participants