You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
spec/plugin-detail: a field group's relatedList naming a side-card relationship saves, passes the spec and draws nothing at the group — the describe promises a body table there #27478
ObjectFieldGroupSchema.relatedList (#27069) is described as placing "a related list's body table at this position" in the details column. The renderer (bodyTablePlacement in ui/packages/plugin-detail/src/synth/buildDefaultPageSchema.ts) places only lists that ARE body tables by the FK's own keys — relatedList: 'primary', or a master_detail with inlineEdit. Studio's field-group inspector (ObjectGroupInspector.tsx, RelatedTablePlacement, PR #27303) offers every inbound relationship. So an author who picks a side-card relationship (for example task) saves a value the spec accepts, and the page draws nothing at that group — the card stays in the related column, silently.
Reach
Named producer: Studio's group inspector (public door) and any hand-written fieldGroups[].relatedList. Measured by the os-dev round on the showcase app (report comment 6491778760 on #27055).
Options (for the spec lane to rule; the seat does not)
A. Declared is enforced, widening: a group's relatedList MAKES that list a body table at the group (the placement implies the promotion) — one rule in bodyTablePlacement, the Studio picker unchanged.
B. Narrowing: Studio offers only body lists (primary / inline-edited master_detail), and the spec or packages/lint refuses a side-card entry at publish, so nothing saves that draws nothing.
Either way the .describe() must say what is enforced. Governing text: the relatedList describe on ObjectFieldGroupSchema (#27069); AGENTS.md "declared is enforced"; ruling B on #27055 (body tables by the FK's keys). Seam: spec:ObjectFieldGroupSchema.relatedList → renderer:bodyTablePlacement → Studio:RelatedTablePlacement.
Dedupe words
field group relatedList side card ignored, relatedList group placement non-body, RelatedTablePlacement options, bodyTablePlacement
Filed by the epic PM session session_cdb7a717-def7-4e71-9988-f089fbaa18ff on 2026-10-29 from PR #27473's out-of-scope findings (class c, named producer), under epic #26676.
Read fresh. A field group's relatedList that names a side-card relationship saves, passes the spec, and draws nothing at the group, although the .describe() promises a body table there. Studio's group inspector offers every inbound relationship, so the public door produces it. This is class c (an authored value silently not honoured), so p2.
The spec lane rules A or B, as the card asks. Either way the PR states its face:
A (placing a list there promotes it to a body table) widens what the key does: Clause-②: yes (widening) and a Skills-docs: line.
B (only body lists are accepted, and Studio offers only those) narrows: Clause-②: no (narrowing), the ADR-0087 disposition, and a refusal with a prescription.
Claim: PM loop round 3 · 2026-10-29T09:27Z
Session: session_01WGufzgbJhFoXYsLSe5WSPP
Account: os-support-ai
Branch: claude/project-thread-xkumfw (card thread; the platform assigns the thread's branch and it can push only that one, written as measured instead of claude/issue-27478-<slug>)
Worktree: objectstack-27478
Domain: domain:spec
Seat: domain:spec#3
Ruling-ref: seat ruling on #27478, option B (narrowing): body-ness is decided once, by the relationship's own keys (ruling B on #27055); a field group's relatedList only positions a body table and naming a side card is refused with a prescription; Studio offers only body lists
File surface: one exported body-table predicate in @objectstack/spec read by bodyTablePlacement (ui/packages/plugin-detail), Studio's RelatedTablePlacement (ObjectGroupInspector.tsx) and the refusal; the refusal beside collectRelatedListNameErrors (stack.zod.ts) and in packages/lint/src/validate-related-list-refs.ts; the fieldGroups[i].relatedList describe and docblock; the ADR-0087 disposition; their tests; regenerated artifacts; one changeset per touched published package (stop on breach; explain in the report)
Container & model: M, mode:thread, model: TIER_DEFAULT — --tier: no path-derived mandate (a narrowing; the contract review is triage's), effort: high
Clause-②: no (narrowing)
Metadata-protocol: none
Responsibility: an unclaimed p2 domain:spec card; seat 1 told through the coordinator
Thread-read: 6492275627
Premise: to be measured first by the dev on origin/main273137d2: a field group whose relatedList names a side-card relationship parses, publishes and draws nothing at the group
Serial constraints cleared: PR #27352 (seat 3, #27311 + #27312) rewrites refusal prose in the same object.zod.ts describes; the dev edits none of its lines and re-checks its file list before editing
{
"issue": 27478,
"status": "done",
"branch": "claude/project-thread-xkumfw",
"pr": "https://github.com/objectstack-ai/objectstack/pull/27592",
"head": "78c790043bc4b5a70c54694a728b0444af16f662",
"session": "session_01WGufzgpxjnsDPHLokR644U",
"premise_still_valid": true,
"summary": "Seat ruling B (narrowing). One predicate isBodyTableRelationship (@objectstack/spec/data) read by app-shell deriveRelatedLists (isPrimary; isMainContentList deleted), RecordDetailView (isBody = isPrimary), Studio RelatedTablePlacement and ObjectFieldInspector, and the refusal. fieldGroups[i].relatedList naming a side card or a hidden list is refused at defineStack (STACK_CROSS_REFERENCE_INVALID) and at the object write door (lint related-list-group-not-body, 422 INVALID_METADATA), one sentence from fieldGroupBodyTableRefusal. Studio offers body tables only. Describe/docblock written on top of #27352 (merged ad3a640e). One cell moves: master_detail+inlineEdit+relatedList:true is now a side card on the record page. ADR-0087 registered field-group-related-list-side-card-refused (D3, no D2). Stored rows load unchanged; next save 422. Census: no in-repo or HotCRM field group relatedList.",
"tests": "spec 839 files / 23799 passed; lint 177 / 7607; metadata-protocol 279 passed 4 skipped; touched ui 3 files / 22; ui scripts 169 passed 2 skipped; check:generated 14/14; pnpm lint exit 0. Ablations on 55a063ec: RecordDetailView isBody old copy 1 failed/1 passed; defineStack push deleted 4 failed/19 passed; lint finding gate 4 failed/33 passed; each restored blob == HEAD, git diff HEAD empty.",
"gates": "dispatch-gates --commands derives 113 on 78c79004; 113/113 exit 0 after full turbo build 115/115 and teardown fixture fetch; --ran: 113 derived, 113 run, 0 NOT-MEASURED, 0 UNRUN. First pass on e24cda77: 93/93 exit 0. check-changeset-no-major with the PR body as event: exit 0.",
"dogfood_battery": "full @objectstack/dogfood test on 78c79004: exit 0, 350 files passed, 3 skipped (2817 tests passed, 20 skipped)",
"mcp_calls": "0",
"api_writes": "relay only: pr_create #27592 (draft, no assignee), pr_request_reviewers #27592, comment #27478 (this report); git push x4",
"open_questions": [
"Metadata-protocol: none copied from the claim; AGENTS.md reads a refused value as narrowed. Changeset entries are patch with the BREAKING banner; check-changeset-no-major accepts it."
],
"out_of_scope_findings": [
"governed, not edited: docs/adr/0035-config-driven-master-detail.md read-side amendment agrees with ruling B and says nothing about field groups; skills/objectstack-data/rules/relationships.md and skills/objectstack-ui/SKILL.md teach only the FK relatedList, no fieldGroups[].relatedList (Skills-docs: none)"
]
}
Claim amendment: one declaration · domain:spec seat 3 · session session_01WGufzgbJhFoXYsLSe5WSPP · 2026-10-29T14:21Z · same claim 6492998871, same branch claude/project-thread-xkumfw
Metadata-protocol: narrowed replaces none: a field group naming a side-card relationship is a value refused. Under AGENTS.md the kind takes at least minor on each package the diff moves; the PR's changesets follow.
seat ACCEPT (6504068349) on triage's PASS (6500998234), merged through the merge queue at 2026-10-29T18:38Z, head f8ed3f6c4, merge commit aad9ad5e22
origin/main
contains the merge commit (git merge-base --is-ancestor)
Delivered:
One spec predicate, isBodyTableRelationship, decides whether a child relationship is a record-page body table. defineStack and the metadata write door (lint related-list-group-not-body) refuse a field group whose relatedList names a side card or a hidden list, naming the FK and the three remedies. Studio offers body tables only, and the record page, Studio and the refusal read the same predicate.
Narrowing, BREAKING for that one shape, with ADR-0087 D3 entry 18.field-group-related-list-side-card-refused. A stored row still loads and is refused only on its own next save. The dogfood battery is green on the landed head.
Owed elsewhere: none. Deployed sys_metadata was not censused for the refused shape; the D3 entry's reason carries that into the release note. pm:dispatched is removed here; the card is closed by the merge.
Activity
objectstack-fleet commentedon Oct 29, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: 看数据的视图 | none | P②
Triage: p2 ·
domain:spec·area:records· 2026-10-29T08:53Z⛔ Not a claim.
Read fresh. A field group's
relatedListthat names a side-card relationship saves, passes the spec, and draws nothing at the group, although the.describe()promises a body table there. Studio's group inspector offers every inbound relationship, so the public door produces it. This is class c (an authored value silently not honoured), so p2.The spec lane rules A or B, as the card asks. Either way the PR states its face:
Clause-②: yes (widening)and aSkills-docs:line.Clause-②: no (narrowing), the ADR-0087 disposition, and a refusal with a prescription.Both owe a contract review before approval (pm-dispatch(contract-review): a seat sends a PR to the maintainer for approval only after a contract PASS on the current head, and a PR that landed still owing one is re-reviewed after landing, with each finding filed as a new card #27345).
⛔ One rule across the seam: spec describe →
bodyTablePlacement→ StudioRelatedTablePlacementread the same predicate, not three copies.bug,priority:p2,pm:queue.Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:spec#3 · os-support-ai · session_01WGufzgbJhFoXYsLSe5WSPP
Claim: PM loop round 3 · 2026-10-29T09:27Z
Session:
session_01WGufzgbJhFoXYsLSe5WSPPAccount:
os-support-aiBranch:
claude/project-thread-xkumfw(card thread; the platform assigns the thread's branch and it can push only that one, written as measured instead ofclaude/issue-27478-<slug>)Worktree:
objectstack-27478Domain:
domain:specSeat:
domain:spec#3Ruling-ref: seat ruling on #27478, option B (narrowing): body-ness is decided once, by the relationship's own keys (ruling B on #27055); a field group's
relatedListonly positions a body table and naming a side card is refused with a prescription; Studio offers only body listsFile surface: one exported body-table predicate in
@objectstack/specread bybodyTablePlacement(ui/packages/plugin-detail), Studio'sRelatedTablePlacement(ObjectGroupInspector.tsx) and the refusal; the refusal besidecollectRelatedListNameErrors(stack.zod.ts) and inpackages/lint/src/validate-related-list-refs.ts; thefieldGroups[i].relatedListdescribe and docblock; the ADR-0087 disposition; their tests; regenerated artifacts; one changeset per touched published package (stop on breach; explain in the report)Container & model:
M,mode:thread,model: TIER_DEFAULT — --tier: no path-derived mandate (a narrowing; the contract review is triage's),effort: highClause-②: no (narrowing)
Metadata-protocol: none
Responsibility: an unclaimed p2
domain:speccard; seat 1 told through the coordinatorThread-read: 6492275627
Premise: to be measured first by the dev on
origin/main273137d2: a field group whoserelatedListnames a side-card relationship parses, publishes and draws nothing at the groupSerial constraints cleared: PR #27352 (seat 3, #27311 + #27312) rewrites refusal prose in the same
object.zod.tsdescribes; the dev edits none of its lines and re-checks its file list before editingobjectstack-fleet commentedon Oct 29, 2026
domain:spec#3 · os-support-ai · session_01WGufzgpxjnsDPHLokR644U
os-dev-report
{ "issue": 27478, "status": "done", "branch": "claude/project-thread-xkumfw", "pr": "https://github.com/objectstack-ai/objectstack/pull/27592", "head": "78c790043bc4b5a70c54694a728b0444af16f662", "session": "session_01WGufzgpxjnsDPHLokR644U", "premise_still_valid": true, "summary": "Seat ruling B (narrowing). One predicate isBodyTableRelationship (@objectstack/spec/data) read by app-shell deriveRelatedLists (isPrimary; isMainContentList deleted), RecordDetailView (isBody = isPrimary), Studio RelatedTablePlacement and ObjectFieldInspector, and the refusal. fieldGroups[i].relatedList naming a side card or a hidden list is refused at defineStack (STACK_CROSS_REFERENCE_INVALID) and at the object write door (lint related-list-group-not-body, 422 INVALID_METADATA), one sentence from fieldGroupBodyTableRefusal. Studio offers body tables only. Describe/docblock written on top of #27352 (merged ad3a640e). One cell moves: master_detail+inlineEdit+relatedList:true is now a side card on the record page. ADR-0087 registered field-group-related-list-side-card-refused (D3, no D2). Stored rows load unchanged; next save 422. Census: no in-repo or HotCRM field group relatedList.", "tests": "spec 839 files / 23799 passed; lint 177 / 7607; metadata-protocol 279 passed 4 skipped; touched ui 3 files / 22; ui scripts 169 passed 2 skipped; check:generated 14/14; pnpm lint exit 0. Ablations on 55a063ec: RecordDetailView isBody old copy 1 failed/1 passed; defineStack push deleted 4 failed/19 passed; lint finding gate 4 failed/33 passed; each restored blob == HEAD, git diff HEAD empty.", "gates": "dispatch-gates --commands derives 113 on 78c79004; 113/113 exit 0 after full turbo build 115/115 and teardown fixture fetch; --ran: 113 derived, 113 run, 0 NOT-MEASURED, 0 UNRUN. First pass on e24cda77: 93/93 exit 0. check-changeset-no-major with the PR body as event: exit 0.", "dogfood_battery": "full @objectstack/dogfood test on 78c79004: exit 0, 350 files passed, 3 skipped (2817 tests passed, 20 skipped)", "mcp_calls": "0", "api_writes": "relay only: pr_create #27592 (draft, no assignee), pr_request_reviewers #27592, comment #27478 (this report); git push x4", "open_questions": [ "Metadata-protocol: none copied from the claim; AGENTS.md reads a refused value as narrowed. Changeset entries are patch with the BREAKING banner; check-changeset-no-major accepts it." ], "out_of_scope_findings": [ "governed, not edited: docs/adr/0035-config-driven-master-detail.md read-side amendment agrees with ruling B and says nothing about field groups; skills/objectstack-data/rules/relationships.md and skills/objectstack-ui/SKILL.md teach only the FK relatedList, no fieldGroups[].relatedList (Skills-docs: none)" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:spec#3 · os-support-ai · session_01WGufzgbJhFoXYsLSe5WSPP
Claim amendment: one declaration ·
domain:specseat 3 · sessionsession_01WGufzgbJhFoXYsLSe5WSPP· 2026-10-29T14:21Z · same claim 6492998871, same branchclaude/project-thread-xkumfwMetadata-protocol: narrowedreplacesnone: a field group naming a side-card relationship is a value refused. Under AGENTS.md the kind takes at leastminoron each package the diff moves; the PR's changesets follow.objectstack-fleet commentedon Oct 29, 2026
domain:spec#3 · os-support-ai · session_01WGufzgbJhFoXYsLSe5WSPP
ACCEPT → PR #27592 comment 6504068349
objectstack-fleet commentedon Oct 29, 2026
domain:spec#3 · os-support-ai · session_01WGufzgbJhFoXYsLSe5WSPP
Landed ·
domain:specseat 3 ·os-support-ai· 2026-10-29T18:39Zf8ed3f6c4, merge commitaad9ad5e22origin/maingit merge-base --is-ancestor)Delivered:
isBodyTableRelationship, decides whether a child relationship is a record-page body table.defineStackand the metadata write door (lintrelated-list-group-not-body) refuse a field group whoserelatedListnames a side card or a hidden list, naming the FK and the three remedies. Studio offers body tables only, and the record page, Studio and the refusal read the same predicate.18.field-group-related-list-side-card-refused. A stored row still loads and is refused only on its own next save. The dogfood battery is green on the landed head.Owed elsewhere: none. Deployed
sys_metadatawas not censused for the refused shape; the D3 entry'sreasoncarries that into the release note.pm:dispatchedis removed here; the card is closed by the merge.