@nebulacomponents/citable 0.1.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/CHANGELOG.md +26 -0
- package/LICENSE +201 -0
- package/README.md +150 -0
- package/cli/bin/citable.js +5 -0
- package/dist/universal/.agents/skills/citable/SKILL.md +137 -0
- package/dist/universal/.agents/skills/citable/VERSION +1 -0
- package/dist/universal/.agents/skills/citable/commands/README.md +36 -0
- package/dist/universal/.agents/skills/citable/commands/ingest.md +44 -0
- package/dist/universal/.agents/skills/citable/commands/measurement.md +49 -0
- package/dist/universal/.agents/skills/citable/commands/optimize-page.md +53 -0
- package/dist/universal/.agents/skills/citable/commands/page-work.md +48 -0
- package/dist/universal/.agents/skills/citable/commands/validate-render.md +24 -0
- package/dist/universal/.agents/skills/citable/manifest.json +54 -0
- package/dist/universal/.agents/skills/citable/policies/crawler-policy-template.md +47 -0
- package/dist/universal/.agents/skills/citable/references/anti-patterns.md +61 -0
- package/dist/universal/.agents/skills/citable/rubrics/README.md +30 -0
- package/dist/universal/.agents/skills/citable/rubrics/answer-extractability.md +44 -0
- package/dist/universal/.agents/skills/citable/rubrics/claim-boundedness.md +36 -0
- package/dist/universal/.agents/skills/citable/rubrics/comparison-fairness.md +30 -0
- package/dist/universal/.agents/skills/citable/rubrics/conversion-alignment.md +37 -0
- package/dist/universal/.agents/skills/citable/rubrics/entity-clarity.md +41 -0
- package/dist/universal/.agents/skills/citable/rubrics/evidence-strength.md +53 -0
- package/dist/universal/.agents/skills/citable/rubrics/information-gain.md +33 -0
- package/dist/universal/.agents/skills/citable/rubrics/intent-alignment.md +41 -0
- package/dist/universal/.agents/skills/citable/rubrics/narrative-accuracy.md +46 -0
- package/dist/universal/.agents/skills/citable/rubrics/recommendation-eligibility.md +36 -0
- package/dist/universal/.agents/skills/citable/rubrics/semantic-clarity.md +42 -0
- package/dist/universal/.agents/skills/citable/rubrics/source-authority.md +37 -0
- package/dist/universal/.agents/skills/citable/schemas/claim.schema.json +53 -0
- package/dist/universal/.agents/skills/citable/schemas/common.defs.json +33 -0
- package/dist/universal/.agents/skills/citable/schemas/competitor.schema.json +28 -0
- package/dist/universal/.agents/skills/citable/schemas/config.schema.json +41 -0
- package/dist/universal/.agents/skills/citable/schemas/crawler.schema.json +33 -0
- package/dist/universal/.agents/skills/citable/schemas/detector-quality.schema.json +39 -0
- package/dist/universal/.agents/skills/citable/schemas/entity.schema.json +39 -0
- package/dist/universal/.agents/skills/citable/schemas/evidence.schema.json +41 -0
- package/dist/universal/.agents/skills/citable/schemas/experiment.schema.json +37 -0
- package/dist/universal/.agents/skills/citable/schemas/finding.schema.json +101 -0
- package/dist/universal/.agents/skills/citable/schemas/page.schema.json +40 -0
- package/dist/universal/.agents/skills/citable/schemas/project.schema.json +29 -0
- package/dist/universal/.agents/skills/citable/schemas/prompt-result.schema.json +37 -0
- package/dist/universal/.agents/skills/citable/schemas/prompt.schema.json +41 -0
- package/dist/universal/.agents/skills/citable/schemas/query.schema.json +43 -0
- package/dist/universal/.agents/skills/citable/schemas/run.schema.json +36 -0
- package/dist/universal/.agents/skills/citable/scripts/README.md +4 -0
- package/dist/universal/.agents/skills/citable/templates/finding-review.md +54 -0
- package/dist/universal/.claude/skills/citable/SKILL.md +137 -0
- package/dist/universal/.claude/skills/citable/VERSION +1 -0
- package/dist/universal/.claude/skills/citable/commands/README.md +36 -0
- package/dist/universal/.claude/skills/citable/commands/ingest.md +44 -0
- package/dist/universal/.claude/skills/citable/commands/measurement.md +49 -0
- package/dist/universal/.claude/skills/citable/commands/optimize-page.md +53 -0
- package/dist/universal/.claude/skills/citable/commands/page-work.md +48 -0
- package/dist/universal/.claude/skills/citable/commands/validate-render.md +24 -0
- package/dist/universal/.claude/skills/citable/manifest.json +54 -0
- package/dist/universal/.claude/skills/citable/policies/crawler-policy-template.md +47 -0
- package/dist/universal/.claude/skills/citable/references/anti-patterns.md +61 -0
- package/dist/universal/.claude/skills/citable/rubrics/README.md +30 -0
- package/dist/universal/.claude/skills/citable/rubrics/answer-extractability.md +44 -0
- package/dist/universal/.claude/skills/citable/rubrics/claim-boundedness.md +36 -0
- package/dist/universal/.claude/skills/citable/rubrics/comparison-fairness.md +30 -0
- package/dist/universal/.claude/skills/citable/rubrics/conversion-alignment.md +37 -0
- package/dist/universal/.claude/skills/citable/rubrics/entity-clarity.md +41 -0
- package/dist/universal/.claude/skills/citable/rubrics/evidence-strength.md +53 -0
- package/dist/universal/.claude/skills/citable/rubrics/information-gain.md +33 -0
- package/dist/universal/.claude/skills/citable/rubrics/intent-alignment.md +41 -0
- package/dist/universal/.claude/skills/citable/rubrics/narrative-accuracy.md +46 -0
- package/dist/universal/.claude/skills/citable/rubrics/recommendation-eligibility.md +36 -0
- package/dist/universal/.claude/skills/citable/rubrics/semantic-clarity.md +42 -0
- package/dist/universal/.claude/skills/citable/rubrics/source-authority.md +37 -0
- package/dist/universal/.claude/skills/citable/schemas/claim.schema.json +53 -0
- package/dist/universal/.claude/skills/citable/schemas/common.defs.json +33 -0
- package/dist/universal/.claude/skills/citable/schemas/competitor.schema.json +28 -0
- package/dist/universal/.claude/skills/citable/schemas/config.schema.json +41 -0
- package/dist/universal/.claude/skills/citable/schemas/crawler.schema.json +33 -0
- package/dist/universal/.claude/skills/citable/schemas/detector-quality.schema.json +39 -0
- package/dist/universal/.claude/skills/citable/schemas/entity.schema.json +39 -0
- package/dist/universal/.claude/skills/citable/schemas/evidence.schema.json +41 -0
- package/dist/universal/.claude/skills/citable/schemas/experiment.schema.json +37 -0
- package/dist/universal/.claude/skills/citable/schemas/finding.schema.json +101 -0
- package/dist/universal/.claude/skills/citable/schemas/page.schema.json +40 -0
- package/dist/universal/.claude/skills/citable/schemas/project.schema.json +29 -0
- package/dist/universal/.claude/skills/citable/schemas/prompt-result.schema.json +37 -0
- package/dist/universal/.claude/skills/citable/schemas/prompt.schema.json +41 -0
- package/dist/universal/.claude/skills/citable/schemas/query.schema.json +43 -0
- package/dist/universal/.claude/skills/citable/schemas/run.schema.json +36 -0
- package/dist/universal/.claude/skills/citable/scripts/README.md +4 -0
- package/dist/universal/.claude/skills/citable/templates/finding-review.md +54 -0
- package/dist/universal/.cursor/skills/citable/SKILL.md +137 -0
- package/dist/universal/.cursor/skills/citable/VERSION +1 -0
- package/dist/universal/.cursor/skills/citable/commands/README.md +36 -0
- package/dist/universal/.cursor/skills/citable/commands/ingest.md +44 -0
- package/dist/universal/.cursor/skills/citable/commands/measurement.md +49 -0
- package/dist/universal/.cursor/skills/citable/commands/optimize-page.md +53 -0
- package/dist/universal/.cursor/skills/citable/commands/page-work.md +48 -0
- package/dist/universal/.cursor/skills/citable/commands/validate-render.md +24 -0
- package/dist/universal/.cursor/skills/citable/manifest.json +54 -0
- package/dist/universal/.cursor/skills/citable/policies/crawler-policy-template.md +47 -0
- package/dist/universal/.cursor/skills/citable/references/anti-patterns.md +61 -0
- package/dist/universal/.cursor/skills/citable/rubrics/README.md +30 -0
- package/dist/universal/.cursor/skills/citable/rubrics/answer-extractability.md +44 -0
- package/dist/universal/.cursor/skills/citable/rubrics/claim-boundedness.md +36 -0
- package/dist/universal/.cursor/skills/citable/rubrics/comparison-fairness.md +30 -0
- package/dist/universal/.cursor/skills/citable/rubrics/conversion-alignment.md +37 -0
- package/dist/universal/.cursor/skills/citable/rubrics/entity-clarity.md +41 -0
- package/dist/universal/.cursor/skills/citable/rubrics/evidence-strength.md +53 -0
- package/dist/universal/.cursor/skills/citable/rubrics/information-gain.md +33 -0
- package/dist/universal/.cursor/skills/citable/rubrics/intent-alignment.md +41 -0
- package/dist/universal/.cursor/skills/citable/rubrics/narrative-accuracy.md +46 -0
- package/dist/universal/.cursor/skills/citable/rubrics/recommendation-eligibility.md +36 -0
- package/dist/universal/.cursor/skills/citable/rubrics/semantic-clarity.md +42 -0
- package/dist/universal/.cursor/skills/citable/rubrics/source-authority.md +37 -0
- package/dist/universal/.cursor/skills/citable/schemas/claim.schema.json +53 -0
- package/dist/universal/.cursor/skills/citable/schemas/common.defs.json +33 -0
- package/dist/universal/.cursor/skills/citable/schemas/competitor.schema.json +28 -0
- package/dist/universal/.cursor/skills/citable/schemas/config.schema.json +41 -0
- package/dist/universal/.cursor/skills/citable/schemas/crawler.schema.json +33 -0
- package/dist/universal/.cursor/skills/citable/schemas/detector-quality.schema.json +39 -0
- package/dist/universal/.cursor/skills/citable/schemas/entity.schema.json +39 -0
- package/dist/universal/.cursor/skills/citable/schemas/evidence.schema.json +41 -0
- package/dist/universal/.cursor/skills/citable/schemas/experiment.schema.json +37 -0
- package/dist/universal/.cursor/skills/citable/schemas/finding.schema.json +101 -0
- package/dist/universal/.cursor/skills/citable/schemas/page.schema.json +40 -0
- package/dist/universal/.cursor/skills/citable/schemas/project.schema.json +29 -0
- package/dist/universal/.cursor/skills/citable/schemas/prompt-result.schema.json +37 -0
- package/dist/universal/.cursor/skills/citable/schemas/prompt.schema.json +41 -0
- package/dist/universal/.cursor/skills/citable/schemas/query.schema.json +43 -0
- package/dist/universal/.cursor/skills/citable/schemas/run.schema.json +36 -0
- package/dist/universal/.cursor/skills/citable/scripts/README.md +4 -0
- package/dist/universal/.cursor/skills/citable/templates/finding-review.md +54 -0
- package/dist/universal/.gemini/skills/citable/SKILL.md +137 -0
- package/dist/universal/.gemini/skills/citable/VERSION +1 -0
- package/dist/universal/.gemini/skills/citable/commands/README.md +36 -0
- package/dist/universal/.gemini/skills/citable/commands/ingest.md +44 -0
- package/dist/universal/.gemini/skills/citable/commands/measurement.md +49 -0
- package/dist/universal/.gemini/skills/citable/commands/optimize-page.md +53 -0
- package/dist/universal/.gemini/skills/citable/commands/page-work.md +48 -0
- package/dist/universal/.gemini/skills/citable/commands/validate-render.md +24 -0
- package/dist/universal/.gemini/skills/citable/manifest.json +54 -0
- package/dist/universal/.gemini/skills/citable/policies/crawler-policy-template.md +47 -0
- package/dist/universal/.gemini/skills/citable/references/anti-patterns.md +61 -0
- package/dist/universal/.gemini/skills/citable/rubrics/README.md +30 -0
- package/dist/universal/.gemini/skills/citable/rubrics/answer-extractability.md +44 -0
- package/dist/universal/.gemini/skills/citable/rubrics/claim-boundedness.md +36 -0
- package/dist/universal/.gemini/skills/citable/rubrics/comparison-fairness.md +30 -0
- package/dist/universal/.gemini/skills/citable/rubrics/conversion-alignment.md +37 -0
- package/dist/universal/.gemini/skills/citable/rubrics/entity-clarity.md +41 -0
- package/dist/universal/.gemini/skills/citable/rubrics/evidence-strength.md +53 -0
- package/dist/universal/.gemini/skills/citable/rubrics/information-gain.md +33 -0
- package/dist/universal/.gemini/skills/citable/rubrics/intent-alignment.md +41 -0
- package/dist/universal/.gemini/skills/citable/rubrics/narrative-accuracy.md +46 -0
- package/dist/universal/.gemini/skills/citable/rubrics/recommendation-eligibility.md +36 -0
- package/dist/universal/.gemini/skills/citable/rubrics/semantic-clarity.md +42 -0
- package/dist/universal/.gemini/skills/citable/rubrics/source-authority.md +37 -0
- package/dist/universal/.gemini/skills/citable/schemas/claim.schema.json +53 -0
- package/dist/universal/.gemini/skills/citable/schemas/common.defs.json +33 -0
- package/dist/universal/.gemini/skills/citable/schemas/competitor.schema.json +28 -0
- package/dist/universal/.gemini/skills/citable/schemas/config.schema.json +41 -0
- package/dist/universal/.gemini/skills/citable/schemas/crawler.schema.json +33 -0
- package/dist/universal/.gemini/skills/citable/schemas/detector-quality.schema.json +39 -0
- package/dist/universal/.gemini/skills/citable/schemas/entity.schema.json +39 -0
- package/dist/universal/.gemini/skills/citable/schemas/evidence.schema.json +41 -0
- package/dist/universal/.gemini/skills/citable/schemas/experiment.schema.json +37 -0
- package/dist/universal/.gemini/skills/citable/schemas/finding.schema.json +101 -0
- package/dist/universal/.gemini/skills/citable/schemas/page.schema.json +40 -0
- package/dist/universal/.gemini/skills/citable/schemas/project.schema.json +29 -0
- package/dist/universal/.gemini/skills/citable/schemas/prompt-result.schema.json +37 -0
- package/dist/universal/.gemini/skills/citable/schemas/prompt.schema.json +41 -0
- package/dist/universal/.gemini/skills/citable/schemas/query.schema.json +43 -0
- package/dist/universal/.gemini/skills/citable/schemas/run.schema.json +36 -0
- package/dist/universal/.gemini/skills/citable/scripts/README.md +4 -0
- package/dist/universal/.gemini/skills/citable/templates/finding-review.md +54 -0
- package/dist/universal/.github/skills/citable/SKILL.md +137 -0
- package/dist/universal/.github/skills/citable/VERSION +1 -0
- package/dist/universal/.github/skills/citable/commands/README.md +36 -0
- package/dist/universal/.github/skills/citable/commands/ingest.md +44 -0
- package/dist/universal/.github/skills/citable/commands/measurement.md +49 -0
- package/dist/universal/.github/skills/citable/commands/optimize-page.md +53 -0
- package/dist/universal/.github/skills/citable/commands/page-work.md +48 -0
- package/dist/universal/.github/skills/citable/commands/validate-render.md +24 -0
- package/dist/universal/.github/skills/citable/manifest.json +54 -0
- package/dist/universal/.github/skills/citable/policies/crawler-policy-template.md +47 -0
- package/dist/universal/.github/skills/citable/references/anti-patterns.md +61 -0
- package/dist/universal/.github/skills/citable/rubrics/README.md +30 -0
- package/dist/universal/.github/skills/citable/rubrics/answer-extractability.md +44 -0
- package/dist/universal/.github/skills/citable/rubrics/claim-boundedness.md +36 -0
- package/dist/universal/.github/skills/citable/rubrics/comparison-fairness.md +30 -0
- package/dist/universal/.github/skills/citable/rubrics/conversion-alignment.md +37 -0
- package/dist/universal/.github/skills/citable/rubrics/entity-clarity.md +41 -0
- package/dist/universal/.github/skills/citable/rubrics/evidence-strength.md +53 -0
- package/dist/universal/.github/skills/citable/rubrics/information-gain.md +33 -0
- package/dist/universal/.github/skills/citable/rubrics/intent-alignment.md +41 -0
- package/dist/universal/.github/skills/citable/rubrics/narrative-accuracy.md +46 -0
- package/dist/universal/.github/skills/citable/rubrics/recommendation-eligibility.md +36 -0
- package/dist/universal/.github/skills/citable/rubrics/semantic-clarity.md +42 -0
- package/dist/universal/.github/skills/citable/rubrics/source-authority.md +37 -0
- package/dist/universal/.github/skills/citable/schemas/claim.schema.json +53 -0
- package/dist/universal/.github/skills/citable/schemas/common.defs.json +33 -0
- package/dist/universal/.github/skills/citable/schemas/competitor.schema.json +28 -0
- package/dist/universal/.github/skills/citable/schemas/config.schema.json +41 -0
- package/dist/universal/.github/skills/citable/schemas/crawler.schema.json +33 -0
- package/dist/universal/.github/skills/citable/schemas/detector-quality.schema.json +39 -0
- package/dist/universal/.github/skills/citable/schemas/entity.schema.json +39 -0
- package/dist/universal/.github/skills/citable/schemas/evidence.schema.json +41 -0
- package/dist/universal/.github/skills/citable/schemas/experiment.schema.json +37 -0
- package/dist/universal/.github/skills/citable/schemas/finding.schema.json +101 -0
- package/dist/universal/.github/skills/citable/schemas/page.schema.json +40 -0
- package/dist/universal/.github/skills/citable/schemas/project.schema.json +29 -0
- package/dist/universal/.github/skills/citable/schemas/prompt-result.schema.json +37 -0
- package/dist/universal/.github/skills/citable/schemas/prompt.schema.json +41 -0
- package/dist/universal/.github/skills/citable/schemas/query.schema.json +43 -0
- package/dist/universal/.github/skills/citable/schemas/run.schema.json +36 -0
- package/dist/universal/.github/skills/citable/scripts/README.md +4 -0
- package/dist/universal/.github/skills/citable/templates/finding-review.md +54 -0
- package/dist/universal/.kiro/skills/citable/SKILL.md +137 -0
- package/dist/universal/.kiro/skills/citable/VERSION +1 -0
- package/dist/universal/.kiro/skills/citable/commands/README.md +36 -0
- package/dist/universal/.kiro/skills/citable/commands/ingest.md +44 -0
- package/dist/universal/.kiro/skills/citable/commands/measurement.md +49 -0
- package/dist/universal/.kiro/skills/citable/commands/optimize-page.md +53 -0
- package/dist/universal/.kiro/skills/citable/commands/page-work.md +48 -0
- package/dist/universal/.kiro/skills/citable/commands/validate-render.md +24 -0
- package/dist/universal/.kiro/skills/citable/manifest.json +54 -0
- package/dist/universal/.kiro/skills/citable/policies/crawler-policy-template.md +47 -0
- package/dist/universal/.kiro/skills/citable/references/anti-patterns.md +61 -0
- package/dist/universal/.kiro/skills/citable/rubrics/README.md +30 -0
- package/dist/universal/.kiro/skills/citable/rubrics/answer-extractability.md +44 -0
- package/dist/universal/.kiro/skills/citable/rubrics/claim-boundedness.md +36 -0
- package/dist/universal/.kiro/skills/citable/rubrics/comparison-fairness.md +30 -0
- package/dist/universal/.kiro/skills/citable/rubrics/conversion-alignment.md +37 -0
- package/dist/universal/.kiro/skills/citable/rubrics/entity-clarity.md +41 -0
- package/dist/universal/.kiro/skills/citable/rubrics/evidence-strength.md +53 -0
- package/dist/universal/.kiro/skills/citable/rubrics/information-gain.md +33 -0
- package/dist/universal/.kiro/skills/citable/rubrics/intent-alignment.md +41 -0
- package/dist/universal/.kiro/skills/citable/rubrics/narrative-accuracy.md +46 -0
- package/dist/universal/.kiro/skills/citable/rubrics/recommendation-eligibility.md +36 -0
- package/dist/universal/.kiro/skills/citable/rubrics/semantic-clarity.md +42 -0
- package/dist/universal/.kiro/skills/citable/rubrics/source-authority.md +37 -0
- package/dist/universal/.kiro/skills/citable/schemas/claim.schema.json +53 -0
- package/dist/universal/.kiro/skills/citable/schemas/common.defs.json +33 -0
- package/dist/universal/.kiro/skills/citable/schemas/competitor.schema.json +28 -0
- package/dist/universal/.kiro/skills/citable/schemas/config.schema.json +41 -0
- package/dist/universal/.kiro/skills/citable/schemas/crawler.schema.json +33 -0
- package/dist/universal/.kiro/skills/citable/schemas/detector-quality.schema.json +39 -0
- package/dist/universal/.kiro/skills/citable/schemas/entity.schema.json +39 -0
- package/dist/universal/.kiro/skills/citable/schemas/evidence.schema.json +41 -0
- package/dist/universal/.kiro/skills/citable/schemas/experiment.schema.json +37 -0
- package/dist/universal/.kiro/skills/citable/schemas/finding.schema.json +101 -0
- package/dist/universal/.kiro/skills/citable/schemas/page.schema.json +40 -0
- package/dist/universal/.kiro/skills/citable/schemas/project.schema.json +29 -0
- package/dist/universal/.kiro/skills/citable/schemas/prompt-result.schema.json +37 -0
- package/dist/universal/.kiro/skills/citable/schemas/prompt.schema.json +41 -0
- package/dist/universal/.kiro/skills/citable/schemas/query.schema.json +43 -0
- package/dist/universal/.kiro/skills/citable/schemas/run.schema.json +36 -0
- package/dist/universal/.kiro/skills/citable/scripts/README.md +4 -0
- package/dist/universal/.kiro/skills/citable/templates/finding-review.md +54 -0
- package/dist/universal/.opencode/skills/citable/SKILL.md +137 -0
- package/dist/universal/.opencode/skills/citable/VERSION +1 -0
- package/dist/universal/.opencode/skills/citable/commands/README.md +36 -0
- package/dist/universal/.opencode/skills/citable/commands/ingest.md +44 -0
- package/dist/universal/.opencode/skills/citable/commands/measurement.md +49 -0
- package/dist/universal/.opencode/skills/citable/commands/optimize-page.md +53 -0
- package/dist/universal/.opencode/skills/citable/commands/page-work.md +48 -0
- package/dist/universal/.opencode/skills/citable/commands/validate-render.md +24 -0
- package/dist/universal/.opencode/skills/citable/manifest.json +54 -0
- package/dist/universal/.opencode/skills/citable/policies/crawler-policy-template.md +47 -0
- package/dist/universal/.opencode/skills/citable/references/anti-patterns.md +61 -0
- package/dist/universal/.opencode/skills/citable/rubrics/README.md +30 -0
- package/dist/universal/.opencode/skills/citable/rubrics/answer-extractability.md +44 -0
- package/dist/universal/.opencode/skills/citable/rubrics/claim-boundedness.md +36 -0
- package/dist/universal/.opencode/skills/citable/rubrics/comparison-fairness.md +30 -0
- package/dist/universal/.opencode/skills/citable/rubrics/conversion-alignment.md +37 -0
- package/dist/universal/.opencode/skills/citable/rubrics/entity-clarity.md +41 -0
- package/dist/universal/.opencode/skills/citable/rubrics/evidence-strength.md +53 -0
- package/dist/universal/.opencode/skills/citable/rubrics/information-gain.md +33 -0
- package/dist/universal/.opencode/skills/citable/rubrics/intent-alignment.md +41 -0
- package/dist/universal/.opencode/skills/citable/rubrics/narrative-accuracy.md +46 -0
- package/dist/universal/.opencode/skills/citable/rubrics/recommendation-eligibility.md +36 -0
- package/dist/universal/.opencode/skills/citable/rubrics/semantic-clarity.md +42 -0
- package/dist/universal/.opencode/skills/citable/rubrics/source-authority.md +37 -0
- package/dist/universal/.opencode/skills/citable/schemas/claim.schema.json +53 -0
- package/dist/universal/.opencode/skills/citable/schemas/common.defs.json +33 -0
- package/dist/universal/.opencode/skills/citable/schemas/competitor.schema.json +28 -0
- package/dist/universal/.opencode/skills/citable/schemas/config.schema.json +41 -0
- package/dist/universal/.opencode/skills/citable/schemas/crawler.schema.json +33 -0
- package/dist/universal/.opencode/skills/citable/schemas/detector-quality.schema.json +39 -0
- package/dist/universal/.opencode/skills/citable/schemas/entity.schema.json +39 -0
- package/dist/universal/.opencode/skills/citable/schemas/evidence.schema.json +41 -0
- package/dist/universal/.opencode/skills/citable/schemas/experiment.schema.json +37 -0
- package/dist/universal/.opencode/skills/citable/schemas/finding.schema.json +101 -0
- package/dist/universal/.opencode/skills/citable/schemas/page.schema.json +40 -0
- package/dist/universal/.opencode/skills/citable/schemas/project.schema.json +29 -0
- package/dist/universal/.opencode/skills/citable/schemas/prompt-result.schema.json +37 -0
- package/dist/universal/.opencode/skills/citable/schemas/prompt.schema.json +41 -0
- package/dist/universal/.opencode/skills/citable/schemas/query.schema.json +43 -0
- package/dist/universal/.opencode/skills/citable/schemas/run.schema.json +36 -0
- package/dist/universal/.opencode/skills/citable/scripts/README.md +4 -0
- package/dist/universal/.opencode/skills/citable/templates/finding-review.md +54 -0
- package/dist/universal/.pi/agent/skills/citable/SKILL.md +137 -0
- package/dist/universal/.pi/agent/skills/citable/VERSION +1 -0
- package/dist/universal/.pi/agent/skills/citable/commands/README.md +36 -0
- package/dist/universal/.pi/agent/skills/citable/commands/ingest.md +44 -0
- package/dist/universal/.pi/agent/skills/citable/commands/measurement.md +49 -0
- package/dist/universal/.pi/agent/skills/citable/commands/optimize-page.md +53 -0
- package/dist/universal/.pi/agent/skills/citable/commands/page-work.md +48 -0
- package/dist/universal/.pi/agent/skills/citable/commands/validate-render.md +24 -0
- package/dist/universal/.pi/agent/skills/citable/manifest.json +54 -0
- package/dist/universal/.pi/agent/skills/citable/policies/crawler-policy-template.md +47 -0
- package/dist/universal/.pi/agent/skills/citable/references/anti-patterns.md +61 -0
- package/dist/universal/.pi/agent/skills/citable/rubrics/README.md +30 -0
- package/dist/universal/.pi/agent/skills/citable/rubrics/answer-extractability.md +44 -0
- package/dist/universal/.pi/agent/skills/citable/rubrics/claim-boundedness.md +36 -0
- package/dist/universal/.pi/agent/skills/citable/rubrics/comparison-fairness.md +30 -0
- package/dist/universal/.pi/agent/skills/citable/rubrics/conversion-alignment.md +37 -0
- package/dist/universal/.pi/agent/skills/citable/rubrics/entity-clarity.md +41 -0
- package/dist/universal/.pi/agent/skills/citable/rubrics/evidence-strength.md +53 -0
- package/dist/universal/.pi/agent/skills/citable/rubrics/information-gain.md +33 -0
- package/dist/universal/.pi/agent/skills/citable/rubrics/intent-alignment.md +41 -0
- package/dist/universal/.pi/agent/skills/citable/rubrics/narrative-accuracy.md +46 -0
- package/dist/universal/.pi/agent/skills/citable/rubrics/recommendation-eligibility.md +36 -0
- package/dist/universal/.pi/agent/skills/citable/rubrics/semantic-clarity.md +42 -0
- package/dist/universal/.pi/agent/skills/citable/rubrics/source-authority.md +37 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/claim.schema.json +53 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/common.defs.json +33 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/competitor.schema.json +28 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/config.schema.json +41 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/crawler.schema.json +33 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/detector-quality.schema.json +39 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/entity.schema.json +39 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/evidence.schema.json +41 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/experiment.schema.json +37 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/finding.schema.json +101 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/page.schema.json +40 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/project.schema.json +29 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/prompt-result.schema.json +37 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/prompt.schema.json +41 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/query.schema.json +43 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/run.schema.json +36 -0
- package/dist/universal/.pi/agent/skills/citable/scripts/README.md +4 -0
- package/dist/universal/.pi/agent/skills/citable/templates/finding-review.md +54 -0
- package/dist/universal/.qoder/skills/citable/SKILL.md +137 -0
- package/dist/universal/.qoder/skills/citable/VERSION +1 -0
- package/dist/universal/.qoder/skills/citable/commands/README.md +36 -0
- package/dist/universal/.qoder/skills/citable/commands/ingest.md +44 -0
- package/dist/universal/.qoder/skills/citable/commands/measurement.md +49 -0
- package/dist/universal/.qoder/skills/citable/commands/optimize-page.md +53 -0
- package/dist/universal/.qoder/skills/citable/commands/page-work.md +48 -0
- package/dist/universal/.qoder/skills/citable/commands/validate-render.md +24 -0
- package/dist/universal/.qoder/skills/citable/manifest.json +54 -0
- package/dist/universal/.qoder/skills/citable/policies/crawler-policy-template.md +47 -0
- package/dist/universal/.qoder/skills/citable/references/anti-patterns.md +61 -0
- package/dist/universal/.qoder/skills/citable/rubrics/README.md +30 -0
- package/dist/universal/.qoder/skills/citable/rubrics/answer-extractability.md +44 -0
- package/dist/universal/.qoder/skills/citable/rubrics/claim-boundedness.md +36 -0
- package/dist/universal/.qoder/skills/citable/rubrics/comparison-fairness.md +30 -0
- package/dist/universal/.qoder/skills/citable/rubrics/conversion-alignment.md +37 -0
- package/dist/universal/.qoder/skills/citable/rubrics/entity-clarity.md +41 -0
- package/dist/universal/.qoder/skills/citable/rubrics/evidence-strength.md +53 -0
- package/dist/universal/.qoder/skills/citable/rubrics/information-gain.md +33 -0
- package/dist/universal/.qoder/skills/citable/rubrics/intent-alignment.md +41 -0
- package/dist/universal/.qoder/skills/citable/rubrics/narrative-accuracy.md +46 -0
- package/dist/universal/.qoder/skills/citable/rubrics/recommendation-eligibility.md +36 -0
- package/dist/universal/.qoder/skills/citable/rubrics/semantic-clarity.md +42 -0
- package/dist/universal/.qoder/skills/citable/rubrics/source-authority.md +37 -0
- package/dist/universal/.qoder/skills/citable/schemas/claim.schema.json +53 -0
- package/dist/universal/.qoder/skills/citable/schemas/common.defs.json +33 -0
- package/dist/universal/.qoder/skills/citable/schemas/competitor.schema.json +28 -0
- package/dist/universal/.qoder/skills/citable/schemas/config.schema.json +41 -0
- package/dist/universal/.qoder/skills/citable/schemas/crawler.schema.json +33 -0
- package/dist/universal/.qoder/skills/citable/schemas/detector-quality.schema.json +39 -0
- package/dist/universal/.qoder/skills/citable/schemas/entity.schema.json +39 -0
- package/dist/universal/.qoder/skills/citable/schemas/evidence.schema.json +41 -0
- package/dist/universal/.qoder/skills/citable/schemas/experiment.schema.json +37 -0
- package/dist/universal/.qoder/skills/citable/schemas/finding.schema.json +101 -0
- package/dist/universal/.qoder/skills/citable/schemas/page.schema.json +40 -0
- package/dist/universal/.qoder/skills/citable/schemas/project.schema.json +29 -0
- package/dist/universal/.qoder/skills/citable/schemas/prompt-result.schema.json +37 -0
- package/dist/universal/.qoder/skills/citable/schemas/prompt.schema.json +41 -0
- package/dist/universal/.qoder/skills/citable/schemas/query.schema.json +43 -0
- package/dist/universal/.qoder/skills/citable/schemas/run.schema.json +36 -0
- package/dist/universal/.qoder/skills/citable/scripts/README.md +4 -0
- package/dist/universal/.qoder/skills/citable/templates/finding-review.md +54 -0
- package/dist/universal/.rovodev/skills/citable/SKILL.md +137 -0
- package/dist/universal/.rovodev/skills/citable/VERSION +1 -0
- package/dist/universal/.rovodev/skills/citable/commands/README.md +36 -0
- package/dist/universal/.rovodev/skills/citable/commands/ingest.md +44 -0
- package/dist/universal/.rovodev/skills/citable/commands/measurement.md +49 -0
- package/dist/universal/.rovodev/skills/citable/commands/optimize-page.md +53 -0
- package/dist/universal/.rovodev/skills/citable/commands/page-work.md +48 -0
- package/dist/universal/.rovodev/skills/citable/commands/validate-render.md +24 -0
- package/dist/universal/.rovodev/skills/citable/manifest.json +54 -0
- package/dist/universal/.rovodev/skills/citable/policies/crawler-policy-template.md +47 -0
- package/dist/universal/.rovodev/skills/citable/references/anti-patterns.md +61 -0
- package/dist/universal/.rovodev/skills/citable/rubrics/README.md +30 -0
- package/dist/universal/.rovodev/skills/citable/rubrics/answer-extractability.md +44 -0
- package/dist/universal/.rovodev/skills/citable/rubrics/claim-boundedness.md +36 -0
- package/dist/universal/.rovodev/skills/citable/rubrics/comparison-fairness.md +30 -0
- package/dist/universal/.rovodev/skills/citable/rubrics/conversion-alignment.md +37 -0
- package/dist/universal/.rovodev/skills/citable/rubrics/entity-clarity.md +41 -0
- package/dist/universal/.rovodev/skills/citable/rubrics/evidence-strength.md +53 -0
- package/dist/universal/.rovodev/skills/citable/rubrics/information-gain.md +33 -0
- package/dist/universal/.rovodev/skills/citable/rubrics/intent-alignment.md +41 -0
- package/dist/universal/.rovodev/skills/citable/rubrics/narrative-accuracy.md +46 -0
- package/dist/universal/.rovodev/skills/citable/rubrics/recommendation-eligibility.md +36 -0
- package/dist/universal/.rovodev/skills/citable/rubrics/semantic-clarity.md +42 -0
- package/dist/universal/.rovodev/skills/citable/rubrics/source-authority.md +37 -0
- package/dist/universal/.rovodev/skills/citable/schemas/claim.schema.json +53 -0
- package/dist/universal/.rovodev/skills/citable/schemas/common.defs.json +33 -0
- package/dist/universal/.rovodev/skills/citable/schemas/competitor.schema.json +28 -0
- package/dist/universal/.rovodev/skills/citable/schemas/config.schema.json +41 -0
- package/dist/universal/.rovodev/skills/citable/schemas/crawler.schema.json +33 -0
- package/dist/universal/.rovodev/skills/citable/schemas/detector-quality.schema.json +39 -0
- package/dist/universal/.rovodev/skills/citable/schemas/entity.schema.json +39 -0
- package/dist/universal/.rovodev/skills/citable/schemas/evidence.schema.json +41 -0
- package/dist/universal/.rovodev/skills/citable/schemas/experiment.schema.json +37 -0
- package/dist/universal/.rovodev/skills/citable/schemas/finding.schema.json +101 -0
- package/dist/universal/.rovodev/skills/citable/schemas/page.schema.json +40 -0
- package/dist/universal/.rovodev/skills/citable/schemas/project.schema.json +29 -0
- package/dist/universal/.rovodev/skills/citable/schemas/prompt-result.schema.json +37 -0
- package/dist/universal/.rovodev/skills/citable/schemas/prompt.schema.json +41 -0
- package/dist/universal/.rovodev/skills/citable/schemas/query.schema.json +43 -0
- package/dist/universal/.rovodev/skills/citable/schemas/run.schema.json +36 -0
- package/dist/universal/.rovodev/skills/citable/scripts/README.md +4 -0
- package/dist/universal/.rovodev/skills/citable/templates/finding-review.md +54 -0
- package/dist/universal/.trae/skills/citable/SKILL.md +137 -0
- package/dist/universal/.trae/skills/citable/VERSION +1 -0
- package/dist/universal/.trae/skills/citable/commands/README.md +36 -0
- package/dist/universal/.trae/skills/citable/commands/ingest.md +44 -0
- package/dist/universal/.trae/skills/citable/commands/measurement.md +49 -0
- package/dist/universal/.trae/skills/citable/commands/optimize-page.md +53 -0
- package/dist/universal/.trae/skills/citable/commands/page-work.md +48 -0
- package/dist/universal/.trae/skills/citable/commands/validate-render.md +24 -0
- package/dist/universal/.trae/skills/citable/manifest.json +54 -0
- package/dist/universal/.trae/skills/citable/policies/crawler-policy-template.md +47 -0
- package/dist/universal/.trae/skills/citable/references/anti-patterns.md +61 -0
- package/dist/universal/.trae/skills/citable/rubrics/README.md +30 -0
- package/dist/universal/.trae/skills/citable/rubrics/answer-extractability.md +44 -0
- package/dist/universal/.trae/skills/citable/rubrics/claim-boundedness.md +36 -0
- package/dist/universal/.trae/skills/citable/rubrics/comparison-fairness.md +30 -0
- package/dist/universal/.trae/skills/citable/rubrics/conversion-alignment.md +37 -0
- package/dist/universal/.trae/skills/citable/rubrics/entity-clarity.md +41 -0
- package/dist/universal/.trae/skills/citable/rubrics/evidence-strength.md +53 -0
- package/dist/universal/.trae/skills/citable/rubrics/information-gain.md +33 -0
- package/dist/universal/.trae/skills/citable/rubrics/intent-alignment.md +41 -0
- package/dist/universal/.trae/skills/citable/rubrics/narrative-accuracy.md +46 -0
- package/dist/universal/.trae/skills/citable/rubrics/recommendation-eligibility.md +36 -0
- package/dist/universal/.trae/skills/citable/rubrics/semantic-clarity.md +42 -0
- package/dist/universal/.trae/skills/citable/rubrics/source-authority.md +37 -0
- package/dist/universal/.trae/skills/citable/schemas/claim.schema.json +53 -0
- package/dist/universal/.trae/skills/citable/schemas/common.defs.json +33 -0
- package/dist/universal/.trae/skills/citable/schemas/competitor.schema.json +28 -0
- package/dist/universal/.trae/skills/citable/schemas/config.schema.json +41 -0
- package/dist/universal/.trae/skills/citable/schemas/crawler.schema.json +33 -0
- package/dist/universal/.trae/skills/citable/schemas/detector-quality.schema.json +39 -0
- package/dist/universal/.trae/skills/citable/schemas/entity.schema.json +39 -0
- package/dist/universal/.trae/skills/citable/schemas/evidence.schema.json +41 -0
- package/dist/universal/.trae/skills/citable/schemas/experiment.schema.json +37 -0
- package/dist/universal/.trae/skills/citable/schemas/finding.schema.json +101 -0
- package/dist/universal/.trae/skills/citable/schemas/page.schema.json +40 -0
- package/dist/universal/.trae/skills/citable/schemas/project.schema.json +29 -0
- package/dist/universal/.trae/skills/citable/schemas/prompt-result.schema.json +37 -0
- package/dist/universal/.trae/skills/citable/schemas/prompt.schema.json +41 -0
- package/dist/universal/.trae/skills/citable/schemas/query.schema.json +43 -0
- package/dist/universal/.trae/skills/citable/schemas/run.schema.json +36 -0
- package/dist/universal/.trae/skills/citable/scripts/README.md +4 -0
- package/dist/universal/.trae/skills/citable/templates/finding-review.md +54 -0
- package/dist/universal/.trae-cn/skills/citable/SKILL.md +137 -0
- package/dist/universal/.trae-cn/skills/citable/VERSION +1 -0
- package/dist/universal/.trae-cn/skills/citable/commands/README.md +36 -0
- package/dist/universal/.trae-cn/skills/citable/commands/ingest.md +44 -0
- package/dist/universal/.trae-cn/skills/citable/commands/measurement.md +49 -0
- package/dist/universal/.trae-cn/skills/citable/commands/optimize-page.md +53 -0
- package/dist/universal/.trae-cn/skills/citable/commands/page-work.md +48 -0
- package/dist/universal/.trae-cn/skills/citable/commands/validate-render.md +24 -0
- package/dist/universal/.trae-cn/skills/citable/manifest.json +54 -0
- package/dist/universal/.trae-cn/skills/citable/policies/crawler-policy-template.md +47 -0
- package/dist/universal/.trae-cn/skills/citable/references/anti-patterns.md +61 -0
- package/dist/universal/.trae-cn/skills/citable/rubrics/README.md +30 -0
- package/dist/universal/.trae-cn/skills/citable/rubrics/answer-extractability.md +44 -0
- package/dist/universal/.trae-cn/skills/citable/rubrics/claim-boundedness.md +36 -0
- package/dist/universal/.trae-cn/skills/citable/rubrics/comparison-fairness.md +30 -0
- package/dist/universal/.trae-cn/skills/citable/rubrics/conversion-alignment.md +37 -0
- package/dist/universal/.trae-cn/skills/citable/rubrics/entity-clarity.md +41 -0
- package/dist/universal/.trae-cn/skills/citable/rubrics/evidence-strength.md +53 -0
- package/dist/universal/.trae-cn/skills/citable/rubrics/information-gain.md +33 -0
- package/dist/universal/.trae-cn/skills/citable/rubrics/intent-alignment.md +41 -0
- package/dist/universal/.trae-cn/skills/citable/rubrics/narrative-accuracy.md +46 -0
- package/dist/universal/.trae-cn/skills/citable/rubrics/recommendation-eligibility.md +36 -0
- package/dist/universal/.trae-cn/skills/citable/rubrics/semantic-clarity.md +42 -0
- package/dist/universal/.trae-cn/skills/citable/rubrics/source-authority.md +37 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/claim.schema.json +53 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/common.defs.json +33 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/competitor.schema.json +28 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/config.schema.json +41 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/crawler.schema.json +33 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/detector-quality.schema.json +39 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/entity.schema.json +39 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/evidence.schema.json +41 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/experiment.schema.json +37 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/finding.schema.json +101 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/page.schema.json +40 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/project.schema.json +29 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/prompt-result.schema.json +37 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/prompt.schema.json +41 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/query.schema.json +43 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/run.schema.json +36 -0
- package/dist/universal/.trae-cn/skills/citable/scripts/README.md +4 -0
- package/dist/universal/.trae-cn/skills/citable/templates/finding-review.md +54 -0
- package/dist/universal/manifest.json +598 -0
- package/package.json +89 -0
- package/schemas/claim.schema.json +53 -0
- package/schemas/common.defs.json +33 -0
- package/schemas/competitor.schema.json +28 -0
- package/schemas/config.schema.json +41 -0
- package/schemas/crawler.schema.json +33 -0
- package/schemas/detector-quality.schema.json +39 -0
- package/schemas/entity.schema.json +39 -0
- package/schemas/evidence.schema.json +41 -0
- package/schemas/experiment.schema.json +37 -0
- package/schemas/finding.schema.json +101 -0
- package/schemas/page.schema.json +40 -0
- package/schemas/project.schema.json +29 -0
- package/schemas/prompt-result.schema.json +37 -0
- package/schemas/prompt.schema.json +41 -0
- package/schemas/query.schema.json +43 -0
- package/schemas/run.schema.json +36 -0
- package/scripts/build-dist.js +143 -0
- package/skill/SKILL.md +137 -0
- package/skill/commands/README.md +36 -0
- package/skill/commands/ingest.md +44 -0
- package/skill/commands/measurement.md +49 -0
- package/skill/commands/optimize-page.md +53 -0
- package/skill/commands/page-work.md +48 -0
- package/skill/commands/validate-render.md +24 -0
- package/skill/policies/crawler-policy-template.md +47 -0
- package/skill/references/anti-patterns.md +61 -0
- package/skill/rubrics/README.md +30 -0
- package/skill/rubrics/answer-extractability.md +44 -0
- package/skill/rubrics/claim-boundedness.md +36 -0
- package/skill/rubrics/comparison-fairness.md +30 -0
- package/skill/rubrics/conversion-alignment.md +37 -0
- package/skill/rubrics/entity-clarity.md +41 -0
- package/skill/rubrics/evidence-strength.md +53 -0
- package/skill/rubrics/information-gain.md +33 -0
- package/skill/rubrics/intent-alignment.md +41 -0
- package/skill/rubrics/narrative-accuracy.md +46 -0
- package/skill/rubrics/recommendation-eligibility.md +36 -0
- package/skill/rubrics/semantic-clarity.md +42 -0
- package/skill/rubrics/source-authority.md +37 -0
- package/skill/templates/finding-review.md +54 -0
- package/src/cli/index.js +135 -0
- package/src/commands/audit.js +111 -0
- package/src/commands/compareSnapshots.js +48 -0
- package/src/commands/context.js +62 -0
- package/src/commands/init.js +111 -0
- package/src/commands/inspect.js +61 -0
- package/src/commands/mapClaims.js +89 -0
- package/src/commands/schemaCmd.js +71 -0
- package/src/commands/substantiate.js +121 -0
- package/src/commands/validate.js +27 -0
- package/src/crawler/fetch.js +31 -0
- package/src/crawler/robots.js +67 -0
- package/src/crawler/sitemap.js +25 -0
- package/src/detectors/ans.js +219 -0
- package/src/detectors/arch.js +154 -0
- package/src/detectors/claim.js +230 -0
- package/src/detectors/crawl.js +143 -0
- package/src/detectors/entity.js +202 -0
- package/src/detectors/evd.js +164 -0
- package/src/detectors/framework.js +137 -0
- package/src/detectors/geoReco.js +218 -0
- package/src/detectors/index.js +50 -0
- package/src/detectors/lifeMeas.js +212 -0
- package/src/detectors/link.js +121 -0
- package/src/detectors/page.js +202 -0
- package/src/detectors/schemaData.js +249 -0
- package/src/detectors/tech.js +397 -0
- package/src/evidence/run.js +88 -0
- package/src/extractor/page.js +125 -0
- package/src/extractor/site.js +175 -0
- package/src/installer/index.js +1117 -0
- package/src/installer/providers.js +164 -0
- package/src/registries/index.js +127 -0
- package/src/reporting/report.js +82 -0
- package/src/shared/io.js +56 -0
- package/src/shared/schemaValidator.js +29 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { defineDetector, indexTargets, pageSubject } from './framework.js';
|
|
2
|
+
|
|
3
|
+
const D = [];
|
|
4
|
+
|
|
5
|
+
D.push(defineDetector({
|
|
6
|
+
id: 'PAGE-001', name: 'Missing title element', namespace: 'PAGE',
|
|
7
|
+
description: 'Index-target page has no <title>.',
|
|
8
|
+
discipline: ['seo', 'aeo'], severity: 'high', deterministic: true, requires: ['site'],
|
|
9
|
+
impact: { ranking: 'high', representation: 'medium' },
|
|
10
|
+
applicable_requirement: 'SEO §2 unique and accurate title; §5 title element',
|
|
11
|
+
remediation: 'Add a concise title identifying the page subject and distinguishing it from other pages.',
|
|
12
|
+
verification: 'Confirm a non-empty <title> in rendered HTML.',
|
|
13
|
+
check(ctx) {
|
|
14
|
+
return indexTargets(ctx).filter((p) => p.status === 200 && !p.title).map((p) => ({
|
|
15
|
+
subject: pageSubject(p), summary: 'Page has no title element', evidence: ['<title> absent or empty'],
|
|
16
|
+
}));
|
|
17
|
+
},
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
D.push(defineDetector({
|
|
21
|
+
id: 'PAGE-002', name: 'Duplicate title across pages', namespace: 'PAGE',
|
|
22
|
+
description: 'Two or more index-target pages share an identical title.',
|
|
23
|
+
discipline: ['seo'], severity: 'medium', deterministic: true, requires: ['site'],
|
|
24
|
+
impact: { ranking: 'medium' },
|
|
25
|
+
applicable_requirement: 'SEO §5 title should distinguish the page from other pages; avoid boilerplate duplication',
|
|
26
|
+
remediation: 'Differentiate titles to reflect each page’s distinct intent.',
|
|
27
|
+
verification: 'Confirm title uniqueness across index targets.',
|
|
28
|
+
check(ctx) {
|
|
29
|
+
const byTitle = new Map();
|
|
30
|
+
for (const p of indexTargets(ctx)) {
|
|
31
|
+
if (!p.title || p.status !== 200) continue;
|
|
32
|
+
if (!byTitle.has(p.title)) byTitle.set(p.title, []);
|
|
33
|
+
byTitle.get(p.title).push(p);
|
|
34
|
+
}
|
|
35
|
+
return [...byTitle.entries()].filter(([, ps]) => ps.length > 1).map(([title, ps]) => ({
|
|
36
|
+
subject: { type: 'site', identifier: `title:${title}` },
|
|
37
|
+
summary: `${ps.length} pages share the title "${title}"`,
|
|
38
|
+
evidence: ps.map((p) => p.url),
|
|
39
|
+
}));
|
|
40
|
+
},
|
|
41
|
+
}));
|
|
42
|
+
|
|
43
|
+
D.push(defineDetector({
|
|
44
|
+
id: 'PAGE-003', name: 'Missing meta description', namespace: 'PAGE',
|
|
45
|
+
description: 'Index-target page lacks a meta description (search-result copy).',
|
|
46
|
+
discipline: ['seo'], severity: 'low', deterministic: true, requires: ['site'],
|
|
47
|
+
impact: { conversion: 'low', ranking: 'none' },
|
|
48
|
+
applicable_requirement: 'SEO §5 meta description as search-result copy, not a ranking lever',
|
|
49
|
+
remediation: 'Add an accurate, page-specific description stating the expected value.',
|
|
50
|
+
verification: 'Confirm meta[name=description] present and non-empty.',
|
|
51
|
+
check(ctx) {
|
|
52
|
+
return indexTargets(ctx).filter((p) => p.status === 200 && !p.metaDescription).map((p) => ({
|
|
53
|
+
subject: pageSubject(p), summary: 'Page has no meta description', evidence: ['meta[name=description] absent'],
|
|
54
|
+
}));
|
|
55
|
+
},
|
|
56
|
+
}));
|
|
57
|
+
|
|
58
|
+
D.push(defineDetector({
|
|
59
|
+
id: 'PAGE-004', name: 'Duplicate meta description', namespace: 'PAGE',
|
|
60
|
+
description: 'Multiple pages share an identical meta description.',
|
|
61
|
+
discipline: ['seo'], severity: 'low', deterministic: true, requires: ['site'],
|
|
62
|
+
impact: { conversion: 'low' },
|
|
63
|
+
applicable_requirement: 'SEO §5 avoid duplicated descriptions',
|
|
64
|
+
remediation: 'Write distinct descriptions per page.',
|
|
65
|
+
verification: 'Confirm description uniqueness.',
|
|
66
|
+
check(ctx) {
|
|
67
|
+
const byDesc = new Map();
|
|
68
|
+
for (const p of indexTargets(ctx)) {
|
|
69
|
+
if (!p.metaDescription || p.status !== 200) continue;
|
|
70
|
+
if (!byDesc.has(p.metaDescription)) byDesc.set(p.metaDescription, []);
|
|
71
|
+
byDesc.get(p.metaDescription).push(p);
|
|
72
|
+
}
|
|
73
|
+
return [...byDesc.entries()].filter(([, ps]) => ps.length > 1).map(([desc, ps]) => ({
|
|
74
|
+
subject: { type: 'site', identifier: `description:${desc.slice(0, 40)}` },
|
|
75
|
+
summary: `${ps.length} pages share the same meta description`,
|
|
76
|
+
evidence: ps.map((p) => p.url),
|
|
77
|
+
}));
|
|
78
|
+
},
|
|
79
|
+
}));
|
|
80
|
+
|
|
81
|
+
D.push(defineDetector({
|
|
82
|
+
id: 'PAGE-005', name: 'Missing or multiple H1', namespace: 'PAGE',
|
|
83
|
+
description: 'Page does not have exactly one primary heading.',
|
|
84
|
+
discipline: ['seo', 'aeo'], severity: 'medium', deterministic: true, requires: ['site'],
|
|
85
|
+
impact: { ranking: 'low', citation: 'low' },
|
|
86
|
+
applicable_requirement: 'SEO §2 one clear primary heading; §5 primary heading',
|
|
87
|
+
remediation: 'Use exactly one H1 that identifies the page purpose.',
|
|
88
|
+
verification: 'Count H1 elements.',
|
|
89
|
+
check(ctx) {
|
|
90
|
+
return indexTargets(ctx).filter((p) => p.status === 200 && p.h1s.length !== 1).map((p) => ({
|
|
91
|
+
subject: pageSubject(p),
|
|
92
|
+
summary: p.h1s.length === 0 ? 'Page has no H1' : `Page has ${p.h1s.length} H1 elements`,
|
|
93
|
+
evidence: p.h1s.length ? p.h1s.map((h) => `H1: ${h.text}`) : ['no <h1> found'],
|
|
94
|
+
captured: p.h1s.length, expected: 1,
|
|
95
|
+
}));
|
|
96
|
+
},
|
|
97
|
+
}));
|
|
98
|
+
|
|
99
|
+
D.push(defineDetector({
|
|
100
|
+
id: 'PAGE-006', name: 'Heading hierarchy skip', namespace: 'PAGE',
|
|
101
|
+
description: 'Heading levels skip (e.g., H1 → H3), indicating headings used for visual size rather than document structure.',
|
|
102
|
+
discipline: ['seo', 'aeo'], severity: 'low', deterministic: true, requires: ['site'],
|
|
103
|
+
impact: { citation: 'low' },
|
|
104
|
+
applicable_requirement: 'SEO §5 headings represent real document hierarchy',
|
|
105
|
+
remediation: 'Restructure headings to descend one level at a time.',
|
|
106
|
+
verification: 'Walk heading sequence and confirm no level is skipped.',
|
|
107
|
+
check(ctx) {
|
|
108
|
+
const hits = [];
|
|
109
|
+
for (const p of indexTargets(ctx)) {
|
|
110
|
+
if (p.status !== 200) continue;
|
|
111
|
+
let prev = 0;
|
|
112
|
+
for (const h of p.headings) {
|
|
113
|
+
if (prev > 0 && h.level > prev + 1) {
|
|
114
|
+
hits.push({
|
|
115
|
+
subject: pageSubject(p),
|
|
116
|
+
summary: `Heading hierarchy skips from H${prev} to H${h.level} ("${h.text.slice(0, 60)}")`,
|
|
117
|
+
evidence: [`sequence: H${prev} → H${h.level}`],
|
|
118
|
+
});
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
prev = h.level;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return hits;
|
|
125
|
+
},
|
|
126
|
+
}));
|
|
127
|
+
|
|
128
|
+
D.push(defineDetector({
|
|
129
|
+
id: 'PAGE-007', name: 'Image missing alt text', namespace: 'PAGE',
|
|
130
|
+
description: 'Content images lack alt attributes.',
|
|
131
|
+
discipline: ['seo'], severity: 'low', deterministic: true, requires: ['site'],
|
|
132
|
+
impact: { ranking: 'low', representation: 'low' },
|
|
133
|
+
applicable_requirement: 'SEO §5 images: appropriate alt text; accessibility preservation (premise 3.7)',
|
|
134
|
+
remediation: 'Add descriptive alt text (or empty alt for purely decorative images, reviewed case by case).',
|
|
135
|
+
verification: 'Confirm every <img> has an alt attribute.',
|
|
136
|
+
check(ctx) {
|
|
137
|
+
return indexTargets(ctx)
|
|
138
|
+
.map((p) => ({ p, missing: p.images.filter((i) => i.alt === undefined || i.alt === null) }))
|
|
139
|
+
.filter(({ p, missing }) => p.status === 200 && missing.length > 0)
|
|
140
|
+
.map(({ p, missing }) => ({
|
|
141
|
+
subject: pageSubject(p),
|
|
142
|
+
summary: `${missing.length} image(s) without alt attribute`,
|
|
143
|
+
evidence: missing.slice(0, 5).map((i) => `img src=${i.src}`),
|
|
144
|
+
}));
|
|
145
|
+
},
|
|
146
|
+
}));
|
|
147
|
+
|
|
148
|
+
D.push(defineDetector({
|
|
149
|
+
id: 'PAGE-008', name: 'Thin index-target content', namespace: 'PAGE',
|
|
150
|
+
description: 'An index-target page has very little primary text.',
|
|
151
|
+
discipline: ['seo', 'aeo'], severity: 'medium', deterministic: false, requires: ['site'],
|
|
152
|
+
impact: { ranking: 'medium', citation: 'medium' },
|
|
153
|
+
applicable_requirement: 'SEO §2 meaningful main content; §4 sufficient depth',
|
|
154
|
+
false_positive_conditions: ['intentionally short pages (contact, legal index) — classify them in the page registry'],
|
|
155
|
+
remediation: 'Either add substantive content for the intent or remove the page from the index target set.',
|
|
156
|
+
verification: 'Re-measure extracted word count after revision.',
|
|
157
|
+
check(ctx) {
|
|
158
|
+
const min = ctx.config?.audit?.thin_content_words ?? 120;
|
|
159
|
+
return indexTargets(ctx)
|
|
160
|
+
.filter((p) => p.status === 200 && p.wordCount > 0 && p.wordCount < min)
|
|
161
|
+
.map((p) => ({
|
|
162
|
+
subject: pageSubject(p),
|
|
163
|
+
summary: `Index-target page has only ~${p.wordCount} words (threshold ${min})`,
|
|
164
|
+
evidence: [`extracted word count: ${p.wordCount}`],
|
|
165
|
+
confidence: 'high',
|
|
166
|
+
}));
|
|
167
|
+
},
|
|
168
|
+
}));
|
|
169
|
+
|
|
170
|
+
D.push(defineDetector({
|
|
171
|
+
id: 'PAGE-009', name: 'Keyword stuffing', namespace: 'PAGE',
|
|
172
|
+
description: 'A single non-trivial term dominates the page text at a frequency inconsistent with natural prose.',
|
|
173
|
+
discipline: ['seo'], severity: 'medium', deterministic: false, requires: ['site'],
|
|
174
|
+
impact: { ranking: 'medium', reputational: 'low' },
|
|
175
|
+
applicable_requirement: 'SEO §5 semantic coverage, not term-frequency quotas; anti-pattern library: keyword stuffing',
|
|
176
|
+
false_positive_conditions: ['glossaries and reference pages legitimately repeating a defined term'],
|
|
177
|
+
remediation: 'Rewrite for human comprehension; vary phrasing naturally; do not chase term-frequency quotas.',
|
|
178
|
+
verification: 'Re-measure dominant-term density.',
|
|
179
|
+
check(ctx) {
|
|
180
|
+
const hits = [];
|
|
181
|
+
for (const p of indexTargets(ctx)) {
|
|
182
|
+
if (p.status !== 200 || p.wordCount < 80) continue;
|
|
183
|
+
const words = p.text.toLowerCase().match(/[a-z][a-z-]{3,}/g) || [];
|
|
184
|
+
const freq = new Map();
|
|
185
|
+
for (const w of words) freq.set(w, (freq.get(w) || 0) + 1);
|
|
186
|
+
const stop = new Set(['this', 'that', 'with', 'from', 'have', 'your', 'about', 'more', 'when', 'they', 'their', 'will', 'which', 'into', 'than', 'them', 'these', 'those', 'because', 'does', 'were', 'been', 'also', 'such', 'other']);
|
|
187
|
+
let top = null;
|
|
188
|
+
for (const [w, n] of freq) if (!stop.has(w) && (!top || n > top[1])) top = [w, n];
|
|
189
|
+
if (top && top[1] / words.length > 0.08 && top[1] >= 10) {
|
|
190
|
+
hits.push({
|
|
191
|
+
subject: pageSubject(p),
|
|
192
|
+
summary: `Term "${top[0]}" is ${(100 * top[1] / words.length).toFixed(1)}% of page words (${top[1]} occurrences)`,
|
|
193
|
+
evidence: [`density ${(100 * top[1] / words.length).toFixed(1)}% exceeds 8% threshold`],
|
|
194
|
+
confidence: 'medium',
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return hits;
|
|
199
|
+
},
|
|
200
|
+
}));
|
|
201
|
+
|
|
202
|
+
export default D;
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { defineDetector, indexTargets, pageSubject, safePath } from './framework.js';
|
|
2
|
+
import { isPastDate } from '../shared/io.js';
|
|
3
|
+
|
|
4
|
+
const D = [];
|
|
5
|
+
|
|
6
|
+
D.push(defineDetector({
|
|
7
|
+
id: 'SCHEMA-001', name: 'JSON-LD parse failure', namespace: 'SCHEMA',
|
|
8
|
+
description: 'A JSON-LD script block does not parse as JSON.',
|
|
9
|
+
discipline: ['seo', 'aeo', 'geo'], severity: 'high', deterministic: true, requires: ['site'],
|
|
10
|
+
impact: { ranking: 'medium', representation: 'medium' },
|
|
11
|
+
applicable_requirement: 'SEO §7 schema validation in CI/CD; detector spec: JSON-LD parse failure',
|
|
12
|
+
remediation: 'Fix the JSON syntax; generate JSON-LD from data structures rather than hand-edited strings.',
|
|
13
|
+
verification: 'All ld+json blocks parse.',
|
|
14
|
+
check(ctx) {
|
|
15
|
+
const hits = [];
|
|
16
|
+
for (const p of ctx.site.pages) {
|
|
17
|
+
for (const j of p.jsonLd) {
|
|
18
|
+
if (j.parseError) {
|
|
19
|
+
hits.push({
|
|
20
|
+
subject: { type: 'schema_block', identifier: `${p.url}#ld+json`, url: p.url, ...(p.sourceFile ? { source_file: p.sourceFile } : {}) },
|
|
21
|
+
summary: `JSON-LD block fails to parse: ${j.parseError}`,
|
|
22
|
+
evidence: [`parse error: ${j.parseError}`, `block head: ${j.raw.slice(0, 120)}`],
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return hits;
|
|
28
|
+
},
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
D.push(defineDetector({
|
|
32
|
+
id: 'SCHEMA-002', name: 'Schema headline/name mismatch with visible content', namespace: 'SCHEMA',
|
|
33
|
+
description: 'Article/WebPage headline in JSON-LD does not match the visible title or H1.',
|
|
34
|
+
discipline: ['seo', 'aeo'], severity: 'medium', deterministic: true, requires: ['site'],
|
|
35
|
+
impact: { representation: 'medium' },
|
|
36
|
+
applicable_requirement: 'Premise 3.4: structured data must match visible content; SEO §7 no invisible marked-up claims',
|
|
37
|
+
remediation: 'Generate the headline from the same authoritative field that renders the visible title.',
|
|
38
|
+
verification: 'Schema headline equals visible title or H1.',
|
|
39
|
+
check(ctx) {
|
|
40
|
+
const hits = [];
|
|
41
|
+
for (const p of indexTargets(ctx)) {
|
|
42
|
+
for (const j of p.jsonLd) {
|
|
43
|
+
for (const b of j.blocks) {
|
|
44
|
+
const type = [].concat(b['@type'] || []).join(',');
|
|
45
|
+
if (!/Article|BlogPosting|TechArticle|WebPage/i.test(type)) continue;
|
|
46
|
+
const headline = b.headline || b.name;
|
|
47
|
+
if (!headline) continue;
|
|
48
|
+
const visible = [p.title, ...(p.h1s.map((h) => h.text))].filter(Boolean).map((s) => s.toLowerCase().trim());
|
|
49
|
+
if (!visible.some((v) => v.includes(String(headline).toLowerCase().trim()) || String(headline).toLowerCase().trim().includes(v))) {
|
|
50
|
+
hits.push({
|
|
51
|
+
subject: { type: 'schema_block', identifier: `${p.url}#${type}`, url: p.url },
|
|
52
|
+
summary: `Schema headline "${headline}" does not match visible title or H1`,
|
|
53
|
+
evidence: [`schema headline: ${headline}`, `visible title: ${p.title}`, `H1: ${p.h1s.map((h) => h.text).join(' | ') || 'none'}`],
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return hits;
|
|
60
|
+
},
|
|
61
|
+
}));
|
|
62
|
+
|
|
63
|
+
D.push(defineDetector({
|
|
64
|
+
id: 'SCHEMA-003', name: 'Schema URL conflicts with canonical', namespace: 'SCHEMA',
|
|
65
|
+
description: 'JSON-LD url/mainEntityOfPage disagrees with the page canonical.',
|
|
66
|
+
discipline: ['seo'], severity: 'medium', deterministic: true, requires: ['site'],
|
|
67
|
+
impact: { ranking: 'medium' },
|
|
68
|
+
applicable_requirement: 'SEO §2 canonical signals should agree across structured data URLs',
|
|
69
|
+
remediation: 'Emit the canonical URL in structured data.',
|
|
70
|
+
verification: 'Schema url matches rel=canonical.',
|
|
71
|
+
check(ctx) {
|
|
72
|
+
const hits = [];
|
|
73
|
+
for (const p of indexTargets(ctx)) {
|
|
74
|
+
if (p.canonicals.length !== 1) continue;
|
|
75
|
+
const canon = safePath(p.canonicals[0], p.url);
|
|
76
|
+
for (const j of p.jsonLd) {
|
|
77
|
+
for (const b of j.blocks) {
|
|
78
|
+
const u = typeof b.url === 'string' ? b.url : typeof b.mainEntityOfPage === 'string' ? b.mainEntityOfPage : b.mainEntityOfPage?.['@id'];
|
|
79
|
+
if (u && /WebPage|Article|BlogPosting|TechArticle/i.test([].concat(b['@type'] || []).join(',')) && safePath(u, p.url) !== canon) {
|
|
80
|
+
hits.push({
|
|
81
|
+
subject: { type: 'schema_block', identifier: `${p.url}#url`, url: p.url },
|
|
82
|
+
summary: `Schema URL ${u} conflicts with canonical ${p.canonicals[0]}`,
|
|
83
|
+
evidence: [`schema url: ${u}`, `canonical: ${p.canonicals[0]}`],
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return hits;
|
|
90
|
+
},
|
|
91
|
+
}));
|
|
92
|
+
|
|
93
|
+
D.push(defineDetector({
|
|
94
|
+
id: 'SCHEMA-004', name: 'Inaccurate schema dates', namespace: 'SCHEMA',
|
|
95
|
+
description: 'datePublished is in the future, or dateModified precedes datePublished.',
|
|
96
|
+
discipline: ['seo', 'aeo'], severity: 'medium', deterministic: true, requires: ['site'],
|
|
97
|
+
impact: { representation: 'medium' },
|
|
98
|
+
applicable_requirement: 'SEO §7 accurate dates; AEO §8 do not update dates without material updates',
|
|
99
|
+
remediation: 'Derive dates from the content system of record.',
|
|
100
|
+
verification: 'datePublished ≤ dateModified ≤ now.',
|
|
101
|
+
check(ctx) {
|
|
102
|
+
const now = ctx.refDate ?? new Date();
|
|
103
|
+
const hits = [];
|
|
104
|
+
for (const p of ctx.site.pages) {
|
|
105
|
+
for (const j of p.jsonLd) {
|
|
106
|
+
for (const b of j.blocks) {
|
|
107
|
+
const pub = b.datePublished ? new Date(b.datePublished) : null;
|
|
108
|
+
const mod = b.dateModified ? new Date(b.dateModified) : null;
|
|
109
|
+
if (pub && !Number.isNaN(pub.getTime()) && pub > now) {
|
|
110
|
+
hits.push({
|
|
111
|
+
subject: { type: 'schema_block', identifier: `${p.url}#datePublished`, url: p.url },
|
|
112
|
+
summary: `datePublished ${b.datePublished} is in the future`,
|
|
113
|
+
evidence: [`datePublished: ${b.datePublished}; audit reference date: ${now.toISOString().slice(0, 10)}`],
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
if (pub && mod && !Number.isNaN(pub.getTime()) && !Number.isNaN(mod.getTime()) && mod < pub) {
|
|
117
|
+
hits.push({
|
|
118
|
+
subject: { type: 'schema_block', identifier: `${p.url}#dateModified`, url: p.url },
|
|
119
|
+
summary: `dateModified ${b.dateModified} precedes datePublished ${b.datePublished}`,
|
|
120
|
+
evidence: [`dateModified: ${b.dateModified}; datePublished: ${b.datePublished}`],
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return hits;
|
|
127
|
+
},
|
|
128
|
+
}));
|
|
129
|
+
|
|
130
|
+
D.push(defineDetector({
|
|
131
|
+
id: 'SCHEMA-005', name: 'Rating/review markup without visible reviews', namespace: 'SCHEMA',
|
|
132
|
+
description: 'aggregateRating or review markup exists but the visible page contains no review content.',
|
|
133
|
+
discipline: ['seo'], severity: 'critical', deterministic: true, requires: ['site'],
|
|
134
|
+
impact: { legal: 'high', reputational: 'high', ranking: 'medium' },
|
|
135
|
+
applicable_requirement: 'Premise 3.4: no fabricated ratings or reviews; SEO §7 required controls',
|
|
136
|
+
remediation: 'Remove the rating markup unless genuine, visible, attributable reviews exist.',
|
|
137
|
+
unsafe_shortcuts: ['keeping the markup and adding boilerplate "reviews" text'],
|
|
138
|
+
verification: 'Rating markup exists only alongside visible review content.',
|
|
139
|
+
check(ctx) {
|
|
140
|
+
const reviewRx = /\b(review(s|ed)?|rating|testimonial)\b/i;
|
|
141
|
+
const hits = [];
|
|
142
|
+
for (const p of ctx.site.pages) {
|
|
143
|
+
for (const j of p.jsonLd) {
|
|
144
|
+
for (const b of j.blocks) {
|
|
145
|
+
if ((b.aggregateRating || b.review) && !reviewRx.test(p.text)) {
|
|
146
|
+
hits.push({
|
|
147
|
+
subject: { type: 'schema_block', identifier: `${p.url}#aggregateRating`, url: p.url },
|
|
148
|
+
summary: 'Rating/review markup present but no visible review content on the page',
|
|
149
|
+
evidence: [`schema contains ${b.aggregateRating ? 'aggregateRating' : 'review'}`, 'page text contains no review/rating/testimonial content'],
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return hits;
|
|
156
|
+
},
|
|
157
|
+
}));
|
|
158
|
+
|
|
159
|
+
D.push(defineDetector({
|
|
160
|
+
id: 'SCHEMA-006', name: 'Stale offer price validity', namespace: 'SCHEMA',
|
|
161
|
+
description: 'Offer markup carries a priceValidUntil in the past.',
|
|
162
|
+
discipline: ['seo', 'geo'], severity: 'medium', deterministic: true, requires: ['site'],
|
|
163
|
+
impact: { representation: 'high', conversion: 'medium' },
|
|
164
|
+
applicable_requirement: 'Premise 3.4: avoid stale prices or availability; GEO §11 pricing: immediate on change',
|
|
165
|
+
remediation: 'Regenerate offers from live commercial data; remove expired offers.',
|
|
166
|
+
verification: 'No offer has priceValidUntil in the past.',
|
|
167
|
+
check(ctx) {
|
|
168
|
+
const hits = [];
|
|
169
|
+
for (const p of ctx.site.pages) {
|
|
170
|
+
for (const j of p.jsonLd) {
|
|
171
|
+
for (const b of j.blocks) {
|
|
172
|
+
const offers = [].concat(b.offers || []);
|
|
173
|
+
for (const o of offers) {
|
|
174
|
+
if (o && o.priceValidUntil && isPastDate(o.priceValidUntil, ctx.refDate)) {
|
|
175
|
+
hits.push({
|
|
176
|
+
subject: { type: 'schema_block', identifier: `${p.url}#offers`, url: p.url },
|
|
177
|
+
summary: `Offer priceValidUntil ${o.priceValidUntil} is in the past`,
|
|
178
|
+
evidence: [`priceValidUntil: ${o.priceValidUntil}; price: ${o.price ?? '?'}`],
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return hits;
|
|
186
|
+
},
|
|
187
|
+
}));
|
|
188
|
+
|
|
189
|
+
D.push(defineDetector({
|
|
190
|
+
id: 'SCHEMA-007', name: 'FAQPage markup without matching visible questions', namespace: 'SCHEMA',
|
|
191
|
+
description: 'FAQPage JSON-LD questions do not appear in the visible page text.',
|
|
192
|
+
discipline: ['seo', 'aeo'], severity: 'high', deterministic: true, requires: ['site'],
|
|
193
|
+
impact: { legal: 'medium', ranking: 'medium' },
|
|
194
|
+
applicable_requirement: 'AEO §6 do not deploy mass-generated FAQ schema; anti-pattern: FAQ schema without substantive FAQ content',
|
|
195
|
+
remediation: 'Only mark up FAQs that are visible, substantive page content.',
|
|
196
|
+
verification: 'Every FAQPage question string appears in visible text.',
|
|
197
|
+
check(ctx) {
|
|
198
|
+
const hits = [];
|
|
199
|
+
for (const p of ctx.site.pages) {
|
|
200
|
+
for (const j of p.jsonLd) {
|
|
201
|
+
for (const b of j.blocks) {
|
|
202
|
+
if (![].concat(b['@type'] || []).includes('FAQPage')) continue;
|
|
203
|
+
const questions = [].concat(b.mainEntity || []).map((q) => q?.name).filter(Boolean);
|
|
204
|
+
const missing = questions.filter((q) => !p.text.toLowerCase().includes(String(q).toLowerCase().slice(0, 40)));
|
|
205
|
+
if (questions.length > 0 && missing.length > 0) {
|
|
206
|
+
hits.push({
|
|
207
|
+
subject: { type: 'schema_block', identifier: `${p.url}#FAQPage`, url: p.url },
|
|
208
|
+
summary: `${missing.length}/${questions.length} FAQ schema questions not found in visible content`,
|
|
209
|
+
evidence: missing.slice(0, 3).map((q) => `not visible: "${q}"`),
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return hits;
|
|
216
|
+
},
|
|
217
|
+
}));
|
|
218
|
+
|
|
219
|
+
D.push(defineDetector({
|
|
220
|
+
id: 'SCHEMA-008', name: 'Contradictory Organization graphs', namespace: 'SCHEMA',
|
|
221
|
+
description: 'Multiple Organization blocks exist with the same @id but different names, or different @id values with the same name (split identity).',
|
|
222
|
+
discipline: ['geo', 'seo'], severity: 'high', deterministic: true, requires: ['site'],
|
|
223
|
+
impact: { representation: 'high' },
|
|
224
|
+
applicable_requirement: 'Detector spec: multiple contradictory entity graphs; GEO §9 graph consistency',
|
|
225
|
+
remediation: 'Emit one shared Organization node from a single data source; reference it by @id everywhere else.',
|
|
226
|
+
verification: 'One @id ↔ one name for the organization across all pages.',
|
|
227
|
+
check(ctx) {
|
|
228
|
+
const byId = new Map();
|
|
229
|
+
for (const p of ctx.site.pages) {
|
|
230
|
+
for (const j of p.jsonLd) {
|
|
231
|
+
for (const b of j.blocks) {
|
|
232
|
+
if (!/Organization|Corporation/i.test([].concat(b['@type'] || []).join(','))) continue;
|
|
233
|
+
if (!b['@id'] || !b.name) continue;
|
|
234
|
+
if (!byId.has(b['@id'])) byId.set(b['@id'], new Set());
|
|
235
|
+
byId.get(b['@id']).add(String(b.name));
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return [...byId.entries()]
|
|
240
|
+
.filter(([, names]) => names.size > 1)
|
|
241
|
+
.map(([id, names]) => ({
|
|
242
|
+
subject: { type: 'schema_block', identifier: id },
|
|
243
|
+
summary: `Organization @id ${id} carries ${names.size} different names: ${[...names].join(' / ')}`,
|
|
244
|
+
evidence: [...names].map((n) => `name: ${n}`),
|
|
245
|
+
}));
|
|
246
|
+
},
|
|
247
|
+
}));
|
|
248
|
+
|
|
249
|
+
export default D;
|