Skip to content

QA run · tier1:automated-pins (77 items) · e4e5c6e3 · 2026-08-17 · 35 PASS / 39 PARTIAL / 0 FAIL #9401

Closed

Description

@os-zhuang

Round R3-T1 of the #9296 wave — Tier-1 automated-pin sweep. Scope: the 77 active, non-blocked checklist items that carry an automated.ref, run per RUNNER rule 6 ("don't re-prove what automation pins"). Verdicts below are pinned-clause verdicts only — the unpinned clauses of these items are Tier-2's, and nothing here was hand-driven.

35 PASS · 39 PARTIAL · 0 FAIL · 3 BLOCKED. No clause failed as a product defect, and no access-control hole was found. The headline is the PARTIAL column: the pins are real and green, but on 39 of 77 items the pin reaches only a subset of the item's acceptance clauses. Every gap is named in the "Coverage gaps" section — that list is the round's most reusable output.

Environment fingerprint

framework sha (subject) e4e5c6e3c608b1b807c83a0d5b734f213eb1a1dd (detached, tree clean, subject not moved)
objectui pin .objectui-sha = 665661ab093263f39f2e660a295ea615dbcee35a
objectui test tree .cache/objectui-665661ab0932 — a full checkout at the pinned sha with node_modules already installed, so objectui unit pins ran against the pin rather than against the sibling checkout (which sits at 195b9e4ab, a different sha)
worktree objectstack-qa-wave
checklist 190 items (190 active); 30 kinds mapped, 0 waived — check-platform-checklist: OK, working-tree sync not committed
item set resolved with checklist-select.mjs area:<a> --json x 15 joined to areas/*.json for the automated object; 77 pinned+active, matching the dispatch counts exactly (records-forms 24, access-security 8, attachments-storage 8, integration-system 6, studio-authoring 6)
node / runners node 22.22.2, vitest 4.1.10, @playwright/test 1.62.1 with executablePath=/opt/pw-browsers/chromium-1194/chrome-linux/chrome
totals executed 76 pinned test files, 953/954 assertions green; + 35 playwright smoke; + 18/29 objectui live e2e; + 2 objectstack verify invocations

Pin inventory was checked before running: all 35 framework refs and all 25 objectui refs resolve to real files. Two refs name companion tests by bare name only — access-security.scope-depth-asymmetry (showcase-scope-depth-write, -fallback) and records-forms.import-wizard-encoding-and-hints (importMissingRequiredHint, importLegacyReferenceGuard, which actually live in plugin-grid/src/__tests__/*.tsx). Both resolve; noting them only because a bare name costs the next runner a search.

Batch commands and real output

1 — dogfood (33 pinned files, one invocation) · packages/qa/dogfood · npx vitest run test/<33 files>

Test Files 33 passed (33) · Tests 283 passed | 1 skipped (284) · Duration 169.90s

The single skip is attachments-permission-matrix > attachments cross-tenant isolation (g), gated by describe.skipIf(!organizationsAvailable). That probe resolves the cloud-private enterprise package @objectstack/organizations through the production resolver; it is absent in this OSS workspace, so the block skips by design and loudly (OS_TEST_MULTI_ORG_ENABLED=1 turns the skip into a hard failure for runs that ship the package). This is blocked(dependency), not a defect — but it does mean every cross-tenant attachment clause is unproven here.

2 — objectql · npx vitest run src/{engine,engine-lookup-referential-integrity,engine-autonumber-runtime-owned,secret-fields,overlay-precedence}.test.ts src/validation/rule-validator.option-visibility.test.ts

262 passed, 0 failed — engine 135/135 · autonumber 32/32 · secret-fields 36/36 · overlay-precedence 26/26 · lookup-RI 13/13 · option-visibility 20/20

3 — mcp / cli / services / connectors (5 invocations, sequential)

mcp 37 passed (plugin 17, skill-prompts 12, validate-expression 8) · cli 11 passed (verify-tenancy-posture 7, format.exit-code 4) · service-automation 31 passed (resume-authority-gate 22, connector-descriptor-audit 9) · connector-mcp 13 passed · service-datasource 54 passed (admin-routes 30, envelope.conformance 24)

4 — scope-depth companions · npx vitest run test/showcase-scope-depth-{write,fallback}.dogfood.test.ts

13 passed (write 9/9, fallback 4/4)

5 — objectui unit pins (25 files, one invocation, run in the pinned-sha cache)

249 passed, 0 failed, 25 files — celAuthoring 34 · CelPredicateField 24 · importParsers 30 · UndoManager 28 · bulkAction* 30 · gantt 22 · discardGuard 14 · RecordPicker/Lookup 18 · occSave 8 · calendar dnd 8 · grid personalization 10 · PermissionMatrixEditor 10 · others

6 — objectstack verify --rls · examples/app-showcase · node packages/cli/bin/run.js verify --rls

✓ verify passed — no runtime failures
CRUD: 15 verified, 0 gaps, 0 FAILED, 1 needs-fixture, 7 skipped (0 mismatches)
RLS: 20 PROVEN (20 consistent, 0 HOLES) · 3 NOT PROVEN (0 member-visible, 0 probe-blocked, 3 skipped)
position personas: 9 of 9 declared position(s) probed · all personas: 35 PROVEN (35 consistent, 0 HOLES)

Confirms R1 finding #1 — --rls is a separate invocation and bare verify emits no RLS section. The run's own ⚠ 3 of 23 objects were NOT proven is a coverage caveat (2 external federated read-only objects + 1 with no plain-text probe field), not a hole. Two personas (exec, auditor) proved nothing — every object was member-visible, probe-blocked or skipped; worth a Tier-2 look, since a persona that proves nothing is indistinguishable from a persona with no policy.

7 — framework playwright smoke · examples/app-showcase · playwright test --config=/tmp/.../pw-showcase.config.ts

35 passed (2.2m) — with the pinned chromium. Confirms R1 finding #2; the scratch config lives in /tmp so the subject tree stays clean.

8 — objectui live e2e (18 pinned specs) · playwright test --config=/tmp/.../pw-live.config.ts against os serve --dev on :3000 + console vite dev on :5180

18 passed, 11 failed (7.8m) — and re-run in isolation: the same 11, deterministic, not load (#9311 ruled out).

Why the 11 live-e2e reds are NOT scored as product failures

RUNNER rule 2 (reproduce, self-check, rule out the traps) and rule 5 (severe findings are hypotheses) both point the same way here. Four independent pieces of evidence:

  1. objectui's own CI runs only 4 of these specs. test:e2e:live:ci is exactly screen-flow · action-modal · master-detail · saved-view-filter, and all four passed in this run. The workflow header is explicit that the lane is continue-on-error: true, "INFORMATIONAL, NON-REQUIRED", and warns: "do not switch all 20+ live specs on at once and inherit whatever flake exists". The 14 specs outside that allowlist have never been proven green by the repo that owns them.
  2. The pinned pairing is a published backend, not this source build. e2e/live/ci/backend.env pins OBJECTSTACK_VERSION=17.0.0-rc.2 / OBJECTSTACK_REF=89d2a4eb…, and its own header says testing a mismatched pair "proves nothing". I ran the pinned console against source-built e4e5c6e3.
  3. Several reds are demonstrably assertion bugs, not product bugs. form-view-subforms and grid-file-upload fail with a strict-mode violation in which the locator matched two elements — one of them the real <h3>Line Items</h3>. The surface rendered; the assertion is ambiguous because a Radix sr-only dialog description now also contains the phrase. user-filters asserts Timeline is absent from the viz whitelist while the app offers it — a product change the spec never caught up with.
  4. The ledger already predicted two of them. platform-core.metadata-authoring-roundtrip and studio-authoring.record-page-roundtrip both carry a stale flag saying studio-record-page.spec.ts is "STALE, NOT RED — that spec fills the Object control as an input when it is now a role=combobox button", with a runnerRule of "do NOT score their failure as a FAIL of this item". This run reproduced that failure byte-for-byte: locator.fill: Error: Element is not an <input>, <textarea> or [contenteditable] element. Independent corroboration of the ledger's own note.

Additionally, meta/app on stock showcase returns exactly showcase_app, setup, account — the Studio app is not installed, confirming #9296 finding #4. That is why studio-object-designer F1 ("a new package appears in the switcher") cannot pass here, while F2/F3/F4 of the same spec do.

So these are recorded as blocked/partial with the reason, never as fail. Tier-2 should still look at them — a deterministic red is worth a matched-pairing re-run before anyone calls it clean.

Per-item verdicts

Verdict scope is the pinned clauses. Scoring rule applied: pass only where the pin's executed tests span the item's acceptance clauses; partial where the pin demonstrably reaches a subset (gap named below); blocked where the pin could not be consulted in a valid pairing.

access-security

id rev verdict evidence
rls-both-sides 3 ✅ pass verify --rls: 20 PROVEN / 0 HOLES over 23 objects, 9/9 position personas; showcase-private-owd 5/5
write-path-guards 2 ✅ pass owner-anchor-and-bulk-writes 9/9 + showcase-static-readonly 3/3 + showcase-readonly-when-parent 5/5
record-access-explain 2 ✅ pass showcase-permission-zoo 13/13 (incl. the explain vama_bypass case)
crud-permission-matrix 1 🟡 partial verify CRUD 15 verified / 0 gaps / 0 FAILED / 0 mismatches; RLS 20 PROVEN / 0 HOLES
owd-sharing-matrix 2 ✅ pass showcase-private-owd 5/5 + public-read-owd 3/3 + controlled-by-parent 4/4 + invoice-cbp 4/4 = 16/16
fls-mask-and-strip 1 🟡 partial showcase-permission-zoo 13/13 (FLS budget case)
scope-depth-asymmetry 1 ✅ pass showcase-scope-depth 7/7 + -write 9/9 + -fallback 4/4 = 20/20
anonymous-deny-surfaces 1 ✅ pass showcase-anonymous-deny-surfaces 25/25

ai

id rev verdict evidence
mcp-http-surface 2 🟡 partial showcase-mcp-http-identity 6/6 (anonymous 401, keyed tools/call, RLS/FLS-scoped query_records + get_record)
mcp-stdio-fail-closed 3 🟡 partial mcp plugin.test 17/17, incl. the 4-test "stdio principal admission — fail-closed (ADR-0101)" block
mcp-validate-expression 2 ✅ pass mcp-validate-expression 8/8 — sound formula, bare-field error, unknown-field did-you-mean, site-dependent binding, unknown object, system-object refusal
skill-instructions-mcp-prompts 1 ✅ pass skill-prompts 12/12 — listing, prompts/get body, no-instructions/inactive not projected, invalid-params rejection, capability withheld when metadata unreadable

api-backend

id rev verdict evidence
query-contract-matrix 1 🟡 partial objectql engine.test 135/135
bulk-write-contract 1 ✅ pass owner-anchor-and-bulk-writes 9/9 (bulk halves)
declarative-endpoint-execution 1 ✅ pass showcase-declarative-endpoints 17/17 + declarative-endpoint-policy 8/8 = 25/25

approvals

id rev verdict evidence
decision-only-via-service 1 ✅ pass resume-authority-gate 22/22 — raw resume refused, owning service admitted, ungated pause still resumable, node-scoped across subflow/map/restart

attachments-storage

id rev verdict evidence
presigned-upload-roundtrip 1 🟡 partial attachments-permission-matrix 15/16
download-authz-both-sides 2 🟡 partial attachments-permission-matrix 15/16 (download requires auth AND parent read)
read-inherits-parent-rls 2 🟡 partial attachments-permission-matrix 15/16 (member cannot list/read rows whose parent is invisible)
attach-requires-parent-edit 2 🟡 partial attachments-permission-matrix 15/16 — ATTACHMENT_PARENT_ACCESS, server-stamped uploaded_by, delete gating, FILES_DISABLED
sys-file-status-pipeline 1 🟡 partial attachments-permission-matrix 15/16 (shared-file survival, un-tombstone on re-attach)
orphan-tombstone-reap 1 🟡 partial attachments-permission-matrix 15/16 — reap after the 7d window, sweep-time re-verification, committed/NULL-deleted_at rows survive
upload-session-abort 3 🟡 partial attachments-permission-matrix 15/16 — abandoned chunked upload reaped AND its parts aborted
inline-grid-receipt-cells 2 ⛔ blocked sole pin objectui e2e/live/grid-file-upload.spec.ts red in this pairing

automation

id rev verdict evidence
flow-node-type-matrix 3 🟡 partial flow-node 2/2
trigger-type-matrix 1 🟡 partial flow-trigger-conformance 2/2 (ledger-driven conformance)
screen-flow-roundtrip 2 ✅ pass objectui e2e/live/screen-flow.spec.ts green — one of the 4 specs on objectui's own CI allowlist
durable-suspend-restart 1 ✅ pass flow-durable-suspend 11/11

cli

id rev verdict evidence
migrate-plan-apply-json 1 🟡 partial format.exit-code 4/4 — emitJson/emitText leave the exit code alone on success, record a requested failure, and a duration can no longer reach the exit-code slot (#4873)
verify-verdict-exit-mapping 1 🟡 partial verify-tenancy-posture 7/7 — OS_TENANCY_POSTURE keys the multi-tenant suite, legacy-boolean back-compat, --multi-tenant override
scaffold-first-run 2 🟡 partial CI pin .github/workflows/scaffold-e2e.yml — last 30 runs: 4 success, 26 action_required (fork/changeset PRs never executed); the 4 green runs are all 2026-08-17

dashboards

id rev verdict evidence
dataset-report-authoring 1 🟡 partial dashboard-designer-roundtrip 3/3 — layout-less draft saves, publishes, reads back with its widgets
empty-null-bucket-boundaries 1 ✅ pass date-bucket-parity-conformance 8/8

identity-auth

id rev verdict evidence
auth-method-matrix 2 🟡 partial oidc-authorization-code-flow 3/3 — skip_consent code redirect, token exchange persists the access-token row, userinfo answers the signed-in subject
invitation-scope-gates 3 🟡 partial delegated-admin-invite 4/4 — delegate may invite, the same delegate issuing admin is refused with no row left behind, org owner may provision a delegate, plain member cannot invite at all
admin-lifecycle-operations 3 🟡 partial admin-identity-audit-trail 3/3 — create-user, set-user-password and import-users each leave the expected sys_audit_log shape

integration-system

id rev verdict evidence
connector-declarative-boot 2 🟡 partial showcase-declarative-mcp 2/2
connector-stdio-default-deny 2 ✅ pass connector-mcp mcp-provider 13/13
connector-descriptor-audit 2 ✅ pass connector-descriptor-audit 9/9
webhook-lifecycle 4 🟡 partial webhook-materialization 1/1 — the authored webhook materializes into sys_webhook
email-template-render 4 🟡 partial email-template-materialization 2/2 — the authored template materializes and renders
datasource-admin-lifecycle 1 🟡 partial service-datasource admin-routes 30/30 + envelope.conformance 24/24 = 54/54

platform-core

id rev verdict evidence
nav-surfaces-render 3 🟡 partial examples/app-showcase showcase-smoke 35/35 with the pinned chromium — every nav destination renders cleanly, charts draw real SVG
metadata-registry-serving 2 🟡 partial meta-types-create-seed 6/6
metadata-authoring-roundtrip 2 🟡 partial package-first-authoring 5/5 green

records-forms

id rev verdict evidence
field-type-matrix 2 ✅ pass field-zoo-roundtrip 46/46 + field-zoo-value-shape 45/45 = 91/91
list-view-capabilities 1 🟡 partial saved-view-filter green (CI allowlist) + showcase-search 5/5
view-type-gallery 1 ✅ pass showcase-smoke 35/35 — page-level render across every view surface (Board, Calendar, Gallery, Timeline, Map, Gantt)
conditional-rules-header 1 🟡 partial required-when-submit + list-row-action-cel both green
conditional-rules-grid 1 🟡 partial grid-conditional-rules + grid-parent-rules both green
cascading-options 1 🟡 partial the SERVER clause is green — "the server rejects an out-of-set option value, and accepts an in-set one" passed
master-detail-atomic-save 2 🟡 partial master-detail green (CI allowlist) + summary-rollup green
related-list-server-pagination 3 ⛔ blocked sole pin objectui e2e/live/detail-related-list.spec.ts red in this pairing
action-param-widgets 2 ✅ pass action-params-contract 3/3 + action-modal green (CI allowlist)
import-wizard-encoding-and-hints 2 ✅ pass importParsers 30/30 + importMissingRequiredHint 2/2 + importLegacyReferenceGuard 3/3 = 35/35
action-location-matrix 4 ✅ pass list-row-action-cel green (row-level CEL visibility) + action-modal green (dialog dispatch)
gantt-interactions 1 ✅ pass plugin-gantt autoscheduledlg 4/4 + summaryedit 8/8 + deptypes 2/2 + scheduling.selfextent 8/8 = 22/22
form-dirty-guard 1 ✅ pass plugin-form discardGuard 14/14
adhoc-filter-sort-builder 1 🟡 partial saved-view-filter green (CI allowlist)
calendar-interactions 1 ✅ pass plugin-calendar CalendarView.dnd 8/8 (move/resize/time-grid drag geometry)
concurrent-edit-conflict 1 🟡 partial plugin-form occSave 8/8 — 409 handling + overwrite retry
grid-personalization 1 ✅ pass plugin-grid groupedPagination 7/7 + groupedBooleanLabel 2/2 + inlineEditPersistence 1/1 = 10/10
bulk-select-all-matching 1 ✅ pass plugin-grid objectBulkActionDispatch 12/12 + BulkActionBar 7/7 + bulkActionRefresh 11/11 = 30/30
lookup-picker-create-new 1 ✅ pass fields LookupField.dependsOn 6/6 + RecordPickerDialog.filterOptions 12/12 = 18/18
record-edit-undo 1 ✅ pass core UndoManager 28/28 (undo/redo stack)
object-hook-lifecycle 1 🟡 partial showcase-public-form 4/4 (beforeInsert stamp) + hook-error-format 4/4 (beforeDelete onError:abort -> REST error body)
field-type-constraints 1 ✅ pass field-zoo-roundtrip 46/46 + value-shape 45/45 + engine-lookup-referential-integrity 13/13 (reference_not_found #4441) + engine-autonumber-runtime-owned 32/32 (autonumber strip #5503)
cascading-multilevel-and-clear 1 🟡 partial rule-validator.option-visibility 20/20 — the server WRITTEN-value gate
encrypted-field-behavior 1 ✅ pass objectql secret-fields 36/36 (encrypt/mask/fail-closed) + field-zoo-roundtrip 46/46 (masked f_secret & f_password vectors)

search

id rev verdict evidence
cross-field-object-search 3 ✅ pass showcase-search 5/5 — multi-field $search returns Northwind via industry, not name (ADR-0061 verbatim)
field-scoped-narrowing 1 ✅ pass showcase-search 5/5 — $searchFields narrows and can never widen

studio-authoring

id rev verdict evidence
object-designer-roundtrip 1 🟡 partial studio-object-designer 3/4 — F2 (typed underscore survives), F3 (API name derives from label on blur), F4 (picklist + empty option row does not trip validation) all green
record-page-roundtrip 2 ⛔ blocked sole pin studio-record-page.spec.ts red — locator.fill: Element is not an <input>
draft-publish-lifecycle 4 🟡 partial dashboard-designer-roundtrip 3/3 — draft save is staged, publish flips visibility, published body reads back
org-override-registry-gate 2 ✅ pass objectql overlay-precedence 26/26
expression-editors 1 ✅ pass celAuthoring 34/34 + CelPredicateField 24/24 + CelTestRunDialog 6/6 + PermissionAdvancedFacets.cel 2/2 = 66/66
permission-matrix-editor-ux 1 ✅ pass PermissionMatrixEditor.fieldBulk 3/3 + PermissionMatrixEditor.readonly 7/7 = 10/10

Coverage gaps — every partial / blocked, with what the pin did not reach

  • access-security.crud-permission-matrix (rev1, partial) — the ref itself says persona-grained cells remain manual — verify proves object-level CRUD + cross-owner RLS, never the persona x CRUD-cell matrix
  • access-security.fls-mask-and-strip (rev1, partial) — ref is explicit: write half only. The read-side clauses (masked value in the GET payload, field stripped from the response shape) have no pin
  • ai.mcp-http-surface (rev2, partial) — pin is the identity-admission block only: C0 (opted-out boot 404 on /mcp and /mcp/skill), C1 (GET /mcp/skill serves SKILL.md unauthenticated) and C2 (405 + Allow: GET) are unpinned
  • ai.mcp-stdio-fail-closed (rev3, partial) — covers C0–C2 + C7 (keyless refusal, unresolvable key, principal binding, no key demanded when disabled). C3–C6 — member-keyed RLS/FLS read parity, aggregate_records parity, FLS aggregate fail-closed, revocation honored on next call — are unpinned
  • api-backend.query-contract-matrix (rev1, partial) — the ref scopes the pin to "[Security: $expand bypasses RLS/FLS on the referenced object (data leak on lookups) #2850] expand sub-read through the secured find path" = C4 only. C0–C3 and C5–C8 (operator answer sets, $top/$skip windowing, $select narrowing, sort + INVALID_SORT, INVALID_FILTER, UNSUPPORTED_QUERY_PARAM, $in/$nin empty-list boundary) are REST-contract clauses this engine unit suite does not reach. filter-comparand-shape.ts is a source module, not a test
  • attachments-storage.presigned-upload-roundtrip (rev1, partial) — pin reaches C4 (anonymous presign 401) and the authenticated upload. C0 (presign envelope {uploadUrl, method, fileId, expiresIn, downloadUrl}), C1 (status pending->committed on complete), C2 (GET /files/:id/url envelope) and C3 (302 redirect) are unpinned
  • attachments-storage.download-authz-both-sides (rev2, partial) — C3 (acl=public_read re-opens the stable anonymous capability URL) and C4 (browser renders friendly denial copy) are unpinned; the cross-tenant case is skipped — see the enterprise-gate note
  • attachments-storage.read-inherits-parent-rls (rev2, partial) — C1 (COUNT filtered identically to rows) and C3 (filter fails CLOSED on compute failure / past the 2000-row pre-scan cap) are unpinned
  • attachments-storage.attach-requires-parent-edit (rev2, partial) — C3 (unscoped multi-delete with neither id nor where is refused outright, installAttachmentAccessHooks does not authorize an UNSCOPED multi-delete: no id + no where reads as "nothing to authorize" and deleteMany runs over the whole table #4757) is unpinned
  • attachments-storage.sys-file-status-pipeline (rev1, partial) — C0 (every status enum variant), C1 (a pending file is not downloadable) and C4 (only scope=attachments committed files tombstone via these hooks) are unpinned
  • attachments-storage.orphan-tombstone-reap (rev1, partial) — C1 (bytes reclaimed BEFORE the row delete — the ordering, not just the outcome) is not separately asserted
  • attachments-storage.upload-session-abort (rev3, partial) — C0 (the chunked round-trip over the real routes: init -> chunk PUTs -> progress) is unpinned
  • attachments-storage.inline-grid-receipt-cells (rev2, blocked) — not consultable — see the live-e2e pairing note; the spec is outside objectui's own CI allowlist and its failure is an ambiguous-locator assertion, not a product signal
  • automation.flow-node-type-matrix (rev3, partial) — two tests against a 6-clause node-type matrix — the pin exercises the node-type registry, not each declared node type's runtime semantics
  • automation.trigger-type-matrix (rev1, partial) — two tests against 6 clauses; the ledger conformance proves declared-vs-registered parity, not each trigger type firing end-to-end
  • cli.migrate-plan-apply-json (rev1, partial) — pin is the exit-code formatter only = C2. C0 (bare os migrate never mutates), C1 (--json shape), C3 (destructive skipped until --allow-destructive), C4 (idempotent re-run in_sync), C5 (busy-DB asymmetry), C6 (--json non-interactive confirmation_required) are unpinned
  • cli.verify-verdict-exit-mapping (rev1, partial) — the pin decides which SUITE runs, not how a verdict maps to an exit code; the verdict->exit clauses are only indirectly covered
  • cli.scaffold-first-run (rev2, partial) — the workflow cannot be executed locally (registry install + docker) and was never run against the subject sha e4e5c6e; the nightly published-package canary job has no run in the window
  • dashboards.dataset-report-authoring (rev1, partial) — three tests against 8 clauses; the dataset/report authoring clauses beyond save->publish->read are unpinned
  • identity-auth.auth-method-matrix (rev2, partial) — C7 says outright that only the OIDC flow is pinned. C0–C6 and C9 (advertisement parity, email+password round trip, phone+password, phone-OTP NOT_SUPPORTED, login-page per-variant presence/absence, server-side refusal of a disabled method, 2FA gate, change-email/delete-user) are unpinned
  • identity-auth.invitation-scope-gates (rev3, partial) — C4 (UI invite affordances, both sides), C5 (lifecycle vocabulary pending->accepted/rejected/expired, cancel/resend) and C6 (/security/my-delegable-scope is self-scoped) are unpinned
  • identity-auth.admin-lifecycle-operations (rev3, partial) — C8 is the only pinned clause. C0–C7 and C9 (ban persistence/reversal, password rotation, explicit-password-wins, set-role flipping gate outcomes, revoke-user-sessions mid-flight, owner_id FK clear on user removal, impersonation attribution + console visibility, non-admin refusal of every /admin/ route) are unpinned
  • integration-system.connector-declarative-boot (rev2, partial) — two tests against 6 clauses — the declarative MCP connector boots, but the wider connector-boot matrix is unpinned
  • integration-system.webhook-lifecycle (rev4, partial) — one test against 6 clauses; delivery, retry, signature and teardown clauses are unpinned
  • integration-system.email-template-render (rev4, partial) — two tests against 8 clauses; requireVars fail-fast, TEMPLATE_INACTIVE, (name, locale) fallback, fromOverride/replyTo/derived bodyText, customized-row survival, stray-key alias prescription and the raw /email/send door are unpinned
  • integration-system.datasource-admin-lifecycle (rev1, partial) — the ref is explicit: this pins route behavior + envelope; the LIVE-mount half is not pinned — a real os dev mount of the datasource is not exercised
  • platform-core.nav-surfaces-render (rev3, partial) — C2 (a bad route renders a NAMED not-found/error inside a live shell) and C3 (route-level ErrorBoundary fallback, recoverable via Try Again) have no spec in the smoke — its 35 cases are clean-render and gated-inline-def cases only
  • platform-core.metadata-registry-serving (rev2, partial) — six tests against 7 clauses — the create/seed path is pinned; the wider registry-serving surface is not fully reached
  • platform-core.metadata-authoring-roundtrip (rev2, partial) — the item carries a ledger stale flag: its studio-record-page.spec.ts ref is STALE, NOT RED (the Object control is now a role=combobox, not an input). This run independently reproduced exactly that — locator.fill: Element is not an <input>. Per the item's own runnerRule the Studio clause (C3, the PUT /api/v1/meta/page/<name>) must be hand-driven and its spec failure must NOT be scored here
  • records-forms.list-view-capabilities (rev1, partial) — the user-filters and inline-edit-polish-2572 halves are not consultable in this pairing — see the live-e2e note
  • records-forms.conditional-rules-header (rev1, partial) — the field-conditional-rules half (visibleWhen/readonlyWhen/requiredWhen reacting to Status) is not consultable in this pairing
  • records-forms.conditional-rules-grid (rev1, partial) — the grid-file-upload half is not consultable in this pairing
  • records-forms.cascading-options (rev1, partial) — the client half ("province options re-filter live as country changes, and the stale value clears") is not consultable in this pairing
  • records-forms.master-detail-atomic-save (rev2, partial) — the form-view-subforms half is not consultable — and note its failure is a strict-mode locator ambiguity in which the Line Items heading WAS found, i.e. the surface rendered
  • records-forms.related-list-server-pagination (rev3, blocked) — not consultable — outside objectui's CI allowlist, unpinned backend pairing
  • records-forms.adhoc-filter-sort-builder (rev1, partial) — the user-filters half is not consultable in this pairing
  • records-forms.concurrent-edit-conflict (rev1, partial) — the inline-edit-polish-2572 half (single save bar / atomic inline save) is not consultable in this pairing
  • records-forms.object-hook-lifecycle (rev1, partial) — the ref is explicit: the transition audit / over-budget warn / priority-ordering LOG oracles and the abort/log/priority SCRATCH variants are NOT dogfood-pinned and must be hand-driven
  • records-forms.cascading-multilevel-and-clear (rev1, partial) — the client clear-on-change half (cascading-options.spec.ts) is not consultable in this pairing
  • studio-authoring.object-designer-roundtrip (rev1, partial) — F1 ("a newly created package appears in the switcher without a reload") is red; the Studio APP is not installed on stock showcase (meta/app = showcase_app, setup, account), so the switcher clause is not scoreable here
  • studio-authoring.record-page-roundtrip (rev2, blocked) — the item carries a ledger stale flag whose runnerRule says outright: do NOT satisfy this item by citing these specs, and do NOT score their failure as a FAIL. This run reproduced the documented staleness exactly (the Object control is now a role=combobox button). Hand-drive until objectui re-points the spec
  • studio-authoring.draft-publish-lifecycle (rev4, partial) — three tests against 12 clauses; If-Match 409 metadata_conflict, package-wide publish-drafts atomicity, invalid-draft gate, Studio chrome badges, history/diff/rollback/audit and X-Actor inertness are unpinned

Checklist-accuracy findings (for the ledger, not for code)

  1. The pins are narrower than the items on 39 of 77. Not a defect in any pin — but an item scored pass on a pin that reaches 1 of 10 clauses would be a false green. The gap list above is the raw material for either tightening automated.ref scope notes (as fls-mask-and-strip, crud-permission-matrix, datasource-admin-lifecycle and object-hook-lifecycle already do well) or promoting the unpinned clauses to real tests per RUNNER rule 6's reverse direction.
  2. 11 items pin objectui e2e/live specs that objectui itself does not gate. Only 4 live specs are in test:e2e:live:ci; the rest are informational and unproven. The ledger should either pin to the allowlist, or record the required pairing (backend.env) so a runner knows a green needs the published backend.
  3. e2e/live/ci/backend.env violates its own stated invariant in the pinned objectui tree: OBJECTSTACK_VERSION=17.0.0-rc.2 while this repo's lock resolves @objectstack/spec ^17.0.0-rc.6, though the file says the two "MUST stay aligned … bump both in the same PR". That is an objectui repo issue, filed here only as a pointer.
  4. api-backend.query-contract-matrix cites a source module as a pin — packages/objectql/src/filter-comparand-shape.ts is not a test.
  5. Cross-tenant clauses are structurally unprovable in the OSS workspace (@objectstack/organizations is cloud-private). The dogfood probe handles this honestly; the checklist should mark such clauses so runners stop rediscovering it.

Not re-derived (already known, confirmed again)

  • objectstack verify --rls is a separate invocation — confirmed, 20 PROVEN / 0 HOLES / 9-of-9 personas.
  • Playwright needs the explicit executablePath — confirmed, 35 passed with it.
  • Studio is not installed on stock showcase — confirmed via meta/app.

Nothing landed in the repo: no commits, no PR, no screenshots. Scratch artifacts stayed in /tmp/qa-wave/**.

Parent: #9296

Activity

  1. os-zhuang commented on Aug 17, 2026

    @os-zhuang
    ContributorAuthor

    ACCEPT — reviewer of record: PM loop (QA wave #9296), session session_01Ai9gUdihXjg7FumzsBNSSs.

    Two claims spot-checked against the tree rather than the report, both hold:

    • The objectui unlock is real. .cache/objectui-665661ab0932 exists in the QA tree with node_modules present. That is what let 25 objectui unit pins (249 tests) run at the exact .objectui-sha pin with zero installs — the sibling /home/user/objectui is at a different sha (195b9e4ab) and has none. Without that read, 26 items would have gone blocked(environment) on a constraint that was not actually binding. This belongs in RUNNER.md's facts section; folded into docs(qa): land the #9296 wave's environment facts in RUNNER.md and the 34 checklist-accuracy corrections in areas/*.json #9386.
    • The checklist-accuracy finding is confirmed. api-backend.query-contract-matrix cites packages/objectql/src/filter-comparand-shape.ts as an automated.ref. That file exists and is a source module, not a test — nothing executes it as a pin. The item carries 9 acceptance clauses, which corroborates the partial rather than pass scoring.

    The finding that changes the wave's cost model

    39 of 77 pinned items are partial because the pin is narrower than the item — identity-auth.admin-lifecycle-operations pins 1 of 10 clauses; api-backend.query-contract-matrix (P0) pins one expand path out of nine. Mapping each pin's executed test titles onto its acceptance clauses, and naming every gap, is the most reusable thing this round produced — more so than the 35 PASS.

    It also corrects a premise I dispatched on. I framed the 77 pinned items as "cheap coverage, already proven by CI". They are cheap, and 0 failed — but automated.ref present ≠ item covered. The honest reading is 35 items fully covered, 39 partially, and the remaining clause gaps join the hand-driving load rather than sitting outside it.

    Judgement calls I am endorsing

    • The 11 deterministic objectui live-e2e reds recorded blocked/partial rather than fail. Four independent lines of evidence, not one: only 4 live specs are on objectui's own CI allowlist (all 4 green here), the lane is continue-on-error, the pinned pairing is a published backend (backend.env → 17.0.0-rc.2) rather than a source build, and several failures are demonstrable assertion bugs (one fails a strict-mode ambiguity in which the element it sought was found). Two are covered by explicit ledger stale runnerRules that forbid scoring a FAIL — and the runner reproduced the exact predicted symptom independently. Recording a red as blocked needs this much justification, and it was supplied.
    • objectui e2e/live/ci/backend.env violating its own stated invariant (OBJECTSTACK_VERSION=17.0.0-rc.2 while the lock resolves @objectstack/spec ^17.0.0-rc.6, where the file's own header says the two must be bumped together) is a finding at destination — it belongs in objectstack-ai/objectui, not here. Filing it there is the right next step; it means that lane may currently be testing a pairing it declares meaningless.

    Carried forward

    • The three checklist-accuracy defects (source-module-as-pin; two refs naming companion tests by bare name with no path) go into the ledger-edit PR alongside the five from QA run · priority:P0 · e4e5c6e3 · 2026-08-17 · 7 PASS / 7 PARTIAL / 2 FAIL / 2 BLOCKED #9334 — one docs-only change with revision bumps, not eight scattered edits.
    • verify --rls: the exec and auditor position personas proved NOTHING — 0 PROVEN, every object member-visible / probe-blocked / skipped. Zero HOLES overall, but as the runner put it, a persona that proves nothing is indistinguishable from a persona with no policy. That deserves its own look before the wave closes; it is not covered by any current item.
    • The 11 items pinning objectui live specs objectui itself does not gate should either re-pin to the 4-spec allowlist or record the required backend pairing.

    Tier-2A (23 unpinned api/cli/build items) dispatched.


    Generated by Claude Code

  2. added a commit that references this issue on Aug 18, 2026
  3. os-zhuang commented on Aug 18, 2026

    @os-zhuang
    ContributorAuthor

    Close-out — extracted. Wave #9296, executed under #9480. Nothing re-judged, nothing re-run.

    No FAIL to dispose of. 0 FAIL across 77 items; no product defect and no access-control finding. The four-way disposition therefore has no input from this record, which is exactly what its PARTIAL column says: the pins are green, and the value is in what they do not reach.

    What was extracted

    The three security-priority coverage gaps from this record's own gap list are filed and in the queue — #9481 (the read side of FLS mask/strip, plus the persona × CRUD cell matrix verify cannot see), #9482 (the admin-lifecycle clauses C0–C7/C9 that the single pinned audit clause leaves open), #9483 (the unpinned authorization clauses of the attachments chain). They are pin-upgrade cards, not defect cards: the property is untested, not broken.

    (d) invalid pairing / environment — recorded blocked, no card

    Recorded here so a later reader does not mistake a red for a product signal:

    • 11 objectui e2e/live specs red, deterministically. Not scored fail, and correctly so: only 4 specs (screen-flow, action-modal, master-detail, saved-view-filter) are on objectui's own test:e2e:live:ci allowlist and all four passed; the lane is continue-on-error: true and warns against switching the rest on; the pinned pairing is a published backend (OBJECTSTACK_VERSION=17.0.0-rc.2 in e2e/live/ci/backend.env) rather than this source build; and at least two of the reds are demonstrably assertion bugs (a strict-mode locator that matched the real <h3>Line Items</h3> twice; a whitelist assertion the product has moved past). A matched-pairing re-run remains worthwhile and is not a clean bill — that stays parked.
    • 3 items blocked: inline-grid-receipt-cells, related-list-server-pagination, record-page-roundtrip — the last two under the ledger's own stale flag whose runnerRule says outright not to score the spec's failure as a FAIL. This run reproduced the documented staleness byte-for-byte, which is corroboration of the ledger, not a defect.
    • 1 skipped cross-tenant attachment probe — @objectstack/organizations is cloud-private and absent from the OSS workspace, so the block skips loudly by design. blocked(dependency).

    Everything else stays parked, by pointer

    All remaining (non-security) coverage gaps in the "Coverage gaps" section above — query-contract REST clauses, presign envelope shapes, the attachments status pipeline / reap ordering / chunked session, the automation node and trigger matrices, auth-method C0–C6/C9, invitation-scope C4–C6, dashboards, webhook and email lifecycle clauses, nav error surfaces, draft-publish clauses — are parked on the wave anchor by the PM's 2026-08-18 comment. This record is the authoritative list; do not re-file from memory without reading it. The five checklist-accuracy findings join the ledger-edit PR.

    Extracted: #9481 #9482 #9483
    Parked-on: #9296


    Generated by Claude Code

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions