feat(cli): WordPress site generator for Studio Code (theme + companion plugin)#3666
feat(cli): WordPress site generator for Studio Code (theme + companion plugin)#3666draganescu wants to merge 19 commits into
Conversation
…tion for studio ai Adds an end-to-end WordPress site generator to the `studio ai`/`studio code` agent: generation tools plus knowledge/runbook skills that produce a pure-presentation block theme and a companion plugin (CPTs, REST routes, build-less plain-JS blocks), seed content into the live DB, and fill AI imagery. Tools (registered in tools/index.ts): generate_design_previews, generate_theme (parallel per-file generation), generate_companion_plugin, seed_content, generate_image. Orchestrated by the `site-generator` skill (/site-generator slash command) alongside theme-architecture, companion-plugin, layout-patterns, wp-best-practices, and data-persistence knowledge skills + bundled generator prompt fragments adapted from Telex. Generation core (apps/cli/ai/generation/): non-streaming parallel Anthropic client reusing the wpcom provider env, transient-error retry/backoff, robust JSON extraction, manifest schema, AI_IMAGE handling, path/WP-CLI helpers. Key correctness fixes from live testing: - seed_content writes large post content to a host file the WP filesystem reads (wp post create/update <file>) instead of a giant --post_content arg that the daemon IPC bus truncates (25KB -> 16 bytes). - CPT entries generated with their meta fields from the companion plugin's post types, so collections actually populate. - AI images use the authorized OpenAI images route (gpt-image-1 under the studio-assistant feature slug); Telex's Imagen slug is 403 for Studio accounts. Placeholders are stripped when not logged into WordPress.com. Adds unit tests (apps/cli/ai/tests/wsg-generation.test.ts, 22 passing). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
This for now is a one size exploration which tries to settle the best shape of porting some of the Telex learnings on site generation into agent friendly skills and tools. Images don't generate because of the auth system on WPCOM for certain ai proxies which is not tied to user auth. The agent using the orchestrator command is still significantly slower than the Telex PHP orchestrator. Finally, an area this exploration shed light on is that we need to have a wp build system bundled somehow so we don't npm install for every theme fresh. Right now the draft instructs generation as vanilla JS for blocks to avoid building. |
|
Thanks for starting this, excited for some consolidation to happen. a few questions:
Reading your comment, it seems you're considering this as a PoC for the whole flow. I wonder how possible would it be to ship the corrections and each step separately as iterations. Maybe you're already considering this? |
|
Yes I am considering this a PoC and I'll push it as far as it gets until I get a site that just works from a prompt. Then we figure out details. Because once we have a working path we can architect it into pieces. That is non standard, I know, but these skills are very finicky to test standalone. Ideally, studio code will get what Telex didn't - an eval system - so we can confidently tweak these. To your questions:
|
|
Most sites I think don't need a plugin (like mine) and would prefer just having core blocks. I think we can discuss these details later, but I'd prefer that we don't optimize for plugin heavy outputs. |
…ce A) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…idate (slice D) Pins custom post type, block, and REST identifiers to a single canonical themePrefix derived from the manifest, then reconciles generated markup to it and validates no reference resolves to nothing registered. Fixes custom blocks that did not render and Query Loops pointed at non-existent post types. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e B) Image generation in resolveAiImagesInHtml was fully serial; it now runs through a bounded pool (injectable generator for testing), cutting the seed stage ~83s on the restaurant case with no rate-limit failures. Generation runPooled caps raised 4/5/3 -> 8 (theme files, plugin blocks, seed pages, CPT entries); these help only phases with many similar-duration calls — per-phase wall-clock is still gated by the single longest call (style.css, main plugin PHP), so the larger win remains a single-pool merge (slice G). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Custom blocks are now authored as JSX/React under blocks/<slug>/src/ (editor imports @wordpress/*; front-end view.js stays plain DOM) and compiled in-process to build/ via esbuild — WordPress packages externalised to their wp.* runtime globals with a generated index.asset.php, the same output shape as @wordpress/scripts but no npm install, no webpack, no subprocess. The plugin registers from build/. Verified end-to-end: a generated reservation-form block compiles and renders on the live site. Reverses the prior build-less plain-JS mandate so Studio's developer-centric users get real React blocks. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ice C) Replaces the per-item seed loop (post list + create/update + a call per meta key + option writes — tens of serial WP-CLI round-trips through the PHP-WASM daemon) with ONE wp eval-file pass: a fixed PHP seeder reads a generated _seed-manifest.json plus each item's content file and upserts every post/page/CPT entry, sets meta, and the static front page in a single WP load (Telex's content-loader pattern). Verified: content inserts, the menu CPT query populates, the reservation block renders, the front page is set; the seed stage's DB-write tax is eliminated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s (slice D follow-up) The harness validated content references against the manifest but not whether the companion plugin's PHP actually registers those post types — a register_post_type drift would orphan seeded entries while every content reference stayed canonical. findRegisteredPostTypes extracts the plugin's literal register_post_type keys (multi-line tolerant); the harness now reports cptUnreg for any manifest CPT the PHP does not register. Verified against real generated output. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…n (slice G) Adds generate_site: theme + companion plugin + page/block/CPT content generation run as ONE parallel pool (orchestrate.ts), then a strict deferred-write sequence (theme write+activate -> plugin write+compile+activate -> single-pass seed). The two long-pole calls (style.css ~14k, main plugin PHP ~12k) now overlap the cheap fan-out instead of gating three serial phases. On restaurant-reservations the generation phase drops from ~280-300s (theme+plugin+seed) to a single 91s stage; total run ~430s -> 229s. Correctness unchanged: idViolations 0, cptUnreg 0, the JSX block compiles + renders, the menu CPT populates, the front page is set. The three legacy tools are unchanged except for export additions and remain available for manual/granular use; SKILL.md collapses steps 4-6 to one. The eval harness gains a --merged mode. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…g when plugin fails Adversarial review of the merged orchestration found two failure-path defects the happy run did not exercise: - Theme tasks (theme.json/style.css/parts/templates) were unguarded, so one runGenerator throw rejected the whole pool and discarded the already-generated plugin + content. Each theme file is now guarded and routed to generationFailed; theme activation is gated on style.css actually being produced. - A failed main plugin PHP still seeded CPT entries under a post type the unwritten plugin never registered (orphaned rows). CPT items are now dropped from seeding when the plugin failed, with an explicit summary instead of a misleading one. Happy path unchanged (the guards/filters are identity on success). Adds unit coverage for theme-failure routing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nto feat/wordpress-site-generator
… recursion, dangling taxonomy, and remote fonts Four real bugs surfaced by a studio code generation, fixed the way Telex avoids them — a deterministic guard plus an aligned generator prompt for each: - CPT archive/page routing collision: sanitizeCptArchiveSlugs() rewrites any has_archive/rewrite slug equal to a page slug so the archive stays at the theme-prefixed base and the page keeps its URL. - Archive-loop recursion (runaway-height pages): port Telex's no-post-content-in-loop / finite-perPage / no-nested-query rules into template.md; add findArchiveLoopViolations() linter. - Unregistered-taxonomy empty query: reconcileMarkup strips an unknown taxQuery so the loop falls back to postType-only (non-empty); validateMarkup flags unknown_taxonomy_reference; prompts steer facets to post_meta. - Remote/file fonts in theme.json: stripRemoteFontFaces() plus token-only fontFamily system stacks in theme-json.md; aligned the contradicting font docs. Eval harness gains four scorecard checks so each class regresses loudly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…generator # Conflicts: # apps/cli/ai/skills.ts # apps/cli/ai/system-prompt.ts
Site generation skills and toolsThis branch intentionally keeps the site-generation surface inside Full generation flowflowchart TD
A["User asks for a complete site"] --> B["Pi runtime starts Studio agent turn"]
B --> C["Skill tool loads site-generator"]
C --> D["site-spec resolves missing site details"]
D --> E{"Use existing site"}
E -->|"Yes"| F["site_info or list_sites"]
E -->|"No"| G["create_site"]
F --> H["start_site if needed"]
G --> H
H --> I["visual-design plus theme-architecture build spec"]
I --> J["generate_design_previews"]
J --> K{"User choice"}
K -->|"Choose direction"| L["generate_site"]
K -->|"Regenerate"| J
K -->|"Stop"| Z["No site changes"]
L --> M{"Review before apply"}
M -->|"Yes"| N["guided mode apply false"]
N --> O["Return manifest warnings STAGED_RUN_ID"]
O --> P{"User approves"}
P -->|"No"| I
P -->|"Yes"| Q["generate_site stagedRunId apply true"]
M -->|"No"| R["one-shot mode"]
R --> S["Plan generate validate apply"]
Q --> S
S --> T["generate_image if needed"]
T --> U["validate_and_fix_blocks"]
U --> V["take_screenshot"]
V --> W{"Rendered issues"}
W -->|"Yes"| X["visual-polish inspect_design Edit or wp_cli"]
X --> U
W -->|"No"| Y["Optional audits preview export sync"]
Skills
Registered Studio tools
Runtime tools also involved
Internal modules behind
|
| Module | Responsibility |
|---|---|
orchestrate.ts |
SiteGenerationEngine phases, guided staging, one-shot apply, summaries. |
manifest.ts |
Manifest schema and normalization. |
generators.ts |
Prompt loading and model calls for theme/plugin/content artifacts. |
llm.ts |
Pooled non-streaming generation client, retries, cancellation/progress support. |
identifier-contract.ts |
Canonical block/CPT/REST identifiers and reconciliation. |
build-block.ts |
Custom block build compilation helpers. |
images.ts |
AI_IMAGE placeholder resolution in HTML. |
wpcom-image.ts |
Image generation proxy integration. |
paths.ts |
Slug derivation and path containment helpers. |
seed-php.ts |
Seeder PHP builder and result parser. |
site-wp.ts |
Site daemon and WP CLI helpers. |
theme-guards.ts |
Theme safety checks such as remote font and archive-loop guards. |
User-choice skip points
- Existing site selected: skip
site-specdetail gathering andcreate_site. - User chooses "regenerate" at design review: repeat
generate_design_previews, skip generation for that preview. - User chooses "stop" at design review: no site files or DB changes.
- User asks for review before applying: use
generate_siteguided mode and skip apply until approval. - User rejects guided result: keep staged artifacts but do not apply; revise spec/design and regenerate.
- User approves guided result: apply exact staged artifacts with
stagedRunId; skip regeneration. - User asks for one-shot or does not need review: skip guided staging and apply immediately.
- User disables imagery or is not logged in: skip image generation and strip/defer placeholders.
- Screenshots look good: skip
inspect_designand manual repair. - User does not need sharing, audits, remote sync, import/export, annotations, SEO, or performance checks: skip those optional tools.
Related issues
How AI was used in this PR
This is an AI-assisted proof of concept for a larger Studio Code capability. AI helped generate the initial implementation, iterate on the generation pipeline, add focused tests, and resolve the latest
origin/trunkmerge conflicts. The current branch state has been reviewed locally enough for draft review, but this should still be treated as directional work rather than merge-ready production code.Proposed Changes
What
Adds a WordPress site generator flow to Studio Code so a user can describe a site and have Studio produce a working local WordPress site from that brief. The flow can plan design directions, generate a block theme, add a companion plugin for behavior and custom data, seed pages and content, generate imagery, and validate the result.
Why
The goal is to make Studio more useful for first-draft site creation. Instead of asking the agent to hand-edit one file at a time, this gives it a purpose-built path for creating a coherent starting point that still follows WordPress conventions: editable block content, a presentation-focused theme, and behavior that survives a theme switch.
How
The branch adds a
site-generatorskill, generation helpers, agent tools, tests, and an eval harness around the workflow. The generated site is split into a block theme plus a companion plugin, with identifiers and manifest checks to keep generated templates, blocks, custom post types, taxonomies, and seeded content aligned.The current state also includes fixes from live iteration:
This PR is current with
origin/trunkas ofeb7ce03dvia merge commit11a08945.Testing Instructions
Verification already run on the updated branch:
./node_modules/.bin/eslint --fix apps/cli/ai/skills.ts apps/cli/ai/system-prompt.tscorepack npm run typecheck --workspace wp-studio./node_modules/.bin/tsc -p scripts/tsconfig.json --noEmit./node_modules/.bin/vitest run apps/cli/ai/tests/system-prompt.test.ts apps/cli/ai/tests/skill-prompts-contract.test.tsSuggested reviewer flow from a complete dependency install:
Then authenticate with WordPress.com if needed and exercise the
/site-generatorflow against a throwaway local site.Note: a full all-workspaces typecheck was attempted from the new worktree, but that worktree did not have its own dependency install. The CLI workspace typecheck and the root scripts TypeScript check passed.
Pre-merge Checklist