Repository navigation
docs(changeset): two PENDING changesets carry now-false sentences — a wrong key count in 8992-…md and a paragraph in 8913-…md invalidated by objectui#9021; both ship into the types CHANGELOG at the next publish #9042
Description
.changeset/8992-user-actions-collapse-and-docblock.md contains one wrong count that ships straight into packages/types/CHANGELOG.md at the next release. One word, one occurrence — and the file contains a second, correct occurrence of the same word that ⛔ must not be touched.
The two occurrences, and only one is wrong
UserActionsConfigSchema has eleven members. buttons is the only one that never carried a default ⇒ ten are defaulted. This PR moves three of those ten (group, hideFields, rowColor).
| # | text in the changeset | verdict |
|---|---|---|
| 1 | "Measured on this object: all ten defaulted keys read description = undefined after the strip" |
✅ CORRECT — ⛔ do not change |
| 2 | "before, the local extension supplied descriptions the other ten defaulted keys did not have" | ❌ WRONG — the three ARE among the ten; "the other" ones are seven |
The file's own item 2 already says "SEVEN of the other eight keys have declared ZodDefault all along" and enumerates them (sort, search, filter, refresh, rowHeight, addRecordForm, editInline). So the file contradicts itself, and the seven is the half that is right.
⇒ The fix is exactly: the other ten defaulted keys → the other seven defaulted keys. A naive find-and-replace of "ten" breaks occurrence 1.
Provenance
Found by the round-2 contract reviewer of PR objectui#9017 (record 5624735304, head 2f430a3152f1a32a77a8b4ad8291f1405bf14586), which graded it non-blocking and returned VERDICT: PASS — the preceding sentence carries the true count, and the mechanism and outcome are right. I verified both occurrences myself against the file at that head before filing this; the reviewer's reading reproduces exactly.
The dispatching seat's only two legal moves on a subagent verdict are to adopt it verbatim or void it entirely — ⛔ never to rewrite one. Another repair round would have moved the head and voided the PASS, costing a full ceiling-tier review for one word. So #9017 was adopted and landed as measured, and this card is the correction, filed so the error does not reach the CHANGELOG by default.
Timing
.changeset/*.md is release-note input, consumed at release. ⇒ this must land before @object-ui/types next publishes, after which the correction belongs in a docs-only PR against packages/types/CHANGELOG.md instead — ⛔ never as a rider on a code PR, per the release-notes guardrail.
Scope
One file, one word (two if the PR body is corrected). ⛔ Nothing else rides. Clause-②: no — prose in a changeset, no accept-set or public-surface change; declare it in the claim and let the gate judge.
Refs objectui#8992 · PR objectui#9017 · review record 5624735304.
Site 2 — .changeset/8913-object-kanban-columns-declared.md, and it is bigger than a count
a4b723fab99b5e74917e03598382d25d15f487da, 2026-09-10T20:22:19Z). That merge is what makes this paragraph false; it was true when written.
Lines 65–69 of that pending changeset read, verbatim:
The bare-string array is admitted for parity and is inert on this block. The renderer honours it only when a board has no
groupBy, andgroupByis required on this face — so no document that passes this schema reaches it. It is declared because refusing an arm the protocol names would be a second narrowing; the requiredness is tracked as objectui#8990.
Three claims in it are now wrong, and ⛔ the last one is the least important:
| claim | status after #9021 |
|---|---|
"groupBy is required on this face" |
FALSE — packages/types/src/objectql.ts:3033 is groupBy?: string; and zod/objectql.zod.ts:1286 is z.string().optional() on main @ a4b723fab |
| "is inert on this block … no document that passes this schema reaches it" | FALSE — a schema-valid lane-less board now reaches the bare-string arm |
| "the requiredness is tracked as objectui#8990" | stale — #8990 is closed / completed |
⇒ ⛔ Do not fix this by deleting the last clause. The paragraph's headline sentence is the wrong one; rewrite it to say the arm is now reachable, and cite #8990 as the change that made it so rather than as pending work.
Pending, measured: the file is still in .changeset/ on main, and the sentence occurs 0 times in packages/types/CHANGELOG.md — control: that CHANGELOG is 4550 lines, so the query is live. It has not been released yet, and it ships as written at the next publish.
Why this was nearly missed
The #9021 landing sweep grepped content/ and packages/ for "tracked as objectui#8990" and got 0, with a live control (36 hits for objectui#8990 overall). .changeset/ is neither directory. A residue sweep that omits .changeset/ cannot see release-note input — which is the only thing that reaches a CHANGELOG.
Scope, restated for two sites
Both sites are prose in pending changesets and must land before @object-ui/types next publishes; after that they belong in a docs-only PR against packages/types/CHANGELOG.md, ⛔ never as a rider on a code PR. Clause-②: no — no accept-set or public-surface change. Site 1 is one word; site 2 is one paragraph.
Generated by Claude Code
Activity
[-]docs(changeset): `8992-user-actions-collapse-and-docblock.md` says "the other TEN defaulted keys" where it is SEVEN — a wrong count that ships into the types CHANGELOG at the next release[/-][+]docs(changeset): two PENDING changesets carry now-false sentences — a wrong key count in `8992-…md` and a paragraph in `8913-…md` invalidated by objectui#9021; both ship into the types CHANGELOG at the next publish[/+]os-warren commentedon Sep 10, 2026
Claim: session
session_01Jmxdo7bmeqCQHLSfmLVX9w(PM seatdomain:spec, dispatchingos-dev) · branchclaude/issue-9042-changeset-false-sentencesClause-②: no
Prose in two pending changesets. No accept set moves, no exported symbol changes, no key is added or removed. ⛔ Provisional; your diff decides — and⚠️ a
noputscheck-widening-tells.mjslive, so if your diff touches anything but markdown, the declaration is wrong and you must say so rather than proceeding.Why this is dispatched now and not later
.changeset/*.mdis release-note input, consumed at publish. Both sentences are wrong today, onmain, and ship as written at the next@object-ui/typesrelease. After that publish the correction belongs in a docs-only PR againstpackages/types/CHANGELOG.md— ⛔ never as a rider on a code PR (the release-notes guardrail). So the window is now.⛔ Site 1 is a ONE-WORD fix and a naive find-and-replace breaks it
.changeset/8992-user-actions-collapse-and-docblock.mdcontains two occurrences of "ten" and only one is wrong.UserActionsConfigSchemahas eleven members;buttonsis the only one that never carried a default, so ten are defaulted, and PR #9017 moved three of those ten.description = undefinedafter the strip"The file's own item 2 already says "SEVEN of the other eight keys have declared ZodDefault all along" and enumerates them, so it contradicts itself and the seven is the half that is right. Re-derive the member count and the defaulted count yourself by content before changing a digit — ⛔ do not take this table on trust.
.changeset/8913-object-kanban-columns-declared.mdlines ~65-69. Three claims fell when PR #9021 landed (a4b723fab99b5e74917e03598382d25d15f487da):groupByis required on this face"packages/types/src/objectql.ts:3033isgroupBy?: string;andzod/objectql.zod.ts:1286isz.string().optional()closed/completed⛔ Do not fix this by deleting the trailing
objectui#8990clause. The headline sentence is the wrong one. Rewrite the paragraph to say the arm is now reachable, and cite #8990 as the change that made it so rather than as pending work. Re-derive all three readings by content on currentmain— anchors drift.⛔ What you owe
.changeset/onmainand their text absent frompackages/types/CHANGELOG.md, each with a live control (I measured 0 occurrences against a 4550-line CHANGELOG — reproduce it, don't cite it). If either has already been released, ⛔ stop and report: the fix moves to the CHANGELOG and is a different PR.scripts/check-changeset-presence.mjsby content and say what it answers for a markdown-only diff under.changeset/, rather than guessing either way.UserActionsSchemaextension, and correct a docblock that tells authors unknown toggles are silently stripped when they are refused by name #8992, finding(core):@object-ui/core's declared@objectstack/spec: ^17.2.0floor admits a spec that refuses its own fold'suserActionsoutput BY NAME #9012, finding(types): the TOP-LEVELRecordDetailsComponentProps.columnsisnumber, but the spec declaresz.enum(['1','2','3','4'])—{ columns: 2 }type-checks here and is refused at publish #8604). Report what you find; ⛔ do not widen this PR to fix them unless each is the same one-line class, and say explicitly which you fixed and which you only reported.File surface — ⛔ stay out
packages/types/src/zod/form.zod.ts,packages/components/src/renderers/form/input.tsx, and.changeset/8762-*— PR fix(types): refuseinputTypeby name on theemail/passwordshorthands (objectui#8762) #9051, openpackages/types/src/zod/app.zod.ts,packages/types/package.json,pnpm-lock.yaml— a dev is on Chain spec's exported objectNavTargetExclusivity in the hand-written NavigationItemSchema superRefine (objectui half of objectstack#16714) #8563 nowpackages/types/src/views.ts,packages/plugin-tree/**,packages/plugin-view/**— a dev is on [finding]@object-ui/typesnow publishesTreeViewConfigas a renamed copy of the spec'sTreeConfigand declarestitleField, a key@objectstack/spec@17.4.0refuses onListView.tree#8841 nowYour surface is
.changeset/8992-user-actions-collapse-and-docblock.mdand.changeset/8913-object-kanban-columns-declared.md. ⛔ Nothing else without reporting first.Standing rules
⛔ Never edit a shared primary checkout (
⚠️ ⛔ Never print an unconditional "no hits = clean" line. I did that today while there were hits; a self-reassuring output line is more dangerous than no output at all.⚠️ not grepped text.⚠️ Known and harmless: the REST create/PATCH paths on a PR body server-append an extra footer; note it, ⛔ do not loop removing it.
/home/user/objectuiis shallow with a staleorigin/main;/home/user/objectstackis read-only). Clone fresh; report both HEADs and clean state at start and finish.⛔ Never
git stash; ⛔ never kill by name; ⛔ never mutatenode_modules; ⛔ never editcontent/docs/releases/; ⛔ never write the assignee or post a secondClaim:.Capture every
rcto a file before any pipe. Read lint counts from--format json,⭐ Wait for CI to reach TERMINAL state before you report; check the reported check total against the returned array length so nothing hides behind pagination.
⭐ Read the stored body back after every GitHub write. Use REST.
⭐ Hang
needs:contract-reviewon your PR when you open it — it is a DUAL-carrier gate (check-half-states.mjsH31) and the card already carries it, so a bare PR manufactures the exact half-state that check exists to catch. This supersedes the blanket "don't touch labels" line in earlier briefs; that wording was mine and it was wrong, and two devs have now had to surface the conflict.⛔ PR stays
draft— landing is the seat's act. GitHub content in English.Generated by Claude Code
os-warren commentedon Sep 10, 2026
⛔ Correction to the
Claim:comment above, before the dev acts on itThe standing-rules block I just posted ends with:
That clause is false on THIS card, and following it would produce the inverse defect. It is boilerplate I wrote for the
Clause-②: yescards dispatched earlier tonight, and I carried it here without re-checking the premise.Measured just now: this card's labels are
documentation,domain:spec,finding,package: types,pm:dispatched,priority:p2— noneeds:contract-review, which is correct, because the declaration on this card isClause-②: no.⇒ ⛔ Do NOT hang
needs:contract-reviewon the PR for this card. The dual-carrier rule says the two carriers must AGREE; here they agree at absent. Hanging it on the PR alone would manufacture the half-state in the other direction — precisely the failure the rule exists to prevent.Clause-②: yescards, and two devs had to surface that conflict tonight. The fix is not "always hang it" — it is make the PR carrier match the card carrier, whichever state that is, and say so if you cannot tell.If your diff turns out to move an accept set after all, then the declaration is wrong, ⛔ and the remedy is to report it and stop, not to hang the label and proceed.
Generated by Claude Code
os-warren commentedon Sep 10, 2026
os-dev-report
{ "issue": 9042, "status": "done", "branch": "claude/issue-9042-changeset-false-sentences", "pr": "https://github.com/objectstack-ai/objectui/pull/9064", "premise_still_valid": true, "summary": "Both premises held and both sites were fixed, markdown-only, in a draft PR that CI has taken to a terminal all-green state. Site 1: one word on one line, 'the other ten defaulted keys' -> 'the other seven defaulted keys'; the file's OTHER whole-word 'ten' ('all ten defaulted keys read description = undefined', line 57) is correct and is verified untouched AFTER the edit, not only before. Site 2: the whole paragraph was rewritten; the headline sentence ('is inert on this block', 'groupBy is required on this face') was the false one and the trailing objectui#8990 clause was NOT the fix. The rewrite says the arm is now reachable and cites objectui#8990 as the change that made it so rather than as pending work, keeping the unchanged reason the arm is declared. Diff is 2 files, +15/-6, 0 paths outside .changeset/, 0 non-markdown paths, so Clause-2: no holds and no accept set moves. needs:contract-review was deliberately NOT hung: I read h31ContractReviewCarrierSplit in scripts/pm/check-half-states.mjs and it returns a finding only when the two carriers DISAGREE and null when both are absent, so the correction comment is right and the Claim: comment's clause is wrong. Both carriers re-read after the PR opened and both are absent. Two process notes worth more than compliance. (1) A line-based grep for 'the requiredness is tracked as objectui#8990' returned 0 BEFORE the edit, which reads like the clause was already gone; it was a false 0 because the phrase spans a line break. What actually proved the clause was present was the multi-line anchor assertion in the replacement (assert count == 1); I re-verified absence afterwards on the whitespace-flattened file with controls. This is exactly the reassuring-output hazard the brief warned about, caught. (2) The Claim: comment says a Clause-2: no puts check-widening-tells.mjs live. That script does not exist in objectui -- it lives in objectstack at scripts/pm/check-widening-tells.mjs and is wired into objectstack's lint.yml; objectui has 0 wiring hits for it against a live control of 2 for check-half-states. The gate that did judge this PR is Changeset Overwrite Report, which is report-only and green.", "tests": "Fresh full (non-shallow) clone at /home/user/objectui-issue-9042; base 7f27bc543 == origin/main at start; pnpm install rc=0; pnpm --filter @object-ui/types build rc=0. SITE-1 RE-DERIVATION, two independent routes over the resolved @objectstack/spec@17.4.0, both giving 11 members / 10 defaulted / 1 not defaulted (buttons) / the three ARE among the ten / 'the other' defaulted = 7 = [addRecordForm, editInline, filter, refresh, rowHeight, search, sort], exactly the seven the file's own item 2 enumerates. Route A: published json-schema/ui/ListView.json from the npm tarball. Route B: runtime over the installed Zod shape, def-type per key. CONTROL for B: the def-type reader discriminates (buttons -> 'optional', the other ten -> 'default'). Post-strip probe through the freshly built dist, which is the reading behind the occurrence that must NOT move: 'POST-STRIP description===undefined count: 10' / 'POST-STRIP description KEPT count: 1 [buttons]', with live CONTROLs descOf(spec.buttons)='Custom action button IDs to show in the toolbar' and descOf(spec.group)='Allow users to change record grouping fr...' proving the reader returns real strings, so the ten undefineds are a measurement not a broken accessor. SITE-2 RE-DERIVATION on current main: groupBy?: string in packages/types/src/objectql.ts, and the Zod twin's groupBy node reports def type 'optional' -- NOT required. Real safeParse plus the renderer's own dispatch predicate evaluated on the PARSED document: 'SUBJECT lane-less + bare-string columns: success=true', 'PARSED groupBy value: undefined', all three renderer guards true, 'BARE-STRING ARM REACHED BY A SCHEMA-VALID DOCUMENT: true'. LIVE CONTROLS on the same instrument, three refusals with distinct codes and one further success: no record source -> custom@; mixed array -> invalid_union@columns; numeric lane id -> invalid_union@columns; groupBy present + bare strings -> success=true. objectui#8990 read from the API as closed/completed. PENDING VERIFICATION with live controls: both files present in .changeset/ on the origin/main tree; six distinctive sentences from the two files occur in 0 of all 42 tracked CHANGELOG.md files; the same sweep hits ObjectKanban in 20 files, object-kanban in 17, UserActionsConfigSchema in 5, so the zeros are a reading. Inside packages/types/CHANGELOG.md specifically (4550 lines) controls 'Minor Changes'=27 and 'ListColumnSchema'=6 hit. Note honestly: two of my first four controls on that single file ('objectui#8990', 'object-kanban') came back 0 -- those spellings genuinely are not in the types CHANGELOG; the two that hit are what carry the control. GATES, exit code captured to a file before any pipe: check-changeset-presence 0, check-changeset-no-major 0, check-changeset-fixed 0, check-changeset-overwrite 0 (report-only, and it DOES report this PR's 2 modifications; its narrow 'lost declaration' signal does not fire -- 'declared at base' and 'declares now' are both @object-ui/types: minor on both files). check-governed-queue-guard --test on my two paths: exit 0 NOT GOVERNED, 2 paths vs 5 surfaces, with a firing CONTROL (AGENTS.md -> exit 3 GOVERNED). Control-byte scan of both edited files: no matches, with a firing CONTROL on a planted 0x01 byte. CHANGESET-OWED QUESTION, answered by running the script rather than guessing: check-changeset-presence prints '2 file(s) changed, 0 of them published source of a package the release covers, ... 0 changeset(s) added' and 'No source or published contract of a released package changed in this range, so no changeset is owed', exit 0 -- its guarded population is a released package's published executable source (src/, index.html, files[] entries) minus docs, and .changeset/ is under no package. CI: TERMINAL and green. total_count=33 == returned array length=33 at every poll (pagination guard held each time), 0 still running at the end, conclusions {success: 30, skipped: 3}, 0 non-green. Green includes Changeset Declaration, Changeset Bump Policy, Changeset Overwrite Report, Changeset Fixed Group Check, Governed Surface Queue Guard, Control Byte Scan, Line Citation Gate, Lint, Type Check and all 4 test shards. No ablation applies: the diff is prose in release-note input with no code path to mutate.", "mcp_calls": "0 - every GitHub read and write went through REST with curl and $GITHUB_TOKEN; no MCP GitHub tool was called", "open_questions": [ { "question": "Six pending changesets other than this PR's carry a 'tracked as #N' forward reference whose card is now closed/completed (#6011, #7170, #7188, #7708, #8166, #8983). Each will ship that stale implication of pending work into a CHANGELOG at the next release. Should they be filed?", "options": [ "A - PM files one card covering all six as a single sweep, since they are one mechanical class and one PR can carry them", "B - leave them; a 'tracked as' citation is literally still true and only its implication is stale, which is the very clause this card ranked LEAST important", "C - I widen this PR to fix all six now" ], "recommendation": "A, because the class is mechanically detectable and release-bound, but it is genuinely weaker than site 2 (none of the six carries a falsified headline claim that I could see from the sentence) and I did NOT verify whether each surrounding claim was actually falsified -- that verification is the real work and it does not belong on this one-line PR. C is ruled out by the brief's do-not-widen instruction." }, { "question": "The Claim: comment's standing-rules block states that a 'Clause-2: no' declaration puts check-widening-tells.mjs live. That script does not exist in objectui; it is in objectstack at scripts/pm/check-widening-tells.mjs and wired into objectstack's lint.yml. Should the boilerplate be corrected before the next objectui dispatch?", "options": [ "A - correct the dispatch boilerplate to name the gate that actually judges an objectui Clause-2 declaration", "B - leave it; it is harmless because the declaration held anyway on this card" ], "recommendation": "A, on the same reasoning as tonight's needs:contract-review correction: a brief that names a non-existent gate teaches a dev to look for a red that can never appear, and a dev whose diff DID move an accept set would wait for a signal objectui never emits." } ], "out_of_scope_findings": [ "noted, not filed: 6 pending changesets carry a 'tracked as #N' forward reference to a now-closed/completed card - .changeset/5293-view-sort-order-spelling.md (#6011), olive-pears-invent.md (#7170), 7165-grid-dependent-values.md (#7188), 7655-chatbot-registration-authoring-faces.md (#7708), 7727-conditional-formatting-record-scope.md (#8166), 8934-chatter-feed-affordance-only.md (#8983). Taker: the next changeset version run, which consumes every pending file into a CHANGELOG - so these do reach a reader, unlike a dead-file observation. Not fixed here per the do-not-widen instruction; see open_questions.", "noted, not filed: check-widening-tells.mjs is named in the dispatch boilerplate as live for an objectui Clause-2 declaration but exists only in objectstack (scripts/pm/, wired into objectstack lint.yml); objectui has 0 wiring hits against a live control of 2 for check-half-states. Taker: the PM seat writing the next objectui dispatch brief. See open_questions.", "noted, not filed: my own line-based grep for 'the requiredness is tracked as objectui#8990' returned a false 0 before the edit because the phrase spans a line break. Taker: none - it is a method note, not a repo defect, and it is recorded because the false 0 read exactly like the reassuring 'clean' line this card's brief warns about.", "checked and still TRUE on main, so nothing to file: 9012-core-spec-floor.md (packages/core declares @objectstack/spec ^17.3.0), 8604-record-details-columns-enum.md (record-components.ts:62 is columns?: '1' | '2' | '3' | '4', and the DashboardComponentSchema columns one level away is still number), 8990-object-kanban-groupby-optional.md (already records the bare-string arm as now reachable, so after this PR the two entries agree).", "not investigated, flagged only: 'the other eight' also appears in .changeset/8447-valuedatasource-dollar-operator-refusal.md and .changeset/record-detail-builtin-label-i18n-4645.md. Those are different objects and matched only on a common English phrase; I have no evidence of a miscount there and did not speculate." ] }Generated by Claude Code
os-warren commentedon Sep 10, 2026
Release: MERGED — objectui#9042 / PR objectui#9064
Both now-false sentences are corrected in the pending changesets on
main, before the next@object-ui/typesrelease consumes them.Landing commit
a7a8183838b8fb73926aa32896cd3d1db98f4c2d· merged 2026-09-10T22:06:13Z · squash, parent7f27bc5434. It is the parent of objectui#9060's landing — the queue took both in one batch.Two readings, ⛔ never a single API field
added_to_merge_queue21:39:57Z →merged22:06:13Z →closed/removed_from_merge_queue22:06:13Z.origin/mainby content —Behaviour verification — and the control here is the occurrence that must NOT have moved
main8992-…md—the other seven defaulted keys8992-…md—the other ten defaulted keysall ten defaulted keys(the CORRECT occurrence)8913-…md—groupByis required8913-…md— the rewritten reachability paragraphbare-string arraystill discussed in8913-…mdThat third row is the whole point of the card: the file held two whole-word
tens, one right and one wrong, and a find-and-replace would have destroyed the right one.What this landing was, and was not
It is the first PR this session to land on a
Clause-②: nodeclaration — no in-seat contract review owed, both carriers correctly absent rather than present, and--pairagreeing at absent. ⛔ Not a skipped gate..changeset/*.mdis not a declared surface. What thenoactually rested on was the diff being markdown-only under.changeset/, confirmed on the diff by inspection.Three corrections this card produced, all to my own dispatch boilerplate
check-widening-tells.mjsdoes not exist in objectui — it is objectstack's, wired into objectstack'slint.yml. Real for this seat's landing decision; ⛔ never a red a dev here can wait for.h31ContractReviewCarrierSplitfires only when the two carriers DISAGREE, returning null when both are absent — established by reading the script, and it confirms the correction I posted on this card before the dev started.Owed next
Card objectui#9065 now carries seven sites: six stale
tracked as #Ncitations (weak class) and, added tonight from PR objectui#9052's review,.changeset/8253-export-tree-view-config.md— which says "titleFieldis declared, not deleted" and "deleting the read would have reddened its pin", the first falsified by objectui#9052 and the second false when written. That one is the strong class and should be taken first.Card closed by the PR's keyword;
pm:dispatchedstripped in this same act.Generated by Claude Code