Skip to content

QA run · surface:browser (61/61) · 316be321 · 2026-10-04 · 38 PASS / 8 PARTIAL / 15 FAIL / 0 BLOCKED / 0 NOT-RUN #21782

Description

@objectstack-fleet

17.7 pre-release verification, browser half: every runnable surface:browser item against origin/main as it stood when the browser run started, with the Console built from the bumped pin (#21710). 17.7 is not cut yet, and the packages still read 17.6.0. The non-browser half is #21720 (subject 251a7dd4). surface:mixed gets its own record against the same subject. Text only. Screenshots were consulted live as oracles and are not attached. The durable truth stays in docs/qa/platform-checklist/areas/.

Environment fingerprint

  • Framework (subject): objectstack-ai/objectstack 316be321 (fix(runtime)!: an app-authored body may not read the stored-metadata tables; it reaches them through the metadata API only (#21594) (#21660)). This is 25 commits past 251a7dd4 and includes the console pin bump chore(objectui): bump the console pin to 2e818d0b51ec (carries objectui#11466, #11574, #11578, #11581 and #11583) #21710. It ran in a dedicated detached worktree. Framework and console both built, and a smoke boot answered health 200 and /_console 200.
  • Console: built from objectui pin 2e818d0b51ec (.objectui-sha, chore(objectui): bump the console pin to 2e818d0b51ec (carries objectui#11466, #11574, #11578, #11581 and #11583) #21710). Every lane checked that the dist stamp equals the pin. Console source questions were read at that revision (git show 2e818d0b51ec:{path}). For the "predates 17.6.0" notes, the 17.6.0 references are framework 617f25f8a and objectui pin 31971ff1e.
  • Checklist: items, RUNNER.md and scripts/checklist-select.mjs come from the subject tree. The table gives every item's revision, and each one matches areas/*.json.
  • App / boots: examples/app-showcase booted with OS_PORT={p} objectstack dev --ui --seed-admin -p {p} -d file:/tmp/qa1770fe/{lane}/{item}.db. Each item had its own file DB, and lanes used disjoint port ranges inside 44101–45909 (the egress proxy port 41333 was excluded). The browser was Playwright on /opt/pw-browsers/chromium. Admins signed in through the console form, so both the bearer and the cookie halves existed. Members were minted with admin invite-member + sign-up/email or with admin/create-user + change-password. Identity was proven with GET /auth/get-session before each persona cell. Scratch fixtures were authored at runtime inside each item's own DB, or in a scratch copy of the showcase under /tmp.
  • Deviations, stated:
    • CRM package in the shared tree. Lane FE2 installed the CRM package (os package install, needed for the marketplace item) into the shared subject examples/app-showcase/.objectstack/installed-packages/ from 12:28 to 12:36Z. FE1's boots on 44105–44108 (account-app-entry, docs-portal-render, home-admin-cluster-links, url-overlay-contract) started in that window and registered crm_app next to the three stock apps. None of their clauses depends on the app list, so the clauses are unaffected. FE2 removed the package through the API, and lanes were ordered from then on to install only into scratch copies.
    • One shared DB in FE2. Seven FE2 items ran on one boot with one shared main.db: keyboard, theme, installability, palette, ai-gating, api-console, and marketplace boot A. As a result, the api-console tree also listed Data: crm_* groups.
    • Port moved in FE4. One FE4 item moved from 44408 to 44409 because the session process held 44408 as an outbound ephemeral port.
  • Execution: this selector was run by six parallel runner subagents (FE1–FE6). Independent verifiers VF1–VF4 checked the results under RUNNER rule 7, and VF3 and VF4 re-derived every fail in this selector. Everything ran in Claude Code session session_018zT8d8NpiQ1ExhuNd5TxY6. The lanes ran on 2026-10-04 from 12:06Z, and verification finished on 2026-10-05. After an earlier overload of the box, concurrency was capped at three lanes (a maintainer order), with verifiers counted as lanes. Tier-1 pins that live in this repository were run and are cited in the table. Items whose automated.ref lives only in objectui were driven by hand as manual browser runs (RUNNER environment facts, option a).

Scope

node scripts/checklist-select.mjs surface:browser --json returned 61 runnable items. One item is hidden as blocked and was not run: approvals.quorum-m-of-n. The selector returned no planned items. All 61 items received a verdict.

item rev verdict evidence (server truth / browser)
access-security.share-link-landing-page 1 PASS anonymous context: redacted fields absent from the record and named in the notice; password, revoked / expired (410), invalid (404) and signed-in legs render their own states; no shell, form or session in the anonymous context (hand-driven, the pin is objectui-only)
ai.console-ai-surface-gating 1 FAIL A4 stale clause (SystemHubPage retired, objectui#10507); A6 known expected-fail K2 (empty-queue state under the 501 alert, 5 s poll never backs off); A1–A3, A5 pass, entitled side blocked(fixture) as the clause prescribes
api-backend.api-console-discovery-execute 1 PASS groups follow /discovery; List showcase_task 200 equals a direct GET; 404 RECORD_NOT_FOUND and 400 VALIDATION_FAILED shown verbatim from the wire
approvals.per-group-signoff 6 PASS per_group finance / manager tallies match the API at every stage; the run stays paused until the last group decides; a foreign actorId is refused 403
approvals.inbox-metadata-actions 3 FAIL A2: Recall is also offered to an override actor (admin) on another submitter's request, by design (#3424 / #12716) — stale clause; a non-override approver sees neither; A1, A3–A5 pass
approvals.viewer-gating-submitter-side 6 PASS submitter sees only Send reminder / Recall; can_act=false; forged approve / reject 403 and the reads before and after are byte-identical
approvals.notification-deep-link 4 PASS reminder action_url opens the drawer on 2 cold loads via both routes; an unknown id answers 404 with the named toast
approvals.record-page-decisions 1 PASS Approve / Reject lead the header; one dialog and exactly one POST; lockRecord gates inline edit; reassignment moves the buttons
approvals.account-app-entry 2 PASS bundle (stamp = pin) carries the approvals:inbox contribution; drawer approve round-trips; deep link opens; zh-CN labels hold (objectui#11326 fixed)
approvals.setup-nav-entry 1 PASS served group_approvals order equals the sidebar; lands on the inbox component; zh-CN labels; nav-contribution pin 1/1
approvals.pending-count-surfaces 1 PASS badge "9+"; popover, Home card, My Pending tab and API agree (6 → 5 after one decision)
approvals.inbox-keyboard-flow 1 PASS j / k / arrows clamp; r / a open one dialog and send one POST on confirm; inert in search, drawer, alertdialog and on dynamic-approval rows
attachments-storage.inline-grid-receipt-cells 3 PASS one Receipt file cell; presigned → PUT → complete; the atomic batch stores the bare id; sys_file committed with ref_object / ref_id / ref_field
automation.screen-flow-roundtrip 3 PASS trigger → paused at collect; screen dialog; resume completes and the task reads the new assignee; empty inputs 400, Cancel sends nothing
automation.setup-packaged-automation-board 2 PASS 30 rows = 30 packaged flows; toggle persists to the activation ledger; 409 / 403 sentences verbatim; setup-packaged-automation-nav pin 4/4
dashboards.chart-first-paint 2 PASS cold load draws bars and axes on Chart Gallery and Delivery Operations; 5 bars = 5 statuses; hero tiles equal the data API
dashboards.drill-through-range 2 PASS month, status and matrix drills each send their own bounds; drawer counts equal the aggregate
dashboards.chart-type-matrix 4 PASS 20 variants judged per widget, counts match the API; coverage 13/13 · dashboard-compareto 17/17; A8 comparison renders (its "vs yesterday" label is a defect outside the clauses, extracted)
dashboards.global-filters-rescope 2 FAIL A6: the named at-risk tile opts out of task_status by design (#7568) — stale clause; the composing tile kpi_awaiting_review shows the API intersection; A1–A5, A7–A9 pass
i18n.notification-localized-and-clears 3 PASS interpolated title in zh chrome; deep link renders zh; read clears server-side and survives a hard reload; EN control
i18n.studio-follows-app-locale 3 FAIL A3: under the language-only zh code dates render in the browser's language — held (verifier unconfirmed, re-run owed); A1, A2, A4, A5 pass
i18n.surface-matrix 4 FAIL A1 relative-dates variant (the same held finding); A2–A5, A7–A11 pass; A6 toast half pass, confirm half blocked(fixture: no zh confirmText)
identity-auth.sso-enforced-first-paint 2 PASS enforced boot never paints the password form (80 ms sampling, 2 loads); 20 s watchdog re-enables the button; unenforced restart shows the form
identity-auth.phone-signin-surfaces 2 PARTIAL A2 / A3 blocked(fixture: features.phoneNumber false, no runtime lever); A1, A4 pass
integration-system.flow-connector-picker 3 PASS picker offers exactly the 5 served connectors with origin tags; MCP action input rendered from inputSchema
platform-core.console-login 4 PASS sign-in, reload, server sign-out → 401 on bearer and cookie, login redirect, re-login to the same route; wrong password sets nothing
platform-core.nav-surfaces-render 5 PASS showcase-smoke 49/49; 49 nav leaves = SURFACES both ways; unknown object renders a named not-found in the live shell
platform-core.builtin-apps-nav-render 4 PASS Setup 45/45 and Account 8/8 walked; member refused Setup in the UI and the API; marketplace catalog content blocked(environment: egress)
platform-core.shell-nav-personalization 1 FAIL A3: no drag-reorder on any grouped navigation (every stock app) — product defect; A1, A2, A4–A6 pass
platform-core.marketplace-console-honesty 1 FAIL A3: offline Details dead-ends on the Disabled card, reseed / purge unreachable — product defect; A4 member gets the Disabled card by design (objectui#5557) — stale clause; A1, A2, A5 pass
platform-core.docs-portal-render 1 FAIL A5: no /home sidebar Documentation entry for any persona (the Help menu is the entry) — assertion defect; the member tree mirror holds; A1–A4, A6 pass
platform-core.url-overlay-contract 1 PASS drawer / tab / form overlays push and pop history as specified; deep tabs; formLink pre-link; breadcrumbs; object-mismatch refusal
platform-core.keyboard-shortcut-surface 1 FAIL A3 / A4 known expected-fail (K1a bare B, K1b five dead accelerators), still present; A5 blocked(fixture) as prescribed; A1, A2 pass
platform-core.home-admin-cluster-links 1 FAIL A2 / A4 stale clause (SystemHubPage retired, objectui#10507); A5 assertion defect (no /home nav); A1, A3 pass by URL
platform-core.theme-mode-persistence 1 PASS dark / light / system persist (key object-ui-theme); auto resolves per emulation; dark screen coherent
platform-core.console-installability-indicators 1 PARTIAL A3 error leg not-run (the connection chip cannot be provoked into its error state); A1, A2, A4 pass
records-forms.crud-roundtrip 8 PARTIAL A7 readonly half blocked(fixture: no stock readonly column is settable over HTTP); create / edit / delete diffs, History, CJK round-trip and the member gate pass
records-forms.list-view-capabilities 1 PASS showcase-search 5/5; 11 variants hand-driven; export through a runtime allowExport grant (export is opt-in)
records-forms.view-type-gallery 1 FAIL A2: kanban per-column summarizeField totals never render — product defect; smoke 49/49; every other variant passes
records-forms.form-view-gallery 1 FAIL A1 drawer variant renders as a centred modal by design (RecordFormPage fallback, #1890 / ADR-0050) — assertion defect; modal blocked(fixture) as prescribed; A2–A5 pass
records-forms.conditional-rules-grid 2 FAIL A5: an untouched sibling re-emits position only when siblings share a stored position (fixture-created) — invalid pairing; holds on stock INV-1001; A1–A4 pass
records-forms.master-detail-atomic-save 3 PASS one atomic batch with $ref; server roll-up equals the line sum; an invalid child aborts the whole batch
records-forms.related-list-server-pagination 4 PASS server paging, 26/26 distinct; relatedList config honoured; read gate both sides (403 / 200)
records-forms.upload-guard-blocks-confirm 2 PASS Confirm disabled mid-flight; dispatch carries the file id; maxSize refused before the wire
records-forms.import-wizard-encoding-and-hints 4 PARTIAL A3 blocked(dependency: the legacy per-row path is absent on a live server, pin objectui-only); GBK decode, required hint, server rows pass
records-forms.action-location-matrix 6 FAIL A1: the fixture hosts no record_header / record_more / record_related surface for showcase_task — invalid pairing; A3 url / api legs blocked(fixture, same cause); A2, A4, A5 pass
records-forms.gantt-interactions 2 PARTIAL A2 / A3 blocked(fixture: no dependenciesField; lockField is not a spec key); drag persists, a 403 veto rolls back
records-forms.kanban-drag-persistence 1 PASS drop → PATCH, survives reload; an invalid transition 400 snaps back with a toast
records-forms.form-dirty-guard 2 PARTIAL A3 not-run (pin discardGuard.test.tsx is objectui-only); A1, A2 pass hand-driven
records-forms.adhoc-filter-sort-builder 2 PASS toolbar filter ANDs with the view filter (2 rows = API); restored per user; uf_ params deep-link
records-forms.calendar-interactions 2 PASS drag PATCH persists; read-only 403 snaps back; month / week / day match the API; A4 on a scratch view (stock quick-create cannot satisfy the required project)
records-forms.record-discussion-mentions 3 PASS comments-permission-matrix 10/10; a mention notifies only the mentioned user; FEEDS_DISABLED 403 on create and re-thread
records-forms.grid-personalization 2 FAIL A2: row height lost on reload (console PUT shape; the server drops the misplaced key) — product defect; A1 resize pass, reorder / pin blocked(fixture); A3–A5 pass
records-forms.saved-view-management 1 PASS draft + publish create; rename / default / pin / delete persist; member sees no controls and is refused 403 server-side
records-forms.bulk-select-all-matching 2 PARTIAL A5 not-run (the 5000 cap is unreachable with 26-row sets); select-all-matching fan-out and dispatch pass
records-forms.lookup-picker-create-new 2 PASS create-new from the picker; parent carries the child id; debounced server search; no create on the sys_user lookup
records-forms.record-edit-undo 2 PASS undo is a real PATCH via toast, Ctrl+Z and Ctrl+Shift+Z; new audit rows; A4 observe-and-flag: undo overwrote a concurrent edit with no conflict signal, recorded as the clause asks
records-forms.script-action-hook-refusal-toast 1 PASS 400 hook sentence in exactly one error toast; no state change; showcase + runtime refusal pins 5/5 + 5/5
search.command-palette-navigation 1 PARTIAL A5 blocked(fixture: no nav item with a visibility predicate); A1–A4, A6 pass
studio-authoring.packaged-automation-studio-lock 1 PASS read-only package: no New, inert canvas and switch, forged PUT 403 NOT_OVERRIDABLE / ITEM_LOCKED, flow byte-identical
studio-authoring.packaged-display-class-direct-edit 1 PASS view and dashboard overlays edit and go live without restart, reset to a byte-identical baseline; flows stay locked

Totals: 38 PASS / 8 PARTIAL / 15 FAIL / 0 BLOCKED / 0 NOT-RUN. The 15 fails break down as follows:

  • 4 carry a verified product defect, all in the objectui console and all predating 17.6.0. One of the four, marketplace-console-honesty, also carries a stale clause.
  • 2 are held: the runner observed a fail and reproduced it, but the verifier could not confirm the mechanism, so no card is filed and a live re-run is owed.
  • 1 is a known expected-fail probe only (keyboard-shortcut-surface, K1a / K1b).
  • 8 fail on checklist clauses only. ai-gating's A6 there is also the known expected-fail K2.

One more defect lies outside the clauses (dashboards.chart-type-matrix, which passes) and is extracted with the four.

Every fail was re-derived by an independent verifier (VF3 or VF4). Where a verifier changed a disposition, the verifier's is recorded:

  • VF4 upgraded shell-nav-personalization A3 from assertion-defect to product defect.
  • VF3 refuted form-view-gallery A1 as a product defect (now assertion defect) and conditional-rules-grid A5 (now invalid pairing).
  • VF4 refuted action-location-matrix A1 (now invalid pairing).
  • VF3 ruled that chart-type-matrix A8's clause holds and the mislabel lies outside it.
  • VF4 recorded inbox-metadata-actions A2 and global-filters-rescope A6 as stale clauses.

One item verdict is derived differently from its lane's summary: form-dirty-guard is PARTIAL rather than pass, because its A3 pin is objectui-only and was not run (RUNNER per-item derivation).

Fails — reproduction rules and dispositions

Product defects

platform-core.shell-nav-personalization A3 {card-1}: drag-reorder is never offered on grouped navigation, and every stock app's navigation is grouped.

  • Server truth: the served GET /api/v1/meta/app?id=showcase_app navigation is grouped (8 groups), and so are the Setup and Account navigations.
  • Browser:
    1. Sign in as admin.
    2. Open /_console/apps/showcase_app/showcase_task.
    3. Hover and try to drag any sidebar entry.
  • Expected: a grip, and an order that is restored after reload (useNavOrder, localStorage objectui-nav-order-showcase_app).
  • Actual: 0 [aria-label="Drag to reorder"], no sortable, and the localStorage key is never written. Seen on two loads.
  • Root cause (VF4):
    • objectui NavigationRenderer.tsx:1590 computes hasGroups.
    • The DndContext / SortableNavigationItem path exists only in the !hasGroups arm (:1614-1631). The grouped arm (:1650 ff.) renders plain items.
    • UnifiedSidebar.tsx:583 passes enableReorder={!isMobile} unconditionally.
    • useNavOrder persists only __root__.
  • Predates 17.6.0: identical at objectui 31971ff1e.
  • Verifier VF4: CONFIRMED, P3. If the maintainers rule that reorder is meant for flat navigation only, the clause becomes an assertion defect; VF4's corrected wording is with the re-point.

platform-core.marketplace-console-honesty A3 {card-2}: on an offline boot, the installed package's Details page is a dead end, so reseed and purge cannot be reached from the console.

  • Server truth:
    • Boot with OS_CLOUD_URL=off. /runtime/config reports marketplace:false.
    • os package install examples/app-crm/dist/objectstack.json -r http://localhost:{p}. Installed Apps then lists com.example.crm v4.0.0.
  • Browser:
    1. Go to Setup → Installed Apps. The row offers Refresh / Details / Uninstall.
    2. Click Details. It opens /system/marketplace/com.example.crm.
  • Expected: reseed / purge affordances that issue POST /api/v1/marketplace/install-local/com.example.crm/{reseed,purge}-sample-data.
  • Actual: the page renders "App Marketplace is turned off" and makes 0 install-local wire calls. Seen twice.
  • Root cause (VF4):
    • objectui InstalledListWidget.tsx:155 links Details to /system/marketplace/:packageId.
    • MarketplacePackagePage.tsx:568 returns the MarketplaceDisabled card before the page reaches its local reseed/purge menu (:752).
  • Predates 17.6.0: identical at objectui 31971ff1e.
  • Verifier VF4: CONFIRMED, P3.
  • Related: the endpoint behind the purge affordance has its own defect, marketplace: install-local purge-sample-data always answers 500 DRIVER_UNAVAILABLE (looks up a bare "driver" service nothing registers) — and seed records carry no id to purge by #21728 (purge answers 500), which is scored by the api lane.

records-forms.view-type-gallery A2 {card-3}: the kanban board never renders its summarizeField per-column totals.

  • Server truth:
    • The fixture board showcase_task.board declares {groupByField:'status', summarizeField:'estimate_hours'} (examples/app-showcase/src/ui/views/task.view.ts:262-275).
    • Summing estimate_hours per status over GET /api/v1/data/showcase_task gives backlog 30 / todo 36 / in_progress 100 / in_review 54 / done 24.
  • Browser: as admin, open /_console/apps/com.example.showcase/showcase_task/view/showcase_task.board.
  • Expected: those five totals in the column headers.
  • Actual: the headers show only the count badge ("BACKLOG 2" … "DONE 2"), and the board's data request selects no estimate_hours. Seen twice by the runner and twice by the verifier, all on fresh loads.
  • Root cause (VF3):
    • Nothing in objectui packages/plugin-kanban/src reads summarizeField (column header around KanbanImpl.tsx:1066-1100).
    • The only consumers, plugin-list/src/ListView.tsx:2002 and :2517, add the field to the projection.
    • The spec declares the key at packages/spec/src/ui/view.zod.ts:1789 with no liveness verdict, making it an ADR-0049 declared-but-unenforced key.
  • Predates 17.6.0: no reader at objectui 31971ff1e either.
  • Verifier VF3: CONFIRMED, P3.

records-forms.grid-personalization A2 {card-4}: the row height (density) is lost on reload.

  • Browser:
    1. As admin, open /_console/apps/com.example.showcase/showcase_task. The runner also used …/view/showcase_task.grid.
    2. Click "Density: Compact (click to cycle)". It changes to "Comfortable" and rows go from 41 px to 45 px.
  • Server truth:
    • The console sends PUT /api/v1/meta/view/showcase_task.default and gets 200 "Saved customization overlay".
    • The body is the whole served item (config{…}, _provenance, scope, _diagnostics) with a flat top-level "rowHeight":"medium".
    • Afterwards, GET /api/v1/meta/view/showcase_task.default carries no rowHeight, either at top level or in config.
    • A reload in a fresh context shows "Density: Compact" again.
  • Expected: the chosen row height survives reload.
  • Control: the same item PUT with config.rowHeight:"tall" reads back "rowHeight":"tall".
  • Root cause (VF3):
    • objectui packages/app-shell/src/views/ObjectView.tsx:1181 buildPersistedViewBody spreads the patch at the envelope top level instead of into config, for views the switcher classes as saved views.
    • The framework save door stores only the declared keys of a view body (ADR-0005 appendix (c)), so it drops the misplaced key while still answering 200. Dropping it is by design, so the fix belongs to the client.
    • VF3 adds a design note: a 200 that silently discards an undeclared envelope key is a silent-loss shape, and a save diagnostic would have surfaced it.
    • sort and hiddenFields patches probably take the same path (not driven).
  • Predates 17.6.0: identical at objectui 31971ff1e.
  • Verifier VF3: CONFIRMED, P2.

dashboards.chart-type-matrix, outside the item's clauses {card-5}: a previousPeriod comparison on the dataset path is labelled "vs yesterday". Clause A8 passes because the comparison renders; only the label is wrong.

  • Server truth:
    1. As admin, PUT /api/v1/meta/dashboard/qa_compareto_probe?mode=draft with:
      • dateRange:{field:'created_at', defaultRange:'last_30_days'};
      • a metric widget on dataset showcase_task_metrics, values:['task_count'], compareTo:{kind:'previousPeriod'}.
    2. POST …/publish.
    3. The dataset query shifts the whole 30-day window (timeDimensions dateRange [2026-09-04, 2026-10-04], task_count__compare: 1).
  • Browser: open /_console/apps/showcase_app/dashboard/qa_compareto_probe.
  • Expected: "vs previous period".
  • Actual: the metric shows "9 ↑800%" with the label "vs yesterday", and the line legend reads "Tasks · vs yesterday".
  • Root cause (VF3):
    • objectui packages/core/src/utils/compare-to.ts:124-136 compareToTrendLabelKey derives the label by regex-sniffing the raw filter for macro tokens (today → vsYesterday).
    • plugin-dashboard/src/DatasetWidget.tsx:1097 reuses it on the ADR-0021 dataset path, where the executor shifts the dimension window (service-analytics dataset-executor.ts:810-819 shiftRange).
    • The heuristic is only right on the inline path.
  • Predates 17.6.0: the same code is at objectui 31971ff1e.
  • Verifier VF3: CONFIRMED by code (not live-driven). P3.
  • Evidence strength: the runner observed it once.

Held: observed, not verified, not extracted

i18n.surface-matrix A1 (relative-dates variant) and i18n.studio-follows-app-locale A3: dates render in the browser's language when the app locale code is the language-only zh.

  • Server truth: GET /api/v1/i18n/translations/zh-CN is the expectation set.
  • Browser:
    1. Fresh boot. Create a Chromium context with locale:'en-US'.
    2. Set localStorage['objectui-locale']='zh' before the first load. This is the code i18n.notification-localized-and-clears tells runners to write.
    3. Sign in as admin and open /_console/apps/showcase_app/showcase_task.
  • Expected: date cells in zh, like the rest of the page.
  • Actual:
    • Headers are zh, but due-date cells read "Sep 16", "Oct 24", "In 3 days" next to "逾期 6 天".
    • The record page reads "截止日期 Sep 16" next to "创建于 20天前".
    • The bell's activity tab reads "12 seconds ago".
  • Discriminators:
    • The same zh session in a zh-CN browser renders 9月16日 / 3天后.
    • The code zh-CN (what the LocaleSwitcher writes) renders zh in an en-US browser.
    • html lang is zh in the failing case and zh-CN in the passing one.
    • Flipping the tenant locale has no effect (A/B on the same boot).
  • Reproduction count: 2 fresh boots × 3 loads.
  • Studio-specific note: Studio's own timestamps follow the app locale under zh-CN. The studio clause fails only through the shared formatter.
  • Verifier VF3: UNCONFIRMED.
    • The code contradicts the stated mechanism. useDisplayLocale passes zh to Intl verbatim, and the date-fns resolution maps it to zh-CN.
    • VF3 did not render live.
    • VF3 found a different possible cause: an unconfigured tenant's en-US default from GET /api/v1/auth/me/localization outranks the UI language. A tenant locale of zh itself is refused by settings.
  • Disposition: held. The observation stands, the mechanism is disputed, and no card is filed. A live re-run of both items is owed (RUNNER rule 7). If the observation stands, the defect belongs to the objectui console. It predates 17.6.0 by code.

Checklist clauses (no product defect)

item · clause disposition what holds instead source
platform-core.docs-portal-render A5 assertion defect /home has no sidebar for any persona. Every persona reaches Documentation through the top-bar Help menu → "All documentation" → /docs. The member's rendered tree equals the member API subset, and every entry opens without 401/403 (that half passes) objectui HomeLayout.tsx:1-6 "deliberately omits the sidebar"; AppHeader.tsx:758-793; pre-17.6.0
platform-core.home-admin-cluster-links A2 / A4 stale clause the System hub card wall and its count badges were deleted. /apps/:app/system redirects in one hop to /system/settings, and every Settings-hub entry resolves objectui 9eea12a2b (objectui#10507, fixes objectui#3743), landed before 17.6.0
platform-core.home-admin-cluster-links A5 assertion defect no persona gets a /home nav. A member's shell offers no Administration entry anywhere, and the server refusal is proven by builtin-apps-nav-render same root as docs-portal-render A5
platform-core.marketplace-console-honesty A4 stale clause on a features.marketplace=false boot every viewer, member included, gets the MarketplaceDisabled card. On the enabled boot a member gets access-denied (holds) objectui d524bde29 (objectui#5557 via #5582), 2573ff434; before 17.6.0
ai.console-ai-surface-gating A4 stale clause no settings hub, nav or Home surface advertises "AI Approvals" on an agent-less boot. The bare /system/ai-approvals route is scored by A6 objectui 9eea12a2b (#10507)
records-forms.form-view-gallery A1 (drawer variant) assertion defect the record form page falls back from drawer/modal to simple on purpose: they are presentation modes, not layouts. A JSX ObjectForm formType="drawer" (Task Desk) renders a real side panel. Named formViews.* are reachable from no console door objectui RecordFormPage.tsx:281-289 (#1890), ADR-0050 (Proposed)
records-forms.conditional-rules-grid A5 invalid pairing on stock INV-1001 (positions 0, 1), editing one line sends only that line. Untouched siblings are byte-identical (VF3 live). The position re-emit happens only when sibling lines share a stored position, and a second line added through the API defaults to position 0, so the collision comes from the fixture objectui GridField.tsx:703-707 + masterDetailTx.ts:180-195; INV-1002 ships a single line
records-forms.action-location-matrix A1 invalid pairing objectui#11270 is in the pin. The showcase hosts none of record_header / record_more / record_related for showcase_task: the task page is kind:'full' with no record-header node (objectui#7298 ruling: "a page is what its author composes"), and the project page replaces the related strip with line items fixture task-detail.page.ts, project-detail.page.ts; pre-17.6.0
approvals.inbox-metadata-actions A2 stale clause Recall is offered on the viewer's own request and, for an override actor (platform/tenant admin), on any pending request. A non-admin approver (control persona Ada) sees neither Recall nor Send reminder on another submitter's request sys-approval-request.object.ts:568-591 (#3424 lever, button #12716); clause rev 3 predates it
dashboards.global-filters-rescope A6 stale clause kpi_at_risk opts out of task_status (filterBindings:{task_status:false}) by design. The tile that composes (kpi_awaiting_review, status=in_review) shows the API intersection: 0 under In Progress, 2 under In Review ops-dashboard.dashboard.ts:87 (#7568), pinned by dashboard-filter-vocabulary.test.ts:230

Known expected-fail (not re-filed)

  • platform-core.keyboard-shortcut-surface A3 / A4: defects K1a and K1b, owned by the 2026-08-30 sweep's follow-ups. Both are still present at the pin.
    • A3 (K1a): bare B leaves the sidebar expanded while the dialog advertises "B". Only ⌘/Ctrl+B is handled.
    • A4 (K1b): each advertised ⌘/, Ctrl+/, N, R, Ctrl/Meta+E and Ctrl/Meta+D was probed on /_console/apps/showcase_app/showcase_task with focus on the body. None changed the URL, focus, dialogs, the root class or data. Seen on two fresh loads.
    • Verifier VF4: confirmed. KeyboardShortcutsDialog.tsx:49 lists bare B, sidebar.tsx:42,122 requires the modifier, and no handler exists for the five advertised accelerators.
  • ai.console-ai-surface-gating A6: defect K2, from the same follow-ups row.
    • Repro: sign in as admin through the form, open /_console/apps/setup/system/ai-approvals and watch for 15 s.
    • Observed: "No actions waiting" renders under the 501 error alert, and pending-actions is re-polled at about +0, +4.9 and +10 s with no backoff. Seen on two runs.
    • Verifier VF4: confirmed at the pin (AiPendingActionsInbox.tsx:327/:373, usePendingActions.ts:294-295).

Partial-coverage gaps (named, not dropped)

  • records-forms.crud-roundtrip A7 readonly half: blocked(fixture). No stock readonly column can be set over HTTP; the server answers x-objectstack-dropped-fields: lead_score;reason=readonly.
  • platform-core.console-installability-indicators A3 error leg: not-run. The connection chip tracks only the initial discovery (see candidates).
  • search.command-palette-navigation A5: blocked(fixture). No stock nav item carries a visibility predicate.
  • identity-auth.phone-signin-surfaces A2 / A3: blocked(fixture). features.phoneNumber is false, and plugins.phoneNumber is code config with no runtime setting.
  • records-forms.import-wizard-encoding-and-hints A3: blocked(dependency). The legacy per-row path exists only when the data source lacks importRecords, the live server always has it, and the pin is objectui-only.
  • records-forms.gantt-interactions A2 / A3: blocked(fixture). The stock view has no dependenciesField, and lockField is not a GanttConfig key.
  • records-forms.form-dirty-guard A3: not-run. The discardGuard.test.tsx pin exists only in objectui.
  • records-forms.bulk-select-all-matching A5: not-run. Match sets of 26 and 10 cannot reach the 5000 cap.
  • Blocked legs inside judged items:
    • records-forms.grid-personalization A1 reorder / pin: reorderableColumns is off, and there is no runtime pin control.
    • records-forms.action-location-matrix A3 url / api dispatch: the fixture hosts no ⋯ surface.
    • i18n.surface-matrix A6 confirm half: no zh confirmText.
    • platform-core.keyboard-shortcut-surface A5 and the ai.console-ai-surface-gating A2 entitled side: blocked(fixture) as their clauses prescribe.
    • Marketplace catalog content (builtin-apps-nav-render, marketplace-console-honesty boot A): blocked(environment), because egress to the catalog is denied.

Fixed since the last run

  • objectui#11326 (the account-app approvals entry stayed English under zh-CN) no longer reproduces. approvals.account-app-entry A7 holds on two loads (待我审批 / 我发起的 / 全部).

Candidates — not verified, not extracted

Each of these was seen by a runner outside the clauses. They are low severity or possibly by design, and they are listed so they are not lost:

  • GET /api/v1/data/{object}?top=0 answers total:0 while top=1 gives the real total, and the console sends top=0 as its record-count probe. Two lanes saw it (FE3, FE4).
  • A malformed JSON body on POST /api/v1/data/showcase_task is treated as an empty body: the answer is 400 "Title is required; Project is required", not a parse error.
  • CSV export renders booleans as hard-coded 是 / 否 regardless of locale, under English headers.
  • On New, select options marked default: true are not pre-selected (invoice status / region), so "Status is required" blocks create. Separately, an edit save wrote region:"amer" into a row whose region was null.
  • A wizard default form renders flat, with no step chrome, in the New modal. Only the /new page route honours it.
  • The action-param dialog is taller than the viewport with no scroll (top at y=-198), so Confirm cannot be reached at 1440×900 or 1600×1200.
  • The Log Time form dispatch leaves the app shell, heads the page with the raw target "showcase_task.form", and toasts "Action completed successfully" before any submit.
  • Line amounts are computed in floating point and never rounded (3598.7999999999997).
  • Related-list pages and inline-grid child fetches carry no sort, so their page order relies on natural order.
  • The Field Zoo row tint does not paint the frozen #/Name columns.
  • Record History shows a currency change unformatted ("— → 4250000"), while the grid shows "$4,250,000.00".
  • After the submitter has approved as an approver, the approvals drawer still says "only the assigned approvers can approve or reject".
  • The approvals drawer opened on an unknown ?request= id leaves an empty "Approval Request" sheet behind the correct toast.
  • showcase_invoice shows two fields both labelled "Owner" (the system owner_id and its own owner).
  • The record feed shows an admin's PATCH as authored by "System". The inlineEdit grid renders two "Actions" header columns.
  • Deleting the view set as default leaves the object with no default view.
  • The home-navigation block in UnifiedSidebar (Home, Documentation, the Administration cluster) has no rendering surface. VF4 also notes this and suggests an item revision rather than a defect.
  • A cross-reference inside the app-scoped docs reader leaves the app container for /docs/….
  • Every console page logs 404 GET /api/v1/usage/storage.
  • Selecting a theme command in the palette (Dark / Light / System) leaves the palette open. Navigation commands close it.
  • The connection chip shows nothing after a backend loss mid-session. A single aborted /api/v1/discovery at load strands the splash at "Preparing workspace" for 45 s or more, with no retry and no error.
  • The PWA manifest icon type is hard-coded image/svg+xml even when the favicon is a PNG.
  • On SSO-enforced boots, LoginForm briefly renders "Sign up" during the config-loading frame. An unenforced invite_only boot shows "Don't have an account? Sign up", which leads to the 403.
  • Recents use humanized names ("Showcase Hours By Status") instead of nav labels.
  • Every navigation PATCHes sys_user_preference (recents), which floods the bell activity feed with "更新了 用户偏好".
  • The sys_user list "updated" cell renders date and time with no separator (10/4/20263:22 pm).
  • On the read-only Studio Automations pillar, a mouse click on a flow node never opens the inspector, while keyboard Enter does.
  • The connector picker keeps the previous connector's action and input map after a connector switch.
  • ResourceHistoryPage hard-codes English ("Back to item", "by …") on a zh session.
  • The view designer says "This view has no object binding yet" on showcase_task, while its Object field reads "Task".
  • The first click of a custom date range commits a one-day query before the second click.
  • For dates, an unconfigured tenant's en-US default (/auth/me/localization) may outrank the UI language. This is VF3's alternative reading of the held zh-date finding and needs a live render.
  • The spec still declares FormView.type drawer / modal and drawerSide with no live renderer path. This is ADR-0049 debt pending ADR-0050 (VF3).
  • records-forms.record-edit-undo A4, observe-and-flag: an undo after a concurrent edit sends a bare PATCH with no If-Match and silently overwrites the other session's value. This is recorded as the clause asks, not as a fail.
  • Three authorization-class observations, withheld pending maintainer (RUNNER rule 2).

Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 5, 2026

    @objectstack-fleet
    ContributorAuthor

    Close-out

    Every fail has a disposition re-derived by an independent verifier (RUNNER rule 7):

    Extracted: objectstack-ai/objectui#11626 · platform-core.shell-nav-personalization · acceptance[2]
    Extracted: objectstack-ai/objectui#11627 · platform-core.marketplace-console-honesty · acceptance[2]
    Extracted: objectstack-ai/objectui#11629 · records-forms.view-type-gallery · acceptance[1]
    Extracted: objectstack-ai/objectui#11625 · records-forms.grid-personalization · acceptance[1]
    Extracted: objectstack-ai/objectui#11632 · dashboards.chart-type-matrix · outside the item's clauses
    Parked-on: #21797 · platform-core.docs-portal-render · acceptance[4]
    Parked-on: #21797 · platform-core.home-admin-cluster-links · acceptance[1]
    Parked-on: #21797 · platform-core.home-admin-cluster-links · acceptance[3]
    Parked-on: #21797 · platform-core.home-admin-cluster-links · acceptance[4]
    Parked-on: #21797 · platform-core.marketplace-console-honesty · acceptance[3]
    Parked-on: #21797 · ai.console-ai-surface-gating · acceptance[3]
    Parked-on: #21797 · records-forms.form-view-gallery · acceptance[0]
    Parked-on: #21797 · records-forms.conditional-rules-grid · acceptance[4]
    Parked-on: #21797 · records-forms.action-location-matrix · acceptance[0]
    Parked-on: #21797 · approvals.inbox-metadata-actions · acceptance[1]
    Parked-on: #21797 · dashboards.global-filters-rescope · acceptance[5]
    

    Held, not extracted, and re-run owed: i18n.surface-matrix acceptance[0] (relative-dates variant) and i18n.studio-follows-app-locale acceptance[2]. The verifier left both UNCONFIRMED, so neither gets a card until a live re-run settles the mechanism.

    Known expected-fail, not re-filed: platform-core.keyboard-shortcut-surface acceptance[2] / acceptance[3] (K1a / K1b) and ai.console-ai-surface-gating acceptance[5] (K2). The 2026-08-30 sweep's follow-ups own them.

    Product defects

    card from severity (verifier) owner note
    objectstack-ai/objectui#11626 shell-nav-personalization A3 P3 objectui grouped navigation offers no drag-reorder, and every stock app is grouped
    objectstack-ai/objectui#11627 marketplace-console-honesty A3 P3 objectui offline Details renders the Disabled card ahead of reseed / purge
    objectstack-ai/objectui#11629 view-type-gallery A2 P3 objectui kanban never reads summarizeField (declared-unenforced)
    objectstack-ai/objectui#11625 grid-personalization A2 P2 objectui the density PUT puts rowHeight at the envelope top level, and the server drops it with a 200
    objectstack-ai/objectui#11632 found in chart-type-matrix A8 P3 objectui dataset previousPeriod comparison labelled "vs yesterday"

    None is a 17.7 regression: every defect above reproduces against console code unchanged since the 17.6.0 pin (31971ff1e) or earlier. No open duplicate was found for any of them.

    Checklist-accuracy findings (no fail attached; for the checklist owner)

    1. platform-core:
      • home-admin-cluster-links and docs-portal-render: the personas say "fresh sign-up", which invite_only refuses. Docs step 4 should name the Help menu. /apps/{pkg}/docs lands on the reader of the first entry rather than on a separate listing.
      • home-admin-cluster-links: the item's whole Administration-cluster premise has no stable rendering surface at the pin (VF4), so it needs a revision beyond the parked clauses.
      • url-overlay-contract: the drawer list is the Review Queue page (recordAction: 'drawer'); /forms/:name takes view names (showcase_task.form); the child-create path is Account → Invoices tab → New.
      • theme-mode-persistence: the storage key is object-ui-theme, not vite-ui-theme, and ModeToggle lives in the avatar menu under Preferences.
      • shell-nav-personalization: pinned items appear under a "Favorites" heading, not "Pinned".
      • marketplace-console-honesty: reseed / purge live on MarketplacePackagePage, not on Installed Apps.
    2. api-backend: api-console-discovery-execute: Realtime (degraded, handlerReady:false) gets no group, although the hook comment says degraded services "stay visible". This is the fail-closed direction.
    3. approvals:
      • account-app-entry A7: the interface language is avatar menu → Language. The Profile "Preferred language" select sets only the notification language.
      • record-page-decisions: the mechanism text is stale. objectui#3055 / objectui PR test(dogfood): 把 temporal 这条线固化成端到端门禁;docs 审计范围传错时立即报错 #4077 retired buildApprovalDecisionActions, and the header renders the declared actions through DeclaredActionsBar. The visible set also includes Reassign / Send back / Request info / Recall, and A5 needs a non-override persona.
      • The inbox tabs are English by default ("My Pending" / "Submitted by me").
      • setup-packaged-automation-board A8: a member gets 403 on activation reads (also on 17.6.0), and reaches the page through other apps' component routes, not through Setup.
      • An invite with role "admin" is not honoured at sign-up; use organization/update-member-role.
      • The run's steps_json omits post-resume nodes, so branch-taken clauses cannot be read from the run.
    4. records-forms:
      • list-view-capabilities:
      • view-type-gallery: packages/spec/liveness/view.json calls kanban "field-by-field wired", which is stale for summarizeField.
      • form-view-gallery: no console door opens the named form views; the wizard renders as steps only on the /new page route; the modal knownGap is partly stale (Task Desk renders a JSX modal form).
      • related-list-server-pagination: the knownGap is stale, because invite + sign-up + a permission-set row works.
      • gantt-interactions: the variants name a lockField that is not a spec key.
      • upload-guard-blocks-confirm: Confirm is relabelled "Uploading…" mid-flight.
      • adhoc-filter-sort-builder A3 verify: by design the sort is not restored, since only {filters, search} are stored.
      • saved-view-management step 1: create saves a draft and needs a publish.
      • bulk-select step 5: top=0 gives total:0.
      • grid-personalization: the column-state key is grid-columns-{object} when the view has no schema.id.
      • calendar-interactions A4: the stock calendar cannot quick-create, because project is required.
      • conditional-rules-grid: INV-1002 ships a single line, so step 3 needs a seeded second line with a distinct position.
    5. dashboards:
      • chart-type-matrix A3 cites combo series[].type / series[].yAxis, which were removed by the 2026-09-12 ruling. The compareTo probe recipe should add dashboard.dateRange, without which the executor refuses.
      • global-filters-rescope: Revenue Pulse's region filter uses static options, so D3's dataset-sourced half needs a scratch optionsFrom dashboard.
    6. i18n:
      • notification-localized-and-clears step 2 is stale: zh-CN is accepted, and sys_user.locale exists. Its prescribed zh code is also what triggers the held date finding.
      • surface-matrix: the record-page knownGap and the variants string are stale, because the sections are named now. E11 needs a wait of more than 30 s after the tenant flip (LOCALE_TTL_MS).
      • studio-follows-app-locale names no Studio surface that carries a relative date.
    7. studio-authoring:
      • packaged-automation-studio-lock: the knownGap ("objectui f7c52e2" shape) is stale (objectui#11124). A2 names 422 writable_package_required, but the live server answers 403 NOT_OVERRIDABLE / ITEM_LOCKED.
      • packaged-display-class-direct-edit: the lock banner reads "This item is locked…", and Reset needs a native confirm() accepted.

    Environment notes are in the record body.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 5, 2026

    @objectstack-fleet
    ContributorAuthor

    Re-run: the two held zh-date clauses (RUNNER rule 7)

    The record held i18n.surface-matrix acceptance[0] (relative-dates variant) and i18n.studio-follows-app-locale acceptance[2] as FAIL, observed but not verified. A live re-run on the same subject (316be321e, console pin 2e818d0b51ec), 2 fresh boots × 2 loads plus controls, settles both:

    item rev was now evidence
    i18n.surface-matrix 4 FAIL (held) PASS switching language through the avatar menu writes the user's locale (zh-CN); /api/v1/auth/me/localization answers zh-CN; every date formatter receives zh-CN; list dates render 10月15日 / 3天后 / 后天, record stamps 创建于: 8天前
    i18n.studio-follows-app-locale 3 FAIL (held) PASS same evidence; switching back writes en and restores "Oct 15" / "In 3 days"

    Disposition of the original fail: invalid pairing. The first lane set the UI language only in browser storage and never used the product's language switcher, so the user's stored locale stayed empty and dates followed the browser. No item step prescribes that, and the clauses are right as written.

    Corrected totals for this record: 40 PASS / 8 PARTIAL / 13 FAIL / 0 BLOCKED / 0 NOT-RUN (the title still shows the pre-re-run counts).

    Close-out for these two clauses: no card. One candidate outside the clauses (when the language save fails, the UI language and the date locale can disagree; console, P3) is noted for the console owner and not extracted.

    Optional step wording for both items (checklist owner): "use the avatar-menu language switcher (it writes the user's locale); seeding browser storage alone is not a language switch."


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 6, 2026

    @objectstack-fleet
    ContributorAuthor

    Close-out addendum: one fail disposed. The record stays open for the rest

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-06T16:08Z. The maintainer approved clearing the open qa-run records' close-out debt: 「同意,动手」. This was audited row by row (read-only) against checklist-test §5 before this write.

    Extracted: objectui#11674 · platform-core.keyboard-shortcut-surface · A3/A4

    • K1 (the dead advertised accelerators) is carried by objectui#11674, closed completed on 2026-10-06.
    • Still undisposed:
      • ai.console-ai-surface-gating A6 (FOLLOW-UPS K2: an empty queue renders under the 501 alert, and the poll never backs off). No card exists.
      • Eight partials: identity-auth.phone-signin-surfaces, platform-core.console-installability-indicators, records-forms.crud-roundtrip, records-forms.import-wizard-encoding-and-hints, records-forms.gantt-interactions, records-forms.form-dirty-guard, records-forms.bulk-select-all-matching, search.command-palette-navigation. Each gap is named in the body, but none is parked on a card.
    • Corrected totals after the re-run comment: 40 PASS / 8 PARTIAL / 13 FAIL. The title still shows the pre-re-run counts.

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 6, 2026

    @objectstack-fleet
    ContributorAuthor

    Close-out complete: the last fail is extracted, and the blocked partial gaps are parked. The record closes completed

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-06T17:05Z. The maintainer approved clearing the open qa-run records' close-out debt: 「同意,动手」. ⛔ No verdict on this record is changed.

    Extracted: objectstack-ai/objectui#11736 · ai.console-ai-surface-gating · acceptance[5]
    Parked-on: #22017 · identity-auth.phone-signin-surfaces · A2 / A3 blocked(fixture)
    Parked-on: #22017 · records-forms.crud-roundtrip · A7 readonly half
    Parked-on: #22017 · records-forms.import-wizard-encoding-and-hints · A3 blocked(dependency)
    Parked-on: #22017 · records-forms.gantt-interactions · A2 / A3 blocked(fixture)
    Parked-on: #22017 · search.command-palette-navigation · A5 blocked(fixture)
    Parked-on: #22017 · records-forms.grid-personalization · A1 reorder / pin leg
    Parked-on: #22017 · records-forms.action-location-matrix · A3 url / api dispatch leg
    Parked-on: #22017 · i18n.surface-matrix · A6 confirm half
    Parked-on: #22017 · platform-core.keyboard-shortcut-surface · A5 blocked(fixture)
    Parked-on: #22017 · ai.console-ai-surface-gating · A2 entitled side
    Parked-on: #22017 · platform-core.builtin-apps-nav-render · catalog content blocked(environment)
    Parked-on: #22017 · platform-core.marketplace-console-honesty · boot A catalog content blocked(environment)

    • Every fail now has a disposition. The others were disposed earlier, in the close-out lines above this comment and in addendum 6020392202. ai.console-ai-surface-gating A6 (K2) was the last, and it is now objectui#11736, graded p3.

    • The not-run legs stay on this record's own handoff list, as §4 requires, with ⛔ no second list:

      • platform-core.console-installability-indicators A3 (the error leg);
      • records-forms.form-dirty-guard A3;
      • records-forms.bulk-select-all-matching A5.

      The next release-candidate Tier 1 run re-selects them (§5, trigger 1).

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions