feat(projects): server-managed blocksMajor marker for Blocks v8 sites
Part of the v8 Studio stack (base: #7796). First of the v8 Fast Preview + Localhost track, on top of #7843. PO decisions of 2026-10-11, requirements R1–R5.
Projects now learn they are Blocks v8 before any thread exists. Today v8 is known only from an async probe that runs only for cms threads, and a thread is cms only when metadata.fastPreview is on: a circle. The server now writes a project marker, metadata.blocksMajor: 8, which the next PRs use to make v8 always Fast Preview (R2/R3) without touching v7 (R1).
What
isBlocksV8Project(meta)(packages/shared/src/thread/session-runtime.ts):meta?.blocksMajor === 8.- Server-managed:
blocksMajorjoinssandboxMapinstripServerManagedMetadata, so the settings form or a tool call can neither set nor clobber it;metadataKeptOnClearkeeps it (withsandboxMapandsiteSlug) when a client sendsmetadata: null. - Written only for orgs with
site_editor_content_protocoland only when main's.deco/schema.gen.jsonis v8; cleared when main is no longer v8. A v7 site never has it. - Where:
hosted/blocks-major.ts(syncBlocksMajorMarker,markBlocksV8OnCreate):- project create / deco import (
tools/virtual/create.ts), so a new v8 project's first thread already opens in Fast Preview; - the admin site-claims backfill on real runs. Run it once before release so existing v8 projects get the marker;
- write-through wherever
mainIsV8already runs: decofile GET and publish, site-token issue, and the hosted/git/*routes (loadHostedDraft).
- project create / deco import (
- Single-key
patchMetadata(no read-merge-write oversandboxMap), best-effort: a failed write is logged, never fails the request. The request-cached project storage now drops its cache onpatchMetadatatoo.
No visible behaviour change in this PR.
R1 (v7 = main)
v7 projects never get the marker, so nothing keyed on it changes for them. Create in a flagged org does one extra read of main's schema (best-effort, errors swallowed).
Tests
apps/api/src/hosted/blocks-major.test.ts: sets, clears, no-op when it already matches, write errors swallowed; on create: v8 repo marked, site folder honoured, v7 never marked, flag off means no read and no write, no repository means nothing happens, repo errors swallowed.apps/api/src/tools/strip-server-managed-metadata.test.ts:blocksMajorstripped; kept on clear.tsc --noEmitforapps/apiandpackages/shared, oxlint, andbiome formatare clean.bun test src/hosted src/api/routes/decofile.test.ts src/api/routes/sandbox-proxy*.test.ts src/tools/virtual→ 152 pass. The 1 failure isstudio-pack.integration, which needs a database and fails on the base too.
Stack
v8 Fast Preview track: previous: #7843 · next: #7872
Review fixes (f735723f1)
- The marker is written on create only when the hosted CMS can serve the project: the project owns its site id and a delivery bucket is configured, the same checks the hosted routes make. A marked project never polls a hosted route that answers 404 or 503.
COLLECTION_VIRTUAL_MCP_CREATEno longer waits for the marker (void markBlocksV8OnCreate(...), which never throws), so creating or importing a site never waits on GitHub. If it misses, the write-through and the backfill set it.projectPackagePathreplaces the inline copies in admin.ts, hosted.ts, decofile.ts and draft-publish-status.ts.
🤖 Generated with Claude Code