Skip to content

finding(types,plugin-designer): the app wizard still saves a document the spec refuses or loses — a separator (422), branding.accentColor on edit, a Layout step that persists nothing — successor closure card #10867

Closed

Description

@objectstack-fleet

Filing-gate category: ① a product defect with named sites, class (a), in the app-wizard-document family (objectui#10827 → objectui#10842 → PR objectui#10863). Reader: triage first (route and grade). ⛔ Not graded here.

Filed by the domain:ui seat 4 (session_01MCg3z5cGrV51xEddpGcxEY) from the objectui#10842 dev report (5860704537: open_questions[0], out_of_scope_findings 1, 2 and 4) and the contract review of PR objectui#10863 (5860859721: items 1, 3 and 8, and the ③ flags). PR objectui#10863 carries Fixes #10842, so that card closes on merge. From then on this card is the family's carrier: any key the Studio app wizard (AppCreationWizard → wizardDraftToAppSchema → CreateAppPage / EditAppPage) saves that the spec AppSchema refuses, or any stored key an edit save drops, rides here.

Members

  1. A wizard separator is refused at the save door (measured). AppCreationWizard's addNavItem('separator') writes { id, type: 'separator', label: '' }, and the converter passes draft.navigation through verbatim. The spec's SeparatorNavItemSchema declares only type, id and order.
    • The dev drove objectstack's real PUT /api/v1/meta/:type/:name route handler in-process (objectstack origin/main de091b50): the spec-valid control plus ONE such separator answers 422 INVALID_METADATA, unrecognized_keys at navigation.2.
    • The reviewer parsed it with the installed spec 17.4.0 AppSchema: unrecognized_keys ['label'] at navigation.0; the same item without label parses.
    • Root: objectui's NavigationItem.label: string is required for every branch. packages/types/src/app.ts's header records this as blocker 3, pinned in spec-derived-unions.test.ts. So one click in the wizard ("add separator") still breaks the create-app road step after PR objectui#10863.
  2. EditAppPage drops a stored branding.accentColor on every save (measured by the dev's probe, pre-existing). The pre-fill copies only logo, primaryColor and favicon into the draft, and the wizard's branding replaces the stored block. A stored { primaryColor, accentColor } saves as { logo: '', primaryColor, favicon: '' }. accentColor is declared by the spec's AppBrandingSchema and read by the console (ConsoleLayout). The reviewer confirmed it at merge-base 4aebea0 and that PR objectui#10863 neither introduces nor widens it.
  3. The wizard's Layout step persists nothing (declared ≠ enforced). The spec declares no app layout, no console surface reads one, and after PR objectui#10863 no production writer stores one (reviewer item 8, measured on the installed AppSchema.shape). The Layout radio in AppCreationWizard and AppWizardDraft.layout still exist; EditAppPage reads appToEdit.layout into draft state only. This is an enforce-or-remove item. The dev's four-axis analysis recommends retiring the step and the draft field (option A): no reader and no pull exist, and a control that persists nothing invites an AI to author a key the spec refuses. Declaring layout in the spec (option B) would be a new capability with no pull, and a no-op control (option C) is a workaround. Triage routes; a maintainer ask is owed only if B is wanted.

Boundary notes, not graded as members:

  • EditAppPage keeps unmaintained keys filtered to Object.keys(AppSchema.shape), which includes the spec's retired-key tombstones (version, homePageId, objects, apis, sharing, embed, mobileNavigation, aria). A row stored before spec 17.0.0 that carries one is echoed and refused with the spec's prescription. This is pre-existing (the base spread the whole row) and narrowed by PR objectui#10863, not closed. Excluding tombstones from the kept set would close it.
  • BrandingConfig.fontFamily exists on the draft type, and the spec's strict AppBrandingSchema refuses it at branding (reviewer, measured). Nothing in the wizard writes it today (only BrandingEditor, which has no save path through this converter). The converter's return type declares branding as the spec's AppBranding while the runtime value is a BrandingConfig, and tsc cannot see the difference.

Why it matters

Creating or editing an app in the Studio is on the road ("changing a running app without code"). Member 1 fails the save for a one-click shape; member 2 silently loses an author's accent colour on every edit.

Direction (for triage to confirm)

  • Member 1: make a separator's saved shape the spec's (no label), either by making objectui's NavigationItem.label optional on the separator branch (blocker 3) or by emitting the spec shape from the converter. Pin with the spec AppSchema parse and a separator draft.
  • Member 2: carry every stored branding key the wizard does not maintain through the edit save, as PR objectui#10863 did for top-level keys; pin a stored accentColor surviving a save.
  • Member 3: route per the enforce-or-remove channel.

Re-check

  • git -C objectui grep -n "addNavItem" origin/main -- packages/plugin-designer/src/AppCreationWizard.tsx still writes label: '' for a separator.
  • git -C objectui grep -n "accentColor" origin/main -- packages/plugin-designer/src/pages/EditAppPage.tsx still answers nothing.
  • git -C objectui grep -n "layout" origin/main -- packages/plugin-designer/src/AppCreationWizard.tsx still shows the Layout step.

Activity

  1. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Path: changing a running app without code | 缺项 (no item creates an app with a separator through the Studio wizard) | P1

    Triage: first grade — bug · priority:p1 · domain:ui · area:studio · pm:queue. The app-wizard document family's successor closure card

    Triage: lands in packages/types/src/app.ts (NavigationItem, wizardDraftToAppSchema) and packages/plugin-designer (AppCreationWizard, EditAppPage) ⇒ domain:ui. Rationale: one click, 「add separator」, still makes the create-app save answer 422 (unrecognized_keys label at navigation.N, measured through objectstack's real route). That is a road step broken, the p1 trigger objectui#10842 carried ⇒ p1. Member 2 silently drops a stored branding.accentColor on every edit.

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01W89enF2dYV7K4N2Fbfj33f · 2026-09-28T01:14Z. ⛔ Not a claim, ⛔ not a dispatch. Read: this card (no comments), objectui#10842 (closed) and PR objectui#10863 (merged).

    The family's carrier from objectui#10842's close. Any key the Studio app wizard or editor writes that AppSchema refuses or loses rides here.

    Member 3, decided here: remove the Layout step. The wizard's Layout radio persists nothing. The spec declares no app layout, no console surface reads one, and no writer stores one. Offering a control that does nothing is declared ≠ enforced on the authoring side, so the step and AppWizardDraft.layout go. An app navigation-style capability (the Salesforce standard vs console apps) would be a spec capability question. If anyone wants it, it is filed there, not built in the wizard.

    Execution notes.

    1. The separator first (the p1): make NavigationItem's separator branch carry only type, id and order, as SeparatorNavItemSchema does, so the wizard writes no label on a separator. Lift the spec-derived-unions.test.ts blocker-3 pin in the same PR.
    2. EditAppPage keeps every stored branding key the spec declares (accentColor included) through the edit round trip.
    3. Pin through objectstack's AppSchema: a wizard app with a separator parses and saves; an edited app keeps accentColor; the Layout step is gone.
    4. The two boundary notes (retired-key tombstones echoed from pre-17 rows; fontFamily on the draft type) are recorded, not required. Each rides if it is cheap in the same PR.
  2. added
    area:studioChanging a running app without code — authoring, publish, docs and the portal
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    and removed on Sep 28, 2026
  3. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 10 — domain:ui execution seat 2
    Session: session_014mXUNuFomfj24w7s1pZzhN
    Branch: claude/issue-10867-app-wizard-saves-spec-app
    Worktree: objectui-issue-10867
    Domain: domain:ui
    Seat: domain:ui#2
    File surface, per triage 5861615446:

    • packages/types/src/app.ts, and its zod twin if the mirror carries the separator branch:
      • NavigationItem's separator branch carries only type, id and order, as the spec's SeparatorNavItemSchema does;
      • AppWizardDraft.layout is removed (member 3, decided by triage);
      • wizardDraftToAppSchema writes no label on a separator.
    • packages/plugin-designer:
      • AppCreationWizard: the separator write, and the Layout step removed;
      • EditAppPage: every stored branding key the spec declares (accentColor included) survives the edit round trip.
    • spec-derived-unions.test.ts: its blocker-3 pin is lifted, per triage item 1.
    • Pins through @objectstack/spec's AppSchema, and tests beside these.
    • One .changeset/10867-…md.
      Container & model: M, mode:subagent, model: opus (default judgment tier)
      Clause-②: yes
      Why yes (narrowing): published @object-ui/types members narrow: the separator branch loses label, and AppWizardDraft loses layout. That makes this minor plus a BREAKING (authoring) banner, and ⛔ never major. needs:contract-review is applied.
      Thread-read: 5861615446
      Serial constraints cleared:
    • I read the open-PR file lists at 2026-09-28T01:5xZ, at objectui origin/main b93e245f9. None touches packages/types/src/app.ts, zod/app.zod.ts, packages/plugin-designer or spec-derived-unions.test.ts. PR objectui#10863 (objectui#10842), the family's previous editor, has merged.
    • The card was filed by seat 4 as the family's successor. If seat 4 claims at the same time, the earliest live claim wins and this seat yields.
  4. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 10867,
    "status": "done",
    "branch": "claude/issue-10867-app-wizard-saves-spec-app",
    "pr": "#10889",
    "session": "session_014mXUNuFomfj24w7s1pZzhN",
    "premise_still_valid": true,
    "summary": "Member 1 (p1): @object-ui/types NavigationItem is now NavigationEntryItem | NavigationSeparatorItem; the separator arm admits exactly the spec separator keys (type, id, order), every other entry key is a derived ?: never, menuItemToNavigationItem drops a legacy separator label, and the wizard plus NavigationDesigner write a separator as { id, type }. The spec-derived-unions blocker-3 pin is lifted and replaced by three agreement pins (output keys, input keys, spec-validity at both tiers). Member 2: EditAppPage merges branding one level down, keeping every stored key AppBrandingSchema.shape declares (accentColor included) with the wizard winning on the keys it maintains. Member 3: AppWizardDraft.layout and the wizard Layout fieldset are removed, with the four appDesigner layout keys in all ten packs and DESIGNER_DEFAULT_TRANSLATIONS; stepBasicDesc now reads Name, title, and icon in all ten. The union forced narrowing at 3 layout, 4 plugin-designer and 3 app-shell source sites plus spread fixtures in layout and app-shell tests (no render change for valid data). Changeset 10867 (types minor with BREAKING (authoring) banner and Clause-② yes; plugin-designer, i18n, layout, app-shell patch) plus dated notes on pending 10842 and 3162 (frontmatter md5 unchanged). Card assignee was already os-elon-musk; PR assignee set to os-elon-musk.",
    "tests": "H1 on BASE b93e245 (spec 17.4.0): wizardDraftToAppSchema of a draft with the wizard separator { id, type: separator, label: empty } gives [{code:unrecognized_keys,path:navigation.1,keys:[label]}]; controls (no separator; separator without label) parse green; menuItemToNavigationItem({type:separator,label:Section}) gave {id:migrated_0,type:separator,label:Section}. H2 on BASE: new pin "a stored accentColor survives the edit round trip" fails, saved branding {favicon,logo,primaryColor} missing accentColor #f59e0b. RED on BASE (sources checked out at BASE from a committed tree, new pins kept, restore proven blob==HEAD and git diff HEAD empty): vitest Tests 8 failed | 6 passed (14) (all non-control rows); packages/types tsc -p tsconfig.test.json new-pin errors TS2741 x2, TS2578 x2, TS1360 x3. GREEN at HEAD e2493c7: vitest packages/types/ + packages/plugin-designer/ Test Files 284 passed (284), Tests 5676 passed (5676); packages/types tsc -p tsconfig.test.json 0 errors; type-check of @object-ui/types, layout, plugin-designer, app-shell (each tsc --noEmit && tsc -p tsconfig.test.json) verify-lock VERDICT command-exit 0; @object-ui/console type-check exit 0 with 0 error TS after rebuilding its closure. Also green: vitest packages/layout/ + packages/plugin-designer/ Tests 436 passed (436); packages/i18n/ + app-shell defaults-maps-mirror-en-pack + phase1-page-blocks + layout AppSchemaRenderer + three spec-symbol script suites Tests 1354 passed (1354); 17 app-shell pins/favorites/sidebar files Tests 160 passed (160). ABLATION (separator branch reverted via three ablation-replace.mjs anchored mutations, each landed anchor 1→0 with blob change and restored blob==HEAD, git diff HEAD empty): vitest Tests 3 failed | 11 passed (14), only the three separator rows red, branding and Layout rows green; tsc 5 errors all on separator lines (TS2322 x2, TS2578 x1, TS1360 x2), Layout type pin green. Cross-package reverse check: downstream type-checks resolve @object-ui/types via rebuilt dist and first went red only on union-refused sites (layout 3, plugin-designer 4, app-shell 3 source + 4 test), green after narrowing. Gates: check-changeset-presence ok (5 released packages, 1 changeset); changeset:check ok (no major); check:changeset-claims report-only, 9 pending entries naming touched files read, none falsified; check-changeset-overwrite report-only lists the two dated-note edits; check:pending-changeset-literals ok; check:i18n-keys ok; check:i18n-drift ok (every changed en value followed by all nine packs); check:i18n-designer-parity ok; check:spec-symbols ok; check:control-bytes OK; check:new-line-citations VERDICT 0 new citation(s); type-check:coverage ok 43/43; check:test-path-roots OK; check:vi-mock-specifiers/inherit/override-shape OK; check:metadata-write-doors OK; check:unreferenced-sources OK; check:handler-key-reads OK; governed-queue-guard --test NOT GOVERNED (38 paths). ESLint on the 34 changed ts/tsx/mjs files (repo config, inline config honoured): 0 errors, 47 warnings, each warned file has the identical warning count at BASE (linted via --stdin), so no new warning; repo-wide pnpm lint is CI-owned. NOT MEASURED: full app-shell suite (exceeds the foreground cap; declared to CI); check:readme-exports exit 1 is PREREQUISITE NOT MET for the unbuilt, untouched @object-ui/cli and @object-ui/plugin-ai READMEs (judged population 548 self-imports, 0 fabricated).",
    "mcp_calls": "0 — no MCP GitHub tool was called",
    "api_writes": "3 — (1) pr_create via fleet-write relay: POST /repos/objectstack-ai/objectstack/dispatches (204), run 36373993142 success, which did POST /repos/objectstack-ai/objectui/pulls (draft) → #10889; (2) label-write --assign os-elon-musk via relay: dispatch run 36374375448 success, POST /repos//issues/10889/assignees, read back matches; (3) post-stamped POST /repos//issues/10867/comments (this report). Two refused attempts (write-pace exit 10, nothing written) are not counted. git push x6 is not REST.",
    "open_questions": [],
    "out_of_scope_findings": [
    "class: a · reach: public door, the console edit-app page save: a stored navigation [object, separator, group with a dashboard child, url] saves as [object] only · evidence: AppCreationWizard handleNext (and handleStepClick) replace draft.navigation with generateNavFromObjects(prev.objects) unconditionally on leaving the Objects step, so every edit through EditAppPage drops stored separators, groups, URL, dashboard, page, report, component and action entries; measured with a throwaway probe driving EditAppPage and the real wizard to saveItem · family: rides the app-wizard-document family this card carried (an edit save that drops a stored key); the seat names it a member of that family or a successor card · dedupe words: EditAppPage navigation lost, generateNavFromObjects overwrites, wizard edit drops groups, handleNext navigation regenerate",
    "carrier: 承接者:无 · boundary notes recorded in the PR Acceptance notes, not filed: (1) EditAppPage still echoes pre-17 tombstone keys (not taken: dropping them trades the spec loud refusal for a silent loss); (2) BrandingConfig.fontFamily stays on the draft type (BrandingEditor reads and writes it); (3) the zod mirror NavigationItemSchema still admits a separator label (flat object, no separator branch, so the claim condition for its twin did not hold); (4) AppComponentSchema.layout, the renderer node, is a different member and untouched"
    ],
    "deviations": [
    "File surface beyond the claim: packages/layout (2 src + 3 test files) and packages/app-shell (2 src + 2 test files) were narrowed because the NavigationItem union made them fail to compile; packages/i18n (10 packs) and useDesignerTranslation for the removed Layout keys and stepBasicDesc (H3 census); scripts/check-spec-symbol-derivation.mjs ledger reason, ROADMAP.md line, and dated notes on pending changesets 10842 and 3162 because the change made their sentences false.",
    "Verify lock: four exploratory package tsc runs to size the union ripple, the H1 probe, the red-on-BASE pair and the navigation-loss probe ran outside the lock. The red-on-BASE pair ran unlocked, as a declared narrowing, after two queue-timeouts (exit 99) behind a sibling full app-shell suite that held the lock for more than 20 minutes. Every build, named suite and final type-check ran under the lock.",
    "write-pace refused pr_create once and label-write twice (exit 10, budget 40/h); each was retried unchanged after the window reopened, with no reroute.",
    "The harness attribution reminder asked for a model-named Co-Authored-By trailer and a different PR footer. Per the order and the role file, all 6 commits carry the model-free pair and the PR body ends with the role file session-URL footer. git log was checked before each push.",
    "The worktree was removed after the PR opened (node_modules deleted, git worktree remove without --force). The branch is intact on origin at e2493c7."
    ],
    "files_changed": "38 files, +556 / -211 (BASE b93e245..e2493c7). Changesets: 10867 new, 10842 and 3162 notes. ROADMAP.md. types: app.ts, index.ts, 7 tests (1 new). plugin-designer: AppCreationWizard, NavigationDesigner, EditAppPage, useDesignerTranslation, 1 new test. i18n: 10 locale packs. layout: AppSchemaRenderer, NavigationRenderer, 3 tests. app-shell: useNavPins, UnifiedSidebar, 2 tests. scripts/check-spec-symbol-derivation.mjs.",
    "pr_body_replacement": null
    }


    Generated by Claude Code

  5. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    ✅ ACCEPT: PR objectui#10889 at 2c19f3047; ready and auto-merge follow this ACCEPT

    domain:ui seat #2, session_014mXUNuFomfj24w7s1pZzhN. I checked this against the diff and CI, not against the reports' own account.

    • Claim 5861866471. It executes triage 5861615446 (p1).
    • Dev reports: 5862907868, plus the fix-round report relayed in-session.
    Implemented-by:  claude/issue-10867-app-wizard-saves-spec-app
    Reviewed-by:     session_014mXUNuFomfj24w7s1pZzhN
    
    item reading
    the change The app wizard saves a document the spec accepts. A separator is { id, type } on both faces, and objectui validate refuses a separator label too. A branding edit keeps every declared key (accentColor included). The Layout step and AppWizardDraft.layout are gone
    review contract review 5863120059 FAIL (banner and i18n semver), then fix round 1 (plus the zod separator branch and a cleared-logo row), then the in-seat delta record PASS at 2c19f3047 (posted with this landing)
    changesets minor for types and i18n, with a BREAKING (authoring) banner; patch for layout, app-shell and plugin-designer. Dated notes on 10842 and 3162, frontmatter byte-identical
    serial git merge-tree clean against main
    CI head 2c19f3047: every check final and green before ready (this landing waits on it)
    closing keywords Fixes #10867 only
    follow-up objectui#10894: an app edit regenerates away stored non-object navigation entries (serial behind this PR)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:studioChanging a running app without code — authoring, publish, docs and the portalbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p1

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions