You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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)
.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)
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
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>
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
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.
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:
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.
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.
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.
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
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)
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
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
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.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)
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.
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.
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.
api-backend.query-contract-matrix cites a source module as a pin — packages/objectql/src/filter-comparand-shape.ts is not a test.
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/**.
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
e4e5c6e3c608b1b807c83a0d5b734f213eb1a1dd(detached, tree clean, subject not moved).objectui-sha=665661ab093263f39f2e660a295ea615dbcee35a.cache/objectui-665661ab0932— a full checkout at the pinned sha withnode_modulesalready installed, so objectui unit pins ran against the pin rather than against the sibling checkout (which sits at195b9e4ab, a different sha)objectstack-qa-wave190 items (190 active); 30 kinds mapped, 0 waived—check-platform-checklist: OK, working-tree sync not committedchecklist-select.mjs area:<a> --jsonx 15 joined toareas/*.jsonfor theautomatedobject; 77 pinned+active, matching the dispatch counts exactly (records-forms 24, access-security 8, attachments-storage 8, integration-system 6, studio-authoring 6)executablePath=/opt/pw-browsers/chromium-1194/chrome-linux/chromeobjectstack verifyinvocationsPin 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) andrecords-forms.import-wizard-encoding-and-hints(importMissingRequiredHint,importLegacyReferenceGuard, which actually live inplugin-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>The single skip is
attachments-permission-matrix > attachments cross-tenant isolation (g), gated bydescribe.skipIf(!organizationsAvailable). That probe resolves the cloud-private enterprise package@objectstack/organizationsthrough the production resolver; it is absent in this OSS workspace, so the block skips by design and loudly (OS_TEST_MULTI_ORG_ENABLED=1turns the skip into a hard failure for runs that ship the package). This isblocked(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.ts3 — mcp / cli / services / connectors (5 invocations, sequential)
4 — scope-depth companions ·
npx vitest run test/showcase-scope-depth-{write,fallback}.dogfood.test.ts5 — objectui unit pins (25 files, one invocation, run in the pinned-sha cache)
6 —
objectstack verify --rls·examples/app-showcase·node packages/cli/bin/run.js verify --rls7 — framework playwright smoke ·
examples/app-showcase·playwright test --config=/tmp/.../pw-showcase.config.ts8 — objectui live e2e (18 pinned specs) ·
playwright test --config=/tmp/.../pw-live.config.tsagainstos serve --devon :3000 + console vite dev on :5180Why 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:
test:e2e:live:ciis exactlyscreen-flow · action-modal · master-detail · saved-view-filter, and all four passed in this run. The workflow header is explicit that the lane iscontinue-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.e2e/live/ci/backend.envpinsOBJECTSTACK_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-builte4e5c6e3.form-view-subformsandgrid-file-uploadfail 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 Radixsr-onlydialog description now also contains the phrase.user-filtersassertsTimelineis absent from the viz whitelist while the app offers it — a product change the spec never caught up with.platform-core.metadata-authoring-roundtripandstudio-authoring.record-page-roundtripboth carry astaleflag sayingstudio-record-page.spec.tsis "STALE, NOT RED — that spec fills the Object control as an input when it is now arole=comboboxbutton", with arunnerRuleof "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/appon stock showcase returns exactlyshowcase_app, setup, account— the Studio app is not installed, confirming #9296 finding #4. That is whystudio-object-designerF1 ("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/partialwith the reason, never asfail. 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:
passonly where the pin's executed tests span the item's acceptance clauses;partialwhere the pin demonstrably reaches a subset (gap named below);blockedwhere the pin could not be consulted in a valid pairing.access-security
rls-both-sidesverify --rls: 20 PROVEN / 0 HOLES over 23 objects, 9/9 position personas; showcase-private-owd 5/5write-path-guardsrecord-access-explainvama_bypasscase)crud-permission-matrixverifyCRUD 15 verified / 0 gaps / 0 FAILED / 0 mismatches; RLS 20 PROVEN / 0 HOLESowd-sharing-matrixfls-mask-and-stripscope-depth-asymmetryanonymous-deny-surfacesai
mcp-http-surfacemcp-stdio-fail-closedmcp-validate-expressionskill-instructions-mcp-promptsapi-backend
query-contract-matrixbulk-write-contractdeclarative-endpoint-executionapprovals
decision-only-via-serviceattachments-storage
presigned-upload-roundtripdownload-authz-both-sidesread-inherits-parent-rlsattach-requires-parent-editsys-file-status-pipelineorphan-tombstone-reapupload-session-abortinline-grid-receipt-cellsobjectui e2e/live/grid-file-upload.spec.tsred in this pairingautomation
flow-node-type-matrixtrigger-type-matrixscreen-flow-roundtripdurable-suspend-restartcli
migrate-plan-apply-jsonverify-verdict-exit-mappingscaffold-first-run.github/workflows/scaffold-e2e.yml— last 30 runs: 4 success, 26action_required(fork/changeset PRs never executed); the 4 green runs are all 2026-08-17dashboards
dataset-report-authoringempty-null-bucket-boundariesidentity-auth
auth-method-matrixinvitation-scope-gatesadminis refused with no row left behind, org owner may provision a delegate, plain member cannot invite at alladmin-lifecycle-operationsintegration-system
connector-declarative-bootconnector-stdio-default-denyconnector-descriptor-auditwebhook-lifecycleemail-template-renderdatasource-admin-lifecycleplatform-core
nav-surfaces-rendermetadata-registry-servingmetadata-authoring-roundtriprecords-forms
field-type-matrixlist-view-capabilitiesview-type-galleryconditional-rules-headerconditional-rules-gridcascading-optionsmaster-detail-atomic-saverelated-list-server-paginationobjectui e2e/live/detail-related-list.spec.tsred in this pairingaction-param-widgetsimport-wizard-encoding-and-hintsaction-location-matrixgantt-interactionsform-dirty-guardadhoc-filter-sort-buildercalendar-interactionsconcurrent-edit-conflictgrid-personalizationbulk-select-all-matchinglookup-picker-create-newrecord-edit-undoobject-hook-lifecyclefield-type-constraintscascading-multilevel-and-clearencrypted-field-behaviorsearch
cross-field-object-searchindustry, notname(ADR-0061 verbatim)field-scoped-narrowing$searchFieldsnarrows and can never widenstudio-authoring
object-designer-roundtriprecord-page-roundtripstudio-record-page.spec.tsred —locator.fill: Element is not an <input>draft-publish-lifecycleorg-override-registry-gateexpression-editorspermission-matrix-editor-uxCoverage gaps — every
partial/blocked, with what the pin did not reachaccess-security.crud-permission-matrix(rev1, partial) — the ref itself says persona-grained cells remain manual —verifyproves object-level CRUD + cross-owner RLS, never the persona x CRUD-cell matrixaccess-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 pinai.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 unpinnedai.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 unpinnedapi-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.tsis a source module, not a testattachments-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/urlenvelope) and C3 (302 redirect) are unpinnedattachments-storage.download-authz-both-sides(rev2, partial) — C3 (acl=public_readre-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 noteattachments-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 unpinnedattachments-storage.attach-requires-parent-edit(rev2, partial) — C3 (unscoped multi-delete with neither id nor where is refused outright,installAttachmentAccessHooksdoes not authorize an UNSCOPED multi-delete: no id + nowherereads as "nothing to authorize" anddeleteManyruns over the whole table #4757) is unpinnedattachments-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 unpinnedattachments-storage.orphan-tombstone-reap(rev1, partial) — C1 (bytes reclaimed BEFORE the row delete — the ordering, not just the outcome) is not separately assertedattachments-storage.upload-session-abort(rev3, partial) — C0 (the chunked round-trip over the real routes: init -> chunk PUTs -> progress) is unpinnedattachments-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 signalautomation.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 semanticsautomation.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-endcli.migrate-plan-apply-json(rev1, partial) — pin is the exit-code formatter only = C2. C0 (bareos migratenever 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 unpinnedcli.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 coveredcli.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 windowdashboards.dataset-report-authoring(rev1, partial) — three tests against 8 clauses; the dataset/report authoring clauses beyond save->publish->read are unpinnedidentity-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 unpinnedidentity-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-scopeis self-scoped) are unpinnedidentity-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 unpinnedintegration-system.connector-declarative-boot(rev2, partial) — two tests against 6 clauses — the declarative MCP connector boots, but the wider connector-boot matrix is unpinnedintegration-system.webhook-lifecycle(rev4, partial) — one test against 6 clauses; delivery, retry, signature and teardown clauses are unpinnedintegration-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 unpinnedintegration-system.datasource-admin-lifecycle(rev1, partial) — the ref is explicit: this pins route behavior + envelope; the LIVE-mount half is not pinned — a realos devmount of the datasource is not exercisedplatform-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 onlyplatform-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 reachedplatform-core.metadata-authoring-roundtrip(rev2, partial) — the item carries a ledgerstaleflag: itsstudio-record-page.spec.tsref is STALE, NOT RED (the Object control is now arole=combobox, not an input). This run independently reproduced exactly that —locator.fill: Element is not an <input>. Per the item's ownrunnerRulethe Studio clause (C3, thePUT /api/v1/meta/page/<name>) must be hand-driven and its spec failure must NOT be scored hererecords-forms.list-view-capabilities(rev1, partial) — theuser-filtersandinline-edit-polish-2572halves are not consultable in this pairing — see the live-e2e noterecords-forms.conditional-rules-header(rev1, partial) — thefield-conditional-ruleshalf (visibleWhen/readonlyWhen/requiredWhen reacting to Status) is not consultable in this pairingrecords-forms.conditional-rules-grid(rev1, partial) — thegrid-file-uploadhalf is not consultable in this pairingrecords-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 pairingrecords-forms.master-detail-atomic-save(rev2, partial) — theform-view-subformshalf is not consultable — and note its failure is a strict-mode locator ambiguity in which theLine Itemsheading WAS found, i.e. the surface renderedrecords-forms.related-list-server-pagination(rev3, blocked) — not consultable — outside objectui's CI allowlist, unpinned backend pairingrecords-forms.adhoc-filter-sort-builder(rev1, partial) — theuser-filtershalf is not consultable in this pairingrecords-forms.concurrent-edit-conflict(rev1, partial) — theinline-edit-polish-2572half (single save bar / atomic inline save) is not consultable in this pairingrecords-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-drivenrecords-forms.cascading-multilevel-and-clear(rev1, partial) — the client clear-on-change half (cascading-options.spec.ts) is not consultable in this pairingstudio-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 herestudio-authoring.record-page-roundtrip(rev2, blocked) — the item carries a ledgerstaleflag whoserunnerRulesays 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 arole=comboboxbutton). Hand-drive until objectui re-points the specstudio-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 unpinnedChecklist-accuracy findings (for the ledger, not for code)
passon a pin that reaches 1 of 10 clauses would be a false green. The gap list above is the raw material for either tighteningautomated.refscope notes (asfls-mask-and-strip,crud-permission-matrix,datasource-admin-lifecycleandobject-hook-lifecyclealready do well) or promoting the unpinned clauses to real tests per RUNNER rule 6's reverse direction.e2e/livespecs that objectui itself does not gate. Only 4 live specs are intest: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.e2e/live/ci/backend.envviolates its own stated invariant in the pinned objectui tree:OBJECTSTACK_VERSION=17.0.0-rc.2while 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.api-backend.query-contract-matrixcites a source module as a pin —packages/objectql/src/filter-comparand-shape.tsis not a test.@objectstack/organizationsis 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 --rlsis a separate invocation — confirmed, 20 PROVEN / 0 HOLES / 9-of-9 personas.executablePath— confirmed, 35 passed with it.meta/app.Nothing landed in the repo: no commits, no PR, no screenshots. Scratch artifacts stayed in
/tmp/qa-wave/**.Parent: #9296