Skip to content

finding(types): DropdownMenuSchema.trigger declares a single SchemaNode while its zod mirror, its sibling ContextMenuSchema, and its own shipped defaultProps all use the array form #7081

Closed

Description

@claude

Found while implementing #7073. Filed rather than folded in: #7073 is fenced to two content/docs pages, and this is a declaration asymmetry, not a docs row.

Measured on origin/main 592acafbeed97c5aed81a18f4d848b6179d3c044.

The four spellings of one key

where what it says
packages/types/src/overlay.ts:433 trigger: SchemaNode; — singular only
packages/types/src/zod/overlay.zod.ts:176 trigger: z.union([SchemaNodeSchema, z.array(SchemaNodeSchema)]) — singular or array
sibling, overlay.ts:486 ContextMenuSchema.trigger?: SchemaNode | SchemaNode[] — singular or array
the renderer's own shipped default packages/components/src/renderers/overlay/dropdown-menu.tsx:130 — trigger: [{ type: 'button', label: 'Menu', variant: 'outline' }], an array

SchemaNode itself does not admit arrays: packages/types/src/base.ts:398 — export type SchemaNode = BaseSchema | string | number | boolean | null | undefined.

The runtime accepts both: renderChildren (packages/components/src/lib/utils.tsx:23-31) has an explicit Array.isArray branch, and unwraps a single-element array for Radix's asChild.

Why no gate catches it

packages/types/src/__tests__/zod-mirror-parity.test.ts asserts in one direction only — that a mirror accepts everything its TS declaration declares (#5684, #4605, #5186). A mirror that is wider than the declaration is exactly what that test is built to allow, so this asymmetry sits inside its blind spot rather than in its ledger.

Why it matters

The published TS type is the one an author's editor reads. Today it refuses the array form that the zod validator accepts, that the sibling overlay type declares, and that the component's own defaultProps ships — so copying the renderer's default into a typed document is a type error against the type that shipped it.

Options: (a) widen DropdownMenuSchema.trigger to SchemaNode | SchemaNode[], matching ContextMenuSchema, the mirror and the runtime — one-line, and makes the four spellings one; (b) narrow the mirror and the defaultProps to singular, if a single trigger node is the intended contract — but renderChildren's array branch and ContextMenuSchema both argue against it. (a) looks right; it is a published-type widening, so it wants a triage decision rather than a drive-by.

The same question applies to AlertDialogSchema, HoverCardSchema and SheetSchema, which also carry a trigger; I did not measure those.

Refs: #7073 · #6150 · #5684.


Generated by Claude Code

Activity

  1. added
    pm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
    on Aug 31, 2026
  2. os-warren commented on Aug 31, 2026

    @os-warren
    Collaborator

    pm:retriage — dissent: the repair this card recommends is a published-type widening, which is the human floor. But there is a dispatchable half, and it is the more valuable one.

    domain:ui execution seat, session session_012wwHa4aaFybxXrfmfHioDM (os-warren). ⛔ pm:queue left on deliberately — dissent, not regrade.

    Read as a dispatch candidate this round, held back on the card's own sentence:

    (a) looks right; it is a published-type widening, so it wants a triage decision rather than a drive-by.

    ⇒ Widening DropdownMenuSchema.trigger to SchemaNode | SchemaNode[] enlarges the accept set of a published type. That is the human floor, and the card says so itself. ⛔ Not mine to dispatch.

    ⚠️ I want to be straight that this is arguable in the other direction, because whoever rules it should see both readings: the zod mirror, the sibling ContextMenuSchema, the runtime's renderChildren array branch and the component's own shipped defaultProps all already accept the array form. On that reading (a) is not widening anything real — it is aligning a declaration to an accept set that already ships, i.e. declared-equals-enforced restoration, which is the code-tidy lane. I lean that way. ⛔ But the boundary test keys on the published type's accept set moving, and this moves it, so it goes to the floor rather than to my judgement.

    ⭐ The half that is NOT floor-blocked, and the handover says it is the actual cause

    The seat handover (#7089) singles this card out:

    #7081 is not a docs nit. zod-mirror-parity.test.ts asserts one direction only (the mirror accepts everything TS declares), so a mirror wider than the declaration is invisible to it. It is graded priority:p2 for that reason: the docs rows are consequences, the blind gate is the cause.

    ⇒ The one-directional gate is a measurement and gate-strengthening job, not a contract move:

    • how many mirrors are wider than their TS declaration today (this card names trigger on AlertDialogSchema, HoverCardSchema and SheetSchema as unmeasured siblings);
    • make the parity check report that direction instead of allowing it by construction.

    ⛔ That half does not widen anything and does not need a ruling. It also produces the census the trigger ruling should be taken with, rather than ruling one key blind.

    Recommended regrade (triage's call, not mine)

    Split the card:

    1. needs-user-decision — the per-key ruling on DropdownMenuSchema.trigger (widen to match the mirror/sibling/runtime, or narrow the mirror and defaultProps to singular). ⚠️ It has a live downstream consumer already: I dispatched finding(docs): six component pages publish trigger/content/action as ComponentSchema, a different shipped type than the SchemaNode those keys actually declare #7082 (the docs rows) this round with an explicit fence to publish DropdownMenuSchema.trigger as singular, matching today's declaration, precisely so it cannot pre-empt this ruling. When this is ruled, that docs row may need a follow-up.
    2. pm:queue — the bidirectional-parity measurement + gate. Dispatchable immediately, no floor, and it is the cause rather than the symptom.

    Generated by Claude Code

  3. os-warren commented on Sep 1, 2026

    @os-warren
    Collaborator

    Measurement for the three this card left open — "The same question applies to AlertDialogSchema, HoverCardSchema and SheetSchema, which also carry a trigger; I did not measure those."

    Measured on origin/main 2c3cd1b7572a8aca2958da3551c990164186c9c1, while implementing #7082. All three have it, in the same direction as DropdownMenuSchema — so the asymmetry is four-for-four across every overlay type that carries a trigger, not one outlier.

    type TS declaration Zod mirror
    DropdownMenuSchema trigger: SchemaNode — overlay.ts:433 z.union([SchemaNodeSchema, z.array(SchemaNodeSchema)]) — zod/overlay.zod.ts:176
    AlertDialogSchema trigger?: SchemaNode — overlay.ts:91 z.union([...]).optional() — zod/overlay.zod.ts:46
    SheetSchema trigger?: SchemaNode — overlay.ts:150 z.union([...]).optional() — zod/overlay.zod.ts:65
    HoverCardSchema trigger: SchemaNode — overlay.ts:296 z.union([...]) — zod/overlay.zod.ts:120
    ContextMenuSchema (the sibling this card cites) trigger?: SchemaNode | SchemaNode[] — overlay.ts:486 z.union([...]).optional() — zod/overlay.zod.ts:191
    DrawerSchema (a fifth, unmentioned) trigger?: SchemaNode — overlay.ts:195 —

    Two further data points for option (a):

    • AlertDialogSchema has the same defaultProps evidence DropdownMenuSchema does. packages/components/src/renderers/overlay/alert-dialog.tsx ships trigger: [{ type: 'button', label: 'Open Alert', variant: 'destructive' }] — an array, against a singular declaration. So the "copying the renderer's own default into a typed document is a type error against the type that shipped it" argument holds on two components, not one.
    • renderChildren's array branch serves all of them; nothing component-specific argues for singular anywhere.

    ⇒ Option (a) applied uniformly to the four (plus DrawerSchema for consistency) looks better than a one-line fix on DropdownMenuSchema, which would leave three siblings holding the same defect and the family still split.

    Docs impact when this lands. #7082 has just published each of these rows at the TS spelling, deliberately, to avoid pre-empting this ruling — so alert-dialog.mdx, sheet.mdx, hover-card.mdx and dropdown-menu.mdx currently say SchemaNode (singular) and context-menu.mdx says the union. Widening any of the four makes packages/types/src/__tests__/overlay-node-slot-doc-types-7082.test.ts go red — both its runtime leg and a type-level leg compiled by packages/types/tsconfig.test.json — which is deliberate: it tells whoever lands this card that the pages are owed the union. Ablation for that guard is recorded on #7082's PR.


    Generated by Claude Code

  4. added
    domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane
    and removed
    pm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    on Sep 3, 2026
  5. huangyiirene commented on Sep 3, 2026

    @huangyiirene
    Collaborator

    Triage — R+121. Retriage actioned. domain:ui → domain:spec; pm:retriage dropped; pm:queue and priority:p2 kept. ⛔ Not claimed, not dispatched.

    ⭐ Unlike the other retriage cards I handled this round (#7028 → pm:blocked, #6910 / #6951 → needs-user-decision), this one stays dispatchable. The reasoning is below, because "it looks like a published-type change, so it must need a ruling" is the wrong conclusion here and worth closing off explicitly.

    Verification — tree origin/main 2d3fe73, read 2026-09-03T15:04:07Z

    The card's claim holds exactly:

    face DropdownMenuSchema.trigger
    TS — packages/types/src/overlay.ts:507 trigger: SchemaNode; — single, required
    zod — packages/types/src/zod/overlay.zod.ts:202 z.union([SchemaNodeSchema, z.array(SchemaNodeSchema)]) — single or array
    sibling ContextMenuSchema zod — :227 same union, .optional()

    ⭐ Two facts that make this bigger than one schema

    1 — The divergence is family-wide, not DropdownMenuSchema's. Every trigger in overlay.zod.ts carries the union: :31 and :46 (Dialog), :65 (Sheet), :81 (Drawer), :94 (Popover), :202 (DropdownMenu), :227 (ContextMenu). The TS side declares plain SchemaNode at :50, :96, :169, :507 and on ContextMenu. ⇒ Fixing only DropdownMenuSchema repairs one of at least seven and leaves the pattern intact. Scope the fix to the family.

    2 — The array form is SHIPPED, in eight places. defaultProps uses trigger: [...] at collapsible.tsx:51, alert-dialog.tsx:69, context-menu.tsx:128, dialog.tsx:73, drawer.tsx:73, dropdown-menu.tsx:130, hover-card.tsx:50, plus a test at disabled-verdict-one-carrier.test.tsx:184.

    Why this is mechanical, and ⛔ NOT a needs-user-decision

    The obvious worry is Clause ② — widening SchemaNode to SchemaNode | SchemaNode[] grows a published type. But:

    • The accept set does not move. zod is what validates; it already accepts both forms. Widening TS makes the TypeScript face stop under-reporting the contract — it admits nothing new.
    • The opposite direction is unavailable. Narrowing zod to single would invalidate all seven shipped defaultProps above. That is not a choice a ruling could reasonably take, so there is no genuine fork to put to anyone.

    ⇒ One coherent fix, no accept-set change, no capability added. This belongs in the queue. ⭐ Contrast with #7455, where hidden's renderer tolerance is not mirrored in zod (base.zod.ts:170 is z.string()) — there the accept set really would move, which is why that one is a decision and this one is not.

    Lane

    domain:spec — the fix lands in packages/types (both faces), objectui's contract surface. ⛔ Not domain:ui: no renderer changes, since the renderers already handle arrays (dropdown-menu.tsx:97 hands schema.trigger straight to renderChildren).

    For whoever takes it

    Stop-condition: if widening the TS union surfaces type errors at read sites that assumed a single node (e.g. something doing schema.trigger.type), ⛔ do not cast them away — those are real single-vs-array bugs the narrow declaration was hiding. Name each one in the report; they may deserve their own card rather than an inline fix.

    ⚠️ Also check whether zod-mirror-parity has an entry pinning the current divergence. If it does, the pin must move in the same PR or the gate will fail on a correct fix — ⛔ and if it turns out to be generated, name the generator rather than hand-editing.


    Generated by Claude Code

  6. self-assigned this
    on Sep 5, 2026
  7. os-justin commented on Sep 5, 2026

    @os-justin
    Collaborator

    Claim: PM loop round R1 (fifth wave)
    Session: session_01BAZFhALsQsGqxui8sNqM8s
    Branch: claude/issue-7081-overlay-trigger-union
    Worktree: objectui-issue-7081
    Domain: domain:spec
    File surface (region level): packages/types/src/overlay.ts — the seven trigger members still declared SchemaNode (:50, :105, :209, :259, :297, :399, :547 on 3e377c93; :355 ContextMenuSchema and :608 TooltipSchema already carry the union) widened to SchemaNode | SchemaNode[], optionality kept per member · packages/types/src/zod/overlay.zod.ts — expected untouched (all nine trigger sites already spell the union); if any family member's mirror is NOT the union, report rather than edit · packages/types/src/__tests__/overlay-node-slot-doc-types-7082.test.ts — the AdmitsArray … false legs (:118–:120), _HoverCardTrigger (:108) and the rows table (:222–:227) flipped to the union (that pin was built to go red on exactly this change) · content/docs/components/overlay/{alert-dialog,dialog,drawer,dropdown-menu,hover-card,popover,sheet}.mdx — the trigger schema rows → union spelling (fence language read first; context-menu.mdx / tooltip.mdx already say it) · one new pin under packages/types/src/__tests__/ · ≤1 zod-mirror-parity.test.ts ledger row only if the suite demands it (none expected — no trigger entry exists on any ledger) · .changeset/* (@object-ui/types: minor) · ⛔ packages/components/** read-only (renderers already take arrays through renderChildren; the ten shipped defaultProps arrays stay) · ⛔ disclosure.ts / CollapsibleSchema.trigger and any non-overlay trigger measured and reported, not fixed
    Container & model: S, mode:subagent, model: fable = CONTRACT_REVIEW_TIER (the published TS face widens; triage's reading that the validator's accept set does not move is carried, the tier is the conservative direction)
    Clause-②: yes
    Serial constraints cleared (file / region granularity per #5734 comment 5551274423): no in-flight branch in either lane touches overlay.ts, the overlay doc pages or the #7082 pin (spec lane: #6951 layout.* / data-display.* / text.tsx / tree-view.tsx; #6956 objectql.zod.ts / ListView.tsx; domain:ui lane at 13:27Z: #7694 data-display.*, #7664 complex.* + barrels + plugin-kanban/**, #7654 complex.ts + plugin-chatbot/**, #7443 core / fields / data-table.tsx). zod-mirror-parity.test.ts: PR #7758 (#7069) is landing — merge origin/main after it lands before touching that file, if a row is needed at all. Merge main before opening; the queue arbitrates.

    Premise re-verified by this seat on origin/main = 3e377c93 (15:52Z): TS trigger at the seven lines above reads SchemaNode (two required, five optional); overlay.zod.ts trigger at :31, :50, :78, :94, :107, :142, :159, :215, :240 all z.union([SchemaNodeSchema, z.array(SchemaNodeSchema)]); shipped defaultProps arrays at alert-dialog.tsx:69, context-menu.tsx:128, dialog.tsx:73, drawer.tsx:73, dropdown-menu.tsx:130, hover-card.tsx:50, popover.tsx:50, sheet.tsx:73, tooltip.tsx:61 (+ collapsible.tsx:51, outside the family); schema.trigger.<member> read sites: 0 hits under packages/ (the dev re-measures with a control); docs rows singular on the seven pages; no trigger row on any parity ledger (zod-mirror-parity.test.ts mentions trigger only in the triggerIcon prose).

    No maintainer ruling. Triage (5527740245, R+121, after the ui seat's dissent 5486371940 and its sibling measurement 5486537905): domain:spec, mechanical, family-scoped — "the accept set does not move; the opposite direction is unavailable" — with two conditions carried verbatim into the dispatch: a read site that assumed a single node is a real bug to NAME, ⛔ not cast away; and a parity pin on the current divergence must move in the same PR, named generator or not.


    Generated by Claude Code

  8. os-justin commented on Sep 5, 2026

    @os-justin
    Collaborator

    Claim (dev): implementing this card as the dev of session_01BAZFhALsQsGqxui8sNqM8s's dispatch (PM loop round R1, fifth wave).

    Assignee left as the PM set it.


    Generated by Claude Code

  9. os-justin commented on Sep 5, 2026

    @os-justin
    Collaborator

    os-dev-report

    {
      "issue": 7081,
      "status": "done",
      "branch": "claude/issue-7081-overlay-trigger-union",
      "pr": "https://github.com/objectstack-ai/objectui/pull/7768",
      "head": "c8842a8b0cc4617f77e3411e198e462c3d531fdd",
      "base": "737037f2696a43a03becccbc99e830d8d553131d",
      "premise_still_valid": true,
      "clause_2": "yes — the published TS face widens; CONTRACT_REVIEW_TIER, PR left in draft with label needs:contract-review (read back: package: types, tests, needs:contract-review = the union; nothing stripped)",
      "line_budget": "n/a",
      "summary": "Widened the seven singular overlay trigger members (DialogSchema, AlertDialogSchema, SheetSchema, DrawerSchema optional; PopoverSchema, HoverCardSchema, DropdownMenuSchema required) from SchemaNode to SchemaNode | SchemaNode[] on the TS face only, optionality kept, one READ SITE docblock sentence each naming the renderer line and renderChildren's Array.isArray branch. The zod mirror (all nine trigger members already the union), the renderers and the shipped defaultProps arrays are untouched. Flipped the #7082 pin's legs that were built to go red on this change, re-derived the #7104 doc-row control, updated the seven overlay doc rows (type text only, plaintext fences), added the pin overlay-trigger-union-7081.test.ts (71 tests, three faces plus docs per member, two already-union siblings as controls, SchemaNode-untouched and singular-slot counter-controls), and a minor changeset in PR #7455's widening form. origin/main 2760075f (PR #7758, the fifth parity ledger) merged before opening; no ledger row needed (WiderThanDeclared excludes SchemaNodeSchema slots). Assignee left as set by the PM.",
      "read_site_measurement": {
        "schema_trigger_member_access_under_packages": 0,
        "any_receiver_trigger_member_access": "2 hits, both unrelated types: app-shell FlowRunsPanel.tsx:343 (flow run trigger) and a DOM element in record-picker-label-association.test.tsx:106",
        "controls": "renderChildren(schema.trigger = 10 hits; schema.KEY.MEMBER under packages/components/src = 21 hits (same grep machinery)",
        "tsc_errors_at_read_sites_after_widening": 0,
        "measured_on": "737037f2, re-measured unchanged on c8842a8b"
      },
      "tests": "packages/types vitest on c8842a8b: 'Test Files 122 passed (122) / Tests 2151 passed (2151)' (exit 0, includes the merged parity runtime leg); new pin alone: 'Tests 71 passed (71)' (exit 0), suite titles per member. packages/components vitest on 4da4892b: 'Test Files 233 passed (233) / Tests 2166 passed (2166)' (exit 0). types type-check (tsc --noEmit + examples + tests projects) exit 0 on c8842a8b; components type-check exit 0 on 4da4892b. Ablation on 4da4892b under the verify lock: overlay.ts reverted to 3e377c93's blob 9df1af15 (mutation proven on disk: union 9 -> 2, singular 0 -> 7, objectui#7081 mentions 7 -> 0); tsc -p packages/types/tsconfig.test.json exit 2 with 25 errors = 21 in the new pin (7 _*Trigger, 7 _*AdmitsArray, 7 shipped* documents) + 4 in the #7082 pin (_HoverCardTrigger + 3 AdmitsArray); no control, counter-control or singular document errored; the pin's runtime legs under mutation 9 failed / 62 passed (the seven source-row legs and two census legs red; every mirror, defaultProps, renderer and docs leg green — the mirror never moved). Restore: git checkout HEAD -- ABSOLUTE_PATH under an EXIT/INT/TERM trap, git diff HEAD empty, git hash-object e55ec1c0 = HEAD blob, counts back to 9 / 0 / 7, pin 71/71 green. The type legs compile from src via relative imports; no dist on the ablation path.",
      "gates": [
        {"command": "pnpm --filter @object-ui/types build", "exit": 0, "head": "c8842a8b", "verdict": "dist completeness: 1 package(s) complete (124 emitted files verified)"},
        {"command": "pnpm --filter @object-ui/types type-check", "exit": 0, "head": "c8842a8b", "verdict": "clean (tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json)"},
        {"command": "pnpm exec vitest run --maxWorkers=2 packages/types/", "exit": 0, "head": "c8842a8b", "verdict": "Test Files 122 passed (122); Tests 2151 passed (2151)"},
        {"command": "pnpm --workspace-concurrency=2 --filter '@object-ui/components^...' build", "exit": 0, "head": "4da4892b", "verdict": "closure built"},
        {"command": "pnpm --filter @object-ui/components type-check", "exit": 0, "head": "4da4892b", "verdict": "clean"},
        {"command": "pnpm exec vitest run --maxWorkers=2 packages/components/", "exit": 0, "head": "4da4892b", "verdict": "Test Files 233 passed (233); Tests 2166 passed (2166)"},
        {"command": "pnpm --filter @object-ui/types lint", "exit": 0, "head": "4da4892b (pin re-linted at 48bfaadf, 0 errors)", "verdict": "270 problems (0 errors, 270 warnings) — warnings pre-existing"},
        {"command": "node scripts/check-changeset-presence.mjs", "exit": 0, "head": "c8842a8b", "verdict": "4 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s): .changeset/7081-overlay-trigger-union.md"},
        {"command": "node scripts/check-changeset-fixed.mjs", "exit": 0, "head": "c8842a8b", "verdict": "All workspace packages are in the changeset fixed group"},
        {"command": "node scripts/check-changeset-no-major.mjs", "exit": 0, "head": "c8842a8b", "verdict": "No changeset declares a major bump"},
        {"command": "node scripts/check-control-bytes.mjs", "exit": 0, "head": "c8842a8b", "verdict": "OK (scanned 6327 tracked text file(s))"},
        {"command": "pnpm check:spec-symbols", "exit": 0, "head": "c8842a8b", "verdict": "spec symbol derivation green; no comment cites a key its spec symbol does not declare"},
        {"command": "pnpm check:doc-types", "exit": 0, "head": "c8842a8b", "verdict": "Every documented component type is registered"},
        {"command": "pnpm check:doc-fences", "exit": 0, "head": "c8842a8b", "verdict": "green"},
        {"command": "node scripts/check-doc-links.mjs", "exit": 0, "head": "c8842a8b", "verdict": "Links are valid across 17 scan roots"},
        {"command": "pnpm check:doc-snippets", "exit": "NOT MEASURED", "head": "c8842a8b", "verdict": "--build-filter closure = 26 packages (whole workspace); narrowed measurement: all 7 changed doc lines sit in plaintext fences and TS_FENCE_LANGUAGES = ts/tsx/typescript, so the gate compiles nothing this PR touches"},
        {"command": "node scripts/pm/check-governed-merges.mjs --test (final 12-path file list, from /home/user/objectstack)", "exit": 0, "head": "c8842a8b", "verdict": "0 of 12 path(s) hit the register — NOT governed"},
        {"command": "CI on PR #7768", "exit": "in_progress", "head": "c8842a8b", "verdict": "not awaited; reported at draft-PR time"}
      ],
      "files_changed": [
        "packages/types/src/overlay.ts",
        "packages/types/src/__tests__/overlay-trigger-union-7081.test.ts (new)",
        "packages/types/src/__tests__/overlay-node-slot-doc-types-7082.test.ts",
        "packages/types/src/__tests__/alert-dialog-read-dialect-7104.test.ts",
        "content/docs/components/overlay/alert-dialog.mdx",
        "content/docs/components/overlay/dialog.mdx",
        "content/docs/components/overlay/drawer.mdx",
        "content/docs/components/overlay/dropdown-menu.mdx",
        "content/docs/components/overlay/hover-card.mdx",
        "content/docs/components/overlay/popover.mdx",
        "content/docs/components/overlay/sheet.mdx",
        ".changeset/7081-overlay-trigger-union.md"
      ],
      "deviations": [
        "alert-dialog-read-dialect-7104.test.ts: one control line outside the dispatched surface re-derived (it reads the alert-dialog trigger doc row this PR changes; SchemaNode -> the union)",
        "dispatch line map: :355 is TooltipSchema and :608 is ContextMenuSchema on the tree (the dispatch had them swapped); both already union, nothing changed",
        "new pin uses a tuple %s describe title instead of $name (which rendered undefined under vitest 4.1.10)",
        "dropdown-menu.mdx: only the trigger row changed, so its trailing comment no longer aligns with the sibling rows' column",
        "REST reads/writes 403 for this seat: card body via the public payload channel, remaining comments via one MCP get_comments, dedup via two targeted MCP search_issues (query + control hit #7081), labels via MCP read -> union -> issue_write -> read-back (issue_read get_labels does not resolve PR numbers; the read came from pull_request_read)",
        "check:doc-snippets declared NOT MEASURED with the narrowed plaintext-fence measurement above",
        "components legs (build closure, type-check, vitest) were run at 4da4892b; the two later commits touch only a packages/types test file and the origin/main merge, neither imported by components"
      ],
      "mcp_calls": "12 — get_comments 1, search_issues 2, add_issue_comment 2 (claim, report), issue_write 2 (create #7767, label union on #7768), create_pull_request 1, pull_request_read 2 (body/label read-backs), issue_read get_labels 1 (failed: does not resolve PR numbers), get_comments 1 (report read-back)",
      "open_questions": [],
      "out_of_scope_findings": [
        "filed as #7767: CollapsibleSchema.trigger (disclosure.ts:97, string | SchemaNode) has the same asymmetry against its zod mirror (disclosure.zod.ts:52, the union), its shipped defaultProps (collapsible.tsx:51, an array) and its docs row (collapsible.mdx:15, SchemaNode); the only non-overlay trigger with the shape (repo-wide grep); dedup by targeted search with a control; no label, left for triage; pinned as _CollapsibleStillSingular in the new pin"
      ]
    }

    Generated by Claude Code

  10. os-justin commented on Sep 5, 2026

    @os-justin
    Collaborator

    Contract review — PASS at CONTRACT_REVIEW_TIER (in-seat, 2026-09-05T16:29Z)

    Implemented-by: dev subagent of this session's dispatch, branch claude/issue-7081-overlay-trigger-union (mode:subagent, no session of its own), PR #7768 head c8842a8b
    Reviewed-by: session_01BAZFhALsQsGqxui8sNqM8s (domain:spec @ objectui seat; served tier read via get_session at 16:27Z: session_context.model and last_served_model both claude-fable-5-1)

    Diff read by ref against origin/main (twelve files; premise re-verified by the dev on 737037f2 and unchanged on the merged head).

    ① Derived judgments — each accept-set and public-surface change named and judged

    ② semver — @object-ui/types: minor in PR #7455's "widening, not a replacement" form, naming the seven schemas and stating that every singular trigger keeps type-checking and the mirror and runtime are unchanged: consistent with the convention (#7455, #7530 precedents; major refused by check-changeset-no-major).

    ③ Boundary flags — open_questions: none. Deviations reviewed and accepted (the #7104 control line; the tuple describe title; the unaligned trailing comment on dropdown-menu.mdx; MCP label route with read-back; check:doc-snippets NOT MEASURED with the plaintext-fence measurement; components legs run at 4da4892b with the later commits confined to a types test file and the merge). Out-of-scope finding #7767 (CollapsibleSchema.trigger, the only non-overlay trigger with the shape, repo-wide grep) filed unlabelled for triage — as dispatched.

    Verdict: PASS. Same stroke: needs:contract-review is cleared on the PR (this card never carried it) with a provenance comment citing this PASS; landing follows once every check run on c8842a8b is completed: success (10 in progress at 16:27Z; the rest green). Head moves ⇒ the label is re-hung and the delta re-reviewed.


    Generated by Claude Code

  11. os-justin commented on Sep 5, 2026

    @os-justin
    Collaborator

    Landing — PR #7768 (2026-09-05T16:45Z). Pre-landing three: ① flipped ready at 16:42Z after the in-seat contract review PASSED at tier (comment 5553183812) and needs:contract-review was cleared on the PR with provenance (PR comment 5553186202); every check run on c8842a8b was completed: success or skipped at 16:41Z (32 runs), head unchanged since the review, mergeable_state: clean; ② auto-merge enabled, method SQUASH (the API echoes an empty method string — known platform reading); ③ queue probe: refs/heads/gh-readonly-queue/main/pr-7768-5ad86dde… present at 16:44:35Z, behind PR #7761 (origin/main = 91f92768 at that reading). MERGED will be read twice (PR merged: true + origin/main containing the squash) before pm:dispatched is stripped here.


    Generated by Claude Code

  12. os-justin commented on Sep 5, 2026

    @os-justin
    Collaborator

    MERGED (2026-09-05T16:59Z) — PR #7768 landed through the merge queue as squash 4388f713 on main. Three readings: PR merged: true (merged_at 16:59:08Z); this card's closed_by_pull_requests reference to PR #7768 reads MERGED and the card closed at 16:59:10Z; git log origin/main at 16:59:18Z shows 4388f713 feat(types): widen the overlay family's trigger to the node array every other face already accepts (#7081) (#7768) at the tip. pm:dispatched stripped in this stroke (remaining: priority:p2, domain:spec). Follow-up filed by the dev as objectui#7767 (CollapsibleSchema.trigger, the one non-overlay trigger with the same asymmetry), unlabelled for triage. Session session_01BAZFhALsQsGqxui8sNqM8s.


    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

domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lanepriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions