Skip to content

Studio report Properties: switching Report type to Joined autosaves a report with no blocks (422), and later edits are refused and lost on reload with no prompt #29022

Closed

Description

@objectstack-fleet

domain:devx#1 · os-warren · session_01JQwxbX9avDwM2goWd7zimE

Filing gate: ① a product defect, found beside the clauses (studio-authoring.report-authoring-options), reach: the Studio autosave, measured 3 times.
Business reason: a report author who switches a report to Joined and touches anything before adding the first block sees "Changes not saved", and every edit is then refused and lost on reload without a prompt. #27785 holds an added Order or Blocks item and a chart type picked before its axes; the type switch itself is the remaining door into the same loss.
Reader who acts: the triage seat, then a domain:ui implementer in ui/packages/app-shell/src/views/studio-design/metadataError.ts. QA suggestion only: area:studio, p2.
Duplicate search: joined report Studio blocks → 65 hits; #27785 (closed) is the sibling for list items and chart axes, #21702 (closed) the spec side of a joined report with no dataset; none is the type switch.
Batch-of: release-18.3.0-w4-c3b1 — 16 cards from QA run #29002 (subject 7fa9873f; the implementer re-checks the landing site on current main).

Reproduction

  1. /_console/studio/PKG/interfaces → nav "+" → Report → a name, a dataset and a measure → Save as draft (PUT 200, type: summary).
  2. In Properties set Report type = Joined. Studio autosaves {"type":"joined","drilldown":true,…} with dataset and values dropped and no blocks → 422 at blocks, "a joined report needs blocks".
  3. Edit Description → the PUT carries the same body plus the description → 422.
  4. Reload: no beforeunload guard (defaultPrevented false) and no prompt; the report is back to Summary and the description is gone.

Expected: the switch is held until a block is complete, or the refused edits are guarded on leave. Actual: as above. Reproduced 3 times on fresh loads.

Mechanism (suspected)

reportHeldEdit in metadataError.ts does not treat a joined report with no blocks as held.

QA-source: #29002 · studio-authoring.report-authoring-options · observed beside the clauses

Activity

  1. added
    area:studioChanging a running app without code — authoring, publish, docs and the portal
    domain:uiDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    on Nov 2, 2026
  2. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: studio-authoring.report-authoring-options

    Triage: domain:ui · p2 · pm:queue · 2026-11-02T07:21Z

    ⛔ Not a claim.

    • Read fresh. reportHeldEdit in ui/packages/app-shell/src/views/studio-design/metadataError.ts does not hold a joined report with no blocks, so Studio autosaves a body that gets a 422 and later edits are lost on reload; domain:ui. Silent loss of an author's edits is a user-visible defect, p2. It has a named location and a 3x repro, so pm:queue.

    Generated by Claude Code

  3. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu

    Claim: PM loop round 19 · 2026-11-02T07:35Z
    Session: session_01QsR2jUqfeyd3MJX6eCeZdA (card thread, os-dev); dispatched by seat session session_01QsR2jUJ19MstFvFhjgiYTu
    Account: zhuangjianguo
    Branch: claude/project-thread-wbw17z (platform-assigned to the card thread; it can push only this branch)
    Worktree: objectstack-issue-29022
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: ui/packages/app-shell/src/views/studio-design/metadataError.ts and the Studio report properties editor the dev names in a claim amendment before code, their tests, and a root .changeset (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default tier (dispatch-gates --tier: no path-derived mandate), effort: medium
    Clause-②: no
    Metadata-protocol: none
    Responsibility: switching a Studio report to Joined autosaves a report with no blocks (422) and later edits are lost
    Thread-read: 6571473866
    Premise: holds (at origin/main 5d3667e2: the card measures the 422 on the Joined switch; the dev re-measures before code)
    Serial constraints cleared: #29006 waits for this card (both edit metadataError.ts).

  4. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 2, 2026
  5. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu

    Claim amended · 2026-11-02T07:36Z · after the dev's reading at origin/main 5d3667e2. This sets the file surface and adds to the round 19 claim on this card. Branch, session and size are unchanged.

  6. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · zhuangjianguo · session_01QsR2jUqfeyd3MJX6eCeZdA
    os-dev-report

    {
      "issue": 29022,
      "status": "done",
      "branch": "claude/project-thread-wbw17z",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29143",
      "session": "session_01QsR2jUqfeyd3MJX6eCeZdA",
      "premise_still_valid": true,
      "summary": "reportHeldEdit (metadataError.ts) gains one arm, joinedReportHeld: a report whose type is joined and whose blocks are missing or empty is held unsent when ReportSchema's only refusal is at blocks, with a clause naming the report form's Blocks list and Show me focusing it; an added block is then judged by the existing list-item rule. A joined report with no blocks that also carries another refused key is still sent, so that refusal stays on screen. One new studio-namespace string (en, zh). The held clause already reaches the surface's beforeunload, header guard and Publish refusal, so the card's reload loss no longer happens on this path. ReportDefaultInspector.tsx unchanged. Within claim 6571686909 and amendment 6571700500; the second new test file (InterfacesPillar.reportJoined-29022.test.tsx) is a test of this arm through the real inspector, beside the 27785 pair.",
      "tests": "Head 21198aa4. New: metadataError.reportHeld-29022.test.ts + InterfacesPillar.reportJoined-29022.test.tsx, 12/12 passed. Ablation (scripts/ablation-replace.mjs, delete `if (joined) return joined;`, anchor 1 to 0, blob f915fdc4 to dea5df87): 6 failed / 6 passed (the 4 held unit cases + pillar not-sent and Show me; controls and list-item handover stay green); restored, blob == HEAD, git diff HEAD empty. Sweep under the lock: 35 app-shell files naming reportHeldEdit / engine.studio.held / ReportDefaultInspector + zh-base-term.i18n-13131 + packages/i18n/: 131 files, 1701 passed, 13 skipped. turbo type-check app-shell + i18n: 66/66, VERDICT exit 0. Narrowing: whole app-shell vitest is CI's Test UI.",
      "gates": "dispatch-gates --commands: 34 derived, all exit 0 (check-sdui-manifest, check-changeset-no-major, check-adr-0087-registration and check-closing-keyword-parity run against the final PR body, check-partof-closing-keyword exit 0 too; pnpm --dir ui exec vitest run scripts/ 169 files passed, 2 skipped). dispatch-gates --ran: 34 derived, 34 run, 0 NOT-MEASURED. PR check-runs at report time on 21198aa4: 17 in_progress, 3 skipped; mergeable_state blocked (draft, checks pending).",
      "dogfood_battery": "n/a: no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "1: get_session (read). No MCP GitHub calls.",
      "api_writes": "2: fleet-write pr_create (run 41411166546, PR #29143, read-back identical, no assignees, no labels); this os-dev-report comment via post-stamped. Plus git push of the branch.",
      "open_questions": [],
      "out_of_scope_findings": [
        "class: a · reach: source reading only, not measured on a public door · ReportDefaultInspector.tsx JOINED_CONTAINER_CLEARED_KEYS clears dataset/values/rows/columns/chart/order on the Joined switch but not dateRange or exportOptions, which ReportSchema's joined arm also refuses (#26548) and whose Period and export section report.form.ts hides on a joined report (visibleWhen type != joined). A report with either key set, switched to Joined, is sent and refused at a key no visible control reaches · dedupe words: joined report dateRange exportOptions type switch cleared keys",
        "class: a · reach: source reading (StudioDesignSurface.tsx InterfacesPillar onDirtyChange mirrors only navDirty; heldEdit carries only held clauses) · a leaf save refused with a 422 leaves later edits that no beforeunload, header or rail guard sees · carrier: seat (filing it as its own card, per the amendment) · dedupe words: refused save guard beforeunload leaf ifDirty Studio"
      ]
    }

    Generated by Claude Code

  7. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu

    Landed · 2026-11-02T09:59Z · PR #29143 merged through the merge queue as 1e4841a2 at 2026-11-02T09:58Z (GitHub's clock). ACCEPT 6572697572.

    probe before (1e4841a2~1) now (origin/main)
    joinedReportHeld in ui/packages/app-shell/src/views/studio-design/metadataError.ts 0 3
    InterfacesPillar.reportJoined-29022.test.tsx exists no yes

    Fixes #29022 closed this card. pm:dispatched comes off in the same stroke as this note. #29006 (seat 2) waited on this PR and can now be ordered on origin/main.

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:uiDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions