feat(metadata-protocol/objectql): turn-atomic package publish — a commit cannot half-land (ADR-0067 D2, #3066)#3074
Merged
Conversation
…67 D2, #3066) Phase 1: every draft promotion + the sys_metadata_commit record run inside ONE engine.transaction() — a mid-batch failure rolls back everything (publishedCount 0; causal item carries its real error, the rest report batch_aborted). publishMetaItem is split into promoteDraftForPublish (guards + promote, metadata-only) and runPublishSideEffects so the batch can transact promotions while deferring side effects. Phase 2 (post-commit): registry refresh, DDL, seed batch apply, materializers, ADR-0094 projections, events — best-effort, surfaced via materializeApplied.failures instead of faking an unpublish (metadata is live; boot reconciliation heals side-effect drift). objectql: engine.transaction() now JOINS an already-open ambient transaction instead of opening a nested driver transaction — a nested begin deadlocks single-connection pools (SQLite knex) and escapes the outer rollback. Locked by two new engine-ambient-transaction tests. BREAKING (behavioral): consumers relying on partial batch publishes now get all-or-nothing. Engines without transaction() keep the previous sequential behavior (same fallback stance as the repo's withTxn). Tests: publish contract suite rewritten to the two-phase seams (+4 new cases incl. rollback/commit tracking and side-effect-failure surfacing); commit-history suite updated; 29 green across the three suites.
…aned search-conformance files - build-probes.test.ts publish suite: spy promoteDraftForPublish + runPublishSideEffects (the batch no longer calls publishMetaItem per item, ADR-0067 D2). objectql suite back to 904/904. - The #3037 packages/dogfood -> packages/qa/dogfood restructure merged concurrently with #3065 and did not carry its three just-added files; they were orphaned at the old path outside every workspace (silently not running in CI). git mv them to packages/qa/dogfood/test — all 5 dogfood suites green at the new home (21 tests).
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 3 package(s): 15 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements ADR-0067 Decision-2 per the design in #3066: package-draft publishing is now all-or-nothing. Previously
publishPackageDraftspromoted drafts per-item with catch-and-continue — a mid-batch failure left earlier items live and later ones unpublished, and the commit record described the partial landing. For AI-authored batches this was a main-path risk: a metadata state nobody reviewed.Design (two-phase publish)
Phase 1 — atomic metadata writes. Every draft promotion AND the
sys_metadata_commitrecord run inside ONEengine.transaction(). Any failure → the whole batch rolls back →publishedCount: 0; the causal item carries its real error/code/issues, every other draft reportscode: 'batch_aborted'. The commit row and the state it describes land or roll back together — a recorded commit can never describe a partial publish.Phase 2 — post-commit side effects. Registry refresh, table DDL, batched seed apply, ADR-0086 P2 materializers, ADR-0094 projections, mutation events — per item, after the metadata committed. Deliberately outside the transaction: DDL can't run inside the driver tx (deadlocks the single-connection SQLite pool), in-memory registry writes can't roll back, and projections are boot-healed. A side-effect failure is surfaced via
materializeApplied.failures, never turned into a fake unpublish (the metadata IS live).Key changes
metadata-protocol:publishMetaItemsplit intopromoteDraftForPublish(guards + promote, metadata-only) andrunPublishSideEffects; single-item behavior unchanged.publishPackageDraftsrewritten to the two-phase flow;recordPackageCommitmoved inside the transaction (it stays internally best-effort, so a commit-store hiccup doesn't abort a good batch).objectql:engine.transaction()now JOINS an already-open ambient transaction instead of opening a nested driver transaction — a nested begin deadlocks single-connection pools and escapes the outer rollback. This is what lets the repository'swithTxn(promoteDraft's put + draft-delete) participate in the batch transaction unchanged — and closes promoteDraft's old best-effort draft-delete gap for free.transaction()(memory driver, minimal stubs) keep the previous sequential behavior — same stance as the repo'swithTxn.BREAKING (behavioral, release-notes)
API consumers relying on partial batch publishes ("2 of 3 landed") now get all-or-nothing. The response shape is unchanged;
failed[]now enumerates the causal item plusbatch_abortedentries.Also in this PR
The concurrent #3037 restructure (
packages/dogfood→packages/qa/dogfood) didn't carry #3065's three just-merged search-conformance files — they were orphaned outside every workspace (silently not running in CI). Moved topackages/qa/dogfood/test/; all 5 dogfood suites green at the new home.Test plan
objectql: 904/904 (publish contract suite rewritten to the two-phase seams: +4 cases incl. transaction rollback/commit tracking, batch_aborted shape, side-effect-failure surfacing; commit-history + build-probes suites migrated; 2 new ambient-join engine tests incl. nested-throw → outer rollback).metadata-protocol: 29/29.packages/qa/dogfood): search-conformance + showcase-search + two-doors-permission + showcase-permission-projection + showcase-permission-seeding — 21/21 (real kernel boot, the publish→materialize→project chain exercised end-to-end).Closes #3066.
🤖 Generated with Claude Code
Generated by Claude Code