@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, entrySubject } from './framework.js';
|
|
2
|
+
import { isPastDate } from '../shared/io.js';
|
|
3
|
+
|
|
4
|
+
const D = [];
|
|
5
|
+
|
|
6
|
+
function allJsonLdBlocks(site) {
|
|
7
|
+
const out = [];
|
|
8
|
+
for (const p of site.pages) {
|
|
9
|
+
for (const j of p.jsonLd) for (const b of j.blocks) out.push({ page: p, block: b });
|
|
10
|
+
}
|
|
11
|
+
return out;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
D.push(defineDetector({
|
|
15
|
+
id: 'ENTITY-001', name: 'Entity missing canonical URL', namespace: 'ENTITY',
|
|
16
|
+
description: 'A registry entity has no canonical URL, so engines have no authoritative page to resolve it to.',
|
|
17
|
+
discipline: ['geo', 'aeo'], severity: 'medium', deterministic: true, requires: ['registries'],
|
|
18
|
+
impact: { representation: 'high' },
|
|
19
|
+
applicable_requirement: 'AEO §3 every entity should have one canonical URL; GEO §3 canonical entities',
|
|
20
|
+
remediation: 'Create or designate one canonical page for the entity and record it in the registry.',
|
|
21
|
+
verification: 'Registry entry has canonical_url set and resolvable.',
|
|
22
|
+
check(ctx) {
|
|
23
|
+
return (ctx.registries.entities?.entries || [])
|
|
24
|
+
.filter((e) => e.status !== 'retired' && !e.canonical_url)
|
|
25
|
+
.map((e) => ({
|
|
26
|
+
subject: entrySubject('entities', e.entity_id),
|
|
27
|
+
summary: `Entity "${e.canonical_name}" has no canonical URL`,
|
|
28
|
+
evidence: [`entities/${e.entity_id}: canonical_url empty`],
|
|
29
|
+
}));
|
|
30
|
+
},
|
|
31
|
+
}));
|
|
32
|
+
|
|
33
|
+
D.push(defineDetector({
|
|
34
|
+
id: 'ENTITY-002', name: 'Schema entity name conflicts with registry', namespace: 'ENTITY',
|
|
35
|
+
description: 'A JSON-LD Organization/Product name does not match the registry canonical name or a documented alias.',
|
|
36
|
+
discipline: ['geo', 'seo'], severity: 'high', deterministic: true, requires: ['site', 'registries'],
|
|
37
|
+
impact: { representation: 'high' },
|
|
38
|
+
applicable_requirement: 'GEO §3 required consistency; detector spec: schema entity differs from visible entity',
|
|
39
|
+
remediation: 'Emit the canonical name from the entity registry in structured data; add legitimate variants to aliases.',
|
|
40
|
+
verification: 'Compare schema names with registry canonical_name and aliases.',
|
|
41
|
+
check(ctx) {
|
|
42
|
+
const entities = (ctx.registries.entities?.entries || []).filter((e) => ['organization', 'product', 'product_family'].includes(e.entity_type));
|
|
43
|
+
if (entities.length === 0) return [];
|
|
44
|
+
const hits = [];
|
|
45
|
+
for (const { page, block } of allJsonLdBlocks(ctx.site)) {
|
|
46
|
+
const type = [].concat(block['@type'] || []).join(',');
|
|
47
|
+
if (!/Organization|Corporation|SoftwareApplication|Product/i.test(type) || !block.name) continue;
|
|
48
|
+
const match = entities.find(
|
|
49
|
+
(e) => e.canonical_name.toLowerCase() === String(block.name).toLowerCase() || (e.aliases || []).some((a) => a.toLowerCase() === String(block.name).toLowerCase())
|
|
50
|
+
);
|
|
51
|
+
if (!match) {
|
|
52
|
+
const nearest = entities.find((e) => String(block.name).toLowerCase().includes(e.canonical_name.toLowerCase().split(' ')[0]) || e.canonical_name.toLowerCase().includes(String(block.name).toLowerCase().split(' ')[0]));
|
|
53
|
+
if (nearest) {
|
|
54
|
+
hits.push({
|
|
55
|
+
subject: { type: 'schema_block', identifier: `${page.url}#${block['@id'] || block.name}`, url: page.url },
|
|
56
|
+
summary: `Schema ${type} name "${block.name}" is not the canonical name "${nearest.canonical_name}" nor a documented alias`,
|
|
57
|
+
evidence: [`schema name: ${block.name}`, `registry canonical: ${nearest.canonical_name}; aliases: ${(nearest.aliases || []).join(', ') || 'none'}`],
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return hits;
|
|
63
|
+
},
|
|
64
|
+
}));
|
|
65
|
+
|
|
66
|
+
D.push(defineDetector({
|
|
67
|
+
id: 'ENTITY-003', name: 'Unstable @id for same entity', namespace: 'ENTITY',
|
|
68
|
+
description: 'The same entity name appears in JSON-LD with different @id values across pages.',
|
|
69
|
+
discipline: ['geo', 'seo'], severity: 'medium', deterministic: true, requires: ['site'],
|
|
70
|
+
impact: { representation: 'medium' },
|
|
71
|
+
applicable_requirement: 'SEO §7 stable @id identifiers; GEO §9 required graph consistency',
|
|
72
|
+
remediation: 'Emit one stable @id per entity from shared data, referenced everywhere.',
|
|
73
|
+
verification: 'Collect @id values per entity name; each name maps to one @id.',
|
|
74
|
+
check(ctx) {
|
|
75
|
+
const byName = new Map();
|
|
76
|
+
for (const { block } of allJsonLdBlocks(ctx.site)) {
|
|
77
|
+
if (!block.name || !block['@id']) continue;
|
|
78
|
+
const key = `${[].concat(block['@type'] || []).join(',')}|${String(block.name).toLowerCase()}`;
|
|
79
|
+
if (!byName.has(key)) byName.set(key, new Set());
|
|
80
|
+
byName.get(key).add(block['@id']);
|
|
81
|
+
}
|
|
82
|
+
return [...byName.entries()]
|
|
83
|
+
.filter(([, ids]) => ids.size > 1)
|
|
84
|
+
.map(([key, ids]) => ({
|
|
85
|
+
subject: { type: 'entity', identifier: key },
|
|
86
|
+
summary: `Entity "${key.split('|')[1]}" uses ${ids.size} different @id values`,
|
|
87
|
+
evidence: [...ids].map((i) => `@id: ${i}`),
|
|
88
|
+
}));
|
|
89
|
+
},
|
|
90
|
+
}));
|
|
91
|
+
|
|
92
|
+
D.push(defineDetector({
|
|
93
|
+
id: 'ENTITY-004', name: 'sameAs profile not in authoritative list', namespace: 'ENTITY',
|
|
94
|
+
description: 'JSON-LD sameAs references a profile URL not recorded as an authoritative profile in the entity registry.',
|
|
95
|
+
discipline: ['geo'], severity: 'low', deterministic: true, requires: ['site', 'registries'],
|
|
96
|
+
impact: { representation: 'medium' },
|
|
97
|
+
applicable_requirement: 'AEO §6 sameAs limited to authoritative profiles; detector spec: unsupported sameAs',
|
|
98
|
+
remediation: 'Either add the profile to authoritative_profiles after verification, or remove it from sameAs.',
|
|
99
|
+
verification: 'Every sameAs URL appears in the registry authoritative_profiles.',
|
|
100
|
+
check(ctx) {
|
|
101
|
+
const entities = ctx.registries.entities?.entries || [];
|
|
102
|
+
if (entities.length === 0) return [];
|
|
103
|
+
const hits = [];
|
|
104
|
+
for (const { page, block } of allJsonLdBlocks(ctx.site)) {
|
|
105
|
+
if (!block.sameAs || !block.name) continue;
|
|
106
|
+
const entity = entities.find((e) => e.canonical_name.toLowerCase() === String(block.name).toLowerCase() || (e.aliases || []).some((a) => a.toLowerCase() === String(block.name).toLowerCase()));
|
|
107
|
+
if (!entity) continue;
|
|
108
|
+
const approved = new Set(entity.authoritative_profiles || []);
|
|
109
|
+
for (const s of [].concat(block.sameAs)) {
|
|
110
|
+
if (!approved.has(s)) {
|
|
111
|
+
hits.push({
|
|
112
|
+
subject: { type: 'schema_block', identifier: `${page.url}#sameAs`, url: page.url },
|
|
113
|
+
summary: `sameAs "${s}" for "${block.name}" is not a registered authoritative profile`,
|
|
114
|
+
evidence: [`schema sameAs: ${s}`, `registered profiles: ${[...approved].join(', ') || 'none'}`],
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return hits;
|
|
120
|
+
},
|
|
121
|
+
}));
|
|
122
|
+
|
|
123
|
+
D.push(defineDetector({
|
|
124
|
+
id: 'ENTITY-005', name: 'Product entity without owner relationship', namespace: 'ENTITY',
|
|
125
|
+
description: 'A product/product-family entity records no owning organization.',
|
|
126
|
+
discipline: ['geo'], severity: 'medium', deterministic: true, requires: ['registries'],
|
|
127
|
+
impact: { representation: 'high' },
|
|
128
|
+
applicable_requirement: 'GEO §3 the engine must determine which products the organization owns; detector spec: product ownership ambiguous',
|
|
129
|
+
remediation: 'Set owner_entity (or a relationship) linking the product to its organization.',
|
|
130
|
+
verification: 'Product entity has owner_entity or an ownership relationship.',
|
|
131
|
+
check(ctx) {
|
|
132
|
+
return (ctx.registries.entities?.entries || [])
|
|
133
|
+
.filter((e) => ['product', 'product_family', 'service'].includes(e.entity_type) && e.status !== 'retired')
|
|
134
|
+
.filter((e) => !e.owner_entity && !(e.relationships || []).some((r) => ['owned_by', 'organization', 'publisher'].includes(r.type)))
|
|
135
|
+
.map((e) => ({
|
|
136
|
+
subject: entrySubject('entities', e.entity_id),
|
|
137
|
+
summary: `Product entity "${e.canonical_name}" has no recorded owning organization`,
|
|
138
|
+
evidence: [`entities/${e.entity_id}: owner_entity empty; no ownership relationship`],
|
|
139
|
+
}));
|
|
140
|
+
},
|
|
141
|
+
}));
|
|
142
|
+
|
|
143
|
+
D.push(defineDetector({
|
|
144
|
+
id: 'ENTITY-006', name: 'Unregistered name variant in page text', namespace: 'ENTITY',
|
|
145
|
+
description: 'Page text uses a variant of an entity name that is neither the canonical name nor a documented alias.',
|
|
146
|
+
discipline: ['geo', 'seo'], severity: 'low', deterministic: false, requires: ['site', 'registries'],
|
|
147
|
+
impact: { representation: 'medium' },
|
|
148
|
+
applicable_requirement: 'GEO §3 category contradictions and naming drift; SEO §6 consistent names',
|
|
149
|
+
false_positive_conditions: ['grammatical possessives and legitimate prose inflections'],
|
|
150
|
+
remediation: 'Standardize on the canonical name, or register the variant as an alias if intentional.',
|
|
151
|
+
verification: 'Page text uses only canonical names and registered aliases.',
|
|
152
|
+
check(ctx) {
|
|
153
|
+
const hits = [];
|
|
154
|
+
for (const e of (ctx.registries.entities?.entries || []).filter((e) => ['organization', 'product'].includes(e.entity_type))) {
|
|
155
|
+
const canonical = e.canonical_name;
|
|
156
|
+
const parts = canonical.split(/\s+/);
|
|
157
|
+
if (parts.length < 2) continue; // single-word names produce too many false variants
|
|
158
|
+
const known = new Set([canonical.toLowerCase(), ...(e.aliases || []).map((a) => a.toLowerCase())]);
|
|
159
|
+
// variant: same words joined/hyphenated/reordered-case
|
|
160
|
+
const variantRx = new RegExp(parts.join('[\\s-]*'), 'gi');
|
|
161
|
+
for (const p of indexTargets(ctx)) {
|
|
162
|
+
for (const m of p.text.matchAll(variantRx)) {
|
|
163
|
+
const found = m[0];
|
|
164
|
+
if (!known.has(found.toLowerCase())) {
|
|
165
|
+
hits.push({
|
|
166
|
+
subject: pageSubject(p),
|
|
167
|
+
summary: `Name variant "${found}" used for entity "${canonical}" (not a registered alias)`,
|
|
168
|
+
evidence: [`found: "${found}"`, `canonical: "${canonical}"`],
|
|
169
|
+
confidence: 'medium',
|
|
170
|
+
});
|
|
171
|
+
break; // one hit per page per entity
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return hits;
|
|
177
|
+
},
|
|
178
|
+
}));
|
|
179
|
+
|
|
180
|
+
D.push(defineDetector({
|
|
181
|
+
id: 'ENTITY-007', name: 'Entity verification stale', namespace: 'ENTITY',
|
|
182
|
+
description: 'An active entity has not been verified within the last 12 months (or last_verified missing).',
|
|
183
|
+
discipline: ['geo'], severity: 'low', deterministic: true, requires: ['registries'],
|
|
184
|
+
impact: { representation: 'medium', maintainability: 'medium' },
|
|
185
|
+
applicable_requirement: 'GEO §3 entity record last_verified; lifecycle premises',
|
|
186
|
+
remediation: 'Re-verify identity, category, relationships, and profiles; update last_verified.',
|
|
187
|
+
verification: 'last_verified within 12 months.',
|
|
188
|
+
check(ctx) {
|
|
189
|
+
const cutoff = new Date(ctx.refDate ?? Date.now());
|
|
190
|
+
cutoff.setMonth(cutoff.getMonth() - 12);
|
|
191
|
+
return (ctx.registries.entities?.entries || [])
|
|
192
|
+
.filter((e) => e.status === 'active' || e.status === 'verified')
|
|
193
|
+
.filter((e) => !e.last_verified || new Date(e.last_verified) < cutoff)
|
|
194
|
+
.map((e) => ({
|
|
195
|
+
subject: entrySubject('entities', e.entity_id),
|
|
196
|
+
summary: `Entity "${e.canonical_name}" not verified in the last 12 months (last: ${e.last_verified ?? 'never'})`,
|
|
197
|
+
evidence: [`last_verified: ${e.last_verified ?? 'missing'}`],
|
|
198
|
+
}));
|
|
199
|
+
},
|
|
200
|
+
}));
|
|
201
|
+
|
|
202
|
+
export default D;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { defineDetector, entrySubject } from './framework.js';
|
|
2
|
+
import { isPastDate } from '../shared/io.js';
|
|
3
|
+
|
|
4
|
+
const D = [];
|
|
5
|
+
|
|
6
|
+
D.push(defineDetector({
|
|
7
|
+
id: 'EVD-001', name: 'Evidence past validity date', namespace: 'EVD',
|
|
8
|
+
description: 'An evidence entry has passed valid_until but its verification_status is not stale/revoked.',
|
|
9
|
+
discipline: ['aeo', 'geo'], severity: 'medium', deterministic: true, requires: ['registries'],
|
|
10
|
+
impact: { legal: 'medium', citation: 'medium' },
|
|
11
|
+
applicable_requirement: 'Registry §6.5 valid_until; AEO §8 source revalidation',
|
|
12
|
+
remediation: 'Re-validate the evidence or mark it stale and re-assess dependent claims.',
|
|
13
|
+
verification: 'No verified evidence past its valid_until date.',
|
|
14
|
+
check(ctx) {
|
|
15
|
+
return (ctx.registries.evidence?.entries || [])
|
|
16
|
+
.filter((e) => isPastDate(e.valid_until, ctx.refDate) && !['stale', 'revoked', 'inaccessible'].includes(e.verification_status))
|
|
17
|
+
.map((e) => ({
|
|
18
|
+
subject: entrySubject('evidence', e.evidence_id),
|
|
19
|
+
summary: `Evidence "${e.title}" passed valid_until ${e.valid_until} but is still ${e.verification_status}`,
|
|
20
|
+
evidence: [`valid_until: ${e.valid_until}; verification_status: ${e.verification_status}`],
|
|
21
|
+
}));
|
|
22
|
+
},
|
|
23
|
+
}));
|
|
24
|
+
|
|
25
|
+
D.push(defineDetector({
|
|
26
|
+
id: 'EVD-002', name: 'Benchmark/test evidence missing methodology', namespace: 'EVD',
|
|
27
|
+
description: 'Benchmark, test-result, or dataset evidence records no methodology or measurement period.',
|
|
28
|
+
discipline: ['aeo', 'geo'], severity: 'medium', deterministic: true, requires: ['registries'],
|
|
29
|
+
impact: { citation: 'medium', legal: 'medium' },
|
|
30
|
+
applicable_requirement: 'AEO §8 version evidence: methodology, test date; detector spec: missing methodology / measurement period',
|
|
31
|
+
remediation: 'Record methodology, test conditions, and measurement period, or downgrade dependent claims.',
|
|
32
|
+
verification: 'Benchmark/test evidence entries carry methodology and measurement_period.',
|
|
33
|
+
check(ctx) {
|
|
34
|
+
return (ctx.registries.evidence?.entries || [])
|
|
35
|
+
.filter((e) => ['benchmark', 'test_result', 'dataset'].includes(e.evidence_type))
|
|
36
|
+
.filter((e) => !e.methodology || !e.measurement_period)
|
|
37
|
+
.map((e) => ({
|
|
38
|
+
subject: entrySubject('evidence', e.evidence_id),
|
|
39
|
+
summary: `${e.evidence_type} evidence "${e.title}" lacks ${!e.methodology ? 'methodology' : ''}${!e.methodology && !e.measurement_period ? ' and ' : ''}${!e.measurement_period ? 'measurement period' : ''}`,
|
|
40
|
+
evidence: [`methodology: ${e.methodology ?? 'missing'}; measurement_period: ${e.measurement_period ?? 'missing'}`],
|
|
41
|
+
}));
|
|
42
|
+
},
|
|
43
|
+
}));
|
|
44
|
+
|
|
45
|
+
D.push(defineDetector({
|
|
46
|
+
id: 'EVD-003', name: 'Claim references dangling or unverified evidence', namespace: 'EVD',
|
|
47
|
+
description: 'A claim references an evidence id that does not exist or has verification_status unverified.',
|
|
48
|
+
discipline: ['aeo', 'geo'], severity: 'high', deterministic: true, requires: ['registries'],
|
|
49
|
+
impact: { legal: 'medium', maintainability: 'medium' },
|
|
50
|
+
applicable_requirement: 'Referential integrity between claim and evidence registries; premise 3.5',
|
|
51
|
+
remediation: 'Register and verify the evidence, or remove the reference and re-assess the claim.',
|
|
52
|
+
verification: 'All claim evidence references resolve to reviewed/verified entries.',
|
|
53
|
+
check(ctx) {
|
|
54
|
+
const ev = new Map((ctx.registries.evidence?.entries || []).map((e) => [e.evidence_id, e]));
|
|
55
|
+
const hits = [];
|
|
56
|
+
for (const c of ctx.registries.claims?.entries || []) {
|
|
57
|
+
for (const id of c.evidence || []) {
|
|
58
|
+
const e = ev.get(id);
|
|
59
|
+
if (!e) {
|
|
60
|
+
hits.push({
|
|
61
|
+
subject: entrySubject('claims', c.claim_id),
|
|
62
|
+
summary: `Claim references unknown evidence id "${id}"`,
|
|
63
|
+
evidence: [`claims/${c.claim_id} → evidence "${id}" not found`],
|
|
64
|
+
});
|
|
65
|
+
} else if (e.verification_status === 'unverified' && ['verified', 'verified_narrowed'].includes(c.status)) {
|
|
66
|
+
hits.push({
|
|
67
|
+
subject: entrySubject('claims', c.claim_id),
|
|
68
|
+
summary: `Verified claim relies on unverified evidence "${id}"`,
|
|
69
|
+
evidence: [`evidence/${id}: verification_status=unverified`],
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return hits;
|
|
75
|
+
},
|
|
76
|
+
}));
|
|
77
|
+
|
|
78
|
+
D.push(defineDetector({
|
|
79
|
+
id: 'EVD-004', name: 'Secondary evidence where primary is required', namespace: 'EVD',
|
|
80
|
+
description: 'A performance or security claim is supported only by secondary evidence (e.g., third-party articles).',
|
|
81
|
+
discipline: ['aeo', 'geo'], severity: 'medium', deterministic: true, requires: ['registries'],
|
|
82
|
+
impact: { legal: 'medium', citation: 'medium' },
|
|
83
|
+
applicable_requirement: 'Detector spec: secondary evidence used where primary evidence is required; AEO §4 primary sources where available',
|
|
84
|
+
remediation: 'Produce primary evidence (test result, architecture spec, certification) or narrow the claim.',
|
|
85
|
+
verification: 'Performance/security claims have at least one primary evidence entry.',
|
|
86
|
+
check(ctx) {
|
|
87
|
+
const ev = new Map((ctx.registries.evidence?.entries || []).map((e) => [e.evidence_id, e]));
|
|
88
|
+
const hits = [];
|
|
89
|
+
for (const c of (ctx.registries.claims?.entries || []).filter((c) => ['performance', 'security'].includes(c.claim_type) && (c.evidence || []).length > 0)) {
|
|
90
|
+
const kinds = (c.evidence || []).map((id) => ev.get(id)).filter(Boolean);
|
|
91
|
+
if (kinds.length > 0 && kinds.every((e) => e.primary_or_secondary === 'secondary')) {
|
|
92
|
+
hits.push({
|
|
93
|
+
subject: entrySubject('claims', c.claim_id),
|
|
94
|
+
summary: `${c.claim_type} claim supported only by secondary evidence`,
|
|
95
|
+
evidence: kinds.map((e) => `${e.evidence_id}: ${e.evidence_type} (secondary)`),
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return hits;
|
|
100
|
+
},
|
|
101
|
+
}));
|
|
102
|
+
|
|
103
|
+
D.push(defineDetector({
|
|
104
|
+
id: 'EVD-005', name: 'Customer evidence lacks attribution', namespace: 'EVD',
|
|
105
|
+
description: 'Customer-reference or case-study evidence has no attribution recorded.',
|
|
106
|
+
discipline: ['aeo', 'geo'], severity: 'low', deterministic: true, requires: ['registries'],
|
|
107
|
+
impact: { reputational: 'medium', legal: 'medium' },
|
|
108
|
+
applicable_requirement: 'Detector spec: customer evidence lacks attribution; premise 3.6 no fabricated customers',
|
|
109
|
+
remediation: 'Record attribution (who, role, permission status) or mark the evidence anonymous-by-consent with reviewer sign-off.',
|
|
110
|
+
verification: 'Customer evidence entries carry attribution or a documented consent basis.',
|
|
111
|
+
check(ctx) {
|
|
112
|
+
return (ctx.registries.evidence?.entries || [])
|
|
113
|
+
.filter((e) => ['customer_reference', 'case_study'].includes(e.evidence_type) && !e.attribution && !e.reviewer)
|
|
114
|
+
.map((e) => ({
|
|
115
|
+
subject: entrySubject('evidence', e.evidence_id),
|
|
116
|
+
summary: `Customer evidence "${e.title}" has no attribution and no reviewer`,
|
|
117
|
+
evidence: ['attribution: missing; reviewer: missing'],
|
|
118
|
+
}));
|
|
119
|
+
},
|
|
120
|
+
}));
|
|
121
|
+
|
|
122
|
+
D.push(defineDetector({
|
|
123
|
+
id: 'EVD-006', name: 'Evidence integrity hash absent', namespace: 'EVD',
|
|
124
|
+
description: 'Primary evidence (test results, benchmarks, datasets, certifications) has no integrity hash, so later tampering or drift cannot be detected.',
|
|
125
|
+
discipline: ['aeo', 'geo'], severity: 'low', deterministic: true, requires: ['registries'],
|
|
126
|
+
impact: { maintainability: 'medium', legal: 'low' },
|
|
127
|
+
applicable_requirement: 'Registry §6.5 integrity_hash; detector spec: evidence integrity hash absent where expected',
|
|
128
|
+
remediation: 'Store a sha256 of the evidence artifact at verification time.',
|
|
129
|
+
verification: 'Primary evidence entries carry integrity_hash.',
|
|
130
|
+
check(ctx) {
|
|
131
|
+
return (ctx.registries.evidence?.entries || [])
|
|
132
|
+
.filter((e) => ['test_result', 'benchmark', 'dataset', 'certification'].includes(e.evidence_type) && e.primary_or_secondary === 'primary' && !e.integrity_hash)
|
|
133
|
+
.map((e) => ({
|
|
134
|
+
subject: entrySubject('evidence', e.evidence_id),
|
|
135
|
+
summary: `Primary ${e.evidence_type} evidence "${e.title}" has no integrity hash`,
|
|
136
|
+
evidence: ['integrity_hash: missing'],
|
|
137
|
+
}));
|
|
138
|
+
},
|
|
139
|
+
}));
|
|
140
|
+
|
|
141
|
+
D.push(defineDetector({
|
|
142
|
+
id: 'EVD-007', name: 'Evidence marked inaccessible still supporting claims', namespace: 'EVD',
|
|
143
|
+
description: 'Evidence with access_status inaccessible (or verification_status inaccessible) is still listed as supporting active claims.',
|
|
144
|
+
discipline: ['aeo', 'geo'], severity: 'medium', deterministic: true, requires: ['registries'],
|
|
145
|
+
impact: { legal: 'medium', citation: 'medium' },
|
|
146
|
+
applicable_requirement: 'Detector spec: evidence source inaccessible; revoked evidence still supporting published claim',
|
|
147
|
+
remediation: 'Restore access to the source, replace the evidence, or downgrade dependent claims.',
|
|
148
|
+
verification: 'No active claim relies solely on inaccessible evidence.',
|
|
149
|
+
check(ctx) {
|
|
150
|
+
const claims = new Map((ctx.registries.claims?.entries || []).map((c) => [c.claim_id, c]));
|
|
151
|
+
return (ctx.registries.evidence?.entries || [])
|
|
152
|
+
.filter((e) => (e.access_status === 'inaccessible' || e.verification_status === 'inaccessible') && (e.supports_claims || []).some((id) => {
|
|
153
|
+
const c = claims.get(id);
|
|
154
|
+
return c && !['retired', 'expired', 'prohibited'].includes(c.status);
|
|
155
|
+
}))
|
|
156
|
+
.map((e) => ({
|
|
157
|
+
subject: entrySubject('evidence', e.evidence_id),
|
|
158
|
+
summary: `Inaccessible evidence "${e.title}" still supports active claims: ${(e.supports_claims || []).join(', ')}`,
|
|
159
|
+
evidence: [`access_status: ${e.access_status}; verification_status: ${e.verification_status}`],
|
|
160
|
+
}));
|
|
161
|
+
},
|
|
162
|
+
}));
|
|
163
|
+
|
|
164
|
+
export default D;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { sha256 } from '../shared/io.js';
|
|
2
|
+
|
|
3
|
+
const REQUIRED = ['id', 'name', 'namespace', 'description', 'discipline', 'severity', 'deterministic', 'remediation', 'verification', 'check'];
|
|
4
|
+
// RENDER (browser-rendered truth / source-render divergence) is reserved for the
|
|
5
|
+
// rendered-truth phase; no RENDER detectors ship until a real renderer backs them.
|
|
6
|
+
const NAMESPACES = ['TECH', 'CRAWL', 'ARCH', 'PAGE', 'ANS', 'ENTITY', 'CLAIM', 'EVD', 'SCHEMA', 'LINK', 'EXT', 'GEO', 'RECO', 'LIFE', 'MEAS', 'RENDER'];
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Detector definition contract. `check(ctx)` returns raw hits:
|
|
10
|
+
* { subject: {type, identifier, url?, source_file?, source_location?}, summary, evidence: [..],
|
|
11
|
+
* captured?, expected?, severity?, confidence? }
|
|
12
|
+
*/
|
|
13
|
+
export function defineDetector(def) {
|
|
14
|
+
for (const k of REQUIRED) {
|
|
15
|
+
if (def[k] === undefined) throw new Error(`detector ${def.id ?? '?'} missing field: ${k}`);
|
|
16
|
+
}
|
|
17
|
+
if (!NAMESPACES.includes(def.namespace)) throw new Error(`detector ${def.id}: unknown namespace ${def.namespace}`);
|
|
18
|
+
if (!def.id.startsWith(def.namespace + '-')) throw new Error(`detector id ${def.id} must be prefixed with namespace`);
|
|
19
|
+
return {
|
|
20
|
+
confidence_model: def.deterministic ? 'binary condition; confirmed when observed' : 'heuristic; confidence reported per finding',
|
|
21
|
+
confidence: def.deterministic ? 'confirmed' : 'medium',
|
|
22
|
+
finding_type: def.deterministic ? 'deterministic_observation' : 'probabilistic_inference',
|
|
23
|
+
impact: {},
|
|
24
|
+
false_positive_conditions: [],
|
|
25
|
+
false_negative_conditions: [],
|
|
26
|
+
applicable_requirement: '',
|
|
27
|
+
...def,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Run detectors over a context; returns { findings, detectorsRun, detectorsSkipped, errors }. */
|
|
32
|
+
export function runDetectors(detectors, ctx) {
|
|
33
|
+
const findings = [];
|
|
34
|
+
const detectorsRun = [];
|
|
35
|
+
const detectorsSkipped = [];
|
|
36
|
+
const errors = [];
|
|
37
|
+
const ts = ctx.timestamp ?? new Date().toISOString();
|
|
38
|
+
for (const d of detectors) {
|
|
39
|
+
if (d.requires && !d.requires.every((r) => ctx[r])) {
|
|
40
|
+
detectorsSkipped.push({ detector_id: d.id, reason: `missing context: ${d.requires.filter((r) => !ctx[r]).join(', ')}` });
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
let hits;
|
|
44
|
+
try {
|
|
45
|
+
hits = d.check(ctx) || [];
|
|
46
|
+
} catch (err) {
|
|
47
|
+
errors.push(`${d.id}: detector error: ${err.message}`);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
detectorsRun.push(d.id);
|
|
51
|
+
for (const hit of hits) {
|
|
52
|
+
const idSeed = `${d.id}|${hit.subject?.identifier ?? ''}|${hit.summary}`;
|
|
53
|
+
findings.push({
|
|
54
|
+
finding_id: `F-${sha256(idSeed).slice(0, 12)}`,
|
|
55
|
+
detector_id: d.id,
|
|
56
|
+
run_id: ctx.runId ?? 'adhoc',
|
|
57
|
+
timestamp: ts,
|
|
58
|
+
discipline: d.discipline,
|
|
59
|
+
subject: hit.subject,
|
|
60
|
+
observation: {
|
|
61
|
+
summary: hit.summary,
|
|
62
|
+
evidence: hit.evidence,
|
|
63
|
+
captured_value: hit.captured ?? null,
|
|
64
|
+
expected_value: hit.expected ?? null,
|
|
65
|
+
},
|
|
66
|
+
classification: {
|
|
67
|
+
finding_type: hit.finding_type ?? d.finding_type,
|
|
68
|
+
severity: hit.severity ?? d.severity,
|
|
69
|
+
confidence: hit.confidence ?? d.confidence,
|
|
70
|
+
deterministic: d.deterministic,
|
|
71
|
+
impact: { ...d.impact, ...(hit.impact || {}) },
|
|
72
|
+
},
|
|
73
|
+
reasoning: {
|
|
74
|
+
applicable_requirement: d.applicable_requirement,
|
|
75
|
+
explanation: d.description,
|
|
76
|
+
assumptions: hit.assumptions ?? [],
|
|
77
|
+
limitations: d.deterministic ? [] : ['heuristic detection; verify manually before acting'],
|
|
78
|
+
},
|
|
79
|
+
remediation: {
|
|
80
|
+
preferred: d.remediation,
|
|
81
|
+
alternatives: d.remediation_alternatives ?? [],
|
|
82
|
+
unsafe_shortcuts: d.unsafe_shortcuts ?? [],
|
|
83
|
+
owner: hit.owner ?? null,
|
|
84
|
+
review_required: d.review_required ?? !d.deterministic,
|
|
85
|
+
},
|
|
86
|
+
verification: {
|
|
87
|
+
method: d.verification,
|
|
88
|
+
expected_result: 'detector no longer reports this subject',
|
|
89
|
+
detector_to_rerun: d.id,
|
|
90
|
+
},
|
|
91
|
+
status: { state: 'open', first_seen: ts, last_seen: ts, resolved_at: null },
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return { findings, detectorsRun, detectorsSkipped, errors };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* ---------- shared helpers for detector implementations ---------- */
|
|
99
|
+
|
|
100
|
+
/** Pages whose declared or default intent is to be indexed. */
|
|
101
|
+
export function indexTargets(ctx) {
|
|
102
|
+
return ctx.site.pages.filter((p) => {
|
|
103
|
+
const reg = registryPageFor(ctx, p);
|
|
104
|
+
if (reg?.indexing_intent === 'noindex') return false;
|
|
105
|
+
return true;
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Match a live page to its registry entry by URL path. */
|
|
110
|
+
export function registryPageFor(ctx, page) {
|
|
111
|
+
const entries = ctx.registries?.pages?.entries || [];
|
|
112
|
+
const pPath = safePath(page.url);
|
|
113
|
+
return entries.find((e) => safePath(e.url, ctx.site?.baseUrl) === pPath) ?? null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** Find the live site page for a registry entry. */
|
|
117
|
+
export function sitePageFor(ctx, registryEntry) {
|
|
118
|
+
if (!ctx.site) return null;
|
|
119
|
+
const target = safePath(registryEntry.url, ctx.site.baseUrl);
|
|
120
|
+
return ctx.site.pages.find((p) => safePath(p.url) === target) ?? null;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function safePath(url, base = 'https://example.test') {
|
|
124
|
+
try {
|
|
125
|
+
return new URL(url, base).pathname.replace(/\/$/, '') || '/';
|
|
126
|
+
} catch {
|
|
127
|
+
return url;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function pageSubject(page) {
|
|
132
|
+
return { type: 'page', identifier: page.url, url: page.url, ...(page.sourceFile ? { source_file: page.sourceFile } : {}) };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function entrySubject(type, id) {
|
|
136
|
+
return { type: 'registry_entry', identifier: `${type}/${id}` };
|
|
137
|
+
}
|