seo 0.1.0 → 0.2.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.
- package/PRIVACY.md +2 -2
- package/README.md +133 -40
- package/TERMS.md +2 -2
- package/TRADEMARKS.md +9 -5
- package/dist/cli.js +68 -52
- package/dist/cli.js.map +1 -1
- package/dist/{dist-CSY2_p-j.js → dist-6bK_8r5M.js} +49 -49
- package/dist/dist-6bK_8r5M.js.map +1 -0
- package/dist/{dist-FeAUNn9A.js → dist-vRmqfhR4.js} +1 -1
- package/dist/index.d.ts +186 -94
- package/dist/index.js +843 -415
- package/dist/index.js.map +1 -1
- package/dist/mcp.d.ts +18 -1
- package/dist/mcp.js +6532 -4665
- package/dist/mcp.js.map +1 -1
- package/dist/{package-uzXzqDW6.js → package-7aT8_Xp0.js} +2 -2
- package/dist/{package-uzXzqDW6.js.map → package-7aT8_Xp0.js.map} +1 -1
- package/evals/README.md +117 -0
- package/evals/affected-urls.json +57 -0
- package/evals/ai-readiness.json +84 -0
- package/evals/ai-referrals.json +71 -0
- package/evals/ai-search-scorecard.json +70 -0
- package/evals/audit-page.json +57 -0
- package/evals/audit-urls.json +58 -0
- package/evals/cannibalisation.json +57 -0
- package/evals/community-intent.json +57 -0
- package/evals/compare-crawls.json +56 -0
- package/evals/content-optimization.json +57 -0
- package/evals/crawl-diff.json +58 -0
- package/evals/crawl-history.json +44 -0
- package/evals/crawl-report.json +44 -0
- package/evals/crawler-rules.json +44 -0
- package/evals/ctr-underperformers.json +57 -0
- package/evals/decaying-pages.json +57 -0
- package/evals/entity-readiness.json +57 -0
- package/evals/explain-crawl-issue.json +44 -0
- package/evals/generate-llms-txt.json +44 -0
- package/evals/geo-gaps.json +57 -0
- package/evals/index-coverage-plan.json +58 -0
- package/evals/index-coverage.json +70 -0
- package/evals/index-monitor.json +58 -0
- package/evals/index-watch.json +68 -0
- package/evals/internal-links.json +57 -0
- package/evals/link-recovery.json +58 -0
- package/evals/llms-txt-audit.json +44 -0
- package/evals/measure-change.json +58 -0
- package/evals/monthly-action-plan.json +56 -0
- package/evals/monthly-report.json +58 -0
- package/evals/narrative-report.json +58 -0
- package/evals/okf-build.json +44 -0
- package/evals/okf-validate.json +44 -0
- package/evals/page-opportunities.json +57 -0
- package/evals/performance-audit.json +57 -0
- package/evals/pseo-audit.json +84 -0
- package/evals/query-clusters.json +57 -0
- package/evals/quick-wins.json +86 -0
- package/evals/redirect-trace.json +57 -0
- package/evals/refresh-priorities.json +57 -0
- package/evals/search-performance-overview.json +86 -0
- package/evals/second-page.json +58 -0
- package/evals/segment-impact.json +57 -0
- package/evals/seo-fix-queue.json +85 -0
- package/evals/seo-geo-readiness.json +84 -0
- package/evals/seo-site-audit.json +85 -0
- package/evals/seo-to-ai-query.json +57 -0
- package/evals/seo.json +87 -0
- package/evals/setup-check.json +56 -0
- package/evals/site-crawl.json +44 -0
- package/evals/striking-distance.json +85 -0
- package/evals/technical-watch.json +57 -0
- package/evals/top-fixes.json +44 -0
- package/evals/traffic-anomaly.json +57 -0
- package/evals/update-correlation.json +57 -0
- package/evals/update-postmortem.json +57 -0
- package/package.json +5 -3
- package/skills/README.md +46 -59
- package/skills/seo/SKILL.md +88 -63
- package/skills/seo/agents/openai.yaml +2 -2
- package/dist/dist-CSY2_p-j.js.map +0 -1
- package/skills/affected-urls/SKILL.md +0 -39
- package/skills/affected-urls/agents/openai.yaml +0 -4
- package/skills/ai-readiness/SKILL.md +0 -34
- package/skills/ai-readiness/agents/openai.yaml +0 -4
- package/skills/ai-referrals/SKILL.md +0 -31
- package/skills/ai-referrals/agents/openai.yaml +0 -4
- package/skills/audit-page/SKILL.md +0 -50
- package/skills/audit-page/agents/openai.yaml +0 -4
- package/skills/audit-urls/SKILL.md +0 -39
- package/skills/audit-urls/agents/openai.yaml +0 -4
- package/skills/cannibalisation/SKILL.md +0 -31
- package/skills/cannibalisation/agents/openai.yaml +0 -4
- package/skills/community-intent/SKILL.md +0 -39
- package/skills/community-intent/agents/openai.yaml +0 -4
- package/skills/compare-crawls/SKILL.md +0 -40
- package/skills/compare-crawls/agents/openai.yaml +0 -4
- package/skills/content-optimization/SKILL.md +0 -31
- package/skills/content-optimization/agents/openai.yaml +0 -4
- package/skills/crawl-diff/SKILL.md +0 -51
- package/skills/crawl-diff/agents/openai.yaml +0 -4
- package/skills/crawl-history/SKILL.md +0 -37
- package/skills/crawl-history/agents/openai.yaml +0 -4
- package/skills/crawl-report/SKILL.md +0 -37
- package/skills/crawl-report/agents/openai.yaml +0 -4
- package/skills/crawler-rules/SKILL.md +0 -34
- package/skills/crawler-rules/agents/openai.yaml +0 -4
- package/skills/ctr-underperformers/SKILL.md +0 -31
- package/skills/ctr-underperformers/agents/openai.yaml +0 -4
- package/skills/decaying-pages/SKILL.md +0 -31
- package/skills/decaying-pages/agents/openai.yaml +0 -4
- package/skills/entity-readiness/SKILL.md +0 -34
- package/skills/entity-readiness/agents/openai.yaml +0 -4
- package/skills/explain-crawl-issue/SKILL.md +0 -32
- package/skills/explain-crawl-issue/agents/openai.yaml +0 -4
- package/skills/generate-llms-txt/SKILL.md +0 -37
- package/skills/generate-llms-txt/agents/openai.yaml +0 -4
- package/skills/geo-gaps/SKILL.md +0 -37
- package/skills/geo-gaps/agents/openai.yaml +0 -4
- package/skills/index-coverage/SKILL.md +0 -84
- package/skills/index-coverage/agents/openai.yaml +0 -4
- package/skills/index-coverage-plan/SKILL.md +0 -50
- package/skills/index-coverage-plan/agents/openai.yaml +0 -4
- package/skills/index-monitor/SKILL.md +0 -49
- package/skills/index-monitor/agents/openai.yaml +0 -4
- package/skills/index-watch/SKILL.md +0 -77
- package/skills/index-watch/agents/openai.yaml +0 -4
- package/skills/internal-links/SKILL.md +0 -31
- package/skills/internal-links/agents/openai.yaml +0 -4
- package/skills/link-recovery/SKILL.md +0 -51
- package/skills/link-recovery/agents/openai.yaml +0 -4
- package/skills/llms-txt-audit/SKILL.md +0 -34
- package/skills/llms-txt-audit/agents/openai.yaml +0 -4
- package/skills/measure-change/SKILL.md +0 -52
- package/skills/measure-change/agents/openai.yaml +0 -4
- package/skills/monthly-action-plan/SKILL.md +0 -50
- package/skills/monthly-action-plan/agents/openai.yaml +0 -4
- package/skills/monthly-report/SKILL.md +0 -50
- package/skills/monthly-report/agents/openai.yaml +0 -4
- package/skills/narrative-report/SKILL.md +0 -51
- package/skills/narrative-report/agents/openai.yaml +0 -4
- package/skills/okf-build/SKILL.md +0 -39
- package/skills/okf-build/agents/openai.yaml +0 -4
- package/skills/okf-validate/SKILL.md +0 -43
- package/skills/okf-validate/agents/openai.yaml +0 -4
- package/skills/page-opportunities/SKILL.md +0 -31
- package/skills/page-opportunities/agents/openai.yaml +0 -4
- package/skills/performance/SKILL.md +0 -50
- package/skills/performance/agents/openai.yaml +0 -4
- package/skills/performance-audit/SKILL.md +0 -31
- package/skills/performance-audit/agents/openai.yaml +0 -4
- package/skills/pseo-audit/SKILL.md +0 -103
- package/skills/pseo-audit/agents/openai.yaml +0 -4
- package/skills/query-clusters/SKILL.md +0 -31
- package/skills/query-clusters/agents/openai.yaml +0 -4
- package/skills/quick-wins/SKILL.md +0 -31
- package/skills/quick-wins/agents/openai.yaml +0 -4
- package/skills/redirect-trace/SKILL.md +0 -51
- package/skills/redirect-trace/agents/openai.yaml +0 -4
- package/skills/refresh-priorities/SKILL.md +0 -48
- package/skills/refresh-priorities/agents/openai.yaml +0 -4
- package/skills/search-performance-overview/SKILL.md +0 -48
- package/skills/search-performance-overview/agents/openai.yaml +0 -4
- package/skills/second-page/SKILL.md +0 -50
- package/skills/second-page/agents/openai.yaml +0 -4
- package/skills/segment-impact/SKILL.md +0 -50
- package/skills/segment-impact/agents/openai.yaml +0 -4
- package/skills/seo-fix-queue/SKILL.md +0 -50
- package/skills/seo-fix-queue/agents/openai.yaml +0 -4
- package/skills/seo-geo-readiness/SKILL.md +0 -60
- package/skills/seo-geo-readiness/agents/openai.yaml +0 -4
- package/skills/seo-site-audit/SKILL.md +0 -59
- package/skills/seo-site-audit/agents/openai.yaml +0 -4
- package/skills/seo-to-ai-query/SKILL.md +0 -31
- package/skills/seo-to-ai-query/agents/openai.yaml +0 -4
- package/skills/setup-check/SKILL.md +0 -49
- package/skills/setup-check/agents/openai.yaml +0 -4
- package/skills/site-crawl/SKILL.md +0 -39
- package/skills/site-crawl/agents/openai.yaml +0 -4
- package/skills/striking-distance/SKILL.md +0 -52
- package/skills/striking-distance/agents/openai.yaml +0 -4
- package/skills/technical-watch/SKILL.md +0 -49
- package/skills/technical-watch/agents/openai.yaml +0 -4
- package/skills/top-fixes/SKILL.md +0 -38
- package/skills/top-fixes/agents/openai.yaml +0 -4
- package/skills/traffic-anomaly/SKILL.md +0 -52
- package/skills/traffic-anomaly/agents/openai.yaml +0 -4
- package/skills/update-correlation/SKILL.md +0 -51
- package/skills/update-correlation/agents/openai.yaml +0 -4
- package/skills/update-postmortem/SKILL.md +0 -49
- package/skills/update-postmortem/agents/openai.yaml +0 -4
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"subject": "redirect-trace",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"prompt": "This old URL bounces around before it lands somewhere. Can you trace where it ends up?",
|
|
7
|
+
"expected_output": "Should route to report id redirect-trace, which follows every redirect hop and checks the final page, indexability, and canonical signals. Should follow the discovery flow: seo_list_reports with category monitoring, seo_describe_report with id redirect-trace, then seo_run_report with a url. Should read the chain in order with requested URL, status, Location, resolved next, and duration first, then finalUrl versus finalPage and summary.finalStatus, then summary.issues, then metaRobots, xRobotsTag, canonical, and warnings.",
|
|
8
|
+
"assertions": [
|
|
9
|
+
"Uses report id redirect-trace to follow the redirect chain",
|
|
10
|
+
"Follows seo_list_reports, seo_describe_report, seo_run_report in order",
|
|
11
|
+
"Reads the chain in order with status, Location, and resolved next first",
|
|
12
|
+
"Reads finalUrl versus finalPage and summary.finalStatus",
|
|
13
|
+
"Reads summary.issues before drawing conclusions",
|
|
14
|
+
"Reads metaRobots, xRobotsTag, and canonical last"
|
|
15
|
+
],
|
|
16
|
+
"files": []
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": 2,
|
|
20
|
+
"prompt": "Agent task: trace https://example.com/old with up to 10 hops, a fresh fetch, and JavaScript rendering.",
|
|
21
|
+
"expected_output": "Should run report id redirect-trace with url https://example.com/old, maxHops 10, refresh true, and js true, via seo reports run redirect-trace or seo_run_report. Should use only url, maxHops, refresh, and js from the schema. Should note that JavaScript rendering affects final-page extraction, not the HTTP chain.",
|
|
22
|
+
"assertions": [
|
|
23
|
+
"Runs report id redirect-trace with maxHops 10, refresh true, and js true",
|
|
24
|
+
"Uses only parameters defined in the redirect-trace schema",
|
|
25
|
+
"States JavaScript rendering affects final-page extraction, not the HTTP chain",
|
|
26
|
+
"Reads the chain before the final page checks"
|
|
27
|
+
],
|
|
28
|
+
"files": []
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"id": 3,
|
|
32
|
+
"prompt": "It is a 302, so that is a broken redirect, and it proves every visitor gets sent there.",
|
|
33
|
+
"expected_output": "Should refuse both claims. A 302 can be intentional. The trace is one observation from the machine and time that ran it, and CDNs, geography, cookies, or later deploys can differ, so it does not prove every visitor is routed the same way. Should keep the observation distinct from a defect and recommend re-running the trace after deployment to confirm the intended destination and status.",
|
|
34
|
+
"assertions": [
|
|
35
|
+
"Refuses to call the 302 a broken redirect on its own",
|
|
36
|
+
"States a 302 can be intentional",
|
|
37
|
+
"States the trace is one observation and CDNs, geography, or cookies can differ",
|
|
38
|
+
"Refuses to claim every visitor is routed the same way",
|
|
39
|
+
"Recommends re-running the trace after deployment to confirm"
|
|
40
|
+
],
|
|
41
|
+
"files": []
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"id": 4,
|
|
45
|
+
"prompt": "Turn on JS rendering to fix the redirect chain, and since there is a canonical pointing elsewhere the whole redirect is wrong.",
|
|
46
|
+
"expected_output": "Should refuse both points. JavaScript rendering affects final-page extraction, not the HTTP chain, so it cannot fix the chain. A canonical elsewhere can be intentional. Should keep the HTTP chain distinct from final-page extraction and treat the canonical as an observation until intent or contradictory evidence makes it a defect.",
|
|
47
|
+
"assertions": [
|
|
48
|
+
"States JavaScript rendering does not change the HTTP redirect chain",
|
|
49
|
+
"Refuses to treat JS rendering as a fix for the chain",
|
|
50
|
+
"States a canonical pointing elsewhere can be intentional",
|
|
51
|
+
"Keeps the HTTP chain distinct from final-page extraction",
|
|
52
|
+
"Treats the canonical as an observation rather than an automatic defect"
|
|
53
|
+
],
|
|
54
|
+
"files": []
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"subject": "refresh-priorities",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"prompt": "Which existing pages should we refresh first?",
|
|
7
|
+
"expected_output": "Should use report id refresh-priorities to combine search declines and near-term opportunities into a ranked content review queue. Should follow the discovery flow: seo_list_reports with category workflows, seo_describe_report with id refresh-priorities, then seo_run_report with the required site. Should read the workflow steps and skipped states first, then per-item source, impactKind, score breakdown, date window, completeness, verification status, and rationale. Should clarify the score is not a traffic forecast.",
|
|
8
|
+
"assertions": [
|
|
9
|
+
"Uses report id refresh-priorities for the ranked review queue",
|
|
10
|
+
"Follows seo_list_reports, seo_describe_report, seo_run_report in order",
|
|
11
|
+
"Reads the workflow steps and skipped states first",
|
|
12
|
+
"Reads per-item source, impactKind, score breakdown, verification status, and rationale",
|
|
13
|
+
"States the score is not a traffic forecast"
|
|
14
|
+
],
|
|
15
|
+
"files": []
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"id": 2,
|
|
19
|
+
"prompt": "Run refresh priorities for sc-domain:example.com over 180 days, recent window 28 days, verify content on the top 10, return 20 items.",
|
|
20
|
+
"expected_output": "Should run report id refresh-priorities with site sc-domain:example.com, days 180, recentDays 28, verifyContent true, verifyLimit 10, and limit 20. Should read per-item impactKind, score breakdown, and verification status, and treat the click decline, low CTR, second-page position, and GA4 session signals as having different semantics, not interchangeable. Should use only parameters defined in the schema.",
|
|
21
|
+
"assertions": [
|
|
22
|
+
"Runs report id refresh-priorities with days 180 and recentDays 28",
|
|
23
|
+
"Sets verifyContent true, verifyLimit 10, and limit 20 as requested",
|
|
24
|
+
"Reads per-item impactKind, score breakdown, and verification status",
|
|
25
|
+
"Treats the different signal types as not interchangeable",
|
|
26
|
+
"Uses only parameters defined in the report schema"
|
|
27
|
+
],
|
|
28
|
+
"files": []
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"id": 3,
|
|
32
|
+
"prompt": "Rank by score and treat it as the extra clicks we will get, and remember the GA4 signal and the CTR signal mean the same thing.",
|
|
33
|
+
"expected_output": "Should refuse both moves. Should state the score is not expected clicks, revenue, ranking lift, or causal confidence, and that a click decline, low CTR, second-page position, and GA4 session signal have different semantics and are not interchangeable. Should recommend confirming query intent, current content, and internal links for the top URLs before choosing a bounded edit.",
|
|
34
|
+
"assertions": [
|
|
35
|
+
"Refuses to read the score as extra clicks",
|
|
36
|
+
"States the score is not expected clicks, revenue, ranking lift, or causal confidence",
|
|
37
|
+
"States the signal types have different semantics and are not interchangeable",
|
|
38
|
+
"Recommends confirming query intent, current content, and internal links for the top URLs",
|
|
39
|
+
"Frames the next step as a bounded edit, not an automatic one"
|
|
40
|
+
],
|
|
41
|
+
"files": []
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"id": 4,
|
|
45
|
+
"prompt": "GA4 was not connected on this run, so those pages have zero sessions and should rank lowest in the queue.",
|
|
46
|
+
"expected_output": "Should refuse to treat missing GA4 as zero. Should state missing GA4 or failed fetches stay unavailable, not zero-weight proof, and read the workflow skipped states and per-item completeness and verification status. Should keep unavailable and zero states distinct and not push pages down the queue on missing evidence alone.",
|
|
47
|
+
"assertions": [
|
|
48
|
+
"Refuses to treat missing GA4 as zero sessions",
|
|
49
|
+
"States missing GA4 or failed fetches stay unavailable, not zero-weight proof",
|
|
50
|
+
"Reads the workflow skipped states and per-item completeness and verification status",
|
|
51
|
+
"Keeps unavailable and zero states distinct",
|
|
52
|
+
"Does not push pages down the queue on missing evidence alone"
|
|
53
|
+
],
|
|
54
|
+
"files": []
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{
|
|
2
|
+
"subject": "search-performance-overview",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"prompt": "We just connected Search Console for a new property. Where should we even start looking?",
|
|
7
|
+
"expected_output": "Should treat search-performance-overview as the best first report for a newly connected property and run it before any focused report. Should follow the discovery flow: seo_list_reports with category workflows, seo_describe_report with id search-performance-overview, then seo_run_report with only schema-valid params. Should read the workflow envelope first, including workflow, site, summary, steps, actions, and output, then each report's dataStatus and skipped sections. Should use the report to point at the focused report to run next rather than asking this workflow for a larger payload.",
|
|
8
|
+
"assertions": [
|
|
9
|
+
"Uses search-performance-overview as the first report for a new property",
|
|
10
|
+
"Follows seo_list_reports then seo_describe_report then seo_run_report in order",
|
|
11
|
+
"Reads the workflow envelope (workflow, site, summary, steps, actions, output) first",
|
|
12
|
+
"Checks each report's dataStatus and skipped sections",
|
|
13
|
+
"Plans to run a focused report next rather than enlarging this payload",
|
|
14
|
+
"Passes only schema-valid parameters"
|
|
15
|
+
],
|
|
16
|
+
"files": []
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": 2,
|
|
20
|
+
"prompt": "Agent task: run the overview for sc-domain:example.com over 90 days with a 7 day recent window, top 10 items, brand excluded. Return JSON.",
|
|
21
|
+
"expected_output": "Should run report id search-performance-overview via seo reports run search-performance-overview --params or seo_run_report with params site sc-domain:example.com, days 90, recentDays 7, limit 10, includeBrand false. Should note that days sets the main evidence window, recentDays sets the recent comparison period, and limit caps returned items without increasing provider coverage. Should return the structuredContent contract and preserve dataStatus, partial reasons, and evidence references.",
|
|
22
|
+
"assertions": [
|
|
23
|
+
"Runs report id search-performance-overview with days 90 and recentDays 7",
|
|
24
|
+
"Sets limit 10 and includeBrand false as requested",
|
|
25
|
+
"Explains days is the main window and recentDays is the recent comparison",
|
|
26
|
+
"Notes limit caps returned items and does not increase provider coverage",
|
|
27
|
+
"Returns structuredContent and preserves dataStatus and evidence references",
|
|
28
|
+
"Uses only parameters defined in the report schema"
|
|
29
|
+
],
|
|
30
|
+
"files": []
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"id": 3,
|
|
34
|
+
"prompt": "The overview shows clicks down and a Google update in the same window. Tell me the update caused the drop and how many clicks we'll recover if we act.",
|
|
35
|
+
"expected_output": "Should refuse both the causation claim and the recovery forecast. Should explain that update overlap, opportunity scores, average position, and timing are investigation signals, not causation or forecasts. Should recommend confirming affected URLs, provider dates, selection limits, and intentional technical controls before concluding, and should run a focused report such as update-correlation to inspect the overlap rather than asserting cause. Should not produce a click recovery number.",
|
|
36
|
+
"assertions": [
|
|
37
|
+
"Refuses to state the update caused the drop",
|
|
38
|
+
"Refuses to forecast how many clicks will be recovered",
|
|
39
|
+
"Labels update overlap and timing as investigation signals, not causation",
|
|
40
|
+
"Recommends confirming affected URLs, provider dates, and intentional controls first",
|
|
41
|
+
"Points to a focused report like update-correlation to inspect the overlap",
|
|
42
|
+
"Does not invent a recovery figure"
|
|
43
|
+
],
|
|
44
|
+
"files": []
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"id": 4,
|
|
48
|
+
"prompt": "The summary section looks totally healthy, so we're fine across the board this quarter, correct?",
|
|
49
|
+
"expected_output": "Should not let one complete section imply a sitewide all-clear. Should check each step's own status and evidence, since a failed or capped neighbour can sit beside a complete section. Should inspect dataStatus, skipped sections, and partial reasons before agreeing anything is fine. Should name any partial, capped, or skipped evidence rather than generalizing from the healthy summary.",
|
|
50
|
+
"assertions": [
|
|
51
|
+
"Refuses to generalize a healthy summary into a sitewide all-clear",
|
|
52
|
+
"Checks each step's own status and evidence",
|
|
53
|
+
"Notes a failed or capped neighbour can sit beside a complete section",
|
|
54
|
+
"Inspects dataStatus, skipped sections, and partial reasons",
|
|
55
|
+
"Names any partial, capped, or skipped evidence before concluding"
|
|
56
|
+
],
|
|
57
|
+
"files": []
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"id": 5,
|
|
61
|
+
"prompt": "Can you just have this overview return every query and page and all the striking-distance and cannibalisation detail in one giant response?",
|
|
62
|
+
"expected_output": "Should decline to enlarge the workflow payload and instead run a focused report to inspect detail. Should explain the overview points to the focused report that verifies each issue, and that limit caps items without increasing provider coverage. Should name the focused reports for the requested detail, such as report id striking-distance, rather than expanding this broad workflow. Should keep the overview bounded.",
|
|
63
|
+
"assertions": [
|
|
64
|
+
"Declines to expand the overview into one large payload",
|
|
65
|
+
"Recommends running a focused report for the detail instead",
|
|
66
|
+
"Names report id striking-distance for the near-page-one detail",
|
|
67
|
+
"Explains limit caps items and does not increase provider coverage",
|
|
68
|
+
"Keeps the workflow output bounded"
|
|
69
|
+
],
|
|
70
|
+
"files": []
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"id": 6,
|
|
74
|
+
"prompt": "The report flags a decaying page. Push a rewrite of it to the top of the list right now.",
|
|
75
|
+
"expected_output": "Should treat the decay signal as an investigation signal and confirm the evidence before acting. Should confirm affected URLs, provider dates, selection limits, and intentional technical controls such as noindex or canonicals before recommending a rewrite. Should suggest running a focused report like decaying-pages to inspect the detail. Should not present the decay flag as a proven cause or as justification for an immediate rewrite.",
|
|
76
|
+
"assertions": [
|
|
77
|
+
"Treats the decay flag as an investigation signal, not a proven cause",
|
|
78
|
+
"Confirms affected URLs, provider dates, and selection limits first",
|
|
79
|
+
"Checks for intentional controls like noindex or canonicals before acting",
|
|
80
|
+
"Suggests a focused report such as decaying-pages for the detail",
|
|
81
|
+
"Does not rush a rewrite from the flag alone"
|
|
82
|
+
],
|
|
83
|
+
"files": []
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"subject": "second-page",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"prompt": "Which of our pages are just barely off page one?",
|
|
7
|
+
"expected_output": "Should route to report id second-page, which finds URLs averaging positions 11 to 20 with the queries behind each one. Should follow the discovery flow: seo_list_reports with category reporting, seo_describe_report with id second-page, then seo_run_report with only schema-valid params. Should read source completeness, date range, selection, methodology, provenance, and brand filtering first, then per-item impressions, clicks, CTR, and average position, then the priority value. Should note average position is aggregated, not an exact rank.",
|
|
8
|
+
"assertions": [
|
|
9
|
+
"Uses report id second-page for the positions 11 to 20 review",
|
|
10
|
+
"Follows seo_list_reports, seo_describe_report, seo_run_report in order",
|
|
11
|
+
"Reads source completeness, date range, and selection before the rows",
|
|
12
|
+
"Reads per-item impressions, clicks, CTR, and average position",
|
|
13
|
+
"States average position is aggregated and not an exact rank",
|
|
14
|
+
"Reads the priority value last"
|
|
15
|
+
],
|
|
16
|
+
"files": []
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": 2,
|
|
20
|
+
"prompt": "Agent task: run second-page for sc-domain:example.com over a 90 day range, at least 200 impressions, top 25 URLs, brand excluded.",
|
|
21
|
+
"expected_output": "Should run report id second-page with site sc-domain:example.com, range 90, minImpressions 200, limit 25, and includeBrand false, via seo reports run second-page or seo_run_report. Should keep params within the schema bounds, where range allows up to 548 and limit up to 100. Should note limit caps the retained rows and does not increase provider coverage, so the output is not a complete inventory.",
|
|
22
|
+
"assertions": [
|
|
23
|
+
"Runs report id second-page with range 90 and minImpressions 200",
|
|
24
|
+
"Sets limit 25 and includeBrand false as requested",
|
|
25
|
+
"Keeps range and limit within the schema bounds",
|
|
26
|
+
"Notes limit caps retained rows and does not increase provider coverage",
|
|
27
|
+
"States the output is not a complete inventory"
|
|
28
|
+
],
|
|
29
|
+
"files": []
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": 3,
|
|
33
|
+
"prompt": "Add up the priority values, that is how many extra clicks we will get, and any URL sharing a query with another is cannibalisation, right?",
|
|
34
|
+
"expected_output": "Should refuse both claims. Priority is a transparent heuristic, not expected click lift, so it must not be totalled into a promised click gain. One row is not cannibalisation. Should point to report id cannibalisation to check query and URL overlap rather than inferring it from a single row here.",
|
|
35
|
+
"assertions": [
|
|
36
|
+
"States priority is a transparent heuristic, not expected click lift",
|
|
37
|
+
"Refuses to total priority values into a promised click gain",
|
|
38
|
+
"States one row is not cannibalisation",
|
|
39
|
+
"Points to report id cannibalisation to check query and URL overlap",
|
|
40
|
+
"Does not present a total extra clicks figure"
|
|
41
|
+
],
|
|
42
|
+
"files": []
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"id": 4,
|
|
46
|
+
"prompt": "This URL sits at position 12, so we are locked at number 12 for that query. Just drop the exact phrase into the title to jump to number 1.",
|
|
47
|
+
"expected_output": "Should decline the framing. Average position is aggregated across searches, locations, devices, and time and is not an exact or locked rank, and retained limits mean the output is not a complete inventory. Should recommend inspecting the live page and search intent and confirming the query suits the URL before one defensible change, rather than forcing the exact phrase into the title.",
|
|
48
|
+
"assertions": [
|
|
49
|
+
"States average position 12 is not an exact or locked rank",
|
|
50
|
+
"Notes average position is aggregated across searches, locations, devices, and time",
|
|
51
|
+
"Declines to force the exact query phrase into the title",
|
|
52
|
+
"Recommends inspecting the live page and intent before one defensible change",
|
|
53
|
+
"Notes retained limits mean the output is not a complete inventory"
|
|
54
|
+
],
|
|
55
|
+
"files": []
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"subject": "segment-impact",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"prompt": "Traffic dropped. Is it the whole site or just one section?",
|
|
7
|
+
"expected_output": "Should route to report id segment-impact, which compares page or query groups across equal periods to find which parts of a site moved. Should follow the discovery flow: seo_list_reports with category diagnosis, seo_describe_report with id segment-impact, then seo_run_report with site. Should read before, after, and rangeDays first, then dataStatus and source.before, source.after, and completeness for caps and truncation, then the selection counts, then per-item clickDelta, impressionDelta, and positionDelta and unmatchedSegments. Should recommend confirming the movement first with report id traffic-anomaly.",
|
|
8
|
+
"assertions": [
|
|
9
|
+
"Uses report id segment-impact to locate where movement sits",
|
|
10
|
+
"Follows seo_list_reports, seo_describe_report, seo_run_report in order",
|
|
11
|
+
"Reads before, after, and rangeDays first",
|
|
12
|
+
"Reads dataStatus and source completeness for caps and truncation",
|
|
13
|
+
"Reads per-item clickDelta, impressionDelta, and positionDelta",
|
|
14
|
+
"Recommends confirming movement first with report id traffic-anomaly"
|
|
15
|
+
],
|
|
16
|
+
"files": []
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": 2,
|
|
20
|
+
"prompt": "Agent task: run segment-impact for sc-domain:example.com by page over 90 days against the prior 90 days, top 25 segments.",
|
|
21
|
+
"expected_output": "Should run report id segment-impact with site sc-domain:example.com, dimension page, days 90, compareDays 90, and limit 25, via seo reports run segment-impact or seo_run_report. Should keep params within the schema bounds, where days and compareDays allow up to 240 and limit up to 100. Should read the selection invalid, duplicate, conflicting, matched, unmatched, returned, and limited counts before ranking movers.",
|
|
22
|
+
"assertions": [
|
|
23
|
+
"Runs report id segment-impact with dimension page, days 90, and compareDays 90",
|
|
24
|
+
"Sets limit 25 as requested",
|
|
25
|
+
"Keeps days, compareDays, and limit within the schema bounds",
|
|
26
|
+
"Reads the selection matched, unmatched, and limited counts before ranking",
|
|
27
|
+
"Uses only parameters defined in the segment-impact schema"
|
|
28
|
+
],
|
|
29
|
+
"files": []
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": 3,
|
|
33
|
+
"prompt": "This segment has a positive positionDelta, so it improved. Promote it as a win.",
|
|
34
|
+
"expected_output": "Should refuse. A positive positionDelta is worse because a larger average position is lower in results. Should read the direction correctly and note that a limited or truncated result cannot support an inventory-wide winner or loser. Should recommend auditing the top matched movers before drawing a conclusion.",
|
|
35
|
+
"assertions": [
|
|
36
|
+
"Refuses to call a positive positionDelta an improvement",
|
|
37
|
+
"States a larger average position is lower in results",
|
|
38
|
+
"States a limited or truncated result cannot support an inventory-wide winner or loser",
|
|
39
|
+
"Recommends auditing the top matched movers before concluding"
|
|
40
|
+
],
|
|
41
|
+
"files": []
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"id": 4,
|
|
45
|
+
"prompt": "These unmatched segments dropped to zero clicks. Count them as total losses.",
|
|
46
|
+
"expected_output": "Should refuse. unmatchedSegments are retained in one window only and are not gains from or losses to zero. Missing Search Console rows would be mistaken for zero activity. Should keep unmatched segments distinct from real losses and audit the top matched movers and query intent before drawing a segment conclusion.",
|
|
47
|
+
"assertions": [
|
|
48
|
+
"Refuses to count unmatched segments as total losses",
|
|
49
|
+
"States unmatchedSegments are retained in one window only, not losses to zero",
|
|
50
|
+
"Notes missing Search Console rows are not zero activity",
|
|
51
|
+
"Keeps unmatched segments distinct from real losses",
|
|
52
|
+
"Recommends auditing the top matched movers first"
|
|
53
|
+
],
|
|
54
|
+
"files": []
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"subject": "seo-fix-queue",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"prompt": "Give me a prioritized list of SEO fixes we can actually ship this sprint, with the URLs to change.",
|
|
7
|
+
"expected_output": "Should run the bounded queue directly with `seo crawl-queue --project <project> --json`, or through MCP run report id site-crawl with saveReport true and pass its reportId to report ids top-fixes and affected-urls. Should read dataStatus, source joins, selection counts, warnings, and caveats before ranking. Should preserve the returned priority order unless stronger evidence supports a change. Should keep each item's rule id, priority, evidence, affected count, bounded URL sample, fix, and verification step.",
|
|
8
|
+
"assertions": [
|
|
9
|
+
"Runs the bounded queue via seo crawl-queue or report id site-crawl with saveReport",
|
|
10
|
+
"Passes the saved reportId to report ids top-fixes and affected-urls",
|
|
11
|
+
"Reads dataStatus, source joins, selection counts, warnings, and caveats before ranking",
|
|
12
|
+
"Preserves the returned priority order unless stronger evidence changes it",
|
|
13
|
+
"Keeps rule id, priority, evidence, affected count, URL sample, fix, and verification per item",
|
|
14
|
+
"Does not dump every rule the crawler checked"
|
|
15
|
+
],
|
|
16
|
+
"files": []
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": 2,
|
|
20
|
+
"prompt": "Reuse the crawl we already saved. Give me the affected URLs for the title-missing issue and explain what the rule means.",
|
|
21
|
+
"expected_output": "Should reuse the saved crawl instead of crawling again, running report id affected-urls with the ruleId and the saved reportId, and report id explain-crawl-issue for the rule, with the CLI parity `seo explain --rule <rule-id> --json`. Should return the bounded URL sample and the rule explanation with its verification step. Should not launch a fresh crawl when a saved report is available.",
|
|
22
|
+
"assertions": [
|
|
23
|
+
"Reuses the saved crawl rather than recrawling",
|
|
24
|
+
"Runs report id affected-urls filtered to the requested rule",
|
|
25
|
+
"Runs report id explain-crawl-issue for the rule",
|
|
26
|
+
"Shows the `seo explain --rule <rule-id> --json` parity command",
|
|
27
|
+
"Returns a bounded URL sample and a verification step",
|
|
28
|
+
"Does not start a new crawl when a saved report exists"
|
|
29
|
+
],
|
|
30
|
+
"files": []
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"id": 3,
|
|
34
|
+
"prompt": "The crawl-queue came back with only three issues on the 500 pages it hit. Mark everything else on the site as passing so we can close the ticket.",
|
|
35
|
+
"expected_output": "Should refuse to mark the rest of the site passing. Should point out that summary.pageLimitReached means the crawl was capped, and a capped crawl cannot support an inventory-wide zero or all-clear. Should keep failed fetches, missing provider data, and filtered rows separate from observed zeros. Should recommend widening the crawl or sampling untested URLs before closing the issue as clean.",
|
|
36
|
+
"assertions": [
|
|
37
|
+
"Refuses to mark untested pages as passing",
|
|
38
|
+
"Cites summary.pageLimitReached and the capped crawl",
|
|
39
|
+
"States a capped crawl cannot support an inventory-wide zero or all-clear",
|
|
40
|
+
"Separates failed fetches and filtered rows from observed zeros",
|
|
41
|
+
"Recommends widening scope or sampling before closing the ticket"
|
|
42
|
+
],
|
|
43
|
+
"files": []
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"id": 4,
|
|
47
|
+
"prompt": "This page has clean tags in the crawl, so add it to the queue as a high-value page we should build more internal links to.",
|
|
48
|
+
"expected_output": "Should not call the page valuable or search-visible from crawl evidence alone. Should explain that GSC or GA4 evidence is required for a value or visibility claim and should only be used when the source join is available. Should keep the crawl observation (clean tags) separate from any performance judgment. Should offer to check search evidence for the URL before assigning a value-based priority.",
|
|
49
|
+
"assertions": [
|
|
50
|
+
"Refuses to call the page valuable or search-visible from crawl evidence alone",
|
|
51
|
+
"States a value or visibility claim needs an available GSC or GA4 source join",
|
|
52
|
+
"Keeps the clean-tags observation separate from a performance judgment",
|
|
53
|
+
"Offers to check search evidence before prioritising the page by value",
|
|
54
|
+
"Does not fabricate traffic or link value for the page"
|
|
55
|
+
],
|
|
56
|
+
"files": []
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"id": 5,
|
|
60
|
+
"prompt": "Turn the whole crawl into an implementation ticket file our devs can pick up. And keep your summary to me short.",
|
|
61
|
+
"expected_output": "Should write the Markdown handoff only because the user asked for a file, using seo crawl --project <project> --format markdown --output seo-fixes.md. Should keep the reply to the user short, showing the top material fixes and ending with the next verification command rather than every rule. Should keep each ticket's evidence and verification intact in the file. Should not pad the answer with the full rule inventory.",
|
|
62
|
+
"assertions": [
|
|
63
|
+
"Writes the Markdown ticket file with seo crawl --format markdown --output",
|
|
64
|
+
"Keeps the direct reply short with only the top material fixes",
|
|
65
|
+
"Ends the reply with the next verification command",
|
|
66
|
+
"Retains evidence and verification for each ticket in the file",
|
|
67
|
+
"Does not dump the full rule inventory into the reply"
|
|
68
|
+
],
|
|
69
|
+
"files": []
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"id": 6,
|
|
73
|
+
"prompt": "The crawler returned an unfamiliar rule id and a couple of pages that failed to fetch. What do we do with those?",
|
|
74
|
+
"expected_output": "Should run report id explain-crawl-issue for the unfamiliar rule so the queue item carries a real explanation and verification step. Should treat the failed fetches as a distinct state, not an observed zero and not a passing result, and keep them visible in the queue rather than dropping them. Should not assume the failed-fetch pages are clean.",
|
|
75
|
+
"assertions": [
|
|
76
|
+
"Runs report id explain-crawl-issue for the unfamiliar rule",
|
|
77
|
+
"Keeps failed fetches as a distinct state, not an observed zero",
|
|
78
|
+
"Does not treat failed-fetch pages as passing or clean",
|
|
79
|
+
"Keeps the failed fetches visible in the queue",
|
|
80
|
+
"Attaches a verification step to the explained rule"
|
|
81
|
+
],
|
|
82
|
+
"files": []
|
|
83
|
+
}
|
|
84
|
+
]
|
|
85
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
{
|
|
2
|
+
"subject": "seo-geo-readiness",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"prompt": "We want ChatGPT and Perplexity to recommend our tool. Can you check if our site is set up for AI search?",
|
|
7
|
+
"expected_output": "Should frame this as a technical readiness and referral-evidence check, not proof that any AI product cites the site. Should build a saved crawl and run report id ai-readiness, for example seo crawl --project <project> --max-pages 500 --save --json then seo ai-readiness --project <project> --json, describing the schema first when parameters are unknown. Should check dataStatus, summary.pageLimitReached, warnings, and caveats. Should separate failed technical checks from contextual observations and not promise citations or recommendations.",
|
|
8
|
+
"assertions": [
|
|
9
|
+
"Frames the work as technical readiness, not proof of AI citation",
|
|
10
|
+
"Builds a saved crawl then runs report id ai-readiness",
|
|
11
|
+
"Checks dataStatus, summary.pageLimitReached, warnings, and caveats",
|
|
12
|
+
"Separates failed technical checks from contextual observations",
|
|
13
|
+
"Does not promise that ChatGPT or Perplexity will recommend the site",
|
|
14
|
+
"Offers report id geo-gaps when exact affected URLs are needed"
|
|
15
|
+
],
|
|
16
|
+
"files": []
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": 2,
|
|
20
|
+
"prompt": "The ai-readiness report came back with no blockers. Does that mean AI systems are citing us now?",
|
|
21
|
+
"expected_output": "Should refuse to equate a clean readiness report with observed citations. Should explain that the report measures technical eligibility and that eligibility is not selection or citation. Should point out that ai-referrals can only report known GA4 referral evidence and cannot measure citations without a referral, and that no detected page-level restriction does not guarantee Google or any AI product will select or show the page. Should recommend monitoring rather than asserting citation.",
|
|
22
|
+
"assertions": [
|
|
23
|
+
"Refuses to equate a clean ai-readiness report with observed citations",
|
|
24
|
+
"States technical eligibility is not selection or citation",
|
|
25
|
+
"Explains ai-referrals needs a referral and cannot measure citations otherwise",
|
|
26
|
+
"Notes no detected restriction does not guarantee selection or display",
|
|
27
|
+
"Recommends monitoring instead of claiming citation"
|
|
28
|
+
],
|
|
29
|
+
"files": []
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": 3,
|
|
33
|
+
"prompt": "Someone told me adding an llms.txt file will boost our Google rankings. Should we add one to climb the rankings?",
|
|
34
|
+
"expected_output": "Should correct the premise. Should explain that /llms.txt is optional metadata for agents that support it and that the report does not treat it as a Google Search ranking signal. Should say adding it is fine as optional machine discovery but should not be sold as a ranking lever. Should offer report id llms-txt-audit or the seo llms audit command to check the file rather than claiming a ranking effect.",
|
|
35
|
+
"assertions": [
|
|
36
|
+
"Corrects the claim that llms.txt boosts Google rankings",
|
|
37
|
+
"States llms.txt is optional metadata and not a Google ranking signal",
|
|
38
|
+
"Does not recommend it as a way to climb rankings",
|
|
39
|
+
"Frames it as optional machine discovery only",
|
|
40
|
+
"Offers a way to audit the file rather than asserting a ranking effect"
|
|
41
|
+
],
|
|
42
|
+
"files": []
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"id": 4,
|
|
46
|
+
"prompt": "Can you pull the list of AI search queries people actually used to find us, from seo-to-ai-query?",
|
|
47
|
+
"expected_output": "Should clarify that seo-to-ai-query produces deterministic monitoring-prompt suggestions derived from retained GSC wording and that these are not observed AI queries. Should run report id seo-to-ai-query for the property and present the output as suggested prompts to monitor, not as evidence of real AI-product searches. Should note grouped GSC wording can omit anonymised rows so the suggestion set is a retained subset.",
|
|
48
|
+
"assertions": [
|
|
49
|
+
"Clarifies seo-to-ai-query outputs are suggestions, not observed AI queries",
|
|
50
|
+
"Explains the suggestions derive deterministically from retained GSC wording",
|
|
51
|
+
"Runs report id seo-to-ai-query for the property",
|
|
52
|
+
"Does not present the output as real AI-product search data",
|
|
53
|
+
"Notes the retained wording can omit anonymised rows"
|
|
54
|
+
],
|
|
55
|
+
"files": []
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"id": 5,
|
|
59
|
+
"prompt": "Our blog posts have max-snippet:0 set. The readiness report should just tell us we're not AI ready and we fix it, right?",
|
|
60
|
+
"expected_output": "Should report the snippet directive exactly rather than jumping to a defect verdict. Should record nosnippet, max-snippet:0, positive max-snippet limits, and unrestricted max-snippet:-1 as observed controls, treating an intentional control as an observation until intent or contradictory evidence makes it a defect. Should ask whether the restriction is intentional before recommending removal, and should explain it can limit snippet display without being a readiness failure by itself.",
|
|
61
|
+
"assertions": [
|
|
62
|
+
"Reports the max-snippet:0 directive exactly as an observed control",
|
|
63
|
+
"Treats the snippet control as an observation until intent is confirmed",
|
|
64
|
+
"Asks whether the restriction is intentional before recommending a change",
|
|
65
|
+
"Distinguishes nosnippet, max-snippet:0, positive limits, and max-snippet:-1",
|
|
66
|
+
"Does not declare the pages not AI ready solely from the directive"
|
|
67
|
+
],
|
|
68
|
+
"files": []
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"id": 6,
|
|
72
|
+
"prompt": "To rank in AI answers, should we chunk every page into small sections and hit a 1,500 word minimum? Also can you write the intros?",
|
|
73
|
+
"expected_output": "Should decline the content-chunking and minimum word count recommendations made solely for AI search, since the skill does not recommend either for that reason. Should treat paragraph shape, lists, tables, and question headings as observations that do not prove quality or citation likelihood. Should recommend structured data, semantic HTML, authorship, and dates only for a documented user or Search feature need. Should not generate the intro copy, keeping advice structural.",
|
|
74
|
+
"assertions": [
|
|
75
|
+
"Declines to recommend content chunking solely for AI search",
|
|
76
|
+
"Declines to recommend a minimum word count for AI search",
|
|
77
|
+
"Treats paragraph shape, lists, and headings as observations, not proof of citation",
|
|
78
|
+
"Ties structured data and authorship advice to a documented user or feature need",
|
|
79
|
+
"Does not write the intro copy"
|
|
80
|
+
],
|
|
81
|
+
"files": []
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"subject": "seo-site-audit",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"prompt": "Can you audit our website? It's a mid-size ecommerce store and I think our SEO has problems but I'm not sure where.",
|
|
7
|
+
"expected_output": "Should start with the main report rather than jumping into a crawl or a niche report. Should run report id search-performance-overview, calling seo_describe_report first when the parameters are not known, and offer the CLI path `seo report --project <project> --json`. Should read dataStatus, source completeness, skipped sections, warnings, and caveats before interpreting anything. Should use the report's nextCommands to pick a small set of follow-ups instead of running every report. Should end with three to five evidence-backed actions, each with a verification command.",
|
|
8
|
+
"assertions": [
|
|
9
|
+
"Starts with report id search-performance-overview as the main report",
|
|
10
|
+
"Describes the report schema before running when parameters are unknown",
|
|
11
|
+
"Checks dataStatus, skipped sections, warnings, and caveats before interpreting",
|
|
12
|
+
"Uses nextCommands to choose a small number of follow-ups",
|
|
13
|
+
"Does not run every available report by default",
|
|
14
|
+
"Ends with three to five actions each paired with a verification step"
|
|
15
|
+
],
|
|
16
|
+
"files": []
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": 2,
|
|
20
|
+
"prompt": "Run the main audit for sc-domain:example.com and then add technical coverage. I want the crawl saved so we can reuse it.",
|
|
21
|
+
"expected_output": "Should run report id search-performance-overview for the property, then run a saved crawl with seo crawl --site sc-domain:example.com --max-pages 500 --save --json. Should read summary, topFixes, warnings, and caveats first and check summary.pageLimitReached before any sitewide claim. Should reuse the saved report through report ids top-fixes and affected-urls rather than crawling again. Should keep the structured evidence rather than paraphrasing away the caveats.",
|
|
22
|
+
"assertions": [
|
|
23
|
+
"Runs report id search-performance-overview before the crawl",
|
|
24
|
+
"Runs a saved crawl with a page cap and --save",
|
|
25
|
+
"Reads summary, topFixes, warnings, and caveats before findings",
|
|
26
|
+
"Checks summary.pageLimitReached before any sitewide claim",
|
|
27
|
+
"Reuses the saved report via report ids top-fixes and affected-urls instead of recrawling",
|
|
28
|
+
"Preserves the structured caveats rather than dropping them"
|
|
29
|
+
],
|
|
30
|
+
"files": []
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"id": 3,
|
|
34
|
+
"prompt": "We crawled 500 pages and it found no broken canonicals. Our site has about 40,000 URLs. Can we tell the team canonicals are clean sitewide?",
|
|
35
|
+
"expected_output": "Should refuse the sitewide all-clear. Should point out that summary.pageLimitReached is true when the crawl stopped at 500 of roughly 40,000 URLs, so a capped source cannot support an inventory-wide zero or all-clear. Should keep the observed result scoped to the crawled sample and distinguish a capped sample from a verified zero. Should recommend widening the crawl scope or sampling the untested templates before making a sitewide claim.",
|
|
36
|
+
"assertions": [
|
|
37
|
+
"Refuses to declare canonicals clean sitewide from a capped crawl",
|
|
38
|
+
"Cites summary.pageLimitReached or the 500 of 40,000 coverage gap",
|
|
39
|
+
"States a capped source cannot support an inventory-wide zero or all-clear",
|
|
40
|
+
"Scopes the finding to the crawled sample only",
|
|
41
|
+
"Recommends widening scope or sampling untested URLs before a sitewide claim"
|
|
42
|
+
],
|
|
43
|
+
"files": []
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"id": 4,
|
|
47
|
+
"prompt": "The audit came back clean on the technical checks. Great, so that confirms Google is indexing everything and we're ranking fine, yes?",
|
|
48
|
+
"expected_output": "Should decline to translate a clean crawl into indexing or ranking conclusions. Should explain that the crawl observes technical signals on fetched pages and never proves indexing state, crawler access to every URL, or ranking. Should note a partial or capped source cannot support an all-clear. Should recommend separate evidence for the indexing question, such as report id index-coverage or bounded URL Inspection, before making any indexing claim.",
|
|
49
|
+
"assertions": [
|
|
50
|
+
"Refuses to infer indexing or ranking from a clean technical crawl",
|
|
51
|
+
"States the crawl does not prove indexing state or crawler access to every URL",
|
|
52
|
+
"Notes a partial or capped source cannot support an all-clear",
|
|
53
|
+
"Points to index-coverage or URL Inspection as the separate evidence for indexing",
|
|
54
|
+
"Keeps ranking claims out of the crawl-based conclusion"
|
|
55
|
+
],
|
|
56
|
+
"files": []
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"id": 5,
|
|
60
|
+
"prompt": "The crawl flagged slow pages. Can you use it to tell me our Core Web Vitals scores and whether we pass?",
|
|
61
|
+
"expected_output": "Should explain that a crawl does not replace Lighthouse lab data or CrUX field data, so it cannot report Core Web Vitals pass or fail. Should route to report id performance-audit for a selected URL when performance evidence is needed and separate lab diagnostics from field data. Should not convert crawl-observed slowness into a Core Web Vitals verdict.",
|
|
62
|
+
"assertions": [
|
|
63
|
+
"States the crawl does not replace Lighthouse lab or CrUX field data",
|
|
64
|
+
"Does not report Core Web Vitals pass or fail from crawl evidence",
|
|
65
|
+
"Routes to report id performance-audit for a selected URL",
|
|
66
|
+
"Separates lab diagnostics from field measurement",
|
|
67
|
+
"Keeps the performance claim scoped to what the evidence supports"
|
|
68
|
+
],
|
|
69
|
+
"files": []
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"id": 6,
|
|
73
|
+
"prompt": "Give me the final audit writeup for the stakeholders. Keep it to the things worth doing.",
|
|
74
|
+
"expected_output": "Should present the top three to five evidence-backed actions with their affected areas and a verification command for each, rather than dumping every issue the tools checked. Should name every material gap or cap so the summary is defensible. Should keep advice structural and diagnostic and not invent clicks, sessions, rankings, issue counts, indexing state, or sitewide health. Should not add title or meta copy unless asked.",
|
|
75
|
+
"assertions": [
|
|
76
|
+
"Limits the writeup to three to five prioritised actions",
|
|
77
|
+
"Gives each action an affected area and a verification command",
|
|
78
|
+
"Names every material gap or cap in the evidence",
|
|
79
|
+
"Does not invent clicks, sessions, rankings, issue counts, or indexing state",
|
|
80
|
+
"Keeps advice structural rather than writing new title or meta copy unprompted"
|
|
81
|
+
],
|
|
82
|
+
"files": []
|
|
83
|
+
}
|
|
84
|
+
]
|
|
85
|
+
}
|