@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,42 @@
|
|
|
1
|
+
# Rubric: semantic clarity
|
|
2
|
+
|
|
3
|
+
Judges whether a page's subject, terminology, and relationships are unambiguous
|
|
4
|
+
to a system that has never seen the organization before.
|
|
5
|
+
|
|
6
|
+
## Scoring dimensions
|
|
7
|
+
|
|
8
|
+
1. **Single subject** — one primary entity/concept per page; competitors for
|
|
9
|
+
attention (multiple unrelated H2 topics) lower the score.
|
|
10
|
+
2. **Controlled terminology** — one canonical term used consistently; variants
|
|
11
|
+
only if registered as aliases (ENTITY-006 flags drift deterministically;
|
|
12
|
+
this rubric judges whether the drift is meaningful or benign inflection).
|
|
13
|
+
3. **Explicit relationships** — product→organization, capability→product,
|
|
14
|
+
evidence→capability, concept→adjacent-concept distinctions stated in prose.
|
|
15
|
+
4. **Category anchoring** — the entity's category named in text, matching the
|
|
16
|
+
registry category.
|
|
17
|
+
5. **Jargon load** — proprietary terms defined at first meaningful use.
|
|
18
|
+
|
|
19
|
+
## Posture
|
|
20
|
+
|
|
21
|
+
`strong` (1–4 hold), `partial` (subject clear, relationships implicit),
|
|
22
|
+
`weak` (subject or category ambiguous), `not_established` (page has no
|
|
23
|
+
registered primary entity — fix the registry first).
|
|
24
|
+
|
|
25
|
+
## Evidence required
|
|
26
|
+
|
|
27
|
+
Quoted passages showing the category statement and each relationship; the
|
|
28
|
+
registry entity rows compared against.
|
|
29
|
+
|
|
30
|
+
## Example / counterexample
|
|
31
|
+
|
|
32
|
+
- Strong: "Gatekeeper is a runtime enforcement component *from Example
|
|
33
|
+
Governance* in the *AI execution governance* category. It differs from
|
|
34
|
+
observability tooling because…"
|
|
35
|
+
- Weak: a page alternating between "platform", "framework", "suite", and
|
|
36
|
+
"solution" for the same product, with the category never named.
|
|
37
|
+
|
|
38
|
+
## Ambiguity → human review
|
|
39
|
+
|
|
40
|
+
- Term meaning is jurisdiction- or discipline-specific (e.g., "authorization"
|
|
41
|
+
in IAM vs healthcare).
|
|
42
|
+
- Two registered entities legitimately share the page (partnership pages).
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Rubric: source authority
|
|
2
|
+
|
|
3
|
+
Judges how much weight an external source can carry as corroboration. Used by
|
|
4
|
+
`/citable audit corroboration` and evidence review.
|
|
5
|
+
|
|
6
|
+
## Scoring dimensions
|
|
7
|
+
|
|
8
|
+
1. **Editorial independence** — no ownership, payment, or reciprocal
|
|
9
|
+
arrangement with the claiming organization; disclosed relationships reduce
|
|
10
|
+
but do not zero the score, *undisclosed* ones zero it.
|
|
11
|
+
2. **Topical retrieval presence** — is this a source engines already retrieve
|
|
12
|
+
for the topic? (Observed citations in prompt-results are the evidence.)
|
|
13
|
+
3. **Substantive treatment** — the source describes the entity accurately and
|
|
14
|
+
substantively, not a directory one-liner.
|
|
15
|
+
4. **Stability** — stable URL, accessible to retrieval systems, not paywalled
|
|
16
|
+
into invisibility.
|
|
17
|
+
5. **Provenance** — publisher identity, publication date, and (for research)
|
|
18
|
+
methodology visible.
|
|
19
|
+
|
|
20
|
+
## Posture
|
|
21
|
+
|
|
22
|
+
`strong` (independent + retrieved + substantive), `partial` (independent but
|
|
23
|
+
thin or unproven retrieval), `weak` (interest-conflicted or unstable),
|
|
24
|
+
`not_established` (independence cannot be determined → treat as owned until
|
|
25
|
+
verified).
|
|
26
|
+
|
|
27
|
+
## Hard exclusions (never count as corroboration)
|
|
28
|
+
|
|
29
|
+
Paid "best vendor" lists presented as editorial · fabricated comparison sites ·
|
|
30
|
+
synthetic community mentions · fake reviews · undisclosed sponsorships ·
|
|
31
|
+
programmatic pages ranking their own operator first · AI-generated third-party
|
|
32
|
+
profiles. These are anti-patterns to report, not sources to weigh.
|
|
33
|
+
|
|
34
|
+
## Ambiguity → human review
|
|
35
|
+
|
|
36
|
+
- Source independence uncertain (affiliate links present, sponsor unclear).
|
|
37
|
+
- Source is authoritative in one jurisdiction but not the claim's jurisdiction.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Templates
|
|
2
|
+
|
|
3
|
+
## Blocked-status response (fail closed)
|
|
4
|
+
|
|
5
|
+
```yaml
|
|
6
|
+
status: blocked
|
|
7
|
+
reason: <what fact/evidence is missing>
|
|
8
|
+
required_input:
|
|
9
|
+
- <exact missing input 1>
|
|
10
|
+
- <exact missing input 2>
|
|
11
|
+
owner: <who can supply it>
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Incomplete external verification
|
|
15
|
+
|
|
16
|
+
```yaml
|
|
17
|
+
status: incomplete
|
|
18
|
+
reason: external verification unavailable
|
|
19
|
+
not_verified:
|
|
20
|
+
- <competitor capabilities>
|
|
21
|
+
- <current engine behaviour>
|
|
22
|
+
consequence: findings below exclude these dimensions
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Posture block (per page or entity)
|
|
26
|
+
|
|
27
|
+
```yaml
|
|
28
|
+
posture:
|
|
29
|
+
retrieval_eligibility: strong | partial | weak | not_established
|
|
30
|
+
semantic_clarity: ...
|
|
31
|
+
answer_extractability: ...
|
|
32
|
+
entity_resolution: ...
|
|
33
|
+
evidence_strength: ...
|
|
34
|
+
recommendation_eligibility: ...
|
|
35
|
+
confidence: confirmed | high | medium | low | unknown
|
|
36
|
+
basis: [run_id, rubric files applied, observations count]
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Experiment record (required before causal claims)
|
|
40
|
+
|
|
41
|
+
```yaml
|
|
42
|
+
experiment_id: <DISC>-EXP-<n>
|
|
43
|
+
hypothesis: >
|
|
44
|
+
<specific, falsifiable>
|
|
45
|
+
primary_metric: <one>
|
|
46
|
+
secondary_metrics: []
|
|
47
|
+
control_group: <or baseline_window>
|
|
48
|
+
baseline_window: <days>
|
|
49
|
+
evaluation_window: <days>
|
|
50
|
+
known_confounders: [algorithm updates, seasonality, competitor publications, retrieval refresh timing]
|
|
51
|
+
decision_rule: >
|
|
52
|
+
<what result retains/reverts the change>
|
|
53
|
+
owner: <name>
|
|
54
|
+
```
|
package/src/cli/index.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { init } from '../commands/init.js';
|
|
5
|
+
import { audit } from '../commands/audit.js';
|
|
6
|
+
import { validate } from '../commands/validate.js';
|
|
7
|
+
import { mapClaims } from '../commands/mapClaims.js';
|
|
8
|
+
import { substantiate } from '../commands/substantiate.js';
|
|
9
|
+
import { inspect } from '../commands/inspect.js';
|
|
10
|
+
import { schemaCommand } from '../commands/schemaCmd.js';
|
|
11
|
+
import { compareSnapshots } from '../commands/compareSnapshots.js';
|
|
12
|
+
import { isInstallerCommand, runInstallerCommand } from '../installer/index.js';
|
|
13
|
+
|
|
14
|
+
const HELP = `citable — SEO / AEO / GEO audit, remediation, validation, and governance
|
|
15
|
+
|
|
16
|
+
Usage: citable <command> [options]
|
|
17
|
+
|
|
18
|
+
Commands
|
|
19
|
+
install Install the Citable skill into coding-agent harnesses
|
|
20
|
+
update Update managed Citable skill installations
|
|
21
|
+
check Report installed and available Citable versions
|
|
22
|
+
uninstall Remove managed Citable skill files
|
|
23
|
+
list List detected providers and installation state
|
|
24
|
+
doctor Diagnose installer, provider, and integrity problems
|
|
25
|
+
init Initialize .citable/ context and registries (non-destructive)
|
|
26
|
+
audit [scope] Run detectors; scopes: technical seo aeo geo architecture entity
|
|
27
|
+
claims evidence schema lifecycle corroboration
|
|
28
|
+
inspect <page> Profile one page (URL path or source file)
|
|
29
|
+
map-claims Extract material claim candidates from pages (--write to save)
|
|
30
|
+
substantiate Assess claim/evidence status (--write to apply downgrades)
|
|
31
|
+
schema Validate deployed JSON-LD and propose registry-derived schema
|
|
32
|
+
validate [mode] registries (default) | claims | evidence | schema | links
|
|
33
|
+
compare-snapshots [a b] Regression diff between two audit runs
|
|
34
|
+
|
|
35
|
+
Options
|
|
36
|
+
--target <dir|url> Built output directory or deployed URL to audit
|
|
37
|
+
--base-url <url> Base URL for path resolution of a built output dir
|
|
38
|
+
--ref-date <YYYY-MM-DD> Reference date for expiry/staleness checks (default: today)
|
|
39
|
+
--write Persist registry changes (map-claims, substantiate)
|
|
40
|
+
--json Machine-readable output only
|
|
41
|
+
|
|
42
|
+
No output of this tool guarantees crawling, indexing, ranking, citation,
|
|
43
|
+
recommendation, inclusion, sentiment, or conversion outcomes.`;
|
|
44
|
+
|
|
45
|
+
function parseArgs(argv) {
|
|
46
|
+
const args = { _: [] };
|
|
47
|
+
for (let i = 0; i < argv.length; i++) {
|
|
48
|
+
const a = argv[i];
|
|
49
|
+
if (a === '--write') args.write = true;
|
|
50
|
+
else if (a === '--json') args.json = true;
|
|
51
|
+
else if (a === '--target') args.target = argv[++i];
|
|
52
|
+
else if (a === '--base-url') args.baseUrl = argv[++i];
|
|
53
|
+
else if (a === '--ref-date') args.refDate = argv[++i];
|
|
54
|
+
else if (a === '--force') args.force = true;
|
|
55
|
+
else args._.push(a);
|
|
56
|
+
}
|
|
57
|
+
return args;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function out(args, human, data) {
|
|
61
|
+
if (args.json) console.log(JSON.stringify(data, null, 2));
|
|
62
|
+
else console.log(human);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export async function main(argv = process.argv.slice(2), options = {}) {
|
|
66
|
+
const cmd = argv[0];
|
|
67
|
+
if (isInstallerCommand(cmd)) return runInstallerCommand(cmd, argv.slice(1), options);
|
|
68
|
+
const args = parseArgs(argv.slice(1));
|
|
69
|
+
const root = options.cwd ?? process.cwd();
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
switch (cmd) {
|
|
73
|
+
case 'init': {
|
|
74
|
+
const r = init(root, { force: args.force });
|
|
75
|
+
out(args, `Initialized .citable/\n created: ${r.created.join(', ') || 'nothing'}\n skipped: ${r.skipped.join(', ') || 'nothing'}\n detected framework: ${r.detected.framework ?? 'unknown'}\n unresolved assumptions:\n${r.unresolved.map((u) => ` - ${u}`).join('\n') || ' none'}`, r);
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
case 'audit': {
|
|
79
|
+
const scope = args._[0];
|
|
80
|
+
const r = await audit(root, { target: args.target, scope, baseUrl: args.baseUrl, refDate: args.refDate });
|
|
81
|
+
out(args, `Audit ${r.runId}: ${r.summary.total} finding(s) [${Object.entries(r.summary.by_severity).map(([k, v]) => `${k}:${v}`).join(' ')}]\nEvidence package: ${r.dir}\nReport: ${path.join(r.dir, 'report.md')}\nStatus: ${r.manifest.status}${r.manifest.incomplete_checks.length ? `\nIncomplete: ${r.manifest.incomplete_checks.join('; ')}` : ''}`, { runId: r.runId, dir: r.dir, summary: r.summary, status: r.manifest.status });
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
case 'inspect': {
|
|
85
|
+
if (!args._[0]) throw new Error('usage: citable inspect <page> --target <dir|url>');
|
|
86
|
+
const r = await inspect(root, args._[0], { target: args.target, baseUrl: args.baseUrl, refDate: args.refDate });
|
|
87
|
+
out(args, `Inspect ${r.url}\n title: ${r.title}\n status: ${r.status}; canonical: ${r.canonicals.join(', ') || 'none'}; robots: ${r.robotsDirectives.join(',') || 'default'}\n intent: ${r.primary_intent ?? 'undeclared'}; conversion: ${r.conversion_action ?? 'undeclared'}\n entities: ${r.entities.map((e) => e.name).join(', ') || 'none'}\n claims: ${r.claims.length}; findings: ${r.findings.length}\n ambiguity:\n${r.unresolved_ambiguity.map((a) => ` - ${a}`).join('\n') || ' none'}`, r);
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
case 'map-claims': {
|
|
91
|
+
const r = await mapClaims(root, { target: args.target, baseUrl: args.baseUrl, write: args.write, refDate: args.refDate });
|
|
92
|
+
out(args, `map-claims: ${r.candidates.length} candidate claim(s)${args.write ? `, ${r.written} written to registry as candidate/review_required` : ' (dry run — use --write to save)'}\n` + r.candidates.map((c) => ` [${c.claim_type}${c.review_required ? ', REVIEW REQUIRED' : ''}] ${c.claim.slice(0, 100)}\n at ${c.source_location}`).join('\n'), r);
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
case 'substantiate': {
|
|
96
|
+
const r = substantiate(root, { write: args.write, refDate: args.refDate });
|
|
97
|
+
out(args, `substantiate: ${r.assessments.length} claim(s) assessed${args.write ? ' (changes written)' : ' (dry run)'}\n` + r.assessments.map((a) => ` ${a.claim_id}: ${a.previous_status} → ${a.outcome}\n ${a.reasons.join('; ')}${a.required_input.length ? `\n required input: ${a.required_input.join(', ')}` : ''}`).join('\n'), r);
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
case 'schema': {
|
|
101
|
+
const r = await schemaCommand(root, { target: args.target, baseUrl: args.baseUrl, refDate: args.refDate });
|
|
102
|
+
out(args, `schema: ${r.findings.length} finding(s), ${r.proposals.length} proposal(s), ${r.blocked.length} blocked (incomplete entity data)\n` + r.blocked.map((b) => ` BLOCKED ${b.entity_id}: needs ${b.required_input.join(', ')}`).join('\n'), r);
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
case 'validate': {
|
|
106
|
+
const mode = args._[0] ?? 'registries';
|
|
107
|
+
const r = await validate(root, { mode, target: args.target, baseUrl: args.baseUrl, refDate: args.refDate });
|
|
108
|
+
out(args, `validate ${mode}: ${r.ok ? 'OK' : 'PROBLEMS'}\n` + (r.problems.length ? r.problems.map((p) => ` - ${p}`).join('\n') : ' registries structurally valid') + (r.findings?.length ? `\n detector findings: ${r.findings.length} (see run ${r.runId})` : ''), r);
|
|
109
|
+
if (!r.ok) process.exitCode = 1;
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
case 'compare-snapshots': {
|
|
113
|
+
const r = compareSnapshots(root, { runA: args._[0], runB: args._[1] });
|
|
114
|
+
out(args, `compare ${r.runA} → ${r.runB}\n new: ${r.summary.new_findings} (critical/high: ${r.summary.regression_critical_or_high})\n resolved: ${r.summary.resolved_findings}\n persisting: ${r.summary.persisting_findings}`, r);
|
|
115
|
+
if (r.summary.regression_critical_or_high > 0) process.exitCode = 1;
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
case undefined:
|
|
119
|
+
console.log(HELP);
|
|
120
|
+
break;
|
|
121
|
+
default:
|
|
122
|
+
console.error(`unknown command: ${cmd}\n`);
|
|
123
|
+
console.log(HELP);
|
|
124
|
+
process.exitCode = 2;
|
|
125
|
+
}
|
|
126
|
+
} catch (err) {
|
|
127
|
+
console.error(`citable: ${err.message}`);
|
|
128
|
+
process.exitCode = 1;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
133
|
+
const code = await main();
|
|
134
|
+
if (Number.isInteger(code)) process.exitCode = code;
|
|
135
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { buildContext } from './context.js';
|
|
4
|
+
import { selectDetectors } from '../detectors/index.js';
|
|
5
|
+
import { runDetectors } from '../detectors/framework.js';
|
|
6
|
+
import { createRun } from '../evidence/run.js';
|
|
7
|
+
import { summarize, renderMarkdownReport } from '../reporting/report.js';
|
|
8
|
+
import { validateAgainst } from '../shared/schemaValidator.js';
|
|
9
|
+
import { writeJson, sha256 } from '../shared/io.js';
|
|
10
|
+
import { extractModified } from '../detectors/lifeMeas.js';
|
|
11
|
+
|
|
12
|
+
/** `citable audit [scope]` — run detectors and produce an evidence package. */
|
|
13
|
+
export async function audit(root, { target, scope, baseUrl, refDate } = {}) {
|
|
14
|
+
const ctx = await buildContext(root, { target, baseUrl, refDate });
|
|
15
|
+
const detectors = selectDetectors({ scope });
|
|
16
|
+
|
|
17
|
+
const run = createRun(root, {
|
|
18
|
+
command: `audit${scope ? ' ' + scope : ''}`,
|
|
19
|
+
argv: process.argv.slice(2),
|
|
20
|
+
target: {
|
|
21
|
+
kind: ctx.site ? ctx.site.mode : 'registries',
|
|
22
|
+
location: ctx.site ? ctx.site.location : path.join(root, '.citable'),
|
|
23
|
+
environment: 'local',
|
|
24
|
+
},
|
|
25
|
+
configHash: sha256(JSON.stringify(ctx.config)),
|
|
26
|
+
});
|
|
27
|
+
ctx.runId = run.runId;
|
|
28
|
+
ctx.timestamp = run.manifest.timestamp;
|
|
29
|
+
|
|
30
|
+
run.manifest.warnings.push(...ctx.warnings);
|
|
31
|
+
if (!ctx.site) {
|
|
32
|
+
run.manifest.incomplete_checks.push('No site target supplied and no built_output_dir configured: page/site detectors were skipped; this run covers registries only.');
|
|
33
|
+
}
|
|
34
|
+
if (ctx.site?.fetchErrors?.length) {
|
|
35
|
+
run.manifest.errors.push(...ctx.site.fetchErrors);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const { findings, detectorsRun, detectorsSkipped, errors } = runDetectors(detectors, ctx);
|
|
39
|
+
run.manifest.detectors_run = detectorsRun;
|
|
40
|
+
run.manifest.detectors_skipped = detectorsSkipped;
|
|
41
|
+
run.manifest.errors.push(...errors);
|
|
42
|
+
|
|
43
|
+
// Validate every finding against the data contract; a contract breach fails the run.
|
|
44
|
+
const invalid = [];
|
|
45
|
+
for (const f of findings) {
|
|
46
|
+
const { valid, errors: e } = validateAgainst('finding.schema.json', f);
|
|
47
|
+
if (!valid) invalid.push(`${f.finding_id}: ${e.join('; ')}`);
|
|
48
|
+
}
|
|
49
|
+
if (invalid.length) {
|
|
50
|
+
run.manifest.errors.push(...invalid);
|
|
51
|
+
run.finalize('failed');
|
|
52
|
+
throw new Error(`findings violate the data contract:\n${invalid.join('\n')}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Evidence package artifacts
|
|
56
|
+
run.writeArtifact('findings.json', findings);
|
|
57
|
+
const summary = summarize(findings);
|
|
58
|
+
run.writeArtifact('summary.json', summary);
|
|
59
|
+
run.writeArtifact('inputs.json', {
|
|
60
|
+
target: run.manifest.target, scope: scope ?? 'all',
|
|
61
|
+
registry_counts: Object.fromEntries(Object.entries(ctx.registries).map(([k, v]) => [k, v.entries.length])),
|
|
62
|
+
pages_audited: ctx.site?.pages.length ?? 0,
|
|
63
|
+
});
|
|
64
|
+
run.writeArtifact('environment.json', {
|
|
65
|
+
node: process.version, platform: process.platform, cwd: root,
|
|
66
|
+
ref_date: ctx.refDate.toISOString(),
|
|
67
|
+
});
|
|
68
|
+
if (ctx.site) {
|
|
69
|
+
run.writeArtifact('pages/index.json', ctx.site.pages.map((p) => ({
|
|
70
|
+
url: p.url, status: p.status, title: p.title, canonicals: p.canonicals,
|
|
71
|
+
noindex: p.noindex, wordCount: p.wordCount, sourceFile: p.sourceFile,
|
|
72
|
+
contentHash: ctx.hashPage(p),
|
|
73
|
+
})));
|
|
74
|
+
if (ctx.site.robotsText != null) run.writeArtifact('robots/robots.txt', ctx.site.robotsText);
|
|
75
|
+
for (const sm of ctx.site.sitemaps) {
|
|
76
|
+
run.writeArtifact(`sitemaps/${path.basename(String(sm.source))}.json`, sm.parsed);
|
|
77
|
+
}
|
|
78
|
+
run.writeArtifact('links/graph.json', {
|
|
79
|
+
inbound: Object.fromEntries([...ctx.site.inbound.entries()].map(([k, v]) => [k, v.length])),
|
|
80
|
+
outbound: Object.fromEntries([...ctx.site.outbound.entries()].map(([k, v]) => [k, v.map((e) => e.to)])),
|
|
81
|
+
});
|
|
82
|
+
const schemaBlocks = [];
|
|
83
|
+
for (const p of ctx.site.pages) for (const j of p.jsonLd) schemaBlocks.push({ url: p.url, parseError: j.parseError, blocks: j.blocks });
|
|
84
|
+
run.writeArtifact('schema/jsonld.json', schemaBlocks);
|
|
85
|
+
for (const p of ctx.site.pages) {
|
|
86
|
+
run.writeArtifact(`headers/${encodeURIComponent(p.url)}.json`, { status: p.status, headers: p.headers });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const report = renderMarkdownReport({ findings, manifest: run.manifest, summary, detectorsSkipped });
|
|
91
|
+
run.writeArtifact('report.md', report);
|
|
92
|
+
|
|
93
|
+
// Update the latest page snapshot for regression/freshness comparison
|
|
94
|
+
if (ctx.site) {
|
|
95
|
+
const snap = { taken_at: run.manifest.timestamp, run_id: run.runId, pages: {} };
|
|
96
|
+
for (const p of ctx.site.pages) {
|
|
97
|
+
snap.pages[p.url] = { contentHash: ctx.hashPage(p), dateModified: extractModified(p), status: p.status };
|
|
98
|
+
}
|
|
99
|
+
const snapDir = path.join(root, '.citable', 'snapshots');
|
|
100
|
+
fs.mkdirSync(snapDir, { recursive: true });
|
|
101
|
+
if (fs.existsSync(path.join(snapDir, 'pages-latest.json'))) {
|
|
102
|
+
fs.copyFileSync(path.join(snapDir, 'pages-latest.json'), path.join(snapDir, `pages-${run.runId}.prev.json`));
|
|
103
|
+
}
|
|
104
|
+
writeJson(path.join(snapDir, 'pages-latest.json'), snap);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const status = run.manifest.errors.length ? 'completed_with_warnings'
|
|
108
|
+
: run.manifest.incomplete_checks.length ? 'incomplete' : 'completed';
|
|
109
|
+
const dir = run.finalize(status);
|
|
110
|
+
return { runId: run.runId, dir, findings, summary, manifest: run.manifest, report };
|
|
111
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { readJson } from '../shared/io.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `citable compare-snapshots [runA runB]` — regression comparison between two audit runs.
|
|
7
|
+
* Defaults to the two most recent runs containing findings.json.
|
|
8
|
+
*/
|
|
9
|
+
export function compareSnapshots(root, { runA, runB } = {}) {
|
|
10
|
+
const runsDir = path.join(root, '.citable', 'runs');
|
|
11
|
+
if (!fs.existsSync(runsDir)) throw new Error('no runs recorded yet');
|
|
12
|
+
const runs = fs.readdirSync(runsDir)
|
|
13
|
+
.filter((r) => fs.existsSync(path.join(runsDir, r, 'findings.json')))
|
|
14
|
+
.sort();
|
|
15
|
+
if (!runA || !runB) {
|
|
16
|
+
if (runs.length < 2) throw new Error(`need two runs with findings to compare; found ${runs.length}`);
|
|
17
|
+
runB = runB ?? runs[runs.length - 1];
|
|
18
|
+
runA = runA ?? runs[runs.length - 2];
|
|
19
|
+
}
|
|
20
|
+
const load = (r) => {
|
|
21
|
+
const dir = path.join(runsDir, r);
|
|
22
|
+
if (!fs.existsSync(path.join(dir, 'findings.json'))) throw new Error(`run ${r} has no findings.json`);
|
|
23
|
+
return {
|
|
24
|
+
findings: readJson(path.join(dir, 'findings.json')),
|
|
25
|
+
manifest: readJson(path.join(dir, 'manifest.json')),
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
const a = load(runA);
|
|
29
|
+
const b = load(runB);
|
|
30
|
+
const key = (f) => `${f.detector_id}|${f.subject.identifier}|${f.observation.summary}`;
|
|
31
|
+
const aKeys = new Map(a.findings.map((f) => [key(f), f]));
|
|
32
|
+
const bKeys = new Map(b.findings.map((f) => [key(f), f]));
|
|
33
|
+
const regressions = [...bKeys.entries()].filter(([k]) => !aKeys.has(k)).map(([, f]) => f);
|
|
34
|
+
const resolved = [...aKeys.entries()].filter(([k]) => !bKeys.has(k)).map(([, f]) => f);
|
|
35
|
+
const persisting = [...bKeys.entries()].filter(([k]) => aKeys.has(k)).map(([, f]) => f);
|
|
36
|
+
return {
|
|
37
|
+
runA, runB,
|
|
38
|
+
baseline_timestamp: a.manifest.timestamp,
|
|
39
|
+
comparison_timestamp: b.manifest.timestamp,
|
|
40
|
+
regressions, resolved, persisting,
|
|
41
|
+
summary: {
|
|
42
|
+
new_findings: regressions.length,
|
|
43
|
+
resolved_findings: resolved.length,
|
|
44
|
+
persisting_findings: persisting.length,
|
|
45
|
+
regression_critical_or_high: regressions.filter((f) => ['critical', 'high'].includes(f.classification.severity)).length,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { readYaml, readJson, sha256 } from '../shared/io.js';
|
|
4
|
+
import { loadRegistries } from '../registries/index.js';
|
|
5
|
+
import { buildSiteFromDir, buildSiteFromUrl } from '../extractor/site.js';
|
|
6
|
+
|
|
7
|
+
/** Assemble the shared execution context used by audit-family commands. */
|
|
8
|
+
export async function buildContext(root, { target, baseUrl, refDate } = {}) {
|
|
9
|
+
const warnings = [];
|
|
10
|
+
const configFile = path.join(root, '.citable', 'config.yaml');
|
|
11
|
+
const config = fs.existsSync(configFile) ? readYaml(configFile) : { version: 1 };
|
|
12
|
+
const { registries, problems } = loadRegistries(root);
|
|
13
|
+
warnings.push(...problems);
|
|
14
|
+
|
|
15
|
+
let site = null;
|
|
16
|
+
const resolvedBase = baseUrl ?? config.site?.base_url ?? 'https://example.test';
|
|
17
|
+
if (target) {
|
|
18
|
+
if (/^https?:\/\//.test(target)) {
|
|
19
|
+
site = await buildSiteFromUrl(target);
|
|
20
|
+
} else if (fs.existsSync(target)) {
|
|
21
|
+
site = buildSiteFromDir(target, { baseUrl: resolvedBase });
|
|
22
|
+
} else {
|
|
23
|
+
throw new Error(`audit target not found: ${target}`);
|
|
24
|
+
}
|
|
25
|
+
} else if (config.site?.built_output_dir && fs.existsSync(path.join(root, config.site.built_output_dir))) {
|
|
26
|
+
site = buildSiteFromDir(path.join(root, config.site.built_output_dir), { baseUrl: resolvedBase });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Prompt observations recorded under .citable/runs/*/prompt-results/
|
|
30
|
+
const promptResults = [];
|
|
31
|
+
const runsDir = path.join(root, '.citable', 'runs');
|
|
32
|
+
if (fs.existsSync(runsDir)) {
|
|
33
|
+
for (const run of fs.readdirSync(runsDir)) {
|
|
34
|
+
const prDir = path.join(runsDir, run, 'prompt-results');
|
|
35
|
+
if (!fs.existsSync(prDir)) continue;
|
|
36
|
+
for (const f of fs.readdirSync(prDir)) {
|
|
37
|
+
if (f.endsWith('.json')) {
|
|
38
|
+
try { promptResults.push(readJson(path.join(prDir, f))); } catch { warnings.push(`unreadable prompt result: ${run}/${f}`); }
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Latest page snapshot (for regression/freshness comparison)
|
|
45
|
+
let snapshots = null;
|
|
46
|
+
const snapFile = path.join(root, '.citable', 'snapshots', 'pages-latest.json');
|
|
47
|
+
if (fs.existsSync(snapFile)) {
|
|
48
|
+
try { snapshots = readJson(snapFile); } catch { warnings.push('unreadable pages snapshot'); }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
root,
|
|
53
|
+
config,
|
|
54
|
+
registries,
|
|
55
|
+
site,
|
|
56
|
+
promptResults: promptResults.length ? promptResults : null,
|
|
57
|
+
snapshots,
|
|
58
|
+
refDate: refDate ? new Date(refDate) : new Date(),
|
|
59
|
+
hashPage: (p) => sha256(p.text),
|
|
60
|
+
warnings,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { writeYaml, readJson, nowIso, listFiles } from '../shared/io.js';
|
|
4
|
+
import { REGISTRY_SPECS, emptyRegistry, contextDir } from '../registries/index.js';
|
|
5
|
+
import { validateAgainst } from '../shared/schemaValidator.js';
|
|
6
|
+
|
|
7
|
+
const DEFAULT_CRAWLERS = [
|
|
8
|
+
['CRAWLER-GOOGLEBOT', 'Googlebot', 'Google', 'search_indexing'],
|
|
9
|
+
['CRAWLER-BINGBOT', 'Bingbot', 'Microsoft', 'search_indexing'],
|
|
10
|
+
['CRAWLER-OAI-SEARCHBOT', 'OAI-SearchBot', 'OpenAI', 'ai_search_discovery'],
|
|
11
|
+
['CRAWLER-GPTBOT', 'GPTBot', 'OpenAI', 'model_training'],
|
|
12
|
+
['CRAWLER-CHATGPT-USER', 'ChatGPT-User', 'OpenAI', 'user_initiated_retrieval'],
|
|
13
|
+
['CRAWLER-PERPLEXITYBOT', 'PerplexityBot', 'Perplexity', 'ai_search_discovery'],
|
|
14
|
+
['CRAWLER-PERPLEXITY-USER', 'Perplexity-User', 'Perplexity', 'user_initiated_retrieval'],
|
|
15
|
+
['CRAWLER-CLAUDEBOT', 'ClaudeBot', 'Anthropic', 'model_training'],
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
function detectFramework(root) {
|
|
19
|
+
const detected = {
|
|
20
|
+
framework: null, rendering_model: null, package_manager: null,
|
|
21
|
+
build_commands: [], test_commands: [], robots_files: [], sitemap_sources: [],
|
|
22
|
+
schema_sources: [], metadata_systems: [], analytics: [], content_collections: [],
|
|
23
|
+
};
|
|
24
|
+
const unresolved = [];
|
|
25
|
+
const pkgFile = path.join(root, 'package.json');
|
|
26
|
+
if (fs.existsSync(pkgFile)) {
|
|
27
|
+
const pkg = readJson(pkgFile);
|
|
28
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
29
|
+
if (deps.next) { detected.framework = 'next.js'; detected.rendering_model = 'hybrid'; }
|
|
30
|
+
else if (deps.astro) { detected.framework = 'astro'; detected.rendering_model = 'static'; }
|
|
31
|
+
else if (deps.nuxt) { detected.framework = 'nuxt'; detected.rendering_model = 'hybrid'; }
|
|
32
|
+
else if (deps['@sveltejs/kit']) { detected.framework = 'sveltekit'; detected.rendering_model = 'hybrid'; }
|
|
33
|
+
else if (deps.gatsby) { detected.framework = 'gatsby'; detected.rendering_model = 'static'; }
|
|
34
|
+
else if (deps.react || deps.vue) { detected.framework = 'spa'; detected.rendering_model = 'csr'; }
|
|
35
|
+
if (pkg.scripts?.build) detected.build_commands.push(`npm run build`);
|
|
36
|
+
if (pkg.scripts?.test) detected.test_commands.push(`npm test`);
|
|
37
|
+
detected.package_manager = fs.existsSync(path.join(root, 'pnpm-lock.yaml')) ? 'pnpm'
|
|
38
|
+
: fs.existsSync(path.join(root, 'yarn.lock')) ? 'yarn'
|
|
39
|
+
: fs.existsSync(path.join(root, 'bun.lockb')) ? 'bun' : 'npm';
|
|
40
|
+
} else if (fs.existsSync(path.join(root, 'pyproject.toml'))) {
|
|
41
|
+
detected.framework = 'python';
|
|
42
|
+
unresolved.push('Python project detected; rendering model and build pipeline need manual confirmation.');
|
|
43
|
+
} else {
|
|
44
|
+
unresolved.push('No package manifest found; framework, build, and test commands unknown.');
|
|
45
|
+
}
|
|
46
|
+
for (const f of listFiles(root, (p) => /robots\.txt$/.test(p))) detected.robots_files.push(path.relative(root, f));
|
|
47
|
+
for (const f of listFiles(root, (p) => /sitemap.*\.(xml|ts|js|mjs)$/.test(p))) detected.sitemap_sources.push(path.relative(root, f));
|
|
48
|
+
for (const f of listFiles(root, (p) => /\.(html|jsx?|tsx?|astro|vue|svelte)$/.test(p)).slice(0, 400)) {
|
|
49
|
+
const text = fs.readFileSync(f, 'utf8');
|
|
50
|
+
if (text.includes('application/ld+json') || text.includes('schema.org')) detected.schema_sources.push(path.relative(root, f));
|
|
51
|
+
if (/gtag\(|googletagmanager|plausible|posthog|umami|matomo/i.test(text)) detected.analytics.push(path.relative(root, f));
|
|
52
|
+
}
|
|
53
|
+
if (detected.rendering_model === null) unresolved.push('Rendering model could not be determined from manifests.');
|
|
54
|
+
return { detected, unresolved };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** `citable init` — inspect the repo and create .citable/ without overwriting anything user-maintained. */
|
|
58
|
+
export function init(root, { force = false } = {}) {
|
|
59
|
+
const dir = contextDir(root);
|
|
60
|
+
const created = [];
|
|
61
|
+
const skipped = [];
|
|
62
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
63
|
+
for (const sub of ['policies', 'findings', 'snapshots', 'reports', 'runs']) {
|
|
64
|
+
fs.mkdirSync(path.join(dir, sub), { recursive: true });
|
|
65
|
+
}
|
|
66
|
+
const { detected, unresolved } = detectFramework(root);
|
|
67
|
+
|
|
68
|
+
const configFile = path.join(dir, 'config.yaml');
|
|
69
|
+
if (!fs.existsSync(configFile) || force) {
|
|
70
|
+
const config = {
|
|
71
|
+
version: 1,
|
|
72
|
+
site: { base_url: null, built_output_dir: null, source_dirs: [], default_locale: 'en', default_jurisdiction: null },
|
|
73
|
+
framework: {
|
|
74
|
+
name: detected.framework, rendering_model: detected.rendering_model,
|
|
75
|
+
package_manager: detected.package_manager,
|
|
76
|
+
build_command: detected.build_commands[0] ?? null, test_command: detected.test_commands[0] ?? null,
|
|
77
|
+
},
|
|
78
|
+
audit: { index_target_default: true, max_crawl_depth: 4, thin_content_words: 120, fetch_external: false },
|
|
79
|
+
};
|
|
80
|
+
const { valid, errors } = validateAgainst('config.schema.json', config);
|
|
81
|
+
if (!valid) throw new Error(`generated config invalid: ${errors.join('; ')}`);
|
|
82
|
+
writeYaml(configFile, config);
|
|
83
|
+
created.push('config.yaml');
|
|
84
|
+
} else skipped.push('config.yaml (exists)');
|
|
85
|
+
|
|
86
|
+
const projectFile = path.join(dir, 'project.yaml');
|
|
87
|
+
if (!fs.existsSync(projectFile) || force) {
|
|
88
|
+
const project = { version: 1, initialized_at: nowIso(), repository_root: root, detected, unresolved_assumptions: unresolved };
|
|
89
|
+
const { valid, errors } = validateAgainst('project.schema.json', project);
|
|
90
|
+
if (!valid) throw new Error(`generated project profile invalid: ${errors.join('; ')}`);
|
|
91
|
+
writeYaml(projectFile, project);
|
|
92
|
+
created.push('project.yaml');
|
|
93
|
+
} else skipped.push('project.yaml (exists)');
|
|
94
|
+
|
|
95
|
+
for (const spec of REGISTRY_SPECS) {
|
|
96
|
+
const file = path.join(dir, spec.file);
|
|
97
|
+
if (fs.existsSync(file)) { skipped.push(`${spec.file} (exists)`); continue; }
|
|
98
|
+
const reg = emptyRegistry(spec.kind);
|
|
99
|
+
if (spec.kind === 'crawlers') {
|
|
100
|
+
reg.entries = DEFAULT_CRAWLERS.map(([id, ua, vendor, purpose]) => ({
|
|
101
|
+
crawler_id: id, user_agent: ua, vendor, purpose,
|
|
102
|
+
decision: 'undecided', status: 'active',
|
|
103
|
+
}));
|
|
104
|
+
}
|
|
105
|
+
const { valid, errors } = validateAgainst(spec.schema, reg);
|
|
106
|
+
if (!valid) throw new Error(`generated ${spec.file} invalid: ${errors.join('; ')}`);
|
|
107
|
+
writeYaml(file, reg);
|
|
108
|
+
created.push(spec.file);
|
|
109
|
+
}
|
|
110
|
+
return { created, skipped, detected, unresolved };
|
|
111
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { buildContext } from './context.js';
|
|
2
|
+
import { registryPageFor, safePath } from '../detectors/framework.js';
|
|
3
|
+
import { selectDetectors } from '../detectors/index.js';
|
|
4
|
+
import { runDetectors } from '../detectors/framework.js';
|
|
5
|
+
|
|
6
|
+
/** `citable inspect <page>` — profile one page: intent, entities, claims, metadata, links, lifecycle, ambiguity. */
|
|
7
|
+
export async function inspect(root, pageRef, { target, baseUrl, refDate } = {}) {
|
|
8
|
+
const ctx = await buildContext(root, { target, baseUrl, refDate });
|
|
9
|
+
if (!ctx.site) throw new Error('inspect requires a site target (built output directory or URL)');
|
|
10
|
+
const wanted = safePath(pageRef, ctx.site.baseUrl);
|
|
11
|
+
const page = ctx.site.pages.find((p) => safePath(p.url) === wanted || p.sourceFile === pageRef);
|
|
12
|
+
if (!page) throw new Error(`page not found in audited output: ${pageRef}`);
|
|
13
|
+
|
|
14
|
+
const reg = registryPageFor(ctx, page);
|
|
15
|
+
const claims = (ctx.registries.claims?.entries || []).filter((c) => (reg?.published_claims || []).includes(c.claim_id) || (c.publication_surfaces || []).some((s) => page.url.includes(s)));
|
|
16
|
+
const entities = (ctx.registries.entities?.entries || []).filter((e) => (reg?.primary_entities || []).includes(e.entity_id) || page.text.toLowerCase().includes(e.canonical_name.toLowerCase()));
|
|
17
|
+
|
|
18
|
+
// Answer-bearing passages: first paragraph + paragraphs following question headings
|
|
19
|
+
const answerPassages = [];
|
|
20
|
+
if (page.paragraphs[0]) answerPassages.push({ role: 'opening', text: page.paragraphs[0].slice(0, 300) });
|
|
21
|
+
for (const h of page.headings.filter((h) => h.text.endsWith('?'))) {
|
|
22
|
+
answerPassages.push({ role: `after heading "${h.text}"`, text: '(verify prose follows; see ANS-002)' });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Per-page detector pass
|
|
26
|
+
const single = { ...ctx, site: { ...ctx.site, pages: [page] } };
|
|
27
|
+
const { findings } = runDetectors(selectDetectors({}), single);
|
|
28
|
+
const pageFindings = findings.filter((f) => f.subject.identifier === page.url || f.subject.url === page.url);
|
|
29
|
+
|
|
30
|
+
const ambiguities = [];
|
|
31
|
+
if (!reg) ambiguities.push('Page has no registry entry: intent, target queries, owner, and lifecycle are undeclared.');
|
|
32
|
+
if (reg && !reg.primary_intent) ambiguities.push('Registry entry declares no primary intent.');
|
|
33
|
+
if (reg && !reg.conversion_action) ambiguities.push('No conversion action declared; commercial role unknown.');
|
|
34
|
+
if (entities.length === 0) ambiguities.push('No registered entity matched on this page.');
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
url: page.url,
|
|
38
|
+
sourceFile: page.sourceFile,
|
|
39
|
+
status: page.status,
|
|
40
|
+
title: page.title,
|
|
41
|
+
metaDescription: page.metaDescription,
|
|
42
|
+
canonicals: page.canonicals,
|
|
43
|
+
robotsDirectives: page.robotsDirectives,
|
|
44
|
+
headings: page.headings,
|
|
45
|
+
wordCount: page.wordCount,
|
|
46
|
+
registry: reg,
|
|
47
|
+
primary_intent: reg?.primary_intent ?? null,
|
|
48
|
+
conversion_action: reg?.conversion_action ?? null,
|
|
49
|
+
lifecycle: reg ? { class: reg.lifecycle_class, owner: reg.content_owner, reviewer: reg.factual_reviewer, next_review: reg.next_review_date } : null,
|
|
50
|
+
entities: entities.map((e) => ({ entity_id: e.entity_id, name: e.canonical_name, type: e.entity_type })),
|
|
51
|
+
claims: claims.map((c) => ({ claim_id: c.claim_id, type: c.claim_type, status: c.status, claim: c.claim })),
|
|
52
|
+
schemaBlocks: page.jsonLd.map((j) => ({ parseError: j.parseError, types: j.blocks.map((b) => b['@type']) })),
|
|
53
|
+
internalLinks: {
|
|
54
|
+
inbound: (ctx.site.inbound.get(ctx.site.normalize(page.url)) || []).length,
|
|
55
|
+
outbound: (ctx.site.outbound.get(ctx.site.normalize(page.url)) || []).length,
|
|
56
|
+
},
|
|
57
|
+
answerPassages,
|
|
58
|
+
findings: pageFindings,
|
|
59
|
+
unresolved_ambiguity: ambiguities,
|
|
60
|
+
};
|
|
61
|
+
}
|