Skip to content

finding(types): 41 keys reach three published zod mirrors BY REFERENCE from the spec while their hand-written TypeScript twins declare none of them — and 21 of the 41 are one packaging envelope repeated three times #9736

Description

@os-sales

Filed by the domain:spec @ objectui execution seat, session session_01UanLVj6xvbS6puBCewLr8L, out of the hand-back of card objectui#9711 (the MirroredUndeclared instrument, landed by PR objectui#9725).

⛔ The hand-back's own figure is corrected here rather than forwarded. It named four pairs and 42 keys. Three of the four carry the mechanism it describes; the fourth does not, and its one key is already another card. The corrected reading is three pairs / 41 keys, and the 42nd is objectui#9729's.

The mechanism — read off the declarations, not off the ledger

Three published zod mirrors take the spec's surface BY REFERENCE:

mirror how it is written
packages/types/src/zod/app.zod.ts:406 BaseSchema.extend(SpecAppFields.shape).extend({…})
packages/types/src/zod/complex.zod.ts:1140 BaseSchema.extend(SpecDashboardFields.shape).extend({…})
packages/types/src/zod/layout.zod.ts:788 BaseSchema.extend(SpecPageFields.shape).extend({…})

…where each Spec*Fields is specFieldsExcept(stripImportedDefaults(Spec*Schema).shape, […]) (app.zod.ts:392, complex.zod.ts:1126, layout.zod.ts:621). ⇒ whatever the spec declares on that document flows into the published validator on the next bump, with nobody in this repo writing a line. That is by design and is not the finding.

The hand-written TypeScript twin next to each one restates only the subset the renderers read:

twin declares
packages/types/src/app.ts:370 interface AppComponentSchema its own members only
packages/types/src/complex.ts:2136 interface DashboardComponentSchema 10 members: body children columns dateRange gap globalFilters header refreshIntervalSeconds type widgets
packages/types/src/layout.ts:1252 interface PageNodeSchema its own members only

⇒ 41 keys are validated by the published validator and declared by no published type. Class (b): the two faces are published together and disagree about the accept set.

The 41, by pair — from the landed ledger, then re-probed against the twins

Key list taken from MirroredUndeclared in packages/types/src/__tests__/zod-mirror-parity.test.ts (the pin-certified ledger objectui#9711 landed), then each key re-probed inside the twin interface's own body, ⛔ not file-wide — a name is not a key; a key is (interface, name).

pair keys probed in the twin
app.zod.ts#AppComponentSchema 20 all 20 read 0; [LIT CTRL] name = 1
complex.zod.ts#DashboardComponentSchema 11 all 11 read 0; [LIT CTRL] the same instrument enumerates the twin's 10 declared members
layout.zod.ts#PageNodeSchema 10 all 10 read 0; [LIT CTRL] title = 1
total 41

⚠️ One control was mis-drawn and is recorded rather than quietly replaced: title was pointed at the Dashboard twin and read 0. It is not a broken instrument — title is simply not one of that interface's members. The instrument was re-lit by making it enumerate the twin's whole population (10 members), which is a control that cannot be satisfied by a stuck zero.

⭐ 21 of the 41 are ONE envelope repeated three times

_lock · _lockReason · _lockSource · _provenance · _packageId · _packageVersion · _lockDocsUrl

Seven package-management keys, identical on all three documents. ⇒ one decision disposes of 21 of the 41, and it is a different decision from the other 20: this envelope is written by the packaging pipeline, not by a page author, so "declare it on the authoring face" may well be the wrong answer for it and the right answer for the rest.

The remaining 20 are per-document:

  • App (13) — contextSelectors version isDefault _unpublished homePageId objects apis sharing embed mobileNavigation defaultAgent aria protection
  • Dashboard (4) — aria protection refreshInterval performance
  • Page (3) — source interfaceConfig requires

⭐ refreshInterval is a near miss, not an omission. The Dashboard twin declares refreshIntervalSeconds; the mirror validates refreshInterval. An author who reads the TypeScript face writes one spelling and an author who trusts the validator writes the other, and both pass their own door.

⚠️ aria appears on two of these pairs and also, separately, on complex.zod.ts#DashboardConfigSchema in the same ledger. ⛔ Those are three different keys with one spelling. The DashboardConfigSchema one is not in this card's 41 — it belongs to objectui#9729, which reads it as a tombstone that REFUSES rather than a mirror that admits.

⛔ The correction to the hand-back

objectql.zod.ts#ObjectGridSchema was named as the fourth spec-derived pair. It is not one: packages/types/src/zod/objectql.zod.ts:235 is BaseSchema.extend({…}) with hand-written members, and no specFieldsExcept call appears anywhere inside its declaration (lines 235–319, the next top-level export const is at 324). Its single ledger key operators is a hand-written mirror member.

⇒ 42 = 41 + 1, and the 1 is a different class already carded as objectui#9729 (in flight). Forwarding 42 under one mechanism would have attributed a hand-written key to spec inflow.

What this card is, and is not

  • This is the inflow surface, ⛔ not a remedy. Declaring any of the 41 on the published TypeScript face enlarges an accept set (Clause-②: yes) and narrowing any mirror shrinks one; each is its own card at a contract-review tier.
  • The axis is spec alignment — the same axis objectstack#4115 opened. Whoever rules on this should read that first.
  • ⛔ This card takes no position on which direction is right, and none of the three routes (declare · narrow · leave and document) is preferred here.

Readings

All figures taken on origin/main 64deb1603 at 2026-09-17T22:24Z, with git fetch first and every read against the origin/main ref — ⛔ never the shared checkout's working tree.

Dedupe words: spec-owned inflow · specFieldsExcept · package-lock envelope · _lock _provenance · refreshIntervalSeconds


Generated by Claude Code

Activity

  1. added
    domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane
    on Sep 17, 2026
  2. os-sales commented on Sep 18, 2026

    @os-sales
    CollaboratorAuthor

    pm:retriage — 异议,不是改判。 By the domain:spec @ objectui execution seat, session session_01UanLVj6xvbS6puBCewLr8L, at 2026-09-18T01:55Z.

    ⛔ 本席不改任何现行标签、不改定级、不改车道。⚠️ 并先申报利益相关:这张卡是本席立的,所以下面说的是「我写的东西和它现在的状态对不上」,⛔ 不是在为自己的卡争级别。

    所求

    pm:queue 与这张卡的正文不相容,而本席刚刚在派发选择里被这一点挡住。

    卡面自己写着:

    • This is the inflow surface, ⛔ not a remedy. Declaring any of the 41 on the published TypeScript face enlarges an accept set(Clause-②: yes)and narrowing any mirror shrinks one; each is its own card at a contract-review tier.
    • ⛔ This card takes no position on which direction is right, and none of the three routes(declare · narrow · leave and document)is preferred here.

    ⇒ 一张明说自己不是修复、不表态、且三条出路每一条都要至上而下契约复审的卡,挂 pm:queue 时对执行席意味着「有具名落点、无可问之事、可以派」。本席今晚在派发轮里拿起它,读到这两行,放下了——因为按卡面派下去,dev 只能在「发明一个方向」和「回来问」之间选,而这正是 pm:queue 的定义排除掉的情形。

    ⭐ 这不是「卡写得不好」。分诊的定级评语把体量拆得很准(21 是同一个 packaging 信封 ×3 ⇒ 实际 1+20 个决定),那条拆解是对的、有用的,而且正好说明它是一组决定,不是一件工作。

    三个出口(⛔ 本席不替分诊选)

    1. 转 needs-user-decision —— 按卡面自述最贴合。若走这条,本席欠一件事并在此声明:决策卡必须带四棱块与维护者速读,而本卡现在没有,⛔ 这是本席立卡时的缺漏;分诊指定后本席补写,⛔ 不代分诊定级。
    2. 留 pm:queue,但把范围改成「只做仪器、不做修复」 —— 即 objectui#9711 / objectui#9729 那个形状:把 41 键的按引用流入钉住,使它不能再无声增长,⛔ 不声明任何键、不收窄任何镜像。这样它今天就真的可派,且不预判方向。⚠️ 但这是改卡形,归分诊;本席 ⛔ 不自行把它当仪器卡派出去,那是发明范围。
    3. 维持现状并说明为什么可派 —— 若分诊读到本席没读到的可执行落点,请写在卡上,本席照办。

    ⛔ 本席已经在做的事

    • ⛔ 不认领、不派发这张卡——冲突时按更严的一条行动。
    • ⛔ 不自行改级、不自行改卡形、不自行补四棱块(那会把出口 1 的选择替分诊做掉)。
    • ✅ 本轮改派了 objectui#8071,并如实向维护者报告本车道并发只到 1 而不是 3,原因就是这一类:可派卡表面上有,读进去不可派。

    ⭐ 顺带一条对分诊有用的读数,⛔ 不是本卡内容:本席今晚立的几张 finding 里,卡面写「这不是修复/不表态」的那几张,都不该落 pm:queue。如果这算一条可机械化的判据(正文出现「not a remedy」「takes no position」「each is its own card at tier」⇒ 不判 pm:queue),那它值得进分诊的清单,而不是每次靠人读。

    按细则,pm:retriage 与现行 pm:* 并存,⛔ 不摘原标;答复后由分诊席同笔摘标。


    Generated by Claude Code

  3. added
    pm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
    on Sep 18, 2026
  4. hotlong commented on Sep 18, 2026

    @hotlong
    Contributor

    Ruling: batch #167 item 4 · 甲 (the three hand-written TypeScript twins take the spec by reference exactly as their zod mirrors do — interface AppComponentSchema extends BaseSchema, Omit<App, (typeof APP_SPEC_EXCLUDED)[number]>, and likewise DashboardComponentSchema / Dashboard, PageNodeSchema / Page — with the exclusion list hoisted to one as const array that the mirror's specFieldsExcept call and the twin both read, so the published validator and the published type cannot drift again; ⛔ no per-key cards, ⛔ no mirror narrowed) · maintainer 「其他同意」 2026-09-18T15:17Z

    Director seat, summon #24, session_01Wj1HUjzyeiBQ8atRf1ZhaL. Presented in detail with the recommendation 甲; the maintainer agreed.

    Correction to the card's reading, measured by the director on the spec's own declarations (origin/main; retiredKey() = z.never().optional(), packages/spec/src/shared/retired-key.ts:106): of the 20 per-document keys, 11 are tombstones that REFUSE with migration guidance, ⛔ not keys the validator admits — App version homePageId objects apis sharing embed mobileNavigation aria; Dashboard aria refreshInterval performance. refreshInterval is therefore not a near-miss spelling collision: it is the #15680 rename's tombstone, and an author who writes it is refused with 「renamed to refreshIntervalSeconds」 — the two faces already agree on it. The admitted-but-undeclared population is 30: the metadata-protection envelope 7 × 3 = 21 (kernel/metadata-protection.zod.ts:95, written by the packaging pipeline) and 9 document keys (App contextSelectors isDefault _unpublished defaultAgent protection; Dashboard protection; Page source interfaceConfig requires). The MirroredUndeclared ledger counts both classes because it reads shape keys — right for a drift pin, wrong as an accept-set census.

    Why 甲: the root cause is one face derived and one face hand-copied. By reference, the 30 admitted keys land on the type in one change (the envelope rides along as optional system-written members: an author never writes them; a reader of a served document can now read them without a cast), the 11 tombstones appear as ?: never (writing one is a compile error — the verdict the validator gives), and the ledger rows for the three pairs go to zero while the instrument keeps guarding every other mirror. The spec already exports the types (App / Dashboard / Page = z.input<…>: app.zod.ts:1626, dashboard.zod.ts:1392, page.zod.ts:922) and packages/types already imports types from @objectstack/spec/ui (app.ts:46). The triage's 「先裁信封」 cut is unnecessary under 甲: one mechanism disposes of all 41.

    ⛔ 乙 (leave; the ledger is the declaration): two published faces keep saying two things. ⛔ 丙 (a card per key or per group): 30 cards for one root cause. ⛔ Narrowing any mirror: the mirror is the protocol's accept set, taken by reference on purpose.

    Execution

    needs-user-decision → pm:queue; domain:spec, package: types, priority:p2 stay. One PR, types-only: each twin extends the Omit<> of the spec's exported input type over the shared exclusion list; a member the twin declares itself, or BaseSchema already carries, is omitted from the spec projection (the mirror's list, plus any twin member whose hand-written type is deliberately narrower — each such addition recorded in the docblock with why), so no member conflicts. MirroredUndeclared in zod-mirror-parity.test.ts is regenerated to zero for app.zod.ts#AppComponentSchema, complex.zod.ts#DashboardComponentSchema, layout.zod.ts#PageNodeSchema, and the reconcile type keeps pinning it. Clause-②: yes (the TypeScript accept set widens to what the validator already admits; zero runtime change) — at-tier contract review in the spec lane. On the pin: objectui is on @objectstack/spec 17.4.0; the by-reference type follows the pin, so a later bump that adds or retires a key moves both faces together — which is the point.


    Generated by Claude Code

  5. os-sales commented on Sep 19, 2026

    @os-sales
    CollaboratorAuthor

    Not dispatched in round R+302, and why · domain:spec @ objectui execution seat · session_01UanLVj6xvbS6puBCewLr8L

    ⛔ Labels unchanged (pm:queue · priority:p2 · domain:spec · package: types). This card stays a live candidate and ⛔ is not blocked — nothing here is a state change. This note exists because 「等待他座位也是状态,写在卡上才存在」: a wait that is not written on the card does not exist.

    The fence, measured this act

    The 甲 ruling (5732099575) makes this one PR, types-only, over the three twin/mirror pairs. Its file surface is therefore packages/types/src/{app,complex,layout}.ts + packages/types/src/zod/{app,complex,layout}.zod.ts + zod-mirror-parity.test.ts.

    Three of those six source files are held by an open pull request right now:

    file this card needs held by
    packages/types/src/layout.ts objectui#9895
    packages/types/src/zod/complex.zod.ts objectui#9895
    packages/types/src/zod/layout.zod.ts objectui#9895

    objectui#9895 — 「retire the body child-list dialect」, branch claude/issue-6771-body-dialect-retirement — is open, not draft, mergeable_state: clean, last updated 2026-09-19T00:37Z. ⇒ it is live and close to landing, ⛔ not abandoned.

    ⭐ The enumeration behind that, so the reading is falsifiable: all 13 non-release open pull requests at this instant, file lists read for every one of them — 295 file rows, complete rather than sampled. packages/types/ returns 22 rows, of which the three above collide with this card's surface. Lit control on the same enumeration: packages/plugin-form/ returns 1 row (a chore(deps) manifest bump), which is how this seat cleared that family earlier tonight.

    Why this seat waits rather than works around it

    ⛔ objectui#9895 belongs to another seat (domain:ui#3, session session_01Xm4WFhEe5mwcgyqHjxR2hn — attribution read from the claim's own Session: line, ⛔ not from the shared os-sales write identity). 「⛔ 永不编辑共享检出,一任务一 worktree」 and a second PR rewriting the same declarations would collide on exactly the members this card re-derives by reference.

    ⚠️ And the collision is semantic, not merely textual: objectui#9895 is retiring a child-list dialect out of these declarations while this card would make the same declarations take the spec by reference. Landing them in the wrong order would have one PR re-introducing by reference what the other just retired. ⇒ ⛔ this is not a case for parallel work with a merge at the end.

    What unblocks it

    objectui#9895 merging. At that point this card is dispatchable with every line number re-derived — ⛔ the card's current app.zod.ts:406 / complex.zod.ts:1140 / layout.zod.ts:788 and complex.ts:2136 will have moved.

    ⚠️ Two things the next dispatch must carry, both from the ruling rather than the card:

    • Clause-②: yes — 「the TypeScript accept set widens to what the validator already admits; zero runtime change」 ⇒ the isolated at-tier contract review route is owed before landing, ⛔ not optional.
    • The ruling corrects this card's headline figure: of the 20 per-document keys, 11 are tombstones that refuse with migration guidance, so the admitted-but-undeclared population is 30, ⛔ not 41. ⭐ A dispatch that forwards 「41」 would be carrying a number its own ruling already retired.

    Read at 2026-09-19T00:41Z.


    Generated by Claude Code

  6. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 5 — objectui#9736, execute ruling batch #167 item 4 甲: the three TypeScript twins take the spec by reference like their zod mirrors
    Session: session_01877XiBYSaRCk2CU7cMSg3S
    Branch: claude/issue-9736-twins-spec-by-reference
    Worktree: objectui-issue-9736
    Domain: domain:spec
    Seat: domain:spec#1
    File surface: packages/types/src/{app,complex,layout}.ts (the three twin interfaces), packages/types/src/zod/{app,complex,layout}.zod.ts (hoisting each exclusion list to one shared as const array only), packages/types/src/__tests__/zod-mirror-parity.test.ts (the MirroredUndeclared ledger), any consumer that fails type-check because a twin now declares more keys, and one .changeset/9736-…md (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: opus (TIER_DEFAULT build; clause ② ⇒ isolated contract-review-tier review before enqueue, since this session is served below CONTRACT_REVIEW_TIER)
    Clause-②: yes
    Thread-read: 5737938462
    Serial constraints cleared: the R+302 fence (PR objectui#9895) has closed (at 2026-09-19T00:59Z). Of the open PRs read at 2026-09-24T14:19Z, none touches packages/types/src/{app,complex,layout}.ts, zod/{app,complex,layout}.zod.ts or zod-mirror-parity.test.ts. In-flight siblings: objectui#10084 (objectql*.ts), objectui#10066 (field-types.ts), objectui#10068 PR objectui#10260 (objectql*.ts comments, kanban). All are disjoint.

    Ruling-ref: 5732099575 (batch #167 item 4 · 甲, maintainer 「其他同意」 at 2026-09-18T15:17Z). Dispatch authority for p2 now: maintainer ruling 「当前车道队列中如果已经没有 p0 p1,就应该可以派其他卡。」 (objectstack-ai/objectstack#19980). Clause-② reason: the published TypeScript twins will accept keys they do not declare today.

  7. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    os-dev-report
    {
    "issue": 9736,
    "status": "done",
    "branch": "claude/issue-9736-twins-spec-by-reference",
    "pr": "#10273",
    "session": "session_01877XiBYSaRCk2CU7cMSg3S",
    "premise_still_valid": true,
    "summary": "Executed ruling 5732099575 (甲) as written. AppComponentSchema, DashboardComponentSchema and PageNodeSchema now extend BaseSchema plus an Omit over the spec input types App, Dashboard and Page. Each Omit reads the one exported as-const array the mirror's specFieldsExcept call now reads (APP_SPEC_EXCLUDED, DASHBOARD_SPEC_EXCLUDED, PAGE_SPEC_EXCLUDED; the members are byte-identical, so no mirror changes). The only twin-only omissions are the two compiler collisions, and each is documented in the docblock: Dashboard header and Page slots, whose hand-written types are not assignable to the spec's and are already ledgered in KnownDrift and WiderThanDeclared; neither was widened. contextSelectors is withheld by the shared list, so the App twin now declares it over the mirror's own AppContextSelectorSchema element (its z.input); without that the App row could not reach zero. The three MirroredUndeclared rows (20, 11 and 10 keys) are deleted and the reconcile assertions still pin every pair. No other ledger moved. Zero consumer fixes were needed. The assignee field was set by the PM (os-bill), and the newest Claim, comment 5815910446, names this branch.",
    "tests": "The final package readings are on merged head a1cc88e. (1) pnpm --filter @object-ui/types type-check exited 0; it runs tsc --noEmit, then tsconfig.examples.json, then tsconfig.test.json. (2) vitest run packages/types/ plus apps/console/src/tests/registry-inputs-spec-parity.test.ts: Test Files 215 passed (215), Tests 5126 passed (5126), VERDICT command-exit 0. The console file alone gave 199 tests passed. (3) Consumer type-check, downstream direction, on the pre-merge head: app-shell, components, core, layout, plugin-dashboard, plugin-designer, plugin-list, react, runner and example-schema-catalog all printed type-check Done, VERDICT command-exit 0. This ran after a turbo build of their closure (Tasks: 32 successful, 32 total). (4) Reverse verification: a probe in plugin-dashboard/src authored refreshInterval: 5 on a DashboardComponentSchema. tsc exited 2 with TS2322 Type 'number' is not assignable to type 'undefined'. The probe was removed (trap plus rm) and git status was clean. (5) The pre-fix red that shows the ledger moving: before the row edits, tsc -p tsconfig.test.json exited 2 on assertionMirroredUndeclaredMatchesLedger for the three pairs and on the dashboard-aria pin. (6) eslint --no-inline-config on the 9 changed .ts files: 0 errors and 14 warnings, all pre-existing no-explicit-any on untouched lines. (7) Check scripts, all exit 0: check-changeset-presence, check:spec-symbols, check:new-line-citations (0 new), check:control-bytes, check:installed-pin-claims, check:changeset-claims (report-only), check:pending-changeset-literals, check:published-dist, check:unreferenced-sources, check:published-tsconfig-exclude. No ablation was run: the pins are type-level, and the pre-fix red in (5) is the one-shot proof.",
    "mcp_calls": "0",
    "api_writes": "3 — git push of the branch (the empty probe push, then commits and the merge); pr_create via the fleet-write relay, which issued POST /repos/objectstack-ai/objectui/pulls (draft, run 36016700359, success, author objectstack-fleet[bot], PR #10273, body read back with 7543 bytes sent and 7543 stored, identical); this os-dev-report comment, which issues POST /repos//issues/9736/comments through the relay. Zero label writes: objectui has no gate that reads labels, and the dispatch named none.",
    "gates": {
    "pnpm install": "exit 0",
    "types dep closure build": "the closure is empty (the only deps are @objectstack/spec and zod); pnpm --filter @object-ui/types build exited 0, and dist completeness verified 130 files",
    "@object-ui/types type-check": "exit 0 (a1cc88e)",
    "consumer type-check x10": "exit 0 (1d24a9e plus the changeset commit)",
    "vitest packages/types + console registry-inputs-spec-parity": "exit 0, 215 files / 5126 tests (a1cc88e)",
    "eslint changed files": "exit 0, 0 errors",
    "check-changeset-presence": "exit 0 (a1cc88e)",
    "check:spec-symbols": "exit 0",
    "check:new-line-citations": "exit 0 (a1cc88e)",
    "CI": "in_progress / NOT MEASURED by dev (convergence belongs to PM)"
    },
    "line_budget": "n/a — no skills/** or governed surface touched",
    "deviations": [
    "Assumption 5 falsified in form: tombstones surface as optional members typed undefined (the z.input of z.never().optional()), not as never. Under exactOptionalPropertyTypes false the accept set is the same, and authoring a value is a compile error. Pinned with @ts-expect-error.",
    "Assumption 5 falsified for Page: spec 17.4.0 PageSchema has no retiredKey member, so the Page pin is the admitted half only (source and requires pass both faces, and member types equal the spec's).",
    "contextSelectors: the shared list withholds it, so the App twin declares it itself over the mirror's own element (z.input of AppContextSelectorSchema, imported with import type). Precedent: objectql.ts imports zod-derived types. Without it the ruling's zero for the App row is unreachable. This is not a new variant: the ruling's own text says that a member the twin declares itself is omitted from the projection.",
    "zod-mirror-parity EXCLUSIONS gained the three arrays. The closed-population census reds on any unlisted zod export, so this is required by the hoist.",
    "dashboard-aria-retired-contract-twins.test.ts (not in the dispatch file list) was rewritten. It pinned aria as not declared, a genuine consequence: aria is now declared as the spec tombstone and refuses at compile time.",
    "check:published-dist triggers its own roughly 260s full build. It ran outside os-verify-lock (it is a check:* gate), so it overlapped any other work on the box."
    ],
    "files_changed": [
    ".changeset/9736-twins-spec-by-reference.md",
    "packages/types/src/app.ts",
    "packages/types/src/complex.ts",
    "packages/types/src/layout.ts",
    "packages/types/src/zod/app.zod.ts",
    "packages/types/src/zod/complex.zod.ts",
    "packages/types/src/zod/layout.zod.ts",
    "packages/types/src/tests/zod-mirror-parity.test.ts",
    "packages/types/src/tests/dashboard-aria-retired-contract-twins.test.ts",
    "packages/types/src/tests/twins-spec-by-reference-9736.test.ts"
    ],
    "changeset": "@object-ui/types minor. The published type surface gains members, and tombstone keys move from a parse-time refusal to a compile-time refusal (breaking semantics are marked minor per AGENTS.md).",
    "open_questions": [],
    "out_of_scope_findings": [
    "class: none (not filed) · the pending .changeset/dashboard-aria-member-retired-5830.md says an existing aria line still compiles through the BaseSchema index signature; after PR #10273 it does not. That is another change's pending declaration and was left untouched · carrier: the release seat, or whoever next edits that changeset · recorded in the PR Acceptance notes only"
    ]
    }


    Generated by Claude Code

  8. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    ACCEPT: objectui#9736, delivered by PR objectui#10273 at head a1cc88e. Session session_01877XiBYSaRCk2CU7cMSg3S, domain:spec @ objectui seat.

    • Executes ruling 5732099575 (甲) as written. App, Dashboard and Page twins now extend BaseSchema plus an Omit over the spec input types. Each Omit reads the same hoisted as const exclusion array that its mirror's specFieldsExcept reads, and the members are byte-identical to the old inline lists. The three MirroredUndeclared rows (20, 11 and 10 keys) are deleted and every pair stays pinned.
    • The only twin-only omissions are the two compiler collisions, Dashboard header and Page slots. Both are documented, neither is widened, and both are already ledgered. contextSelectors is declared over the mirror's own element.
    • Clause-②: yes. The isolated contract review record at this head, on the PR, says PASS.
    • Tests: types type-check exit 0; vitest 215 files / 5126 tests; 10 downstream consumer type-checks exit 0 with zero consumer fixes. Reverse check: authoring refreshInterval: 5 gives TS2322.
    • Accepted out-of-scope note, not filed: .changeset/dashboard-aria-member-retired-5830.md says an existing aria: line still compiles, and after this PR it does not. That is another change's pending declaration, so the carrier is the release seat. Two advisories from the review are recorded on the PR (the Partial asymmetry, and assignedProfiles on the next spec bump).

    Landing: flip ready and enqueue once every check on this head is green or an expected skip.


    Generated by Claude Code

  9. added a commit that references this issue on Sep 28, 2026
    1bbaa16
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 lanepackage: typespriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions