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 }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
finding(plugin-detail): DetailSection reads section.hideEmpty, but the detail-section node does not declare it, so an authored hideEmpty is warned unknown-prop and dropped at render #10485
Filing-gate category: ③ a trap: the renderer honours a key the node's declared inputs omit, so the validator steers an author away from a working key (class c). Reader: triage first (route and grade). ⚠️ Widening an authoring surface is a product decision, so this is likely a director-ruling card like its sibling objectui#9529.
Filed by the domain:ui execution seat (seat 1, session session_01BA3nKVUwKQJf8DBxrSVtNC) from the os-dev-report of objectui#9529 (PR objectui#10484). ⛔ Not graded and not routed: domain:*, priority:* and type are the triage seat's.
Fact (the dev's probe at 274e14af4, relayed, ⛔ not re-run by the seat)
DetailSection (packages/plugin-detail/src/DetailSection.tsx) reads section.hideEmpty === true, the all-empty hide that objectui#8603 restored. objectui#9529 measured the node's gap at bbc9dc3, before that read existed, so it counted exactly one member.
The detail-section registration (packages/plugin-detail/src/index.tsx) and DETAIL_SECTION_NODE_INPUTS (DetailSectionNode.tsx) do not declare hideEmpty, even after PR objectui#10484 adds icon.
The probe used a live manifest built as page.tsx builds it. An authored hideEmpty on the node draws unknown-prop. DetailSectionNode then passes it as a host prop, which DetailSection ignores, so it is dropped at render.
Producer: an authored JSX/SDUI page typed against DetailViewSection, which declares hideEmpty.
Grading notes (for triage, not a grade)
Same class and same site as objectui#9529 (ruled there: declare, because the renderer already honours the key). The dev notes one extra wrinkle for whoever rules: the omitted default for hideEmpty differs between record:details and detail-view.
REST page walk over the 1000 most recently updated objectui items (oldest updated_at 2026-09-18). hideEmpty ⇒ PR objectui#10484 (the source) and two unrelated closed items. DETAIL_SECTION_NODE_INPUTS ⇒ objectui#9529 and PR objectui#10484. Must-hit control detail-section ⇒ 4 hits.
Triage: lands in packages/plugin-detail/src/index.tsx / DetailSectionNode.tsx (DETAIL_SECTION_NODE_INPUTS omits hideEmpty, which DetailSection.tsx reads, on objectui origin/maind999617) ⇒ domain:ui; rationale: the same class and site as objectui#9529, whose ruling was to declare a key the renderer already honours. A new branch reuses the parent ruling, so this is queued, not escalated. p3.
Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01CRZSc7dU8oDStbTbSwhuZe · 2026-09-25T06:59Z. ⛔ Not a claim, ⛔ not a dispatch. Read: this card and its full thread, and objectui origin/maind999617. Dedupe by this seat over 739 objectui cards (open, plus closed since 2026-09-18): hideEmpty → 4 hits (this card; #6152 and #7716, different mirror/designer cards; #7996, closed).
Execution note: declare hideEmpty on the node's inputs; state the node's omitted default explicitly (the card notes it differs between record:details and detail-view) — if that difference is a real semantic split rather than a default to declare, stop and report here.
Claim: PM loop round 1 — domain:ui execution seat
Session: session_01BA3nKVUwKQJf8DBxrSVtNC
Branch: claude/issue-10485-detail-section-hideempty-input
Worktree: objectui-issue-10485
Domain: domain:ui
Seat: domain:ui#1
File surface: packages/plugin-detail/src/DetailSectionNode.tsx (DETAIL_SECTION_NODE_INPUTS: the hideEmpty entry only) and packages/plugin-detail/src/index.tsx only if the node's registration inputs live there, the registry-input readers' pins that enumerate this node's inputs (as objectui#9529 / PR objectui#10484 touched), a pin beside detailSectionAuthoredIcon-9529.test.tsx, and one .changeset/10485-…md (stop on breach; explain in the report)
Container & model: S, mode:subagent, model: opus (default judgement tier) — priority:p3: the validator warns unknown-prop on, and drops, a key the renderer honours
Clause-②: yes
Thread-read: 5828292064
Serial constraints cleared: open-PR file lists read 2026-09-25T08:04Z ⇒ none names DetailSectionNode.tsx, plugin-detail/src/index.tsx or DetailSection.tsx. Draft PR objectui#8941 edits plugin-detail/package.json and one icon string in DetailView.tsx, which this card does not touch. No live pm:dispatched claim names these files.
Scope
The triage (5828292064) reuses objectui#9529's ruling (5724939941): declare a key the renderer already honours.
Declare hideEmpty on the detail-section node's inputs, so an authored hideEmpty is no longer warned unknown-prop and dropped.
State the omitted default explicitly. The card notes it differs between record:details and detail-view (hideEmpty: s.hideEmpty ?? true on one path). ⛔ If that difference is a real semantic split rather than a default to declare, stop and report instead of declaring.
{
"issue": 10485,
"status": "done",
"branch": "claude/issue-10485-detail-section-hideempty-input",
"pr": "https://github.com/objectstack-ai/objectui/pull/10552",
"session": "session_01BA3nKVUwKQJf8DBxrSVtNC. This ran as a subagent, so it is the parent PM session; the Claude-Session trailer on commit d0f0649d8 names it, and the relay route resolved the same id from the container.",
"premise_still_valid": true,
"summary": "Declared hideEmpty on the detail-section node, in the shape of PR #10484: the registration in plugin-detail index.tsx gains { name: 'hideEmpty', type: 'boolean', description }, and DETAIL_SECTION_NODE_INPUTS gains 'hideEmpty'. No defaultValue, because no other input of this node carries one. DetailSection's hide logic is untouched, and DetailView.tsx was not opened for edit. I measured the triage's stop condition and it did not fire. On base 0d5d66aee, with a lit sibling control in every case: detail-view keeps when hideEmpty is omitted, hides on true, keeps on false; record:details hides when omitted (its own `?? true` on its own authored sections), hides on true, keeps on false; the node keeps in all three on base (the key was warned and then dropped), and after the fix it keeps when omitted, hides on true, keeps on false. So true and false mean the same thing on all three surfaces, and on the node an omitted key has exactly one meaning, keep (the same as detail-view). That is a default to declare, not a semantic split, and the input's description states it. The assignee field held os-bill when I took the card; I did not touch it. PM mechanism assumptions: #1 held, with one correction: the validator only warns (unknown-prop); the drop is the fold in DetailSectionNode, which routes an undeclared key to hostProps, and DetailSection ignores that prop. #2 held (table above). #3 is falsified: no reader needed a new row, and PR #10484 did not update any either. The four console readers have 0 hits for detail-section and stay green. check:component-surface-parity is report-only and has no pin file. check:sdui-registration-pins pins registration keys and never reads inputs. #4: ablation done in three legs (see tests). One in-surface comment edit: DetailSectionNode.tsx 'a ninth input' became 'a new input', making it count-free. The two sibling pins (#8626, #9529) pass without changes. Clean-up: the worktree was removed after the PR opened.",
"tests": "All at head d0f0649d8. (1) Base reproduction with the new pin detailSectionAuthoredHideEmpty-10485.test.tsx on base 0d5d66aee: 'Tests 3 failed | 3 passed (6)'. Red: both validate rows (received unknown-prop, message 'DETAIL-SECTION has no prop hideEmpty', tag spelled out for the sanitizer) and the true render row ('expected span to be null', meaning the heading still rendered). Green: the name control, the false row, the omitted row. Head: 6/6. (2) From the repo root, 'pnpm exec vitest run packages/plugin-detail/' plus the four console readers (registry-inputs-spec-parity, ga-honoured-inputs-author-reach, public-contract, component-input-union-specimens): 'Test Files 212 passed | 1 skipped (213)', 'Tests 2301 passed | 8 skipped (2309)', lock VERDICT command-exit 0. The readers alone with the verbose reporter: 'Test Files 4 passed (4)', 'Tests 240 passed (240)', each file named in the output. (3) 'pnpm exec turbo run build --filter=@object-ui/plugin-detail^... --concurrency=2': 'Tasks: 11 successful, 11 total'. Then 'pnpm --filter @object-ui/plugin-detail type-check' (it echoed 'tsc --noEmit && tsc -p tsconfig.test.json'): exit 0, and 'tsc -p tsconfig.test.json --listFiles' lists the new pin (1 hit). (4) Ablation, three legs, all on the committed d0f0649d8, each mutation through objectstack scripts/ablation-replace.mjs --delete inside a wrapper with its own trap on EXIT INT TERM that restores both files by 'git checkout HEAD --' on an absolute path and proves blob == HEAD plus an empty 'git diff HEAD'. No build is needed: the pin imports ../index, and the root vitest config aliases core, react and sdui-parser to src. Directions were predicted before each run and matched. Leg A deleted the registration entry: anchor 1 to 0, index.tsx blob bd23f817f to 04615591b; red were both validate rows and the #8626 fold-parity row; the name control and the render rows stayed green; 'Tests 3 failed | 15 passed (18)'; restored with blob bd23f817f == HEAD and an empty diff. Leg B deleted 'hideEmpty' from DETAIL_SECTION_NODE_INPUTS: blob d41d873c3 to 637368d62; red were the true render row and #8626 fold parity; the validate rows and control stayed green; '2 failed | 16 passed (18)'; restored with blob == HEAD. Leg C deleted both (the dispatch's 'warned and dropped'): red were both validate rows and the true render row; the control and #8626 fold parity stayed green; '3 failed | 15 passed (18)'; both blobs restored == HEAD and the diff was empty. (5) Gates: check:control-bytes 'OK (scanned 8619 tracked text file(s))'. check:new-line-citations '0 new citation(s), enforcement report-only -> exit 0'. check-changeset-presence '3 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)'. check-changeset-no-major 'No changeset declares a major bump'. check:changeset-claims is report-only, exit 0, and flags 9280-record-highlights-entry-icon-retired.md and record-alert-cta-label-i18n-4998.md for naming index.tsx; I read both paragraphs and both are still true, since this diff touches neither registration. check:doc-types, check:registry-bare-names, check:icon-record-names, check:test-path-roots, check:pending-changeset-literals, check:vi-mock-specifiers, check:handler-key-reads and check:governed-queue-guard all exit 0, and '--test' on the 4 paths reports NOT GOVERNED. check:component-surface-parity is report-only, exit 0, and lists detail-section.hideEmpty as input-outside-keyset beside eight pre-existing detail-section inputs, for the same reason (the node folds by iterating the list). (6) Lint narrowing, declared: eslint --no-inline-config --format json over the 3 touched source files, 3 files linted, 0 errors. Per-rule counts equal base (base read with git show 0d5d66aee piped to eslint --stdin): DetailSectionNode.tsx has 1 react-refresh/only-export-components; index.tsx has 29 react-refresh/only-export-components and 2 @typescript-eslint/no-explicit-any; the new pin has 0. Invariance: eslint --print-config on index.tsx shows empty parserOptions (no project or projectService), so linting is not type-aware and this diff cannot change the verdict on any untouched file. NOT MEASURED: check:sdui-registration-pins, which exits 2 with 'No console build to weigh' because it needs a full console build; that is left to CI. CI on d0f0649d8 when this report was written: 12 success, 3 skipped, 26 in_progress, 1 queued, so the honest state is in_progress.",
"mcp_calls": "0. No MCP GitHub tool was called. Reads went through REST GET: the card, its comments, parent ruling 5724939941, PR #10484, the PR-by-head lookup, check-runs, and the prior #9529 report comment.",
"api_writes": "2, both through the fleet-write relay as objectstack-fleet[bot]. (1) pr_create: POST /repos/objectstack-ai/objectstack/dispatches (request fw-20260925T082754Z-32a293, run 36113059727, conclusion success), which executed POST /repos/objectstack-ai/objectui/pulls as a draft, giving #10552. The body was read back and is byte-identical to what was sent (13352 bytes, 0 angle brackets). (2) This os-dev-report comment: POST /repos/objectstack-ai/objectui/issues/10485/comments via post-stamped --repo=objectstack-ai/objectui. There were two git pushes (the empty-branch probe, then d0f0649d8); those are not REST writes. Zero label writes, zero PATCH calls.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none (承接者:无) · noted in PR #10552 Acceptance notes, not filed · four texts outside the claim's file surface still describe the detail-section node as a section nobody can write hideEmpty on. Their conclusion (the node keeps its skeleton when the key is omitted) still holds; only the premise is stale. Quoted by content: DetailSection.tsx, the comment above hideAllEmptySection ('the detail-section node both synthesize one, and neither surface declares hideEmpty'); renderers/record-details.tsx, the comment on 'hideEmpty: s.hideEmpty ?? true' ('Sections nobody can write it on stay out: ... the detail-section node'); renderers/__tests__/record-details.emptySectionDefault.test.tsx, the file header ('a section nobody could have written the key on ... the detail-section node'); packages/types/src/views.ts, the DetailViewSection.hideEmpty docblock ('This type is consumed by two authorable renderers'), which now has a third, the node, behaving like detail-view. The fix for each is named in the PR body. The last one is an incomplete list, not an error.",
"carrier: none (承接者:无) · noted in PR #10552 Acceptance notes, not filed · the pending .changeset/8626-detail-section-authored-node.md still says in present tense that the registration 'declares eight FLAT inputs'. PR #10484 already noted this at nine, and it is ten now.",
"carrier: the seat / maintainer, as an observation and not a finding · noted in PR #10552 Acceptance notes · the #8603 reason for keeping the node out of the hide default ('no declarable spelling to ask the skeleton back') no longer applies to the node now that the key is declarable. Whether the node should adopt record:details' hide-by-default is a product question this card forbids acting on (no behaviour change). The PR declares today's behaviour, keep, which matches detail-view."
]
}
{
"issue": 10485,
"status": "done",
"branch": "claude/issue-10485-detail-section-hideempty-input",
"pr": "https://github.com/objectstack-ai/objectui/pull/10552",
"session": "session_01BA3nKVUwKQJf8DBxrSVtNC (subagent, parent PM session)",
"premise_still_valid": true,
"summary": "Patch round 1 (addendum; supersedes nothing in comment 5829379233 except the head sha). New head 9b178bacd, one commit on d0f0649d8, prose only, with no code or assertion change. (1) .changeset/8626-detail-section-authored-node.md: added one in-release paragraph, 'Superseded in this release by objectui#9529 and objectui#10485', stating ten flat inputs measured at head: title, description, icon, fields, collapsible, defaultCollapsed, columns, showBorder, headerColor, hideEmpty. The count was read from DETAIL_SECTION_NODE_INPUTS and the registration, and the two lists agree. Numstat is 8 added, 0 deleted; frontmatter unchanged. (2) Only the premise was corrected; each conclusion stands (an omitted key keeps the skeleton on the node). The three sites: the DetailSection.tsx comment above hideAllEmptySection; the record-details.tsx comment on 'hideEmpty: s.hideEmpty ?? true', where the adjacent 'reaches exactly the surface that declares the key' now reads 'the authored sections this renderer resolves it on', since the node also declares the key now; and the record-details.emptySectionDefault.test.tsx header. A diff filter over packages/ shows no changed line that is not a comment line. packages/types/src/views.ts was left untouched as instructed. No PR body edit.",
"tests": "At head 9b178bacd. check-changeset-overwrite: exit 0, report-only, '1 changeset(s) added, 1 modified, 0 deleted' — 'M .changeset/8626-detail-section-authored-node.md', declared at base '@object-ui/plugin-detail: patch', declares now '@object-ui/plugin-detail: patch' (case 2, a deliberate correction). check-changeset-presence: exit 0, '6 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s): .changeset/10485-detail-section-declares-hideempty.md'. check-changeset-no-major: exit 0, 'No changeset declares a major bump'. check:changeset-claims: exit 0, report-only, flags 6 pending changesets naming touched files: 7997-detail-view-related-retired, 8394-record-page-emptiness-authority, 8400-kanban-name-field-skip-set, 8649-detail-renderer-undeclared-keys, 9280-record-highlights-entry-icon-retired, record-alert-cta-label-i18n-4998. I read all six paragraphs; all are still true, since none describes the comments edited here. check:control-bytes: 'OK (scanned 8619 tracked text file(s); skipped 85 binary)'. check:new-line-citations: '0 new citation(s), enforcement report-only -> exit 0'. eslint --no-inline-config over the 3 edited source files: 3 linted, 0 errors, per-rule counts equal base 0d5d66aee. DetailSection.tsx: no-explicit-any 10, react-hooks/set-state-in-effect 1, react-refresh/only-export-components 1. record-details.tsx: no-explicit-any 34, only-export-components 1. emptySectionDefault.test.tsx: no-explicit-any 1. 'pnpm exec vitest run packages/plugin-detail/' from the repo root: 'Test Files 208 passed | 1 skipped (209)', 'Tests 2061 passed | 8 skipped (2069)', lock VERDICT command-exit 0.",
"mcp_calls": "0",
"api_writes": "1 this round: POST /repos/objectstack-ai/objectui/issues/10485/comments (this addendum, via post-stamped relay). git push d0f0649d8..9b178bacd is not a REST write. Zero label writes, zero PR body edits. Total over both rounds: 3.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none (承接者:无) · Acceptance note only, not filed · packages/types/src/views.ts, the DetailViewSection.hideEmpty docblock 'This type is consumed by two authorable renderers': an incomplete list (the node is now a third, behaving like detail-view). Left out of this round as the seat instructed.",
"carrier: the seat / maintainer, observation · Acceptance note only · whether the node should adopt record:details' hide-by-default is a product question; the PR declares today's behaviour, keep."
]
}
✅ ACCEPT — PR objectui#10552 at 9b178bacd · entering the merge queue once CI is green
domain:ui seat #1, session_01BA3nKVUwKQJf8DBxrSVtNC. The seat read the dev report, its patch-round addendum and the diff against the triage 5828292064 (which reuses objectui#9529's ruling 5724939941) and the claim 5829068872. Clause-②: yes: the detail-section authoring surface widens by one key the renderer already honours, and the changeset is minor. Per batch #151 item 3, no at-tier review is owed in domain:ui, so the seat reviewed it.
draft · base main · Fixes #10485 · Clause-②: yes at line start · the PR's shape follows objectui#10484
stop condition
Measured on base with a lit sibling control on every row. true hides and false keeps on all three surfaces (detail-view, record:details, the node). An omitted key keeps on detail-view and on the node, and hides only on record:details, which resolves its own ?? true on its own authored sections, which never pass through the node. So the node's omitted default is one value (keep), not a semantic split. It is stated in the input's description, with no defaultValue (no other input of the node has one)
the fix
{ name: 'hideEmpty', type: 'boolean', description } on the registration, plus 'hideEmpty' in DETAIL_SECTION_NODE_INPUTS. ⛔ DetailSection's hide logic and DetailView.tsx are untouched
the claim, falsified
Zone 2 item 3 (the registry-input readers would need a new row) is falsified: no reader enumerates this node's inputs, and objectui#10484 updated none either. Taken
ablation
Three legs, each restored by blob. Removing the registration entry turns the validate rows red. Removing the fold entry turns the true render row red. Removing both turns both red. The name control stays green in every leg
patch round 9b178bacd
Prose only: every changed source line is a comment. ① The pending 8626-detail-section-authored-node.md gets an in-release note: ten inputs now, not eight (plus icon from objectui#9529 and hideEmpty from here). Frontmatter untouched, 0 lines deleted; check-changeset-overwrite reports 1 modified, report-only case 2. ② The three comments whose premise this PR falsified ("nobody can write hideEmpty on the node") are corrected in DetailSection.tsx, renderers/record-details.tsx and the record-details.emptySectionDefault test header, each keeping its conclusion
tests + gates
packages/plugin-detail/ 208 files / 2061 tests passed at 9b178bacd (212 / 2301 with the console readers at d0f0649d8). The closure build is 11/11 and type-check passes. eslint per rule matches base. Changeset presence / no-major / overwrite / claims, control bytes and new line citations exit 0, and the queue guard says NOT GOVERNED. check:sdui-registration-pins needs a console build, so it is left to CI
Dev notes — each one routed
The DetailViewSection.hideEmpty docblock in packages/types/src/views.ts lists two consuming renderers, and the node is now a third. That is an incomplete list, not a false statement ⇒ PR Acceptance notes. 承接者:无.
Whether the node should adopt record:details' hide-by-default (objectui#8603's reason for exempting it no longer holds now that the key is declarable) is a product question this card forbade acting on ⇒ PR Acceptance notes, as an observation for the maintainer. 承接者:无.
Activity
objectstack-fleet commentedon Sep 25, 2026
Path: business objects, records and views | records-forms.crud-roundtrip | P2
Triage: first grade —
bug·priority:p3·domain:ui·area:records·pm:queue(findingremoved — graded)Triage: lands in
packages/plugin-detail/src/index.tsx/DetailSectionNode.tsx(DETAIL_SECTION_NODE_INPUTSomitshideEmpty, whichDetailSection.tsxreads, on objectuiorigin/maind999617) ⇒domain:ui; rationale: the same class and site as objectui#9529, whose ruling was to declare a key the renderer already honours. A new branch reuses the parent ruling, so this is queued, not escalated. p3.Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) ·
session_01CRZSc7dU8oDStbTbSwhuZe· 2026-09-25T06:59Z. ⛔ Not a claim, ⛔ not a dispatch. Read: this card and its full thread, and objectuiorigin/maind999617. Dedupe by this seat over 739 objectui cards (open, plus closed since 2026-09-18):hideEmpty→ 4 hits (this card; #6152 and #7716, different mirror/designer cards; #7996, closed).Execution note: declare
hideEmptyon the node's inputs; state the node's omitted default explicitly (the card notes it differs betweenrecord:detailsanddetail-view) — if that difference is a real semantic split rather than a default to declare, stop and report here.objectstack-fleet commentedon Sep 25, 2026
Claim: PM loop round 1 —
domain:uiexecution seatSession:
session_01BA3nKVUwKQJf8DBxrSVtNCBranch:
claude/issue-10485-detail-section-hideempty-inputWorktree:
objectui-issue-10485Domain:
domain:uiSeat:
domain:ui#1File surface:
packages/plugin-detail/src/DetailSectionNode.tsx(DETAIL_SECTION_NODE_INPUTS: thehideEmptyentry only) andpackages/plugin-detail/src/index.tsxonly if the node's registration inputs live there, the registry-input readers' pins that enumerate this node's inputs (as objectui#9529 / PR objectui#10484 touched), a pin besidedetailSectionAuthoredIcon-9529.test.tsx, and one.changeset/10485-…md(stop on breach; explain in the report)Container & model:
S,mode:subagent,model: opus(default judgement tier) —priority:p3: the validator warnsunknown-propon, and drops, a key the renderer honoursClause-②: yes
Thread-read: 5828292064
Serial constraints cleared: open-PR file lists read 2026-09-25T08:04Z ⇒ none names
DetailSectionNode.tsx,plugin-detail/src/index.tsxorDetailSection.tsx. Draft PR objectui#8941 editsplugin-detail/package.jsonand one icon string inDetailView.tsx, which this card does not touch. No livepm:dispatchedclaim names these files.Scope
The triage (
5828292064) reuses objectui#9529's ruling (5724939941): declare a key the renderer already honours.hideEmptyon thedetail-sectionnode's inputs, so an authoredhideEmptyis no longer warnedunknown-propand dropped.record:detailsanddetail-view(hideEmpty: s.hideEmpty ?? trueon one path). ⛔ If that difference is a real semantic split rather than a default to declare, stop and report instead of declaring.Clause-②: yes, like the parent: the authoring surface widens by one key that already works. The changeset isminor. Per batch Add automated display issue detection for component renderers #151 item 3, no at-tier review is owed indomain:ui; the seat reviews.hideEmptypasses the node's validation and reachesDetailSection, with a lit control (an undeclared key is still warned).⇒
Fixes #10485.domain:uiseat #1 ·session_01BA3nKVUwKQJf8DBxrSVtNC· claim · 2026-09-25T08:05Zobjectstack-fleet commentedon Sep 25, 2026
os-dev-report
{ "issue": 10485, "status": "done", "branch": "claude/issue-10485-detail-section-hideempty-input", "pr": "https://github.com/objectstack-ai/objectui/pull/10552", "session": "session_01BA3nKVUwKQJf8DBxrSVtNC. This ran as a subagent, so it is the parent PM session; the Claude-Session trailer on commit d0f0649d8 names it, and the relay route resolved the same id from the container.", "premise_still_valid": true, "summary": "Declared hideEmpty on the detail-section node, in the shape of PR #10484: the registration in plugin-detail index.tsx gains { name: 'hideEmpty', type: 'boolean', description }, and DETAIL_SECTION_NODE_INPUTS gains 'hideEmpty'. No defaultValue, because no other input of this node carries one. DetailSection's hide logic is untouched, and DetailView.tsx was not opened for edit. I measured the triage's stop condition and it did not fire. On base 0d5d66aee, with a lit sibling control in every case: detail-view keeps when hideEmpty is omitted, hides on true, keeps on false; record:details hides when omitted (its own `?? true` on its own authored sections), hides on true, keeps on false; the node keeps in all three on base (the key was warned and then dropped), and after the fix it keeps when omitted, hides on true, keeps on false. So true and false mean the same thing on all three surfaces, and on the node an omitted key has exactly one meaning, keep (the same as detail-view). That is a default to declare, not a semantic split, and the input's description states it. The assignee field held os-bill when I took the card; I did not touch it. PM mechanism assumptions: #1 held, with one correction: the validator only warns (unknown-prop); the drop is the fold in DetailSectionNode, which routes an undeclared key to hostProps, and DetailSection ignores that prop. #2 held (table above). #3 is falsified: no reader needed a new row, and PR #10484 did not update any either. The four console readers have 0 hits for detail-section and stay green. check:component-surface-parity is report-only and has no pin file. check:sdui-registration-pins pins registration keys and never reads inputs. #4: ablation done in three legs (see tests). One in-surface comment edit: DetailSectionNode.tsx 'a ninth input' became 'a new input', making it count-free. The two sibling pins (#8626, #9529) pass without changes. Clean-up: the worktree was removed after the PR opened.", "tests": "All at head d0f0649d8. (1) Base reproduction with the new pin detailSectionAuthoredHideEmpty-10485.test.tsx on base 0d5d66aee: 'Tests 3 failed | 3 passed (6)'. Red: both validate rows (received unknown-prop, message 'DETAIL-SECTION has no prop hideEmpty', tag spelled out for the sanitizer) and the true render row ('expected span to be null', meaning the heading still rendered). Green: the name control, the false row, the omitted row. Head: 6/6. (2) From the repo root, 'pnpm exec vitest run packages/plugin-detail/' plus the four console readers (registry-inputs-spec-parity, ga-honoured-inputs-author-reach, public-contract, component-input-union-specimens): 'Test Files 212 passed | 1 skipped (213)', 'Tests 2301 passed | 8 skipped (2309)', lock VERDICT command-exit 0. The readers alone with the verbose reporter: 'Test Files 4 passed (4)', 'Tests 240 passed (240)', each file named in the output. (3) 'pnpm exec turbo run build --filter=@object-ui/plugin-detail^... --concurrency=2': 'Tasks: 11 successful, 11 total'. Then 'pnpm --filter @object-ui/plugin-detail type-check' (it echoed 'tsc --noEmit && tsc -p tsconfig.test.json'): exit 0, and 'tsc -p tsconfig.test.json --listFiles' lists the new pin (1 hit). (4) Ablation, three legs, all on the committed d0f0649d8, each mutation through objectstack scripts/ablation-replace.mjs --delete inside a wrapper with its own trap on EXIT INT TERM that restores both files by 'git checkout HEAD --' on an absolute path and proves blob == HEAD plus an empty 'git diff HEAD'. No build is needed: the pin imports ../index, and the root vitest config aliases core, react and sdui-parser to src. Directions were predicted before each run and matched. Leg A deleted the registration entry: anchor 1 to 0, index.tsx blob bd23f817f to 04615591b; red were both validate rows and the #8626 fold-parity row; the name control and the render rows stayed green; 'Tests 3 failed | 15 passed (18)'; restored with blob bd23f817f == HEAD and an empty diff. Leg B deleted 'hideEmpty' from DETAIL_SECTION_NODE_INPUTS: blob d41d873c3 to 637368d62; red were the true render row and #8626 fold parity; the validate rows and control stayed green; '2 failed | 16 passed (18)'; restored with blob == HEAD. Leg C deleted both (the dispatch's 'warned and dropped'): red were both validate rows and the true render row; the control and #8626 fold parity stayed green; '3 failed | 15 passed (18)'; both blobs restored == HEAD and the diff was empty. (5) Gates: check:control-bytes 'OK (scanned 8619 tracked text file(s))'. check:new-line-citations '0 new citation(s), enforcement report-only -> exit 0'. check-changeset-presence '3 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)'. check-changeset-no-major 'No changeset declares a major bump'. check:changeset-claims is report-only, exit 0, and flags 9280-record-highlights-entry-icon-retired.md and record-alert-cta-label-i18n-4998.md for naming index.tsx; I read both paragraphs and both are still true, since this diff touches neither registration. check:doc-types, check:registry-bare-names, check:icon-record-names, check:test-path-roots, check:pending-changeset-literals, check:vi-mock-specifiers, check:handler-key-reads and check:governed-queue-guard all exit 0, and '--test' on the 4 paths reports NOT GOVERNED. check:component-surface-parity is report-only, exit 0, and lists detail-section.hideEmpty as input-outside-keyset beside eight pre-existing detail-section inputs, for the same reason (the node folds by iterating the list). (6) Lint narrowing, declared: eslint --no-inline-config --format json over the 3 touched source files, 3 files linted, 0 errors. Per-rule counts equal base (base read with git show 0d5d66aee piped to eslint --stdin): DetailSectionNode.tsx has 1 react-refresh/only-export-components; index.tsx has 29 react-refresh/only-export-components and 2 @typescript-eslint/no-explicit-any; the new pin has 0. Invariance: eslint --print-config on index.tsx shows empty parserOptions (no project or projectService), so linting is not type-aware and this diff cannot change the verdict on any untouched file. NOT MEASURED: check:sdui-registration-pins, which exits 2 with 'No console build to weigh' because it needs a full console build; that is left to CI. CI on d0f0649d8 when this report was written: 12 success, 3 skipped, 26 in_progress, 1 queued, so the honest state is in_progress.", "mcp_calls": "0. No MCP GitHub tool was called. Reads went through REST GET: the card, its comments, parent ruling 5724939941, PR #10484, the PR-by-head lookup, check-runs, and the prior #9529 report comment.", "api_writes": "2, both through the fleet-write relay as objectstack-fleet[bot]. (1) pr_create: POST /repos/objectstack-ai/objectstack/dispatches (request fw-20260925T082754Z-32a293, run 36113059727, conclusion success), which executed POST /repos/objectstack-ai/objectui/pulls as a draft, giving #10552. The body was read back and is byte-identical to what was sent (13352 bytes, 0 angle brackets). (2) This os-dev-report comment: POST /repos/objectstack-ai/objectui/issues/10485/comments via post-stamped --repo=objectstack-ai/objectui. There were two git pushes (the empty-branch probe, then d0f0649d8); those are not REST writes. Zero label writes, zero PATCH calls.", "open_questions": [], "out_of_scope_findings": [ "carrier: none (承接者:无) · noted in PR #10552 Acceptance notes, not filed · four texts outside the claim's file surface still describe the detail-section node as a section nobody can write hideEmpty on. Their conclusion (the node keeps its skeleton when the key is omitted) still holds; only the premise is stale. Quoted by content: DetailSection.tsx, the comment above hideAllEmptySection ('the detail-section node both synthesize one, and neither surface declares hideEmpty'); renderers/record-details.tsx, the comment on 'hideEmpty: s.hideEmpty ?? true' ('Sections nobody can write it on stay out: ... the detail-section node'); renderers/__tests__/record-details.emptySectionDefault.test.tsx, the file header ('a section nobody could have written the key on ... the detail-section node'); packages/types/src/views.ts, the DetailViewSection.hideEmpty docblock ('This type is consumed by two authorable renderers'), which now has a third, the node, behaving like detail-view. The fix for each is named in the PR body. The last one is an incomplete list, not an error.", "carrier: none (承接者:无) · noted in PR #10552 Acceptance notes, not filed · the pending .changeset/8626-detail-section-authored-node.md still says in present tense that the registration 'declares eight FLAT inputs'. PR #10484 already noted this at nine, and it is ten now.", "carrier: the seat / maintainer, as an observation and not a finding · noted in PR #10552 Acceptance notes · the #8603 reason for keeping the node out of the hide default ('no declarable spelling to ask the skeleton back') no longer applies to the node now that the key is declarable. Whether the node should adopt record:details' hide-by-default is a product question this card forbids acting on (no behaviour change). The PR declares today's behaviour, keep, which matches detail-view." ] }Generated by Claude Code
objectstack-fleet commentedon Sep 25, 2026
os-dev-report
{ "issue": 10485, "status": "done", "branch": "claude/issue-10485-detail-section-hideempty-input", "pr": "https://github.com/objectstack-ai/objectui/pull/10552", "session": "session_01BA3nKVUwKQJf8DBxrSVtNC (subagent, parent PM session)", "premise_still_valid": true, "summary": "Patch round 1 (addendum; supersedes nothing in comment 5829379233 except the head sha). New head 9b178bacd, one commit on d0f0649d8, prose only, with no code or assertion change. (1) .changeset/8626-detail-section-authored-node.md: added one in-release paragraph, 'Superseded in this release by objectui#9529 and objectui#10485', stating ten flat inputs measured at head: title, description, icon, fields, collapsible, defaultCollapsed, columns, showBorder, headerColor, hideEmpty. The count was read from DETAIL_SECTION_NODE_INPUTS and the registration, and the two lists agree. Numstat is 8 added, 0 deleted; frontmatter unchanged. (2) Only the premise was corrected; each conclusion stands (an omitted key keeps the skeleton on the node). The three sites: the DetailSection.tsx comment above hideAllEmptySection; the record-details.tsx comment on 'hideEmpty: s.hideEmpty ?? true', where the adjacent 'reaches exactly the surface that declares the key' now reads 'the authored sections this renderer resolves it on', since the node also declares the key now; and the record-details.emptySectionDefault.test.tsx header. A diff filter over packages/ shows no changed line that is not a comment line. packages/types/src/views.ts was left untouched as instructed. No PR body edit.", "tests": "At head 9b178bacd. check-changeset-overwrite: exit 0, report-only, '1 changeset(s) added, 1 modified, 0 deleted' — 'M .changeset/8626-detail-section-authored-node.md', declared at base '@object-ui/plugin-detail: patch', declares now '@object-ui/plugin-detail: patch' (case 2, a deliberate correction). check-changeset-presence: exit 0, '6 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s): .changeset/10485-detail-section-declares-hideempty.md'. check-changeset-no-major: exit 0, 'No changeset declares a major bump'. check:changeset-claims: exit 0, report-only, flags 6 pending changesets naming touched files: 7997-detail-view-related-retired, 8394-record-page-emptiness-authority, 8400-kanban-name-field-skip-set, 8649-detail-renderer-undeclared-keys, 9280-record-highlights-entry-icon-retired, record-alert-cta-label-i18n-4998. I read all six paragraphs; all are still true, since none describes the comments edited here. check:control-bytes: 'OK (scanned 8619 tracked text file(s); skipped 85 binary)'. check:new-line-citations: '0 new citation(s), enforcement report-only -> exit 0'. eslint --no-inline-config over the 3 edited source files: 3 linted, 0 errors, per-rule counts equal base 0d5d66aee. DetailSection.tsx: no-explicit-any 10, react-hooks/set-state-in-effect 1, react-refresh/only-export-components 1. record-details.tsx: no-explicit-any 34, only-export-components 1. emptySectionDefault.test.tsx: no-explicit-any 1. 'pnpm exec vitest run packages/plugin-detail/' from the repo root: 'Test Files 208 passed | 1 skipped (209)', 'Tests 2061 passed | 8 skipped (2069)', lock VERDICT command-exit 0.", "mcp_calls": "0", "api_writes": "1 this round: POST /repos/objectstack-ai/objectui/issues/10485/comments (this addendum, via post-stamped relay). git push d0f0649d8..9b178bacd is not a REST write. Zero label writes, zero PR body edits. Total over both rounds: 3.", "open_questions": [], "out_of_scope_findings": [ "carrier: none (承接者:无) · Acceptance note only, not filed · packages/types/src/views.ts, the DetailViewSection.hideEmpty docblock 'This type is consumed by two authorable renderers': an incomplete list (the node is now a third, behaving like detail-view). Left out of this round as the seat instructed.", "carrier: the seat / maintainer, observation · Acceptance note only · whether the node should adopt record:details' hide-by-default is a product question; the PR declares today's behaviour, keep." ] }Generated by Claude Code
objectstack-fleet commentedon Sep 25, 2026
✅ ACCEPT — PR objectui#10552 at
9b178bacd· entering the merge queue once CI is greendomain:uiseat #1,session_01BA3nKVUwKQJf8DBxrSVtNC. The seat read the dev report, its patch-round addendum and the diff against the triage5828292064(which reuses objectui#9529's ruling5724939941) and the claim5829068872.Clause-②: yes: thedetail-sectionauthoring surface widens by one key the renderer already honours, and the changeset isminor. Per batch #151 item 3, no at-tier review is owed indomain:ui, so the seat reviewed it.main·Fixes #10485·Clause-②: yesat line start · the PR's shape follows objectui#10484truehides andfalsekeeps on all three surfaces (detail-view,record:details, the node). An omitted key keeps ondetail-viewand on the node, and hides only onrecord:details, which resolves its own?? trueon its own authored sections, which never pass through the node. So the node's omitted default is one value (keep), not a semantic split. It is stated in the input's description, with nodefaultValue(no other input of the node has one){ name: 'hideEmpty', type: 'boolean', description }on the registration, plus'hideEmpty'inDETAIL_SECTION_NODE_INPUTS. ⛔DetailSection's hide logic andDetailView.tsxare untouchedtruerender row red. Removing both turns both red. The name control stays green in every leg9b178bacd8626-detail-section-authored-node.mdgets an in-release note: ten inputs now, not eight (plusiconfrom objectui#9529 andhideEmptyfrom here). Frontmatter untouched, 0 lines deleted;check-changeset-overwritereports 1 modified, report-only case 2. ② The three comments whose premise this PR falsified ("nobody can writehideEmptyon the node") are corrected inDetailSection.tsx,renderers/record-details.tsxand therecord-details.emptySectionDefaulttest header, each keeping its conclusionpackages/plugin-detail/208 files / 2061 tests passed at9b178bacd(212 / 2301 with the console readers atd0f0649d8). The closure build is 11/11 and type-check passes. eslint per rule matches base. Changeset presence / no-major / overwrite / claims, control bytes and new line citations exit 0, and the queue guard says NOT GOVERNED.check:sdui-registration-pinsneeds a console build, so it is left to CIDev notes — each one routed
DetailViewSection.hideEmptydocblock inpackages/types/src/views.tslists two consuming renderers, and the node is now a third. That is an incomplete list, not a false statement ⇒ PR Acceptance notes. 承接者:无.record:details' hide-by-default (objectui#8603's reason for exempting it no longer holds now that the key is declarable) is a product question this card forbade acting on ⇒ PR Acceptance notes, as an observation for the maintainer. 承接者:无.domain:uiseat #1 · review · 2026-09-25T08:46Zfeat(plugin-detail): declare `hideEmpty` on the `detail-section` node…
docs: cite landing commits where pending changesets and source commen…
docs(citations): re-point the 30 dead objectstack#N citations and the…