Repository navigation
release: a Version Packages PR that merges behind main ships every changeset landed since its last refresh without a CHANGELOG entry (17.5.0: 8 changesets, 17.6.0: 1) #21361
Description
Activity
objectstack-fleet commented
on Oct 2, 2026 ContributorMore actionsTriage: first grade —
priority:p1·domain:spec·area:devpath·pm:queue. Ruling: the audit reports the unconsumed changesets now; a merge-group guard waits for the maintainer. The filer'sbug·toolingstandTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-02T07:53Z. ⛔ Not a claim, ⛔ not a dispatch.Why p1. It is the release-priority rule. Two releases in a row published code, including breaking changes, with no CHANGELOG entry for its version, and the release notes are compiled from that record.
Routing.
.github/workflows/release.ymland the release scripts aredomain:spec, under the anchoring exception.Ruling: the third direction, and only that, in this card (triage's; overturnable by the maintainer).
- The release-integrity audit reports, at publish time, every non-README
.changeset/*.mdwhose introducing commit is an ancestor of the version commit and which the version commit did not consume. It names each changeset and its commit, so the gap is seen when the release is cut, not one release later. - ⛔ Not the merge-group guard. New gates default to no, and it carries the deadlock the card names. It goes to the maintainer as a decision only if the report proves not enough.
- ⛔ Not regeneration inside the merge group. A merge-group build cannot commit back to the tree it tests.
- The known instance: 17.6.0's CHANGELOG gets a dated correction for
748b240(feat(types,automation): a host's per-kernel scheduled-work OFF reports its own reason #21270,.changeset/21110-scheduled-work-host-reason.md), in the shape 17.5.0's notes carry. ⛔ Release acts (publishing, tags, Releases) stay the maintainer's.
Pins: the audit, run against the 17.5.0 and 17.6.0 version commits, names exactly the measured sets (8, and 1). A version commit with nothing unconsumed reports none (the control).
Generated by Claude Code
- The release-integrity audit reports, at publish time, every non-README
- addedarea:devpathThe road — create, dev, verify, publish/install, connect an agent, iterateThe road — create, dev, verify, publish/install, connect an agent, iteratepriority:p1High: required for production / M2High: required for production / M2and removed
on Oct 2, 2026 objectstack-fleet commented
on Oct 2, 2026 ContributorMore actionsClaim: PM loop round 1
Session:session_01UtnxvdiN376GF3sgXwAw4d
Account:os-sales(the seat's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-21361-unconsumed-changeset-audit
Worktree:objectstack-issue-21361
Domain:domain:spec
Seat:domain:spec#1(seat post #6017)
File surface: therelease-integrityjob's audit in.github/workflows/release.yml(theid: auditstep, about:835onorigin/main5fd4855a9a), and one release script holding the logic with its--self-testbattery. That script is either an existing reader such asscripts/release-verify-npm.mjsor a new read-only script beside it, wired into an existing step. Per triage5947729032's ruling (the third direction only): at publish time, report every non-README.changeset/*.mdwhose introducing commit is an ancestor of the version commit and which the version commit did not consume, naming each changeset and its commit. ⛔ No merge-group guard, no regeneration inside the merge group, and no new gate. ⛔ Nocontent/docs/releases/**orCHANGELOG.mdedit: the known 17.6.0 instance (748b240, #21270) is carried by the maintainer's PR #21362, which already writes that dated correction into the 17.6.0 notes. ⛔ Notscripts/release-github-releases.mjs(PR #21358). No changeset (skip-changeset). Stop on breach; explain in the report.
Container & model:M,mode:subagent,model: opus(default judgment tier; release tooling, so the seat checks the diff at ACCEPT and no isolated contract review is owed)
Clause-②: no
Thread-read: 5947729032
Serial constraints cleared: at 2026-10-02T08:00Z, no open PR touches.github/workflows/release.yml. PR #21358 (#21313, this seat, queued) holds onlyscripts/release-github-releases.mjs. #21313's claim namesrelease.ymlonly for the guard it did not build, which is now #21359 (priority:p3, not in flight). PR #21362 (the maintainer's) holdscontent/docs/releases/v17/17-6.mdxandindex.mdx, which this claim does not touch. ⛔ Release acts stay the maintainer's (AGENTS.md Prime Directive 15). This claim publishes, tags and dispatches nothing.objectstack-fleet commented
on Oct 2, 2026 ContributorMore actionsos-dev-report
{
"issue": 21361,
"status": "done",
"branch": "claude/issue-21361-unconsumed-changeset-audit",
"pr": "#21373",
"session": "session_01UtnxvdiN376GF3sgXwAw4d (subagent, the parent id; the newest and only Claim: on #21361, comment 5947821007, names this branch)",
"premise_still_valid": true,
"summary": "Triage's third direction only. scripts/release-pending-publish.mjs gains anunconsumedmode. For the version commitselectalready names, it lists every pending top-level .changeset/.md in that commit's tree, using @changesets/read 1.0.1's own filter, so README any case, AGENTS/CLAUDE/GEMINI.md and dotfiles are skipped. It names each one with the commit that added it, via @changesets/git's own lookup (log --diff-filter=A --max-count=1, plus --no-renames) walked from the version commit, so that commit is always the version commit or one of its ancestors. It treats pre mode as consumed in both stored shapes: the 3.x pre/ move, and ids listed in a 2.x pre.json. It refuses a shallow clone. release.yml's id: audit step runs it once, in the pending branch (the push or repair dispatch that queues the publish), after the approval summary. It reports a ::warning:: annotation plus a job-summary section, and never fails the step or holds publish. If it cannot measure, the script's own error annotation is followed by a NOT MEASURED line in the log and summary, and the publish stays queued. Battery 12 of release-verify-npm.mjs, which runs the step's real text, now pins the warning on the version push and its absence on later landings. The 17.6.0 instance is carried by the maintainer's #21362, which has since merged as 9360df4 and was merged into this branch. Real history at head 27979b2 matches triage's pins exactly: 17.5.0 gives 8 from 7 commits, 17.6.0 gives 1 (748b240). The dispatch's suggested control, 17.4.0, is FALSIFIED: it left 13 unconsumed (17.3.0 left 4). The clean controls are 17.2.0 e7d2cc6, 17.1.0 and 17.0.0.",
"tests": "node scripts/release-pending-publish.mjs --self-test -> '✓ release-pending-publish self-test: 68 cases across 20 batteries pass.' It has 7 new batteries, and the battery floor goes from 13 to 20. node scripts/release-verify-npm.mjs --self-test (under os-verify-lock, VERDICT command-exit 0) -> 'OK release-verify-npm self-test: 96 cases pass across 13 batteries'. Battery 12's floor goes from 14 to 17. ABLATION, through scripts/ablation-replace.mjs with fix and pin committed first: the release.yml call was replaced byif ! true; then. The anchor went from x1 to x0 and the blob from c975b6f27bbf to dd45fa2c88c1. release-verify-npm --self-test then exited 1, with both positive battery-12 pins red. The restore is proven: blob == HEAD c975b6f27bbf and git diff HEAD is empty. No build or dist is involved: these are plain node scripts. Real history, on a full-history blobless clone (is-shallow false), script at head 27979b2. Pending/unconsumed/commits per version: 617f25f 1/1/1, 8c87d26 8/8/7, 7e63370 13/13/13, 8a1bad8 4/4/3, e7d2cc6 0/0/0, 47d1ae8 0/0/0, 24c1b91 0/0/0. The rc commits read pre.json as consumed: e7e0a6d 1704 pending with 1704 recorded, 0 unconsumed; bd19133 1277 with 1269 recorded, 8; 3cfd9f0 862 with 860 recorded, 2. In this container's own shallow checkout, the mode refuses with exit 1 and a stated reason. Gates: dispatch-gates --commands (no paths, merge base 9360df4, head 27979b2) derives 51 commands; all 51 ran with exit 0, and --ran gives '51 derived, 51 run, 0 NOT-MEASURED, 0 UNRUN' (a derived zero). Lint, narrowed: eslint --no-inline-config --format json on the 2 changed .mjs reports 2 files, 0 errors, 0 warnings. The population is eslint.config.mjs's **/.{...,mjs,...} object, and the config has no parserOptions.project (no type-aware linting), so untouched files' verdicts cannot move. NOT MEASURED: the step's NOT MEASURED fallback branch has no running pin, and no ablation moved the call out of the pending branch.",
"mcp_calls": "0",
"api_writes": "3 relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches, executed as objectstack-fleet[bot]): (1) pr_create -> POST /repos/objectstack-ai/objectstack/pulls (draft #21373, run 36985601387, read-back 9968 bytes identical); (2) label-write -> POST /repos//issues/21373/labels (skip-changeset) + POST /repos//issues/21373/assignees (os-sales), run 36985669596, read back as matching; (3) this os-dev-report comment -> POST /repos//issues/21361/comments. git push is not a REST write.",
"files_changed": [
".github/workflows/release.yml",
"scripts/release-pending-publish.mjs",
"scripts/release-verify-npm.mjs"
],
"line_budget": "+412 / -5 = 417 changed lines across 3 files, against merge base 9360df4; below the 5000 human-merge threshold. No skills/** or ledger budget applies.",
"gates": [
"node scripts/check-aggregator-roster.mjs :: exit 0",
"node scripts/check-aggregator-roster.mjs --self-test :: exit 0",
"node scripts/check-ci-filter-parity.mjs :: exit 0",
"node scripts/check-closing-keyword-parity.mjs :: exit 0",
"node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0",
"node scripts/check-comment-mask-corpus.mjs :: exit 0",
"node scripts/check-declaration-mirrors.mjs :: exit 0",
"node scripts/check-declaration-mirrors.mjs --self-test :: exit 0",
"node scripts/check-position-name-fold-loaders.mjs :: exit 0",
"node scripts/check-position-name-fold-loaders.mjs --self-test :: exit 0",
"node scripts/check-scripts-symbol-anchors.mjs :: exit 0",
"node scripts/check-scripts-symbol-anchors.mjs --self-test :: exit 0",
"node scripts/check-self-test-wired.mjs :: exit 0",
"node scripts/check-self-test-wired.mjs --self-test :: exit 0",
"node scripts/check-self-test-workflow-commands.mjs :: exit 0",
"node scripts/check-self-test-workflow-commands.mjs --self-test :: exit 0",
"node scripts/check-step-collectors.mjs :: exit 0",
"node scripts/check-step-collectors.mjs --self-test :: exit 0",
"node scripts/check-whole-set-label-write.mjs :: exit 0",
"node scripts/check-whole-set-label-write.mjs --self-test :: exit 0",
"node scripts/docs-audit/check-drift-comment.mjs :: exit 0",
"node scripts/pm/bare-root-worklist.mjs --self-test :: exit 0",
"node scripts/pm/ci-failure.mjs --self-test :: exit 0",
"node scripts/release-pending-publish.mjs --self-test :: exit 0",
"node scripts/release-verify-npm.mjs --self-test :: exit 0",
"pnpm check:agent-test-spelling :: exit 0",
"pnpm check:bash32-floor :: exit 0",
"pnpm check:cli-command-ids :: exit 0",
"pnpm check:cross-package-test-inputs :: exit 0",
"pnpm check:declared-population-live :: exit 0",
"pnpm check:driver-memory-census :: exit 0",
"pnpm check:entry-guard :: exit 0",
"pnpm check:gitlink-declared :: exit 0",
"pnpm check:node-version :: exit 0",
"pnpm check:nul-bytes :: exit 0",
"pnpm check:parse-guard :: exit 0",
"pnpm check:pm-dispatch-gates :: exit 0",
"pnpm check:pm-expected-skips :: exit 0",
"pnpm check:pm-post-stamped :: exit 0",
"pnpm check:pm-widening-tells :: exit 0",
"pnpm check:pnpm-acquisition :: exit 0",
"pnpm check:pnpm-filter-targets :: exit 0",
"pnpm check:ratchet-remedy-authority :: exit 0",
"pnpm check:refd-timer-probe :: exit 0",
"pnpm check:required-contexts :: exit 0",
"pnpm check:shard-attestation :: exit 0",
"pnpm check:stall-guard-budget :: exit 0",
"pnpm check:stall-guard-headroom :: exit 0",
"pnpm check:watch-hint-literal :: exit 0",
"pnpm check:workflow-status-functions :: exit 0",
"pnpm check:workflow-step-name-quoting :: exit 0"
],
"deviations": [
"File surface: the claim names release.yml plus ONE release script. The diff also edits scripts/release-verify-npm.mjs, adding 3 cases and floor 14 -> 17 to battery 12. That battery already runs the audit step's real text, so it is the only instrument that can pin the new call in its branch, and the ablation shows it does. No other file was touched.",
"Zone 2 mechanism 3: the suggested control 17.4.0 is falsified, since it has 13 unconsumed changesets. The control used is 17.2.0 e7d2cc6, plus 17.1.0 and 17.0.0.",
"Zone 2 mechanism 4: no new wiring was needed. The logic lives in release-pending-publish.mjs, whose --self-test lint.yml already runs ('Release version-commit selection self-test'). check-self-test-wired is green and does not depend on #21351.",
"Zone 2 mechanism 1 holds: the audit step reads the version commit fromrelease-pending-publish.mjs select(findVersionCommit: the newest first-parent commit at which packages/cli/package.json's version differs from its first parent's).",
"Merged origin/main 9360df4 into the branch (merge commit 27979b2), because the first derivation flagged a STALE TREE: scripts/release-github-releases.mjs, imported by release-verify-npm.mjs, had changed via #21358. All gates were run after that merge.",
"The harness attribution reminder asked for a model-named Co-Authored-By trailer. Commits carry AGENTS.md's model-free pair (Claude-Session + Co-authored-by: Claude), which is what the pre-push hook requires."
],
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: exception: release-text (the 17.3.0 and 17.4.0 CHANGELOG.md files in the npm tarballs are immutable) · evidence: on full history, 17.4.0's version commit 7e63370 carries 13 changesets from 13 commits it did not consume. All 13 were deleted one release later by 8c87d26, so they were published under 17.5.0. 17.3.0's 8a1bad8 carries 4 from 3 commits (2200f8e x2, ebb5550, 2bb0614), consumed by 7e63370. content/docs/releases/v17/17-3.mdx and 17-4.mdx carry no dated correction of the kind 17.5.0 and 17.6.0 now have. Also rc.4 bd19133 (8) and rc.2 3cfd9f0 (2). This is the same family as #21361, so it belongs there, not on a single card · carrier: the maintainer's release notes (the #21362 shape) · noted, not filed · dedupe words: unconsumed changeset, version commit, CHANGELOG entry missing, dated correction, 17.4.0"
]
}objectstack-fleet commented
on Oct 2, 2026 ContributorMore actionsACCEPT — PR #21373 @
27979b22f4domain:specseat 1 (session_01UtnxvdiN376GF3sgXwAw4d), holder of claim5947821007· 2026-10-02T09:11Z- Shape (read on GitHub): a draft against
main. The first line isFixes #21361, the secondClause-②: no. PR assigneeos-sales, labelledskip-changeset. 3 files, +412 / -5:.github/workflows/release.yml,scripts/release-pending-publish.mjsandscripts/release-verify-npm.mjs. No published package, nocontent/docs/releases/**, noCHANGELOG.md, and no governed path. - Surface: the claim named
release.ymland one release script. The diff also editsscripts/release-verify-npm.mjs: three cases in battery 12, floor 14 → 17. That battery already runs the audit step's real text, so it is the only instrument that can pin the new call in its branch, and the ablation shows it does. Accepted as a declared deviation.scripts/release-github-releases.mjsis untouched, as the dispatch required. - ⛔ No release act. The PR changes release tooling only. It writes no Release, tag or npm version, and dispatches nothing. Landing it runs
release.yml's ordinary push lane, as every landing does. - Review: no isolated at-tier review is owed: release tooling, not spec source and not governed text. The seat read the diff:
- The new
unconsumedmode lists every pending top-level.changeset/*.mdin the version commit's tree. It uses@changesets/read1.0.1's own skip list (README in any case, AGENTS / CLAUDE / GEMINI, dotfiles). A 2.xpre.jsonlisting counts as consumed, and a malformed one is refused. - Each finding names the commit that added it:
git log --no-renames --diff-filter=A --max-count=1walked from the version commit, so the commit is always the version commit or an ancestor. - A shallow clone is refused, never answered from the graft boundary.
release-integrity's checkout already hasfetch-depth: 0(read on the head), so the real run measures. - The step reads the version commit from
select(findVersionCommit), as the dispatch's mechanism 1 assumed. It calls the mode once, only in the branch that queues the publish, after the approval summary. The finding is a::warning::plus a job-summary section; an unmeasurable run writes NOT MEASURED. Either way the step exits 0 and the publish stays queued. That matches the level this job gives its other non-refusing findings, andpublishneedsthis job, so a failure here would hold npm, the tag and the image.
- The new
- Acceptance (triage
5947729032, third direction only): on full history the mode names exactly triage's sets: 17.5.08c87d26a58 changesets from 7 commits, and 17.6.0617f25f8a1 (748b24072, feat(types,automation): a host's per-kernel scheduled-work OFF reports its own reason #21270). The 17.6.0 instance's dated correction is the maintainer's docs(releases): finalize the 17.6.0 notes after publish #21362 (9360df4138), which this PR does not touch.- Dispatch premise falsified: the suggested control 17.4.0 is not clean. It left 13, and 17.3.0 left 4. The clean controls are 17.2.0
e7d2cc67f, 17.1.0 and 17.0.0. release-pending-publish --self-test: 68 cases in 20 batteries (13 before).release-verify-npm --self-test: 96 cases. One ablation (the call replaced) turns battery 12's two positive pins red, and the restore is proven.- NOT MEASURED, stated in the PR: the step's NOT MEASURED fallback has no running pin, and the negative pin (no report off the pending branch) is unablated.
- Dispatch premise falsified: the suggested control 17.4.0 is not clean. It left 13, and 17.3.0 left 4. The clean controls are 17.2.0
- Gates on this head: 35 check-runs: 24
success, 11 skipped, none failed and none pending.check-expected-skips: OK, all 11 skips are on the roster.check-governed-merges --pr 21373: NOT governed, 417 changed lines.mergeable_state: clean. A localgit merge-treeagainstorigin/main3937ad2f32merges without conflict, and nomaincommit since the merge base9360df4138touches these paths. - Out-of-scope findings:
- 17.3.0 and 17.4.0 carry the same gap (4 and 13 changesets whose code shipped without that version's CHANGELOG entry), and their release notes have no dated correction yet. This is the same family as this card. Its fix is release-owned text (the docs(releases): finalize the 17.6.0 notes after publish #21362 shape), which no code PR may edit. Reported to the maintainer, not filed.
- The 17.0.0-rc.4 (8) and rc.2 (2) residues are prerelease history. Acceptance notes.
Landing: ready, then auto-merge through the merge queue.
- Shape (read on GitHub): a draft against
objectstack-fleet commented
on Oct 2, 2026 ContributorMore actionsLanded: PR #21373 →
7b21af80cbdomain:specseat 1 (session_01UtnxvdiN376GF3sgXwAw4d), holder of claim5947821007· 2026-10-02T09:46Z⛔ Release acts stay the maintainer's (AGENTS.md Prime Directive 15). This landing changes release tooling only.
- Landed: PR ci(release): the release-integrity audit names the changesets a version commit did not consume #21373 went through the merge queue as
7b21af80cb, with one parent (43e928dd4c). All 3 files are blob-equal to the accepted head27979b22f4, on the merge commit and onorigin/main:.github/workflows/release.yml(c926fd6878),scripts/release-pending-publish.mjs(978abbbf3c) andscripts/release-verify-npm.mjs(fad7caa4e8). - Card: closed
completedby the PR'sFixesline, and by no other PR. This act removespm:dispatchedand the assignee. - Review: seat-checked release tooling (no at-tier review owed); ACCEPT
5948868115. - What changes at the next release: the push (or repair dispatch) that queues a publish lists every changeset the version commit carries but did not consume, each with the commit that added it. It is a
::warning::plus a job-summary section. It never fails the step or holds the publish, and an unmeasurable run says NOT MEASURED. - Unlock scan: no open card names
Blocked-by: #21361. - Carried:
- 17.3.0 and 17.4.0 have the same gap and no dated correction in their notes. That is release-owned text, reported to the maintainer.
- release.yml: the push-lane "Backfill GitHub Releases" step runs while the same version's publish job is still creating its Releases, because the #20627 gate reads only npm #21359 (
priority:p3) still holds the backfill's second guard.
- Landed: PR ci(release): the release-integrity audit names the changesets a version commit did not consume #21373 went through the merge queue as
- added 3 commits that reference this issue
on Oct 7, 2026
Summary
The Version Packages PR is regenerated on a schedule and on demand (#11233), and it cannot be refreshed while it sits in the merge queue. When it lands, the merge queue builds it on top of the current
main. So the version commit's tree carries every commit that landed after the PR's last refresh. The PR's own diff deletes, and turns into CHANGELOG entries, only the changesets that existed at that refresh.The code of the later commits is therefore published under the new version, but their changesets stay in
.changeset/. No CHANGELOG entry for that version names them. They show up one release later, under the wrong version.#20625 (#20613) made the publish ship the version commit and nothing after it. This is the window before the version commit, which #20625 does not cover.
Measured twice
8c87d26a(#17076)f11b5f2#20568,e73ee2d#20567 (two changesets),c876a74#20504,7a1faf1#20579,c9d234c#20577,24d521e#20572,2123fcc#20576e73ee2d,c876a74). The 17.5.0 notes carry a dated correction for them.617f25f8(#20639)748b240#21270 (ScheduledWorkPolicy.hostDisabledReason, aminorfor three packages).changeset/21110-scheduled-work-host-reason.mdis still pending onmain. No 17.6.0CHANGELOG.mdin the published tarballs mentions it (also observed in objectstack-ai/hotcrm#1982).How to check either one:
Why it matters
The generated CHANGELOG is the record an upgrading agent or operator reads, and the release notes are compiled from it. A breaking change that ships without its entry is invisible exactly where people look for it. For 17.5.0 that was the
RealtimeEventTypenarrowing and the forced-Turso-replica refusal.Directions (not decided here)
.changeset/*.mdthat the PR does not delete, so the PR must be refreshed first. The guard needs a re-run path that does not deadlock with "cannot refresh while queued".changeset versionon the merge-group tree, so the version commit consumes everything in it.