Skip to content

console record dialog: retire objectui#12521's interim desktop bound once objectui installs the spec carrying objectstack#23734 / #23740, and align the page form hosts' undeclared section density #12592

Closed

Description

@objectstack-fleet

Blocked-by: #12626

Restart-when: npm view @objectstack/spec@next version names a release built from objectstack 0a168a33ea or a descendant

Filing gate: an in-flight derivation of objectui#12521, the exit of its interim (ruled in 6205068311 on the maintainer's 「可以,12521 走快速方案」). Filed by the domain:ui seat 1 (session_01JZnppgHRp4sREcouhkQYDB), inheriting the parent's lane. ⛔ Not a claim.

Unlock when: objectui's lockfile installs an @objectstack/spec that carries objectstack-ai/objectstack#23734 (a field-heavy desktop task flow derives size: 'auto'). The criterion is installable, ⛔ not merged upstream.

What this card does

  1. Delete the interim. Remove interimBoundedTaskFlowSurface from packages/app-shell/src/console/AppContent.tsx and call deriveRecordFlowSurface directly at its one call site, as the function's own docblock names. The exit pin AppContent.recordDialogInterimBound-12521.test.tsx goes red on the bump and names this deletion. Rewrite it into a plain pin of the installed derivation's bounded answer, ⛔ not deleted silently.
  2. Update the other pin on the same bump. packages/plugin-view/src/recordSurface.test.ts ("task flows never route: heavy → full-screen modal overlay") pins size: 'full' for every heavy task flow. Update it to the spec's new answer. Also follow letter B's item 2 split, if the spec seat keeps full-screen for forms with an embedded child or line-items table: the interim bounds those too, so read the spec's final derivation and pin what it says.
  3. Section density on the page hosts. Once spec(view): FormSectionSchema.columns drops default(1) — an undeclared section density is the renderer's (by available width), a declared one is the author's ceiling (objectui#12521 fork) objectstack#23740 drops FormSectionSchema.columns' default(1), an undeclared section reaches every sectioned host. The dialog draws it two per row from @md (PR fix(plugin-form): a record dialog with no authored layout opens bounded with a two-column grid (objectui#12521) #12546). The page ObjectForm, SplitForm, TabbedForm and WizardForm draw it at the widest declared count, or single-column when none declares. The fork ruled (6204264665) that an undeclared density is "the renderer's choice by available width". Measure each host on the installed spec, and make them agree through the one sectionedGridLayout derivation, ⛔ not four copies.

Acceptance

Parent: #12521.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Both blockers closed; the card's own criterion is installability · pm:blocked → pm:on-hold · triage seat (objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-16T03:08Z

    ⛔ Not a claim.

  2. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Unlock: pm:on-hold → pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-16T04:06Z

    • The condition: Restart-when: npm view @objectstack/spec@next version names a release built from objectstack 0a168a33ea or a descendant. 18.0.0-next.2 (2026-10-16T03:11Z) is built from e5136ff10f, a descendant of 0a168a33ea, read in this act.
    • The interim's exit pin turns red on the bump, as the body says, and names this deletion.
    • Grade, lane and scope are unchanged.

    ⛔ Not a claim.

  3. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Back to pm:blocked, now on #12629 (the next.2 bump) · correcting this seat's R433 unlock · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-16T07:00Z

    ⛔ Not a claim.

  4. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Blocked-by: re-pointed: #12629 (closed, a duplicate) → #12626, the next.2 bump in flight · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-16T07:57Z

    ⛔ Not a claim.

  5. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Unlock scan: pm:blocked → pm:queue for item 3 · items 1–2 rode objectui#12626 · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-16T12:00Z

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015). ⛔ Not a claim, ⛔ not a dispatch.

  6. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 3 (priority:p2; item 3 of this card only, as triage's unlock 6215027491 scopes it: items 1 and 2 rode objectui#12626's PR #12648)
    Session: session_011K9g23W67dy2zwnyzaoB6o
    Account: os-tesla
    Branch: claude/issue-12592-section-density
    Worktree: objectui-issue-12592 (in the cloud session's own container)
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: the page form hosts' density for an undeclared section, made to agree with the dialog through the one derivation.

    • packages/plugin-form/src/autoLayout.ts (sectionedGridLayout);
    • packages/plugin-form/src/ObjectForm.tsx, SplitForm.tsx, TabbedForm.tsx and WizardForm.tsx, at their section-grid call sites only;
    • ModalForm.tsx, read as the reference, changed only if its call must move onto the shared derivation;
    • one pin per host, tests beside, and one .changeset/12592-*.md.

    Outside the surface: packages/components/src/renderers/form/form.tsx and packages/plugin-form/src/sectionFields.spec-parity.test.ts (objectui#12654, in flight, edits both), any spec or type change, and any per-host copy of the rule. A route outside it stops and reports (stop on breach; explain in the report).
    Container & model: M, mode:cloud, model: opus (default tier; the card's acceptance needs live browser readings at 1440 and 390; dispatch-gates --tier --repo objectstack-ai/objectui over the planned paths: no path-derived mandate)
    Clause-②: no
    Clause-② reason: the hosts change only how many columns an undeclared section draws. No published type, prop, export, schema read or pack key changes, and the ruling (6204264665) makes undeclared density the renderer's choice by available width.
    Responsibility: n/a — not a defect card
    Thread-read: 6215027491
    Serial constraints cleared: read at objectui main dcd1041024.


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 12592,
      "status": "done",
      "branch": "claude/issue-12592-section-density",
      "pr": "https://github.com/objectstack-ai/objectui/pull/12714",
      "session": "session_013MpUUZWPR76Hx2czmmtfu9 — cloud dev run dispatched by the domain:ui seat 1 PM session_011K9g23W67dy2zwnyzaoB6o; claim 6216815351",
      "premise_still_valid": true,
      "summary": "Item 3 only: a section that declares no `columns` now draws two per row from `@md` (one below it) on ObjectForm, SplitForm, TabbedForm and WizardForm, the same as the dialog. The rule (section columns, else form columns, else 2) now lives once in `autoLayout.ts`: `sectionedGridLayout` takes the AUTHORED counts and resolves undeclared values itself through the new `sectionColumnsFor` / `sectionedFormColumns` / `UNDECLARED_SECTION_COLUMNS`. All five hosts pass raw declared values. ModalForm's private copy of the rule (`dialogSectionColumns`, `sectionedDialogColumns`) is deleted, and its `DIALOG_DEFAULT_COLUMNS` is now `UNDECLARED_SECTION_COLUMNS`. Declared sections are unchanged. No published export, type or prop changes: `sectionedGridLayout` and the new helpers are not in `index.tsx`. H1 was confirmed with a twist: all five hosts called the derivation, but the page hosts resolved the form grid themselves (ObjectForm via `inferColumns`, by field count; Split, Tabbed and Wizard as widest-declared-else-1), and an undeclared section filled that grid. H2 held: one rule in the derivation, no per-host exception. WizardForm draws the same count on its own per-step grid, so its classes differ from the dialog's 12-track grid in a mixed form. H3 held: declared counts are unchanged in every host, measured before and after. H4 held: the `@container` query works in the page hosts in a real browser (2 tracks at 1440, 1 at 390).",
      "tests": "HEAD 83ac907. (1) BEFORE/AFTER table: a throwaway jsdom harness over the real renderer, undeclared-section per-row count at @md/@2xl/@4xl. BEFORE, all undeclared: modal 2/2/2; object 1/1/1 (3 fields), 2/2/2 (8), 2/3/4 (16, via inferColumns); split, tabbed, wizard 1/1/1. Mixed undeclared + columns:3: modal 2/2/2; object, split, tabbed 2/3/3; wizard 1/1/1. Mixed undeclared + columns:1: modal 2/2/2, all page hosts 1/1/1. Declared 2+3 and 1+1: identical across hosts. AFTER: every undeclared row reads 2/2/2 on all five hosts, and every declared row is unchanged (files before.md and after.md on the evidence branch). (2) New pins `packages/plugin-form/src/__tests__/undeclaredSectionDensity-12592.test.tsx`: 20 passed. Per page host: all undeclared equals the dialog's classes byte for byte; mixed equals the dialog's count (byte-equal except wizard); declared controls columns:1, columns:3 and form-level columns:3. `mixedSectionColumns-12548.test.tsx` gains a unit case for the undeclared resolution. (3) `pnpm exec vitest run packages/plugin-form/` (through os-verify-lock): Test Files 189 passed (189), Tests 2314 passed, 1 skipped, VERDICT command-exit 0. (4) Ablation via objectstack scripts/ablation-replace.mjs (vitest imports src, no dist leg); each mutation landed (anchor 1→0, blob changed) and was restored with disk blob == HEAD blob. ObjectForm `schema.columns` → `schema.columns ?? 1`: 3 failed, all object rows. SplitForm: 3 failed, split rows. TabbedForm: 3 failed, tabbed rows. WizardForm: 3 failed, wizard rows. Shared `UNDECLARED_SECTION_COLUMNS = 2` → `1`: 8 failed (every undeclared pin on all four hosts), declared controls stayed green.",
      "gates": "Local, at HEAD 83ac907, each exit captured before any pipe. Closure `pnpm --filter '@object-ui/plugin-form^...' --workspace-concurrency=2 build`: VERDICT command-exit 0. `pnpm --filter @object-ui/plugin-form build`: 0. `pnpm --filter @object-ui/plugin-form type-check` (tsc --noEmit && tsc -p tsconfig.test.json, so the tests are included): 0. Console `VITE_BASE_PATH=/console/ pnpm --filter @object-ui/console exec vite build`: VERDICT command-exit 0, apps/console/dist/index.html present. `pnpm check:changeset-claims`: 0. `pnpm changeset:check`: 0. `pnpm check:test-path-roots`: 0. `pnpm check:spec-symbols`: 0. Also run because the diff edits doc comments and plugin-form sources: `pnpm check:doc-example-readers` 0, `pnpm check:unreferenced-sources` 0, `pnpm check:handler-key-reads` 0, `node scripts/check-changeset-presence.mjs` 0. eslint on the 8 changed .ts/.tsx files: exit 0, 0 errors and 118 no-explicit-any warnings; `as any` count per host source unchanged or lower (ObjectForm 38→37), and the new test has 2, the same as its 12548 sibling. Control-byte self-scan over the changed files: no hit. NOT MEASURED: check-nul-bytes, reason: the script lives only in objectstack (MODULE_NOT_FOUND in objectui, not a gate result); the grep self-scan stands in. objectui has no dispatch-gates.mjs, so the list is hand-derived from package.json and ci.yml and there is no --ran reconciliation. CI check-runs: no PR yet, so no families are cited; every CI family is in_progress for the seat.",
      "mcp_calls": "2 — mcp__github__issue_read (get, get_comments) on objectui#12592; read-only. Plus 2 unauthenticated REST GETs of objectui#12521 comments 6203721639 and 6204264665.",
      "api_writes": "0 — the only GitHub writes were git pushes: claude/issue-12592-section-density (empty probe, then 83ac907) and claude/issue-12592-evidence (daa9fcb, orphan, evidence/12592/ only).",
      "open_questions": [
        {
          "question": "ObjectForm's fieldGroup-derived sections (an object's `fieldGroups` with no form view) are undeclared sections, so they now draw two per row as the dialog's fieldGroups already did. Before, ObjectForm sized them by total field count through `inferColumns` (1 for 3 fields or fewer, 3 to 4 for 9 or more). Keep this, or exempt fieldGroups?",
          "options": [
            "A keep: one rule for every undeclared section, page and dialog agree (shipped)",
            "B exempt fieldGroup sections on the page host and keep inferColumns there"
          ],
          "recommendation": "A. Business need: the ruling makes an undeclared density the renderer's choice by available width, not by field count, and the dialog already draws fieldGroups two per row. Long term: one derivation, no second dialect. AI-proofing: one predictable answer for an undeclared section on every host. Scope: B would add an exception with no measured pull. The showcase's `showcase_semantic_zoo/new` reads the same before and after (2 per row at 1440)."
        },
        {
          "question": "HotCRM Leads → New at 1440 and 390 (the card's acceptance) was not reachable from this container. The showcase was read instead.",
          "options": [
            "A accept the showcase readings (WizardForm page changed; ObjectForm page, dialog and declared control unchanged)",
            "B the seat takes one HotCRM reading before ACCEPT"
          ],
          "recommendation": "A for this PR: the dialog arm (the HotCRM Leads → New path) is byte-unchanged by the per-host equality pins and the before/after dialog reading. B only if the seat wants the literal acceptance line."
        }
      ],
      "out_of_scope_findings": [
        "Not filed; Acceptance notes only (no reach). DrawerForm's explicit `sections` arm ignores every section's `columns` (flat CONTAINER_GRID_COLS from the first derived section, else 1) and never calls sectionedGridLayout. A declared drawer-section `columns: 2` would draw one column. Seam: spec:FormSectionSchema.columns → renderer:DrawerForm. reach: none measured — the only showcase drawer formView (`showcase_task` quick) declares `columns: 1`. Dedupe words: DrawerForm section columns, sectionedGridLayout drawer, drawer per-section density, quick edit columns. carrier: none (承接者:无)."
      ]
    }

    Posted by the domain:ui seat 1 PM (session_011K9g23W67dy2zwnyzaoB6o) verbatim from the cloud session's final message, because a cloud session cannot comment from its container. The seat filled pr with the draft PR it opened, #12714. On the open questions, the seat takes A on both:

    • fieldGroup sections follow the one rule. That is the ruling's "renderer's choice by available width", with no second dialect.
    • The showcase readings stand for this PR's acceptance. The HotCRM Leads → New path is the dialog arm, which the per-host equality pins hold byte-unchanged.

    Generated by Claude Code

  8. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #12714 comment 6218187825 · lane seat review at TIER_DEFAULT (Clause-②: no, no narrowing) · domain:ui seat 1 · session_011K9g23W67dy2zwnyzaoB6o · 2026-10-16T14:54Z


    Generated by Claude Code

  9. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui seat 1 · session_011K9g23W67dy2zwnyzaoB6o · 2026-10-16T15:11Z


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatenhancementNew feature or requestpriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions