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.

plugin-detail: record:related_list reads its declared actions and renders them on the related list, host-bridge actions as the default (objectstack#20665 ruling ENFORCE) #11163

Closed

Description

@objectstack-fleet

Child of objectstack-ai/objectstack#20665, filed by the director seat (objectstack#12708, session_01AsCNgFBs8HCjwhyHQsFbx3) on the maintainer's ruling ENFORCE (batch #247, 2026-09-30, 「业务上需要支持,ENFORCE」; the ruling record is on objectstack#20665). objectstack#20665 is pm:blocked on this card. ⛔ Not a claim.

What the ruling decided

record:related_list.actions (packages/spec/src/ui/component.zod.ts:1285, "Action IDs available for related records") is declared, published and parsed, and no renderer reads it. Under ruling A′ ④ (#18900) the maintainer chose ENFORCE on business need: a related list carries its own action buttons, as a Salesforce related list does (the standard New plus custom list buttons), and CRM authoring — hotcrm's included — configures actions per list.

What this card builds (objectui plugin-detail, record-related-list.tsx)

  • The renderer reads schema.actions: each action ID resolves through the existing action registry and renders on the list.
  • Host-bridge actions stay the default when actions is absent; when the author declares actions, the authored list is what renders (the composition rule the maintainer's letter implies — the seat states it in the PR and pins it).
  • An action ID the registry cannot resolve is refused loudly where the registry resolves it (an author-visible refusal, never a silently dropped button).
  • The parity ledger's last exemption, NO_READ_SITE_TO_PIN for this key (apps/console/src/__tests__/registry-inputs-spec-parity.test.ts), becomes a member pin, and MEMBER_PIN_EXEMPTION_CEILING goes 1 → 0.
  • Pins: authored actions render in order; absent actions renders the host default; an unresolvable ID is refused; the parity ledger holds no exemption.

Measurement the seat records first (it no longer flips the word)

Whether the host bridge already offers a per-list action configuration. If it does, the PR states how the two channels compose (authored actions wins, the bridge is the default) rather than treating the key as a duplicate; the maintainer's letter is ENFORCE either way.

After landing

objectstack#20665 closes: the spec key is unchanged, its liveness row flips to live with this pin as the read site.

Related: objectstack#20665 (the ruling), objectui#8071 (the parity population), objectui#7300 (the closed tracker this replaces), objectui#11113 (slice 18, the ceiling at 1).

Activity

  1. added
    enhancementNew feature or request
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    and removed on Sep 30, 2026
  2. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_0122Knsowci76D2rBWReCzzZ
    Account: os-warren (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-11163-related-list-actions
    Worktree: objectui-issue-11163
    Domain: domain:ui
    Seat: domain:ui#1
    File surface:

    • packages/plugin-detail/src/renderers/record-related-list.tsx: the renderer reads schema.actions and resolves each ID through the existing action registry. Host-bridge actions stay the default when actions is absent.
    • packages/plugin-detail/src/index.tsx: the record:related_list registration's inputs, only if actions must be declared there.
    • packages/plugin-detail/src/RelatedRecordActionsBridge* / RelatedList.tsx: only where the authored list replaces the bridge default.
    • apps/console/src/__tests__/registry-inputs-spec-parity.test.ts: the record:related_list.actions NO_READ_SITE_TO_PIN exemption becomes a member pin, and MEMBER_PIN_EXEMPTION_CEILING goes to 0.
    • Their pins, and one .changeset/11163-*.md.

    ⛔ Not RelatedToolbarButton's visible truthiness gate (objectui#11244, a finding awaiting triage). ⛔ Not DetailView.tsx (PR objectui#11246, seat 2). The dev stops on a breach and explains it in the report.
    Container & model: M, mode:subagent, model: opus (default judgment tier; dispatch-gates.mjs --tier answers no path-derived mandate for objectui paths)
    Clause-②: yes
    Thread-read: none
    Serial constraints cleared: read 2026-09-30T18:58Z at objectui origin/main. Open PR objectui#11246 (seat 2, objectui#9843) touches plugin-detail's DetailView.tsx, package.json and README.md, not the related-list files. No open PR touches record-related-list.tsx, RelatedList.tsx, RelatedRecordActionsBridge or the parity ledger. PR objectui#11237 (objectui#11212), which last edited RelatedList.tsx, merged as 8bab1571d9. area:records: no other card on this axis is in flight on these files.

    Scope: the maintainer's ruling ENFORCE on objectstack-ai/objectstack#20665 (batch #247, 「业务上需要支持,ENFORCE」), as the card body records it, and the card body's build list: authored actions render in order; absent actions renders the host default; an unresolvable ID is refused loudly; the parity ledger holds no exemption. PR says Fixes #11163.
    Clause-②: yes — why: a published block starts honouring a declared key it ignored (a behaviour change for every document that authors actions), and its registration may declare a new input. Unsure ⇒ yes.

    domain:ui seat 1 · claim · 2026-09-30T18:58Z


    Generated by Claude Code

  3. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
    "issue": 11163,
    "status": "done",
    "branch": "claude/issue-11163-related-list-actions",
    "pr": "#11263",
    "session": "session_0122Knsowci76D2rBWReCzzZ",
    "premise_still_valid": true,
    "summary": "record:related_list now reads its declared actions (ENFORCE ruling on objectstack-ai/objectstack#20665). Composition rule, stated in the PR and pinned: absent = the host bridge's list_toolbar/list_item actions unchanged, with no lookup; authored = the authored list replaces the default, in authored order, each id resolved against the related object's registered actions (useMetadataItem + resolveDeclaredActionIds, the record:quick_actions.actionNames lookup, no second registry) and placed by its own locations (list_toolbar = header, list_item = row menu), run by the bridge's executor; [] = no actions (New/Edit/Delete/View are not action ids and stay the host's). An unresolvable id, an id with no list location, or a non-id array is named in a role=status notice on the list (never while the lookup is in flight; the resolvable entries still render). Measured: the bridge has NO per-list channel (resolve is keyed on the child object), and the registration already declared actions, so index.tsx and the bridge are untouched. Parity ledger: the NO_READ_SITE_TO_PIN exemption becomes a MEMBER_PINS entry and the constant is deleted; MEMBER_PIN_EXEMPTION_CEILING goes 5 → 4, not 1 → 0 as the card says, because the objectui#11111 bookings owed to objectui#11168 (4 units) landed in between.",
    "tests": "RED FIRST at ae0b9d3 (renderer unmodified): vitest run packages/plugin-detail/src/tests/RecordRelatedListRenderer.authoredActions-11163.test.tsx → 'Tests 10 failed | 2 passed (12)', e.g. "expected [ 'invite', 'export_csv' ] to deeply equal [ 'export_csv', 'invite' ]". After the fix, same file → 'Tests 12 passed (12)'. ABLATION (fix committed at 0de68bb, via objectstack scripts/ablation-replace.mjs, anchor hit x1 → x0, blob 35704b30774d → e4cbb940b1ef): removing the in-flight guard → 'Tests 1 failed | 11 passed (12)', exactly 'CONTROL: no refusal is drawn while the lookup is still in flight'; restore: 'ok restored: blob == HEAD (35704b30774d) and git diff HEAD is empty'. No dist in the path (tests import the renderer relatively). FINAL head 95a8cd5 (branch merged with main af9e957 after PR objectui#11246 landed; pnpm install + deps rebuilt): build pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-detail^...' build → 'VERDICT command-exit 0'; pnpm --filter @object-ui/plugin-detail type-check (script name echoed) → 'VERDICT command-exit 0'; tsc -p tsconfig.test.json --listFiles lists the new test, relatedListActions.ts and record-related-list.tsx; vitest run packages/plugin-detail/src/tests/ → 'Test Files 144 passed | 1 skipped (145)', 'Tests 1296 passed | 8 skipped (1304)'; vitest run over the other 83 plugin-detail test files → 'Test Files 83 passed (83)', 'Tests 962 passed (962)'; vitest run over the 25 suites outside plugin-detail that git grep -l 'record:related_list' finds (incl. apps/console registry-inputs-spec-parity.test.ts) → 'Test Files 25 passed (25)', 'Tests 1020 passed (1020)'. Gates exit 0: check:action-forward-parity, check:component-surface-parity (REPORT-ONLY, no record:related_list row), check:handler-key-reads, check:new-line-citations ('VERDICT new-cross-file-line-citations: 0 new citation(s)'), check:control-bytes, check:doc-fences, docs:check-links, check-changeset-presence ('1 changeset(s): .changeset/11163-related-list-actions.md'), markdown-test-inputs --audit, check:doc-types, check:doc-example-ids, check:docs-route-closure, check:doc-example-readers, check:changeset-claims, check:pending-changeset-literals, check:test-path-roots, check:unreferenced-sources, check:spec-symbols, check:phantom-deps, check:element-data-source-declaration, check:action-ref-convention, check:self-import. eslint --no-inline-config on the 4 changed TS files: 0 errors, 17 warnings all on pre-existing lines of record-related-list.tsx (a narrowed run, not a measurement of the lint population). NOT MEASURED: check:doc-snippets and check:doc-examples (exit 2 PRECONDITION NOT MET, 34 packages unbuilt; they read TS fences / @example, the diff adds a json fence); check:sdui-registration-pins (exit 2, no console build; no registration changed); apps/console type-check and repo-wide pnpm lint (CI). CI on 95a8cd5 at report time: 42 check runs, 20 success, 3 skipped, 19 in_progress, 0 failed.",
    "mcp_calls": "0 - no MCP GitHub tool called",
    "api_writes": "3 - all through the fleet-write relay (POST /repos/objectstack-ai/objectstack/dispatches, landing as objectstack-fleet[bot]): (1) pr_create → POST /repos/objectstack-ai/objectui/pulls (draft, PR 11263); (2) label-write --assign os-warren → POST /repos//issues/11263/assignees; (3) this os-dev-report comment → POST /repos//issues/11163/comments. git push x4 (not REST).",
    "gates": {
    "build_deps": "exit 0",
    "type_check_plugin_detail": "exit 0",
    "vitest_plugin_detail": "228 files: 227 passed, 1 skipped; 2258 passed, 8 skipped",
    "vitest_outside_suites": "25 files passed, 1020 tests passed",
    "check:action-forward-parity": 0,
    "check:component-surface-parity": 0,
    "check:handler-key-reads": 0,
    "check:new-line-citations": 0,
    "check:control-bytes": 0,
    "check:doc-fences": 0,
    "docs:check-links": 0,
    "check-changeset-presence": 0,
    "markdown-test-inputs --audit": 0,
    "check:doc-types": 0,
    "check:doc-example-ids": 0,
    "check:docs-route-closure": 0,
    "check:doc-example-readers": 0,
    "check:changeset-claims": 0,
    "check:pending-changeset-literals": 0,
    "check:test-path-roots": 0,
    "check:unreferenced-sources": 0,
    "check:spec-symbols": 0,
    "check:phantom-deps": 0,
    "check:element-data-source-declaration": 0,
    "check:action-ref-convention": 0,
    "check:self-import": 0,
    "check:doc-snippets": "NOT MEASURED (exit 2 precondition)",
    "check:doc-examples": "NOT MEASURED (exit 2 precondition)",
    "check:sdui-registration-pins": "NOT MEASURED (exit 2 precondition)",
    "ci": "in_progress"
    },
    "line_budget": "n/a - no skills/** or governed surface touched (check-governed-queue-guard --test: NOT GOVERNED)",
    "files_changed": [
    ".changeset/11163-related-list-actions.md (+14 -0)",
    "apps/console/src/tests/registry-inputs-spec-parity.test.ts (+37 -45)",
    "content/docs/guide/slotted-pages.md (+32 -0)",
    "packages/plugin-detail/src/tests/RecordRelatedListRenderer.authoredActions-11163.test.tsx (+314 -0, new)",
    "packages/plugin-detail/src/renderers/record-related-list.tsx (+108 -2)",
    "packages/plugin-detail/src/renderers/relatedListActions.ts (+171 -0, new)"
    ],
    "deviations": [
    "MEMBER_PIN_EXEMPTION_CEILING 5 → 4, not the card's 1 → 0: the objectui#11111 decision 3 = B bookings (4 element:* units owed to objectui#11168) landed after the card was written; they are untouched.",
    "content/docs/guide/slotted-pages.md is outside the claim's file list; added under objectui AGENTS.md commandment #2 (docs-driven). The plugin-detail README was deliberately not touched (PR objectui#11246's surface).",
    "packages/plugin-detail/src/renderers/relatedListActions.ts is a new module beside the renderer (the pure resolve-and-place rule), so the renderer file keeps exporting components only.",
    "Merged main af9e957 into the branch after PR objectui#11246 landed (per the dispatch's same-day churn line); the full matrix was rerun on the merged head.",
    "Commit trailers use objectui AGENTS.md's model-free pair (Claude-Session + Co-authored-by: Claude) rather than the harness reminder's model-named trailer; PR footer uses the os-dev session-URL form. Both per the stated precedence.",
    "RelatedRecordActionsBridge, RelatedList.tsx and index.tsx are untouched: the bridge has no per-list channel and the registration already declared the key."
    ],
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: the seat that settles objectstack-ai/objectstack#20665 and flips its liveness row · noted, not filed · objectstack's action-name-undefined lint (validate-action-name-refs.ts, objectstack#20105) deliberately does not walk record:related_list.actions; now that the key renders, a misspelled id is refused only at runtime (the notice). Dedupe words: action-name-undefined, related_list actions, validate-action-name-refs, authoring-time refusal",
    "carrier: 承接者:无 · noted, not filed (no reach measured) · the record_related action location: spec ACTION_LOCATIONS JSDoc 'actions on a related list section inside a record' and the platform docs table 'Related-list sections', while the related list (bridge default and now the authored channel) places by list_item/list_toolbar; an action declaring only record_related and named in actions is refused by the notice. Dedupe words: record_related location, related-list sections, ACTION_LOCATIONS, related list placement",
    "carrier: 承接者:无 · noted, not filed · the bridge supplies onRowAction/onToolbarAction only when its own derived list for that surface is non-empty; authored placement uses the same rule over the same registry, so they agree whenever the bridge's objects and the MetadataProvider agree; on disagreement the authored surface is withheld (never a dead button). Dedupe words: onRowAction, onToolbarAction, RelatedRecordActionsBridge executor",
    "carrier: objectui#11244 (finding awaiting triage) · not touched · authored toolbar actions flow through RelatedToolbarButton, whose visible truthiness gate is that card's; no pin fixture declares visible, so it does not bite these pins"
    ]
    }


    Generated by Claude Code

  4. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    ✅ ACCEPT: PR objectui#11263 at 95a8cd520; ready and auto-merge follow this ACCEPT

    domain:ui seat 1 · session_0122Knsowci76D2rBWReCzzZ · 2026-09-30T20:35Z. Checked against the diff and the head's check-runs. Claim 5917731712; dev report 5919004096.

    • Contract review at CONTRACT_REVIEW_TIER: PASS on this head, which is the landing head (5919231109). Implemented-by: claude/issue-11163-related-list-actions, Reviewed-by: session_0122Knsowci76D2rBWReCzzZ.
    item reading
    the ruling: ENFORCE on objectstack#20665 (「业务上需要支持,ENFORCE」) record:related_list now reads its declared actions
    the composition rule (stated in the PR and pinned) Absent: the host bridge's list_toolbar / list_item actions, unchanged, with no lookup. Authored: the authored list replaces the default, in authored order. Each id resolves against the related object's registered actions through the existing record:quick_actions.actionNames lookup (useMetadataItem + resolveDeclaredActionIds; no second registry), is placed by its own locations, and is run by the bridge's executor. []: no actions. New / Edit / Delete / View are not action ids and stay the host's
    the loud refusal a role="status" notice on the list names every id that resolves nowhere or has no list location, and a non-id value. It is never drawn while the lookup is in flight (ablation: removing that guard reddens exactly the in-flight control), and the resolvable entries still render
    red first 10 of 12 red at base, then 12 of 12
    the parity ledger the record:related_list.actions exemption becomes a MEMBER_PINS entry, and NO_READ_SITE_TO_PIN is deleted. MEMBER_PIN_EXEMPTION_CEILING goes 5 → 4, not the card's 1 → 0. The review verified this against main's history: 1 → 7 at objectui#11073 after the card was written, 7 → 5 at objectui#11168; this diff only lowers it
    measured, not changed the bridge has no per-list channel, and the registration already declared actions. So index.tsx, the bridge and RelatedList.tsx are untouched
    semver @object-ui/plugin-detail minor: the accept set is unchanged, and a published block now honours a key it ignored. Clause-②: yes (the claim)
    CI head 95a8cd520: 43 runs, 40 success, 3 expected skips, 0 failure; Spec Main Shape Gate and all eight Test shards success
    main since the merge base the branch merged main (af9e9572c7) once, after PR objectui#11246 landed; the net diff is exactly the PR's 6 files. A test merge onto current main is clean
    scope / governed 6 files, +676 / −47; check-governed-merges.mjs: not governed. Fixes #11163. On landing, objectstack#20665's renderer half is met

    Out-of-scope findings:

    domain:ui seat 1 · ACCEPT · 2026-09-30T20:35Z


    Generated by Claude Code

  5. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR objectui#11263 merged as f4ed2387e9; closed completed

    domain:ui seat 1 · session_0122Knsowci76D2rBWReCzzZ · 2026-09-30T20:55Z.

    domain:ui seat 1 · landed · 2026-09-30T20:55Z


    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

No one assigned

    Labels

    area:recordsBusiness objects, records, the views that show data, usable forms, searchdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatenhancementNew feature or requestpriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions