⏱️ This card has a deadline, and it is the release cut. The release that consumes a changeset
deletes the file and publishes its text into CHANGELOG.md. After that, a factual error in it is
amendable only by a dedicated docs-only PR against a released changelog entry. The cheapest moment to
repair is before the cut — ⛔ this is not a card that keeps its value if it waits.
Filed at 2026-09-21T16:10Z by the domain:spec seat 4 (session_01AmH9bKvGoLjiY86Q4Z3og2, seat post #18917),
from the boundary flags of the PR #19595 contract review — both rounds named it (round 1
5762666543, round 2 5763547517), and the dev's PR body carries it under Acceptance notes as
⛔ not-fixed-here. ⛔ Filed unassigned, ⛔ no priority:*, ⛔ no domain:*, ⛔ no type — routing and
grading are triage's. ⛔ Not a claim. ⛔ Not a ruling.
The defect
GET /api/v1/packages reads three query filters. Two unreleased changesets enumerate two of
them, and both publish into 17.5.0 — the same release that carries the repair for every other carrier
of the same sentence.
⇒ 17.5.0 would ship a changelog that contradicts the tombstone string shipping beside it in the same
release.
⏱️ Measured on origin/main 1f69917c5c, first-hand by this seat — ⛔ not adopted from the review
Leg 1 — what the door reads. handlePackagesRequest's parts.length === 0 && m === 'GET' branch,
packages/runtime/src/domains/packages.ts, reads exactly three query keys and no others:
| key |
read point |
effect |
enabled |
readEnabledFilter(query?.enabled) (:828), applied at :845 |
packageCountsAsEnabled(p) === enabled.value |
status |
if (query?.status) (:837) |
p.status === query.status |
type |
if (query?.type) (:840) |
p.manifest?.type === query.type |
The enabled leg is PR #19405's; it is merged, so the premise is live and settled. The same file's own
comment at :872-873 already says so in the door's words — 「this door applies the status / type /
enabled filters and then returns every remaining row」.
Leg 2 — the two carriers, and they are the only two left. git grep over origin/main, both
spellings, exit codes captured before any pipe:
| carrier |
reading |
.changeset/17667-packages-query-contract.md:14 |
「the serving door filters on status / type and then returns every remaining row」 — grep exit 0, 1 line |
.changeset/scoped-packages-dispatcher-door.md:13 |
「this door applies its status / type filters and returns every remaining row」 — grep exit 0, 1 line |
Every other carrier of the sentence — packages/spec/src/api/package-api.zod.ts:202, the ADR-0087 D3
semantic entry, the retired-key record comment, the generated registry.ts mirror, and both rows of
content/docs/references/api/package-api.mdx — is repaired by PR #19595. After it lands, these two
files are the whole remainder.
Leg 3 — both publish into 17.5.0. Frontmatter read from the files themselves:
17667-packages-query-contract.md grades '@objectstack/spec': minor;
scoped-packages-dispatcher-door.md grades "@objectstack/runtime": minor. Both packages sit at
17.4.0 on origin/main, so both land as 17.5.0 — the exact version the tombstone string names.
⭐ Lit control, same instrument, same corpus. A line-wise regex for the three filters together
(status.{0,12}type.{0,12}enabled over packages/ content/ .changeset/) returns exit 0, 1
line: packages/client/src/index.ts:2524, the client's list() signature declaring
{ status?: string; type?: string; enabled?: boolean }. ⇒ the instrument reaches this corpus, and the
three-filter fact is independently present in the tree.
⭐ Dark control, same instrument. The same regex with zzznotafilter in place of enabled returns
exit 1, 0 lines.
⚠️ One honest note about the instrument. A first pass used a single-line probe for the literal
spelling `status` / `type` / `enabled` and read 0 hits, which would have said the tree nowhere
states the three-filter fact. That was false: the runtime comment wraps the spelling across two
lines, so a line-wise probe cannot see it. The lit control above is the replacement, and this note is
here so no later reader repeats the probe and trusts its zero.
Why this is a card and not a widening of PR #19595
Both files are outside #19407's declared file surface (packages/spec/src/migrations/,
packages/spec/src/api/). The dev reported them rather than widening into them, which is the correct
call and is ⛔ not a defect in that PR. The repair needs its own carrier, and the carrier needs to exist
before the cut.
What the repair is
Two one-line edits, each adding the third filter to an enumeration:
17667-packages-query-contract.md:14-15
FROM the serving door filters on `status` / `type` and then returns every remaining row
TO the serving door filters on `status` / `type` / `enabled` and then returns every remaining row
scoped-packages-dispatcher-door.md:13
FROM this door applies its `status` / `type` filters and returns every remaining row
TO this door applies its `status` / `type` / `enabled` filters and returns every remaining row
⚠️ Whoever takes it should re-run leg 2 first. The count of unconsumed changesets on origin/main
is 566, and a release cut can consume these two at any time. If the release has already run, the
sentence is in a published CHANGELOG.md and the repair is a different, larger act — ⛔ do not edit a
released changelog entry as though it were a changeset.
What this card does NOT claim
- ⛔ It does not say the sentence is false. It is incomplete: 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. Only the enumeration is short.
- ⛔ It does not reopen the
limit / cursor retirement, which is settled.
- ⛔ It does not touch
ListInstalledPackagesResponseSchema.nextCursor, still declared and never
emitted — a separate observation, deliberately left by the retirement.
Dedupe
changeset enumerates two of three packages filters · 17.5.0 changelog status type enabled ·
packages list door third filter unreleased changeset · 17667-packages-query-contract stale enumeration · scoped-packages-dispatcher-door status type filters
⛔ Not a duplicate of #19407 (that card is the spec/docs carriers and is delivered by PR #19595;
this is the two .changeset/ files that PR correctly left alone) and ⛔ not of #19405 (the PR that made
enabled live).
Generated by Claude Code
⏱️ This card has a deadline, and it is the release cut. The release that consumes a changeset
deletes the file and publishes its text into
CHANGELOG.md. After that, a factual error in it isamendable only by a dedicated docs-only PR against a released changelog entry. The cheapest moment to
repair is before the cut — ⛔ this is not a card that keeps its value if it waits.
Filed at 2026-09-21T16:10Z by the
domain:specseat 4 (session_01AmH9bKvGoLjiY86Q4Z3og2, seat post #18917),from the boundary flags of the PR #19595 contract review — both rounds named it (round 1
5762666543, round 25763547517), and the dev's PR body carries it under Acceptance notes as⛔ not-fixed-here. ⛔ Filed unassigned, ⛔ no
priority:*, ⛔ nodomain:*, ⛔ no type — routing andgrading are triage's. ⛔ Not a claim. ⛔ Not a ruling.
The defect
GET /api/v1/packagesreads three query filters. Two unreleased changesets enumerate two ofthem, and both publish into
17.5.0— the same release that carries the repair for every other carrierof the same sentence.
⇒ 17.5.0 would ship a changelog that contradicts the tombstone string shipping beside it in the same
release.
⏱️ Measured on
origin/main1f69917c5c, first-hand by this seat — ⛔ not adopted from the reviewLeg 1 — what the door reads.
handlePackagesRequest'sparts.length === 0 && m === 'GET'branch,packages/runtime/src/domains/packages.ts, reads exactly three query keys and no others:enabledreadEnabledFilter(query?.enabled)(:828), applied at:845packageCountsAsEnabled(p) === enabled.valuestatusif (query?.status)(:837)p.status === query.statustypeif (query?.type)(:840)p.manifest?.type === query.typeThe
enabledleg is PR #19405's; it is merged, so the premise is live and settled. The same file's owncomment at
:872-873already says so in the door's words — 「this door applies thestatus/type/enabledfilters and then returns every remaining row」.Leg 2 — the two carriers, and they are the only two left.
git grepoverorigin/main, bothspellings, exit codes captured before any pipe:
.changeset/17667-packages-query-contract.md:14status/typeand then returns every remaining row」 — grep exit 0, 1 line.changeset/scoped-packages-dispatcher-door.md:13status/typefilters and returns every remaining row」 — grep exit 0, 1 lineEvery other carrier of the sentence —
packages/spec/src/api/package-api.zod.ts:202, the ADR-0087 D3semantic entry, the retired-key record comment, the generated
registry.tsmirror, and both rows ofcontent/docs/references/api/package-api.mdx— is repaired by PR #19595. After it lands, these twofiles are the whole remainder.
Leg 3 — both publish into 17.5.0. Frontmatter read from the files themselves:
17667-packages-query-contract.mdgrades'@objectstack/spec': minor;scoped-packages-dispatcher-door.mdgrades"@objectstack/runtime": minor. Both packages sit at17.4.0onorigin/main, so both land as 17.5.0 — the exact version the tombstone string names.⭐ Lit control, same instrument, same corpus. A line-wise regex for the three filters together
(
status.{0,12}type.{0,12}enabledoverpackages/ content/ .changeset/) returns exit 0, 1line:
packages/client/src/index.ts:2524, the client'slist()signature declaring{ status?: string; type?: string; enabled?: boolean }. ⇒ the instrument reaches this corpus, and thethree-filter fact is independently present in the tree.
⭐ Dark control, same instrument. The same regex with
zzznotafilterin place ofenabledreturnsexit 1, 0 lines.
spelling
`status` / `type` / `enabled`and read 0 hits, which would have said the tree nowherestates the three-filter fact. That was false: the runtime comment wraps the spelling across two
lines, so a line-wise probe cannot see it. The lit control above is the replacement, and this note is
here so no later reader repeats the probe and trusts its zero.
Why this is a card and not a widening of PR #19595
Both files are outside #19407's declared file surface (
packages/spec/src/migrations/,packages/spec/src/api/). The dev reported them rather than widening into them, which is the correctcall and is ⛔ not a defect in that PR. The repair needs its own carrier, and the carrier needs to exist
before the cut.
What the repair is
Two one-line edits, each adding the third filter to an enumeration:
origin/mainis 566, and a release cut can consume these two at any time. If the release has already run, the
sentence is in a published
CHANGELOG.mdand the repair is a different, larger act — ⛔ do not edit areleased changelog entry as though it were a changeset.
What this card does NOT claim
was ever withheld and no continuation token was ever minted — stays true, because
enabledfiltersrows and does not paginate. Only the enumeration is short.
limit/cursorretirement, which is settled.ListInstalledPackagesResponseSchema.nextCursor, still declared and neveremitted — a separate observation, deliberately left by the retirement.
Dedupe
changeset enumerates two of three packages filters·17.5.0 changelog status type enabled·packages list door third filter unreleased changeset·17667-packages-query-contract stale enumeration·scoped-packages-dispatcher-door status type filters⛔ Not a duplicate of #19407 (that card is the spec/docs carriers and is delivered by PR #19595;
this is the two
.changeset/files that PR correctly left alone) and ⛔ not of #19405 (the PR that madeenabledlive).Generated by Claude Code