Skip to content

docs(ui): generate the component reference for all 106 components from sdui.manifest.json; retire the Setup, Console and Studio pages into the metadata pages and rename the section User Interface - #27179

Merged
os-zhuang merged 11 commits into
mainfrom
claude/project-thread-7ka124
Oct 28, 2026
Merged

os-zhuang merged 11 commits into
mainfrom
claude/project-thread-7ka124

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Requested by Tesla · project thread

Fixes #27142

Clause-②: no
Metadata-protocol: none

Tier H: the diff edits .github/workflows/lint.yml (one new gate step), so the maintainer lands it.

维护者速读

  • 改了什么: 新增 scripts/gen-sdui-reference.mjs,从根目录 sdui.manifest.json 生成文档站的「组件参考」(content/docs/ui/components/:7 个分类页加 1 个索引页),一次覆盖全部 106 个组件,每个组件列出输入项的类型、可选值、是否必填和说明。lint 新增一步 pnpm check:sdui-reference:manifest 变了而参考页没重新生成,这一步就红。
  • 为什么改: 106 个可编写组件里有 89 个过去没有自己的文档页,输入项说明只存在于 manifest 文件里。manifest 由 CI 对照渲染器校验,参考页从它生成,就不会像 17 个手写页那样与渲染器脱节。
  • 风险与回滚: 只新增文档页、一个脚本和一个 lint 步骤,不发布任何包;另把这个目录登记为「生成物」(文档审计范围、合并驱动、role-word 扫描、os-regen-merge 分类四处名单)。回滚 = revert 本 PR。
  • 先看: ① scripts/gen-sdui-reference.mjs 的 pageFor()(分页规则)和 cellText()(MDX 转义);② .github/workflows/lint.yml 新增的那一步;③ scripts/check-role-word.mjs 的 SKIP_SUBTREES。
  • 两分钟验证: 运行 node scripts/gen-sdui-reference.mjs --check,应看到 ✓ … matches sdui.manifest.json (106 components on 7 pages);或在预览站打开 /docs/ui/components,索引表有 106 行。
  • 范围扩大(按你 12:23Z 的两条裁定:「删掉」「板块名用 User Interface」): 删掉 ui/ 下的 setup-app、console、studio 三页。三页中写给元数据作者的内容并入 apps、views、actions、automation/approvals 和 deployment/validating-metadata;产品导览统一指向 build-without-code。栏目名从「Views & Apps」改为「User Interface」。另加 3 条跳转,并改了 1 条旧跳转,避免形成跳转链。
  • 需要你做的: Tier H(改了 workflow),需要你审批并合并。

Wider scope on head 906bbcaa (maintainer rulings)

In the K3 card thread on 2026-10-28 at 12:23Z, Tesla answered 「删掉」 to retiring the three Console-tour pages under content/docs/ui/ and 「板块名用 User Interface」 to the section name. Head 906bbcaa (on top of a merge of main, f4815b07) carries both:

Retired page Where its author-facing facts went
ui/setup-app.mdx ui/apps.mdx: navigationContributions and the Setup group anchors
ui/console.mdx ui/views.mdx: the record overlay and per-user list state. ui/actions.mdx gains a troubleshooting line, automation/approvals.mdx the record tab, and deployment/validating-metadata.mdx _diagnostics, the sweep endpoint and runtime predicate failure. The product tour is build-without-code.
ui/studio.mdx the same targets as console; the tour is build-without-code

Other changes:

What changes

  • scripts/gen-sdui-reference.mjs (new). Reads sdui.manifest.json and writes content/docs/ui/components/. Modes: write (default), --check (exit 1 when the committed pages differ, naming the file and the first differing line), --self-test (20 rows, a pinned battery roster and floor, and the verdict handshake, copied from check-agent-model-declared.mjs).
  • Layout: one page per namespace, with two grouping rules. At 106 entries a page per component would be mostly one-row pages, since 48 of them are HTML elements whose only inputs are className and children. So:
    • a component whose tier is html goes to HTML Elements (48);
    • all plugin-* namespaces share Plugin Blocks (16), because each holds one to three components;
    • every other namespace has its own page: Layout & Basic (ui, 14), Page Structure (page, 7), Record (11), Elements (6), Actions (4).
    • A namespace the manifest gains with no page row is refused, with the remedy, so a person writes its title and introduction once.
  • Each component is an h2 with an explicit id (action:button becomes #action-button), a line with its namespace, tier and whether it is a container, and an inputs table: name, type (unions, enum values, the array element type and the data binding included), required, description. Manifest descriptions are escaped for MDX: braces, angle brackets and pipes outside code spans, and pipes inside them.
  • The index page links all 106 components to their anchors.
  • Every page carries an AUTO-GENERATED comment and a visible callout that name the regeneration command.
  • Absence is loud. An unknown component key, input key or tier value is refused rather than silently omitted from the reference. So are an empty manifest, a key that is not its component's type, and two components whose heading ids collide.
  • Drift check wiring. Root aliases check:sdui-reference (--self-test then --check) and gen:sdui-reference. A new lint.yml step in job lint-repo-tooling (Lint · repo & tooling gates) runs pnpm check:sdui-reference, placed next to the manifest's own check, so a manifest change and its reference change land in one PR. It needed a workflow edit because every gate in this repo is wired as its own lint step; no existing family runs an arbitrary root alias.
  • Navigation. content/docs/ui/meta.json lists components after setup-app. content/docs/ui/index.mdx gains the matching card, which check-section-landing-index requires.
  • The directory is registered as generated in the four places that keep such a list:
    • scripts/docs-audit/affected-docs.mjs excludes content/docs/ui/components/** from the hand-written audit scope beside references/. handwritten-docs.json is regenerated and its readme names both trees. The maintainer ruling recorded in that file's header is that prompting authors about generated pages is wrong advice.
    • scripts/regen-artifacts.mjs gets a REGEN_ARTIFACTS row, and .gitattributes routes the directory to merge=os-regen. check:merge-driver requires every generator to have a recorded disposition. The pages are rendered whole, so regenerating after a merge loses nothing a person wrote.
    • scripts/check-role-word.mjs adds the directory to SKIP_SUBTREES, beside references/ and protocol-upgrade/, for the reason its header gives: the fix site is the input description in the component's registration under ui/, which this gate does not scan.
    • scripts/pm/os-regen-merge.sh classifies the directory in OS_REGEN_CLASSES as whole (commit a6ea420). CI's os-regen-merge self-test requires every merge=os-regen path to have a class; dispatch-gates did not derive that family locally, so it was first seen red on CI.

Why

A metadata author placing a component finds no page of its own for 89 of the 106 authorable components today. Their inputs and descriptions exist only inside the manifest file. The manifest is regenerated and compared by CI's Build & E2E UI, so a reference generated from it cannot drift from the renderer the way the 17 hand pages could.

Tests

  • node scripts/gen-sdui-reference.mjs --self-test: 20 cases pass, 20 batteries at their floor.
  • node scripts/gen-sdui-reference.mjs --check on the PR head: ✓ … matches sdui.manifest.json (106 components on 7 pages).
  • All 106 manifest types are headings, each on exactly one page. The generator asserts this on every run, and the self-test row "the real manifest renders every component on exactly one page" asserts it against the live manifest.
One-time ablation: a hand-edited generated line makes --check exit non-zero

Through scripts/ablation-replace.mjs on the committed tree, which drops yes from the Required cell of tabs's defaultValue row in ui.mdx:

ablation-replace: anchor   x1 -> x0
ablation-replace: blob     b00794f278674100b6694fadeec925dabf73757f -> 657a3cff533551a8703d7fcb0dc33c282c636fc5
ablation-replace: ok mutation landed: anchor 1 -> 0, blob b00794f27867 -> 657a3cff5335
ablation-replace: running: node scripts/gen-sdui-reference.mjs --check
✗ gen-sdui-reference --check: content/docs/ui/components/ is not what sdui.manifest.json generates:
  - ui.mdx differs from the manifest's rendering, first at line 160:
      committed: "| `defaultValue` | `string` |  | — |"
      generated: "| `defaultValue` | `string` | yes | — |"
ablation-replace: command exited 1
ablation-replace: ok restored: blob == HEAD (b00794f27867) and `git diff HEAD` is empty

Acceptance notes

URL map for K4's redirects (#27145). The old objectui.org pages are under https://www.objectui.org/docs/... (ui/apps/site/lib/source.ts, baseUrl: '/docs'). The new pages are on the objectstack docs site:

Old path (objectui.org) New path
/docs/components (components/index) /docs/ui/components
/docs/components/basic/icon /docs/ui/components/ui#icon
/docs/components/basic/image /docs/ui/components/ui#image
/docs/components/basic/span /docs/ui/components/html#span
/docs/components/basic/text /docs/ui/components/ui#text
/docs/components/complex/table /docs/ui/components/html#table
/docs/components/data-display/alert /docs/ui/components/ui#alert
/docs/components/data-display/badge /docs/ui/components/ui#badge
/docs/components/disclosure/accordion /docs/ui/components/ui#accordion
/docs/components/form/button /docs/ui/components/ui#button
/docs/components/form/label /docs/ui/components/html#label
/docs/components/layout/box /docs/ui/components/ui#box
/docs/components/layout/card /docs/ui/components/ui#card
/docs/components/layout/container /docs/ui/components/ui#container
/docs/components/layout/flex /docs/ui/components/ui#flex
/docs/components/layout/grid /docs/ui/components/ui#grid
/docs/components/layout/stack /docs/ui/components/ui#stack
/docs/components/layout/tabs /docs/ui/components/ui#tabs

check-docs-redirects strips a #fragment before it resolves a destination, so the anchored targets are legal redirect destinations.

Worked examples the hand pages carry and the manifest lacks. None of it was copied into the generated pages:

  • Live demos (SchemaExample) on every one of the 17 pages. form/button has 15 (variants, sizes, icons, disabled and loading states); basic/text has 10; the rest have 1 to 4.
  • basic/icon: the section "name is identity, not the glyph", which covers the refused name-as-glyph node and the migrateIconNodeKeys converter from @object-ui/types for stored metadata.
  • layout/box: "Migrating from div". box reads children only, and an html page's div is refused at compile time with a refusal that names box.
  • basic/span: the deprecation of span for JSON-authored pages, which does not apply to the html tier, and its migration guide.
  • complex/table, layout/* and the others: hand-written TypeScript Schema interfaces. Where these differ from the manifest, the manifest is the contract.

Observations, not filed:

  • content/docs/ui/pages.mdx § Components lists record:chatter, element:image, element:record_picker and element:text_input, which are not in the public manifest. The manifest carries record:discussion, element:definition-list and element:repeater, which that list omits. That list may be describing the spec's PageComponentType rather than the public tier, so this is noted for K2's merge of the UI pages, not filed.
  • The object-kanban input cardFields uses the word "role" in its description, a reserved word under ADR-0090 D3. The fix site is that registration's description under ui/, outside this card's surface. Triage's contract review (6467314546) asked for a carrier card. The dispatching seat screened it out under the filing gate's business test: the phrase is "the object's highlightFields role", which means ADR-0085's semantic field role, not an access-control role. No reader is misled about permissions, and check-role-word's own header says not every hit is a bug (its examples are ARIA role and sys_member.role). If the word should still change, the next PR that edits ui/packages/plugin-kanban/src/index.tsx can say "designation".
  • The serial constraint with K2 (docs(ui-merge): merge the 46 objectui field, Console-behaviour and schema pages into the objectstack docs (K2) #27170) stands: both edit content/docs/ui/meta.json, so whichever lands second merges main.

Verification

CI on head c935c785 (merges main after K2 #27170 landed; content/docs/ui/meta.json and the UI landing index list console, studio, components in that order): every required context is green (Lint & Repo Gates, TypeScript Type Check, Test Core, Build Core, Governed Surface Queue Guard, Lint UI, Type Check UI, Test UI, Build & E2E UI), Build Docs is green, and mergeable_state reads clean.

Local, on head ca0a9747, which merges main at b8615afa:

  • pnpm --filter @objectstack/docs build: green (os-verify-lock VERDICT command-exit 0). Served with next start, /docs/ui/components/plugins answers 200 with 16 tables and id="object-grid", and /docs/ui/components answers 200 with 107 table rows (106 plus the header).
  • node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran …: 99 derived families, 98 run green, 1 NOT MEASURED (check:dual-build-cjs-loads, exit 3, which needs every published package's dist and so is left to CI).
  • First-run reds the sweep found, each fixed in this PR and re-run green: check-section-landing-index (the landing card), check:docs-audit-scope (the generated-tree exclusion), check:merge-driver (the REGEN_ARTIFACTS row) and check:role-word (SKIP_SUBTREES). check:pm-dispatch-gates was red once because it ran while those edits were in progress; it was re-run on the committed tree and is green.
  • The gate families CI runs are read from this PR's check-runs, not re-run locally.

Human Minimum

  • 1. Schemas start as Zod; packages/spec holds no runtime logic. (No spec change.)
  • 2. Every name I added uses the casing for its kind.
  • 3. No formatter ran; pnpm lint is CI's to run.
  • 4. One issue, one branch off an up-to-date main, one pull request.
  • 5. Nothing publishes, so there is no changeset (skip-changeset); both declaration lines are filled in above.
  • 6. packages/spec not touched.
  • 7. No hand edits to content/docs/references/, packages/*/CHANGELOG.md or content/docs/releases/.
  • 8. Title, body and comments are in English.

🤖 Generated with Claude Code

https://claude.ai/code/session_01L9qibwMyAnTNeas3ANYhyi


Generated by Claude Code

…ith a drift check

scripts/gen-sdui-reference.mjs renders content/docs/ui/components/ from the
repo-root manifest: one page per namespace (html-tier elements and the
plugin-* blocks each share a page), every input as a table row, and an
index linking all components. --check fails when the committed pages
differ; lint.yml runs it next to the manifest's own check.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9qibwMyAnTNeas3ANYhyi
… audit scope and the merge driver

The docs-accuracy audit's hand-written scope now excludes
content/docs/ui/components/** beside references/, and the directory is
routed to the os-regen merge driver with gen:sdui-reference as its
regeneration.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9qibwMyAnTNeas3ANYhyi
…n, beside the other generated trees

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9qibwMyAnTNeas3ANYhyi
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 28, 2026
@github-actions github-actions Bot added size/xl ci/cd dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation labels Oct 28, 2026
@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs.

What this run could not see

Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 9ff8154cf694c616de5d467b35af21e037de1509 → packageMentionDocs.

…n os-regen-merge's table

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9qibwMyAnTNeas3ANYhyi
# Conflicts:
#	content/docs/ui/index.mdx
#	content/docs/ui/meta.json
@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 28, 2026 10:04
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

Contract-review-claim: session_01AavokzJ5DndAwitDXvKy4U · head c935c785ba2f027a10ad106b788c72a5ee8d129f · 2026-10-28T10:55Z

Triage seat, under the gap rule (#27062), condition (b). This PR touches a governed path (.github/workflows/lint.yml), and the head has been ready for more than one round with no ## Contract review record and no claim. Triage runs the review at CONTRACT_REVIEW_TIER. If the lane claims or posts a record on this head first, triage withdraws.


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: c935c785ba2f027a10ad106b788c72a5ee8d129f
Local-runs: none
Scope: .github/workflows/lint.yml + package.json (the check:sdui-reference and gen:sdui-reference aliases the step runs), scripts/gen-sdui-reference.mjs (the gate behind the alias), sdui.manifest.json and scripts/check-sdui-manifest.mjs (the input and the neighbouring step the hunk cites), content/docs/ui/components/** (the output the gate compares; read, not reviewed), scripts/ci/lane-verdict.mjs (reads the step), .gitattributes with scripts/regen-artifacts.mjs and scripts/pm/os-regen-merge.sh (the merge=os-regen routing of the generated tree)

① Derived judgments

  • No existing check is narrowed or skipped — right. git diff origin/main prr-27179 -- .github/workflows/lint.yml .gitattributes is 12 insertions, 0 deletions. lint.yml gains one gate step (Component reference matches the SDUI manifest, id component-reference-matches-the-sdui-manifest) at line 1022, between sdui-manifest-is-present-intact-and-fresh and the pm-dispatch SKILL.md ratchet. No if:, no paths filter, no step removed or reordered.
  • Trigger and permission scope unchanged — right. on: still reads push(main) / pull_request / merge_group / schedule / workflow_dispatch; the job lint-repo-tooling keeps permissions: contents: read and timeout-minutes: 30. No new uses: line, so the pinning convention (actions/checkout@v7, the local ./.github/actions/setup-workspace composite) is not touched by this PR.
  • The step is wired the way this file requires — right. GATE INVOCATION IDIOM (lint.yml lines 126–158): a new gate gets a root check:* alias of exactly --self-test then the gate and CI runs pnpm check:thing. package.json:42 is node scripts/gen-sdui-reference.mjs --self-test && node scripts/gen-sdui-reference.mjs --check; the step runs pnpm check:sdui-reference. EVERY GATE RUNS (lines 168–190): unique id: plus continue-on-error: true, and the lane's last step Lane verdict reads the roster out of the workflow and each gate's outcome from toJSON(steps). Measured on the head, GitHub job 122740964452 (Lint · repo & tooling gates, conclusion success): step 19 SDUI manifest is present, intact and fresh at the objectui pin success, step 20 Component reference matches the SDUI manifest success, step 65 Lane verdict success; aggregate Lint & Repo Gates success. scripts/pm/dispatch-gates.mjs derives the family from either spelling and takes its watch hints from the module-body literals sdui.manifest.json and content/docs/ui/components; Lint · PM dispatch-gates is green on the head.
  • The freshness gate is measured correctly — right. --check renders the committed sdui.manifest.json in memory (renderReference) and compares every rendered file byte-for-byte with the committed one (diffReference), naming the first differing line; a missing page and a file the generator did not write (meta.json and index.mdx included) are both drift. The manifest's own freshness is not this step's claim and is held where it is built: ci.yml Build & E2E UI step "The committed SDUI manifest is the one this tree generates" (ci.yml:4306, filtered on sdui.manifest.json and the registry inputs) regenerates and git diff --quiets it; a hand edit to the manifest reds check-sdui-manifest check 2 (sha256 vs the provenance record) in the step above. So the chain registry → manifest → pages is closed at every link on pull_request and merge_group, with the pages link unfiltered.
  • The committed reference is the generator's output — right. Read, not run: the head manifest holds 106 components (48 tier: html, 58 untiered; namespaces ui 62, record 11, page 7, element 6, action 4, eleven plugin-* 16); the seven pages carry exactly 106 headings of the form ## type [#id], with zero manifest types missing and zero headings not in the manifest; index.mdx has 106 table rows; meta.json lists ui, page, record, element, action, plugins, html, equal to PAGE_ORDER. The head's green step 20 is the byte-level measurement.
  • .gitattributes content/docs/ui/components/** merge=os-regen — right. It is one row with its two required companions: the REGEN_ARTIFACTS row (gen:sdui-reference / check:sdui-reference, owner: ROOT_OWNER, both aliases present in the root manifest) and the OS_REGEN_CLASSES row whole. whole is the true class: writeReference removes every entry of the directory that is not in the rendering before writing. CI's check:merge-driver and the os-regen-merge self-test reconcile both tables against .gitattributes in both directions and are green. The driver is local; the GitHub merge queue runs no custom driver, and the lint step above is what catches a textual merge of two manifest-changing branches there.
  • Public surface — right. Nothing under packages/* or ui/packages/* changes; the docs site gains the components section (content/docs/ui/meta.json after studio, which is the post-K2 order) and its landing card.
  • PR body claim judged wrong (prose, not tree): the body says the step lives in Lint · docs & code guards. It does not: lint-docs-code starts at lint.yml line 2024; the step is at line 1022 inside lint-repo-tooling (Lint · repo & tooling gates), which is where the manifest check lives and the right lane for it. The tree is right; the account is wrong. Should-fix: correct the body.
  • Tier H — right. A .github/workflows/** edit; the PR is out of draft on a green head, the maintainer lands it.

② Semver level

skip-changeset label present, Clause-②: no, Metadata-protocol: none; Check Changeset skipped on the head. The diff publishes nothing: no file under any published package, two new scripts in the private root package.json, docs content and tooling. The level is correct and the Clause-②: line matches the diff.

③ Boundary flags

  • open_questions: [] — nothing to answer.
  • Tier H flag — answered: workflow edit, maintainer merge; green on the head.
  • Serial constraint with K2 (content/docs/ui/meta.json) — answered: the head merges main after K2 landed; the hunk context reads setup-app, console, studio, components.
  • check:dual-build-cjs-loads NOT MEASURED locally — answered by CI: every lane and both aggregates are green on the head.
  • out_of_scope_findings[0] (pages.mdx § Components vs the public manifest) — carried to K2 docs(ui-merge): fold objectui.org into objectstack docs, K2 — merge the 46 field, Console-behaviour and schema pages into the existing objectstack pages #27141, per the report protocol in .claude/agents/os-dev.md:377. Accepted.
  • out_of_scope_findings[1] (object-kanban cardFields description uses the ADR-0090 D3 reserved word role) — carrier: none, placed in the PR's Acceptance notes as the protocol allows. Escalated here, should-fix: the word is in the generated page (content/docs/ui/components/plugins.mdx:272, "highlightFields role"), and this PR's SKIP_SUBTREES entry is what stops check:role-word seeing it; ui/ is outside that gate's ROOTS (content/docs, skills), so after this PR no gate holds the finding. The skip itself is correct (the gate's header rule for generated trees; the fix site is forbidden to this card), but the finding needs a carrier — a card for the kanban registration's description under ui/.

④ Design judgment

.github/workflows/lint.yml — the rule (one check:* alias runs self-test then --check) and the gate (one lane step, verdict kept by Lane verdict), read as one against scripts/ci/lane-verdict.mjs, the GATE INVOCATION IDIOM, scripts/gen-sdui-reference.mjs and the scenario it is accepted against (a manifest change without a regenerated reference goes red in the same PR).

Holds. Tried to break it:

  • No id: or no continue-on-error — both present and the id is unique in the file, so the verdict reads the outcome rather than redding the lane "unread".
  • Hand-edit one generated line — diffReference reports the file and first differing line (self-test row "check: one hand-edited line is drift", and the ablation the dev recorded; CI's row "the real manifest renders every component on exactly one page" runs against the live manifest on every run).
  • Delete a page, add a hand page, leave a page behind after its namespace leaves the manifest — missing and stray files are both drift; a write removes strays.
  • Change the generator's template without regenerating — the committed pages differ; red.
  • Manifest gains a component key, input key, tier value or namespace the generator does not render — refused with the remedy, exit 1; nothing is silently omitted. Enum, union, of and binding all reach the type cell.
  • Hand-edit the manifest — check-sdui-manifest check 2 (sha256) reds the step above; registry drift — ci.yml's regeneration step reds Build & E2E UI.
  • Description text that breaks MDX — cellText escapes { } < | outside code spans and | inside, keeps an unclosed backtick literal, and Build Docs compiles the pages on every PR whose diff touches content/docs, which a regeneration necessarily does.
  • Lane budget — the gate reads two tracked inputs and builds nothing; seconds against a 10-minute body budget.
  • No path filter, no if:, so the gate cannot go dormant on a queue build or a PR that moves only one side of its inputs.

Findings: no must-fix. Should-fix (non-blocking): (1) the PR body names the wrong lane for the step; (2) file a carrier for the role word in the object-kanban cardFields registration, which this PR's role-word skip removes from the gate's view.

.gitattributes (read with scripts/regen-artifacts.mjs and scripts/pm/os-regen-merge.sh): the routing is complete in all three registers, the class is true to the generator, and nothing about how CI treats the tree changes — CI never runs the driver; the lint step is the CI-side guard. Holds.

Implemented-by: claude/project-thread-7ka124
Reviewed-by: session_01AavokzJ5DndAwitDXvKy4U

VERDICT: PASS


Generated by Claude Code

…ction User Interface

The three pages described products rather than metadata. Their author-facing
facts move to the page that owns each behavior:

- apps: navigationContributions, the missing-anchor diagnostic and the Setup
  app's group anchors
- views: how a list opens a record (navigation.mode, ?recordId, the drawer
  stack), per-user list state never writing the view, the 403 for a gated view
- deployment/validating-metadata: the load-time _diagnostics envelope, the
  /api/v1/meta/diagnostics sweep, and what a predicate that cannot be
  evaluated does at runtime
- actions: why a placed action appears nowhere
- automation/approvals: the record's Approvals tab

The product tour stays in build-without-code. The old URLs answer 308s
(/docs/ui/setup-app to /docs/ui/apps, console and studio to
build-without-code), and /docs/concepts/setup-app is re-pointed so no chain
forms. The audit's hand-written list drops the three pages.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9qibwMyAnTNeas3ANYhyi
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract-review-handoff: triage — CONTRACT_REVIEW_TIER unavailable (maintainer rule 「契约复审都要等分诊」, the dispatching seat does not review, 2026-10-28T12:48Z) · head 906bbca

Delta review owed on 906bbcaa. The scope widened on Tesla's 2026-10-28T12:23Z rulings in the K3 card thread (「删掉」, 「板块名用 User Interface」): ui/{setup-app,console,studio}.mdx are retired and their facts folded into apps, views, actions, approvals and validating-metadata, the section is renamed, and there are 3 new redirects plus 1 re-pointed. The prior PASS 6467314546 covers c935c785. The body's new section "Wider scope on head 906bbcaa" lists where each fact went.


Generated by Claude Code

@objectstack-fleet objectstack-fleet Bot changed the title docs(ui): generate the component reference for all 106 components from sdui.manifest.json, with a drift check docs(ui): generate the component reference for all 106 components from sdui.manifest.json; retire the Setup, Console and Studio pages into the metadata pages and rename the section User Interface Oct 28, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract-review-handoff: triage — CONTRACT_REVIEW_TIER unavailable (maintainer rule 「契约复审都要等分诊」, the dispatching seat does not review, 2026-10-28T12:54Z) · head 3c36420

This supersedes 6469401570, whose head is now stale. On 906bbcaa the new check:sdui-reference step went red: main's fbe344b (#26966) renamed the action variant destructive to danger in sdui.manifest.json, and CI's merge ref picked that up. The head moved to fix it: bc0c9e7 merges main, and 3c36420 regenerates content/docs/ui/components/action.mdx, a 2-line change. The delta review covers everything since c935c785, the head of PASS 6467314546. That is the wider scope in the body section "Wider scope on head 906bbcaa", plus this regeneration.


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

Contract-review-claim: session_01AavokzJ5DndAwitDXvKy4U · head 3c36420c2b745ac8a0484d63ad5ce46f999f77a0 · 2026-10-28T13:10Z

Triage seat, taking the Contract-review-handoff: triage … line that names this head. The review runs at CONTRACT_REVIEW_TIER. If the lane claims or posts a record on this head first, triage withdraws.


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 3c36420c2b745ac8a0484d63ad5ce46f999f77a0
Local-runs: none
Scope: .github/workflows/lint.yml + package.json (the check:sdui-reference and gen:sdui-reference aliases the step runs), scripts/gen-sdui-reference.mjs (the gate behind the alias), sdui.manifest.json and scripts/check-sdui-manifest.mjs (the input and the neighbouring step the hunk cites), content/docs/ui/components/** (the output the gate compares; read, not reviewed), scripts/ci/lane-verdict.mjs (reads the step), .gitattributes with scripts/regen-artifacts.mjs and scripts/pm/os-regen-merge.sh (the merge=os-regen routing of the generated tree); delta since c935c785: the two merges of main (f4815b07, bc0c9e72), the page retirement 906bbcaa (apps/docs/redirects.mjs, content/docs/ui/**, scripts/docs-audit/handwritten-docs.json) and the regeneration 3c36420c

① Derived judgments

Review on a moved head. The last record (comment 6467314546) names c935c785; this one judges the four commits since in their own right, then re-confirms the earlier judgments on 3c36420c.

  • Merge f4815b07 (c935c78 + main d745bb5) — clean. git merge-tree --write-tree of its two parents gives tree 633ef6a8, identical to the commit's tree. No evil-merge content.
  • Merge bc0c9e72 (906bbca + main 9ff8154) — clean. Recomputed tree 33c46bf4 equals the commit's tree. No evil-merge content.
  • 906bbcaa "retire the Console, Studio and Setup app pages; name the section User Interface" — judged in its own right; outside hits. 14 files, 184+/584−: deletes content/docs/ui/{console,setup-app,studio}.mdx, folds their author-facing facts into ui/apps.mdx, ui/views.mdx, ui/actions.mdx, automation/approvals.mdx and deployment/validating-metadata.mdx, retitles content/docs/ui/meta.json to "User Interface" and drops the three slots, removes the three landing cards, adds three redirects and re-points one (/docs/concepts/setup-app → /docs/ui/apps, so no chain forms; nothing else in redirects.mjs targets the retired paths), and regenerates scripts/docs-audit/handwritten-docs.json minus the three pages. It touches nothing under .github/**, no gate script, no package.json, no .gitattributes. No inbound link to /docs/ui/console, /docs/ui/studio or /docs/ui/setup-app remains under content/, apps/docs/ or skills/; Check Documentation Links, Build Docs and Lint & Repo Gates (which holds check-docs-redirects, the anchors gate and check:docs-audit-scope) are green on the head. It is the lane seat's ACCEPT at TIER_DEFAULT; its premise (the 12:23Z rulings) is a boundary flag, in ③.
  • 3c36420c "regenerate the component reference after main renamed the action variant to danger" — right, and it is the freshness gate working as designed. main's fbe344b (feat(spec)!: the action blocks spell the destructive variant danger, the word ActionSchema.variant uses #26966) renamed the action variant enum value destructive → danger in sdui.manifest.json; on 906bbcaa CI's merge ref carried that manifest and the new step went red (the seat's handoff 12:54Z records it). The fix is a 2-line regeneration of content/docs/ui/components/action.mdx (destructive → danger on the action:button and action:icon rows). Read, not run, on the new head: the manifest still holds 106 components; the seven pages carry exactly 106 ## type [#id] headings, zero missing, zero extra; index.mdx has 106 rows; meta.json equals PAGE_ORDER; action.mdx has two danger cells and no destructive. The byte-level measurement is CI: job 122828446275 (Lint · repo & tooling gates, success on 3c36420c): step 19 SDUI manifest is present, intact and fresh at the objectui pin success, step 20 Component reference matches the SDUI manifest success, step 65 Lane verdict success; aggregate Lint & Repo Gates success.
  • The governed hunk is unchanged — right. The .github/workflows/lint.yml hunk in the head's net diff against main is byte-identical (index lines aside) to the one reviewed on c935c785: 11 insertions, 0 deletions, one gate step with a unique id: and continue-on-error: true, run: pnpm check:sdui-reference, inside lint-repo-tooling beside the manifest check. .gitattributes is still the one added row. Net against main for .github, .gitattributes, package.json and scripts/ is 784+/15− over the same 10 files as before. Triggers, permissions: contents: read, action pinning, lane budget: no change; no existing check narrowed or skipped.
  • Every earlier ① judgment re-holds on this head: idiom and verdict wiring (above); freshness chain registry → manifest → pages closed (ci.yml's regeneration step held the manifest side on main, this step held the pages side on the PR, and the red on 906bbcaa is the live proof); .gitattributes row with its REGEN_ARTIFACTS and OS_REGEN_CLASSES whole companions reconciled by the green check:merge-driver; public surface none.
  • Earlier should-fix (1), PR body named the wrong lane — taken. The body now reads "A new lint.yml step in job lint-repo-tooling (Lint · repo & tooling gates)".
  • Earlier should-fix (2), a carrier for the role word in object-kanban cardFields — answered, and the answer holds on my own reading. ui/packages/plugin-kanban/src/index.tsx:710 says "the object's highlightFields role". ADR-0085 §1 defines highlightFields as one of the four object-level semantic roles ("The four roles", table "Role | Question it answers"), and ADR-0090 D3 reserves role for the access-control sense (sys_role → position); check-role-word.mjs's own header lists the non-bug classes (ARIA role=, sys_member.role, quoted history). The phrase is ADR-0085's term of art, not a permission role; no carrier is owed. The body's Acceptance notes record the screening and name the alternative wording ("designation") for the next PR that edits that file. Resolved.
  • Tier H — right. Workflow edit; maintainer merges. mergeable_state reads blocked (pending check and the needs:contract-review label), not clean.

② Semver level

skip-changeset label, Clause-②: no, Metadata-protocol: none; Check Changeset skipped on the head. The delta publishes nothing: the dev's two commits touch content/docs/**, apps/docs/redirects.mjs and one generated register; the two merges bring main in unchanged. Level and Clause-②: line still match the diff.

③ Boundary flags

④ Design judgment

.github/workflows/lint.yml — unchanged since the PASS on c935c785, re-read against scripts/ci/lane-verdict.mjs, the GATE INVOCATION IDIOM, scripts/gen-sdui-reference.mjs (unchanged in the delta) and the scenario it is accepted against. Holds, and the delta supplied the field test the earlier record could only argue: main changed sdui.manifest.json under the PR, CI's merge ref carried it, the step went red on 906bbcaa with the file and line, and the regeneration 3c36420c made it green again — the "manifest change and reference change land in one PR" claim, observed. Earlier break attempts (missing id or flag, hand edit, missing or stray file, template change, unknown key or namespace, hand-edited manifest, registry drift, MDX-breaking text, no filter) all re-read the same on this head.

Findings: no must-fix. No open should-fix: both earlier should-fixes are taken or resolved.

.gitattributes (with scripts/regen-artifacts.mjs and scripts/pm/os-regen-merge.sh): unchanged; the two merges of main went through git's text merge (no driver on either side, trees recompute identically), and the pages' drift after them was caught by the lint step, which is exactly the CI-side guard the earlier record said covers the driver's absence. Holds.

Implemented-by: claude/project-thread-7ka124
Reviewed-by: session_01AavokzJ5DndAwitDXvKy4U

VERDICT: PASS


Generated by Claude Code

@os-zhuang
os-zhuang added this pull request to the merge queue Oct 28, 2026
Merged via the queue into main with commit 1287b2f Oct 28, 2026
66 checks passed
@os-zhuang
os-zhuang deleted the claude/project-thread-7ka124 branch October 28, 2026 13:55
os-tesla pushed a commit that referenced this pull request Oct 28, 2026
K3 #27179 renamed the content/docs/ui section from "Views & Apps" to
"User Interface"; the frontend landing's pointer follows it.

Claude-Session: https://claude.ai/code/session_01L9qibzngYyRjmvNxjkfVyd
Co-authored-by: Claude <noreply@anthropic.com>
os-support-ai pushed a commit that referenced this pull request Oct 28, 2026
…ons input retired

main's #27179 generates content/docs/ui/components/ from sdui.manifest.json;
the merged manifest no longer publishes list-view's options input.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WGufzevL8Q6rTfGz2XHXGT
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation size/xl skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

3 participants