Skip to content

feat(metadata-protocol/objectql): turn-atomic package publish — a commit cannot half-land (ADR-0067 D2, #3066) - #3074

Merged
os-zhuang merged 3 commits into
mainfrom
claude/auth-model-design-eval-xxgzcl
Jul 16, 2026
Merged

feat(metadata-protocol/objectql): turn-atomic package publish — a commit cannot half-land (ADR-0067 D2, #3066)#3074
os-zhuang merged 3 commits into
mainfrom
claude/auth-model-design-eval-xxgzcl

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Summary

Implements ADR-0067 Decision-2 per the design in #3066: package-draft publishing is now all-or-nothing. Previously publishPackageDrafts promoted 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_commit record run inside ONE engine.transaction(). Any failure → the whole batch rolls back → publishedCount: 0; the causal item carries its real error/code/issues, every other draft reports code: '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: publishMetaItem split into promoteDraftForPublish (guards + promote, metadata-only) and runPublishSideEffects; single-item behavior unchanged. publishPackageDrafts rewritten to the two-phase flow; recordPackageCommit moved 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's withTxn (promoteDraft's put + draft-delete) participate in the batch transaction unchanged — and closes promoteDraft's old best-effort draft-delete gap for free.
  • Fallback: engines without transaction() (memory driver, minimal stubs) keep the previous sequential behavior — same stance as the repo's withTxn.

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 plus batch_aborted entries.

Also in this PR

The concurrent #3037 restructure (packages/dogfoodpackages/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 to packages/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.
  • dogfood (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).
  • ESLint clean on all changed files. Changeset included (minor ×2, BREAKING noted).

Closes#3066.

🤖 Generated with Claude Code


Generated by Claude Code

claude added 2 commits July 16, 2026 15:13
…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).
@vercel

vercelBot commented Jul 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
specCanceledCanceledJul 16, 2026 3:26pm

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling size/l labels Jul 16, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/metadata-protocol, @objectstack/objectql, packages/qa.

15 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/concepts/metadata-lifecycle.mdx(via @objectstack/metadata-protocol, @objectstack/objectql)
  • content/docs/data-modeling/formulas.mdx(via packages/objectql)
  • content/docs/deployment/migration-from-objectql.mdx(via @objectstack/objectql)
  • content/docs/deployment/vercel.mdx(via @objectstack/objectql)
  • content/docs/kernel/services-checklist.mdx(via @objectstack/objectql)
  • content/docs/kernel/services.mdx(via @objectstack/objectql)
  • content/docs/permissions/authentication.mdx(via @objectstack/objectql)
  • content/docs/permissions/authorization.mdx(via packages/qa)
  • content/docs/permissions/delegated-administration.mdx(via packages/qa)
  • content/docs/plugins/index.mdx(via @objectstack/objectql)
  • content/docs/plugins/packages.mdx(via @objectstack/objectql)
  • content/docs/protocol/kernel/index.mdx(via @objectstack/objectql)
  • content/docs/protocol/objectql/state-machine.mdx(via @objectstack/objectql)
  • content/docs/releases/implementation-status.mdx(via @objectstack/objectql)
  • content/docs/releases/v9.mdx(via @objectstack/objectql)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang marked this pull request as ready for review July 16, 2026 15:34
@os-zhuang
os-zhuang merged commit d75c7ac into mainJul 16, 2026
17 checks passed
@os-zhuang
os-zhuang deleted the claude/auth-model-design-eval-xxgzcl branch July 16, 2026 15:34
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/lteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ADR-0067 Decision-2 unimplemented: package-draft publish is not turn-atomic — a commit CAN half-land

2 participants

@os-zhuang@claude