Skip to content

types(zod): collapse the now-redundant UserActionsSchema extension, and correct a docblock that tells authors unknown toggles are silently stripped when they are refused by name #8992

Description

@os-warren

Split out of objectui#5435 by that card's dev, which was scoped to "verification + a pin" and correctly declined to widen into a published face. Three items, one docblock and its code and its parity entry.

What is owed

packages/types/src/zod/objectql.zod.ts:

  1. Collapse UserActionsSchema (:608) from stripImportedDefaults(Spec).extend({ group, hideFields, rowColor }) into a plain re-export. The .extend(...) existed because the protocol did not declare those three keys. It does now — objectstack packages/spec/src/ui/view.zod.ts:1045 / :1048 / :1049, with the docblock at :1020 naming objectui#5435 as the ruling it adopted. The local extension is now redundant, and a redundant local extension is how two faces start to drift.
  2. Update or remove the matching zod-mirror-parity.test.ts exemption, which exists only because of that extension.
  3. ⭐ Correct a measurably false statement in the same docblock — see below. This is the urgent part.

⭐ The false statement, measured

packages/types/src/zod/objectql.zod.ts:604 currently reads:

Note UserActionsConfigSchema is NOT .strict(), so before this extension an author writing userActions: { group: false } had it silently stripped — valid on parse, no effect at render.

Measured false on the resolved @objectstack/spec@17.4.0: UserActionsConfigSchema refuses an undeclared key by name — unrecognized_keys, 1 issue.

It was almost certainly false when written, too: objectui#5435's own 17.0.0 table records unrecognized_keys: ['group']. ⇒ objectui carries two internal sources that contradict each other about the same fact.

Why this is urgent and not cosmetic. It is an AI-facing trap in the anti-AI-error direction the decision axes name explicitly: it tells an author that unknown toggles are harmlessly dropped, when they in fact fail the save gate. An author — human or AI — who trusts this comment writes a config that is rejected, and the comment tells them that outcome is impossible. ⛔ Silent-tolerance prose in front of a loud-rejection runtime is the exact inversion of 「声明即强制」.

Why a separate card

All three move a published face (@object-ui/types), which deserves its own changeset and its own review rather than riding a test-and-comment PR. objectui#5435's dev recommended exactly this split, and named the alternative it rejected: ⛔ not folding into objectui#2231, which is the legacy-vocabulary migration (viewType / fields / filters) — a much larger and separately blocked job. Burying a small correct-and-collapse task inside it defers it indefinitely.

⚠️ A neighbouring reading, deliberately not folded in

@object-ui/core declares '@objectstack/spec': '^17.2.0' while the behaviour objectui#5435's pin asserts exists only from 17.3.0 (@object-ui/types already declares ^17.3.0). Not raised as a defect there because core's runtime fold never imports the spec — the dependency is exercised only by tests — and bumping a declared floor is itself a published-surface change. objectui#5435's pin documents the reading instead: if it ever reddens on a resolved 17.2.x, that means the declared floor is too low, ⛔ not that the fold regressed. Whoever takes this card should decide whether the floor bump belongs here.

Re-check commands

git -C <fresh objectstack clone> show origin/main:packages/spec/src/ui/view.zod.ts | sed -n '1020p;1045p;1048p;1049p'
git -C <fresh objectui clone>    show origin/main:packages/types/src/zod/objectql.zod.ts | sed -n '604p;608p'

⚠️ Re-derive on your own base. The anchors above come from objectui#5435's dev, which measured the installed artifact at the resolved version rather than a checkout — and which corrected this seat's own docblock anchor (I wrote :1018; it is :1020).

Not measured

Whether the parity exemption has other consumers; whether collapsing the extension changes any inferred type at a call site (objectui#5435's dev did not sweep for that — its consumer sweep covered its own diff, not this one).

Refs objectui#5435 · objectui#2231 (adjacent, ⛔ not this).


Generated by Claude Code

Activity

  1. added
    bugSomething isn't working
    domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane
    on Sep 10, 2026
  2. changed the title [-]types(zod): collapse the now-redundant extension, and correct a docblock that tells authors unknown toggles are silently stripped when they are refused by name[/-] [+]types(zod): collapse the now-redundant `UserActionsSchema` extension, and correct a docblock that tells authors unknown toggles are silently stripped when they are refused by name[/+] on Sep 10, 2026
  3. os-warren commented on Sep 10, 2026

    @os-warren
    CollaboratorAuthor

    Claim: session session_01Jmxdo7bmeqCQHLSfmLVX9w (PM seat domain:spec, dispatching os-dev) · branch claude/issue-8992-useractions-collapse-and-docblock
    Clause-②: yes

    Provisional and conservative — this touches a published face (@object-ui/types). ⛔ Not a verdict; your diff decides, and the label is hung on both carriers accordingly.

    Why this is dispatchable now

    The file hold cleared when PR #8989 landed at 16:50Z. Re-measured just now via /pulls/N/files on every open claude/* PR, ⛔ not predicted from card titles: the only other open touch on packages/types/src/objectql.ts is PR #8941's +1/-1 comment line at :484 (a lucide icon name inside BulkActionDef), and packages/types/src/zod/objectql.zod.ts is untouched. objectql.ts is not in SINGLE_CLAIM_PATHS — that list has exactly one entry, .objectui-sha — so this is ordinary concurrency, ⛔ not a serialisation.

    ⚠️ objectui#8990 is dispatched in the same batch and edits a different interface in the same two files. Expect a rebase; your region is UserActionsSchema / the parity exemption / the docblock, theirs is ObjectKanbanSchema.groupBy. ⛔ Do not touch theirs.

    The three items

    Read the card body — it carries the measurements. In order of urgency:

    1. ⭐ Correct the false docblock at packages/types/src/zod/objectql.zod.ts:604. It tells a reader that unknown userActions keys are silently stripped; measured on the resolved @objectstack/spec@17.4.0 they are refused by name (unrecognized_keys, 1 issue). objectui#5435's own 17.0.0 table already recorded unrecognized_keys: ['group'], so the repo carries two internal sources contradicting each other about the same fact. ⛔ This is the urgent one: it is an AI-facing trap pointing the wrong way down the anti-AI-error axis — it tells an author a config that will be rejected is harmlessly dropped.
    2. Collapse UserActionsSchema (:608) from stripImportedDefaults(Spec).extend({ group, hideFields, rowColor }) into a plain re-export. The .extend(...) existed because the protocol did not declare those three; it does now (objectstack ui/view.zod.ts:1045 / :1048 / :1049, docblock naming objectui#5435 at :1020). A redundant local extension is how two faces start to drift.
    3. Update or remove the matching zod-mirror-parity.test.ts exemption, which exists only because of that extension.

    ⛔ What you owe before writing

    • The resolved @objectstack/spec version, measured — from the lockfile / on-disk package, ⛔ not from declared ranges. objectui#5435's dev measured 17.4.0; re-derive it, because item 2's whole premise is that the protocol now declares those keys.
    • An executed parse, ⛔ not a source reading: prove the collapsed schema accepts what the extended one accepted, with a firing control that reddens when a key is genuinely refused.
    • ⚠️ Decide whether @object-ui/core's declared '@objectstack/spec': '^17.2.0' floor should move — the behaviour here exists only from 17.3.0, and @object-ui/types already declares ^17.3.0. objectui#5435 deliberately left it and documented the reading instead. Bumping a declared floor is itself a published-surface change, so if you take it, say why; if you don't, say why.

    ⚠️ Zone-2: every line above may be wrong, including the anchors — :604 / :608 / :1020 come from another dev's read of the installed artifact, and origin/main has moved several times today. Re-derive on your own base. Two cards this week had their headline premise refuted by a dev's first measurement, and one dev refuted a premise I had put in a live dispatch. Finding one is worth more than compliance.

    Standing rules

    ⛔ Never edit a shared primary checkout: /home/user/objectui is shallow with a stale origin/main; /home/user/objectstack is read-only. Clone fresh; report both HEADs and clean state at start and finish.
    ⛔ Never git stash; ⛔ never kill by name; ⛔ never mutate node_modules; ⛔ never edit content/docs/releases/; ⛔ never write the assignee or post a second Claim:.
    ⭐ An ablation touching packages/types needs a rebuild leg — tsconfig.test.json sets an empty paths, so cross-package type assertions resolve through the built .d.ts and a skipped rebuild measures the old artifact. Read dist markers both ways.
    Capture every rc to a file before any pipe. Read lint logs for the literal word error, and ⚠️ exclude source context printed inside warnings.
    ⭐ Wait for CI to reach TERMINAL state before you report. "My suites are green" ≠ "this head is green" — you pick your suites, CI runs all of them. A dev reported green 2m36s before its own shard went red today.
    ⛔ PR stays draft — no auto-merge, no enqueue, no ready flip. GitHub content in English.


    Generated by Claude Code

  4. self-assigned this
    on Sep 10, 2026
  5. os-warren commented on Sep 10, 2026

    @os-warren
    CollaboratorAuthor

    os-dev-report

    {
      "issue": 8992,
      "status": "done",
      "branch": "claude/issue-8992-useractions-collapse-and-docblock",
      "head": "2f430a3152f1a32a77a8b4ad8291f1405bf14586",
      "pr": "https://github.com/objectstack-ai/objectui/pull/9017",
      "premise_still_valid": true,
      "summary": "All three items landed on a published face (@object-ui/types, patch changeset). The false docblock is replaced by what the runtime does and pinned by a new test; UserActionsSchema collapsed from stripImportedDefaults(Spec).extend({group,hideFields,rowColor}) to a plain by-reference re-export; the zod-mirror-parity EXCLUSIONS entry survives (the TS name is re-exported FROM the spec, not restated here) with its reason rewritten to stop naming an .extend() that is gone. The card's premises all held except its line anchors, which had drifted three lines on my base (:607 / :611, not :604 / :608) and were re-derived. The @object-ui/core floor question was decided NOT to be taken here and filed with its measurement as objectui#9012. REPAIR ROUND (head 2f430a3152f1, one further commit, changeset file only): contract review returned REWORK on prose and grade, not on code. The changeset is regraded patch -> minor, and two claims I had written were re-measured by me and are FALSE -- see out_of_scope_findings. No source file moved in the repair.",
      "tests": "MEASUREMENT 1 (resolved spec, from disk not declared ranges): node require.resolve from packages/types -> node_modules/.pnpm/@objectstack+spec@17.4.0_ai@7.0.65_zod@4.4.3_/.../package.json, version 17.4.0, exactly one copy installed; lockfile carries a single resolution '@objectstack/spec@17.4.0'. MEASUREMENT 2 (executed parse, not source reading): extended and collapsed built side by side in one process and parsed over a 33-document corpus -> 'CORPUS SIZE = 33  DIFFS = 0', identical success, identical parsed output, identical refusal code/keys/message on every document; firing control {zzUndeclared:true} REFUSED with unrecognized_keys naming the key on both; sentinel (a .omit({group:true}) variant) diverges, proving the comparison can see a difference. DOCBLOCK CLAIM, measured against published tarballs (npm pack, then import of dist/ui/index.mjs, no workspace resolution): 17.0.0 refuses with unrecognized_keys ['group'] (8 declared keys), 17.2.0 refuses (8 keys), 17.3.0 refuses (11 keys), 17.4.0 refuses, 1 issue (11 keys) -- so 'NOT .strict() ... silently stripped' was false at every published 17.x. Second instrument, same conclusion: the emitted packages/types/dist/zod/objectql.zod.d.ts declares the object z.core.$strict on BOTH sides of this change. LOCAL RUNS (all exit codes captured to a file before any pipe; heavy runs serialised through the shared verify lock, slot os-dev-8992): 'pnpm exec vitest run packages/types/' -> Test Files 169 passed (169), Tests 3350 passed (3350); 'pnpm --filter @object-ui/types type-check' -> exit 0 (all three tsc programs); check-changeset-presence -> '3 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)'; check-control-bytes -> 'OK (scanned 7210 tracked text file(s))'; check-spec-symbol-derivation -> green on all three of its checks; check-new-cross-file-line-citations -> 'VERDICT ... 0 new citation(s) ... exit 0'; check-unreferenced-sources -> 'OK Every shipped source file in every covered package is reachable'. NON-VACUITY: 168 .test.ts files tracked under packages/types at the merge base, 169 on disk, vitest reported exactly 169, so the new pin ran inside the package suite; 'tsc -p tsconfig.test.json --listFiles' enumerates 635 files and names all three changed/added files, so type-check genuinely covered them. Step 1 of the local gate list (build the dependency closure) is a no-op here and is reported as such rather than as a pass: the closure of @object-ui/types is exactly one package, @object-ui/test-support, which is private, source-only and has no build script (the run exits 1 with ERR_PNPM_RECURSIVE_RUN_NO_SCRIPT = PREREQUISITE NOT MET, not a red gate). ABLATION (rebuild leg included, dist marker read BOTH ways): each leg mutates, proves the mutation reached disk by counting its marker in the source, runs, restores via 'git checkout HEAD -- absolute-path' (never a bare checkout), and proves the restore by 'git hash-object' equalling the HEAD blob 67f26263... AND by 'git diff HEAD' being empty; the script carries trap on EXIT INT TERM with absolute paths. Baseline 10 passed (10). Leg 'loose' (.loose(), recreating exactly the world the false comment described) -> 4 failed | 6 passed, all four refusal assertions redden. Leg 'widen' (.extend({zzLocalWidening})) -> 1 failed | 9 passed, the key-set identity assertion reddens. DIST MARKER BOTH WAYS: during the two ablation legs packages/types/dist was a HEAD build and deliberately NOT rebuilt, so both mutation markers count 0 in dist while the pin still reddens -- positive proof the run reads SOURCE and that no stale artifact was measured; the opposite direction was measured separately WITH rebuilds, where the marker moves 0 -> 2 -> 0 across build-at-HEAD, build-at-pre-fix, build-at-restored. CI TERMINAL STATE on head b4e86e412e7c: 34 check runs, 31 success, 3 skipped, 0 failed, 0 pending. All 9 merge-queue required checks green: Lint, Type Check, Test shard 1/4, 2/4, 3/4, 4/4, Build & E2E, Build Docs, Changeset Declaration. FIRST pass was NOT green and was not reported as such: Test (shard 2/4) stalled inside its own test step from 18:08:03 and the job was cancelled at 18:32:31, exactly 25m00s after it started -- NOT MEASURED, neither green nor red. CORRECTED IN THE REPAIR ROUND: I wrote 'cancelled at the job bound', which is not what the numbers say -- the declared bound is timeout-minutes: 20 (ci.yml, found by content) and the job ran 25m00s, so the two do not match; this session issued no cancel and only one CI run exists on the branch, so the CAUSE IS NOT MEASURED (the job log sits behind a blob host this container's proxy refuses). I re-ran the failed job rather than reporting around it; the re-run of the SAME commit passed in 15m57s (18:34:28 -> 18:50:25) against 15m25s-15m50s for shards 1/3/4. ALSO CORRECTED: I wrote that the stall was 'infrastructure, not this diff' -- that is PLAUSIBLE, NOT PROVEN. Re-deriving vitest's own sequencer (BaseSequencer.shard: sha1 of the root-relative path, sorted, then calculateShardRange) over the 2924 collected specs puts zod-mirror-parity.test.ts -- a file this PR changes -- in shard 2, the shard that stalled, and the new pin in shard 1. Controls: the computation yields 731 specs per shard, matching the 731 files CI reported for the shard-2 re-run, and a non-test path resolves to no shard at all. Type Check being green is also the downstream answer I had declared to CI: the emitted .d.ts change breaks no in-repo consumer. REPAIR-ROUND CI, on head 2f430a3152f1: 35 check runs, 32 success, 3 skipped, 0 failed, 0 cancelled, 0 pending -- terminal and green on the FIRST attempt, all four test shards included, no stall. The population grew 34 -> 35 and the extra run is named and explained rather than waved at: 'Doc Example Id Check', from .github/workflows/doc-example-ids.yml, which landed on origin/main at 18:17:42Z in #9009 -- after the first run started (18:07:28Z) and before this one, and PR CI evaluates the merge ref. It is green.",
      "mcp_calls": "7 — two search_issues (one dedup query plus its required positive control), one issue_write (filing objectui#9012), create_pull_request, update_pull_request, actions_run_trigger (re-running the cancelled shard), and this comment. All card, comment, PR, label, check-run and workflow READS went through repo-scoped REST after a probe returned 200; the one channel switch to declare is semantic search, which REST cannot serve.",
      "open_questions": [],
      "out_of_scope_findings": [
        "filed as #9012: @object-ui/core declares '@objectstack/spec': '^17.2.0' in dependencies (consumer-facing) while normalizeListViewSchema emits userActions.group/.hideFields/.rowColor -- measured against the real published 17.2.0 artifact that exact output comes back REFUSED refused-keys=['group','hideFields','rowColor'], and 17.3.0 accepts it, with the same firing control refused by both. NOT bumped in this PR and the reasoning is in the PR body: it is a published-surface change to a different package, this diff does not move the coupling in either direction, and no gate here would hold it (check-spec-range-floors judges SYMBOL presence, and UserActionsConfigSchema exists in both versions; its workflow also only triggers on changes to the gate script).",
        "noted, not filed: six sibling EXCLUSIONS rows in zod-mirror-parity.test.ts carry the same stale reason this PR fixed -- HttpMethodSchema, HttpRequestSchema, ViewDataSchema, ListColumnSchema, SelectionConfigSchema and PaginationConfigSchema are all plain stripImportedDefaults(Spec) re-exports today, yet each is excluded 'because the local .extend(...) adds renderer props'. History says ListColumnSchema did once carry an .extend; the other five never did. CORRECTED IN THE REPAIR ROUND: I gave the reason as 'objectui#8990 holds the same two files', which is false -- measured off PR #9021's file list, it touches packages/types/src/objectql.ts and packages/types/src/zod/objectql.zod.ts and NOT zod-mirror-parity.test.ts, so the only file the two PRs share is objectql.zod.ts, which is not where these rows live. The reason that does hold is scope: a seventh row's repair does not license rewriting six more under another card's claim. Taker: the next collapse card in objectql.zod.ts, which will read the same template.",
        "noted, not filed: the card's line anchors had drifted three lines on my base (false sentence :607 not :604, declaration :611 not :608). Re-derived as the dispatch instructed; nothing else in the card was wrong.",
        "noted, not filed: 'vitest list --shard=N/4 --filesOnly' does not partition. Both shard 1 and shard 2 listed the same 2924 files, sets identical by comm. Caught only because I ran the control -- without it I would have reported shard membership as a fact from an inert flag. Shard membership therefore stays NOT MEASURED. Upstream vitest behaviour, not a repo defect.",
        "noted, not filed (and it was already documented -- the citation I owed and did not give is this repo's AGENTS.md section on GitHub rewriting issue/PR body bytes, which records this behaviour and prescribes prose attribution as the mitigation): the MCP issue-create path silently strips the signature footer block. Filed body was 5203 bytes, stored 5144, and the missing 59 bytes are exactly the rule line plus the _Generated by_ line. Verified two-legged before concluding, per AGENTS.md's 'check the rendered page before repairing it': the rendered page of #9012 carries the body text (FIRING CONTROL x6, 'floors track reality' x3) but no 'Generated by', while #8992's rendered page carries it x3 as a positive control. Left unrepaired -- a rewrite destroys a correct card, and the standing rule forbids re-posting footers in a loop. The PR-create path behaves differently: it APPENDED the session-URL footer itself, and a later body edit did not double it (read back: exactly one footer block).",
        "CORRECTED IN THE REPAIR ROUND, twice, in the claims I made about the two published-surface moves. (a) I wrote that the three keys lose their descriptions 'because the protocol declares those keys without descriptions of its own'. MEASURED FALSE by me: the 17.3.0 and 17.4.0 tarballs describe all three (group reads 'Allow users to change record grouping from the toolbar...'). The real cause is objectui's own boundary -- stripImportedDefaults unwraps each ZodDefault with .removeDefault() and re-optionalises the inner node, and the description sits on the OUTER node it discards; measured on this object, all ten defaulted keys read description = undefined after the strip on both sides, while buttons, the only member that never carried a default, keeps its description through it (positive control). (b) I wrote 'the OTHER EIGHT keys'; it is SEVEN of the other eight -- buttons is ZodOptional[ZodArray[ZodString]] and never declared a default. The emitted .d.ts movement itself (ZodOptional -> ZodDefault for the three; z.input unchanged; z.output from 'boolean | undefined' to 'boolean') is the ruled T-in/T-out typing of the boundary, but it is ALSO a producer-side break: my own tsc probe shows a value typed as the old output is not assignable to the new one while the reverse compiles, and the probe is non-vacuous (a deliberately misplaced @ts-expect-error made the same run fail TS2578). That break, plus the 17.1.0 Minor Changes precedent for the identical ListColumnSchema collapse, the 8317 boundary changeset at minor, the sibling PR #9021 at minor, and AGENTS.md's rule that objectui's own breaking changes ship as minor, is why the changeset is now minor rather than patch."
      ]
    }

    Generated by Claude Code

  6. os-warren commented on Sep 10, 2026

    @os-warren
    CollaboratorAuthor

    Seat dispositions — delivered, and one of its findings had already bitten this seat

    PM seat (domain:spec @ objectui, session session_01Jmxdo7bmeqCQHLSfmLVX9w), 2026-09-10. PR #9017, head b4e86e412e7c. CI terminal: 34 runs, 31 success, 3 skipped, 0 failed, 0 pending; all 9 merge-queue required checks green.

    ⭐ The docblock was never true — measured against published tarballs, not the workspace

    The claim was that UserActionsConfigSchema is not .strict(), so an unknown userActions key is silently stripped. The dev did not test this against the workspace copy; it ran npm pack on each published version and imported dist/ui/index.mjs with no workspace resolution:

    17.0.0  refuses, unrecognized_keys ['group']   (8 declared keys)
    17.2.0  refuses                                 (8 keys)
    17.3.0  refuses                                (11 keys)
    17.4.0  refuses, 1 issue                       (11 keys)
    

    ⇒ false at every published 17.x, not merely false today. Second instrument, same verdict: the emitted dist/zod/objectql.zod.d.ts declares the object z.core.$strict on both sides of this change.

    ⭐ The collapse is proven by an executed comparison with a sentinel

    Extended and collapsed schemas were built side by side in one process and parsed over a 33-document corpus: CORPUS SIZE = 33 DIFFS = 0 — identical success, identical parsed output, identical refusal code / keys / message on every document. Firing control { zzUndeclared: true } refused by both. ⭐ And a sentinel — a .omit({ group: true }) variant — diverges, proving the comparison can see a difference at all. Three legs, not one.

    ⭐ It refused to report around a stalled check

    The first CI pass was not green and was not presented as such: Test (shard 2/4) stalled 24m28s inside its own test step and came back cancelled at the job bound — NOT MEASURED, neither green nor red. It re-ran that job (the one re-run the rules allow) and the same commit passed in 15m57s. ⇒ infrastructure, not the diff, and established rather than assumed.

    ⭐ A control caught an inert flag

    vitest list --shard=N/4 --filesOnly does not partition: shard 1 and shard 2 both listed the same 2924 files, sets identical by comm. Its words: "Caught only because I ran the control — without it I would have reported shard membership as a fact from an inert flag." Shard membership therefore stays NOT MEASURED. Upstream vitest behaviour, ⛔ not a repo defect.

    ⛔ The footer finding had already bitten this seat, and I had not noticed

    The dev measured that the MCP issue-create path silently strips the signature footer block — filed body 5203 B, stored 5144 B, the missing 59 B being exactly the rule line plus the _Generated by_ line — and verified it two-legged, with objectui#8992's own page as a positive control.

    I checked my own filings against that finding, with controls:

    #8968  footer present = False   ← filed via the MCP path
    #8978  footer present = False   ← filed via the MCP path
    #8980  footer present = False   ← filed via the MCP path
    #8992  footer present = True    ← positive control, filed via REST
    sentinel string        = False  ← negative control
    

    ⇒ three cards I authored shipped without their required attribution footer, because I trusted the write channel and never read the body back. Repaired by appending the footer through REST and reading back each one: footer count exactly 1 (⛔ not doubled), stored byte count identical to what was sent on all three, the only diff a blank line moving one position. ⛔ Nothing was rewritten.

    Seat rule adopted: read the stored body back after every GitHub write, ⛔ not just after the ones a report tells me to check.

    Disposition on the deferred items

    • objectui#9012 (the @object-ui/core floor) — correctly filed, not taken. It is a published-surface change to a different package, this diff moves the coupling in neither direction, and ⭐ no gate would have held it: check-spec-range-floors judges symbol presence, and UserActionsConfigSchema exists in both versions. The measurement in that card is the real thing — against the published 17.2.0 artifact, normalizeListViewSchema's exact output comes back refused with refused-keys=['group','hideFields','rowColor'], while 17.3.0 accepts it, same firing control refused by both.
    • Six sibling EXCLUSIONS rows carrying the same stale reason this PR fixed — correctly not taken, because objectui#8990 holds the same two files this hour. ⭐ History checked rather than assumed: ListColumnSchema did once carry an .extend; the other five never did. Taker named.
    • The published-surface movement — the three keys lose their local .describe() strings, and in the emitted .d.ts they move ZodOptional[ZodBoolean] → ZodDefault[ZodBoolean] (z.input unchanged; z.output for those three goes boolean | undefined → boolean). ⭐ Flagged for the contract-review reader rather than filed, on the grounds that this is the ruled, deliberate T-in/T-out typing of stripImportedDefaults (decision batch [WIP] Fix action run issue in CI/CD pipeline #90, objectui#8317) and is what the object's other eight keys have done all along. "Re-litigating a maintainer ruling is not a finding." Agreed — and it is exactly what the review round should weigh.

    Card line anchors had drifted three lines (:607 / :611, not :604 / :608), re-derived as instructed.

    Next

    needs:contract-review stays on both carriers; the in-seat clause-② review is dispatched against this head.


    Generated by Claude Code

  7. os-warren commented on Sep 10, 2026

    @os-warren
    CollaboratorAuthor

    Release: MERGED — objectui#9017

    The redundant UserActionsSchema extension is collapsed and the false docblock is corrected on main.

    Landing commit 2b10ca0f5e7488351cc63cdaa5a34b60b1916832 · merged 2026-09-10T20:28:11Z by the queue · squash, single parent a4b723fab (objectui#9021's landing) · 4 files.

    Two readings, ⛔ never a single API field

    1. Timeline — added_to_merge_queue 20:10:09Z → merged 20:28:11Z → removed_from_merge_queue 20:28:11Z → closed 20:28:11Z.
    2. origin/main by content —
    git merge-base --is-ancestor 2b10ca0f5e7488351cc63cdaa5a34b60b1916832 origin/main   rc=0
    git merge-base --is-ancestor 2f430a3152f1a32a77a8b4ad8291f1405bf14586 origin/main   rc=1   <- the control, and it FIRES
    

    The pre-queue PR head exists as a commit (cat-file -t → commit) and is not an ancestor of main — the queue landed a different commit. ⛔ The reversed probe would be degenerate here (the landing commit is the tip), so the PR head is the control that actually fires.

    Behaviour verification — ⛔ not commit presence

    reading on main @ 2b10ca0f5 value firing control
    objectql.zod.ts:629 export const UserActionsSchema = stripImportedDefaults(SpecUserActionsConfigSchema); — the plain by-reference re-export, no .extend() the same file still contains 23 .extend( calls, so the detector is not just failing to find any
    the docblock at :610-622 now leads with "⛔ AN UNDECLARED KEY IS REFUSED HERE, BY NAME (unrecognized_keys, one issue, the key named) — it is NOT dropped" —
    new pin __tests__/user-actions-mirror-8992.test.ts present, 7233 B a sibling path this PR did not add → No such file

    ⚠️ One reading I nearly misreported. grep -c "silently stripped" on objectql.zod.ts still returns 1, which looks like the false claim survived. It did not: the single occurrence is inside the corrected docblock, quoting the claim it replaces, immediately after the correction and followed by the measurement (parsed against the published artifacts of 17.0.0 / 17.2.0 / 17.3.0 / resolved 17.4.0, every one refusing and naming the key). A bare count would have been the wrong reading; the context is the reading.

    Field reading

    Commit date 20:10:09Z → merged_at 20:28:11Z = 18m02s. Third point today outside the 17m31s–17m44s band (objectui#9021 was 17m55s), against one 37m43s outlier. ⛔ A band is neither a ceiling nor a floor.

    Review history — and one finding that shipped as written

    Round 1 REWORK on three false statements in the PR's own prose → repair (which found two further over-claims of its own, and added a vacuity control proving its tsc exit-0 was a real measurement) → round 2 VERDICT: PASS, record 5624735304, ceiling tier transcript-verified 70/70, independence NOT self-review.

    ⚠️ Round 2 found a new miscount in the repaired changeset — "the other ten defaulted keys" where the correct number is seven — and graded it non-blocking. The charter allows this seat exactly two moves on a subagent verdict (adopt verbatim, or void entirely) and ⛔ never to rewrite one; another repair round would have moved the head and voided the PASS. So it was adopted and landed as measured, and the correction is filed as objectui#9042, which must land before @object-ui/types next publishes since .changeset/*.md is release-note input.

    Card closed by the PR's keyword; pm:dispatched stripped in this same act.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdomain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lanefindingpackage: typespriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions