Repository navigation
Description
Run record for the 18.0 release sweep, selector studio-authoring (resolved with node scripts/checklist-select.mjs area:studio-authoring --json), plan B (Tier 1 + Tier 2; Tier 3 deferred).
Environment fingerprint
- framework:
5b14b7f3ad8e2e0786d228772f473d07b36b2477(objectstack-ai/objectstack main), working tree clean - console:
.objectui-sha=4016370af3c9c9dafec2bc5299afd8e8079701b8, built withpnpm objectui:build;packages/console/dist/.objectui-shastamp equals the pin (pnpm check:console-shagreen), so the stale-console-bundle trap is ruled out for every console observation - app: showcase (examples/app-showcase), canonical boot
OS_PORT=PORT pnpm -C examples/app-showcase exec objectstack dev --ui --seed-admin -p PORT -d file:/tmp/qa18/ITEM/data.db; every hand-driven item had its own port and file DB (listed per item below); seed:--seed-admin(admin@objectos.ai) + showcase seed + per-item scratch fixtures - Tier 1 pins: vitest per package against the same tree (
pnpm exec vitest run FILES), 97 framework files / 2209 tests, 0 failed; objectui-side pins run inside a clone of objectui at4016370af3c9(unit vitest +playwright.live.config.tsagainst a showcase boot on :47431 through the objectui console dev server), RUNNER option (b) - browser: Playwright with
/opt/pw-browsers/chromium, own context per persona, sign-in through the form - timestamps: 2026-10-19, environment prep 12:26–12:43 UTC, testing 12:43–13:53 UTC; Tier 2 items were driven in parallel by sub-runners (≤ 3–4 browser items at once), each on its own port/DB
Scope
Selector studio-authoring → 20 runnable item(s). Blocked items hidden by the resolver were not run (no --include-blocked).
Tiering (checklist-test SKILL §1): Tier 1 = item carries automated.ref (pin run, cited); Tier 2 = unpinned P0/P1 (hand-driven); Tier 3 = unpinned P2 (deferred, not-run).
| item | priority | surface | tier | revision | item verdict |
|---|---|---|---|---|---|
studio-authoring.first-run-loop |
P0 | mixed | 2 | 3 | pass |
studio-authoring.object-designer-roundtrip |
P1 | mixed | 1 | 4 | partial |
studio-authoring.view-authoring-live |
P1 | mixed | 2 | 2 | pass |
studio-authoring.record-page-roundtrip |
P1 | mixed | 1 | 4 | partial |
studio-authoring.draft-publish-lifecycle |
P1 | mixed | 1 | 6 | partial |
studio-authoring.authoring-validation-not-persisted |
P1 | mixed | 2 | 3 | pass |
studio-authoring.org-override-registry-gate |
P1 | api | 1 | 3 | pass |
studio-authoring.expression-editors |
P1 | mixed | 1 | 3 | partial |
studio-authoring.permission-matrix-editor-ux |
P2 | mixed | 1 | 3 | partial |
studio-authoring.custom-page-render-and-blocks |
P2 | mixed | 3 | 1 | not-run |
studio-authoring.page-variables-and-actions |
P2 | mixed | 3 | 1 | not-run |
studio-authoring.custom-page-source-tiers |
P2 | mixed | 3 | 3 | not-run |
studio-authoring.packaged-automation-studio-lock |
P1 | browser | 2 | 3 | pass |
studio-authoring.packaged-display-class-direct-edit |
P2 | browser | 3 | 2 | not-run |
studio-authoring.metadata-diagnostics-sweep |
P2 | mixed | 1 | 4 | partial |
studio-authoring.doc-on-app-menu |
P1 | mixed | 2 | 3 | pass |
studio-authoring.picklist-bound-select |
P2 | mixed | 3 | 1 | not-run |
studio-authoring.meta-save-preconditions-and-draft-rows |
P1 | api | 1 | 1 | pass |
studio-authoring.multi-package-item-rows |
P1 | api | 1 | 1 | pass |
studio-authoring.save-door-runs-authoring-rules |
P1 | api | 1 | 1 | pass |
Per-clause verdicts
A = acceptance[n], N = negative[n]. Tier 1 rule: a clause is pass only when a passing pin covers it (server-side oracles, or clauses the ref names); clauses a ref says it does not cover, and UI-oracle clauses a server-side pin cannot see, are not-run. Evidence is text from the oracle — no images.
studio-authoring.first-run-loop — pass (hand-driven (port 47421 · file:/tmp/qa18/first-run/data.db))
| clause | verdict | evidence |
|---|---|---|
| A0 | pass | POST /api/v1/packages {manifest name 维修中心 id com.example.repairs} → 201 source authored; console moved to /_console/studio/com.example.repairs/data without reload (window marker survived); switcher lists it Writable beside showcase Read-only |
| A1 | pass | PUT /api/v1/meta/object/repairs_repair_ticket?mode=draft&package=com.example.repairs → 200 (OWD default Private); picklist Status autosaved; POST /api/v1/packages/com.example.repairs/publish-drafts → 200 publishedCount 1; GET meta object → _packageId com.example.repairs, status select open/in_progress/done |
| A2 | pass | POST /api/v1/data/repairs_repair_ticket {name,status:in_progress} → 201; GET → total 1, status in_progress |
| A3 | pass | launcher shows the Repair Center tile; list row renders label In Progress, not the raw value (fresh context too); GET /api/v1/meta/app lists repair_center with nav to repairs_repair_ticket |
| A4 | pass | server.log: one boot banner, one ready line, no restart/recompile; same listener PID 12:44:32–12:51:47Z across the whole loop |
| A5 | pass | forged writes to com.example.showcase: new object draft → 422 WRITABLE_PACKAGE_REQUIRED; overlay of showcase_task → 403 ITEM_LOCKED (draft and non-draft); PUT meta field → 403 code-only; no residue |
| N0–N1 | pass | every write aimed at the read-only showcase package refused server-side; app present and label rendered |
studio-authoring.object-designer-roundtrip — partial (Tier 1 pin)
| clause | verdict | evidence |
|---|---|---|
| A0 | not-run | not covered by a passing pin (objectui@4016370a e2e/live/studio-object-designer.spec.ts vs live boot :47431 via Vite console: F3 pass every run (A1), F2 pass R1/R2 (A2; R3 timing flake). F4 stale vs A3's own judging order; F1 stale route (Studio app not loaded on stock boots)); not hand-driven in this Tier 1 pass |
| A1, A2 | pass | pin: objectui@4016370a e2e/live/studio-object-designer.spec.ts vs live boot :47431 via Vite console: F3 pass every run (A1), F2 pass R1/R2 (A2; R3 timing flake). F4 stale vs A3's own judging order; F1 stale route (Studio app not loaded on stock boots) |
| A3 | not-run | not covered by a passing pin (objectui@4016370a e2e/live/studio-object-designer.spec.ts vs live boot :47431 via Vite console: F3 pass every run (A1), F2 pass R1/R2 (A2; R3 timing flake). F4 stale vs A3's own judging order; F1 stale route (Studio app not loaded on stock boots)); not hand-driven in this Tier 1 pass |
| N0 | not-run | negative spans the UI half not driven in this Tier 1 pass |
studio-authoring.view-authoring-live — pass (hand-driven (port 47451 · file:/tmp/qa18/view-live/data.db · scratch package com.qa.repair))
| clause | verdict | evidence |
|---|---|---|
| A0 | pass | PUT /api/v1/meta/view/qa_repair_asset_views?mode=draft → 200 state draft |
| A1 | pass | before publish GET /api/v1/meta/view/qa_repair_asset_views → 404 and GET /api/v1/meta/view?object=repair_asset → []; the list renders the synthesized default columns |
| A2 | pass | POST /api/v1/meta/view/qa_repair_asset_views/publish → 200; after reload the list shows tab QA Assets with Serial No / Asset Name / Cost and Edit/New show the authored sections; one server banner, same PID — no restart |
| A3 | pass | GET /api/v1/meta/view?object=repair_asset → repair_asset.default (list) and repair_asset.form with the authored config |
| A4 | pass | second draft (reordered columns) 200 seq 6, publish 200 seq 7; headers reorder accordingly; draft invisible before its publish |
| N0–N1 | pass | both publishes live without restart; no draft leak |
studio-authoring.record-page-roundtrip — partial (hand-driven (port 47453 · file:/tmp/qa18/record-page/data.db · automated.ref is marked stale — not run, not cited; all clauses driven by hand))
| clause | verdict | evidence |
|---|---|---|
| A0 | pass | new record page (type record, object showcase_invoice) → PUT /api/v1/meta/page/invoice_page_qa1?mode=draft 200; body has a seeded main region (page:header, record:highlights, record:path, page:tabs, record:discussion) — not blank |
| A1 | pass | editor renders Basics + canvas preview; Add block picker lists Card, Section, Record details, Highlights |
| A2 | pass | added Card titled QA Authored Card QA1; POST /api/v1/meta/page/invoice_page_qa1/publish 200; GET shows the page:card block; ?state=draft → 404 NO_DRAFT |
| A3 | blocked(fixture) | showcase ships showcase_invoice_document isDefault:true for showcase_invoice, which wins by design; authoring the page with isDefault:true → 422 DEFAULT_RECORD_PAGE_CONFLICT. (A non-default page on showcase_contact did render its card for admin — substitute observation, not scored) |
| N0 | pass | regions seeded and non-empty |
studio-authoring.draft-publish-lifecycle — partial (Tier 1 pin)
| clause | verdict | evidence |
|---|---|---|
| A0–A5 | pass | pin: dashboard-designer-roundtrip.dogfood.test.ts 3/3 passed |
| A6 | not-run | screenshot oracle — the pin is server-side; UI half not driven in this Tier 1 pass |
| A7–A11 | pass | pin: dashboard-designer-roundtrip.dogfood.test.ts 3/3 passed |
| N0–N4 | not-run | negative spans the UI half not driven in this Tier 1 pass |
studio-authoring.authoring-validation-not-persisted — pass (hand-driven (port 47452 · file:/tmp/qa18/validation/data.db))
| clause | verdict | evidence |
|---|---|---|
| A0 | pass | PUT /api/v1/meta/object/qa_invalid_probe?mode=draft with a typeless field → 422 INVALID_METADATA issues[path fields.amount.type] |
| A1 | pass | container-shaped view body with stray type/columns → 422 Unrecognized key(s) on this view container … Wrap it: defineView({ list: … }); the flat body gets the names-no-viewKind variant, also with the wrap prescription |
| A2 | pass | after each rejected PUT the item and its draft read 404 / NO_DRAFT; a pre-existing good draft survives an invalid PUT unchanged |
| A3 | pass | Setup metadata editor Source tab autosave PUT → 422; located red banner Fields → amount → type shown; reproduced twice |
| A4 | pass | corrected object and view PUTs → 200 state draft |
| N0–N2 | pass | no invalid shape got 2xx or became readable; error visible in the browser |
studio-authoring.org-override-registry-gate — pass (Tier 1 pin)
| clause | verdict | evidence |
|---|---|---|
| A0–N0 | pass | pin: overlay-precedence.test.ts 26/26 passed |
studio-authoring.expression-editors — partial (Tier 1 pin)
| clause | verdict | evidence |
|---|---|---|
| A0 | pass | pin: objectui@4016370a celAuthoring.test.ts 39/39, CelPredicateField.test.tsx 24/24, CelTestRunDialog.test.tsx 6/6, PermissionAdvancedFacets.cel.test.tsx 2/2; A3/A4 only partly pinned, A1/A6 not pinned |
| A1 | not-run | not covered by a passing pin (objectui@4016370a celAuthoring.test.ts 39/39, CelPredicateField.test.tsx 24/24, CelTestRunDialog.test.tsx 6/6, PermissionAdvancedFacets.cel.test.tsx 2/2; A3/A4 only partly pinned, A1/A6 not pinned); not hand-driven in this Tier 1 pass |
| A2 | pass | pin: objectui@4016370a celAuthoring.test.ts 39/39, CelPredicateField.test.tsx 24/24, CelTestRunDialog.test.tsx 6/6, PermissionAdvancedFacets.cel.test.tsx 2/2; A3/A4 only partly pinned, A1/A6 not pinned |
| A3, A4 | not-run | not covered by a passing pin (objectui@4016370a celAuthoring.test.ts 39/39, CelPredicateField.test.tsx 24/24, CelTestRunDialog.test.tsx 6/6, PermissionAdvancedFacets.cel.test.tsx 2/2; A3/A4 only partly pinned, A1/A6 not pinned); not hand-driven in this Tier 1 pass |
| A5 | pass | pin: objectui@4016370a celAuthoring.test.ts 39/39, CelPredicateField.test.tsx 24/24, CelTestRunDialog.test.tsx 6/6, PermissionAdvancedFacets.cel.test.tsx 2/2; A3/A4 only partly pinned, A1/A6 not pinned |
| A6 | not-run | not covered by a passing pin (objectui@4016370a celAuthoring.test.ts 39/39, CelPredicateField.test.tsx 24/24, CelTestRunDialog.test.tsx 6/6, PermissionAdvancedFacets.cel.test.tsx 2/2; A3/A4 only partly pinned, A1/A6 not pinned); not hand-driven in this Tier 1 pass |
| A7 | pass | pin: objectui@4016370a celAuthoring.test.ts 39/39, CelPredicateField.test.tsx 24/24, CelTestRunDialog.test.tsx 6/6, PermissionAdvancedFacets.cel.test.tsx 2/2; A3/A4 only partly pinned, A1/A6 not pinned |
| N0–N2 | not-run | negative spans the UI half not driven in this Tier 1 pass |
studio-authoring.permission-matrix-editor-ux — partial (Tier 1 pin)
| clause | verdict | evidence |
|---|---|---|
| A0, A1 | pass | pin: objectui@4016370a PermissionMatrixEditor.fieldBulk.test.tsx 3/3 + .readonly.test.tsx 11/11; A3 partial, A2/A4 not pinned |
| A2–A4 | not-run | not covered by a passing pin (objectui@4016370a PermissionMatrixEditor.fieldBulk.test.tsx 3/3 + .readonly.test.tsx 11/11; A3 partial, A2/A4 not pinned); not hand-driven in this Tier 1 pass |
| A5 | pass | pin: objectui@4016370a PermissionMatrixEditor.fieldBulk.test.tsx 3/3 + .readonly.test.tsx 11/11; A3 partial, A2/A4 not pinned |
| N0, N1 | not-run | negative spans the UI half not driven in this Tier 1 pass |
studio-authoring.custom-page-render-and-blocks — not-run (Tier 3)
| clause | verdict | evidence |
|---|---|---|
| A0–A6, N0–N2 | not-run | Tier 3 deferred by the 18.0 release-sweep plan |
studio-authoring.page-variables-and-actions — not-run (Tier 3)
| clause | verdict | evidence |
|---|---|---|
| A0–A5, N0–N3 | not-run | Tier 3 deferred by the 18.0 release-sweep plan |
studio-authoring.custom-page-source-tiers — not-run (Tier 3)
| clause | verdict | evidence |
|---|---|---|
| A0–A5, N0–N3 | not-run | Tier 3 deferred by the 18.0 release-sweep plan |
studio-authoring.packaged-automation-studio-lock — pass (hand-driven (port 47471 · file:/tmp/qa18/pkgflow/data.db))
| clause | verdict | evidence |
|---|---|---|
| A0 | pass | /_console/studio/com.example.showcase/automations?surface=flow:showcase_urgent_task_alert: no New button (positive control on a writable package shows New automation); drag/fill/wait past debounce → zero non-GET requests; repeated on a second fresh load |
| A1 | pass | forged PUT /api/v1/meta/flow/showcase_urgent_task_alert?mode=draft&package=com.example.showcase → 403 ITEM_LOCKED; without package → 403 NOT_OVERRIDABLE; flow body sha256 identical before/after |
| A2 | pass | Enabled switch disabled, aria-describedby → Read-only package — switch to or create a writable package to edit.; forced clicks change nothing, no request |
| A3 | pass | Notify Assignee inspector: 17 controls disabled; values unchanged after reload |
| N0–N2 | pass | no flow write got 2xx; nothing took effect then vanished; scope respected |
studio-authoring.packaged-display-class-direct-edit — not-run (Tier 3)
| clause | verdict | evidence |
|---|---|---|
| A0–A4, N0–N3 | not-run | Tier 3 deferred by the 18.0 release-sweep plan |
studio-authoring.metadata-diagnostics-sweep — partial (Tier 1 pin)
| clause | verdict | evidence |
|---|---|---|
| A0–A6 | not-run | not covered by pin (ref: pins the outage clause ONLY); not hand-driven in this Tier 1 pass |
| A7 | pass | pin: protocol.diagnostics-store-outage.test.ts 10/10 passed |
| N0 | not-run | not covered by pin (ref: pins the outage clause ONLY); not hand-driven in this Tier 1 pass |
| N1 | pass | pin: protocol.diagnostics-store-outage.test.ts 10/10 passed |
| N2–N4 | not-run | not covered by pin (ref: pins the outage clause ONLY); not hand-driven in this Tier 1 pass |
studio-authoring.doc-on-app-menu — pass (hand-driven (port 47472 · file:/tmp/qa18/docmenu/data.db · scratch package com.qa18.docmenu with docs/books/app; reader holds showcase_auditor, outsider holds none))
| clause | verdict | evidence |
|---|---|---|
| A0 | pass | GET /api/v1/meta/app?id=qa18_docs_app: reader 6 doc/book entries; outsider and admin 3 (gated pruned); outsider GET /api/v1/meta/doc/qa18_gated_doc → 403 and /api/v1/meta/book/qa18_auditor_book/tree → 403; reader 200 |
| A1 | pass | rendered menus: reader 6 links, outsider 3; diff vs each persona's /meta/app answer empty both ways |
| A2 | pass | doc entries land in the claiming book (not first by label); book entries open the first readable page; sidebars equal each persona's tree |
| A3 | pass | outsider on 7 gated direct routes sees You do not have access to this documentation inside the shell; unknown-name control renders Documentation not found with server 404 |
| N0–N4 | pass | no gated entry drawn for the outsider; no not-found where 403 is due; no blank page; no unclaiming book; scope respected |
studio-authoring.picklist-bound-select — not-run (Tier 3)
| clause | verdict | evidence |
|---|---|---|
| A0–A7, N0–N3 | not-run | Tier 3 deferred by the 18.0 release-sweep plan |
studio-authoring.meta-save-preconditions-and-draft-rows — pass (Tier 1 pin)
| clause | verdict | evidence |
|---|---|---|
| A0–A3 | pass | pin: meta-item-version-token-occ.test.ts 15/15 passed; meta-draft-head-package-inheritance.test.ts 25/25 passed; meta-save-preconditions-parity.test.ts 23/23 passed; sys-metadata-repository-list-drafts.test.ts 6/6 passed; protocol-metadata-row-actor.test.ts 4/4 passed |
studio-authoring.multi-package-item-rows — pass (Tier 1 pin)
| clause | verdict | evidence |
|---|---|---|
| A0–A4 | pass | pin: meta-delete-drop-storage-other-rows.test.ts 5/5 passed; package-uninstall-shared-object.integration.test.ts 5/5 passed; protocol-runtime-owner-overlay-refusal.test.ts 4/4 passed; protocol-sentinel-owner-package-save-refusal.test.ts 15/15 passed; package-promote-runtime-owner-refusal.integration.test.ts 8/8 passed; rest-meta-sealed-first-draft-remedy.test.ts 2/2 passed; protocol.packageless-save-address.test.ts 66/66 passed; protocol.sealed-remedy-kind.test.ts 13/13 passed; package-revert-stored-members.integration.test.ts 8/8 passed |
studio-authoring.save-door-runs-authoring-rules — pass (Tier 1 pin)
| clause | verdict | evidence |
|---|---|---|
| A0–N0 | pass | pin: protocol.runtime-authoring-gate.test.ts 152/152 passed; protocol.save-door-protection.test.ts 12/12 passed; protocol.save-door-lock-family.test.ts 25/25 passed; default-record-page-save-door.test.ts 34/34 passed; page-slot-pair.test.ts 12/12 passed; meta-view-chart-binding.test.ts 4/4 passed; runtime-gate.object-option-visibility-writes.test.ts 18/18 passed; validate-component-props-url-target.test.ts 20/20 passed |
Reproduction rules
No fail in this selector. Both P0 items (studio-authoring.first-run-loop, and the integration P0 in its own record) passed; no rule-7 re-derivation was owed.
Derived item verdicts
9 pass · 6 partial · 5 not-run (Tier 3). Partials: object-designer-roundtrip (objectui live spec F2/F3 cover A1/A2; F4 and F1 are stale specs, see below), record-page-roundtrip (A3 blocked by fixture), draft-publish-lifecycle (A6 screenshot clause not driven), expression-editors and permission-matrix-editor-ux (objectui unit pins cover part), metadata-diagnostics-sweep (pin covers the outage clause only).
Checklist-accuracy findings / fixture gaps (for the wave anchor card)
first-run-loop: knownGaps[0] is stale — Publish now opens a "Pending changes" review sheet (item list, key-level diff, a separate "Publish all"); step 3's "Save draft" is not a button for fields (picklist options autosave); step 4's toast reads "Published 1 item in this package (one atomic release)"; step 6 Create app with the default-on menu checkbox already adds the nav item; step 7 the Studio house icon goes to Studio home, the logo goes to/_console/home; step 2 a CJK display name derives no package id. Side observation: a packagelessPUT /api/v1/meta/object/showcase_qa_probe2?mode=draft(nopackage) saves an env-wide draft under theshowcase_prefix withpackageId: null— not attributed to the read-only package, recorded for a look.record-page-roundtripfixture gap (blocks acceptance[3]):showcase_invoicenow has a package-shipped default record page (showcase_invoice_document,isDefault: true), which wins by design (authoringisDefault: true→ 422 DEFAULT_RECORD_PAGE_CONFLICT) — re-point steps 7–8 / acceptance[3] at an object with no shipped default (showcase_contactworks; shipped defaults exist forshowcase_project,showcase_task,showcase_invoice,showcase_preference). Step 4's "Basics and Layout sections" — the panel now shows Basics / Data Context / Advanced; layout is on the canvas. Itsautomated.refstays stale (not run).view-authoring-live: a publishable runtime object needssharingModel(publish-drafts refusessecurity-owd-unsetthough the draft PUT answered 200) — say so in the recipe; step 4 "open a record" shows the record page, the authored form shows in Edit/New dialogs; a non-admin list render of a runtime object needs a permission-set grant.authoring-validation-not-persisted: acceptance[1]'s quoted text appears only for container-shaped bodies; step 2's flat body gets thenames no viewKind … Wrap itvariant — add a container key or accept either; step 4's "Studio designer" door gates client-side, the door reaching the server gate is the Setup metadata editor Source tab (/_console/apps/setup/metadata/object/NAME). Cosmetic objectui observation: after the 422 the editor pill keeps reading "Auto-saving…" beside "Unsaved".doc-on-app-menu: step 1 says the Studio doc editor while knownGaps[2] prescribes the metadata-API recipe — align. objectui observations: an app whose nav holds only doc entries lands on an empty main area; the menu highlights the book entry after clicking a doc entry (href prefix match).object-designer-roundtripobjectui live spec (e2e/live/studio-object-designer.spec.tsat 4016370): F4 contradicts acceptance[3]'s own judging order (adds a picklist with no real options, expects 0 banners); F1 targets a Studio app no stock boot loads. Both red against their own same-sha console — the objectui live lane is not green at the pin.packaged-automation-studio-lock: the disabled Enabled switch still looks green "on" (cosmetic); canvas nodes are not React Flow nodes (target by label).
Hand-off (items without a judged verdict)
custom-page-render-and-blocks,page-variables-and-actions,custom-page-source-tiers,packaged-display-class-direct-edit,picklist-bound-select(all P2) — not-run: Tier 3 deferred by the 18.0 release-sweep plan.- Partial items' uncovered clauses are listed per item above (
not-runrows).
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 19, 2026
Parked-on: #24579 · this record's checklist-accuracy findings, fixture gaps, partial coverage gaps and not-run handover (wave anchor §2–§4)
Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
Superseded-by: #24604
Round 2 at ba4afcc re-judged this record's A-class unjudged clauses (six studio-authoring partials — 4 now pass,
expression-editorsnegative[0] FAIL (rule-7 verified),draft-publish-lifecyclestays partial) and carried every other verdict forward to #24604 (Carried-forward:lines there, valid for 5b14b7f). B-class gaps stay parked on #24579.Generated by Claude Code
docs(qa): re-point expression-editors' RLS clauses to the engine's er…