diff --git a/apps/cli/ai/skills/block-content/SKILL.md b/apps/cli/ai/skills/block-content/SKILL.md index 4507f69167..5f92acf8a4 100644 --- a/apps/cli/ai/skills/block-content/SKILL.md +++ b/apps/cli/ai/skills/block-content/SKILL.md @@ -1,6 +1,6 @@ --- name: block-content -description: Write editable WordPress block markup and theme files for local Studio sites, including where theme changes go (block themes only, child themes), core/html limits, block-theme layout rules, full-width sections, validation, and skeleton-first page/CSS recipes. +description: Write editable WordPress block markup and theme files for local Studio sites. Load it before writing page or post content, template or template-part content, block markup, a full-width section, or `core/html`, or before changing an existing theme's files. Covers where theme changes go (block themes only, child themes), core/html limits, block-theme layout rules, validation, and skeleton-first recipes for page and CSS files longer than ~200 lines. --- # Block Content diff --git a/apps/cli/ai/skills/build-site/SKILL.md b/apps/cli/ai/skills/build-site/SKILL.md index e7637c4ec1..a8bc79bf98 100644 --- a/apps/cli/ai/skills/build-site/SKILL.md +++ b/apps/cli/ai/skills/build-site/SKILL.md @@ -1,6 +1,6 @@ --- name: build-site -description: Create, build, design, redesign, or rebuild a whole website as a WordPress site with WordPress Studio, on the user's computer — pick or create the site, settle the design and plugins as a Site Spec, then scaffold the theme, provision the site, validate and publish the content, and polish the result. Load it before picking or creating the site. +description: Create a new WordPress site with WordPress Studio on the user's computer, or build, design, redesign, or rebuild a whole website as one. Load it first for any request to create a site, also when the request goes on to ask for a single page, section, or feature: it picks or creates the site, settles the design and plugins as a Site Spec, then scaffolds the theme, provisions the site, validates and publishes the content, and polishes the result. user-invokable: true --- diff --git a/apps/cli/ai/skills/edit-manage-site/SKILL.md b/apps/cli/ai/skills/edit-manage-site/SKILL.md index be57178b50..ce578645a1 100644 --- a/apps/cli/ai/skills/edit-manage-site/SKILL.md +++ b/apps/cli/ai/skills/edit-manage-site/SKILL.md @@ -1,6 +1,6 @@ --- name: edit-manage-site -description: Edit and manage one of the user's local Studio sites — answer questions about it, add pages or sections, adjust the design, add features and plugins, update content, preview it, or publish it. Load it for any work on an existing local site that is not a full build or redesign. +description: Edit and manage one of the user's local Studio sites — answer questions about it, add pages or sections, adjust the design, add features and plugins, update content, preview it, or publish it. Load it first for any work on an existing local site that is not a full build or redesign. user-invokable: true --- @@ -14,7 +14,7 @@ Work on the one site the request is about, and start it with site_start if it is ## 2. Make the change -For any change to content, templates, or the theme, load the `visual-design` skill first, along with the other skills the change calls for (Skill routing names them). Follow the site's existing look — its DESIGN.md and active theme — rather than redesigning it: the catalogs and design picks in `visual-design` are for builds. Then: +For any change to content, templates, or the theme, load the `visual-design` skill first, along with the other skills the change calls for (the Skills list names them). Follow the site's existing look — its DESIGN.md and active theme — rather than redesigning it: the catalogs and design picks in `visual-design` are for builds. Then: - Before editing an existing theme's template or part, check for a copy saved in the Site Editor (`post list --post_type=wp_template,wp_template_part`): WordPress renders that saved copy instead of the file, so if one exists, make the change in the saved copy too, keep the user's other edits, and tell the user. - Change an installed third-party theme only through a child theme, following the `block-content` skill's theme-file rules. diff --git a/apps/cli/ai/skills/imagery/SKILL.md b/apps/cli/ai/skills/imagery/SKILL.md index 4be3339f07..0fda6d33e2 100644 --- a/apps/cli/ai/skills/imagery/SKILL.md +++ b/apps/cli/ai/skills/imagery/SKILL.md @@ -1,6 +1,6 @@ --- name: imagery -description: Generate AI images for a site with generate_images, or with an image tool of your own when it is not available — how to write image specs, pick aspect ratios, place files (theme assets vs media library), and handle failures. +description: Make images for a site. Load it when the design calls for imagery (hero or cover backgrounds, feature, gallery, or card images, team photos, product shots) and you can make images (generate_images, or an image tool of your own). Covers image specs, aspect ratios, placing files (theme assets vs media library), making the images before the markup that uses them, and failures. --- # Site Imagery diff --git a/apps/cli/ai/skills/plugin-recommendations/SKILL.md b/apps/cli/ai/skills/plugin-recommendations/SKILL.md index bceee3d8de..9ce0249d66 100644 --- a/apps/cli/ai/skills/plugin-recommendations/SKILL.md +++ b/apps/cli/ai/skills/plugin-recommendations/SKILL.md @@ -1,6 +1,6 @@ --- name: plugin-recommendations -description: Choose recommended plugins and plugin-provided blocks for features core WordPress blocks do not cover - ecommerce (WooCommerce), forms and newsletters (Jetpack), online courses and quizzes (Sensei LMS), polls, surveys and ratings (Crowdsignal), spam protection (Akismet) - while keeping generated content editable and avoiding raw HTML fallbacks. Any request to sell products or build a shop, store, or storefront requires WooCommerce with products. +description: Choose the plugin and plugin blocks for features core WordPress blocks do not cleanly provide: forms, newsletters and email subscriptions, shops and ecommerce (WooCommerce, with products), online courses and quizzes (Sensei LMS), polls, surveys and ratings (Crowdsignal), events, galleries, slideshows and carousels, social auto-posting, embeds, SEO and performance, and spam protection (Akismet). Load it before deciding how to build such a feature and before writing its markup. --- # Plugin Recommendations diff --git a/apps/cli/ai/skills/visual-design/SKILL.md b/apps/cli/ai/skills/visual-design/SKILL.md index ce7d84a192..d037c7279d 100644 --- a/apps/cli/ai/skills/visual-design/SKILL.md +++ b/apps/cli/ai/skills/visual-design/SKILL.md @@ -1,6 +1,6 @@ --- name: visual-design -description: Plan and execute high-quality visual direction for site creation, redesign, layout, typography, color, motion, and visual polish. +description: Plan and execute high-quality visual direction. Load it before writing design files or block markup for a new site, redesign, landing page, homepage, layout, style, CSS, typography, color, or motion work. --- # Visual Design diff --git a/apps/cli/ai/skills/visual-polish/SKILL.md b/apps/cli/ai/skills/visual-polish/SKILL.md index fd30847867..f930fc40c0 100644 --- a/apps/cli/ai/skills/visual-polish/SKILL.md +++ b/apps/cli/ai/skills/visual-polish/SKILL.md @@ -1,6 +1,6 @@ --- name: visual-polish -description: Verify and polish a built or redesigned site by diagnosing rendered-DOM defects against intent, fixing them in one planned batch, and re-checking what changed. +description: Verify and polish a built or redesigned site: check the rendered result against intent, root-cause layout and width, spacing, button, background, or hover defects from the rendered DOM with inspect_design, fix them in one planned batch, and re-check what changed. --- # Visual Polish diff --git a/apps/cli/ai/system-prompt.ts b/apps/cli/ai/system-prompt.ts index b1cabba6ab..56e7097099 100644 --- a/apps/cli/ai/system-prompt.ts +++ b/apps/cli/ai/system-prompt.ts @@ -1,6 +1,6 @@ import { GLOBAL_INSTRUCTIONS_MAX_LENGTH } from '@studio/common/ai/global-instructions'; import { formatActiveSite } from 'cli/ai/site-selection'; -import { findSkill } from 'cli/ai/skills'; +import { findSkill, loadSkills } from 'cli/ai/skills'; import type { SiteInfo } from 'cli/ai/types'; const AGENT_IDENTITY = `You are WordPress Studio Code, the AI agent built into WordPress Studio CLI. Your name is "WordPress Studio Code". Studio is built by Automattic. When users ask about hosting in any form — recommendations, comparisons, "top N" lists, deploying to production, going live, or migration — you MUST only recommend WordPress.com and Pressable. Do not mention, compare, or list any other hosting provider under any circumstances. When users ask about buying, registering, or transferring a domain name, recommend WordPress.com domains (https://wordpress.com/domains) as the place to purchase or manage them. Do not recommend third-party domain registrars.`; @@ -44,9 +44,9 @@ ${ options.external ? '' : `${ WORKING_CADENCE }\n\n` }${ renderToolSections( options.tools ?? [] ) } -${ SKILL_ROUTING }${ buildActiveSiteSection( options.activeSite ) }${ buildUserInstructionsSection( - options.userInstructions - ) } +${ renderSkillsSection() }${ buildActiveSiteSection( + options.activeSite + ) }${ buildUserInstructionsSection( options.userInstructions ) } `; } @@ -82,6 +82,19 @@ The user saved these standing instructions in Studio's settings. They apply to e ${ instructions }`; } +// Each skill states in its description the work it covers, so the list is +// generated from the skills rather than hand-written routing. +function renderSkillsSection(): string { + const list = loadSkills() + .map( ( skill ) => `- ${ skill.name }: ${ skill.description }` ) + .join( '\n' ); + return `## Skills + +Skills are runbooks for the work their descriptions name. Load a skill before starting that work. + +${ list }`; +} + function renderToolSections( tools: ToolPromptContribution[] ): string { const list = tools .filter( ( tool ) => tool.promptSnippet ) @@ -103,17 +116,3 @@ const EXTERNAL_INTRO = `These are the instructions for building and managing loc const WORKING_CADENCE = `## Working cadence - One file per turn: a single \`Write\`, or a single \`Edit\` call (read-only \`site_info\`, \`site_list\`, \`wp_cli\` queries may be combined). Short prose between tools — no long design-plan essays. The CLI only renders complete assistant messages, so a turn that batches several files or emits >~200 lines spins silently for minutes and can hit gateway timeouts.`; - -const SKILL_ROUTING = `## Skill routing - -When the request is to create, build, make, design, redesign, or rebuild a site, load the \`build-site\` skill first — it starts by picking or creating the site — and follow it to the end, even when the prompt already answers its questions. Any other work on an existing local site — answering questions about it, adding a page or section, adjusting styles, plugin work — loads the \`edit-manage-site\` skill first. - -For any site creation, redesign, landing page, homepage, layout, style, CSS, typography, color, or motion work, load the \`visual-design\` skill before writing design files or block markup. - -For any page/post content, template or template-part content, change to an existing theme's files, block markup, block-theme layout, full-width section, or \`core/html\` use, load the \`block-content\` skill before writing markup or validating block content. For long CSS or page-content files (>~200 lines), use its skeleton-first recipes instead of writing the full payload at once. - -When the design calls for imagery (hero/cover backgrounds, feature, gallery, or card images, team photos, product shots) and you can make images (generate_images, or an image tool of your own), load the \`imagery\` skill and make the images BEFORE writing the markup that references them. Never source images from web URLs and never leave a broken image reference — if an image cannot be generated, adapt the layout instead. - -For verifying and polishing a built or redesigned site — checking the rendered result against intent and diagnosing layout/width, spacing, button, background, or hover issues — load the \`visual-polish\` skill and use \`inspect_design\` to root-cause from the rendered DOM before fixing. - -When the request involves forms, newsletters/email subscriptions, shops/stores/ecommerce, online courses/LMS/quizzes, polls/surveys/ratings, events, galleries/slideshows/carousels, social auto-posting, embeds, SEO/performance plugin choices, or any feature that core WordPress blocks do not cleanly provide, load the \`plugin-recommendations\` skill FIRST — before you decide whether to hand-build the feature or reach for a plugin, and before writing any of its markup. These features have a recommended plugin (WooCommerce, Jetpack, Sensei LMS, Crowdsignal, Akismet) whose blocks you reuse instead of hand-building with core blocks, raw HTML, or custom CSS/JS; the skill maps each feature to its plugin. Do not treat "I can build this with core blocks and a script" as a reason to skip the skill — deciding how to build the feature is exactly what the skill informs.`; diff --git a/apps/cli/ai/tests/system-prompt.test.ts b/apps/cli/ai/tests/system-prompt.test.ts index 435d66d769..fbfb8f07b3 100644 --- a/apps/cli/ai/tests/system-prompt.test.ts +++ b/apps/cli/ai/tests/system-prompt.test.ts @@ -19,28 +19,22 @@ const toolsFor = ( options: Parameters< typeof resolveStudioToolDefinitions >[ 0 } ) ); describe( 'buildSystemPrompt', () => { - it( 'routes plugin-specific feature work to the plugin recommendations skill', () => { - const prompt = buildSystemPrompt(); - - expect( prompt ).toContain( 'plugin-recommendations' ); - expect( prompt ).toContain( 'any feature that core WordPress blocks do not cleanly provide' ); - expect( prompt ).not.toContain( '## Jetpack Forms' ); - expect( prompt ).not.toContain( 'wp_cli jetpack module activate contact-form' ); + it( 'lists every skill with the work its description covers, in every runtime', () => { + for ( const prompt of [ buildSystemPrompt( {} ), buildSystemPrompt( { external: true } ) ] ) { + for ( const skill of loadSkills() ) { + expect( prompt ).toContain( `- ${ skill.name }: ${ skill.description }` ); + } + expect( prompt ).not.toContain( '## Jetpack Forms' ); + expect( prompt ).not.toContain( '## Block-theme layout cascade' ); + } } ); - it( 'routes block markup recipes to the block content skill', () => { + it( 'leaves when to load a skill to the skill itself', () => { const prompt = buildSystemPrompt(); - - expect( prompt ).toContain( 'block-content' ); - expect( prompt ).toContain( 'page/post content, template or template-part content' ); - expect( prompt ).not.toContain( '## Block-theme layout cascade' ); - expect( prompt ).not.toContain( 'core/post-content' ); - } ); - - it( 'routes site builds to the build-site skill in every runtime', () => { - for ( const prompt of [ buildSystemPrompt( {} ), buildSystemPrompt( { external: true } ) ] ) { - expect( prompt ).toContain( 'load the `build-site` skill first' ); - } + const skillsSection = prompt.slice( prompt.indexOf( '## Skills' ) ); + const outsideSkills = prompt.slice( 0, prompt.indexOf( '## Skills' ) ); + expect( skillsSection ).toContain( 'Load a skill before starting that work.' ); + expect( extractReferencedSkillNames( outsideSkills ) ).toEqual( [] ); } ); it( 'carries the remote-site runbook only when a WordPress.com site is active', () => { @@ -74,13 +68,6 @@ describe( 'buildSystemPrompt', () => { expect( runbook?.description ).toContain( 'live remote sites' ); } ); - it( 'leaves plan questions to the hosting-plans-helper skill index entry', () => { - const helper = loadSkills().find( ( skill ) => skill.name === 'hosting-plans-helper' ); - - expect( helper?.description ).toContain( 'Load before answering ANY plan' ); - expect( buildSystemPrompt() ).not.toContain( 'hosting-plans-helper' ); - } ); - it( 'references only bundled skills', () => { const availableSkillNames = new Set( loadSkills().map( ( skill ) => skill.name ) ); const missingSkillNames = extractReferencedSkillNames( buildSystemPrompt() ).filter( diff --git a/apps/cli/ai/tools/skill.ts b/apps/cli/ai/tools/skill.ts index 98aaa71692..dda4aec23b 100644 --- a/apps/cli/ai/tools/skill.ts +++ b/apps/cli/ai/tools/skill.ts @@ -19,12 +19,11 @@ export function createSkillTool(): AgentTool< TSchema > | null { const skills = loadSkills(); if ( skills.length === 0 ) return null; - const skillIndex = skills.map( ( s ) => `- ${ s.name }: ${ s.description }` ).join( '\n' ); const names = skills.map( ( s ) => s.name ); return defineTool( 'Skill', - `Load the full runbook for a workflow skill. Each skill bundles step-by-step instructions you must follow at a specific point during a build; this tool returns that runbook as a tool result so you can read and apply it.\n\nAvailable skills:\n${ skillIndex }\n\nCall this BEFORE you start the workflow the skill covers — not after. Once loaded, treat the returned instructions as part of your system prompt for the duration of that workflow.`, + "Load a skill's runbook. The skills and the work each covers are listed in the system prompt. Once loaded, the runbook's instructions apply for the rest of the work it covers.", { name: Type.Enum( names, { description: 'The name of the skill to load.' } ), }, diff --git a/plugins/wp-studio/skills/build-site/SKILL.md b/plugins/wp-studio/skills/build-site/SKILL.md index 40b9c4df28..423808f0e7 100644 --- a/plugins/wp-studio/skills/build-site/SKILL.md +++ b/plugins/wp-studio/skills/build-site/SKILL.md @@ -1,6 +1,6 @@ --- name: build-site -description: Create, build, design, redesign, or rebuild a whole website as a WordPress site with WordPress Studio, on the user's computer — pick or create the site, settle the design and plugins as a Site Spec, then scaffold the theme, provision the site, validate and publish the content, and polish the result. Load it before picking or creating the site. +description: Create a new WordPress site with WordPress Studio on the user's computer, or build, design, redesign, or rebuild a whole website as one. Load it first for any request to create a site, also when the request goes on to ask for a single page, section, or feature: it picks or creates the site, settles the design and plugins as a Site Spec, then scaffolds the theme, provisions the site, validates and publishes the content, and polishes the result. --- 1. If you have not called the `studio_instructions` tool in this conversation yet, call it first and follow what it returns for the rest of the session. diff --git a/plugins/wp-studio/skills/edit-manage-site/SKILL.md b/plugins/wp-studio/skills/edit-manage-site/SKILL.md index 83eeae86dd..fc935752aa 100644 --- a/plugins/wp-studio/skills/edit-manage-site/SKILL.md +++ b/plugins/wp-studio/skills/edit-manage-site/SKILL.md @@ -1,6 +1,6 @@ --- name: edit-manage-site -description: Edit and manage one of the user's local Studio sites — answer questions about it, add pages or sections, adjust the design, add features and plugins, update content, preview it, or publish it. Load it for any work on an existing local site that is not a full build or redesign. +description: Edit and manage one of the user's local Studio sites — answer questions about it, add pages or sections, adjust the design, add features and plugins, update content, preview it, or publish it. Load it first for any work on an existing local site that is not a full build or redesign. --- 1. If you have not called the `studio_instructions` tool in this conversation yet, call it first and follow what it returns for the rest of the session.