Skip to content

QA run · release-18.4.0-w1-owed (11/11) · ff04ad81 · 2026-11-10 · 5 PASS / 2 PARTIAL / 4 FAIL / 0 BLOCKED / 0 NOT-RUN #32102

Closed

Description

@objectstack-fleet

qa#2 · os-bob · session_012dn2Acf5wtyrf2yKWCThBj

Runner session_012dn2Aej8bK94WiqAMApccX (cloud, effort high), dispatched by qa#2 (#32023) as round 1, slice R1: an early probe of the 18.4.0 release wave, on the maintainer's word 「开跑」. The runner staged the record; the seat posts it through the relay. The seat cross-checked the mechanisms of cards A, D, P-1, P-2 and P-3 against the subject's source.

This record covers the owed retest list release-18.4.0-w1-owed (scripts/qa/retest-owed.mjs): 11 items whose QA-extracted fix cards closed after their last verdict.

Result: 11/11 judged · 5 PASS / 2 PARTIAL / 4 FAIL / 0 BLOCKED / 0 NOT-RUN. No planned item. No security finding.

Environment fingerprint

  • Framework: ff04ad811da54166a5d1114fade5a1a6ab99138c (main, 2026-11-10), detached. ui/ is the in-tree import at the same commit, and the Console was built from it.
  • Build: one cold cloud container. pnpm install --frozen-lockfile 19 s; pnpm build --concurrency=2 119/119 tasks in 10m26s; pnpm console:build a cache hit plus copy; check-dev-prereqs 107 artifacts.
  • Slices: the main session plus three runner sub-agents (effort high) in the same container, in parallel. Each item had its own port and file DB under /tmp. Boots were objectstack dev --ui --seed-admin --no-compile --no-watch -p PORT -d file:/tmp/... with OS_PORT and OS_STORAGE_LOCAL_ROOT exported, unless an item's fixture says otherwise.
    • main: access-security, cli, platform-core.seed-mode-matrix, studio-authoring.meta-save (ports 41441–41458)
    • s1: automation.screen-flow-roundtrip, platform-core.url-overlay-contract, studio-authoring.expression-editors (41410–41412)
    • s2: the two ux-conventions items (41420–41421)
    • s3: identity-auth.auth-method-matrix, integration-system.email-template-render (41430–41435, SMTP sink 41439 via plugin-email startFakeSmtp)
  • Seed and personas: the stock showcase seed and seeded admin. Members were made by invite plus sign-up with invitationId, or by admin create-user on walled boots. Identity was proved server-side before each persona's cells.
  • Walled boots: OS_TENANCY_POSTURE=group and isolated, OS_PLATFORM_OWNER_EMAIL=admin@objectos.ai, OS_AUTH_MEMBERSHIP_POLICY=invite-only, from the tree.
  • Older databases:
    • v17: a create-objectstack@17.7.0 blank scaffold booted once by its own 17.7.0 os dev.
    • 18.0 pre-release: the committed cli-18-prerelease-db restore.
  • Hygiene: every port free at the end, git status clean, .objectstack/installed-packages empty. One apply report escaped into the tree and was moved out at once (cli item).
  • Rule 7: a second, independent agent re-derived the P0 FAIL (access-security acceptance[4] and [6]) from the captured evidence alone. It agreed: FAIL, stale spec.
  • Spend: runner session $31.07 (get_session usage.cost_usd, sub-agents included).

Scope

Selector release-18.4.0-w1-owed: 11 ids, each resolved with node scripts/checklist-select.mjs ID --json. access-security was resolved with --include-blocked: its blocked marker (#9334) hides it, but its walled-boot fixture is provisionable on this tree, so it was run.

access-security.no-active-org-session-semantics r9 · automation.screen-flow-roundtrip r7 · cli.organization-ownership-ceremony r9 · identity-auth.auth-method-matrix r10 · integration-system.email-template-render r17 · platform-core.seed-mode-matrix r8 · platform-core.url-overlay-contract r5 · studio-authoring.expression-editors r9 · studio-authoring.meta-save-preconditions-and-draft-rows r3 · ux-conventions.disabled-control-reason r6 · ux-conventions.labels-over-machine-names r4

Derived item verdicts

Per-clause verdict tables

access-security.no-active-org-session-semantics r9 (P0 api) · main · 41443 (group), 41444 (isolated)

Fixture: a walled boot of the stock showcase (RUNNER "A walled boot is a fixture of its own"). Both postures booted with no FATAL.

Producer (2) of knownGaps[0]:

  1. The operator creates org A and org B (POST /api/v1/auth/organization/create, 200 each).
  2. The operator seeds a showcase_account in B as the cross-tenant control.
  3. With A active, the operator mints member M by POST /api/v1/auth/admin/create-user (200, organizationId A, membershipCreated true).
  4. M changes its password, signs in, sets A active, then POST /api/v1/auth/organization/set-active {"organizationId": null} (200).
  5. GET /api/v1/auth/get-session reads activeOrganizationId null.

Producer (1), a member-less user, has had no door since #25626, so its legs are blocked(fixture) per knownGaps[0].

clause verdict evidence
acceptance[0] pass isolated: M reads showcase_account, showcase_project and showcase_task → 200, 0 rows each. group: 200 with 14, 5 and 10 rows, all organization_id A, none of B. The producer (1) leg is blocked(fixture).
acceptance[1] pass Both postures: M POST /api/v1/data/showcase_task → 403 PERMISSION_DENIED "… this session has no active organization — so this insert has no organization to place the record in. Join or select an active organization and retry."
acceptance[2] pass Admin-side SQLite count of NULL or empty organization_id: showcase_task 0 → 0, showcase_account 0 → 0. Task total 30 → 30.
acceptance[3] pass M (no active org): GET org B's showcase_account row → 404; PATCH → 403; GET /api/v1/sharing/rules → 403 (manage_sharing). Pin sharing-rule-org-less-caller.dogfood.test.ts green.
acceptance[4] fail M's raw sys_audit_log rows, both postures: login A, login A, logout with tenant_id NULL (sent while the session had no active org), login A. The operator reads it (200); M gets 403 (object permission). → R-1
acceptance[5] pass get-session 200. M reads sys_user 200 and meta/object/showcase_task 200. Zero 5xx and zero "Unhandled error".
acceptance[6] fail Sharing refuses (403) and layer 0 and the write path scope or refuse, but the audit ledger accepts a NULL-attributed logout row for the same state. → R-1 (same root)
acceptance[7] pass Walled group, producer (2) with membership {A}: POST showcase_task → 403 (the acceptance[1] envelope, not 500 ERR_SYSTEM_WRITE_ORGANIZATION_REQUIRED), again on a second sign-in. NULL count 0 → 0. Control: with A active → 201, organization_id A. #24784 HOLDS live.
negatives[0]–[5] held No cross-tenant read or write; no NULL-stamped row; the acceptance[4] row is visible to the operator; no 5xx; the refusal names the missing org; the code is PERMISSION_DENIED.

Pins: plugin-security no-active-organization-write-refusal.test.ts and no-active-organization-insert-union-scope.test.ts (29 passed); dogfood no-active-organization-write-refusal.dogfood.test.ts and sharing-rule-org-less-caller.dogfood.test.ts (22 passed).

cli.organization-ownership-ceremony r9 (P0 cli) · main · 41450–41458

v17 database: a blank create-objectstack@17.7.0 scaffold (npm install --legacy-peer-deps). Its own 17.7.0 os dev --seed-admin booted once over file:/tmp/qa/v17/db/v17.db. Copies c1–c4 and H were taken from it (sha256 3a84e5c9…). The ceremony legs ran as a production os serve with OS_AUTH_SECRET and OS_SECRET_KEY set; the 18.0 leg ran under --dev.

clause verdict evidence
acceptance[0] pass 9 pin files green at ff04ad8 (cli apply-flags 7, organization-ownership-apply 117, occupancy.integration 5, dialect 19, apply-organization-ownership-gate.integration 5, comment-reactions.integration 7, host-supplement.integration 7, apply.generation-1 17; runtime organization-ownership-boot-guard 30).
acceptance[1] pass First os serve over c1 → exit 1, refusal. Bare plan → exit 0, organization-ownership-plan, ceremony "ADR-0131 D10", 150 table rows ("127 table(s) planned … 74 will receive NOT NULL"). Primary sha256 unchanged. --apply without --plan-file → exit 1 apply_refused / plan-file-required (text: "✗ Refused: --apply executes only a plan you reviewed."); checksum unchanged.
acceptance[2] pass --apply --plan-file plan.json --backup-taken --out apply.json --json → exit 0, complete, blocking 0, 13 steps done. sys_migration adr-0131-organization-ownership verified, shapeGeneration 1 equals ORGANIZATION_OWNERSHIP_SHAPE_GENERATION.
acceptance[3] pass os serve over migrated c1 → ready, health 200. Over unmigrated c2 → exit 1 "✗ This database carries no organization-ownership marker …" with "Run 'os migrate organization-ownership --out PLAN' …". 0 hits for "17.x release". The --dev 18.0 boot printed the --dev form of the command.
acceptance[4] pass Fresh c4: comment-reactions --apply without --yes → exit 1; with --yes twice → exit 0. Then os migrate apply --allow-destructive --yes --json → exit 1 refused_organization_ownership_unmigrated naming 9 tables, "applied":[], sha256 unchanged.
acceptance[5] pass cli-18-prerelease-db restore (the committed dump), reset token re-dated. The census matched the manifest. serve --dev → exit 1 naming sys_flow_credential and sys_secret; plan → exit 0; apply → exit 0, complete, blocking 0 (sibling-moves moved 10, jobsRewritten 2, mirrorsDeleted 1, column-drops 2). Second boot ready. Identity mails moved to sys_identity_email (24 common columns equal except updated_at and attempt_count); invitation mails stay; 8 global audit rows moved to sys_platform_setting_audit; 2 identity-mail jobs re-pointed. Admin, member A and member B sign in with their 18.0 passwords (wrong password → 401). The reset token from the moved mail works. One showcase_task PATCH → exactly one sys_http_delivery row, ref_id declared:showcase_task_changed. The only unlisted count decrease is telemetry sys_activity__r20261027 (66 rows), which is sys_activity's 14-day rotation, not the apply (A-3).
negative[0] held The plan run and every refusing arm left the checksum unchanged.

#31488 HOLDS. os start --no-ui --no-compile --home H over a v17 copy → exit 1, and the printed commands carry --database-url file:H/data/objectstack.db and the auth secret. Run verbatim with OS_HOME and OS_DATABASE_URL unset, the plan writes and the apply completes; os start --home H then boots. A path with a space is quoted correctly.

Hygiene: the verbatim apply (no --out) wrote its report into examples/app-showcase/. It was moved out at once. Not a defect: the ceremony prints where it wrote.

platform-core.seed-mode-matrix r8 (P1 api) · main · 41441

Fixture: writable package com.objectstack.qa.seedmodes (namespace seedmodes) with object seedmodes_probe (name, value, other; private). Seeds authored as drafts and applied by POST /api/v1/packages/com.objectstack.qa.seedmodes/publish-drafts.

clause verdict evidence
acceptance[0] pass upsert {A:a1, B:b1} → inserted 2. A.other edited at runtime. upsert {A:a1, B:b2, C:c1} → inserted 1, updated 1. B keeps its id with value b2. A is unchanged, updated_at identical (a no-op skip despite the runtime edit).
acceptance[1] pass update {A:a2, D:d1} → updated 1, inserted 0; count 3 → 3; D absent.
acceptance[2] pass ignore {A:a3, E:e1} → A keeps a2, E inserted. Probe: a seed with no mode → A keeps a2, H inserted, so the default is ignore.
acceptance[3] pass insert re-declaring A → a second A row on the unconstrained object.
acceptance[4] pass F hand-inserted; replace {G} → F survives, G inserted. Source: seed-loader.ts case 'replace' routes to insert ("caller should have cleared the table").
acceptance[5] pass SeedMode has 5 members, SeedSchema.mode defaults to 'ignore' (seed.zod.ts:207); seam dataset.mode || config.defaultMode (metadata-protocol seed-loader.ts:1303).
negative[0] held The second idempotence replay: inserted 0, updated 0, every updated_at unchanged.
negative[1] held update created nothing; ignore rewrote nothing.

Observation (knownGaps[2], not scored): after the insert duplicate, upsert bound A to the newer duplicate. #31497 HOLDS.

studio-authoring.meta-save-preconditions-and-draft-rows r3 (P1 api) · main · 41442

clause verdict evidence
acceptance[0] pass 5 pins green (rest meta-item-version-token-occ 15, meta-draft-head-package-inheritance 25; runtime meta-save-preconditions-parity 23; objectql sys-metadata-repository-list-drafts 6, protocol-metadata-row-actor 4).
acceptance[1] pass Draft PUT 200; If-Match with the served version → 200; the stale If-Match → 409 METADATA_CONFLICT with currentVersion; If-None-Match: * while only the draft exists → 200, then 409 once active exists; If-None-Match: "abc" → 400; both headers → 400. The active label is unchanged.
acceptance[2] pass GET /api/v1/meta/_drafts → the row with type, name, label, packageId null and updatedBy the admin id.
acceptance[3] pass History → 4 events, every actor the admin id, matching the _drafts row's updatedBy.

#31490 HOLDS. ?package= unknown → 400; a package filter scopes the list; &type= filters; ?packageId= and ?bogus=1 → 400 VALIDATION_ERROR "Supported parameters: package, type". Probe finding: card P-3.

automation.screen-flow-roundtrip r7 (P1 browser) · s1 · 41410

clause verdict evidence
acceptance[0] pass The row menu → POST /api/v1/actions/showcase_task/showcase_bulk_reassign → 200 paused, screen.nodeId collect. No trigger-route POST.
acceptance[1] pass GET runs/ID/screen → 200, field new_assignee (text, required).
acceptance[2] pass Modal "Reassign Task · Step 1 of 1" with a required "New Assignee" input, Cancel and Submit. The DOM has one heading and one #ff-new_assignee.
acceptance[3] pass Resume with the input → 200; run completed (start, collect, apply).
acceptance[4] pass The task's assignee is the submitted email.
acceptance[5] pass Resume with {} inputs → 400 INVALID_SCREEN_INPUT "is required"; the run stays paused; a later valid resume completes.
acceptance[6] pass Cancel or Escape → no resume POST, run paused; a valid resume then completes.
negatives[0]–[1] held Not consumed on a bad resume; not cancelled by a dismiss.

#31491 HOLDS. Non-string values (42, objects, arrays, booleans) → 400 "must be a string"; null and blank → 400 "is required"; the run stays paused and a later valid resume completes. Replayed on a second run.

platform-core.url-overlay-contract r5 (P1 browser) · s1 · 41411

clause verdict evidence
acceptance[0] pass The ?recordId= drawer, ?form=new and edit-from-drawer each push one entry, and Back unwinds them in order.
acceptance[1] pass Six tab switches: leaving Overview pushes once, every later switch replaces ?related=. Back → bare record, then the list.
acceptance[2] pass A cold tab on ?related=showcase_contact.account selects Contacts.
acceptance[3] pass Hooli → Invoices → New gives ?form=new&formObject=showcase_invoice&formLink=account:ID with the account pre-linked; a cold load gives the same.
acceptance[4] pass Related hrefs carry from=. The two-level record-page-trail breadcrumb links up one level each and survives a reload.
acceptance[5] pass forms/showcase_task.form?recordId=TASK&recordObject=showcase_project → refused ("This form edits showcase_task, but the link says record … belongs to showcase_project"), with no form and no data read. Case variants are refused the same way.
negatives[0]–[3] held Covered above.

Pins: FormPage.recordObject.test.tsx and useUrlOverlay.test.tsx (17 passed). #31498 HOLDS.

studio-authoring.expression-editors r9 (P1 mixed) · s1 · 41412

Fixture: writable package com.qa.s1expr, object s1expr_est (numbers est_hours, a, b; formulas f_total, f_sib), permission set s1expr_rls. Engine side: live MCP validate_expression and the permission publish door.

clause verdict evidence
acceptance[0] pass record.est_hours * 1.1 → "Valid CEL · Result type: Number". record.a + record.b → "Unknown … Wrap operands in double() / int() / string()". MCP agrees.
acceptance[1] pass Editing f_total only and publishing → f_total returnType number, f_sib still text.
acceptance[2] pass A misspelt field → "unknown field … did you mean est_hours?"; a bare reference → error with no PUT; a non-pushdownable RLS predicate → editor error, publish 422 rls-predicate-unenforceable.
acceptance[3] pass previous. and record. list all 7 fields; current_user. and parent. offer none; accepting inserts record.status.
acceptance[4] fail Non-pushdownable and parse-fault predicates are held with no PUT. The formula-field USING predicate record.f_total > 5 is not held on its first autosave: the client reads "Valid CEL", the draft PUT → 200, and only the re-read shows the server verdict (INVALID_FIELD). Each new guard text PUTs again; edits beside it are then held; publish → 422. → R-2
acceptance[5] pass The Test policy dialog's Allowed, Denied and "Non-boolean result: 3" match ExpressionEngine.evaluate.
acceptance[6] pass The editor tier equals the engine on all 9 probes.
acceptance[7] pass 6 ui test files, 95 passed.
negative[0] held No editor-versus-engine divergence.
negative[1] fail Same root as acceptance[4]: a refused formula-field RLS predicate saves to the draft; publish still refuses it (422), so it never goes live. → R-2
negative[2] held No unbound-root members offered; bare references flagged.

#27482 HOLDS against its ruled acceptance (PR #31549, "Acceptance reading (seat ruling on the step-1 report)").

ux-conventions.disabled-control-reason r6 (P1 browser) · s2 · 41420

Controls V0–V5 and Publish-with-no-drafts were driven on 2 fresh loads each, with a real pointer hover and real Tab presses.

clause verdict evidence
acceptance[0] fail Studio Form tab "Move group up/down" and the Studio New object "Save as draft" with an empty name: hover shows no tooltip and no adjacent text. Every other control shows its reason. → R-3
acceptance[1] fail Those three are native disabled with no wrapper, aria-describedby or title, and Tab never reaches them. The All-metadata Save (resource-save) carries "No changes to save" only as title and aria-label on a natively disabled button. Every passing control sits on a tabindex=0 wrapper whose aria-describedby resolves to the reason. → R-3
acceptance[2] fail The reason is absent for those controls; every other reason is specific. → R-3
negative[0] held No leftover reason on enabled controls.
negative[1] held For the member, the list toolbar's Reassign… is absent rather than disabled (A-9).

#31493 HOLDS (import "Save current": tabindex=0 wrapper, aria-describedby "Map at least one column to save a template.", tooltip on hover and focus). #31495 HOLDS (Studio Publish "No drafts pending publish", the same treatment).

ux-conventions.labels-over-machine-names r4 (P1 browser) · s2 · 41421

Fixture: package com.qa.lbl (object "Gadget Thing", permission set "Gadget Editors", app nav "My Gadget Shelf"). A member bound as contributor, interface language 简体中文.

clause verdict evidence
acceptance[0] fail Setup → Audit log, Record column: j7snASPp… → showcase_contributor, the position machine name, although GET /api/v1/meta/position/showcase_contributor has label "Contributor". Every other surface checked renders labels. → R-4
acceptance[1] fail The same cell shows the member as a raw user id (sys_user name "QA Member S2"). The same text is the record title in Setup → User Positions (list Title column and record H1). → R-4
acceptance[2] pass Every machine name met sits beside its label in smaller mono or muted text.
acceptance[3] pass No platform-built text carries ADR or issue references.
negative[0] not met No label-less item was met.

#31494 HOLDS (PATCH → 404; the toast reads 「这条任务记录已不存在,或者您已无权访问它。」 and the card snaps back).

identity-auth.auth-method-matrix r10 (P1 mixed) · s3 · 41430 (dev; phone and 2FA on), 41431 (stock), 41432 (production serve; phone on, no SMS), 41435 (OS_AUTH_URL issuer)

clause verdict evidence
acceptance[0] email, phone, OTP, 2FA, magic-link, passkeys pass /auth/config features match each boot (phoneNumberOtp false without SMS; all off on stock; emailPassword flips with the setting; magicLink and passkeys absent).
acceptance[0] SSO and device variants blocked(environment) knownGaps[3]: no device switch and no reachable IdP.
acceptance[1] pass Email sign-in, session, sign-out, then 401. Sign-up → 403 SELF_REGISTRATION_CLOSED.
acceptance[2] pass Phone sign-in 200; the session names "Mei Phone (demo)".
acceptance[3] pass Production boot with no SMS: send-otp → 400 SMS_SERVICE_REQUIRED. Control → 200.
acceptance[4] pass Phone and OTP controls appear only where advertised.
acceptance[5] pass All-off boot: every disabled method → 404 (social → PROVIDER_NOT_FOUND); email off → 400 EMAIL_PASSWORD_DISABLED.
acceptance[6] pass Password → twoFactorRedirect + cookie → session 401 → verify-totp 200 → session holds the user.
acceptance[7] pass OIDC and two-factor-lockout dogfood pins, 8 passed.
acceptance[8] pass Both .well-known docs 200 with issuer /api/v1/auth; jwks_uri byte-equal; the issuer follows OS_AUTH_URL.
acceptance[9] pass Unit pins 25 passed; change-email and delete-user door checks.
negatives[0]–[4] held No 2xx on a disabled method; loud OTP 400; nothing unmounted advertised.

#31492 HOLDS (phone-only card, no SSO view, server refuses email sign-in).

integration-system.email-template-render r17 (P2 mixed) · s3 · 41433, 41434 (writable copy), SMTP sink 41439

clause verdict evidence
acceptance[0] pass Delivered at the sink "Subject: ✅ Task done: Ship the QA build", no {{ residue, row sent.
acceptance[1] pass No title → dead MISSING_VARIABLES; no project → sent with an empty slot.
acceptance[2] pass An inactive template → dead TEMPLATE_INACTIVE.
acceptance[3] pass zh-CN and zh recipients get 「✅ 任务完成:…」; ja-JP falls back to English.
acceptance[4] pass From override, Reply-To and a derived text/plain part on the wire.
acceptance[5] pass Admin overlay PUT 200, package-less PUT 403; the edit survives a reboot. Declared-source half: an edit on a writable copy plus objectstack compile is served about 4 s later with the PID unchanged.
acceptance[6] pass content → "Did you mean content → bodyHtml?"; a bad name → refusal; meta door 422 / 400.
acceptance[7] pass (no-provider 501 from the pin only) Admin send 200; anonymous 401; member 403; forged from, sentBy, headers, organizationId and identityMail → 403 with no row; non-object bodies → 400 with no row. The no-provider 501 is scored from the unit pin (rule 6).
negatives[0]–[2] held

#31496 HOLDS (array and non-object bodies → 400 INVALID_REQUEST, no row).

Repro rules (every FAIL)

R-1 · access-security · acceptance[4], [6] · stale spec.

  1. Boot walled as above.
  2. Create org A and set it active.
  3. Create member M in A.
  4. As M: change the password, sign in, set-active {"organizationId": null}, then sign out.
  5. Read sys_audit_log in the telemetry sibling for M.

The logout row has tenant_id NULL. Mechanism: plugin-auth auth-session-audit.ts logoutEventFor takes the session's activeOrganizationId; plugin-audit auth-event-audit.ts writes tenant_id: event.organizationId ?? null. ADR-0131 D7 makes sys_audit_log deployment-level, "governed by object permission, not by the wall", and its 2026-10-22 note keeps the NULL arm by design. The clause predates D7. The residual question (should such a logout be attributed?) goes to the maintainer through the re-point card.

R-2 · expression-editors · acceptance[4], negative[1] · stale spec.

  1. In Studio, open permission set s1expr_rls → RLS tab → Add policy, object s1expr_est.
  2. Enter the USING predicate record.f_total > 5.

The draft PUT → 200, and the re-read shows INVALID_FIELD. Later edits are held, and publish → 422. This is #27482's ruled acceptance (PR #31549). Reproduced on 2 loads.

R-3 · disabled-control-reason · acceptance[0]–[2] · product defect. Studio form "Move group up/down", Studio New object "Save as draft" with an empty name, and the All-metadata Save: native disabled, no reason on hover or keyboard focus. Cards below. Reproduced on 2 loads each.

R-4 · labels-over-machine-names · acceptance[0], [1] · product defect. sys_user_position's record title formula record.user_id + ' → ' + record.position is rendered as the title in Setup → User Positions and the audit log. Card below.

§5 dispositions

fail disposition
R-1 stale spec (ADR-0131 D7/D9) → re-point card
R-2 stale spec (#27482's ruled acceptance, PR #31549) → re-point card
R-3 product defect → three cards
R-4 product defect → one card

Off-clause probes (rule 8)

About 25 runner-minutes, after every clause had a verdict, on the same boots.

  • main: seed modes and bad input; _drafts parameters; If-Match edges; no-active-org PATCH and bulk; a path with a space. Found the draft-door wording card.
  • s1: screen-flow input edges; overlays by URL; formula CHECK; unbound roots. Nothing found.
  • s2: Studio controls on read-only and writable packages; import wizard; flow inspector. Found the field "Move up" (folded into the form-designer card) and the User Positions surface.
  • s3: login card states; phone versus email with two-factor; forged method calls; send-door body edges. Found the phone two-factor card and the send-door type card.

Checklist-accuracy notes and fixture gaps (not extracted)

  • A-1 access-security:
  • A-2 cli: an apply without --out writes its report into the working directory; steps[1] could say to pass --out.
  • A-3 cli-18-prerelease-db recipe: the restored sys_activity__r20261027 shard is dropped by the 14-day rotation once the dump is 14 days old. The recipe needs a knownGaps line.
  • A-4 auth-method-matrix:
    • The phone fixture is the seeded phone.demo@example.com (+8613800138000).
    • A production boot needs objectstack serve with OS_DATABASE_URL, OS_AUTH_SECRET and a 32-byte OS_SECRET_KEY.
  • A-5 email-template-render:
    • The declared-source half is drivable from a /tmp copy plus objectstack compile.
    • The 403 envelopes are nested {error:{code,message}}.
  • A-6 url-overlay:
    • The "← PARENT link" is now the record-page-trail breadcrumb.
    • Few-children accounts collapse tabs into "+N".
  • A-7 screen-flow: automated.ref could add src/builtin/screen-string-field-resume.test.ts; the run read has no current-node field.
  • A-8 expression-editors: the formula textarea id is field-formula-FIELD; Escape closes the inspector.
  • A-9 disabled-control-reason:
  • A-10 labels-over-machine-names: add User Positions and the audit Record column as variants; Node Type options need a writable flow.
  • A-11 seed-mode-matrix: a seed draft naming a nonexistent object publishes "published" while seedApplied.success is false (the declared failures-returned behaviour, recorded only).

Wall clock

  • Environment: 06:54–07:06Z, about 12 min. The v17 scaffold ran in parallel, about 3 min.
  • Testing: 07:06–07:45Z, about 39 min, four runners in parallel. About 30 runner-minutes setup to 86 testing (about 1 : 3).

Activity

  1. objectstack-fleet commented on Nov 10, 2026

    @objectstack-fleet
    ContributorAuthor

    qa#2 · os-bob · session_012dn2Acf5wtyrf2yKWCThBj

    Close-out · 2026-11-10T08:03Z

    Extracted: #32103 · ux-conventions.disabled-control-reason · acceptance[1]
    Extracted: #32104 · ux-conventions.disabled-control-reason · acceptance[0]
    Extracted: #32105 · ux-conventions.disabled-control-reason · acceptance[1]
    Extracted: #32106 · ux-conventions.labels-over-machine-names · acceptance[1]
    Extracted: #32107 · identity-auth.auth-method-matrix · off-clause probe
    Extracted: #32108 · integration-system.email-template-render · off-clause probe
    Extracted: #32109 · studio-authoring.meta-save-preconditions-and-draft-rows · off-clause probe
    Extracted: #32111 · access-security.no-active-org-session-semantics · acceptance[4] (re-point, stale spec)
    Extracted: #32112 · studio-authoring.expression-editors · acceptance[4] (re-point, stale spec)
    

    Every fail has its §5 disposition: R-1 and R-2 are stale specs (re-point cards #32111 and #32112), and R-3 and R-4 are product defects (#32103 to #32106). The two partials name their gaps in the record: SSO and device variants are blocked(environment) by knownGaps[3], and the no-provider 501 rests on the unit pin. The checklist-accuracy notes A-1 to A-11 stay in the record body. Retests follow through retest-owed.mjs when the fixes land. The record closes now.

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