Repository navigation
docs(changeset): date the spec-symbol gate's export filter in the #6286 release note (objectui#9528) - #10970
Conversation
…filter in the past tense (objectui#9528) The pending `6286-explain-batch-cap-from-spec.md` said both scanners of `scripts/check-spec-symbol-derivation.mjs` "skip non-exported declarations". That was true when #6333 landed (c38162d: both `scanFile` and `scanFileForClaims` opened with `if (!hasExportModifier(stmt)) continue;`) and stopped being true at 9207c53 (objectui#6291), which dropped the filter from both. The body publishes verbatim at the next release, so the sentence now keeps the history and dates it: skipped when this change landed, filter since removed. Frontmatter (package, bump level) unchanged. Claude-Session: https://claude.ai/code/session_01EBx9rvB7dufCz4at53x35U Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Inputs: card #9528 (body and both comments — the PM claim comment and the ① Derived judgments
② Semver level
③ Boundary flags
Check-runs on the head, read at 2026-09-28T12:11Z (their conclusions are the gate verdicts): 41 runs, 38 completed Implemented-by: VERDICT: PASS Posted 2026-09-28T12:11Z. Generated by Claude Code |
Fixes #9528
Clause-②: no — release-note prose; no contract, accept set or public surface changes (a contract review is still owed: the diff is
.changesetprose)What changes
One sentence in the pending
.changeset/6286-explain-batch-cap-from-spec.md. That body publishes verbatim into@object-ui/plugin-grid's CHANGELOG at the next release, and the release PR objectui#5400 regenerates frommain, so this only helps if it lands before that PR merges. The frontmatter is untouched:check-changeset-overwrite.mjsprintsdeclared at base: @object-ui/plugin-grid: patchanddeclares now: @object-ui/plugin-grid: patch.Before:
After:
Why this wording, and why the history stays
The sentence was true when written and went false later. It is not a false sentence from the start. So the fix keeps the explanation, puts it in the past tense and dates it. Deleting it would lose true history.
1. True when the changeset landed.
c38162d7c9(#6333, 2026-08-25) added the changeset. At that commit, both scanners in the gate open with the same filter line, once inscanFileForClaims(rule 2) and once inscanFile(rule 1):The table below counts that line and two related markers in each revision of the gate file (
git show REV:scripts/check-spec-symbol-derivation.mjs | grep -c …):if (!hasExportModifier(stmt)) continue;const hasExportModifier// No export filterc38162d7c9(#6333 lands)9207c53e45^9207c53e45(#7274, objectui#6291)b120b66077(this PR's base)2. False since
9207c53e45(#7274, objectui#6291, 2026-09-02). On the base, the two scanners now carry// No export filter: a module-local declaration carrying a spec-alignmentinscanFileForClaimsand// No export filter (objectui#6291). A module-local declaration under a specinscanFile. The gate's own header says the same thing: "⛔ HISTORY, NOT BEHAVIOUR. Neither scanner has an export filter today."The order of the two commits was checked on a shallow checkout, so it needs a control leg:
git merge-base --is-ancestor c38162d7c9 9207c53e45exits 0.git merge-base --is-ancestor 62311b6419 c38162d7c9exits 0.62311b6419is the gate's first commit (2026-07-30), older than both.3. Which rule would catch this const, then and now. I measured this with a 2×2 probe, not read it off the header:
@objectstack/spec/security#6333 hook source,git show c38162d7c9^:packages/plugin-grid/src/hooks/useRecordCrudVerdicts.ts. In it,const EXPLAIN_BATCH_MAX_RECORD_IDS = 200;is module-local.exportadded. It is the control.EXPLAIN_BATCH_MAX_RECORD_IDSmaps to@objectstack/spec/security).c38162d7c9copy was exporting itsscanFile. The anchor count was checked on disk: 1 plain before and 0 after; 0 exported before and 1 after.c38162d7c9: rule 1b120b66077: rule 1constfindingexportadded (control)constfindingconstfindingWhat the probe shows:
DEBTis empty and noALLOWkey names it, so it would be a fresh finding and the gate would exit 1.findClaimreturnsnullon the const's doc comment. The comment names@objectstack/spec@17.0.0-rc.6but contains none of theCLAIM_PATTERNSphrases.The new sentence therefore states only history: the filter existed when the change landed, and objectui#6291 removed it from both scanners. It asserts no live capability of the gate, so a later change to the gate cannot make it false the way the old sentence became false (AGENTS.md #9).
The other pending changesets that name the gate
git grep -l check-spec-symbol-derivation b120b66077 -- .changesetlists seven files. As a positive control, the same form of search forplugin-gridin the 6286 file counts 1. I widened the search to every spelling of the gate (spec-symbol,check:spec-symbols), which gives 17 files, and read all 17 in full. I also grepped every pending body fornon-exported|unexported|not exported|export filter|hasExportModifier|export modifier|exported onlyand formodule-local. Only the 6286 file states the export-filter property. The other 16 say nothing about it:7265-core-context-token-mirrors,7265-data-objectstack-filter-operator-rename,7265-components-sort-direction-bound,7265-plugin-detail-record-alert-renderer-props,spec-symbol-mirrors-app-shell-7265,7265-types-user-filter-field-derives,9596-debt-issue-anchor-truthiness: these describe module-local mirrors that the rule-1DEBTledger carried, which fits today's behaviour.console-form-container-specs-one-declaration-5596: says derivation is the gate's sanctioned form.listview-comment-pair-4559: says rule 2 reads the attached comment block.9542-result-dialog-i18nlabel: names the rule-2 failure class.3162-types-ledger-batch8-verdicts,spec-pin-17-1-0-5328,spec-refresh-17-2-0-5668: ledger and pin history.ci-decide-markdown-trace-9241: says the gate openscontent/docs/**.8841-tree-view-config-deriveanddate-range-default-range-binding-4984: explain a miss by name matching (and, in 4984, rule 2's tie test). That is a different property, which I did not re-measure here.Gates (all read at HEAD
25b8b6eeb2, the only commit on this branch)pnpm check:changeset-claims✅ No pending changeset names a file this change touches.; self-contradiction:Every package declared across those 1 body(ies) is either not negated in its own prose, …; born-false:Line addresses read in them: 0.node scripts/check-changeset-presence.mjs✅ No source or published contract of a released package changed in this range, so no changeset is owed.node scripts/check-changeset-overwrite.mjs1 modified— case 2, "CORRECTING a declaration on purpose … prose that no longer matches the change"; the declared package set is unchangednode scripts/check-changeset-no-major.mjsnode scripts/check-changeset-fixed.mjs✅ All workspace packages are in the changeset fixed group.pnpm check:control-bytes✅ check-control-bytes: OK (scanned 9240 tracked text file(s); skipped 85 binary).pnpm check:new-line-citationsVERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0pnpm exec vitest run --maxWorkers=2on the 24scripts/__tests__/*.test.tsthat mention.changeset(viaos-verify-lock.sh)Test Files 24 passed (24)/Tests 914 passed (914)/VERDICT command-exit 0The 24-file set is a superset of what
node scripts/markdown-test-inputs.mjs --changed -returns for this file. That helper records.changeset/**as the input ofcheck-changeset-no-major.test.ts; the positive control ispackages/plugin-dashboard/README.md, which it echoes back. No package source, gate or test is touched, so nothing else is owed.node scripts/check-governed-queue-guard.mjs --teston the file answers✅ NOT GOVERNED.Acceptance notes
spec-symbol-mirrors-app-shell-7265reads "held six declarations … Four are now bound … and three were renamed". That is 4 + 3 against six. Its commit (14a1b92035, refactor(app-shell): bind or rename the six spec-symbol mirrors, shrinking the ledger 11 to 5 (objectui#7265 app-shell slice) #9465) removes six app-shell names fromDEBT, so one name may have held two declarations. I did not measure this. That changeset has empty frontmatter, so it publishes nothing. Nobody is carrying this; it is only noted here.fatal: Invalid symmetric difference expression 0000…line on stderr while every test passed. The SHA in it is all zeros;check-changeset-overwrite.test.tsanddocs-build-trigger.test.tsare the two files in the set that spell such a SHA. I did not trace it further. It is not a failure.Contract review
A contract review is owed and the PM seat commissions it. Everything above is meant to be re-runnable: every quoted code string, commit and command reproduces on this repo. This PR touches no gate, adds no checker, and leaves the frontmatter and bump level unchanged.
Session:
https://claude.ai/code/session_01EBx9rvB7dufCz4at53x35UGenerated by Claude Code