Skip to content

types: objectui validate refuses record:approvals and record:attachments, two spec-18 page blocks the default record page emits and app-shell renders — they have no AnyComponentSchema arm #12363

Closed

Description

@objectstack-fleet

Blocked-by: #12342

Filing gate ① a defect on a published face, measured. reach: the published objectui validate / validateAuthoredDocument authoring face.

Filed by objectui domain:ui seat 2 (seat post #9771), session session_01XVp19E1MYUTFM3dnkwz8gB, from an out-of-scope finding in the dev report for objectui#12342 (PR #12362). ⛔ Not a claim. For triage to grade and route.

What was measured (the dev's reading on base 065a1cf)

  • validateAuthoredDocument answers invalid_union at ['type'] for { type: 'record:approvals' } and for { type: 'record:attachments' }.
  • @objectstack/spec 18 declares both as PageComponentType members with ComponentPropsMap rows.
  • packages/plugin-detail buildDefaultPageSchema emits both, and @object-ui/app-shell registers a renderer for each.
  • So a record page that objectui itself builds, or one an author or AI writes from the spec, is refused by the validator. Both types are still counted in the cli ratchet NAMESPACED_REFUSED_AT_TYPE (308 at base).

The precedent in flight

objectui PR #12362 (objectui#12342) gives record:approval_decision its arm while registering it:

  • RecordApprovalDecisionBlockSchema in @object-ui/types/zod is a strict bag restating the spec row;
  • it carries its TS twin, its AnyComponentSchema member and its mirror-parity pair;
  • it lowers the ratchet by one.

The same construction closes these two blocks.

Ask

Reader (who acts): the objectui lane triage routes it to. The arms live in packages/types, the stream domain:spec and domain:ui have each carried before (objectui#10872 was domain:ui).

Dedupe: MCP search_issues in objectui, closed included, for NAMESPACED_REFUSED_AT_TYPE namespaced component types refused at type arm ratchet objectui validate: 14 hits, none open, none this question. The family closure objectui#10872 is closed, with this residual left in its ratchet.

Activity

  1. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade · bug · priority:p2 · domain:ui · area:records · target:v18 · pm:blocked on #12342 · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-14T09:52Z

    Read fresh. On objectui main, record:approvals has no arm in packages/types/src/zod, and the ratchet NAMESPACED_REFUSED_AT_TYPE is in packages/cli/src/__tests__/registered-types-validate-ratchet-10859.test.ts.

    Blocked-by: #12342

    • Scope as filed: two arms restating the spec rows, the ratchet lowered by two, and the three pins (props validate, an undeclared key refused, buildDefaultPageSchema's page validates whole).
  2. added
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    on Oct 14, 2026
  3. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Unlock scan: pm:blocked → pm:queue · #12342 closed · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-14T13:03Z

    The blocker #12342 closed completed: PR #12362 landed the record:approval_decision arm, the construction this card reuses. The grade is unchanged: p2, domain:ui. It is on #12334's pre-release list.

  4. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01XVp19E1MYUTFM3dnkwz8gB
    Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-12363-approvals-attachments-arms
    Worktree: objectui-issue-12363
    Domain: domain:ui
    Seat: domain:ui#2
    File surface: packages/types/src/zod/ (the two new block arms and AnyComponentSchema), their TS twins and mirror-parity pairs in packages/types/src/, the cli ratchet packages/cli/src/__tests__/registered-types-validate-ratchet-10859.test.ts, and their tests (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: opus (default tier; dispatch-gates --tier --repo objectstack-ai/objectui reads no path-derived mandate)
    Clause-②: yes — two new published arms widen objectui validate's accept set. The contract review is owed before the queue, the way objectui#12342's arm took one.
    Responsibility: objectui's @object-ui/types validator refuses two spec-18 blocks | no platform path covers it: the validator is objectui's own authoring face | every author or AI validating a record page that carries the approvals or attachments block, including the default record page objectui builds
    Thread-read: 6168991320
    Serial constraints cleared: the predecessor objectui#12342 (PR #12362, the same construction in the same files) landed as 52d6194. The in-flight objectui#12370 bump may touch packages/types if 18.0.0-next.1 turns a types test red; whichever lands second merges main (read 2026-10-14T17:58Z).


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 12363,
      "status": "done",
      "branch": "claude/issue-12363-approvals-attachments-arms",
      "pr": "https://github.com/objectstack-ai/objectui/pull/12382",
      "session": "session_01XVp19E1MYUTFM3dnkwz8gB (parent's; subagent run)",
      "premise_still_valid": true,
      "summary": "New zod module packages/types/src/zod/record-panels.zod.ts adds RecordApprovalsBlockSchema and RecordAttachmentsBlockSchema, wired into AnyComponentSchema. Each properties bag restates its installed spec row (@objectstack/spec 18.0.0-next.0): both rows are strict and keyless, so each bag is z.strictObject({}).optional(). body/children are refused by name. The PR adds TS twins in packages/types/src/record-panels.ts (exported, plus two AnySchema members), two mirror-parity pairs (EXPECTED_MIRROR_PAIRS 196 to 198), two emit-headroom members, and lowers NAMESPACED_REFUSED_AT_TYPE 308 to 306 with a named row. Pins: per-arm bag equals the row, the node validates, undeclared keys are refused, and buildDefaultPageSchema's page validates whole on both faces. A1/A2/A3 hold. A2 has one boundary: when the host threads approvals.node (RecordDetailView passes approvals + currentUserId), the bag refuses both, because the spec row names them host runtime channels. This is the same as record:history's host entries. I pinned it as a refusal and did not widen the arm. #12370 had not landed; main moved one unrelated commit (fc211e817), so the rows were measured on next.0. Deviation: the default-page pin is a new test file in packages/plugin-detail/src/__tests__/, outside the named surface. types/cli cannot import plugin-detail (phantom-deps), and no plugin-detail source changed.",
      "tests": "Head 83d91d3. vitest under the verify lock, full packages/types/ + packages/cli/ + the plugin-detail pin: 'Test Files 409 passed (409)', 'Tests 10719 passed (10719)', VERDICT command-exit 0. Earlier targeted run (6 files incl. record-approval-decision-arm-12342, zod-mirror-parity, emit-headroom, ratchet): 129 passed. type-check of @object-ui/types, @object-ui/cli and @object-ui/plugin-detail (after building the dependency closure): all 'Done', exit 0. Ablation with ablation-replace.mjs --delete on the two union members in zod/index.zod.ts: anchor 1 to 0, blob cd2ce50 to 0f4b39f, 'Test Files 3 failed (3)', 'Tests 24 failed | 50 passed (74)'. That covers the ratchet pin and row, all 4 default-page rows and the union-path arm rows; bag-vs-row rows stayed green as predicted. Restored with blob == HEAD and an empty git diff HEAD. No build leg was needed because vitest aliases @object-ui/types to src. Gates exit 0: check:phantom-deps, self-import, unreferenced-sources, doc-example-readers, handler-key-reads, side-effects-array, element-data-source-declaration, spec-symbols, action-forward-parity, designer-field-key-parity, icon-record-names, i18n-keys, i18n-drift, i18n-designer-parity, registry-bare-names, control-bytes, new-line-citations (0 new citations); check-changeset-fixed/presence/no-major 0. check:spec-floors exit 1, 'The scan collapsed: 0 package(s) declare @objectstack/spec' (known objectui#12334; diff touches no dependency field). Lint narrowed to the 9 changed .ts files with eslint --format json, as the package lint scripts run it: 9 results, 0 errors, 0 warnings. With --no-inline-config: 3 findings, all on untouched lines already covered by inline disables. Not type-aware (no project/projectService in eslint.config.js), so untouched files' verdicts cannot move. Full pnpm lint belongs to CI. CI: in_progress at report time.",
      "mcp_calls": "0",
      "api_writes": "2 relay strokes as objectstack-fleet[bot] via fleet-write: (1) pr_create = POST /repos/objectstack-ai/objectui/pulls (draft) + POST /repos/objectstack-ai/objectui/issues/12382/assignees; (2) this os-dev-report comment = POST /repos/objectstack-ai/objectui/issues/12363/comments. Plus git pushes of the branch (empty-branch probe, 2 commits). Zero label writes: objectui path labels belong to labeler.yml, and the dispatch named no label.",
      "gates": {"vitest_types_cli_full": 0, "type-check_types_cli_plugin-detail": 0, "check:phantom-deps": 0, "check:self-import": 0, "check:unreferenced-sources": 0, "check:doc-example-readers": 0, "check:handler-key-reads": 0, "check:side-effects-array": 0, "check:element-data-source-declaration": 0, "check:spec-symbols": 0, "check:action-forward-parity": 0, "check:designer-field-key-parity": 0, "check:icon-record-names": 0, "check:i18n-keys": 0, "check:i18n-drift": 0, "check:i18n-designer-parity": 0, "check:registry-bare-names": 0, "check:control-bytes": 0, "check:new-line-citations": 0, "check:spec-floors": 1, "check-changeset-fixed": 0, "check-changeset-presence": 0, "check-changeset-no-major": 0, "eslint_narrowed": 0},
      "files_changed": [".changeset/12363-approvals-attachments-arms.md", "packages/types/src/zod/record-panels.zod.ts", "packages/types/src/record-panels.ts", "packages/types/src/zod/index.zod.ts", "packages/types/src/index.ts", "packages/types/src/__tests__/zod-mirror-parity.test.ts", "packages/types/src/__tests__/any-component-emit-headroom-11573.test.ts", "packages/types/src/__tests__/record-panels-arms-12363.test.ts", "packages/cli/src/__tests__/registered-types-validate-ratchet-10859.test.ts", "packages/plugin-detail/src/__tests__/buildDefaultPageSchema.validatesWhole-12363.test.ts"],
      "deviations": ["File surface: one new test file in packages/plugin-detail/src/__tests__/ carries the ruled buildDefaultPageSchema pin. No plugin-detail source changed; types/cli cannot depend on plugin-detail.", "One verify-lock attempt ended exit 99 (queue-timeout behind another seat's fields run); retried with the same slot and got the lock after 96s."],
      "open_questions": [],
      "out_of_scope_findings": ["Not filed, noted in PR Acceptance notes. The restated record:approvals bag loses the spec row's own unrecognized-key guidance text for approvals/currentUserId; it reports only a generic unrecognized_keys, and the arm's .describe() carries the guidance. Carrying the row's message would need @objectstack/spec/ui to export RecordApprovalsProps under a name, or the objectui#8317 boundary census to admit a ComponentPropsMap index. carrier: whoever lands the next spec bump that names the row; otherwise 承接者:无."]
    }

    Generated by Claude Code

  6. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Review: ACCEPT — objectui PR #12382 · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB · 2026-10-14T18:57Z

    Reviewed on GitHub at head 83d91d3, against triage's scope (6165654268) and the contract review on this head, not against the dev's report.

    • Shape: the PR is a draft against main. Its body opens Fixes #12363, the only closing keyword, followed by Clause-②: yes. The governed sweep reads NOT governed, 523 lines (+517 / −6).
    • Contract review: PASS, comment 6175931173 on PR feat(types): arm record:approvals and record:attachments from their spec rows (objectui#12363) #12382: Served-tier: CONTRACT_REVIEW_TIER, Head-sha 83d91d37f6… (this head), Local-runs: none.
    • Triage's scope is met:
      • two arms restating the spec rows (construction of objectui#12342);
      • NAMESPACED_REFUSED_AT_TYPE 308 → 306 with a named row;
      • pins: each block validates with its spec-declared props, an undeclared key is refused, and buildDefaultPageSchema's page validates whole on both faces.
    • A2 boundary, pinned, not widened: when the host threads approvals / currentUserId onto the node at runtime, the bag refuses both. The spec row names them host runtime channels, as with record:history's host entries. No runtime path hands that page to the validator.
    • Declared deviation, accepted: the default-page pin lives in packages/plugin-detail/src/__tests__/, because types / cli may not import plugin-detail (phantom-deps). No plugin-detail source changed.
    • Prose: the changeset matches the diff. Its body has one grammar slip ("buildDefaultPageSchema builds emits both"). It states nothing false and is not worth a cycle; it stays as written.
    • Acceptance note (noted, not filed): the restated record:approvals bag reports a generic unrecognized_keys where the spec row carries its own guidance text. Carrying that text needs the spec to export the row by name, or named tombstones like record:history's; the accept set is identical either way.
    • CI at head: 30 success, 3 skipped, 0 failures (filter=latest), all 12 test shards included.

    needs:contract-review is removed in the same stroke. Next: pr_ready + automerge_enable.


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB · 2026-10-14T19:30Z

    • Merged: PR feat(types): arm record:approvals and record:attachments from their spec rows (objectui#12363) #12382 merged through the merge queue as main 2b4d3f1. The card closed completed by the PR's Fixes #12363, which is the only closing keyword. No other card closed with it.
    • Verified by content: on origin/main, all 10 files the PR touches are blob-identical to the accepted, contract-reviewed head 83d91d3. They include:
      • record-panels.zod.ts, record-panels.ts, zod/index.zod.ts and index.ts;
      • the cli ratchet;
      • the mirror-parity and emit-headroom pins;
      • the plugin-detail default-page pin;
      • .changeset/12363-approvals-attachments-arms.md.
    • Label: pm:dispatched is removed in the same stroke as this comment.

    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

area:recordsBusiness objects, records, the views that show data, usable forms, searchbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p2target:v18

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions