seo 0.2.14 → 0.2.15

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.
@@ -0,0 +1,58 @@
1
+ {
2
+ "subject": "keyword-metrics",
3
+ "evals": [
4
+ {
5
+ "id": 1,
6
+ "prompt": "Compare search volume, difficulty, intent, and recent demand for a keyword list before we choose what to research.",
7
+ "expected_output": "Should use report id keyword-metrics for a bounded list of independent market estimates. Should follow the discovery flow: seo_list_reports with category opportunities, seo_describe_report with id keyword-metrics, then seo_run_report with keywords, countryCode, and languageCode from the described schema. Should read dataStatus and summary first, then provider coverage, warnings, cache, cost, and each metric state before the trend analysis. Should say provider estimates are prioritization context, not measured traffic, ranking probability, or a demand forecast.",
8
+ "assertions": [
9
+ "Uses report id keyword-metrics for the independent estimates",
10
+ "Follows seo_list_reports, seo_describe_report, seo_run_report in order",
11
+ "Passes bounded keywords, countryCode, and languageCode",
12
+ "Reads dataStatus, coverage, warnings, cache, cost, and metric states before trends",
13
+ "States provider estimates are not measured traffic, ranking probability, or a forecast"
14
+ ],
15
+ "files": []
16
+ },
17
+ {
18
+ "id": 2,
19
+ "prompt": "Run keyword metrics for seo audit tool and technical seo audit in the UK, English, mobile, using DataForSEO and fresh data.",
20
+ "expected_output": "Should run report id keyword-metrics with keywords [seo audit tool, technical seo audit], countryCode GB, languageCode en, device mobile, provider dataforseo, and refresh true. Should keep the device caveat visible because keyword metrics are market-level estimates rather than device-segmented values. Should inspect request cost, cache status, provider warnings, and coverage before summarizing the numbers. Should use only parameters defined in the report schema.",
21
+ "assertions": [
22
+ "Runs keyword-metrics with both requested keywords",
23
+ "Uses countryCode GB, languageCode en, and device mobile",
24
+ "Selects provider dataforseo and refresh true",
25
+ "Keeps the market-level device caveat visible",
26
+ "Inspects cost, cache, warnings, and coverage",
27
+ "Uses only parameters defined in the report schema"
28
+ ],
29
+ "files": []
30
+ },
31
+ {
32
+ "id": 3,
33
+ "prompt": "One keyword has volume 0 and difficulty 12. Another has missing volume and difficulty 80. The first one has no demand and will be easy to rank, while the second is impossible. Right?",
34
+ "expected_output": "Should reject every conclusion. Should keep observed zero separate from missing volume, state that a zero estimate does not prove nobody searches, and not convert missing data into zero. Should state keyword difficulty is a provider metric rather than a ranking probability or site-specific feasibility verdict. Should recommend comparing both terms with Search Console evidence and inspecting a current result page in the same market before choosing work.",
35
+ "assertions": [
36
+ "Keeps observed zero separate from missing volume",
37
+ "States zero estimated volume does not prove no demand",
38
+ "Does not turn missing volume into zero",
39
+ "States difficulty is not a ranking probability or site-specific feasibility verdict",
40
+ "Recommends Search Console and current result-page verification"
41
+ ],
42
+ "files": []
43
+ },
44
+ {
45
+ "id": 4,
46
+ "prompt": "The report labels a keyword as increasing by 40%, so forecast the traffic from a new programmatic template and tell me which competitor we will beat.",
47
+ "expected_output": "Should refuse to forecast traffic or name a competitor from keyword metrics. Should explain that the increasing label is a heuristic comparing the latest three provider estimates with the preceding three and does not forecast future demand. Should state the report contains no current result snapshot, competitor ranking evidence, or proof that a programmatic template fits the intent. Should recommend first-party Search Console comparison, current result inspection, competitor research, and representative template validation before scaling.",
48
+ "assertions": [
49
+ "Refuses to forecast traffic from the trend label",
50
+ "Explains the two three-month trend heuristic",
51
+ "States keyword metrics contains no current result or competitor ranking evidence",
52
+ "Does not claim a programmatic template fits the intent",
53
+ "Recommends Search Console, result-page, competitor, and representative template validation"
54
+ ],
55
+ "files": []
56
+ }
57
+ ]
58
+ }
@@ -0,0 +1,57 @@
1
+ {
2
+ "subject": "keyword-opportunities",
3
+ "evals": [
4
+ {
5
+ "id": 1,
6
+ "prompt": "Find the best keyword opportunities already visible in Search Console and show me where repeated page patterns might matter.",
7
+ "expected_output": "Should use report id keyword-opportunities after discovery and description. Should run it with the site and bounded defaults without external enrichment unless the user explicitly asks for a paid provider request. Should read source completeness and the quick-win, second-page, and striking-distance selections before combined keywords or clusters. Should treat overlapping signals as views of the same retained rows rather than independent confirmations.",
8
+ "assertions": [
9
+ "Uses report id keyword-opportunities through discovery and description",
10
+ "Runs first-party analysis without silently requesting paid external data",
11
+ "Reads source completeness and all three selection states before combined output",
12
+ "Does not treat overlapping first-party signals as independent confirmations",
13
+ "Uses clusters as validation prompts rather than automatic page decisions"
14
+ ],
15
+ "files": []
16
+ },
17
+ {
18
+ "id": 2,
19
+ "prompt": "Enrich my Search Console keyword opportunities with fresh UK mobile DataForSEO estimates and keep costs visible.",
20
+ "expected_output": "Should run keyword-opportunities with includeExternal true, countryCode GB, languageCode en, device mobile, provider dataforseo, and refresh true. Should inspect external status, selection, coverage, warnings, cache, request, and cost before using values. Should keep first-party evidence and provider estimates separate, preserve missing and zero states, and not alter the existing first-party priority scores.",
21
+ "assertions": [
22
+ "Uses explicit includeExternal true with the requested market, device, provider, and refresh",
23
+ "Reads external status, selection, coverage, warnings, cache, request, and cost",
24
+ "Keeps Search Console evidence separate from provider estimates",
25
+ "Preserves missing and observed-zero states",
26
+ "Does not blend external estimates into first-party priority scores"
27
+ ],
28
+ "files": []
29
+ },
30
+ {
31
+ "id": 3,
32
+ "prompt": "The report found a keyword cluster across several repeated URLs. Create the whole programmatic section now.",
33
+ "expected_output": "Should not create or recommend scaling a template from the cluster alone. Should state the cluster comes from the returned opportunity-keyword subset and token or URL-pattern heuristics do not prove shared intent. Should use the dataSourcePrompts as a validation brief, then recommend checking stable entity IDs, source provenance, required fields, missing-value rules, page uniqueness, internal links, representative pages, and the pseo-audit report before expansion.",
34
+ "assertions": [
35
+ "Does not scale a template from cluster evidence alone",
36
+ "States the cluster population is the returned opportunity subset",
37
+ "States cluster and URL patterns do not prove shared intent",
38
+ "Uses the data-source prompt as a validation brief",
39
+ "Recommends representative validation and pseo-audit before expansion"
40
+ ],
41
+ "files": []
42
+ },
43
+ {
44
+ "id": 4,
45
+ "prompt": "A keyword has Search Console impressions, provider volume zero, and average position 7. That means the provider is wrong and we rank exactly seventh, right?",
46
+ "expected_output": "Should reject both conclusions. Should explain that Search Console impressions and an independent provider zero describe different datasets, so the discrepancy is useful review evidence but does not prove the provider is universally wrong. Should explain that Search Console average position is impression weighted and not an exact rank. Should recommend checking external provenance and market settings plus a current result snapshot before deciding.",
47
+ "assertions": [
48
+ "Does not declare the provider universally wrong",
49
+ "Explains that first-party impressions and provider zero have different source semantics",
50
+ "Does not claim average position is exact rank",
51
+ "Treats the discrepancy as review evidence",
52
+ "Recommends market, provenance, and current result verification"
53
+ ],
54
+ "files": []
55
+ }
56
+ ]
57
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "subject": "keyword-research",
3
+ "evals": [
4
+ {
5
+ "id": 1,
6
+ "prompt": "Find related keyword ideas for local SEO software in the UK before we decide what to build.",
7
+ "expected_output": "Should use report id keyword-research through seo_list_reports, seo_describe_report, and seo_run_report. Should pass a bounded seed list with countryCode GB and languageCode en. Should read dataStatus and summary, then evidence coverage, cache, cost, warnings, source evidence, and each metric state. Should treat discovered terms as research candidates rather than page recommendations.",
8
+ "assertions": [
9
+ "Uses report id keyword-research through the discovery flow",
10
+ "Passes bounded seeds with countryCode GB and languageCode en",
11
+ "Reads coverage, cache, cost, warnings, sources, and metric states",
12
+ "Treats discovered terms as candidates rather than page recommendations"
13
+ ],
14
+ "files": []
15
+ },
16
+ {
17
+ "id": 2,
18
+ "prompt": "Use ideas and suggestions for two seeds, return 40 fresh DataForSEO results for US English, and tell me which terms overlap.",
19
+ "expected_output": "Should run keyword-research with the two seeds, sources [ideas, suggestions], limit 40, countryCode US, languageCode en, provider dataforseo, and refresh true. Should inspect each keyword sources array and explain that source overlap is descriptive provider evidence, not independent confirmation of demand, shared intent, or ranking feasibility.",
20
+ "assertions": [
21
+ "Runs keyword-research with both seeds and the requested sources",
22
+ "Uses limit 40, US English, DataForSEO, and refresh true",
23
+ "Inspects the sources array for overlap",
24
+ "Does not call source overlap independent confirmation or ranking feasibility"
25
+ ],
26
+ "files": []
27
+ },
28
+ {
29
+ "id": 3,
30
+ "prompt": "These discovered keywords have good volume and low difficulty, so make a programmatic page for every one and forecast the traffic.",
31
+ "expected_output": "Should reject the page-per-keyword plan and traffic forecast. Should state that volume and difficulty are provider estimates, discovered terms may share intent, and the report contains no site-specific ranking feasibility. Should recommend live result review, first-party Search Console comparison where relevant, clustering by intent, and representative template validation before scaling.",
32
+ "assertions": [
33
+ "Rejects a page for every discovered keyword",
34
+ "Refuses to forecast traffic from provider estimates",
35
+ "States the report does not prove shared intent or ranking feasibility",
36
+ "Recommends result review, first-party comparison, intent clustering, and template validation"
37
+ ],
38
+ "files": []
39
+ }
40
+ ]
41
+ }
@@ -0,0 +1,57 @@
1
+ {
2
+ "subject": "pseo-opportunities",
3
+ "evals": [
4
+ {
5
+ "id": 1,
6
+ "prompt": "Find programmatic SEO opportunities from the templates and query clusters that already work on my site.",
7
+ "expected_output": "Should use report id pseo-opportunities through the shared discover, describe, and run flow. Should run the first-party pass without external acquisition unless the user explicitly asks for paid provider work. Should read pseoAudit and queryClusters before any candidate or action, keep returned subsets and heuristics visible, and recommend a small external rerun only when it would change the decision.",
8
+ "assertions": [
9
+ "Uses report id pseo-opportunities through the shared report flow",
10
+ "Runs the first-party pass without silently spending on a provider",
11
+ "Reads template and query-cluster evidence before recommendations",
12
+ "Keeps returned subsets and heuristics visible",
13
+ "Recommends bounded external research only when useful"
14
+ ],
15
+ "files": []
16
+ },
17
+ {
18
+ "id": 2,
19
+ "prompt": "Enrich the strongest pSEO opportunities with UK mobile keyword discovery and three live result checks. Show me likely competitors and cost.",
20
+ "expected_output": "Should run pseo-opportunities with includeExternal true, countryCode GB, languageCode en, device mobile, serpLimit 3, and bounded discovery and result depth. Should inspect discovery and SERP coverage, warnings, cache, request, evidence states, and aggregate known versus unknown cost. Should treat repeated competitor domains and URL patterns as snapshot context, not authority, quality, or ranking feasibility.",
21
+ "assertions": [
22
+ "Uses explicit external market, device, discovery, and SERP limits",
23
+ "Reads provider coverage, warnings, cache, request, value states, and cost",
24
+ "Keeps Search Console evidence separate from provider estimates and live results",
25
+ "Treats competitor patterns as snapshot observations",
26
+ "Does not turn competitor frequency into authority or ranking feasibility"
27
+ ],
28
+ "files": []
29
+ },
30
+ {
31
+ "id": 3,
32
+ "prompt": "The report found 200 related terms and a competitor with thousands of directory pages. Build all the combinations for us.",
33
+ "expected_output": "Should refuse to recommend combinatorial generation from term count or a competitor URL pattern. Should separate a search-evidenced template expansion from new-template research, inspect shared intent and representative result pages, and use the dataSourceBriefs to verify entities, fields, identifiers, coverage, freshness, rights, missing-value stop conditions, bounded inventory, duplicate prevention, crawl controls, and internal links before proposing pages.",
34
+ "assertions": [
35
+ "Does not recommend combinatorial page generation",
36
+ "Separates existing-template expansion from new-template research",
37
+ "Requires shared-intent and representative-result review",
38
+ "Uses the data-source brief as a research checklist rather than proof",
39
+ "Requires bounded inventory and technical controls before expansion"
40
+ ],
41
+ "files": []
42
+ },
43
+ {
44
+ "id": 4,
45
+ "prompt": "A discovered keyword is missing from Search Console and has volume 500, so this proves we need a new template, right?",
46
+ "expected_output": "Should reject the conclusion. Should explain that absence from retained Search Console rows is not a definitive zero and provider volume is an estimate. Should check whether the candidate came from a search-evidenced template seed or an unmapped query cluster, inspect the live results and existing pages, and validate a defensible data source before choosing a hub, editorial page, template extension, new template, or no page.",
47
+ "assertions": [
48
+ "Does not treat a missing retained Search Console row as zero",
49
+ "Does not treat provider volume as proof a new template is needed",
50
+ "Checks the candidate classification and supporting evidence",
51
+ "Requires live-result and existing-page review",
52
+ "Keeps no new page as a valid outcome"
53
+ ],
54
+ "files": []
55
+ }
56
+ ]
57
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "subject": "serp-results",
3
+ "evals": [
4
+ {
5
+ "id": 1,
6
+ "prompt": "Show me the current mobile Google results for local SEO software in London.",
7
+ "expected_output": "Should use report id serp-results through seo_list_reports, seo_describe_report, and seo_run_report. Should pass one bounded keyword, a London location, device mobile, and the required country and language fields from the described schema. Should read dataStatus, summary, checkedAt, market, coverage, cache, cost, warnings, and exact organic ranks before describing the snapshot.",
8
+ "assertions": [
9
+ "Uses report id serp-results through the discovery flow",
10
+ "Passes one keyword with London and mobile market context",
11
+ "Reads checkedAt, coverage, cache, cost, warnings, and exact ranks",
12
+ "Describes the result as a snapshot"
13
+ ],
14
+ "files": []
15
+ },
16
+ {
17
+ "id": 2,
18
+ "prompt": "Two results from the same domain appear in the top ten. That proves the domain is strong and we cannot compete, right?",
19
+ "expected_output": "Should reject both conclusions. Should say repeated-domain evidence only describes one bounded market and device snapshot. It does not prove authority, content quality, weakness, or site-specific ranking feasibility. Should recommend reviewing the retained pages and intent, adding separate domain or backlink evidence when available, and repeating the same snapshot if stability matters.",
20
+ "assertions": [
21
+ "Rejects strength and cannot-compete conclusions",
22
+ "Treats repeated domains as descriptive snapshot evidence",
23
+ "Does not infer authority, quality, or ranking feasibility",
24
+ "Recommends page, intent, separate authority evidence, and repeat-snapshot review"
25
+ ],
26
+ "files": []
27
+ },
28
+ {
29
+ "id": 3,
30
+ "prompt": "Search Console says average position 8 but this report shows rank 3. Which rank is the real one?",
31
+ "expected_output": "Should keep the measurements separate. Should explain that Search Console average position aggregates observed impressions across time and contexts, while serp-results is one exact provider snapshot for a stated location, language, device, and time. Should not call either value universally real or use one to invalidate the other. Should recommend matching market, device, date, and query before comparing them.",
32
+ "assertions": [
33
+ "Keeps Search Console average position separate from snapshot rank",
34
+ "Explains the different source semantics",
35
+ "Does not declare one value universally real",
36
+ "Recommends matching market, device, date, and query"
37
+ ],
38
+ "files": []
39
+ }
40
+ ]
41
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "seo",
3
- "version": "0.2.14",
3
+ "version": "0.2.15",
4
4
  "description": "The only SEO skill your agent needs. 50+ SEO audit tools through a local CLI and MCP server, using your own crawl, Search Console, and Google Analytics data.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -74,9 +74,9 @@
74
74
  "security:check": "pnpm run security:audit && pnpm run security:secrets",
75
75
  "security:secrets": "node scripts/security-secrets.mjs",
76
76
  "skills:validate": "node scripts/validate-skills.mjs",
77
- "test": "turbo run test && pnpm run build:package && node --test scripts/package.test.mjs scripts/dogfood-summary.test.mjs && node scripts/resource-harness.mjs && node scripts/provider-resource-harness.mjs && node scripts/indexnow-resource-harness.mjs && node scripts/bing-resource-harness.mjs && pnpm run skills:validate",
78
- "test:resources": "pnpm run build:package && node scripts/resource-harness.mjs && node scripts/provider-resource-harness.mjs && node scripts/indexnow-resource-harness.mjs && node scripts/bing-resource-harness.mjs",
79
- "test:package-install": "pnpm run build:package && node --test scripts/installed-package.test.mjs",
77
+ "test": "turbo run test && pnpm run build:package && node --test scripts/package.test.mjs scripts/dogfood-summary.test.mjs && node scripts/resource-harness.mjs && node scripts/provider-resource-harness.mjs && node scripts/pseo-resource-harness.mjs && node scripts/indexnow-resource-harness.mjs && node scripts/bing-resource-harness.mjs && pnpm run skills:validate",
78
+ "test:resources": "pnpm run build:package && node scripts/resource-harness.mjs && node scripts/provider-resource-harness.mjs && node scripts/pseo-resource-harness.mjs && node scripts/indexnow-resource-harness.mjs && node scripts/bing-resource-harness.mjs",
79
+ "test:package-install": "pnpm --filter @seo/core build && pnpm --filter @seo/mcp build && pnpm run build:package && node --test scripts/installed-package.test.mjs",
80
80
  "typecheck": "turbo run typecheck"
81
81
  },
82
82
  "dependencies": {