claude-plugin-wordpress-manager 2.12.2 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/.claude-plugin/plugin.json +8 -3
  2. package/CHANGELOG.md +55 -0
  3. package/docs/GUIDE.md +240 -1
  4. package/docs/VALIDATION.md +341 -0
  5. package/docs/plans/2026-03-02-content-framework-architecture.md +612 -0
  6. package/docs/plans/2026-03-02-content-framework-strategic-reflections.md +228 -0
  7. package/docs/plans/2026-03-02-content-intelligence-phase2.md +560 -0
  8. package/docs/plans/2026-03-02-content-pipeline-phase1.md +456 -0
  9. package/docs/plans/2026-03-02-editorial-calendar-phase3.md +490 -0
  10. package/docs/validation/.gitkeep +0 -0
  11. package/docs/validation/dashboard.html +286 -0
  12. package/docs/validation/results.json +1705 -0
  13. package/package.json +12 -3
  14. package/scripts/run-validation.mjs +1132 -0
  15. package/servers/wp-rest-bridge/build/server.js +16 -5
  16. package/servers/wp-rest-bridge/build/tools/index.js +0 -9
  17. package/servers/wp-rest-bridge/build/tools/plugin-repository.js +23 -31
  18. package/servers/wp-rest-bridge/build/tools/schema.js +10 -2
  19. package/servers/wp-rest-bridge/build/tools/unified-content.js +10 -2
  20. package/servers/wp-rest-bridge/build/wordpress.d.ts +0 -3
  21. package/servers/wp-rest-bridge/build/wordpress.js +16 -98
  22. package/servers/wp-rest-bridge/package.json +1 -0
  23. package/skills/wp-analytics/SKILL.md +153 -0
  24. package/skills/wp-analytics/references/signals-feed-schema.md +417 -0
  25. package/skills/wp-content-pipeline/SKILL.md +461 -0
  26. package/skills/wp-content-pipeline/references/content-brief-schema.md +377 -0
  27. package/skills/wp-content-pipeline/references/site-config-schema.md +431 -0
  28. package/skills/wp-editorial-planner/SKILL.md +262 -0
  29. package/skills/wp-editorial-planner/references/editorial-schema.md +268 -0
@@ -0,0 +1,417 @@
1
+ # Signals Feed Schema
2
+
3
+ **Version**: 1.0.0
4
+ **Phase**: Content Intelligence (Phase 2)
5
+ **Location**: `.content-state/signals-feed.md`
6
+
7
+ ## Overview
8
+
9
+ The `signals-feed.md` file bridges wp-analytics output and GenSignal input. It translates WordPress metrics collected by GA4, Plausible, GSC, and Core Web Vitals tools into the NormalizedEvent format, enabling GenSignal's pattern detection and scoring pipelines to operate on WordPress analytics data without custom adapters. Each feed is a point-in-time snapshot covering a defined measurement period with optional period-over-period delta calculations.
10
+
11
+ ## Frontmatter Fields
12
+
13
+ The file uses YAML frontmatter to declare feed metadata.
14
+
15
+ | Field | Type | Required | Default | Description |
16
+ |-------|------|----------|---------|-------------|
17
+ | `feed_id` | string | Yes | -- | Unique identifier. Format: `FEED-{site_id}-YYYY-MM` |
18
+ | `site_id` | string | Yes | -- | Must match a `.content-state/{site_id}.config.md` |
19
+ | `generated` | ISO 8601 | Yes | -- | Timestamp auto-set at generation time |
20
+ | `period` | string | Yes | -- | Measurement window. Format: `YYYY-MM-DD..YYYY-MM-DD` |
21
+ | `comparison_period` | string | No | -- | Baseline window. Auto-calculated: same duration offset backward |
22
+ | `source_tools` | string[] | Yes | -- | List of MCP tools that contributed data to this feed |
23
+ | `anomaly_threshold` | number | No | 30 | Percentage delta that qualifies an event as an anomaly |
24
+ | `status` | enum | No | generated | One of: `generated`, `reviewed`, `actioned` |
25
+
26
+ ### Field Notes
27
+
28
+ - `feed_id` is deterministic: regenerating the feed for the same site and month produces the same ID
29
+ - `site_id` is validated against existing `.content-state/{site_id}.config.md` files
30
+ - `comparison_period` is omitted when no historical data exists (first run)
31
+ - `source_tools` lists only tools that returned data, not all tools attempted
32
+
33
+ ## NormalizedEvent Format
34
+
35
+ Each event in the feed body represents a single metric observation for an entity during the measurement period.
36
+
37
+ ### Fields
38
+
39
+ | Field | Type | Required | Description |
40
+ |-------|------|----------|-------------|
41
+ | `entity_id` | string | Yes | Format: `{EntityType}:{identifier}` |
42
+ | `relation` | string | Yes | The metric being measured |
43
+ | `value` | number | Yes | Metric value for the current period |
44
+ | `unit` | string | Yes | One of: `count`, `seconds`, `percentage`, `position` |
45
+ | `ts` | ISO 8601 | Yes | End of measurement period |
46
+ | `delta_pct` | integer | No | % change vs comparison period. Positive = increase. Omitted if no baseline. Note: in YAML `+47` and `47` are equivalent integers; the `+` prefix is a display convention only |
47
+ | `provenance` | object | Yes | Data origin metadata |
48
+
49
+ ### Entity Types
50
+
51
+ The `entity_id` field uses a typed prefix to identify the entity:
52
+
53
+ | Prefix | Format | Example |
54
+ |--------|--------|---------|
55
+ | `Page:` | `Page:{url_path}` | `Page:/cactus-water-benefici` |
56
+ | `Keyword:` | `Keyword:{search_term}` | `Keyword:acqua di cactus` |
57
+ | `Source:` | `Source:{source_name}` | `Source:linkedin` |
58
+ | `Site:` | `Site:{site_id}` | `Site:opencactus` |
59
+
60
+ ### Valid Relations by Entity Type
61
+
62
+ **Page**
63
+
64
+ | Relation | Unit | Description |
65
+ |----------|------|-------------|
66
+ | `pageviews` | count | Total page views in the period |
67
+ | `sessions` | count | Sessions that included this page |
68
+ | `avg_engagement_time` | seconds | Mean engaged time on the page |
69
+ | `bounce_rate` | percentage | Non-engaged session rate |
70
+ | `conversions` | count | Conversion events on this page |
71
+
72
+ **Keyword**
73
+
74
+ | Relation | Unit | Description |
75
+ |----------|------|-------------|
76
+ | `search_impressions` | count | Times the page appeared in search results |
77
+ | `search_clicks` | count | Clicks from search results |
78
+ | `search_ctr` | percentage | Click-through rate from search |
79
+ | `search_position` | position | Average ranking position |
80
+
81
+ **Source**
82
+
83
+ | Relation | Unit | Description |
84
+ |----------|------|-------------|
85
+ | `referral_sessions` | count | Sessions from this traffic source |
86
+ | `referral_conversions` | count | Conversions from this traffic source |
87
+ | `referral_bounce_rate` | percentage | Bounce rate for sessions from this source |
88
+
89
+ **Site**
90
+
91
+ | Relation | Unit | Description |
92
+ |----------|------|-------------|
93
+ | `total_sessions` | count | Total sessions across all pages |
94
+ | `total_pageviews` | count | Total page views across all pages |
95
+ | `total_conversions` | count | Total conversions site-wide |
96
+ | `lcp` | seconds | Largest Contentful Paint (Core Web Vital) |
97
+ | `cls` | count | Cumulative Layout Shift (Core Web Vital, unitless score). `count` is used as catch-all for unitless numeric values when no more specific unit applies |
98
+ | `inp` | seconds | Interaction to Next Paint (Core Web Vital) |
99
+ | `fcp` | seconds | First Contentful Paint |
100
+ | `ttfb` | seconds | Time to First Byte |
101
+
102
+ > All CWV time-based metrics are normalized to **seconds** for consistency with other time metrics. API values in milliseconds should be divided by 1000.
103
+
104
+ ### Provenance Object
105
+
106
+ | Field | Type | Required | Description |
107
+ |-------|------|----------|-------------|
108
+ | `source_id` | string | Yes | MCP tool name that produced this data point (e.g., `ga4_top_pages`) |
109
+ | `site` | string | Yes | The `site_id` this data belongs to |
110
+
111
+ ### GenSignal Compatibility
112
+
113
+ The NormalizedEvent format maps 1:1 to GenSignal's Harvest stage input:
114
+
115
+ - The `entity_id` format uses GenSignal's `{Type}:{identifier}` convention, so events can be ingested without transformation
116
+ - The `provenance` block enables GenSignal's `quality.corroboration` scoring by tracking which tool produced each data point
117
+ - Multiple events for the same entity from different tools strengthen corroboration scores
118
+ - The `delta_pct` field provides pre-computed trend data that GenSignal's Detect stage can use directly
119
+
120
+ ## Body Structure
121
+
122
+ The Markdown body after frontmatter contains YAML code blocks organized by signal category.
123
+
124
+ ### Section Layout
125
+
126
+ ```
127
+ # Normalized Events
128
+
129
+ ## Traffic Signals
130
+ (Page-level metrics from GA4/Plausible)
131
+
132
+ ## Search Signals
133
+ (Keyword-level metrics from GSC)
134
+
135
+ ## Source Signals
136
+ (Traffic source metrics from GA4)
137
+
138
+ ## Performance Signals
139
+ (CWV metrics from CrUX/PageSpeed)
140
+
141
+ # Anomalies & Patterns
142
+ (Markdown table of detected anomalies)
143
+ ```
144
+
145
+ ### Traffic Signals
146
+
147
+ Contains `Page:` entity events sourced from `ga4_top_pages`, `ga4_report`, or `pl_aggregate`. Each event is a YAML object in a fenced code block.
148
+
149
+ ### Search Signals
150
+
151
+ Contains `Keyword:` entity events sourced from `gsc_search_analytics`. Captures search visibility and click behavior.
152
+
153
+ ### Source Signals
154
+
155
+ Contains `Source:` entity events sourced from `ga4_traffic_sources`. Tracks referral performance by channel.
156
+
157
+ ### Performance Signals
158
+
159
+ Contains `Site:` entity events sourced from `cwv_crux_origin` (site-level) or `cwv_pagespeed` (URL-level). Captures Core Web Vitals and loading metrics.
160
+
161
+ ### Anomalies & Patterns
162
+
163
+ A Markdown table listing all events where `|delta_pct| >= anomaly_threshold`. Only events that exceed the threshold appear here.
164
+
165
+ | Column | Description |
166
+ |--------|-------------|
167
+ | Entity | The `entity_id` of the anomalous event |
168
+ | Metric | The `relation` that triggered the anomaly |
169
+ | Delta | The `delta_pct` value with sign (e.g., `+120%`) |
170
+ | Pattern Match | Name of the matched GenSignal pattern, or "Unclassified anomaly" |
171
+ | Action | Recommended action template |
172
+
173
+ ## Delta Calculation Rules
174
+
175
+ Period-over-period deltas compare the current `period` to the `comparison_period`.
176
+
177
+ ### Formula
178
+
179
+ ```
180
+ delta_pct = round(((current - previous) / previous) * 100)
181
+ ```
182
+
183
+ ### Edge Cases
184
+
185
+ | Scenario | Result |
186
+ |----------|--------|
187
+ | `previous = 0` and `current > 0` | `delta_pct = +999` |
188
+ | `previous = 0` and `current = 0` | `delta_pct = 0` |
189
+ | No previous data available | Omit `delta_pct` entirely |
190
+ | Normal calculation | Round to nearest integer |
191
+
192
+ ### Notes
193
+
194
+ - Values are always integers (no decimal places)
195
+ - Positive values indicate an increase, negative values a decrease
196
+ - The `comparison_period` frontmatter field records which period was used as baseline
197
+ - When `comparison_period` is omitted, no event will have a `delta_pct` field
198
+
199
+ ## GenSignal Pattern Matching
200
+
201
+ Three patterns are detectable from WordPress analytics data alone. The wp-analytics Step 7 evaluates each anomaly against these patterns before writing the Anomalies & Patterns table.
202
+
203
+ ### 1. Search Intent Shift
204
+
205
+ Users are clicking more on existing rankings, indicating growing search intent for the topic.
206
+
207
+ **Detection**: GSC shows `search_ctr` increasing while `search_position` remains stable -- users are clicking more on existing rankings without position changes.
208
+
209
+ **Trigger conditions** (any):
210
+ - `search_ctr` delta >= +20% sustained over the measurement period
211
+ - `search_impressions` delta >= +50% on keywords containing commercial modifiers (e.g., "comprare", "prezzo", "migliore", "acquistare") -- commercial modifiers are a strong signal qualifier
212
+ - `search_impressions` delta >= +100% on any keyword, regardless of modifiers
213
+
214
+ **Data sources**: `gsc_search_analytics`
215
+
216
+ **Action template**: `"Investigate: content cluster opportunity"`
217
+
218
+ ### 2. Early-Adopter Surge
219
+
220
+ A single traffic source is growing disproportionately compared to overall site traffic, signaling an emerging audience channel.
221
+
222
+ **Detection**: Single traffic source shows disproportionate growth vs other sources.
223
+
224
+ **Trigger conditions**:
225
+ - A single `Source:*` entity has `referral_sessions` delta >= +50%
226
+ - AND site-level `total_sessions` delta < +20%
227
+
228
+ **Data sources**: `ga4_traffic_sources`
229
+
230
+ **Action template**: `"Scale: increase posting frequency on {source}"`
231
+
232
+ ### 3. Hype-to-Utility Crossover
233
+
234
+ Engagement metrics improve while raw pageviews plateau, indicating a shift from curiosity-driven to utility-driven traffic.
235
+
236
+ **Detection**: Engagement improving while raw pageviews plateau -- shift from curiosity to utility traffic.
237
+
238
+ **Trigger conditions** (all must be true):
239
+ - `avg_engagement_time` delta >= +15%
240
+ - `bounce_rate` delta <= -10%
241
+ - `pageviews` delta between -20% and +10%
242
+
243
+ **Data sources**: `ga4_top_pages`, `ga4_report`
244
+
245
+ **Action template**: `"Shift: add conversion touchpoints to high-engagement pages"`
246
+
247
+ ### Unclassified Anomalies
248
+
249
+ Any anomaly (event with `|delta_pct| >= anomaly_threshold`) that does not match one of the three patterns above is labeled:
250
+
251
+ - **Pattern Match**: `"Unclassified anomaly"`
252
+ - **Action**: `"Review: investigate cause of {delta_pct} change in {relation}"`
253
+
254
+ ## Status Lifecycle
255
+
256
+ ```
257
+ generated --> reviewed --> actioned
258
+ ```
259
+
260
+ | Status | Meaning | Set By |
261
+ |--------|---------|--------|
262
+ | `generated` | Created by wp-analytics Step 7. No human review yet | Automated |
263
+ | `reviewed` | User or Claude reviewed anomalies, confirmed or dismissed findings | Manual |
264
+ | `actioned` | Findings acted upon -- briefs created, campaigns launched, or changes deployed | Manual |
265
+
266
+ Status transitions are forward-only. A feed does not revert from `actioned` to `reviewed`.
267
+
268
+ ## Integration Notes
269
+
270
+ ### GenSignal
271
+
272
+ NormalizedEvent maps 1:1 to the GenSignal Harvest stage. The `provenance` block enables corroboration scoring. Multiple source tools reporting on the same entity strengthen the signal quality score.
273
+
274
+ ### Phase 1 Bridge (wp-content-pipeline)
275
+
276
+ Anomalies with the action `"Investigate: content cluster opportunity"` feed the `wp-content-pipeline` skill by creating content briefs in `pipeline-active/`. The Search Intent Shift pattern is the primary trigger for new content ideation.
277
+
278
+ ### Phase 3 Bridge (wp-editorial-planner)
279
+
280
+ The Anomalies & Patterns table provides data-driven topic suggestions for `wp-editorial-planner`. Each anomaly row can be converted into an editorial calendar entry with priority based on delta magnitude.
281
+
282
+ ### Overwrite Semantics
283
+
284
+ `signals-feed.md` is overwritten each time Step 7 runs. It is not archived -- it is a point-in-time snapshot. The `comparison_period` field preserves the baseline reference so the context of delta calculations is never lost. For historical tracking, rely on the underlying analytics platforms (GA4, GSC) rather than feed archives.
285
+
286
+ ## Validation Rules
287
+
288
+ Before writing a `signals-feed.md` file, Step 7 validates the following:
289
+
290
+ | Rule | Check |
291
+ |------|-------|
292
+ | `feed_id` format | Must follow `FEED-{site_id}-YYYY-MM` pattern |
293
+ | `site_id` exists | Must match an existing `.content-state/{site_id}.config.md` |
294
+ | Event completeness | Every event must have `entity_id`, `relation`, `value`, `unit`, `ts`, and `provenance` |
295
+ | Entity prefix | `entity_id` must use a recognized prefix: `Page:`, `Keyword:`, `Source:`, `Site:` |
296
+ | Relation validity | `relation` must be valid for the entity type (see Valid Relations table) |
297
+ | Delta type | `delta_pct` values must be integers when present |
298
+ | Threshold value | `anomaly_threshold` must be a positive number |
299
+
300
+ If any validation fails, Step 7 logs the error and does not write the file.
301
+
302
+ ## Example Feed
303
+
304
+ A complete `signals-feed.md` for the opencactus site, February 2026.
305
+
306
+ ````markdown
307
+ ---
308
+ feed_id: "FEED-opencactus-2026-02"
309
+ site_id: opencactus
310
+ generated: "2026-03-01T09:00:00Z"
311
+ period: "2026-02-01..2026-02-28"
312
+ comparison_period: "2026-01-01..2026-01-31"
313
+ source_tools:
314
+ - ga4_top_pages
315
+ - ga4_traffic_sources
316
+ - ga4_report
317
+ - gsc_search_analytics
318
+ - cwv_crux_origin
319
+ anomaly_threshold: 30
320
+ status: generated
321
+ ---
322
+
323
+ # Normalized Events
324
+
325
+ ## Traffic Signals
326
+
327
+ ```yaml
328
+ - entity_id: "Page:/cactus-water-benefici"
329
+ relation: pageviews
330
+ value: 3240
331
+ unit: count
332
+ ts: "2026-02-28T23:59:59Z"
333
+ delta_pct: +47
334
+ provenance:
335
+ source_id: ga4_top_pages
336
+ site: opencactus
337
+
338
+ - entity_id: "Page:/cactus-water-benefici"
339
+ relation: avg_engagement_time
340
+ value: 185
341
+ unit: seconds
342
+ ts: "2026-02-28T23:59:59Z"
343
+ delta_pct: +12
344
+ provenance:
345
+ source_id: ga4_top_pages
346
+ site: opencactus
347
+
348
+ - entity_id: "Page:/prodotti"
349
+ relation: pageviews
350
+ value: 1850
351
+ unit: count
352
+ ts: "2026-02-28T23:59:59Z"
353
+ delta_pct: +8
354
+ provenance:
355
+ source_id: ga4_top_pages
356
+ site: opencactus
357
+ ```
358
+
359
+ ## Search Signals
360
+
361
+ ```yaml
362
+ - entity_id: "Keyword:acqua di cactus"
363
+ relation: search_impressions
364
+ value: 8500
365
+ unit: count
366
+ ts: "2026-02-28T23:59:59Z"
367
+ delta_pct: +120
368
+ provenance:
369
+ source_id: gsc_search_analytics
370
+ site: opencactus
371
+
372
+ - entity_id: "Keyword:acqua di cactus benefici"
373
+ relation: search_ctr
374
+ value: 4.2
375
+ unit: percentage
376
+ ts: "2026-02-28T23:59:59Z"
377
+ delta_pct: -8
378
+ provenance:
379
+ source_id: gsc_search_analytics
380
+ site: opencactus
381
+ ```
382
+
383
+ ## Source Signals
384
+
385
+ ```yaml
386
+ - entity_id: "Source:linkedin"
387
+ relation: referral_sessions
388
+ value: 420
389
+ unit: count
390
+ ts: "2026-02-28T23:59:59Z"
391
+ delta_pct: +85
392
+ provenance:
393
+ source_id: ga4_traffic_sources
394
+ site: opencactus
395
+ ```
396
+
397
+ ## Performance Signals
398
+
399
+ ```yaml
400
+ - entity_id: "Site:opencactus"
401
+ relation: lcp
402
+ value: 2.1
403
+ unit: seconds
404
+ ts: "2026-02-28T23:59:59Z"
405
+ provenance:
406
+ source_id: cwv_crux_origin
407
+ site: opencactus
408
+ ```
409
+
410
+ # Anomalies & Patterns
411
+
412
+ | Entity | Metric | Delta | Pattern Match | Action |
413
+ |--------|--------|-------|---------------|--------|
414
+ | Keyword:acqua di cactus | search_impressions | +120% | Search Intent Shift | Investigate: content cluster opportunity |
415
+ | Source:linkedin | referral_sessions | +85% | Early-Adopter Surge | Scale: increase posting frequency on linkedin |
416
+ | Page:/cactus-water-benefici | pageviews | +47% | Unclassified anomaly | Review: investigate cause of +47% change in pageviews |
417
+ ````