seo 0.0.15 → 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/LICENSE +201 -0
- package/PRIVACY.md +95 -0
- package/README.md +431 -35
- package/SECURITY.md +55 -0
- package/TERMS.md +94 -0
- package/TRADEMARKS.md +31 -0
- package/dist/cli.js +141 -0
- package/dist/cli.js.map +1 -0
- package/dist/dist-6bK_8r5M.js +713 -0
- package/dist/dist-6bK_8r5M.js.map +1 -0
- package/dist/dist-vRmqfhR4.js +3 -0
- package/dist/index.d.ts +18013 -0
- package/dist/index.js +27197 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp.d.ts +74 -0
- package/dist/mcp.js +28611 -0
- package/dist/mcp.js.map +1 -0
- package/dist/package-7aT8_Xp0.js +23818 -0
- package/dist/package-7aT8_Xp0.js.map +1 -0
- 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 +103 -23
- package/skills/README.md +68 -0
- package/skills/seo/SKILL.md +99 -0
- package/skills/seo/agents/openai.yaml +4 -0
- package/.jshintrc +0 -18
- package/.npmignore +0 -3
- package/.travis.yml +0 -3
- package/Makefile +0 -10
- package/index.js +0 -2
- package/lib/middleware.js +0 -159
- package/lib/seo.js +0 -32
- package/test/init.js +0 -43
- package/test/middleware.test.js +0 -111
- package/test/seo-page-result.html +0 -9
- package/test/seo-page.html +0 -9
- package/test/seo-routes.js +0 -5
- package/test/vendor/jquery-1.11.1.min.js +0 -4
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","names":["readConfig","shellArg","truncate","truncate","urlListArgs","crawlUrlArg","crawlModeArg","writeOrPrint","parseUrlList","truncate","formatNumber","truncate","today","changeScope","writeOrPrint","truncate","truncate","truncate","truncate","truncate","truncate","truncate","truncate","truncate","truncate","truncate","truncate","truncate","truncate","truncate","truncate","readConfig","truncate","truncate","listCommand","runCommand","truncate"],"sources":["../packages/core/dist/export/update-postmortem.js","../packages/core/dist/ga4/matching.js","../packages/core/dist/utils/time.js","../packages/cli/src/args.ts","../packages/cli/src/utils.ts","../packages/cli/src/commands/auth.ts","../packages/cli/src/commands/cache.ts","../packages/cli/src/selection.ts","../packages/cli/src/commands/shared.ts","../packages/cli/src/commands/mcp-clients.ts","../packages/cli/src/commands/mcp-config.ts","../packages/cli/src/commands/setup/prompts.ts","../packages/cli/src/commands/setup/flow.ts","../packages/cli/src/commands/setup/index.ts","../packages/cli/src/commands/clients/brand.ts","../packages/cli/src/commands/clients/profiles/output.ts","../packages/cli/src/commands/clients/profiles/add.ts","../packages/cli/src/commands/clients/profiles/default.ts","../packages/cli/src/commands/clients/profiles/delete.ts","../packages/cli/src/commands/clients/profiles/list.ts","../packages/cli/src/commands/clients/profiles/show.ts","../packages/cli/src/commands/clients/profiles.ts","../packages/cli/src/commands/clients/index.ts","../packages/cli/src/commands/output.ts","../packages/cli/src/commands/content.ts","../packages/cli/src/commands/crawl.ts","../packages/cli/src/commands/crawl-reports.ts","../packages/cli/src/commands/data.ts","../packages/cli/src/commands/report-options.ts","../packages/cli/src/commands/diagnosis-reports.ts","../packages/cli/src/commands/readiness.ts","../packages/cli/src/commands/entity-readiness.ts","../packages/cli/src/commands/experiments/change-log.ts","../packages/cli/src/commands/experiments/content-groups.ts","../packages/cli/src/commands/experiments/tests.ts","../packages/cli/src/progress.ts","../packages/cli/src/commands/reports/args.ts","../packages/cli/src/commands/export/shared.ts","../packages/cli/src/commands/export/diagnose.ts","../packages/cli/src/commands/okf-files.ts","../packages/cli/src/commands/export/knowledge.ts","../packages/cli/src/commands/export/monthly.ts","../packages/cli/src/commands/export/narrative.ts","../packages/cli/src/commands/pseo/options.ts","../packages/cli/src/commands/export/pseo.ts","../packages/cli/src/commands/export/refresh-priorities.ts","../packages/cli/src/commands/export/update-postmortem.ts","../packages/cli/src/commands/export/index.ts","../packages/cli/src/commands/init.ts","../packages/cli/src/commands/llms.ts","../packages/cli/src/commands/mcp.ts","../packages/cli/src/commands/monitoring/crawl-diff.ts","../packages/cli/src/commands/monitoring/args.ts","../packages/cli/src/commands/workflows/output.ts","../packages/cli/src/commands/monitoring/output.ts","../packages/cli/src/commands/monitoring/index.ts","../packages/cli/src/commands/monitoring/index-coverage.ts","../packages/cli/src/commands/monitoring/index-watch.ts","../packages/cli/src/commands/monitoring/link-recover.ts","../packages/cli/src/commands/monitoring/redirect-trace.ts","../packages/cli/src/commands/okf.ts","../packages/cli/src/commands/opportunities/ai-referrals.ts","../packages/cli/src/commands/opportunities/cannibal.ts","../packages/cli/src/commands/opportunities/community-intent.ts","../packages/cli/src/commands/opportunities/ctr.ts","../packages/cli/src/commands/opportunities/decaying.ts","../packages/cli/src/commands/opportunities/internal-links.ts","../packages/cli/src/commands/opportunities/page-opportunities.ts","../packages/cli/src/commands/opportunities/query-cluster.ts","../packages/cli/src/commands/opportunities/quick-wins.ts","../packages/cli/src/commands/opportunities/second-page.ts","../packages/cli/src/commands/opportunities/seo-to-ai-query.ts","../packages/cli/src/commands/page-audit.ts","../packages/cli/src/commands/performance.ts","../packages/cli/src/commands/product/diagnose.ts","../packages/cli/src/commands/product/doctor.ts","../packages/cli/src/commands/product/ga4-properties.ts","../packages/cli/src/commands/product/segment-impact.ts","../packages/cli/src/commands/product/striking-distance.ts","../packages/cli/src/commands/pseo/audit.ts","../packages/cli/src/commands/pseo/index.ts","../packages/cli/src/commands/report-catalog.ts","../packages/cli/src/commands/reports/monthly.ts","../packages/cli/src/commands/reports/narrative.ts","../packages/cli/src/commands/rules.ts","../packages/cli/src/commands/schedule.ts","../packages/cli/src/commands/skill-paths.ts","../packages/cli/src/commands/skills-eval.ts","../packages/cli/src/commands/skills.ts","../packages/cli/src/commands/system.ts","../packages/cli/src/commands/workflows/crawl-queue.ts","../packages/cli/src/commands/workflows/diagnose-property.ts","../packages/cli/src/commands/workflows/refresh-priorities.ts","../packages/cli/src/commands/workflows/technical-watch.ts","../packages/cli/src/commands/workflows/update-postmortem.ts","../packages/cli/src/index.ts"],"sourcesContent":["const HEADERS = {\n summary: [\n 'workflow',\n 'site',\n 'generated_at',\n 'summary',\n 'attribution',\n 'confidence',\n 'classification',\n 'updates_matched',\n 'known_confounders',\n 'page_segment_status',\n 'page_segment_eligible_rows',\n 'page_segment_returned_rows',\n 'page_segment_limited_rows',\n 'page_segment_result_limit',\n 'page_segment_source_row_limit',\n 'page_segment_source_possibly_truncated',\n 'page_segment_warnings',\n 'query_segment_status',\n 'query_segment_eligible_rows',\n 'query_segment_returned_rows',\n 'query_segment_limited_rows',\n 'query_segment_result_limit',\n 'query_segment_source_row_limit',\n 'query_segment_source_possibly_truncated',\n 'query_segment_warnings',\n 'device_segment_status',\n 'device_segment_eligible_rows',\n 'device_segment_returned_rows',\n 'device_segment_limited_rows',\n 'device_segment_result_limit',\n 'device_segment_source_row_limit',\n 'device_segment_source_possibly_truncated',\n 'device_segment_warnings',\n 'country_segment_status',\n 'country_segment_eligible_rows',\n 'country_segment_returned_rows',\n 'country_segment_limited_rows',\n 'country_segment_result_limit',\n 'country_segment_source_row_limit',\n 'country_segment_source_possibly_truncated',\n 'country_segment_warnings',\n ],\n steps: ['rank', 'tool', 'status', 'summary'],\n actions: ['rank', 'title', 'confidence', 'action'],\n findings: [\n 'dimension',\n 'data_status',\n 'eligible_rows',\n 'returned_rows',\n 'limited_rows',\n 'result_limit',\n 'unmatched_rows',\n 'summary',\n 'winner_key',\n 'winner_click_delta',\n 'winner_impression_delta',\n 'winner_position_delta',\n 'loser_key',\n 'loser_click_delta',\n 'loser_impression_delta',\n 'loser_position_delta',\n ],\n templates: [\n 'rank',\n 'direction',\n 'template',\n 'confidence',\n 'url_count',\n 'click_delta',\n 'impression_delta',\n 'movement_share',\n 'movement_share_scope',\n 'confidence_scope',\n 'eligible_rows',\n 'returned_rows',\n 'limited_rows',\n 'result_limit',\n 'source_possibly_truncated',\n 'common_terms',\n 'sample_urls',\n 'summary',\n ],\n evidence: ['rank', 'evidence'],\n confounders: [\n 'rank',\n 'source',\n 'title',\n 'date',\n 'scope',\n 'target',\n 'description',\n ],\n segment: [\n 'rank',\n 'dimension',\n 'data_status',\n 'evidence_scope',\n 'key',\n 'before_clicks',\n 'after_clicks',\n 'click_delta',\n 'before_impressions',\n 'after_impressions',\n 'impression_delta',\n 'before_position',\n 'after_position',\n 'position_delta',\n ],\n unmatchedSegment: [\n 'rank',\n 'dimension',\n 'data_status',\n 'key',\n 'retained_in',\n 'clicks',\n 'impressions',\n 'position',\n 'reason',\n ],\n};\nfunction postmortemSegmentRows(report, dimension) {\n return [\n ...report.output.segments[dimension].winners,\n ...report.output.segments[dimension].losers,\n ].map((item, index) => ({\n rank: index + 1,\n dimension,\n data_status: report.output.segments[dimension].dataStatus,\n evidence_scope: item.evidenceScope,\n key: item.key,\n before_clicks: item.beforeClicks,\n after_clicks: item.afterClicks,\n click_delta: item.clickDelta,\n before_impressions: item.beforeImpressions,\n after_impressions: item.afterImpressions,\n impression_delta: item.impressionDelta,\n before_position: item.beforePosition,\n after_position: item.afterPosition,\n position_delta: item.positionDelta,\n }));\n}\nfunction postmortemUnmatchedSegmentRows(report, dimension) {\n return report.output.segments[dimension].unmatchedSegments.map((item, index) => ({\n rank: index + 1,\n dimension,\n data_status: report.output.segments[dimension].dataStatus,\n key: item.key,\n retained_in: item.retainedIn,\n clicks: item.clicks,\n impressions: item.impressions,\n position: item.position,\n reason: item.reason,\n }));\n}\nexport function updatePostmortemCsvFiles(report) {\n return [\n {\n filename: 'postmortem-summary.csv',\n headers: [...HEADERS.summary],\n rows: [\n {\n workflow: report.workflow,\n site: report.site,\n generated_at: report.generatedAt,\n summary: report.summary,\n attribution: report.output.update.attribution,\n confidence: report.output.update.confidence,\n classification: report.output.update.classification,\n updates_matched: report.output.update.overlappingUpdates.length,\n known_confounders: report.output.update.confounders.length,\n page_segment_status: report.output.segments.page.dataStatus,\n page_segment_eligible_rows: report.output.segments.page.coverage.eligibleRows,\n page_segment_returned_rows: report.output.segments.page.coverage.returnedRows,\n page_segment_limited_rows: report.output.segments.page.coverage.limitedRows,\n page_segment_result_limit: report.output.segments.page.coverage.resultLimit,\n page_segment_source_row_limit: report.output.segments.page.coverage.sourceRowLimit,\n page_segment_source_possibly_truncated: report.output.segments.page.coverage.sourcePossiblyTruncated,\n page_segment_warnings: report.output.segments.page.warnings.join('; '),\n query_segment_status: report.output.segments.query.dataStatus,\n query_segment_eligible_rows: report.output.segments.query.coverage.eligibleRows,\n query_segment_returned_rows: report.output.segments.query.coverage.returnedRows,\n query_segment_limited_rows: report.output.segments.query.coverage.limitedRows,\n query_segment_result_limit: report.output.segments.query.coverage.resultLimit,\n query_segment_source_row_limit: report.output.segments.query.coverage.sourceRowLimit,\n query_segment_source_possibly_truncated: report.output.segments.query.coverage.sourcePossiblyTruncated,\n query_segment_warnings: report.output.segments.query.warnings.join('; '),\n device_segment_status: report.output.segments.device.dataStatus,\n device_segment_eligible_rows: report.output.segments.device.coverage.eligibleRows,\n device_segment_returned_rows: report.output.segments.device.coverage.returnedRows,\n device_segment_limited_rows: report.output.segments.device.coverage.limitedRows,\n device_segment_result_limit: report.output.segments.device.coverage.resultLimit,\n device_segment_source_row_limit: report.output.segments.device.coverage.sourceRowLimit,\n device_segment_source_possibly_truncated: report.output.segments.device.coverage.sourcePossiblyTruncated,\n device_segment_warnings: report.output.segments.device.warnings.join('; '),\n country_segment_status: report.output.segments.country.dataStatus,\n country_segment_eligible_rows: report.output.segments.country.coverage.eligibleRows,\n country_segment_returned_rows: report.output.segments.country.coverage.returnedRows,\n country_segment_limited_rows: report.output.segments.country.coverage.limitedRows,\n country_segment_result_limit: report.output.segments.country.coverage.resultLimit,\n country_segment_source_row_limit: report.output.segments.country.coverage.sourceRowLimit,\n country_segment_source_possibly_truncated: report.output.segments.country.coverage.sourcePossiblyTruncated,\n country_segment_warnings: report.output.segments.country.warnings.join('; '),\n },\n ],\n },\n {\n filename: 'workflow-steps.csv',\n headers: [...HEADERS.steps],\n rows: report.steps.map((step, index) => ({\n rank: index + 1,\n tool: step.tool,\n status: step.status,\n summary: step.summary,\n })),\n },\n {\n filename: 'workflow-actions.csv',\n headers: [...HEADERS.actions],\n rows: report.actions.map((action, index) => ({\n rank: index + 1,\n title: action.title,\n confidence: action.confidence,\n action: action.action,\n })),\n },\n {\n filename: 'postmortem-findings.csv',\n headers: [...HEADERS.findings],\n rows: report.output.insights.map((item) => ({\n dimension: item.dimension,\n data_status: item.dataStatus,\n eligible_rows: item.coverage.eligibleRows,\n returned_rows: item.coverage.returnedRows,\n limited_rows: item.coverage.limitedRows,\n result_limit: item.coverage.resultLimit,\n unmatched_rows: item.unmatchedRows,\n summary: item.summary,\n winner_key: item.winner?.key,\n winner_click_delta: item.winner?.clickDelta,\n winner_impression_delta: item.winner?.impressionDelta,\n winner_position_delta: item.winner?.positionDelta,\n loser_key: item.loser?.key,\n loser_click_delta: item.loser?.clickDelta,\n loser_impression_delta: item.loser?.impressionDelta,\n loser_position_delta: item.loser?.positionDelta,\n })),\n },\n {\n filename: 'postmortem-template-movement.csv',\n headers: [...HEADERS.templates],\n rows: report.output.templateMovement.map((item, index) => ({\n rank: index + 1,\n direction: item.direction,\n template: item.signature,\n confidence: item.confidence,\n url_count: item.urlCount,\n click_delta: item.clickDelta,\n impression_delta: item.impressionDelta,\n movement_share: item.movementShare,\n movement_share_scope: item.movementShareScope,\n confidence_scope: item.confidenceScope,\n eligible_rows: item.segmentCoverage.eligibleRows,\n returned_rows: item.segmentCoverage.returnedRows,\n limited_rows: item.segmentCoverage.limitedRows,\n result_limit: item.segmentCoverage.resultLimit,\n source_possibly_truncated: item.segmentCoverage.sourcePossiblyTruncated,\n common_terms: item.commonTerms.join('; '),\n sample_urls: item.sampleUrls.join('; '),\n summary: item.summary,\n })),\n },\n {\n filename: 'postmortem-update-evidence.csv',\n headers: [...HEADERS.evidence],\n rows: report.output.update.evidence.map((evidence, index) => ({\n rank: index + 1,\n evidence,\n })),\n },\n {\n filename: 'postmortem-confounders.csv',\n headers: [...HEADERS.confounders],\n rows: report.output.update.confounders.map((item, index) => ({\n rank: index + 1,\n source: item.source,\n title: item.title,\n date: item.date,\n scope: item.scope,\n target: item.target,\n description: item.description,\n })),\n },\n ...['page', 'query', 'device', 'country'].map((dimension) => ({\n filename: `postmortem-segment-${dimension}.csv`,\n headers: [...HEADERS.segment],\n rows: postmortemSegmentRows(report, dimension),\n })),\n ...['page', 'query', 'device', 'country'].map((dimension) => ({\n filename: `postmortem-segment-${dimension}-unmatched.csv`,\n headers: [...HEADERS.unmatchedSegment],\n rows: postmortemUnmatchedSegmentRows(report, dimension),\n })),\n ];\n}\n//# sourceMappingURL=update-postmortem.js.map","function hostnameFromUrl(value) {\n try {\n const url = new URL(value);\n if (url.protocol !== 'http:' && url.protocol !== 'https:')\n return undefined;\n return url.hostname.toLowerCase().replace(/\\.$/, '') || undefined;\n }\n catch {\n return undefined;\n }\n}\nfunction domainFromProperty(value) {\n if (!value.startsWith('sc-domain:'))\n return undefined;\n const domain = value.slice('sc-domain:'.length).trim().toLowerCase();\n if (!domain || /[/:]/.test(domain))\n return undefined;\n return domain.replace(/\\.$/, '') || undefined;\n}\nfunction matchForSite(site, streamHostname) {\n const domain = domainFromProperty(site);\n if (domain) {\n return streamHostname === domain || streamHostname.endsWith(`.${domain}`)\n ? 'domain'\n : undefined;\n }\n return hostnameFromUrl(site) === streamHostname ? 'hostname' : undefined;\n}\nexport function matchGa4WebStreams(site, candidates) {\n return candidates.flatMap((candidate) => {\n const defaultUri = candidate.stream.webStreamData?.defaultUri;\n if (!defaultUri)\n return [];\n const hostname = hostnameFromUrl(defaultUri);\n if (!hostname)\n return [];\n const match = matchForSite(site, hostname);\n if (!match)\n return [];\n return [{ ...candidate, defaultUri, hostname, match }];\n });\n}\nexport function ga4MatchReason(match, site) {\n const stream = match.stream.displayName ?? match.defaultUri;\n const location = match.match === 'domain' ? 'is inside' : 'matches';\n return `Matched GA4 web stream ${stream} (${match.defaultUri}): its hostname ${location} ${site}.`;\n}\n//# sourceMappingURL=matching.js.map","export function parseOlderThan(input) {\n if (!input) {\n return undefined;\n }\n const match = input.trim().match(/^(\\d+)([smhdw])$/i);\n if (!match) {\n throw new Error(`Invalid duration \"${input}\". Use values like 7d, 12h, 30m.`);\n }\n const valuePart = match[1];\n const unitPart = match[2];\n if (!valuePart || !unitPart) {\n throw new Error(`Invalid duration \"${input}\".`);\n }\n const value = Number.parseInt(valuePart, 10);\n const unit = unitPart.toLowerCase();\n const multipliers = {\n s: 1_000,\n m: 60_000,\n h: 3_600_000,\n d: 86_400_000,\n w: 604_800_000,\n };\n const multiplier = multipliers[unit];\n if (!multiplier) {\n throw new Error(`Unsupported duration unit in \"${input}\".`);\n }\n return value * multiplier;\n}\nexport function formatRelativeExpiry(expiresAt) {\n const delta = expiresAt - Date.now();\n if (delta <= 0) {\n return 'expired';\n }\n const minutes = Math.round(delta / 60_000);\n if (minutes < 60) {\n return `in ${minutes}m`;\n }\n const hours = Math.floor(minutes / 60);\n const remMinutes = minutes % 60;\n return remMinutes ? `in ${hours}h ${remMinutes}m` : `in ${hours}h`;\n}\nexport function isoDate(daysAgo = 0) {\n const date = new Date();\n date.setUTCDate(date.getUTCDate() - daysAgo);\n return date.toISOString().slice(0, 10);\n}\n//# sourceMappingURL=time.js.map","import { readFile } from 'node:fs/promises'\nimport { type JavaScriptRenderingMode, SeoError } from '@seo/core'\nimport type { BooleanArgDef } from 'citty'\n\nexport function defaultTrueBooleanArg(\n description: string,\n negativeDescription: string,\n): BooleanArgDef {\n return {\n type: 'boolean',\n default: true,\n description,\n negativeDescription,\n }\n}\n\nexport function stringArg(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined\n}\n\nexport function projectArg(args: Record<string, unknown>): string | undefined {\n const project = stringArg(args.project)\n const client = stringArg(args.client)\n if (project && client && project !== client) {\n throw new Error('Use either --project or --client, not both.')\n }\n return project ?? client\n}\n\nexport function booleanArg(value: unknown): boolean | undefined {\n return typeof value === 'boolean' ? value : undefined\n}\n\n/**\n * `--js` remains an alias for `--rendering on` while callers move to the\n * explicit modes. A mode is returned even when neither flag was supplied so\n * commands can pass it straight to the core API.\n */\nexport function renderingModeArg(\n args: Record<string, unknown>,\n): JavaScriptRenderingMode {\n const rendering = stringArg(args.rendering)\n if (\n rendering !== undefined &&\n rendering !== 'auto' &&\n rendering !== 'on' &&\n rendering !== 'off'\n ) {\n throw new SeoError('INVALID_INPUT', '--rendering must be auto, on, or off.')\n }\n if (booleanArg(args.js) === true && rendering && rendering !== 'on') {\n throw new SeoError(\n 'INVALID_INPUT',\n 'Use either --js or --rendering on, not both with different modes.',\n )\n }\n return rendering ?? (booleanArg(args.js) ? 'on' : 'auto')\n}\n\nexport function negatedBooleanArg(\n args: Record<string, unknown>,\n name: string,\n): boolean | undefined {\n const positive = booleanArg(args[name])\n if (positive === false) return true\n if (positive === true) return false\n const camelPositive = booleanArg(args[toCamelCase(name)])\n if (camelPositive === false) return true\n if (camelPositive === true) return false\n const explicitNo = booleanArg(args[`no-${name}`])\n if (explicitNo === true) return true\n const camelNo = booleanArg(args[`no${toPascalCase(name)}`])\n if (camelNo === true) return true\n return undefined\n}\n\nfunction toCamelCase(value: string): string {\n return value.replace(/-([a-z])/g, (_, letter: string) => letter.toUpperCase())\n}\n\nfunction toPascalCase(value: string): string {\n const camel = toCamelCase(value)\n return camel ? `${camel[0]?.toUpperCase()}${camel.slice(1)}` : ''\n}\n\nexport function numberArg(value: unknown): number | undefined {\n if (typeof value === 'number') return value\n if (typeof value !== 'string' || !value.trim()) return undefined\n const parsed = Number(value)\n return Number.isFinite(parsed) ? parsed : undefined\n}\n\nexport function strictNumberArg(\n value: unknown,\n label: string,\n): number | undefined {\n if (value === undefined || value === '') return undefined\n const parsed = numberArg(value)\n if (parsed === undefined)\n throw new SeoError('INVALID_INPUT', `${label} must be a number.`)\n return parsed\n}\n\nexport function csvArg(value: unknown): string[] | undefined {\n if (typeof value !== 'string') return undefined\n const items = value\n .split(',')\n .map((item) => item.trim())\n .filter(Boolean)\n return items.length ? items : undefined\n}\n\nexport function listArg(value: unknown): string[] {\n return csvArg(value) ?? []\n}\n\nexport function fetchRateArg(args: Record<string, unknown>):\n | {\n concurrency?: number\n intervalCap?: number\n intervalMs?: number\n }\n | undefined {\n const rate = {\n concurrency: numberArg(args['fetch-concurrency']),\n intervalCap: numberArg(args['fetch-interval-cap']),\n intervalMs: numberArg(args['fetch-interval-ms']),\n }\n return Object.values(rate).some((value) => value !== undefined)\n ? rate\n : undefined\n}\n\nexport function strictFetchRateArg(args: Record<string, unknown>):\n | {\n concurrency?: number\n intervalCap?: number\n intervalMs?: number\n }\n | undefined {\n const rate = {\n concurrency: strictNumberArg(\n args['fetch-concurrency'],\n '--fetch-concurrency',\n ),\n intervalCap: strictNumberArg(\n args['fetch-interval-cap'],\n '--fetch-interval-cap',\n ),\n intervalMs: strictNumberArg(\n args['fetch-interval-ms'],\n '--fetch-interval-ms',\n ),\n }\n return Object.values(rate).some((value) => value !== undefined)\n ? rate\n : undefined\n}\n\nexport function jsonFlag(args: Record<string, unknown>): boolean {\n return args.json === true\n}\n\nexport async function jsonBodyArg(\n value: unknown,\n fileValue: unknown,\n): Promise<Record<string, unknown> | undefined> {\n const inline = stringArg(value)\n const file = stringArg(fileValue)\n if (inline && file) {\n throw new Error('Use either --body or --body-file, not both.')\n }\n if (!inline && !file) return undefined\n const source = inline ?? (await readFile(file ?? '', 'utf8'))\n const parsed = JSON.parse(source) as unknown\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error('JSON body must be an object.')\n }\n return parsed as Record<string, unknown>\n}\n","import Table from 'cli-table3'\nimport pc from 'picocolors'\nimport updateNotifier from 'update-notifier'\n\nconst terminalColors = pc.createColors(\n Boolean(process.stdout.isTTY && !process.env.NO_COLOR),\n)\n\nexport function maybeCheckForUpdates(pkg: { name: string; version: string }) {\n if (process.env.CI || process.env.NO_UPDATE_NOTIFIER) {\n return\n }\n\n updateNotifier({ pkg, shouldNotifyInNpmScript: false }).notify()\n}\n\nexport function canPrompt(options: { json?: boolean } = {}): boolean {\n return Boolean(\n !options.json &&\n process.stdin.isTTY &&\n process.stdout.isTTY &&\n !process.env.CI,\n )\n}\n\nexport function printJson(data: unknown): void {\n process.stdout.write(`${JSON.stringify(data, null, 2)}\\n`)\n}\n\nexport function printKeyValue(rows: Array<[string, string]>): void {\n const width = Math.max(...rows.map(([label]) => label.length), 0)\n for (const [label, value] of rows) {\n process.stdout.write(\n `${terminalColors.bold(label.padEnd(width))} ${value}\\n`,\n )\n }\n}\n\nexport function printTable(\n head: string[],\n rows: Array<Array<string | number>>,\n): void {\n const table = new Table({ head })\n for (const row of rows) {\n table.push(row)\n }\n process.stdout.write(`${table.toString()}\\n`)\n}\n\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) {\n return `${bytes} B`\n }\n if (bytes < 1024 * 1024) {\n return `${(bytes / 1024).toFixed(1)} KB`\n }\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\nexport function maybeExitCancelled<T>(value: T | symbol): T {\n if (typeof value === 'symbol') {\n process.exit(1)\n }\n return value\n}\n","import { intro, note, outro, password, text } from '@clack/prompts'\nimport {\n authStatus,\n deleteTokens,\n formatRelativeExpiry,\n getSeoCliPaths,\n getTokenStorageStatus,\n loginWithLoopback,\n refreshAuthToken,\n SeoError,\n setTokenStorageMode,\n writeOauthClient,\n} from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { jsonFlag } from '../args.js'\nimport {\n canPrompt,\n maybeExitCancelled,\n printJson,\n printKeyValue,\n} from '../utils.js'\n\nfunction serviceAccountSource(source?: string): string {\n if (!source) return 'invalid or conflicting configuration'\n if (source === 'environment-json') {\n return 'SEO_GOOGLE_SERVICE_ACCOUNT_JSON'\n }\n if (source === 'environment-file') {\n return 'SEO_GOOGLE_SERVICE_ACCOUNT_FILE'\n }\n return 'GOOGLE_APPLICATION_CREDENTIALS'\n}\n\nfunction tokenStorageLabel(input: {\n configured: 'keychain' | 'file'\n active: 'keychain' | 'file'\n reason?: string\n}): string {\n if (input.active === 'keychain') return 'system keychain'\n return input.configured === 'keychain'\n ? 'private file fallback'\n : 'private file'\n}\n\nexport const authCommand = defineCommand({\n meta: {\n name: 'auth',\n description: 'Authentication commands',\n },\n subCommands: {\n login: defineCommand({\n meta: { name: 'login', description: 'Run Google OAuth flow' },\n run: async () => {\n const status = await authStatus()\n if (status.activeMode === 'service-account') {\n throw new SeoError(\n 'AUTH_CONFIG_REQUIRED',\n 'A service account is active from the environment. Unset its credential variable before running browser OAuth.',\n )\n }\n const tokens = await loginWithLoopback()\n process.stdout.write(\n `${tokens.account_email} · ${tokens.scope.replace('https://www.googleapis.com/auth/', '')} · ${tokens.client_source === 'shared' ? 'shared seo app' : 'BYO client'}\\n`,\n )\n },\n }),\n logout: defineCommand({\n meta: { name: 'logout', description: 'Delete locally stored tokens' },\n run: async () => {\n const status = await authStatus()\n await deleteTokens()\n if (status.activeMode === 'service-account') {\n process.stdout.write(\n 'Deleted local OAuth tokens. Service account credentials remain available through the environment.\\n',\n )\n return\n }\n process.stdout.write(\n 'Deleted local OAuth tokens.\\nRevoke at https://myaccount.google.com/permissions if you also want Google to forget the grant.\\n',\n )\n },\n }),\n whoami: defineCommand({\n meta: {\n name: 'whoami',\n description: 'Show the signed-in Google account',\n },\n run: async () => {\n const status = await authStatus()\n if (status.activeMode === 'service-account') {\n process.stdout.write(\n 'service account · ' +\n (status.identity ?? 'invalid configuration') +\n ' · ' +\n serviceAccountSource(status.serviceAccount.source) +\n '\\n',\n )\n return\n }\n const tokens = status.tokens\n if (!tokens) {\n process.stdout.write('Not logged in.\\n')\n return\n }\n process.stdout.write(\n `${tokens.account_email} · ${tokens.scope.replace('https://www.googleapis.com/auth/', '')} · ${formatRelativeExpiry(tokens.expires_at)} · ${tokens.client_source === 'shared' ? 'shared seo app' : 'BYO client'}\\n`,\n )\n },\n }),\n status: defineCommand({\n meta: {\n name: 'status',\n description: 'Show local Google auth status',\n },\n args: {\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const status = await authStatus()\n const storage =\n status.activeMode === 'oauth'\n ? await getTokenStorageStatus()\n : undefined\n if (jsonFlag(args)) {\n printJson({\n authenticated:\n status.activeMode === 'oauth'\n ? Boolean(status.tokens)\n : status.serviceAccount.configured,\n mode: status.activeMode,\n identity: status.identity,\n account:\n status.activeMode === 'oauth'\n ? status.tokens?.account_email\n : undefined,\n scopes:\n status.activeMode === 'oauth' ? status.tokens?.scope : undefined,\n clientSource:\n status.activeMode === 'oauth'\n ? status.tokens?.client_source\n : undefined,\n expiresAt:\n status.activeMode === 'oauth'\n ? status.tokens?.expires_at\n : undefined,\n sharedConfigured: status.sharedConfigured,\n byoConfigured: status.byoConfigured,\n serviceAccount: {\n configured: status.serviceAccount.configured,\n identity: status.serviceAccount.identity,\n source: status.serviceAccount.source,\n error: status.serviceAccount.error,\n },\n ...(storage ? { tokenStorage: storage } : {}),\n })\n return\n }\n if (status.activeMode === 'service-account') {\n const rows: Array<[string, string]> = [\n ['Mode', 'service account'],\n ['Identity', status.identity ?? 'unavailable'],\n ['Source', serviceAccountSource(status.serviceAccount.source)],\n ['Scopes', 'Search Console readonly, GA4 readonly'],\n ['Storage', 'credentials stay in the environment'],\n ]\n if (status.serviceAccount.error) {\n rows.push(['Status', status.serviceAccount.error])\n }\n printKeyValue(rows)\n return\n }\n if (!status.tokens) {\n const authMode = status.serviceAccount.error\n ? status.serviceAccount.error\n : status.sharedConfigured\n ? 'Shared seo app available'\n : status.byoConfigured\n ? 'BYO client configured'\n : 'No OAuth client configured'\n process.stdout.write(\n `Not logged in. ${authMode}. Run \\`seo auth login\\` to connect Google.\\n`,\n )\n return\n }\n const tokenStorage = storage ?? (await getTokenStorageStatus())\n printKeyValue([\n ['Account', status.tokens.account_email],\n ['Scopes', status.tokens.scope],\n [\n 'Client',\n status.tokens.client_source === 'shared'\n ? 'shared seo app'\n : 'BYO client',\n ],\n ['Expires', formatRelativeExpiry(status.tokens.expires_at)],\n ['Tokens file', getSeoCliPaths().tokensFile],\n ['Token storage', tokenStorageLabel(tokenStorage)],\n ...(tokenStorage.reason\n ? [['Storage note', tokenStorage.reason] as [string, string]]\n : []),\n [\n 'OAuth mode',\n status.sharedConfigured\n ? 'shared app available'\n : status.byoConfigured\n ? 'BYO client configured'\n : 'missing',\n ],\n ['Revoke at', 'https://myaccount.google.com/permissions'],\n ])\n },\n }),\n storage: defineCommand({\n meta: {\n name: 'storage',\n description: 'Show or change local OAuth token storage',\n },\n args: {\n keychain: {\n type: 'boolean',\n default: false,\n description:\n 'Store OAuth tokens in the system keychain when available.',\n },\n file: {\n type: 'boolean',\n default: false,\n description: 'Store OAuth tokens in the private local file.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n if (args.keychain && args.file) {\n throw new SeoError(\n 'INVALID_INPUT',\n 'Choose either --keychain or --file, not both.',\n )\n }\n const storage =\n args.keychain || args.file\n ? await setTokenStorageMode(args.keychain ? 'keychain' : 'file')\n : await getTokenStorageStatus()\n\n if (jsonFlag(args)) {\n printJson(storage)\n return\n }\n\n printKeyValue([\n ['Configured storage', storage.configured],\n ['Active storage', tokenStorageLabel(storage)],\n ...(storage.reason\n ? [['Note', storage.reason] as [string, string]]\n : []),\n ])\n },\n }),\n refresh: defineCommand({\n meta: {\n name: 'refresh',\n description: 'Refresh the Google OAuth token',\n },\n run: async () => {\n const status = await authStatus()\n if (status.activeMode === 'service-account') {\n process.stdout.write(\n 'Service accounts request short-lived Google tokens automatically. No local refresh token is stored.\\n',\n )\n return\n }\n const tokens = await refreshAuthToken()\n process.stdout.write(\n `Refreshed. New expiry ${new Date(tokens.expires_at).toISOString()}.\\n`,\n )\n },\n }),\n 'setup-client': defineCommand({\n meta: {\n name: 'setup-client',\n description: 'Save your own Google Desktop OAuth client',\n },\n args: {\n json: {\n type: 'boolean',\n default: false,\n description: 'Return a structured error instead of prompting.',\n },\n },\n run: async ({ args }) => {\n if (!canPrompt({ json: jsonFlag(args) })) {\n throw new SeoError(\n 'INVALID_INPUT',\n '`seo auth setup-client` needs an interactive terminal. Run it without --json, or set SEO_GOOGLE_CLIENT_ID and SEO_GOOGLE_CLIENT_SECRET.',\n )\n }\n intro('seo BYO OAuth client')\n note(\n [\n 'This is the advanced path.',\n 'Most users should use the shared seo Google app.',\n 'Your actual sensitive data is the local refresh token, not the desktop app client secret.',\n ].join('\\n'),\n 'Advanced',\n )\n const clientId = maybeExitCancelled(\n await text({\n message: 'Google Desktop OAuth client ID',\n validate: (value) => (value ? undefined : 'Client ID is required'),\n }),\n )\n const clientSecret = maybeExitCancelled(\n await password({\n message: 'Google Desktop OAuth client secret',\n validate: (value) =>\n value ? undefined : 'Client secret is required',\n }),\n )\n writeOauthClient({ clientId, clientSecret })\n outro(`Saved BYO OAuth client to ${getSeoCliPaths().oauthClientFile}`)\n },\n }),\n },\n})\n","import { clearCache, getCacheStats } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { formatBytes, printKeyValue } from '../utils.js'\n\nexport const cacheCommand = defineCommand({\n meta: { name: 'cache', description: 'Cache helpers' },\n subCommands: {\n stats: defineCommand({\n meta: {\n name: 'stats',\n description: 'Show local cache size and row counts',\n },\n run: async () => {\n const stats = getCacheStats()\n printKeyValue([\n ['DB', stats.dbPath],\n ['Size', formatBytes(stats.sizeBytes)],\n ['sites', String(stats.counts.sites ?? 0)],\n ['gsc_cache', String(stats.counts.gsc_cache ?? 0)],\n ['ga4_cache', String(stats.counts.ga4_cache ?? 0)],\n ['semrush_cache', String(stats.counts.semrush_cache ?? 0)],\n ['http_cache', String(stats.counts.http_cache ?? 0)],\n ])\n },\n }),\n clear: defineCommand({\n meta: {\n name: 'clear',\n description: 'Clear cached API and HTTP data',\n },\n args: {\n provider: {\n type: 'string',\n description: 'Optional cache provider: gsc, ga4, semrush, or http',\n },\n },\n run: async ({ args }) => {\n const removed = clearCache(\n args.provider as 'gsc' | 'ga4' | 'semrush' | 'http' | undefined,\n )\n process.stdout.write(`Removed ${removed} cached rows.\\n`)\n },\n }),\n },\n})\n","import { type Option, select, text } from '@clack/prompts'\nimport {\n type ClientProfile,\n ga4PropertyIdFromName,\n getClient,\n listClients,\n listGa4AccountSummaries,\n listSites,\n readConfig,\n SeoError,\n} from '@seo/core'\nimport { canPrompt, maybeExitCancelled } from './utils.js'\n\ntype ResolveOptions = {\n json?: boolean\n refresh?: boolean\n}\n\ntype SiteChoice = {\n siteUrl: string\n permissionLevel?: string\n}\n\ntype Ga4Choice = {\n property: string\n displayName: string\n account: string\n}\n\nexport type ClientSelection = {\n client?: ClientProfile\n site: string\n}\n\nfunction includesQuery(values: string[], query: string): boolean {\n const normalized = query.trim().toLowerCase()\n if (!normalized) return true\n return values.some((value) => value.toLowerCase().includes(normalized))\n}\n\nasync function chooseFromSearch<T>(input: {\n message: string\n searchMessage: string\n emptyMessage: string\n choices: T[]\n label: (choice: T) => string\n hint?: (choice: T) => string | undefined\n searchValues: (choice: T) => string[]\n}): Promise<T> {\n let visible = input.choices\n\n if (input.choices.length > 8) {\n const query = maybeExitCancelled(\n await text({\n message: input.searchMessage,\n placeholder: 'Type part of the name or URL, or leave blank',\n }),\n )\n visible = input.choices.filter((choice) =>\n includesQuery(input.searchValues(choice), query),\n )\n\n if (!visible.length) {\n throw new SeoError('INVALID_INPUT', input.emptyMessage)\n }\n }\n\n return maybeExitCancelled(\n await select({\n message: input.message,\n options: visible.map((choice) => {\n const hint = input.hint?.(choice)\n return {\n value: choice,\n label: input.label(choice),\n ...(hint ? { hint } : {}),\n }\n }) as Option<T>[],\n }),\n )\n}\n\nexport async function resolveSite(input: {\n site?: string\n options?: ResolveOptions\n}): Promise<string> {\n if (input.site) return input.site\n\n const config = readConfig()\n const defaultSiteKnown =\n Boolean(config.defaultSite) &&\n (config.clients.some((client) => client.siteUrl === config.defaultSite) ||\n config.sites.some((site) => site.siteUrl === config.defaultSite))\n if (config.defaultSite && defaultSiteKnown) return config.defaultSite\n\n if (input.options?.json || !canPrompt()) {\n throw new SeoError(\n 'INVALID_INPUT',\n config.defaultSite\n ? `Saved default site ${config.defaultSite} does not match any saved project. Pass --site or --project, or run \\`seo start\\` to save a new default.`\n : 'No site selected. Pass --site, use --project on supported commands, or run `seo start` in a terminal.',\n )\n }\n\n const sites = await listSites(input.options?.refresh)\n if (!sites.length) {\n throw new SeoError(\n 'PROPERTY_NOT_FOUND',\n 'No Search Console properties found for this Google login.',\n )\n }\n if (sites.length === 1) {\n return sites[0]?.siteUrl ?? ''\n }\n\n const choice = await chooseFromSearch<SiteChoice>({\n message: 'Choose a Search Console property',\n searchMessage: 'Search Search Console properties',\n emptyMessage: 'No Search Console properties matched that search.',\n choices: sites,\n label: (site) => site.siteUrl,\n hint: (site) => site.permissionLevel,\n searchValues: (site) => [site.siteUrl, site.permissionLevel ?? ''],\n })\n\n return choice.siteUrl\n}\n\nexport async function resolveClientSelection(input: {\n client?: string\n project?: string\n site?: string\n options?: ResolveOptions\n}): Promise<ClientSelection> {\n if (input.client && input.project && input.client !== input.project) {\n throw new SeoError(\n 'INVALID_INPUT',\n 'Use either --project or --client, not both.',\n )\n }\n const project = input.project ?? input.client\n if (project) {\n const client = getClient(project)\n if (!client) {\n throw new SeoError('INVALID_INPUT', `Project not found: ${project}`)\n }\n return { client, site: client.siteUrl }\n }\n\n const defaultClient = getClient()\n if (!input.site && defaultClient) {\n return { client: defaultClient, site: defaultClient.siteUrl }\n }\n\n return {\n site: await resolveSite({ site: input.site, options: input.options }),\n }\n}\n\nexport async function resolveClient(input: {\n client?: string\n project?: string\n options?: ResolveOptions\n}): Promise<ClientProfile | undefined> {\n if (input.client && input.project && input.client !== input.project) {\n throw new SeoError(\n 'INVALID_INPUT',\n 'Use either --project or --client, not both.',\n )\n }\n const project = input.project ?? input.client\n if (project) {\n const client = getClient(project)\n if (!client) {\n throw new SeoError('INVALID_INPUT', `Project not found: ${project}`)\n }\n return client\n }\n\n const clients = listClients()\n if (!clients.length) return undefined\n const defaultClient = getClient()\n if (defaultClient) return defaultClient\n\n if (input.options?.json || !canPrompt()) return undefined\n\n return chooseFromSearch<ClientProfile>({\n message: 'Choose a project',\n searchMessage: 'Search projects',\n emptyMessage: 'No projects matched that search.',\n choices: clients,\n label: (client) => client.name,\n hint: (client) => client.siteUrl,\n searchValues: (client) => [client.id, client.name, client.siteUrl],\n })\n}\n\nexport async function resolveGa4Property(input: {\n property?: string\n options?: ResolveOptions\n}): Promise<string> {\n if (input.property) return input.property\n\n const config = readConfig()\n if (config.google.defaultGa4PropertyId) {\n return config.google.defaultGa4PropertyId\n }\n\n if (input.options?.json || !canPrompt()) {\n throw new SeoError(\n 'INVALID_INPUT',\n 'No GA4 property selected. Pass --property or run this command in a terminal to choose one.',\n )\n }\n\n const accountSummaries = await listGa4AccountSummaries()\n const choices = accountSummaries.flatMap((account) =>\n account.propertySummaries.map((property) => ({\n property: ga4PropertyIdFromName(property.property),\n displayName: property.displayName ?? property.property,\n account: account.displayName ?? account.account,\n })),\n )\n\n if (!choices.length) {\n throw new SeoError(\n 'PROPERTY_NOT_FOUND',\n 'No GA4 properties found for this Google login.',\n )\n }\n if (choices.length === 1) {\n return choices[0]?.property ?? ''\n }\n\n const choice = await chooseFromSearch<Ga4Choice>({\n message: 'Choose a GA4 property',\n searchMessage: 'Search GA4 properties',\n emptyMessage: 'No GA4 properties matched that search.',\n choices,\n label: (property) => `${property.displayName} (${property.property})`,\n hint: (property) => property.account,\n searchValues: (property) => [\n property.property,\n property.displayName,\n property.account,\n ],\n })\n\n return choice.property\n}\n","import type {\n PageFetchDiagnostics,\n QueryContentClassification,\n} from '@seo/core'\nimport { resolveClientSelection } from '../selection.js'\n\nexport async function selectedSiteOrThrow(\n input: {\n client?: string\n project?: string\n site?: string\n },\n options: { json?: boolean; refresh?: boolean } = {},\n): Promise<string> {\n return (\n await resolveClientSelection({\n client: input.client,\n project: input.project,\n site: input.site,\n options,\n })\n ).site\n}\n\nexport function startUrlForSite(site: string): string | undefined {\n if (site.startsWith('http://') || site.startsWith('https://')) return site\n if (site.startsWith('sc-domain:')) return `https://${site.slice(10)}/`\n return undefined\n}\n\nexport function suggestedClientName(site: string): string {\n return site.replace(/^sc-domain:/, '').replace(/^https?:\\/\\//, '')\n}\n\nexport function slugId(value: string): string {\n return value\n .toLowerCase()\n .replace(/^https?:\\/\\//, '')\n .replace(/^sc-domain:/, '')\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 60)\n}\n\nexport function formatFetchDiagnostics(\n diagnostics?: PageFetchDiagnostics,\n): string {\n if (!diagnostics) return '-'\n if (diagnostics.backpressure?.status === 'stopped') {\n return `stopped: ${diagnostics.backpressure.reason ?? 'origin cooldown'}`\n }\n if (diagnostics.backpressure?.status === 'slowed') {\n return `slowed ${diagnostics.backpressure.delayMs}ms`\n }\n if (diagnostics.rendering?.status === 'unavailable') {\n return 'raw HTML; rendering unavailable'\n }\n if (diagnostics.rendering?.status === 'failed') {\n return 'raw HTML; rendering failed'\n }\n if (diagnostics.blocked) return 'blocked'\n if (diagnostics.rendered) return 'rendered'\n if (diagnostics.cache === 'hit') return 'cached'\n if (diagnostics.fetched) return 'fetched'\n return diagnostics.source\n}\n\nexport function formatContentCheck(\n classification?: QueryContentClassification,\n): string {\n if (!classification) return '-'\n if (classification === 'serp-framing') return 'wording gap'\n if (classification === 'content-gap') return 'content gap'\n if (classification === 'technical-check') return 'technical check'\n return 'covered'\n}\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { dirname, join, posix, win32 } from 'node:path'\n\nexport type SupportedClient =\n | 'claude-desktop'\n | 'claude-code'\n | 'codex'\n | 'cursor'\n\ninterface BaseClientTarget {\n client: SupportedClient\n label: string\n path: string\n commandNames: string[]\n detectionPaths: string[]\n}\n\nexport interface JsonClientConfigTarget extends BaseClientTarget {\n kind: 'json'\n includeType?: boolean\n}\n\nexport interface NativeClientConfigTarget extends BaseClientTarget {\n kind: 'native'\n executable: 'codex'\n}\n\nexport type ClientConfigTarget =\n | JsonClientConfigTarget\n | NativeClientConfigTarget\n\nfunction platformConfigRoot(input: {\n home: string\n platform: NodeJS.Platform\n env: NodeJS.ProcessEnv\n}): string {\n const path = input.platform === 'win32' ? win32 : posix\n if (input.platform === 'win32') {\n return input.env.APPDATA ?? path.resolve(input.home, 'AppData/Roaming')\n }\n if (input.platform === 'darwin') {\n return path.resolve(input.home, 'Library/Application Support')\n }\n return input.env.XDG_CONFIG_HOME ?? path.resolve(input.home, '.config')\n}\n\nexport function mcpClientTargets(\n input: {\n home?: string\n platform?: NodeJS.Platform\n env?: NodeJS.ProcessEnv\n } = {},\n): ClientConfigTarget[] {\n const home = input.home ?? homedir()\n const platform = input.platform ?? process.platform\n const env = input.env ?? process.env\n const configRoot = platformConfigRoot({ home, platform, env })\n const path = platform === 'win32' ? win32 : posix\n const targets: ClientConfigTarget[] = []\n\n if (platform === 'darwin' || platform === 'win32') {\n const claudeRoot = path.resolve(configRoot, 'Claude')\n targets.push({\n kind: 'json',\n client: 'claude-desktop',\n label: 'Claude Desktop',\n path: path.resolve(claudeRoot, 'claude_desktop_config.json'),\n commandNames: [],\n detectionPaths:\n platform === 'darwin'\n ? [claudeRoot, '/Applications/Claude.app']\n : [claudeRoot],\n })\n }\n\n targets.push(\n {\n kind: 'json',\n client: 'claude-code',\n label: 'Claude Code',\n path: path.resolve(home, '.claude.json'),\n includeType: true,\n commandNames: ['claude'],\n detectionPaths: [path.resolve(home, '.claude')],\n },\n {\n kind: 'native',\n client: 'codex',\n label: 'Codex',\n path: path.resolve(home, '.codex/config.toml'),\n executable: 'codex',\n commandNames: ['codex'],\n detectionPaths: [path.resolve(home, '.codex')],\n },\n {\n kind: 'json',\n client: 'cursor',\n label: 'Cursor',\n path: path.resolve(home, '.cursor/mcp.json'),\n commandNames: ['cursor', 'cursor-agent'],\n detectionPaths: [\n path.resolve(home, '.cursor'),\n ...(platform === 'darwin' ? ['/Applications/Cursor.app'] : []),\n ],\n },\n )\n\n return targets\n}\n\nexport function resolveMcpClientExecutable(\n command: string,\n input: {\n exists?: (path: string) => boolean\n nodePath?: string\n path?: string\n platform?: NodeJS.Platform\n } = {},\n): string {\n const platform = input.platform ?? process.platform\n const exists = input.exists ?? existsSync\n const nodePath = input.nodePath ?? process.execPath\n const names =\n platform === 'win32'\n ? [`${command}.cmd`, `${command}.exe`, command]\n : [command]\n\n const pathEntries = (input.path ?? process.env.PATH ?? '')\n .split(platform === 'win32' ? ';' : ':')\n .filter(Boolean)\n for (const directory of pathEntries) {\n for (const name of names) {\n const candidate = join(directory, name)\n if (exists(candidate)) return candidate\n }\n }\n\n for (const name of names) {\n const candidate = join(dirname(nodePath), name)\n if (exists(candidate)) return candidate\n }\n return command\n}\n\nfunction commandExists(command: string): boolean {\n return resolveMcpClientExecutable(command) !== command\n}\n\nexport function detectMcpClients(\n input: {\n targets?: ClientConfigTarget[]\n hasCommand?: (command: string) => boolean\n hasPath?: (path: string) => boolean\n } = {},\n): ClientConfigTarget[] {\n const targets = input.targets ?? mcpClientTargets()\n const hasCommand = input.hasCommand ?? commandExists\n const hasPath = input.hasPath ?? existsSync\n return targets.filter((target) => {\n if (target.kind === 'native') {\n return target.commandNames.some(hasCommand)\n }\n return (\n hasPath(target.path) ||\n target.detectionPaths.some(hasPath) ||\n target.commandNames.some(hasCommand)\n )\n })\n}\n","import { spawnSync } from 'node:child_process'\nimport {\n constants,\n copyFileSync,\n existsSync,\n mkdirSync,\n readFileSync,\n realpathSync,\n renameSync,\n statSync,\n writeFileSync,\n} from 'node:fs'\nimport { dirname } from 'node:path'\nimport { isDeepStrictEqual } from 'node:util'\nimport { getSeoCliPaths, SEO_VERSION } from '@seo/core'\nimport {\n applyEdits,\n modify,\n type ParseError,\n parse,\n printParseErrorCode,\n} from 'jsonc-parser'\nimport type {\n ClientConfigTarget,\n JsonClientConfigTarget,\n NativeClientConfigTarget,\n SupportedClient,\n} from './mcp-clients.js'\nimport { resolveMcpClientExecutable } from './mcp-clients.js'\n\ninterface CommandResult {\n status: number | null\n stdout: string\n stderr: string\n error?: Error\n}\n\ntype CommandRunner = (command: string, args: string[]) => CommandResult\n\nexport interface McpServerCommand {\n command: string\n args: string[]\n}\n\nexport interface McpConfigOptions {\n runCommand?: CommandRunner\n reinstall?: boolean\n serverCommand?: McpServerCommand\n}\n\nconst formattingOptions = {\n insertSpaces: true,\n tabSize: 2,\n eol: '\\n',\n}\n\nfunction timestamp(): string {\n return new Date().toISOString().replace(/[:.]/g, '-')\n}\n\nfunction writeAtomic(path: string, value: string): void {\n mkdirSync(dirname(path), { recursive: true, mode: 0o700 })\n const tmp = `${path}.${process.pid}.${Date.now()}.tmp`\n const mode = existsSync(path) ? statSync(path).mode & 0o777 : 0o600\n writeFileSync(tmp, value, { encoding: 'utf8', mode })\n renameSync(tmp, path)\n}\n\nfunction backup(path: string): void {\n const base = `${path}.bak-${timestamp()}`\n let candidate = base\n let suffix = 2\n while (existsSync(candidate)) {\n candidate = `${base}-${suffix}`\n suffix += 1\n }\n copyFileSync(path, candidate, constants.COPYFILE_EXCL)\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction readConfig(target: JsonClientConfigTarget): {\n source: string\n config: Record<string, unknown>\n} {\n if (!existsSync(target.path)) return { source: '{}\\n', config: {} }\n\n const source = readFileSync(target.path, 'utf8')\n const errors: ParseError[] = []\n const config = parse(source, errors, { allowTrailingComma: true })\n if (errors.length > 0) {\n const first = errors[0]\n const detail = first\n ? `${printParseErrorCode(first.error)} at offset ${first.offset}`\n : 'unknown parse error'\n throw new Error(`Cannot update ${target.path}: invalid JSONC (${detail}).`)\n }\n if (!isRecord(config)) {\n throw new Error(\n `Cannot update ${target.path}: config root must be an object.`,\n )\n }\n if (config.mcpServers !== undefined && !isRecord(config.mcpServers)) {\n throw new Error(\n `Cannot update ${target.path}: mcpServers must be an object.`,\n )\n }\n return { source, config }\n}\n\nfunction isSeoPackageCommand(args: string[]): boolean {\n return (\n args.includes('mcp') &&\n args.includes('serve') &&\n args.some(\n (item) =>\n item === 'seo' || item.startsWith('seo@') || item === '@seo/cli',\n )\n )\n}\n\nfunction isManagedNodeCommand(\n value: Record<string, unknown>,\n args: string[],\n): boolean {\n if (\n typeof value.command !== 'string' ||\n args.length !== 3 ||\n args[1] !== 'mcp' ||\n args[2] !== 'serve' ||\n !isRecord(value.env)\n ) {\n return false\n }\n return value.env.SEO_MCP_CONFIGURED_BY === 'seo'\n}\n\nfunction managedServer(value: unknown): boolean {\n if (!isRecord(value) || !Array.isArray(value.args)) return false\n const args = value.args.filter(\n (item): item is string => typeof item === 'string',\n )\n return isSeoPackageCommand(args) || isManagedNodeCommand(value, args)\n}\n\nfunction writeConfigEdit(input: {\n target: JsonClientConfigTarget\n source: string\n value: unknown\n}): void {\n const next = applyEdits(\n input.source,\n modify(input.source, ['mcpServers', 'seo'], input.value, {\n formattingOptions,\n }),\n )\n if (existsSync(input.target.path)) backup(input.target.path)\n writeAtomic(input.target.path, next)\n}\n\nfunction defaultCommandRunner(command: string, args: string[]): CommandResult {\n const result = spawnSync(command, args, { encoding: 'utf8' })\n return {\n status: result.status,\n stdout: result.stdout ?? '',\n stderr: result.stderr ?? '',\n error: result.error,\n }\n}\n\nfunction isTemporaryNpxPath(path: string): boolean {\n const normalized = path.replaceAll('\\\\', '/').toLowerCase()\n return (\n normalized.includes('/_npx/') ||\n normalized.includes('/.npm/_npx/') ||\n normalized.includes('/.cache/pnpm/dlx/')\n )\n}\n\nfunction installedCliPath(cliPath: string | undefined): string | undefined {\n if (!cliPath || !existsSync(cliPath)) return undefined\n const resolved = realpathSync(cliPath)\n return isTemporaryNpxPath(resolved) ? undefined : resolved\n}\n\nexport function resolveMcpServerCommand(\n input: {\n cliPath?: string\n nodePath?: string\n platform?: NodeJS.Platform\n version?: string\n } = {},\n): McpServerCommand {\n const cliPath = installedCliPath(input.cliPath ?? process.argv[1])\n if (cliPath) {\n return {\n command: input.nodePath ?? process.execPath,\n args: [cliPath, 'mcp', 'serve'],\n }\n }\n\n const packageName = `seo@${input.version ?? SEO_VERSION}`\n if ((input.platform ?? process.platform) === 'win32') {\n return {\n command: 'cmd',\n args: ['/c', 'npx', '-y', packageName, 'mcp', 'serve'],\n }\n }\n return { command: 'npx', args: ['-y', packageName, 'mcp', 'serve'] }\n}\n\nfunction serverConfig(\n includeType = false,\n command = resolveMcpServerCommand(),\n): Record<string, unknown> {\n const paths = getSeoCliPaths()\n const config: Record<string, unknown> = {\n command: command.command,\n args: command.args,\n env: {\n SEO_CONFIG_DIR: paths.configDir,\n SEO_MCP_CONFIGURED_BY: 'seo',\n },\n }\n if (includeType) config.type = 'stdio'\n return config\n}\n\nfunction codexManaged(output: string): boolean {\n return (\n output.includes('SEO_MCP_CONFIGURED_BY') ||\n /args:\\s+-y\\s+(?:seo(?:@\\S+)?|@seo\\/cli)\\s+mcp\\s+serve\\b/.test(output)\n )\n}\n\nfunction codexCommand(\n target: NativeClientConfigTarget,\n operation: 'install' | 'uninstall',\n options: Required<\n Pick<McpConfigOptions, 'runCommand' | 'reinstall' | 'serverCommand'>\n >,\n): { client: SupportedClient; path: string; changed: boolean } {\n const executable = resolveMcpClientExecutable(target.executable)\n const current = options.runCommand(executable, ['mcp', 'get', 'seo'])\n if ((current.error as NodeJS.ErrnoException | undefined)?.code === 'ENOENT') {\n throw new Error(\n 'Cannot install SEO MCP for Codex: the `codex` command is not available on PATH. Install Codex CLI or choose another MCP client.',\n )\n }\n const exists = current.status === 0\n if (exists && !codexManaged(current.stdout)) {\n throw new Error(\n `Cannot ${operation} SEO MCP: ${target.path} already has an unmanaged mcp_servers.seo entry.`,\n )\n }\n if (operation === 'install' && exists && !options.reinstall) {\n return { client: target.client, path: target.path, changed: false }\n }\n if (operation === 'uninstall' && !exists) {\n return { client: target.client, path: target.path, changed: false }\n }\n\n if (operation === 'install' && exists) {\n const removed = options.runCommand(executable, ['mcp', 'remove', 'seo'])\n if (removed.error || removed.status !== 0) {\n const detail =\n removed.error?.message ?? removed.stderr.trim() ?? 'unknown error'\n throw new Error(`Cannot reinstall SEO MCP for Codex: ${detail}`)\n }\n }\n\n const paths = getSeoCliPaths()\n const args =\n operation === 'install'\n ? [\n 'mcp',\n 'add',\n 'seo',\n '--env',\n `SEO_CONFIG_DIR=${paths.configDir}`,\n '--env',\n 'SEO_MCP_CONFIGURED_BY=seo',\n '--',\n options.serverCommand.command,\n ...options.serverCommand.args,\n ]\n : ['mcp', 'remove', 'seo']\n const result = options.runCommand(executable, args)\n if (result.error || result.status !== 0) {\n const detail =\n result.error?.message ?? result.stderr.trim() ?? 'unknown error'\n throw new Error(`Cannot ${operation} SEO MCP for Codex: ${detail}`)\n }\n return { client: target.client, path: target.path, changed: true }\n}\n\nexport function installMcpConfig(\n target: ClientConfigTarget,\n options: McpConfigOptions = {},\n): { client: SupportedClient; path: string; changed: boolean } {\n const resolved = {\n runCommand: options.runCommand ?? defaultCommandRunner,\n reinstall: options.reinstall ?? false,\n serverCommand: options.serverCommand ?? resolveMcpServerCommand(),\n }\n if (target.kind === 'native') {\n return codexCommand(target, 'install', resolved)\n }\n\n const { source, config } = readConfig(target)\n const servers = config.mcpServers as Record<string, unknown> | undefined\n const current = servers?.seo\n const desired = serverConfig(target.includeType, resolved.serverCommand)\n if (isDeepStrictEqual(current, desired) && !resolved.reinstall) {\n return { client: target.client, path: target.path, changed: false }\n }\n if (current !== undefined && !managedServer(current)) {\n throw new Error(\n `Cannot install SEO MCP: ${target.path} already has an unmanaged mcpServers.seo entry.`,\n )\n }\n\n writeConfigEdit({ target, source, value: desired })\n return { client: target.client, path: target.path, changed: true }\n}\n\nexport function uninstallMcpConfig(\n target: ClientConfigTarget,\n options: Pick<McpConfigOptions, 'runCommand'> = {},\n): { client: SupportedClient; path: string; changed: boolean } {\n if (target.kind === 'native') {\n return codexCommand(target, 'uninstall', {\n runCommand: options.runCommand ?? defaultCommandRunner,\n reinstall: false,\n serverCommand: resolveMcpServerCommand(),\n })\n }\n if (!existsSync(target.path)) {\n return { client: target.client, path: target.path, changed: false }\n }\n\n const { source, config } = readConfig(target)\n const servers = config.mcpServers as Record<string, unknown> | undefined\n if (servers?.seo === undefined) {\n return { client: target.client, path: target.path, changed: false }\n }\n if (!managedServer(servers.seo)) {\n throw new Error(\n `Cannot uninstall SEO MCP: ${target.path} has an unmanaged mcpServers.seo entry.`,\n )\n }\n\n writeConfigEdit({ target, source, value: undefined })\n return { client: target.client, path: target.path, changed: true }\n}\n","import { spawnSync } from 'node:child_process'\nimport {\n confirm,\n multiselect,\n note,\n password,\n select,\n text,\n} from '@clack/prompts'\nimport {\n authStatus,\n type Ga4WebStreamCandidate,\n type Ga4WebStreamMatch,\n ga4MatchReason,\n ga4PropertyIdFromName,\n listGa4AccountSummaries,\n listGa4DataStreams,\n loginWithLoopback,\n matchGa4WebStreams,\n SeoError,\n writeOauthClient,\n} from '@seo/core'\nimport { canPrompt, maybeExitCancelled } from '../../utils.js'\nimport { detectMcpClients } from '../mcp-clients.js'\nimport { installMcpConfig } from '../mcp-config.js'\n\nexport type SetupAuthStatus =\n | 'connected'\n | 'already-connected'\n | 'service-account'\n | 'skipped'\nexport type SetupMcpInstall = {\n client: string\n path: string\n changed: boolean\n error?: string\n}\nexport type SetupGa4Selection = {\n propertyId: string\n selection: 'explicit' | 'matched' | 'manual'\n reason: string\n}\nexport type SetupSkillInstall = {\n status: 'installed' | 'declined' | 'skipped' | 'failed'\n error?: string\n}\n\ntype Ga4PropertyChoice = {\n property: string\n label: string\n account: string\n}\n\ntype Ga4SetupChoice = Ga4PropertyChoice & {\n match?: Ga4WebStreamMatch\n}\n\ntype AuthSetupChoice = 'login' | 'setup' | 'skip'\n\nexport function authSetupOptions(input: {\n sharedConfigured: boolean\n byoConfigured: boolean\n canSkip: boolean\n}): Array<{\n value: AuthSetupChoice\n label: string\n hint?: string\n}> {\n const skipOption = input.canSkip\n ? [{ value: 'skip' as const, label: 'Skip for now' }]\n : []\n const hasOauthClient = input.sharedConfigured || input.byoConfigured\n\n return hasOauthClient\n ? [\n {\n value: 'login',\n label: 'Connect Google',\n hint: 'Opens your browser for read-only Search Console and GA4 access',\n },\n ...skipOption,\n ]\n : [\n {\n value: 'setup',\n label: 'Set up Google login for local development',\n hint: 'This source checkout does not include the public app credentials',\n },\n ...skipOption,\n ]\n}\n\nasync function findGa4WebStreamCandidates(\n properties: Ga4PropertyChoice[],\n): Promise<{ candidates: Ga4WebStreamCandidate[]; complete: boolean }> {\n const candidates: Ga4WebStreamCandidate[] = []\n let complete = true\n let nextIndex = 0\n\n async function worker(): Promise<void> {\n while (nextIndex < properties.length) {\n const property = properties[nextIndex]\n nextIndex += 1\n if (!property) continue\n\n try {\n const streams = await listGa4DataStreams(property.property)\n candidates.push(\n ...streams\n .filter((stream) => stream.webStreamData)\n .map((stream) => ({\n account: property.account,\n property: property.property,\n propertyName: property.label,\n stream,\n })),\n )\n } catch {\n complete = false\n }\n }\n }\n\n await Promise.all(\n Array.from({ length: Math.min(properties.length, 4) }, () => worker()),\n )\n return { candidates, complete }\n}\n\nexport async function maybeConnectAuth(\n args: Record<string, unknown>,\n): Promise<SetupAuthStatus> {\n const status = await authStatus()\n if (status.activeMode === 'service-account') return 'service-account'\n if (status.tokens) return 'already-connected'\n if (args['skip-auth']) return 'skipped'\n if (!canPrompt({ json: args.json === true })) {\n throw new SeoError(\n 'AUTH_REQUIRED',\n 'Not logged in. Run `seo auth login`, or pass --skip-auth to save a project profile without connecting Google.',\n )\n }\n\n const choice = maybeExitCancelled(\n await select<AuthSetupChoice>({\n message: 'Connect Google now?',\n options: authSetupOptions({\n sharedConfigured: status.sharedConfigured,\n byoConfigured: status.byoConfigured,\n canSkip: typeof args.site === 'string' && args.site.length > 0,\n }),\n }),\n )\n\n if (choice === 'skip') return 'skipped'\n if (choice === 'setup') {\n const clientId = maybeExitCancelled(\n await text({\n message: 'Google Desktop OAuth client ID',\n validate: (value) => (value ? undefined : 'Client ID is required'),\n }),\n )\n const clientSecret = maybeExitCancelled(\n await password({\n message: 'Google Desktop OAuth client secret',\n validate: (value) => (value ? undefined : 'Client secret is required'),\n }),\n )\n writeOauthClient({ clientId, clientSecret })\n }\n\n const tokens = await loginWithLoopback()\n note(\n `Connected as ${tokens.account_email}. seo has read-only access and cannot change your site.`,\n 'Google connected',\n )\n return 'connected'\n}\n\nexport async function chooseGa4Property(input: {\n property?: string\n site: string\n interactive?: boolean\n}): Promise<SetupGa4Selection | undefined> {\n if (input.property) {\n return {\n propertyId: input.property,\n selection: 'explicit',\n reason: 'Set with --ga4.',\n }\n }\n const interactive = input.interactive ?? canPrompt()\n if (!interactive) return undefined\n\n const summaries = await listGa4AccountSummaries().catch(() => [])\n const properties: Ga4PropertyChoice[] = summaries.flatMap((account) =>\n account.propertySummaries.map((property) => ({\n property: ga4PropertyIdFromName(property.property),\n label: property.displayName ?? property.property,\n account: account.displayName ?? account.account,\n })),\n )\n if (!properties.length) return undefined\n\n const { candidates, complete: streamsComplete } =\n await findGa4WebStreamCandidates(properties)\n const matches = streamsComplete\n ? matchGa4WebStreams(input.site, candidates)\n : []\n const matchesByProperty = new Map<string, Ga4WebStreamMatch>()\n for (const match of matches) {\n matchesByProperty.set(match.property, match)\n }\n const matchedProperties = [...matchesByProperty.values()]\n\n if (matchedProperties.length === 1) {\n const match = matchedProperties[0]\n if (!match) return undefined\n return {\n propertyId: match.property,\n selection: 'matched',\n reason: ga4MatchReason(match, input.site),\n }\n }\n\n const choices: Ga4SetupChoice[] = matchedProperties.length\n ? matchedProperties.map((match) => ({\n property: match.property,\n label: match.propertyName,\n account: match.account,\n match,\n }))\n : properties\n\n const choice = maybeExitCancelled(\n await select<Ga4SetupChoice | ''>({\n message: matchedProperties.length\n ? 'Several GA4 properties match this site. Which property should seo use?'\n : streamsComplete\n ? 'No GA4 web stream clearly matches this site. Attach a property?'\n : 'Some GA4 web streams could not be read. Attach a property?',\n options: [\n { value: '', label: 'Skip GA4 for now' },\n ...choices.map((property) => ({\n value: property,\n label: `${property.label} (${property.property})`,\n hint: property.match\n ? ga4MatchReason(property.match, input.site)\n : property.account,\n })),\n ],\n }),\n )\n if (!choice) return undefined\n\n return {\n propertyId: choice.property,\n selection: 'manual',\n reason: choice.match\n ? ga4MatchReason(choice.match, input.site)\n : streamsComplete\n ? `Selected ${choice.label} during setup. Its web stream did not clearly match ${input.site}.`\n : `Selected ${choice.label} during setup. seo could not read every GA4 web stream, so it did not guess a match.`,\n }\n}\n\nexport async function maybeInstallSkill(\n args: Record<string, unknown>,\n): Promise<SetupSkillInstall> {\n if (args['skip-skill'] || !canPrompt({ json: args.json === true })) {\n return { status: 'skipped' }\n }\n const shouldInstall = maybeExitCancelled(\n await confirm({\n message:\n 'Install the SEO skill so coding agents know how to run reports?',\n initialValue: true,\n }),\n )\n if (!shouldInstall) return { status: 'declined' }\n\n const result = spawnSync('npx', ['-y', 'skills', 'add', 'iannuttall/seo'], {\n stdio: 'inherit',\n })\n if (result.error) {\n return { status: 'failed', error: result.error.message }\n }\n if (result.status !== 0) {\n return {\n status: 'failed',\n error: `npx skills add exited with status ${result.status ?? 'unknown'}.`,\n }\n }\n return { status: 'installed' }\n}\n\nexport async function maybeInstallMcp(\n args: Record<string, unknown>,\n): Promise<SetupMcpInstall[]> {\n if (args['skip-mcp'] || !canPrompt({ json: args.json === true })) return []\n const detected = detectMcpClients()\n if (detected.length === 0) return []\n const shouldInstall = maybeExitCancelled(\n await confirm({\n message: 'Install seo as an MCP server too?',\n initialValue: true,\n }),\n )\n if (!shouldInstall) return []\n\n const selected = maybeExitCancelled(\n await multiselect({\n message: 'Which MCP clients?',\n options: detected.map((target) => ({\n value: target.client,\n label: target.label,\n hint: target.path,\n })),\n initialValues: detected.map((target) => target.client),\n }),\n )\n\n return detected\n .filter((target) => selected.includes(target.client))\n .map((target) => {\n try {\n return installMcpConfig(target)\n } catch (error) {\n return {\n client: target.client,\n path: target.path,\n changed: false,\n error: error instanceof Error ? error.message : String(error),\n }\n }\n })\n}\n","import { confirm, intro, note, outro, text } from '@clack/prompts'\nimport {\n type ClientProfile,\n deriveBrandTerms,\n ensureSeoCliDirs,\n listClients,\n saveClient,\n} from '@seo/core'\nimport pc from 'picocolors'\nimport {\n booleanArg,\n jsonFlag,\n listArg,\n numberArg,\n stringArg,\n} from '../../args.js'\nimport { resolveSite } from '../../selection.js'\nimport {\n canPrompt,\n maybeExitCancelled,\n printJson,\n printKeyValue,\n} from '../../utils.js'\nimport { slugId, startUrlForSite, suggestedClientName } from '../shared.js'\nimport {\n chooseGa4Property,\n maybeConnectAuth,\n maybeInstallMcp,\n maybeInstallSkill,\n type SetupAuthStatus,\n type SetupGa4Selection,\n type SetupMcpInstall,\n type SetupSkillInstall,\n} from './prompts.js'\n\ntype SetupResult = {\n client?: ClientProfile\n site: string\n auth: SetupAuthStatus\n ga4?: SetupGa4Selection\n mcp: SetupMcpInstall[]\n skill?: SetupSkillInstall\n next: string[]\n}\n\nfunction skillInstallLabel(skill: SetupSkillInstall): string {\n if (skill.status === 'installed') return 'installed'\n if (skill.status === 'failed') return 'install failed'\n return 'not installed'\n}\n\nfunction shellArg(value: string): string {\n if (/^[A-Za-z0-9_./:@-]+$/.test(value)) {\n return value\n }\n return `'${value.replaceAll(\"'\", \"'\\\\''\")}'`\n}\n\nfunction printStarAsk(): void {\n console.log(\n pc.dim(\n 'Find seo useful? A star helps other people discover it: https://github.com/iannuttall/seo',\n ),\n )\n}\n\nfunction mcpInstallLabel(installs: SetupMcpInstall[]): string {\n const failed = installs.filter((install) => install.error).length\n const installed = installs.length - failed\n if (installs.length === 0) return 'not installed'\n if (failed === 0) return `${installed} installed`\n if (installed === 0) return `${failed} skipped`\n return `${installed} installed, ${failed} skipped`\n}\n\nfunction mcpFailureMessage(installs: SetupMcpInstall[]): string | undefined {\n const failures = installs.filter(\n (install): install is SetupMcpInstall & { error: string } =>\n Boolean(install.error),\n )\n if (failures.length === 0) return undefined\n return failures\n .map((install) => `${install.client}: ${install.error}`)\n .join('\\n')\n}\n\nfunction existingProfileForSetup(\n site: string,\n name: string,\n requestedId: string | undefined,\n): ClientProfile | undefined {\n if (requestedId) return undefined\n const matches = listClients().filter((client) => client.siteUrl === site)\n if (matches.length === 1) return matches[0]\n return (\n matches.find((client) => client.isDefault) ??\n matches.find(\n (client) => client.name.toLocaleLowerCase() === name.toLocaleLowerCase(),\n )\n )\n}\n\nexport async function runGuidedSetup(\n args: Record<string, unknown>,\n): Promise<void> {\n const json = jsonFlag(args)\n if (!json) intro(process.argv[2] === 'start' ? 'seo start' : 'seo setup')\n\n if (args['dry-run']) {\n const next = [\n 'seo auth login',\n 'seo start',\n 'seo report --project acme',\n 'seo refresh-priorities --project acme --verify-content',\n 'seo technical-watch --project acme',\n ]\n if (json) {\n printJson({ dryRun: true, next })\n } else {\n note(next.join('\\n'), 'This setup will guide you through')\n outro('Dry run complete.')\n }\n return\n }\n\n ensureSeoCliDirs()\n const siteInput = {\n site: stringArg(args.site),\n options: { json, refresh: booleanArg(args.refresh) },\n }\n const selectedSite = json ? await resolveSite(siteInput) : undefined\n const auth = await maybeConnectAuth(args)\n const site = selectedSite ?? (await resolveSite(siteInput))\n const defaultName = suggestedClientName(site)\n if (canPrompt({ json })) {\n note(\n 'A project profile remembers the site and report defaults so future commands stay short.',\n 'Project profile',\n )\n }\n const shouldSaveProfile =\n booleanArg(args['skip-profile']) === true\n ? false\n : canPrompt({ json })\n ? maybeExitCancelled(\n await confirm({\n message: 'Save this site as a project profile?',\n initialValue: true,\n }),\n )\n : true\n\n if (!shouldSaveProfile) {\n const mcp = await maybeInstallMcp(args)\n const skill = await maybeInstallSkill(args)\n const siteArg = `--site ${shellArg(site)}`\n const next = [\n `seo report ${siteArg}`,\n `seo refresh-priorities ${siteArg} --verify-content`,\n `seo technical-watch ${siteArg}`,\n ]\n const result: SetupResult = { site, auth, mcp, skill, next }\n\n if (json) {\n printJson(result)\n return\n }\n\n printKeyValue([\n ['Project profile', 'not saved'],\n ['GSC property', site],\n ['Auth', auth],\n ['MCP', mcpInstallLabel(mcp)],\n ['SEO skill', skillInstallLabel(skill)],\n ])\n const mcpFailure = mcpFailureMessage(mcp)\n if (mcpFailure) note(mcpFailure, 'MCP setup skipped')\n if (skill.error) note(skill.error, 'SEO skill install failed')\n note(next.join('\\n'), 'Try next')\n outro('Setup complete.')\n printStarAsk()\n return\n }\n\n const name =\n stringArg(args.name) ??\n (canPrompt({ json })\n ? maybeExitCancelled(\n await text({\n message: 'Project name',\n placeholder: defaultName,\n defaultValue: defaultName,\n }),\n )\n : defaultName)\n const requestedId = stringArg(args.id)\n const id =\n requestedId ??\n existingProfileForSetup(site, name, requestedId)?.id ??\n slugId(name)\n const defaultStartUrl = startUrlForSite(site) ?? ''\n const startUrl =\n stringArg(args.url) ??\n (canPrompt({ json })\n ? maybeExitCancelled(\n await text({\n message: 'Website URL to crawl',\n placeholder: defaultStartUrl || 'https://example.com',\n defaultValue: defaultStartUrl,\n }),\n )\n : defaultStartUrl || undefined)\n const watchUrls = listArg(args.urls).length > 0 ? listArg(args.urls) : []\n const ga4 = await chooseGa4Property({\n property: stringArg(args.ga4),\n site,\n interactive: canPrompt({ json }),\n })\n const ga4PropertyId = ga4?.propertyId\n const derivedBrandTerms = deriveBrandTerms({ id, name, siteUrl: site })\n const brandTerms =\n listArg(args.brand).length > 0 ? listArg(args.brand) : derivedBrandTerms\n const reportDay = numberArg(args['report-day']) ?? 1\n const technicalWeekday = numberArg(args.weekday) ?? 1\n const isDefault = booleanArg(args.default) ?? true\n\n const client = saveClient({\n id,\n name,\n siteUrl: site,\n startUrl,\n watchUrls,\n brandTerms,\n ga4PropertyId,\n reportDay,\n technicalWeekday,\n isDefault,\n })\n const mcp = await maybeInstallMcp(args)\n const skill = await maybeInstallSkill(args)\n const next = [\n `seo report --project ${client.id}`,\n `seo refresh-priorities --project ${client.id} --verify-content`,\n `seo technical-watch --project ${client.id}`,\n ]\n const result: SetupResult = { client, site, auth, ga4, mcp, skill, next }\n\n if (json) {\n printJson(result)\n return\n }\n\n printKeyValue([\n ['Project profile', `${client.name} (${client.id})`],\n ['GSC property', client.siteUrl],\n ['Crawl URL', client.startUrl ?? 'not set'],\n ['Watch URLs', String(client.watchUrls.length)],\n ['Brand terms', client.brandTerms.join(', ') || 'not set'],\n ['GA4 property', client.ga4PropertyId ?? 'not connected (optional)'],\n ...(ga4 ? [['GA4 selection', ga4.reason] as [string, string]] : []),\n ['Auth', auth],\n ['MCP', mcpInstallLabel(mcp)],\n ['SEO skill', skillInstallLabel(skill)],\n ])\n const mcpFailure = mcpFailureMessage(mcp)\n if (mcpFailure) note(mcpFailure, 'MCP setup skipped')\n if (skill.error) note(skill.error, 'SEO skill install failed')\n note(next.join('\\n'), 'Try next')\n outro('Setup complete.')\n printStarAsk()\n}\n","import { defineCommand } from 'citty'\nimport { runGuidedSetup } from './flow.js'\n\nexport const setupCommand = defineCommand({\n meta: {\n name: 'setup',\n description:\n 'Guided setup for auth, one project profile, MCP, and next commands',\n },\n args: {\n id: { type: 'string', description: 'Short stable project id.' },\n name: { type: 'string', description: 'Human project name.' },\n site: {\n type: 'string',\n description: 'GSC property URL, for example sc-domain:example.com.',\n },\n url: { type: 'string', description: 'Default technical crawl start URL.' },\n urls: {\n type: 'string',\n description: 'Comma-separated URLs to watch with URL Inspection.',\n },\n ga4: { type: 'string', description: 'Optional GA4 property ID.' },\n brand: {\n type: 'string',\n description: 'Comma-separated branded query terms to exclude by default.',\n },\n 'report-day': {\n type: 'string',\n description: 'Preferred monthly report day. Defaults to 1.',\n },\n weekday: {\n type: 'string',\n description: 'Preferred technical-watch weekday. Defaults to Monday.',\n },\n default: {\n type: 'boolean',\n description: 'Make this the default project.',\n },\n 'skip-profile': {\n type: 'boolean',\n default: false,\n description: 'Do not save a project profile during setup.',\n },\n 'skip-auth': {\n type: 'boolean',\n default: false,\n description: 'Skip Google sign-in during setup.',\n },\n 'skip-mcp': {\n type: 'boolean',\n default: false,\n description: 'Skip MCP install prompts.',\n },\n 'skip-skill': {\n type: 'boolean',\n default: false,\n description: 'Skip the SEO skill install prompt.',\n },\n refresh: {\n type: 'boolean',\n default: false,\n description: 'Refresh GSC property discovery.',\n },\n 'dry-run': {\n type: 'boolean',\n default: false,\n description: 'Show what setup does without changing files.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => runGuidedSetup(args),\n})\n\nexport const startCommand = defineCommand({\n ...setupCommand,\n meta: {\n name: 'start',\n description:\n 'Start here: connect Google, save a profile, and get the first report commands',\n },\n})\n\nexport const clientSetupCommand = defineCommand({\n ...setupCommand,\n meta: {\n name: 'setup',\n description: 'Guided setup for one saved project profile',\n },\n})\n","import { detectBrandTerms, getClient, saveClient } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n jsonFlag,\n numberArg,\n projectArg,\n stringArg,\n} from '../../args.js'\nimport { resolveSite } from '../../selection.js'\nimport { printJson, printKeyValue, printTable } from '../../utils.js'\n\nexport const clientBrandCommand = defineCommand({\n meta: {\n name: 'brand',\n description: 'Detect and manage project brand query terms',\n },\n subCommands: {\n detect: defineCommand({\n meta: {\n name: 'detect',\n description:\n 'Suggest branded query terms from GSC navigational queries',\n },\n args: {\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name. Defaults to default.',\n },\n site: {\n type: 'string',\n description: 'GSC property URL, for example sc-domain:example.com.',\n },\n days: {\n type: 'string',\n description: 'Detection window length in days. Defaults to 28.',\n },\n limit: {\n type: 'string',\n description: 'Maximum candidate terms. Defaults to 10.',\n },\n 'min-impressions': {\n type: 'string',\n description: 'Minimum query impressions. Defaults to 10.',\n },\n save: {\n type: 'boolean',\n default: false,\n description: 'Save suggested terms to the selected project.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n refresh: {\n type: 'boolean',\n default: false,\n description: 'Bypass local GSC cache.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const client = getClient(projectArg(args))\n const siteUrl = await resolveSite({\n site: stringArg(args.site) ?? client?.siteUrl,\n options: { json, refresh: booleanArg(args.refresh) },\n })\n const detection = await detectBrandTerms({\n site: siteUrl,\n id: client?.id,\n name: client?.name,\n days: numberArg(args.days),\n limit: numberArg(args.limit),\n minImpressions: numberArg(args['min-impressions']),\n refresh: booleanArg(args.refresh),\n })\n const saved =\n booleanArg(args.save) && client\n ? saveClient({\n id: client.id,\n name: client.name,\n siteUrl: client.siteUrl,\n startUrl: client.startUrl,\n watchUrls: client.watchUrls,\n ga4PropertyId: client.ga4PropertyId,\n brandTerms: detection.suggestedTerms,\n reportDay: client.reportDay,\n technicalWeekday: client.technicalWeekday,\n isDefault: client.isDefault,\n })\n : undefined\n\n if (booleanArg(args.save) && !client) {\n throw new Error('Pass --project to save detected brand terms.')\n }\n if (json) {\n printJson({ ...detection, saved })\n return\n }\n\n printKeyValue([\n ['Property', detection.site],\n ['Derived terms', detection.derivedTerms.join(', ')],\n ['Suggested terms', detection.suggestedTerms.join(', ')],\n ['Saved', saved ? saved.id : 'no'],\n ])\n printTable(\n ['Term', 'Score', 'Evidence'],\n detection.candidates.map((candidate) => [\n candidate.term,\n candidate.score,\n candidate.evidence\n .map(\n (item) => `${item.query} (${Math.round(item.clicks)} clicks)`,\n )\n .join(', '),\n ]),\n )\n },\n }),\n },\n})\n","import type { ClientProfile } from '@seo/core'\nimport { printKeyValue, printTable } from '../../../utils.js'\n\nexport function printClientList(clients: ClientProfile[]): void {\n printTable(\n [\n 'Default',\n 'ID',\n 'Name',\n 'GSC property',\n 'Crawl URL',\n 'Watch URLs',\n 'Brand terms',\n ],\n clients.map((client) => [\n client.isDefault ? 'yes' : '',\n client.id,\n client.name,\n client.siteUrl,\n client.startUrl ?? '',\n client.watchUrls.length,\n client.brandTerms.join(', '),\n ]),\n )\n}\n\nexport function printClientProfile(client: ClientProfile): void {\n printKeyValue([\n ['ID', client.id],\n ['Name', client.name],\n ['GSC property', client.siteUrl],\n ['Crawl URL', client.startUrl ?? 'not set'],\n ['Watch URLs', client.watchUrls.join(', ') || 'not set'],\n ['Brand terms', client.brandTerms.join(', ') || 'not set'],\n ['GA4 property', client.ga4PropertyId ?? 'not set'],\n ['Report day', client.reportDay ? String(client.reportDay) : 'not set'],\n [\n 'Technical weekday',\n client.technicalWeekday === undefined\n ? 'not set'\n : String(client.technicalWeekday),\n ],\n ['Default', client.isDefault ? 'yes' : 'no'],\n ])\n}\n","import { saveClient } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n jsonFlag,\n listArg,\n numberArg,\n stringArg,\n} from '../../../args.js'\nimport { resolveSite } from '../../../selection.js'\nimport { printJson } from '../../../utils.js'\nimport { printClientProfile } from './output.js'\n\nexport const clientAddCommand = defineCommand({\n meta: {\n name: 'add',\n description: 'Create or update a project profile',\n },\n args: {\n id: {\n type: 'string',\n description: 'Short stable project id, for example acme.',\n },\n name: {\n type: 'string',\n description: 'Human project name.',\n },\n site: {\n type: 'string',\n description: 'GSC property URL, for example sc-domain:example.com.',\n },\n url: {\n type: 'string',\n description: 'Default technical crawl start URL.',\n },\n urls: {\n type: 'string',\n description: 'Comma-separated URLs to watch with URL Inspection.',\n },\n ga4: {\n type: 'string',\n description: 'Optional GA4 property ID for this project.',\n },\n brand: {\n type: 'string',\n description: 'Comma-separated branded query terms to exclude by default.',\n },\n 'report-day': {\n type: 'string',\n description: 'Preferred monthly report day, 1-31.',\n },\n weekday: {\n type: 'string',\n description: 'Preferred technical-watch weekday, 0-7.',\n },\n default: {\n type: 'boolean',\n description: 'Make this the default project.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const client = saveClient({\n id: stringArg(args.id),\n name: stringArg(args.name),\n siteUrl: await resolveSite({\n site: stringArg(args.site),\n options: { json },\n }),\n startUrl: stringArg(args.url),\n watchUrls: listArg(args.urls),\n brandTerms: listArg(args.brand),\n ga4PropertyId: stringArg(args.ga4),\n reportDay: numberArg(args['report-day']),\n technicalWeekday: numberArg(args.weekday),\n isDefault: booleanArg(args.default),\n })\n if (json) {\n printJson(client)\n return\n }\n printClientProfile(client)\n },\n})\n","import { setDefaultClient } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { jsonFlag, stringArg } from '../../../args.js'\nimport { printJson } from '../../../utils.js'\n\nexport const clientDefaultCommand = defineCommand({\n meta: {\n name: 'default',\n description: 'Set the default project',\n },\n args: {\n id: {\n type: 'string',\n required: true,\n description: 'Project id or name.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const client = setDefaultClient(stringArg(args.id) ?? '')\n if (jsonFlag(args)) {\n printJson(client)\n return\n }\n process.stdout.write(`Default project set to ${client.id}.\\n`)\n },\n})\n","import { deleteClient } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { jsonFlag, stringArg } from '../../../args.js'\nimport { printJson } from '../../../utils.js'\n\nexport const clientDeleteCommand = defineCommand({\n meta: {\n name: 'delete',\n description: 'Delete a project profile',\n },\n args: {\n id: {\n type: 'string',\n required: true,\n description: 'Project id or name.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const id = stringArg(args.id) ?? ''\n const deleted = deleteClient(id)\n if (jsonFlag(args)) {\n printJson({ id, deleted })\n return\n }\n process.stdout.write(`${deleted ? 'Deleted' : 'Not found'} ${id}.\\n`)\n },\n})\n","import { listClients } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { jsonFlag } from '../../../args.js'\nimport { printJson } from '../../../utils.js'\nimport { printClientList } from './output.js'\n\nexport const clientListCommand = defineCommand({\n meta: {\n name: 'list',\n description: 'List saved project profiles',\n },\n args: {\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const clients = listClients()\n if (jsonFlag(args)) {\n printJson({ clients })\n return\n }\n printClientList(clients)\n },\n})\n","import { getClient } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { jsonFlag, stringArg } from '../../../args.js'\nimport { printJson } from '../../../utils.js'\nimport { printClientProfile } from './output.js'\n\nexport const clientShowCommand = defineCommand({\n meta: {\n name: 'show',\n description: 'Show one project profile',\n },\n args: {\n id: {\n type: 'string',\n description: 'Project id or name. Defaults to the default project.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const client = getClient(stringArg(args.id))\n if (!client) throw new Error('Project not found.')\n if (jsonFlag(args)) {\n printJson(client)\n return\n }\n printClientProfile(client)\n },\n})\n","import { clientAddCommand } from './profiles/add.js'\nimport { clientDefaultCommand } from './profiles/default.js'\nimport { clientDeleteCommand } from './profiles/delete.js'\nimport { clientListCommand } from './profiles/list.js'\nimport { clientShowCommand } from './profiles/show.js'\n\nexport const clientProfileCommands = {\n list: clientListCommand,\n add: clientAddCommand,\n show: clientShowCommand,\n default: clientDefaultCommand,\n delete: clientDeleteCommand,\n}\n","import { defineCommand } from 'citty'\nimport { clientSetupCommand } from '../setup/index.js'\nimport { clientBrandCommand } from './brand.js'\nimport { clientProfileCommands } from './profiles.js'\n\nexport const clientCommand = defineCommand({\n meta: {\n name: 'client',\n description: 'Manage saved project profiles',\n },\n subCommands: {\n setup: clientSetupCommand,\n brand: clientBrandCommand,\n ...clientProfileCommands,\n },\n})\n\nexport const projectCommand = defineCommand({\n ...clientCommand,\n meta: {\n name: 'projects',\n description: 'Manage saved project profiles',\n },\n})\n","import { printTable } from '../utils.js'\n\nconst HUMAN_ROW_LIMIT = 25\ntype TableRow = Array<string | number>\ntype ActionDetail = {\n label: string\n action: string\n context?: string\n}\n\nexport function formatCount(value: number): string {\n return Math.round(value).toLocaleString('en-GB')\n}\n\nexport function formatPosition(value: number): string {\n return value.toFixed(1)\n}\n\nexport function formatPercent(value: number): string {\n return `${(value * 100).toFixed(1)}%`\n}\n\nexport function truncate(value: string, maxLength = 72): string {\n if (value.length <= maxLength) return value\n return `${value.slice(0, maxLength - 3)}...`\n}\n\nexport function verificationSummary(report: {\n verification?: { requested: boolean; verified: number; failed: number }\n}): string {\n if (!report.verification?.requested) return 'off'\n return `${report.verification.verified} checked, ${report.verification.failed} failed`\n}\n\nexport function printLimitedTable(head: string[], rows: TableRow[]): void {\n printTable(head, rows.slice(0, HUMAN_ROW_LIMIT))\n if (rows.length > HUMAN_ROW_LIMIT) {\n process.stdout.write(\n `Showing ${HUMAN_ROW_LIMIT} of ${rows.length}. Use --json for full data.\\n`,\n )\n }\n}\n\nexport function printActionDetails(\n title: string,\n actions: ActionDetail[],\n limit = 5,\n): void {\n const visible = actions\n .filter((item) => item.action.trim().length > 0)\n .slice(0, limit)\n if (!visible.length) return\n\n process.stdout.write(`\\n${title}\\n`)\n for (const [index, item] of visible.entries()) {\n const context = item.context ? ` (${item.context})` : ''\n process.stdout.write(\n `${index + 1}. ${item.label}${context}: ${item.action}\\n`,\n )\n }\n if (actions.length > visible.length) {\n process.stdout.write(\n `Showing ${visible.length} of ${actions.length}. Use --json for full data.\\n`,\n )\n }\n}\n\nexport function printNextCommand(command: string): void {\n process.stdout.write(`\\nNext: ${command}\\n`)\n}\n\nexport function printNotes(title: string, notes: string[]): void {\n const visible = notes.filter((note) => note.trim().length > 0)\n if (!visible.length) return\n process.stdout.write(`\\n${title}\\n`)\n for (const note of visible) {\n process.stdout.write(`- ${note}\\n`)\n }\n}\n","import { contentOptimizationReport } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n defaultTrueBooleanArg,\n jsonFlag,\n numberArg,\n projectArg,\n stringArg,\n} from '../args.js'\nimport { resolveClientSelection } from '../selection.js'\nimport { printJson, printKeyValue } from '../utils.js'\nimport {\n formatCount,\n printActionDetails,\n printLimitedTable,\n printNotes,\n truncate,\n} from './output.js'\n\nexport const contentCommand = defineCommand({\n meta: {\n name: 'content',\n description: 'Optimize page content from real GSC queries',\n },\n subCommands: {\n optimize: defineCommand({\n meta: {\n name: 'optimize',\n description: 'Build a content optimization report for one URL',\n },\n args: {\n site: { type: 'string' },\n client: { type: 'string', description: 'Legacy alias for --project.' },\n project: { type: 'string', description: 'Saved project id or name.' },\n url: { type: 'string', required: true },\n days: {\n type: 'string',\n description: 'GSC lookback days. Defaults to 28.',\n },\n limit: {\n type: 'string',\n description: 'Maximum GSC queries to inspect. Defaults to 25.',\n },\n 'min-impressions': {\n type: 'string',\n description: 'Minimum query impressions. Defaults to 10.',\n },\n 'include-brand': {\n type: 'boolean',\n default: false,\n description: 'Include branded queries.',\n },\n 'verify-content': defaultTrueBooleanArg(\n 'Fetch the page for content checks. Defaults to true.',\n 'Skip fetching the page for content checks.',\n ),\n js: {\n type: 'boolean',\n default: false,\n description: 'Force JavaScript rendering for page extraction.',\n },\n refresh: {\n type: 'boolean',\n default: false,\n description: 'Bypass local GSC and HTTP cache.',\n },\n json: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json, refresh: booleanArg(args.refresh) },\n })\n const report = await contentOptimizationReport({\n site: selection.site,\n url: stringArg(args.url) ?? '',\n days: numberArg(args.days),\n limit: numberArg(args.limit),\n minImpressions: numberArg(args['min-impressions']),\n brandTerms: selection.client?.brandTerms,\n includeBrand: booleanArg(args['include-brand']),\n verifyContent: booleanArg(args['verify-content']) !== false,\n js: booleanArg(args.js) ? true : 'auto',\n refresh: booleanArg(args.refresh),\n })\n if (json) {\n printJson(report)\n return\n }\n\n printKeyValue([\n ['Property', report.site],\n ['URL', report.url],\n ['Score', `${report.summary.score}/100`],\n ['Primary intent', report.summary.primaryIntent],\n ['Primary query', report.summary.primaryQuery ?? 'none'],\n ['Queries', formatCount(report.summary.queries)],\n ['Opportunities', formatCount(report.summary.opportunities)],\n ['Estimated lift', formatCount(report.summary.estimatedClickLift)],\n ['Verdict', report.summary.verdict],\n ])\n\n printActionDetails(\n 'Top actions',\n report.topActions.map((action) => ({\n label: action.title,\n action: action.action,\n context: action.plainEnglish,\n })),\n )\n\n if (report.brief.sections.length) {\n process.stdout.write('\\nSuggested sections\\n')\n printLimitedTable(\n ['Heading', 'Queries'],\n report.brief.sections.map((section) => [\n truncate(section.heading, 48),\n truncate(section.queries.join(', '), 80),\n ]),\n )\n }\n\n if (report.intentMix.length) {\n process.stdout.write('\\nIntent mix\\n')\n printLimitedTable(\n ['Intent', 'Queries', 'Impressions', 'Clicks'],\n report.intentMix.map((intent) => [\n intent.intent,\n formatCount(intent.queries),\n formatCount(intent.impressions),\n formatCount(intent.clicks),\n ]),\n )\n }\n\n printNotes('Caveats', report.caveats)\n },\n }),\n },\n})\n","import { mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { dirname } from 'node:path'\nimport {\n type CrawlOutputFormat,\n crawlSite,\n renderCrawlCsv,\n renderCrawlHtml,\n renderCrawlMarkdownTickets,\n renderCrawlPagesCsv,\n renderCrawlPretty,\n reviewObservations,\n saveCrawlReport,\n topFixes,\n} from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n csvArg,\n fetchRateArg,\n jsonFlag,\n negatedBooleanArg,\n numberArg,\n projectArg,\n renderingModeArg,\n stringArg,\n} from '../args.js'\nimport { resolveClientSelection } from '../selection.js'\nimport { printKeyValue } from '../utils.js'\nimport { startUrlForSite } from './shared.js'\n\ntype Severity = 'low' | 'medium' | 'high'\n\nconst severityRank: Record<Severity, number> = {\n high: 3,\n medium: 2,\n low: 1,\n}\n\nexport const crawlCommand = defineCommand({\n meta: {\n name: 'crawl',\n description: 'Crawl a site and run technical SEO checks',\n },\n args: {\n crawlUrl: {\n type: 'positional',\n required: false,\n description: 'Start URL to crawl.',\n },\n url: {\n type: 'string',\n description:\n 'Start URL to crawl. Optional when --project has a saved crawl URL.',\n },\n site: {\n type: 'string',\n description: 'GSC property URL for joining page metrics.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n 'ga4-property': {\n type: 'string',\n description:\n 'GA4 property ID for landing-page sessions. Defaults from --project when saved.',\n },\n mode: {\n type: 'string',\n description:\n 'Crawl mode: site, page, list, or sitemap. Defaults to site.',\n },\n urls: {\n type: 'string',\n description: 'Comma-separated URLs for list mode.',\n },\n 'urls-file': {\n type: 'string',\n description: 'File with one URL per line for list mode.',\n },\n 'max-pages': {\n type: 'string',\n description: 'Maximum pages to crawl. Defaults to 500.',\n },\n 'max-depth': {\n type: 'string',\n description: 'Maximum click depth. Defaults to 16.',\n },\n concurrency: {\n type: 'string',\n description: 'Parallel page fetches. Defaults to 8.',\n },\n 'fetch-interval-cap': {\n type: 'string',\n description: 'Maximum page fetches per interval per host.',\n },\n 'fetch-interval-ms': {\n type: 'string',\n description: 'Fetch rate interval in milliseconds.',\n },\n refresh: {\n type: 'boolean',\n default: false,\n description: 'Bypass local HTTP cache and fetch fresh pages.',\n },\n include: {\n type: 'string',\n description: 'Comma-separated URL patterns to include.',\n },\n exclude: {\n type: 'string',\n description: 'Comma-separated URL patterns to exclude.',\n },\n 'no-sitemap': {\n type: 'boolean',\n default: false,\n description: 'Do not seed URLs from sitemap.xml.',\n },\n 'no-robots': {\n type: 'boolean',\n default: false,\n description: 'Do not skip URLs disallowed by robots.txt.',\n },\n 'no-external': {\n type: 'boolean',\n default: false,\n description:\n 'Do not check external links. Reserved for full link checks.',\n },\n js: {\n type: 'boolean',\n default: false,\n description: 'Legacy alias for --rendering on.',\n },\n rendering: {\n type: 'string',\n description:\n 'JavaScript rendering mode: auto, on, or off. Defaults to auto.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON. Alias for --format json.',\n },\n format: {\n type: 'string',\n description: 'Output format: pretty, json, csv, html, or markdown.',\n },\n output: {\n type: 'string',\n description: 'Write output to this path instead of stdout.',\n },\n csv: {\n type: 'string',\n description: 'CSV table to render: issues or pages. Defaults to issues.',\n },\n save: {\n type: 'boolean',\n default: false,\n description: 'Save the crawl report locally.',\n },\n severity: {\n type: 'string',\n description: 'Only show top fixes at this severity.',\n },\n 'fail-on': {\n type: 'string',\n description: 'Exit non-zero when issues exist at this severity or above.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const format = crawlFormatArg(args.format, json)\n const output = stringArg(args.output)\n const csv = crawlCsvArg(args.csv)\n const severity = severityArg(args.severity)\n const failOn = severityArg(args['fail-on'])\n const project = projectArg(args)\n const urls = await urlListArgs(args)\n const explicitUrl = crawlUrlArg(args)\n const selection =\n stringArg(args.site) || project || (!explicitUrl && !urls.length)\n ? await resolveClientSelection({\n client: project,\n site: stringArg(args.site),\n options: { json },\n })\n : undefined\n const crawlUrl =\n explicitUrl ??\n selection?.client?.startUrl ??\n (selection?.site ? startUrlForSite(selection.site) : undefined) ??\n urls[0]\n if (!crawlUrl) {\n throw new Error(\n 'No crawl URL selected. Pass a URL, --url, or use --project with a saved crawl URL.',\n )\n }\n\n const report = await crawlSite({\n url: crawlUrl,\n projectId: selection?.client?.id,\n site: selection?.site,\n mode: crawlModeArg(args.mode) ?? (urls.length ? 'list' : undefined),\n urls,\n maxPages: numberArg(args['max-pages']),\n maxDepth: numberArg(args['max-depth']),\n concurrency: numberArg(args.concurrency),\n refresh: booleanArg(args.refresh),\n fetchRate: fetchRateArg({\n ...args,\n 'fetch-concurrency': args.concurrency,\n }),\n include: csvArg(args.include),\n exclude: csvArg(args.exclude),\n ga4PropertyId:\n stringArg(args['ga4-property']) ?? selection?.client?.ga4PropertyId,\n useSitemap: !negatedBooleanArg(args, 'sitemap'),\n respectRobots: !negatedBooleanArg(args, 'robots'),\n checkExternal: !negatedBooleanArg(args, 'external'),\n js: renderingModeArg(args),\n })\n const saved = booleanArg(args.save) ? saveCrawlReport(report) : undefined\n const rankedFixes = topFixes(report, { severity })\n const failedThreshold = failOn\n ? report.issues.some(\n (issue) => severityRank[issue.severity] >= severityRank[failOn],\n )\n : false\n const failedRun = report.status === 'failed'\n\n const payload = {\n ...report,\n topFixes: rankedFixes,\n reviewObservations: reviewObservations(report, { severity }),\n ...(failOn ? { failOn, failedThreshold } : {}),\n ...(saved ? { saved } : {}),\n }\n\n if (format === 'json') {\n await writeOrPrint(output, `${JSON.stringify(payload, null, 2)}\\n`)\n if (failedRun || failedThreshold) process.exitCode = 1\n return\n }\n\n if (format === 'csv') {\n await writeOrPrint(\n output,\n csv === 'pages' ? renderCrawlPagesCsv(report) : renderCrawlCsv(report),\n )\n if (failedRun || failedThreshold) process.exitCode = 1\n return\n }\n\n if (format === 'html') {\n await writeOrPrint(output, renderCrawlHtml(report, rankedFixes))\n if (failedRun || failedThreshold) process.exitCode = 1\n return\n }\n\n if (format === 'markdown') {\n await writeOrPrint(\n output,\n renderCrawlMarkdownTickets(report, rankedFixes),\n )\n if (failedRun || failedThreshold) process.exitCode = 1\n return\n }\n\n if (output) {\n await writeOrPrint(output, renderCrawlPretty(report, rankedFixes))\n if (failedRun || failedThreshold) process.exitCode = 1\n return\n }\n\n process.stdout.write(renderCrawlPretty(report, rankedFixes))\n if (saved || failOn) {\n process.stdout.write('\\nRun metadata\\n')\n printKeyValue([\n ['Saved report', saved?.id ?? 'no'],\n ['Fail threshold', failOn ?? 'off'],\n ])\n }\n if (failedRun || failedThreshold) {\n process.exitCode = 1\n }\n },\n})\n\nfunction crawlModeArg(value: unknown) {\n const mode = stringArg(value)\n if (!mode) return undefined\n if (['site', 'page', 'list', 'sitemap'].includes(mode)) {\n return mode as 'site' | 'page' | 'list' | 'sitemap'\n }\n throw new Error('Mode must be one of: site, page, list, sitemap.')\n}\n\nfunction severityArg(value: unknown): Severity | undefined {\n const severity = stringArg(value)\n if (!severity) return undefined\n if (['low', 'medium', 'high'].includes(severity)) {\n return severity as Severity\n }\n throw new Error('Severity must be one of: low, medium, high.')\n}\n\nfunction crawlUrlArg(args: Record<string, unknown>): string | undefined {\n const positional = stringArg(args.crawlUrl)\n const flag = stringArg(args.url)\n if (positional && flag && positional !== flag) {\n throw new Error('Use either a URL argument or --url, not both.')\n }\n return positional ?? flag\n}\n\nfunction crawlFormatArg(value: unknown, json: boolean): CrawlOutputFormat {\n const format = stringArg(value)\n if (json && format && format !== 'json') {\n throw new Error('Use either --json or --format, not both.')\n }\n if (!format) return json ? 'json' : 'pretty'\n if (['pretty', 'json', 'csv', 'html', 'markdown'].includes(format)) {\n return format as CrawlOutputFormat\n }\n throw new Error('Format must be one of: pretty, json, csv, html, markdown.')\n}\n\nfunction crawlCsvArg(value: unknown): 'issues' | 'pages' {\n const csv = stringArg(value)\n if (!csv) return 'issues'\n if (['issues', 'pages'].includes(csv)) return csv as 'issues' | 'pages'\n throw new Error('CSV table must be one of: issues, pages.')\n}\n\nasync function urlListArgs(args: Record<string, unknown>): Promise<string[]> {\n const urls = csvArg(args.urls) ?? []\n const file = stringArg(args['urls-file'])\n if (file) {\n urls.push(...parseUrlList(await readFile(file, 'utf8')))\n }\n return [...new Set(urls)]\n}\n\nfunction parseUrlList(value: string): string[] {\n return value\n .split(/[\\n,]/)\n .map((item) => item.trim())\n .filter((item) => item && !item.startsWith('#'))\n}\n\nasync function writeOrPrint(path: string | undefined, content: string) {\n if (!path) {\n process.stdout.write(content)\n return\n }\n await mkdir(dirname(path), { recursive: true })\n await writeFile(path, content)\n process.stdout.write(`Wrote ${path}\\n`)\n}\n","import {\n type CrawlReport,\n type CrawlReportMeta,\n compareCrawlReports,\n crawlSite,\n deleteCrawlReport,\n latestCrawlReport,\n listCrawlReports,\n loadCrawlReport,\n reviewObservations,\n saveCrawlReport,\n topFixes,\n} from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n jsonFlag,\n numberArg,\n projectArg,\n stringArg,\n} from '../args.js'\nimport { resolveClientSelection } from '../selection.js'\nimport { printJson, printKeyValue, printTable } from '../utils.js'\nimport { printNotes, truncate } from './output.js'\n\nasync function reportSiteFilter(args: Record<string, unknown>, json: boolean) {\n const project = projectArg(args)\n const site = stringArg(args.site)\n if (!project && !site) return undefined\n return (\n await resolveClientSelection({\n client: project,\n site,\n options: { json },\n })\n ).site\n}\n\nfunction printReportList(reports: CrawlReportMeta[]): void {\n if (!reports.length) {\n process.stdout.write('No saved crawl reports found.\\n')\n return\n }\n printTable(\n ['Created', 'Status', 'Pages', 'Issues', 'Site', 'ID'],\n reports.map((report) => [\n report.createdAt,\n report.status,\n String(report.totalPages),\n String(report.issueCount),\n report.site ?? '-',\n report.id,\n ]),\n )\n}\n\nfunction printReport(report: CrawlReport): void {\n const rows: Array<[string, string]> = [\n ['ID', report.id],\n ['URL', report.config.url],\n ['Site', report.site ?? '-'],\n ['Status', report.status],\n ['Generated', report.generatedAt],\n ['Pages', String(report.summary.totalPages)],\n ['Discovered', String(report.summary.discoveredUrls)],\n ['Queued', String(report.summary.queuedUrls)],\n ['Skipped', String(report.summary.skippedUrls)],\n ['Failed fetches', String(report.summary.failedUrls)],\n ['Observed internal links', String(report.summary.observedInternalLinks)],\n ['Indexable', String(report.summary.indexablePages)],\n ['Issues', String(report.issues.length)],\n ['High', String(report.summary.highIssues)],\n ['Medium', String(report.summary.mediumIssues)],\n ['Low', String(report.summary.lowIssues)],\n ]\n if (report.externalLinkVerification) {\n const external = report.externalLinkVerification\n rows.push([\n 'External links',\n `${external.fetchedUrls} fetched, ${external.failedUrls} failed, ${external.deferredUrls} deferred (${external.dataStatus})`,\n ])\n }\n printKeyValue(rows)\n\n if (report.issueGroups.length) {\n process.stdout.write('\\nTop issues\\n')\n printTable(\n ['Severity', 'Rule', 'Count', 'Sample URL'],\n report.issueGroups\n .slice(0, 10)\n .map((group) => [\n group.severity,\n group.ruleId,\n String(group.count),\n truncate(group.sampleUrls[0] ?? '', 64),\n ]),\n )\n }\n\n printNotes('Warnings', report.warnings.slice(0, 10))\n printNotes('Caveats', report.caveats)\n}\n\nfunction printReportDiff(report: ReturnType<typeof compareCrawlReports>): void {\n printKeyValue([\n ['Before', `${report.before.id} (${report.before.generatedAt})`],\n ['After', `${report.after.id} (${report.after.generatedAt})`],\n ['Comparability', report.comparability.status],\n ['Completeness', report.completeness.status],\n ['Truncated', report.completeness.truncated ? 'yes' : 'no'],\n ['Headline', report.headline],\n [\n 'Pages',\n `${report.after.summary.totalPages} (${report.summary.pageDelta >= 0 ? '+' : ''}${report.summary.pageDelta})`,\n ],\n [\n 'Issues',\n `${report.after.summary.highIssues + report.after.summary.mediumIssues + report.after.summary.lowIssues} (${report.summary.issueDelta >= 0 ? '+' : ''}${report.summary.issueDelta})`,\n ],\n ['New status errors', String(report.summary.newStatusErrors)],\n ['Fixed status errors', String(report.summary.fixedStatusErrors)],\n ['Issue groups worse', String(report.summary.issueGroupsWorse)],\n ['Issue groups better', String(report.summary.issueGroupsBetter)],\n ['Changed pages', String(report.summary.changedPages)],\n ['Added pages', String(report.summary.addedPages)],\n ['Removed pages', String(report.summary.removedPages)],\n ])\n\n if (report.topActions.length) {\n process.stdout.write('\\nTop actions\\n')\n for (const [index, action] of report.topActions.entries()) {\n process.stdout.write(`${index + 1}. ${action.title}: ${action.action}\\n`)\n process.stdout.write(` ${action.plainEnglish}\\n`)\n }\n }\n\n if (report.pageChanges.length) {\n process.stdout.write('\\nChanged pages\\n')\n printTable(\n ['Kind', 'Changes', 'URL'],\n report.pageChanges\n .slice(0, 15)\n .map((item) => [\n item.kind,\n item.changes.join(', '),\n truncate(item.url, 80),\n ]),\n )\n if (report.pageChanges.length > 15) {\n process.stdout.write(\n `Showing 15 of ${report.pageChanges.length}. Use --json for all changes.\\n`,\n )\n }\n }\n\n if (report.issueChanges.length) {\n process.stdout.write('\\nIssue movement\\n')\n printTable(\n ['Rule', 'Before', 'After', 'Delta'],\n report.issueChanges\n .slice(0, 10)\n .map((item) => [\n item.ruleId,\n String(item.before),\n String(item.after),\n `${item.delta >= 0 ? '+' : ''}${item.delta}`,\n ]),\n )\n }\n\n printNotes('Caveats', report.caveats)\n}\n\nfunction selectReportAliasMeta(\n reports: CrawlReportMeta[],\n input: {\n value: 'latest' | 'previous'\n skipId?: string\n },\n): CrawlReportMeta | undefined {\n if (input.value === 'latest') {\n return reports.find((item) => item.id !== input.skipId)\n }\n\n if (input.skipId) {\n const skippedIndex = reports.findIndex((item) => item.id === input.skipId)\n const older = skippedIndex >= 0 ? reports.slice(skippedIndex + 1) : reports\n return older.find((item) => item.id !== input.skipId)\n }\n\n return reports[1]\n}\n\nfunction resolveReportAlias(input: {\n value: string\n site?: string\n skipId?: string\n}): CrawlReport | undefined {\n if (input.value !== 'latest' && input.value !== 'previous') {\n return loadCrawlReport(input.value)\n }\n const reports = listCrawlReports({ site: input.site, limit: 20 })\n const meta = selectReportAliasMeta(reports, {\n value: input.value,\n skipId: input.skipId,\n })\n return meta ? loadCrawlReport(meta.id) : undefined\n}\n\nexport const crawlReportsCommand = defineCommand({\n meta: {\n name: 'crawl-reports',\n description: 'List, show, or delete saved crawl reports',\n },\n args: {\n site: {\n type: 'string',\n description: 'GSC property URL for filtering reports.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n id: {\n type: 'string',\n description: 'Saved crawl report id to show.',\n },\n latest: {\n type: 'boolean',\n default: false,\n description: 'Show the latest saved crawl report.',\n },\n delete: {\n type: 'string',\n description: 'Delete a saved crawl report by id.',\n },\n rerun: {\n type: 'string',\n description: 'Rerun a saved crawl report by id, or pass latest.',\n },\n compare: {\n type: 'string',\n description: 'Compare a saved report id, latest, or previous.',\n },\n against: {\n type: 'string',\n description: 'Baseline report id. Defaults to previous.',\n },\n limit: {\n type: 'string',\n description: 'Maximum reports to list. Defaults to 20.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const site = await reportSiteFilter(args, json)\n const deleteId = stringArg(args.delete)\n const rerunId = stringArg(args.rerun)\n const compareId = stringArg(args.compare)\n const id = stringArg(args.id)\n\n if (deleteId) {\n const deleted = deleteCrawlReport(deleteId)\n if (json) {\n printJson({ id: deleteId, deleted })\n return\n }\n process.stdout.write(\n deleted\n ? `Deleted crawl report ${deleteId}.\\n`\n : `No saved crawl report found for ${deleteId}.\\n`,\n )\n return\n }\n\n if (rerunId) {\n const previous =\n rerunId === 'latest'\n ? latestCrawlReport(site)\n : loadCrawlReport(rerunId)\n if (!previous) {\n throw new Error(\n rerunId === 'latest'\n ? 'No saved crawl reports found.'\n : `No saved crawl report found for ${rerunId}.`,\n )\n }\n const report = await crawlSite({\n ...previous.config,\n projectId: previous.projectId,\n site: previous.site,\n ga4PropertyId: previous.ga4PropertyId,\n })\n const saved = saveCrawlReport(report)\n if (json) {\n printJson({\n ...report,\n rerunOf: previous.id,\n saved,\n topFixes: topFixes(report),\n reviewObservations: reviewObservations(report),\n })\n return\n }\n process.stdout.write(`Reran crawl report ${previous.id}.\\n\\n`)\n printReport(report)\n return\n }\n\n if (compareId) {\n const after = resolveReportAlias({ value: compareId, site })\n if (!after) {\n throw new Error(`No saved crawl report found for ${compareId}.`)\n }\n const beforeAlias = stringArg(args.against) ?? 'previous'\n const before = resolveReportAlias({\n value: beforeAlias,\n site: after.site ?? site,\n skipId: after.id,\n })\n if (!before) {\n throw new Error(\n `No baseline crawl report found for ${beforeAlias}. Save at least two reports or pass --against <id>.`,\n )\n }\n const diff = compareCrawlReports({ before, after })\n if (json) {\n printJson(diff)\n return\n }\n printReportDiff(diff)\n return\n }\n\n if (id || booleanArg(args.latest)) {\n const report = id ? loadCrawlReport(id) : latestCrawlReport(site)\n if (!report) {\n throw new Error(\n id\n ? `No saved crawl report found for ${id}.`\n : 'No saved crawl reports found.',\n )\n }\n if (json) {\n printJson(report)\n return\n }\n printReport(report)\n return\n }\n\n const reports = listCrawlReports({\n site,\n limit: numberArg(args.limit),\n })\n if (json) {\n printJson({ reports })\n return\n }\n printReportList(reports)\n },\n})\n","import {\n ga4RowsToObjects,\n inspectUrl,\n querySearchAnalytics,\n runGa4Report,\n} from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n csvArg,\n jsonBodyArg,\n jsonFlag,\n numberArg,\n projectArg,\n stringArg,\n} from '../args.js'\nimport { resolveClient, resolveGa4Property } from '../selection.js'\nimport { printJson, printKeyValue, printTable } from '../utils.js'\nimport { selectedSiteOrThrow } from './shared.js'\n\nexport const gscQueryCommand = defineCommand({\n meta: {\n name: 'gsc-query',\n description: 'Run a raw Search Console Search Analytics query',\n },\n args: {\n site: {\n type: 'string',\n description: 'GSC property URL, for example sc-domain:example.com.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n 'start-date': { type: 'string', description: 'Start date YYYY-MM-DD.' },\n 'end-date': { type: 'string', description: 'End date YYYY-MM-DD.' },\n dimensions: {\n type: 'string',\n description: 'Comma-separated GSC dimensions, for example query,page.',\n },\n type: { type: 'string', description: 'Search type. Defaults to web.' },\n limit: {\n type: 'string',\n description: 'Maximum rows to request and print.',\n },\n body: { type: 'string', description: 'Raw Search Analytics JSON body.' },\n 'body-file': {\n type: 'string',\n description: 'Path to a Search Analytics JSON body file.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n refresh: {\n type: 'boolean',\n default: false,\n description: 'Bypass local cache and fetch fresh GSC data.',\n },\n },\n run: async ({ args }) => {\n const body =\n (await jsonBodyArg(args.body, args['body-file'])) ??\n ({\n startDate: stringArg(args['start-date']),\n endDate: stringArg(args['end-date']),\n dimensions: csvArg(args.dimensions) ?? ['query', 'page'],\n type: stringArg(args.type) ?? 'web',\n rowLimit: numberArg(args.limit),\n dataState: 'final',\n } as Record<string, unknown>)\n const json = jsonFlag(args)\n const site = await selectedSiteOrThrow(\n {\n client: projectArg(args),\n site: stringArg(args.site) ?? stringArg(body.siteUrl),\n },\n { json, refresh: booleanArg(args.refresh) },\n )\n delete body.siteUrl\n const result = await querySearchAnalytics(site, body as never, {\n refresh: booleanArg(args.refresh),\n })\n const limit = numberArg(args.limit)\n const rows = limit ? result.rows.slice(0, limit) : result.rows\n if (json) {\n printJson({\n site,\n request: body,\n ...result,\n rows,\n rowsReturned: rows.length,\n })\n return\n }\n printKeyValue([\n ['Property', site],\n ['Rows returned', String(rows.length)],\n ['Rows fetched', String(result.rowsFetched)],\n ['API calls', String(result.calls)],\n ])\n printTable(\n ['Keys', 'Clicks', 'Impr', 'CTR', 'Pos'],\n rows\n .slice(0, 25)\n .map((row) => [\n row.keys.join(' | '),\n Math.round(row.clicks),\n Math.round(row.impressions),\n row.ctr.toFixed(3),\n row.position.toFixed(1),\n ]),\n )\n },\n})\n\nexport const urlInspectCommand = defineCommand({\n meta: {\n name: 'url-inspect',\n description: 'Inspect a URL with the Search Console URL Inspection API',\n },\n args: {\n site: {\n type: 'string',\n description: 'GSC property URL, for example sc-domain:example.com.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n url: { type: 'string', description: 'URL to inspect.' },\n language: {\n type: 'string',\n description: 'Optional inspection language code.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const siteUrl = await selectedSiteOrThrow(\n { client: projectArg(args), site: stringArg(args.site) },\n { json },\n )\n const inspectionUrl = stringArg(args.url)\n if (!inspectionUrl) throw new Error('Pass --url.')\n const result = await inspectUrl({\n siteUrl,\n inspectionUrl,\n languageCode: stringArg(args.language),\n })\n if (json) {\n printJson(result)\n return\n }\n const indexStatus = result.inspectionResult?.indexStatusResult\n printKeyValue([\n ['Property', siteUrl],\n ['URL', inspectionUrl],\n ['Verdict', indexStatus?.verdict ?? 'unknown'],\n ['Coverage', indexStatus?.coverageState ?? 'unknown'],\n ['Robots', indexStatus?.robotsTxtState ?? 'unknown'],\n ['Last crawl', indexStatus?.lastCrawlTime ?? 'unknown'],\n ['Google canonical', indexStatus?.googleCanonical ?? 'unknown'],\n ])\n },\n})\n\nexport const ga4ReportCommand = defineCommand({\n meta: {\n name: 'ga4-report',\n description: 'Run a GA4 Data API report',\n },\n args: {\n property: {\n type: 'string',\n description: 'GA4 property ID. If omitted in a terminal, choose one.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name with an optional GA4 property.',\n },\n 'start-date': { type: 'string', default: '28daysAgo' },\n 'end-date': { type: 'string', default: 'yesterday' },\n dimensions: { type: 'string', default: 'landingPage' },\n metrics: { type: 'string', default: 'sessions,totalUsers,eventCount' },\n limit: { type: 'string', default: '25' },\n body: { type: 'string' },\n 'body-file': { type: 'string' },\n refresh: {\n type: 'boolean',\n default: false,\n description: 'Bypass local GA4 cache.',\n },\n json: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const client = await resolveClient({\n client: projectArg(args),\n options: { json },\n })\n const property = await resolveGa4Property({\n property: stringArg(args.property) ?? client?.ga4PropertyId,\n options: { json },\n })\n const body =\n (await jsonBodyArg(args.body, args['body-file'])) ??\n ({\n dateRanges: [\n {\n startDate: stringArg(args['start-date']),\n endDate: stringArg(args['end-date']),\n },\n ],\n dimensions: (csvArg(args.dimensions) ?? []).map((name) => ({ name })),\n metrics: (csvArg(args.metrics) ?? []).map((name) => ({ name })),\n limit: stringArg(args.limit),\n } as Record<string, unknown>)\n const result = await runGa4Report(property, body as never, {\n refresh: booleanArg(args.refresh),\n })\n if (json) {\n printJson(result)\n return\n }\n const rows = ga4RowsToObjects(result)\n printKeyValue([\n ['Property', property],\n ['Rows', String(result.rowCount ?? rows.length)],\n ])\n if (rows.length) {\n const headings = Object.keys(rows[0] ?? {})\n printTable(\n headings,\n rows\n .slice(0, 25)\n .map((row) => headings.map((heading) => row[heading] ?? '')),\n )\n }\n },\n})\n","import type { ArgDef } from 'citty'\n\n// Shared report option metadata used by CLI commands. The parity check keeps\n// this aligned with scripts/report-surface-catalog.mjs.\ntype CliReportOption = {\n cli: string\n arg: ArgDef\n}\n\nconst REPORT_OPTIONS = {\n days: {\n cli: 'days',\n arg: {\n type: 'string',\n description: 'GSC lookback window. Defaults to 28.',\n },\n },\n recentDays: {\n cli: 'recent',\n arg: {\n type: 'string',\n description: 'Recent anomaly window in days. Defaults to 14.',\n },\n },\n range: {\n cli: 'days',\n arg: {\n type: 'string',\n description: 'GSC lookback window. Defaults to 28.',\n },\n },\n limit: {\n cli: 'limit',\n arg: {\n type: 'string',\n description: 'Maximum rows to return.',\n },\n },\n checkLimit: {\n cli: 'check-limit',\n arg: {\n type: 'string',\n description: 'Maximum candidate pages to fetch and check.',\n },\n },\n minImpressions: {\n cli: 'min-impressions',\n arg: {\n type: 'string',\n description: 'Minimum query impressions.',\n },\n },\n includeBrand: {\n cli: 'include-brand',\n arg: {\n type: 'boolean',\n default: false,\n description: 'Include branded queries in opportunity reports.',\n },\n },\n verifyContent: {\n cli: 'verify-content',\n arg: {\n type: 'boolean',\n default: false,\n description:\n 'Verify top opportunities against page title, meta, and content.',\n },\n },\n verifyLimit: {\n cli: 'verify-limit',\n arg: {\n type: 'string',\n description: 'Maximum opportunity URLs to verify.',\n },\n },\n js: {\n cli: 'js',\n arg: {\n type: 'boolean',\n default: false,\n description: 'Force JavaScript rendering for verified pages.',\n },\n },\n fetchConcurrency: {\n cli: 'fetch-concurrency',\n arg: {\n type: 'string',\n description: 'Maximum concurrent page fetches per host. Defaults to 4.',\n },\n },\n fetchIntervalCap: {\n cli: 'fetch-interval-cap',\n arg: {\n type: 'string',\n description: 'Maximum page fetches per interval per host. Defaults to 4.',\n },\n },\n fetchIntervalMs: {\n cli: 'fetch-interval-ms',\n arg: {\n type: 'string',\n description: 'Fetch rate interval in milliseconds. Defaults to 1000.',\n },\n },\n refresh: {\n cli: 'refresh',\n arg: {\n type: 'boolean',\n default: false,\n description: 'Bypass local cache and fetch fresh data.',\n },\n },\n} as const satisfies Record<string, CliReportOption>\n\ntype ReportOptionKey = keyof typeof REPORT_OPTIONS\n\nexport function cliReportArgs<const T extends readonly ReportOptionKey[]>(\n keys: T,\n overrides: Partial<Record<ReportOptionKey, Partial<ArgDef>>> = {},\n): Record<(typeof REPORT_OPTIONS)[T[number]]['cli'], ArgDef> {\n return Object.fromEntries(\n keys.map((key) => {\n const option = REPORT_OPTIONS[key]\n return [option.cli, { ...option.arg, ...overrides[key] }]\n }),\n ) as Record<(typeof REPORT_OPTIONS)[T[number]]['cli'], ArgDef>\n}\n","import { trafficAnomaly, updateCorrelation } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n jsonFlag,\n numberArg,\n projectArg,\n stringArg,\n} from '../args.js'\nimport { printJson, printKeyValue, printTable } from '../utils.js'\nimport { printLimitedTable, printNextCommand, printNotes } from './output.js'\nimport { cliReportArgs } from './report-options.js'\nimport { selectedSiteOrThrow } from './shared.js'\n\nfunction formatNumber(value: number): string {\n return value.toLocaleString('en-GB', {\n maximumFractionDigits: value >= 100 ? 0 : 1,\n })\n}\n\nfunction formatChange(value: number | null): string {\n if (value === null) return 'n/a'\n const rounded = Math.abs(value) >= 10 ? value.toFixed(0) : value.toFixed(1)\n return `${value > 0 ? '+' : ''}${rounded}%`\n}\n\nexport const trafficAnomalyCommand = defineCommand({\n meta: {\n name: 'traffic-anomaly',\n description: 'Detect unusual recent GSC traffic movement',\n },\n args: {\n site: { type: 'string' },\n project: { type: 'string', description: 'Saved project id or name.' },\n client: { type: 'string', description: 'Legacy alias for --project.' },\n ...cliReportArgs(['days', 'recentDays', 'refresh'], {\n days: { description: 'Baseline window length in days. Defaults to 90.' },\n recentDays: {\n description: 'Recent anomaly window in days. Defaults to 7.',\n },\n refresh: {\n description: 'Bypass local cache and fetch fresh GSC data.',\n },\n }),\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const report = await trafficAnomaly({\n site: await selectedSiteOrThrow(\n { client: projectArg(args), site: stringArg(args.site) },\n {\n json,\n refresh: booleanArg(args.refresh),\n },\n ),\n days: numberArg(args.days),\n recentDays: numberArg(args.recent),\n refresh: booleanArg(args.refresh),\n })\n if (json) {\n printJson(report)\n return\n }\n printLimitedTable(\n [\n 'Metric',\n 'Direction',\n 'Baseline/day',\n 'Recent/day',\n 'Change',\n 'z',\n 'Significant',\n ],\n report.anomalies.map((anomaly) => [\n anomaly.metric,\n anomaly.direction,\n formatNumber(anomaly.baselineMean),\n formatNumber(anomaly.comparisonMean),\n formatChange(anomaly.percentChange),\n anomaly.zScore ?? 'n/a',\n anomaly.significant ? 'yes' : 'no',\n ]),\n )\n if (report.coverage) {\n printNotes('Evidence coverage', [\n `${report.coverage.observedDays} of ${report.coverage.expectedDays} requested calendar days returned date aggregates.`,\n ...report.coverage.caveats,\n ])\n }\n },\n})\n\nexport const updateCorrelateCommand = defineCommand({\n meta: {\n name: 'update-correlate',\n description: 'Compare traffic movement with official Google update windows',\n },\n args: {\n site: { type: 'string' },\n project: { type: 'string', description: 'Saved project id or name.' },\n client: { type: 'string', description: 'Legacy alias for --project.' },\n ...cliReportArgs(['days', 'recentDays', 'refresh'], {\n days: { description: 'Baseline window length in days. Defaults to 90.' },\n recentDays: {\n description: 'Recent anomaly window in days. Defaults to 7.',\n },\n refresh: {\n description: 'Bypass local cache and fetch fresh GSC data.',\n },\n }),\n 'padding-days': {\n type: 'string',\n description: 'Days around update windows to count as overlap.',\n },\n 'known-change': {\n type: 'string',\n description:\n 'Manual site-side change to treat as a confounder, for example pruning pages or blocking traffic.',\n },\n 'ignore-change-log': {\n type: 'boolean',\n default: false,\n description: 'Do not use saved change-log entries as confounders.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const client = projectArg(args)\n const site = await selectedSiteOrThrow(\n { client, site: stringArg(args.site) },\n {\n json,\n refresh: booleanArg(args.refresh),\n },\n )\n const report = await updateCorrelation({\n site,\n days: numberArg(args.days),\n recentDays: numberArg(args.recent),\n paddingDays: numberArg(args['padding-days']),\n knownConfounders: stringArg(args['known-change'])\n ? [stringArg(args['known-change']) ?? '']\n : undefined,\n includeChangeLog: !booleanArg(args['ignore-change-log']),\n refresh: booleanArg(args.refresh),\n })\n if (json) {\n printJson(report)\n return\n }\n printKeyValue([\n ['Classification', report.classification.replaceAll('-', ' ')],\n ['Causal attribution', report.attribution.replaceAll('-', ' ')],\n ['Causal confidence', report.confidence],\n ['Updates matched', String(report.overlappingUpdates.length)],\n ['Known confounders', String(report.confounders.length)],\n ['Source', report.source.name],\n ])\n process.stdout.write(`\\n${report.summary}\\n`)\n printNotes('Evidence', report.evidence)\n printNotes('Report caveats', report.caveats)\n printNotes('Recommended next checks', report.actions)\n printLimitedTable(\n ['Metric', 'Direction', 'Baseline/day', 'Recent/day', 'Change', 'z'],\n report.anomalies.map((anomaly) => [\n anomaly.metric,\n anomaly.direction,\n formatNumber(anomaly.baselineMean),\n formatNumber(anomaly.comparisonMean),\n formatChange(anomaly.percentChange),\n anomaly.zScore ?? 'n/a',\n ]),\n )\n if (report.overlappingUpdates.length) {\n process.stdout.write('\\nUpdates\\n')\n printTable(\n ['Start', 'End', 'Type', 'Name'],\n report.overlappingUpdates.map((update) => [\n update.start.slice(0, 10),\n update.end?.slice(0, 10) ?? 'open',\n update.type,\n update.name,\n ]),\n )\n }\n const target = client\n ? `--project ${JSON.stringify(client)}`\n : `--site ${JSON.stringify(site)}`\n printNextCommand(`seo segment-impact ${target} --dimension page`)\n },\n})\n","import {\n type AiReadinessReport,\n aiReadiness,\n type CrawlReport,\n latestCrawlReport,\n loadCrawlReport,\n} from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { jsonFlag, projectArg, stringArg } from '../args.js'\nimport { resolveClientSelection } from '../selection.js'\nimport { printJson, printKeyValue, printTable } from '../utils.js'\nimport { printNotes, truncate } from './output.js'\n\nexport async function resolveSavedCrawlReport(\n args: Record<string, unknown>,\n options: { json?: boolean } = {},\n): Promise<CrawlReport> {\n const reportId = stringArg(args['report-id'])\n if (reportId) {\n const report = loadCrawlReport(reportId)\n if (!report) throw new Error(`No saved crawl report found for ${reportId}.`)\n return report\n }\n\n const project = projectArg(args)\n const site = stringArg(args.site)\n const selection =\n project || site\n ? await resolveClientSelection({\n client: project,\n site,\n options,\n })\n : undefined\n const report = latestCrawlReport(selection?.site)\n if (!report) {\n throw new Error(\n selection?.site\n ? `No saved crawl report found for ${selection.site}. Run \\`seo crawl --project ${selection.client?.id ?? selection.site} --save\\` first.`\n : 'No saved crawl report found. Run `seo crawl <url> --save` first, or pass --report-id.',\n )\n }\n return report\n}\n\nfunction printAiReadiness(report: AiReadinessReport): void {\n process.stdout.write(`AI-search evidence for ${report.url}\\n\\n`)\n printKeyValue([\n ['Assessment', 'evidence only'],\n ['Data', report.dataStatus],\n ['Report', report.reportId],\n ])\n process.stdout.write(`\\n${report.headline}\\n`)\n\n if (report.topActions.length) {\n process.stdout.write('\\nTop actions\\n')\n printTable(\n ['Status', 'Check', 'Action'],\n report.topActions.map((action) => [\n action.status,\n action.title,\n truncate(action.action, 96),\n ]),\n )\n }\n\n if (report.botAccess.length) {\n process.stdout.write('\\nBot access\\n')\n printTable(\n ['User agent', 'Allowed', 'Declared'],\n report.botAccess.map((bot) => [\n bot.userAgent,\n bot.allowed === null ? 'unknown' : bot.allowed ? 'yes' : 'no',\n bot.declared ? 'yes' : bot.coveredByWildcard ? 'wildcard' : 'no',\n ]),\n )\n }\n\n printNotes('Caveats', report.caveats)\n}\n\nexport const aiReadinessCommand = defineCommand({\n meta: {\n name: 'ai-readiness',\n description:\n 'Review AI-search technical evidence and optional observations',\n },\n args: {\n 'report-id': {\n type: 'string',\n description: 'Saved crawl report id to analyze.',\n },\n site: {\n type: 'string',\n description: 'GSC property URL for selecting the latest saved crawl.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const report = await resolveSavedCrawlReport(args, { json })\n const readiness = aiReadiness(report)\n if (json) {\n printJson(readiness)\n return\n }\n printAiReadiness(readiness)\n },\n})\n","import { type EntityReadinessReport, entityReadiness } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { jsonFlag } from '../args.js'\nimport { printJson, printKeyValue, printTable } from '../utils.js'\nimport { printNotes } from './output.js'\nimport { resolveSavedCrawlReport } from './readiness.js'\n\nfunction printEntityReadiness(report: EntityReadinessReport): void {\n process.stdout.write(`Entity evidence for ${report.url}\\n\\n`)\n printKeyValue([\n ['Assessment', 'evidence only'],\n ['Data', report.dataStatus],\n ['Evaluated pages', `${report.evaluatedPages}/${report.crawlPages}`],\n ['Report', report.reportId],\n ['sameAs profiles', String(report.entities.sameAs.length)],\n ['Social profiles', String(report.entities.socialProfiles.length)],\n ['Authors', String(report.entities.authors.length)],\n ])\n process.stdout.write(`\\n${report.headline}\\n`)\n\n const schemaRows = Object.entries(report.entities.schemaTypes)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 10)\n if (schemaRows.length) {\n process.stdout.write('\\nSchema types\\n')\n printTable(\n ['Type', 'Pages'],\n schemaRows.map(([type, count]) => [type, String(count)]),\n )\n }\n\n printNotes('sameAs', report.entities.sameAs.slice(0, 10))\n printNotes('Social profiles', report.entities.socialProfiles.slice(0, 10))\n}\n\nexport const entityReadinessCommand = defineCommand({\n meta: {\n name: 'entity-readiness',\n description:\n 'Check schema, sameAs, social, author, and naming signals from a saved crawl',\n },\n args: {\n 'report-id': {\n type: 'string',\n description: 'Saved crawl report id to analyze.',\n },\n site: {\n type: 'string',\n description: 'GSC property URL for selecting the latest saved crawl.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const report = await resolveSavedCrawlReport(args, { json })\n const readiness = entityReadiness(report)\n if (json) {\n printJson(readiness)\n return\n }\n printEntityReadiness(readiness)\n },\n})\n","import {\n type ChangeScope,\n deleteChange,\n listChanges,\n measureChange,\n recordChange,\n} from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n jsonFlag,\n numberArg,\n strictNumberArg,\n stringArg,\n} from '../../args.js'\nimport { resolveSite } from '../../selection.js'\nimport { printJson, printKeyValue, printTable } from '../../utils.js'\nimport { printNotes } from '../output.js'\n\nfunction today(): string {\n return new Date().toISOString().slice(0, 10)\n}\n\nfunction changeScope(value: unknown): ChangeScope {\n const scope = stringArg(value) ?? 'page'\n if (\n scope !== 'site' &&\n scope !== 'page' &&\n scope !== 'query' &&\n scope !== 'group'\n ) {\n throw new Error('Invalid --scope. Use site, page, query, or group.')\n }\n return scope\n}\n\nexport const changeLogCommand = defineCommand({\n meta: {\n name: 'change-log',\n description: 'Annotate SEO changes and measure before/after impact',\n },\n subCommands: {\n list: defineCommand({\n meta: {\n name: 'list',\n description: 'List recorded SEO changes',\n },\n args: {\n site: { type: 'string' },\n limit: { type: 'string' },\n json: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const changes = listChanges({\n site: stringArg(args.site),\n limit: numberArg(args.limit),\n })\n if (jsonFlag(args)) {\n printJson({ changes })\n return\n }\n printTable(\n ['ID', 'Date', 'Site', 'Scope', 'Target', 'Title'],\n changes.map((change) => [\n change.id,\n change.changedAt,\n change.site,\n change.scope,\n change.target,\n change.title,\n ]),\n )\n },\n }),\n add: defineCommand({\n meta: {\n name: 'add',\n description: 'Record an SEO change',\n },\n args: {\n site: { type: 'string' },\n scope: { type: 'string', default: 'page' },\n target: { type: 'string', required: true },\n title: { type: 'string', required: true },\n description: { type: 'string' },\n date: { type: 'string' },\n json: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const change = recordChange({\n site: await resolveSite({\n site: stringArg(args.site),\n options: { json },\n }),\n scope: changeScope(args.scope),\n target: stringArg(args.target) ?? '',\n title: stringArg(args.title) ?? '',\n description: stringArg(args.description),\n changedAt: stringArg(args.date) ?? today(),\n })\n if (json) {\n printJson(change)\n return\n }\n printKeyValue([\n ['ID', change.id],\n ['Date', change.changedAt],\n ['Site', change.site],\n ['Scope', change.scope],\n ['Target', change.target],\n ['Title', change.title],\n ])\n },\n }),\n delete: defineCommand({\n meta: {\n name: 'delete',\n description: 'Delete a recorded SEO change',\n },\n args: {\n id: { type: 'string', required: true },\n json: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const id = stringArg(args.id) ?? ''\n const deleted = deleteChange(id)\n if (jsonFlag(args)) {\n printJson({ id, deleted })\n return\n }\n process.stdout.write(`${deleted ? 'Deleted' : 'Not found'} ${id}.\\n`)\n },\n }),\n measure: defineCommand({\n meta: {\n name: 'measure',\n description:\n 'Measure a change with equal finalized before/after windows',\n },\n args: {\n id: { type: 'string' },\n site: { type: 'string' },\n scope: { type: 'string' },\n target: { type: 'string' },\n title: { type: 'string' },\n date: { type: 'string' },\n before: { type: 'string' },\n after: { type: 'string' },\n json: { type: 'boolean', default: false },\n refresh: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const id = stringArg(args.id)\n if (\n !id &&\n (!stringArg(args.site) ||\n !stringArg(args.scope) ||\n !stringArg(args.target) ||\n !stringArg(args.date))\n ) {\n throw new Error(\n 'Pass --id, or pass --site, --scope, --target, and --date for an ad hoc measurement.',\n )\n }\n const report = await measureChange({\n id,\n site: id\n ? undefined\n : await resolveSite({\n site: stringArg(args.site),\n options: { json },\n }),\n scope: id ? undefined : changeScope(args.scope),\n target: id ? undefined : stringArg(args.target),\n title: stringArg(args.title),\n changedAt: id ? undefined : stringArg(args.date),\n beforeDays: strictNumberArg(args.before, '--before'),\n afterDays: strictNumberArg(args.after, '--after'),\n refresh: booleanArg(args.refresh),\n })\n if (json) {\n printJson(report)\n return\n }\n printKeyValue([\n ['Change', report.change.title],\n ['Data status', report.dataStatus],\n ['Verdict', report.verdict],\n ['Confidence', report.confidence],\n ['Before', `${report.before.startDate} to ${report.before.endDate}`],\n ['After', `${report.after.startDate} to ${report.after.endDate}`],\n [\n 'Window',\n `${report.window.effectiveDays}/${report.window.requestedDays} finalized days`,\n ],\n ['Note', report.note],\n ])\n printTable(\n ['Metric', 'Before', 'After', 'Delta'],\n [\n [\n 'Clicks',\n report.before.metrics?.clicks ?? 'unavailable',\n report.after.metrics?.clicks ?? 'unavailable',\n report.delta.clicks === null\n ? 'unavailable'\n : report.delta.clickPct === null\n ? `${report.delta.clicks}`\n : `${report.delta.clicks} (${report.delta.clickPct}%)`,\n ],\n [\n 'Impressions',\n report.before.metrics?.impressions ?? 'unavailable',\n report.after.metrics?.impressions ?? 'unavailable',\n report.delta.impressions === null\n ? 'unavailable'\n : report.delta.impressionPct === null\n ? `${report.delta.impressions}`\n : `${report.delta.impressions} (${report.delta.impressionPct}%)`,\n ],\n [\n 'CTR',\n report.before.metrics?.ctr ?? 'unavailable',\n report.after.metrics?.ctr ?? 'unavailable',\n report.delta.ctr ?? 'unavailable',\n ],\n [\n 'Position',\n report.before.metrics?.position ?? 'unavailable',\n report.after.metrics?.position ?? 'unavailable',\n report.delta.position ?? 'unavailable',\n ],\n ],\n )\n printNotes('Warnings', report.warnings)\n printNotes('Caveats', report.caveats)\n },\n }),\n },\n})\n","import {\n type ContentGroupDimension,\n type ContentGroupMatchType,\n createContentGroup,\n deleteContentGroup,\n listContentGroups,\n} from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { jsonFlag, stringArg } from '../../args.js'\nimport { resolveSite } from '../../selection.js'\nimport { printJson, printKeyValue, printTable } from '../../utils.js'\n\nfunction groupDimension(value: unknown): ContentGroupDimension {\n const dimension = stringArg(value) ?? 'page'\n if (dimension !== 'page' && dimension !== 'query') {\n throw new Error('Invalid --dimension. Use page or query.')\n }\n return dimension\n}\n\nfunction matchType(value: unknown): ContentGroupMatchType {\n const type = stringArg(value) ?? 'contains'\n if (type !== 'equals' && type !== 'contains' && type !== 'regex') {\n throw new Error('Invalid --match. Use equals, contains, or regex.')\n }\n return type\n}\n\nexport const contentGroupsCommand = defineCommand({\n meta: {\n name: 'content-groups',\n description: 'Create and manage reusable page/query groups',\n },\n subCommands: {\n list: defineCommand({\n meta: {\n name: 'list',\n description: 'List saved content groups',\n },\n args: {\n site: { type: 'string' },\n json: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const groups = listContentGroups(stringArg(args.site))\n if (jsonFlag(args)) {\n printJson({ groups })\n return\n }\n printTable(\n ['ID', 'Site', 'Name', 'Dimension', 'Match', 'Pattern'],\n groups.map((group) => [\n group.id,\n group.site,\n group.name,\n group.dimension,\n group.matchType,\n group.pattern,\n ]),\n )\n },\n }),\n add: defineCommand({\n meta: {\n name: 'add',\n description: 'Create a reusable page or query group',\n },\n args: {\n site: { type: 'string' },\n name: { type: 'string', required: true },\n dimension: { type: 'string', default: 'page' },\n match: { type: 'string', default: 'contains' },\n pattern: { type: 'string', required: true },\n json: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const group = createContentGroup({\n site: await resolveSite({\n site: stringArg(args.site),\n options: { json },\n }),\n name: stringArg(args.name) ?? '',\n dimension: groupDimension(args.dimension),\n matchType: matchType(args.match),\n pattern: stringArg(args.pattern) ?? '',\n })\n if (json) {\n printJson(group)\n return\n }\n printKeyValue([\n ['ID', group.id],\n ['Site', group.site],\n ['Name', group.name],\n ['Filter', `${group.dimension} ${group.matchType} ${group.pattern}`],\n ])\n },\n }),\n delete: defineCommand({\n meta: {\n name: 'delete',\n description: 'Delete a content group',\n },\n args: {\n id: { type: 'string', required: true },\n json: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const id = stringArg(args.id) ?? ''\n const deleted = deleteContentGroup(id)\n if (jsonFlag(args)) {\n printJson({ id, deleted })\n return\n }\n process.stdout.write(`${deleted ? 'Deleted' : 'Not found'} ${id}.\\n`)\n },\n }),\n },\n})\n","import {\n type ChangeMeasurement,\n type ChangeScope,\n listChanges,\n measureChange,\n recordChange,\n} from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n jsonFlag,\n numberArg,\n projectArg,\n strictNumberArg,\n stringArg,\n} from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson, printKeyValue, printTable } from '../../utils.js'\nimport { formatCount, printNotes } from '../output.js'\n\nfunction today(): string {\n return new Date().toISOString().slice(0, 10)\n}\n\nfunction changeScope(value: unknown): ChangeScope {\n const scope = stringArg(value) ?? 'page'\n if (\n scope !== 'site' &&\n scope !== 'page' &&\n scope !== 'query' &&\n scope !== 'group'\n ) {\n throw new Error('Invalid --scope. Use site, page, query, or group.')\n }\n return scope\n}\n\nfunction maybeScope(value: unknown): ChangeScope | undefined {\n return value ? changeScope(value) : undefined\n}\n\nfunction pct(value: number | null): string {\n return value === null ? 'n/a' : `${value.toFixed(1)}%`\n}\n\nfunction countMetric(value: number | null | undefined): string {\n return value === null || value === undefined\n ? 'unavailable'\n : formatCount(value)\n}\n\nfunction countDelta(value: number | null, percentage: number | null): string {\n return value === null\n ? 'unavailable'\n : `${formatCount(value)} (${pct(percentage)})`\n}\n\nfunction decimalMetric(value: number | null | undefined, digits = 1): string {\n return value === null || value === undefined\n ? 'unavailable'\n : value.toFixed(digits)\n}\n\nfunction printMeasurement(report: ChangeMeasurement): void {\n printKeyValue([\n ['Test', report.change.title],\n ['Data status', report.dataStatus],\n ['Verdict', report.verdict],\n ['Confidence', report.confidence],\n ['Before', `${report.before.startDate} to ${report.before.endDate}`],\n ['After', `${report.after.startDate} to ${report.after.endDate}`],\n [\n 'Window',\n `${report.window.effectiveDays}/${report.window.requestedDays} finalized days`,\n ],\n ['Note', report.note],\n ])\n printTable(\n ['Metric', 'Before', 'After', 'Delta'],\n [\n [\n 'GSC clicks',\n countMetric(report.before.metrics?.clicks),\n countMetric(report.after.metrics?.clicks),\n countDelta(report.delta.clicks, report.delta.clickPct),\n ],\n [\n 'GSC impressions',\n countMetric(report.before.metrics?.impressions),\n countMetric(report.after.metrics?.impressions),\n countDelta(report.delta.impressions, report.delta.impressionPct),\n ],\n [\n 'GSC CTR',\n report.before.metrics\n ? `${(report.before.metrics.ctr * 100).toFixed(1)}%`\n : 'unavailable',\n report.after.metrics\n ? `${(report.after.metrics.ctr * 100).toFixed(1)}%`\n : 'unavailable',\n report.delta.ctr === null\n ? 'unavailable'\n : `${(report.delta.ctr * 100).toFixed(1)} pts`,\n ],\n [\n 'GSC position',\n decimalMetric(report.before.metrics?.position),\n decimalMetric(report.after.metrics?.position),\n decimalMetric(report.delta.position),\n ],\n ],\n )\n\n if (report.analytics) {\n process.stdout.write('\\nGA4 impact\\n')\n printTable(\n ['Metric', 'Before', 'After', 'Delta'],\n [\n [\n 'Sessions',\n formatCount(report.analytics.before.metrics.sessions),\n formatCount(report.analytics.after.metrics.sessions),\n `${formatCount(report.analytics.delta.sessions)} (${pct(report.analytics.delta.sessionPct)})`,\n ],\n [\n 'Conversions',\n formatCount(report.analytics.before.metrics.conversions),\n formatCount(report.analytics.after.metrics.conversions),\n `${formatCount(report.analytics.delta.conversions)} (${pct(report.analytics.delta.conversionPct)})`,\n ],\n [\n 'Revenue',\n report.analytics.before.metrics.totalRevenue.toFixed(2),\n report.analytics.after.metrics.totalRevenue.toFixed(2),\n `${report.analytics.delta.totalRevenue.toFixed(2)} (${pct(report.analytics.delta.revenuePct)})`,\n ],\n ],\n )\n }\n\n if (report.control) {\n process.stdout.write('\\nControl comparison\\n')\n printKeyValue([\n ['Control', report.control.change.title],\n [\n 'Adjusted clicks',\n report.control.adjusted.clickDelta === null\n ? 'n/a'\n : formatCount(report.control.adjusted.clickDelta),\n ],\n [\n 'Adjusted click %',\n report.control.adjusted.clickPctPoints === null\n ? 'n/a'\n : `${report.control.adjusted.clickPctPoints.toFixed(1)} pts`,\n ],\n ['Note', report.control.note],\n ])\n }\n printNotes('Warnings', report.warnings)\n printNotes('Caveats', report.caveats)\n}\n\nexport const testsCommand = defineCommand({\n meta: {\n name: 'tests',\n description: 'Create and report local SEO tests from GSC and GA4 data',\n },\n subCommands: {\n list: defineCommand({\n meta: { name: 'list', description: 'List saved SEO tests' },\n args: {\n site: { type: 'string', description: 'GSC property URL.' },\n client: { type: 'string', description: 'Legacy alias for --project.' },\n project: { type: 'string', description: 'Saved project id or name.' },\n limit: {\n type: 'string',\n description: 'Maximum tests to list. Defaults to 20.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const project = projectArg(args)\n const selection =\n project || stringArg(args.site)\n ? await resolveClientSelection({\n client: project,\n site: stringArg(args.site),\n options: { json },\n })\n : undefined\n const changes = listChanges({\n site: selection?.site,\n limit: numberArg(args.limit),\n })\n if (json) {\n printJson({ tests: changes })\n return\n }\n printTable(\n ['ID', 'Date', 'Scope', 'Target', 'Title'],\n changes.map((change) => [\n change.id,\n change.changedAt,\n change.scope,\n change.target,\n change.title,\n ]),\n )\n },\n }),\n create: defineCommand({\n meta: { name: 'create', description: 'Create a local SEO test' },\n args: {\n site: { type: 'string', description: 'GSC property URL.' },\n client: { type: 'string', description: 'Legacy alias for --project.' },\n project: { type: 'string', description: 'Saved project id or name.' },\n scope: {\n type: 'string',\n default: 'page',\n description: 'Change scope: site, page, query, or group.',\n },\n target: {\n type: 'string',\n required: true,\n description: 'Changed URL, query, group pattern, or site marker.',\n },\n title: {\n type: 'string',\n required: true,\n description: 'Plain-English name for the test.',\n },\n description: {\n type: 'string',\n description: 'Optional note about what changed.',\n },\n date: {\n type: 'string',\n description: 'Change date in YYYY-MM-DD. Defaults to today.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json },\n })\n const change = recordChange({\n site: selection.site,\n scope: changeScope(args.scope),\n target: stringArg(args.target) ?? '',\n title: stringArg(args.title) ?? '',\n description: stringArg(args.description),\n changedAt: stringArg(args.date) ?? today(),\n })\n if (json) {\n printJson(change)\n return\n }\n printKeyValue([\n ['ID', change.id],\n ['Date', change.changedAt],\n ['Project', selection.client?.name ?? selection.site],\n ['Scope', change.scope],\n ['Target', change.target],\n ['Title', change.title],\n ])\n },\n }),\n report: defineCommand({\n meta: {\n name: 'report',\n description:\n 'Report an SEO test with equal finalized before/after windows',\n },\n args: {\n id: { type: 'string', description: 'Saved SEO test id.' },\n site: { type: 'string', description: 'GSC property URL.' },\n client: { type: 'string', description: 'Legacy alias for --project.' },\n project: { type: 'string', description: 'Saved project id or name.' },\n scope: {\n type: 'string',\n description: 'Ad-hoc change scope: site, page, query, or group.',\n },\n target: {\n type: 'string',\n description:\n 'Ad-hoc changed URL, query, group pattern, or site marker.',\n },\n title: { type: 'string', description: 'Ad-hoc test title.' },\n date: {\n type: 'string',\n description: 'Ad-hoc change date in YYYY-MM-DD.',\n },\n property: { type: 'string', description: 'GA4 property ID.' },\n 'control-scope': {\n type: 'string',\n description: 'Control scope: site, page, query, or group.',\n },\n 'control-target': {\n type: 'string',\n description: 'Control URL, query, group pattern, or site marker.',\n },\n 'control-title': {\n type: 'string',\n description: 'Plain-English name for the control group.',\n },\n before: {\n type: 'string',\n description: 'Days before the change date. Defaults to 28.',\n },\n after: {\n type: 'string',\n description: 'Days after the change date. Defaults to 28.',\n },\n refresh: {\n type: 'boolean',\n default: false,\n description: 'Bypass local GSC and GA4 cache.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const id = stringArg(args.id)\n const needsSelection =\n !id || Boolean(projectArg(args) || stringArg(args.site))\n const selection = needsSelection\n ? await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json, refresh: booleanArg(args.refresh) },\n })\n : undefined\n const report = await measureChange({\n id,\n site: id ? undefined : selection?.site,\n scope: id ? undefined : maybeScope(args.scope),\n target: id ? undefined : stringArg(args.target),\n title: stringArg(args.title),\n changedAt: id ? undefined : stringArg(args.date),\n ga4PropertyId:\n stringArg(args.property) ?? selection?.client?.ga4PropertyId,\n controlScope: maybeScope(args['control-scope']),\n controlTarget: stringArg(args['control-target']),\n controlTitle: stringArg(args['control-title']),\n beforeDays: strictNumberArg(args.before, '--before'),\n afterDays: strictNumberArg(args.after, '--after'),\n refresh: booleanArg(args.refresh),\n })\n if (json) {\n printJson(report)\n return\n }\n printMeasurement(report)\n },\n }),\n },\n})\n","import type { ProgressReporter } from '@seo/core'\n\nexport function createProgressReporter(\n enabled: boolean,\n): ProgressReporter | undefined {\n if (!enabled) return undefined\n const startedAt = Date.now()\n return (message) => {\n const elapsed = ((Date.now() - startedAt) / 1000).toFixed(1)\n process.stderr.write(`[seo ${elapsed}s] ${message}\\n`)\n }\n}\n","import {\n booleanArg,\n fetchRateArg,\n numberArg,\n projectArg,\n stringArg,\n} from '../../args.js'\nimport { cliReportArgs } from '../report-options.js'\n\nexport const reportSelectionArgs = {\n site: {\n type: 'string',\n description: 'GSC property URL, for example sc-domain:example.com.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n} as const\n\nexport const reportFetchArgs = {\n ...cliReportArgs([\n 'includeBrand',\n 'verifyContent',\n 'verifyLimit',\n 'js',\n 'fetchConcurrency',\n 'fetchIntervalCap',\n 'fetchIntervalMs',\n 'refresh',\n ]),\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n} as const\n\nexport function reportFetchOptions(args: Record<string, unknown>) {\n return {\n includeBrand: booleanArg(args['include-brand']),\n verifyContent: booleanArg(args['verify-content']),\n verifyLimit: numberArg(args['verify-limit']) ?? 3,\n js: booleanArg(args.js) ? true : undefined,\n rate: fetchRateArg(args),\n refresh: booleanArg(args.refresh),\n }\n}\n\nexport function reportSelectionInput(args: Record<string, unknown>) {\n return {\n client: projectArg(args),\n site: stringArg(args.site),\n refresh: booleanArg(args.refresh),\n }\n}\n","import { mkdir, writeFile } from 'node:fs/promises'\nimport { resolve } from 'node:path'\nimport { type CsvFile, countLabel, renderCsv } from '@seo/core'\nimport { reportFetchArgs } from '../reports/args.js'\n\nconst { json: _json, ...reportFetchArgsWithoutJson } = reportFetchArgs\n\nexport const exportReportFetchArgs = reportFetchArgsWithoutJson\n\nexport const exportSelectionArgs = {\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description:\n 'Saved project id or name. Defaults to the configured default.',\n },\n site: {\n type: 'string',\n description: 'GSC property URL/id when not using a saved project.',\n },\n} as const\n\nexport function outArg(report: string) {\n return {\n type: 'string',\n description: `Output folder. Defaults to ./seo-export/<project>-${report}-YYYY-MM-DD.`,\n } as const\n}\n\nfunction slug(value: string): string {\n return value\n .toLowerCase()\n .replace(/^sc-domain:/, '')\n .replace(/^https?:\\/\\//, '')\n .replace(/[^a-z0-9._-]+/g, '-')\n .replace(/^-+|-+$/g, '')\n}\n\nexport function defaultOutDir(input: {\n report: string\n clientId?: string\n site: string\n}) {\n const day = new Date().toISOString().slice(0, 10)\n const id = slug(input.clientId ?? input.site)\n return resolve(process.cwd(), 'seo-export', `${id}-${input.report}-${day}`)\n}\n\nexport async function writeCsvFiles(outDir: string, files: CsvFile[]) {\n await mkdir(outDir, { recursive: true })\n const written: string[] = []\n for (const file of files) {\n const path = resolve(outDir, file.filename)\n await writeFile(path, renderCsv(file.rows, file.headers), 'utf8')\n written.push(path)\n }\n return written\n}\n\nexport function printWritten(outDir: string, files: string[]) {\n process.stdout.write(\n `Wrote ${countLabel(files.length, 'CSV file')} to ${outDir}\\n`,\n )\n for (const file of files) {\n process.stdout.write(`- ${file}\\n`)\n }\n}\n","import { diagnoseCsvFiles, diagnoseProperty } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n fetchRateArg,\n numberArg,\n projectArg,\n stringArg,\n} from '../../args.js'\nimport { createProgressReporter } from '../../progress.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport {\n defaultOutDir,\n exportSelectionArgs,\n outArg,\n printWritten,\n writeCsvFiles,\n} from './shared.js'\n\nexport const exportDiagnoseCommand = defineCommand({\n meta: {\n name: 'diagnose',\n description:\n 'Export diagnosis tables: priorities, anomalies, movement, decay, cannibalisation, striking-distance, and quick wins.',\n },\n args: {\n ...exportSelectionArgs,\n out: outArg('diagnose'),\n days: {\n type: 'string',\n description: 'GSC lookback window. Defaults to 90.',\n },\n recent: {\n type: 'string',\n description: 'Recent anomaly window in days.',\n },\n limit: {\n type: 'string',\n description: 'Maximum rows per movement/opportunity table.',\n },\n 'include-brand': {\n type: 'boolean',\n default: false,\n description: 'Include branded queries in opportunity reports.',\n },\n 'verify-content': {\n type: 'boolean',\n default: false,\n description:\n 'Verify top opportunities against page title, meta, and content.',\n },\n 'verify-limit': {\n type: 'string',\n description: 'Maximum opportunity URLs to verify.',\n },\n js: {\n type: 'boolean',\n default: false,\n description: 'Force JavaScript rendering for verified pages.',\n },\n 'fetch-concurrency': {\n type: 'string',\n description: 'Maximum concurrent page fetches per host. Defaults to 4.',\n },\n 'fetch-interval-cap': {\n type: 'string',\n description: 'Maximum page fetches per interval per host. Defaults to 4.',\n },\n 'fetch-interval-ms': {\n type: 'string',\n description: 'Fetch rate interval in milliseconds. Defaults to 1000.',\n },\n refresh: {\n type: 'boolean',\n default: false,\n description: 'Bypass local cache and fetch fresh data.',\n },\n },\n run: async ({ args }) => {\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n })\n const report = await diagnoseProperty({\n site: selection.site,\n days: numberArg(args.days),\n recentDays: numberArg(args.recent),\n limit: numberArg(args.limit),\n brandTerms: selection.client?.brandTerms,\n includeBrand: booleanArg(args['include-brand']),\n verifyContent: booleanArg(args['verify-content']),\n verifyLimit: numberArg(args['verify-limit']),\n js: booleanArg(args.js) ? true : 'auto',\n rate: fetchRateArg(args),\n refresh: booleanArg(args.refresh),\n progress: createProgressReporter(true),\n })\n const outDir =\n stringArg(args.out) ??\n defaultOutDir({\n report: 'diagnose',\n clientId: selection.client?.id,\n site: selection.site,\n })\n const written = await writeCsvFiles(outDir, diagnoseCsvFiles(report))\n printWritten(outDir, written)\n },\n})\n","import { randomUUID } from 'node:crypto'\nimport {\n lstat,\n mkdir,\n mkdtemp,\n readdir,\n readFile,\n rename,\n rm,\n writeFile,\n} from 'node:fs/promises'\nimport {\n basename,\n dirname,\n isAbsolute,\n join,\n relative,\n resolve,\n} from 'node:path'\nimport {\n type OkfFile,\n type OkfValidationReport,\n SeoError,\n validateOkfFiles,\n} from '@seo/core'\n\nconst markerName = '.seo-okf.json'\nconst marker = `${JSON.stringify({ generator: 'seo', format: 'okf', version: 1 })}\\n`\n\nfunction safeFilePath(root: string, filePath: string): string {\n const path = resolve(root, filePath)\n const fromRoot = relative(resolve(root), path)\n if (!fromRoot || fromRoot.startsWith('..') || isAbsolute(fromRoot)) {\n throw new SeoError('INVALID_INPUT', `Unsafe OKF file path: ${filePath}`)\n }\n return path\n}\n\nasync function writeFiles(root: string, files: OkfFile[]): Promise<void> {\n for (const file of files) {\n const path = safeFilePath(root, file.path)\n await mkdir(dirname(path), { recursive: true })\n await writeFile(path, file.content)\n }\n await writeFile(join(root, markerName), marker)\n}\n\nexport async function readOkfMarkdownFiles(root: string): Promise<OkfFile[]> {\n const files: OkfFile[] = []\n async function walk(dir: string, prefix = ''): Promise<void> {\n const entries = await readdir(dir, { withFileTypes: true })\n for (const entry of entries) {\n const relative = prefix ? `${prefix}/${entry.name}` : entry.name\n const fullPath = join(dir, entry.name)\n if (entry.isDirectory()) {\n await walk(fullPath, relative)\n } else if (entry.isFile() && entry.name.endsWith('.md')) {\n files.push({\n path: relative,\n content: await readFile(fullPath, 'utf8'),\n })\n }\n }\n }\n await walk(root)\n return files.sort((left, right) =>\n left.path < right.path ? -1 : left.path > right.path ? 1 : 0,\n )\n}\n\nasync function assertReplaceable(path: string): Promise<boolean> {\n try {\n const stats = await lstat(path)\n if (stats.isSymbolicLink() || !stats.isDirectory()) {\n throw new SeoError(\n 'INVALID_INPUT',\n `OKF output must be a real directory: ${path}`,\n )\n }\n const entries = await readdir(path)\n if (!entries.length) return true\n try {\n const value = await readFile(join(path, markerName), 'utf8')\n if (value === marker) return true\n } catch {\n // The directory is not managed by seo.\n }\n throw new SeoError(\n 'INVALID_INPUT',\n `Refusing to replace non-empty unmanaged directory: ${path}`,\n )\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return false\n throw error\n }\n}\n\nexport async function writeOkfDirectory(\n output: string,\n files: OkfFile[],\n): Promise<OkfValidationReport> {\n const validation = validateOkfFiles(files)\n if (!validation.valid) {\n throw new SeoError(\n 'INVALID_INPUT',\n 'Generated bundle did not pass seo OKF checks and was not written.',\n )\n }\n const target = resolve(output)\n const parent = dirname(target)\n await mkdir(parent, { recursive: true })\n const existed = await assertReplaceable(target)\n const staging = await mkdtemp(join(parent, `.${basename(target)}-staging-`))\n const backup = join(parent, `.${basename(target)}-backup-${randomUUID()}`)\n let movedExisting = false\n try {\n await writeFiles(staging, files)\n const diskValidation = validateOkfFiles(await readOkfMarkdownFiles(staging))\n if (!diskValidation.valid) {\n throw new SeoError(\n 'INTERNAL_ERROR',\n 'Staged OKF files failed validation after writing.',\n )\n }\n if (existed) {\n await rename(target, backup)\n movedExisting = true\n }\n await rename(staging, target)\n if (movedExisting) await rm(backup, { recursive: true, force: true })\n return diskValidation\n } catch (error) {\n await rm(staging, { recursive: true, force: true })\n if (movedExisting) {\n await rm(target, { recursive: true, force: true })\n await rename(backup, target)\n }\n throw error\n }\n}\n","import { mkdir, writeFile } from 'node:fs/promises'\nimport { dirname } from 'node:path'\nimport {\n aiReadiness,\n auditLlmsTxt,\n buildOkfBundle,\n type CrawlReport,\n entityReadiness,\n okfConceptLimit,\n} from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { jsonFlag, strictNumberArg, stringArg } from '../../args.js'\nimport { printJson, printKeyValue } from '../../utils.js'\nimport { writeOkfDirectory } from '../okf-files.js'\nimport { resolveSavedCrawlReport } from '../readiness.js'\n\ntype KnowledgeFormat = 'okf' | 'markdown' | 'json'\n\nasync function writeOrPrint(path: string | undefined, content: string) {\n if (!path) {\n process.stdout.write(content)\n return\n }\n await mkdir(dirname(path), { recursive: true })\n await writeFile(path, content)\n process.stdout.write(`Wrote ${path}\\n`)\n}\n\nfunction formatArg(value: unknown): KnowledgeFormat {\n const format = stringArg(value) ?? 'okf'\n if (['okf', 'markdown', 'json'].includes(format)) {\n return format as KnowledgeFormat\n }\n throw new Error('Format must be one of: okf, markdown, json.')\n}\n\nexport function knowledgePayload(report: CrawlReport) {\n return {\n reportId: report.id,\n url: report.config.url,\n generatedAt: report.generatedAt,\n crawl: {\n summary: report.summary,\n caveats: report.caveats,\n warnings: report.warnings,\n pages: report.pages.map((page) => ({\n url: page.finalUrl,\n title: page.title,\n metaDescription: page.metaDescription,\n status: page.status,\n indexable: page.indexable,\n wordCount: page.wordCount,\n schemaTypes: page.schemaTypes,\n sameAs: page.schemaSameAs,\n internalInlinks: page.internalInlinkCount,\n contentSample: page.contentSample,\n })),\n },\n aiReadiness: aiReadiness(report),\n entityReadiness: entityReadiness(report),\n llmsTxt: auditLlmsTxt(report),\n }\n}\n\nfunction renderKnowledgeMarkdown(report: CrawlReport): string {\n const payload = knowledgePayload(report)\n const lines = [\n `# Site Knowledge Export`,\n '',\n `Source: ${report.config.url}`,\n `Crawl report: ${report.id}`,\n `Generated: ${payload.generatedAt}`,\n '',\n '## Summary',\n '',\n `- Documents: ${report.summary.totalPages}${report.requestEvidenceStatus === 'available' ? ` from ${report.requests.length} URL requests` : report.requestEvidenceStatus === 'partial' ? ` from ${report.requests.length} observed URL requests (request evidence is partial)` : ' (request evidence unavailable for this legacy report)'}`,\n `- Indexable pages: ${report.summary.indexablePages}`,\n `- Crawl findings: ${report.issues.length} (${report.summary.highIssues} high, ${report.summary.mediumIssues} medium, ${report.summary.lowIssues} low)`,\n `- AI-search evidence: ${payload.aiReadiness.dataStatus} (${payload.aiReadiness.assessment})`,\n `- Entity evidence: ${payload.entityReadiness.dataStatus} (${payload.entityReadiness.assessment})`,\n '',\n '## Top AI Readiness Actions',\n '',\n ...(payload.aiReadiness.topActions.length\n ? payload.aiReadiness.topActions.map(\n (action) => `- ${action.title}: ${action.action}`,\n )\n : ['- No AI-search technical actions in this crawl.']),\n '',\n '## Entity Signals',\n '',\n `- sameAs profiles: ${payload.entityReadiness.entities.sameAs.length}`,\n `- Social profiles: ${payload.entityReadiness.entities.socialProfiles.length}`,\n `- Authors: ${payload.entityReadiness.entities.authors.length}`,\n '',\n '## Important Pages',\n '',\n ...report.pages\n .filter((page) => page.indexable && page.status < 400)\n .slice(0, 100)\n .map(\n (page) =>\n `- [${page.title ?? page.finalUrl}](${page.finalUrl}) - ${page.metaDescription ?? page.contentSample ?? 'No summary available.'}`,\n ),\n '',\n '# Citations',\n '',\n `- [Crawl start URL](${report.config.url})`,\n '',\n ]\n return `${lines.join('\\n')}\\n`\n}\n\nexport const exportKnowledgeCommand = defineCommand({\n meta: {\n name: 'knowledge',\n description:\n 'Export site knowledge from a saved crawl as OKF, Markdown, or JSON',\n },\n args: {\n 'report-id': {\n type: 'string',\n description: 'Saved crawl report id to export.',\n },\n site: {\n type: 'string',\n description: 'GSC property URL for selecting the latest saved crawl.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n format: {\n type: 'string',\n description: 'Output format: okf, markdown, or json. Defaults to okf.',\n },\n output: {\n type: 'string',\n description:\n 'Output directory for OKF, or output file for Markdown/JSON.',\n },\n 'max-concepts': {\n type: 'string',\n description: 'Maximum OKF concept files. Defaults to 500.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print command metadata as JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const format = formatArg(args.format)\n const maxConcepts =\n format === 'okf'\n ? okfConceptLimit(\n strictNumberArg(args['max-concepts'], '--max-concepts'),\n )\n : undefined\n const report = await resolveSavedCrawlReport(args, { json })\n const output = stringArg(args.output)\n\n if (format === 'okf') {\n const bundle = buildOkfBundle(report, {\n maxConcepts,\n })\n const outDir = output ?? './okf'\n const validation = await writeOkfDirectory(outDir, bundle.files)\n if (json) {\n printJson({ format, output: outDir, bundle, validation })\n return\n }\n process.stdout.write(`Wrote OKF bundle to ${outDir}\\n\\n`)\n printKeyValue([\n ['Files', String(bundle.files.length)],\n ['Concepts', String(bundle.conceptCount)],\n ['Valid', validation.valid ? 'yes' : 'no'],\n ])\n return\n }\n\n if (format === 'json') {\n const content = `${JSON.stringify(knowledgePayload(report), null, 2)}\\n`\n await writeOrPrint(output, content)\n return\n }\n\n await writeOrPrint(output, renderKnowledgeMarkdown(report))\n },\n})\n","import { monthlyReport, narrativeCsvFiles } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { booleanArg, numberArg, projectArg, stringArg } from '../../args.js'\nimport { createProgressReporter } from '../../progress.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { cliReportArgs } from '../report-options.js'\nimport { reportFetchOptions } from '../reports/args.js'\nimport {\n defaultOutDir,\n exportReportFetchArgs,\n exportSelectionArgs,\n outArg,\n printWritten,\n writeCsvFiles,\n} from './shared.js'\n\nexport const exportMonthlyCommand = defineCommand({\n meta: {\n name: 'monthly',\n description:\n 'Export monthly report tables plus the underlying diagnosis detail CSVs.',\n },\n args: {\n ...exportSelectionArgs,\n out: outArg('monthly'),\n month: {\n type: 'string',\n description:\n 'Report month as YYYY-MM. Defaults to the latest month with final GSC data.',\n },\n ...cliReportArgs(['limit'], {\n limit: {\n description: 'Maximum rows per diagnostic section. Defaults to 10.',\n },\n }),\n ...exportReportFetchArgs,\n },\n run: async ({ args }) => {\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { refresh: booleanArg(args.refresh) },\n })\n const report = await monthlyReport({\n site: selection.site,\n month: stringArg(args.month),\n limit: numberArg(args.limit),\n brandTerms: selection.client?.brandTerms,\n ...reportFetchOptions(args),\n progress: createProgressReporter(true),\n })\n const outDir =\n stringArg(args.out) ??\n defaultOutDir({\n report: 'monthly',\n clientId: selection.client?.id,\n site: selection.site,\n })\n const written = await writeCsvFiles(outDir, narrativeCsvFiles(report))\n printWritten(outDir, written)\n },\n})\n","import { narrativeCsvFiles, reportNarrative } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { booleanArg, numberArg, projectArg, stringArg } from '../../args.js'\nimport { createProgressReporter } from '../../progress.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { cliReportArgs } from '../report-options.js'\nimport { reportFetchOptions } from '../reports/args.js'\nimport {\n defaultOutDir,\n exportReportFetchArgs,\n exportSelectionArgs,\n outArg,\n printWritten,\n writeCsvFiles,\n} from './shared.js'\n\nexport const exportNarrativeCommand = defineCommand({\n meta: {\n name: 'narrative',\n description:\n 'Export report narrative tables plus the underlying diagnosis detail CSVs.',\n },\n args: {\n ...exportSelectionArgs,\n out: outArg('narrative'),\n ...cliReportArgs(['days', 'recentDays'], {\n days: {\n description: 'Diagnosis window length in days. Defaults to 90.',\n },\n }),\n 'start-date': {\n type: 'string',\n description: 'Optional report start date as YYYY-MM-DD.',\n },\n 'end-date': {\n type: 'string',\n description: 'Optional report end date as YYYY-MM-DD.',\n },\n ...cliReportArgs(['limit'], {\n limit: {\n description: 'Maximum rows per diagnostic section. Defaults to 10.',\n },\n }),\n 'change-limit': {\n type: 'string',\n description: 'Maximum saved changes to measure. Defaults to 5.',\n },\n ...exportReportFetchArgs,\n },\n run: async ({ args }) => {\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { refresh: booleanArg(args.refresh) },\n })\n const report = await reportNarrative({\n site: selection.site,\n days: numberArg(args.days),\n recentDays: numberArg(args.recent),\n startDate: stringArg(args['start-date']),\n endDate: stringArg(args['end-date']),\n limit: numberArg(args.limit),\n changeLimit: numberArg(args['change-limit']),\n brandTerms: selection.client?.brandTerms,\n ...reportFetchOptions(args),\n progress: createProgressReporter(true),\n })\n const outDir =\n stringArg(args.out) ??\n defaultOutDir({\n report: 'narrative',\n clientId: selection.client?.id,\n site: selection.site,\n })\n const written = await writeCsvFiles(outDir, narrativeCsvFiles(report))\n printWritten(outDir, written)\n },\n})\n","import { pseoAuditOptions } from '@seo/core'\nimport {\n booleanArg,\n csvArg,\n strictFetchRateArg,\n strictNumberArg,\n} from '../../args.js'\n\nexport function pseoOptions(args: Record<string, unknown>) {\n return pseoAuditOptions({\n days: strictNumberArg(args.days, '--days'),\n sitemaps: csvArg(args.sitemap),\n maxSitemapUrls: strictNumberArg(\n args['max-sitemap-urls'],\n '--max-sitemap-urls',\n ),\n templateLimit: strictNumberArg(args.limit, '--limit'),\n minimumTemplateUrls: strictNumberArg(\n args['minimum-template-urls'],\n '--minimum-template-urls',\n ),\n minimumTemplateShare: strictNumberArg(\n args['minimum-template-share'],\n '--minimum-template-share',\n ),\n minimumTemplateImpressions: strictNumberArg(\n args['minimum-template-impressions'],\n '--minimum-template-impressions',\n ),\n crawlSamples: strictNumberArg(args['crawl-samples'], '--crawl-samples'),\n inspectSamples: strictNumberArg(\n args['inspect-samples'],\n '--inspect-samples',\n ),\n brandTerms: csvArg(args['brand-terms']),\n includeBrand: booleanArg(args['include-brand']),\n js: booleanArg(args.js) ? true : ('auto' as const),\n refresh: booleanArg(args.refresh),\n rate: strictFetchRateArg(args),\n })\n}\n","import { pseoAuditReport, pseoCsvFiles } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { projectArg, stringArg } from '../../args.js'\nimport { createProgressReporter } from '../../progress.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { pseoOptions } from '../pseo/options.js'\nimport {\n defaultOutDir,\n exportSelectionArgs,\n outArg,\n printWritten,\n writeCsvFiles,\n} from './shared.js'\n\nexport const exportPseoCommand = defineCommand({\n meta: {\n name: 'pseo',\n description:\n 'Export pSEO audit tables: templates, demand patterns, top queries, sample coverage, crawl samples, and inspection samples.',\n },\n args: {\n ...exportSelectionArgs,\n out: outArg('pseo'),\n days: {\n type: 'string',\n description: 'GSC lookback window. Defaults to 28.',\n },\n limit: {\n type: 'string',\n description: 'Maximum pSEO templates to export.',\n },\n sitemap: {\n type: 'string',\n description: 'Comma-separated sitemap URLs. Can be passed once.',\n },\n 'crawl-samples': {\n type: 'string',\n description:\n 'Number of representative URLs to fetch per template. Defaults to 0.',\n },\n 'inspect-samples': {\n type: 'string',\n description:\n 'Number of representative URLs to inspect in GSC per template. Defaults to 0.',\n },\n 'max-sitemap-urls': {\n type: 'string',\n description: 'Maximum discovered URLs per sitemap. Defaults to 50000.',\n },\n 'minimum-template-urls': {\n type: 'string',\n description:\n 'Minimum repeated URLs required for a template. Defaults to 3.',\n },\n 'minimum-template-share': {\n type: 'string',\n description:\n 'Minimum share of discovered URLs from 0 to 1. Defaults to 0.',\n },\n 'minimum-template-impressions': {\n type: 'string',\n description:\n 'Minimum retained page impressions for a template. Defaults to 0.',\n },\n 'brand-terms': {\n type: 'string',\n description:\n 'Comma-separated brand terms to exclude from query evidence.',\n },\n 'include-brand': {\n type: 'boolean',\n default: false,\n description: 'Include branded queries in pSEO demand analysis.',\n },\n js: {\n type: 'boolean',\n default: false,\n description: 'Force JavaScript rendering for crawled samples.',\n },\n 'fetch-concurrency': {\n type: 'string',\n description: 'Maximum concurrent page fetches per host. Defaults to 4.',\n },\n 'fetch-interval-cap': {\n type: 'string',\n description: 'Maximum page fetches per interval per host. Defaults to 4.',\n },\n 'fetch-interval-ms': {\n type: 'string',\n description: 'Fetch rate interval in milliseconds. Defaults to 1000.',\n },\n refresh: {\n type: 'boolean',\n default: false,\n description: 'Bypass local cache and fetch fresh data.',\n },\n },\n run: async ({ args }) => {\n const options = pseoOptions(args)\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n })\n const report = await pseoAuditReport({\n site: selection.site,\n ...options,\n brandTerms: options.brandTerms ?? selection.client?.brandTerms,\n progress: createProgressReporter(true),\n })\n const outDir =\n stringArg(args.out) ??\n defaultOutDir({\n report: 'pseo',\n clientId: selection.client?.id,\n site: selection.site,\n })\n const written = await writeCsvFiles(outDir, pseoCsvFiles(report))\n printWritten(outDir, written)\n },\n})\n","import { refreshPrioritiesCsvFiles, refreshPrioritiesWorkflow } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n defaultTrueBooleanArg,\n numberArg,\n projectArg,\n stringArg,\n} from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { cliReportArgs } from '../report-options.js'\nimport {\n defaultOutDir,\n exportSelectionArgs,\n outArg,\n printWritten,\n writeCsvFiles,\n} from './shared.js'\n\nexport const exportRefreshPrioritiesCommand = defineCommand({\n meta: {\n name: 'refresh-priorities',\n description:\n 'Export the ranked SEO priority queue, score breakdowns, grouped findings, and diagnosis detail CSVs.',\n },\n args: {\n ...exportSelectionArgs,\n out: outArg('refresh-priorities'),\n ...cliReportArgs(\n ['days', 'recentDays', 'limit', 'includeBrand', 'refresh'],\n {\n days: {\n description: 'Diagnosis window length in days. Defaults to 90.',\n },\n limit: {\n description: 'Maximum queue items to export. Defaults to 25.',\n },\n },\n ),\n 'ga4-property': {\n type: 'string',\n description:\n 'GA4 property ID to use for analytics value. Defaults from the selected project.',\n },\n 'verify-content': defaultTrueBooleanArg(\n 'Verify top opportunities against page title, meta, and content. Defaults to true.',\n 'Skip page content verification.',\n ),\n 'verify-limit': {\n type: 'string',\n description: 'Maximum opportunity URLs to verify. Defaults to 5.',\n },\n },\n run: async ({ args }) => {\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { refresh: booleanArg(args.refresh) },\n })\n const report = await refreshPrioritiesWorkflow({\n site: selection.site,\n days: numberArg(args.days),\n recentDays: numberArg(args.recent),\n limit: numberArg(args.limit),\n brandTerms: selection.client?.brandTerms,\n includeBrand: booleanArg(args['include-brand']),\n ga4PropertyId:\n stringArg(args['ga4-property']) ?? selection.client?.ga4PropertyId,\n verifyContent: booleanArg(args['verify-content']),\n verifyLimit: numberArg(args['verify-limit']),\n refresh: booleanArg(args.refresh),\n })\n const outDir =\n stringArg(args.out) ??\n defaultOutDir({\n report: 'refresh-priorities',\n clientId: selection.client?.id,\n site: selection.site,\n })\n const written = await writeCsvFiles(\n outDir,\n refreshPrioritiesCsvFiles(report),\n )\n printWritten(outDir, written)\n },\n})\n","import { updatePostmortemCsvFiles, updatePostmortemWorkflow } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { booleanArg, numberArg, projectArg, stringArg } from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { cliReportArgs } from '../report-options.js'\nimport {\n defaultOutDir,\n exportSelectionArgs,\n outArg,\n printWritten,\n writeCsvFiles,\n} from './shared.js'\n\nexport const exportUpdatePostmortemCommand = defineCommand({\n meta: {\n name: 'update-postmortem',\n description:\n 'Export update postmortem attribution, findings, template movement, and segment movers.',\n },\n args: {\n ...exportSelectionArgs,\n out: outArg('update-postmortem'),\n ...cliReportArgs(\n ['days', 'recentDays', 'limit', 'includeBrand', 'refresh'],\n {\n days: {\n description: 'Diagnosis window length in days. Defaults to 90.',\n },\n limit: {\n description: 'Maximum winners/losers per segment. Defaults to 20.',\n },\n },\n ),\n 'known-change': {\n type: 'string',\n description:\n 'Manual site-side change to treat as a confounder, for example pruning pages or blocking traffic.',\n },\n 'ignore-change-log': {\n type: 'boolean',\n default: false,\n description: 'Do not use saved change-log entries as confounders.',\n },\n },\n run: async ({ args }) => {\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { refresh: booleanArg(args.refresh) },\n })\n const report = await updatePostmortemWorkflow({\n site: selection.site,\n days: numberArg(args.days),\n recentDays: numberArg(args.recent),\n limit: numberArg(args.limit),\n brandTerms: selection.client?.brandTerms,\n includeBrand: booleanArg(args['include-brand']),\n knownConfounders: stringArg(args['known-change'])\n ? [stringArg(args['known-change']) ?? '']\n : undefined,\n includeChangeLog: !booleanArg(args['ignore-change-log']),\n refresh: booleanArg(args.refresh),\n })\n const outDir =\n stringArg(args.out) ??\n defaultOutDir({\n report: 'update-postmortem',\n clientId: selection.client?.id,\n site: selection.site,\n })\n const written = await writeCsvFiles(\n outDir,\n updatePostmortemCsvFiles(report),\n )\n printWritten(outDir, written)\n },\n})\n","import { defineCommand } from 'citty'\nimport { exportDiagnoseCommand } from './diagnose.js'\nimport { exportKnowledgeCommand } from './knowledge.js'\nimport { exportMonthlyCommand } from './monthly.js'\nimport { exportNarrativeCommand } from './narrative.js'\nimport { exportPseoCommand } from './pseo.js'\nimport { exportRefreshPrioritiesCommand } from './refresh-priorities.js'\nimport { exportUpdatePostmortemCommand } from './update-postmortem.js'\n\nexport const exportCommand = defineCommand({\n meta: {\n name: 'export',\n description: 'Export full report data to CSV files',\n },\n subCommands: {\n diagnose: exportDiagnoseCommand,\n knowledge: exportKnowledgeCommand,\n narrative: exportNarrativeCommand,\n monthly: exportMonthlyCommand,\n 'update-postmortem': exportUpdatePostmortemCommand,\n 'refresh-priorities': exportRefreshPrioritiesCommand,\n pseo: exportPseoCommand,\n },\n})\n","import { defineCommand } from 'citty'\nimport { startCommand } from './setup/index.js'\n\n/**\n * Kept for existing scripts. New users should start with `seo start`.\n *\n * Do not let this become a second onboarding flow. A person should see the\n * same calm Google, project-profile, and MCP setup whichever entry they use.\n */\nexport const initCommand = defineCommand({\n ...startCommand,\n meta: {\n name: 'init',\n description: 'Legacy alias for `seo start`.',\n },\n})\n","import { mkdir, writeFile } from 'node:fs/promises'\nimport { dirname } from 'node:path'\nimport { auditLlmsTxt, generateLlmsTxt } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { csvArg, jsonFlag, numberArg, stringArg } from '../args.js'\nimport { printJson, printKeyValue, printTable } from '../utils.js'\nimport { printNotes, truncate } from './output.js'\nimport { resolveSavedCrawlReport } from './readiness.js'\n\nasync function writeOrPrint(path: string | undefined, content: string) {\n if (!path) {\n process.stdout.write(content)\n return\n }\n await mkdir(dirname(path), { recursive: true })\n await writeFile(path, content)\n process.stdout.write(`Wrote ${path}\\n`)\n}\n\nconst sharedArgs = {\n 'report-id': {\n type: 'string',\n description: 'Saved crawl report id to use.',\n },\n site: {\n type: 'string',\n description: 'GSC property URL for selecting the latest saved crawl.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n} as const\n\nexport const llmsAuditCommand = defineCommand({\n meta: {\n name: 'audit',\n description: 'Inspect optional llms.txt presence from a saved crawl',\n },\n args: sharedArgs,\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const report = await resolveSavedCrawlReport(args, { json })\n const audit = auditLlmsTxt(report)\n if (json) {\n printJson(audit)\n return\n }\n\n process.stdout.write(`llms.txt audit for ${audit.url}\\n\\n`)\n printKeyValue([\n ['SEO impact', audit.googleSearchImpact],\n ['Optional', audit.optional ? 'yes' : 'no'],\n ['Found', audit.exists ? 'yes' : 'no'],\n ['URL', audit.llmsTxtUrl],\n ['Status', audit.status ? String(audit.status) : '-'],\n ])\n process.stdout.write(`\\n${audit.headline}\\n`)\n if (audit.issues.length) {\n process.stdout.write('\\nIssues\\n')\n printTable(\n ['Severity', 'Issue', 'Action'],\n audit.issues.map((issue) => [\n issue.severity,\n issue.title,\n truncate(issue.action, 96),\n ]),\n )\n }\n printNotes(\n 'Recommended pages',\n audit.recommendedPages\n .slice(0, 10)\n .map((page) => `${page.section}: ${page.url}`),\n )\n },\n})\n\nexport const llmsGenerateCommand = defineCommand({\n meta: {\n name: 'generate',\n description: 'Generate an llms.txt draft from a saved crawl',\n },\n args: {\n ...sharedArgs,\n output: {\n type: 'string',\n description: 'Write llms.txt to this path instead of stdout.',\n },\n 'max-urls': {\n type: 'string',\n description: 'Maximum URLs to include. Defaults to 250.',\n },\n 'token-budget': {\n type: 'string',\n description: 'Approximate token budget. Defaults to 12000.',\n },\n exclude: {\n type: 'string',\n description: 'Comma-separated URL patterns to exclude.',\n },\n title: {\n type: 'string',\n description: 'Override the llms.txt title.',\n },\n description: {\n type: 'string',\n description: 'Override the llms.txt description.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const report = await resolveSavedCrawlReport(args, { json })\n const generated = generateLlmsTxt(report, {\n maxUrls: numberArg(args['max-urls']),\n tokenBudget: numberArg(args['token-budget']),\n exclude: csvArg(args.exclude),\n title: stringArg(args.title),\n description: stringArg(args.description),\n })\n\n if (json) {\n printJson(generated)\n return\n }\n await writeOrPrint(stringArg(args.output), generated.content)\n if (stringArg(args.output)) {\n printKeyValue([\n ['URLs', String(generated.includedUrls)],\n ['Estimated tokens', String(generated.estimatedTokens)],\n ])\n }\n },\n})\n\nexport const llmsCommand = defineCommand({\n meta: {\n name: 'llms',\n description: 'Inspect or generate optional llms.txt from saved crawl data',\n },\n subCommands: {\n audit: llmsAuditCommand,\n generate: llmsGenerateCommand,\n },\n})\n","import { multiselect } from '@clack/prompts'\nimport { SeoError } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { booleanArg, jsonFlag } from '../args.js'\nimport { canPrompt, maybeExitCancelled, printJson } from '../utils.js'\nimport {\n detectMcpClients,\n mcpClientTargets,\n type SupportedClient,\n} from './mcp-clients.js'\nimport { installMcpConfig, uninstallMcpConfig } from './mcp-config.js'\n\nconst targetFlags: Array<{\n client: SupportedClient\n flag: 'claude-desktop' | 'claude-code' | 'codex' | 'cursor'\n}> = [\n {\n client: 'claude-desktop',\n flag: 'claude-desktop',\n },\n { client: 'claude-code', flag: 'claude-code' },\n { client: 'codex', flag: 'codex' },\n { client: 'cursor', flag: 'cursor' },\n]\n\nfunction selectedClients(\n args: Record<string, unknown>,\n available: SupportedClient[],\n): SupportedClient[] {\n if (booleanArg(args.all)) return available\n return targetFlags\n .filter(({ flag }) => booleanArg(args[flag]))\n .map(({ client }) => client)\n}\n\nexport const mcpCommand = defineCommand({\n meta: { name: 'mcp', description: 'MCP server helpers' },\n subCommands: {\n serve: defineCommand({\n meta: {\n name: 'serve',\n description: 'Run the SEO MCP server',\n },\n args: {\n test: {\n type: 'boolean',\n default: false,\n description: 'Start in test mode',\n },\n },\n run: async ({ args }) => {\n const { startMcpServer } = await import('@seo/mcp')\n await startMcpServer({ test: booleanArg(args.test) })\n },\n }),\n install: defineCommand({\n meta: {\n name: 'install',\n description: 'Install or remove SEO MCP config for local clients',\n },\n args: {\n uninstall: {\n type: 'boolean',\n default: false,\n description: 'Remove the SEO MCP config instead of adding it',\n },\n reinstall: {\n type: 'boolean',\n default: false,\n description: 'Rewrite an existing managed SEO MCP config',\n },\n 'claude-desktop': {\n type: 'boolean',\n default: false,\n description: 'Update Claude Desktop',\n },\n 'claude-code': {\n type: 'boolean',\n default: false,\n description: 'Update Claude Code',\n },\n codex: {\n type: 'boolean',\n default: false,\n description: 'Update Codex CLI, app, and IDE extension',\n },\n cursor: {\n type: 'boolean',\n default: false,\n description: 'Update Cursor',\n },\n all: {\n type: 'boolean',\n default: false,\n description: 'Update every detected MCP client',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print structured JSON output',\n },\n },\n run: async ({ args }) => {\n if (booleanArg(args.uninstall) && booleanArg(args.reinstall)) {\n throw new SeoError(\n 'INVALID_INPUT',\n 'Use either --uninstall or --reinstall, not both.',\n )\n }\n const targets = mcpClientTargets()\n const detected = detectMcpClients({ targets })\n const json = jsonFlag(args)\n let selected = selectedClients(\n args,\n detected.map((target) => target.client),\n )\n\n if (selected.length === 0) {\n if (!canPrompt({ json })) {\n throw new SeoError(\n 'INVALID_INPUT',\n 'Choose an MCP client with --claude-desktop, --claude-code, --codex, --cursor, or --all.',\n )\n }\n const choices = detected.length > 0 ? detected : targets\n selected = maybeExitCancelled(\n await multiselect({\n message: args.uninstall\n ? 'Remove seo from which MCP clients?'\n : 'Install seo into which MCP clients?',\n options: choices.map((target) => ({\n value: target.client,\n label: target.label,\n hint: target.path,\n })),\n initialValues: detected.map((target) => target.client),\n required: true,\n }),\n )\n }\n\n const unavailable = selected.filter(\n (client) => !targets.some((target) => target.client === client),\n )\n if (unavailable.length > 0) {\n throw new SeoError(\n 'INVALID_INPUT',\n `MCP setup is not supported for ${unavailable.join(', ')} on ${process.platform}.`,\n )\n }\n\n const results = targets\n .filter((entry) => selected.includes(entry.client))\n .map((target) =>\n booleanArg(args.uninstall)\n ? uninstallMcpConfig(target)\n : installMcpConfig(target, {\n reinstall: booleanArg(args.reinstall),\n }),\n )\n\n if (json) {\n printJson({\n operation: booleanArg(args.uninstall) ? 'uninstall' : 'install',\n results,\n })\n return\n }\n\n for (const result of results) {\n process.stdout.write(\n `${result.changed ? 'updated' : 'skipped'} ${result.client} · ${result.path}\\n`,\n )\n }\n },\n }),\n },\n})\n","import { crawlDiff } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { booleanArg, jsonFlag, numberArg, stringArg } from '../../args.js'\nimport { printJson, printKeyValue, printTable } from '../../utils.js'\nimport { printActionDetails, truncate } from '../output.js'\n\nexport const crawlDiffCommand = defineCommand({\n meta: {\n name: 'crawl-diff',\n description: 'Crawl a site and diff technical/page changes vs last run',\n },\n args: {\n url: {\n type: 'string',\n required: true,\n description: 'Start URL to crawl.',\n },\n site: {\n type: 'string',\n description: 'Optional GSC property to associate with the crawl.',\n },\n limit: {\n type: 'string',\n description: 'Maximum pages to crawl. Defaults to 50.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n refresh: {\n type: 'boolean',\n default: false,\n description: 'Bypass local HTTP cache.',\n },\n js: {\n type: 'boolean',\n default: false,\n description: 'Force JavaScript rendering when Playwright is installed.',\n },\n },\n run: async ({ args }) => {\n const report = await crawlDiff({\n startUrl: stringArg(args.url) ?? '',\n site: stringArg(args.site),\n limit: numberArg(args.limit),\n refresh: booleanArg(args.refresh),\n js: booleanArg(args.js) ? true : 'auto',\n })\n if (jsonFlag(args)) {\n printJson(report)\n return\n }\n\n printKeyValue([\n ['Run', report.run.id],\n ['Start URL', report.run.startUrl],\n ['Crawled', String(report.summary.crawled)],\n ['Previous run', report.previousRun?.id ?? 'none'],\n ['Added', String(report.summary.added)],\n ['Removed', String(report.summary.removed)],\n ['Changed', String(report.summary.changed)],\n ['New errors', String(report.summary.newErrors)],\n ['Indexability flips', String(report.summary.indexabilityFlips)],\n [\n 'High-priority actions',\n String(report.summary.highPriorityRecommendations),\n ],\n ])\n if (report.recommendations.length) {\n process.stdout.write('\\nRecommended actions\\n')\n printTable(\n ['Severity', 'Category', 'URL', 'Action'],\n report.recommendations\n .slice(0, 10)\n .map((item) => [\n item.severity,\n item.category,\n truncate(item.url, 56),\n truncate(item.action, 72),\n ]),\n )\n printActionDetails(\n 'Top crawl actions',\n report.recommendations.map((item) => ({\n label: item.category,\n context: `${item.severity}, ${truncate(item.url, 96)}`,\n action: item.action,\n })),\n )\n }\n if (report.items.length) {\n process.stdout.write('\\nChanged URLs\\n')\n printTable(\n ['Kind', 'URL', 'Changes', 'Recommendation'],\n report.items\n .slice(0, 50)\n .map((item) => [\n item.kind,\n truncate(item.url, 56),\n item.changes.join(', '),\n item.recommendation?.title ?? '-',\n ]),\n )\n }\n if (report.warnings.length) {\n process.stdout.write('\\nWarnings\\n')\n for (const warning of report.warnings.slice(0, 10)) {\n process.stdout.write(`- ${warning}\\n`)\n }\n }\n },\n})\n","import { defaultTrueBooleanArg } from '../../args.js'\n\nexport function monitoringRunArgs() {\n return {\n site: {\n type: 'string',\n description: 'GSC property URL, for example sc-domain:example.com.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n url: {\n type: 'string',\n description:\n 'Start URL to crawl. Defaults from the project or GSC property.',\n },\n urls: {\n type: 'string',\n description: 'Comma-separated URLs to inspect with URL Inspection.',\n },\n sitemaps: {\n type: 'string',\n description:\n 'Comma-separated XML sitemap URLs for quota-aware index monitoring.',\n },\n properties: {\n type: 'string',\n description:\n 'Comma-separated GSC properties for sitemap index monitoring.',\n },\n limit: {\n type: 'string',\n description: 'Maximum pages to crawl. Defaults to 50.',\n },\n 'daily-limit': {\n type: 'string',\n description: 'URL Inspection daily limit per property. Defaults to 2000.',\n },\n 'inspect-limit': {\n type: 'string',\n description:\n 'Maximum sitemap URLs to inspect in this run. Defaults to 100.',\n },\n 'max-urls': {\n type: 'string',\n description:\n 'Maximum sitemap URLs to load for monitoring. Defaults to 50000.',\n },\n language: {\n type: 'string',\n description: 'Optional URL Inspection language code.',\n },\n 'recover-links': defaultTrueBooleanArg(\n 'Check search-value GSC pages for broken, blocked, or poorly redirected URLs.',\n 'Skip link recovery checks.',\n ),\n 'recover-days': {\n type: 'string',\n description: 'GSC lookback window for link recovery. Defaults to 90.',\n },\n 'recover-limit': {\n type: 'string',\n description:\n 'Maximum search-value pages to check for link recovery. Defaults to 10.',\n },\n 'recover-min-clicks': {\n type: 'string',\n description:\n 'Minimum clicks for link recovery candidates. Defaults to 1.',\n },\n 'recover-min-impressions': {\n type: 'string',\n description:\n 'Minimum impressions for link recovery candidates. Defaults to 100.',\n },\n refresh: {\n type: 'boolean',\n default: false,\n description: 'Bypass local HTTP/GSC cache where supported.',\n },\n js: {\n type: 'boolean',\n default: false,\n description: 'Force JavaScript rendering when Playwright is installed.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n } as const\n}\n\nexport function monitoringStatusArgs() {\n return {\n site: {\n type: 'string',\n description: 'GSC property URL, for example sc-domain:example.com.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n 'stale-days': {\n type: 'string',\n description: 'Mark checks stale after this many days. Defaults to 8.',\n },\n refresh: {\n type: 'boolean',\n default: false,\n description: 'Refresh property selection data when prompting.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n } as const\n}\n","import { printKeyValue, printTable } from '../../utils.js'\nimport { printActionDetails } from '../output.js'\n\nexport function printWorkflow(report: {\n workflow: string\n site: string\n summary: string\n steps: Array<{ tool: string; status: string; summary: string }>\n actions: Array<{ title: string; confidence: string; action: string }>\n}): void {\n printKeyValue([\n ['Workflow', report.workflow],\n ['Property', report.site],\n ['Summary', report.summary],\n ])\n printTable(\n ['Tool', 'Status', 'Summary'],\n report.steps.map((step) => [step.tool, step.status, step.summary]),\n )\n if (report.actions.length) {\n printTable(\n ['Priority', 'Confidence', 'Action'],\n report.actions.map((action) => [\n action.title,\n action.confidence,\n action.action,\n ]),\n )\n printActionDetails(\n 'Priority action details',\n report.actions.map((action) => ({\n label: action.title,\n context: action.confidence,\n action: action.action,\n })),\n )\n }\n}\n","import type { MonitoringStatusReport, technicalWatchWorkflow } from '@seo/core'\nimport { printKeyValue, printTable } from '../../utils.js'\nimport { formatCount, printActionDetails, truncate } from '../output.js'\nimport { printWorkflow } from '../workflows/output.js'\n\ntype TechnicalWatchReport = Awaited<ReturnType<typeof technicalWatchWorkflow>>\n\nexport function printMonitoringRun(report: TechnicalWatchReport): void {\n printWorkflow(report)\n\n if (report.output.crawl?.recommendations.length) {\n process.stdout.write('\\nCrawl actions\\n')\n printTable(\n ['Severity', 'URL', 'Action'],\n report.output.crawl.recommendations\n .slice(0, 10)\n .map((item) => [\n item.severity,\n truncate(item.url, 56),\n truncate(item.action, 72),\n ]),\n )\n printActionDetails(\n 'Top crawl actions',\n report.output.crawl.recommendations.map((item) => ({\n label: item.severity,\n context: truncate(item.url, 96),\n action: item.action,\n })),\n )\n }\n\n if (report.output.index?.items.length) {\n const items = report.output.index.items\n .filter(\n (item) =>\n item.currentIssue ||\n item.changed ||\n item.inspectionStatus !== 'succeeded',\n )\n .slice(0, 25)\n if (items.length) {\n process.stdout.write('\\nIndex reviews, changes, and failed checks\\n')\n printTable(\n ['Check', 'Change', 'Index state', 'Evidence', 'URL'],\n items.map((item) => [\n item.inspectionStatus,\n item.changeKind,\n item.indexStatus,\n truncate(\n (item.errorCode ?? item.issueCodes.join(', ')) || 'none',\n 40,\n ),\n truncate(item.url, 64),\n ]),\n )\n }\n }\n\n if (report.output.recovery?.items.length) {\n process.stdout.write('\\nRecoverable URLs\\n')\n printTable(\n ['Severity', 'Issue', 'Clicks', 'Impr', 'URL', 'Action'],\n report.output.recovery.items\n .slice(0, 10)\n .map((item) => [\n item.severity,\n item.issue,\n formatCount(item.clicks),\n formatCount(item.impressions),\n truncate(item.url, 56),\n truncate(item.recommendation.action, 72),\n ]),\n )\n printActionDetails(\n 'Top recovery actions',\n report.output.recovery.items.map((item) => ({\n label: truncate(item.url, 96),\n context: `${item.severity}, ${formatCount(item.clicks)} clicks at risk`,\n action: item.recommendation.action,\n })),\n )\n }\n}\n\nexport function printMonitoringStatus(report: MonitoringStatusReport): void {\n printKeyValue([\n ['Property', report.site],\n ['Health', report.health],\n ['Attention', String(report.summary.attention)],\n ['Stale', String(report.summary.stale)],\n ['Not run', String(report.summary.notRun)],\n ])\n\n printTable(\n ['Check', 'Status', 'Last run', 'Summary'],\n report.checks.map((check) => [\n check.name,\n check.status,\n check.lastRunAt ?? '-',\n check.summary,\n ]),\n )\n\n const actions = report.checks.filter((check) => check.action)\n if (actions.length) {\n process.stdout.write('\\nNext actions\\n')\n printTable(\n ['Check', 'Action'],\n actions.map((check) => [check.name, truncate(check.action ?? '', 96)]),\n )\n printActionDetails(\n 'Next action details',\n actions.map((check) => ({\n label: check.name,\n action: check.action ?? '',\n })),\n )\n }\n}\n","import { monitoringStatus, technicalWatchWorkflow } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n jsonFlag,\n listArg,\n numberArg,\n projectArg,\n stringArg,\n} from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson, printKeyValue } from '../../utils.js'\nimport { startUrlForSite } from '../shared.js'\nimport { monitoringRunArgs, monitoringStatusArgs } from './args.js'\nimport { printMonitoringRun, printMonitoringStatus } from './output.js'\n\nfunction quotedFlag(name: string, value: unknown): string | undefined {\n const text = stringArg(value)\n return text ? `--${name} ${JSON.stringify(text)}` : undefined\n}\n\nfunction booleanFlag(name: string, value: unknown): string | undefined {\n return booleanArg(value) ? `--${name}` : undefined\n}\n\nfunction recoverLinksFlag(value: unknown): string | undefined {\n return booleanArg(value) === false ? '--recover-links=false' : undefined\n}\n\nexport const monitoringCommand = defineCommand({\n meta: {\n name: 'monitoring',\n description: 'Run and review recurring technical SEO monitoring',\n },\n subCommands: {\n run: defineCommand({\n meta: {\n name: 'run',\n description:\n 'Run crawl, index, and link recovery monitoring for a property',\n },\n args: monitoringRunArgs(),\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json, refresh: booleanArg(args.refresh) },\n })\n const urls = listArg(args.urls)\n const sitemaps = listArg(args.sitemaps)\n const startUrl =\n stringArg(args.url) ??\n selection.client?.startUrl ??\n startUrlForSite(selection.site)\n const report = await technicalWatchWorkflow({\n site: selection.site,\n startUrl,\n urls: urls.length ? urls : selection.client?.watchUrls,\n sitemaps: sitemaps.length ? sitemaps : undefined,\n properties: listArg(args.properties).length\n ? listArg(args.properties)\n : undefined,\n limit: numberArg(args.limit),\n languageCode: stringArg(args.language),\n dailyLimit: numberArg(args['daily-limit']),\n inspectLimit: numberArg(args['inspect-limit']),\n maxUrls: numberArg(args['max-urls']),\n refresh: booleanArg(args.refresh),\n js: booleanArg(args.js) ? true : 'auto',\n recoverLinks: booleanArg(args['recover-links']),\n recoverDays: numberArg(args['recover-days']),\n recoverLimit: numberArg(args['recover-limit']),\n recoverMinClicks: numberArg(args['recover-min-clicks']),\n recoverMinImpressions: numberArg(args['recover-min-impressions']),\n })\n\n if (json) {\n printJson(report)\n return\n }\n printMonitoringRun(report)\n },\n }),\n status: defineCommand({\n meta: {\n name: 'status',\n description: 'Show the latest saved monitoring state for a property',\n },\n args: monitoringStatusArgs(),\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json, refresh: booleanArg(args.refresh) },\n })\n const report = monitoringStatus({\n site: selection.site,\n staleAfterDays: numberArg(args['stale-days']),\n })\n if (json) {\n printJson(report)\n return\n }\n printMonitoringStatus(report)\n },\n }),\n cron: defineCommand({\n meta: {\n name: 'cron',\n description: 'Print a local cron line for recurring monitoring',\n },\n args: {\n ...monitoringRunArgs(),\n hour: {\n type: 'string',\n default: '9',\n description: 'Hour in local cron time. Defaults to 9.',\n },\n minute: {\n type: 'string',\n default: '0',\n description: 'Minute in local cron time. Defaults to 0.',\n },\n weekday: {\n type: 'string',\n description:\n 'Weekly monitoring day. Defaults to client setting, then Monday.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json, refresh: booleanArg(args.refresh) },\n })\n const hour = numberArg(args.hour) ?? 9\n const minute = numberArg(args.minute) ?? 0\n const weekday =\n numberArg(args.weekday) ?? selection.client?.technicalWeekday ?? 1\n const identityArg = selection.client\n ? `--project ${JSON.stringify(selection.client.id)}`\n : `--site ${JSON.stringify(selection.site)}`\n const command = [\n 'seo monitoring run',\n identityArg,\n quotedFlag('url', args.url),\n quotedFlag('urls', args.urls),\n quotedFlag('sitemaps', args.sitemaps),\n quotedFlag('properties', args.properties),\n quotedFlag('limit', args.limit),\n quotedFlag('daily-limit', args['daily-limit']),\n quotedFlag('inspect-limit', args['inspect-limit']),\n quotedFlag('max-urls', args['max-urls']),\n quotedFlag('language', args.language),\n quotedFlag('recover-days', args['recover-days']),\n quotedFlag('recover-limit', args['recover-limit']),\n quotedFlag('recover-min-clicks', args['recover-min-clicks']),\n quotedFlag(\n 'recover-min-impressions',\n args['recover-min-impressions'],\n ),\n recoverLinksFlag(args['recover-links']),\n booleanFlag('refresh', args.refresh),\n booleanFlag('js', args.js),\n '--json',\n ]\n .filter(Boolean)\n .join(' ')\n const line = {\n name: 'monitoring',\n cron: `${minute} ${hour} * * ${weekday}`,\n command,\n }\n\n if (json) {\n printJson({ site: selection.site, line })\n return\n }\n printKeyValue([\n ['Property', selection.site],\n ['Install', 'crontab -e'],\n ])\n process.stdout.write(`${line.cron} ${line.command}\\n`)\n },\n }),\n },\n})\n","import { indexCoverageSignals } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n jsonFlag,\n listArg,\n numberArg,\n projectArg,\n stringArg,\n} from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson, printKeyValue, printTable } from '../../utils.js'\nimport { truncate } from '../output.js'\n\nexport const indexCoverageCommand = defineCommand({\n meta: {\n name: 'index-coverage',\n description:\n 'Find crawlable pages that deserve a closer Google index check',\n },\n args: {\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n site: {\n type: 'string',\n description: 'GSC property URL, for example sc-domain:example.com.',\n },\n 'crawl-report-id': {\n type: 'string',\n description:\n 'Saved crawl report id. Defaults to the latest for the site.',\n },\n sitemaps: {\n type: 'string',\n description:\n 'Comma-separated XML sitemap URLs. Defaults to declarations captured by the crawl.',\n },\n days: {\n type: 'string',\n description: 'Finalized Search Console date range. Defaults to 90 days.',\n },\n 'row-limit': {\n type: 'string',\n description: 'Maximum Search Console page rows. Defaults to 100000.',\n },\n 'max-sitemap-urls': {\n type: 'string',\n description: 'Maximum sitemap inventory URLs. Defaults to 100000.',\n },\n limit: {\n type: 'string',\n description:\n 'Maximum URLs returned in each evidence group. Defaults to 100.',\n },\n refresh: {\n type: 'boolean',\n default: false,\n description: 'Bypass the local Search Console cache.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json, refresh: booleanArg(args.refresh) },\n })\n const sitemapValues = listArg(args.sitemaps)\n const report = await indexCoverageSignals({\n site: selection.site,\n crawlReportId: stringArg(args['crawl-report-id']),\n sitemaps: sitemapValues.length ? sitemapValues : undefined,\n days: numberArg(args.days),\n rowLimit: numberArg(args['row-limit']),\n maxSitemapUrls: numberArg(args['max-sitemap-urls']),\n itemsPerSection: numberArg(args.limit),\n refresh: booleanArg(args.refresh),\n })\n\n if (json) {\n printJson(report)\n return\n }\n\n printKeyValue([\n ['Project site', report.site],\n ['Crawl report', report.input.crawlReport.id],\n ['Crawl evidence', report.sources.crawl.completeness],\n ['Sitemap evidence', report.sources.sitemap.completeness],\n [\n 'Search Console window',\n `${report.sources.searchConsole.startDate} to ${report.sources.searchConsole.endDate}`,\n ],\n ['Search Console evidence', report.sources.searchConsole.completeness],\n [\n 'Pages in returned Search Console data',\n String(report.summary.retainedSearchVisibleUrls),\n ],\n [\n 'Crawlable pages to review',\n String(\n report.summary.crawlableCandidatesWithoutRetainedSearchVisibility,\n ),\n ],\n [\n 'Blocked or non-indexable crawl pages',\n String(report.summary.blockedOrNonIndexableCrawlUrls),\n ],\n ['Sitemap-only pages', String(report.summary.sitemapOnlyUrls)],\n [\n 'Search Console-only pages',\n String(report.summary.searchConsoleOnlyUrls),\n ],\n ])\n\n if (report.crawlableWithoutRetainedSearchVisibility.items.length) {\n process.stdout.write('\\nRepresentative URL Inspection candidates\\n')\n printTable(\n ['URL', 'Status', 'In sitemap'],\n report.crawlableWithoutRetainedSearchVisibility.items.map((item) => [\n truncate(item.url, 80),\n item.status,\n item.inSitemap ? 'yes' : 'no',\n ]),\n )\n }\n\n if (report.caveats.length) {\n process.stdout.write('\\nHow to read this report\\n')\n for (const caveat of report.caveats) {\n process.stdout.write(`- ${caveat}\\n`)\n }\n }\n },\n})\n","import {\n countLabel,\n indexCoveragePlan,\n indexMonitor,\n indexWatch,\n} from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n jsonFlag,\n listArg,\n numberArg,\n stringArg,\n} from '../../args.js'\nimport { resolveSite } from '../../selection.js'\nimport { printJson, printKeyValue, printTable } from '../../utils.js'\n\nexport const indexWatchCommand = defineCommand({\n meta: {\n name: 'index-watch',\n description: 'Inspect URLs with GSC and alert on index status changes',\n },\n args: {\n site: {\n type: 'string',\n description: 'GSC property URL, for example sc-domain:example.com.',\n },\n urls: {\n type: 'string',\n description: 'Comma-separated URLs to inspect.',\n },\n sitemaps: {\n type: 'string',\n description:\n 'Comma-separated XML sitemap URLs to plan quota-aware monitoring.',\n },\n plan: {\n type: 'boolean',\n default: false,\n description:\n 'Plan sitemap URL allocation across GSC properties without inspecting URLs.',\n },\n properties: {\n type: 'string',\n description:\n 'Comma-separated GSC properties to use for planning. Defaults to account properties.',\n },\n 'daily-limit': {\n type: 'string',\n description: 'URL Inspection daily limit per property. Defaults to 2000.',\n },\n 'target-days': {\n type: 'string',\n description:\n 'Target number of days to inspect all monitored URLs. Defaults to 1.',\n },\n 'max-urls': {\n type: 'string',\n description:\n 'Maximum sitemap URLs to load for planning. Defaults to 50000.',\n },\n 'inspect-limit': {\n type: 'string',\n description:\n 'Maximum URLs to inspect in this run from sitemap mode. Defaults to 100.',\n },\n language: {\n type: 'string',\n description: 'Optional URL Inspection language code.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const urls = listArg(args.urls)\n const site = await resolveSite({\n site: stringArg(args.site),\n options: { json },\n })\n\n const sitemaps = listArg(args.sitemaps)\n\n if (booleanArg(args.plan)) {\n if (!sitemaps.length) {\n throw new Error('Pass at least one sitemap with --sitemaps.')\n }\n const report = await indexCoveragePlan({\n site,\n sitemaps,\n properties: listArg(args.properties).length\n ? listArg(args.properties)\n : undefined,\n dailyLimit: numberArg(args['daily-limit']),\n targetCycleDays: numberArg(args['target-days']),\n maxUrls: numberArg(args['max-urls']),\n })\n if (json) {\n printJson(report)\n return\n }\n printKeyValue([\n ['Project site', report.site],\n ['Sitemap URLs', String(report.summary.urlCount)],\n ['Properties used', String(report.summary.properties)],\n ['Daily capacity', String(report.summary.dailyCapacity)],\n [\n 'Estimated cycle',\n countLabel(report.summary.estimatedCycleDays, 'day'),\n ],\n ['Target cycle', countLabel(report.summary.targetCycleDays, 'day')],\n ['Suggested properties', String(report.summary.suggestedProperties)],\n ])\n if (report.properties.length) {\n printTable(\n ['Property', 'URLs', 'Cycle', 'Sample URL'],\n report.properties.map((property) => [\n property.property,\n property.urlCount,\n countLabel(property.cycleDays, 'day'),\n property.sampleUrls[0] ?? '-',\n ]),\n )\n }\n if (report.suggestions.length) {\n process.stdout.write('\\nSuggested URL-prefix properties\\n')\n printTable(\n ['Property', 'URLs', 'Current property', 'Cycle', 'Reason'],\n report.suggestions.map((suggestion) => [\n suggestion.property,\n suggestion.urlCount,\n suggestion.currentProperty,\n countLabel(suggestion.estimatedCycleDays, 'day'),\n suggestion.reason,\n ]),\n )\n }\n if (report.warnings.length) {\n process.stdout.write('\\nWarnings\\n')\n for (const warning of report.warnings.slice(0, 10)) {\n process.stdout.write(`- ${warning}\\n`)\n }\n }\n return\n }\n\n if (sitemaps.length) {\n const report = await indexMonitor({\n site,\n sitemaps,\n properties: listArg(args.properties).length\n ? listArg(args.properties)\n : undefined,\n dailyLimit: numberArg(args['daily-limit']),\n inspectLimit: numberArg(args['inspect-limit']),\n maxUrls: numberArg(args['max-urls']),\n languageCode: stringArg(args.language),\n })\n if (json) {\n printJson(report)\n return\n }\n printKeyValue([\n ['Project site', report.site],\n ['Discovered sitemap URLs', String(report.source.discoveredUrls)],\n ['Invalid sitemap URLs', String(report.source.invalidUrls)],\n ['Inventory URLs', String(report.summary.inventoryUrls)],\n ['Properties used', String(report.summary.properties)],\n ['Daily capacity', String(report.summary.dailyCapacity)],\n ['Never attempted', String(report.summary.neverAttempted)],\n ['Never succeeded', String(report.summary.neverSucceeded)],\n ['Retry waiting', String(report.summary.retryWaiting)],\n ['Fresh', String(report.summary.fresh)],\n ['Stale', String(report.summary.stale)],\n ['Due', String(report.summary.due)],\n ['Selected this run', String(report.summary.selected)],\n ['Due but not selected', String(report.summary.unselectedDue)],\n ['Attempted', String(report.summary.attempted)],\n ['Inspected', String(report.summary.inspected)],\n ['Failed', String(report.summary.failed)],\n ['Quota blocked', String(report.summary.quotaBlocked)],\n ['Deferred', String(report.summary.deferred)],\n ['Current reviews', String(report.summary.currentIssues)],\n ['Regressions', String(report.summary.regressions)],\n ['Recoveries', String(report.summary.recoveries)],\n ['Changed', String(report.summary.changed)],\n ['New alerts', String(report.summary.alerts)],\n ['Skipped', String(report.summary.skipped)],\n ])\n if (report.properties.length) {\n printTable(\n [\n 'Property',\n 'Inventory',\n 'Selected',\n 'Inspected',\n 'Failed',\n 'Current',\n 'Alerts',\n ],\n report.properties.map((property) => [\n property.property,\n property.inventoryUrls,\n property.selectedUrls,\n property.inspected,\n property.failed + property.quotaBlocked,\n property.currentIssues,\n property.alerts,\n ]),\n )\n }\n const issueItems = report.items\n .filter(\n (item) =>\n item.currentIssue ||\n item.changed ||\n item.inspectionStatus !== 'succeeded',\n )\n .slice(0, 50)\n if (issueItems.length) {\n process.stdout.write('\\nIndex reviews, changes, and failed checks\\n')\n printTable(\n ['Check', 'Change', 'Index state', 'Evidence', 'URL'],\n issueItems.map((item) => [\n item.inspectionStatus,\n item.changeKind,\n item.indexStatus,\n (item.errorCode ?? item.issueCodes.join(', ')) || 'none',\n item.url,\n ]),\n )\n }\n if (report.warnings.length) {\n process.stdout.write('\\nWarnings\\n')\n for (const warning of report.warnings.slice(0, 10)) {\n process.stdout.write(`- ${warning}\\n`)\n }\n }\n return\n }\n\n if (!urls.length) throw new Error('Pass at least one URL with --urls.')\n\n const report = await indexWatch({\n site,\n urls,\n languageCode: stringArg(args.language),\n dailyLimit: numberArg(args['daily-limit']),\n })\n if (json) {\n printJson(report)\n return\n }\n printKeyValue([\n ['Project site', report.site],\n ['Inspection property', report.source.property],\n ['Attempted', String(report.summary.attempted)],\n ['Inspected', String(report.summary.inspected)],\n ['Failed', String(report.summary.failed)],\n ['Quota blocked', String(report.summary.quotaBlocked)],\n ['Deferred', String(report.summary.deferred)],\n ['Current reviews', String(report.summary.currentIssues)],\n ['Regressions', String(report.summary.regressions)],\n ['Recoveries', String(report.summary.recoveries)],\n ['Changed', String(report.summary.changed)],\n ['New alerts', String(report.summary.alerts)],\n ])\n printTable(\n ['Check', 'Change', 'Index state', 'Evidence', 'URL'],\n report.items.map((item) => [\n item.inspectionStatus,\n item.changeKind,\n item.indexStatus,\n (item.errorCode ?? item.issueCodes.join(', ')) || 'none',\n item.url,\n ]),\n )\n },\n})\n","import { linkRecover } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n jsonFlag,\n numberArg,\n projectArg,\n stringArg,\n} from '../../args.js'\nimport { printJson, printKeyValue } from '../../utils.js'\nimport {\n formatCount,\n printActionDetails,\n printLimitedTable,\n truncate,\n} from '../output.js'\nimport { cliReportArgs } from '../report-options.js'\nimport { selectedSiteOrThrow } from '../shared.js'\n\nexport const linkRecoverCommand = defineCommand({\n meta: {\n name: 'link-recover',\n description:\n 'Find search-value URLs that are now broken, blocked, or poorly redirected',\n },\n args: {\n site: { type: 'string' },\n project: { type: 'string', description: 'Saved project id or name.' },\n client: { type: 'string', description: 'Legacy alias for --project.' },\n ...cliReportArgs(['days', 'limit', 'minImpressions', 'refresh', 'js'], {\n days: {\n description: 'GSC lookback window. Defaults to 90.',\n },\n limit: {\n description: 'Maximum GSC pages to check. Defaults to 50.',\n },\n minImpressions: {\n description: 'Minimum impressions to check a page. Defaults to 100.',\n },\n refresh: {\n description: 'Bypass local GSC and HTTP caches.',\n },\n js: {\n description: 'Force JavaScript rendering for final page extraction.',\n },\n }),\n 'min-clicks': {\n type: 'string',\n description: 'Minimum clicks to check a page. Defaults to 1.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const report = await linkRecover({\n site: await selectedSiteOrThrow(\n { client: projectArg(args), site: stringArg(args.site) },\n { json },\n ),\n days: numberArg(args.days),\n limit: numberArg(args.limit),\n minClicks: numberArg(args['min-clicks']),\n minImpressions: numberArg(args['min-impressions']),\n refresh: booleanArg(args.refresh),\n js: booleanArg(args.js) ? true : 'auto',\n })\n if (json) {\n printJson(report)\n return\n }\n\n printKeyValue([\n ['Site', report.site],\n ['Range', `${report.range.startDate} to ${report.range.endDate}`],\n ['Checked', formatCount(report.summary.checked)],\n ['Recoverable', formatCount(report.summary.recoverable)],\n ['High severity', formatCount(report.summary.high)],\n ['Clicks at risk', formatCount(report.summary.clicksAtRisk)],\n ['Impressions at risk', formatCount(report.summary.impressionsAtRisk)],\n ])\n if (report.items.length) {\n printLimitedTable(\n ['Severity', 'Issue', 'Clicks', 'Impr', 'URL', 'Action'],\n report.items.map((item) => [\n item.severity,\n item.issue,\n formatCount(item.clicks),\n formatCount(item.impressions),\n truncate(item.url, 56),\n truncate(item.recommendation.action, 72),\n ]),\n )\n printActionDetails(\n 'Top recovery actions',\n report.items.map((item) => ({\n label: truncate(item.url, 96),\n context: `${item.severity}, ${formatCount(item.clicks)} clicks at risk`,\n action: item.recommendation.action,\n })),\n )\n }\n if (report.warnings.length) {\n process.stdout.write('\\nWarnings\\n')\n for (const warning of report.warnings.slice(0, 10)) {\n process.stdout.write(`- ${warning}\\n`)\n }\n }\n },\n})\n","import { redirectTrace } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { booleanArg, jsonFlag, numberArg, stringArg } from '../../args.js'\nimport { printJson, printKeyValue, printTable } from '../../utils.js'\nimport { truncate } from '../output.js'\n\nexport const redirectTraceCommand = defineCommand({\n meta: {\n name: 'redirect-trace',\n description:\n 'Trace redirects and report final indexability/canonical issues',\n },\n args: {\n url: {\n type: 'string',\n required: true,\n description: 'URL to trace.',\n },\n 'max-hops': {\n type: 'string',\n description: 'Maximum redirect hops to follow. Defaults to 10.',\n },\n refresh: {\n type: 'boolean',\n default: false,\n description: 'Bypass local HTTP cache for final page extraction.',\n },\n js: {\n type: 'boolean',\n default: false,\n description: 'Force JavaScript rendering for final page extraction.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const report = await redirectTrace({\n url: stringArg(args.url) ?? '',\n maxHops: numberArg(args['max-hops']),\n refresh: booleanArg(args.refresh),\n js: booleanArg(args.js) ? true : 'auto',\n })\n if (jsonFlag(args)) {\n printJson(report)\n return\n }\n\n printKeyValue([\n ['URL', report.url],\n ['Final URL', report.finalUrl],\n ['Final status', String(report.summary.finalStatus)],\n [\n 'Indexable',\n report.summary.finalIndexable === undefined\n ? 'unknown'\n : report.summary.finalIndexable\n ? 'yes'\n : 'no',\n ],\n ['Hops', String(report.summary.hops)],\n [\n 'Issues',\n report.summary.issues.length\n ? report.summary.issues.join(', ')\n : 'none',\n ],\n ])\n printTable(\n ['#', 'Status', 'URL', 'Next'],\n report.chain.map((step, index) => [\n index + 1,\n step.status,\n truncate(step.url, 72),\n truncate(step.nextUrl ?? '-', 72),\n ]),\n )\n if (report.finalPage) {\n process.stdout.write('\\nFinal page\\n')\n printKeyValue([\n ['Title', report.finalPage.title ?? '-'],\n ['Canonical', report.finalPage.canonical ?? '-'],\n ['Meta robots', report.finalPage.metaRobots ?? '-'],\n ])\n }\n if (report.warnings.length) {\n process.stdout.write('\\nWarnings\\n')\n for (const warning of report.warnings.slice(0, 10)) {\n process.stdout.write(`- ${warning}\\n`)\n }\n }\n },\n})\n","import {\n buildOkfBundle,\n explainOkfValidation,\n okfConceptLimit,\n validateOkfFiles,\n} from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { jsonFlag, strictNumberArg, stringArg } from '../args.js'\nimport { printJson, printKeyValue, printTable } from '../utils.js'\nimport { readOkfMarkdownFiles, writeOkfDirectory } from './okf-files.js'\nimport { resolveSavedCrawlReport } from './readiness.js'\n\nfunction printValidation(\n filesPath: string,\n validation: ReturnType<typeof validateOkfFiles>,\n) {\n process.stdout.write(`OKF validation for ${filesPath}\\n\\n`)\n printKeyValue([\n ['Valid', validation.valid ? 'yes' : 'no'],\n ['Files', String(validation.files)],\n ['Concepts', String(validation.concepts)],\n [\n 'Errors',\n String(\n validation.issues.filter((issue) => issue.severity === 'error').length,\n ),\n ],\n [\n 'Warnings',\n String(\n validation.issues.filter((issue) => issue.severity === 'warning')\n .length,\n ),\n ],\n ])\n if (validation.issues.length) {\n process.stdout.write('\\nIssues\\n')\n printTable(\n ['Severity', 'Path', 'Message'],\n validation.issues\n .slice(0, 25)\n .map((issue) => [issue.severity, issue.path, issue.message]),\n )\n }\n}\n\nexport const okfExportCommand = defineCommand({\n meta: {\n name: 'export',\n description: 'Export a saved crawl as an OKF bundle',\n },\n args: {\n 'report-id': {\n type: 'string',\n description: 'Saved crawl report id to export.',\n },\n site: {\n type: 'string',\n description: 'GSC property URL for selecting the latest saved crawl.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n output: {\n type: 'string',\n description: 'Output directory. Defaults to ./okf.',\n },\n 'max-concepts': {\n type: 'string',\n description: 'Maximum concept files to export. Defaults to 500.',\n },\n title: {\n type: 'string',\n description: 'Override the root bundle title.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const maxConcepts = okfConceptLimit(\n strictNumberArg(args['max-concepts'], '--max-concepts'),\n )\n const report = await resolveSavedCrawlReport(args, { json })\n const bundle = buildOkfBundle(report, {\n maxConcepts,\n title: stringArg(args.title),\n })\n const output = stringArg(args.output) ?? './okf'\n const validation = await writeOkfDirectory(output, bundle.files)\n if (json) {\n printJson({ output, bundle, validation })\n return\n }\n process.stdout.write(`Wrote OKF bundle to ${output}\\n\\n`)\n printKeyValue([\n ['Files', String(bundle.files.length)],\n ['Concepts', String(bundle.conceptCount)],\n ['Valid', validation.valid ? 'yes' : 'no'],\n ])\n },\n})\n\nexport const okfValidateCommand = defineCommand({\n meta: {\n name: 'validate',\n description: 'Validate an OKF bundle directory',\n },\n args: {\n path: {\n type: 'positional',\n required: true,\n description: 'OKF bundle directory.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const path = stringArg(args.path)\n if (!path) throw new Error('Pass an OKF bundle directory.')\n const files = await readOkfMarkdownFiles(path)\n const validation = validateOkfFiles(files)\n if (!validation.valid) process.exitCode = 1\n if (jsonFlag(args)) {\n printJson(validation)\n return\n }\n printValidation(path, validation)\n },\n})\n\nexport const okfExplainCommand = defineCommand({\n meta: {\n name: 'explain',\n description: 'Explain OKF validation results in plain English',\n },\n args: {\n path: {\n type: 'positional',\n required: true,\n description: 'OKF bundle directory.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const path = stringArg(args.path)\n if (!path) throw new Error('Pass an OKF bundle directory.')\n const validation = validateOkfFiles(await readOkfMarkdownFiles(path))\n const explanation = explainOkfValidation(validation)\n if (!explanation.valid) process.exitCode = 1\n if (jsonFlag(args)) {\n printJson(explanation)\n return\n }\n process.stdout.write(`${explanation.summary}\\n\\n`)\n printKeyValue([\n ['Valid', explanation.valid ? 'yes' : 'no'],\n ['Files', String(explanation.files)],\n ['Concepts', String(explanation.concepts)],\n ['Errors', String(explanation.errors)],\n ['Warnings', String(explanation.warnings)],\n ])\n if (explanation.nextActions.length) {\n process.stdout.write('\\nNext actions\\n')\n for (const action of explanation.nextActions) {\n process.stdout.write(`- ${action}\\n`)\n }\n }\n },\n})\n\nexport const okfCommand = defineCommand({\n meta: {\n name: 'okf',\n description: 'Export, validate, and explain OKF site knowledge bundles',\n },\n subCommands: {\n export: okfExportCommand,\n validate: okfValidateCommand,\n explain: okfExplainCommand,\n },\n})\n","import { aiReferralsReport } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { jsonFlag, projectArg, strictNumberArg, stringArg } from '../../args.js'\nimport { resolveClient, resolveGa4Property } from '../../selection.js'\nimport { printJson, printKeyValue } from '../../utils.js'\nimport {\n formatCount,\n formatPercent,\n printLimitedTable,\n truncate,\n} from '../output.js'\n\nexport const aiReferralsCommand = defineCommand({\n meta: {\n name: 'ai-referrals',\n description: 'Find AI referral traffic detected in GA4',\n },\n args: {\n property: {\n type: 'string',\n description: 'GA4 property ID. If omitted in a terminal, choose one.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name with an optional GA4 property.',\n },\n 'start-date': { type: 'string', default: '28daysAgo' },\n 'end-date': { type: 'string', default: 'yesterday' },\n 'max-rows': {\n type: 'string',\n description: 'Maximum GA4 rows per query. Defaults to 100000.',\n },\n 'result-limit': {\n type: 'string',\n description: 'Maximum ranked landing pages returned. Defaults to 25.',\n },\n limit: {\n type: 'string',\n description: 'Legacy alias for --max-rows.',\n },\n refresh: {\n type: 'boolean',\n default: false,\n description: 'Bypass cached GA4 responses.',\n },\n json: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const client = await resolveClient({\n client: projectArg(args),\n options: { json },\n })\n const property = await resolveGa4Property({\n property: stringArg(args.property) ?? client?.ga4PropertyId,\n options: { json },\n })\n const report = await aiReferralsReport({\n property,\n startDate: stringArg(args['start-date']),\n endDate: stringArg(args['end-date']),\n maxRows: strictNumberArg(args['max-rows'], '--max-rows'),\n resultLimit: strictNumberArg(args['result-limit'], '--result-limit'),\n limit: strictNumberArg(args.limit, '--limit'),\n refresh: args.refresh === true,\n })\n\n if (json) {\n printJson(report)\n return\n }\n\n printKeyValue([\n ['Property', report.property],\n ['Evidence', report.dataStatus === 'complete' ? 'Complete' : 'Partial'],\n ['Verdict', report.summary.verdict],\n ['AI sessions', formatCount(report.summary.sessions)],\n [\n 'AI users',\n report.summary.totalUsers === null\n ? 'Unavailable'\n : formatCount(report.summary.totalUsers),\n ],\n ['Sources', formatCount(report.summary.sources)],\n ['Landing pages', formatCount(report.summary.landingPages)],\n [\n 'Landing-page output',\n `${formatCount(report.selection.landingPages.returnedRows)} returned / ${formatCount(report.selection.landingPages.retainedRows)} retained`,\n ],\n [\n 'Source rows',\n formatCount(report.dataSource.sourceDiscovery.returnedRows),\n ],\n ])\n\n if (report.sources.length) {\n process.stdout.write('\\nAI sources\\n')\n printLimitedTable(\n ['Source', 'Sessions', 'Events', 'Share of AI sessions'],\n report.sources.map((source) => [\n source.label,\n formatCount(source.sessions),\n formatCount(source.eventCount),\n formatPercent(source.shareOfAiSessions),\n ]),\n )\n }\n\n if (report.landingPages.length) {\n process.stdout.write('\\nLanding pages\\n')\n printLimitedTable(\n ['Landing page', 'Sessions', 'Events', 'Top source'],\n report.landingPages.map((page) => [\n truncate(page.landingPage, 64),\n formatCount(page.sessions),\n formatCount(page.eventCount),\n page.topSourceDetails.label,\n ]),\n )\n }\n\n if (report.dataSource.partialReasons.length) {\n process.stdout.write('\\nEvidence warnings\\n')\n for (const warning of report.dataSource.partialReasons) {\n process.stdout.write(`- ${warning}\\n`)\n }\n }\n\n process.stdout.write(`\\nNote: ${report.summary.caveat}\\n`)\n },\n})\n","import { cannibalReport } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n csvArg,\n jsonFlag,\n projectArg,\n strictNumberArg,\n stringArg,\n} from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson, printKeyValue } from '../../utils.js'\nimport {\n formatCount,\n printActionDetails,\n printLimitedTable,\n printNotes,\n truncate,\n} from '../output.js'\nimport { cliReportArgs } from '../report-options.js'\n\nexport const cannibalCommand = defineCommand({\n meta: {\n name: 'cannibal',\n description: 'Find queries with material exposure across multiple URLs',\n },\n args: {\n site: { type: 'string' },\n project: { type: 'string', description: 'Saved project id or name.' },\n client: { type: 'string', description: 'Legacy alias for --project.' },\n ...cliReportArgs(\n ['days', 'limit', 'includeBrand', 'minImpressions', 'refresh'],\n {\n minImpressions: {\n description: 'Minimum query impressions. Defaults to 50.',\n },\n },\n ),\n 'brand-terms': {\n type: 'string',\n description: 'Comma-separated brand terms to exclude.',\n },\n json: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const refresh = booleanArg(args.refresh)\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json, refresh },\n })\n const report = await cannibalReport({\n site: selection.site,\n days: strictNumberArg(args.days, '--days'),\n limit: strictNumberArg(args.limit, '--limit'),\n minImpressions: strictNumberArg(\n args['min-impressions'],\n '--min-impressions',\n ),\n brandTerms: [\n ...(selection.client?.brandTerms ?? []),\n ...(csvArg(args['brand-terms']) ?? []),\n ],\n includeBrand: booleanArg(args['include-brand']),\n refresh,\n })\n if (json) {\n printJson(report)\n return\n }\n printKeyValue([\n ['Site', report.site],\n ['Status', report.dataStatus],\n ['Range', `${report.range.startDate} to ${report.range.endDate}`],\n ['Eligible candidates', formatCount(report.summary.eligibleClusters)],\n ['Returned candidates', formatCount(report.summary.returnedClusters)],\n [\n 'Suppressed brand queries',\n formatCount(report.summary.suppressedQueries),\n ],\n ['GSC completeness', report.source.completeness],\n [\n 'Brand queries',\n booleanArg(args['include-brand']) ? 'included' : 'excluded',\n ],\n ['Verdict', report.summary.verdict],\n ])\n printLimitedTable(\n ['Query', 'URLs', 'Property impr', 'Exposure', 'HHI', 'Review first'],\n report.items.map((item) => [\n truncate(item.query, 42),\n item.pages.length,\n item.propertyImpressions === undefined\n ? 'n/a'\n : formatCount(item.propertyImpressions),\n formatCount(item.pageExposureImpressions),\n item.hhi.toFixed(2),\n truncate(item.suggestedOwnerUrl, 56),\n ]),\n )\n printActionDetails(\n 'Top cannibalisation actions',\n report.items.map((item) => ({\n label: item.query,\n context: `${item.pages.length} material URLs; first review ${truncate(item.suggestedOwnerUrl, 64)}`,\n action: item.recommendation.action,\n })),\n )\n printNotes('Report caveats', report.caveats)\n printNotes('Provider usage', [report.ledgerSummary])\n },\n})\n","import { communityIntentReport } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n csvArg,\n jsonFlag,\n projectArg,\n strictNumberArg,\n stringArg,\n} from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson, printKeyValue } from '../../utils.js'\nimport {\n formatCount,\n printActionDetails,\n printLimitedTable,\n printNotes,\n truncate,\n} from '../output.js'\nimport { cliReportArgs } from '../report-options.js'\n\nexport const communityIntentCommand = defineCommand({\n meta: {\n name: 'community-intent',\n description: 'Find GSC queries with forum, review, and comparison intent',\n },\n args: {\n site: { type: 'string' },\n project: { type: 'string', description: 'Saved project id or name.' },\n client: { type: 'string', description: 'Legacy alias for --project.' },\n 'start-date': {\n type: 'string',\n description: 'Exact GSC start date (YYYY-MM-DD). Use with --end-date.',\n },\n 'end-date': {\n type: 'string',\n description: 'Exact GSC end date (YYYY-MM-DD). Use with --start-date.',\n },\n 'max-rows': {\n type: 'string',\n description: 'Maximum retained GSC query rows. Defaults to 50000.',\n },\n 'brand-terms': {\n type: 'string',\n description: 'Comma-separated brand terms to exclude.',\n },\n ...cliReportArgs(\n ['days', 'limit', 'minImpressions', 'includeBrand', 'refresh'],\n {\n days: {\n description: 'GSC lookback within the current 16-month retention.',\n },\n limit: {\n description: 'Maximum intent queries to print. Defaults to 25.',\n },\n minImpressions: {\n description: 'Minimum query impressions. Defaults to 20.',\n },\n includeBrand: {\n description: 'Include branded queries in community-intent reports.',\n },\n refresh: { description: 'Bypass local GSC cache.' },\n },\n ),\n json: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json, refresh: booleanArg(args.refresh) },\n })\n const report = await communityIntentReport({\n site: selection.site,\n days: strictNumberArg(args.days, '--days'),\n startDate: stringArg(args['start-date']),\n endDate: stringArg(args['end-date']),\n limit: strictNumberArg(args.limit, '--limit'),\n minImpressions: strictNumberArg(\n args['min-impressions'],\n '--min-impressions',\n ),\n maxRows: strictNumberArg(args['max-rows'], '--max-rows'),\n brandTerms: [\n ...(selection.client?.brandTerms ?? []),\n ...(csvArg(args['brand-terms']) ?? []),\n ],\n includeBrand: booleanArg(args['include-brand']),\n refresh: booleanArg(args.refresh),\n })\n\n if (json) {\n printJson(report)\n return\n }\n\n printKeyValue([\n ['Property', report.site],\n ['Status', report.dataStatus],\n ['Verdict', report.summary.verdict],\n ['Classified queries', formatCount(report.summary.classifiedQueries)],\n ['Returned queries', formatCount(report.summary.returnedQueries)],\n ['Returned impressions', formatCount(report.summary.returnedImpressions)],\n ['Returned clicks', formatCount(report.summary.returnedClicks)],\n ['GSC completeness', report.source.completeness],\n ])\n\n printLimitedTable(\n ['Intent', 'Query', 'Impr', 'Clicks', 'Confidence', 'Action'],\n report.items.map((item) => [\n item.intent,\n truncate(item.query, 42),\n formatCount(item.impressions),\n formatCount(item.clicks),\n item.confidence,\n truncate(item.action, 76),\n ]),\n )\n printActionDetails(\n 'Top community-intent actions',\n report.items.map((item) => ({\n label: item.query,\n context: `${item.intent}, ${formatCount(item.impressions)} impressions`,\n action: item.action,\n })),\n )\n printNotes('Report caveats', report.caveats)\n printNotes('Warnings', report.warnings)\n },\n})\n","import { ctrUnderperformersReport } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n jsonFlag,\n numberArg,\n projectArg,\n stringArg,\n} from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson, printKeyValue } from '../../utils.js'\nimport {\n formatCount,\n formatPercent,\n formatPosition,\n printActionDetails,\n printLimitedTable,\n printNotes,\n truncate,\n} from '../output.js'\nimport { cliReportArgs } from '../report-options.js'\n\nexport const ctrUnderperformersCommand = defineCommand({\n meta: {\n name: 'ctr-underperformers',\n description:\n 'Find high-impression queries with weak CTR for their position',\n },\n args: {\n site: { type: 'string' },\n project: { type: 'string', description: 'Saved project id or name.' },\n client: { type: 'string', description: 'Legacy alias for --project.' },\n ...cliReportArgs(['includeBrand', 'minImpressions'], {\n minImpressions: {\n description: 'Minimum query impressions. Defaults to 200.',\n },\n }),\n json: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json },\n })\n const report = await ctrUnderperformersReport({\n site: selection.site,\n minImpressions: numberArg(args['min-impressions']),\n brandTerms: selection.client?.brandTerms,\n includeBrand: booleanArg(args['include-brand']),\n })\n if (json) {\n printJson(report)\n return\n }\n printKeyValue([\n ['Site', report.site],\n ['Underperformers', formatCount(report.summary.underperformers)],\n [\n 'Estimated click gap',\n formatCount(report.summary.estimatedClickShortfall),\n ],\n ['Brand queries', report.summary.brandFiltering],\n ['Verdict', report.summary.verdict],\n ])\n printNotes('Why this matters', [\n 'These queries already have visibility; the fastest win is usually better SERP framing, not new content.',\n 'Start with high-impression rows where actual CTR is far below the expected CTR for that ranking position.',\n ])\n printNotes('Recommended actions', report.recommendations)\n printNotes('Report caveats', report.caveats)\n printLimitedTable(\n ['Query', 'URL', 'Pos', 'Impr', 'CTR', 'Expected', 'Gap', 'Action'],\n report.items.map((item) => [\n truncate(item.query, 36),\n truncate(item.url, 48),\n formatPosition(item.position),\n formatCount(item.impressions),\n formatPercent(item.actualCtr),\n formatPercent(item.expectedCtr),\n formatCount(item.clickShortfall),\n truncate(item.recommendation.action, 72),\n ]),\n )\n printActionDetails(\n 'Top CTR actions',\n report.items.map((item) => ({\n label: item.query,\n context: `${formatCount(item.clickShortfall)} click gap, ${formatPercent(item.actualCtr)} CTR`,\n action: item.recommendation.action,\n })),\n )\n },\n})\n","import { decayingReport, SeoError } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n csvArg,\n jsonFlag,\n projectArg,\n strictNumberArg,\n stringArg,\n} from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson, printKeyValue } from '../../utils.js'\nimport {\n formatCount,\n formatPercent,\n formatPosition,\n printActionDetails,\n printLimitedTable,\n printNotes,\n truncate,\n} from '../output.js'\nimport { cliReportArgs } from '../report-options.js'\n\nfunction formatMaybePosition(value: number): string {\n return value > 0 ? formatPosition(value) : 'n/a'\n}\n\nexport const decayingCommand = defineCommand({\n meta: {\n name: 'decaying',\n description: 'Find query/page rows losing clicks between two GSC windows',\n },\n args: {\n site: { type: 'string' },\n project: { type: 'string', description: 'Saved project id or name.' },\n client: { type: 'string', description: 'Legacy alias for --project.' },\n ...cliReportArgs(['days', 'limit', 'includeBrand', 'refresh']),\n comparison: {\n type: 'string',\n description: 'Comparison: previous-period or year-over-year.',\n },\n 'brand-terms': {\n type: 'string',\n description: 'Comma-separated brand terms to exclude.',\n },\n 'min-drop-pct': {\n type: 'string',\n description: 'Minimum click drop percentage. Defaults to 20.',\n },\n 'min-previous-clicks': {\n type: 'string',\n description:\n 'Minimum previous-window clicks for a query/page row. Defaults to 2.',\n },\n 'min-click-loss': {\n type: 'string',\n description: 'Minimum absolute click loss. Defaults to 1.',\n },\n json: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const refresh = booleanArg(args.refresh)\n const comparison = stringArg(args.comparison)\n const days = strictNumberArg(args.days, '--days')\n const limit = strictNumberArg(args.limit, '--limit')\n const minDropPct = strictNumberArg(args['min-drop-pct'], '--min-drop-pct')\n const minPreviousClicks = strictNumberArg(\n args['min-previous-clicks'],\n '--min-previous-clicks',\n )\n const minClickLoss = strictNumberArg(\n args['min-click-loss'],\n '--min-click-loss',\n )\n if (\n comparison !== undefined &&\n comparison !== 'previous-period' &&\n comparison !== 'year-over-year'\n ) {\n throw new SeoError(\n 'INVALID_INPUT',\n '--comparison must be previous-period or year-over-year.',\n )\n }\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json, refresh },\n })\n const report = await decayingReport({\n site: selection.site,\n days,\n limit,\n comparison,\n brandTerms: [\n ...(selection.client?.brandTerms ?? []),\n ...(csvArg(args['brand-terms']) ?? []),\n ],\n includeBrand: booleanArg(args['include-brand']),\n minDropPct,\n minPreviousClicks,\n minClickLoss,\n refresh,\n })\n if (json) {\n printJson(report)\n return\n }\n printKeyValue([\n ['Site', report.site],\n ['Status', report.dataStatus],\n ['Comparison', report.comparison],\n [\n 'Observed query/page declines',\n formatCount(report.summary.returnedRows),\n ],\n ['Eligible declines', formatCount(report.summary.eligibleRows)],\n ['Decay clusters', formatCount(report.summary.groups)],\n [\n 'Eligible observed click decline',\n formatCount(report.summary.observedRetainedQueryClickLoss),\n ],\n [\n 'Returned observed click decline',\n formatCount(report.summary.returnedObservedRetainedQueryClickLoss),\n ],\n ['Brand queries', report.summary.brandFiltering],\n ['Min drop', `${report.filters.minDropPct}%`],\n ['Min previous clicks', formatCount(report.filters.minPreviousClicks)],\n ['GSC completeness', report.source.completeness],\n ['Verdict', report.summary.verdict],\n ])\n printNotes('Why this matters', [\n 'This report compares retained query/page rows and only counts declines observed in both windows.',\n 'Position, CTR, and impression movements are signals for investigation, not proof of cause.',\n ])\n printNotes('Recommended actions', report.recommendations)\n printNotes('Report caveats', report.caveats)\n printNotes('Warnings', report.warnings)\n\n if (!report.items.length) {\n return\n }\n\n if (report.groups.length) {\n printLimitedTable(\n ['Cluster', 'Rows', 'Observed loss', 'Drop', 'Sample query', 'Action'],\n report.groups.map((group) => [\n truncate(group.label, 42),\n formatCount(group.count),\n formatCount(group.totalClickLoss),\n `${group.averageDropPct.toFixed(1)}%`,\n truncate(group.sampleQueries[0] ?? '-', 40),\n truncate(group.recommendation, 72),\n ]),\n )\n printActionDetails(\n 'Top decay cluster actions',\n report.groups.map((group) => ({\n label: group.label,\n context: `${formatCount(group.count)} retained rows, ${formatCount(group.totalClickLoss)} observed click decline`,\n action: group.recommendation,\n })),\n )\n }\n\n printLimitedTable(\n [\n 'Query',\n 'Template',\n 'URL',\n 'Signals',\n 'Decline',\n 'Clicks',\n 'Impr',\n 'CTR',\n 'Pos',\n 'Action',\n ],\n report.items.map((item) => [\n truncate(item.query, 32),\n truncate(item.template.label, 26),\n truncate(item.url, 44),\n item.signals.join(', '),\n formatCount(item.clickLoss),\n `${formatCount(item.previous.clicks)} -> ${formatCount(item.current.clicks)}`,\n `${formatCount(item.previous.impressions)} -> ${formatCount(item.current.impressions)}`,\n `${formatPercent(item.previous.ctr)} -> ${formatPercent(item.current.ctr)}`,\n `${formatMaybePosition(item.previous.position)} -> ${formatMaybePosition(item.current.position)}`,\n truncate(item.recommendation.action, 64),\n ]),\n )\n printActionDetails(\n 'Top decay actions',\n report.items.map((item) => ({\n label: item.query,\n context: `${item.template.label}, ${formatCount(item.clickLoss)} fewer observed clicks`,\n action: item.recommendation.action,\n })),\n )\n },\n})\n","import { internalLinksReport } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n csvArg,\n jsonFlag,\n projectArg,\n strictFetchRateArg,\n strictNumberArg,\n stringArg,\n} from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson, printKeyValue } from '../../utils.js'\nimport {\n formatCount,\n printActionDetails,\n printLimitedTable,\n printNotes,\n truncate,\n} from '../output.js'\nimport { cliReportArgs } from '../report-options.js'\n\nexport const internalLinksCommand = defineCommand({\n meta: {\n name: 'internal-links',\n description: 'Find verified internal-link review candidates for one URL',\n },\n args: {\n site: {\n type: 'string',\n description: 'GSC property URL, for example sc-domain:example.com.',\n },\n project: { type: 'string', description: 'Saved project id or name.' },\n client: { type: 'string', description: 'Legacy alias for --project.' },\n url: {\n type: 'string',\n required: true,\n description: 'Target page that should receive relevant internal links.',\n },\n ...cliReportArgs([\n 'days',\n 'limit',\n 'checkLimit',\n 'minImpressions',\n 'includeBrand',\n 'js',\n 'fetchConcurrency',\n 'fetchIntervalCap',\n 'fetchIntervalMs',\n 'refresh',\n ]),\n 'brand-terms': {\n type: 'string',\n description: 'Comma-separated brand terms to exclude.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const refresh = booleanArg(args.refresh)\n const days = strictNumberArg(args.days, '--days')\n const limit = strictNumberArg(args.limit, '--limit')\n const checkLimit = strictNumberArg(args['check-limit'], '--check-limit')\n const minImpressions = strictNumberArg(\n args['min-impressions'],\n '--min-impressions',\n )\n const rate = strictFetchRateArg(args)\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json, refresh },\n })\n const report = await internalLinksReport({\n site: selection.site,\n targetUrl: stringArg(args.url) ?? '',\n days,\n limit,\n checkLimit,\n minImpressions,\n brandTerms: [\n ...(selection.client?.brandTerms ?? []),\n ...(csvArg(args['brand-terms']) ?? []),\n ],\n includeBrand: booleanArg(args['include-brand']),\n js: booleanArg(args.js) ? true : undefined,\n rate,\n refresh,\n })\n if (json) {\n printJson(report)\n return\n }\n\n printKeyValue([\n ['Site', report.site],\n ['Target', report.targetUrl],\n ['Preferred target', report.target.preferredUrl],\n ['Target state', report.target.verification],\n ['Target queries', formatCount(report.summary.targetQueries)],\n ['Matched sources', formatCount(report.summary.candidateSources)],\n ['Attempted sources', formatCount(report.summary.attemptedSources)],\n ['Checked sources', formatCount(report.summary.checkedSources)],\n ['Review candidates', formatCount(report.summary.returnedSources)],\n [\n 'Existing contextual links',\n formatCount(report.summary.existingLinksObserved),\n ],\n ['Technical exclusions', formatCount(report.summary.technicalExclusions)],\n ['Failed checks', formatCount(report.summary.failedChecks)],\n ['Unchecked sources', formatCount(report.summary.uncheckedCandidates)],\n ['GSC completeness', report.source.completeness],\n ['Brand queries', report.summary.brandFiltering],\n ['Verdict', report.summary.verdict],\n ])\n printNotes('Why this matters', [\n 'Exact-query overlap is useful affinity evidence; precision lexical matches are review evidence only.',\n 'Source and target pages are checked for redirects, indexability, canonicals, and existing link placement before an action is returned.',\n ])\n printNotes('Recommended actions', report.recommendations)\n printNotes('Report caveats', report.caveats)\n if (!report.items.length) return\n\n printLimitedTable(\n ['Source URL', 'Matched impr', 'Match', 'Link evidence', 'Action'],\n report.items.map((item) => [\n truncate(item.sourceUrl, 52),\n formatCount(item.matchedQueryImpressions),\n item.bestMatchKind,\n item.linkEvidence.status,\n item.actionType,\n ]),\n )\n printActionDetails(\n 'Top internal-link reviews',\n report.items.map((item) => ({\n label: truncate(item.sourceUrl, 96),\n context: `${formatCount(item.matchedQueryImpressions)} matched-query impressions; ${item.bestMatchKind}`,\n action: item.recommendation.action,\n })),\n )\n printNotes('Provider usage', [report.ledgerSummary])\n },\n})\n","import { pageOpportunitiesReport } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n defaultTrueBooleanArg,\n jsonFlag,\n numberArg,\n projectArg,\n stringArg,\n} from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson, printKeyValue } from '../../utils.js'\nimport {\n formatCount,\n formatPercent,\n printActionDetails,\n printLimitedTable,\n printNotes,\n truncate,\n} from '../output.js'\nimport { cliReportArgs } from '../report-options.js'\nimport { formatFetchDiagnostics } from '../shared.js'\n\nexport const pageOpportunitiesCommand = defineCommand({\n meta: {\n name: 'page-opportunities',\n description: 'Find first-party traffic growth opportunities for one URL',\n },\n args: {\n site: { type: 'string' },\n project: { type: 'string', description: 'Saved project id or name.' },\n client: { type: 'string', description: 'Legacy alias for --project.' },\n url: { type: 'string', required: true },\n ...cliReportArgs(\n ['days', 'limit', 'minImpressions', 'includeBrand', 'js', 'refresh'],\n {\n limit: {\n description: 'Maximum page queries to inspect. Defaults to 25.',\n },\n minImpressions: {\n description: 'Minimum query impressions. Defaults to 10.',\n },\n includeBrand: {\n description: 'Include branded queries in page opportunity reports.',\n },\n js: {\n description: 'Force JavaScript rendering for page extraction.',\n },\n refresh: {\n description: 'Bypass local GSC and HTTP cache.',\n },\n },\n ),\n 'verify-content': defaultTrueBooleanArg(\n 'Fetch the page for title/H1/body checks. Defaults to true.',\n 'Skip fetching the page for title/H1/body checks.',\n ),\n json: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json, refresh: booleanArg(args.refresh) },\n })\n const report = await pageOpportunitiesReport({\n site: selection.site,\n url: stringArg(args.url) ?? '',\n days: numberArg(args.days),\n limit: numberArg(args.limit),\n minImpressions: numberArg(args['min-impressions']),\n brandTerms: selection.client?.brandTerms,\n includeBrand: booleanArg(args['include-brand']),\n verifyContent: booleanArg(args['verify-content']) !== false,\n js: booleanArg(args.js) ? true : 'auto',\n refresh: booleanArg(args.refresh),\n })\n\n if (json) {\n printJson(report)\n return\n }\n\n printKeyValue([\n ['Property', report.site],\n ['URL', report.url],\n ['Title', report.page?.title ?? 'not fetched'],\n ['Fetch', formatFetchDiagnostics(report.page?.fetchDiagnostics)],\n ['Verification', report.verification.status],\n [\n 'Rows',\n `${formatCount(report.selection.returnedRows)} returned / ${formatCount(report.selection.eligibleRows)} eligible / ${formatCount(report.selection.sourceRows)} source`,\n ],\n ['Queries', formatCount(report.summary.queries)],\n ['Impressions', formatCount(report.summary.impressions)],\n ['Opportunities', formatCount(report.summary.opportunities)],\n ['CTR shortfall', formatCount(report.summary.estimatedCtrClickShortfall)],\n ['Focus', report.summary.focus],\n ['Verdict', report.summary.verdict],\n ])\n printNotes('Why this matters', [\n 'This report starts from queries where this exact URL already has impressions, so recommendations stay tied to first-party demand.',\n 'Content verification separates body gaps from title/meta framing issues, which helps avoid adding copy when the page already covers the query.',\n ])\n printNotes('Recommended actions', report.recommendations)\n printNotes('Report caveats', report.caveats)\n\n if (!report.items.length) {\n process.stdout.write(\n report.dataStatus === 'empty'\n ? 'No GSC query rows found for this exact URL.\\n'\n : 'GSC rows were found, but none met the report criteria.\\n',\n )\n return\n }\n\n printLimitedTable(\n [\n 'Type',\n 'Query',\n 'Evidence',\n 'Pos',\n 'CTR',\n 'Expected',\n 'Impr',\n 'Shortfall',\n 'Action',\n ],\n report.items.map((item) => [\n item.opportunityType,\n truncate(item.query, 38),\n item.verification.signals.length\n ? item.verification.signals.join(', ')\n : item.verification.status,\n item.position.toFixed(1),\n formatPercent(item.ctr),\n item.expectedCtr === undefined\n ? 'n/a'\n : formatPercent(item.expectedCtr),\n formatCount(item.impressions),\n item.estimatedCtrClickShortfall === undefined\n ? 'n/a'\n : formatCount(item.estimatedCtrClickShortfall),\n truncate(item.recommendation, 72),\n ]),\n )\n printActionDetails(\n 'Top page actions',\n report.items.map((item) => ({\n label: item.query,\n context: `${item.opportunityType}, ${formatCount(item.impressions)} impressions`,\n action: item.recommendation,\n })),\n )\n },\n})\n","import { queryClusterReport } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n jsonFlag,\n numberArg,\n projectArg,\n stringArg,\n} from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson, printKeyValue } from '../../utils.js'\nimport {\n formatCount,\n formatPercent,\n printActionDetails,\n printLimitedTable,\n printNotes,\n truncate,\n} from '../output.js'\nimport { cliReportArgs } from '../report-options.js'\n\nexport const queryClusterCommand = defineCommand({\n meta: {\n name: 'query-cluster',\n description: 'Cluster GSC queries into repeated demand themes',\n },\n args: {\n site: { type: 'string' },\n project: { type: 'string', description: 'Saved project id or name.' },\n client: { type: 'string', description: 'Legacy alias for --project.' },\n scope: { type: 'string' },\n ...cliReportArgs(['includeBrand', 'minImpressions', 'limit'], {\n includeBrand: {\n description: 'Include branded queries in query clustering.',\n },\n minImpressions: {\n description: 'Minimum impressions per query. Defaults to 25.',\n },\n limit: {\n description: 'Maximum clusters to return. Defaults to 25; max 100.',\n },\n }),\n json: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json },\n })\n const report = await queryClusterReport({\n site: selection.site,\n scope: stringArg(args.scope),\n brand: selection.client?.brandTerms?.[0],\n brandTerms: selection.client?.brandTerms,\n includeBrand: booleanArg(args['include-brand']),\n minImpressions: numberArg(args['min-impressions']),\n limit: numberArg(args.limit),\n })\n if (json) {\n printJson(report)\n return\n }\n printKeyValue([\n ['Site', report.site],\n ['Scope', report.scope ?? 'all pages'],\n ['Clusters', formatCount(report.summary.clusters)],\n ['Queries', formatCount(report.summary.queries)],\n ['Impressions', formatCount(report.summary.impressions)],\n ['Clicks', formatCount(report.summary.clicks)],\n ['Minimum impressions', formatCount(report.summary.minImpressions)],\n ['Result limit', formatCount(report.summary.limit)],\n ['Brand queries', report.summary.brandFiltering],\n [\n 'High-opportunity clusters',\n formatCount(report.summary.highOpportunityClusters),\n ],\n ['Verdict', report.summary.verdict],\n ])\n printNotes('Why this matters', [\n 'Clusters show repeated demand themes, so they are better inputs for page sections, hubs, and templates than one-off query exports.',\n 'Prioritise clusters with high impressions and low clicks; they usually reveal unclear intent coverage or weak SERP framing.',\n ])\n printNotes('Recommended actions', report.recommendations)\n printNotes('Report caveats', report.caveats)\n printLimitedTable(\n [\n 'Cluster',\n 'Intent',\n 'Queries',\n 'Impr',\n 'CTR',\n 'Expected',\n 'Lift',\n 'Action',\n ],\n report.clusters.map((cluster) => {\n return [\n truncate(cluster.label, 32),\n cluster.intent,\n cluster.queries.length,\n formatCount(cluster.totals?.impressions ?? 0),\n formatPercent(cluster.totals?.ctr ?? 0),\n formatPercent(cluster.benchmark?.expectedCtr ?? 0),\n cluster.estimatedClickLift === undefined\n ? '-'\n : formatCount(cluster.estimatedClickLift),\n truncate(cluster.recommendation ?? '', 72),\n ]\n }),\n )\n printActionDetails(\n 'Top cluster actions',\n report.clusters.map((cluster) => ({\n label: cluster.label,\n context: `${formatCount(cluster.totals?.impressions ?? 0)} impressions, ${cluster.estimatedClickLift === undefined ? 'ranking opportunity' : `${formatCount(cluster.estimatedClickLift)} estimated click lift`}`,\n action: cluster.recommendation ?? '',\n })),\n )\n },\n})\n","import { quickWinsReport } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n csvArg,\n fetchRateArg,\n jsonFlag,\n numberArg,\n projectArg,\n stringArg,\n} from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson, printKeyValue } from '../../utils.js'\nimport {\n formatCount,\n formatPercent,\n formatPosition,\n printActionDetails,\n printLimitedTable,\n printNotes,\n truncate,\n verificationSummary,\n} from '../output.js'\nimport { cliReportArgs } from '../report-options.js'\nimport { formatContentCheck, formatFetchDiagnostics } from '../shared.js'\n\nexport const quickWinsCommand = defineCommand({\n meta: {\n name: 'quick-wins',\n description: 'Find high-ranking low-CTR query/page opportunities',\n },\n args: {\n site: { type: 'string' },\n project: { type: 'string', description: 'Saved project id or name.' },\n client: { type: 'string', description: 'Legacy alias for --project.' },\n ...cliReportArgs([\n 'days',\n 'limit',\n 'includeBrand',\n 'minImpressions',\n 'verifyContent',\n 'verifyLimit',\n 'js',\n 'fetchConcurrency',\n 'fetchIntervalCap',\n 'fetchIntervalMs',\n 'refresh',\n ]),\n 'brand-terms': {\n type: 'string',\n description: 'Comma-separated brand terms to exclude.',\n },\n json: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const verifyLimit = numberArg(args['verify-limit'])\n const verifyContent =\n booleanArg(args['verify-content']) === true || verifyLimit !== undefined\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json },\n })\n const report = await quickWinsReport({\n site: selection.site,\n days: numberArg(args.days),\n limit: numberArg(args.limit),\n minImpressions: numberArg(args['min-impressions']),\n brandTerms: [\n ...(selection.client?.brandTerms ?? []),\n ...(csvArg(args['brand-terms']) ?? []),\n ],\n includeBrand: booleanArg(args['include-brand']),\n verifyContent,\n verifyLimit,\n js: booleanArg(args.js) ? true : undefined,\n rate: fetchRateArg(args),\n refresh: booleanArg(args.refresh),\n })\n if (json) {\n printJson(report)\n return\n }\n printKeyValue([\n ['Site', report.site],\n ['Eligible rows', formatCount(report.summary.eligibleRows)],\n ['Returned rows', formatCount(report.summary.returnedRows)],\n [\n 'Repeated-query clusters',\n formatCount(report.summary.repeatedQueryGroups),\n ],\n ['Template patterns', formatCount(report.summary.templatePatterns)],\n [\n 'CTR click shortfall',\n formatCount(report.summary.returnedEstimatedCtrClickShortfall),\n ],\n ['Brand queries', report.summary.brandFiltering],\n ['Verification', verificationSummary(report)],\n ['Verdict', report.summary.verdict],\n ])\n printNotes('Why this matters', [\n 'These rows have GSC average positions from 4 to 10 and observed CTR below a site-peer or versioned fallback target.',\n 'Page evidence is needed before treating a CTR shortfall as a title, content, or technical finding.',\n ])\n printNotes('Recommended actions', report.recommendations)\n printNotes('Report caveats', report.caveats)\n\n if (!report.items.length) {\n return\n }\n\n if (report.templateRecommendations.length) {\n printLimitedTable(\n ['Template', 'URLs', 'Rows', 'Shortfall', 'Impr', 'Action'],\n report.templateRecommendations.map((template) => [\n truncate(template.templateLabel, 34),\n formatCount(template.urlCount),\n formatCount(template.rowCount),\n formatCount(template.totalEstimatedCtrClickShortfall),\n formatCount(template.totalImpressions),\n truncate(template.action, 72),\n ]),\n )\n printActionDetails(\n 'Top template actions',\n report.templateRecommendations.map((template) => ({\n label: template.templateLabel,\n context: `${formatCount(template.urlCount)} URLs, ${formatCount(template.totalEstimatedCtrClickShortfall)} heuristic CTR click shortfall`,\n action: `${template.action} ${template.evidence}`,\n })),\n )\n }\n\n if (report.groups.length) {\n printLimitedTable(\n [\n 'Cluster',\n 'URLs',\n 'Rows',\n 'Shortfall',\n 'Impr',\n 'Sample URL',\n 'Action',\n ],\n report.groups.map((group) => [\n truncate(group.label, 44),\n formatCount(group.urlCount),\n formatCount(group.rowCount),\n formatCount(group.totalEstimatedCtrClickShortfall),\n formatCount(group.totalImpressions),\n truncate(group.sampleUrls[0] ?? '-', 46),\n truncate(group.recommendation, 72),\n ]),\n )\n printActionDetails(\n 'Top cluster actions',\n report.groups.map((group) => ({\n label: group.label,\n context: `${formatCount(group.urlCount)} URLs, ${formatCount(group.totalEstimatedCtrClickShortfall)} heuristic CTR click shortfall`,\n action: group.recommendation,\n })),\n )\n }\n\n printLimitedTable(\n [\n 'Query',\n 'Template',\n 'URL',\n 'Pos',\n 'Impr',\n 'CTR / target',\n 'Shortfall',\n 'Fetch',\n 'Check',\n 'Action',\n ],\n report.items.map((item) => [\n truncate(item.query, 36),\n truncate(item.template.label, 24),\n truncate(item.url, 48),\n formatPosition(item.position),\n formatCount(item.impressions),\n `${formatPercent(item.ctr)} / ${formatPercent(item.targetCtr)}`,\n formatCount(item.estimatedCtrClickShortfall),\n formatFetchDiagnostics(item.contentVerification?.fetchDiagnostics),\n formatContentCheck(item.contentVerification?.classification),\n truncate(item.recommendation.action, 64),\n ]),\n )\n printActionDetails(\n 'Top opportunity actions',\n report.items.map((item) => ({\n label: item.query,\n context: `${item.template.label}, pos ${formatPosition(item.position)}, ${formatCount(item.impressions)} impressions`,\n action: item.recommendation.action,\n })),\n )\n },\n})\n","import { secondPage } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n fetchRateArg,\n jsonFlag,\n numberArg,\n projectArg,\n stringArg,\n} from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson, printKeyValue } from '../../utils.js'\nimport {\n formatCount,\n formatPosition,\n printActionDetails,\n printLimitedTable,\n printNotes,\n verificationSummary,\n} from '../output.js'\nimport { cliReportArgs } from '../report-options.js'\nimport { formatContentCheck, formatFetchDiagnostics } from '../shared.js'\n\nexport const secondPageCommand = defineCommand({\n meta: {\n name: 'second-page',\n description: 'Find URLs averaging positions above 10 through 20 in GSC',\n },\n args: {\n site: {\n type: 'string',\n description: 'GSC property URL, for example sc-domain:example.com.',\n },\n project: { type: 'string', description: 'Saved project id or name.' },\n client: { type: 'string', description: 'Legacy alias for --project.' },\n ...cliReportArgs([\n 'range',\n 'minImpressions',\n 'limit',\n 'includeBrand',\n 'verifyContent',\n 'verifyLimit',\n 'js',\n 'fetchConcurrency',\n 'fetchIntervalCap',\n 'fetchIntervalMs',\n 'refresh',\n ]),\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const verifyLimit = numberArg(args['verify-limit'])\n const verifyContent =\n booleanArg(args['verify-content']) === true || verifyLimit !== undefined\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json, refresh: booleanArg(args.refresh) },\n })\n const report = await secondPage({\n site: selection.site,\n range: numberArg(args.days),\n minImpressions: numberArg(args['min-impressions']),\n limit: stringArg(args.limit) ? Number(stringArg(args.limit)) : 10,\n brandTerms: selection.client?.brandTerms,\n includeBrand: booleanArg(args['include-brand']),\n verifyContent,\n verifyLimit,\n js: booleanArg(args.js) ? true : undefined,\n rate: fetchRateArg(args),\n refresh: booleanArg(args.refresh),\n })\n if (json) {\n printJson(report)\n return\n }\n printKeyValue([\n ['Site', report.site],\n ['Eligible pages', formatCount(report.summary.eligiblePages)],\n ['Returned pages', formatCount(report.summary.returnedPages)],\n ['Eligible queries', formatCount(report.summary.eligibleQueries)],\n ['Eligible impressions', formatCount(report.summary.eligibleImpressions)],\n ['Content issues', formatCount(report.summary.contentIssues)],\n ['Technical issues', formatCount(report.summary.technicalIssues)],\n ['Fetch failures', formatCount(report.summary.fetchFailures)],\n ['Brand queries', report.summary.brandFiltering],\n ['Verification', verificationSummary(report)],\n ['Verdict', report.summary.verdict],\n ])\n printNotes('Recommended actions', report.recommendations)\n printNotes('Report caveats', report.caveats)\n if (!report.items.length) {\n process.stdout.write(\n 'No average-position candidates matched this report.\\n',\n )\n process.stdout.write(`${report.ledgerSummary}\\n`)\n return\n }\n printLimitedTable(\n [\n 'Query',\n 'Template',\n 'Pos',\n 'Impr',\n 'CTR',\n 'Queries',\n 'Fetch',\n 'Check',\n 'Action',\n ],\n report.items.map((item) => [\n item.primaryQuery,\n item.template.label,\n item.position.toFixed(1),\n Math.round(item.impressions),\n item.ctr.toFixed(3),\n formatCount(item.queryCount),\n formatFetchDiagnostics(item.fetchDiagnostics),\n formatContentCheck(item.contentVerification?.classification),\n item.recommendation.action,\n ]),\n )\n printActionDetails(\n 'Top second-page actions',\n report.items.map((item) => ({\n label: item.primaryQuery,\n context: `${item.template.label}, pos ${formatPosition(item.position)}, ${formatCount(item.impressions)} impressions`,\n action: item.recommendation.action,\n })),\n )\n process.stdout.write(`${report.ledgerSummary}\\n`)\n },\n})\n","import { seoToAiQueryReport } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n csvArg,\n jsonFlag,\n projectArg,\n strictNumberArg,\n stringArg,\n} from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson, printKeyValue } from '../../utils.js'\nimport {\n formatCount,\n printLimitedTable,\n printNotes,\n truncate,\n} from '../output.js'\nimport { cliReportArgs } from '../report-options.js'\n\nexport const seoToAiQueryCommand = defineCommand({\n meta: {\n name: 'seo-to-ai-query',\n description: 'Convert GSC search queries into AI-style monitoring prompts',\n },\n args: {\n site: { type: 'string' },\n project: { type: 'string', description: 'Saved project id or name.' },\n client: { type: 'string', description: 'Legacy alias for --project.' },\n 'start-date': {\n type: 'string',\n description: 'Exact GSC start date (YYYY-MM-DD). Use with --end-date.',\n },\n 'end-date': {\n type: 'string',\n description: 'Exact GSC end date (YYYY-MM-DD). Use with --start-date.',\n },\n 'max-rows': {\n type: 'string',\n description: 'Maximum retained GSC query rows. Defaults to 50000.',\n },\n 'brand-terms': {\n type: 'string',\n description: 'Comma-separated brand terms to exclude.',\n },\n ...cliReportArgs(\n ['days', 'limit', 'minImpressions', 'includeBrand', 'refresh'],\n {\n days: {\n description: 'GSC lookback within the current 16-month retention.',\n },\n limit: {\n description: 'Maximum source queries to convert. Defaults to 25.',\n },\n minImpressions: {\n description: 'Minimum query impressions. Defaults to 20.',\n },\n includeBrand: {\n description: 'Include branded queries in prompt generation.',\n },\n refresh: { description: 'Bypass local GSC cache.' },\n },\n ),\n json: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json, refresh: booleanArg(args.refresh) },\n })\n const report = await seoToAiQueryReport({\n site: selection.site,\n days: strictNumberArg(args.days, '--days'),\n startDate: stringArg(args['start-date']),\n endDate: stringArg(args['end-date']),\n limit: strictNumberArg(args.limit, '--limit'),\n minImpressions: strictNumberArg(\n args['min-impressions'],\n '--min-impressions',\n ),\n maxRows: strictNumberArg(args['max-rows'], '--max-rows'),\n brandTerms: [\n ...(selection.client?.brandTerms ?? []),\n ...(csvArg(args['brand-terms']) ?? []),\n ],\n includeBrand: booleanArg(args['include-brand']),\n refresh: booleanArg(args.refresh),\n })\n\n if (json) {\n printJson(report)\n return\n }\n\n printKeyValue([\n ['Property', report.site],\n ['Status', report.dataStatus],\n ['Verdict', report.summary.verdict],\n ['Eligible queries', formatCount(report.summary.eligibleQueries)],\n ['Returned queries', formatCount(report.summary.returnedQueries)],\n ['Prompts', formatCount(report.summary.prompts)],\n ['GSC completeness', report.source.completeness],\n ])\n\n printLimitedTable(\n ['Query', 'Impr', 'Prompt'],\n report.items.flatMap((item) =>\n item.prompts.map((prompt) => [\n truncate(item.query, 42),\n formatCount(item.impressions),\n truncate(prompt, 86),\n ]),\n ),\n )\n printNotes('Report caveats', report.caveats)\n printNotes('Warnings', report.warnings)\n },\n})\n","import { auditPage } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { booleanArg, jsonFlag, projectArg, stringArg } from '../args.js'\nimport { resolveClient } from '../selection.js'\nimport { printJson, printKeyValue, printTable } from '../utils.js'\nimport { formatFetchDiagnostics } from './shared.js'\n\nexport const auditPageCommand = defineCommand({\n meta: {\n name: 'audit-page',\n description:\n 'Fetch one page and audit title, metadata, content, links, and schema',\n },\n args: {\n url: { type: 'string', required: true, description: 'URL to audit.' },\n site: {\n type: 'string',\n description:\n 'Optional GSC property for page search metrics, for example sc-domain:example.com.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n js: {\n type: 'boolean',\n default: false,\n description: 'Force JavaScript rendering for extraction.',\n },\n refresh: {\n type: 'boolean',\n default: false,\n description: 'Bypass local HTTP cache.',\n },\n },\n run: async ({ args }) => {\n const project = projectArg(args)\n const explicitSite = stringArg(args.site)\n const selectedProject = project\n ? await resolveClient({ project, options: { json: jsonFlag(args) } })\n : undefined\n const defaultProject =\n project || explicitSite\n ? undefined\n : await resolveClient({ options: { json: jsonFlag(args) } })\n const report = await auditPage({\n url: stringArg(args.url) ?? '',\n site: selectedProject?.siteUrl ?? explicitSite ?? defaultProject?.siteUrl,\n js: booleanArg(args.js) ? true : 'auto',\n refresh: booleanArg(args.refresh),\n })\n if (jsonFlag(args)) {\n printJson(report)\n return\n }\n printKeyValue([\n ['URL', report.url],\n ['Final URL', report.page.finalUrl],\n ['Title', report.page.title ?? 'missing'],\n ['Meta description', report.page.metaDescription ?? 'missing'],\n ['Word count', String(report.page.wordCount)],\n ['Fetch', formatFetchDiagnostics(report.fetchDiagnostics)],\n ])\n if (report.issues.length) {\n process.stdout.write('\\nIssues\\n')\n printTable(\n ['Code', 'Severity', 'Principle', 'Detail'],\n report.issues.map((issue) => [\n issue.code,\n issue.severity,\n issue.principle,\n issue.detail,\n ]),\n )\n }\n },\n})\n","import { performanceAudit, SeoError } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { booleanArg, jsonFlag, projectArg, stringArg } from '../args.js'\nimport { resolveClient } from '../selection.js'\nimport { printJson, printKeyValue } from '../utils.js'\nimport { printActionDetails, printNotes } from './output.js'\n\nfunction strategy(value: unknown): 'mobile' | 'desktop' {\n const selected = stringArg(value) ?? 'mobile'\n if (selected !== 'mobile' && selected !== 'desktop') {\n throw new SeoError(\n 'INVALID_INPUT',\n 'Invalid --strategy. Use mobile or desktop.',\n )\n }\n return selected\n}\n\nfunction metric(value?: { displayValue?: string; value?: number }): string {\n if (!value) return 'not measured'\n return value.displayValue ?? String(value.value ?? 'not measured')\n}\n\nfunction fieldMetric(value?: {\n p75: number\n rating: string\n unit: 'milliseconds' | 'score'\n}): string {\n if (!value) return 'not available'\n const suffix = value.unit === 'milliseconds' ? 'ms' : ''\n return `${value.p75}${suffix} (${value.rating})`\n}\n\nexport const performanceCommand = defineCommand({\n meta: {\n name: 'perf',\n description: 'Audit lab performance and field Core Web Vitals',\n },\n subCommands: {\n audit: defineCommand({\n meta: {\n name: 'audit',\n description: 'Run a Lighthouse/Core Web Vitals performance audit',\n },\n args: {\n url: {\n type: 'string',\n description:\n 'URL to audit. Defaults to the selected project crawl URL.',\n },\n client: { type: 'string', description: 'Legacy alias for --project.' },\n project: { type: 'string', description: 'Saved project id or name.' },\n strategy: {\n type: 'string',\n default: 'mobile',\n description: 'Audit strategy: mobile or desktop.',\n },\n 'lighthouse-bin': {\n type: 'string',\n description:\n 'Custom Lighthouse binary path. Defaults to the bundled version.',\n },\n 'crux-key': {\n type: 'string',\n description:\n 'CrUX API key. Prefer SEO_CRUX_API_KEY to avoid shell history.',\n },\n raw: {\n type: 'boolean',\n default: false,\n description: 'Include the full Lighthouse JSON in JSON output.',\n },\n refresh: {\n type: 'boolean',\n default: false,\n description: 'Bypass the local performance report cache.',\n },\n json: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const project = await resolveClient({\n client: projectArg(args),\n options: { json },\n })\n const url = stringArg(args.url) ?? project?.startUrl\n if (!url) {\n throw new Error(\n 'No URL selected. Pass --url or use --project with a crawl URL.',\n )\n }\n const report = await performanceAudit({\n url,\n strategy: strategy(args.strategy),\n lighthouseBin: stringArg(args['lighthouse-bin']),\n cruxApiKey: stringArg(args['crux-key']),\n refresh: booleanArg(args.refresh),\n includeRaw: json && booleanArg(args.raw),\n })\n if (json) {\n printJson(report)\n return\n }\n printKeyValue([\n ['URL', report.url],\n ['Source', report.source],\n ['Strategy', report.strategy],\n [\n 'Lab score',\n report.score === undefined ? 'unknown' : `${report.score}/100`,\n ],\n ['Lab grade', report.grade],\n ['Data status', report.dataStatus],\n ['Headline', report.headline],\n ['FCP', metric(report.metrics.firstContentfulPaint)],\n ['LCP', metric(report.metrics.largestContentfulPaint)],\n ['TBT', metric(report.metrics.totalBlockingTime)],\n ['CLS', metric(report.metrics.cumulativeLayoutShift)],\n ['INP', metric(report.metrics.interactionToNextPaint)],\n ['Server response', metric(report.metrics.serverResponseTime)],\n ['Fallback fetch', metric(report.metrics.fallbackFetchDuration)],\n [\n 'Field data',\n report.fieldData\n ? `${report.fieldData.scope} ${report.fieldData.formFactor.toLowerCase()} (${report.fieldData.assessment.status})`\n : report.fieldDataStatus.status,\n ],\n [\n 'Field period',\n report.fieldData?.collectionPeriod?.firstDate &&\n report.fieldData.collectionPeriod.lastDate\n ? `${report.fieldData.collectionPeriod.firstDate} to ${report.fieldData.collectionPeriod.lastDate}`\n : 'not available',\n ],\n [\n 'Field LCP p75',\n fieldMetric(report.fieldData?.metrics.largestContentfulPaint),\n ],\n [\n 'Field INP p75',\n fieldMetric(report.fieldData?.metrics.interactionToNextPaint),\n ],\n [\n 'Field CLS p75',\n fieldMetric(report.fieldData?.metrics.cumulativeLayoutShift),\n ],\n ])\n printActionDetails(\n 'Top actions',\n report.topActions.map((action) => ({\n label: action.title,\n action: action.action,\n context: action.plainEnglish,\n })),\n )\n printNotes('Caveats', report.caveats)\n },\n }),\n },\n})\n","import { diagnoseProperty } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n jsonFlag,\n numberArg,\n projectArg,\n stringArg,\n} from '../../args.js'\nimport { createProgressReporter } from '../../progress.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson, printKeyValue, printTable } from '../../utils.js'\nimport { printActionDetails } from '../output.js'\nimport { cliReportArgs } from '../report-options.js'\n\nexport const diagnoseCommand = defineCommand({\n meta: {\n name: 'diagnose',\n description: 'Find where Google Search performance changed',\n },\n args: {\n site: {\n type: 'string',\n description: 'GSC property URL, for example sc-domain:example.com.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n ...cliReportArgs(\n ['days', 'recentDays', 'limit', 'includeBrand', 'refresh'],\n {\n days: {\n description: 'Baseline window length in days. Defaults to 90.',\n },\n limit: {\n description: 'Maximum rows per diagnostic section. Defaults to 10.',\n },\n },\n ),\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json, refresh: booleanArg(args.refresh) },\n })\n const report = await diagnoseProperty({\n site: selection.site,\n days: numberArg(args.days),\n recentDays: numberArg(args.recent),\n limit: numberArg(args.limit),\n brandTerms: selection.client?.brandTerms,\n includeBrand: booleanArg(args['include-brand']),\n refresh: booleanArg(args.refresh),\n progress: createProgressReporter(!json),\n })\n if (json) {\n printJson(report)\n return\n }\n printKeyValue([\n ['Property', report.site],\n ['Data status', report.dataStatus],\n ['Update overlap', report.summary.updateAttribution.replaceAll('-', ' ')],\n ['Significant anomalies', String(report.summary.significantAnomalies)],\n ['Update matches', String(report.summary.updateMatches)],\n ['Decay items', String(report.summary.decayItems)],\n ['Cannibal items', String(report.summary.cannibalItems)],\n ['Striking distance', String(report.summary.strikingDistanceItems)],\n ['Quick wins', String(report.summary.quickWinItems)],\n ])\n printTable(\n ['Priority', 'Confidence', 'Reason', 'Action'],\n report.priorities.map((priority) => [\n priority.label,\n priority.confidence,\n priority.reason,\n priority.action,\n ]),\n )\n if (report.skippedSections?.length) {\n printTable(\n ['Skipped section', 'Reason'],\n report.skippedSections.map((section) => [\n section.section,\n section.reason,\n ]),\n )\n }\n printActionDetails(\n 'Priority action details',\n report.priorities.map((priority) => ({\n label: priority.label,\n context: priority.confidence,\n action: priority.action,\n })),\n )\n },\n})\n","import { runDoctor } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { jsonFlag } from '../../args.js'\nimport { printJson, printKeyValue, printTable } from '../../utils.js'\n\nexport const doctorCommand = defineCommand({\n meta: {\n name: 'doctor',\n description: 'Check local auth, scopes, config, and defaults',\n },\n args: {\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const report = await runDoctor()\n if (jsonFlag(args)) {\n printJson(report)\n return\n }\n printKeyValue([\n ['Status', report.ok ? 'ok' : 'needs attention'],\n ['Generated', report.generatedAt],\n ])\n printTable(\n ['Check', 'Status', 'Detail', 'Fix'],\n report.checks.map((check) => [\n check.label,\n check.status,\n check.detail,\n check.fix ?? '',\n ]),\n )\n },\n})\n","import {\n ga4PropertyIdFromName,\n listGa4AccountSummaries,\n readConfig,\n writeConfig,\n} from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { jsonFlag, stringArg } from '../../args.js'\nimport { printJson, printTable } from '../../utils.js'\n\nexport const ga4PropertiesCommand = defineCommand({\n meta: {\n name: 'ga4-properties',\n description: 'List GA4 accounts and properties available to Google OAuth',\n },\n args: {\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n save: {\n type: 'string',\n description: 'Save this numeric GA4 property ID as the default.',\n },\n },\n run: async ({ args }) => {\n const summaries = await listGa4AccountSummaries()\n const rows = summaries.flatMap((account) =>\n account.propertySummaries.map((property) => ({\n account: account.displayName ?? account.account,\n property: ga4PropertyIdFromName(property.property),\n displayName: property.displayName ?? property.property,\n })),\n )\n\n const save = stringArg(args.save)\n if (save) {\n const config = readConfig()\n config.google.defaultGa4PropertyId = save\n writeConfig(config)\n }\n\n if (jsonFlag(args)) {\n printJson({ accountSummaries: summaries, properties: rows, saved: save })\n return\n }\n if (save) {\n process.stdout.write(`Saved default GA4 property ${save}.\\n`)\n }\n printTable(\n ['Property', 'Name', 'Account'],\n rows.map((row) => [row.property, row.displayName, row.account]),\n )\n },\n})\n","import { type SegmentDimension, segmentImpact } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n jsonFlag,\n projectArg,\n strictNumberArg,\n stringArg,\n} from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson, printKeyValue, printTable } from '../../utils.js'\nimport { printNotes } from '../output.js'\nimport { cliReportArgs } from '../report-options.js'\n\nconst segmentDimension = (value: unknown): SegmentDimension => {\n const dimension = stringArg(value) ?? 'page'\n if (\n dimension !== 'page' &&\n dimension !== 'query' &&\n dimension !== 'country' &&\n dimension !== 'device'\n ) {\n throw new Error('Invalid --dimension. Use page, query, country, or device.')\n }\n return dimension\n}\n\nexport const segmentImpactCommand = defineCommand({\n meta: {\n name: 'segment-impact',\n description: 'Compare GSC movement by page, query, device, or country',\n },\n args: {\n site: {\n type: 'string',\n description: 'GSC property URL, for example sc-domain:example.com.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n dimension: {\n type: 'string',\n default: 'page',\n description: 'Segment by page, query, country, or device.',\n },\n ...cliReportArgs(['days', 'limit', 'refresh'], {\n days: {\n description: 'Recent window length from 1 to 240 days. Defaults to 28.',\n },\n limit: {\n description: 'Maximum segment rows to print. Defaults to 25.',\n },\n refresh: {\n description: 'Bypass local cache and fetch fresh GSC data.',\n },\n }),\n compare: {\n type: 'string',\n description:\n 'Legacy 1-240 day comparison length. Must equal the current window.',\n },\n 'start-date': {\n type: 'string',\n description: 'Exact current-window start date in YYYY-MM-DD format.',\n },\n 'end-date': {\n type: 'string',\n description: 'Exact current-window end date in YYYY-MM-DD format.',\n },\n 'max-rows': {\n type: 'string',\n description: 'Maximum retained GSC rows per window. Defaults to 100000.',\n },\n 'unmatched-limit': {\n type: 'string',\n description:\n 'Maximum one-window evidence rows to return. Defaults to 25.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const dimension = segmentDimension(args.dimension)\n const days = strictNumberArg(args.days, '--days')\n const compareDays = strictNumberArg(args.compare, '--compare')\n const limit = strictNumberArg(args.limit, '--limit')\n const unmatchedLimit = strictNumberArg(\n args['unmatched-limit'],\n '--unmatched-limit',\n )\n const maxRows = strictNumberArg(args['max-rows'], '--max-rows')\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json, refresh: booleanArg(args.refresh) },\n })\n const report = await segmentImpact({\n site: selection.site,\n dimension,\n days,\n compareDays,\n startDate: stringArg(args['start-date']),\n endDate: stringArg(args['end-date']),\n limit,\n unmatchedLimit,\n maxRows,\n refresh: booleanArg(args.refresh),\n })\n if (json) {\n printJson(report)\n return\n }\n printKeyValue([\n ['Property', report.site],\n ['Dimension', report.dimension],\n ['Status', report.dataStatus],\n ['Before', `${report.before.startDate} to ${report.before.endDate}`],\n ['After', `${report.after.startDate} to ${report.after.endDate}`],\n ['Verdict', report.summary.verdict],\n ])\n printTable(\n ['Segment', 'Clicks before', 'Clicks after', 'Delta', 'Pos delta'],\n report.items.map((item) => [\n item.key,\n item.beforeClicks,\n item.afterClicks,\n item.clickDelta,\n item.positionDelta ?? '-',\n ]),\n )\n if (report.unmatchedSegments.length) {\n process.stdout.write('\\nOne-window evidence (not treated as zero)\\n')\n printTable(\n ['Segment', 'Retained in', 'Clicks', 'Impressions'],\n report.unmatchedSegments.map((item) => [\n item.key,\n item.retainedIn,\n item.clicks,\n item.impressions,\n ]),\n )\n }\n printNotes('Warnings', report.warnings)\n },\n})\n","import { strikingDistance } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n fetchRateArg,\n jsonFlag,\n numberArg,\n projectArg,\n stringArg,\n} from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson, printKeyValue } from '../../utils.js'\nimport {\n formatCount,\n formatPercent,\n formatPosition,\n printActionDetails,\n printLimitedTable,\n printNotes,\n truncate,\n} from '../output.js'\nimport { cliReportArgs } from '../report-options.js'\nimport { formatContentCheck, formatFetchDiagnostics } from '../shared.js'\n\nfunction rowCountLabel(count: number): string {\n return `${formatCount(count)} ${count === 1 ? 'row' : 'rows'}`\n}\n\nexport const strikingDistanceCommand = defineCommand({\n meta: {\n name: 'striking-distance',\n description: 'Find query/page rows averaging positions above 10 through 20',\n },\n args: {\n site: {\n type: 'string',\n description: 'GSC property URL, for example sc-domain:example.com.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n ...cliReportArgs([\n 'days',\n 'minImpressions',\n 'limit',\n 'includeBrand',\n 'verifyContent',\n 'verifyLimit',\n 'js',\n 'fetchConcurrency',\n 'fetchIntervalCap',\n 'fetchIntervalMs',\n 'refresh',\n ]),\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const verifyLimit = numberArg(args['verify-limit'])\n const verifyContent =\n booleanArg(args['verify-content']) === true || verifyLimit !== undefined\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json, refresh: booleanArg(args.refresh) },\n })\n const report = await strikingDistance({\n site: selection.site,\n days: numberArg(args.days),\n minImpressions: numberArg(args['min-impressions']),\n limit: numberArg(args.limit),\n brandTerms: selection.client?.brandTerms,\n includeBrand: booleanArg(args['include-brand']),\n verifyContent,\n verifyLimit,\n js: booleanArg(args.js) ? true : undefined,\n rate: fetchRateArg(args),\n refresh: booleanArg(args.refresh),\n })\n if (json) {\n printJson(report)\n return\n }\n printKeyValue([\n ['Site', report.site],\n ['Eligible rows', formatCount(report.summary.eligibleRows)],\n ['Returned rows', formatCount(report.summary.returnedRows)],\n ['Template groups', formatCount(report.summary.groups)],\n ['Eligible impressions', formatCount(report.summary.eligibleImpressions)],\n ['Brand queries', report.summary.brandFiltering],\n ['Verification', report.verification.requested ? 'requested' : 'off'],\n ['Verdict', report.summary.verdict],\n ])\n printNotes('Why this matters', [\n 'These rows have a GSC average position above 10 and at most 20. Treat them as candidates for investigation, not guaranteed page-two rankings.',\n 'Groups use all eligible rows. A shared-template label is only a candidate until recurring evidence is verified across distinct URLs.',\n ])\n printNotes('Recommended actions', report.recommendations)\n printNotes('Report caveats', report.caveats)\n\n if (report.groups.length) {\n printLimitedTable(\n ['Group', 'Rows', 'URLs', 'Impr', 'Avg pos', 'Scope', 'Action'],\n report.groups.map((group) => [\n truncate(group.label, 36),\n formatCount(group.rowCount),\n formatCount(group.uniqueUrls),\n formatCount(group.totalImpressions),\n formatPosition(group.impressionWeightedPosition),\n group.actionScope,\n truncate(group.recommendation.action, 72),\n ]),\n )\n printActionDetails(\n 'Top striking-distance group actions',\n report.groups.map((group) => ({\n label: group.label,\n context: `${rowCountLabel(group.rowCount)}, ${formatCount(group.totalImpressions)} impressions`,\n action: group.recommendation.action,\n })),\n )\n }\n\n if (!report.items.length) {\n process.stdout.write(\n 'No striking-distance opportunities matched these filters.\\n',\n )\n return\n }\n\n printLimitedTable(\n [\n 'Query',\n 'Template',\n 'URL',\n 'Impr',\n 'CTR',\n 'Pos',\n 'Score',\n 'Fetch',\n 'Check',\n 'Action',\n ],\n report.items.map((item) => [\n truncate(item.query, 36),\n truncate(item.template.label, 24),\n truncate(item.url, 48),\n formatCount(item.impressions),\n formatPercent(item.ctr),\n formatPosition(item.position),\n item.priority.score,\n formatFetchDiagnostics(item.contentVerification?.fetchDiagnostics),\n formatContentCheck(item.contentVerification?.classification),\n truncate(item.recommendation.action, 72),\n ]),\n )\n printActionDetails(\n 'Top striking-distance actions',\n report.items.map((item) => ({\n label: item.query,\n context: `${item.template.label}, pos ${formatPosition(item.position)}, ${formatCount(item.impressions)} impressions`,\n action: item.recommendation.action,\n })),\n )\n },\n})\n","import { countLabel, pseoAuditReport } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { booleanArg, jsonFlag, projectArg, stringArg } from '../../args.js'\nimport { createProgressReporter } from '../../progress.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson, printKeyValue } from '../../utils.js'\nimport {\n formatCount,\n formatPercent,\n formatPosition,\n printLimitedTable,\n printNextCommand,\n printNotes,\n truncate,\n} from '../output.js'\nimport { cliReportArgs } from '../report-options.js'\nimport { pseoOptions } from './options.js'\n\nfunction formatInspection(input: {\n indexed: number\n notIndexed: number\n unknown: number\n warnings: number\n}): string {\n const total =\n input.indexed + input.notIndexed + input.unknown + input.warnings\n if (!total) return '-'\n return `${input.indexed}/${total} indexed`\n}\n\nfunction formatCrawl(input: {\n samples: unknown[]\n blockedOrFailed: number\n usable: number\n medianWordCount?: number\n weakQueryCoverage?: number\n}): string {\n if (!input.samples.length) return '-'\n const words =\n input.medianWordCount === undefined\n ? 'words ?'\n : `${formatCount(input.medianWordCount)} words`\n const weak = input.weakQueryCoverage\n ? `; ${input.weakQueryCoverage} weak coverage`\n : ''\n return `${words}; ${input.usable}/${input.samples.length} usable${weak}`\n}\n\nfunction formatCoverage(classification: string): string {\n if (classification === 'serp-framing-review') return 'wording review'\n if (classification === 'body-term-review') return 'literal term review'\n return 'covered terms'\n}\n\nfunction formatTemplateShape(\n shape: Awaited<\n ReturnType<typeof pseoAuditReport>\n >['templates'][number]['shape'],\n): string {\n const staticPath = shape.staticSegments\n .map((segment) => `/${segment.value}`)\n .join('')\n const variables = shape.variableSegments.slice(0, 3).map((segment) => {\n const examples = segment.examples.slice(0, 3).join(', ')\n return `${segment.placeholder}@${segment.index + 1}${examples ? ` (${examples})` : ''}`\n })\n return [\n staticPath ? `static ${staticPath}` : 'no fixed path prefix',\n variables.length ? `variables ${variables.join('; ')}` : 'no variables',\n ].join('; ')\n}\n\nfunction formatEntityFit(\n fit: Awaited<\n ReturnType<typeof pseoAuditReport>\n >['templates'][number]['metrics']['entityFit'],\n): string | undefined {\n if (!fit.checkedQueries) return undefined\n return `${Math.round(fit.impressionShare * 100)}% impression fit across ${countLabel(fit.checkedQueries, 'checked query/page row')}`\n}\n\nfunction formatDemandLabel(label: string): string {\n if (label.startsWith('theme: ')) {\n return `${label.slice('theme: '.length)}-related`\n }\n if (label === 'general') return 'broad'\n return label\n}\n\nfunction printTemplateDetails(\n templates: Awaited<ReturnType<typeof pseoAuditReport>>['templates'],\n): void {\n for (const template of templates.slice(0, 5)) {\n process.stdout.write(`\\n${template.signature}\\n`)\n if (template.evidence.length) {\n process.stdout.write(` Evidence: ${template.evidence.join('; ')}.\\n`)\n }\n process.stdout.write(` Shape: ${formatTemplateShape(template.shape)}\\n`)\n const entityFit = formatEntityFit(template.metrics.entityFit)\n if (entityFit) {\n process.stdout.write(` Entity fit: ${entityFit}\\n`)\n }\n const patterns = template.metrics.queryPatterns\n .slice(0, 3)\n .map(\n (pattern) =>\n `${formatDemandLabel(pattern.label)} (${formatCount(pattern.impressions)} impr: ${pattern.examples\n .slice(0, 2)\n .join('; ')})`,\n )\n if (patterns.length) {\n process.stdout.write(` Demand: ${patterns.join(' | ')}\\n`)\n }\n const topQueries = template.metrics.topQueries.slice(0, 3)\n if (topQueries.length) {\n process.stdout.write(' Top queries:\\n')\n for (const query of topQueries) {\n process.stdout.write(\n ` - ${truncate(query.query, 72)} (${formatCount(query.impressions)} impr, pos ${formatPosition(query.position)})\\n`,\n )\n }\n }\n const coverage = template.crawl.samples\n .map((sample) => sample.queryCoverage)\n .filter((item): item is NonNullable<typeof item> => Boolean(item))\n .slice(0, 3)\n if (coverage.length) {\n process.stdout.write(' Sample coverage:\\n')\n for (const item of coverage) {\n const missing = item.missingTerms.length\n ? ` missing ${item.missingTerms.slice(0, 4).join(', ')}`\n : ''\n process.stdout.write(\n ` - ${formatCoverage(item.classification)}: ${truncate(item.query, 64)} (body ${(item.bodyCoverage * 100).toFixed(0)}%${missing})\\n`,\n )\n }\n }\n const weakEntityExamples = template.metrics.entityFit.weakExamples.slice(\n 0,\n 2,\n )\n if (weakEntityExamples.length) {\n process.stdout.write(' Weak entity-fit examples:\\n')\n for (const item of weakEntityExamples) {\n const terms = item.pathTerms.slice(0, 4)\n process.stdout.write(\n ` - ${truncate(item.query, 64)} -> expected ${countLabel(terms.length, 'path term')}: ${terms.join(', ')}\\n`,\n )\n }\n }\n process.stdout.write(` Action: ${template.recommendation}\\n`)\n }\n}\n\nexport const pseoAuditCommand = defineCommand({\n meta: {\n name: 'audit',\n description:\n 'Group GSC/sitemap URLs into pSEO templates, then sample pages for crawl and index evidence',\n },\n args: {\n site: { type: 'string' },\n project: { type: 'string', description: 'Saved project id or name.' },\n client: { type: 'string', description: 'Legacy alias for --project.' },\n ...cliReportArgs(['days', 'limit', 'includeBrand', 'js', 'refresh'], {\n limit: {\n description: 'Maximum templates to show. Defaults to 25.',\n },\n includeBrand: {\n description: 'Include branded queries in template metrics.',\n },\n js: {\n description: 'Force JavaScript rendering for crawl samples.',\n },\n refresh: {\n description: 'Bypass local GSC and HTTP cache.',\n },\n }),\n sitemap: {\n type: 'string',\n description:\n 'Comma-separated sitemap URLs to include in template counts.',\n },\n 'crawl-samples': {\n type: 'string',\n description:\n 'Sample URLs to fetch per detected template. This is not crawl depth.',\n },\n 'inspect-samples': {\n type: 'string',\n description:\n 'Sample URLs to check per detected template with URL Inspection.',\n },\n 'max-sitemap-urls': {\n type: 'string',\n description: 'Maximum discovered URLs per sitemap. Defaults to 50000.',\n },\n 'minimum-template-urls': {\n type: 'string',\n description:\n 'Minimum repeated URLs required for a template. Defaults to 3.',\n },\n 'minimum-template-share': {\n type: 'string',\n description:\n 'Minimum share of discovered URLs from 0 to 1. Defaults to 0.',\n },\n 'minimum-template-impressions': {\n type: 'string',\n description:\n 'Minimum retained page impressions for a template. Defaults to 0.',\n },\n 'brand-terms': {\n type: 'string',\n description:\n 'Comma-separated brand terms to exclude from query evidence.',\n },\n 'fetch-concurrency': {\n type: 'string',\n description: 'Maximum concurrent page fetches per host. Defaults to 4.',\n },\n 'fetch-interval-cap': {\n type: 'string',\n description: 'Maximum page fetches per interval per host. Defaults to 4.',\n },\n 'fetch-interval-ms': {\n type: 'string',\n description: 'Fetch rate interval in milliseconds. Defaults to 1000.',\n },\n json: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const options = pseoOptions(args)\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json, refresh: booleanArg(args.refresh) },\n })\n const report = await pseoAuditReport({\n site: selection.site,\n ...options,\n brandTerms: options.brandTerms ?? selection.client?.brandTerms,\n progress: createProgressReporter(!json),\n })\n\n if (json) {\n printJson(report)\n return\n }\n\n printKeyValue([\n ['Property', report.site],\n ['Templates', formatCount(report.summary.templates)],\n ['GSC pages', formatCount(report.summary.gscPages)],\n ['Sitemap URLs', formatCount(report.summary.sitemapUrls)],\n ['Clicks', formatCount(report.summary.clicks)],\n ['Impressions', formatCount(report.summary.impressions)],\n [\n 'Usable crawls',\n `${formatCount(report.summary.crawledUrls)}/${formatCount(report.summary.crawlAttempts)}`,\n ],\n [\n 'Inspection responses',\n `${formatCount(report.summary.inspectedUrls)}/${formatCount(report.summary.inspectionAttempts)}`,\n ],\n ])\n printNotes('Report caveats', report.caveats)\n\n if (!report.templates.length) {\n process.stdout.write('No pSEO templates found from GSC/sitemap data.\\n')\n return\n }\n\n printLimitedTable(\n [\n 'Verdict',\n 'Template',\n 'URLs',\n 'Clicks',\n 'Impr',\n 'CTR',\n 'Pos',\n 'Index',\n 'Crawl',\n 'Action',\n ],\n report.templates.map((template) => [\n `${template.verdict} (${template.confidence})`,\n truncate(template.signature, 28),\n formatCount(template.urlCount),\n formatCount(template.metrics.clicks),\n formatCount(template.metrics.impressions),\n formatPercent(template.metrics.ctr),\n template.metrics.position.toFixed(1),\n formatInspection(template.inspection),\n formatCrawl(template.crawl),\n truncate(template.recommendation, 72),\n ]),\n )\n\n printTemplateDetails(report.templates)\n\n if (report.warnings.length) {\n process.stdout.write(`Warnings: ${report.warnings.join('; ')}\\n`)\n }\n const target = selection.client\n ? `--project ${JSON.stringify(selection.client.id)}`\n : `--site ${JSON.stringify(selection.site)}`\n printNextCommand(`seo export pseo ${target}`)\n },\n})\n","import { defineCommand } from 'citty'\nimport { pseoAuditCommand } from './audit.js'\n\nexport const pseoCommand = defineCommand({\n meta: {\n name: 'pseo',\n description:\n 'Programmatic SEO audits that cluster URL patterns and sample template pages',\n },\n subCommands: {\n audit: pseoAuditCommand,\n },\n})\n","import { readFile } from 'node:fs/promises'\nimport { SeoError, type SeoErrorCode } from '@seo/core'\nimport {\n describeReport,\n executeReport,\n listReports,\n REPORT_CATEGORIES,\n type ReportCategory,\n} from '@seo/mcp'\nimport { defineCommand } from 'citty'\nimport { jsonFlag, stringArg } from '../args.js'\nimport { printJson, printKeyValue, printTable } from '../utils.js'\n\nfunction categoryArg(value: unknown): ReportCategory | undefined {\n const category = stringArg(value)\n if (!category) return undefined\n if (!REPORT_CATEGORIES.includes(category as ReportCategory)) {\n throw new SeoError(\n 'INVALID_INPUT',\n `Unknown report category: ${category}. Choose ${REPORT_CATEGORIES.join(', ')}.`,\n )\n }\n return category as ReportCategory\n}\n\nasync function paramsArg(\n inlineValue: unknown,\n fileValue: unknown,\n): Promise<Record<string, unknown>> {\n const inline = stringArg(inlineValue)\n const file = stringArg(fileValue)\n if (inline && file) {\n throw new SeoError(\n 'INVALID_INPUT',\n 'Use either --params or --params-file, not both.',\n )\n }\n if (!inline && !file) return {}\n\n const source = inline ?? (await readFile(file ?? '', 'utf8'))\n let parsed: unknown\n try {\n parsed = JSON.parse(source)\n } catch {\n throw new SeoError('INVALID_INPUT', 'Report parameters must be valid JSON.')\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new SeoError('INVALID_INPUT', 'Report parameters must be an object.')\n }\n return parsed as Record<string, unknown>\n}\n\nfunction throwToolError(result: {\n isError?: boolean\n structuredContent?: Record<string, unknown>\n}): void {\n if (!result.isError) return\n const envelope = result.structuredContent as\n | { error?: { code?: SeoErrorCode; message?: string } }\n | undefined\n throw new SeoError(\n envelope?.error?.code ?? 'INTERNAL_ERROR',\n envelope?.error?.message ?? 'The report could not be completed.',\n )\n}\n\nconst listCommand = defineCommand({\n meta: {\n name: 'list',\n description: 'List report ids available to the CLI and MCP server',\n },\n args: {\n category: {\n type: 'string',\n description: `Filter by category: ${REPORT_CATEGORIES.join(', ')}.`,\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const category = categoryArg(args.category)\n const reports = listReports(category)\n if (jsonFlag(args)) {\n printJson({ reports, categories: REPORT_CATEGORIES })\n return\n }\n printTable(\n ['ID', 'Category', 'Name', 'Description'],\n reports.map((report) => [\n report.id,\n report.category,\n report.name,\n report.description,\n ]),\n )\n },\n})\n\nconst describeCommand = defineCommand({\n meta: {\n name: 'describe',\n description: 'Show the purpose and parameter schema for one report',\n },\n args: {\n id: {\n type: 'positional',\n required: true,\n description: 'Report id from `seo reports list`.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const report = describeReport(stringArg(args.id) ?? '')\n if (jsonFlag(args)) {\n printJson({ report })\n return\n }\n printKeyValue([\n ['ID', report.id],\n ['Category', report.category],\n ['Name', report.name],\n ['Description', report.description],\n ['Outcome', report.outcome],\n ])\n process.stdout.write('\\nUse when\\n')\n for (const reason of report.useWhen) process.stdout.write(`- ${reason}\\n`)\n process.stdout.write('\\nAvoid when\\n')\n for (const reason of report.avoidWhen) process.stdout.write(`- ${reason}\\n`)\n process.stdout.write('\\nRead in order\\n')\n for (const field of report.readOrder) process.stdout.write(`- ${field}\\n`)\n process.stdout.write('\\nDo not claim\\n')\n for (const limit of report.doNotClaim) process.stdout.write(`- ${limit}\\n`)\n process.stdout.write(`\\nVerify\\n- ${report.verify}\\n`)\n if (report.related.length > 0) {\n process.stdout.write('\\nRelated reports\\n')\n for (const item of report.related) {\n process.stdout.write(`- ${item.id}: ${item.reason}\\n`)\n }\n }\n process.stdout.write('\\nParameters (JSON Schema)\\n')\n printJson(report.inputSchema)\n },\n})\n\nconst runCommand = defineCommand({\n meta: {\n name: 'run',\n description: 'Run one report with JSON parameters',\n },\n args: {\n id: {\n type: 'positional',\n required: true,\n description: 'Report id from `seo reports list`.',\n },\n params: {\n type: 'string',\n description: 'Report parameters as a JSON object.',\n },\n 'params-file': {\n type: 'string',\n description: 'Read report parameters from a JSON file.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const id = stringArg(args.id) ?? ''\n const params = await paramsArg(args.params, args['params-file'])\n const result = await executeReport(id, params)\n throwToolError(result)\n\n if (jsonFlag(args)) {\n printJson(result.structuredContent ?? {})\n return\n }\n for (const item of result.content) {\n process.stdout.write(`${item.text}\\n`)\n }\n },\n})\n\nexport const reportCatalogCommand = defineCommand({\n meta: {\n name: 'reports',\n description: 'Discover and run the complete report catalog',\n },\n subCommands: {\n list: listCommand,\n describe: describeCommand,\n run: runCommand,\n },\n})\n","import { monthlyReport } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { jsonFlag, numberArg, stringArg } from '../../args.js'\nimport { createProgressReporter } from '../../progress.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson } from '../../utils.js'\nimport { printNextCommand } from '../output.js'\nimport { cliReportArgs } from '../report-options.js'\nimport {\n reportFetchArgs,\n reportFetchOptions,\n reportSelectionArgs,\n reportSelectionInput,\n} from './args.js'\n\nexport const monthlyReportCommand = defineCommand({\n meta: {\n name: 'monthly-report',\n description: 'Generate a monthly SEO report narrative',\n },\n args: {\n ...reportSelectionArgs,\n month: {\n type: 'string',\n description:\n 'Report month as YYYY-MM. Defaults to the latest month with final GSC data.',\n },\n ...cliReportArgs(['limit'], {\n limit: {\n description: 'Maximum rows per diagnostic section. Defaults to 10.',\n },\n }),\n ...reportFetchArgs,\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const selectionInput = reportSelectionInput(args)\n const selection = await resolveClientSelection({\n client: selectionInput.client,\n site: selectionInput.site,\n options: { json, refresh: selectionInput.refresh },\n })\n const report = await monthlyReport({\n site: selection.site,\n month: stringArg(args.month),\n limit: numberArg(args.limit),\n brandTerms: selection.client?.brandTerms,\n ...reportFetchOptions(args),\n progress: createProgressReporter(!json),\n })\n\n if (json) {\n printJson(report)\n return\n }\n process.stdout.write(`${report.markdown}\\n`)\n const target = selection.client\n ? `--project ${JSON.stringify(selection.client.id)}`\n : `--site ${JSON.stringify(selection.site)}`\n const month = stringArg(args.month)\n process.stdout.write('\\n')\n printNextCommand(\n `seo export monthly ${target}${month ? ` --month ${JSON.stringify(month)}` : ''}`,\n )\n },\n})\n","import { reportNarrative } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { jsonFlag, numberArg, stringArg } from '../../args.js'\nimport { createProgressReporter } from '../../progress.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson } from '../../utils.js'\nimport { printNextCommand } from '../output.js'\nimport { cliReportArgs } from '../report-options.js'\nimport {\n reportFetchArgs,\n reportFetchOptions,\n reportSelectionArgs,\n reportSelectionInput,\n} from './args.js'\n\nexport const reportNarrativeCommand = defineCommand({\n meta: {\n name: 'report-narrative',\n description: 'Generate a client-ready SEO narrative from diagnosis data',\n },\n args: {\n ...reportSelectionArgs,\n ...cliReportArgs(['days', 'recentDays'], {\n days: { description: 'Diagnosis window length in days. Defaults to 90.' },\n }),\n 'start-date': {\n type: 'string',\n description: 'Optional report start date as YYYY-MM-DD.',\n },\n 'end-date': {\n type: 'string',\n description: 'Optional report end date as YYYY-MM-DD.',\n },\n ...cliReportArgs(['limit'], {\n limit: {\n description: 'Maximum rows per diagnostic section. Defaults to 10.',\n },\n }),\n 'change-limit': {\n type: 'string',\n description: 'Maximum saved changes to measure. Defaults to 5.',\n },\n ...reportFetchArgs,\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const selectionInput = reportSelectionInput(args)\n const selection = await resolveClientSelection({\n client: selectionInput.client,\n site: selectionInput.site,\n options: { json, refresh: selectionInput.refresh },\n })\n const report = await reportNarrative({\n site: selection.site,\n days: numberArg(args.days),\n recentDays: numberArg(args.recent),\n startDate: stringArg(args['start-date']),\n endDate: stringArg(args['end-date']),\n limit: numberArg(args.limit),\n changeLimit: numberArg(args['change-limit']),\n brandTerms: selection.client?.brandTerms,\n ...reportFetchOptions(args),\n progress: createProgressReporter(!json),\n })\n\n if (json) {\n printJson(report)\n return\n }\n process.stdout.write(`${report.markdown}\\n`)\n const target = selection.client\n ? `--project ${JSON.stringify(selection.client.id)}`\n : `--site ${JSON.stringify(selection.site)}`\n process.stdout.write('\\n')\n printNextCommand(`seo export narrative ${target}`)\n },\n})\n","import { explainRule, listRules } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { jsonFlag, stringArg } from '../args.js'\nimport { printJson, printKeyValue, printTable } from '../utils.js'\n\nexport const rulesCommand = defineCommand({\n meta: {\n name: 'rules',\n description: 'List crawler rule ids and default guidance',\n },\n args: {\n category: {\n type: 'string',\n description: 'Filter rules by category.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const category = stringArg(args.category)\n const rules = listRules().filter((rule) =>\n category ? rule.category === category : true,\n )\n\n if (jsonFlag(args)) {\n printJson({ rules })\n return\n }\n\n printTable(\n ['ID', 'Severity', 'Category', 'Title'],\n rules.map((rule) => [\n rule.id,\n rule.defaultSeverity,\n rule.category,\n rule.title,\n ]),\n )\n },\n})\n\nexport const explainCommand = defineCommand({\n meta: {\n name: 'explain',\n description: 'Explain one crawler rule in plain English',\n },\n args: {\n rule: {\n type: 'string',\n required: true,\n description: 'Rule id to explain, for example missing_title.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const ruleId = stringArg(args.rule) ?? ''\n const rule = explainRule(ruleId)\n if (!rule) {\n throw new Error(`Unknown rule: ${ruleId}`)\n }\n\n if (jsonFlag(args)) {\n printJson(rule)\n return\n }\n\n printKeyValue([\n ['Rule', rule.id],\n ['Title', rule.title],\n ['Category', rule.category],\n ['Severity', rule.defaultSeverity],\n ])\n process.stdout.write(`\\nWhy it matters\\n${rule.whyItMatters}\\n`)\n process.stdout.write(`\\nHow to fix\\n${rule.howToFix}\\n`)\n process.stdout.write(`\\nImpact if ignored\\n${rule.impactIfIgnored}\\n`)\n process.stdout.write(`\\nHow to verify\\n${rule.howToVerify}\\n`)\n },\n})\n","import { ensureSeoCliDirs } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { jsonFlag, numberArg, projectArg, stringArg } from '../args.js'\nimport { resolveClientSelection } from '../selection.js'\nimport { printJson, printKeyValue } from '../utils.js'\nimport { startUrlForSite } from './shared.js'\n\nfunction quote(value: string): string {\n return JSON.stringify(value)\n}\n\nexport const scheduleCommand = defineCommand({\n meta: {\n name: 'schedule',\n description: 'Print local cron entries for recurring SEO workflows',\n },\n subCommands: {\n cron: defineCommand({\n meta: {\n name: 'cron',\n description: 'Print crontab lines for local recurring SEO workflows',\n },\n args: {\n site: {\n type: 'string',\n description: 'GSC property URL, for example sc-domain:example.com.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n url: {\n type: 'string',\n description:\n 'Start URL for technical-watch. Defaults from the GSC property when possible.',\n },\n urls: {\n type: 'string',\n description: 'Comma-separated URLs for index-watch.',\n },\n hour: {\n type: 'string',\n default: '9',\n description: 'Hour in local cron time. Defaults to 9.',\n },\n minute: {\n type: 'string',\n default: '0',\n description: 'Minute in local cron time. Defaults to 0.',\n },\n weekday: {\n type: 'string',\n description:\n 'Weekly technical-watch day. Defaults to client setting, then Monday.',\n },\n day: {\n type: 'string',\n description:\n 'Monthly report day. Defaults to client setting, then 1.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json },\n })\n const site = selection.site\n const startUrl =\n stringArg(args.url) ??\n selection.client?.startUrl ??\n startUrlForSite(selection.site)\n const hour = numberArg(args.hour) ?? 9\n const minute = numberArg(args.minute) ?? 0\n const weekday =\n numberArg(args.weekday) ?? selection.client?.technicalWeekday ?? 1\n const day = numberArg(args.day) ?? selection.client?.reportDay ?? 1\n const identityArg = selection.client\n ? `--project ${quote(selection.client.id)}`\n : `--site ${quote(site)}`\n const watchUrls =\n stringArg(args.urls) ?? selection.client?.watchUrls.join(',')\n\n const lines = [\n {\n name: 'technical-watch',\n cron: `${minute} ${hour} * * ${weekday}`,\n command: [\n 'seo technical-watch',\n identityArg,\n startUrl ? `--url ${quote(startUrl)}` : undefined,\n watchUrls ? `--urls ${quote(watchUrls)}` : undefined,\n '--json',\n ]\n .filter(Boolean)\n .join(' '),\n },\n {\n name: 'monthly-report',\n cron: `${minute} ${hour} ${day} * *`,\n command: ['seo monthly-report', identityArg, '--json'].join(' '),\n },\n ]\n\n if (json) {\n printJson({ site, lines })\n return\n }\n\n const paths = ensureSeoCliDirs()\n printKeyValue([\n ['Property', site],\n ['Install', 'crontab -e'],\n ])\n for (const line of lines) {\n process.stdout.write(\n `${line.cron} ${line.command} >> ${quote(`${paths.logDir}/${line.name}.log`)} 2>&1\\n`,\n )\n }\n },\n }),\n },\n})\n","import { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { SeoError } from '@seo/core'\n\n// Skills and evals ship at the package root. Both resolvers honour an explicit\n// override, otherwise walk up from the bundled CLI until the directory and its\n// README appear. Kept in its own module so the skills command and the eval\n// command can share it without importing each other.\nexport function skillsDirectory(): string {\n return resolvePackagedDirectory('skills', process.env.SEO_SKILLS_DIR)\n}\n\nexport function evalsDirectory(): string {\n return resolvePackagedDirectory('evals', process.env.SEO_EVALS_DIR)\n}\n\nfunction resolvePackagedDirectory(name: string, override?: string): string {\n if (override) return resolve(override)\n\n let current = dirname(fileURLToPath(import.meta.url))\n for (let depth = 0; depth < 6; depth += 1) {\n const candidate = join(current, name)\n if (existsSync(join(candidate, 'README.md'))) return candidate\n current = dirname(current)\n }\n\n throw new SeoError(\n 'INTERNAL_ERROR',\n `Packaged ${name} could not be found. Reinstall \\`seo\\` and try again.`,\n )\n}\n\nexport function readSkillDescription(path: string): string {\n const source = readFileSync(join(path, 'SKILL.md'), 'utf8')\n return source.match(/^description:\\s*(.+)$/m)?.[1]?.trim() ?? ''\n}\n","import { spawn } from 'node:child_process'\nimport { existsSync, readdirSync, readFileSync } from 'node:fs'\nimport { basename, join } from 'node:path'\nimport { SeoError } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n defaultTrueBooleanArg,\n jsonFlag,\n numberArg,\n stringArg,\n} from '../args.js'\nimport { printJson } from '../utils.js'\nimport { evalsDirectory, skillsDirectory } from './skill-paths.js'\n\nconst SCHEMA_VERSION = 1\nconst DEFAULT_AGENT = 'claude -p'\nconst DEFAULT_TIMEOUT_SECONDS = 300\nconst MAX_CONCURRENCY = 4\nconst ROUTER_SKILL = 'seo'\n\ntype EvalItem = {\n id: number\n prompt: string\n expected_output: string\n assertions: string[]\n files: string[]\n}\n\ntype EvalFile = {\n subject: string\n evals: EvalItem[]\n}\n\ntype AssertionVerdict = {\n assertion: string\n verdict: 'pass' | 'fail' | 'unjudged'\n reason?: string\n source?: 'judge verdict'\n}\n\ntype EvalStatus = 'passed' | 'failed' | 'errored' | 'unjudged'\n\ntype EvalResult = {\n id: number\n prompt: string\n status: EvalStatus\n reply: string\n error?: string\n agentDurationMs: number\n judgeDurationMs?: number\n durationMs: number\n assertions: AssertionVerdict[]\n}\n\ntype SubjectResult = {\n subject: string\n passed: number\n failed: number\n errored: number\n unjudged: number\n evals: EvalResult[]\n}\n\nfunction listSubjectFiles(): Array<{ subject: string; path: string }> {\n const root = evalsDirectory()\n return readdirSync(root, { withFileTypes: true })\n .filter((entry) => entry.isFile() && entry.name.endsWith('.json'))\n .map((entry) => ({\n subject: basename(entry.name, '.json'),\n path: join(root, entry.name),\n }))\n .sort((a, b) =>\n a.subject < b.subject ? -1 : a.subject > b.subject ? 1 : 0,\n )\n}\n\nexport function loadEvalFile(subject: string, path: string): EvalFile {\n let raw: string\n try {\n raw = readFileSync(path, 'utf8')\n } catch {\n throw new SeoError('INVALID_INPUT', `Cannot read eval file for ${subject}.`)\n }\n let doc: unknown\n try {\n doc = JSON.parse(raw)\n } catch {\n throw new SeoError(\n 'INVALID_INPUT',\n `Eval file ${subject}.json is not valid JSON.`,\n )\n }\n if (!doc || typeof doc !== 'object' || Array.isArray(doc)) {\n throw new SeoError(\n 'INVALID_INPUT',\n `Eval file ${subject}.json must be an object.`,\n )\n }\n const record = doc as Record<string, unknown>\n if (record.subject !== subject) {\n throw new SeoError(\n 'INVALID_INPUT',\n `Eval file ${subject}.json must set subject to \"${subject}\".`,\n )\n }\n if (!Array.isArray(record.evals) || record.evals.length === 0) {\n throw new SeoError(\n 'INVALID_INPUT',\n `Eval file ${subject}.json must have a non-empty evals array.`,\n )\n }\n const seen = new Set<number>()\n const evals: EvalItem[] = record.evals.map((entry, index) => {\n const item = entry as Record<string, unknown>\n const label = `${subject}.json eval ${index + 1}`\n if (!Number.isInteger(item?.id)) {\n throw new SeoError('INVALID_INPUT', `${label}: id must be an integer.`)\n }\n const id = item.id as number\n if (seen.has(id)) {\n throw new SeoError('INVALID_INPUT', `${label}: duplicate id ${id}.`)\n }\n seen.add(id)\n if (typeof item.prompt !== 'string' || item.prompt.trim().length === 0) {\n throw new SeoError(\n 'INVALID_INPUT',\n `${label}: prompt must be a non-empty string.`,\n )\n }\n if (\n typeof item.expected_output !== 'string' ||\n item.expected_output.trim().length === 0\n ) {\n throw new SeoError(\n 'INVALID_INPUT',\n `${label}: expected_output must be a non-empty string.`,\n )\n }\n if (\n !Array.isArray(item.assertions) ||\n item.assertions.length === 0 ||\n item.assertions.some(\n (value) => typeof value !== 'string' || value.trim().length === 0,\n )\n ) {\n throw new SeoError(\n 'INVALID_INPUT',\n `${label}: assertions must be a non-empty array of non-empty strings.`,\n )\n }\n if (item.files !== undefined && !Array.isArray(item.files)) {\n throw new SeoError('INVALID_INPUT', `${label}: files must be an array.`)\n }\n return {\n id,\n prompt: item.prompt,\n expected_output: item.expected_output,\n assertions: item.assertions as string[],\n files: (item.files as string[] | undefined) ?? [],\n }\n })\n return { subject, evals }\n}\n\nfunction routerSkillBody(): string {\n const path = join(skillsDirectory(), ROUTER_SKILL, 'SKILL.md')\n if (!existsSync(path)) {\n throw new SeoError(\n 'INTERNAL_ERROR',\n 'The seo router skill could not be found. Reinstall `seo` or use --no-skill.',\n )\n }\n return readFileSync(path, 'utf8')\n}\n\n// Split a command template into argv tokens without a shell. Single quotes,\n// double quotes, and backslash escapes group tokens; nothing is expanded, so a\n// substituted prompt can never break out into extra arguments or shell syntax.\nexport function tokenizeCommand(command: string): string[] {\n const tokens: string[] = []\n let current = ''\n let started = false\n let inSingle = false\n let inDouble = false\n for (let i = 0; i < command.length; i += 1) {\n const ch = command[i] as string\n if (inSingle) {\n if (ch === \"'\") inSingle = false\n else current += ch\n started = true\n continue\n }\n if (inDouble) {\n if (ch === '\"') {\n inDouble = false\n } else if (\n ch === '\\\\' &&\n (command[i + 1] === '\"' || command[i + 1] === '\\\\')\n ) {\n current += command[i + 1]\n i += 1\n } else {\n current += ch\n }\n started = true\n continue\n }\n if (ch === \"'\") {\n inSingle = true\n started = true\n continue\n }\n if (ch === '\"') {\n inDouble = true\n started = true\n continue\n }\n if (ch === '\\\\') {\n if (i + 1 < command.length) {\n current += command[i + 1]\n i += 1\n started = true\n }\n continue\n }\n if (ch === ' ' || ch === '\\t' || ch === '\\n' || ch === '\\r') {\n if (started) {\n tokens.push(current)\n current = ''\n started = false\n }\n continue\n }\n current += ch\n started = true\n }\n if (inSingle || inDouble) {\n throw new SeoError('INVALID_INPUT', 'Unbalanced quote in agent command.')\n }\n if (started) tokens.push(current)\n return tokens\n}\n\nexport function buildArgv(\n template: string,\n prompt: string,\n): { argv: string[]; usesPlaceholder: boolean } {\n const tokens = tokenizeCommand(template)\n if (tokens.length === 0) {\n throw new SeoError('INVALID_INPUT', 'Agent command must not be empty.')\n }\n const usesPlaceholder = tokens.some((token) => token.includes('{prompt}'))\n const argv = usesPlaceholder\n ? tokens.map((token) => token.split('{prompt}').join(prompt))\n : tokens\n return { argv, usesPlaceholder }\n}\n\nexport function assembleAgentPrompt(\n skillBody: string | null,\n prompt: string,\n): string {\n if (!skillBody) return prompt\n return `${skillBody.trim()}\\n\\n---\\n\\nUser request:\\n${prompt}`\n}\n\nconst JUDGE_CORRECTION =\n 'Your previous reply could not be parsed as the required JSON with one result per assertion. Reply again with STRICT JSON only, in the exact shape shown, and nothing else.'\n\nexport function buildJudgePrompt(\n prompt: string,\n reply: string,\n assertions: string[],\n corrective = false,\n): string {\n const list = assertions\n .map((entry, index) => `${index + 1}. ${entry}`)\n .join('\\n')\n const base = [\n 'You are judging whether an AI agent response satisfies a list of assertions.',\n 'Judge only against the assertions. Be strict but fair.',\n '',\n 'Original request:',\n prompt,\n '',\n 'Agent response:',\n reply,\n '',\n 'Assertions to evaluate, in this exact order:',\n '<assertions>',\n list,\n '</assertions>',\n '',\n 'Judge outcomes, not narration. An assertion about reading, checking, or',\n 'following fields or steps passes when the reply demonstrably used that',\n 'information or produced the result it protects, even if the reply never',\n 'names the field or step. Fail it only when the reply contradicts it or',\n 'shows the work was not done.',\n '',\n 'Reply with STRICT JSON only. No prose, no markdown, no code fence:',\n '{\"results\":[{\"assertion\":\"<assertion text>\",\"pass\":true,\"reason\":\"<short reason>\"}]}',\n `Return exactly ${assertions.length} result${assertions.length === 1 ? '' : 's'}, one per assertion, in the same order.`,\n ].join('\\n')\n return corrective ? `${base}\\n\\n${JUDGE_CORRECTION}` : base\n}\n\n// Pull the first complete JSON object out of a larger reply. Judges wrap JSON\n// in prose or code fences, so scan for the first balanced `{...}` and parse it.\nexport function extractJsonObject(text: string): unknown | undefined {\n const start = text.indexOf('{')\n if (start === -1) return undefined\n let depth = 0\n let inString = false\n let escaped = false\n for (let i = start; i < text.length; i += 1) {\n const ch = text[i]\n if (inString) {\n if (escaped) escaped = false\n else if (ch === '\\\\') escaped = true\n else if (ch === '\"') inString = false\n continue\n }\n if (ch === '\"') inString = true\n else if (ch === '{') depth += 1\n else if (ch === '}') {\n depth -= 1\n if (depth === 0) {\n try {\n return JSON.parse(text.slice(start, i + 1))\n } catch {\n return undefined\n }\n }\n }\n }\n return undefined\n}\n\ntype ParsedVerdicts = { verdicts: AssertionVerdict[] } | { error: string }\n\nexport function parseJudgeVerdicts(\n output: string,\n assertions: string[],\n): ParsedVerdicts {\n const parsed = extractJsonObject(output)\n if (!parsed || typeof parsed !== 'object') {\n return { error: 'Judge reply did not contain a JSON object.' }\n }\n const results = (parsed as Record<string, unknown>).results\n if (!Array.isArray(results)) {\n return { error: 'Judge reply had no results array.' }\n }\n if (results.length !== assertions.length) {\n return {\n error: `Judge returned ${results.length} results for ${assertions.length} assertions.`,\n }\n }\n const verdicts = assertions.map((assertion, index) => {\n const entry = results[index] as Record<string, unknown>\n return {\n assertion,\n verdict: entry?.pass === true ? 'pass' : 'fail',\n reason:\n typeof entry?.reason === 'string' && entry.reason.trim().length > 0\n ? entry.reason.trim()\n : 'No reason given.',\n source: 'judge verdict' as const,\n } satisfies AssertionVerdict\n })\n return { verdicts }\n}\n\ntype ProcessResult = {\n stdout: string\n stderr: string\n code: number | null\n timedOut: boolean\n spawnError?: string\n durationMs: number\n}\n\nfunction runProcess(\n argv: string[],\n options: { input?: string; timeoutMs: number },\n): Promise<ProcessResult> {\n return new Promise((resolvePromise) => {\n const start = Date.now()\n const [command, ...rest] = argv\n let child: ReturnType<typeof spawn>\n try {\n child = spawn(command as string, rest, {\n stdio: ['pipe', 'pipe', 'pipe'],\n })\n } catch (error) {\n resolvePromise({\n stdout: '',\n stderr: '',\n code: null,\n timedOut: false,\n spawnError: error instanceof Error ? error.message : String(error),\n durationMs: Date.now() - start,\n })\n return\n }\n let stdout = ''\n let stderr = ''\n let settled = false\n let timedOut = false\n let killTimer: NodeJS.Timeout | undefined\n const timer = setTimeout(() => {\n timedOut = true\n child.kill('SIGTERM')\n killTimer = setTimeout(() => {\n try {\n child.kill('SIGKILL')\n } catch {\n // process already gone\n }\n }, 2000)\n killTimer.unref()\n }, options.timeoutMs)\n const finish = (result: Omit<ProcessResult, 'durationMs'>) => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n if (killTimer) clearTimeout(killTimer)\n resolvePromise({ ...result, durationMs: Date.now() - start })\n }\n child.stdout?.on('data', (chunk) => {\n stdout += chunk\n })\n child.stderr?.on('data', (chunk) => {\n stderr += chunk\n })\n child.on('error', (error) => {\n finish({\n stdout,\n stderr,\n code: null,\n timedOut,\n spawnError: error.message,\n })\n })\n child.on('close', (code) => {\n finish({ stdout, stderr, code, timedOut })\n })\n if (child.stdin) {\n if (options.input !== undefined) child.stdin.end(options.input)\n else child.stdin.end()\n }\n })\n}\n\nasync function runCommandTemplate(\n template: string,\n prompt: string,\n timeoutMs: number,\n): Promise<ProcessResult> {\n const { argv, usesPlaceholder } = buildArgv(template, prompt)\n return runProcess(argv, {\n input: usesPlaceholder ? undefined : prompt,\n timeoutMs,\n })\n}\n\ntype RunOptions = {\n agent: string\n judge: string | null\n skillBody: string | null\n timeoutMs: number\n}\n\nasync function runSingleEval(\n item: EvalItem,\n options: RunOptions,\n): Promise<EvalResult> {\n const start = Date.now()\n const agentPrompt = assembleAgentPrompt(options.skillBody, item.prompt)\n const agentRun = await runCommandTemplate(\n options.agent,\n agentPrompt,\n options.timeoutMs,\n )\n const reply = agentRun.stdout.trim()\n\n const base = {\n id: item.id,\n prompt: item.prompt,\n reply,\n agentDurationMs: agentRun.durationMs,\n }\n\n if (agentRun.spawnError) {\n return {\n ...base,\n status: 'errored',\n error: `Agent command failed to start: ${agentRun.spawnError}`,\n durationMs: Date.now() - start,\n assertions: unjudgedAssertions(item.assertions),\n }\n }\n if (agentRun.timedOut) {\n return {\n ...base,\n status: 'errored',\n error: `Agent timed out after ${Math.round(options.timeoutMs / 1000)}s.`,\n durationMs: Date.now() - start,\n assertions: unjudgedAssertions(item.assertions),\n }\n }\n if (reply.length === 0) {\n return {\n ...base,\n status: 'errored',\n error: 'Agent returned no output on stdout.',\n durationMs: Date.now() - start,\n assertions: unjudgedAssertions(item.assertions),\n }\n }\n\n if (!options.judge) {\n return {\n ...base,\n status: 'unjudged',\n durationMs: Date.now() - start,\n assertions: unjudgedAssertions(item.assertions),\n }\n }\n\n let judgeDurationMs = 0\n let parseError = ''\n for (let attempt = 0; attempt < 2; attempt += 1) {\n const judgePrompt = buildJudgePrompt(\n item.prompt,\n reply,\n item.assertions,\n attempt > 0,\n )\n const judgeRun = await runCommandTemplate(\n options.judge,\n judgePrompt,\n options.timeoutMs,\n )\n judgeDurationMs += judgeRun.durationMs\n if (judgeRun.spawnError) {\n return {\n ...base,\n status: 'errored',\n error: `Judge command failed to start: ${judgeRun.spawnError}`,\n judgeDurationMs,\n durationMs: Date.now() - start,\n assertions: unjudgedAssertions(item.assertions),\n }\n }\n if (judgeRun.timedOut) {\n return {\n ...base,\n status: 'errored',\n error: `Judge timed out after ${Math.round(options.timeoutMs / 1000)}s.`,\n judgeDurationMs,\n durationMs: Date.now() - start,\n assertions: unjudgedAssertions(item.assertions),\n }\n }\n const parsed = parseJudgeVerdicts(judgeRun.stdout, item.assertions)\n if ('verdicts' in parsed) {\n const failed = parsed.verdicts.some((entry) => entry.verdict === 'fail')\n return {\n ...base,\n status: failed ? 'failed' : 'passed',\n judgeDurationMs,\n durationMs: Date.now() - start,\n assertions: parsed.verdicts,\n }\n }\n parseError = parsed.error\n }\n\n return {\n ...base,\n status: 'errored',\n error: `Judge output could not be parsed after a retry: ${parseError}`,\n judgeDurationMs,\n durationMs: Date.now() - start,\n assertions: unjudgedAssertions(item.assertions),\n }\n}\n\nfunction unjudgedAssertions(assertions: string[]): AssertionVerdict[] {\n return assertions.map((assertion) => ({ assertion, verdict: 'unjudged' }))\n}\n\nasync function mapWithConcurrency<T, R>(\n items: T[],\n limit: number,\n fn: (item: T, index: number) => Promise<R>,\n): Promise<R[]> {\n const results = new Array<R>(items.length)\n let next = 0\n const worker = async () => {\n while (true) {\n const index = next\n next += 1\n if (index >= items.length) return\n results[index] = await fn(items[index] as T, index)\n }\n }\n const size = Math.max(1, Math.min(limit, items.length))\n await Promise.all(Array.from({ length: size }, () => worker()))\n return results\n}\n\nfunction tally(evals: EvalResult[]): {\n passed: number\n failed: number\n errored: number\n unjudged: number\n} {\n const counts = { passed: 0, failed: 0, errored: 0, unjudged: 0 }\n for (const item of evals) counts[item.status] += 1\n return counts\n}\n\nfunction collectSubjects(args: Record<string, unknown>): string[] {\n const raw: string[] = []\n const first = stringArg(args.subject)\n if (first) raw.push(first)\n const rest = args._\n if (Array.isArray(rest)) {\n for (const value of rest) {\n if (typeof value === 'string' && value.length > 0) raw.push(value)\n }\n }\n return [...new Set(raw)]\n}\n\nfunction resolveSelectedSubjects(requested: string[]): Array<{\n subject: string\n path: string\n}> {\n const available = listSubjectFiles()\n if (requested.length === 0) return available\n const byName = new Map(available.map((entry) => [entry.subject, entry]))\n return requested.map((subject) => {\n const match = byName.get(subject)\n if (!match) {\n const known = available.map((entry) => entry.subject).join(', ')\n throw new SeoError(\n 'INVALID_INPUT',\n `Unknown eval subject: ${subject}.${known ? ` Known subjects: ${known}.` : ''}`,\n )\n }\n return match\n })\n}\n\nfunction renderList(json: boolean): void {\n const subjects = listSubjectFiles().map((entry) => {\n const doc = loadEvalFile(entry.subject, entry.path)\n return { subject: entry.subject, evals: doc.evals.length }\n })\n if (json) {\n printJson({ schemaVersion: SCHEMA_VERSION, subjects })\n return\n }\n if (subjects.length === 0) {\n process.stdout.write('No eval subjects found.\\n')\n return\n }\n const width = Math.max(...subjects.map((entry) => entry.subject.length))\n process.stdout.write('Eval subjects\\n')\n for (const entry of subjects) {\n const label = entry.evals === 1 ? 'eval' : 'evals'\n process.stdout.write(\n ` ${entry.subject.padEnd(width)} ${entry.evals} ${label}\\n`,\n )\n }\n}\n\nfunction statusLabel(status: EvalStatus): string {\n if (status === 'passed') return 'PASS'\n if (status === 'failed') return 'FAIL'\n if (status === 'errored') return 'ERROR'\n return 'UNJUDGED'\n}\n\nfunction renderHuman(\n subjects: SubjectResult[],\n options: { judged: boolean; agent: string; judge: string | null },\n): void {\n if (options.judged) {\n process.stdout.write(\n 'Assertion verdicts below are judge verdicts, model judgments from the judge agent, not ground truth.\\n\\n',\n )\n } else {\n process.stdout.write(\n 'Judging was skipped. Review each agent reply against the assertion checklist by hand.\\n\\n',\n )\n }\n for (const subject of subjects) {\n process.stdout.write(`# ${subject.subject}\\n`)\n for (const item of subject.evals) {\n process.stdout.write(\n `\\n[${statusLabel(item.status)}] eval ${item.id} (${item.durationMs}ms)\\n`,\n )\n process.stdout.write(` prompt: ${truncate(item.prompt, 100)}\\n`)\n if (item.error) {\n process.stdout.write(` error: ${item.error}\\n`)\n }\n if (!options.judged) {\n process.stdout.write(` reply: ${truncate(item.reply, 200)}\\n`)\n process.stdout.write(' assertions to review:\\n')\n for (const verdict of item.assertions) {\n process.stdout.write(` - [ ] ${verdict.assertion}\\n`)\n }\n continue\n }\n for (const verdict of item.assertions) {\n const mark =\n verdict.verdict === 'pass'\n ? 'pass'\n : verdict.verdict === 'fail'\n ? 'fail'\n : 'unjudged'\n process.stdout.write(` - ${mark}: ${verdict.assertion}\\n`)\n if (verdict.reason) {\n process.stdout.write(` judge verdict: ${verdict.reason}\\n`)\n }\n }\n }\n const counts = tally(subject.evals)\n process.stdout.write(\n `\\nSubject ${subject.subject}: ${counts.passed} passed, ${counts.failed} failed, ${counts.errored} errored${counts.unjudged ? `, ${counts.unjudged} unjudged` : ''}.\\n\\n`,\n )\n }\n const totals = totalCounts(subjects)\n process.stdout.write(\n `Totals: ${totals.passed} passed, ${totals.failed} failed, ${totals.errored} errored${totals.unjudged ? `, ${totals.unjudged} unjudged` : ''} across ${totals.evals} evals.\\n`,\n )\n}\n\nfunction totalCounts(subjects: SubjectResult[]): {\n passed: number\n failed: number\n errored: number\n unjudged: number\n evals: number\n} {\n const totals = { passed: 0, failed: 0, errored: 0, unjudged: 0, evals: 0 }\n for (const subject of subjects) {\n totals.passed += subject.passed\n totals.failed += subject.failed\n totals.errored += subject.errored\n totals.unjudged += subject.unjudged\n totals.evals += subject.evals.length\n }\n return totals\n}\n\nfunction truncate(value: string, max: number): string {\n const collapsed = value.replace(/\\s+/g, ' ').trim()\n return collapsed.length > max ? `${collapsed.slice(0, max - 1)}…` : collapsed\n}\n\nexport const skillsEvalCommand = defineCommand({\n meta: {\n name: 'eval',\n description:\n 'Run behaviour evals for the seo skill against a local agent and judge the results',\n },\n args: {\n subject: {\n type: 'positional',\n required: false,\n description:\n 'Eval subject (report id or job). Omit to run every subject.',\n },\n list: {\n type: 'boolean',\n default: false,\n description: 'List eval subjects with their eval counts and exit.',\n },\n id: {\n type: 'string',\n description: 'Run one eval id within a single subject.',\n },\n agent: {\n type: 'string',\n default: DEFAULT_AGENT,\n description:\n 'Agent command. Use {prompt} to place the prompt in argv, otherwise it is sent on stdin.',\n },\n 'judge-agent': {\n type: 'string',\n description: 'Judge command. Defaults to the same command as --agent.',\n },\n judge: defaultTrueBooleanArg(\n 'Judge assertions with an agent.',\n 'Skip judging and print replies with an assertion checklist.',\n ),\n skill: defaultTrueBooleanArg(\n 'Send the seo router skill as context before the prompt.',\n 'Omit the seo router skill context.',\n ),\n timeout: {\n type: 'string',\n default: String(DEFAULT_TIMEOUT_SECONDS),\n description: 'Timeout in seconds per agent or judge call.',\n },\n concurrency: {\n type: 'string',\n default: '1',\n description: `Evals to run in parallel (max ${MAX_CONCURRENCY}).`,\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n\n if (args.list === true) {\n renderList(json)\n return\n }\n\n const requested = collectSubjects(args)\n const selected = resolveSelectedSubjects(requested)\n\n const idFilter = numberArg(args.id)\n if (idFilter !== undefined && selected.length !== 1) {\n throw new SeoError(\n 'INVALID_INPUT',\n '--id needs exactly one subject. Name the subject to filter.',\n )\n }\n\n const timeoutSeconds = numberArg(args.timeout) ?? DEFAULT_TIMEOUT_SECONDS\n if (!(timeoutSeconds > 0)) {\n throw new SeoError(\n 'INVALID_INPUT',\n '--timeout must be a positive number of seconds.',\n )\n }\n const concurrency = Math.max(\n 1,\n Math.min(MAX_CONCURRENCY, numberArg(args.concurrency) ?? 1),\n )\n\n const agent = stringArg(args.agent) ?? DEFAULT_AGENT\n const judgeEnabled = args.judge !== false\n const judge = judgeEnabled\n ? (stringArg(args['judge-agent']) ?? agent)\n : null\n const skillBody = args.skill === false ? null : routerSkillBody()\n\n const runOptions: RunOptions = {\n agent,\n judge,\n skillBody,\n timeoutMs: timeoutSeconds * 1000,\n }\n\n const subjectResults: SubjectResult[] = []\n for (const entry of selected) {\n const doc = loadEvalFile(entry.subject, entry.path)\n let items = doc.evals\n if (idFilter !== undefined) {\n items = items.filter((item) => item.id === idFilter)\n if (items.length === 0) {\n throw new SeoError(\n 'INVALID_INPUT',\n `No eval with id ${idFilter} in subject ${entry.subject}.`,\n )\n }\n }\n if (!json) {\n process.stderr.write(\n `Running ${items.length} eval${items.length === 1 ? '' : 's'} for ${entry.subject}...\\n`,\n )\n }\n const evals = await mapWithConcurrency(items, concurrency, (item) =>\n runSingleEval(item, runOptions),\n )\n const counts = tally(evals)\n subjectResults.push({ subject: entry.subject, ...counts, evals })\n }\n\n const totals = totalCounts(subjectResults)\n const failed = totals.failed > 0 || totals.errored > 0\n\n if (json) {\n printJson({\n schemaVersion: SCHEMA_VERSION,\n agent,\n judge,\n judged: judge !== null,\n skillContext: skillBody !== null,\n timeoutSeconds,\n concurrency,\n subjects: subjectResults,\n totals,\n })\n } else {\n renderHuman(subjectResults, { judged: judge !== null, agent, judge })\n }\n\n if (failed) process.exitCode = 1\n },\n})\n","import { existsSync, readdirSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { SeoError } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { jsonFlag, stringArg } from '../args.js'\nimport { printJson, printTable } from '../utils.js'\nimport { readSkillDescription, skillsDirectory } from './skill-paths.js'\nimport { skillsEvalCommand } from './skills-eval.js'\n\ntype SkillInfo = {\n name: string\n description: string\n path: string\n}\n\nfunction listSkills(): SkillInfo[] {\n const root = skillsDirectory()\n return readdirSync(root, { withFileTypes: true })\n .filter(\n (entry) =>\n entry.isDirectory() && existsSync(join(root, entry.name, 'SKILL.md')),\n )\n .map((entry) => ({\n name: entry.name,\n description: readSkillDescription(join(root, entry.name)),\n path: join(root, entry.name),\n }))\n .sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0))\n}\n\nfunction selectedSkill(name?: string): SkillInfo[] {\n const skills = listSkills()\n if (!name) return skills\n const skill = skills.find((entry) => entry.name === name)\n if (!skill) {\n throw new SeoError('INVALID_INPUT', `Unknown skill: ${name}.`)\n }\n return [skill]\n}\n\nconst listCommand = defineCommand({\n meta: { name: 'list', description: 'Show the packaged SEO skill' },\n args: {\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: ({ args }) => {\n const skills = listSkills()\n if (jsonFlag(args)) {\n printJson({ skills })\n return\n }\n printTable(\n ['Skill', 'Description'],\n skills.map((skill) => [skill.name, skill.description]),\n )\n },\n})\n\nconst pathCommand = defineCommand({\n meta: { name: 'path', description: 'Print a packaged agent skill path' },\n args: {\n name: {\n type: 'positional',\n description: 'Skill name. Omit it for the skill directory.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: ({ args }) => {\n const name = stringArg(args.name)\n const path = name ? selectedSkill(name)[0]?.path : skillsDirectory()\n if (jsonFlag(args)) {\n printJson({ name, path })\n } else {\n process.stdout.write(`${path}\\n`)\n }\n },\n})\n\nexport const skillsCommand = defineCommand({\n meta: {\n name: 'skill',\n description: 'Inspect the packaged SEO skill and run its evals',\n },\n subCommands: {\n list: listCommand,\n path: pathCommand,\n eval: skillsEvalCommand,\n },\n})\n","import { rmSync } from 'node:fs'\nimport { cancel, confirm } from '@clack/prompts'\nimport {\n deleteTokens,\n getCacheStats,\n getPrivacySnapshot,\n getSeoCliPaths,\n listSearchUpdates,\n listSites,\n SeoError,\n} from '@seo/core'\nimport { defineCommand } from 'citty'\nimport { booleanArg, jsonFlag, numberArg, stringArg } from '../args.js'\nimport {\n canPrompt,\n formatBytes,\n maybeExitCancelled,\n printJson,\n printKeyValue,\n printTable,\n} from '../utils.js'\n\nexport const privacyCommand = defineCommand({\n meta: {\n name: 'privacy',\n description: 'Show local config, token, cache, and log storage paths',\n },\n run: async () => {\n const snapshot = getPrivacySnapshot()\n const stats = getCacheStats()\n printKeyValue(\n snapshot.map((item) => [\n item.label,\n `${item.path} · ${formatBytes(item.sizeBytes)} · ${item.mode}`,\n ]),\n )\n process.stdout.write('\\n')\n printKeyValue(\n Object.entries(stats.counts).map(([key, value]) => [key, String(value)]),\n )\n },\n})\n\nexport const resetCommand = defineCommand({\n meta: {\n name: 'reset',\n description: 'Delete local seo config, tokens, cache, and logs',\n },\n args: {\n yes: {\n type: 'boolean',\n default: false,\n description: 'Confirm deletion without prompting.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const paths = getSeoCliPaths()\n const json = jsonFlag(args)\n if (!args.yes && !canPrompt({ json })) {\n throw new SeoError(\n 'INVALID_INPUT',\n 'Cannot prompt here. Pass --yes to confirm reset.',\n )\n }\n const approved = args.yes\n ? true\n : maybeExitCancelled(\n await confirm({\n message: 'Delete config, tokens, cache, and logs?',\n initialValue: false,\n }),\n )\n if (!approved) {\n cancel('Reset aborted.')\n return\n }\n await deleteTokens()\n rmSync(paths.configDir, { recursive: true, force: true })\n rmSync(paths.cacheDir, { recursive: true, force: true })\n rmSync(paths.logDir, { recursive: true, force: true })\n if (json) {\n printJson({ reset: true })\n } else {\n process.stdout.write('Reset complete.\\n')\n }\n },\n})\n\nexport const sitesCommand = defineCommand({\n meta: {\n name: 'sites',\n description:\n 'List Search Console properties available to this Google login',\n },\n args: {\n json: { type: 'boolean', default: false },\n refresh: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const sites = await listSites(booleanArg(args.refresh))\n if (jsonFlag(args)) {\n printJson({ sites })\n return\n }\n printTable(\n ['Property', 'Permission'],\n sites.map((site) => [site.siteUrl, site.permissionLevel ?? 'unknown']),\n )\n },\n})\n\nexport const updatesCommand = defineCommand({\n meta: {\n name: 'updates',\n description: 'List official Google Search Status ranking updates',\n },\n args: {\n product: { type: 'string', default: 'Ranking' },\n limit: { type: 'string', default: '10' },\n json: { type: 'boolean', default: false },\n },\n run: async ({ args }) => {\n const updates = await listSearchUpdates({\n product: stringArg(args.product),\n limit: numberArg(args.limit),\n })\n if (jsonFlag(args)) {\n printJson({ updates })\n return\n }\n printTable(\n ['Start', 'End', 'Type', 'Name', 'Status'],\n updates.map((update) => [\n update.start.slice(0, 10),\n update.end?.slice(0, 10) ?? 'open',\n update.type,\n update.name,\n update.status,\n ]),\n )\n },\n})\n","import { readFile } from 'node:fs/promises'\nimport { crawlImplementationQueueWorkflow } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n csvArg,\n fetchRateArg,\n jsonFlag,\n negatedBooleanArg,\n numberArg,\n projectArg,\n stringArg,\n} from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson, printTable } from '../../utils.js'\nimport { printActionDetails } from '../output.js'\nimport { startUrlForSite } from '../shared.js'\nimport { printWorkflow } from './output.js'\n\nexport const crawlQueueCommand = defineCommand({\n meta: {\n name: 'crawl-queue',\n description: 'Run a crawl and return a ranked implementation queue',\n },\n args: {\n crawlUrl: {\n type: 'positional',\n required: false,\n description: 'Start URL to crawl.',\n },\n url: {\n type: 'string',\n description:\n 'Start URL to crawl. Optional when --project has a saved crawl URL.',\n },\n site: {\n type: 'string',\n description: 'GSC property URL for joining page metrics.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n 'ga4-property': {\n type: 'string',\n description:\n 'GA4 property ID for landing-page sessions. Defaults from --project when saved.',\n },\n mode: {\n type: 'string',\n description:\n 'Crawl mode: site, page, list, or sitemap. Defaults to site.',\n },\n urls: {\n type: 'string',\n description: 'Comma-separated URLs for list mode.',\n },\n 'urls-file': {\n type: 'string',\n description: 'File with one URL per line for list mode.',\n },\n 'max-pages': {\n type: 'string',\n description: 'Maximum pages to crawl. Defaults to 500.',\n },\n 'max-depth': {\n type: 'string',\n description: 'Maximum click depth. Defaults to 16.',\n },\n concurrency: {\n type: 'string',\n description: 'Parallel page fetches. Defaults to 8.',\n },\n 'fetch-interval-cap': {\n type: 'string',\n description: 'Maximum page fetches per interval per host.',\n },\n 'fetch-interval-ms': {\n type: 'string',\n description: 'Fetch rate interval in milliseconds.',\n },\n refresh: {\n type: 'boolean',\n default: false,\n description: 'Bypass local HTTP cache and fetch fresh pages.',\n },\n include: {\n type: 'string',\n description: 'Comma-separated URL patterns to include.',\n },\n exclude: {\n type: 'string',\n description: 'Comma-separated URL patterns to exclude.',\n },\n limit: {\n type: 'string',\n description: 'Maximum queue items to print. Defaults to 25.',\n },\n 'no-sitemap': {\n type: 'boolean',\n default: false,\n description: 'Do not seed URLs from sitemap.xml.',\n },\n 'no-robots': {\n type: 'boolean',\n default: false,\n description: 'Do not skip URLs disallowed by robots.txt.',\n },\n 'no-external': {\n type: 'boolean',\n default: false,\n description: 'Do not check external links.',\n },\n js: {\n type: 'boolean',\n default: false,\n description: 'Force JavaScript rendering when Playwright is installed.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const project = projectArg(args)\n const urls = await urlListArgs(args)\n const explicitUrl = crawlUrlArg(args)\n const selection =\n stringArg(args.site) || project || (!explicitUrl && !urls.length)\n ? await resolveClientSelection({\n client: project,\n site: stringArg(args.site),\n options: { json },\n })\n : undefined\n const crawlUrl =\n explicitUrl ??\n selection?.client?.startUrl ??\n (selection?.site ? startUrlForSite(selection.site) : undefined) ??\n urls[0]\n if (!crawlUrl) {\n throw new Error(\n 'No crawl URL selected. Pass a URL, --url, or use --project with a saved crawl URL.',\n )\n }\n\n const report = await crawlImplementationQueueWorkflow({\n url: crawlUrl,\n projectId: selection?.client?.id,\n site: selection?.site,\n mode: crawlModeArg(args.mode) ?? (urls.length ? 'list' : undefined),\n urls,\n maxPages: numberArg(args['max-pages']),\n maxDepth: numberArg(args['max-depth']),\n concurrency: numberArg(args.concurrency),\n refresh: booleanArg(args.refresh),\n fetchRate: fetchRateArg({\n ...args,\n 'fetch-concurrency': args.concurrency,\n }),\n include: csvArg(args.include),\n exclude: csvArg(args.exclude),\n ga4PropertyId:\n stringArg(args['ga4-property']) ?? selection?.client?.ga4PropertyId,\n useSitemap: !negatedBooleanArg(args, 'sitemap'),\n respectRobots: !negatedBooleanArg(args, 'robots'),\n checkExternal: !negatedBooleanArg(args, 'external'),\n js: Boolean(booleanArg(args.js)),\n limit: numberArg(args.limit),\n })\n\n if (json) {\n printJson(report)\n return\n }\n\n printWorkflow(report)\n printTable(\n ['Rank', 'Score', 'Rule', 'Severity', 'Affected', 'Target', 'Action'],\n report.output.queue.map((item, index) => [\n index + 1,\n item.score,\n item.ruleId,\n item.severity,\n item.affectedUrls,\n item.target,\n item.action,\n ]),\n )\n printActionDetails(\n 'Implementation queue details',\n report.output.queue.map((item) => ({\n label: `${item.ruleId} (${item.affectedUrls} URLs)`,\n context: `${item.severity}, score ${item.score}`,\n action: `${item.action} Verify with: ${item.verification.command}`,\n })),\n )\n },\n})\n\nfunction crawlModeArg(value: unknown) {\n const mode = stringArg(value)\n if (!mode) return undefined\n if (['site', 'page', 'list', 'sitemap'].includes(mode)) {\n return mode as 'site' | 'page' | 'list' | 'sitemap'\n }\n throw new Error('Mode must be one of: site, page, list, sitemap.')\n}\n\nfunction crawlUrlArg(args: Record<string, unknown>): string | undefined {\n const positional = stringArg(args.crawlUrl)\n const flag = stringArg(args.url)\n if (positional && flag && positional !== flag) {\n throw new Error('Use either a URL argument or --url, not both.')\n }\n return positional ?? flag\n}\n\nasync function urlListArgs(args: Record<string, unknown>): Promise<string[]> {\n const urls = csvArg(args.urls) ?? []\n const file = stringArg(args['urls-file'])\n if (file) urls.push(...parseUrlList(await readFile(file, 'utf8')))\n return [...new Set(urls)]\n}\n\nfunction parseUrlList(value: string): string[] {\n return value\n .split(/[\\n,]/)\n .map((item) => item.trim())\n .filter((item) => item && !item.startsWith('#'))\n}\n","import {\n type CrawlReport,\n diagnosePropertyWorkflow,\n resolveTechnicalBaseline,\n reviewObservations,\n SeoError,\n type TechnicalBaseline,\n topFixes,\n} from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n defaultTrueBooleanArg,\n jsonFlag,\n negatedBooleanArg,\n numberArg,\n projectArg,\n stringArg,\n} from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson, printTable } from '../../utils.js'\nimport { truncate } from '../output.js'\nimport { cliReportArgs } from '../report-options.js'\nimport { startUrlForSite } from '../shared.js'\nimport { printWorkflow } from './output.js'\n\ntype DiagnoseWorkflowReport = Awaited<\n ReturnType<typeof diagnosePropertyWorkflow>\n>\n\nfunction compactMainReportJson(\n report: DiagnoseWorkflowReport,\n workflowName?: string,\n) {\n const { narrative } = report.output\n const { diagnosis } = narrative\n\n return {\n ...report,\n ...(workflowName ? { workflow: workflowName } : {}),\n output: {\n narrative: {\n site: narrative.site,\n generatedAt: narrative.generatedAt,\n dataStatus: narrative.dataStatus,\n periodDays: narrative.periodDays,\n period: narrative.period,\n headline: narrative.headline,\n caveats: narrative.caveats,\n sections: narrative.sections,\n priorities: narrative.priorities,\n diagnosis: {\n site: diagnosis.site,\n generatedAt: diagnosis.generatedAt,\n dataStatus: diagnosis.dataStatus,\n summary: diagnosis.summary,\n skippedSections: diagnosis.skippedSections,\n partialReasons: diagnosis.partialReasons,\n priorities: diagnosis.priorities,\n },\n },\n },\n }\n}\n\nfunction shellArg(value: string): string {\n if (/^[A-Za-z0-9_./:@-]+$/.test(value)) {\n return value\n }\n return `'${value.replaceAll(\"'\", \"'\\\\''\")}'`\n}\n\nfunction siteForDirectUrl(url: string): string {\n try {\n return new URL(url).origin\n } catch {\n throw new SeoError('INVALID_INPUT', 'Pass a valid absolute URL with --url.')\n }\n}\n\nfunction addFollowup(\n commands: Array<{ command: string; why: string }>,\n command: string,\n why: string,\n): void {\n if (commands.some((item) => item.command === command)) {\n return\n }\n commands.push({ command, why })\n}\n\nfunction crawlDataSourceLines(\n dataSources: CrawlReport['dataSources'],\n): string[] {\n if (!dataSources) return []\n\n const sourceLine = (input: {\n label: string\n status: string\n joinedPages: number\n totalPages: number\n window?: { days: number }\n warning?: string\n }): string => {\n const range = input.window ? ` in the last ${input.window.days} days` : ''\n const coverage = `for ${input.joinedPages} of ${input.totalPages} crawled URLs`\n\n if (input.status === 'skipped') return `${input.label}: not connected.`\n if (input.status === 'unavailable') {\n return `${input.label}: unavailable. ${input.warning ?? 'No data was joined.'}`\n }\n if (input.status === 'partial') {\n return `${input.label}: partial data ${coverage}${range}. ${input.warning ?? ''}`.trim()\n }\n if (input.status === 'none') {\n return `${input.label}: no matching crawled URLs${range}.`\n }\n return `${input.label}: joined ${coverage}${range}.`\n }\n\n return [\n sourceLine({\n label: 'Search Console',\n status: dataSources.searchConsole.status,\n joinedPages: Math.max(\n dataSources.searchConsole.joinedMetricPages,\n dataSources.searchConsole.joinedQueryPages,\n ),\n totalPages: dataSources.searchConsole.totalPages,\n window: dataSources.searchConsole.window,\n warning: dataSources.searchConsole.warning,\n }),\n sourceLine({\n label: 'GA4',\n status: dataSources.analytics.status,\n joinedPages: dataSources.analytics.joinedPages,\n totalPages: dataSources.analytics.totalPages,\n window: dataSources.analytics.window,\n warning: dataSources.analytics.warning,\n }),\n ]\n}\n\nfunction technicalSection(baseline: TechnicalBaseline) {\n const report = baseline.report\n if (!report) {\n return {\n status: baseline.status,\n ...(baseline.reason ? { reason: baseline.reason } : {}),\n }\n }\n return {\n status: baseline.status,\n ...(baseline.reason ? { reason: baseline.reason } : {}),\n reportId: report.id,\n generatedAt: report.generatedAt,\n crawlStatus: report.status,\n capped: report.summary.pageLimitReached,\n maxPages: report.config.maxPages,\n searchDataJoined:\n (report.dataSources?.searchConsole.joinedMetricPages ?? 0) > 0 ||\n (report.dataSources?.searchConsole.joinedQueryPages ?? 0) > 0,\n dataSources: report.dataSources,\n summary: report.summary,\n topFixes: topFixes(report, { limit: 5 }),\n reviewObservations: reviewObservations(report, { limit: 5 }),\n }\n}\n\nfunction compactTechnicalFinding(finding: ReturnType<typeof topFixes>[number]) {\n return {\n ruleId: finding.ruleId,\n title: finding.title,\n category: finding.category,\n severity: finding.severity,\n recommendation: finding.recommendation,\n count: finding.count,\n sampleUrls: finding.sampleUrls.slice(0, 3),\n score: finding.score,\n scoreFactors: finding.scoreFactors,\n whyThisRanks: finding.whyThisRanks,\n detailsCommand: `seo explain --rule ${finding.ruleId}`,\n }\n}\n\nfunction compactTechnicalSection(section: ReturnType<typeof technicalSection>) {\n if (!('topFixes' in section)) return section\n\n return {\n ...section,\n topFixes: section.topFixes.slice(0, 3).map(compactTechnicalFinding),\n reviewObservations: section.reviewObservations\n .slice(0, 3)\n .map(compactTechnicalFinding),\n }\n}\n\nfunction printTechnicalSection(\n section: ReturnType<typeof technicalSection>,\n): void {\n if (!('topFixes' in section)) {\n process.stdout.write(\n `\\nTechnical crawl evidence: ${section.reason ?? section.status}\\n`,\n )\n return\n }\n\n const coverage = section.status === 'reused' ? 'saved' : 'new'\n process.stdout.write(`\\nTechnical crawl evidence (${coverage})\\n`)\n if (section.reason) process.stdout.write(`${section.reason}\\n`)\n if (section.capped) {\n process.stdout.write(\n `Coverage is capped at ${section.maxPages} pages. Run \\`seo crawl\\` for a broader investigation.\\n`,\n )\n }\n for (const line of crawlDataSourceLines(section.dataSources)) {\n process.stdout.write(`${line}\\n`)\n }\n if (!section.topFixes.length) {\n process.stdout.write('No prioritised technical fixes were found.\\n')\n if (section.reviewObservations.length) {\n process.stdout.write(\n `${section.reviewObservations.length} review observation${section.reviewObservations.length === 1 ? '' : 's'} need confirmation before they become implementation work.\\n`,\n )\n }\n return\n }\n process.stdout.write(\n section.searchDataJoined\n ? '\\nTechnical fixes with search value\\n'\n : '\\nTechnical fixes (no Search Console data joined)\\n',\n )\n if (!section.searchDataJoined) {\n printTable(\n ['#', 'Rule', 'Severity', 'Affected URLs', 'Verify'],\n section.topFixes.map((fix, index) => [\n index + 1,\n fix.ruleId,\n fix.severity,\n fix.count,\n truncate(fix.howToVerify, 72),\n ]),\n )\n } else {\n printTable(\n ['Score', 'Rule', 'Severity', 'Search value', 'Verify'],\n section.topFixes.map((fix) => [\n fix.score,\n fix.ruleId,\n fix.severity,\n `${fix.scoreFactors.clicks} clicks / ${fix.scoreFactors.sessions} sessions / ${fix.scoreFactors.conversions} conv.`,\n truncate(fix.howToVerify, 72),\n ]),\n )\n }\n if (section.reviewObservations.length) {\n process.stdout.write(\n `\\n${section.reviewObservations.length} review observation${section.reviewObservations.length === 1 ? '' : 's'} were kept out of this action queue.\\n`,\n )\n }\n}\n\nexport function reportFollowups(\n report: DiagnoseWorkflowReport,\n input: {\n crawlStartUrl?: string\n projectId?: string\n technicalBaselineStatus?: TechnicalBaseline['status']\n searchDataAvailable?: boolean\n } = {},\n) {\n if (input.searchDataAvailable === false) {\n const commands: Array<{ command: string; why: string }> = []\n if (\n input.crawlStartUrl &&\n input.technicalBaselineStatus !== 'created' &&\n input.technicalBaselineStatus !== 'refreshed' &&\n input.technicalBaselineStatus !== 'reused'\n ) {\n addFollowup(\n commands,\n `seo crawl --url ${shellArg(input.crawlStartUrl)} --save`,\n 'Create the technical crawl that this report needs before opening a page-level follow-up.',\n )\n } else if (input.crawlStartUrl) {\n addFollowup(\n commands,\n `seo audit-page --url ${shellArg(input.crawlStartUrl)}`,\n 'Inspect one important page in detail after the site-level crawl.',\n )\n }\n addFollowup(\n commands,\n 'seo start',\n 'Connect Search Console when you want traffic, query, and ranking evidence alongside the crawl.',\n )\n return commands\n }\n\n const identity = input.projectId\n ? `--project ${shellArg(input.projectId)}`\n : `--site ${shellArg(report.site)}`\n const diagnosis = report.output.narrative.diagnosis\n const days = diagnosis.decay.rangeDays\n const commands: Array<{ command: string; why: string }> = []\n const skippedNames = new Set(\n (diagnosis.skippedSections ?? []).map((section) => section.section),\n )\n\n addFollowup(\n commands,\n `seo refresh-priorities ${identity} --days ${days} --verify-content --limit 25`,\n 'Turn the report into a ranked action queue with content checks.',\n )\n\n if (diagnosis.decay.summary.eligibleRows > 0) {\n addFollowup(\n commands,\n `seo decaying ${identity} --days ${days} --limit 25`,\n 'Inspect query/page declines observed in both retained-row windows.',\n )\n }\n\n if (diagnosis.cannibalization.items.length > 0) {\n addFollowup(\n commands,\n `seo cannibal ${identity} --days ${days} --limit 25`,\n 'Find queries split across competing URLs.',\n )\n }\n\n if (diagnosis.quickWins.summary.eligibleRows > 0) {\n addFollowup(\n commands,\n `seo quick-wins ${identity} --days ${days} --verify-content --verify-limit 5`,\n 'Review average-position rows below their heuristic CTR target with optional page evidence.',\n )\n }\n\n if (diagnosis.strikingDistance.summary.eligibleRows > 0) {\n addFollowup(\n commands,\n `seo second-page ${identity} --days ${days} --verify-content --verify-limit 5`,\n 'Work pages sitting just outside page-one rankings.',\n )\n }\n\n if (\n skippedNames.has('traffic anomaly') ||\n skippedNames.has('update correlation')\n ) {\n addFollowup(\n commands,\n `seo quick-wins ${identity} --days ${days} --min-impressions 10 --verify-content --verify-limit 5`,\n 'Sparse GSC data: lower thresholds and look for early content wins.',\n )\n addFollowup(\n commands,\n `seo second-page ${identity} --days ${days} --min-impressions 10 --verify-content --verify-limit 5`,\n 'Sparse GSC data: inspect early second-page opportunities.',\n )\n }\n\n const topMovedPage = diagnosis.segments.page.items.find((item) =>\n item.key.startsWith('http'),\n )\n if (topMovedPage) {\n addFollowup(\n commands,\n `seo audit-page --url ${shellArg(topMovedPage.key)}`,\n 'Audit the biggest moved URL for title, metadata, links, and schema.',\n )\n }\n\n if (\n input.crawlStartUrl &&\n input.technicalBaselineStatus !== 'created' &&\n input.technicalBaselineStatus !== 'refreshed' &&\n input.technicalBaselineStatus !== 'reused'\n ) {\n addFollowup(\n commands,\n `seo crawl --url ${shellArg(input.crawlStartUrl)} ${identity} --save`,\n 'Create the first technical crawler baseline with plain-English fixes and JSON-ready issue data.',\n )\n }\n\n addFollowup(\n commands,\n `seo technical-watch ${identity} --limit 50`,\n 'Save a crawl/index baseline so future reports can flag technical drift.',\n )\n\n return commands.slice(0, 6)\n}\n\nfunction printReportFollowups(\n commands: Array<{ command: string; why: string }>,\n): void {\n if (!commands.length) {\n return\n }\n process.stdout.write('\\nRecommended next commands\\n')\n printTable(\n ['Command', 'Why'],\n commands.map((item) => [item.command, item.why]),\n )\n}\n\nfunction printTechnicalOnlyIntro(site: string): void {\n process.stdout.write(`# Technical SEO report: ${site}\\n\\n`)\n process.stdout.write(\n 'Search Console is not connected for this run. The crawl below shows local technical evidence only. Run `seo start` when you want traffic, query, and ranking evidence in the same report.\\n',\n )\n}\n\nfunction workflowCommandMeta(input: {\n name: string\n description: string\n workflowName?: string\n printFollowups?: boolean\n}) {\n return defineCommand({\n meta: input,\n args: {\n site: {\n type: 'string',\n description: 'GSC property URL, for example sc-domain:example.com.',\n },\n ...(input.printFollowups\n ? {\n url: {\n type: 'string' as const,\n description:\n 'Crawl URL for a technical-only report. Search Console analyses are skipped unless you also pass --site or --project.',\n },\n }\n : {}),\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n ...cliReportArgs(\n ['days', 'recentDays', 'limit', 'includeBrand', 'refresh'],\n {\n days: {\n description: 'Search performance window in days. Defaults to 90.',\n },\n limit: {\n description: 'Maximum rows per section. Defaults to 10.',\n },\n },\n ),\n ...(input.printFollowups\n ? {\n crawl: defaultTrueBooleanArg(\n 'Create or reuse a bounded technical crawl before the report.',\n 'Skip technical crawl evidence for this report.',\n ),\n 'crawl-max-pages': {\n type: 'string' as const,\n description:\n 'Maximum pages for the report crawl. Defaults to 100.',\n },\n 'crawl-max-depth': {\n type: 'string' as const,\n description:\n 'Maximum link depth for the report crawl. Defaults to 4.',\n },\n full: {\n type: 'boolean' as const,\n default: false,\n description:\n 'Include the full report in JSON output. Default JSON is a compact summary for agents.',\n },\n }\n : {}),\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const full = input.printFollowups && booleanArg(args.full)\n const project = projectArg(args)\n const explicitSite = stringArg(args.site)\n const directUrl = input.printFollowups ? stringArg(args.url) : undefined\n const useSearchData = Boolean(project || explicitSite || !directUrl)\n const selection = useSearchData\n ? await resolveClientSelection({\n client: project,\n site: explicitSite,\n options: { json, refresh: booleanArg(args.refresh) },\n })\n : undefined\n const site = selection?.site ?? siteForDirectUrl(directUrl ?? '')\n const report = await diagnosePropertyWorkflow({\n site,\n days: numberArg(args.days),\n recentDays: numberArg(args.recent),\n limit: numberArg(args.limit),\n brandTerms: selection?.client?.brandTerms,\n includeBrand: booleanArg(args['include-brand']),\n refresh: booleanArg(args.refresh),\n skipSearchData: !useSearchData,\n })\n const outputReport = input.workflowName\n ? { ...report, workflow: input.workflowName }\n : report\n const technicalBaseline = input.printFollowups\n ? await resolveTechnicalBaseline({\n site,\n searchSite: selection?.site,\n url:\n directUrl ?? selection?.client?.startUrl ?? startUrlForSite(site),\n projectId: selection?.client?.id,\n ga4PropertyId: selection?.client?.ga4PropertyId,\n crawl: !negatedBooleanArg(args, 'crawl'),\n refresh: booleanArg(args.refresh),\n maxPages: numberArg(args['crawl-max-pages']),\n maxDepth: numberArg(args['crawl-max-depth']),\n })\n : undefined\n const technicalCrawl = technicalBaseline\n ? technicalSection(technicalBaseline)\n : undefined\n const followups = input.printFollowups\n ? reportFollowups(outputReport, {\n crawlStartUrl:\n directUrl ?? selection?.client?.startUrl ?? startUrlForSite(site),\n projectId: selection?.client?.id,\n technicalBaselineStatus: technicalBaseline?.status,\n searchDataAvailable: useSearchData,\n })\n : undefined\n if (json) {\n const jsonReport =\n input.printFollowups && !full\n ? compactMainReportJson(report, input.workflowName)\n : outputReport\n printJson(\n technicalCrawl || followups\n ? {\n ...jsonReport,\n ...(input.printFollowups\n ? { detail: full ? 'full' : 'summary' }\n : {}),\n ...(technicalCrawl\n ? {\n technicalCrawl:\n input.printFollowups && !full\n ? compactTechnicalSection(technicalCrawl)\n : technicalCrawl,\n }\n : {}),\n ...(followups ? { nextCommands: followups } : {}),\n }\n : jsonReport,\n )\n return\n }\n if (useSearchData) {\n process.stdout.write(`${outputReport.output.narrative.markdown}\\n\\n`)\n printWorkflow(outputReport)\n } else {\n printTechnicalOnlyIntro(site)\n }\n if (technicalCrawl) printTechnicalSection(technicalCrawl)\n if (followups) printReportFollowups(followups)\n },\n })\n}\n\nexport const diagnosePropertyWorkflowCommand = workflowCommandMeta({\n name: 'diagnose-property',\n description: 'Find what changed in Google Search and what to inspect next',\n})\n\nexport const mainReportCommand = workflowCommandMeta({\n name: 'report',\n workflowName: 'report',\n printFollowups: true,\n description:\n 'Run the main SEO report and recommend the next best follow-up commands',\n})\n","import { refreshPrioritiesWorkflow } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n defaultTrueBooleanArg,\n jsonFlag,\n numberArg,\n projectArg,\n stringArg,\n} from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson, printTable } from '../../utils.js'\nimport { printActionDetails } from '../output.js'\nimport { cliReportArgs } from '../report-options.js'\nimport { printWorkflow } from './output.js'\n\nexport const refreshPrioritiesCommand = defineCommand({\n meta: {\n name: 'refresh-priorities',\n description: 'Agent workflow for a ranked SEO action queue',\n },\n args: {\n site: {\n type: 'string',\n description: 'GSC property URL, for example sc-domain:example.com.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n ...cliReportArgs(\n ['days', 'recentDays', 'limit', 'includeBrand', 'refresh'],\n {\n days: {\n description: 'Diagnosis window length in days. Defaults to 90.',\n },\n limit: {\n description: 'Maximum queue items to print. Defaults to 25.',\n },\n },\n ),\n 'ga4-property': {\n type: 'string',\n description:\n 'GA4 property ID to use for analytics value. Defaults from the selected project.',\n },\n 'verify-content': defaultTrueBooleanArg(\n 'Verify top opportunities against page title, meta, and content. Defaults to true.',\n 'Skip page content verification.',\n ),\n 'verify-limit': {\n type: 'string',\n description: 'Maximum opportunity URLs to verify. Defaults to 5.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json, refresh: booleanArg(args.refresh) },\n })\n const report = await refreshPrioritiesWorkflow({\n site: selection.site,\n days: numberArg(args.days),\n recentDays: numberArg(args.recent),\n limit: numberArg(args.limit),\n brandTerms: selection.client?.brandTerms,\n includeBrand: booleanArg(args['include-brand']),\n ga4PropertyId:\n stringArg(args['ga4-property']) ?? selection.client?.ga4PropertyId,\n verifyContent: booleanArg(args['verify-content']),\n verifyLimit: numberArg(args['verify-limit']),\n refresh: booleanArg(args.refresh),\n })\n if (json) {\n printJson(report)\n return\n }\n printWorkflow(report)\n printTable(\n [\n 'Source',\n 'Category',\n 'Score',\n 'Findings',\n 'Template',\n 'GA4',\n 'Target',\n 'Action',\n ],\n report.output.queue.map((item) => [\n item.source,\n item.category,\n item.score,\n item.grouped?.count ?? 1,\n item.template?.label ?? '-',\n item.analytics?.sessions ?? '-',\n item.target,\n item.action,\n ]),\n )\n printActionDetails(\n 'Queue action details',\n report.output.queue.map((item) => ({\n label: item.target,\n context: `${item.category}, score ${item.score}`,\n action: item.action,\n })),\n )\n },\n})\n","import { technicalWatchWorkflow } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n defaultTrueBooleanArg,\n jsonFlag,\n listArg,\n numberArg,\n projectArg,\n stringArg,\n} from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson } from '../../utils.js'\nimport { printMonitoringRun } from '../monitoring/output.js'\nimport { startUrlForSite } from '../shared.js'\n\nexport const technicalWatchCommand = defineCommand({\n meta: {\n name: 'technical-watch',\n description: 'Agent workflow for crawl-diff and index-watch monitoring',\n },\n args: {\n site: {\n type: 'string',\n description: 'GSC property URL, for example sc-domain:example.com.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n url: {\n type: 'string',\n description:\n 'Start URL to crawl. Defaults from the GSC property when possible.',\n },\n urls: {\n type: 'string',\n description: 'Comma-separated URLs to inspect with URL Inspection.',\n },\n sitemaps: {\n type: 'string',\n description:\n 'Comma-separated XML sitemap URLs for quota-aware index monitoring.',\n },\n properties: {\n type: 'string',\n description:\n 'Comma-separated GSC properties for sitemap index monitoring.',\n },\n limit: {\n type: 'string',\n description: 'Maximum pages to crawl. Defaults to 50.',\n },\n 'daily-limit': {\n type: 'string',\n description: 'URL Inspection daily limit per property. Defaults to 2000.',\n },\n 'inspect-limit': {\n type: 'string',\n description:\n 'Maximum sitemap URLs to inspect in this run. Defaults to 100.',\n },\n 'max-urls': {\n type: 'string',\n description:\n 'Maximum sitemap URLs to load for monitoring. Defaults to 50000.',\n },\n language: {\n type: 'string',\n description: 'Optional URL Inspection language code.',\n },\n 'recover-links': defaultTrueBooleanArg(\n 'Check search-value GSC pages for broken, blocked, or poorly redirected URLs. Defaults to true.',\n 'Skip link recovery checks.',\n ),\n 'recover-days': {\n type: 'string',\n description: 'GSC lookback window for link recovery. Defaults to 90.',\n },\n 'recover-limit': {\n type: 'string',\n description:\n 'Maximum search-value pages to check for link recovery. Defaults to 10.',\n },\n 'recover-min-clicks': {\n type: 'string',\n description:\n 'Minimum clicks for link recovery candidates. Defaults to 1.',\n },\n 'recover-min-impressions': {\n type: 'string',\n description:\n 'Minimum impressions for link recovery candidates. Defaults to 100.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n refresh: {\n type: 'boolean',\n default: false,\n description: 'Bypass local HTTP/GSC cache where supported.',\n },\n js: {\n type: 'boolean',\n default: false,\n description: 'Force JavaScript rendering when Playwright is installed.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json, refresh: booleanArg(args.refresh) },\n })\n const watchUrls = listArg(args.urls)\n const sitemaps = listArg(args.sitemaps)\n const startUrl =\n stringArg(args.url) ??\n selection.client?.startUrl ??\n startUrlForSite(selection.site)\n const report = await technicalWatchWorkflow({\n site: selection.site,\n startUrl,\n urls: watchUrls.length ? watchUrls : selection.client?.watchUrls,\n sitemaps: sitemaps.length ? sitemaps : undefined,\n properties: listArg(args.properties).length\n ? listArg(args.properties)\n : undefined,\n limit: numberArg(args.limit),\n languageCode: stringArg(args.language),\n dailyLimit: numberArg(args['daily-limit']),\n inspectLimit: numberArg(args['inspect-limit']),\n maxUrls: numberArg(args['max-urls']),\n refresh: booleanArg(args.refresh),\n js: booleanArg(args.js) ? true : 'auto',\n recoverLinks: booleanArg(args['recover-links']),\n recoverDays: numberArg(args['recover-days']),\n recoverLimit: numberArg(args['recover-limit']),\n recoverMinClicks: numberArg(args['recover-min-clicks']),\n recoverMinImpressions: numberArg(args['recover-min-impressions']),\n })\n if (json) {\n printJson(report)\n return\n }\n printMonitoringRun(report)\n },\n})\n","import { updatePostmortemWorkflow } from '@seo/core'\nimport { defineCommand } from 'citty'\nimport {\n booleanArg,\n jsonFlag,\n numberArg,\n projectArg,\n stringArg,\n} from '../../args.js'\nimport { resolveClientSelection } from '../../selection.js'\nimport { printJson, printKeyValue, printTable } from '../../utils.js'\nimport { printNextCommand, printNotes } from '../output.js'\nimport { cliReportArgs } from '../report-options.js'\n\ntype SegmentSplit = Awaited<\n ReturnType<typeof updatePostmortemWorkflow>\n>['output']['segments']['page']\n\nfunction formatNumber(value: number | null): string {\n if (value === null) return '-'\n return value.toLocaleString('en-GB', {\n maximumFractionDigits: value >= 100 ? 0 : 1,\n })\n}\n\nfunction segmentRows(split: SegmentSplit) {\n return [\n ...split.winners.map((item) => ({ direction: 'winner', item })),\n ...split.losers.map((item) => ({ direction: 'loser', item })),\n ]\n}\n\nfunction printSegmentTable(label: string, split: SegmentSplit): void {\n const rows = segmentRows(split)\n if (!rows.length) return\n process.stdout.write(`\\n${label}\\n`)\n printTable(\n ['Direction', 'Key', 'Clicks', 'Impr.', 'Position'],\n rows.map(({ direction, item }) => [\n direction,\n item.key,\n formatNumber(item.clickDelta),\n formatNumber(item.impressionDelta),\n formatNumber(item.positionDelta),\n ]),\n )\n}\n\nfunction printSegmentCoverage(\n segments: Awaited<\n ReturnType<typeof updatePostmortemWorkflow>\n >['output']['segments'],\n): void {\n process.stdout.write('\\nSegment coverage\\n')\n printTable(\n [\n 'Dimension',\n 'Eligible',\n 'Returned',\n 'Limited',\n 'Result cap',\n 'Source cap',\n 'Source capped',\n ],\n (['page', 'query', 'device', 'country'] as const).map((dimension) => {\n const coverage = segments[dimension].coverage\n return [\n dimension,\n coverage.eligibleRows,\n coverage.returnedRows,\n coverage.limitedRows,\n coverage.resultLimit,\n coverage.sourceRowLimit,\n coverage.sourcePossiblyTruncated ? 'yes' : 'no',\n ]\n }),\n )\n}\n\ntype TemplateMovement = Awaited<\n ReturnType<typeof updatePostmortemWorkflow>\n>['output']['templateMovement'][number]\n\nfunction printTemplateMovement(items: TemplateMovement[]): void {\n if (!items.length) return\n process.stdout.write('\\nTemplate movement\\n')\n printTable(\n [\n 'Direction',\n 'Template',\n 'Pattern confidence',\n 'URLs',\n 'Clicks',\n 'Returned share',\n 'Common terms',\n ],\n items.map((item) => [\n item.direction,\n item.signature,\n item.confidence,\n item.urlCount,\n formatNumber(item.clickDelta),\n `${Math.round(item.movementShare * 100)}%`,\n item.commonTerms.join(', ') || '-',\n ]),\n )\n printNotes(\n 'Template actions',\n items.map((item) => item.summary),\n )\n printNotes('Template evidence scope', [\n 'Shares use returned directional page click movement. Pattern confidence applies only to returned matched-retained page segments.',\n ])\n}\n\nexport const updatePostmortemCommand = defineCommand({\n meta: {\n name: 'update-postmortem',\n description: 'Agent workflow for Google update winner/loser analysis',\n },\n args: {\n site: {\n type: 'string',\n description: 'GSC property URL, for example sc-domain:example.com.',\n },\n client: {\n type: 'string',\n description: 'Legacy alias for --project.',\n },\n project: {\n type: 'string',\n description: 'Saved project id or name.',\n },\n ...cliReportArgs(\n ['days', 'recentDays', 'limit', 'includeBrand', 'refresh'],\n {\n days: {\n description: 'Diagnosis window length in days. Defaults to 90.',\n },\n limit: {\n description: 'Maximum winners/losers per segment. Defaults to 20.',\n },\n },\n ),\n 'known-change': {\n type: 'string',\n description:\n 'Manual site-side change to treat as a confounder, for example pruning pages or blocking traffic.',\n },\n 'ignore-change-log': {\n type: 'boolean',\n default: false,\n description: 'Do not use saved change-log entries as confounders.',\n },\n json: {\n type: 'boolean',\n default: false,\n description: 'Print machine-readable JSON.',\n },\n },\n run: async ({ args }) => {\n const json = jsonFlag(args)\n const selection = await resolveClientSelection({\n client: projectArg(args),\n site: stringArg(args.site),\n options: { json, refresh: booleanArg(args.refresh) },\n })\n const report = await updatePostmortemWorkflow({\n site: selection.site,\n days: numberArg(args.days),\n recentDays: numberArg(args.recent),\n limit: numberArg(args.limit),\n brandTerms: selection.client?.brandTerms,\n includeBrand: booleanArg(args['include-brand']),\n knownConfounders: stringArg(args['known-change'])\n ? [stringArg(args['known-change']) ?? '']\n : undefined,\n includeChangeLog: !booleanArg(args['ignore-change-log']),\n refresh: booleanArg(args.refresh),\n })\n if (json) {\n printJson(report)\n return\n }\n printKeyValue([\n ['Workflow', report.workflow],\n ['Property', report.site],\n ['Summary', report.summary],\n [\n 'Causal attribution',\n report.output.update.attribution.replaceAll('-', ' '),\n ],\n ['Confidence', report.output.update.confidence],\n ['Known confounders', String(report.output.update.confounders.length)],\n ])\n printNotes(\n 'Recommended actions',\n report.actions.map(\n (action) => `${action.title} (${action.confidence}): ${action.action}`,\n ),\n )\n printNotes(\n 'Postmortem findings',\n report.output.insights.map((insight) => insight.summary),\n )\n printNotes(\n 'Segment evidence warnings',\n [\n ...report.output.segments.page.warnings,\n ...report.output.segments.query.warnings,\n ...report.output.segments.device.warnings,\n ...report.output.segments.country.warnings,\n ].filter(\n (warning, index, warnings) => warnings.indexOf(warning) === index,\n ),\n )\n printTemplateMovement(report.output.templateMovement)\n printNotes('Update evidence', report.output.update.evidence)\n printSegmentCoverage(report.output.segments)\n printSegmentTable('Page winners and losers', report.output.segments.page)\n printSegmentTable('Query winners and losers', report.output.segments.query)\n printSegmentTable(\n 'Device winners and losers',\n report.output.segments.device,\n )\n printSegmentTable(\n 'Country winners and losers',\n report.output.segments.country,\n )\n const target = selection.client\n ? `--project ${JSON.stringify(selection.client.id)}`\n : `--site ${JSON.stringify(selection.site)}`\n printNextCommand(`seo export update-postmortem ${target}`)\n },\n})\n","import { SEO_VERSION, seoErrorEnvelope, toSeoError } from '@seo/core'\nimport { defineCommand, runCommand, runMain } from 'citty'\nimport { authCommand } from './commands/auth.js'\nimport { cacheCommand } from './commands/cache.js'\nimport { clientCommand, projectCommand } from './commands/clients/index.js'\nimport { contentCommand } from './commands/content.js'\nimport { crawlCommand } from './commands/crawl.js'\nimport { crawlReportsCommand } from './commands/crawl-reports.js'\nimport {\n ga4ReportCommand,\n gscQueryCommand,\n urlInspectCommand,\n} from './commands/data.js'\nimport {\n trafficAnomalyCommand,\n updateCorrelateCommand,\n} from './commands/diagnosis-reports.js'\nimport { entityReadinessCommand } from './commands/entity-readiness.js'\nimport {\n changeLogCommand,\n contentGroupsCommand,\n testsCommand,\n} from './commands/experiments/index.js'\nimport { exportCommand } from './commands/export/index.js'\nimport { initCommand } from './commands/init.js'\nimport { llmsCommand } from './commands/llms.js'\nimport { mcpCommand } from './commands/mcp.js'\nimport {\n crawlDiffCommand,\n indexCoverageCommand,\n indexWatchCommand,\n linkRecoverCommand,\n monitoringCommand,\n redirectTraceCommand,\n} from './commands/monitoring.js'\nimport { okfCommand } from './commands/okf.js'\nimport {\n aiReferralsCommand,\n cannibalCommand,\n communityIntentCommand,\n ctrUnderperformersCommand,\n decayingCommand,\n internalLinksCommand,\n pageOpportunitiesCommand,\n queryClusterCommand,\n quickWinsCommand,\n secondPageCommand,\n seoToAiQueryCommand,\n} from './commands/opportunities/index.js'\nimport { auditPageCommand } from './commands/page-audit.js'\nimport { performanceCommand } from './commands/performance.js'\nimport {\n diagnoseCommand,\n doctorCommand,\n ga4PropertiesCommand,\n segmentImpactCommand,\n strikingDistanceCommand,\n} from './commands/product/index.js'\nimport { pseoCommand } from './commands/pseo/index.js'\nimport { aiReadinessCommand } from './commands/readiness.js'\nimport { reportCatalogCommand } from './commands/report-catalog.js'\nimport {\n monthlyReportCommand,\n reportNarrativeCommand,\n} from './commands/reports.js'\nimport { explainCommand, rulesCommand } from './commands/rules.js'\nimport { scheduleCommand } from './commands/schedule.js'\nimport { setupCommand, startCommand } from './commands/setup/index.js'\nimport { skillsCommand } from './commands/skills.js'\nimport {\n privacyCommand,\n resetCommand,\n sitesCommand,\n updatesCommand,\n} from './commands/system.js'\nimport {\n crawlQueueCommand,\n diagnosePropertyWorkflowCommand,\n mainReportCommand,\n refreshPrioritiesCommand,\n technicalWatchCommand,\n updatePostmortemCommand,\n} from './commands/workflows/index.js'\nimport { maybeCheckForUpdates } from './utils.js'\n\nconst pkg = {\n name: 'seo',\n version: SEO_VERSION,\n}\n\ntype HelpSection = {\n title: string\n commands: Array<[command: string, description: string]>\n}\n\nconst helpSections: HelpSection[] = [\n {\n title: 'Start here',\n commands: [\n ['seo start', 'Connect Google and save a project profile'],\n ['seo report', 'Run the main SEO report for the default project'],\n ['seo report --site sc-domain:example.com', 'Run without a profile'],\n [\n 'seo report --url https://example.com',\n 'Start with a local technical report',\n ],\n ],\n },\n {\n title: 'Projects',\n commands: [\n ['seo projects list', 'List saved project profiles'],\n ['seo projects add', 'Create or update a project profile'],\n ['seo sites', 'List Search Console properties'],\n ['seo doctor', 'Check local auth and config'],\n ],\n },\n {\n title: 'Act on a report',\n commands: [\n ['seo refresh-priorities', 'Rank the next best SEO actions'],\n ['seo quick-wins', 'Find ranking 4-10 low-CTR wins'],\n ['seo second-page', 'Investigate URLs averaging positions 10-20'],\n ['seo technical-watch', 'Crawl and index-monitor a site'],\n ],\n },\n {\n title: 'Agent and power tools',\n commands: [\n ['seo report --json', 'Run the main report as structured JSON'],\n ['seo export diagnose', 'Export report data to CSV'],\n ['seo mcp install', 'Install SEO tools into MCP clients'],\n ['seo skill list', 'Show the packaged SEO skill'],\n ['seo reports list', 'Discover every structured report'],\n ],\n },\n]\n\nconst allHelpSections: HelpSection[] = [\n ...helpSections,\n {\n title: 'Deeper analysis',\n commands: [\n ['seo decaying', 'Find pages and queries losing clicks'],\n ['seo cannibal', 'Review queries exposed across multiple URLs'],\n ['seo ctr-underperformers', 'Find weak CTR by ranking position'],\n ['seo query-cluster', 'Cluster repeated demand themes'],\n ['seo page-opportunities', 'Analyze one URL for growth ideas'],\n ['seo content optimize', 'Build a content optimization report'],\n ['seo perf audit', 'Run a page performance audit'],\n ['seo internal-links', 'Find internal link opportunities'],\n ['seo community-intent', 'Find forum, review, and comparison intent'],\n ['seo ai-referrals', 'Find AI referral traffic in GA4'],\n ['seo seo-to-ai-query', 'Convert searches into AI-monitor prompts'],\n ],\n },\n {\n title: 'Technical and data',\n commands: [\n ['seo audit-page', 'Audit one page'],\n ['seo crawl', 'Crawl a site for technical SEO issues'],\n ['seo ai-readiness', 'Review AI-search technical evidence'],\n ['seo llms audit', 'Inspect optional llms.txt presence'],\n ['seo entity-readiness', 'Check brand/entity signals from a saved crawl'],\n ['seo okf export', 'Export a saved crawl as an OKF knowledge bundle'],\n ['seo crawl-queue', 'Run a crawl and rank the implementation queue'],\n ['seo crawl-reports', 'List saved crawl reports'],\n ['seo rules', 'List crawler rule ids'],\n ['seo explain --rule missing_title', 'Explain a crawler rule'],\n ['seo crawl-diff', 'Compare crawl changes'],\n ['seo index-coverage', 'Choose pages for URL Inspection'],\n ['seo index-watch', 'Check URL Inspection status'],\n ['seo link-recover', 'Find broken search-value URLs'],\n ['seo redirect-trace', 'Trace redirects'],\n ['seo gsc-query', 'Run a raw GSC query'],\n ['seo url-inspect', 'Run URL Inspection'],\n ['seo ga4-report', 'Run a GA4 report'],\n ['seo updates', 'List official Google ranking updates'],\n ],\n },\n {\n title: 'Reports and ops',\n commands: [\n ['seo monthly-report', 'Generate a monthly narrative'],\n ['seo report-narrative', 'Generate a client-ready narrative'],\n ['seo update-postmortem', 'Analyze update winners and losers'],\n ['seo schedule cron', 'Print cron entries'],\n ['seo monitoring', 'Run and review monitoring'],\n ['seo change-log', 'Track SEO changes'],\n ['seo tests', 'Create and report local SEO tests'],\n ['seo content-groups', 'Manage reusable page/query groups'],\n ['seo pseo', 'Audit programmatic SEO templates'],\n ['seo auth', 'Manage Google auth'],\n ['seo cache', 'Manage local cache'],\n ['seo privacy', 'Show local storage paths'],\n ['seo reset', 'Delete local SEO data'],\n ],\n },\n]\n\nfunction printHelpSections(sections: HelpSection[]): void {\n process.stdout.write(`seo v${pkg.version}\\n\\n`)\n process.stdout.write(\n 'Human-friendly SEO reports first, power tools when you need them.\\n\\n',\n )\n for (const section of sections) {\n process.stdout.write(`${section.title}\\n`)\n const width = Math.max(\n ...section.commands.map(([command]) => command.length),\n )\n for (const [command, description] of section.commands) {\n process.stdout.write(` ${command.padEnd(width)} ${description}\\n`)\n }\n process.stdout.write('\\n')\n }\n process.stdout.write(\n 'Use `seo help <command>` or `seo <command> --help` for command help.\\n',\n )\n process.stdout.write('Use `seo help all` for the longer command list.\\n')\n}\n\nconst main = defineCommand({\n meta: {\n name: 'seo',\n version: pkg.version,\n description: 'Local-first SEO CLI and MCP server',\n },\n subCommands: {\n init: initCommand,\n llms: llmsCommand,\n auth: authCommand,\n mcp: mcpCommand,\n okf: okfCommand,\n doctor: doctorCommand,\n 'ga4-properties': ga4PropertiesCommand,\n privacy: privacyCommand,\n reset: resetCommand,\n cache: cacheCommand,\n crawl: crawlCommand,\n 'crawl-queue': crawlQueueCommand,\n 'crawl-reports': crawlReportsCommand,\n client: clientCommand,\n content: contentCommand,\n project: projectCommand,\n projects: projectCommand,\n 'change-log': changeLogCommand,\n tests: testsCommand,\n 'content-groups': contentGroupsCommand,\n 'crawl-diff': crawlDiffCommand,\n diagnose: diagnoseCommand,\n 'diagnose-property': diagnosePropertyWorkflowCommand,\n export: exportCommand,\n 'index-coverage': indexCoverageCommand,\n 'index-watch': indexWatchCommand,\n 'link-recover': linkRecoverCommand,\n 'monthly-report': monthlyReportCommand,\n monitoring: monitoringCommand,\n 'report-narrative': reportNarrativeCommand,\n rules: rulesCommand,\n explain: explainCommand,\n 'refresh-priorities': refreshPrioritiesCommand,\n 'redirect-trace': redirectTraceCommand,\n schedule: scheduleCommand,\n skill: skillsCommand,\n start: startCommand,\n setup: setupCommand,\n report: mainReportCommand,\n reports: reportCatalogCommand,\n 'segment-impact': segmentImpactCommand,\n 'striking-distance': strikingDistanceCommand,\n 'technical-watch': technicalWatchCommand,\n 'update-postmortem': updatePostmortemCommand,\n sites: sitesCommand,\n 'gsc-query': gscQueryCommand,\n 'url-inspect': urlInspectCommand,\n 'ga4-report': ga4ReportCommand,\n updates: updatesCommand,\n 'traffic-anomaly': trafficAnomalyCommand,\n 'update-correlate': updateCorrelateCommand,\n 'ai-referrals': aiReferralsCommand,\n 'ai-readiness': aiReadinessCommand,\n 'entity-readiness': entityReadinessCommand,\n 'audit-page': auditPageCommand,\n 'second-page': secondPageCommand,\n cannibal: cannibalCommand,\n 'community-intent': communityIntentCommand,\n decaying: decayingCommand,\n 'quick-wins': quickWinsCommand,\n 'page-opportunities': pageOpportunitiesCommand,\n perf: performanceCommand,\n 'internal-links': internalLinksCommand,\n 'ctr-underperformers': ctrUnderperformersCommand,\n 'query-cluster': queryClusterCommand,\n 'seo-to-ai-query': seoToAiQueryCommand,\n pseo: pseoCommand,\n },\n run: async () => {\n if (process.argv.slice(2).length === 0) {\n process.stdout.write(\n 'Use `seo start` to set up, then `seo report` for the main report.\\n',\n )\n }\n },\n})\n\nmaybeCheckForUpdates(pkg)\n\nconst argv = process.argv.slice(2)\nif (\n argv.length === 0 ||\n (argv.length === 1 && ['help', '--help', '-h'].includes(argv[0] ?? ''))\n) {\n printHelpSections(helpSections)\n process.exit(0)\n}\nif (argv[0] === 'help' && argv[1] === 'all') {\n printHelpSections(allHelpSections)\n process.exit(0)\n}\nconst commandArgs =\n argv[0] === 'help' && argv.length > 1 ? [...argv.slice(1), '--help'] : argv\nif (commandArgs !== argv) {\n process.argv = [\n process.argv[0] ?? 'node',\n process.argv[1] ?? 'seo',\n ...commandArgs,\n ]\n}\nconst helpRequested = commandArgs.some((arg) => ['--help', '-h'].includes(arg))\nconst versionRequested =\n argv.length === 1 && ['--version', '-v'].includes(argv[0] ?? '')\n\nif (helpRequested || versionRequested) {\n await runMain(main)\n} else {\n try {\n await runCommand(main, { rawArgs: commandArgs })\n } catch (error) {\n const normalized = toSeoError(error)\n if (argv.includes('--json')) {\n process.stdout.write(\n `${JSON.stringify(seoErrorEnvelope(normalized), null, 2)}\\n`,\n )\n } else {\n process.stderr.write(`Error: ${normalized.message}\\n`)\n }\n process.exitCode = normalized.exitCode\n }\n}\n"],"mappings":"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"}
|