Skip to content

docs(cli): state the per-package dedup bound the CLI actually holds in #18677 / #18778 pending changesets - #19531

Merged
os-project-manager merged 1 commit into
mainfrom
claude/issue-19245-retire-union-could-not-see-assertions
Sep 22, 2026
Merged

os-project-manager merged 1 commit into
mainfrom
claude/issue-19245-retire-union-could-not-see-assertions

Conversation

@os-project-manager

Copy link
Copy Markdown
Collaborator

Fixes #19245

Clause-②: no

Two pending, unreleased changesets each asserted the sentence packages/cli's own source now explicitly forbids restating, and each attributed it to that source. A changeset body ships verbatim into packages/cli/CHANGELOG.md, so this correction costs a diff today and a published falsehood after the release that consumes them. Prose only — two .changeset/*.md files, no code path changes, no export, no key, no accept set moved.

The two shas this diff is actually between: merge base eec56c37dfc89086658c1659bb2da869dfa08d4f (the tip of origin/main at branch time and at every measurement below) → head 2babd1876786eb135509df70ab4fc2ee0113a7f3. Verified with git merge-base origin/main HEAD, not assumed from the branch point.

1. The settled bound, read at the head this branch points at

⛔ No fourth phrasing was invented. Both replacement sentences are the tree's own, read from the two docblocks the card names:

packages/cli/src/commands/compile.ts:465-470

findingKey now neutralises the top-level collection index, so what survives is the set of per-package findings no union finding already carried under the same rule, where, message and non-top-level position. ⛔ Do not re-inflate that to "exactly the set the union could not see" — utils/artifact-packages.ts states the bound and why it is narrower than that sentence.

packages/cli/src/utils/artifact-packages.ts:237-244

What reaches the lists below is therefore the set of per-package findings whose rule, where, message and NON-top-level position no union finding already carried. ⚠️ That is the whole claim, and it is deliberately narrower than "exactly the set the union could not see" — ⛔ do not restate it as that sentence. Two entries rendering the same where still collapse (see findingKey) …

Both halves are carried into both entries: the bound, and the reason it is narrower (two entries rendering the same where still collapse). An amended note that stated the bound and dropped the caveat would be the same defect one notch smaller, so neither entry drops it.

⚠️ Deliberately, neither replacement reproduces the retired sentence verbatim, not even as the "narrower than" contrast the source uses. The source can quote it because the source is the thing that prohibits it; a release note quoting it would put the sentence back into CHANGELOG.md, which is the entire cost this card exists to avoid — and it would leave the population sweep in §3 reading 3 again.

2. What each entry now says

file before after
.changeset/18677-validate-per-package-authoring-pass.md:7 "By compile.ts' own description the survivors of that second pass are «exactly the set the union could not see», so that whole set was findings os build reported and os validate structurally could not." "By compile.ts' own description the survivors of that second pass are the per-package findings no union finding already carried under the same rule, where, message and non-top-level position — deliberately narrower than everything the union run missed, because two entries rendering the same where still collapse. That whole set was findings os build reported and os validate structurally could not."
.changeset/18778-lint-per-package-authoring-pass.md:10-13 "every finding that pass produces — «exactly the set the union could not see», in the build command's own words — was reported by the command that ships and invisible on the fastest of the three doors." "every finding that pass produces — in the build command's own words, the per-package findings no union finding already carried under the same rule, where, message and non-top-level position — was reported by the command that ships and invisible on the fastest of the three doors. That bound is deliberately narrower than everything the union run missed: two entries rendering the same where still collapse."

Both attributions are now accurate: compile.ts does say the replacement, in those words. The downstream conclusion each entry draws is untouched and still holds — a survivor is by construction something the union run did not report, so it remains a finding os build reported and the other door structurally could not. Only the size claimed for that set moves, which is exactly the correction #18779 landed in the code and did not reach these two notes.

One correction, not two. The two entries needed the same substantive change; only the sentence surgery differed, because one file is unwrapped prose and the other is hard-wrapped at 80 columns. Each file's own wrapping convention is preserved.

The **BREAKING** section PR #18867 just added to 18677-…md is not touched. The assertion sits at :7; that banner and its table occupy :22-29. git diff shows one changed line in that file.

3. The sweep over the whole .changeset/ population, with lit controls

⚠️ The first instrument was wrong and is reported rather than quietly replaced. Its normaliser collapsed \s+ only. That is enough for markdown, but inside a block comment the sentence's line wrap carries a * continuation marker, so a bare \s+ bridge does not join "exactly the to set the union could not see". On the tree scan in §4 it silently undercounted 13 → 11. The corrected normaliser strips each line's comment-continuation prefix (*, //, #) before collapsing whitespace. Every number below is from the corrected instrument; both are kept in the report.

Whole population, whitespace-normalised, case-insensitive, every hit opened:

run population lit control needle
.changeset/ @ origin/main eec56c37df (before) 554 files superset "the union could not see" → 3 occurrences, INSTRUMENT LIT 3
.changeset/ @ head 2babd18767 (after) 554 files superset → 1, INSTRUMENT LIT 1

The three before, each opened, ⛔ not counted:

  1. 18677-…md:7 — assertion, attributed to compile.tscorrected here
  2. 18778-…md:11 — assertion, attributed to the build command → corrected here
  3. 18779-…md:52"Also corrected: the sentence «…», which was false for as long as the key was positional"quoted correction, untouched

The one after is row 3. ✅ The only surviving hit in the whole population is 18779's quoted correction, which is what the claim comment asked to be shown rather than trusted.

⚠️ A note on the population figure: the card recorded 482 changesets at 847e5773a. At eec56c37df it is 554. The tree moved; the count is re-measured here, ⛔ not inherited. The needle count is unchanged at 3, which is the number that matters.

⚠️ A second lit control was run on the before-sweep and is recorded because a zero is not a reading until a control hits: the distinctive string position-insensitive, not collision-proof returned exactly 1 file (18779-…md), confirming the loop was reading real bytes at real paths — the failure mode the card records (a loop that double-prefixed .changeset/ and returned a wholly convincing 0).

4. .changeset/18779-…md is untouched, and this PR makes its completeness claim true

18779-…md:55-56 claims the sentence "is now stated at the bound the pass can actually hold, in every file that carried it". That claim was false on origin/main, falsified by the two rows above. It is true at this head. Measured over the whole tree, not just .changeset/ — 9128 tracked text files at head, corrected normaliser, lit control 15 occurrences of the superset in 10 files:

13 occurrences in 10 files, every one opened and classified. Zero are assertions.

site class
.changeset/18779-per-package-dedup-positional-key.md quoted correction
packages/cli/src/commands/compile.ts ×2 1 quoted correction ("used to end … and that was FALSE"), 1 prohibition ("⛔ Do not re-inflate that to")
packages/cli/src/utils/artifact-packages.ts ×3 1 "narrower than" contrast (:101), 1 historical account that names #18677 and #18778 by number as the two that quoted it, 1 prohibition ("⛔ do not restate it as that sentence")
packages/cli/src/commands/lint.ts quoted correction
packages/cli/src/commands/validate.ts quoted correction
packages/cli/test/{lint,validate}-per-package-authoring-{parity,seam}.test.ts ×4 quoted corrections
packages/cli/test/per-package-dedup-positional-echo.test.ts quoted correction

⇒ Nothing in the tree still asserts the sentence. Editing 18779-…md would be a no-op that spends a third file on the serial. ⛔ Left alone, exactly as ordered.

5. ⭐ The written confirmation Check Changeset route 0 asks for — and why that check stays red

node scripts/check-empty-changeset.mjs --base origin/main exits 1 here, and that is by design, ⛔ not a defect and ⛔ not a finding about the gate. The route-0 discriminator .github/workflows/pr-automation.yml prescribes was run rather than reasoned about:

$ git merge-base origin/main HEAD
eec56c37dfc89086658c1659bb2da869dfa08d4f
$ git diff --name-status eec56c37df HEAD -- '.changeset/*.md'
M	.changeset/18677-validate-per-package-authoring-pass.md
M	.changeset/18778-lint-per-package-authoring-pass.md

Every row is M, none is A ⇒ the DELIBERATE CORRECTION class. The workflow's own instruction for it, verbatim:

-> do NOT apply 'skip-changeset'. Write the confirmation on the PR -- name the note and what changed under it, and get it confirmed there in writing -- and LEAVE THIS CHECK RED.
… Ruled on #18375 (ruling D, maintainer 2026-09-18): the 'skip-changeset' label is never applied to a PR that edits an existing changeset.

So, saying it, as the gate asks:

⚠️ This PR carries no label, and the red is expected on CI. Step 11 of changeset-check ("Require a changeset (or the skip-changeset label)") fails first — this PR adds no changeset of its own — which short-circuits the job, so the foreign-changeset refusal above never executes on CI at all. Check Changeset is not a required context, so its red blocks no merge and an approver merges over it. ⭐ Measured on the adjacent precedent rather than recalled: PR #18867's head 1056c00195 shows Check Changeset = failure on both runs, its final label set is documentation, size/s, tooling with no skip-changeset, and it merged. The route-0 block and ruling D are present in pr-automation.yml at #18867's own merge commit 03008c7e1a, so that ruling is not newer than the precedent.

6. Verification

All 19 commands derived for this surface, re-derived at this head — node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, which reported --repo … checked against this checkout's 'origin' remote — it holds, change set 2 path(s) vs merge base eec56c37d, and emitted exactly the 19 the dispatch named. Exit codes captured by redirecting first (⛔ never through a pipe).

# command exit
1 node scripts/check-adr-0087-registration.mjs --base origin/main 0
2 node scripts/check-adr-0087-registration.mjs --self-test 0
3 node scripts/check-changeset-no-major.mjs --base origin/main 0
4 node scripts/check-changeset-no-major.mjs --self-test 0
5 node scripts/check-closing-keyword-parity.mjs 0
6 node scripts/check-closing-keyword-parity.mjs --self-test 0
7 node scripts/check-comment-mask-corpus.mjs 0
8 node scripts/check-empty-changeset.mjs --base origin/main 1 — by design, §5
9 node scripts/check-empty-changeset.mjs --self-test 0
10 node scripts/pm/release-rehearsal-clone.mjs --self-test 0
11 pnpm check:changeset-gate-self-tests 0
12 pnpm check:driver-memory-census 0
13 pnpm check:gitlink-declared 0
14 pnpm check:nul-bytes 0
15 pnpm check:objectui-changeset 0
16 pnpm check:pm-changeset-deadline-census 0
17 pnpm check:published-files 0
18 pnpm check:refd-timer-probe 0
19 pnpm check:watch-hint-literal 0

Gate 8's refusal names both files and the DELIBERATE CORRECTION class; §5 is its remedy. Gate 1 reads .changeset/18677-…md [BREAKING] not-required (no-migration-prescription) — the disposition PR #18867 added survives this edit intact.

Beyond the 19, run because the derivation refuses to call their silence a clearance:

what result
node scripts/check-changeset-fixed.mjs — flagged ⛔ by the derivation, "roster under .changeset, which one of your paths is in" exit 0 — config fixed group in sync with 70 public packages
pnpm check:pm-governed-prose exit 0 — and it names the 6 governed surfaces (docs/adr/** · .claude/** · skills/** · AGENTS.md · CLAUDE.md · docs/NORTH-STAR.md). .changeset/** is not among them, so no governed-surface obligations attach to this diff
pnpm lint — whole repo, eslint . --no-inline-config, ⛔ not narrowed, so no narrowing argument is owed exit 0 at 2babd18767
control characters — grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]' over both changed files no hits (grep exit 1)

No package test or typecheck is owed and none is claimed. The diff touches no package source, no exports, no spec contract, no built artefact and no test. turbo's affected set is empty of packages for a .changeset/*.md edit; that is stated as "not owed", ⛔ not as "green".

No changeset is owed for this PR. It declares no release of its own — route 0 above is the discriminator, and it also forbids the skip-changeset label that would otherwise declare that in writing.

No label is written by this PR, as ordered, and the order is independently correct: ruling D forbids skip-changeset on exactly this class.

7. Where this PR's reading differs from the dispatch order

⭐ Reported rather than silently accommodated, per the order's own instruction.

  • Clause-②: no is declared above exactly as the seat declared it, and this PR's reading of the finished diff agrees: prose in two unreleased notes, no export, no key, no member, no registration, no accept set moved in either direction.
  • ⚠️ The order's label reasoning is right and its prediction is wrong. "Write no labels" is correct — ruling D forbids skip-changeset here by name. But "⇒ your round needs no label to go green" does not hold: PR docs(cli): #18769's pending changeset declares the os validate --strict narrowing an at-tier review exhibited #18867, the precedent cited for it, went red on Check Changeset and was merged over, as measured in §5. This round will be red too, and ⛔ that red is not "a real finding about the gate" — it is the gate's documented behaviour for this class, and §5 is the prose-and-person remedy it prescribes.
  • Nothing else in the order needed refusing. The settled bound fits both sentences; 18677's **BREAKING** section is untouched; the two entries needed one correction, not two.

Boundaries — what this PR deliberately does not do

  • ⛔ It does not touch .changeset/18779-per-package-dedup-positional-key.md. §4 shows why that would be a no-op.
  • ⛔ It does not touch packages/cli/src/**, any test, content/docs/releases/, or any packages/*/CHANGELOG.md.
  • ⛔ It does not add or change a Clause-②: line inside either changeset body. 18778-…md carries Clause-②: yes (narrowing) at :36; that is a landed declaration about its own release and ⛔ not this card's to re-grade.
  • ⛔ It writes no label, and it did not route around that anywhere.

Acceptance notes

  • Noted, not filed: .changeset/18677-…md:9-16 pins a measurement to origin/main 09e16a574os build --json warnings: 4 against os validate --json warnings: 3 — and [finding] the per-package de-duplication key is POSITIONAL, so echoes survive it — and compile.ts's own comment that the survivors are "exactly the set the union could not see" overstates what it keeps #18779 has since moved that fixture's build count from 4 to 3. It is ⛔ not a defect: the reading is explicitly bound to a named sha, it was true there, and 18779-…md:19-24 publishes the 4→3 move in the same release, so a CHANGELOG reader gets both. Rewriting a correctly-dated historical measurement would be the larger error. Carrier: none — no PR is in flight on that file and none is predicted; recorded here because the "somebody will touch this anyway" fallback ⛔ does not hold for .changeset/*.
  • Noted, not filed: the first sweep instrument used for §4 undercounted the tree scan 13 → 11 by collapsing \s+ without first stripping block-comment continuation markers. That is a fact about a throwaway script in this session, ⛔ not about any tracked file — no gate, helper or committed tool has the defect. It is written down because the card's own history records the opposite failure of the same instrument class (a convincing 0), and the pair is the argument for the lit control. Carrier: none; nothing in the repo carries this code.

Generated by Claude Code

…#18677 / #18778's pending changesets

Both entries asserted "exactly the set the union could not see" and attributed
it to source text that now explicitly forbids restating it
(packages/cli/src/commands/compile.ts:457-470 and
packages/cli/src/utils/artifact-packages.ts:236-246). A changeset body ships
verbatim into packages/cli/CHANGELOG.md, and both entries are still pending, so
the correction costs a diff today and a published falsehood after the next
release.

Each now states the settled bound in the source's own words -- the per-package
findings no union finding already carried under the same rule, `where`, message
and non-top-level position -- together with the narrowness caveat those
docblocks give for it: two entries rendering the same `where` still collapse.

Prose only; no code path changes.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QCdUBjM47SxioST9z5Zwdf

Copy link
Copy Markdown
Collaborator Author

Check Changeset is red by design here — ⛔ not a fix this PR can push

domain:cli execution PM seat #6024 · session session_01QCdUBjM47SxioST9z5Zwdf · read 2026-09-21T07:34Z at head 2babd1876786eb135509df70ab4fc2ee0113a7f3

What is failing: Check Changeset — the only red. Everything else on this head is clean: RUNS latest-per-name 25, of which 14 success · 8 skipped · 2 still running · this 1 failure.

Why it is not this PR's to fix. The route-0 discriminator was run, ⛔ not reasoned about — git diff --name-status eec56c37df HEAD -- '.changeset/*.md' returns two M rows and no A row, which is the DELIBERATE CORRECTION class. .github/workflows/pr-automation.yml:841 prescribes, for exactly that class: ⛔ no skip-changeset, write the confirmation on the PR naming the note and what changed under it, and 「leave this check red」. §5 of the body is that confirmation.

No remedy is being withheld. The three candidate moves are all refused, by name:

Measured on the adjacent precedent, ⛔ not recalled: PR #18867 edited one of these same two files, showed Check Changeset = failure at its merged head 1056c001953497cb83bba50debd6f4784c0d962a, carried documentation, size/s, tooling with no skip-changeset, and merged over the red. ⚠️ This seat's own dispatch order got that precedent half-wrong — it read the label set and inferred a green — and the dev refused the reasoning; recorded as order error #12 on #19245 (5756976899).

What it waits on: a person's word that .changeset/18677-validate-per-package-authoring-pass.md and .changeset/18778-lint-per-package-authoring-pass.md may be corrected in place, plus the per-head waiver of landing pre-check ③ for Check Changeset only — the shape ruling batch #200 item 2 took for PR #18867. Card #19245 is needs-user-decision; this PR stays draft until then. ⛔ This seat will not re-run the check (a re-run cannot change a by-design verdict) and ⛔ will not self-waive the pre-check.


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

Maintainer confirmation received — the route-0 written confirmation this class requires

domain:cli execution PM seat #6024 · session session_01QCdUBjM47SxioST9z5Zwdf · written 2026-09-22T01:58Z against head 2babd1876786eb135509df70ab4fc2ee0113a7f3

.github/workflows/pr-automation.yml:841 asks, for a PR whose only .changeset/*.md rows are M, that the confirmation be written on the PR — naming the note and what changed under it — and that the check be left red. Record 5756982768 above is the standing-down half. This is the confirmation half.

1. The notes, and what changed under each

Both files are somebody else's pending release notes. Neither is this PR's own release; this PR adds no changeset of its own.

  • .changeset/18677-validate-per-package-authoring-pass.md (+1 / −1, line 7) — the sentence describing what os build's second authoring pass yields. It asserted the survivors are "exactly the set the union could not see". Corrected to: the per-package findings no union finding already carried under the same rule, where, message and non-top-level position — deliberately narrower than everything the union run missed, because two entries rendering the same where still collapse.
  • .changeset/18778-lint-per-package-authoring-pass.md (+6 / −3, line 11) — the same claim, restated as a quotation of the build command's own words. Corrected to the same bound, with the narrowing stated explicitly.

Nothing else moves: GET /pulls/19531/files returns exactly these two paths, +7 / −4, 11 changed lines. check-governed-merges.mjs --pr 19531 reads 0 of 2 paths governed, so ordinary queue landing applies.

⚠️ .changeset/18779-per-package-dedup-positional-key.md:52 states the same bound correctly already and is deliberately not touched.

2. The confirmation, quoted rather than paraphrased

Given by the maintainer in session on 2026-09-22, in answer to this seat's naming of the two notes and the pre-check:

确认这两处更正,豁免 Check Changeset 的预检③

Two acts, and both were needed: (a) the notes may be corrected in place, and (b) landing pre-check ③ is waived for Check Changeset only, at this head. ⛔ This seat did not self-waive ③, and ⛔ did not carry the batch #200 item 2 ruling over from PR #18867 — that ruling is per-correction, so it never reached this PR.

3. The three red-with-enqueue conditions, each measured on this head

condition reading
the source itself says the red is by design on pushed branches pr-automation.yml:729-730 — 「The red is the point, and it costs nothing: Check Changeset is not one of the required contexts, so its red blocks no merge」
the check does not run on merge_group on: pull_request with types [opened, synchronize, reopened, labeled, unlabeled, edited]; grep -c merge_group over the whole file = 0, so the queue never re-runs it
a PR comment records the gate and the reason 5756982768 plus this comment

CI on 2babd1876786eb135509df70ab4fc2ee0113a7f3, all three layers read this act rather than recalled:

  • ① RUNS latest-per-name (the gate): 26 = 17 success · 8 skipped · 1 failureCheck Changeset, run 106248779978, red since 2026-09-21T07:30:10Z.
  • ② SUITES (what a human sees): 14 = 8 success · 1 skipped · 1 failure · 4 queued with 0 runsvercel, fly-io, claude, cloudflare-workers-and-pages, created 2026-09-21T07:15:58Z with updated == created; they never started, and none of them has produced a check run to judge.
  • ③ legacy combined status: success (Vercel only).

Stated rather than assumed: GET /repos/objectstack-ai/objectstack/branches/main/protection answers 403 Resource not accessible by integration to this seat. So whether any of those four never-started suites is a required context is unmeasured, and this comment does not claim the PR is otherwise unblocked — only that the one red is the by-design one, and that the queue will not see it.

4. What this seat does next

Pre-check ① is not owed (Clause-②: no on both limbs, lane domain:cli, and the diff touches no contract face); pre-check ② reads --pair 19531 exit 0; pre-check ③ is waived above for Check Changeset only. So: flip out of draft, enqueue through the merge queue, and confirm MERGED by content on origin/main. ⛔ No direct merge, ⛔ no queue bypass, and ⛔ no skip-changeset label — ruling D on #18375 stands.


Generated by Claude Code

@os-project-manager
os-project-manager marked this pull request as ready for review September 22, 2026 01:59

Copy link
Copy Markdown
Collaborator Author

Correction to §2 of 5770146936 — only ONE of the two acts was a person's to give

domain:cli execution PM seat #6024 · session session_01QCdUBjM47SxioST9z5Zwdf · written 2026-09-22T02:02Z against head 2babd1876786eb135509df70ab4fc2ee0113a7f3

That comment says of the maintainer's two acts: 「Two acts, and both were needed」. ⛔ That is wrong on the second one, and it is wrong in the direction that manufactures a precedent, so it is corrected here rather than left to be read by the next seat.

What is actually true. Landing pre-check ③ (references/contract-review.md:42) reads 「③ PR check 全绿,⛔ 非 required 子集;例外:merge-base 同签名的红不计、按设计而红见 SKILL.md」. That carve-out is not a discretionary one: SKILL.md:629-631 spells it out as three measurable conditions — 「源码自述 pushed 分支上按设计而红、不跑 merge_group、PR 评论记明门与因,缺一即否」 — scoped to 「本循环派发的 dev PR」, which this PR is.

All three already held before the maintainer was asked, and §3 of 5770146936 is the measurement that shows it: the source says so at pr-automation.yml:729-730, grep -c merge_group over that file is 0, and comment 5756982768 had recorded the gate and the reason since 2026-09-21T07:34Z. ⇒ the pre-check ③ waiver was this seat's to derive from the instrument, ⛔ not a person's to grant. It was asked for anyway.

What genuinely was a person's. The route-0 confirmation itself — pr-automation.yml:841 asks that the correction to somebody else's pending release note 「get it confirmed there in writing」. ⛔ No measurement answers that; it is a decision about somebody else's release. So a person was needed, and the PR could not have landed without one. Only the second reason given for needing them was manufactured.

Nothing about the landing changes, and nothing is re-litigated: the confirmation stands, the three conditions stand as measured, and this PR proceeds to the queue exactly as §4 of 5770146936 describes. What changes is the precedent this thread leaves behind: ⛔ a route-0 correction does not require a per-head pre-check ③ waiver from a maintainer — it requires the written content confirmation, plus the three conditions being true.

Recorded as this shift's order error #16 on card #19245. It is the same pattern as #12 and #15asserting a rule instead of running the instrument that decides it — this time in the asking direction: the seat escalated a question the checked-in rules already answered.


Generated by Claude Code

@os-project-manager
os-project-manager added this pull request to the merge queue Sep 22, 2026
Merged via the queue into main with commit 6ffccc5 Sep 22, 2026
27 of 28 checks passed
@os-project-manager
os-project-manager deleted the claude/issue-19245-retire-union-could-not-see-assertions branch September 22, 2026 02:20
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/s tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[finding] two pending changesets still assert the per-package dedup sentence the CLI source forbids restating, and ship it to CHANGELOG

2 participants