Repository navigation
Description
domain:devx#1 · os-warren · session_01JQwxbXSZs9PBUc2H8z6mtB
Part of #27377 (wave 4, W4-L3)
QA run record for the 18.3.0 release-candidate sweep, wave 4 card W4-L3: the Tier 1 live legs for records-forms and studio-authoring. The wave-4 Tier 1 card W4-C2b (record #28965) ran each item's automated.ref only, so it left these 41 items PARTIAL. This card drove every clause #28965 marked partial, skipped or blocked on a booted stack (API, DB, logs, and Playwright Chromium against the Console built from the subject). Clauses #28965 scored pass keep that verdict and are cited, not re-run. Item verdicts are derived from the clause verdicts, never hand-assigned. Run under .claude/skills/checklist-test/SKILL.md and docs/qa/platform-checklist/RUNNER.md. It is a QA run, not a lane card; Warren approved the live-leg cards on 2026-11-02 07:06Z.
Result: 41/41 judged · 37 PASS / 2 PARTIAL / 2 FAIL / 0 BLOCKED / 0 NOT-RUN. No item is planned. Clause rows: 304 in all. 60 are pins passes cited from #28965. Of the 244 judged live, 237 pass, 3 fail, 3 partial and 1 is blocked.
Environment fingerprint
- Framework:
objectstack-ai/objectstack@7fa9873f38f7a0158e3ce17338dcc0f446b113e3(main, 2026-11-02 02:44Z), detached in its own worktree. It never followedmainor the Version PR chore: version packages #26517.ui/is the same commit. - Build:
npm_config_nodedir=/opt/node22 pnpm install --frozen-lockfile(26 s), thenpnpm exec turbo run build --concurrency=2(118/118 tasks, exit 0, 21m58s), thenpnpm console:build(71/72 cached, plus the copy intopackages/console/dist).check-dev-prereqs: 106 build artifacts present. Node v22.23.4, pnpm 10.31.0, Playwright Chromium build 1243 from/opt/pw-browsers, 4 CPUs, about 15 GiB. - Boot, one per runner and more where an item needed them: a scratch copy of
examples/app-showcase(tar withoutnode_modulesand.objectstack,node_modulessymlinked to the tree), started from the copy withOS_PORT=PORT OS_STORAGE_LOCAL_ROOT=RUN/uploads OS_HOME=RUN/home setsid node packages/cli/bin/run.js dev --ui --no-watch --seed-admin -p PORT -d file:RUN/data.db. A canary boot answered/api/v1/health200 after 22 s, served/_console/200 and listedshowcase_appbefore any runner started. - Other boots, each on its own port and file DB:
OS_AUTOMATION_SCHEDULED_WORK_ENABLED=1(flow-status-matches-runtime, schedule half); a walledgroupboot withOS_TENANCY_POSTURE=group OS_PLATFORM_OWNER_EMAIL=admin@objectos.ai OS_AUTH_MEMBERSHIP_POLICY=invite-only(record-discussion-mentions A9 cross-org leg); anexamples/app-crmscratch copy (import-job-undo-cancel, recipeqa-crm-import-console). - Ports 41910–41964, a block of 5 per runner. Seed:
--seed-admin(admin@objectos.ai), the stock showcase seed and demo personas. Members were minted by invite then sign-up, or by admin create-user, and each persona's identity was proved withGET /api/v1/auth/get-sessionbefore its cells. - Execution: 6 runner subagents (opus, effort high). At most 3 browser-heavy runners ran at once, and each drove its items one after another with one browser. The orchestrator checked every FAIL against its runner's reproduction rule and the source. It reproduced R-1 itself over the API on a fresh boot (400 on the action door, 200 on the target).
- Hygiene: after the run,
git statusis clean,examples/app-showcase/.objectstackandexamples/app-crm/.objectstackdo not exist, and no listener remains on any run port.
Scope
Selector release-18.3.0-w4-l3: the item list of card W4-L3 in the wave-4 live-leg brief, computed from the ledger at the subject. The per-item target was every clause the pins record #28965 left partial, skipped or blocked. No planned items. Revisions were pinned from the ledger at the subject, and all match the item file and #28965:
records-forms.action-param-widgets r6 · records-forms.adhoc-filter-sort-builder r8 · records-forms.bulk-select-all-matching r6 · records-forms.cascading-multilevel-and-clear r9 · records-forms.cascading-options r7 · records-forms.concurrent-edit-conflict r5 · records-forms.conditional-rules-grid r11 · records-forms.conditional-rules-header r8 · records-forms.delete-behavior-matrix r5 · records-forms.field-history-tracking r11 · records-forms.field-type-constraints r6 · records-forms.field-type-matrix r8 · records-forms.field-unique-enforcement r13 · records-forms.form-dirty-guard r7 · records-forms.gantt-interactions r8 · records-forms.import-job-undo-cancel r8 · records-forms.import-wizard-encoding-and-hints r9 · records-forms.list-view-capabilities r8 · records-forms.master-detail-atomic-save r9 · records-forms.record-clone-contract r3 · records-forms.record-discussion-mentions r13 · records-forms.related-list-server-pagination r11 · records-forms.v18-semantic-defaults r6 · records-forms.view-type-gallery r3 · studio-authoring.actions-tab-presets r3 · studio-authoring.automations-rail-and-new-flow r2 · studio-authoring.flow-status-matches-runtime r2 · studio-authoring.held-edit-publish-refusal r3 · studio-authoring.hooks-tab-authoring r3 · studio-authoring.interfaces-create-dialogs r2 · studio-authoring.meta-save-preconditions-and-draft-rows r2 · studio-authoring.metadata-diagnostics-sweep r10 · studio-authoring.multi-package-item-rows r4 · studio-authoring.object-api-tab-curl r2 · studio-authoring.object-designer-roundtrip r10 · studio-authoring.org-override-registry-gate r7 · studio-authoring.org-scope-flows r2 · studio-authoring.permission-matrix-editor-ux r7 · studio-authoring.record-page-roundtrip r11 · studio-authoring.save-door-runs-authoring-rules r4 · studio-authoring.validation-rules-authoring r3
The per-clause verdict table is in the three comments below this body.
Derived item verdicts
37 PASS / 2 PARTIAL / 2 FAIL / 0 BLOCKED / 0 NOT-RUN (41 of 41 judged).
- FAIL (2): records-forms.list-view-capabilities (A8, R-1), records-forms.adhoc-filter-sort-builder (A3, N2, R-2)
- PARTIAL (2):
- records-forms.field-unique-enforcement: A3 and N2 are partial. The atomic REST
updateManyhalf was driven live (refusedROLLED_BACK+UNIQUE_VIOLATION, both rows re-read byte-identical). The predicate-update half isblocked(fixture): no REST door takes a predicate update at the subject (batchupdateManyis per id), so that half rests on the memory-driver pin. - records-forms.gantt-interactions: A1 is
blocked(fixture), because auto-schedule needs adependenciesFieldthat stockshowcase_taskdoes not declare and a field overlay is refused on stock (item knownGaps[0]). A2 is partial: the direct drag on a locked bar was proven live on alockField: 'done'view overlay (no PATCH, row unchanged; the control drag lands PATCH 200), and its "survives auto-schedule" half is blocked for the same reason.
- records-forms.field-unique-enforcement: A3 and N2 are partial. The atomic REST
- PASS (37): every other item.
Delta against the pins record #28965 (W4-C2b, same subject)
PARTIAL→PASS: 37 · PARTIAL→PARTIAL: 2 (field-unique-enforcement, gantt-interactions) · PARTIAL→FAIL: 2 (list-view-capabilities, adhoc-filter-sort-builder). Every one of the 41 items was PARTIAL there because no live leg ran. The two FAILs sit on clauses #28965 recorded skipped, so the pins themselves did not regress.
Delta against wave 3 (#27438, at c4c515ad)
| item | #27438 | here | why |
|---|---|---|---|
| records-forms.field-history-tracking | FAIL | PASS | A2: wave 3 looked for the History tab that record page v3 removed (#27055), so the clause was re-pointed to a network oracle (#27492, rev 11). Live here on 2 fresh loads: the account detail made exactly 1 sys_audit_log read and its Changes chip read "Industry Finance → Technology"; the task detail made 0. Scratch objects isolate the flag half: per-field flags alone gave 0 reads, enable.trackHistory gave 1 |
| studio-authoring.object-api-tab-curl | FAIL | PASS | A1/A2/N0: wave 3 met related_record_id in every reference and in owner_id, refused 400 reference_not_found (#27490). Live here: a draft-only field appears in the example body; the body leaves out owner_id and the optional lookup and shows the required lookup as <id of a showcase_contact record>; after substitution the five copied cURLs answered list 200, create 201, get 200, PATCH 200, DELETE 200. #27613's fix holds |
| records-forms.list-view-capabilities | PASS | FAIL | A8: the console now sends the aggregate api action through the action door (#27611), and that door refuses a record-less dispatch 400 (R-1). Wave 3 scored the request against the direct target URL the clause still names |
| records-forms.adhoc-filter-sort-builder | PASS | FAIL | A3/N2: driven this time through the realistic same-browser path (account-menu sign-out, then sign-in on the login page that opens), which carries the previous user's uf__* URL state (R-2). The per-user storage keys themselves are clean |
| records-forms.field-unique-enforcement | PASS | PARTIAL | A3/N2 predicate half: no REST predicate-update door at the subject; scored partial with the half named (RUNNER rule 6), not pass |
| records-forms.gantt-interactions | PARTIAL | PARTIAL | auto-schedule still needs a dependenciesField fixture |
| the other 35 | PASS | PASS | unchanged |
Wave-3 FAIL delta lines for the anchor:
records-forms.field-history-trackingA2: FAIL (QA run · release-18.3.0-w3-tier1-b (89/89) · c4c515ad · 2026-10-29 · 79 PASS / 6 PARTIAL / 4 FAIL / 0 BLOCKED / 0 NOT-RUN #27438) → PASS here; re-point checklist: re-point records-forms.field-history-tracking acceptance[2] to the record page v3 Timeline › Changes stream — the History tab it asserts was removed by design (#27055) #27492 holds.studio-authoring.object-api-tab-curlA1/A2/N0: FAIL (QA run · release-18.3.0-w3-tier1-b (89/89) · c4c515ad · 2026-10-29 · 79 PASS / 6 PARTIAL / 4 FAIL / 0 BLOCKED / 0 NOT-RUN #27438) → PASS here; fix Studio API tab: the example body puts the placeholder id "related_record_id" into every reference field (owner_id included), so the copied Create/Update cURL is refused 400 reference_not_found #27490 / fix(app-shell): Studio API tab example body leaves out owner_id and optional references #27613 holds.
Reproduction rule for every fail
R-1 · records-forms.list-view-capabilities · A8 (product defect; card in the close-out)
- Stock showcase boot; form sign-in as admin@objectos.ai.
- Open
/_console/apps/com.example.showcase/showcase_task/view/bulk_actions; tick three rows; clickgetByTestId('bulk-action-showcase_recalc_selection'); in the dialog click the "Run" button. - Network:
POST /api/v1/actions/showcase_task/showcase_recalc_selection{"params":{"_selectedIds":[ID1,ID2,ID3]}}→ 400VALIDATION_ERROR"Action "Recalculate Selection" identifies its record by "id", but that field is not present on the record — running without it would send a request that names no record." The dialog reads "Succeeded 0 / 3 · Failed 3"; the target is never called. - Expected: ONE aggregate dispatch carrying every selected id reaches the recalc target and succeeds.
- Controls: the same body plus
recordId→ 200; the targetPOST /api/v1/apps/showcase/recalc{"_selectedIds":[…]}called directly → 200 (selected: 2, acted: 2); the per-record bulk action (Mark Done) on the same bar succeeds.
Reproduced on 2 fresh browser loads (3-row and 2-row selections), by a forged API call, and by the orchestrator on a fresh boot. Mechanism (read at the subject):packages/runtime/src/action-execution.ts— a record-less dispatch reachesbuildApiActionRequestwithinput.record = {}; therecordIdParambranch (around L1428–1458) treats any object as a row, finds noidand refuses, although its own comment says a record-less dispatch should go out without the param.
R-2 · records-forms.adhoc-filter-sort-builder · A3, N2 (product defect; card in the close-out)
- Stock showcase boot. Mint a second member B (invite, then sign-up).
- In a fresh browser context, account A (admin) signs in through the form and opens
/_console/apps/com.example.showcase/showcase_task/view/in_progress. A adds two toolbar conditions in the filter builder (toolbar-filter-trigger: Estimate (h) greater than 10, Progress less than 80), searches "pipeline" and sorts Due Date newest first. - A opens the account menu and clicks "Sign out". The login page opens at
/_console/login?redirect=+ the list URL, with itsuf__filter,uf__sortanduf__searchparameters. - On that page B signs in.
GET /api/v1/auth/get-sessionreads B. - Expected: B's view opens with no toolbar filter, search or sort authored by A. Actual: B lands on A's list URL. B's toolbar shows A's 2 conditions, A's sort and A's search term. B's first
GET /api/v1/data/showcase_taskcarriessearch=pipeline&sort=-due_date&filter=[…estimate_hours>10…progress<80…].
Reproduced 2/2 in fresh browser contexts. The user-keyed storage is clean: A'slist-state:<A id>key andsys_user_preferencerow are A's, B has neither, and B gets 404 on A's preference row by id. So the vehicle is the redirect URL, not a cache. The rows B sees are still read under B's own permissions. Mechanism:ui/packages/app-shell/src/console/auth/LoginPage.tsxfollows?redirect=verbatim (L95), and the signed-out guard composes that redirect from the full path and query, which carries the list's URL-mirrored state (ui/packages/app-shell/src/views/userFilterUrlState.ts).
Fixture gaps (for the anchor, not cards)
- records-forms.gantt-interactions: auto-schedule (A1, and the second half of A2) needs a
dependenciesFieldon the task gantt; stockshowcase_taskdeclares none and no overlay path adds one. - records-forms.field-unique-enforcement: no REST predicate-update door, so the predicate half of A3/N2 is memory-pin only.
- studio-authoring.org-scope-flows: the clone fixture is stale. The clone door writes into
com.example.showcase.custom(ADR-0146 D4). The package-less flow was minted with a raw package-lessPUT /meta/flow, which ADR-0146 D11 schedules to close; after that this item has no fixture. - records-forms.conditional-rules-grid: stock INV-1002 ships one line, so the second line is added per run (as fixtures say).
- records-forms.cascading-multilevel-and-clear: no 3-level
dependsOnfixture (knownGaps, unchanged). - records-forms.bulk-select-all-matching: staging the >5000-row cap fixture costs about 15 minutes on 4 CPUs (createMany of 200 tasks takes 23–43 s because flows fire per row).
- records-forms.field-type-matrix:
f_user/f_users/f_ownerhold no value on "Specimen — Full", so their pickers render an empty "Select…" (the widget type is still observable). - studio-authoring.record-page-roundtrip: no stock non-admin persona reads
showcase_contact, so A3's end-user leg ran as admin (as personas[1] allows).
The checklist-accuracy findings (stale steps, routes and labels; the stale knownGap of bulk-select-all-matching) are listed in the anchor comment on #27377. They are not cards.
Off-clause probes (RUNNER rule 8)
About 51 minutes summed across the six runners (7 + 8 + 9 + 12 + 6 + 9), on each runner's own boot.
- Doors: clone, OCC PATCH/DELETE, unique writes,
updateMany, field-zoo constraint writes, the action door (unknown action/object/recordId, missing and undeclared params),/metadraft PUT with If-Match boundary values,/meta/_drafts, package revert,/meta/diagnostics,sys_commentcreate/patch/read, notifications read, sync import and import jobs (undo, cancel, results), the permission fields map, flow and app meta PUTs, the page aggregate's related rows, the export door,sys_user_preference, invoice line writes under a paid invoice,/api/v1/batch, and console flows (form clear, sort reset, Display popover, sign-out redirect, page publish). - Personas: the seeded admin, plain members, contributor-bound and manager-bound members, a non-authoring demo persona (
phone.demo), a member holding only a package permission set, and a notification bystander. - Boundary classes: empty string and whitespace, missing id, unknown id, object, type or package, malformed tokens, undeclared extra input, out-of-range values, empty selections, readers and writers outside the asserted scope, and the opposite posture (doors the UI hides).
- Found: seven product defects that pass the filing gate, extracted (numbers in the close-out). Plus one security finding:
records-forms.record-discussion-mentions · observed beside the clauses · security finding — detail withheld, reported to PM
A probe scores no clause, so no item verdict moves on it. - Observed, not extracted: the Sort popover's "Reset to view default" stayed disabled while a user sort differed from the view's empty declared sort. Its mechanism is untraced, and List personalization: 「恢复视图默认」 clears the reader's stored setting instead of copying the default into it — today the reader stays on the old value after the view changes #28948 reworked that reset after the subject. An api-forwarded action on a record the caller cannot see answers 400
FLOW_FAILED, where the declarative door answers 404. Exporting an unregistered object answers 403 rather than 404. Cancelling a finished import job answers 200 and changes nothing. An empty CSV creates a "succeeded" job with 0 rows. A permission fields-map key naming a missing field saves with no warning. The Project Detail header reads "Discussion (1)" beside two rows. A paid invoice is deletable over the API with its lines cascading, becauseuserActionspredicates are advisory by spec (packages/spec/src/data/object.zod.ts); the conditional-rules-header clauses check only the UI menu.
Time: environment prep vs testing
- Environment prep: orchestrator 25 min (install 26 s, full build 21m58s, console build and canary boot 2 min), runners about 30 min summed (scratch boots, personas, fixtures).
- Testing: about 190 min summed across the six runners, including 51 min of probes. Prep to testing is about 1 : 3.5.
- Wall clock 07:13Z to 08:45Z.
Activity
objectstack-fleet commentedon Nov 2, 2026
domain:devx#1 · os-warren · session_01JQwxbXSZs9PBUc2H8z6mtB
Per-clause verdicts (1/3): records-forms.
#28965is the pins-only verdict of W4-C2b;hereis this card's verdict. A clause the pins scoredpassis cited, not re-run; every other clause was driven live on a booted stack at7fa9873f.scaleis not valid on acurrencyfield'; zoo f_currency 1234.567 → 201 re-read 1234.567 (unrounded)unique: trueon an object WITH a tenant column scopes per organization' + sql-driver-8577 'AFTER: the same cross-organization create is accepted — 409 flips to 201'; live two-org probe not provisioned (knownGaps[2]).label (name)and disables Next' and 'clears the hint and enables Next once the required column is supplied'objectstack-fleet commentedon Nov 2, 2026
domain:devx#1 · os-warren · session_01JQwxbXSZs9PBUc2H8z6mtB
Per-clause verdicts (2/3): records-forms.
#28965is the pins-only verdict of W4-C2b;hereis this card's verdict. A clause the pins scoredpassis cited, not re-run; every other clause was driven live on a booted stack at7fa9873f.objectstack-fleet commentedon Nov 2, 2026
domain:devx#1 · os-warren · session_01JQwxbXSZs9PBUc2H8z6mtB
Per-clause verdicts (3/3): studio-authoring.
#28965is the pins-only verdict of W4-C2b;hereis this card's verdict. A clause the pins scoredpassis cited, not re-run; every other clause was driven live on a booted stack at7fa9873f.titelis not a proppage:headerdeclares … Did you meantitel→title?'objectstack-fleet commentedon Nov 2, 2026
domain:devx#1 · os-warren · session_01JQwxbXSZs9PBUc2H8z6mtB
Close-out (RUNNER extraction obligation, checklist-test §5). Every FAIL has a disposition, and each probe finding that passed the filing gate is extracted with a
QA-source:line.Extracted: #29173 · records-forms.list-view-capabilities · A8
Extracted: #29174 · records-forms.adhoc-filter-sort-builder · A3, N2
Extracted: #29175 · records-forms.list-view-capabilities · observed beside the clauses
Extracted: #29176 · records-forms.field-unique-enforcement · observed beside the clauses
Extracted: #29177 · records-forms.field-type-matrix · observed beside the clauses
Extracted: #29179 · studio-authoring.metadata-diagnostics-sweep · observed beside the clauses
Extracted: #29180 · studio-authoring.meta-save-preconditions-and-draft-rows · observed beside the clauses
Extracted: #29181 · studio-authoring.actions-tab-presets · observed beside the clauses
Extracted: #29182 · studio-authoring.record-page-roundtrip · observed beside the clauses
Parked-on: #27377 · checklist-accuracy findings, fixture gaps and the partial gaps of records-forms.field-unique-enforcement and records-forms.gantt-interactions (anchor comment 6573003409)
Dispositions: R-1 and R-2 are product defects. R-1 is a regression against wave 3: it came when the console started routing api actions through the action door (#27611). A8's step text also names the old direct URL, which is an accuracy line on the anchor. The two PARTIALs are fixture gaps, not defects.
Generated by Claude Code