Skip to content

docs(spec): relatedList describe states each value's role, not the record page's tabs - #29799

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-vud2s3
Nov 3, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-vud2s3

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

domain:spec#3 · os-support-ai · session_01WGufzgh6TyUUCFMAfapZqb

Requested by Yibo Wang · project thread

Fixes #28888
Ruling-ref: 6568787922

Clause-②: no
Metadata-protocol: none
Skills-docs: none — this PR moves no skill text. One skill sentence still names the old chrome for the same placement, skills/objectstack-data/rules/relationships.md:345-348 ("in the Details tab, no tab of its own", "a side card"); it is out of this card's file surface (spec only) and is reported to the seat for its own card.

维护者速读

  • 改了什么:relatedList 字段的说明文字(.describe() 与上方 TSDoc)不再提任何标签页或栏位:false = 父记录页不显示该子对象;true 或不写 = 记录页上的一个辅助面板;'primary' = 记录详情主体里的一张通栏表格。版式只引 ADR-0085,不复述。
  • 为什么改:裁决 6568787922(字母 B)。旧文字描述的共用「Related」标签和「Details」标签在现在的记录页上已不存在,AI 作者照着读会把用户引向不存在的标签。
  • 风险与回滚:只改文字,不动键、默认值、可接受值;@objectstack/spec patch。生成的参考页(field / object / migration 三页的同一行)随之重生成。回滚即还原本 PR。
  • 先看:packages/spec/src/data/field.zod.ts(describe 与 TSDoc)、packages/spec/src/data/record-page-describes.test.ts(原来钉着旧措辞的用例改钉新措辞,并加一条「不提 tab / column / Related / Details / side card」)。
  • 两分钟验证:pnpm --filter @objectstack/spec exec vitest run src/data/record-page-describes.test.ts 全绿;换回 origin/main 的 field.zod.ts 再跑,2 条红。
  • 需要你做的:无,席位落地。

What changes

packages/spec/src/data/field.zod.ts, the relatedList .describe() and the TSDoc block above it. Every other clause keeps its meaning: the master_detail + inlineEdit 'primary' default, relatedLists ordering, and the derived-list sort sentences are unchanged.

Before (the value clauses):

false = suppress; true/absent = shown as a supporting list, a side card in the record's related column (the shared "Related" tab on the tabbed page); 'primary' = part of the record's main content, drawn in the record's body (the details column, after its first field section) as a full-width table (inside the Details tab on the tabbed page, with no tab of its own). Absent on a master_detail field that sets inlineEdit, the list is 'primary' by default; write true to keep it a side card. 'primary' places a list and does not order it: the parent object's relatedLists orders the body tables and the side cards (ADR-0085).

After:

false = the child object is not shown on the parent record page; true/absent = shown as an auxiliary panel on the record page; 'primary' = part of the record's main content, shown as a full-width table in the record's detail body. Absent on a master_detail field that sets inlineEdit, the list is 'primary' by default; write true to keep it an auxiliary panel. 'primary' places a list and does not order it: the parent object's relatedLists orders the full-width tables and the auxiliary panels. The page layout is defined by ADR-0085.

The TSDoc drops "related column", "shared "Related" tab", "details column", "Details tab ... no tab of its own" and "side card" the same way, and adds one line saying the layout is ADR-0085's to define. It keeps the sentence that a field group's relatedList can place a primary list among the field sections, since that is a real placement key, not page chrome.

Generated: content/docs/references/data/field.mdx, data/object.mdx, system/migration.mdx (the same relatedList row; check:generated --fix, then check:generated clean).

Why

Ruling 6568787922, letter B: the describe states the field's meaning, not the page's chrome, so the next layout card under #26676 does not make it wrong again.

Verification

  • Acceptance: git grep -n 'Related tab\|Details tab' -- packages/spec/src/data/field.zod.ts is empty at head.
  • record-page-describes.test.ts: the [#27312] case that pinned "the details column, after its first field section" and "inside the Details tab on the tabbed page, with no tab of its own" now pins the three new value clauses and the ADR-0085 sentence; a new case refuses tab(s), column, "Related", Details and side card in the describe. Red first: with origin/main's field.zod.ts, Tests 2 failed | 9 passed (11); restored, green.
  • pnpm exec vitest run src/data/record-page-describes.test.ts src/data/field.test.ts under os-verify-lock: Tests 303 passed (303), VERDICT command-exit 0.
  • Derived gates: dispatch-gates --commands derived 102 families at 9a801adf; 95 exit 0, 0 red, 7 NOT MEASURED (exit 3, prerequisite not met: check-plugin-teardown-shape --self-test needs its pinned fixture commit in this shallow clone; check:doc-formula-expressions, check:doc-security-posture, check:skill-examples, check:docs-transcript-drift, check:dual-build-cjs-loads, check:lean-entry-closure need a full build). dispatch-gates --ran: 102 accounted, 0 unrun. CI covers the 7.

Acceptance notes

Grep of packages/spec/src/** for the record page's "Related" / "Details" tab and its columns, other than this describe:

  • src/data/record-page-describes.test.ts (the old pin, changed here).
  • src/data/object.zod.ts:1251,1273 and src/data/object.form.ts:113: fieldGroups[i].relatedList says "details column", "body table" and "side card". That is a different key (a field group's placement), so per the order it is reported, not fixed.
  • src/migrations/entries/semantic/18.field-group-related-list-side-card-refused.ts: migration history text, left as it is.

Human Minimum

None; the seat lands it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WGufzgh6TyUUCFMAfapZqb

…cord page's tabs

false = not shown on the parent record page; true/absent = an auxiliary
panel; 'primary' = a full-width table in the detail body. The layout is
cited as ADR-0085 instead of naming the retired "Related"/"Details" tabs
and the page's columns. TSDoc, generated references and the describe
pin follow.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WGufzgh6TyUUCFMAfapZqb
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation protocol:data tests tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface labels Nov 3, 2026
@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec, touching 1 documentable anchor(s).

11 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/concepts/metadata-driven.mdx (via FieldSchema (symbol, a top-level const))
  • content/docs/data-modeling/external-datasources.mdx (via FieldSchema (symbol, a top-level const))
  • content/docs/data-modeling/field-types.mdx (via FieldSchema (symbol, a top-level const))
  • content/docs/data-modeling/validation-rules.mdx (via FieldSchema (symbol, a top-level const))
  • content/docs/deployment/troubleshooting.mdx (via FieldSchema (symbol, a top-level const))
  • content/docs/deployment/validating-metadata.mdx (via FieldSchema (symbol, a top-level const))
  • content/docs/getting-started/quick-reference.mdx (via FieldSchema (symbol, a top-level const))
  • content/docs/kernel/contracts/data-engine.mdx (via FieldSchema (symbol, a top-level const))
  • content/docs/protocol/backward-compatibility.mdx (via FieldSchema (symbol, a top-level const))
  • content/docs/protocol/objectql/types.mdx (via FieldSchema (symbol, a top-level const))
  • content/docs/protocol/objectui/concept.mdx (via FieldSchema (symbol, a top-level const))

⛔ 2 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v17/17-0.mdx (via FieldSchema (symbol, a top-level const))
  • content/docs/releases/v17/17-1.mdx (via FieldSchema (symbol, a top-level const))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • the SDK route bridge reached 61 of 219 client-bound route-ledger rows — the other 158 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 158: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 103 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 168 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 97c2982c001e106e846511e4cdc760ac66a3b2ed → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 534a82f27a378b8d9fc0b1093b91e315d6e8c7ef — the merge of head 9a801adf289bb527025710c50c57e4e3ecdf5183 into base 97c2982c001e106e846511e4cdc760ac66a3b2ed, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 534a82f27a378b8d9fc0b1093b91e315d6e8c7ef && git checkout 534a82f27a378b8d9fc0b1093b91e315d6e8c7ef
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 97c2982c001e106e846511e4cdc760ac66a3b2ed 9a801adf289bb527025710c50c57e4e3ecdf5183 && git checkout -B drift-repro 97c2982c001e106e846511e4cdc760ac66a3b2ed && git merge --no-ff 9a801adf289bb527025710c50c57e4e3ecdf5183

node scripts/docs-audit/affected-docs.mjs --json 97c2982c001e106e846511e4cdc760ac66a3b2ed

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 97c2982c001e106e846511e4cdc760ac66a3b2ed → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#3 · os-support-ai · session_01WGufzfgvGexKn9vLHsy89K

Contract review

Served-tier: TIER_DEFAULT
Head-sha: 9a801adf289bb527025710c50c57e4e3ecdf5183
Local-runs: none

Inputs read: card #28888 (decision card body, ruling 6568787922 letter B, the seat's claims 6595386663 and 6595407202, os-dev-report 6596124364), PR #29799 body and its six-file list, and the net diff against the merge base. reviewFace on the PR's paths: face declaration, no schema or governed hit, so this record is the lane seat's at TIER_DEFAULT.

① Derived judgments

② Semver level

  • .changeset/28888-related-list-describe.md: '@objectstack/spec': patch. The PR body carries Clause-②: no and Metadata-protocol: none, as the ruling binds, and the dev reports check-changeset-no-major exit 0 against the body. The meaning an author reads is unchanged (unlike a reversed promise, which would be semantic), so none at patch is right.

③ Boundary flags

  • Deviation 1, the test file outside the claimed surface: accepted. It pinned the stale phrase, so the describe fix moves it by necessity.
  • Deviations 2 and 3 (the red-first swap overlapping the gate run's start, the kept worktree) are process notes; the gates that read the file ran after it and are green at this head.
  • Gates: 102 derived, 95 exit 0, 7 exit 3. The 7 are prerequisite exits (a shallow fixture and six that need a full build), and CI's check-runs answer them.
  • Out of scope, seat-carried: skills/objectstack-data/rules/relationships.md:343-348 still teaches the old chrome for the same placement. It is governed and token-ratcheted, so it goes to the skills lane, not this PR. The fieldGroups[i].relatedList wording in object.zod.ts and object.form.ts names no tab; left, as the order says.
  • open_questions: none.

Implemented-by: claude/project-thread-vud2s3
Reviewed-by: session_01WGufzfgvGexKn9vLHsy89K

VERDICT: PASS

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#3 · os-support-ai · session_01WGufzfgvGexKn9vLHsy89K

维护者速读

席位意见:裁决 B 的验收条款逐条满足,而且被新的 pin 固定在 CI 里;技能文本里同样的旧说法已由 skills 车道立卡 #29801;同意落地。

席位核对 — ACCEPT · domain:spec#3 · head 9a801adf289bb527025710c50c57e4e3ecdf5183

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation protocol:data size/s tests tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface

Projects

None yet

1 participant