assertEngineFindOnePredicate now exists and is published from @objectstack/metadata-core (re-exported by @objectstack/objectql), proved against the REAL engine by packages/objectql/src/engine-findone-predicate.test.ts. The findOne slice of scripts/check-engine-double-contract.mjs was NOT added in that PR, and this card is the remainder — stated with the measurement rather than an estimate.
The measurement
Taken by temporarily adding a findOne slice to SLICES in scripts/check-engine-double-contract.mjs and running the gate. Re-derivable the same way; the slice body is four lines (verb / producer / symbols / modules), mirroring the two write-side entries.
Before adoption: 232 files, 275 doubles would newly fail PINNED [findOne].
After the objectql-package adoption that shipped: 209 files, 250 doubles remain.
| package | files | doubles | already pinned for a write verb | DEBT-ledgered only | in neither ledger |
|---|
packages/metadata-protocol/src | 102 | 120 | 90 | 0 | 12 |
packages/plugins/plugin-security | 22 | 27 | 10 | 1 | 11 |
packages/plugins/plugin-auth | 20 | 24 | 15 | 1 | 4 |
packages/services/service-messaging | 12 | 18 | 2 | 9 | 1 |
packages/rest/src | 11 | 11 | 6 | 0 | 5 |
packages/runtime/src | 10 | 10 | 8 | 0 | 2 |
packages/services/service-automation | 9 | 13 | 2 | 6 | 1 |
packages/services/service-storage | 7 | 7 | 4 | 2 | 1 |
packages/mcp/src | 6 | 6 | 3 | 0 | 3 |
packages/plugins/plugin-webhooks | 4 | 4 | 2 | 2 | 0 |
packages/plugins/plugin-sharing | 2 | 2 | 2 | 0 | 0 |
packages/core/src | 1 | 1 | 1 | 0 | 0 |
packages/metadata/src | 1 | 1 | 1 | 0 | 0 |
packages/services/service-datasource | 1 | 1 | 0 | 1 | 0 |
packages/spec/src | 1 | 5 | 0 | 1 | 0 |
| total | 209 | 250 | 146 | 23 | 40 |
"already pinned for a write verb" = the file appears in scripts/engine-double-contract.pinned.json, so its author already routes delete and/or update through the producer's predicate and the findOne pin is one import plus one call. "DEBT-ledgered only" / "in neither ledger" are the two populations that need more than a mechanical edit.
Why the slice did not land with the guard
Two reasons, both structural rather than a matter of effort.
- The diff. 209 files is past any reviewable size, and the acceptance criterion for each is a real suite run — the point of the wave is precisely that some of those suites may be relying on the permissive double, which is a finding, not a rebase conflict.
- 63 of the 209 cannot be closed by a dev seat at all. The 23 DEBT-ledgered and 40 unledgered files include cases where a one-line pin does not reach (a signature declaring too few parameters, a package depending on neither home of the predicate,
packages/spec which cannot import the predicate even in principle because metadata-core depends on spec). Those want scripts/engine-double-contract.baseline.json entries, and the gate's own failure text is explicit that a baseline entry is MAINTAINER-ONLY — "that baseline is shrink-only, so an entry weakens a ratchet and needs a maintainer to agree first — do not take this path to get CI green."
The update slice landed the same way in #5480 — a first measurement with 116 unguarded doubles ledgered in one act, recorded in the baseline's own $comment as "not newly written looseness and not a raised ratchet". Whether the findOne slice repeats that shape, or lands per-package behind a shrinking remainder, is the decision this card carries.
Suggested shape
- Add the
findOne slice to SLICES (the gate's pinCall reads assertEngineFindOnePredicate(object, query) — note it takes the object name, unlike the two write-side asserts, because the engine's refusal message quotes the object twice). - Adopt per package, largest first, each batch running that package's own suite.
packages/metadata-protocol alone is 102 files / 120 doubles and 90 of them are already pinned for a write verb. - Decide the disposition of the 63 files that are not a mechanical pin, with the maintainer, before the slice goes red.
The exact remainder
The 209 files, one per line, as the gate reported them:
209 files
packages/core/src/utils/migration-journal.test.ts
packages/mcp/src/__tests__/plugin.test.ts
packages/mcp/src/mcp-stdio-tools.test.ts
packages/mcp/src/mcp-write-response-internal-fields.tripwire.test.ts
packages/mcp/src/plugin.record-resource-exposure.test.ts
packages/mcp/src/stdio-data-bridge.exposure.test.ts
packages/mcp/src/stdio-data-bridge.not-found.test.ts
packages/metadata-protocol/src/migrations/recorded-by-sentinel.test.ts
packages/metadata-protocol/src/protocol-publish-drafts-advisories.test.ts
packages/metadata-protocol/src/protocol-publish-drafts-closure.test.ts
packages/metadata-protocol/src/protocol-publish-drafts-endpoint-gate.test.ts
packages/metadata-protocol/src/protocol-publish-drafts-org-scope.test.ts
packages/metadata-protocol/src/protocol-publish-drafts-package-scope.test.ts
packages/metadata-protocol/src/protocol.adr0005-org-override-rollback.test.ts
packages/metadata-protocol/src/protocol.audit-field-governance.test.ts
packages/metadata-protocol/src/protocol.batch-atomic.test.ts
packages/metadata-protocol/src/protocol.batch-not-attempted.test.ts
packages/metadata-protocol/src/protocol.batch-row-conformance.test.ts
packages/metadata-protocol/src/protocol.batch-row-driver-text.test.ts
packages/metadata-protocol/src/protocol.batch-row-http-status.test.ts
packages/metadata-protocol/src/protocol.batch-verb-driver-code.test.ts
packages/metadata-protocol/src/protocol.batch-verb-driver-text.test.ts
packages/metadata-protocol/src/protocol.bulk-record-not-found.test.ts
packages/metadata-protocol/src/protocol.capability-write-door.test.ts
packages/metadata-protocol/src/protocol.code-only-types.test.ts
packages/metadata-protocol/src/protocol.container-issue-descent.test.ts
packages/metadata-protocol/src/protocol.dashboard-dataset-publish-gate.test.ts
packages/metadata-protocol/src/protocol.delete-object-registry-unregister.test.ts
packages/metadata-protocol/src/protocol.delete-receipt-wording.test.ts
packages/metadata-protocol/src/protocol.delete-rewrap-envelope.test.ts
packages/metadata-protocol/src/protocol.destructive-409-face-inventory.test.ts
packages/metadata-protocol/src/protocol.destructive-gate-reachable-types.test.ts
packages/metadata-protocol/src/protocol.diagnostics-store-outage.test.ts
packages/metadata-protocol/src/protocol.diff-canonical-type-and-history-outage.test.ts
packages/metadata-protocol/src/protocol.diff-credential-redaction.test.ts
packages/metadata-protocol/src/protocol.diff-dead-history-read.test.ts
packages/metadata-protocol/src/protocol.driver-text-disclosure.test.ts
packages/metadata-protocol/src/protocol.dropped-fields.bulk.test.ts
packages/metadata-protocol/src/protocol.dropped-fields.test.ts
packages/metadata-protocol/src/protocol.flow-org-override-closed.test.ts
packages/metadata-protocol/src/protocol.graft-folded-form-sections.test.ts
packages/metadata-protocol/src/protocol.hydrate-overlay-canonical-type.test.ts
packages/metadata-protocol/src/protocol.i18n-bundle-list-merge.test.ts
packages/metadata-protocol/src/protocol.injected-system-columns.test.ts
packages/metadata-protocol/src/protocol.invalid-metadata-422-face-inventory.test.ts
packages/metadata-protocol/src/protocol.legacy-overlay-delete.test.ts
packages/metadata-protocol/src/protocol.lifecycle-audit-rows.test.ts
packages/metadata-protocol/src/protocol.lock-gate-canonical-type.test.ts
packages/metadata-protocol/src/protocol.lock-gate-fail-closed.test.ts
packages/metadata-protocol/src/protocol.many-data-atomic.test.ts
packages/metadata-protocol/src/protocol.meta-list-runtime-baseline-dedup.test.ts
packages/metadata-protocol/src/protocol.meta-types-mint-door-agreement.test.ts
packages/metadata-protocol/src/protocol.metadata-redaction.test.ts
packages/metadata-protocol/src/protocol.metadata-store-outage.test.ts
packages/metadata-protocol/src/protocol.migrate-stored-noncanonical-type.test.ts
packages/metadata-protocol/src/protocol.object-registry-write-through-spelling.test.ts
packages/metadata-protocol/src/protocol.org-scoped-cold-boot-audit-live-registry.test.ts
packages/metadata-protocol/src/protocol.org-scoped-cold-boot-audit.test.ts
packages/metadata-protocol/src/protocol.org-scoped-write-refused.test.ts
packages/metadata-protocol/src/protocol.package-closure-gate.test.ts
packages/metadata-protocol/src/protocol.package-publish-audit-rows.test.ts
packages/metadata-protocol/src/protocol.platform-schedule-org-gate.test.ts
packages/metadata-protocol/src/protocol.publish-commit-capture-read-failure.test.ts
packages/metadata-protocol/src/protocol.publish-item-draft-org-scope.test.ts
packages/metadata-protocol/src/protocol.publish-item-rebind-announce.test.ts
packages/metadata-protocol/src/protocol.publish-side-effects-canonical-type.test.ts
packages/metadata-protocol/src/protocol.publish-stored-type-canonical.test.ts
packages/metadata-protocol/src/protocol.read-decorations.test.ts
packages/metadata-protocol/src/protocol.read-seam-empty-accumulator.test.ts
packages/metadata-protocol/src/protocol.read-verb-canonical-fold.test.ts
packages/metadata-protocol/src/protocol.record-not-found.test.ts
packages/metadata-protocol/src/protocol.record-package-commit-durability.test.ts
packages/metadata-protocol/src/protocol.reference-derivation.test.ts
packages/metadata-protocol/src/protocol.reference-target-unanswerable.test.ts
packages/metadata-protocol/src/protocol.revert-stored-type-canonical.test.ts
packages/metadata-protocol/src/protocol.runtime-authoring-gate.test.ts
packages/metadata-protocol/src/protocol.save-flow-canonicalization.test.ts
packages/metadata-protocol/src/protocol.save-meta-missing-item.test.ts
packages/metadata-protocol/src/protocol.save-receipt-wording.test.ts
packages/metadata-protocol/src/protocol.save-union-issues.test.ts
packages/metadata-protocol/src/protocol.stored-conversions.test.ts
packages/metadata-protocol/src/protocol.stored-migration.test.ts
packages/metadata-protocol/src/protocol.stored-residue-resave.test.ts
packages/metadata-protocol/src/protocol.unrecognised-meta-type.test.ts
packages/metadata-protocol/src/protocol.update-path-id-wins.test.ts
packages/metadata-protocol/src/protocol.upsert-existence.test.ts
packages/metadata-protocol/src/protocol.write-response-internal-fields.tripwire.test.ts
packages/metadata-protocol/src/seed-loader-composite-external-id.test.ts
packages/metadata-protocol/src/seed-loader-deferred-dropped.test.ts
packages/metadata-protocol/src/seed-loader-deferred-failure.test.ts
packages/metadata-protocol/src/seed-loader-driver-text.test.ts
packages/metadata-protocol/src/seed-loader-engine-schema-fallback.test.ts
packages/metadata-protocol/src/seed-loader-env-scope.test.ts
packages/metadata-protocol/src/seed-loader-existing-records-read-failure.test.ts
packages/metadata-protocol/src/seed-loader-multi-value-reference.test.ts
packages/metadata-protocol/src/seed-loader-name-probe.test.ts
packages/metadata-protocol/src/seed-loader-pointer-pair.test.ts
packages/metadata-protocol/src/seed-loader-replay.test.ts
packages/metadata-protocol/src/seed-loader-retry.test.ts
packages/metadata-protocol/src/seed-loader-state-machine-exempt.test.ts
packages/metadata-protocol/src/seed-loader-summary-stale.test.ts
packages/metadata-protocol/src/seed-loader-unresolved-drop.test.ts
packages/metadata-protocol/src/sys-metadata-repository.contract.test.ts
packages/metadata-protocol/src/sys-metadata-repository.draft-drain.test.ts
packages/metadata-protocol/src/sys-metadata-repository.draft-package-inherit.test.ts
packages/metadata-protocol/src/sys-metadata-repository.history-counters.test.ts
packages/metadata-protocol/src/sys-metadata-repository.package-writability.test.ts
packages/metadata-protocol/src/sys-metadata-repository.recorded-by.test.ts
packages/metadata-protocol/src/view-container-runtime-expansion.test.ts
packages/metadata/src/migrations/migrate-sys-notification-to-event.test.ts
packages/plugins/plugin-auth/src/accept-invitation-adopt-membership.test.ts
packages/plugins/plugin-auth/src/admin-revoke-user-session-match-guard.test.ts
packages/plugins/plugin-auth/src/audience-posture.test.ts
packages/plugins/plugin-auth/src/auth-contains-filter.test.ts
packages/plugins/plugin-auth/src/auth-manager.jwt-eddsa-fallback.test.ts
packages/plugins/plugin-auth/src/auth-manager.optional-plugin-isolation.test.ts
packages/plugins/plugin-auth/src/auth-manager.test.ts
packages/plugins/plugin-auth/src/auth-where-operator-coverage.test.ts
packages/plugins/plugin-auth/src/change-email-delete-user-wiring.test.ts
packages/plugins/plugin-auth/src/first-session-membership-ordering.test.ts
packages/plugins/plugin-auth/src/impersonation-bearer-rotation.test.ts
packages/plugins/plugin-auth/src/membership-policy-setting.test.ts
packages/plugins/plugin-auth/src/org-create-posture-gate.test.ts
packages/plugins/plugin-auth/src/organization-add-member.test.ts
packages/plugins/plugin-auth/src/remove-member-permission-guard.test.ts
packages/plugins/plugin-auth/src/remove-user-atomicity.test.ts
packages/plugins/plugin-auth/src/revoke-session-match-guard.test.ts
packages/plugins/plugin-auth/src/scim-case-insensitive-identifier.test.ts
packages/plugins/plugin-auth/src/session-of-record.test.ts
packages/plugins/plugin-auth/src/session-tombstone.test.ts
packages/plugins/plugin-security/src/authored-row-write-verdict.test.ts
packages/plugins/plugin-security/src/check-only-write-scope.test.ts
packages/plugins/plugin-security/src/controlled-by-parent-chain.test.ts
packages/plugins/plugin-security/src/controlled-by-parent-detail-write-authority.test.ts
packages/plugins/plugin-security/src/controlled-by-parent-master-widener.test.ts
packages/plugins/plugin-security/src/controlled-by-parent-sharing.test.ts
packages/plugins/plugin-security/src/explain-engine.test.ts
packages/plugins/plugin-security/src/field-masking-rule.test.ts
packages/plugins/plugin-security/src/invitation-placement.test.ts
packages/plugins/plugin-security/src/packaged-permission-set-lock.test.ts
packages/plugins/plugin-security/src/packaged-permission-set-restore-leg.test.ts
packages/plugins/plugin-security/src/permission-denied-user-copy.test.ts
packages/plugins/plugin-security/src/permission-set-active.test.ts
packages/plugins/plugin-security/src/permission-set-projection.test.ts
packages/plugins/plugin-security/src/permission-set-resolution-memo.test.ts
packages/plugins/plugin-security/src/resolve-permission-sets-for-context.pin.test.ts
packages/plugins/plugin-security/src/row-write-widener-composition.test.ts
packages/plugins/plugin-security/src/security-denial-user-copy.test.ts
packages/plugins/plugin-security/src/security-plugin.test.ts
packages/plugins/plugin-security/src/select-only-write-visibility.test.ts
packages/plugins/plugin-security/src/store-fault-fail-closed.test.ts
packages/plugins/plugin-security/src/vama-write-path-convergence.test.ts
packages/plugins/plugin-sharing/src/authored-row-write-deferral.test.ts
packages/plugins/plugin-sharing/src/share-link-eligibility.test.ts
packages/plugins/plugin-webhooks/src/auto-enqueuer.test.ts
packages/plugins/plugin-webhooks/src/bootstrap-declared-webhooks.test.ts
packages/plugins/plugin-webhooks/src/webhook-drop-durable-record.test.ts
packages/plugins/plugin-webhooks/src/webhook-signing-secret.test.ts
packages/rest/src/meta-compound-save-force-parity.test.ts
packages/rest/src/meta-compound-save-mode-parity.test.ts
packages/rest/src/meta-object-extension-agreement.test.ts
packages/rest/src/meta-object-extension-property-classes.test.ts
packages/rest/src/meta-object-materialization-agreement.test.ts
packages/rest/src/meta-object-overlay-extension-fold.test.ts
packages/rest/src/meta-object-search-companion-agreement.test.ts
packages/rest/src/meta-published-overlay.test.ts
packages/rest/src/public-form-lookup-picker.test.ts
packages/rest/src/public-form-routes.stored-row.test.ts
packages/rest/src/rest-server-meta-read-org-scope.test.ts
packages/runtime/src/action-execution-calldata-batch-retired.test.ts
packages/runtime/src/action-execution-calldata-not-found.test.ts
packages/runtime/src/domains/meta-published-runtime-publish.test.ts
packages/runtime/src/domains/meta-save-destructive-remedy.test.ts
packages/runtime/src/meta-compound-arity-mint-door.test.ts
packages/runtime/src/meta-field-overlay-lock.test.ts
packages/runtime/src/meta-overlay-read-your-writes.test.ts
packages/runtime/src/meta-write-org-scope.test.ts
packages/runtime/src/sandbox/quickjs-runner.test.ts
packages/runtime/src/seed-loader.test.ts
packages/services/service-automation/src/builtin/crud-bulk-intent.test.ts
packages/services/service-automation/src/builtin/crud-config-aliases.test.ts
packages/services/service-automation/src/builtin/crud-filter-guard.test.ts
packages/services/service-automation/src/builtin/crud-output-var.test.ts
packages/services/service-automation/src/builtin/crud-runas.test.ts
packages/services/service-automation/src/builtin/notify-organization-stamp.integration.test.ts
packages/services/service-automation/src/record-lookup-expand.integration.test.ts
packages/services/service-automation/src/run-summary.test.ts
packages/services/service-automation/src/runas-grant-resolution.integration.test.ts
packages/services/service-datasource/src/__tests__/datasource-admin-plugin.test.ts
packages/services/service-messaging/src/delivery-headers-at-rest.integration.test.ts
packages/services/service-messaging/src/email-channel.test.ts
packages/services/service-messaging/src/inbox-channel.test.ts
packages/services/service-messaging/src/messaging-service-plugin.test.ts
packages/services/service-messaging/src/messaging-service.test.ts
packages/services/service-messaging/src/notification-schema-conformance.test.ts
packages/services/service-messaging/src/preference-resolver.test.ts
packages/services/service-messaging/src/read-receipt-organization.test.ts
packages/services/service-messaging/src/recipient-resolver.test.ts
packages/services/service-messaging/src/sms-channel.test.ts
packages/services/service-messaging/src/sql-outbox-audit-columns.test.ts
packages/services/service-messaging/src/template-renderer.test.ts
packages/services/service-storage/src/attachment-access-hooks.test.ts
packages/services/service-storage/src/attachment-lifecycle.test.ts
packages/services/service-storage/src/file-reference-lifecycle.test.ts
packages/services/service-storage/src/lax-deviation-reclamation-gate.test.ts
packages/services/service-storage/src/metadata-store.test.ts
packages/services/service-storage/src/storage-routes.metadata-outage.test.ts
packages/services/service-storage/src/tombstone-download-live-reference.test.ts
packages/spec/src/contracts/data-engine.test.ts
Related
assertEngineFindOnePredicatenow exists and is published from@objectstack/metadata-core(re-exported by@objectstack/objectql), proved against the REAL engine bypackages/objectql/src/engine-findone-predicate.test.ts. ThefindOneslice ofscripts/check-engine-double-contract.mjswas NOT added in that PR, and this card is the remainder — stated with the measurement rather than an estimate.The measurement
Taken by temporarily adding a
findOneslice toSLICESinscripts/check-engine-double-contract.mjsand running the gate. Re-derivable the same way; the slice body is four lines (verb / producer / symbols / modules), mirroring the two write-side entries.Before adoption: 232 files, 275 doubles would newly fail
PINNED [findOne].After the objectql-package adoption that shipped: 209 files, 250 doubles remain.
packages/metadata-protocol/srcpackages/plugins/plugin-securitypackages/plugins/plugin-authpackages/services/service-messagingpackages/rest/srcpackages/runtime/srcpackages/services/service-automationpackages/services/service-storagepackages/mcp/srcpackages/plugins/plugin-webhookspackages/plugins/plugin-sharingpackages/core/srcpackages/metadata/srcpackages/services/service-datasourcepackages/spec/src"already pinned for a write verb" = the file appears in
scripts/engine-double-contract.pinned.json, so its author already routesdeleteand/orupdatethrough the producer's predicate and thefindOnepin is one import plus one call. "DEBT-ledgered only" / "in neither ledger" are the two populations that need more than a mechanical edit.Why the slice did not land with the guard
Two reasons, both structural rather than a matter of effort.
packages/specwhich cannot import the predicate even in principle becausemetadata-coredepends onspec). Those wantscripts/engine-double-contract.baseline.jsonentries, and the gate's own failure text is explicit that a baseline entry is MAINTAINER-ONLY — "that baseline is shrink-only, so an entry weakens a ratchet and needs a maintainer to agree first — do not take this path to get CI green."The
updateslice landed the same way in #5480 — a first measurement with 116 unguarded doubles ledgered in one act, recorded in the baseline's own$commentas "not newly written looseness and not a raised ratchet". Whether thefindOneslice repeats that shape, or lands per-package behind a shrinking remainder, is the decision this card carries.Suggested shape
findOneslice toSLICES(the gate'spinCallreadsassertEngineFindOnePredicate(object, query)— note it takes the object name, unlike the two write-side asserts, because the engine's refusal message quotes the object twice).packages/metadata-protocolalone is 102 files / 120 doubles and 90 of them are already pinned for a write verb.The exact remainder
The 209 files, one per line, as the gate reported them:
209 files
Related
assertEngineFindOnePredicate— a fake answers a predicate-less findOne that the real engine REFUSES, and #11767 is what that costs #11957 — the guard this completes (the predicate, the conformance case-set, and thepackages/objectqladoption).findOnethen returns the first row #4419 — the engine rule the predicate mirrors.resolveEngineDeleteDispatch,update 的同款三分支只是 engine.ts 里的一个内联 throw #5480 — the precedent for how a new slice's first measurement lands.