Skip to content

v16.0 browser test checklist — exercise every 16.0 feature in the running app #3358

Description

@os-zhuang

Centralized browser-based verification of the entire 16.0 release. Each item is a shipped 16.0 capability with a concrete path to exercise it and the expected result. Source of truth: content/docs/releases/v16.mdx (PRs #3322 / #3331 / #3357).

Environment

  • Boot the showcase / CRM example app and drive it in a browser as admin + a regular user (see the dogfood-verification skill). Showcase seeds make most features demonstrable out of the box.
  • Legend: 🖥️ = verify in the Console/Studio browser UI · 🔌 = backend/API/CLI — not directly browser-driven, verify via REST/os CLI or an API panel · ⚠️ = a fix that is easiest to confirm by reproducing the old broken behavior.

1. Approvals 🖥️

  • M-of-N quorum — configure an approval step with quorum + minApprovals; submit; confirm it approves once the threshold is met, and that a single rejection still vetoes.
  • Per-group sign-off (会签) — configure per_group with 2 named groups (e.g. manager + finance); confirm it needs one approver from each group; try the showcase ExpenseSignoffFlow.
  • Server-computed progress — a pending multi-approver request shows per-group tick badges / “2 of 3 · finance pending”, not a client guess.
  • Decision attachments — on approve/reject, attach a file through the decision dialog; confirm it uploads and shows as a named chip in the timeline.
  • Notification deep link — click an approval bell notification; confirm ?request=<id> opens the request drawer directly.
  • Metadata-driven inbox actions — the inbox renders approve / reject / reassign / send-back / request-info / remind / recall / resubmit from declared actions (no hand-wired buttons); each executes its REST route.
  • Viewer gating — as the submitter viewing your own pending request: you do not see approver buttons; as a position-addressed approver: you do see them (not hidden by a client heuristic).
  • Reassign user picker — the reassign dialog renders a real sys_user picker (not a free-text id box).

2. Automation / Flow (Studio) 🖥️

  • Time-relative trigger — author a flow start node with timeRelative (offsetDays: [60,30,7] or withinDays); confirm the first-class designer panel; verify it fires per matching record on the daily sweep.
  • Nested regions on the canvas — a loop/parallel/try_catch node shows its nested region inline (not an opaque card); select and edit a node inside a region through the schema-driven inspector.
  • Flow Runs step logs — run a flow with a loop; the Runs panel nests per-iteration / per-region steps.
  • Schema-driven keyValue / numberList — a node with a free-form {var:value} map renders a keyValue editor (not raw JSON); a number array renders numberList.
  • Roll-up summary filter editor — edit a summary field; set a child-row filter via the visual editor; confirm the parent total only counts matching children.
  • 🔌 Flow observability banner — on os dev/serve, a misauthored auto-launched flow surfaces ⚠ lines in the Flows: startup banner and ERROR logs on a failed trigger run.

3. Dashboards & Analytics 🖥️

  • Dataset-only widget authoring — the widget config panel is a dataset picker (chart and pivot); the inspector emits only dataset + dimensions + values.
  • ⚠️ Strict dashboard widgets — author a widget with a stray/legacy key (e.g. categoryField); confirm a loud parse error naming the key + pointing at the dataset shape (was: silently renders nothing).
  • Report drill-through range — drill a date-bucket cell (e.g. “2026-Q2”); confirm the drilled list is scoped to that exact time range, not a superset.
  • ⚠️ Chart first paint — a dashboard with bar charts draws bars on first paint (no blank-until-resize).

4. Records / Lists / Detail / Forms 🖥️

  • Action param real widgets — an action with file/image/richtext/color/date params renders each real widget in the dialog (not a text input); file params upload via the ambient provider (multiple/accept/maxSize).
  • ⚠️ Upload guard + autonumber — Confirm is disabled while a file/image param is still uploading; a spec autonumber param maps to the AutoNumber widget.
  • Option-widget visibleWhen parity — a dependent select/multiselect/radio/checkboxes option shows/hides as its parent changes (cascading + dependsOn); select + multiple renders a multi-value chip picker.
  • Master-detail atomic save — save a master + line items in one go; confirm one atomic batch (no partial writes on failure).
  • Related lists pagination — a record with many children paginates via server $top/$skip (doesn’t load every row).
  • Record History tab — shows display values, not raw audit payloads; no phantom “value → null” rows for computed fields.
  • Inline edit — double-click a field, edit several (incl. header highlights), save once atomically; computed/readonly fields stay non-editable.
  • List polish — toolbar manual refresh button; injected owner_id stays out of leading columns and lands in the detail meta section.
  • ⚠️ Import wizard — a disabled Next explains itself (unmapped required fields hint); GBK/GB18030 zh-CN CSV imports without garbled headers; legacy per-row fallback shows a “compatibility fallback” notice.
  • Single-file child grid — a child object with one file field stays an inline grid (doesn’t flip to a per-row form).

5. Access / Studio pillar 🖥️

  • Permission matrix hits first screen (B1) — identity + zero-grant capability sections start collapsed.
  • Explain panel object dropdown (B2) — object field is a package-scoped dropdown, not free text.
  • Field-level bulk + filter (B4) — a wide object gets a field filter + Read-all/Write-all/Clear over visible rows; Bulk column not clipped at narrow widths (B3).
  • Record-grained AccessExplainPanel — pick user+object+record; see per-layer attribution (permission set → position → sharing → row rules) + a record.visible verdict with the deciding layer.
  • Provenance / bucket badges — platform/package/admin provenance badges; writable-system objects distinguished from engine-owned in badges + empty states.
  • Read-only package locks matrix — on a read-only package the matrix checkboxes/Save are actually disabled.

6. Auth / Login / Identity 🖥️

  • ⚠️ SSO-only not stranded — on a cold-started env, the login page honors ssoEnforced on first paint (no password wall flash); a hung sign-in recovers via watchdog.
  • Dev admin hint — os dev login page shows the dev-seeded admin credential hint.
  • Import wizard auto policy — the user-import wizard defaults to Automatic (recommended); reachable rows are invited, unreachable get a one-time password shown once.
  • Phone sign-in surfaces — create a phone-based user; the phone number shows in the create result dialog, the All Users list, and the record detail highlights.

7. i18n 🖥️

  • ⚠️ Notifications actually clear — on a zh-CN workspace, a collab.assignment bell notification title is localized (recipient locale), opens a localized detail page, and mark-as-read clears the unread state on standalone/os dev (the notifications REST routes are now mounted).
  • Action result dialog localized — create a user on a translated locale; the temporary-password result dialog (title/description/acknowledge/field labels) is translated, not hardcoded English.
  • Storage objects localized — sys_file detail page labels + the Pending/Committed/Deleted status pipeline render in the workspace locale.
  • Studio follows in-app locale — switch the in-app locale; Studio/metadata-admin follow it (no mixed-language session); relative dates localize.

8. Gantt (plugin-gantt) 🖥️

  • Ownership-aware reschedule — drag/auto-schedule an own-dates summary; it carries its unlocked subtree; locked tasks are reported, not moved; toolbar auto-schedule confirms first (“shift N tasks? (M locked skipped)”).
  • Manual scheduling + veto — manual-scheduling summary bars; a beforeTaskUpdate host veto blocks a bad drag; dependencyTypes switch hidden for id-only stores.
  • Removed — the mobile QR-share context action is gone.

9. Backend / API / CLI (indirect) 🔌

  • organizationId in hooks/actions — ctx.user.organizationId / ctx.session.organizationId resolve; tenantId alias removed.
  • MCP stdio API-key — stdio auto-start without OS_MCP_STDIO_API_KEY fails closed; with a valid key, reads honor RLS/FLS.
  • transactionalBatch discovery bit — client.capabilities.transactionalBatch reflects whether /batch is mounted + transaction-capable.
  • ⚠️ Write-path guards — readonly fields stripped on INSERT+UPDATE via REST; owner_id forge/transfer denied; cross-object /batch gated by per-object API rules; bulk-update runs validation rules.
  • ⚠️ Formula fixes — record.due_date == today() matches; cond ? x : null + floor/ceil work; date arithmetic (end - start + 1) is now a build-time error in os build.
  • ⚠️ checkboxes per-option visibleWhen enforced server-side — a crafted write of a gated checkboxes option is rejected.
  • enforce-or-remove sweep — authoring a removed field/object key, a dead hook event, events:['delete'], a webhook undelete/api trigger, or aiStudio/aiSeat fails at parse/build.
  • Server-Timing — with OS_SERVER_TIMING / X-OS-Debug-Timing, an admin sees auth/db/hooks/serialize spans; a non-admin does not.
  • MCP validate_expression — an agent validating a formula against an object schema gets errors/warnings/inferred type.

Notes

  • Track findings by checking boxes; file a linked bug per failure with repro steps + the responsible PR/ADR from v16.mdx.
  • ⚠️ items are regressions/holes fixed in 16.0 — the strongest test is to reproduce the old broken behavior and confirm it no longer happens.

Activity

  1. os-zhuang commented on Jul 20, 2026

    @os-zhuang
    ContributorAuthor

    v16.0 verification sweep — results (automated dogfood pass)

    Ran the checklist against the showcase app on a fresh isolated os dev instance (framework main @ d8b8354, console 16.0.0-rc.1, vendored objectui pin 69fa5d16 — confirmed to include all post-rc.0 Console work af1b0db+). Drove it as admin in the browser + REST/CLI, with build-time gates exercised against the built packages.

    🐛 Confirmed regressions filed

    Both are the same architectural seam: a v16 feature wired into the runtime HttpDispatcher / dispatcher-plugin that never reaches the hono server os serve/dev actually runs.

    ✅ Verified PASS

    §9 Backend/API/CLI (8/9):

    • transactionalBatch discovery bit = true + /api/v1/batch mounted; atomic:false → 400 BATCH_NOT_ATOMIC
    • readonly stripped on INSERT (lead_score=999 → stored null)
    • Formula fixes (harness vs built @objectstack/formula): date-arith end-start+1 & today()+30 → build error; due_date==today(), cond?5:null, floor, ceil, daysBetween → ok
    • enforce-or-remove: ObjectSchema.create throws located guidance for recordName/search/versioning/softDelete/keyPrefix/tags/abstract; field referenceFilters silently stripped
    • checkboxes per-option visibleWhen server-side: CHOICE_FIELD_TYPES includes checkboxes; live cascade write (country=cn, province=ca) → 400 VALIDATION_FAILED
    • organizationId on author ctx (no tenantId alias); MCP stdio fail-closed guard present (plugin.ts:178)

    §2 Flow (Studio designer): time-relative trigger panel (Sweep object / Date field / Offset days numberList); nested regions expand inline (Loop {tasks}, not opaque card, incl. #3304 clean {tasks}); schema-driven numberList; observability banner (Flows: 43 flow(s) 34 bound … time_relative … · 6 draft).

    §3 Dashboards: ⚠️ strict widgets — decisive (categoryField/valueField+aggregate/pivot rowField/hallucinated key all rejected with the loud named ADR-0021 error); ⚠️ chart first paint (bars/axes draw immediately, no blank-until-resize).

    §1 Approvals (authoring): showcase_committee_quorum → approval node "Committee Sign-off (2 of 3)", schema-driven inspector with per-approver Type/Value/Group (会签). quorum/per_group/minApprovals present in the server-driven palette (/automation/actions).

    §5 Access pillar: matrix on first screen w/ zero-grant capabilities minimal (B1); provenance badges (包内置, OWD Public/Private/parent-controlled, Ext); read-only package lock (只读 badge); Explain-access button present.

    §6 / §8: dev-admin login hint; Gantt renders (granularity, bars, milestones, dependencies, auto-schedule wand); mobile QR-share action removed (objectui#2687); auto-schedule confirm-first dialog present.

    ⚠️ Blocked / not fully driven (need setup or deeper interaction)

    • §1 live approval flow — showcase seeds 0 positions / 0 invoices / 0 pending requests, so the end-to-end inbox scenario (progress badges, decision attachments, ?request= deep link, viewer gating, reassign picker) isn't demonstrable out of the box. The checklist's "ExpenseSignoffFlow + finance/legal approvers" assumption doesn't hold without seeding.
    • §2 Flow Runs step logs — 0 automation runs (no flow has fired a loop yet).
    • §9 MCP validate_expression — MCP HTTP is off (501) on this config; the underlying validateExpression fn works.
    • §9 owner_id forge — needs a non-admin session to be meaningful (admin write is legitimate).
    • §4 remaining (action-param widgets, upload guard+autonumber, master-detail atomic save, related-list pagination, History tab, inline edit, import wizard, single-file grid) — not yet driven; visibleWhen cascade dependsOn gating + list refresh button confirmed.
    • §6 SSO-only cold-start, import auto-policy default, phone sign-in surfaces — not yet driven.

    Automated pass; happy to drive the blocked items with proper seeding in a follow-up.

  2. os-zhuang commented on Jul 22, 2026

    @os-zhuang
    ContributorAuthor

    §4 Import wizard — ticked on test evidence, not a browser click-through

    This item stayed ⚠️ because the wizard starts at a native file picker, which the browser sweep can't drive. I went to write a Playwright e2e for it and found that would be redundant: all three clauses of this checklist line are already covered by targeted tests in objectui, and they assert the exact behaviours worded here.

    Checklist clause Test Asserts
    GBK/GB18030 zh-CN CSV without garbled headers packages/plugin-grid/src/importParsers.test.ts:115 Feeds real GBK bytes and asserts the exact decode [['名称 *','编号 *'],['测试岛2','TEST-001']] — mojibake would fail it. Siblings cover UTF-8-no-BOM, UTF-8 BOM strip, UTF-16LE BOM.
    A disabled Next explains itself (unmapped required hint) packages/plugin-grid/src/__tests__/importMissingRequiredHint.test.tsx:40,50 Hint reads Lifecycle (status) (the label (name) form) and import-next-btn is disabled; supplying the column clears the hint live, without a remount.
    Legacy per-row fallback shows a "compatibility fallback" notice packages/plugin-grid/src/__tests__/importLegacyReferenceGuard.test.tsx:82 Result carries degraded === true, import-degraded-notice renders, and the copy matches /compatibility fallback/i — i.e. the downgrade is not silent (#2639).

    Run just now on objectui@main:

    pnpm --filter @object-ui/plugin-grid exec vitest run \
      src/importParsers.test.ts \
      src/__tests__/importMissingRequiredHint.test.tsx \
      src/__tests__/importLegacyReferenceGuard.test.tsx
    → Test Files 3 passed (3) · Tests 35 passed (35)
    

    The decode path itself is real, not test-only: importParsers.ts:118-129 sniffs BOM → strict UTF-8 (whose validation rejects GBK multi-byte runs) → GB18030 fallback, with a documented degrade for small-ICU runtimes lacking the gb18030 decoder.

    What is still not exercised anywhere: the native <input type=file> picker hand-off itself. That's the flakiest, lowest-value slice to automate, and it is not what this line asserts — so I'm ticking the box on the evidence above rather than adding a redundant e2e. Happy to reopen if you'd rather have the full-stack e2e regardless.

  3. os-zhuang commented on Jul 22, 2026

    @os-zhuang
    ContributorAuthor

    §4 — browser-verified the two items shipped in #3393

    Both were made demonstrable by #3393 but I had only confirmed them programmatically. Drove them in the running showcase (os dev, fresh seed) and they hold up, so I'm ticking them.

    Action param real widgets — ran Action Param Gallery from the Field Zoo row menu and read the dialog's DOM. Every param renders its real widget, not a text input:

    Param Rendered as
    Title input[type=text]
    Rich note rich-text editor (格式: markdown), not a plain textarea
    Priority custom select (button), not a text input
    Effective date input[type=date]
    Accent color input[type=color] (swatch + #7C3AED)
    Reference # AutoNumber — read-only —, server-assigned
    Cover image input[type=file] accept="image/*"
    Attachments input[type=file] accept="application/pdf,image/*" + multiple

    So multiple and accept land as real DOM attributes, with distinct values per param. Caveat: maxSize is enforced in JS, not as an HTML attribute, so it isn't directly observable this way — I did not verify it.

    Related lists pagination — Northwind (26 contacts). The related list is genuinely server-paged, not client-sliced:

    GET /api/v1/data/showcase_contact?top=1&filter=["account","=","aKCTDUYTmJgn4xTU"]     ← count probe
    GET /api/v1/data/showcase_contact?top=5&filter=[...]                                   ← page 1
    GET /api/v1/data/showcase_contact?top=5&skip=5&filter=[...]                            ← after 下一页
    

    Page 1 rendered 5 of 26 rows; clicking 下一页 issued top=5&skip=5 and the grid switched to Prospect 04…08 with the pager reading 第 2 页,共 6 页. It never fetches all 26.

    Still not ticked, deliberately

    • ⚠️ Upload guard + autonumber (the line above) — the dialog does carry the copy "Confirm stays disabled while a file is still uploading (ADR-0059 upload guard)", and the AutoNumber half is confirmed above, but I did not prove the guard actually enforces: that needs a real upload caught mid-flight. Leaving it open rather than ticking on the strength of a label.
  4. os-zhuang commented on Jul 22, 2026

    @os-zhuang
    ContributorAuthor

    §1 evidence pass — two ticked, and two showcase defects found & fixed

    Driven in the running showcase (os dev, wiped DB, console rebuilt to the pinned objectui@cf2d56e32a11 so this isn't testing a stale bundle).

    Two things weren't merely un-ticked — they weren't running at all:

    • fix(showcase): stop passing a non-existent org column when seeding the phone demo user #3408 (merged) — the phone demo persona was never provisioned on any boot. The seed inserted sys_user with an organization_id key; that field does not exist (not in the 25-field object definition, not in the 26-column table — org membership is on sys_member), and it is not dropped on the way down: it reaches SQL as a real column and the insert dies with table sys_user has no column named organization_id. A best-effort try/catch reduced it to one ERROR line in the boot log. §6 "Phone sign-in surfaces" had nothing to show.
    • feat(showcase): actually exercise the per-group (会签) approval demo #3409 (merged) — the per_group (会签) demo had never opened a request. showcase_expense_signoff is the only flow authoring behavior: 'per_group', but the seed never launched it, and nobody held auditor (the position behind its finance group), so the group would have resolved empty anyway. Fixed by adding an Ada Auditor (demo) persona holding only auditor — deliberately a different user from the admin, since one user in both groups satisfies both tallies with a single decision — and launching it on EXP-2001 ($1,500), under the $5,000 committee threshold so the quorum demo doesn't also fire on the same record.

    The inbox now carries exactly one request per behavior: unanimous (INV-1001), quorum (EXP-DEMO), per_group (EXP-2001).

    Ticked

    Server-computed progress — the per_group drawer renders the tally server-side, per group, with the two distinct holders:

    Sign-off progress — 0 of 2 groups
    [finance 0/1]  [manager 0/1]
    等待以下审批人:  Dev Admin · Ada Auditor (demo)
    

    and the inbox row for the quorum request reads Committee Sign-off (2 of 3). That is the "per-group tick badges / N of M · group pending" assertion.

    Notification deep link — …/system/approvals?request=areq_b19241c6-… opens the request drawer directly (第 1 / 3 条), verified twice on fresh loads.

    Not ticked, with what's missing

    • Metadata-driven inbox actions — 5 of the 7 render from metadata: Approve Reject Reassign Send back Request info. remind and recall never appear, and I believe that is correct here rather than a bug: they are submitter-side actions, and every seeded request has an empty submitter (申请人 —) because the demo seed launches flows as SYS. Which means…
    • Viewer gating — …the "as the submitter viewing your own pending request" half is not demonstrable at all today: the 我发起的 tab is empty for every user. Stamping a real submitter on one seeded request would unlock both this and the remind/recall half above. Worth doing.
    • Reassign user picker — the dialog's New approver* is a picker control (选择..., helper "User to hand this step to"), not a free-text id box, which is the substance of the assertion — but I could not get the option list open to confirm it enumerates real sys_user rows, so I'm leaving it.
    • M-of-N quorum — config verified (behavior: quorum, minApprovals: 2, three position approvers). But the slate collapses onto one person: the admin holds manager+finance+legal, so pending_approvers = <admin>,<admin>,<admin> and "approves once the threshold is met, remaining tasks close" cannot be observed. There's a genuine tension here — admin holding every position is deliberate so a single logged-in user can action the whole inbox, but splitting the positions across three people would also stop the unanimous invoice demo from being completable solo. That's a showcase design call, so I've left it rather than changing it unilaterally.
    • Decision attachments — not reached this pass.

    Minor, low confidence

    The inbox footer advertises Enter 打开, but pressing j then Enter highlighted the row without opening the drawer (URL unchanged, no dialog). Focus may simply not have been where I assumed — flagging rather than filing.

  5. os-zhuang commented on Jul 22, 2026

    @os-zhuang
    ContributorAuthor

    §1 continued — 会签 and the full action set now proven end-to-end

    Third showcase defect found and fixed on the way: every seeded request had a null submitter (#3411). The demo launches flows as SYS and the approval node stamps the requester from context.userId, so 申请人 was — everywhere, the 我发起的 tab was empty for every user, and the two submitter-gated actions could never render. Fixed by routing userId deliberately: the invoice is submitted by the admin (so the logged-in user owns one request), the other two by Mei Phone (demo), who holds no position and is therefore never one of her own approvers.

    Ticked

    Per-group sign-off (会签) — the decisive run. Approved as Dev Admin, who holds the manager group only:

    before   status=pending   pending=[Dev Admin, Ada Auditor (demo)]   finance 0/1  manager 0/1
    after    status=pending   pending=[Ada Auditor (demo)]
    

    One group's approval satisfies that group and drops it from the slate, but does not finalize the request — it keeps waiting on finance. That is exactly "needs one approval from each group". The contrast is right there in the same session: the unanimous invoice, whose two slots both resolve to the admin, went straight to approved on a single decision.

    Metadata-driven inbox actions — all 7 render, and are gated by the viewer's relationship to the request rather than hand-wired. Same viewer (admin), two requests:

    Request Rendered actions
    submitted by Mei Approve Reject Reassign Send back Request info
    submitted by admin those + Send reminder + Recall

    Decision attachments — dialog confirmed, upload not exercised

    Approve opens a real param dialog: Comment + Attachments with a drag-and-drop input[type=file] carrying multiple. The comment round-trips (sys_approval_action.comment = "Approved by manager group…"). I did not attach an actual file, so the "uploads and shows as a chip" half is unproven — leaving it unticked.

    Correction to my previous comment: I suspected the drawer's action buttons were dead, because three coordinate-based clicks on Approve closed the drawer without issuing any request. That was my automation, not the product — a ref-targeted click opens the dialog and the decision commits normally. No bug; disregard that note.

    Quorum — now with a concrete symptom

    The collapse I flagged earlier is not cosmetic. showcase_committee_quorum declares minApprovals: 2 over three position approvers, but all three resolve to the admin, and the drawer renders:

    Approvals — 0 of 1
    等待以下审批人:  Dev Admin · Dev Admin · Dev Admin
    

    The runtime has clamped the threshold to the number of distinct approvers — sensible as a fail-safe (a 2-of-3 with one real person could otherwise never complete), but it means the demo advertises 2-of-3 and behaves as 1-of-1. M-of-N is still not demonstrable, and fixing it needs three distinct position holders — a showcase design call I'm still leaving to you, since splitting the positions also stops the unanimous invoice demo from being completable by one person.

    Viewer gating — half demonstrated

    The submitter-gated direction is proven above (recall/remind appear only on the viewer's own request). The other half — "as the submitter you do not see approver buttons" — remains unreachable, because the admin holds every approver position and is therefore an approver on all three seeded requests. It needs one request routed to a position the admin does not hold.

  6. os-zhuang commented on Jul 22, 2026

    @os-zhuang
    ContributorAuthor

    §2 Automation — run-step nesting ticked, roll-up filter half-proven

    Flow Runs step logs ✔ — ran showcase_batch_reminders (a loop flow) from the developer Flow Runs page with a 3-item tasks input. The engine tags each body step with its container, iteration and region:

    start                                            —
    loop_tasks                                       —
    send_reminder   parent=loop_tasks  iter=0  region=loop-body
    send_reminder   parent=loop_tasks  iter=1  region=loop-body
    send_reminder   parent=loop_tasks  iter=2  region=loop-body
    

    and the flow designer's Runs panel renders that as the execution tree, not a flat list:

    run run_f82c33cd-… · trigger manual
    SUCCESS start        START   0ms
    SUCCESS loop_tasks   LOOP    1ms
      └ ITERATION 1   SUCCESS send_remi…  SCRIPT  0ms
      └ ITERATION 2   SUCCESS send_remi…  SCRIPT  0ms
      └ ITERATION 3   SUCCESS send_remi…  SCRIPT  0ms
    

    Worth noting for anyone else checking this: the nesting lives in the flow designer's Runs panel (FlowRunsPanel, #1505). The developer Flow Runs page renders runDetail.steps flat — looking there alone would read as a miss.

    Roll-up summary filter — recompute proven, the editor half is not reachable

    The "parent recomputes" half is solid. showcase_expense_report declares filtered roll-ups in all three filter shapes, and I flipped one $780 child line from approved → rejected over REST:

    Field Filter shape before → after
    approved_amount equality status = 'approved' 825.0 → 45.0
    rejected_count equality COUNT 1 → 2
    total_amount none 917.0 → 917.0 (correctly unmoved)
    reimbursable_amount boolean billable 825.0 (correctly unmoved)
    over_limit_count operator amount $gte 500 1 (correctly unmoved)

    Every value matches an independent recomputation from the child rows, and only the filters the edit actually touched moved — which is the part a naive "recompute everything" implementation would get wrong.

    What I could not do is the other half — "set a child-row filter via the visual editor". The showcase ships as a read-only package (Studio shows the 只读 badge and "只读软件包 — 请切换或新建可写软件包后再编辑"), so no field on it can be edited in Studio at all. Exercising the visual filter editor needs a writable package with a summary field in it; that's a fixture gap, not a product finding, so I've left the item unticked rather than ticking it on the recompute half alone.

  7. os-zhuang commented on Jul 22, 2026

    @os-zhuang
    ContributorAuthor

    §3 blocked by a showcase data defect — filed as #3415

    While setting up the Report drill-through range check I found the showcase has 1 project and 1 task at runtime, against 5 and 10 in the built artifact.

    Root cause: showcase_project declares initialStates: ['planned'] with events: ['insert','update'] (the #3165 FSM entry gate), but the project seed creates projects as active / active / on_hold / planned / completed. Seeds run validation on purpose (SEED_OPTIONS — "Lifecycle HOOKS … validation still run"), so four are correctly rejected; the 9 tasks that master-detail onto those dead projects go with them, and showcase_project_membership lands 0 of 3.

    Nothing reports this. SeedLoader warns per rejection, but not one [SeedLoader] line reaches os dev output even at OS_LOG_LEVEL=debug LOG_LEVEL=debug DEBUG=*.

    Consequences for this checklist:

    Dataset-only widget authoring is also not checkable in this environment for an unrelated reason: the showcase ships as a read-only package (Studio shows 只读 and "只读软件包 — 请切换或新建可写软件包后再编辑"), so no widget inspector on it can be opened for editing. Same blocker as the roll-up filter editor above.

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions