Skip to content

feat(metadata): draft/package lifecycle for publish-as-preview (overlay reads, teardown, discard, delete)#1569

Merged
xuyushun441-sys merged 4 commits into
mainfrom
worktree-draft-overlay-preview
Jun 3, 2026
Merged

feat(metadata): draft/package lifecycle for publish-as-preview (overlay reads, teardown, discard, delete)#1569
xuyushun441-sys merged 4 commits into
mainfrom
worktree-draft-overlay-preview

Conversation

@xuyushun441-sys
Copy link
Copy Markdown
Contributor

@xuyushun441-sys xuyushun441-sys commented Jun 3, 2026

Backend for the draft/package lifecycle behind "publish-as-preview" (ADR-0033 review loop) — drafts as a first-class state for both humans and the AI. Five composable capabilities, each independently tested.

1. Draft-overlay reads (previewDrafts)

Render the console (or let the AI discover) pending drafts before publish. getMetaItems/getMetaItem overlay state='draft' on active (draft wins; draft-only surfaces; _draft:true tag); dispatcher threads ?preview=draft.

2. Storage teardown on delete (dropStorage)

Object storage was create-only — delete left an orphan table. engine.dropObjectSchema → driver dropTable; deleteMetaItem({dropStorage}) DESTRUCTIVE/opt-in, gated (object+active only, never sys_); DELETE /meta/:type/:name?dropStorage=true.

3. discardPackageDrafts — abandon edits, revert to baseline

NON-destructive: drops only draft rows. POST /packages/:id/discard-drafts. "Edited a while, it's worse — abandon all changes."

4. deletePackage — remove an unwanted package entirely

DESTRUCTIVE: all package rows + object tables (keepData=true preserves tables). DELETE /packages/:id now does this persisted removal (was registry-only). "Don't want this package anymore."

5. AI authoring is draft-aware + package-aware (Fix 4)

Found while verifying the process guardrail:

  • list_objects/list_metadata were active-only → the agent couldn't find an object it just drafted when authoring a flow for it. Now pass previewDrafts:true (reusing Add metamodel interfaces for ObjectQL/ObjectUI contract #1, the unifying mechanism).
  • apply_blueprint now surfaces a top-level packageId + bindingHint so the agent binds the follow-up flow to the app package instead of orphaning it.

Why this shape (design note)

True data preview of a brand-new draft object is hard (no table until publish; the platform had no drop-table teardown at all). Chosen approach: cheap draft-overlay for structural/AI discovery, and lean on publish (into a dev sandbox) for data-level confirmation — made safe by reversible item teardown + package discard/delete. Admin-gating ?preview=draft is a deliberate follow-up. See docs/notes/draft-overlay-preview-plan.md.

Tests

protocol-meta (overlay), protocol-publish-rollback (teardown), protocol-package-lifecycle (discard/delete), metadata-tools + blueprint-tools (Fix 4). Full objectql green (519); service-ai green (one pre-existing env-dependent embedder test aside). Dispatcher/rest typecheck clean.

Pairs with objectui#1472 (Discard/Delete buttons) and framework#1570 (process guardrail).

🤖 Generated with Claude Code

…review

ADR-0033's loop is build(draft) -> review -> publish, but review was only a
JSON diff; the rendered object page / kanban / form / nav that actually
confirms a change only existed AFTER publish. This adds a request-scoped
draft-overlay read mode so an (admin) reviewer can render the console off
pending drafts before publishing:

- getMetaItems({previewDrafts}) overlays state='draft' rows on active (draft
  wins; draft-only surfaces; never hydrates the SchemaRegistry).
- getMetaItem({previewDrafts}) is non-strict: draft if present, else active
  (vs strict state:'draft' which 404s no_draft).
- overlaid items tagged _draft:true for UI badging.
- dispatcher threads ?preview=draft on GET /metadata/:type[/:name].

Admin gating of the flag is a deliberate follow-up (step 2). The same overlay
also unblocks the AI agent referencing its own drafts (follow-up).

Tests: protocol-meta draft-overlay (draft wins, draft-only, _draft, getMetaItem
fallback) + full objectql sweep green (509).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 3, 2026

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

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jun 3, 2026 11:58am

Request Review

Object storage was create-only: publish creates a table, but deleteMetaItem
only tombstones the metadata row, leaving the physical table behind. That made
"publish an object just to preview it with data, then discard" leave residue.

- engine.dropObjectSchema(name): inverse of syncObjectSchema; calls the driver's
  existing dropTable.
- deleteMetaItem({dropStorage}): opt-in, DESTRUCTIVE, guarded — object + active
  only, never sys_; default false keeps delete non-destructive. Best-effort.
- REST: DELETE /meta/:type/:name?dropStorage=true.

Makes "publish to preview -> discard" cleanly reversible (the chosen approach:
lean on publish-into-dev for data confirmation, made safely undoable).

Tests: deleteMetaItem teardown (drops for object+active; not by default; not
sys_; not non-object) + objectql sweep green (513).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@xuyushun441-sys xuyushun441-sys changed the title feat(metadata): draft-overlay reads (previewDrafts) for pre-publish preview [PR1/backend] feat(metadata): draft-overlay reads + storage teardown (publish-as-preview backend) Jun 3, 2026
});

it('does not drop storage for a non-object type even with dropStorage', async () => {
const { engine, rows } = makeStubEngine();
…rd / delete)

Two distinct package-level operations on the per-item delete primitive:

- discardPackageDrafts(packageId): drop only pending DRAFT rows, revert to the
  published baseline. NON-destructive (active metadata + tables untouched).
  "I edited this app a while, it's worse than before — abandon all changes."
  sys_metadata path (no metadata-service dep, unlike POST /packages/:id/revert).
  REST: POST /packages/:id/discard-drafts.

- deletePackage(packageId): remove ALL package rows (active + draft) + tear down
  each object's table by default (DESTRUCTIVE; keepData:true preserves tables,
  sys_ guard still applies). "I don't want this package anymore."
  DELETE /packages/:id now also does this persisted removal (previously only the
  in-memory registry unregister, leaving AI-package rows + tables behind);
  ?keepData=true opts out of teardown.

Drafts deleted before active so each table is dropped once; per-item failures
collected without aborting. Tests: orchestration for both + objectql sweep (519).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot added size/l and removed size/m labels Jun 3, 2026
@xuyushun441-sys xuyushun441-sys changed the title feat(metadata): draft-overlay reads + storage teardown (publish-as-preview backend) feat(metadata): draft/package lifecycle for publish-as-preview (overlay reads, teardown, discard, delete) Jun 3, 2026
…kageId (Fix 4)

Two gaps that broke the multi-step "build app -> author a flow for it" path
(found verifying the solution_design guardrail):

1. AI couldn't discover its own draft objects: list_objects/list_metadata read
   getMetaItems active-only, so a just-drafted object was "not found" when the
   agent then authored a flow against it. They now pass previewDrafts:true
   (older runtimes ignore the flag -> stay active-only). describe was already
   draft-first.
2. The auto-authored flow had no package to bind to: apply_blueprint now
   surfaces a top-level packageId + bindingHint so the agent passes it to
   create_metadata and the flow lands in the app package, not an orphan draft.

Makes the guardrail's "model data, then proactively draft the approval flow
bound to the app" executable end-to-end. service-ai suite green (ai-service
embedder test fails only locally — env-dependent, untouched).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@xuyushun441-sys xuyushun441-sys merged commit ac1fc4c into main Jun 3, 2026
12 checks passed
@xuyushun441-sys xuyushun441-sys deleted the worktree-draft-overlay-preview branch June 3, 2026 14:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/l tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants