Skip to content

Page designer: a readable source editor, a Properties tab with the page's metadata, a Run mode that differs #12522

Closed

Description

@objectstack-fleet

Source

Measured on objectui main d4bc81eab, 2026-10-15, Interfaces pillar, a new html page (help_center, "Written in: HTML"): the aside's Source tab shows the page source (<flex direction="col" gap={4}>…) in about 10 px mono at the top of a 479 × 856 px panel that is otherwise empty; the Properties tab says only "This page is html source, not a block tree — edit it in the Source tab"; the header's Design / Run toggle changes nothing visible for a static page.

Target

  1. The source editor uses the console's 12–13 px mono, shows line numbers, fills the panel's height and wraps long lines; a one-line status under it says "Saved HH:MM" or "Unsaved".
  2. The Properties tab for an html page shows the page's metadata: label, identifier, kind (html / react), the nav entries that point at it, and the same "Written in" value, editable where the schema allows.
  3. Run mode hides the designer chrome (selection ring, dashed regions, the Add block toolbar) and renders the page as the app does; when a page has no designer chrome, the toggle is disabled with a tooltip reason (objectui#12303 pattern).

File surface

packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx (InterfacesPillar page branch), the page source editor and the page preview under packages/app-shell/src/views/metadata-admin/previews/, packages/app-shell/src/views/metadata-admin/i18n.ts, tests beside.

Acceptance

  1. Tests: Properties for an html page lists label, identifier and kind; Run mode renders without the designer chrome.
  2. Screenshots of Source, Properties and Run, light and dark.
  3. pnpm --filter @object-ui/app-shell test green.

Constraints

  • No new editor dependency; the editor the console already ships.
  • Existing data-testids (if-inspector, if-canvas-caption) stay.

Filed by the epic PM session session_cdb7a717-def7-4e71-9988-f089fbaa18ff from the 2026-10-15 Studio test pass: objectui main d4bc81eab, HotCRM 63db83e2, the vite console on :5180 against objectstack serve --dev on :4001, viewport 1482 × 1119, dark theme with a light-theme check.

Evidence

Screenshots from the test pass, kept on the temporary branch claude/studio-test-pass-evidence-20261015 of objectstack-ai/objectui (commit 72115588c, never merged: the maintainer ruled that screenshots do not enter main, and asked for a temporary branch referenced from the card). The branch's docs/design/studio-redesign/findings/2026-10-15/README.md maps every file to its card. Pane captures, 800 × 604 of a 1482 × 1119 viewport, dark unless named light.

page properties tab
docs/design/studio-redesign/findings/2026-10-15/12522-page-properties-tab.jpg — page properties tab.

page run mode
docs/design/studio-redesign/findings/2026-10-15/12522-page-run-mode.jpg — page run mode.

page source tab
docs/design/studio-redesign/findings/2026-10-15/12522-page-source-tab.jpg — page source tab.

Parent: #12446

Body refreshed 2026-10-15T15:19Z by the epic PM session: an Evidence section with the test-pass screenshots added.

Activity

  1. added
    enhancementNew feature or request
    pm:epicParent delegated to a dedicated epic PM — other PMs never dispatch into its subtree
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    area:studioChanging a running app without code — authoring, publish, docs and the portal
    and removed
    pm:epicParent delegated to a dedicated epic PM — other PMs never dispatch into its subtree
    on Oct 15, 2026
  2. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 (domain:ui lane queue; an objectui#12446 test-pass card)
    Session: session_01SJn1GEkrbbBQkhGC26wEDw
    Account: os-sales (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-12522-page-designer
    Worktree: objectui-issue-12522 (in the cloud session's own container)
    Domain: domain:ui
    Seat: domain:ui#4
    File surface: packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx (the InterfacesPillar page branch only; not the canvas mount objectui#12508 round 2 holds), the page source editor and the page preview under packages/app-shell/src/views/metadata-admin/previews/, metadata-admin/i18n.ts (new keys only), new tests beside them, one .changeset/12522-*.md (stop on breach; explain in the report)
    Container & model: L, mode:cloud, model: opus (cloud on the maintainer's stance 「可以的话,ui 后续开发尽量用云 session,并且要求截图给我看」; lane scope on 「你也可以接ui车道的卡」; batch 5 on 「上限提到 5,提速」, this session's chat, 2026-10-15)
    Clause-②: no
    Responsibility: n/a — not a defect card
    Thread-read: none
    Serial constraints cleared: objectui#12455 (InterfacesPillar) landed as b541694 and objectui#12519 (its rail) as 73a3eb2, so the page branch is free. objectui#12508 round 2 holds the canvas mount (about :4017–:4025) and studio-canvas-preview.tsx; this card does not edit those lines. In flight on StudioDesignSurface.tsx from this seat at this claim: objectui#12508 round 2 (the InterfacesPillar canvas mount and studio-canvas-preview.tsx only), and the sibling cards of this wave: objectui#12510 (accessible names across the shell), objectui#12514 (the Automations and Access empty branches), objectui#12515 (the Form tab preview branch) and objectui#12522 (the InterfacesPillar page branch). They are in disjoint regions; any textual overlap is resolved by merging origin/main.

  3. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 12522,
    "status": "done",
    "branch": "claude/issue-12522-page-designer",
    "pr": null,
    "session": "session_01TMRmamUSS4m88TGPxNSTSP",
    "premise_still_valid": true,
    "summary": "Built the html/react page designer in the Interfaces pillar. 1) The source editor's plain-textarea fallback, used when Monaco is unavailable, now has a line-number gutter, wraps long lines and fills the panel at 12 px mono, like the Monaco editor. A one-line status under the editor reads Saved, Unsaved or Saved HH:MM. 2) The Properties tab is a new SourcePageProperties panel. It shows the page's label, which can be edited and uses the existing renamedLabel so a per-language label keeps its other languages. It also shows the identifier and the 'Written in' kind, both read-only, and lists every navigation entry that opens the page, with its group. 3) On a source page the Design / Run switch is disabled, and its reason is given the objectui#12303 way: a focusable wrapper that shows a tooltip, plus a visually hidden copy. Block-tree pages keep a working switch; measured in the browser, Run already drops their designer chrome, and a new test pins that. PM assumption checks: #1 partly false: on current main the Monaco editor already uses 12 px, line numbers, full height and wrapping. The test pass saw the loading skeleton and then the textarea fallback, which is what changed. #2 false: the pillar kept no saved-at state. A timestamp tied to the leaf is now set where the existing save succeeds; there is no new save path. #3 held. #4 held: block pages differ between Design and Run; html pages draw the same thing in both. #5 respected: the canvas mount and studio-canvas-preview.tsx were not edited. objectui#12508 round 2 has since landed on main as 1b28dbf, and my branch merges cleanly with current origin/main.",
    "tests": "At HEAD b3ca8ff. New test files (vitest run from the repo root): InterfacesPillar.sourcePage-12522.test.tsx, 5/5 pass, exit 0; SourcePageProperties.test.tsx plus SourcePageEditor.lineNumbers-12522.test.tsx, 6/6 pass, exit 0. Existing tests my diff touches (75 files: every test naming SourcePageEditor, canvas-mode-toggle, InterfacesPillar, Page source, modeRun or engine.studio.if keys, plus app-shell i18n tests), run under os-verify-lock: Test Files 75 passed (75), Tests 856 passed (856), VERDICT command-exit 0. Full pnpm --filter @object-ui/app-shell test, run once in the foreground under os-verify-lock: Test Files 1413 passed, 1 skipped (1414); Tests 13472 passed, 9 skipped (13481); VERDICT command-exit 0. packages/i18n machineLocaleCensus-9909.test.ts: 7/7, exit 0. Ablations, each done with objectstack scripts/ablation-replace.mjs; each mutation was confirmed on disk, its test went red (exit 1), then the file was restored to the HEAD blob with an empty git diff HEAD: (a) toggle disabled={isSourcePage} changed to false: the disabled-switch pin went red. (b) nav filter pageName === currentPageName changed to true: the Properties pin went red. (c) setLeafSavedAt line deleted: the Saved HH:MM pin went red. (d) gutter {i + 1} deleted: the line-number pin went red. (e) PagePreview designMode && shape === 'regions' changed to shape === 'regions': the block-page Run pin went red. (f) renamedLabel changed to String(e.target.value): the per-language label pin went red. The first try at (f) used e.target.value as the replacement; the tool refused it because that text was already in the file, so it changed nothing and ran no test, and I re-ran it with a distinct replacement. No dist rebuild was needed: the tests import app-shell source through relative paths.",
    "gates": "Local, at b3ca8ff, exit codes captured before any pipe. pnpm --filter '@object-ui/app-shell^...' build (dependency packages): 0. pnpm --filter @object-ui/app-shell type-check: 0, with 0 'error TS' lines. pnpm --filter @object-ui/app-shell build: 0. eslint --no-inline-config on the 7 touched files: 0, with 0 errors and 15 warnings, all at lines outside this diff. pnpm check:i18n-keys 0; check:i18n-drift 0 ('9 key(s) added, 2 removed'); check:i18n-designer-parity 0; check:i18n-dead-keys 0; node scripts/check-changeset-presence.mjs 0; check:new-line-citations 0 ('0 new citation(s)'). I derived the gate list by hand: objectui has no scripts/pm/dispatch-gates.mjs, so there was no --ran reconciliation. No PR exists yet, so no CI check runs exist; those are NOT MEASURED until the PM opens the PR.",
    "mcp_calls": "8 calls, all reads, no GitHub writes: claude-code-remote add_repo x2 (read access; objectstack and hotcrm, both public, nothing attached); ToolSearch x1; github issue_read x4 (#12522 get and get_comments, #12446 get and get_comments). Not counted: chrome-devtools and shadcn tools, which were not used.",
    "api_writes": "None besides git push: the branches claude/issue-12522-page-designer (empty probe, then 630e164 and b3ca8ff) and claude/issue-12522-evidence (d3817f2).",
    "open_questions": [
    {
    "question": "Properties tab: the page kind is shown read-only, although the spec's kind enum would accept html to react. Is that right?",
    "options": [
    "A: read-only, worded as 'Written in' with 'Chosen when the page was created' (what was built)",
    "B: an editable html/react select"
    ],
    "recommendation": "A. The four axes: (business need) no producer switches kind after creation, and interfaceCreate's PageCreateFields docblock already says the Studio does not change it. (Long term) html source is parsed and never run while react source runs, so switching kind changes what the same text means and is a trust-tier jump, not an edit. (Preventing AI mistakes) an editable select would let an agent flip the trust tier without touching the source. (Startup focus) it adds nothing. The dispatch ruling, 'edits only what the page schema allows', allows A, since showing a field read-only is permitted."
    },
    {
    "question": "Status line when nothing was saved during this visit: it shows 'Saved' with no time, because the pillar's draft read carries no time. Is that acceptable?",
    "options": [
    "A: 'Saved' with no time until the first save of this visit lands (built)",
    "B: read updatedAt off the draft read"
    ],
    "recommendation": "A. B would add a read-shape dependency the card does not ask for (startup axis), and the dispatch said the status must add no new save path."
    },
    {
    "question": "Folded layout (when the chat dock folds the aside into center tabs): its Properties tab is still the source editor alone, with the status line now added. The metadata panel is not shown there. Should it be?",
    "options": [
    "A: leave as is; the card's target is the aside (built)",
    "B: add a third center tab"
    ],
    "recommendation": "A. It is outside the card's artboard; a follow-up should be filed only if the epic PM's acceptance asks for it."
    }
    ],
    "out_of_scope_findings": [
    "Observation, no card filed: interface pages (a page with interfaceConfig.source) render InterfaceListPage in both Design and Run; only the inline config callback differs. I did not measure this in the browser, and their switch was left live. Carrier: none.",
    "Observation, no card filed: the Monaco loader comes from the jsdelivr CDN, so a sandboxed or CSP-restricted browser shows the skeleton for up to 4 s before the textarea. This is what the test pass captured, and the improved fallback covers it. Carrier: none."
    ],
    "deviations": [
    "i18n: the dispatch says 'new keys only', but I also retired two keys, engine.studio.inspector.sourcePageLine1 and sourcePageLine2, in en and zh. They held the old Properties-tab copy the card replaces, and nothing reads them now. check:i18n-dead-keys and check:i18n-drift exit 0. Retiring them at once follows the startup axis.",
    "File surface: besides the page branch, StudioDesignSurface.tsx changed in three spots in InterfacesPillar: the header's Design/Run switch (canvasModeToggleEl; the card's target 3 requires it), one new state hook beside ifDirty, and one line in the existing doSave that stamps the saved-at time. The canvas mount lines and studio-canvas-preview.tsx were not touched.",
    "The os-dev contract says to post the report as a card comment and to open the PR. The dispatch's degraded-channel order (the fleet-write relay is refused in this container) says to do neither, so I posted no comment and opened no PR. Where the two disagree I followed the dispatch, because the write route the contract assumes is unavailable here.",
    "The commit trailers use the model-free pair (Claude-Session plus Co-authored-by: Claude), following objectui AGENTS.md over the harness's model-named trailer.",
    "The feature worktree /home/user/objectui-issue-12522 is kept, because the PR is not open yet. The evidence worktree was removed. The backend (:4122) and console (:5222) I started are stopped."
    ],
    "files_changed": [
    "packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx",
    "packages/app-shell/src/views/metadata-admin/previews/SourcePageEditor.tsx",
    "packages/app-shell/src/views/metadata-admin/previews/SourcePageProperties.tsx (new)",
    "packages/app-shell/src/views/metadata-admin/i18n.ts",
    "packages/app-shell/src/views/studio-design/InterfacesPillar.sourcePage-12522.test.tsx (new)",
    "packages/app-shell/src/views/metadata-admin/previews/SourcePageProperties.test.tsx (new)",
    "packages/app-shell/src/views/metadata-admin/previews/SourcePageEditor.lineNumbers-12522.test.tsx (new)",
    ".changeset/12522-page-designer-source-page.md (new)"
    ],
    "screenshots": [
    "https://github.com/objectstack-ai/objectui/blob/d3817f2b46728ce7b8f812f9e00f383f8b322572/docs/design/studio-redesign/findings/12522/12522-html-source-dark.png?raw=true",
    "https://github.com/objectstack-ai/objectui/blob/d3817f2b46728ce7b8f812f9e00f383f8b322572/docs/design/studio-redesign/findings/12522/12522-html-source-light.png?raw=true",
    "https://github.com/objectstack-ai/objectui/blob/d3817f2b46728ce7b8f812f9e00f383f8b322572/docs/design/studio-redesign/findings/12522/12522-html-source-fallback-dark.png?raw=true",
    "https://github.com/objectstack-ai/objectui/blob/d3817f2b46728ce7b8f812f9e00f383f8b322572/docs/design/studio-redesign/findings/12522/12522-html-source-fallback-light.png?raw=true",
    "https://github.com/objectstack-ai/objectui/blob/d3817f2b46728ce7b8f812f9e00f383f8b322572/docs/design/studio-redesign/findings/12522/12522-html-properties-dark.png?raw=true",
    "https://github.com/objectstack-ai/objectui/blob/d3817f2b46728ce7b8f812f9e00f383f8b322572/docs/design/studio-redesign/findings/12522/12522-html-properties-light.png?raw=true",
    "https://github.com/objectstack-ai/objectui/blob/d3817f2b46728ce7b8f812f9e00f383f8b322572/docs/design/studio-redesign/findings/12522/12522-html-run-disabled-dark.png?raw=true",
    "https://github.com/objectstack-ai/objectui/blob/d3817f2b46728ce7b8f812f9e00f383f8b322572/docs/design/studio-redesign/findings/12522/12522-html-run-disabled-light.png?raw=true",
    "https://github.com/objectstack-ai/objectui/blob/d3817f2b46728ce7b8f812f9e00f383f8b322572/docs/design/studio-redesign/findings/12522/12522-block-design-dark.png?raw=true",
    "https://github.com/objectstack-ai/objectui/blob/d3817f2b46728ce7b8f812f9e00f383f8b322572/docs/design/studio-redesign/findings/12522/12522-block-design-light.png?raw=true",
    "https://github.com/objectstack-ai/objectui/blob/d3817f2b46728ce7b8f812f9e00f383f8b322572/docs/design/studio-redesign/findings/12522/12522-block-run-dark.png?raw=true",
    "https://github.com/objectstack-ai/objectui/blob/d3817f2b46728ce7b8f812f9e00f383f8b322572/docs/design/studio-redesign/findings/12522/12522-block-run-light.png?raw=true"
    ],
    "line_budget": "n/a",
    "pr_title_draft": "feat(app-shell): page designer for html/react pages: a numbered source editor with a save status, a Properties tab with the page's metadata, and a disabled Run switch that says why (objectui#12522)",
    "pr_body_draft": "(elided by the seat: opened verbatim as the body of PR #12582, read back identical)"
    }

    Relayed verbatim by seat domain:ui#4 (session session_01SJn1GEkrbbBQkhGC26wEDw) from the cloud session's final message, the degraded write channel. The seat opened the draft PR #12582 from pr_title_draft and pr_body_draft, with assignee os-sales. "pr": null above is the session's own value at report time.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · PR #12582 merged as 830eb1f on main · read 2026-10-15T22:48Z

    probe on origin/main 830eb1f reading control
    leafSavedAt in StudioDesignSurface.tsx (state and read) 2 lines the saved-at stamp is on main
    engine.studio.if.modeSourcePage in StudioDesignSurface.tsx 1 the disabled Run switch's reason
    metadata-admin/previews/SourcePageProperties.tsx present —
    sourcePageLine1 in metadata-admin/i18n.ts 0 the old Properties copy is retired
    InterfacesPillar.sourcePage-12522.test.tsx, .changeset/12522-page-designer-source-page.md present —

    State change: the card closed as completed through Fixes #12522, and pm:dispatched is removed in this act. The cloud session session_01TMRmamUSS4m88TGPxNSTSP is archived. objectui#12524 (the item headers' draft status chip, ifHeaderEl), which was queued behind this card, is free.


    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

area:studioChanging a running app without code — authoring, publish, docs and the portaldomain: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