Repository navigation
types,components: layout spacing keys declared as a bare number while the renderer maps a closed set; stack gap 7 and flex gap 9 parse green and draw no gap class (family closure card after objectui#10286 and objectui#11424) #11474
Description
Activity
objectstack-fleet commented
on Oct 2, 2026 ContributorAuthorMore actionsTriage: first grade —
bug·priority:p3·domain:spec·area:devpath·pm:queue;findingremoved. Each open spacing key closes to its renderer's set, with one enumeration pinTriage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-02T14:54Z. ⛔ Not a claim, ⛔ not a dispatch.Why p3. It matches its closed sibling objectui#11424 (p3). It is class (c): a gap outside the mapped set parses green and draws no class, which is silent but cosmetic.
Routing.
packages/types(layout.zod.tsand the TS faces) isdomain:spec, as its closed members were. The registration inputs ride as the declared cross-lanedomain:uisurface.Direction: the card's, accepted as the family close-out.
stack.gapandflex.gapeach close to their renderer's mapped set, on both faces and on the registration input, incontainer.padding'senumform. The refusal names the set.- The
flex/griddescribes stop advertising "0-8", unless that is the set. grid.gapis measured first: does a runtime-built class reach a compiled stylesheet? If it does, the pin records it as an open scale. If not, it closes like the other two.- ⛔ The renderer never rounds or clamps. ⛔ No per-key card.
- Enumeration pin:
container-padding-set-11424.test.tsxis generalised into one test. It renders each layout node's spacing key across a range, derives the mapped set, and holds the declaration and the registration to it.
Generated by Claude Code
- addedarea:devpathThe road — create, dev, verify, publish/install, connect an agent, iterateThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingSomething isn't workingdomain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec laneobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec laneand removed
on Oct 2, 2026 objectstack-fleet commented
on Oct 2, 2026 ContributorAuthorMore actionsClaim: PM loop round 1 (triage's family close-out direction
5955082167:stack.gapandflex.gapclose to their renderers' sets on both faces and the registration inputs;grid.gapis measured first; one enumeration pin)
Session:session_01XvhGmGAP79ZB8swnkapxPC
Account:os-tesla(the seat's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-11474-layout-spacing-sets
Worktree:objectui-issue-11474
Domain:domain:spec
Seat:domain:spec#1(objectui#10217)
File surface:StackSchema,FlexSchema(and the flex bag that mirrors it) andGridSchemagapinpackages/types/src/zod/layout.zod.ts, and their TS twins inpackages/types/src/layout.ts.- The
gapregistration inputs inpackages/components/src/renderers/layout/stack.tsx,flex.tsxandgrid.tsx: the declared cross-lanedomain:uisurface. ⛔ Not their branches; nothing rounds or clamps. - The generalised enumeration pin, replacing or absorbing
container-padding-set-11424.test.tsx. - Corpus documents that author an unmapped
gap. - Tests, and one changeset.
Stop on breach; explain in the report.
Container & model:M,mode:subagent,model: opus(TIER_DEFAULT;dispatch-gates --tier --repo objectstack-ai/objectuiprinted "no path-derived mandate" forlayout.ts,zod/layout.zod.tsand the renderer paths)
Clause-②: no
Why no (narrowing):gapshrinks from every number to each renderer's mapped set, and a describe stops advertising a range. Nothing widens. Ifgrid.gapis measured as an open scale, it does not move. The at-tier contract record is owed on the landing head, because a published accept set moves.
Thread-read: 5955082167
Serial constraints cleared: read 2026-10-02T16:26Z at objectuiorigin/main50c73fed0. layout.zod.ts/layout.ts: no open PR or in-flight claim edits them. objectui#11424's PR objectui#11470 (container.padding) landed as3f6efd640, and objectui#11468's PR objectui#11477 (FlexBlockNode, derived from the flex mirror by reference) landed as2c0ddf226. A closedflex.gapflows intoFlexBlockNodewith no edit there.- Open PRs of this seat: objectui#11482 (
complex.ts), feat(types)!: SidebarSchema declares what the sidebar node draws; nine unread keys retire, variant takes the registration's enum (objectui#11465) #11485 (navigation.ts) and fix(types): AnySchema includes every declared node type, pinned by an enumeration (objectui#11478) #11486 (index.ts). File-disjoint.
objectstack-fleet commented
on Oct 2, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 11474, "status": "done", "branch": "claude/issue-11474-layout-spacing-sets", "pr": "https://github.com/objectstack-ai/objectui/pull/11489", "session": "session_01XvhGmGAP79ZB8swnkapxPC (subagent run: the dispatching seat's session, as the Claude-Session trailer names it)", "premise_still_valid": true, "summary": "stack.gap, flex.gap (and the authored flex bag, which holds the member by reference) and grid.gap now accept only their renderer's mapped steps on both faces and on the registration inputs, with the refusal naming the set. The sets are stack 0-6, 8, 10; flex 0-8; grid 0-6, 8, 10, 12. grid.gap was measured first: its runtime-built gap-[N*0.25rem] class for an unmapped number is absent from both compiled sheets (console and components), while every mapped class is present and the arbitrary-value matcher finds max-w-[16rem] and px-[0.3rem]. So grid closes like the other two. One shared zod helper (rendererSpacingSteps) now carries container.padding (refusal text byte-identical to base) and the three gaps. TS StackSchema declares its own gap through Omit over FlexLayoutProps, which has no index signature. The flex/grid describes no longer say 0-8. Registrations use container.padding's enum object form, and the renderers' branches are untouched. container-padding-set-11424.test.tsx is generalised into layout-spacing-sets-11474.test.tsx. It derives the enumeration (every isContainer registration's numeric inputs), classifies spacing keys by rendering, and counts a step as mapped only when its drawn utilities are rules in the package's compiled stylesheet. It then holds the declaration (tolerant and strict faces, authored spelling derived) and the registration enum to that set. Surface beyond the claim, declared: GridBuilder.gap/FlexBuilder.gap in @object-ui/core (a typed producer that tsc forces to follow the declaration), three docs reference pages, and one fixture code (invalid_type to invalid_value) in flex-properties-bag-11276.test.ts. Card assignee untouched. The PR assignee write was refused by the local classifier; the seat should do it.", "tests": "All at head 1db960ca unless noted. Builds: pnpm --filter '@object-ui/components^...' --filter @object-ui/components run build (9 pkgs, exit 0); turbo run build --filter='./packages/*' --concurrency=2 (39/39 tasks). type-check (script name echoed, test tsconfigs include the new pins per --listFilesOnly): types 0, core 0, components 0. vitest from worktree root: packages/types/ 334 files 8840 passed; packages/core/ 193 files 3844 passed 27 skipped; packages/components/ 353 passed 1 skipped (3584 tests passed); examples/schema-catalog/ 40 files 2259 passed; packages/sdui-parser/ 20 files 289 passed; 9 registry-reading files (console component-input-union-specimens, ga-honoured-inputs-author-reach, html-tier-manifest, public-contract, registry-inputs-spec-parity; app-shell widget-dom-leak-sweep; layout containment-declared-slot-9910; plugin-designer designerRegistrationInputs-11434; scripts check-component-surface-parity test) 584 passed. Before-reading at base 50c73fed0 (throwaway probe, real SchemaRenderer): stack gap 7 and flex properties.gap 9 parse green on safeValidateSchema and StrictAnyComponentSchema and draw no gap class; grid gap 9 parses green and draws gap-[2.25rem]. validateTree probe at head: stack gap 7 / flex gap 9 / grid gap 9 / container padding 9 each answer error invalid-enum naming the set; controls 4/8/12/8 answer nothing. Ablations (committed head, objectstack scripts/ablation-replace.mjs wrap mode; landing proven by anchor count and blob change; restore proven by blob == HEAD and empty git diff HEAD; src-aliased tests, no dist in path): A1b registration drops 10, red ('stack.gap registration enum: expected [ +0, 1, 2, 3, 4, 5, 6, 8 ] to deeply equal [ +0, 1, 2, 3, 4, 5, 6, 8, 10 ]'). A2b stack.tsx gains a gap===7 branch, red ('stack.gap on the tolerant face: expected [ +0..6, 8, 10 ] to deeply equal [ +0..8, 10 ]'). A3 STACK_GAP_STEPS gains 7, red in both pins. A4 grid GAPS drops 10, red (grid.gap 1 failed / 11 passed), which shows the stylesheet criterion is live. A5 TS StackSchema.gap gains 7, tsc -p tsconfig.test.json red (unused ts-expect-error; Same true-to-false; plus zod-mirror-parity). Expected direction red for all five; observed red. The first A1/A2 attempts were no-ops refused by the tool (empty replacement; anchor inside its replacement) and were re-run as A1b/A2b. Lint narrowed: eslint --format json over the 11 changed ts/tsx files; population = all 11 linted per the root config's isPathIgnored; JSON reports 11 files, 0 errors, 9 warnings, all on untouched lines; the config enables no type-aware linting, so untouched files' verdicts cannot move. The repo-wide lint is CI's.", "mcp_calls": "0", "api_writes": "2 — (1) fleet-write relay: POST /repos/objectstack-ai/objectstack/dispatches (HTTP 204), run 37038949141 executed pr_create on objectstack-ai/objectui as objectstack-fleet[bot], making PR #11489 (draft); read-back 14381 bytes sent, 14381 stored, identical. (2) post-stamped.mjs --comment=11474: POST /repos/objectstack-ai/objectui/issues/11474/comments (this os-dev-report). Attempted and refused before any network: label-write.mjs --issue 11489 --assign os-tesla, denied by the local auto-mode classifier [External System Writes], 0 requests sent. git push is not counted.", "open_questions": [], "out_of_scope_findings": [ "class: c · reach: public door + wrong answer, measured at head through the real SchemaRenderer: { type: 'grid', columns: 13 } parses green on safeValidateSchema and StrictAnyComponentSchema and draws 'grid-cols-1 sm:grid-cols-2' (the md count is dropped); columns 0 and -1 draw 'grid-cols-2' (substituted); columns { md: 13 } draws 'grid-cols-1'; columns { xs: 13 } draws 'grid-cols-2' · evidence: GridSchema.columns is z.number() or a partialRecord of z.number(), the registration's columns/smColumns/mdColumns/lgColumns/xlColumns inputs are type 'number', and grid.tsx maps 1 to 12 through its GRID_COLS* maps with a '|| grid-cols-2' base fallback · family: the same shape as this card's (a numeric layout key declared as any number, renderer maps a closed set). The dispatch said report, not close; the seat decides whether it joins this family close-out or gets a follow-up. It is not a spacing key, so the new pin classifies it and holds nothing · dedupe words: grid columns 13 no md class · grid columns z.number GRID_COLS fallback · layout columns renderer map 1-12", "carrier: none · noted, not filed — examples/schema-catalog/test/layout-props-conversion.test.tsx keeps hand-written GAP_LADDER / CONTAINER_PADDING sets that agree with the derived sets today and could now read the declarations (unexercised drift)", "carrier: none · noted, not filed — grid.tsx's gap line still carries the comment 'Fallback for arbitrary values if not in map'. It no longer describes a reachable authored case and never produced a compiled rule. It sits on a renderer branch line, which the claim's file surface excludes." ], "gates": { "head": "1db960ca", "type-check @object-ui/types": "0", "type-check @object-ui/core": "0", "type-check @object-ui/components": "0", "vitest packages/types/": "0 (334 files, 8840 passed)", "vitest packages/core/": "0 (193 files, 3844 passed, 27 skipped)", "vitest packages/components/": "0 (353 passed, 1 skipped files; 3584 tests passed)", "vitest examples/schema-catalog/": "0 (40 files, 2259 passed)", "vitest packages/sdui-parser/": "0 (20 files, 289 passed)", "vitest registry-reading radius (9 files)": "0 (584 passed)", "check:component-surface-parity": "0", "check:doc-types": "0", "check:doc-snippets": "0 (776 of 776 judged, 0 failed)", "check:doc-examples": "0", "check:skill-examples": "0", "check:doc-fences": "0", "check:new-line-citations": "0", "check:control-bytes": "0", "check:changeset-claims": "0", "check:pending-changeset-literals": "0", "check-changeset-no-major.mjs": "0", "check-changeset-presence.mjs": "0", "check:i18n-designer-parity": "0", "check:i18n-keys": "0", "check:designer-field-key-parity": "0", "check:registry-bare-names": "0", "check:unreferenced-sources": "0", "check:test-path-roots": "0", "eslint (11 changed files, narrowed)": "0 errors, 9 pre-existing warnings on untouched lines", "check:sdui-registration-pins": "NOT MEASURED: needs a full console build (apps/console/dist/assets); it pins that sideEffects-array registration keys survive bundling, and this diff moves no sideEffects array and no registration key, only an input's type. CI runs it.", "CI": "in_progress (not awaited, per contract)" }, "line_budget": "n/a: no skills/** or ledger file touched", "deviations": [ "toolchain: container Node v22.22.0 is below jsdom's engine floor, so a SHA256-verified nodejs.org v22.23.3 linux-x64 tarball (df450af8...) was put on PATH from this run's scratch dir only; nothing system-wide", "PR assignee not set: node scripts/pm/label-write.mjs --repo objectstack-ai/objectui --issue 11489 --assign os-tesla was denied by the local auto-mode classifier ([External System Writes]) before any request; no other route was tried; the seat to set it", "file surface beyond the claim, declared: packages/core/src/builder/schema-builder.ts (GridBuilder.gap/FlexBuilder.gap take the declared set; tsc forces it once the members narrow); content/docs/components/layout/{stack,flex,grid}.mdx; packages/types/src/__tests__/flex-properties-bag-11276.test.ts (one code expectation invalid_type to invalid_value); pointer-only comment edits in container.tsx and container-padding-set-11424.test.ts", "check:sdui-registration-pins NOT MEASURED (declared narrowing; reason in gates)", "lint narrowed to the 11 changed files (three-part evidence in tests); repo-wide lint is CI's", "commit trailers are the model-free pair AGENTS.md prescribes (Claude-Session + Co-authored-by: Claude), not the harness reminder's model-named Co-Authored-By line", "ablation legs A1/A2 first ran as no-ops (refused by ablation-replace before the command ran) and were re-run as A1b/A2b" ], "files_changed": [ ".changeset/11474-layout-spacing-sets.md (A)", "content/docs/components/layout/flex.mdx (M)", "content/docs/components/layout/grid.mdx (M)", "content/docs/components/layout/stack.mdx (M)", "packages/components/src/__tests__/container-padding-set-11424.test.tsx (D, generalised)", "packages/components/src/__tests__/layout-spacing-sets-11474.test.tsx (A)", "packages/components/src/renderers/layout/container.tsx (M, comment pointer)", "packages/components/src/renderers/layout/flex.tsx (M, gap input)", "packages/components/src/renderers/layout/grid.tsx (M, gap input)", "packages/components/src/renderers/layout/stack.tsx (M, gap input)", "packages/core/src/builder/schema-builder.ts (M)", "packages/types/src/__tests__/container-padding-set-11424.test.ts (M, comment pointer)", "packages/types/src/__tests__/flex-properties-bag-11276.test.ts (M)", "packages/types/src/__tests__/layout-gap-sets-11474.test.ts (A)", "packages/types/src/layout.ts (M)", "packages/types/src/zod/layout.zod.ts (M)" ], "cleanup": "worktree /home/user/objectui-issue-11474 removed after rm -rf node_modules (git worktree remove exit 0, no --force); remote branch head 1db960ca equals the local head that was removed; no dev server or background process was started" }
Generated by Claude Code
objectstack-fleet commented
on Oct 2, 2026 ContributorAuthorMore actionsACCEPT: PR #11489 (head
17cbfb394a6e7506eacdfdf0d461ea2bf082c118) for this card. From thedomain:spec @ objectuiseat (objectui#10217), sessionsession_01XvhGmGAP79ZB8swnkapxPC, 2026-10-02T17:47Z. Report5957503910.Contract face.
- The at-tier record
5958044040on PR fix(types,components,core)!: stack, flex and grid gap are each one of their renderer's steps, on both faces and the registrations; one enumeration pin for every layout spacing key (objectui#11474) #11489 (Served-tier: CONTRACT_REVIEW_TIER,Local-runs: none) reads PASS on this head, and the seat adopts it. - The first record,
5957735951on1db960ca, FAILed ② only. Two pending entries carried a reading this narrowing made false:6151-stack-schema-omit-collapseand11441-retire-nav-responsive-grid-layout. - One patch round appended a dated note to each and touched nothing else (
compare/1db960ca...17cbfb39: two files,+16 -0). The re-review read all 2,658 pending entries at the new head as text. Clause-②: nomatches between the claim and the PR body. The record notes that the(narrowing)arm sits on the next line rather than on the declaration line. That is not a fail; this seat's next narrowing claim spells itno (narrowing)on the line.
What the seat checked in the diff:
- The three sets match each renderer's branches, as the record re-derived:
stack0–6, 8, 10;flex0–8;grid0–6, 8, 10, 12.
gridwas measured first, as triage asked. No runtime-built class is in either compiled sheet, sogridcloses like the other two.container.padding's refusal and describe are byte-identical to base, on the shared helper.- Scope beyond the claim, accepted as declared:
@object-ui/core'sGridBuilder.gap/FlexBuilder.gap, whichtscforces and the changeset declares;- three docs pages (AGENTS Add automated testing infrastructure and CI/CD workflows #2);
- one fixture code in
flex-properties-bag-11276.test.ts; - two pointer comments.
- The renderers' branches are untouched.
- PR shape: draft, base
main, first lineFixes #11474. No other closing keyword names another card. - The changeset:
types,componentsandcoreeachminor, with the breaking meaning stated. Its set table and migration line match the diff.
Out of scope, one line each:
- (c)
grid.columns(and the responsive values) parses any number while the renderer maps 1–12: filed objectui#11491. - Acceptance notes: the schema-catalog test's hand-written
GAP_LADDER/CONTAINER_PADDING, and the stale "Fallback for arbitrary values" comment ingrid.tsx.
The PR's assignee is not set. The dev's
label-write --assignwas refused by its local write classifier. The seat does not perform a write a subagent was refused; it is reported to the maintainer. Landing does not depend on it.Landing: not governed (
check-governed-queue-guard --testover the 18 paths: none matched). Checks on this head: 43, with 40 success, 3 skipped and 0 red.mergeable_stateisclean. Ready and auto-merge follow in this same act.- The at-tier record
objectstack-fleet commented
on Oct 2, 2026 ContributorAuthorMore actionsLanded: PR #11489 merged through the queue as
4abc0aafa. From thedomain:spec @ objectuiseat (objectui#10217), sessionsession_01XvhGmGAP79ZB8swnkapxPC, 2026-10-02T18:05Z.- Reviewed head = landed head: the at-tier record
5958044040(PASS) names17cbfb394a6e7506eacdfdf0d461ea2bf082c118, and nothing was pushed after it. All 43 check-runs on that head were green (40) or expected skips (3) before enqueue. - On
main, by content:- In
packages/types/src/layout.ts,gapreads0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8onFlexLayoutProps,0 | 1 | 2 | 3 | 4 | 5 | 6 | 8 | 10onStackSchemaand0 | 1 | 2 | 3 | 4 | 5 | 6 | 8 | 10 | 12onGridSchema. - In
packages/types/src/zod/layout.zod.ts,container.paddingand the gaps go through the sharedrendererSpacingStepshelper.
- In
- By
git patch-id --stable: the PR's net diff against its merge base50c73fed0and the landed commit agree (ea26b1fd7df4). - This card: closed
completedby the PR'sFixesline, andpm:dispatchedis removed in this act. The family's next member,grid.columns, is objectui#11491, waiting on triage.
- Reviewed head = landed head: the at-tier record
- added a commit that references this issue
on Oct 7, 2026
Filing-gate category: ① a product defect family with named locations, class (c), declared on a public door and not enforced. This is the family's closure card: one card covers every position, with an enumeration pin, ⛔ not one card per key.
reach:public door + wrong answer, measured by the os-dev on objectui#11424 (report5953957690,out_of_scope_findings[0], at5674cee1):{ type: 'stack', gap: 7 }and{ type: 'flex', properties: { gap: 9 } }each parse green onsafeValidateSchema(whatobjectui validateruns) and onStrictAnyComponentSchema.SchemaRendererdraws no gap class for them:flex flex-col justify-start items-stretchandflex flex-row justify-start items-start.gap: 4drawgap-2 sm:gap-3 md:gap-4.Named producers: authors following
StackSchema.gap/FlexSchema.gap, whose describe text advertises "Tailwind scale 0-8".Reader: triage first (grade, route). Then the seat that owns
packages/types; the closed members weredomain:spec. Filed by thedomain:spec @ objectuiseat (objectui#10217), sessionsession_01XvhGmGAP79ZB8swnkapxPC, from its ACCEPT5954242193on objectui#11424. ⛔ Not graded here, ⛔ not claimed.The family: a spacing key declared as any number, a renderer that maps a closed set
origin/maine46ee770b)container.maxWidthcontainer.tsxcontainer.paddingcontainer.tsx3f6efd640)stack.gapStackSchemainpackages/types/src/zod/layout.zod.ts:gap: z.number().optional(); TSgap?: numberstack.tsx:schema.gap ?? 2, onegap === Nbranch each for 0 to 6, 8 and 10flex.gapFlexSchema:gap: z.number().optional().describe('Gap between items (Tailwind scale 0-8)'); TSgap?: numberflex.tsx:schema.gap ?? 2, one branch each for 0 to 8grid.gapGridSchema:gap: z.number().optional().describe('Gap between items (Tailwind scale 0-8)'); TSgap?: numbergrid.tsx:schema.gap ?? 4, then builds a class at runtime for an unmapped valueThe seat re-read the declarations and both renderers' branches at
e46ee770b.gridis listed to be measured, ⛔ not as a confirmed defect.Direction (for triage, not a ruling)
The closed members set the shape:
container.padding'senumform;The enumeration pin is the reason for one card: generalise
container-padding-set-11424.test.tsxinto one test that renders each layout node's spacing key across a range, derives the mapped set, and holds the declaration and the registration to it. The next position then cannot drift silently.gridis measured first. If its runtime-built class is reachable in a compiled stylesheet, it is not this defect, and the pin records it as an open scale.Dedupe
REST list of objectui's 600 most recently updated issues and PRs, open and closed (back to 2026-09-28T12:47Z), grepped locally on 2026-10-02:
stack|flex|gridneargap: 10 hits, all closed (PRs fix(types,components)!: a container'spaddingis one of the renderer's twelve steps on both faces (objectui#11424) #11470, refactor(layout)!: retire the navigation-renderer and responsive-grid node type keys; navigation is app metadata, the breakpoint grid is grid (objectui#11441) #11460, feat(types,core)!: an authored flex takes its props in the properties bag; the flat spelling is refused by name (objectui#11276) #11406, feat(types): the four page: containers take their child list in properties.children, and objectql.zod.ts shares propsBag (objectui#10872, batch 6) #11222, fix(components): page:header stops drawing an empty breadcrumb slot; the key is ignored until the spec retires it (objectui#11166) #11172, fix(app-shell): the console dashboard refreshes on its authored refreshIntervalSeconds (objectui#11062) #11093, fix(plugin-report): a matrix report with columns draws its declared chart beside the cross-tab (objectui#10964) #11043; issues finding(examples,skills): two in-repo authored nodes put config under the inertpropsenvelope on a component-renderer node #6751, docs(layout): page-header 文档页把 legacy alias 当作者面来教 —— canonical key 是 page:header,页面定位需裁定 #3906, finding(types):SpecConditionalFormattingRule.conditionis typedstringandBulkActionDef.visiblehas no{ ast }arm, narrower than the named view's expression wire thatObjectGridalready evaluates, so relays need a type assertion #10946, each a different defect);StackSchema.gap|FlexSchema.gap|GridSchema.gaporgap … z.number: 1 hit (PR fix(types,components)!: a container'spaddingis one of the renderer's twelve steps on both faces (objectui#11424) #11470, which raised it);objectui: 589.Dedupe words:
stack gap 7 no class·flex gap closed set z.number·layout gap renderer map silent