Repository navigation
[finding] build-docs.ts renders nested item shapes as a collapsed signature and drops their describe() text — an item-level key's documentation never reaches the reference page #11601
Description
Activity
Concentrated triage batch:
finding→pm:queue, Task, M (domain:specstands) — an item-level.describe()is authored, substantial, and structurally unreachable by the generated reference (measured: editing it produces zero docs diff). Fix: teachbuild-docs.tsto render nested item shapes as a sub-table (or expandable rows) carrying each nested key's describe text, instead of one collapsed signature cell; regenerate and let the diff show which pages gain content. Design freedom on the rendering shape; the acceptance is that the measuredvisibleWhendescribe reaches the page.
Generated by Claude Code
Claim: PM loop round R6
Session:session_01NDGG54XF5gbTLdQzCtnaVV
Branch:claude/issue-11601-nested-describe-rendering
Worktree:objectstack-issue-11601
Domain:domain:spec
File surface:packages/spec/scripts/build-docs.ts(nested item-shape rendering) + its tests + regeneratedcontent/docs/references/**pages the change moves (tool-regenerated only) (stop on breach; explain in the report)
Container & model: M,mode:subagent,model: opus— dispatch-gates 2026-08-25 @0b478e1: "no path-derived mandate … floor sonnet · default opus · ceiling fable"; rendering-shape design + population enumeration is judgment no gate checks ⇒ default opus
Clause-②: no (docs generator + generated pages; no accept/reject change, nopackages/spec/src/**path expected — if the implementation unexpectedly needs one, the enqueue gate re-judges)
Serial constraints cleared:build-docs.tsprior writer PR #12213 (#11482, §3 enumeration) MERGED 13:45Z — premise re-verified on main@0b478e1:content/docs/references/ui/component.mdx:459still rendersitemsas one collapsed signature cell with an empty description column. Disjoint from batch sibling #12051 (check-skill-examples.ts). No pin assertions on sibling behavior.
Generated by Claude Code
{ "issue": 11601, "status": "done", "premise_still_valid": true, "branch": "claude/issue-11601-nested-describe-rendering", "pr": "https://github.com/objectstack-ai/objectstack/pull/12309", "pr_number": 12309, "head_sha": "044ceb120f1847505d9e8109ad6e0cb710bf85fc", "pr_state": "draft, base main, 147 files, +14848/-122", "premise_verification": { "assumption_1_collapsed_cell": "CONFIRMED on main@0b478e1. content/docs/references/ui/component.mdx:459 was exactly the collapsed signature with an empty Description column. packages/spec/src/ui/component.zod.ts:699-700 carries a ~600-char visibleWhen describe (row-vs-adapter binding, ADR-0089 rejection list). Both re-read, not assumed.", "assumption_3_pr_12213_disjoint": "CONFIRMED disjoint. #12213 extracted section 3 (rootCategoryDirs, lib/root-meta.ts). The rendering path this card touches is lib/schema-section.ts + lib/format-type.ts. No overlap; build-docs.ts itself is unchanged by this PR.", "zero_diff_reversal": "CONFIRMED both directions. Before: gen:docs produced zero diff for a nested describe edit. After (reverse verification): with nestedShapeOf neutered, check:docs exits 1 with 'content/docs/references/ is out of date with packages/spec'." }, "population_census": { "method": "walked packages/spec/json-schema (the generator's own input tree, regenerated at this HEAD), reproducing selectRootDef and the two branches of renderSchemaSection that emit a Properties table; shapes counted at the one depth level a cell opens, matching SHAPE_DEPTH_LIMIT=1", "documents_emitted": 1585, "property_rows_rendered": 8615, "property_rows_opening_a_nested_shape": 1293, "property_rows_with_at_least_one_described_nested_key": 1208, "distinct_schemas_affected": 566, "categories_affected": "13 of 14 (all but contracts, which publishes no JSON Schema)", "described_nested_keys": 7502, "nested_keys_total_including_undescribed": 8560, "describe_characters_unreachable": 472805, "rows_by_reach_path": { "objectChild": 735, "arrayItem": 374, "recordValue": 63, "unionVariant": 36 }, "rows_opening_more_than_one_shape_excluded_by_design": 28, "distinct_shapes_behind_the_1293_occurrences": 877, "occurrences_whose_shape_is_structurally_a_published_schema": 860, "unbounded_deep_walk_for_contrast": "22459 describe occurrences below a property row if every level were expanded; this design deliberately publishes only the 7502 at level 1" }, "rendering_choice": { "chosen": "sub-table, one per qualifying property row, emitted directly under the Properties table as '### Nested Shape: `Schema.key` followed by the accessor' where the accessor is a real TypeScript indexed access ('' for a direct object, '[number]' for an array element, '[string]' for a Record value, composed for wrapper stacks)", "why_sub_table_over_expandable_rows": "population is 1208 rows / 7502 keys across 566 schemas, far too large for inline prose in a Description cell, and the renderer already has exactly one relocation grammar for 'text a cell cannot carry' (### Allowed Values, #6225): same position, same addressing, same heading level. Expandable rows would be a second omission/disclosure notation, which #6226 ruled against for this table.", "why_indexed_accessor_notation": "names WHICH shape without inventing a sigil for a table that already carries two omission markers; 'items[number]' is the real TypeScript spelling of the element type", "bounds": [ "one level only, matched to the SHAPE_DEPTH_LIMIT budget a cell already spends", "only when at least one key of the shape carries describe text (1208 of 1293 rows)", "never for a property opening two or more object shapes (28 rows) - no single shape to name, mirroring formatPropertyType's refusal to relocate out of an array-of-enum", "a nested table elides vocabularies instead of relocating them; without this rule the 288-member ApiError.code list was re-emitted under every nested error shape: 20260 bullet lines, api/metadata.mdx alone +6097" ], "output_shape": "purely additive. 143 pages, +14195/-118 lines. Line-multiset comparison of origin/main's tree against the regenerated tree: 0 lines present before and absent after. '## SchemaName' heading multiset identical (same md5). Tree 38177 -> 52254 lines.", "rejected_alternatives": [ "per-page dedupe of identical sub-tables: measured 192 of 1180 blocks are same-page duplicates, would save 2926 of 14195 lines (21%); rejected because it needs a second addressing notation and breaks the adjacency rule the Allowed Values relocation set", "link a nested shape to the published schema it structurally matches: 860 of 1293 occurrences match, would cut added rows 7502 -> 1435; rejected because key-names-plus-describe-text is not schema identity and a confident link to the wrong schema is the #4696 defect" ] }, "file_list": { "hand_written": [ "packages/spec/scripts/lib/format-type.ts (+129: nestedShapeOf, NestedShape)", "packages/spec/scripts/lib/schema-section.ts (+96/-6: nested-shape sections, carriesDescription, summary-cell mode)", "packages/spec/scripts/nested-shape.test.ts (new, 22 pins)", ".changeset/docs-nested-item-shape-tables.md (@objectstack/spec: patch)" ], "tool_regenerated": "143 files under content/docs/references/** via `pnpm --filter @objectstack/spec gen:docs` only; no hand edit", "not_touched": "packages/spec/scripts/build-docs.ts, packages/spec/src/**, content/docs/releases/**, skills/**" }, "verification": [ { "command": "pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 (full spec suite)", "verdict": "Test Files 428 passed | 1 skipped (429) / Tests 11416 passed | 1 skipped (11417)" }, { "command": "pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 scripts/nested-shape.test.ts", "verdict": "Test Files 1 passed (1) / Tests 22 passed (22)" }, { "command": "pnpm --filter @objectstack/spec run check:docs", "verdict": "check:docs OK - '229 generated files in sync with packages/spec'" }, { "command": "pnpm --filter @objectstack/spec run check:generated", "verdict": "'All 14 generated artifacts are up to date.'" }, { "command": "pnpm --filter @objectstack/spec typecheck", "verdict": "tsc --noEmit + check:scripts-typecheck clean; 'check:test-typecheck: OK - @objectstack/spec's test layer compiles under packages/spec/tsconfig.test.json; 55 file(s) / 263 error(s) held in test-typecheck-debt.json (shrink-only)' - ledger unchanged" }, { "command": "pnpm lint (eslint . --no-inline-config, whole repo, no narrowing)", "verdict": "os-verify-lock: VERDICT command-exit 0 - held the lock 98s (1m38s)" }, { "command": "pnpm --filter @objectstack/spec run check:skill-examples", "verdict": "'256 prose examples type-check across 3 surface(s)'" }, { "command": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (re-derived from the real diff, no path list passed)", "verdict": "exit 0; 146 paths, 169 families discovered; the local list it printed is the one run below" }, { "command": "derived gate union re-run at HEAD 044ceb1 - 35 gates", "verdict": "all exit=0: check:cross-package-test-inputs, check:doc-anchors, check:doc-authoring, check:doc-formula-expressions, check:doc-security-posture, check:docs, check:docs-audit-scope, check:docs-redirects, check:empty-state, check:liveness, check:merge-driver, check:published-files, check:published-readme-links, check:quick-reference-counts, check:react-page-adapter-contract, check:role-word, check:skill-examples, check:slot-lookup, check:strictness-ledger, check:test-source-alias, check:type-source-resolution, check:variant-docs, check-ci-filter-parity, check-cross-package-test-inputs, check-doc-frontmatter, check-doc-route-spelling, check-docs-section-name, check-plugin-teardown-shape, check-section-landing-index, docs-audit/check-affected-docs, check:engine-double-contract, check:where-matcher, check:query-options-erasure, check:type-check-coverage, check:nul-bytes" }, { "command": "changeset families: check:changeset-gate-self-tests, check:objectui-changeset, check-adr-0087-registration --self-test, check-changeset-no-major --self-test, check-empty-changeset --self-test, release-rehearsal-clone --self-test", "verdict": "all exit=0" }, { "command": "grep -naP control-character scan over the four hand-written files", "verdict": "exit 1 (no match) - no raw control bytes" }, { "command": "REVERSE VERIFICATION (from the committed state, trap-restored): nestedShapeOf neutered to return null", "verdict": "mutation proved on disk first - injected marker 0 -> 1 occurrences, anchor still 1, git diff --stat '1 file changed, 1 insertion(+)'. MUTATED: 'Tests 14 failed | 8 passed (22)' and check:docs exit 1 'content/docs/references/ is out of date with packages/spec'. RESTORED: marker back to 0, git status clean, 'Tests 22 passed (22)', check:docs '229 generated files in sync'. Predicted direction was red; observed red. The 8 survivors are exactly the refusal cases (leaf, tombstone, named/self ref, cycle, two-object union) which answer null either way. No build/dist is involved - the renderer runs from source under tsx - so no dist preflight applies." } ], "not_measured_locally": [ "check:dev-prereqs - refuses on an unbuilt workspace ('62 packages missing dist'); needs a full `pnpm build`. Not a finding about this diff; CI builds before it gates.", "check:type-check-debt --re-measure - its own text says it needs the workspace closure built and refuses otherwise. check:type-check-coverage (the structural half) ran green." ], "deviations": [ "DISPATCH PREMISE FALSIFIED: 'your seat's GitHub API is unavailable (placeholder token, no gh)' is only half true. `gh` is absent and raw REST with $GITHUB_TOKEN returns 'GitHub access is not enabled for this session', BUT the github MCP tools work from this seat - get_me, issue_read(get_comments), create_pull_request and pull_request_read all succeeded. That is how PR #12309 and this report comment exist. Consequence for the standing contract: the skip-changeset additive-POST curl recipe would fail from this seat; MCP is the working channel.", "FILE SURFACE: the dispatch named packages/spec/scripts/build-docs.ts. The rendering logic lives in its extracted libs (lib/schema-section.ts since #7658, lib/format-type.ts since #4912); build-docs.ts itself is unchanged. Same declared surface in intent, different file, reported rather than assumed.", "CLAIM COMMENT: re-read before writing code (late, once MCP was found to work). Comment 5413332143 carries this dispatch's own session id and branch; no competing claim. Triage comment 5404975243 matches the ruling quoted in the dispatch verbatim.", "PR BODY vs API READ: pull_request_read returns the body with the generic Record type (angle brackets holding string comma string) stripped down to a bare `Record`. WebFetch of the rendered page shows it intact in both code blocks. Per AGENTS.md ('a body reading short only through the API is probably intact - check the rendered page before repairing it'), NO repair was made.", "Findings below are reported to the PM rather than filed, per the dispatch's 'findings(报给 PM 代查重)'. The standing 'search open issues before filing' step is unreachable from this seat anyway: raw REST list endpoints are blocked and the dispatch forbids MCP list_issues/search_issues (GraphQL pool). Say the word and I can file them via MCP issue_write." ], "findings": [ "OBSERVATION (finding class, not a defect in this PR): 28 property rows open two or more object shapes and keep the collapsed cell by design - ui/App.navigation (9 variants), ui/NavigationArea.navigation, ui/NavigationContribution.items, data/ConditionalValidation.then/.otherwise (5 each). Their nested describes stay unreachable. A follow-up could render one sub-table per variant under a variant-indexed heading.", "OBSERVATION: describes below level 1 stay unreachable by design (SHAPE_DEPTH_LIMIT=1). Contrast reading: an unbounded walk finds 22459 describe occurrences below a property row vs the 7502 this PR publishes.", "OBSERVATION: 860 of 1293 nested-shape occurrences are structurally a published schema that already has its own section (66x api/ApiError, 25x ui/AriaProps, 21x shared/Protection, 12x kernel/ExecutionContext, ...). Linking instead of re-tabling would cut the added rows from 7502 to 1435, at the cost of a schema-identity matcher. Candidate card if reference-tree size becomes a concern.", "OBSERVATION: packages/spec/json-schema emits ZERO named $refs - a survey of every emitted document finds only 854 '#/$defs/__schemaN' and 30 '#'. So formatType's named-$ref branch, and the category-scoped page resolution behind it (schemaHrefFrom / resolveSchemaPage, #4696), are unexercised by the current emitter: no generated reference cell can contain a schema link today. That is a lot of live-looking machinery over a dead path - worth a card to confirm whether build-schemas.ts is expected to hoist named refs, or whether the linking branch should be retired.", "OBSERVATION: the reference tree grows 1.70 MB -> 2.94 MB (38177 -> 52254 lines) with this change. Nothing in CI ratchets docs size (checked: quick-reference-counts counts PAGES per category, unchanged at 229 files; llms-txt gates claims, not bytes), so this is recorded for judgement rather than as a blocked gate." ], "summary": "Taught the reference-docs renderer to publish a nested item shape as its own table instead of collapsing it into a signature cell with no description column. nestedShapeOf (new, in lib/format-type.ts beside renderType so the two agree about what one shape level is) names the single shape a property cell opens plus the TypeScript indexed accessor that selects it; renderSchemaSection emits it as a '### Nested Shape:' table directly under the Properties table, in the position and grammar the '### Allowed Values:' relocation has used since #6225. Bounded four ways, each measured: one level, only where a key carries describe text, never for a multi-shape union, and no vocabulary relocation inside a nested table (that one alone was worth 20260 bullet lines). Regenerating moved 143 pages purely additively (+14195/-118, zero pre-existing lines lost), and the acceptance holds: the measured page:tabs visibleWhen describe now renders at content/docs/references/ui/component.mdx under '### Nested Shape: `PageTabsProps.items[number]`'.", "open_questions": [], "out_of_scope_findings": [] }
Generated by Claude Code
os-dev-report
(Re-post of comment 5414179949 with a literal-text marker: the HTML-comment form of this marker did not survive GitHub's body sanitizer, so that comment is invisible to a marker scan. Same JSON, byte for byte. There is no comment-edit tool on this seat, hence a second comment rather than an edit.)
{ "issue": 11601, "status": "done", "premise_still_valid": true, "branch": "claude/issue-11601-nested-describe-rendering", "pr": "https://github.com/objectstack-ai/objectstack/pull/12309", "pr_number": 12309, "head_sha": "044ceb120f1847505d9e8109ad6e0cb710bf85fc", "pr_state": "draft, base main, 147 files, +14848/-122", "premise_verification": { "assumption_1_collapsed_cell": "CONFIRMED on main@0b478e1. content/docs/references/ui/component.mdx:459 was exactly the collapsed signature with an empty Description column. packages/spec/src/ui/component.zod.ts:699-700 carries a ~600-char visibleWhen describe (row-vs-adapter binding, ADR-0089 rejection list). Both re-read, not assumed.", "assumption_3_pr_12213_disjoint": "CONFIRMED disjoint. #12213 extracted section 3 (rootCategoryDirs, lib/root-meta.ts). The rendering path this card touches is lib/schema-section.ts + lib/format-type.ts. No overlap; build-docs.ts itself is unchanged by this PR.", "zero_diff_reversal": "CONFIRMED both directions. Before: gen:docs produced zero diff for a nested describe edit. After (reverse verification): with nestedShapeOf neutered, check:docs exits 1 with 'content/docs/references/ is out of date with packages/spec'." }, "population_census": { "method": "walked packages/spec/json-schema (the generator's own input tree, regenerated at this HEAD), reproducing selectRootDef and the two branches of renderSchemaSection that emit a Properties table; shapes counted at the one depth level a cell opens, matching SHAPE_DEPTH_LIMIT=1", "documents_emitted": 1585, "property_rows_rendered": 8615, "property_rows_opening_a_nested_shape": 1293, "property_rows_with_at_least_one_described_nested_key": 1208, "distinct_schemas_affected": 566, "categories_affected": "13 of 14 (all but contracts, which publishes no JSON Schema)", "described_nested_keys": 7502, "nested_keys_total_including_undescribed": 8560, "describe_characters_unreachable": 472805, "rows_by_reach_path": { "objectChild": 735, "arrayItem": 374, "recordValue": 63, "unionVariant": 36 }, "rows_opening_more_than_one_shape_excluded_by_design": 28, "distinct_shapes_behind_the_1293_occurrences": 877, "occurrences_whose_shape_is_structurally_a_published_schema": 860, "unbounded_deep_walk_for_contrast": "22459 describe occurrences below a property row if every level were expanded; this design deliberately publishes only the 7502 at level 1" }, "rendering_choice": { "chosen": "sub-table, one per qualifying property row, emitted directly under the Properties table as '### Nested Shape: `Schema.key` followed by the accessor' where the accessor is a real TypeScript indexed access ('' for a direct object, '[number]' for an array element, '[string]' for a Record value, composed for wrapper stacks)", "why_sub_table_over_expandable_rows": "population is 1208 rows / 7502 keys across 566 schemas, far too large for inline prose in a Description cell, and the renderer already has exactly one relocation grammar for 'text a cell cannot carry' (### Allowed Values, #6225): same position, same addressing, same heading level. Expandable rows would be a second omission/disclosure notation, which #6226 ruled against for this table.", "why_indexed_accessor_notation": "names WHICH shape without inventing a sigil for a table that already carries two omission markers; 'items[number]' is the real TypeScript spelling of the element type", "bounds": [ "one level only, matched to the SHAPE_DEPTH_LIMIT budget a cell already spends", "only when at least one key of the shape carries describe text (1208 of 1293 rows)", "never for a property opening two or more object shapes (28 rows) - no single shape to name, mirroring formatPropertyType's refusal to relocate out of an array-of-enum", "a nested table elides vocabularies instead of relocating them; without this rule the 288-member ApiError.code list was re-emitted under every nested error shape: 20260 bullet lines, api/metadata.mdx alone +6097" ], "output_shape": "purely additive. 143 pages, +14195/-118 lines. Line-multiset comparison of origin/main's tree against the regenerated tree: 0 lines present before and absent after. '## SchemaName' heading multiset identical (same md5). Tree 38177 -> 52254 lines.", "rejected_alternatives": [ "per-page dedupe of identical sub-tables: measured 192 of 1180 blocks are same-page duplicates, would save 2926 of 14195 lines (21%); rejected because it needs a second addressing notation and breaks the adjacency rule the Allowed Values relocation set", "link a nested shape to the published schema it structurally matches: 860 of 1293 occurrences match, would cut added rows 7502 -> 1435; rejected because key-names-plus-describe-text is not schema identity and a confident link to the wrong schema is the #4696 defect" ] }, "file_list": { "hand_written": [ "packages/spec/scripts/lib/format-type.ts (+129: nestedShapeOf, NestedShape)", "packages/spec/scripts/lib/schema-section.ts (+96/-6: nested-shape sections, carriesDescription, summary-cell mode)", "packages/spec/scripts/nested-shape.test.ts (new, 22 pins)", ".changeset/docs-nested-item-shape-tables.md (@objectstack/spec: patch)" ], "tool_regenerated": "143 files under content/docs/references/** via `pnpm --filter @objectstack/spec gen:docs` only; no hand edit", "not_touched": "packages/spec/scripts/build-docs.ts, packages/spec/src/**, content/docs/releases/**, skills/**" }, "verification": [ { "command": "pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 (full spec suite)", "verdict": "Test Files 428 passed | 1 skipped (429) / Tests 11416 passed | 1 skipped (11417)" }, { "command": "pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 scripts/nested-shape.test.ts", "verdict": "Test Files 1 passed (1) / Tests 22 passed (22)" }, { "command": "pnpm --filter @objectstack/spec run check:docs", "verdict": "check:docs OK - '229 generated files in sync with packages/spec'" }, { "command": "pnpm --filter @objectstack/spec run check:generated", "verdict": "'All 14 generated artifacts are up to date.'" }, { "command": "pnpm --filter @objectstack/spec typecheck", "verdict": "tsc --noEmit + check:scripts-typecheck clean; 'check:test-typecheck: OK - @objectstack/spec's test layer compiles under packages/spec/tsconfig.test.json; 55 file(s) / 263 error(s) held in test-typecheck-debt.json (shrink-only)' - ledger unchanged" }, { "command": "pnpm lint (eslint . --no-inline-config, whole repo, no narrowing)", "verdict": "os-verify-lock: VERDICT command-exit 0 - held the lock 98s (1m38s)" }, { "command": "pnpm --filter @objectstack/spec run check:skill-examples", "verdict": "'256 prose examples type-check across 3 surface(s)'" }, { "command": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (re-derived from the real diff, no path list passed)", "verdict": "exit 0; 146 paths, 169 families discovered; the local list it printed is the one run below" }, { "command": "derived gate union re-run at HEAD 044ceb1 - 35 gates", "verdict": "all exit=0: check:cross-package-test-inputs, check:doc-anchors, check:doc-authoring, check:doc-formula-expressions, check:doc-security-posture, check:docs, check:docs-audit-scope, check:docs-redirects, check:empty-state, check:liveness, check:merge-driver, check:published-files, check:published-readme-links, check:quick-reference-counts, check:react-page-adapter-contract, check:role-word, check:skill-examples, check:slot-lookup, check:strictness-ledger, check:test-source-alias, check:type-source-resolution, check:variant-docs, check-ci-filter-parity, check-cross-package-test-inputs, check-doc-frontmatter, check-doc-route-spelling, check-docs-section-name, check-plugin-teardown-shape, check-section-landing-index, docs-audit/check-affected-docs, check:engine-double-contract, check:where-matcher, check:query-options-erasure, check:type-check-coverage, check:nul-bytes" }, { "command": "changeset families: check:changeset-gate-self-tests, check:objectui-changeset, check-adr-0087-registration --self-test, check-changeset-no-major --self-test, check-empty-changeset --self-test, release-rehearsal-clone --self-test", "verdict": "all exit=0" }, { "command": "grep -naP control-character scan over the four hand-written files", "verdict": "exit 1 (no match) - no raw control bytes" }, { "command": "REVERSE VERIFICATION (from the committed state, trap-restored): nestedShapeOf neutered to return null", "verdict": "mutation proved on disk first - injected marker 0 -> 1 occurrences, anchor still 1, git diff --stat '1 file changed, 1 insertion(+)'. MUTATED: 'Tests 14 failed | 8 passed (22)' and check:docs exit 1 'content/docs/references/ is out of date with packages/spec'. RESTORED: marker back to 0, git status clean, 'Tests 22 passed (22)', check:docs '229 generated files in sync'. Predicted direction was red; observed red. The 8 survivors are exactly the refusal cases (leaf, tombstone, named/self ref, cycle, two-object union) which answer null either way. No build/dist is involved - the renderer runs from source under tsx - so no dist preflight applies." } ], "not_measured_locally": [ "check:dev-prereqs - refuses on an unbuilt workspace ('62 packages missing dist'); needs a full `pnpm build`. Not a finding about this diff; CI builds before it gates.", "check:type-check-debt --re-measure - its own text says it needs the workspace closure built and refuses otherwise. check:type-check-coverage (the structural half) ran green." ], "deviations": [ "DISPATCH PREMISE FALSIFIED: 'your seat's GitHub API is unavailable (placeholder token, no gh)' is only half true. `gh` is absent and raw REST with $GITHUB_TOKEN returns 'GitHub access is not enabled for this session', BUT the github MCP tools work from this seat - get_me, issue_read(get_comments), create_pull_request and pull_request_read all succeeded. That is how PR #12309 and this report comment exist. Consequence for the standing contract: the skip-changeset additive-POST curl recipe would fail from this seat; MCP is the working channel.", "REPORT MARKER: the prescribed HTML-comment marker did NOT survive GitHub's comment sanitizer (measured: comment 5414179949 came back starting with a blank line, marker gone). This seat has no comment-edit tool, so the report is re-posted with the literal-text marker instead of edited.", "FILE SURFACE: the dispatch named packages/spec/scripts/build-docs.ts. The rendering logic lives in its extracted libs (lib/schema-section.ts since #7658, lib/format-type.ts since #4912); build-docs.ts itself is unchanged. Same declared surface in intent, different file, reported rather than assumed.", "CLAIM COMMENT: re-read before writing code (late, once MCP was found to work). Comment 5413332143 carries this dispatch's own session id and branch; no competing claim. Triage comment 5404975243 matches the ruling quoted in the dispatch verbatim.", "PR BODY vs API READ: pull_request_read returns the body with the generic Record type (angle brackets holding string comma string) stripped down to a bare `Record`. WebFetch of the rendered page shows it intact in both code blocks. Per AGENTS.md ('a body reading short only through the API is probably intact - check the rendered page before repairing it'), NO repair was made.", "Findings below are reported to the PM rather than filed, per the dispatch's 'findings(报给 PM 代查重)'. The standing 'search open issues before filing' step is unreachable from this seat anyway: raw REST list endpoints are blocked and the dispatch forbids MCP list_issues/search_issues (GraphQL pool). Say the word and I can file them via MCP issue_write." ], "findings": [ "OBSERVATION (finding class, not a defect in this PR): 28 property rows open two or more object shapes and keep the collapsed cell by design - ui/App.navigation (9 variants), ui/NavigationArea.navigation, ui/NavigationContribution.items, data/ConditionalValidation.then/.otherwise (5 each). Their nested describes stay unreachable. A follow-up could render one sub-table per variant under a variant-indexed heading.", "OBSERVATION: describes below level 1 stay unreachable by design (SHAPE_DEPTH_LIMIT=1). Contrast reading: an unbounded walk finds 22459 describe occurrences below a property row vs the 7502 this PR publishes.", "OBSERVATION: 860 of 1293 nested-shape occurrences are structurally a published schema that already has its own section (66x api/ApiError, 25x ui/AriaProps, 21x shared/Protection, 12x kernel/ExecutionContext, ...). Linking instead of re-tabling would cut the added rows from 7502 to 1435, at the cost of a schema-identity matcher. Candidate card if reference-tree size becomes a concern.", "OBSERVATION: packages/spec/json-schema emits ZERO named $refs - a survey of every emitted document finds only 854 '#/$defs/__schemaN' and 30 '#'. So formatType's named-$ref branch, and the category-scoped page resolution behind it (schemaHrefFrom / resolveSchemaPage, #4696), are unexercised by the current emitter: no generated reference cell can contain a schema link today. That is a lot of live-looking machinery over a dead path - worth a card to confirm whether build-schemas.ts is expected to hoist named refs, or whether the linking branch should be retired.", "OBSERVATION: the reference tree grows 1.70 MB -> 2.94 MB (38177 -> 52254 lines) with this change. Nothing in CI ratchets docs size (checked: quick-reference-counts counts PAGES per category, unchanged at 229 files; llms-txt gates claims, not bytes), so this is recorded for judgement rather than as a blocked gate." ], "summary": "Taught the reference-docs renderer to publish a nested item shape as its own table instead of collapsing it into a signature cell with no description column. nestedShapeOf (new, in lib/format-type.ts beside renderType so the two agree about what one shape level is) names the single shape a property cell opens plus the TypeScript indexed accessor that selects it; renderSchemaSection emits it as a '### Nested Shape:' table directly under the Properties table, in the position and grammar the '### Allowed Values:' relocation has used since #6225. Bounded four ways, each measured: one level, only where a key carries describe text, never for a multi-shape union, and no vocabulary relocation inside a nested table (that one alone was worth 20260 bullet lines). Regenerating moved 143 pages purely additively (+14195/-118, zero pre-existing lines lost), and the acceptance holds: the measured page:tabs visibleWhen describe now renders at content/docs/references/ui/component.mdx under '### Nested Shape: `PageTabsProps.items[number]`'.", "open_questions": [], "out_of_scope_findings": [] }
Generated by Claude Code
PM review: ACCEPT — PR #12309, head
044ceb1(round R6, sessionsession_01NDGG54XF5gbTLdQzCtnaVV).Acceptance met, verified in the tree: the measured
page:tabsitemvisibleWhendescribe now renders atcontent/docs/references/ui/component.mdx:586under### Nested Shape: \PageTabsProps.items[number]`` — the exact criterion the triage ruling set.Verified against the diff: hand-written surface is 4 files (
lib/format-type.ts+129nestedShapeOf,lib/schema-section.ts+117,nested-shape.test.ts22 pins, changeset patch); the 143 changed reference pages are tool-regenerated only, all confined tocontent/docs/references/**;build-docs.tsitself unchanged — the dispatch's file-surface line resolved honestly (the rendering lives in the extracted libs since #7658/#4912; same intent surface, reported not assumed).Design quality: population-first exactly as dispatched — 1,208 qualifying rows / 7,502 nested describes / 566 schemas / 13 of 14 categories counted before the shape was chosen. Sub-table under the existing
### Allowed Valuesrelocation grammar (#6225) with a real TypeScript indexed accessor; four measured bounds, the sharpest being no-vocabulary-relocation-inside-nested-tables (that rule alone avoided 20,260 re-emitted bullet lines). Output proven purely additive (line-multiset: zero pre-existing lines lost; heading multiset md5-identical). Reverse verification flipscheck:docsred when the new path is neutered — the zero-diff defect measurably reversed. Full derived gate union green; the two workspace-build-gated checks declared to CI.Findings disposition (deduped, both new, filed on the dev's behalf): #12315 (the named-$ref link branch is a dead path —
json-schemaemits zero named refs,schemaHrefFrom/resolveSchemaPageunexercised; interacts with the 860-occurrence linking observation) and #12316 (the 28 multi-shape rows that stay collapsed by design). Two observations recorded here without cards: level-2+ describes stay out of scope by theSHAPE_DEPTH_LIMIT=1design, and the reference tree grows 1.70 → 2.94 MB with nothing in CI ratcheting docs size — the latter is surfaced to the maintainer in the round report as a judgment fact, not a defect.Clause-②: does not fire — no
packages/spec/src/**path. Normal queue path: ready + auto-merge once every check on044ceb1is green.
Generated by Claude Code
os-dev-report
Continuation round: rebase-drift fix for the single red gate on PR #12309. (Literal-text marker again — the HTML-comment form does not survive GitHub's comment sanitizer on this repo.)
{ "issue": 11601, "round": "R6 continuation - base drift repair", "status": "done", "premise_still_valid": true, "branch": "claude/issue-11601-nested-describe-rendering", "pr_number": 12309, "pushed_head_sha": "caf59b29b0bcfcead71775c1f4e491facec639a8", "merged_main_sha": "79cf692b0e1336b62f5170215c872e5859f44088", "merge_commit_sha": "08abc9fa47b89741eb6591df83110a3daa0535c1", "regen_commit_sha": "caf59b29b0bcfcead71775c1f4e491facec639a8", "diagnosis_confirmed": "Base drift, not an implementation defect. The branch regenerated 143 pages from main@0b478e1; PR #12203 then landed SearchAllResponseSchema / SearchAllHitSchema / CloneDataResponseSchema in packages/spec/src/api/protocol.zod.ts. On the merge ref the branch's protocol.mdx described a source the merged tree no longer has, so check:docs called it out of date.", "procedure": "bash scripts/pm/os-regen-merge.sh (the in-repo authority). It committed the merge at step 1 and its step-3 commit was REFUSED by the os-regen pre-commit hook, with the reason stated: 'check:docs reads packages/spec/json-schema/, which is missing or older than src - NOT running it'. That is the hook working: the gitignored schema tree does not survive a fresh worktree. Verified before regenerating that HEAD was already the merge commit and no MERGE_HEAD existed, so the AGENTS.md anchor trap ('never run gen:schema in MERGE state') did not apply - regeneration ran on the merged HEAD, which is exactly the sanctioned order. Then gen:schema + gen:docs, git add -A, commit. Hook output on that commit: 'os-regen: all deferred artifacts are current - marker cleared.' No hand edits to any generated file, no stash, no force-push.", "protocol_mdx": { "vs_merge_commit": "+56 / -2 lines; 1 new nested-shape section: '### Nested Shape: `SearchAllResponse.hits[number]`' - this branch's renderer applied to #12203's new array-of-object property, exactly the expected interaction", "vs_origin_main": "+978 / -0 lines, 74 '### Nested Shape:' sections on this page", "new_schema_sections_present": "## CloneDataResponse (line 477), ## SearchAllHit (2377), ## SearchAllResponse (2392)" }, "worth_flagging": "The textual auto-merge of the two generated pages DID lose content: regenerating from the merged tree re-added three '### Properties' headings that git's ort merge had dropped from api/protocol.mdx while exiting 0 with no conflict markers. That is the exact silent-drop signature .gitattributes' merge=os-regen driver exists to catch, observed live here. The regeneration is what recovered it; a textual conflict resolution would have shipped the loss.", "verification_at_caf59b29": [ { "command": "pnpm --filter @objectstack/spec run check:docs", "verdict": "'229 generated files in sync with packages/spec' (exit 0)" }, { "command": "pnpm --filter @objectstack/spec run check:generated", "verdict": "'All 14 generated artifacts are up to date.' (exit 0)" }, { "command": "pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 scripts/nested-shape.test.ts scripts/schema-section.test.ts scripts/format-type.test.ts", "verdict": "Test Files 3 passed (3) / Tests 132 passed (132) - the 22 nested-shape pins included" }, { "command": "pnpm --filter @objectstack/spec run check:skill-examples", "verdict": "'256 prose examples type-check across 3 surface(s)' (exit 0)" }, { "command": "turbo run build --filter spec/formula/lint/client/client-react", "verdict": "'Tasks: 33 successful, 33 total' - prerequisite for the two dist-reading gates above" }, { "command": "line-multiset comparison of origin/main's reference tree against the regenerated tree", "verdict": "0 lines present in origin/main and absent from ours - still purely additive after the merge. 38221 -> 52308 lines; 143 files, +14205 / -118 vs origin/main" }, { "command": "tree-wide nested-shape section count", "verdict": "1180 -> 1181 (the one new section is SearchAllResponse.hits[number])" }, { "command": "git status --porcelain", "verdict": "0 - clean at push time; push exit 0 first attempt, no retry needed" } ], "not_re_run_this_round": "Full spec suite, pnpm lint and the 35-gate union were green at 044ceb1 and this round changed only two regenerated .mdx files plus a merge of main. CI on the merged ref is the authority for the rest, per the standing contract that CI convergence is the PM's.", "housekeeping": "Worktree rebuilt for this round and removed again afterwards (rm -rf node_modules then git worktree remove, exit 0, no --force). The three sibling agent worktrees are untouched. A further patch round needs a fresh worktree add + pnpm install + a spec build, which cost roughly 9 minutes of shared-lock queueing this round - worth knowing before dispatching another mechanical continuation." }
Generated by Claude Code
- added a commit that references this issue
on Aug 26, 2026 - added a commit that references this issue
on Aug 26, 2026
Filed unassigned by the
domain:specseat while implementing #11256 (sessionsession_01T9cDbY2NBiVJWYx3BpWfH2, PR #11600). Observation, not a defect claim — nothing is broken; a describe simply does not reach the surface an author reads.What was measured
ComponentSchema'spage:tabsitems[]carries a per-itemvisibleWhenwith its own substantial.describe()(packages/spec/src/ui/component.zod.ts). In the generated reference, the whole item shape collapses into one signature cell and every nested describe is dropped —content/docs/references/ui/component.mdx:The description column is empty, and
visibleWhen?: string \| objectis the entirety of what an author learns. Editing that describe produces no docs diff at all — confirmed on #11256, where agen:docsrun over a changed nested describe moved zero lines incomponent.mdx(the sibling top-level describe inpage.zod.tsmoved its row normally).Why it is worth recording rather than shrugging at
page:tabsitemvisibleWhenis the surface wheredatameans the record row, whereas the identically-named component-node key bindsdatato the data-source adapter (measured at.objectui-shapin190fbd01d061:containers.tsx:450-457vsSchemaRenderer.tsx:463-471). docs(spec): visibleWhen's describe states the bound roots per ADR-0068 (was three of nine) #11600 wrote that divergence into the item describe precisely so an author would meet it — and on the reference page they will not.items[]/options[]shapes on the UI surfaces — has the same shape, so this is a class rather than a single miss. The size of that population has not been enumerated here; that is the first thing whoever takes this should measure.Not a request to change anything yet
The honest options differ a lot in cost — emit nested describes inline in the signature cell, give nested shapes their own sub-table, or rule that nested describes are deliberately source-only and stop treating the reference page as their audience. Which is right depends on how large the affected population actually is, so this records the observation rather than proposing the fix.
Adjacent and distinct: #11482 (
build-docs.ts§3 rootmeta.jsonenumeration) is about routing categories, not nested field rendering.Generated by Claude Code