mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-09 05:26:24 +09:00
0.290.0
465
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
21ca567686 |
fix: Stop owned preview process trees (#6111)
## Summary Supervise generated preview processes so the CLI terminates the complete owned process tree when an MCP session disconnects, a command finishes, or the owner receives a termination signal. Record owned PIDs and report actionable locked-path recovery when cleanup still fails. Closes #6019 ## Technical choices - Start generated previews through a dedicated supervisor process connected to its CLI/MCP owner over IPC. - Disconnect the supervisor to stop a preview; the supervisor owns all descendant cleanup. - Use Execa `killDescendants` for cross-platform process-tree termination instead of maintaining separate Windows and POSIX kill implementations. - Force-stop the owned tree so a descendant that ignores SIGTERM cannot survive its launcher. - Record supervisor and preview PIDs beside the generated preview directory. - Include the supervisor in the CLI build output. ## Implementation checklist - [x] Add owned preview process-tree supervision. - [x] Dispose previews on MCP completion, failure, disconnect, and signals. - [x] Add scoped locked-path diagnostics and recovery instructions. - [x] Add lifecycle and command regression coverage. - [x] Run the CLI typecheck and broader test suite. - [x] Review authoritative `docs/` content; no user-facing documentation changes are needed. - [ ] Run the complete agent evaluation suite after explicit approval. ## Verification - Preview server and supervisor tests: 42 passed. - Full CLI test suite: passed. - CLI typecheck: passed. - CLI production build: passed. - Package-boundary check: passed. - Targeted lint and formatting: passed. - `git diff --check`: passed. - The supervisor-disconnect regression was verified to fail without the new behavior and pass with it restored. - Agent evaluations were not run because repository policy requires separate explicit approval. |
||
|
|
87968f40ff |
fix: Improve MCP authoring and preview reliability (#6105)
## Summary
Fix MCP reliability failures reported in ten issues against CLI 0.288.0
and 0.289.0:
- keep every advertised array input schema client-valid, including
compact and tuple schemas
- report a text asset update as successful when its persisted revision
and bytes confirm that the server committed despite a failed response
- preserve standard package import resolution in generated React Router
previews
- upload variable WOFF2 fonts when callers provide the documented static
font metadata shape
- explain unmatched JSX as a stateless fragment syntax error
- distinguish the `animation` component namespace from value helpers and
reject unsupported CSS at-rules with an actionable validation error
- forward optional session tools such as `download-asset` through
top-level CLI shortcuts
- isolate published generated-preview dependencies from parent
workspaces
- return structured screenshot failures when React Router production
builds fail
Sensitive visual regression checks also run automatically for
organization-authored fork PRs. External fork PRs remain gated by
`safe-to-deploy`.
## Root causes and implementation
The MCP handshake compactor retained an array's type but discarded its
`items` schema. Unconstrained and tuple arrays could also be advertised
without `items`. Schema normalization now adds `items: {}` whenever an
array omits it, while focused discovery retains complete constraints.
Catalog coverage rejects every missing array item, including tuple
schemas, and the handshake remains below its 200 KB budget.
Asset content updates previously treated any failed response as a failed
mutation, even when the server had already swapped the revision.
Recovery now reads the current revision, compares the persisted bytes,
and confirms the revision remains stable across the read. It returns the
updated asset only when all evidence agrees. Otherwise it returns
`ASSET_UPDATE_COMMIT_UNCERTAIN` with guidance not to retry blindly.
Definitive 4xx responses retain their original errors.
The generated React Router Vite config replaced the client and SSR
resolver condition lists without explicitly retaining the standard
`import` condition. Both lists now preserve `import`. The regression
test generates a dynamic route, stages the built React Router SDK as a
published dependency without the local `webstudio` source condition, and
runs the generated build.
Variable fonts are detected with `variationAxes`. Merging the documented
static `style` and `weight` upload metadata into that detected variable
shape made validation fail after the binary was read. Font override
validation and shape-aware merging now live in `@webstudio-is/fonts`.
The SDK delegates to that domain function, which validates the complete
override before applying compatible fields, retains the detected
static-or-variable shape, and keeps the detected format.
Fragment parsing is stateless. Unmatched opening and closing tags now
explain that every opening element must use the same closing tag or be
self-closing, and that refreshing the session cannot repair malformed
JSX.
The `animation` binding is a component namespace, not a callable helper.
Tool schema text, evaluation errors, and the MCP manual now separate
component namespaces from value helpers. The MCP JSX `css` binding
parses the final interpolated CSS with CSS-tree and recursively rejects
selectors and unsupported at-rules such as `@keyframes`, while
preserving supported declarations and case-insensitive `@media` rules.
Keeping this validation at the external binding avoids changing internal
component templates.
CLI shortcut discovery previously omitted optional session tools even
though the runtime registered their handlers. Shortcut discovery now
includes the same optional tool categories as the CLI MCP host, while
real top-level CLI commands keep precedence.
Published generated previews could reuse a stale `node_modules` symlink
into a parent source workspace. Only development manifests containing
the local placeholder version may now reuse the CLI dependency tree.
Published manifests replace symlinks with a local install and disable
npm workspace discovery.
React Router could report a bundler failure while its build command
exited successfully outside CI, allowing screenshot startup to terminate
without a structured result. Managed production builds now set `CI=1`,
so the existing MCP error boundary receives the nonzero build failure
and prints structured JSON.
Visual regression authorization now distinguishes repository members
from external contributors. Organization members' fork PRs run on open,
synchronize, and reopen events; external fork code runs only from a
`safe-to-deploy` label event, and a later commit does not reuse that
approval.
## Implementation checklist
- [x] Preserve valid array item schemas in compact MCP discovery
- [x] Normalize tuple input schemas with an `items` fallback
- [x] Keep the MCP handshake below its 200 KB size budget
- [x] Cover the real `update-props` schema and oversized array
compaction
- [x] Reconcile failed asset-update responses against stable persisted
content
- [x] Reject recovery when a concurrent asset revision is detected
- [x] Preserve `import` resolution in generated React Router client and
SSR builds
- [x] Build a generated dynamic route against a staged published SDK
package
- [x] Regenerate and verify affected React Router fixtures
- [x] Preserve detected variable-font axes with documented upload
metadata
- [x] Add actionable unmatched-tag and unsupported-CSS validation
- [x] Correct animation namespace guidance in tool discovery and errors
- [x] Forward optional session tools through top-level CLI shortcuts
- [x] Replace parent-workspace dependency links for published previews
- [x] Disable npm workspace discovery for isolated preview installs
- [x] Make React Router build failures return nonzero in managed
previews
- [x] Run visual regression automatically for organization-authored PRs
- [x] Verify each regression test fails without its corresponding fix
- [x] Review documentation impact and update the authoritative MCP
manual plus generated outputs
- [x] Confirm no database migration or compatibility migration is
required
- [ ] Run `pnpm evaluations` after explicit approval; not run because
repository policy requires approval before agent evaluations
## Verification
- `packages/cli/src/prebuild.test.ts`: 57 tests passed
- `packages/cli/src/commands/schema.test.ts` and `mcp.test.ts`: 51 tests
passed
- `packages/project-build/src/runtime/components.test.ts` and
`mcp.test.ts`: 194 tests passed
- `packages/asset-uploader`: 196 tests passed
- focused font schema, SDK asset schema, CSS parser, and template CSS
tests passed
- `packages/http-client/src/index.test.ts`: 38 tests passed
- relevant CLI, project-build, asset-uploader, fonts, SDK, CSS data,
template, HTTP client, and React Router SDK typechecks passed
- MCP documentation tests, typecheck, generation, and Markdown source
tests passed
- React Router SDK package build passed
- full fixture link, sync, and generation pipeline passed
- affected Docker and Vercel fixture typechecks and locally bootstrapped
production builds passed
- complete CLI suite: 61 test files and 966 tests passed
- CLI typecheck passed
- preserved nested-workspace dynamic preview installed local `0.289.0`
dependencies and completed its production build
- visual-regression workflow YAML parsing and authorization truth table
passed
- repository lint passed with warnings denied
- formatting and `git diff --check` passed
## Tradeoffs and limitations
Deferred array schemas advertise unconstrained `items` in the compact
handshake to remain client-valid without duplicating detailed
constraints. Agents can retrieve the complete item schema through
focused `meta.get-more-tools` discovery.
Asset reconciliation performs three read requests only after an
uncertain 5xx, malformed response, or transport failure. This keeps the
normal successful path unchanged and avoids claiming success if the
revision changes during recovery.
For variable fonts, detected axes define the metadata shape. Static
`style` and `weight` hints are ignored because they cannot be
represented alongside `variationAxes`; compatible fields such as
`family` still override detection.
Native CSS keyframe authoring remains unsupported in fragment `css`
templates. The tool now rejects it before rendering and directs callers
to editable Webstudio Animation components instead of advertising a
nonexistent callable helper.
Published previews perform one isolated npm install when no valid local
dependency tree is cached. Local source development keeps the fast
workspace symlink path for placeholder-version manifests.
Closes #6104
Closes #6099
Closes #6098
Closes #6106
Closes #6107
Closes #6108
Closes #6114
Closes #6115
Closes #6116
Closes #6117
|
||
|
|
db2d092268 |
ci: replace Lost Pixel with self-hosted visual regression (#6086)
## Summary Replace the defunct Lost Pixel service and the interim Chromatic workflow with a fast, self-hosted visual comparison pipeline. The workflow indexes the existing CSF stories without building Storybook, builds and serves a lightweight browser app with Vite, renders the merge base and current revision through Webstudio's shared browser tooling, and compares screenshots with Webstudio's pixel-diff and OCR engine. It uses GitHub Actions cache and artifacts only—no R2 bucket or external visual-testing service. Closes #6064 ## Implementation - [x] Remove the Lost Pixel workflow, configuration, acknowledgement, and global two-second wait. - [x] Remove the interim Chromatic workflow and settings. - [x] Extract source-agnostic capture, diff, OCR, audit, cache, and report tooling into `@webstudio-is/vision`; rename the Webstudio-specific preview boundary to `@webstudio-is/project-build/preview`. - [x] Expose the reusable browser capture session through the shared vision boundary. - [x] Make OCR and diff-artifact generation conditional on detected pixel changes. - [x] Render existing CSF stories through a typed, lightweight browser harness built with Vite. - [x] Replace the embedded HTML and handwritten HTTP/MIME server with a real HTML entry, Vite production build, and Vite preview server; isolate declarative build configuration in `story-build.ts`. - [x] Apply Storybook preview annotations, decorators, global CSS, backgrounds, and story metadata. - [x] Store story scopes as shared data and load each revision's own configuration. - [x] Discover changed, added, and removed stories from both revisions. - [x] Populate private story sources symmetrically in the baseline worktree. - [x] Isolate every story with a fresh React root and deterministic time, randomness, intervals, focus, animation, and layout readiness. - [x] Preserve story-owned visual options for masking, settling, and interval control. - [x] Reuse Vite preview servers, one Chromium process, grouped browser pages, production bundles, and a bounded CPU worker pool for image comparison. - [x] Recheck initial pixel differences with serial captures, then recapture persistent baseline/current pairs on the same browser page so renderer variance cannot create false failures. - [x] Report individual story render failures without discarding successful captures. - [x] Enforce a 0.1 per-pixel threshold and 0.001% total mismatch tolerance. - [x] Run OCR only for changed comparisons and include text-change evidence. - [x] Move the generic report model, writer, static viewer, and opener into the shared Vision package for reuse by CI and future CLI comparisons. - [x] Bundle report HTML, styling, and browser behavior as static Vision assets without runtime source-file lookups. - [x] Copy external screenshot inputs into self-contained report artifacts for CLI reuse. - [x] Handle cached removed-only comparisons without rendering the removed story on the current server. - [x] Support focused local reproduction and opening the report with one command. - [x] Pin CI to the lockfile's Playwright Chromium, cache complete revision screenshots with matching restore/save paths and automatically derived runtime invalidation, and render both revisions on a miss. - [x] Keep cache archives bounded to one revision instead of accumulating the cache history. - [x] Run the complete visual suite in one CI job and upload one report as a 14-day artifact. - [x] Fail PR checks on visual differences, empty runs, missing screenshots, missing or empty report artifacts, and infrastructure failures. - [x] Rerun fork checks when `safe-to-deploy` is added. - [x] Allow reviewed visual-only differences through `visual-change-approved` and invalidate approval after new commits. - [x] Keep capture, pixel diff, OCR, and report generation source-agnostic for future draft-versus-published project comparisons. - [x] Use Vite for the complete story HTML, module, asset, production-build, and preview-server lifecycle; inline the selected stories and skip ineffective tree-shaking to keep the cached run under one minute. - [x] Review Builder product documentation impact: no user-facing Builder documentation is affected; contributor usage is documented in `scripts/visual-regression/README.md`. - [x] Review fixture impact: no fixture inputs or generated fixture outputs are affected. ## Verification - [x] Project-build Vision tests, including the reusable report test, and entrypoint contract tests pass. - [x] CLI screenshot, preview, and browser-session tests pass. - [x] Project-build, CLI, Builder, design-system, and visual-runner typechecks pass. - [x] Visual runner tests pass (10), and the complete Vision package passes (79), including demonstrated fail-before/pass-after coverage. - [x] Full Storybook production build passes. - [x] Full local Vite run completes all 238 stories in 69.9s cold and 50.3s with a cached baseline plus two same-page serial verifications, with zero differences; identical-image comparison remains sub-second. - [x] The report writer passes a bundled-output smoke test and materializes external screenshot assets. - [x] The generated report validates all 238 entries and referenced images. - [x] Hosted cached-baseline comparison completes all 238 stories in 52.9s with zero differences; the cache-miss fallback completes in 101.3s. - [x] Cache-miss fallback renders both Git revisions on demand. - [x] Visual differences produce baseline, current, diff, OCR, JSON, and HTML evidence and fail without approval. - [x] Hosted single-job visual workflow restores both the pinned browser and baseline cache, validates all 238 public and private stories with zero differences, and uploads the report. - [x] The final Vite production build renders all 238 stories without dependency invalidation or duplicate React runtimes, and restores `NODE_ENV` so cached serial fallback installs the baseline's dev dependencies. - [x] Root lint, package-boundary validation, and relevant formatting checks pass. - [x] Workflow YAML parses successfully. - [x] `git diff --check`, staged-diff review, and final worktree review pass. ## Usage Run the complete local comparison and open the visual report: ```sh pnpm visual-regression:ui ``` Focus one component while iterating: ```sh pnpm visual-regression:ui -- --grep "Design system/Button" ``` Reopen the latest report without rerunning: ```sh pnpm visual-regression:report ``` The CI report is available as the `visual-regression-report` artifact. ## Tradeoffs - Baseline screenshots are a disposable acceleration cache, not source of truth. A missing or invalid cache renders the merge base directly from Git. - GitHub artifact storage provides downloadable one-click reports; permanently hosted browser links would require another hosting surface. - OCR runs after pixel triage because invoking Tesseract for every unchanged story would make the common path unnecessarily slow. - Vite production builds add Rollup's module graph and HTML/asset pipeline. The runner emits one bundle because every selected story is rendered, and skips tree-shaking because it removed little while increasing build time. - The verified local path is 50.3s cached and 69.9s cold. The hosted path is 52.9s cached and 101.3s cold. A new browser/runtime cache must render its baseline once; the pinned browser keeps later runners on the reusable path. - The complete suite stays in one Actions job; browser-page concurrency is internal and bounded. |
||
|
|
5c6ffd3148 |
docs: document Content Engine workflows (#6097)
## Summary - add a step-by-step Content Engine guide for building a Markdown article overview and dynamic article page - clarify that the example folder structure is optional and link to the Markdown Blog marketplace template - explain that an AI agent can complete the entire workflow through Webstudio MCP and include a ready-to-use prompt - document frontmatter, JSON files, relative and published asset paths, document references, draft filtering, and single-result resources - document Markdown-to-Markdown, Markdown-to-JSON, JSON-to-Markdown, and JSON-to-JSON document references, including fragments and JSON Pointer escaping - add a schema-aware `webstudio man content-engine` reference for fields, operators, saved and preview inputs, result/output/content modes, diagnostics, limits, and reference syntax - generate the GitBook Content Engine reference and the matching MCP manual section from that shared CLI source - fail documentation generation when result modes, output modes, content modes, diagnostic fields, or Content Engine limits drift from the implementation - add four focused visual-editor screenshots - keep the Assets page focused on asset management and link it to the dedicated Content Engine guide - update MCP Assets examples and the Markdown blog recipe to use Markdown files, `result: "one"`, direct detail bindings, page metadata, and visual verification ## Impact Users get one workflow for treating files as the source of truth while designing article listings and detail pages in Webstudio. The generated reference documents the complete Assets query contract and document-reference system. Agents receive the same reference through the MCP manual, so the product and agent documentation no longer need separate factual copies. This does not change product runtime behavior. ## Checklist - [x] Documentation impact reviewed - [x] Added the Content Engine guide and generated reference to `docs/SUMMARY.md` - [x] Updated related Assets, Data variables, and MCP documentation - [x] Verified internal documentation and image targets - [x] Verified the Markdown Blog marketplace URL returns HTTP 200 - [x] Confirmed the MCP recipe test failed before the recipe correction and passed afterward - [x] Confirmed the schema-coverage test fails when an implemented result mode is omitted and passes after restoration - [x] Confirmed both Content Engine generator tests fail without their corresponding generator behavior and pass after restoration - [x] Ran `pnpm --filter @webstudio-is/project-build test -- src/mcp.test.ts` - [x] Ran `pnpm --filter webstudio test -- src/commands/api-command-docs.test.ts` - [x] Ran the Content Engine and MCP generator tests - [x] Ran project-build and CLI typechecks - [x] Ran `pnpm check:package-boundaries` - [x] Ran targeted lint and formatting checks - [x] Ran `pnpm check:generated-docs` - [x] Verified the final diff and working tree - [ ] Agent evaluation suite: not run because it requires explicit approval Ref #5973 |
||
|
|
93fa799cb8 |
fix: Preserve SSG exports with Assets queries (#6102)
## What changed - Preserve the SSG asset-resource template as a package-relative file URL in the bundled CLI. - Ignore Assets queries that do not bind any parameters from the current dynamic SSG route, while retaining the error for partial or split multi-parameter bindings. - Recognize the persisted `$ws$system.params.*` expression form when enumerating dynamic SSG paths. - Add a required package smoke test that deploys the release-shaped SSG package, runs the packaged CLI, runs Vite and Vike, and verifies rendered Assets data. ## Why Two gaps caused the staging export failures: 1. Vite inlined the template URL as a `data:` URL, which Node could not pass to `readFile`. 2. Dynamic-route validation treated an unrelated Assets query as an incomplete route enumerator. The initial smoke test only checked that an HTML file existed and could pass while resource loading logged a `400`. The replacement test verifies the rendered query result and fails on resource-loading errors. ## Technical choices - The package smoke uses `createPublishedProjectBundleFixture`, so fixture data stays checked against the published bundle contract. - Persisted expressions use `encodeDataSourceVariable`; the generated query now receives the real route parameter instead of compiling to `undefined`. - Temporary deployment, cleanup, subprocess execution, and assertions live in `test:ssg-package`. The workflow invokes one repository command. - Asset downloads are disabled to keep the smoke deterministic. It still covers CLI packaging, the embedded Assets index, dynamic path enumeration, generated resource execution, Vite compilation, and Vike prerender. - The test asserts the queried title in `/posts/hello-world`, rejects any resource-load error, and verifies that an unrelated query does not invent a dynamic path. ## Todo - [x] Reproduce the invalid URL scheme through a bundled template reader. - [x] Preserve the package-relative template URL in the production CLI bundle. - [x] Ignore Assets queries unrelated to the current dynamic route. - [x] Preserve rejection of incomplete multi-parameter route queries. - [x] Support persisted system-variable expressions during route enumeration. - [x] Add a production-shaped packaged CLI and Vike smoke test. - [x] Make the packaged SSG smoke test required on `main`. - [x] Run CLI tests, typecheck, lint, build, and the packaged smoke test. - [x] Rerun the previously failing `WEBSTUDIO-LANDING` SaaS SSG workflow. - [x] Review documentation impact; no user-facing documentation changes are needed. - [x] Review fixture impact; synced fixture inputs and generated outputs are unaffected because smoke data exists only in a temporary deployment. ## Verification - `pnpm --filter webstudio test` — 61 files, 977 tests passed before the final test addition - `pnpm --filter webstudio test -- prebuild.test.ts ssg-asset-resource-fetch-template.test.ts` — 57 tests passed - `pnpm --filter webstudio test:ssg-package` - `pnpm --filter webstudio typecheck` - `pnpm lint` - `pnpm --filter webstudio build` - Package regression proof: the smoke failed on the original unrelated-query implementation with `Dynamic SSG route parameters must be completely enumerated by one Assets query`, then passed with the fix restored. - Persisted-expression regression proof: the focused test returned no prerender path before encoded-system support, then passed with the support restored. - Template regression proof: the focused bundle test failed with `ERR_INVALID_URL_SCHEME` before the fix and passed after it. - Exact SaaS E2E rerun passed: project sync, CLI build, Vike build, archive upload, and database update ([run 31519515809](https://github.com/webstudio-is/webstudio-saas/actions/runs/31519515809)). Closes #6100 Supersedes #6101 after moving the change to the staging branch. |
||
|
|
eb46abf4e5 |
fix: Recover missing preview assets (#6091)
## Summary Fix session-based generated preview startup when the local `.webstudio/assets` directory has not been created yet. - materialize the current session's asset files before compiling the Assets resource index - reuse the existing safe asset downloader so missing parent directories are created and downloads retain retry and temporary-file cleanup behavior - return the stable `PREVIEW_ASSET_DOWNLOAD_FAILED` code with a concrete recovery action when asset access cannot be restored automatically - document the automatic recovery and regenerate the authoritative MCP manual ## Root cause `preview.start` materialized current ProjectSession data and compiled reachable Assets resources before generated-app prebuild. That compilation called `realpath` on the local assets directory, but the session path had never downloaded assets the way `webstudio sync` does. A newly linked project without `.webstudio/assets` therefore failed with `ENOENT` before preview generation. ## Technical choices - Download only after confirming that the project has a reachable Assets resource compilation plan. - Keep canonical path and symlink validation in the filesystem content source after materialization. - Wrap download failures at the preview boundary without exposing local paths or raw remote diagnostics. - Preserve the existing generated-doc source/generator workflow rather than editing generated guidance alone. ## Todo - [x] Reproduce startup from a missing local assets directory - [x] Materialize required session assets before index compilation - [x] Add actionable failure recovery - [x] Add fail/pass regression coverage - [x] Review documentation impact and update the MCP vision guidance - [x] Regenerate the CLI and GitBook MCP manuals - [x] Review fixture impact — no fixture inputs or generated fixture outputs are affected - [x] Run the focused low-reasoning Markdown fixture, including the cold assets-directory scenario - [ ] Deferred: run the remaining agent evaluation fixtures ## Verification - Regression demonstrated failing before the fix with `ENOENT` for the missing assets directory, then passing after the fix. - Recovery regression demonstrated failing with raw `ENOENT`, then passing with `PREVIEW_ASSET_DOWNLOAD_FAILED` and the retry action. - `pnpm --filter webstudio test` — 60 files, 976 tests passed. - `pnpm --filter webstudio exec vitest run src/project-session.test.ts src/mcp-guidance.test.ts` — 25 tests passed after final fixture cleanup. - `pnpm --filter webstudio typecheck` — passed. - Targeted `oxlint --deny-warnings` — passed. - Documentation generation, docs tests, and docs typecheck — passed. The aggregate generated-doc clean-tree guard reports the intentionally changed generated CLI/GitBook outputs included in this PR. - `git diff --check` — passed. - Focused real-world evaluation: `gpt-5.4-mini` with `model_reasoning_effort="low"`, `markdown-blog-v1`, 12/12 MCP calls succeeded, 0 failures, 0 retries, 2 rendered verifications, and all fixture checks passed. - Cold-directory variant: removed `.webstudio/assets` immediately before the first rendered verification; preview restored the required assets, and both verification calls plus content-database checks passed. - Remaining high-impact fixtures were not run; this was the targeted real-world scenario requested for #6090. ## Known limitations Preview startup still requires network and project asset access when required files are not already local. It now reports a stable error and tells the caller to restore access and retry instead of leaking an `ENOENT`. Closes #6090 |
||
|
|
63fcc9c5a6 |
fix: Improve MCP preview verification reliability (#6084)
## Summary Fix the third MCP reliability batch across generated catch-all routes, rendered screenshot evidence, and preview startup diagnostics. ## Root causes - Incremental prebuild rewrote an authored `/*` route with the redirect-only fallback at `routes/$.tsx`. - Screenshot capture trusted the browser writer result without verifying that the output artifact was readable and non-empty. - Generated preview dependency installation had no timeout, and preparation exposed only one broad progress phase. ## Implementation - [x] Preserve authored catch-all HTML routes during full and incremental React Router generation while retaining the redirect fallback when no catch-all page exists. - [x] Probe every single and responsive screenshot artifact before returning success; reject missing, unreadable, or zero-byte output with stable error codes. - [x] Bound generated preview dependency installation to two minutes. - [x] Report session materialization, route generation, dependency preparation, and completion phases through MCP progress output. - [x] Deduplicate preview dependency preparation and MCP progress wiring, flatten generation control flow, and consolidate overlapping test setup. - [x] Add regression coverage and demonstrate each new test failing before its implementation and passing afterward. - [x] Review documentation impact: no documentation update is required because the existing preview and audit workflow is unchanged; this PR makes its generated output and failure behavior reliable. - [x] Review fixture impact and run the full fixture pipeline; no fixture diff was produced. - [ ] Agent evaluations — not run because repository policy requires separate explicit approval. ## Verification - `pnpm --filter webstudio test` — 60 files, 974 tests passed. - `pnpm --filter webstudio typecheck` - `pnpm lint` - `pnpm check:package-boundaries` - `pnpm check:generated-api` - `pnpm check:generated-docs` - `pnpm fixtures` Closes #6081 Closes #6080 Closes #6078 |
||
|
|
dd316c53cc |
fix: Complete interrupted preview workflows (#6076)
## Summary `webstudio mcp run` now emits a terminal structured error when the process is interrupted while an MCP call such as `preview.start` is still active. It preserves completed call results, identifies the unfinished call and terminating signal, attempts preview cleanup, and then propagates the original signal. The MCP runner owns process termination for this workflow so the preview controller cannot race it or propagate the same signal twice. Cleanup is bounded to five seconds so a stalled preview startup cannot prevent termination. ## Todo - [x] Reproduce the missing terminal result for an interrupted `preview.start` call - [x] Report the active call and original signal in structured output - [x] Preserve completed results from the shared MCP session - [x] Clean up preview resources before propagating the signal - [x] Prevent competing MCP-run and preview-controller signal handlers - [x] Add regression coverage and verify it fails before the fix and passes after it - [x] Review for DRY violations and unnecessary abstractions - [x] Review documentation impact; existing CLI documentation already describes the restored terminal JSON behavior - [x] Review fixture impact; no fixture inputs or generated fixture bundles are affected - [x] Run CLI tests, typecheck, lint, package-boundary checks, generated API checks, and generated docs checks - [x] Verify CI; all checks pass or are intentionally skipped except the requested Lost Pixel exemption - [ ] Run the complete local agent evaluation suite (requires explicit user approval) ## Verification - `pnpm --filter webstudio test` — 60 files, 972 tests passed - `pnpm --filter webstudio typecheck` - `pnpm lint` - `pnpm check:package-boundaries` - `pnpm check:generated-api` - `pnpm check:generated-docs` - `pnpm exec oxfmt --check packages/cli/src/commands/mcp.ts packages/cli/src/commands/mcp.test.ts packages/cli/src/preview-server.ts packages/cli/src/preview-server.test.ts` - `git diff --check` - GitHub CI — all checks passed or skipped except Lost Pixel, which is explicitly excluded Closes #6075 |
||
|
|
e4983b0d1d |
fix: Report unsupported Node versions (#6058)
Closes #6057 ## Outcome Generated projects now reject Node.js versions older than 22.12 before React Router, Remix, or Vite evaluates SDK components. Users see the package-manager engine error with the current and required versions instead of the indirect `sanitize-html` / `htmlparser2` `ERR_REQUIRE_ESM` stack trace. ## Root cause `sanitize-html@2.17.6` synchronously loads the ESM-only `htmlparser2@12`. That dependency combination relies on synchronous `require(ESM)` support, which Node.js enabled by default in 22.12. Generated projects incorrectly declared the broader `>=22` range, allowing an unsupported runtime to reach SSR evaluation. ## Implementation - Set the CLI and all generated base templates to `engines.node: >=22.12.0`. - Add npm `devEngines.runtime` with `onFail: error`, which runs before install, CI, and run commands. - Enable `engine-strict` in generated npm configuration so pnpm also rejects an unsupported runtime. - Regenerate every tracked CLI fixture package manifest. - Update CLI documentation and the release-smoke manifest contract. - Remove the earlier sanitizer-bundling workaround from the branch; sanitizer code and packaging are unchanged from `main`. ## Checklist - [x] Declare the exact Node.js compatibility floor - [x] Fail before generated development, build, and start commands - [x] Cover the generated engine contract with a fail/pass regression - [x] Regenerate and inspect all affected fixtures - [x] Review documentation impact and update the CLI guide - [x] Keep sanitizer behavior and SDK packaging unchanged ## Verification - Regression demonstrated failing before the template metadata change and passing afterward - `pnpm --filter webstudio test` — 946 passed - `pnpm --filter webstudio typecheck` - `pnpm --filter webstudio build` - `pnpm fixtures` - `pnpm lint` - `pnpm exec oxfmt --check` on changed source, template, fixture, and documentation files - `git diff --check` Agent evaluations were not run because they require separate approval. |
||
|
|
1fe087ed26 |
fix: Improve MCP preview and mutation reliability (#6073)
## Summary Fix the second MCP reliability batch across tool discovery, runtime mutations, preview/screenshot setup, Windows process launching, and stdio recovery. ## Implementation - [x] #6071 Accept canonical dotted/kebab tool names and MCP underscore names in `mcp run`; return near matches and `meta.index` guidance for unknown tools. - [x] #6067 Parse JSON-stringified `tools` arrays in `meta.get-more-tools`. - [x] #6069 Preserve resource-backed variables when renaming without a replacement value. - [x] #6068 Parse CSS declaration strings consistently in design-token style updates. - [x] #6065 Fail immediately for occupied explicit screenshot ports and discover Chromium from the Playwright browser cache. - [x] #6066 Recover the stdio MCP transport after an abandoned partial newline-delimited frame. - [x] #6072 Launch managed Windows previews through Node plus `npm-cli.js`, avoiding `spawn EINVAL`. - [x] #6061 Reuse `npm-cli.js` when launched through `npx`, fall back to the Node-adjacent npm CLI on Windows, forward `npm_config_cache`, and include sanitized package-manager diagnostics. - [x] Address review findings: preserve rebinding on resource scope changes and discover default Playwright caches on Linux, macOS, and Windows. - [x] Complete the DRY pass: remove the dead npm command selector, centralize accepted MCP tool-name lookup, simplify stdio frame recovery, and share Levenshtein distance across MCP suggestions and screenshot text matching. - [x] Complete the follow-up review: centralize preview URL port resolution, use `get-port` instead of custom TCP probing, use named resolver dependencies, and correctly reuse owned previews on default HTTP/HTTPS ports. - [x] Complete the final review: use non-reserving `detect-port` checks for explicit ports and repair the generated-app guidance regression coverage. - [x] Audit new utility code against maintained libraries: use `fastest-levenshtein` for edit distance; retain custom stdio recovery, Playwright cache discovery, and npm launching where no supported library API preserves the required behavior. - [x] Audit Windows/macOS/Linux compatibility helpers: use `path-key` for environment PATH casing and `which` for executable discovery; retain explicit Playwright layouts, browser application paths, npm CLI resolution, symlink types, and process-tree shutdown where behavior is platform- or product-specific. - [x] Add fail/pass regression coverage for every fix. - [x] Review documentation impact and update the CLI MCP sources plus generated GitBook output. - [x] Review fixture impact: no fixture inputs or generated fixture bundles are affected. - [x] Run targeted tests, package type checks, lint, package-boundary checks, generated API checks, and generated documentation checks. - [ ] Agent evaluations — not run because repository policy requires separate explicit approval. ## Verification - Complete CLI suite: 60 files, 968 tests passed. - Project-build affected tests: 4 files, 382 tests passed. - `pnpm --filter webstudio typecheck` - `pnpm --filter @webstudio-is/project-build typecheck` - `pnpm lint` - `pnpm check:package-boundaries` - `pnpm check:generated-api` - `pnpm check:generated-docs` Each new regression test was run against the unfixed behavior to confirm the expected failure, then rerun after its fix. ## Compatibility note The stdio recovery layer discards only an unterminated frame that remains idle for five seconds. Complete newline-delimited JSON-RPC frames continue through the SDK transport unchanged. Closes #6072 Closes #6071 Closes #6069 Closes #6065 Closes #6066 Closes #6067 Closes #6068 Closes #6061 |
||
|
|
d5b3f3ab80 |
fix: Improve MCP authoring reliability (#6056)
## Summary This consolidates the reported MCP reliability fixes into one delivery. - validate all inserted fragment expressions with the shared runtime rules and reject text/expression children when component content models require elements - return an actionable error for unsupported existing-resource references in JSX - preserve siblings rendered before expression children - accept unresolved CSS-variable shorthand expansion and eliminate dynamic-alt/`htmlFor` audit false positives - resolve exposed underscore MCP names during focused discovery - omit unavailable stopped-preview fields and restart stale iterative previews for external clients - bound single and responsive screenshot capture, return `SCREENSHOT_TIMEOUT`, and discard failed reusable browser sessions - dispose previews when shared MCP runs fail or stdio clients disconnect, including complete Windows process-tree cleanup - resolve generated route templates from the CLI-managed preview workspace during responsive verification - retry a browser that exits during rendered-audit startup and report sanitized exit diagnostics with a concrete browser-path recovery action - materialize complete current session data before preview generation so route order and project styles cannot collapse from missing lazy namespaces - always include CLI and Node.js version fields in generated issue reports, with explicit legacy-client fallbacks - document the updated preview and screenshot contracts and regenerate the CLI manual The current branch also retains the protections already present on `main` for dry-run isolation, CSS rewrite truncation metadata, stderr-only progress, shortcut argument forwarding, strict MCP schemas, and refreshed conflict diagnostics. ## Technical choices - MCP command orchestration stays in `mcp.ts`; preview port/retry behavior lives with `mcp-preview`, and persisted checkpoint storage lives in `mcp-checkpoint`. Each module owns its matching tests. - Expression validation lives on the shared fragment input schema, reuses `listFragmentExpressions`, and emits the same structured validation issues as prop bindings, so JSX-derived and structured fragments follow one contract across fragment, collection, and runtime UI insertion. - Element-child requirements come from component registry content models during fragment insertion; no component names are hardcoded in the JSX parser. `CollapsibleTrigger` metadata now matches its enforced `asChild` implementation. - Stopped preview status returns only `running: false`; unavailable `url`, `pid`, and `mode` fields are optional and omitted from JSON. - Explicit `preview.start` restarts a stale compatible iterative preview; managed screenshots keep their optimized refresh path. - Screenshot operations share one timeout utility. A single capture or complete responsive batch is bounded after preview readiness; lower-level CDP deadlines use the same stable error code. - Failed managed captures close and forget their browser session. A closed browser session cannot restart itself while cancellation is in progress, which prevents orphaned Chromium processes. - One ownership helper disposes one-shot and multi-project MCP hosts on success or failure. Shared `mcp run` hosts dispose in one `finally` boundary, long-running MCP hosts dispose on connection close, and Windows uses `taskkill /T /F` instead of killing only the npm wrapper. - Framework template readers receive the absolute template directory captured from the build root, so later async work cannot redirect them to the linked project's cwd. The same option drives cleanup for React Router, Remix, and Vike. - Browser startup gets one bounded retry before a rendered capture batch fails. Persistent failures report only the exit code, signal, or spawn error code plus the supported `WEBSTUDIO_BROWSER_PATH` recovery action; local paths and raw browser output are not exposed. - CLI and MCP preview share one session materializer that ensures the canonical Builder namespace set before writing `.webstudio/data.json`. Serialization rejects incomplete snapshots instead of converting missing style/instance namespaces into valid-looking empty arrays, and preview freshness records the post-materialization project version. - The CLI injects its package version and `process.versions.node`; issue formatting now keeps both fields visible even for legacy reports that omit runtime metadata. ## Checklist - [x] Add regression coverage for every changed behavior - [x] Demonstrate new regression tests fail without the corresponding fixes and pass with them - [x] Run affected package test suites and typechecks - [x] Run lint, package-boundary, and generated API checks - [x] Review fixture impact — no fixture inputs or outputs are affected - [x] Review documentation impact and update the authoritative MCP CLI manual source/generated output - [x] Run the complete local agent evaluation suite ## Verification - `@webstudio-is/project-build`: 2,090 tests passed - MCP asset query result modes are preserved across create, read, and update serialization - complete local agent evaluation suite: all 5 fixtures passed, 1,308,276 aggregate tokens - `@webstudio-is/react-sdk`: 140 tests passed - `@webstudio-is/template`: 43 tests passed - `webstudio` CLI: 956 tests passed - issue reporter: 5 targeted tests passed - MCP host disposal regression was demonstrated failing without the shared ownership boundary and passing with it - relevant package typechecks passed - `pnpm lint` passed - `pnpm check:package-boundaries` passed - `pnpm check:generated-api` passed - generated-doc tests, typecheck, sync, and regeneration passed; the aggregate clean-tree command reports the intentionally changed generated CLI manual - stalled single capture, stalled four-viewport capture, startup retry across a four-viewport batch, sanitized browser-exit diagnostics, complete preview materialization, post-refresh version tracking, closed-session restart, Windows process-tree cleanup, and preview-workspace regressions were demonstrated failing without their fixes and passing with them ## Known limitations - External `baseUrl` screenshots remain caller-owned and intentionally do not regenerate, restart, or stop that external server. Closes #6034 Closes #6035 Closes #6038 Closes #6042 Closes #6043 Closes #6044 Closes #6045 Closes #6046 Closes #6047 Closes #6048 Closes #6049 Closes #6050 Closes #6051 Closes #6052 Closes #6059 Closes #6060 |
||
|
|
2ec78c183d |
feat: Add single-result modes to Assets queries (#6040)
## Summary - Add `many`, `one`, `first`, and `last` result modes to Assets queries while keeping `many` as the backward-compatible default. - Return direct items for single-result modes, validate deterministic ordering, and report duplicate `one` matches as a structured `MULTIPLE_RESULTS` error. - Update Builder controls, preview/published runtime handling, SDK resource encoding, MCP/CLI guidance, generated contracts, and fixtures. ## Implementation TODOs - [x] Add result-mode schemas and core execution behavior. - [x] Select single results before content hydration and preserve deterministic ID tie-breaking. - [x] Add structured duplicate-match transport errors. - [x] Update Builder controls and hide/reset pagination for single-result modes. - [x] Keep existing settings first, then Output and Result, without a duplicate Return label. - [x] Preserve legacy saved resources with an implicit `many` default. - [x] Update preview, published runtime, SDK, protocol, MCP, and CLI behavior. - [x] Regenerate runtime contracts, server metadata, CLI docs, and fixtures. - [x] Review documentation impact and update the authoritative MCP/CLI guidance. - [x] Add regression coverage and verify the new tests fail without the implementation. - [ ] Run the agent evaluation suite (not run; requires explicit user approval). ## Compatibility and behavior - Existing queries without `result` continue to behave as `many` and retain the ID-keyed collection shape. - `one` returns an item or `null`, but fails when more than one asset matches. - `first` and `last` require explicit sorting; the existing asset-ID tie-breaker makes equal sort values deterministic. - Single-result modes ignore and do not persist pagination controls. Materialized collection queries remain collection-only; single-result queries execute dynamically. ## Verification - Content engine typecheck and full test suite (291 tests). - Query builder, query-builder React, SDK, protocol, asset uploader, project build, Builder, and CLI targeted typechecks/tests. - Root lint. - MCP documentation tests, typecheck, sync check, and generated-doc checks. - Generated API contract checks. - Fixture generation pipeline. - Final focused content-engine regression run (53 tests). - Final DRY review: affected typechecks, focused tests, lint, package boundaries, generated checks, and fixtures. Closes #6039 |
||
|
|
b6d4d645f5 |
fix: Include runtime metadata in CLI issue reports (#6026)
## Summary Automatically attach anonymous CLI runtime metadata when the resolved public API command is `report-issue`. The transport previously compared the route operation ID (`reports.issue`) with the command name (`report-issue`), so enrichment was skipped. The change keeps enrichment owned by the CLI transport and preserves the existing server contract for Builder UI and other clients. ## Technical choices - Resolve the public operation by route ID as before. - Pass its typed command to runtime enrichment, removing ambiguity between route IDs and commands. - Exercise the real `reports.issue` transport path and inspect the serialized request body. - Keep runtime fields limited to CLI version, Node.js version, OS family/version, architecture, execution mode, and API contract version. ## Todo - [x] Attach runtime metadata using the resolved report command. - [x] Add transport-level regression coverage for the outgoing request. - [x] Confirm non-report operations preserve existing behavior. - [x] Review documentation impact; no documentation changes are required because the public report schema and workflow are unchanged. - [x] Confirm fixture inputs and generated fixture outputs are unaffected. - [ ] Run `pnpm evaluations` after explicit approval for agent evaluations. ## Verification - Regression test demonstrated failure before the implementation and passed afterward. - `pnpm --filter webstudio test -- project-session.test.ts` — 20 passed. - `pnpm --filter webstudio test` — 943 passed. - `pnpm --filter webstudio typecheck` — passed. - `pnpm exec oxlint --deny-warnings packages/cli/src/project-session.ts packages/cli/src/project-session.test.ts` — passed. - `git diff --check` — passed. ## Known limitations The complete agent evaluation suite has not been run because repository policy requires separate explicit approval before invoking it. Closes #6025 |
||
|
|
6d2389ee54 |
fix: Stop managed preview process groups (#6037)
## Summary - start managed POSIX preview servers in their own process group - terminate the complete preview process group from `preview.stop` - clean up the owned preview group before propagating `SIGHUP`, `SIGINT`, or `SIGTERM` - preserve the existing child-process fallback on Windows - keep standalone `webstudio preview` signal behavior unchanged ## Root cause The managed preview controller spawned an npm wrapper and stopped only that direct child with `ChildProcess.kill()`. React Router runs below that wrapper, so the dev server could survive as an orphan. Its inherited stdout/stderr pipes could also keep `webstudio mcp run` alive after the manifest had completed. ## Impact `preview.stop` now terminates the npm wrapper and all descendants. If the CLI is terminated while it owns a managed preview, it kills that process group before re-propagating the original signal to itself. ## Todo - [x] Reproduce the missing process-group cleanup in regression tests - [x] Isolate managed POSIX previews in their own process group - [x] Stop the full group on `preview.stop` - [x] Stop the full group on CLI termination signals - [x] Preserve standalone preview behavior - [x] Run an independent real subprocess test with an npm wrapper and long-lived grandchild - [x] Review documentation impact — existing MCP documentation already describes `preview.stop` as ending the owned preview, so no docs change is required - [x] Verify fixture impact — no fixture inputs or generated outputs are affected ## Verification - `pnpm --filter webstudio test` — 58 files, 945 tests passed - `pnpm --filter webstudio typecheck` — passed - targeted `oxlint`, `oxfmt`, and `git diff --check` — passed - regression tests were demonstrated failing without the process-group and signal cleanup, then passing with it - independent real-process test on macOS / Node 22.22.1: - `preview.stop` removed the npm wrapper, server, and long-lived grandchild in 458 ms; harness exited in 0.93 s - parent `SIGTERM` removed the complete process group in 0.01 s; harness exited with expected status 143 - all observed PIDs were absent afterward - agent evaluations were not run because they require separate explicit approval Closes #5958 |
||
|
|
b8cbd09020 |
fix: Preserve MCP run results on termination (#6033)
## Summary - emit a structured terminal result when an active `mcp run` reaches Node `beforeExit` - preserve completed call results and identify the unfinished call - add regression coverage for a four-call run that terminates during `preview-asset-query` ## Root cause `mcp run` only wrote its final JSON after the awaited tool call settled. An unresolved tool promise does not keep Node's event loop alive by itself, so a read-only preview call could reach `beforeExit` after its start lifecycle event without producing either a terminal call event or the run result. ## Implementation The CLI tracks only the currently active call while a run is executing and installs one scoped `beforeExit` handler. If Node would exit while that call is unresolved, the handler reuses the existing MCP run error envelope to return `MCP_RUN_TERMINATED` with completed results, total call count, the unfinished call number and tool, elapsed time, and the original exit code. Existing success, tool-failure, and checkpoint control flow remains unchanged. OS-level termination that cannot be intercepted, such as `SIGKILL`, remains outside the process's ability to report. ## Checklist - [x] Preserve completed MCP call results on unexpected termination - [x] Identify the unfinished call in the terminal payload - [x] Emit a nonzero exit status - [x] Add fail-then-pass regression coverage for asset query preview termination - [x] Review implementation for correctness, unnecessary work, and duplication - [x] Review documentation impact: no update needed because this restores the existing documented stdout JSON contract - [x] Verify fixture impact: no fixture inputs or generated fixture outputs are affected ## Verification - `pnpm --filter webstudio typecheck` - `pnpm exec oxlint --deny-warnings packages/cli/src/commands/mcp.ts packages/cli/src/commands/mcp.test.ts` - `pnpm --filter webstudio test` — 943 tests passed - `git diff --check` The separate `pnpm evaluations` agent evaluation suite was not run because it requires explicit approval. Closes #6032 |
||
|
|
928867a08b |
fix: Improve MCP CSS variable safety and state feedback (#6018)
Closes #6017 Ref #6019 ## Summary Improve agent-facing CLI/MCP feedback for CSS variables, mutation durability, batch operations, and preview freshness. ## Implementation - Validate structured hex colors as normalized channels and recommend CSS strings for ordinary 0–255 hex input. - Return exact CSS variable values while retaining `valueLength` in compact output for compatibility. - Preserve optional boolean inputs generically in compact MCP SDK schemas, including `withUsage`, `verbose`, `overwrite`, and `force`. - Add multi-variable define/delete examples and document safe batching. - Derive `meta.session.commitStatus` from the session envelope so reads, plans, failed/no-op mutations, and durable mutations are unambiguous. - Retain `committed` on read results for compatibility while reporting `commitStatus: "not-applicable"`. - Report preview `stale` state and `renderedProjectVersion`, and avoid marking a preview fresh when the project changes during regeneration. - Track WSL2/9P cleanup hardening separately in #6019. ## Todo - [x] Reject out-of-range structured hex color channels and alpha. - [x] Add fail-before/pass-after CSS color regression coverage. - [x] Return exact compact CSS variable values without removing `valueLength`. - [x] Clarify mutation durability with `commitStatus`. - [x] Distinguish failed, unchanged, planned, committed, and read-only results. - [x] Distinguish server-backed reads from committed mutations at the session boundary. - [x] Preserve optional boolean schemas without a per-field allowlist. - [x] Add multi-variable define and delete examples. - [x] Report preview freshness and rendered project version. - [x] Investigate WSL cleanup behavior and create follow-up #6019. - [x] Review and update authoritative CLI/MCP documentation. - [x] Verify fixture impact; no fixture inputs or outputs changed. - [x] Run affected tests, typechecks, lint, and generated-file checks. - [ ] Run the complete local agent evaluation suite after explicit approval. ## Verification - [x] Regression tests demonstrated failing before their implementation and passing afterward. - [x] `pnpm --filter @webstudio-is/project-build test` — 82 files, 2,085 tests passed. - [x] `pnpm --filter webstudio test` — 57 files, 939 tests passed. - [x] Project-build and CLI typechecks passed. - [x] `pnpm lint` passed. - [x] `pnpm oxfmt --check` passed. - [x] `pnpm check:generated-api` passed. - [x] `pnpm check:generated-docs` passed. - [ ] `pnpm evaluations` — awaiting explicit approval per repository policy. ## Compatibility and limitations - `committed` remains available on every session result. For reads it is `false` and durability does not apply; use `commitStatus: "not-applicable"`. - Compact CSS-variable records include both exact `value` and `valueLength`. - Structured hex color channels remain normalized `0..1`; CSS color strings such as `"#2d3748"` are the recommended 0–255 representation. - WSL2/9P process cleanup is not changed in this PR and is scoped in #6019. |
||
|
|
8e7a8a21aa |
feat: Report anonymous MCP reliability issues (#6021)
Closes #6020 ## Summary Adds the first end-to-end slice for anonymous, LLM-authored reliability reports from the CLI and MCP. The shared report contract captures the generalized user story, attempted workflow, expectation, actual result, recovery attempts, user impact, technical context, acceptance criteria, and agent runtime (client, provider, model, version, and reasoning effort). Guidance requires removing any user- or project-identifying information before submission. ## Architecture - Adds a project-authenticated `api.reports.issue` tRPC mutation as the reusable product boundary. - Maps that mutation to the public `report-issue` operation for CLI and MCP callers. - Keeps the endpoint directly callable from a future Builder UI through the existing tRPC client. - Publishes through a server-side GitHub App installation, so end users do not need GitHub accounts or tokens. - Discovers the App installation for the fixed Webstudio reporting repository instead of requiring deployment-specific installation or repository configuration. - Searches for a hidden anonymous technical marker before creation to avoid obvious duplicates. ## Todo 1. [x] Define a shared anonymous LLM-authored report contract. 2. [x] Include the user story, attempted workflow, expected and actual behavior, recovery attempts, impact, technical context, and acceptance criteria. 3. [x] Include the LLM client, provider, model, client version when known, and reasoning effort. 4. [x] Attach sanitized CLI, Node.js, operating-system, architecture, execution-mode, and API-contract metadata automatically. 5. [x] Add the Builder-reusable project tRPC mutation. 6. [x] Expose the mutation to CLI and MCP as `report-issue`. 7. [x] Add GitHub App authentication and issue publication. 8. [x] Reduce deployment configuration to the App ID and private key. 9. [x] Add marker-based duplicate detection. 10. [x] Add guidance for explicit user-requested reports and qualifying repeated-friction reports. 11. [x] Review and simplify repeated GitHub request handling and public protocol exports. 12. [ ] Add server-side throttling and harden concurrent duplicate creation. 13. [x] Configure and install the reporting GitHub App in deployed environments. 14. [x] Exercise the deployed endpoint with a controlled test report. 15. [ ] Run the complete agent evaluation suite after explicit approval. 16. [x] Review documentation impact and update the generated MCP documentation. ## Verification - Protocol issue-report contract tests: passed (3) - Builder GitHub reporting tests: passed (4) - Builder API router tests: passed (30) - CLI schema, command-doc, MCP, and project-session tests: passed - Protocol, HTTP client, project-build, CLI, and Builder typechecks: passed - Root lint: passed - Generated API and documentation checks: passed - New and changed regression tests were demonstrated failing against the previous behavior, then passing after implementation - No fixture inputs or outputs are affected - Agent evaluations were not run because they require explicit approval ## Deployment notes The Builder only needs `GITHUB_ISSUE_REPORT_APP_ID` and `GITHUB_ISSUE_REPORT_PRIVATE_KEY`. The server discovers the App installation for `webstudio-is/webstudio` and creates a short-lived installation token. The App needs repository metadata read access and Issues write access. ## Known limitations Duplicate detection currently uses GitHub issue search and can race when identical reports arrive concurrently. The endpoint is project-authenticated, but dedicated server-side throttling remains a follow-up before production rollout. No Builder UI is included yet; the tRPC boundary is intentionally ready for one. |
||
|
|
57d9ad14cd |
fix: Retry published CLI registry lookup (#6013)
## What changed - Retry npm version and integrity resolution inside the CLI registry smoke test. - Keep retry timing injectable so the propagation race is covered by a fast unit test. - Preserve the final npm error when all registry attempts are exhausted. ## Why CLI 0.286.0 was published successfully, but npm briefly exposed integrity metadata while the exact version lookup still returned 404. The post-publish smoke failed and the dependent docs publication job was skipped. The 0.286.0 documentation snapshot has been recovered directly on the `docs` branch. Ref #6007 ## Verification - [x] Regression test demonstrated failing before the implementation and passing afterward - [x] CLI registry/versioning tests: 3 passed - [x] CLI typecheck - [x] Formatting and diff checks - [x] Documentation impact reviewed: no product-doc source change is needed in this PR; the missed 0.286.0 snapshot was published separately to `docs` |
||
|
|
6385e290c6 |
feat: Add syntax highlighting to Code Text (#6007)
Closes #4119 Supersedes #5999 after GitHub closed it during the head-branch rename. ## Approach Code Text uses one optional public highlighting boundary: - `@webstudio-is/sdk-components-react/code-text` → `src/code-text.tsx` The ordinary `components` entry remains Shiki-free. Canvas loading, metadata options, theme variables, and the plain semantic `<code>` component remain private implementation details. **Code** uses the code editor. **Language** and **Theme** use normal bindable selects. Fixed selections generate direct imports for only the per-page language/theme union; plaintext imports no grammar. Bound selections generate Shiki's lazy language/theme registries. SSR and client rendering share the same factory. Missing bound assets suspend the first render while SSR resolves the selected modules. SSG now waits for Suspense before serializing HTML. During hydration the completed server markup stays in place while the browser fetches only the selected language and theme. Later client-side binding changes load only the new selections and keep the same `<code>` node and focus. Highlighted output preserves the semantic root, ref, author classes/styles, whitespace, escaped source, and legacy children/native `lang` behavior. Shiki's implicit tab stop is disabled. A color-only transformer strips theme typography so asynchronous highlighting cannot change text geometry. ## Bundle impact Measured from same-commit production React Router + Cloudflare builds containing one JavaScript / GitHub Light Code Text instance. Sizes are the sum of emitted JavaScript files; gzip is the sum of each file compressed independently. | Worker output | Files | Raw | Sum gzip | | --- | ---: | ---: | ---: | | Fixed selections | 3 | 1,341,851 B | 288,342 B | | Bound selections | 310 | 10,372,112 B | 1,872,273 B | | Increase | +307 | +9,030,261 B (8.61 MiB) | +1,583,931 B (1.51 MiB) | The bound browser build also emits the catalog as lazy chunks: +9,012,594 raw bytes / +1,578,779 sum-gzip bytes across the complete deployed output. Those chunks are not all delivered on page load. The production SSG regression verifies 100+ catalog chunks are emitted while the HTML directly module-preloads only one shared runtime chunk; the browser fetches the runtime-selected language/theme modules on demand. ## Tradeoffs and compatibility - Instances with both highlighting properties unset keep the legacy plain renderer. - Static highlighting still requires both **Language** and **Theme**. - Binding either selection includes that catalog in deploy output because its runtime value is not known at publish time. - The syntax-highlighting property is `language`; legacy native HTML `lang` remains preserved. - Invalid or unavailable runtime selections render as plain code. - Fixed selections retain the smallest publish output; bound selections trade deploy/worker size for runtime flexibility. ## Todo - [x] Restore the specialized Code Text component and semantic plain fallback - [x] Use a code editor for Code and bindable selects for Language and Theme - [x] Persist JavaScript / GitHub Light template defaults - [x] Collapse highlighting to one public `./code-text` entry - [x] Keep canvas loaders and option/theme helpers private - [x] Generate direct imports for fixed selections and omit plaintext grammar - [x] Generate lazy catalogs when Language or Theme is bound - [x] Preserve highlighted SSR markup during hydration without node/focus movement - [x] Support Suspense-aware highlighted SSG output - [x] Preserve escaping, accessibility, legacy children, and native `lang` - [x] Measure fixed versus bound Cloudflare worker output - [x] Deep-review correctness, DRYness, package surface, and obsolete binding infrastructure - [x] Review documentation impact and update Code Text documentation - [x] Run focused tests, typechecks, production builds, formatting, and staged diff review - [ ] Fixture pipeline — blocked during sync because the current API rejects this local CLI version as incompatible; no fixture output changed ## Verification - [x] New/changed regressions were demonstrated failing without their behavior and passing after restoration - [x] SDK Code Text metadata, rendering, hydration, and bundle tests: 17 passed - [x] Component registry tests: 3 passed - [x] CLI asset collection and full prebuild suite: 59 passed - [x] SDK components, component registry, SDK, and CLI typechecks - [x] SDK components declaration and production builds - [x] Component registry production build - [x] Production Vite + Vike prerender emits highlighted bound SSG HTML with one doctype - [x] Dynamic catalog chunks remain outside the SSG page's direct preload set - [x] Documentation reviewed and updated - [x] Formatting and staged diff checks |
||
|
|
1ca01e96a3 |
docs: Guide MCP agents to build dynamic JSON-LD (#5998)
## Summary Clarify how MCP agents should author JSON-LD without serializing dynamic values prematurely. Static structured data remains a validated compact JSON string, while runtime-backed structured data uses an expression that evaluates directly to an object or array. The focused guide now provides machine-readable input recipes for both paths. ## Implementation - [x] Update the focused `components.get` JSON-LD guidance. - [x] Update the JSON-LD `meta.guide` workflow and include `bind-props`. - [x] Add structured `fixedCodeUpdate` and `dynamicCodeBinding` recipes. - [x] Document that expression source is stored as text while its evaluated value must be an object or array. - [x] Warn agents not to call `JSON.stringify` or assemble JSON with string concatenation. - [x] Update CLI use-case documentation and generated docs. - [x] Parse the fixed JSON and dynamic expression AST in regression coverage, including the `post.title` runtime binding. - [x] Demonstrate that the semantic regression test fails when the structured recipe is absent. ## Verification - `pnpm --filter @webstudio-is/project-build test` — 2,066 tests passed - `pnpm --filter @webstudio-is/project-build typecheck` - `pnpm --filter webstudio typecheck` - Focused MCP semantic regression tests - `pnpm oxfmt --check ...` - `pnpm oxlint packages/project-build/src/mcp.ts packages/project-build/src/mcp.test.ts` - `pnpm check:generated-docs` - Fixtures not run: documentation and MCP guidance do not affect fixture inputs or generated fixture bundles. - Agent evaluations not run: explicit approval was not provided. Closes #5997 |
||
|
|
1f4095cf9a |
fix: Improve generated MCP documentation (#5991)
## Summary
- render the generated MCP version as visible body content immediately
below the page heading
- keep the GitBook navigation label stable as `MCP`
- stamp only the CLI version placeholder during release publication,
leaving Markdown content owned by the template
- remove empty `{}` blocks from the rendered MCP argument examples while
preserving meaningful examples and complete structured JSON data
## Root cause
GitBook uses the `SUMMARY.md` link label as the published page heading
and suppresses the Markdown H1 from the document body. The generated
version was therefore present in source but absent from the rendered
page.
The release workflow also coupled version stamping to the complete
rendered Markdown line. It now replaces and verifies only the standard
`0.0.0-webstudio-version` placeholder.
## Verification
- live page structure inspected: published H1 is `MCP`
- MCP manual regression test demonstrated failing before empty argument
blocks were filtered, then passing after the fix
- release placeholder stamping simulated against the generated page
- `pnpm --filter webstudio exec vitest run src/commands/man.test.ts`
- `pnpm --filter @webstudio-is/project-build typecheck`
- `pnpm --filter webstudio typecheck`
- `pnpm check:generated-docs`
- `pnpm lint`
- `pnpm oxfmt --check packages/project-build/src/mcp.ts
packages/cli/src/commands/man.ts packages/cli/src/commands/man.test.ts`
- `git diff --check`
Fixture inputs and outputs are unaffected.
## Todo
- [x] Generate the release version as visible GitBook body content.
- [x] Decouple release stamping from the rendered Markdown content.
- [x] Remove empty MCP argument example blocks.
- [x] Validate generated output and regression coverage.
- [ ] Merge this pull request.
- [ ] Publish the latest released revision to the `docs` branch.
- [ ] Verify the version on the live GitBook page.
Ref #5986
|
||
|
|
e855a1e7cf |
fix: Skip unenumerated dynamic SSG pages (#5982)
## Outcome Restore SSG downloads for projects that contain dynamic pages without enumerable Assets query paths. Static pages continue to export, while unsupported dynamic routes are omitted as they were before Assets-backed SSG prerendering was introduced. Closes #5981 ## Root cause Assets-backed dynamic prerendering changed the SSG framework from skipping every dynamic route to throwing whenever the computed prerender path list was empty. That empty list also represents existing dynamic routes without a configured Assets query, so otherwise valid static downloads began failing during scaffolding. ## Implementation - Return no framework files for dynamic pages whose prerender path list is empty. - Preserve generated Vike routes for Assets-backed pages that enumerate at least one path. - Preserve the existing prebuild validation errors for Assets queries that bind parameters incompletely or cannot enumerate every query branch. - Add an integration regression test covering a static home page alongside `/blog/:slug` with no Assets query. ## Todo - [x] Reproduce the production failure in a regression test - [x] Restore omission of unenumerated dynamic routes - [x] Verify Assets-backed dynamic SSG behavior remains passing - [x] Run focused lint, formatting, typecheck, and integration tests ## Verification - [x] New regression test demonstrated failing before the implementation change and passing afterward - [x] `pnpm --filter webstudio test -- src/prebuild.test.ts` — 49 passed - [x] `pnpm --filter webstudio typecheck` - [x] `pnpm exec oxfmt --check packages/cli/src/framework-vike-ssg.ts packages/cli/src/prebuild.test.ts` - [x] `pnpm exec oxlint --deny-warnings packages/cli/src/framework-vike-ssg.ts packages/cli/src/prebuild.test.ts` - [x] `git diff --check` ## Notes - No fixture inputs or generated fixture outputs are affected. - The agent evaluation suite was not run because repository policy requires separate explicit approval. - Production failure: https://github.com/webstudio-is/webstudio-saas/actions/runs/30769678212/job/91554478283 |
||
|
|
92084aeea3 |
fix: Remove MCP workflow friction (#5974)
## Summary - Make MCP discoverable from the CLI README and expose direct MCP tool calls as restart-free CLI subcommands. - Preserve required discriminator fields in compact MCP SDK schemas and surface the `set-text-content` contract. - Return instance props by default from `inspect-instance` and improve the `list-instances` input hint. - Add a Builder context-menu **Move** submenu as an accessible alternative to drag-and-drop sibling reordering. Companion generated documentation: https://github.com/webstudio-is/webstudio-community/pull/274 ## Technical choices and compatibility - Compact SDK schemas retain required fields only inside root composition branches, avoiding broad schema expansion. - `inspect-instance` now defaults to `props` only; larger styles, bindings, sources, children, and ancestors remain opt-in. - Existing move commands and shortcuts back the new menu, so command behavior stays centralized. - No migrations, fixture inputs, generated fixture bundles, or generated API contracts are affected. ## Todo - [x] Add direct CLI MCP discovery and restart guidance. - [x] Preserve discriminated-union requirements for SDK clients. - [x] Improve instance inspection and input diagnostics. - [x] Add accessible menu-based instance movement. - [x] Add regression coverage and verify fail/pass behavior. - [x] Run targeted tests, typechecks, lint, package-boundary, and generated-doc checks. - [ ] Deferred: run `pnpm evaluations` after separate explicit approval, as required by repository policy. ## Verification - `@webstudio-is/project-build`: 172 targeted tests passed. - `@webstudio-is/protocol`: 8 targeted tests passed; typecheck passed. - `@webstudio-is/builder`: 8 targeted tests passed; typecheck passed. - CLI and project-build typechecks passed. - Root lint, package-boundary check, generated-doc check, and diff checks passed. - New and modified regression tests were demonstrated failing before their fixes and passing afterward. ## Known limitations Synthetic drag-and-drop behavior is unchanged. The new menu and existing keyboard shortcuts provide the automatable and accessible reordering path. Agent evaluations were not run because explicit approval was not provided. |
||
|
|
f335340a54 |
fix: Correct content database sizing and Markdown references (#5972)
## Summary - Report only serialized content-database bytes that are actually included in the published bundle. - Replace the ambiguous `markdown-body` query mode with the strict `markdown-body-ref` mode. - Require every selected Markdown body to have a document-graph node; compilation now fails instead of embedding source bytes as a fallback. - Apply the same Markdown eligibility rule during compilation and runtime query execution, excluding non-Markdown files from reference-only databases and results. - Highlight database sizes in red only when documents were omitted because of the size limit. - Refresh Assets diagnostics after an Assets resource edit is confirmed by the server. - Update CLI/MCP guidance, examples, schemas, generated contracts, and fixtures to use the reference-only mode. ## Root cause Dynamic Markdown-body queries conservatively treated unrelated files, including remote images, as possible hydration candidates. The old mode could also fall back to embedding a Markdown body when graph resolution was unavailable, despite its intended storage-backed behavior. Compilation and runtime selection did not previously share the same content-mode eligibility check. Diagnostics displayed the unbounded pre-limit estimate instead of the serialized bundled size, did not carry the omission reason into query-preview diagnostics, and an early cached preview could leave the merged measurement stale until reload. ## Impact Content database diagnostics and publish warnings now reflect bundled database bytes rather than remote source-file sizes. Saved query filters trigger a post-sync diagnostics refresh. Markdown detail queries must use `content.mode: "markdown-body-ref"`; the old `markdown-body` value is rejected, missing graph support is an explicit compilation error, and non-Markdown assets cannot be selected or counted by a reference-only query. Ref #5966 ## Verification - Content engine: 39 files / 261 tests passed. - Asset uploader: 22 files / 183 tests passed. - SDK: 29 files / 505 tests passed. - Protocol: 9 files / 86 tests passed. - Project build: 82 files / 2,055 tests passed. - CLI: full suite previously passed (57 files / 933 tests); final prebuild verification passed 48 tests. - Focused Builder diagnostics tests: 4 files / 10 tests passed. - Typechecks passed for Builder, content engine, asset uploader, SDK, protocol, project build, and CLI. - Generated API contracts and docs are current. - Fixture build passed and is reproducible after the final review changes. - Formatting, lint, package-boundary checks, and diff checks passed. - New strict-reference, runtime-selection, compilation-selection, and size-highlight regression tests were demonstrated failing without their implementations and passing with them. - Agent evaluations were not run because this follow-up did not receive separate evaluation approval. |
||
|
|
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 |
||
|
|
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`.
|
||
|
|
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. |
||
|
|
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. |
||
|
|
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 |
||
|
|
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 |
||
|
|
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 |
||
|
|
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. |
||
|
|
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 |
||
|
|
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`. |
||
|
|
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. |