mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-03 10:37:48 +09:00
0.284.0
6551
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
44c9e67b29 | build: Release 02-08-2026 0.284.0 | ||
|
|
56a22fde8a |
feat: Add storage-backed document graph resolution (#5966)
## Summary Introduce a document graph architecture for Assets resources so structured documents can reference one another while keeping full document payloads on CDN-backed storage. The content database will retain the searchable index and dependency graph. At runtime, the server will select a root document, determine its complete dependency set before performing I/O, fetch each unique document concurrently, and assemble the final result server-side. ## Implementation todos ### Document graph foundation - [x] Add normalized internal reference contracts for whole documents, JSON paths, Markdown body, and Markdown frontmatter. - [x] Add an immutable graph abstraction with deterministic ordering, dependency traversal, revision validation, and cycle detection. - [x] Add a storage-independent resolver with dependency closure, bounded parallel loading, shared-content deduplication, representation selection, assembly hooks, cancellation, and structured errors. - [x] Add focused unit coverage for the isolated document-graph abstraction. - [x] Define and validate the external remote-document reference syntax. - [x] Add a pure graph compiler that resolves canonical document URLs into IDs and revisions and validates missing, duplicate, and cyclic dependencies. ### Build-time graph - [x] Add a storage-independent source-catalog compiler for bounded parallel reference discovery and deterministic graph compilation. - [x] Add a versioned deterministic document graph artifact with canonical serialization and integrity verification. - [x] Discover and normalize statically declared references while Assets resources are processed. - [x] Resolve document identities and revisions and report missing, stale, or cyclic dependencies with document context. - [x] Persist document nodes and dependency edges alongside searchable resource metadata. - [x] Include persisted graph data in artifact integrity and size validation. ### Document representations - [x] Add a standalone JSON document adapter for exact reference markers, compiler occurrences, JSON path selection, and immutable assembly. - [x] Add a standalone Markdown document adapter for bounded decoding, frontmatter references, immutable assembly, and source, body, and frontmatter selection. - [x] Parse fetched JSON and Markdown documents through format-specific adapters. - [x] Select complete documents, JSON fragments, Markdown body, and Markdown frontmatter through the shared reference model. - [x] Assemble nested and shared references into the final server-side value. ### Runtime resolution - [x] Enforce reachable-document, per-document byte, and aggregate-byte limits before parsing and assembly. - [x] Add a revision-keyed bounded source-cache wrapper with replayable bytes, stale-entry fallback, and in-flight deduplication. - [x] Add a storage-neutral loaded-source contract that rejects revision mismatches before parsing. - [x] Resolve graph-backed property paths before filtering, sorting, pagination, and projection; skip graph loading for unrelated queries. - [x] Add an injected HTTP/CDN document loader with revision metadata validation. - [x] Apply runtime payload limits, bounded concurrency, caching, and structured failure mapping. - [x] Ensure shared documents are fetched and parsed once per resolution. ### Product integration - [x] Integrate equivalent behavior in local preview, SSR, SSG, and published runtime paths. - [x] Preserve existing embedded Assets resource behavior without requiring migration. - [x] Add observability for graph loading, document fetching, caching, and resolution failures. - [x] Document the public reference and resolution behavior. ### Review hardening - [x] Enforce graph, artifact, cache, and published-storage identity consistency. - [x] Compile only graph sources reachable from selected build entries. - [x] Resolve graph-backed fields before query evaluation and avoid unnecessary graph loading. - [x] Consolidate duplicated graph schemas, utilities, and document content-type detection. - [x] Correct runtime documentation and use structural evaluation validation. ### Verification - [x] Keep a deterministic high-impact agent evaluation for Markdown-to-JSON references across the dynamic blog overview and article routes. - [x] Add a separate discoverability evaluation that must learn the reference workflow from MCP guidance without prompt-supplied syntax, queries, bindings, or call order. - [ ] Re-run the complete local agent evaluation suite after the discoverability fixture change and compare every fixture with its accepted baseline. - [x] Add integration coverage for CDN-backed hydration, parallel fetching, caching, and shared dependencies. - [x] Add integration coverage for missing references, cycles, revision changes, limits, and cancellation. - [x] Verify equivalent behavior across preview, SSR, SSG, and published deployments. - [x] Verify that existing embedded Assets resources retain their current behavior. ## Intended outcome - Storage-backed documents do not require their complete payloads to be embedded in the content database. - The server knows the complete statically discoverable dependency set before fetching document content. - Shared dependencies are fetched once per resolution and independent resources can be fetched in parallel. - JSON fragments and Markdown body/frontmatter representations use the same document-resolution system. - Reference and payload revisions cannot be mixed silently. - Existing Assets resources continue to work without migration. ## Verification results - `@webstudio-is/content-engine`: 37 files / 244 tests passed; typecheck passed. - `@webstudio-is/asset-uploader`: 22 files / 182 tests passed; typecheck passed. - CLI: 57 files / 925 tests passed, including generated SSR and SSG build/prerender coverage; typecheck passed. - Repository-wide `pnpm oxfmt --check` passed across 2,757 files. - Package-boundary validation passed. - Previous `pnpm evaluations` run: all 4 original high-impact fixtures passed. The complete 5-fixture rerun is pending explicit approval after adding the discoverability fixture. |
||
|
|
3ccb46cec7 |
fix: restore Marketplace settings and optimize Assets publishing (#5964)
## Outcome Restore the Marketplace section for projects without existing marketplace metadata, make the complete review-submission workflow available over MCP, clarify shared Assets database diagnostics, and reduce published database size by materializing fully static Assets queries. ## Implementation ### Marketplace and MCP - Initialize the Marketplace form from a safe partial default instead of rendering nothing when metadata is unconfigured. - Keep review submission disabled until the complete metadata schema is valid. - Allow `get-marketplace-product` to return `null` and `update-marketplace-product` to create the first marketplace product through ProjectSession/MCP. - Add a confirmed `submit-marketplace-product` server operation that validates configured metadata before setting review status to `PENDING`. - Document the MCP workflow: upload the thumbnail, update metadata, publish production, then submit. - Correct the Marketplace thumbnail upload example to use the current MCP input field. ### Assets database - Show query size and merged published-database size separately in resource diagnostics. - Clarify that only the merged database counts toward the publish limit. - Allow the Assets query editor to scroll long query source. - Materialize fully static metadata-only Assets queries at publish time. - Store materialized results as compact field columns and rows keyed by a deterministic normalized-query hash. - Serve materialized rows through the existing Assets response contract without candidate documents or a runtime field catalog. - Keep route- or variable-dependent queries on the existing document-backed runtime path. - Exclude overview-only fields from dynamic detail documents so the merged database does not duplicate them. - Preserve byte-limit selection, truncation diagnostics, integrity verification, caching, and backward compatibility with existing artifacts. ### Release - Keep the release lockfile stable when preparing the CLI package. - Regenerate runtime contracts, server-only API metadata, and CLI documentation where required. ## Todo - [x] Restore the empty Marketplace settings state - [x] Prevent empty review submissions - [x] Support first-time Marketplace metadata creation over MCP - [x] Add MCP review submission - [x] Document the end-to-end MCP workflow - [x] Correct query and merged-database diagnostics - [x] Make long Assets query source scrollable - [x] Materialize static overview queries - [x] Preserve dynamic detail-query behavior - [x] Add regression coverage with fail/pass proof - [x] Run relevant package and integration checks ## Verification - [x] Content engine tests: 158 passed - [x] Asset uploader tests: 179 passed - [x] SDK tests: 505 passed - [x] CLI tests: 921 passed - [x] CLI prebuild integration tests: 46 passed - [x] Builder Assets resource and diagnostics tests: 14 passed - [x] Project runtime and ProjectSession tests: 133 passed - [x] Builder API router tests: 30 passed - [x] Protocol operation tests: 18 passed - [x] Content engine build and declaration generation - [x] Content engine, asset uploader, SDK, Builder, and CLI typechecks - [x] Repository lint and formatting checks - [x] Generated API and documentation checks - [x] New materialization tests demonstrated failing with the implementation disabled and passing after restoration ## Notes - The representative five-post overview fixture shrinks from 2,122 bytes to 1,197 bytes while returning the same sorted and paginated result. - Materialization is intentionally limited to static, metadata-only field queries without runtime asset fields. Unsupported or data-incompatible queries safely use the existing runtime database. - The complete `pnpm evaluations` agent suite was not run because repository policy requires separate explicit approval. - No database schema or migration changes are required. |
||
|
|
3aeb4b3f61 |
fix: Reuse npm launcher for generated previews (#5962)
## Summary Generated previews now reuse the npm CLI path supplied by the npx launcher instead of rediscovering npm or npm.cmd through the MCP subprocess PATH. The same invocation is used for dependency installation, production builds, and preview server startup, with the existing platform command retained as a fallback for direct launches. ## Technical choices - Invoke npm-cli.js with the current Node executable when npm_execpath identifies npm as the launcher. - Parse Windows paths with the platform path implementation. - Keep npm and npm.cmd fallback behavior when Webstudio was not launched through npm. - Inject executable paths in tests so launcher behavior is deterministic. ## Todo - [x] Reuse the npx npm launcher during generated dependency installation. - [x] Apply the same launcher to generated build and server commands. - [x] Cover Windows launcher paths and direct-launch fallbacks. - [x] Run focused tests, typecheck, lint, formatting, and production build. ## Verification - pnpm --filter webstudio test -- src/commands/preview.test.ts src/preview-server.test.ts - pnpm --filter webstudio typecheck - pnpm exec oxlint --deny-warnings on the four changed files - pnpm --filter webstudio build - git diff --check All checks passed. The build emitted the existing Radix use-client bundling warnings. Agent evaluations were not run because they require separate explicit approval. |
||
|
|
e210fedc02 |
fix: support Cursor-compatible MCP tool names (#5961)
## Summary - configure Cursor connections to request underscore-only MCP tool names - advertise Cursor-safe names while mapping calls back to canonical Webstudio operations - preserve canonical tool names for other MCP clients and shell workflows ## Verification - pnpm --filter webstudio test -- src/commands/connect.test.ts src/commands/mcp.test.ts - pnpm --filter @webstudio-is/project-build test -- src/mcp.test.ts - pnpm --filter webstudio typecheck - pnpm --filter @webstudio-is/project-build typecheck - pnpm exec oxlint --deny-warnings on changed files - pnpm exec oxfmt on changed files - pnpm evaluations not run (requires separate explicit approval) Closes #5960 |
||
|
|
efbc3098c4 |
feat: add queryable Assets resources (#5946)
Closes #5919 Ref #5920 ## Outcome Extend the existing Assets system resource with optional queries for Markdown, JSON, and standard file metadata. Unconfigured Assets resources retain the existing fetch-all behavior and activate none of the content-query infrastructure. Files are the authoring model. A standalone content engine converts an immutable snapshot of only the files required by configured queries into one bounded, deterministic runtime database. Builder preview, SSR, and SSG use the same query semantics without requiring a database service for a published site. ## Final architecture ```text Markdown / JSON files │ ▼ ContentSource adapter (FS or Webstudio Assets) │ immutable snapshot ▼ ContentCompilationPlan (union of configured query requirements) │ ▼ ContentCompiler (parse, normalize, discover fields, enforce budget) │ ▼ ContentArtifact (bounded, deterministic, immutable JSON) │ ▼ ContentDatabase (filter, OR groups, sort, paginate, project, read content) │ ├── Builder preview ├── SSR runtime └── SSG build only ``` The authoring/storage layer owns mutable files. The content engine consumes immutable snapshots and produces immutable, disposable artifacts. Query authoring is a separate OpenAPI-driven path: ```text Assets REST OpenAPI operation + standard request JSON Schema + dynamic field paths │ ▼ Generic OpenAPI adapter │ resolved schemas, controls, paths, and transport mapping ▼ Generic query-builder core and React renderer │ arbitrary provider-defined value ▼ Assets REST request adapter │ ▼ { query: value } ``` The selected standard OpenAPI operation is the only source of query UI semantics. Request parameters and JSON Schema describe the editable data; the generic renderer derives controls and owns layout. ### Activation and compilation - The compiler does not index every asset. It combines all reachable configured Assets-resource queries into one `ContentCompilationPlan`. - Static constraints such as folder, path, and file type select candidate files. Dynamic values such as a route-bound slug cannot reduce the build-time candidate set. - The plan contains the union of fields used by filtering, sorting, routing, projection, excerpts, and requested full content. - Documents shared by multiple resources are stored once in one deployment-wide runtime database. - Markdown/frontmatter, JSON properties, excerpts, and full bodies are prepared only when required. - No configured content query means no parsing, artifact, or shipped runtime dependency. Fresh generated apps need no content-runtime cleanup; incremental generation removes stale integration if a previously configured query is deleted. ### Runtime database limit - `CONTENT_DATABASE_MAX_BYTES` limits the complete serialized runtime database, not source files, images, or unrelated assets. - The default is `500 * 1024` bytes and is presented as 500 KiB. - Counted data includes indexed metadata, frontmatter/JSON properties, excerpts, the field catalog, serialization overhead, and full Markdown bodies only when requested. - Prepublish validation builds and serializes the exact database that will be attached to the immutable build, so it knows the unbounded size, bounded size, included documents, omitted documents, and affected resources. - Overflow never stores partial documents. Candidates are ordered by `createdAt` descending, canonical path ascending, and stable document ID ascending. Missing dates follow dated documents. A document that does not fit is skipped while smaller later documents are still considered. - Exceeding the limit warns but does not block publishing. - Builder preview can report exact bounded versus unbounded results when dynamic expressions have concrete preview values. Prepublish warnings remain conservative for future route values. ### Snapshot consistency The source contract guarantees a consistent compilation, while adapters provide the mechanism: - Webstudio Assets captures asset metadata and immutable content references. - Filesystem sources capture file identity and verify files did not change before accepting the artifact. - A changed source retries once, then fails clearly instead of producing a mixed-revision database. - This requires no universal snapshot service, source-tree copy, or new versioned-asset infrastructure. ### Package ownership - `@webstudio-is/content-engine`: runtime artifact schema, query execution, field catalog, compact runtime statistics. - `@webstudio-is/content-engine/compiler`: source snapshots, compilation plans, Markdown/JSON parsing, deterministic compilation, byte accounting, and compiler diagnostics. This entry exists to keep Remark/YAML/future MDX dependencies out of runtime bundles. - `@webstudio-is/query-builder`: resolves standard OpenAPI operation schemas into an internal provider-neutral editor model, validation, mutations, and source serialization. It owns no Assets, provider-authored UI contract, or fixed REST-query semantics. - `@webstudio-is/query-builder/react`: container-neutral schema renderer whose layout is renderer policy. It remains separate from the content engine. - SDK: Webstudio Assets/Resource domain models and mapping Webstudio expressions into generic content requirements. - Protocol: external Assets REST/OpenAPI transport contracts. - Asset uploader/repository: asset and folder mutations, generic metadata, immutable byte references, and storage access. Its hosted adapter supplies Webstudio Assets snapshots and parsed-metadata cache persistence to the content engine; parsing, artifact creation, and query semantics remain engine-owned. - Builder and generated-app integrations decide when to compile, cache, embed, load, or discard a database. ### Runtime lifecycle - Builder caches immutable `ContentDatabase` instances by source revision plus compilation-plan hash and coalesces concurrent compilation. Matching operations reuse the same instance; field discovery uses a dedicated minimal all-properties plan that excludes excerpts and bodies. - SSR attaches the validated bounded database to the build and includes the small runtime only when required. - SSG uses the database only while generating pages and omits it and the runtime from final output unless a future runtime-query feature requires them. - Local development compiles from the filesystem and uses identical query semantics. - Published pages query their local artifact; they do not call Builder REST endpoints. - Published artifacts need no external index store, invalidation, garbage collection, SaaS content proxy, new bucket, or new environment variable. ## Implemented foundation These existing parts remain useful and should be moved behind the final ownership boundaries rather than reimplemented. - [x] Upgrade the existing Assets system resource in place and preserve unconfigured fetch-all behavior. - [x] Implement typed filtering, nested boolean groups, deterministic sorting, pagination, projections, dynamic values, and content hydration. - [x] Add Markdown frontmatter, excerpt, JSON-property, and field-catalog extraction. - [x] Add reusable query-control implementations and a separately imported React UI as a foundation for the final OpenAPI-driven contract. - [x] Add Assets query authoring and dynamic field discovery as existing behavior to migrate into the Assets OpenAPI operation. - [x] Add synchronized visual and editable expression authoring. - [x] Unify Assets REST operations under `/rest/assets/*`. - [x] Define authenticated collection, item, content, upload, folder, query, field-catalog, and OpenAPI operations. - [x] Support Builder cookie authentication and public API token authentication. - [x] Add Builder preview, MCP/CLI operations, SSR execution, SSG path generation, and conditional activation. - [x] Add revision-keyed parsed metadata persistence for the hosted Builder. - [x] Add focused query, API, authorization, Builder, CLI, SSR, SSG, migration, and fixture coverage. ## Remaining implementation plan ### 1. Establish the content engine - [x] Rename the generic `@webstudio-is/asset-resource` implementation to `@webstudio-is/content-engine`. - [x] Move existing behavior instead of creating a parallel implementation. - [x] Keep the primary entry runtime-only and add only the compiler entry needed for bundle separation. - [x] Remove the old package after all consumers migrate. - [x] Ensure the engine has no Builder, SDK, asset-uploader, PostgreSQL, R2, or deployment-target dependency. ### 2. Define source snapshots and compilation plans - [x] Introduce `ContentSource.openSnapshot()` and a revision-bearing `ContentSourceSnapshot`. - [x] Include canonical path, stable document ID, content type, immutable content reference, size, and optional `createdAt`. - [x] Implement Webstudio Assets and filesystem snapshot guarantees using their adapter-specific mechanisms. - [x] Introduce `ContentCompilationPlan` for the union of reachable configured resource requirements. - [x] Separate statically selectable candidates from dynamic runtime predicates. - [x] Add mutation-during-compilation tests for replacement, deletion, folder movement, and filesystem changes. ### 3. Separate storage from content processing - [x] Keep upload, replacement, folders, byte storage, revisions, and generic metadata in the Assets repository/uploader. - [x] Move parsing, excerpts, field discovery, query execution, and artifact creation into the content engine. - [x] Remove content-index coordination from asset mutation business logic. - [x] Preserve original source `createdAt` across content replacement and expose it as optional queryable metadata. - [x] Keep hosted parsed-document persistence behind the content compiler's optional cache interface. ### 4. Build deterministic compilation - [x] Move the existing Markdown, frontmatter, JSON, canonicalization, hashing, document-building, and tests into the compiler. - [x] Keep frontmatter behind a dedicated module and continue using the existing Remark/Micromark pipeline. - [x] Parse only candidate files and only the tiers required by the compilation plan. - [x] Deduplicate documents and fields required by multiple resources. - [x] Define a versioned, deterministic `ContentArtifact` with integrity information. - [x] Keep verbose parse and omission diagnostics outside the runtime artifact. - [x] Reject incompatible artifact versions cleanly. ### 5. Enforce the deployment-wide database budget - [x] Replace the old asset-index limit with `CONTENT_DATABASE_MAX_BYTES`, defaulting to 500 KiB. - [x] Have applications read configuration and pass the byte limit into the compiler. - [x] Measure the exact serialized database, including selected bodies and overhead. - [x] Implement deterministic skip-and-continue packing of complete documents. - [x] Return compiler diagnostics with unbounded/bounded bytes, included/omitted counts, omitted identities, largest contributors, and affected resources. - [x] Expose only compact artifact statistics at runtime through `ContentDatabase.getStats()`. - [x] Add exact boundary, deterministic ordering, deduplication, and oversized-document tests. ### 6. Finalize the runtime database - [x] Define `ContentDatabase` over an immutable artifact. - [x] Preserve filtering, nested AND/OR groups, sorting, offset/limit, projection, field references, and content retrieval. - [x] Expose `getFieldCatalog()` and compact `getStats()`. - [x] Keep Markdown/YAML/compiler dependencies out of the runtime entry. - [x] Add execution guards and maximum-size runtime benchmarks. ### 7. Make query authoring OpenAPI-driven The selected standard OpenAPI operation is the complete query-authoring contract. The query builder resolves parameters and request-body JSON Schema, derives its internal editor model, and applies renderer-owned layout policy. It must not embed or fetch a second capabilities/UI language through `x-webstudio-query` or another side channel. - [x] Remove `x-webstudio-query` and all vendor query-definition metadata from the Assets OpenAPI operation. - [x] Resolve local OpenAPI references and derive the editable request value, defaults, validation, labels, choices, arrays, objects, and unions solely from standard operation parameters and request-body JSON Schema. - [x] Represent dynamic Assets field paths with standard JSON Schema vocabulary in the `queryAssets` request schema. - [x] Keep the normalized editor representation internal to query-builder; do not expose another provider-authored capabilities contract. - [x] Remove provider-controlled layout metadata such as `group`; make compact scalar packing and all other layout renderer policy. - [x] Keep Webstudio expression binding as a consumer/editor concern layered over schema values, not part of the OpenAPI contract. - [x] Preserve the existing Assets filter, sort, output selection, full-content/range selection, limit/offset, editable source, and configured-field behavior. - [x] Keep the Assets resource adapter responsible for serializing the edited query into its request body. - [x] Remove the obsolete Assets query-capabilities endpoint, URL, and UI-side capability parsing. - [x] Add a non-Assets OpenAPI proof with differently named parameters and no vendor metadata. - [x] Verify the generic packages contain no Assets imports, fixed Assets property contract, or provider-authored layout model. - [x] Update focused core, React, SDK, protocol/OpenAPI, Builder, and source round-trip tests. ### 8. Manage ContentDatabase lifecycle in Builder - [x] Cache databases by source revision plus normalized compilation-plan hash. - [x] Coalesce concurrent compilation requests. - [x] Reuse cached database instances across field discovery, autocomplete, query preview, and response preview when their normalized compilation plans match. - [x] Replace it when source revision or query requirements change. - [x] Preserve the optional revision-keyed hosted parsed-document cache without making it a source of truth. - [x] Show exact preview warnings when concrete values reveal missing bounded results. ### 9. Materialize and verify immutable builds - [x] Compile and serialize the exact deployment-wide database during prepublish validation. - [x] Attach that validated bounded database to the immutable build without rebuilding it from later asset state. - [x] Show non-blocking prepublish warnings with database bytes, omissions, and potentially affected resources. - [x] Avoid claiming exact future route matches when dynamic values are unknown. - [x] Include the database/runtime only when a reachable configured query requires them. - [x] Ensure detail resources requesting Markdown content include all statically eligible bodies needed by dynamic routes. ### 10. Integrate all targets - [x] SSR: load the build's bounded database and conditionally include the small runtime. - [x] SSG: query the same database during generation, then omit database/runtime output when no runtime query is needed. - [x] Local/CLI: compile from the filesystem source with the same semantics. - [x] Preserve overview pagination, alternative route fields, draft-as-user-data behavior, and full article rendering. - [x] Verify ordinary Assets and fresh query-free sites perform no parser, artifact, content-runtime dependency install, or cleanup work. ### 11. Correct API and package ownership - [x] Move external Assets REST/OpenAPI contracts to `@webstudio-is/protocol`. - [x] Keep Webstudio domain models and Assets system-resource configuration in the SDK. - [x] Keep both cookie and token authentication behavior on the unified Assets REST surface. - [x] Remove pass-through route wrappers/reexports that add no transport behavior. - [x] Keep published runtime queries local to the artifact rather than routing them through Builder REST. ### 12. Remove superseded deployment infrastructure - [x] Remove external deployment-index upload, fetch, invalidation, cleanup, and garbage-collection code. - [x] Remove the SaaS asset-origin adapter requirement; close webstudio-is/webstudio-saas#652 as superseded because it has no independent purpose. - [x] Remove index-bucket compatibility configuration and avoid adding Infisical variables. - [x] Remove obsolete external-index paths, package dependencies, routes, scripts, and tests. - [x] Consolidate unreleased intermediate migrations where safe and retain only schema required by the final hosted cache/API design. ### 13. Verification and release readiness - [x] Move and preserve existing tests while changing ownership; add new tests only for changed contracts and behavior. - [x] Run content-engine compiler/runtime tests, query-builder tests, SDK/protocol/API tests, Builder tests, CLI tests, and affected typechecks. - [x] Run formatting, generated-file idempotence, fixtures, clean Supabase-compatible migrations, E2E shards, and complete agent evaluations. - [x] Verify SSR and SSG conditional inclusion and query-free generated package manifests. - [x] Run the five-article MCP blog workflow: authoring, field discovery, overview, dynamic detail routes, full Markdown rendering, publishing, and published-site verification. - [x] Run a maximum-budget database test and a mutation-during-compilation test. - [x] Perform a final architecture, security, API compatibility, migration, bundle, correctness, and DRY review. - [x] Reconcile every checkbox and replace the verification section with results from the final architecture before release. ## Future MDX work MDX is intentionally separate from this release. - The compiler contract should allow a future build-only MDX parser. - MDX compilation must not enter the published runtime. - Embedded JSX must use an explicit compiled representation rather than runtime source evaluation. - Webstudio components, tokens, styles, and component allowlists remain Webstudio integration concerns. - The future MDX work should reuse `ContentArtifact` and `ContentDatabase` where practical. ## Superseded design The following earlier design choices are no longer the target architecture: - GROQ or GraphQL as the Assets query language. - One external or long-lived index object per resource/query. - A deployment index fetched by the Worker from SaaS/CDN infrastructure. - Lazy production reads of source Markdown bodies. - A separate index bucket, asset origin, invalidation service, or garbage collector. - A 4 MiB published index limit. - Rebuilding an old build's database from the current mutable asset set. - Bundling query infrastructure into projects without a configured content query. ## Verification baseline The embedded runtime-database architecture previously passed the checks below. The OpenAPI-driven query-authoring change additionally passed: - Query-builder core: 4 files / 19 tests. - Query-builder React: 1 file / 7 tests. - SDK Assets source/config: 1 file / 7 tests. - Protocol Assets OpenAPI: 1 file / 9 tests, including independent OpenAPI validation. - Builder Assets OpenAPI description: 1 file / 5 tests. - Query-builder, React, SDK, protocol, and Builder typechecks. - Package-boundary validation and formatting of every affected file. Local verification baseline: - Content engine: 15 files / 104 tests. - Asset uploader: 24 files / 175 tests. - Builder: 204 files / 2,423 tests. - CLI: 54 files / 866 tests. - Complete workspace typecheck, formatting, lint, package boundaries, generated fixtures, and fixture builds. - The complete migration history applied successfully to a fresh Supabase-compatible database, including every migration after the consolidated Assets migration. - Builder production build and full local E2E suite passed. - Complete agent evaluations passed: authenticated page (170,859 ms), design input (207,101 ms), and font assets (67,050 ms). - Final review additionally verified correct REST edit/view/build permits, cookie and public-token read paths, immutable snapshot retries, exact database budgeting, query-free dependency omission, and SSR/SSG conditional runtime inclusion. Final staging verification passed against the embedded runtime-database architecture: MCP uploaded and updated five Markdown articles, discovered dynamic frontmatter fields, previewed a five-item sorted overview and one full-body slug query, updated both Assets resources, found zero binding issues, rendered `/blog` and `/blog/dynamic-routes` at HTTP 200, published build version 266, and verified both published routes at HTTP 200 with the expected article metadata and Markdown body. The workflow also found and fixed offset-form asset timestamps failing canonical datetime validation and made MCP `preview.start({ port: 0 })` correctly select an available local port. ## Release constraints - No new SaaS content service, bucket, or environment variable. - No published-site database dependency. - No parser/compiler dependency in query-free sites or runtime-only bundles. - The validated content database is immutable build output. - Publishing warnings do not block deployment. - The selected standard OpenAPI operation and its request JSON Schema are the only source of query UI semantics. |
||
|
|
7bc9942774 |
perf: Improve MCP evaluation reliability and efficiency (#5959)
## Summary - capture bounded MCP failure codes, validation issue paths, per-tool latency, mutation timing, uncached input, catalog size, and per-call/per-tool response bytes in every evaluation result - require every raw fixture outcome to have zero failed calls and zero retries, even when the workflow later recovers - update baselines only when all raw outcomes and all regression comparisons pass - refuse to replace an accepted aggregate token baseline with a noisier, higher-token sample - regression-gate aggregate response bytes alongside tokens, calls, focused reads, mutations, errors, and retries - compact repeated SDK schemas while preserving required arguments, destructive safety controls, and ordinary optional fields for common goal-guided tools - omit low-frequency optional argument names until focused discovery, reducing the initial tool handshake without removing callable tools - stop echoing the caller's goal from `meta.guide` responses - make evaluations copy their canonical objective verbatim into `meta.guide`, preventing vague paraphrases from selecting a generic workflow - normalize grouped `styles` and `declarations` maps into canonical flat `update-styles` operations before validation - normalize relative `create-page` paths through the platform URL parser - bundle the four bounded authentication discovery reads into one `inspect-auth-context` call - bound large MCP style-key mutation results while preserving a representative sample and exact total count - combine fragment insertion with immediate persisted binding verification to remove a sequential model turn ## Root causes and impact Recovered MCP failures could previously be reported as successful raw outcomes, and baseline files could be written before the complete comparison result was known. Raw outcomes now fail on any MCP error or retry, and accepted baselines are written only after every fixture and comparison passes. Rejected samples exposed two concrete error sources. A vague authentication objective selected a generic workflow and produced four validation failures, 20 calls, and 1.07M tokens; evaluations now pass the canonical objective verbatim. A relative `create-page.path` caused an `INVALID_INPUT` failure and retry; the adapter now canonicalizes it before validation. The deterministic catalog in the accepted baseline measures **50,864 bytes**, down from **53,317 bytes** (−4.60%). Input schemas fell from **31,190 to 28,737 bytes** (−7.86%). The two composite workflows add two conditionally exposed tools and 360 catalog bytes (about +0.71%) when their backing operations are available. Broad experiments that removed focused descriptions or all goal-specific examples made guide responses smaller but increased token use or caused retries. Those variants were rejected. The current implementation compacts only recognized goal guides, while retaining the detailed `update-styles` schema and the `upload-assets` batch example proven necessary by the evaluations. ## Workflow-churn iteration Authenticated discovery uses one model-visible `inspect-auth-context` call. Fragment authoring can now use `insert-fragment-verified`, which commits the insertion and immediately runs persisted binding verification for up to 200 bindings. This removes the following sequential verification turn without changing mutation or verification counts. Current deterministic workflow shape: - authenticated workflow calls: **14 → 10** (−28.57%) - design workflow calls: **17 → 16** (−5.88%) - aggregate workflow calls: **39 → 34** (−12.82%) - failures: **0** - retries: **0** - authenticated MCP response bytes: **52,524 → 46,900** (−10.71%) - authenticated guide response: **26,782 → 24,358 bytes** (−9.05%) One complete run measured authenticated tokens at **348,225** (−11.44%) and first verification at **38.3s** (−30.14%); design first verification moved to **28.1s** (−27.27%). The final exact-code run also passed with **10/16/8** calls and zero failures/retries, measuring authenticated tokens at **377,802** (−3.92%) and design first verification at **34.5s** (−10.67%). The composite preserves post-commit safety: if verification infrastructure fails after insertion, the result remains `committed:true`, returns `POST_COMMIT_VERIFICATION_FAILED`, and explicitly instructs the agent not to repeat the insertion. A guarded baseline-update run was rejected because stochastic aggregate tokens did not beat the accepted result, so no result artifacts were rewritten. ## Style response compaction Large style mutations previously returned every generated style key. In the design fixture, that single successful response was **19,121 bytes** and remained in context for all later turns. MCP responses now retain the first 20 keys plus `styleKeyCount` and `styleKeysTruncated`; the typed runtime operation remains unchanged. Focused evaluation results: - `update-styles` response: **19,121 → 2,815 bytes** (−85.28%) - design-workflow MCP responses: **70,941 → 54,633 bytes** (−22.99%) - calls: **17 → 17** - failures/retries: **0 / 0** - tokens: **498,764 → 505,136** (+1.28%, treated as noise and not accepted as a new baseline) The subsequent complete `pnpm evaluations` run passed all three fixtures with exact **11/17/8** call sequences and zero failures/retries. The accepted lower-token baseline remains unchanged. ## Goal-guide context compaction Recognized goal guides no longer repeat every selected tool's description and examples. Current Codex clients defer MCP tools and load each named tool's exact contract before invocation, so the guide keeps the goal-specific workflow while returning compact tool references. Free-form guide searches remain fully descriptive. Two complex inputs remain intentionally hydrated: `update-styles` keeps its detailed schema, and `upload-assets` keeps one batch example. Removing the upload example caused five failed attempts in a complete run; restoring only that example returned the font workflow to its exact 8-call, zero-error path. Final complete-suite results: - calls: **10 / 16 / 8** (**34 aggregate**) - failures/retries: **0 / 0** - goal-guide payload: **58,082 → 37,718 bytes** (−35.06%) - authenticated MCP responses: **46,900 → 38,268 bytes** (−18.41%) - design MCP responses: **51,854 → 44,008 bytes** (−15.13%) - aggregate MCP responses versus the accepted baseline: **147,335 → 101,922 bytes** (−30.82%) - aggregate tokens: **1,146,951**, only **+0.33%** above the stricter accepted 1,143,217-token baseline The complete suite and every per-fixture comparison passed. The guarded updater did not replace the accepted artifacts because the aggregate token sample did not beat the existing baseline. ## Responsive verification batching The MCP now exposes `screenshot.responsive` when reusable page capture is available. It accepts one generated route plus 1–8 viewports, refreshes the session preview once, reuses one browser target, and returns bounded evidence for every viewport. Auth and design evaluation workflows use one responsive capture instead of a separate preview start and two screenshot turns. Automatic screenshots now allocate an available preview port and reuse an already-running managed preview port. This prevents an unrelated service on the historical 5173 default from producing an MCP failure. Explicit ports, local previews, and external URLs remain unchanged. The evaluator records the bounded viewport array, counts the batch as verification and visual evidence, and compares its latency, response size, calls, errors, retries, and token consumption on every run. The new regression tests were demonstrated fail-then-pass. Guarded accepted results: - aggregate tokens: **1,143,217 → 990,190** (−13.39%) - aggregate calls: **39 → 30** (−23.08%) - aggregate MCP response bytes: **147,335 → 98,470** (−33.17%) - failures/retries: **0 / 0** - authenticated calls: **14 → 8** (−42.86%) - design calls: **17 → 14** (−17.65%) ## Design and font workflow batching Design discovery now uses one conditionally exposed `inspect-design-context` call to return bounded pages, breakpoints, design tokens, assets, and variables instead of five model-visible reads. Font persistence now uses one `verify-font-assets` call to refresh the asset namespace and return every changed font asset instead of a refresh plus separate verification reads. The evaluation tasks and validators require these composite paths. Both tools retain the underlying operation limits, namespace metadata, persisted-result checks, and zero-error/retry gates. Review also confirmed that SDK schemas must keep `additionalProperties:false` and that non-default MCP safety hints must remain explicit; those protocol constraints were preserved rather than traded for catalog-token savings. Guarded accepted improvements versus the previous responsive-batching baseline: - aggregate tokens: **990,190 → 914,760** (−7.62%) - aggregate calls: **30 → 24** (−20.00%) - aggregate focused reads: **8 → 2** (−75.00%) - aggregate MCP response bytes: **98,470 → 95,614** (−2.90%) - design calls: **14 → 10** (−28.57%) - font calls: **8 → 6** (−25.00%) - failures/retries: **0 / 0** The strict SDK catalog is **51,362 bytes** with **28,964 input-schema bytes**. The two new conditional workflow tools add 355 catalog bytes (+0.70%) and 130 schema bytes (+0.45%) while removing six model-visible workflow turns. ## Terminal responsive verification Auth and design now finish with one conditionally exposed `verify-page-responsive` call. It captures every requested viewport in one browser session and immediately runs the static page audit, removing one sequential model turn per workflow while retaining both kinds of evaluator evidence. The tool inherits the audit operation's permit and read namespaces; strict SDK schemas and MCP safety annotations remain unchanged. Latest complete comparison against the accepted baseline: - aggregate tokens: **914,760 → 869,274** (−4.97%) - aggregate calls: **24 → 22** (−8.33%) - aggregate MCP response bytes: **95,614 → 95,053** (−0.59%) - authenticated calls: **8 → 7** - design calls: **10 → 9** - font calls: **6 → 6** - failures/retries: **0 / 0** - authenticated focused run: **289,078 tokens** (−10.06%) and first verification **55,552 ms** (−17.90%) - design focused run: p95 MCP latency **9,642 ms** (−10.32%); token and first-verification variance increased in that individual sample, so only the complete comparison is used for the aggregate conclusion The complete comparison passed all fixture and aggregate regression gates. Two subsequent guarded `--update-baselines` attempts could not start any fixture because the external Codex runner had reached its usage limit; both exited before the first MCP call and wrote no accepted result files. Therefore the tracked accepted baseline below remains **914,760 tokens / 24 calls**, while **869,274 tokens / 22 calls** is the latest successful complete comparison. Regression coverage was demonstrated fail then pass. After this iteration, project-build MCP tests passed **105/105**, high-impact evaluation tests passed **41/41**, and project/CLI typechecks, lint, package boundaries, generated docs, and diff checks all passed. ## Accepted evaluation baseline | Fixture | Failed | Retries | Calls | Mutations | Tokens | Uncached input | Response bytes | First mutation | First verification | | --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | | authenticated-page-v1 | 0 | 0 | 8 | 4 | 321,396 | 44,353 | 37,536 | 39,076 ms | 67,660 ms | | design-input-v1 | 0 | 0 | 10 | 6 | 330,580 | 54,441 | 40,036 | 30,419 ms | 36,551 ms | | font-assets-v1 | 0 | 0 | 6 | 3 | 262,784 | 20,704 | 18,042 | 37,609 ms | 47,073 ms | Accepted aggregate: **914,760 tokens**, **24 calls**, **2 focused reads**, and **95,614 MCP response bytes**, with zero failures and zero retries. Compared with the previous accepted baseline, tokens fell **7.62%**, calls fell **20.00%**, focused reads fell **75.00%**, and response bytes fell **2.90%**. ## Verification - [x] Complete `pnpm evaluations -- --update-baselines` - [x] Independent complete `pnpm evaluations` after the composite workflow change - [x] Worse-token and error-containing samples rejected without replacing accepted baselines - [x] Added/changed regression tests demonstrated fail then pass - [x] Project-build MCP tests: 105 passed - [x] Complete high-impact evaluation tests: 41 passed - [x] Project-build and CLI typechecks - [x] `pnpm lint` - [x] `pnpm check:package-boundaries` - [x] `pnpm check:generated-docs` - [x] `git diff --check` - [x] Earlier workspace tests, including 2,356 builder tests - [x] Earlier generated API checks - [ ] Fixture sync/build: sync could not reach `main.development.webstudio.is` and timed out; no local test, evaluation, or code check failed ## Implementation checklist - [x] Error and retry rate enforced at zero for raw and compared outcomes - [x] Relative page paths normalized to prevent a known validation failure and retry - [x] Baseline replacement blocked unless every outcome and comparison passes - [x] Aggregate token baselines cannot ratchet upward - [x] Workflow churn bounded and regression-gated - [x] Authentication discovery collapsed from four model-visible reads to one - [x] Fragment insertion and persisted binding verification combined safely - [x] Large style-key mutation results bounded at the MCP boundary - [x] Token consumption captured, compared, and regression-gated - [x] Response bytes captured per call and tool, summarized, and aggregate regression-gated - [x] Per-tool latency, mutation timing, catalog size, and validation paths captured - [x] Repeated catalog/schema and focused-guide context reduced - [x] Canonical goal selection stabilized for evaluations - [x] Grouped style maps normalized before validation - [x] Responsive verification batches desktop and mobile evidence in one call - [x] Automatic screenshot previews avoid occupied default ports - [x] Responsive viewport evidence is captured and regression-gated - [x] Accepted evaluation artifacts preserve the best measured token baseline |
||
|
|
e80ca3b54c |
fix: Improve MCP authoring and screenshot reliability (#5957)
Closes #5954 Closes #5951 Closes #5950 Closes #5953 ## Summary - route external screenshot `url` and `baseUrl` targets through the self-closing browser path - keep reusable Chromium sessions limited to Webstudio-managed session previews - validate typed style values at the public runtime boundary while retaining CSS strings for design tokens - build MCP and shell validation messages from compact structured issues - advertise typed style objects with a concrete keyword example - persist `update-asset` metadata patches to the related file record and verify the saved value - store multi-sentence page titles and metadata as fixed text without misclassifying sentence punctuation as member access - capture privacy-safe aggregate token usage and MCP workflow metrics in every high-impact evaluation result - compare each evaluation with a compatible checked-in baseline and fail on correctness, token, tool-use, error/retry, broad-read, or MCP-latency regressions ## Root causes ### External screenshot lifecycle The fast iterative preview change made `session` the default preview source. External captures were then treated as managed session-preview captures and opened a reusable Chromium session. One-shot MCP processes do not call `preview.stop`, so the browser kept the process alive and could be orphaned when the caller killed the hung CLI. ### Validation errors and schemas `update-styles` declared `value` as unconstrained input, and design-token objects were checked only for a string `type`. Invalid values therefore passed the advertised/input schema and failed later in the full `StyleValue` parser, exposing the raw Zod union message. Error serialization already carried flattened issues but did not use them for `error.message`. ### Asset metadata persistence `update-asset` correctly produced an `assets/[id]/meta` patch, but asset persistence compared only Asset-table fields. Metadata lives on the related File row, so the patch was treated as unchanged and the successful mutation never wrote the new value. ### Page text expression disambiguation Page text normalization treated a period followed by whitespace and a word as JavaScript member access. Normal prose such as `Marques. Toutes nos marques` was therefore validated as an expression and rejected instead of being stored as a string literal. ### Evaluation observability The evaluation result only stored duration and two call counts, so token cost, failures, retries, mutation flow, verification coverage, and MCP latency could regress without a durable comparison. Results now use a bounded schema-v2 aggregate and never persist prompts, transcripts, stdout/stderr, credentials, arguments, or response payloads. ## Impact - external screenshots complete without retaining browser processes - repeated managed-preview screenshots retain browser reuse - invalid style inputs fail at the public boundary with paths such as `updates.0.value` - `error.message` is concise and actionable instead of a repeated raw union dump - generated schemas no longer advertise primitive or array values for `update-styles` - supported design-token CSS strings remain accepted - `update-asset` font metadata remains changed after commit, refresh, and reload - `create-page` and `update-page` accept ordinary multi-sentence titles and SEO descriptions while preserving computed expressions - every high-impact run reports input, cached-input, cache-write, output, reasoning-output, total-token, and cache-rate aggregates - MCP results report calls, success/failure, retries, focused/broad reads, dry runs, planned/committed mutations, verifications, total/p50/p95 latency, and first-mutation/verification timing - compatible results are compared with accepted baselines using a 15% relative regression threshold; correctness failures and zero-baseline errors, retries, or broad reads remain zero-tolerance - stochastic wall-clock and milestone timings remain visible as deltas without making a single noisy run fail ## Todo - [x] Reproduce external URL browser-session routing - [x] Use self-closing capture for external screenshots - [x] Preserve browser reuse for managed session previews - [x] Reproduce primitive style-value schema acceptance - [x] Validate typed style values at the public boundary - [x] Preserve CSS-string design-token inputs - [x] Format stdio and shell validation messages from structured issues - [x] Regenerate and verify runtime operation contracts - [x] Reproduce dropped asset metadata at the persistence boundary - [x] Persist and verify related File metadata updates - [x] Reproduce multi-sentence page text failures on create and update - [x] Distinguish sentence punctuation from computed member access - [x] Add privacy-safe token and MCP workflow metrics - [x] Add per-fixture baseline comparisons and regression gates - [x] Refresh accepted schema-v2 baselines for all fixtures - [x] Review the complete diff - [x] Run repository checks and the complete agent evaluation suite ## Verification - `pnpm checks` — passed, including workspace tests, typechecks, lint, package-boundary checks, generated API/docs checks, fixture sync, and fixture builds - builder tests — 189 files, 2,356 tests passed - CLI tests — 53 files, 852 tests passed - project-build tests — 81 files, 2,023 tests passed - asset-uploader tests — 11 files, 98 tests passed - targeted evaluation metrics/regression/trace/runner tests — 5 files, 17 tests passed - all four issue regression tests and the new evaluation harness tests were demonstrated failing without their implementations and passing with them - `pnpm evaluations -- --update-baselines` — 3/3 fixtures passed and schema-v2 baselines were updated - a subsequent real `font-assets-v1` result compared successfully after the regression policy was finalized |
||
|
|
c0687e3323 |
fix: Accept CSS strings in animation keyframes (#5956)
## Summary Allow MCP `update-props` callers to configure `animationAction` keyframes with normal CSS strings, including values such as `transform: "translateX(-75%)"`. Use one SDK-owned animation authoring schema in both the Builder UI and MCP so CSS parsing, timing defaults, and validation cannot drift between entry points. ## Root cause The Builder UI and MCP did not share an authoring contract. Builder controls produced Webstudio's structured style values and animation factories supplied timing objects, while MCP passed its input directly toward the persisted prop schema. As a result, normal CSS strings failed deep Zod validation and omitted timing objects were rejected. ## Implementation - Add a shared `createAnimationActionInput` schema factory to the SDK. - Inject the CSS parser into the schema factory to avoid adding an `sdk` → `css-data` dependency cycle. - Use the shared schema in both Builder animation validation and MCP `update-props`. - Accept raw CSS strings or existing structured Webstudio values in `keyframes[].styles`. - Parse string values before persistence and default omitted animation `timing` to an empty options object. - Update Animation Group guidance and regenerate the runtime operation contract. - Preserve strict validation for existing structured animation style values. ## Checklist - [x] Add regression coverage for the reported horizontal scroll payload. - [x] Verify the regression fails before implementation and passes after it. - [x] Add SDK coverage for shared animation authoring normalization. - [x] Use the shared authoring schema in Builder and MCP. - [x] Verify package boundaries and generated runtime contracts. - [x] Run affected typechecks, targeted tests, lint, and formatting. - [x] Run the complete agent evaluation suite. - [ ] Resolve evaluation read-budget failures: `authenticated-page-v1` and `design-input-v1` failed only `boundedReads`. ## Validation Passed: - `pnpm --filter @webstudio-is/sdk test -- src/schema/animation-schema.test.ts` - `pnpm --filter @webstudio-is/project-build test -- src/runtime/props.test.ts src/mcp.test.ts` - `pnpm --filter @webstudio-is/sdk typecheck` - `pnpm --filter @webstudio-is/project-build typecheck` - `pnpm --filter @webstudio-is/builder typecheck` - `pnpm check:package-boundaries` - `pnpm exec oxlint --deny-warnings <changed source and test files>` - `pnpm exec oxfmt --check <changed source and test files>` - `pnpm check:generated-api` - `font-assets-v1` agent evaluation Agent evaluation findings: - `authenticated-page-v1`: failed only `boundedReads`; all functional, audit, binding, privacy, and visual checks passed. - `design-input-v1`: failed only `boundedReads`; all functional, audit, responsive, design-system, privacy, and visual checks passed. - `font-assets-v1`: passed all checks. |
||
|
|
77cb5403a3 |
fix: Allow publishing projects with custom elements (#5955)
## Summary Prevent the pre-publish HTML content-model audit from crashing when a project contains a tag that is not present in the generated HTML metadata. Unknown tags on generic Element instances now produce a non-blocking publish warning. Legacy component instances remain permitted for backward compatibility. Known HTML elements continue to use their existing category and child constraints. ## Root cause The content-model validator indexed `elementsByTag` and immediately read `categories` or `children`. A project tag absent from that dataset returned `undefined`, causing the publishing audit to throw before publishing could continue. ## Impact Projects containing unsupported tags can complete the pre-publish audit instead of failing with an uncaught `categories` error. Invalid generic element tags are still reported, and legacy components are not rejected solely because their rendered tag is absent from current HTML metadata. ## Todo - [x] Safely resolve HTML content-model metadata - [x] Preserve validation for known HTML elements - [x] Warn for unknown generic Element tags - [x] Preserve legacy component compatibility - [x] Add pre-publish audit regressions - [x] Run project-build and builder formatting, lint, typecheck, and tests ## Verification - `pnpm exec oxfmt --check packages/project-build/src/runtime/content-model.ts packages/project-build/src/runtime/pre-publish-audit.test.tsx` - `pnpm exec oxlint --deny-warnings packages/project-build/src/runtime/content-model.ts packages/project-build/src/runtime/pre-publish-audit.test.tsx` - `pnpm --filter @webstudio-is/project-build typecheck` - `pnpm --filter @webstudio-is/builder typecheck` - `pnpm --filter @webstudio-is/project-build test` — 81 files, 2,021 tests passed - `pnpm --filter @webstudio-is/builder test` — 189 files, 2,356 tests passed |
||
|
|
0b192c7802 |
fix: Sort style sources with temporary local source (#5949)
## Summary - Allow style sources to be reordered when the displayed local source has not been persisted yet. - Submit only attached style source IDs to the runtime reorder operation. - Add regression coverage for reordering tokens alongside a temporary local source. ## Root cause The style panel displays a temporary local style source until local styles are persisted. Sorting included that temporary ID in the runtime mutation, but the runtime accepts only attached style source IDs and rejected the entire reorder. ## Todo - [x] Filter temporary style source IDs from reorder mutations. - [x] Add regression coverage. - [x] Run targeted tests, lint, formatting, and Builder typecheck. ## Verification - `pnpm --filter @webstudio-is/builder test -- app/builder/features/style-panel/style-source-section.test.ts` — 12 tests passed - `pnpm exec oxlint --deny-warnings apps/builder/app/builder/features/style-panel/style-source-section.tsx apps/builder/app/builder/features/style-panel/style-source-section.test.ts` - `pnpm exec oxfmt --check apps/builder/app/builder/features/style-panel/style-source-section.tsx apps/builder/app/builder/features/style-panel/style-source-section.test.ts` - `pnpm --filter @webstudio-is/builder typecheck`0.282.1 |
||
|
|
5141f61f75 |
fix: prevent mixed router dependencies in MCP previews (#5948)
## Summary
- generate MCP previews from the standalone React Router template
- prevent Remix and React Router runtimes from being merged into one
dependency graph
- keep the normal Remix build path unchanged
## Root cause
The preview generator combined the complete React Router template with
the Remix defaults template. That installed React Router 7 alongside
Remix-provided React Router DOM 6, causing Vite to fail on incompatible
exports before the iterative preview server became ready.
## User impact
`preview.start({ source: "session", mode: "iterative" })` can now start
successfully, so agents can reuse the preview for fast edit, reload,
screenshot, and vision cycles.
## Verification
- [x] Generated a preview from production-size project data and received
HTTP 200
- [x] Verified the generated package contains React Router and no Remix
router dependencies
- [x] 55 targeted CLI preview, screenshot, and MCP preview tests
- [x] CLI typecheck and formatting
- [x] `pnpm checks`
- [x] `pnpm evaluations` (all three real agent fixtures passed)
|
||
|
|
b2a34f1713 |
feat: Fast MCP iterative previews (#5947)
## Summary
This PR documents a measured architecture plan for making the MCP
edit-to-screenshot loop fast enough and reliable enough for iterative
site authoring. It intentionally changes no runtime behavior yet.
The current implementation rebuilds a production preview after small
committed mutations. Testing an editable local clone of the production
Webstudio homepage also exposed a correctness gap: a path screenshot
called directly after a mutation can return a stale, byte-identical
image.
## Measured baseline
Repository fixture:
- committed text edit: **24-25 ms**
- post-edit regeneration, production build, and server restart: **7.9
s**
- first screenshot after restart and browser relaunch: **9.1 s**
- combined first post-edit screenshot: **17.1 s**
- unchanged warm screenshot: **1.1 s**
Production homepage, read-only:
- remote refresh: **3.1 s**
- complete production preview preparation/start: **16.0 s**
- cold homepage screenshot: **10.2 s**
- unchanged warm screenshot: **1.36 s**
- predicted post-edit screenshot from measured phases: **approximately
26.2 s**
Editable local production-homepage clone:
- retained **43 routes** and **266 homepage text nodes**
- committed heading mutation: **0.81-0.87 s**
- explicit post-edit preview generation/build/start: **11.6-12.6 s**
- first screenshot after explicit preview start: **9.8-11.8 s**
- complete mutation-to-visible-screenshot cycle: **22.9-25.2 s**
- complete edit, verify, screenshot, restore, and stop run: **52.7 s**
The changed screenshot visibly rendered the test heading, and the
restored screenshot matched the original byte for byte.
## Correctness finding
Calling a path screenshot directly after the committed mutation took
**20.1 s**, but both post-edit captures were byte-identical to the
baseline and rendered the old heading. Explicitly calling
`preview.start({ source: "session" })` made the edit visible.
The reported generated-build version also remained at 1 while the
project session advanced through versions 4 and 5. Current screenshot
output therefore cannot prove that it rendered the mutation it is meant
to verify.
## Proposed direction
- [ ] Introduce explicit iterative and production preview modes under
one controller contract.
- [ ] Keep a Vite development preview and browser alive for MCP
authoring screenshots.
- [ ] Preserve production preview for rendered audits and final
verification.
- [ ] Regenerate from the authoritative project session, wait for Vite
compilation, then normally reload the retained browser page.
- [ ] Make a direct post-mutation path screenshot refresh the latest
committed session without using HMR.
- [ ] Add a project-version freshness handshake so stale screenshots
fail.
- [ ] Serialize and coalesce regeneration after rapid mutations.
- [ ] Return preview mode, rendered project version, and complete phase
timings.
- [ ] Add lifecycle, integration, and local agent evaluation coverage.
## Performance target
Warm edit-to-screenshot latency should be at most **3 seconds p95**
across ten sequential small edits, without invoking `npm run build`,
`npm run start`, or launching another browser.
## Verification
- [x] Measured the source CLI against the authenticated repository
fixture.
- [x] Measured the production homepage without changing production.
- [x] Synchronized the production bundle into a disposable local Builder
project.
- [x] Committed and visually verified a real heading edit through local
MCP.
- [x] Restored the original heading and verified the restored screenshot
byte for byte.
- [x] Reproduced the stale direct-screenshot behavior.
- [x] Formatted the plan with `oxfmt`.
- [x] Verified the documentation diff with `git diff --check`.
The complete architecture, race handling, test matrix, acceptance
criteria, and non-goals are in
`apps/builder/docs/mcp-iterative-preview-plan.md`.
0.282.0
|
||
|
|
9a087c573a |
fix: use local URLs for expression assets in exports (#5945)
Fixes #5763 ## Description Assets selected directly in a project already use the generated app's configured asset base. Assets referenced through `assets.data[...]`, however, were still emitted with builder-only `/cgi/` URLs, so those references broke in Docker and other self-hosted exports. This makes generated asset resources use the same local asset base as direct asset props while keeping their runtime metadata. The live builder continues to use its existing `/cgi/` routes. ## Steps for reproduction 1. Upload an audio file and reference `assets.data["<asset-id>"].url` from the expression editor. 2. Generate a self-hosted project. 3. Inspect `app/__generated__/$resources.assets.ts`. 4. The asset URL is now `/assets/<filename>` instead of the unavailable `/cgi/asset/<filename>?format=raw` route. ## Testing - `pnpm --filter webstudio test -- src/prebuild.test.ts -t "uses the local asset base"` - `pnpm --filter webstudio exec vite build` - `pnpm exec oxfmt --check packages/cli/src/prebuild.ts packages/cli/src/prebuild.test.ts` - `pnpm exec oxlint --deny-warnings packages/cli/src/prebuild.ts packages/cli/src/prebuild.test.ts` ## Code Review @kof, could you please: - [ ] Review the generated asset URL behavior - [ ] Review the implementation and regression test - [ ] Verify an expression-based asset in a self-hosted preview ## Before requesting a review - [x] Made a self-review - [x] Added a comment explaining why generated exports override the runtime URL - [x] Added a regression test --------- Co-authored-by: Sviat Barbutsa <9897782+sviat-barbutsa@users.noreply.github.com> Co-authored-by: Oleg Isonen <oleg008@gmail.com> |
||
|
|
c3c0e32204 |
fix: make MCP font assets editable and deterministic (#5944)
Closes #5943 Closes #5942 ## User impact MCP-managed font assets now keep their identity, metadata, and generated CSS behavior predictable across upload, editing, synchronization, and rendering. ## Changes - Preserve explicit font metadata overrides while validating supported fields and rejecting unsupported metadata instead of silently dropping it. - Expose font metadata through `update-asset`, with partial updates merged into the existing metadata and validated before the mutation is committed. - Prefer the typographic family name when reading font files, so Fontsource and Google font files resolve to the same logical family where the file provides that information. - Deduplicate generated font sources by URL and format, choose a deterministic source when legacy assets collide, and derive the CSS format hint from the filename when historical metadata is stale. - Add MCP and CLI examples explaining font metadata upload and correction. - Add regression coverage for metadata persistence, invalid overrides, family-name extraction, duplicate source handling, stale format metadata, and generated runtime contracts. ## Verification - `pnpm checks` - 46 workspace packages tested, including 2,355 Builder tests, 809 CLI tests, 2,019 project-build tests, and 97 asset-uploader tests. - All workspace typechecks, Oxlint, package-boundary checks, generated API/docs checks, and fixture link/sync/build checks passed. |
||
|
|
a803aa352d |
fix: expand CSS shorthands in MCP style updates (#5941)
Closes #5940 ## What changed - Route shorthand properties from `update-styles`, `update-design-token-styles`, and shared style mutation helpers through the existing CSS parser. - Store expanded longhand declarations so generated CSS and Builder editing use the same data model as JSX fragment insertion. - Preserve breakpoint, pseudo-state, and listed metadata across generated declarations. ## User impact MCP-authored shorthands such as `inset` and `grid-area` no longer disappear from generated CSS or remain as declarations the Builder cannot edit. The three style authoring paths now produce consistent, editable project data. ## Verification - `pnpm --filter @webstudio-is/project-build test` (2,015 tests) - `pnpm --filter @webstudio-is/project-build typecheck` - `pnpm oxfmt --check packages/project-build/src/runtime/styles.ts packages/project-build/src/runtime/styles.test.ts` - `pnpm oxlint --deny-warnings packages/project-build/src/runtime/styles.ts packages/project-build/src/runtime/styles.test.ts` - `git diff --check` |
||
|
|
7eb58664b0 |
fix: harden asset folder uploads and selection (#5939)
## Summary Fixes folder uploads and asset-manager selection behavior. ## Changes - Preserve folder IDs for newly uploaded assets. - Place duplicate assets into the dropped folder, including server-side deduplication and assets already uploading. - Handle browser `NotFoundError` cases while reading dropped directories. - Keep lasso selection anchored correctly while scrolling. - Add `Cmd/Ctrl+A` to select all currently rendered assets and folders. - Document the new shortcut in the keyboard shortcuts dialog. - TIFF support was removed in the base branch. ## Verification - [x] Asset upload and directory-drop tests - [x] Asset-manager tests - [x] Keyboard shortcuts dialog tests - [x] Builder typecheck - [x] Formatting and diff checks |
||
|
|
085f705cc4 |
fix: remove unsupported TIFF assets (#5938)
## Summary - Remove `.tif` and `.tiff` from supported asset extensions. - Stop categorizing TIFF files as images in the asset manager. - Update SDK URL coverage to reflect the supported direct-served image formats. ## Why The asset manager classified TIFF files as images, but the browser and image optimization pipeline cannot reliably render TIFF thumbnails. Treating TIFF as supported created broken previews. ## Verification - SDK asset tests: 95 passed - Formatting completed - Diff checked against `main` |
||
|
|
54aa7be145 |
fix: Make MCP authoring reliable across assets, styles, and embeds (#5932)
Closes #5924 Closes #5925 Closes #5926 Closes #5927 Closes #5928 Closes #5929 ## Outcome Makes MCP and CLI authoring predictable across project-wide CSS variables, font uploads, retried asset uploads, destructive asset selection, design-token collisions, and SVG HtmlEmbed edits. ## Delivered ### Project-global CSS variables - [x] `define-css-variable` writes to `ROOT_INSTANCE_ID` / `:root` instead of the home-page Body. - [x] Breakpoint and overwrite behavior is preserved, and compact results identify the root scope. - [x] Existing body-local declarations remain untouched. - [x] Runtime and Builder integration tests cover root selection and generated project behavior. ### Font metadata and upload overrides - [x] Static fonts prefer authoritative `OS/2.usWeightClass`. - [x] Fallback matching normalizes spaces, hyphens, and underscores and checks specific aliases before shorter ones. - [x] Explicit format and partial metadata overrides travel through HTTP, filesystem, and S3 upload paths and are validated after merging with detected metadata. - [x] Regression tests cover ExtraBold, Extra-Bold, Semi Bold Italic, Ultra Light, valid weight classes, invalid weight classes, partial overrides, and invalid overrides. ### Idempotent asset uploads - [x] API uploads compute a project-scoped SHA-256 content hash. - [x] Sequential and concurrent duplicate uploads reuse the existing asset and return `deduplicated: true`. - [x] `force: true` bypasses deduplication for intentional duplicates. - [x] A partial unique index enforces one non-null content hash per uploader project. - [x] Stale reservations are cleaned up and active concurrent uploads are bounded by polling and an actionable retry error. - [x] HTTP, protocol, uploader, and CLI tests cover hash reuse, uniqueness races, force propagation, and result markers. The migration does not backfill historical files. Existing assets begin participating in deduplication when uploaded through the new path; matching content keeps the existing asset's metadata rather than silently rewriting it. ### Consistent asset inputs and permissions output - [x] `delete-asset` exposes exact `assetIds` and explicit `assetIdPrefixes`. - [x] The legacy `assetIdsOrPrefixes` input remains accepted and is marked deprecated. - [x] Exact ids no longer accidentally select longer prefixed ids. - [x] `webstudio permissions` prints a readable role/capability summary by default while `--json` remains unchanged for machine callers. - [x] Help and discovery describe JSON output as optional. - [x] Runtime, CLI, metadata, and generated-contract tests cover canonical and compatibility behavior. ### Deterministic fragment design tokens - [x] Fragment insertion reconciles incoming tokens against project tokens and earlier tokens in the same fragment. - [x] Equal name/style tokens are reused instead of creating suffixed twins. - [x] Same-name/different-style fragments require an explicit `ours`, `theirs`, or `merge` policy at the public runtime boundary. - [x] Builder's established internal paste behavior retains its explicit incoming-value default. - [x] `create-design-token` accepts documented CSS strings through the property-aware CSS parser as well as typed style values. - [x] Tests cover same-fragment reuse/conflicts, persisted tokens, explicit policies, and CSS string parsing. ### Editable SVG HtmlEmbed content - [x] HtmlEmbed validation uses parse5 parser errors and source structure instead of serialization-string equality. - [x] Valid inline SVG is accepted without silently normalizing authored markup. - [x] Fragment insertion now uses the same validator as prop update and text replacement paths. - [x] Malformed markup is rejected before mutation. - [x] Regression tests cover realistic SVG, parser failures, and no-partial-mutation behavior. ## Verification - [x] `pnpm checks`: all workspace tests, typechecks, lint, package boundaries, generated API/docs checks, and fixtures passed on the final committed tree. - [x] `pnpm --filter webstudio test:release-smoke`: packaged install, compact comparison, preview, agent workflow, stdio MCP, and structured commands passed. - [x] Prisma schema validation passed with test connection variables. - [x] Two minimally prompted weak-model subagents independently exercised the changed CLI/MCP discovery and focused workflows. - [x] The subagent-found stale `permissions --help` requirement was fixed, regression-tested, and retested. - [x] Final diff and worktree are clean. |
||
|
|
918e569fd4 |
fix: Show publish warnings immediately (#5935)
## Summary Show client-side pre-publish audit findings as soon as the user starts publishing, and apply the Builder's standard text styling to warning banners. ## Root cause The cloud publish audit ran inside an async form action, while the static export audit ran inside an async transition. React deferred their ordinary state updates until those async operations completed, so warnings could appear only after publishing or export finished even though validation itself ran synchronously on the client. ## Changes - Run the cloud publish audit in the synchronous button click handler before starting the async publish transition. - Run the static export audit before starting its async transition. - Keep warnings non-blocking while preserving blocking audit errors. - Render warning-banner content with the design-system `Text` component. ## Checklist - [x] Show cloud publish warnings before publishing starts - [x] Show static export warnings before export starts - [x] Style warning text consistently - [x] Run Builder tests - [x] Run Builder typecheck - [x] Run lint and formatting checks ## Verification - `pnpm --filter @webstudio-is/builder test` — 2,351 tests passed - `pnpm --filter @webstudio-is/builder typecheck` - `pnpm exec oxlint --deny-warnings apps/builder/app/builder/features/publish/publish.tsx` - `pnpm exec oxfmt apps/builder/app/builder/features/publish/publish.tsx` |
||
|
|
f08cc01c9f |
fix: Preserve tokens when pasting Slot content (#5934)
## Summary Preserve design-token selections on instances nested inside pasted Slot content. ## Root cause Token style sources receive new or reused IDs during fragment insertion. Regular copied instances applied that token ID mapping to their style-source selections, but preserved Slot/portal content copied selections with the stale clipboard IDs. As a result, an Accordion's shared HtmlEmbed icon could lose its visible token after pasting the whole Accordion even though pasting the icon alone worked. ## Changes - Pass the token style-source ID map into Slot/portal style insertion. - Remap token IDs while preserving local style-source IDs. - Add unit coverage for portal selection remapping. - Add a fragment-level regression test using a tokenized HtmlEmbed inside a Slot. ## Checklist - [x] Remap token selections in pasted Slot content - [x] Add regression coverage - [x] Run project-build tests - [x] Run project-build typecheck - [x] Run lint and formatting checks ## Verification - `pnpm --filter @webstudio-is/project-build test` — 1,993 tests passed - `pnpm --filter @webstudio-is/project-build typecheck` - `pnpm exec oxlint --deny-warnings packages/project-build/src/runtime/style-copy.ts packages/project-build/src/runtime/fragment.ts packages/project-build/src/runtime/style-copy.test.ts packages/project-build/src/runtime/fragment.test.tsx` - `pnpm exec oxfmt packages/project-build/src/runtime/style-copy.ts packages/project-build/src/runtime/fragment.ts packages/project-build/src/runtime/style-copy.test.ts packages/project-build/src/runtime/fragment.test.tsx` |
||
|
|
4ea8928880 |
fix: preserve legacy content through validation (#5933)
## Summary - Keep the shared content-model validator strict during normal Builder authoring. - Report HTML and component nesting violations as publish warnings instead of blocking legacy projects. - Allow paste operations to retain violations already contained inside legacy fragments and surface them as warnings. - Continue rejecting new violations introduced at the paste destination boundary. - Remove obsolete empty content models from CodeText and Video so their runtime-supported, HTML-valid children pass validation. ## Root cause The new pre-publish audit applied current authoring constraints to historical project trees. Some legacy structures, including old Accordion triggers containing an h3 inside a button, were created by earlier Webstudio templates and cannot satisfy the current HTML model without migration. Blocking publish or paste would make untouched legacy content unusable. CodeText and Video also had metadata that rejected children their renderers intentionally support. Those verified metadata mismatches are corrected independently of the compatibility policy. ## Behavior - New invalid nesting remains prevented by normal authoring operations. - Existing invalid nesting produces a Publish warning and does not abort publishing. - Webstudio instance, HTML, JSX, and Webflow paste retain fragment-internal violations and show a paste warning. - Paste still validates the destination and cannot introduce a new invalid parent-child relationship. - Resource integrity and missing audit inputs still prevent publishing. ## Verification - [x] Legacy button containing h3 reports a publish warning - [x] Legacy invalid subtree pastes successfully with a warning - [x] New paste destination violations remain rejected or use the closest valid target - [x] Valid legacy CodeText children pass validation - [x] Valid Video source and track children pass validation - [x] Project-build matcher and insert-target tests - [x] Builder instance, HTML, JSX, and Webflow paste tests - [x] Project-build and Builder typechecks - [x] Focused oxlint and formatting checks |
||
|
|
620f8b54ed |
feat: Create blank text assets (#5931)
## Summary - add a **Create text file** action to the Assets toolbar and shared context/dropdown menu - validate filenames against the central editable-asset registry, create the empty file in the current asset folder, and open it in the text editor - keep simultaneous empty uploads distinct by including the filename in the upload fingerprint - keep internal Nano ID storage suffixes out of visible asset names and subsequent content revisions - show the immutable file extension beside the editable basename in Asset settings Asset querying, content hydration, structured data, bindings, generated runtime support, and MCP integration remain owned by #5921. ## Verification - Builder asset/text tests: 34 passed - SDK asset tests: 110 passed - project-build asset tests: 71 passed - asset-uploader revision tests: 5 passed - SDK, project-build, asset-uploader, and Builder typechecks - lint and package-boundary checks Ref #5824 |
||
|
|
5016426bfb |
fix: Preserve resource URL expression formatting (#5916)
## What changed - preserve the user’s original whitespace and newlines in resource URL binding expressions ## Change of plan Automatic expression formatting is not needed. Prop binding expressions already preserve user-entered formatting; only resource URL bindings were losing their newlines. This PR aligns resource URL bindings with the existing prop binding behavior and does not add a formatter or change expression formatting rules. ## Root cause The resource URL expression was stored in an input hidden with the HTML `hidden` attribute. Because its input type still defaulted to `text`, the browser value-sanitization algorithm removed newline characters before the form was serialized. The URL form field now uses `type="hidden"`, which preserves the original expression during form submission. ## Validation - `pnpm --filter @webstudio-is/builder typecheck` - `pnpm lint` - `git diff --check` Closes #5858 |
||
|
|
cfba520e6d |
feat: Open text assets in code editor (#5918)
## What changed - open every textual asset type from the upload registry in an editable CodeMirror dialog - select installed CodeMirror language support by MIME type and use plain text editing as the fallback - support `txt`, `csv`, `md`, `js`, `css`, `json`, `html`, `xml`, and `svg` without adding asset-specific language branches to the shared editor - keep the canvas mounted and interactive behind the dialog - persist edits on blur, `Cmd/Ctrl+S`, or `Cmd/Ctrl+Enter` through the asset replacement pipeline - preserve folder and description metadata and repoint supported asset references - clean up failed replacement uploads instead of leaving orphan assets ## Impact Users can open, edit, and persist all text-based upload formats directly in the builder without replacing or reloading the canvas. New `text/*` upload types will automatically become editable as plain text; installed syntax support is selected by MIME type. ## Validation - `pnpm --filter @webstudio-is/builder test -- app/builder/features/text-file-editor/text-file-utils.test.ts app/builder/shared/assets/replace-asset.test.ts app/builder/shared/asset-manager/asset-manager.test.tsx` - `pnpm --filter @webstudio-is/builder typecheck` - `pnpm exec oxlint --deny-warnings <changed files>` - `pnpm exec oxfmt --check <changed files>` - `git diff --check` - verified the running dev server applied the changes through Vite HMR Ref #5824 |
||
|
|
9ce325b94c |
feat: Deep-link Builder instances (#5923)
## Summary - add optional `instanceId` support to the shared Builder link parameters used by `builderPath` and `builderUrl` - synchronize the selected instance into the Builder URL without adding a browser-history entry for every selection - restore the selected page and full instance selector when opening an instance deep link - render a **Show element** link for pre-publish audit findings that identify an instance - switch to the affected page, select and scroll to the instance, and close the publish popover when the link is used ## Why The pre-publish audit introduced in #5922 identifies the invalid page and instance, but its error was text-only. Users still had to locate the offending element manually. A shared instance deep-link parameter also makes these links copyable and reusable outside the audit UI. ## Impact Builder URLs can now include `instanceId` alongside `pageId`. Existing page-opening links continue using the same central `builderPath`/`builderUrl` abstraction. Missing or stale instance IDs safely fall back to the requested page. ## Validation - focused Builder tests passed (4 tests) - `@webstudio-is/builder` typecheck passed - focused Oxlint passed - focused Oxfmt check passed - `git diff --check` passed |
||
|
|
be906afb5b |
fix: validate projects before publishing (#5922)
## Summary - add a reusable pre-publish audit pipeline with normalized findings and extensible checks - validate HTML content-model nesting and existing resource integrity before regular and static publishing - identify the affected page and instance in invalid-markup errors - move generated HTML formatting from automatic `postbuild` to the explicit local `build:debug` command ## Root cause A project contained an invalid stored component hierarchy, with an `h2` nested inside a paragraph. The Builder did not run a holistic content-model validation before publishing, so the invalid hierarchy reached static generation. The static fixture then ran `oxfmt` automatically during `postbuild`; its parse failure made the otherwise completed static build fail. ## Impact Users now see a specific Builder error before publishing, including the affected page and invalid nesting. Static publish CI no longer formats generated HTML automatically, while developers can still produce formatted output locally with `pnpm build:debug`. ## Validation - 65 focused project-build tests passed - `@webstudio-is/project-build` typecheck passed - `@webstudio-is/builder` typecheck passed - focused Oxlint passed - focused Oxfmt check passed - `git diff --check` passed |
||
|
|
0070fa66a1 |
ci: deduplicate builder E2E setup (#5917)
## What changed - reuse the shared CI setup action in both Builder E2E jobs - use one build command for CI and local E2E runs - centralize shard filename parsing and suite-name formatting - remove redundant suite-level shard filtering - parse each E2E filename's shard metadata once ## Why The merged image-asset PR introduced multiple owners for Builder E2E setup, build dependencies, and shard filename semantics. Consolidating them prevents CI and local behavior from drifting as the shard layout evolves. ## Validation - `pnpm --filter=@webstudio-is/builder test -- e2e/test-modules.test.ts` - `pnpm --filter=@webstudio-is/builder typecheck` - `pnpm lint` - `pnpm e2e:builder:build` - shell syntax and YAML parsing - shard discovery returned shards 1–6 |
||
|
|
597642ac2e |
fix: Accept numeric page status codes (#5915)
## Summary - accept fixed page status codes as JSON numbers from 200 through 599 - preserve dynamic status expressions and backwards-compatible numeric strings - remove a stored status when the Builder input is cleared, while leaving omitted status values untouched - advertise the correct number-or-expression contract through runtime and MCP schemas - update CLI guidance and examples to use numeric status values ## Testing - `pnpm --filter @webstudio-is/project-build exec vitest run src/runtime/pages.test.ts src/contracts/builder-runtime.test.ts src/mcp.test.ts` - `pnpm --filter @webstudio-is/project-build typecheck` - `pnpm --filter webstudio typecheck` - `pnpm lint` - `pnpm check:package-boundaries` - `pnpm check:generated-api` - `pnpm check:generated-docs` Closes #5913 |
||
|
|
ef94d85ccf |
feat: drag image assets onto canvas (#5912)
## Summary - allow dragging a single image asset from the Assets panel onto the canvas - insert an Image component with its source bound to the dragged asset in one undoable mutation - preserve asset-folder drops and canceled drags - build the Builder once in CI and reuse the compact build artifact across all E2E shards ## E2E timing Recent CI showed shard test runtimes of roughly 101–145 seconds, while every shard also repeated a roughly two-minute Builder build. The four shards are already reasonably balanced, so a fifth shard would not address the primary bottleneck. The shared artifact is about 30 MB uncompressed and roughly 5 MB compressed because checked-out public assets are excluded. This should return individual shard jobs to the 2–3 minute range. ## Validation - 45 focused unit tests - image asset to canvas E2E using the prebuilt-artifact path - image asset to folder regression E2E - Builder typecheck - lint - package-boundary validation - workflow YAML validation - shell syntax validation |
||
|
|
7d7c23d30a |
fix: Center empty asset folder drop state (#5911)
## Summary - center the reusable “Drop files here” state against the full empty-folder area - keep the Back thumbnail independently positioned and interactive - add regression coverage for empty folders with additional content - add a fourth builder E2E shard and split the serial asset-folder workflows using measured CI durations ## Root cause The Back thumbnail participated in the same column flow as the drop state, reducing the drop state’s available height and shifting its center downward. The asset-folder E2E module also accumulated ten serial workflows and became shard 1’s 214-second bottleneck. ## User impact Empty folders now align the drop message consistently with the root empty state and full-panel drag overlay. The E2E split reduces shard 1’s measured workload from about 230 seconds to a projected 113 seconds, with shard 4 at about 100 seconds. ## Validation - focused asset tests: 62 passed - E2E shard discovery test - shard 1 and shard 4 module loading - builder typecheck - workspace typechecks - lint - package boundaries - generated API and docs checks - fixtures - full workspace tests; three CLI subprocess tests initially timed out under concurrent load and passed when rerun in isolation |
||
|
|
af29a0cef7 |
fix: Improve shared Slot selector guidance for MCP agents (#5910)
## What changed - documents `extract-slot.instanceSelector` as a leaf-to-root occurrence path - provides valid examples for sections directly under Body and nested in a page wrapper - exposes those examples through `meta.get_more_tools` - makes invalid parent ordering errors explain how to recover using `list-instances` IDs and `parentId` - regenerates the public runtime schema with the selector contract ## Why Agents could discover `extract-slot` but could not determine the selector ordering expected by the runtime. Plausible selectors failed with a generic direct-parent error, and focused MCP discovery returned no working example. ## User impact Agents can now reliably convert existing sections into shared Slots without guessing the Navigator path format. Invalid selectors return enough context to correct the call instead of repeatedly probing the project. ## Verification - project-build slot and MCP tests: 108 passed - protocol operation docs and operation tests: 17 passed - CLI MCP tests: 35 passed - project-build, protocol, and CLI typechecks - repository lint - package-boundary check - generated API and documentation checks |
||
|
|
cca9f93e3d |
feat: Improve asset folder move workflows (#5908)
## Summary - use the design-system native scroll area and auto-scroll long asset lists during internal drag operations - add a shared **Move** action to thumbnail and context menus for individual and multiselected assets and folders - add a folder-only move dialog that excludes invalid descendant destinations - consolidate bulk move, duplicate, delete, and clipboard behavior into shared asset-manager operations with undo/redo coverage - simplify dialog state, folder exclusion traversal, and long-list E2E setup ## User impact Users can drag assets or folders to destinations outside the currently visible part of a long panel, and can move one or many selected items through an explicit folder picker. ## Validation - `pnpm --filter @webstudio-is/builder test app/builder/shared/asset-manager` — 126 tests passed - `pnpm --filter @webstudio-is/builder typecheck` - `pnpm lint` - `pnpm check:package-boundaries` - focused builder E2E: dragging auto-scrolls a long folder list - focused builder E2E: multiselected assets move from the context menu ## Review note The current validation prevents missing destinations and folder cycles. A small follow-up is still needed to disable moves when every selected item is already in the chosen destination, avoiding a no-op mutation and announcement. |
||
|
|
558ac1c18e |
fix: Fix insertion of content-model component parts (#5907)
## What changed - Allow template-less component parts to be inserted when the target parent explicitly permits them through `children`. - Honor component parts permitted by an ancestor through `descendants`. - Keep invalid standalone insertion blocked. - Support legacy instances without a `children` field while resolving ancestor selectors. - Add regression coverage for Text Animation, Stagger Animation, nested Radix parts, and legacy instances. ## Why Text Animation and Stagger Animation were valid direct children of Animation Group according to their content models, but the runtime rejected every template-less component with `contentModel.category: "none"` before considering its target parent. The registry audit also found that hidden base and Radix component parts could hit the same rejection through direct internal or MCP insertion, even when an ancestor explicitly allowed them. ## Impact Text Animation and Stagger Animation can now be inserted into Animation Group. Programmatic insertion of hidden component parts also follows the same content-model rules consistently. ## Validation - `pnpm --filter @webstudio-is/project-build test` — 1,984 tests passed - `pnpm --filter @webstudio-is/project-build typecheck` - `pnpm lint` - `pnpm check:package-boundaries` - Formatting and diff checks |
||
|
|
878d6f1de1 |
feat: Add asset folders to asset manager and improve asset manager UX (#5892)
Closes https://github.com/webstudio-is/webstudio/issues/5877 Closes https://github.com/webstudio-is/webstudio/issues/4775 - Organize assets into nested folders. - Navigate folders with breadcrumbs and Back controls. - Select and manage multiple assets and folders at once. - Drag, copy, cut, paste, duplicate, move, and delete items. - Use context menus and familiar keyboard shortcuts for common actions. - Search and sort assets and folders, with folders grouped first. - Upload files directly into the active folder. - Manage folder placement from asset and folder settings. - Automate asset and folder management through MCP.0.280.0 |
||
|
|
d440e02990 |
feat: Add safer MCP authoring and draft-page verification (#5905)
- **Restore points for agent work**: Create named restore points before major edits, review changes with a dry run, and safely revert project content if needed. - **Shared Slot authoring**: Agents can turn existing sections into shared Slots and insert linked copies across pages, including valid nested Slots. - **DTCG and Figma token imports**: Import design tokens and CSS variables through CLI, MCP, or direct paste, with aliases, modes, composite values, and mappings supported. - **Consistent token conflict handling**: Every paste workflow now offers the same preserve, rename, or merge choices instead of silently overwriting existing design tokens. - **Draft-page previews**: Agents can generate and inspect previews of draft pages without publishing them or exposing drafts in production builds. - **Safer MCP mutations**: Destructive operations require explicit confirmation, invalid raw patches and invented record IDs are rejected, and restore operations commit atomically. - **More dependable agent contracts**: New tools have complete runtime schemas, clearer validation errors, and consistent behavior across CLI, MCP, Builder, and server APIs. |
||
|
|
13c0351a03 |
fix: Move agent connection setup from Builder to the CLI (#5899)
## Summary - remove the misleading **Connect your agent** section from Builder Project Settings - make the CLI the sole owner of MCP client configuration - verify the linked project endpoint and credential before changing client configuration - safely merge Webstudio into existing Claude Code, Cursor, and VS Code MCP files - print the explicit global registration command for Codex instead of editing its global configuration silently - document the agent-led setup flow and safe handling of editable share links ## Why Builder runs in the browser and cannot configure files or global settings on a user's local machine. The previous Project Settings UI duplicated client definitions in the protocol package, exposed a setup command containing the project credential, and could appear successful without proving that the local agent was connected. This moves local-client concerns into the CLI, removes the browser-only setup surface, and makes configuration success depend on a valid, reachable project link. ## User impact A user can ask their agent to connect the current folder to Webstudio. The agent links and synchronizes the project, runs `webstudio connect <client>`, reloads the client, and verifies the connection by listing project pages. Invalid or stale links fail before any client file is changed, with a credential-safe recovery message. ## Validation - full CLI suite: 50 files, 786 tests - full Builder suite: 163 files, 2,148 tests - protocol suite: 73 tests - CLI, Builder, and protocol typechecks - root lint and package-boundary checks - generated API and documentation checks - real VS Code MCP handshake against a saved project: 156 tools discovered - fresh weak-model subagent test: repeated connection remained idempotent and `meta.index` returned `ok: true` |
||
|
|
98d5c607ee |
feat: Improve MCP safety, context efficiency, and agent workflows (#5895)
## Summary This combines the three reported MCP improvements into one release-ready change: - Safer mutation planning and confirmation for destructive operations. - Much smaller MCP handshake and default discovery responses. - Better agent workflows for checkpoints, multi-project work, and page duplication. ## Safer destructive operations - Exposes `dryRun` in MCP schemas for every local-capable mutation. - Returns planned transactions through `meta.session.transaction`. - Requires a two-step confirmation flow for destructive semantic operations. - Returns a short-lived token bound to the project, build version, input, and exact generated patch plan. - Rejects expired tokens, altered inputs, changed versions, and changed plans. - Sets `destructiveHint: true` only for operations that actually require confirmation. - Explicitly protects destructive operations whose names do not begin with delete or replace, including replacing all redirects and clearing all styles from a style source. ## Smaller, focused MCP context - Defers oversized tool input schemas from the initial MCP handshake. - Keeps complete focused schemas available through `meta.get_more_tools` and CLI schema inspection. - Makes template registry lists compact while preserving complete payloads through focused get calls. - Makes component summaries compact by default and supports paginated component details. - Replaces placeholder operation descriptions with useful command descriptions. - Constrains previously untyped JSON schema fields so clients can validate inputs earlier. - Keeps runtime output schemas compatible with strict MCP clients. ## Better agent workflows - Allows read-only discovery and inspection while a workflow checkpoint is awaiting acknowledgement. - Continues blocking mutations until the checkpoint is acknowledged. - Checks persisted checkpoints before every workflow call rather than only the first call. - Adds `--project` support so saved projects can be selected without relinking the current directory. - Isolates project sessions and checkpoints by selected project. - Adds atomic `duplicate-page` substitutions for copied fixed text and copied variable values. - Prevents substitutions from modifying source content or global root state. - Rejects ambiguous or missing copied variables without leaving a partial duplicate. ## Realistic agent verification Minimal-context tests used a weak agent against the local packaged CLI and stdio MCP: - Planned a page deletion, stopped for explicit user confirmation, committed the unchanged plan, and verified the page was absent. - Tried to reuse a confirmation token with altered input; Webstudio returned `DESTRUCTIVE_CONFIRMATION_INVALID` and preserved both pages. - Verified compact handshake schemas and focused retrieval of the complete oversized schema. - Verified compact template and component discovery responses. - Selected a saved project explicitly without relying on the directory link. - Verified checkpointed workflows permit reads but block mutations. - Duplicated a London page into a Paris page with atomic text and variable substitutions. - Verified source content remained London, copied content became Paris, and temporary pages were removed. ## Validation - Project-build focused suites: 188 tests passed. - CLI focused suites: 183 tests passed. - Protocol focused suites: 21 tests passed. - CLI, project-build, and protocol typechecks passed. - Repository lint passed with zero warnings. - Package-boundary validation passed. - Generated runtime operation contracts were regenerated from source. - Real local CLI/MCP tests passed against a running Builder server. Closes #5887 Closes #5888 Closes #5889 |
||
|
|
27eecd1a29 |
fix: remap conflicting pasted breakpoint ids (#5898)
## What changed - Remap pasted breakpoint IDs when the same ID already belongs to a different breakpoint in the destination project. - Carry the remapped ID into pasted style declarations. - Add a regression test for inserting a fragment whose breakpoint ID conflicts with an existing project breakpoint. ## Why HTML and Tailwind conversion uses compact fragment-local breakpoint IDs such as `"0"` and `"1"`. In non-empty projects, one of those IDs can already identify a different breakpoint. The fragment copy path previously retained the incoming ID, causing the runtime to reject the mutation with `Generated record id "1" already exists`. ## Impact Pasting HTML with Tailwind classes now works in existing projects even when generated fragment breakpoint IDs overlap project breakpoint IDs. Matching breakpoints continue to be reused. ## Validation - `pnpm --filter @webstudio-is/project-build test -- src/runtime/components.test.ts` - `pnpm --filter @webstudio-is/project-build test -- src/runtime/fragment.test.tsx src/runtime/breakpoints.test.ts` - `pnpm --filter @webstudio-is/project-build typecheck` - `pnpm exec oxlint packages/project-build/src/runtime/fragment.ts packages/project-build/src/runtime/components.test.ts` - `pnpm exec oxfmt --check packages/project-build/src/runtime/fragment.ts packages/project-build/src/runtime/components.test.ts` - `git diff --check` |
||
|
|
b395556d7a |
fix: wait for db over TCP in dev/backend.sh to avoid false-positive readiness (#5891)
## Description `builder_backend_wait_for_db` checks readiness by running `psql` inside the `db` container, which connects over the **unix socket**. The official `postgres` image's entrypoint starts a temporary server with `listen_addresses=''` (socket only) while it runs its init phase. During that window the socket probe succeeds, but host-side clients (prisma migrate, postgrest) connecting over TCP still get `connection refused` . so the wait can return before the database is actually reachable. It's a timing race: it rarely bites with a fast init, but it's reproducible with slower images/machines (we hit it consistently in our fork's CI, which uses a pg image with a longer init phase). Fix: make the readiness probe connect the same way real clients do. Over TCP (`psql -h 127.0.0.1`). `PGPASSWORD` is needed because host connections use password auth, unlike the socket which is `trust`. Same one-line change to the probe in `builder_backend_wait_for_db`; behavior is otherwise identical. ## Steps for reproduction 1. `docker compose down -v` in `apps/builder` (force a fresh initdb) 2. run `dev/run-local.sh` (or anything using `builder_backend_wait_for_db`) 3. on a slow machine the wait returns during the init phase and the following `prisma migrate` / postgrest startup fails with `connection refused`; with this patch the wait only returns once TCP is accepting connections ## Code Review - [ ] hi @kof, I need you to do - detailed review (it's a one-line probe change in `dev/backend.sh`) ## Before requesting a review - [x] made a self-review - [x] added inline comments where things may be not obvious (the "why", not "what") ## Before merging - [ ] tested locally and on preview environment (preview dev login: 0000) - [ ] updated test cases document n/a (dev tooling only) - [ ] added tests -> n/a (shell dev script) - [x] if any new env variables are added, added them to `.env` file -> none added Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
1ef64506aa |
fix: render head slot JSON-LD in document head (#5897)
## What changed - mark published Head Slot descendants with an internal context - portal JSON-LD scripts nested in Head Slot into `document.head` - preserve page-flow rendering for JSON-LD used outside Head Slot - add browser-DOM regression coverage for both placements ## Root cause React hoists `title`, `meta`, and `link` elements rendered by Head Slot, but it does not hoist inline `script type="application/ld+json"` elements. As a result, JSON-LD nested in Head Slot remained under the page body. ## Impact JSON-LD placed in Head Slot now appears in the document head after the published page mounts. JSON-LD intentionally placed outside Head Slot remains in its original page position. ## Validation - `pnpm --filter @webstudio-is/sdk-components-react test` - `pnpm --filter @webstudio-is/sdk-components-react typecheck` - targeted oxlint on changed files - `pnpm --filter @webstudio-is/sdk-components-react build` - `pnpm build` |
||
|
|
12ad74584a |
feat: Improve MCP authoring, auditing, and verification (#5886)
## Summary This improves how coding agents discover, author, verify, and audit Webstudio projects through the CLI and MCP. The work focuses on making agents more reliable with less context, while keeping edits semantic and Builder-editable. ## What changes for users - Agents can verify dynamic bindings after authoring and receive actionable diagnostics when expressions, resources, scopes, or component props do not line up. - Agents can create complete resource-backed runtime UI through a semantic operation instead of coordinating fragile low-level edits. - MCP discovery and command output are compact by default, with pagination and focused verbose detail when an agent needs more context. - Asset, style, token, font, page, and component inspection provides stronger usage context so agents can preserve the existing design system. - Rendered audits provide better evidence for responsive behavior, geometry, contrast, generated-build size, and large-project runs. - Cross-project MCP workflows can run from a manifest with explicit mutation approval, isolated failures, resumable progress, and persistent checkpoints. - Project-specific agent onboarding is clearer and does not add telemetry. - Packaged CLI releases gain stronger smoke verification for install, MCP startup, authoring, preview, screenshots, and audits. ## Reliability and architecture - Runtime operation output schemas are generated from the runtime registry and remain client-compatible. - Project-build exports are consolidated around architectural boundaries instead of feature-by-feature convenience entry points. - HTTP, preview, screenshot, and project-session paths are hardened for longer autonomous workflows. - Craft compatibility work is read-only and provenance-aware; it does not silently opt ordinary projects into Craft behavior. - A minimal-context evaluation harness exercises key workflows with a weaker model and stores bounded, privacy-safe evidence. ## Validation - Rebased on the latest `origin/main`. - `pnpm lint` - Repository-wide `oxfmt --check` - CLI typecheck and full test suite: 773 tests passed. - Project-build typecheck and full test suite: 1,866 tests passed. - Protocol typecheck and full test suite: 83 tests passed. - HTTP client tests: 23 passed. - CSS data tests: 3,620 passed, 1 skipped. - Focused Builder tests: 67 passed. - Package-boundary, generated API, and generated documentation checks passed. - Minimal-context agent evaluations passed for authenticated resource-backed UI and design-system-aware responsive authoring. |
||
|
|
d579607ed8 |
feat: Add draft pages (#5885)
Closes https://github.com/webstudio-is/webstudio/issues/3036 ## Summary - add an optional page-level draft state with a presentation-only `[Draft]` prefix in Builder - add **Mark as draft** and **Stage for publish** actions to the Page details header menu - keep drafts editable, previewable, linkable, duplicable, and path-reserving in Builder - exclude drafts from generated routes, public page collections, sitemap output, staging, and production builds - expose draft state and usage guidance through the runtime API, HTTP client, CLI docs, and MCP contracts ## Why Pages need a way to remain unfinished inside Builder without being included in the next site deployment. Draft is an exclusion flag, not a separate revision or publishing workflow state. ## Behavior and fixes - home and `/*` catch-all pages cannot be drafts - draft pages must be staged before becoming the home page - restricted features used only on draft pages no longer block publishing the publishable site - **Stage for publish** only clears draft state; it does not deploy the site - missing or explicit `false` draft state remains backward-compatible and publishable ## Validation - 5,179 package tests passed across SDK, migrations, project-build, CLI, and Builder - targeted Builder browser E2E passed for draft/stage actions, persistence, home-page guidance, copy, duplicate, delete, and generated-app build behavior - all affected package typechecks passed - lint and package-boundary checks passed - generated runtime contracts and CLI docs are reproducible - `git diff --check` passed |
||
|
|
dde30ffb54 |
feat: Improve MCP authoring, compact output, and agent onboarding (#5883)
## Summary This improves how agents discover, author, inspect, and verify Webstudio projects while reducing unnecessary MCP context usage. ## What changed - Adds an **Agents** section to Project Settings with ready-to-run setup commands and client configuration for Claude Code, Codex, Cursor, and VS Code. - Makes large list and schema responses compact and paginated by default, with **verbose** available when complete records or diagnostics are needed. - Applies consistent compact output to assets, instances, styles, design tokens, CLI schemas, and project-session metadata. - Returns actionable expression warnings for props, resources, and Collection bindings, including unknown variables and risky render-time mutation resources. - Improves Collection expression guidance so agents can bind array items with the correct scoped variables. - Reports rendered audit outcomes explicitly as complete, partial, confirmation-required, or failed. - Expands runtime output schemas so MCP clients can validate responses reliably. - Strengthens the packaged CLI smoke workflow with a realistic seven-page stdio MCP scenario. ## Architecture - Consolidates `project-build` from 65 file-oriented entrypoints to 11 architecture-owned surfaces. - Separates the core model, contracts, runtime authoring, transfer, state, project sessions, MCP, visual tooling, persistence codecs, and authenticated server services. - Isolates Node-only JSX evaluation from browser-safe transfer utilities and authenticated server modules. - Keeps persistence codecs independent from authenticated database services, preventing unrelated module initialization. - Defines shared instance-path types once and reuses them across runtime modules. - Preserves Immer initialization through explicit package side-effect metadata. - Adds package tests that prevent a return to source-file entrypoints or generic exposure of Node-only surfaces. ## Validation - Full repository checks, tests, typechecks, generated-file checks, and fixtures - All 163 Builder test files and 2,141 tests - All 71 project-build test files and 1,794 tests - Lint and package-boundary validation - Full packed CLI release smoke test, including install, preview, agent setup, seven-page stdio MCP workflow, rendered audit, and structured commands |
||
|
|
3304819d7e |
feat: Add complete, client-compatible MCP output schemas (#5882)
## What changed\n\n- Define concrete output schemas for every public runtime operation.\n- Expose output schemas through generated runtime contracts and MCP tool discovery.\n- Validate runtime results against their declared schemas, including mutation result envelopes.\n- Add output contracts for project-session status, refresh, reset, Collection insertion, and generated-preview tools.\n- Make every advertised MCP output schema explicitly object-shaped for strict clients.\n- Keep generated schema definitions at the correct root so local references resolve during tool discovery.\n- Report the correct session operation metadata for refresh and reset.\n- Preserve local workspace package resolution when the local CLI builds a generated React Router preview.\n\n## Why\n\nAgents could discover input requirements, but several tools did not describe their returned data. Strict MCP clients could also reject the complete tool catalog during reconnect because output schemas were not consistently object-shaped or contained unresolved local references.\n\n## User impact\n\n- Agents can plan calls from complete input and output contracts.\n- MCP clients can fetch the full Webstudio tool catalog without schema-validation failures.\n- Agents can reliably parse and validate command results.\n- Local generated previews continue to work for visual verification.\n\n## Validation\n\n- Every public runtime operation has an output schema.\n- Every advertised MCP output schema is object-shaped and has resolvable local references.\n- A real stdio MCP client connected through the local CLI and fetched 154 tools, including 119 valid output schemas.\n- Runtime output contracts validate representative query and mutation results.\n- A fresh subagent refreshed a real project session, built and started the generated site, captured the target route with HTTP 200, checked preview status, and stopped the server.\n- Focused project-build tests, project-build and CLI typechecks, lint, formatting, and generated-doc checks passed.\n |
||
|
|
2808f06808 |
feat: Improve MCP validation errors with actionable guidance (#5881)
## What changed - Return structured validation issues with stable codes, complete field paths, constraints, and minimal correction examples. - Preserve validation details through the Builder API, CLI, MCP, local project sessions, and tRPC errors. - Explain invalid expressions, JSX fragments, page selectors, component inputs, asset updates, and project settings in terms an agent can act on. - Remove stack frames and credentials from parser details before exposing them. - Keep concise human-readable errors while making the complete structured issues available to agents. ## Why Agents previously received vague errors without enough information to repair a request. They could repeat the same invalid call or require manual intervention. ## User impact CLI and MCP agents can now identify the exact invalid field, understand the constraint, see a valid example, and retry with a corrected request. ## Validation - Focused runtime, MCP, CLI, API, and tRPC validation tests. - Structured error propagation tests across local and server execution. - Typechecks and generated contract verification. |
||
|
|
03aeb535ef |
feat: Add semantic Collection authoring to MCP (#5880)
## What changed - Add an `insert-collection` MCP and CLI operation for creating repeated UI from array or object data. - Create the Collection, iterable binding, current-item/current-key parameters, repeated item structure, and descendant bindings atomically. - Accept literal JSON data or expressions backed by project variables and resource results. - Support `collectionItem` and `collectionItemKey` expressions inside the repeated Webstudio JSX item. - Return the created Collection, item root, and parameter IDs for immediate inspection and follow-up edits. - Document when agents should use Collection for lists, grids, cards, rows, options, tabs, and other repeated content. ## Why Building a data-driven list previously required several low-level operations and manual handling of Collection's internal parameters. A missed step could leave a partially configured or incorrectly scoped Collection. ## User impact Agents can turn resource or variable data into a correctly bound repeated layout in one operation, then inspect and refine the result normally. ## Validation - Real-world local CLI test created and rendered a three-product Collection from project data. - Tests cover literal arrays, objects, resource expressions, item/key bindings, malformed fragments, ID conflicts, server execution, and project-session behavior. - 176 focused tests, project-build typecheck, and generated-doc checks pass after rebasing onto current `main`. |
||
|
|
dd99e49fbe | fix: Preserve selection after instance deletion (#5879) | ||
|
|
7b59e70fde |
fix: Fix MCP mutation persistence and deterministic instance ordering (#5878)
Fixes three MCP issues that could cause misleading mutation results, unstable instance ordering, and project settings that disappeared after refresh. ## Changes - Prevents committed mutations from returning `PROJECT_SESSION_BUSY`. - Ensures retrying after a reported failure cannot silently create duplicate instances. - Reconciles the local project session after a mutation commits remotely. - Adds deterministic append behavior with `position: "end"`. - Preserves the requested order when moving multiple instances. - Makes project settings updates persist across refreshes. - Reports no-op project settings updates accurately. - Updates MCP documentation and generated contracts for the new behavior. ## Verification - Reproduced and retested all three user reports with a subagent against a real local project. - Verified overlapping duplicate operations commit exactly once. - Verified ordered moves remain correct after refresh. - Verified project settings survive refresh. - Passed all project-build tests: 1,745 tests. - Passed all CLI tests: 720 tests. - Passed type checks and lint. |
||
|
|
e57bd297f5 | test: cover drag gestures in builder e2e (#5876) |