Repository navigation
Description
epic:#28130#1 · hotlong · session_040dfd80c4c9411b895c698e785a6848
QA run record, run on the maintainer's word in direct chat with the epic PM seat, 2026-11-03: 「如果都落地了,就更新最新代码,使用右侧浏览器完整的测试验证」; filing: 「发记录并立卡」. It re-runs the seven ADR-0146 items of #29560 after #29563, #29564, #29566, #29567, #29568 and #29569 landed. The record is text only.
Environment fingerprint
- Framework:
mainat322cf9068f.pnpm install --frozen-lockfile,pnpm build,pnpm console:build. The console is this tree's own build, served at/_console. - Boot:
objectstack dev --ui --seed-adminon the showcase, port 3781, own file database andOS_HOME,OS_PORTexported. The CLI item ran on a second database and port 3782. - Browser: the desktop app's built-in browser pane, driven by hand, one item at a time (sequential).
- Personas: the seeded admin
admin@objectos.ai, and one member made with admin create-user and change-password. - The customize legs ran under one uptime (863 s at the check). The boot was then restarted once on purpose, with every customization published.
Scope
Selector: adr-0146-new-items, the same seven ids as #29560, each resolved by id through scripts/checklist-select.mjs.
| item | revision |
|---|---|
| platform-core.customization-pair-ensure-door | 2 |
| studio-authoring.package-customize-restore-display | 2 |
| studio-authoring.package-extension-field-c | 2 |
| automation.package-flow-override | 2 |
| cli.packageless-overlay-ceremony-and-close | 1 |
| studio-authoring.package-customization-counts-and-marks | 2 |
| platform-core.setup-metadata-redirects-to-studio | 2 |
Pins named in each item's automated.ref, on the same tree, all exit 0:
| package | files | tests |
|---|---|---|
runtime (with packages-export-base-unchanged-per-type.integration.test.ts) |
4 | 65 |
| objectql | 4 | 65 |
| metadata-protocol | 2 | 41 |
| service-automation | 1 | 16 |
| cli | 1 | 5 |
| ui | 13 | 233 |
Not run here: the live spec ui/e2e/live/studio-customize-journey.spec.ts.
Per-clause verdicts
platform-core.customization-pair-ensure-door (r2) — PASS
| clause | verdict | evidence |
|---|---|---|
| 0 | pass | 201 with showcase_custom, ^0, created: true, writable: true; the pair's manifest agrees. |
| 1 | pass | 200 with created: false; the pair's read is byte-identical before and after. |
| 2 | pass | 400 body, 400 query, 400 pair as base, 404 not installed, 409 writable, member 403 PERMISSION_DENIED naming manage_metadata. The list gained only the run's fixture. The member's first call answered PASSWORD_RESET_REQUIRED, a fixture step (change-password), not a verdict. |
| 3 | pass | 409 starts Delete the customization package "com.example.qa-pair-base.custom" first and names its export; the base still reads 200; pair DELETE 200, then base DELETE 200. |
| 4 | pass | DELETE of the showcase answers 422 WRITABLE_PACKAGE_REQUIRED with its pair installed; both stay listed. |
studio-authoring.package-customize-restore-display (r2) — FAIL
Variants: showcase_ops_dashboard, showcase_hours_by_status, showcase_task.in_progress.
| clause | verdict | evidence |
|---|---|---|
| 0 | pass | Customize sent no metadata write on any variant. The first edit sent one ensure (201, then 200), then the draft PUT naming package=com.example.showcase.custom with overrides: {package:'com.example.showcase', basedOn:'0.1.0'} and no _ keys. No write named the base. |
| 1 | pass | The bare, base-named, list and /layers effective reads carry the edit and agree; /layers code is unchanged from step 1. |
| 2 | pass | As the member: the dashboard and report show the edited label, and the task list drops Due Date, with no server restart. After restore, read as the admin: the dashboard shows its shipped title and the task list has Due Date again. The report's restored render was not opened; its reads equal the baseline. |
| 3 | pass | studio-override-chip reads the overrides sentence naming ObjectStack Showcase; its title names 0.1.0. |
| 4 | fail | The pair's export carries each override with its block. The base's export carries the view byte-identical, but the dashboard and the report are absent: dashboards 3 → 2, reports 4 → 3. Reproduction below. |
| 5 | pass | Cancel deleted nothing. Confirm sent the two DELETEs at the pair, 200 each. All four reads and the base export then equal step 1 byte for byte, for every variant. |
| 6 | pass | Every variant offers Customize on the read-only base; clauses 0–3 and 5 hold on each. The dashboard and report fail clause 4 only. |
studio-authoring.package-extension-field-c (r2) — PASS
| clause | verdict | evidence |
|---|---|---|
| 0 | pass | The preview reads region__c; one ensure, then the extension draft PUT with exactly {extend, fields: {region__c: {type:'text', label:'Region'}}}; no object PUT. tier__c joined the same extension with no second ensure. |
| 1 | pass | The object read lists both beside the shipped fields; the pair's extension read returns them; a task created with both values reads back EMEA / Gold. |
| 2 | pass | A label edit saves fieldPatches: {assignee: {label: 'Assignee QA'}} alone; required is disabled; field-base-patch-only names the whitelist. |
| 3 | pass | note__c outside the pair and plain_note in the pair each answer 400 VALIDATION_ERROR located in issues; neither is stored. |
| 4 | pass | The hint names region__c as taken; add-field-create is aria-disabled. |
automation.package-flow-override (r2) — PASS
| clause | verdict | evidence |
|---|---|---|
| 0 | pass | Customize sent nothing; one ensure, then the flow draft PUT at the pair under the base's name with the block; no toggle and no ledger write. |
| 1 | pass | _status has one row; the bare read serves the override; the next change started exactly one run, stepping start, then the renamed node. |
| 2 | pass | Stronger than the steps: a base run paused at manager_review, then an override renaming that node to manager_review_pin was published, then the request was approved. The run completed on start, manager_review, needs_exec, exec_review (skipped). The next run took manager_review_pin. |
| 3 | pass | The switch posted {enabled:false} and {enabled:true}, 200 each. Off: no run. On: the next run took the override's node. The ledger row has package_id com.example.showcase. One switch is drawn. |
| 4 | pass | Two DELETEs at the pair, 200 each; the chip is gone; the bare read has no overrides key; the next run took the base's manager_review. |
| 5 | pass | After the restore, New similar answered 200 with status obsolete and packageId com.example.showcase.custom; the console opened the copy, Added, in the pair. See the second finding below for New similar while the override is live. |
cli.packageless-overlay-ceremony-and-close (r1) — PASS
| clause | verdict | evidence |
|---|---|---|
| 0 | pass | Exit 0, apply: false, rows: []; row and pair counts unchanged. |
| 1 | pass | The staged row reads movable, pair com.example.showcase.custom; nothing written. |
| 2 | pass | {"error":"confirmation_required","hint":"pass --yes"}, exit 1; the row unchanged. |
| 3 | pass | Moved with overrides {package, basedOn:'0.1.0'}; no package-less row remains; after a boot the bare read serves the staged label and /layers code stays the shipped one; a re-run lists nothing. |
| 4 | pass | The package-less PUT and DELETE and the base-named PUT each answer 403 naming the pair; the item is unchanged after each; the declared PUT into the pair answers 200. |
The first staging wrote the body as a BLOB (sqlite readfile), and that move failed spec validation with the row kept. That was the run's own staging error, corrected with CAST(... AS TEXT), not a verdict.
studio-authoring.package-customization-counts-and-marks (r2) — PASS
| clause | verdict | evidence |
|---|---|---|
| 0 | pass | Served counts 4 overrides, 2 extensions, 1 switched off; the card reads 6 customized, 1 switched off; the pair link opens the pair's Data, the switched-off link the Automations pillar. |
| 1 | pass | The directory total reads 6. Dashboard list: one row marked Customized, the filter leaves 3 → 1. Flow list: Customized and Added marked, the filter leaves 33 → 2. |
| 2 | pass | The landing asks the read-only base only, with a writable card present. A writable package's area asks, answers zero and draws no total, mark or filter. The pair id answers 400 VALIDATION_ERROR naming its base. |
platform-core.setup-metadata-redirects-to-studio (r2) — PASS
| clause | verdict | evidence |
|---|---|---|
| 0 | pass | Each URL's first history entry is its /studio/~all/metadata/... target. The lists stay on ~all (#29566 holds), confirmed on full load for /apps/setup/metadata/object. |
| 1 | pass | ?package= opens the leg, then the Data pillar; ?scope=environment keeps the cross-package leg; ?review=1 and #fields survive the redirect. |
| 2 | pass | Datasource list, item and alias settle on Setup with no /studio entry; the list shows showcase_external; metadata-edit-datasource renders. |
| 3 | pass | The bookmark lands on /studio/~all/metadata/flow (33 rows), and with a package on its Automations pillar. |
Chains were read from a history.pushState / replaceState hook with client-side navigation, plus full loads for the list, the datasource and the bookmark.
Reproduction rules
- A published dashboard or report override drops the item from the base's export (restore-display, clause 4; product defect). Reproduced before and after a restart.
- On a fresh showcase,
GET /api/v1/packages/com.example.showcase/export:dashboards[]holdsshowcase_ops_dashboard. POST /api/v1/packages/com.example.showcase/ensure-customization;PUT /api/v1/meta/dashboard/showcase_ops_dashboard?mode=draft&package=com.example.showcase.customwith the item andoverrides: {package:'com.example.showcase', basedOn:'0.1.0'};POST /api/v1/packages/com.example.showcase.custom/publish-drafts.- Repeat step 1's read. Expected: the item byte-identical to step 1. Actual: absent. The same happens with report
showcase_hours_by_status. Viewshowcase_task.in_progressstays. Removing the override brings the item back.
- On a fresh showcase,
- New similar on a flow with a live override is refused (off-clause; product defect). Reproduced twice in Studio and once over the API. Publish an override of
showcase_budget_approval, thenPOST /api/v1/automation/showcase_budget_approval/clonewith{name:'showcase_budget_approval_copy', label:'x'}. Expected: a switched-off copy in the pair (ADR-0146 D4). Actual: 403 NOT_OVERRIDABLE, "declares an override of 'com.example.showcase', which ships no flow named 'showcase_budget_approval_copy'". After Restore the same call answers 200.
Derived
- PASS (6), FAIL (1):
studio-authoring.package-customize-restore-display, clause 4. - PARTIAL, BLOCKED and NOT-RUN: none. No fixture gaps.
packages-export-base-unchanged-per-type.integration.test.tsis green while clause 4 fails live: on its harness the per-package layer lists both documents, and on the showcase boot it does not hold the base's.
Off-clause observations, not extracted
- At a 1024 px wide pane, the selected customized row in the flow rail showed only its mark, with the name squeezed out.
- At the same width, the item header's more menu (
if-item-more,auto-item-more) sits under the right panel until the panel is collapsed. GET /api/v1/meta/object/showcase_task/layers:code.fields.assignee.labelreads the patched label, not the shipped one.- The clone's notice sentence "The copy is switched off…" renders in English in a zh-CN console.
Activity
objectstack-fleet commentedon Nov 2, 2026
epic:#28130#1 · hotlong · session_040dfd80c4c9411b895c698e785a6848
2026-11-02T23:52Z
Close-out of this run.
Extracted: #29649 · studio-authoring.package-customize-restore-display · acceptance[4]
Extracted: #29650 · automation.package-flow-override · off-clause
Assertion defects: none. Coverage gaps: none. The four off-clause observations in the body are not extracted.
This record stays open until #29649 and #29650 land and the owed items are re-judged. #29560 covered the same seven ids; its
Superseded-by:line is not written yet, because that close was not part of the instruction to this seat.