Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions apps/cli/ai/skills/hosting-plans-helper/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
name: hosting-plans-helper
description: Answer WordPress.com plan, pricing, upgrade, and feature-tier questions (plan names, what each tier unlocks — plugins, themes, custom code, SSH, hosting — and current prices) from authoritative live data. Load before answering ANY plan, pricing, or feature-gating question; never answer these from memory.
user-invokable: true
---

# Hosting Plans Helper

Use this skill whenever the user asks about WordPress.com (or Pressable) plans,
pricing, upgrades, or what a plan tier unlocks — for example "which plan do I need
for plugins?", "what does Business include?", "how much is Commerce?", "can I use
custom CSS on Premium?", or "should I upgrade?".

## Hard rule: never answer from memory

Plan names, prices, and feature-tier gating change, and your training data is stale.
You MUST fetch current data with this skill before answering. Do not state a plan
name, a price, or which tier unlocks a feature from memory — even if you are
confident. If the fetch fails, say you can't verify current plan data right now and
point the user to https://wordpress.com/pricing; do not guess.

## Step 1: Fetch plan names and features

Fetch `wpcom/v2/plans/features`. It returns, per plan, the current `name`, the
`product_slug` (used to look up the price in Step 2), and the full list of `features`
that tier unlocks — grouped (Essential features, Performance boosters, High
Availability, Developer tools, Security, etc.).

**Local sites (Bash tool available):**

```text
curl -s "https://public-api.wordpress.com/wpcom/v2/plans/features?locale=en"
```

**Connected WordPress.com sites (wpcom_request tool available, no Bash):**

```text
wpcom_request method=GET path="!/plans/features" apiNamespace="wpcom/v2"
```

## Step 2: Fetch current prices

Fetch `wpcom/v2/products` for prices. It is keyed by product slug; each product has a
`cost_display` (the formatted, **already-localized** price, e.g. `"$300"`) and a
`currency_code`.

**Local sites:**

```text
curl -s "https://public-api.wordpress.com/wpcom/v2/products"
```

**Connected WordPress.com sites:**

```text
wpcom_request method=GET path="!/products" apiNamespace="wpcom/v2"
```

Both endpoints are public (no authentication) and both are reachable in either
environment.

## Step 3: Answer from the fetched data only

- Use the exact plan **names** from Step 1 — do not rename or substitute legacy
names.
- For a plan's **price**, look up `products[ plan.product_slug ].cost_display` and
quote it as-is (it is already localized; mention the currency). The free plan has
no price.
- To answer "does plan X include feature Y?" or "what do I need for Y?", check the
per-plan `features` list from Step 1. Each feature has a `title`, a `tooltip` (use
it to explain), and a `group`. Recommend the lowest tier whose `features` includes
what the user needs.
- When recommending an upgrade, name the specific tier and the concrete features it
unlocks for the user's stated goal.

### Phrasing

Answer directly and authoritatively, as plain product knowledge. Do not mention that
you fetched anything, or reference "the live data", "the data I fetched", "according
to the API", or any source or tool. The fetched data is simply the truth — state it.

- Yes: "Plugins are supported on the Personal plan and above."
- No: "Based on the live data I just fetched, plugins are supported on Personal and
above."

## Scope

Currently covers the WordPress.com consumer plans (Free, Personal, Premium,
Business, Commerce). If the user asks about a plan or product not in the response
(e.g. Pressable, Woo Hosted, VIP, enterprise), say it's not covered by this data and
point them to https://wordpress.com/pricing rather than answering from memory.
4 changes: 4 additions & 0 deletions apps/cli/ai/system-prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ function buildRemoteIntro( site: RemoteSiteContext ): string {
IMPORTANT: The active site is a remote WordPress.com site: "${ site.name }" (ID: ${ site.id }) at ${ site.url }.
IMPORTANT: You MUST use the wpcom_request tool to manage this site. Do NOT use WP-CLI, Bash, or local site file operations — this site is hosted on WordPress.com and cannot be modified through the local filesystem. You may use local Read/Write/Edit/Ls for temporary working files within Studio app data; those files do not affect the remote site until passed to wpcom_request.
IMPORTANT: Before doing ANY work, you MUST first check the site's plan by calling \`GET /\` (apiNamespace: \`""\`). The \`plan.product_slug\` field indicates the plan. If the site is on a free plan (e.g. \`free_plan\`), you MUST refuse design customization requests — this includes custom CSS, inline styles, style attributes on blocks, global styles editing, custom JavaScript, animations, custom colors/fonts/layouts, and plugin management. Do NOT attempt workarounds like inline styles or style block attributes — these produce invalid blocks on WordPress.com. Instead, tell the user that design customizations require upgrading to a paid WordPress.com plan and STOP. Do not proceed with the design task.
IMPORTANT: ${ PLAN_DATA_GUARDRAIL }

## Available Tools

Expand Down Expand Up @@ -95,6 +96,7 @@ ${ getStudioWidgetPromptManifest() }`
return `${ AGENT_IDENTITY } You manage and modify local WordPress sites using your Studio tools and generate content for these sites.

IMPORTANT: You MUST use your Studio tools to manage WordPress sites. Never create, start, or stop sites using Bash commands, shell scripts, or manual file operations. Never run \`wp\` commands via Bash — always use the wp_cli tool instead. The Studio tools handle all server management, database setup, and WordPress provisioning automatically.
IMPORTANT: ${ PLAN_DATA_GUARDRAIL }
IMPORTANT: For any generated content for the site, these three principles are mandatory:

- Gorgeous design: Load the \`visual-design\` skill for site creation, redesign, layout, style, CSS, typography, color, or motion work. To verify and polish the rendered result, load the \`visual-polish\` skill.
Expand Down Expand Up @@ -233,6 +235,8 @@ const REMOTE_DESIGN_GUIDELINES = `## Design capabilities by plan
- Custom CSS, global styles, plugin management, and advanced customization become available.
- Check the specific plan to determine exact capabilities.`;

const PLAN_DATA_GUARDRAIL = `For ANY question about WordPress.com or Pressable plans, pricing, upgrades, or what a plan tier includes (plugins, themes, custom code, SSH, hosting, storage, etc.), you MUST load the \`hosting-plans-helper\` skill and answer only from the data it fetches. Do NOT answer from memory: your training knowledge of plan names, prices, and feature-tier gating is stale and frequently wrong. In particular, do not claim a tier lacks a feature (e.g. that Personal or Premium cannot install plugins) based on memory — check the fetched per-tier feature list, which is the only source of truth. If you cannot fetch the data, say you cannot verify current plan details and point the user to https://wordpress.com/pricing; never guess.`;

const LOCAL_SKILL_ROUTING = `## Skill routing

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.
Expand Down
16 changes: 16 additions & 0 deletions apps/cli/ai/tests/system-prompt.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,22 @@ describe( 'buildSystemPrompt', () => {
expect( prompt ).not.toContain( '## Common wp/v2 Endpoints' );
} );

it( 'guards plan/pricing/feature answers behind the hosting-plans-helper skill (local)', () => {
const prompt = buildSystemPrompt( { chatArtifactsEnabled: true } );

expect( prompt ).toContain( '`hosting-plans-helper` skill' );
expect( prompt ).toContain( 'Do NOT answer from memory' );
expect( prompt ).toContain( 'Personal or Premium cannot install plugins' );
} );

it( 'guards plan/pricing/feature answers behind the hosting-plans-helper skill (remote)', () => {
const prompt = buildSystemPrompt( { remoteSite } );

expect( prompt ).toContain( '`hosting-plans-helper` skill' );
expect( prompt ).toContain( 'Do NOT answer from memory' );
expect( prompt ).toContain( 'Personal or Premium cannot install plugins' );
} );

it( 'references only bundled skills', () => {
const prompts = [
buildSystemPrompt( { chatArtifactsEnabled: true } ),
Expand Down
Loading