@nebulacomponents/citable 1.19.0 → 1.21.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 +35 -0
- package/README.md +12 -1
- package/dist/universal/.agents/skills/citable/SKILL.md +11 -2
- package/dist/universal/.agents/skills/citable/VERSION +1 -1
- package/dist/universal/.agents/skills/citable/manifest.json +24 -12
- package/dist/universal/.agents/skills/citable/schemas/action-plan.schema.json +38 -1
- package/dist/universal/.agents/skills/citable/schemas/audit-coverage.schema.json +118 -0
- package/dist/universal/.agents/skills/citable/schemas/claim-evidence.schema.json +21 -0
- package/dist/universal/.agents/skills/citable/schemas/claim-verification.schema.json +18 -0
- package/dist/universal/.agents/skills/citable/schemas/collection-result.schema.json +35 -0
- package/dist/universal/.agents/skills/citable/schemas/config.schema.json +2 -0
- package/dist/universal/.agents/skills/citable/schemas/cro-report.schema.json +8 -1
- package/dist/universal/.agents/skills/citable/schemas/derivation.schema.json +18 -0
- package/dist/universal/.agents/skills/citable/schemas/external-comparison.schema.json +16 -0
- package/dist/universal/.agents/skills/citable/schemas/external-observation.schema.json +32 -0
- package/dist/universal/.agents/skills/citable/schemas/finding.schema.json +105 -2
- package/dist/universal/.agents/skills/citable/schemas/prompt-set.schema.json +47 -0
- package/dist/universal/.agents/skills/citable/schemas/remediation-verification.schema.json +12 -1
- package/dist/universal/.agents/skills/citable/schemas/representation-data.schema.json +21 -0
- package/dist/universal/.agents/skills/citable/schemas/research-dataset.schema.json +27 -0
- package/dist/universal/.agents/skills/citable/schemas/run.schema.json +15 -2
- package/dist/universal/.agents/skills/citable/schemas/search-discovery-data.schema.json +20 -0
- package/dist/universal/.agents/skills/citable/schemas/search-report.schema.json +8 -1
- package/dist/universal/.agents/skills/citable/schemas/summary.schema.json +41 -0
- package/dist/universal/.claude/agents/citable/manifest.json +2 -2
- package/dist/universal/.claude/skills/citable/SKILL.md +11 -2
- package/dist/universal/.claude/skills/citable/VERSION +1 -1
- package/dist/universal/.claude/skills/citable/manifest.json +24 -12
- package/dist/universal/.claude/skills/citable/schemas/action-plan.schema.json +38 -1
- package/dist/universal/.claude/skills/citable/schemas/audit-coverage.schema.json +118 -0
- package/dist/universal/.claude/skills/citable/schemas/claim-evidence.schema.json +21 -0
- package/dist/universal/.claude/skills/citable/schemas/claim-verification.schema.json +18 -0
- package/dist/universal/.claude/skills/citable/schemas/collection-result.schema.json +35 -0
- package/dist/universal/.claude/skills/citable/schemas/config.schema.json +2 -0
- package/dist/universal/.claude/skills/citable/schemas/cro-report.schema.json +8 -1
- package/dist/universal/.claude/skills/citable/schemas/derivation.schema.json +18 -0
- package/dist/universal/.claude/skills/citable/schemas/external-comparison.schema.json +16 -0
- package/dist/universal/.claude/skills/citable/schemas/external-observation.schema.json +32 -0
- package/dist/universal/.claude/skills/citable/schemas/finding.schema.json +105 -2
- package/dist/universal/.claude/skills/citable/schemas/prompt-set.schema.json +47 -0
- package/dist/universal/.claude/skills/citable/schemas/remediation-verification.schema.json +12 -1
- package/dist/universal/.claude/skills/citable/schemas/representation-data.schema.json +21 -0
- package/dist/universal/.claude/skills/citable/schemas/research-dataset.schema.json +27 -0
- package/dist/universal/.claude/skills/citable/schemas/run.schema.json +15 -2
- package/dist/universal/.claude/skills/citable/schemas/search-discovery-data.schema.json +20 -0
- package/dist/universal/.claude/skills/citable/schemas/search-report.schema.json +8 -1
- package/dist/universal/.claude/skills/citable/schemas/summary.schema.json +41 -0
- package/dist/universal/.cursor/skills/citable/SKILL.md +11 -2
- package/dist/universal/.cursor/skills/citable/VERSION +1 -1
- package/dist/universal/.cursor/skills/citable/manifest.json +24 -12
- package/dist/universal/.cursor/skills/citable/schemas/action-plan.schema.json +38 -1
- package/dist/universal/.cursor/skills/citable/schemas/audit-coverage.schema.json +118 -0
- package/dist/universal/.cursor/skills/citable/schemas/claim-evidence.schema.json +21 -0
- package/dist/universal/.cursor/skills/citable/schemas/claim-verification.schema.json +18 -0
- package/dist/universal/.cursor/skills/citable/schemas/collection-result.schema.json +35 -0
- package/dist/universal/.cursor/skills/citable/schemas/config.schema.json +2 -0
- package/dist/universal/.cursor/skills/citable/schemas/cro-report.schema.json +8 -1
- package/dist/universal/.cursor/skills/citable/schemas/derivation.schema.json +18 -0
- package/dist/universal/.cursor/skills/citable/schemas/external-comparison.schema.json +16 -0
- package/dist/universal/.cursor/skills/citable/schemas/external-observation.schema.json +32 -0
- package/dist/universal/.cursor/skills/citable/schemas/finding.schema.json +105 -2
- package/dist/universal/.cursor/skills/citable/schemas/prompt-set.schema.json +47 -0
- package/dist/universal/.cursor/skills/citable/schemas/remediation-verification.schema.json +12 -1
- package/dist/universal/.cursor/skills/citable/schemas/representation-data.schema.json +21 -0
- package/dist/universal/.cursor/skills/citable/schemas/research-dataset.schema.json +27 -0
- package/dist/universal/.cursor/skills/citable/schemas/run.schema.json +15 -2
- package/dist/universal/.cursor/skills/citable/schemas/search-discovery-data.schema.json +20 -0
- package/dist/universal/.cursor/skills/citable/schemas/search-report.schema.json +8 -1
- package/dist/universal/.cursor/skills/citable/schemas/summary.schema.json +41 -0
- package/dist/universal/.gemini/skills/citable/SKILL.md +11 -2
- package/dist/universal/.gemini/skills/citable/VERSION +1 -1
- package/dist/universal/.gemini/skills/citable/manifest.json +24 -12
- package/dist/universal/.gemini/skills/citable/schemas/action-plan.schema.json +38 -1
- package/dist/universal/.gemini/skills/citable/schemas/audit-coverage.schema.json +118 -0
- package/dist/universal/.gemini/skills/citable/schemas/claim-evidence.schema.json +21 -0
- package/dist/universal/.gemini/skills/citable/schemas/claim-verification.schema.json +18 -0
- package/dist/universal/.gemini/skills/citable/schemas/collection-result.schema.json +35 -0
- package/dist/universal/.gemini/skills/citable/schemas/config.schema.json +2 -0
- package/dist/universal/.gemini/skills/citable/schemas/cro-report.schema.json +8 -1
- package/dist/universal/.gemini/skills/citable/schemas/derivation.schema.json +18 -0
- package/dist/universal/.gemini/skills/citable/schemas/external-comparison.schema.json +16 -0
- package/dist/universal/.gemini/skills/citable/schemas/external-observation.schema.json +32 -0
- package/dist/universal/.gemini/skills/citable/schemas/finding.schema.json +105 -2
- package/dist/universal/.gemini/skills/citable/schemas/prompt-set.schema.json +47 -0
- package/dist/universal/.gemini/skills/citable/schemas/remediation-verification.schema.json +12 -1
- package/dist/universal/.gemini/skills/citable/schemas/representation-data.schema.json +21 -0
- package/dist/universal/.gemini/skills/citable/schemas/research-dataset.schema.json +27 -0
- package/dist/universal/.gemini/skills/citable/schemas/run.schema.json +15 -2
- package/dist/universal/.gemini/skills/citable/schemas/search-discovery-data.schema.json +20 -0
- package/dist/universal/.gemini/skills/citable/schemas/search-report.schema.json +8 -1
- package/dist/universal/.gemini/skills/citable/schemas/summary.schema.json +41 -0
- package/dist/universal/.github/skills/citable/SKILL.md +11 -2
- package/dist/universal/.github/skills/citable/VERSION +1 -1
- package/dist/universal/.github/skills/citable/manifest.json +24 -12
- package/dist/universal/.github/skills/citable/schemas/action-plan.schema.json +38 -1
- package/dist/universal/.github/skills/citable/schemas/audit-coverage.schema.json +118 -0
- package/dist/universal/.github/skills/citable/schemas/claim-evidence.schema.json +21 -0
- package/dist/universal/.github/skills/citable/schemas/claim-verification.schema.json +18 -0
- package/dist/universal/.github/skills/citable/schemas/collection-result.schema.json +35 -0
- package/dist/universal/.github/skills/citable/schemas/config.schema.json +2 -0
- package/dist/universal/.github/skills/citable/schemas/cro-report.schema.json +8 -1
- package/dist/universal/.github/skills/citable/schemas/derivation.schema.json +18 -0
- package/dist/universal/.github/skills/citable/schemas/external-comparison.schema.json +16 -0
- package/dist/universal/.github/skills/citable/schemas/external-observation.schema.json +32 -0
- package/dist/universal/.github/skills/citable/schemas/finding.schema.json +105 -2
- package/dist/universal/.github/skills/citable/schemas/prompt-set.schema.json +47 -0
- package/dist/universal/.github/skills/citable/schemas/remediation-verification.schema.json +12 -1
- package/dist/universal/.github/skills/citable/schemas/representation-data.schema.json +21 -0
- package/dist/universal/.github/skills/citable/schemas/research-dataset.schema.json +27 -0
- package/dist/universal/.github/skills/citable/schemas/run.schema.json +15 -2
- package/dist/universal/.github/skills/citable/schemas/search-discovery-data.schema.json +20 -0
- package/dist/universal/.github/skills/citable/schemas/search-report.schema.json +8 -1
- package/dist/universal/.github/skills/citable/schemas/summary.schema.json +41 -0
- package/dist/universal/.kiro/skills/citable/SKILL.md +11 -2
- package/dist/universal/.kiro/skills/citable/VERSION +1 -1
- package/dist/universal/.kiro/skills/citable/manifest.json +24 -12
- package/dist/universal/.kiro/skills/citable/schemas/action-plan.schema.json +38 -1
- package/dist/universal/.kiro/skills/citable/schemas/audit-coverage.schema.json +118 -0
- package/dist/universal/.kiro/skills/citable/schemas/claim-evidence.schema.json +21 -0
- package/dist/universal/.kiro/skills/citable/schemas/claim-verification.schema.json +18 -0
- package/dist/universal/.kiro/skills/citable/schemas/collection-result.schema.json +35 -0
- package/dist/universal/.kiro/skills/citable/schemas/config.schema.json +2 -0
- package/dist/universal/.kiro/skills/citable/schemas/cro-report.schema.json +8 -1
- package/dist/universal/.kiro/skills/citable/schemas/derivation.schema.json +18 -0
- package/dist/universal/.kiro/skills/citable/schemas/external-comparison.schema.json +16 -0
- package/dist/universal/.kiro/skills/citable/schemas/external-observation.schema.json +32 -0
- package/dist/universal/.kiro/skills/citable/schemas/finding.schema.json +105 -2
- package/dist/universal/.kiro/skills/citable/schemas/prompt-set.schema.json +47 -0
- package/dist/universal/.kiro/skills/citable/schemas/remediation-verification.schema.json +12 -1
- package/dist/universal/.kiro/skills/citable/schemas/representation-data.schema.json +21 -0
- package/dist/universal/.kiro/skills/citable/schemas/research-dataset.schema.json +27 -0
- package/dist/universal/.kiro/skills/citable/schemas/run.schema.json +15 -2
- package/dist/universal/.kiro/skills/citable/schemas/search-discovery-data.schema.json +20 -0
- package/dist/universal/.kiro/skills/citable/schemas/search-report.schema.json +8 -1
- package/dist/universal/.kiro/skills/citable/schemas/summary.schema.json +41 -0
- package/dist/universal/.opencode/skills/citable/SKILL.md +11 -2
- package/dist/universal/.opencode/skills/citable/VERSION +1 -1
- package/dist/universal/.opencode/skills/citable/manifest.json +24 -12
- package/dist/universal/.opencode/skills/citable/schemas/action-plan.schema.json +38 -1
- package/dist/universal/.opencode/skills/citable/schemas/audit-coverage.schema.json +118 -0
- package/dist/universal/.opencode/skills/citable/schemas/claim-evidence.schema.json +21 -0
- package/dist/universal/.opencode/skills/citable/schemas/claim-verification.schema.json +18 -0
- package/dist/universal/.opencode/skills/citable/schemas/collection-result.schema.json +35 -0
- package/dist/universal/.opencode/skills/citable/schemas/config.schema.json +2 -0
- package/dist/universal/.opencode/skills/citable/schemas/cro-report.schema.json +8 -1
- package/dist/universal/.opencode/skills/citable/schemas/derivation.schema.json +18 -0
- package/dist/universal/.opencode/skills/citable/schemas/external-comparison.schema.json +16 -0
- package/dist/universal/.opencode/skills/citable/schemas/external-observation.schema.json +32 -0
- package/dist/universal/.opencode/skills/citable/schemas/finding.schema.json +105 -2
- package/dist/universal/.opencode/skills/citable/schemas/prompt-set.schema.json +47 -0
- package/dist/universal/.opencode/skills/citable/schemas/remediation-verification.schema.json +12 -1
- package/dist/universal/.opencode/skills/citable/schemas/representation-data.schema.json +21 -0
- package/dist/universal/.opencode/skills/citable/schemas/research-dataset.schema.json +27 -0
- package/dist/universal/.opencode/skills/citable/schemas/run.schema.json +15 -2
- package/dist/universal/.opencode/skills/citable/schemas/search-discovery-data.schema.json +20 -0
- package/dist/universal/.opencode/skills/citable/schemas/search-report.schema.json +8 -1
- package/dist/universal/.opencode/skills/citable/schemas/summary.schema.json +41 -0
- package/dist/universal/.pi/agent/skills/citable/SKILL.md +11 -2
- package/dist/universal/.pi/agent/skills/citable/VERSION +1 -1
- package/dist/universal/.pi/agent/skills/citable/manifest.json +24 -12
- package/dist/universal/.pi/agent/skills/citable/schemas/action-plan.schema.json +38 -1
- package/dist/universal/.pi/agent/skills/citable/schemas/audit-coverage.schema.json +118 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/claim-evidence.schema.json +21 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/claim-verification.schema.json +18 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/collection-result.schema.json +35 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/config.schema.json +2 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/cro-report.schema.json +8 -1
- package/dist/universal/.pi/agent/skills/citable/schemas/derivation.schema.json +18 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/external-comparison.schema.json +16 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/external-observation.schema.json +32 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/finding.schema.json +105 -2
- package/dist/universal/.pi/agent/skills/citable/schemas/prompt-set.schema.json +47 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/remediation-verification.schema.json +12 -1
- package/dist/universal/.pi/agent/skills/citable/schemas/representation-data.schema.json +21 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/research-dataset.schema.json +27 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/run.schema.json +15 -2
- package/dist/universal/.pi/agent/skills/citable/schemas/search-discovery-data.schema.json +20 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/search-report.schema.json +8 -1
- package/dist/universal/.pi/agent/skills/citable/schemas/summary.schema.json +41 -0
- package/dist/universal/.qoder/skills/citable/SKILL.md +11 -2
- package/dist/universal/.qoder/skills/citable/VERSION +1 -1
- package/dist/universal/.qoder/skills/citable/manifest.json +24 -12
- package/dist/universal/.qoder/skills/citable/schemas/action-plan.schema.json +38 -1
- package/dist/universal/.qoder/skills/citable/schemas/audit-coverage.schema.json +118 -0
- package/dist/universal/.qoder/skills/citable/schemas/claim-evidence.schema.json +21 -0
- package/dist/universal/.qoder/skills/citable/schemas/claim-verification.schema.json +18 -0
- package/dist/universal/.qoder/skills/citable/schemas/collection-result.schema.json +35 -0
- package/dist/universal/.qoder/skills/citable/schemas/config.schema.json +2 -0
- package/dist/universal/.qoder/skills/citable/schemas/cro-report.schema.json +8 -1
- package/dist/universal/.qoder/skills/citable/schemas/derivation.schema.json +18 -0
- package/dist/universal/.qoder/skills/citable/schemas/external-comparison.schema.json +16 -0
- package/dist/universal/.qoder/skills/citable/schemas/external-observation.schema.json +32 -0
- package/dist/universal/.qoder/skills/citable/schemas/finding.schema.json +105 -2
- package/dist/universal/.qoder/skills/citable/schemas/prompt-set.schema.json +47 -0
- package/dist/universal/.qoder/skills/citable/schemas/remediation-verification.schema.json +12 -1
- package/dist/universal/.qoder/skills/citable/schemas/representation-data.schema.json +21 -0
- package/dist/universal/.qoder/skills/citable/schemas/research-dataset.schema.json +27 -0
- package/dist/universal/.qoder/skills/citable/schemas/run.schema.json +15 -2
- package/dist/universal/.qoder/skills/citable/schemas/search-discovery-data.schema.json +20 -0
- package/dist/universal/.qoder/skills/citable/schemas/search-report.schema.json +8 -1
- package/dist/universal/.qoder/skills/citable/schemas/summary.schema.json +41 -0
- package/dist/universal/.rovodev/skills/citable/SKILL.md +11 -2
- package/dist/universal/.rovodev/skills/citable/VERSION +1 -1
- package/dist/universal/.rovodev/skills/citable/manifest.json +24 -12
- package/dist/universal/.rovodev/skills/citable/schemas/action-plan.schema.json +38 -1
- package/dist/universal/.rovodev/skills/citable/schemas/audit-coverage.schema.json +118 -0
- package/dist/universal/.rovodev/skills/citable/schemas/claim-evidence.schema.json +21 -0
- package/dist/universal/.rovodev/skills/citable/schemas/claim-verification.schema.json +18 -0
- package/dist/universal/.rovodev/skills/citable/schemas/collection-result.schema.json +35 -0
- package/dist/universal/.rovodev/skills/citable/schemas/config.schema.json +2 -0
- package/dist/universal/.rovodev/skills/citable/schemas/cro-report.schema.json +8 -1
- package/dist/universal/.rovodev/skills/citable/schemas/derivation.schema.json +18 -0
- package/dist/universal/.rovodev/skills/citable/schemas/external-comparison.schema.json +16 -0
- package/dist/universal/.rovodev/skills/citable/schemas/external-observation.schema.json +32 -0
- package/dist/universal/.rovodev/skills/citable/schemas/finding.schema.json +105 -2
- package/dist/universal/.rovodev/skills/citable/schemas/prompt-set.schema.json +47 -0
- package/dist/universal/.rovodev/skills/citable/schemas/remediation-verification.schema.json +12 -1
- package/dist/universal/.rovodev/skills/citable/schemas/representation-data.schema.json +21 -0
- package/dist/universal/.rovodev/skills/citable/schemas/research-dataset.schema.json +27 -0
- package/dist/universal/.rovodev/skills/citable/schemas/run.schema.json +15 -2
- package/dist/universal/.rovodev/skills/citable/schemas/search-discovery-data.schema.json +20 -0
- package/dist/universal/.rovodev/skills/citable/schemas/search-report.schema.json +8 -1
- package/dist/universal/.rovodev/skills/citable/schemas/summary.schema.json +41 -0
- package/dist/universal/.trae/skills/citable/SKILL.md +11 -2
- package/dist/universal/.trae/skills/citable/VERSION +1 -1
- package/dist/universal/.trae/skills/citable/manifest.json +24 -12
- package/dist/universal/.trae/skills/citable/schemas/action-plan.schema.json +38 -1
- package/dist/universal/.trae/skills/citable/schemas/audit-coverage.schema.json +118 -0
- package/dist/universal/.trae/skills/citable/schemas/claim-evidence.schema.json +21 -0
- package/dist/universal/.trae/skills/citable/schemas/claim-verification.schema.json +18 -0
- package/dist/universal/.trae/skills/citable/schemas/collection-result.schema.json +35 -0
- package/dist/universal/.trae/skills/citable/schemas/config.schema.json +2 -0
- package/dist/universal/.trae/skills/citable/schemas/cro-report.schema.json +8 -1
- package/dist/universal/.trae/skills/citable/schemas/derivation.schema.json +18 -0
- package/dist/universal/.trae/skills/citable/schemas/external-comparison.schema.json +16 -0
- package/dist/universal/.trae/skills/citable/schemas/external-observation.schema.json +32 -0
- package/dist/universal/.trae/skills/citable/schemas/finding.schema.json +105 -2
- package/dist/universal/.trae/skills/citable/schemas/prompt-set.schema.json +47 -0
- package/dist/universal/.trae/skills/citable/schemas/remediation-verification.schema.json +12 -1
- package/dist/universal/.trae/skills/citable/schemas/representation-data.schema.json +21 -0
- package/dist/universal/.trae/skills/citable/schemas/research-dataset.schema.json +27 -0
- package/dist/universal/.trae/skills/citable/schemas/run.schema.json +15 -2
- package/dist/universal/.trae/skills/citable/schemas/search-discovery-data.schema.json +20 -0
- package/dist/universal/.trae/skills/citable/schemas/search-report.schema.json +8 -1
- package/dist/universal/.trae/skills/citable/schemas/summary.schema.json +41 -0
- package/dist/universal/.trae-cn/skills/citable/SKILL.md +11 -2
- package/dist/universal/.trae-cn/skills/citable/VERSION +1 -1
- package/dist/universal/.trae-cn/skills/citable/manifest.json +24 -12
- package/dist/universal/.trae-cn/skills/citable/schemas/action-plan.schema.json +38 -1
- package/dist/universal/.trae-cn/skills/citable/schemas/audit-coverage.schema.json +118 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/claim-evidence.schema.json +21 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/claim-verification.schema.json +18 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/collection-result.schema.json +35 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/config.schema.json +2 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/cro-report.schema.json +8 -1
- package/dist/universal/.trae-cn/skills/citable/schemas/derivation.schema.json +18 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/external-comparison.schema.json +16 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/external-observation.schema.json +32 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/finding.schema.json +105 -2
- package/dist/universal/.trae-cn/skills/citable/schemas/prompt-set.schema.json +47 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/remediation-verification.schema.json +12 -1
- package/dist/universal/.trae-cn/skills/citable/schemas/representation-data.schema.json +21 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/research-dataset.schema.json +27 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/run.schema.json +15 -2
- package/dist/universal/.trae-cn/skills/citable/schemas/search-discovery-data.schema.json +20 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/search-report.schema.json +8 -1
- package/dist/universal/.trae-cn/skills/citable/schemas/summary.schema.json +41 -0
- package/dist/universal/manifest.json +292 -148
- package/package.json +1 -1
- package/schemas/action-plan.schema.json +38 -1
- package/schemas/audit-coverage.schema.json +118 -0
- package/schemas/claim-evidence.schema.json +21 -0
- package/schemas/claim-verification.schema.json +18 -0
- package/schemas/collection-result.schema.json +35 -0
- package/schemas/config.schema.json +2 -0
- package/schemas/cro-report.schema.json +8 -1
- package/schemas/derivation.schema.json +18 -0
- package/schemas/external-comparison.schema.json +16 -0
- package/schemas/external-observation.schema.json +32 -0
- package/schemas/finding.schema.json +105 -2
- package/schemas/prompt-set.schema.json +47 -0
- package/schemas/remediation-verification.schema.json +12 -1
- package/schemas/representation-data.schema.json +21 -0
- package/schemas/research-dataset.schema.json +27 -0
- package/schemas/run.schema.json +15 -2
- package/schemas/search-discovery-data.schema.json +20 -0
- package/schemas/search-report.schema.json +8 -1
- package/schemas/summary.schema.json +41 -0
- package/skill/SKILL.md +11 -2
- package/src/acceptance/reproducibility.js +5 -25
- package/src/analysis/croRoadmap.js +3 -3
- package/src/analysis/strategicRoadmap.js +3 -3
- package/src/artifacts/interchange.js +2 -6
- package/src/cli/index.js +15 -3
- package/src/commands/actionPlan.js +46 -5
- package/src/commands/applyRemediation.js +5 -5
- package/src/commands/audit.js +75 -8
- package/src/commands/ciWorkflow.js +7 -2
- package/src/commands/compareSnapshots.js +155 -47
- package/src/commands/connect.js +24 -4
- package/src/commands/context.js +41 -2
- package/src/commands/croSuite.js +51 -13
- package/src/commands/delivery.js +7 -7
- package/src/commands/governance.js +9 -10
- package/src/commands/implementationKit.js +2 -1
- package/src/commands/init.js +8 -1
- package/src/commands/previewCro.js +1 -1
- package/src/commands/prioritize.js +3 -2
- package/src/commands/reviews.js +31 -5
- package/src/commands/roadmapCmd.js +7 -13
- package/src/commands/sweep.js +15 -2
- package/src/commands/verifyRemediation.js +94 -19
- package/src/connectors/collectionResult.js +80 -0
- package/src/connectors/ga4.js +46 -11
- package/src/connectors/gsc.js +45 -6
- package/src/connectors/index.js +1 -1
- package/src/connectors/webflow.js +140 -10
- package/src/connectors/wordpress.js +92 -8
- package/src/crawler/fetch.js +220 -24
- package/src/crawler/resourceValidity.js +119 -0
- package/src/crawler/sitemap.js +435 -16
- package/src/crawler/sitemapCollector.js +364 -0
- package/src/crawler/urlIdentity.js +97 -0
- package/src/detectors/agent.js +11 -0
- package/src/detectors/ans.js +16 -1
- package/src/detectors/arch.js +6 -0
- package/src/detectors/claim.js +9 -0
- package/src/detectors/crawl.js +7 -0
- package/src/detectors/cro.js +21 -0
- package/src/detectors/cwv.js +4 -0
- package/src/detectors/entity.js +7 -0
- package/src/detectors/evd.js +9 -0
- package/src/detectors/framework.js +28 -2
- package/src/detectors/geoReco.js +16 -0
- package/src/detectors/hreflang.js +3 -0
- package/src/detectors/lifeMeas.js +9 -0
- package/src/detectors/link.js +6 -1
- package/src/detectors/page.js +11 -0
- package/src/detectors/schemaData.js +16 -1
- package/src/detectors/tech.js +34 -3
- package/src/discovery/searchConsole.js +186 -0
- package/src/evidence/coverage.js +448 -0
- package/src/evidence/determination.js +157 -0
- package/src/evidence/downstream.js +110 -0
- package/src/evidence/external.js +251 -0
- package/src/evidence/hashes.js +109 -0
- package/src/evidence/run.js +68 -8
- package/src/extractor/page.js +29 -2
- package/src/extractor/site.js +298 -50
- package/src/reporting/executiveCroReport.js +36 -13
- package/src/reporting/executiveExport.js +45 -16
- package/src/reporting/executiveSearchReport.js +56 -22
- package/src/reporting/report.js +56 -9
- package/src/representation/prompts.js +117 -0
- package/src/representation/representation.js +186 -0
- package/src/shared/epistemicLanguage.js +86 -0
- package/src/shared/evidenceSourceResolver.js +48 -17
- package/src/shared/htmlEscape.js +8 -4
- package/src/shared/runPackageVerifier.js +99 -8
- package/src/shared/verifiedRunLoader.js +129 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$id": "citable://schemas/research-dataset.schema.json",
|
|
3
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
4
|
+
"title": "Immutable research dataset",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["dataset_id", "dataset_version", "declared_purpose", "declared_population", "population_size", "inclusion_criteria", "exclusion_criteria", "collection", "source_references", "observation_references", "normalization", "derivation_references", "coverage", "coverage_status", "limitations", "dataset_hash"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"dataset_id": { "type": "string", "minLength": 1 },
|
|
10
|
+
"dataset_version": { "type": "integer", "minimum": 1 },
|
|
11
|
+
"declared_purpose": { "type": "string", "minLength": 1 },
|
|
12
|
+
"declared_population": { "type": "object", "additionalProperties": false, "required": ["type", "id"], "properties": { "type": { "type": "string", "minLength": 1 }, "id": { "type": "string", "minLength": 1 }, "size": { "type": ["integer", "null"], "minimum": 0 } } },
|
|
13
|
+
"population_size": { "type": ["integer", "null"], "minimum": 0 },
|
|
14
|
+
"inclusion_criteria": { "type": "array", "items": { "type": "string" } },
|
|
15
|
+
"exclusion_criteria": { "type": "array", "items": { "type": "string" } },
|
|
16
|
+
"collection": { "type": "object", "additionalProperties": false, "required": ["started_at", "ended_at"], "properties": { "started_at": { "type": "string", "format": "date-time" }, "ended_at": { "type": "string", "format": "date-time" } } },
|
|
17
|
+
"source_references": { "type": "array", "items": { "type": "string" } },
|
|
18
|
+
"source_retrieval_timestamps": { "type": "array", "items": { "type": "string", "format": "date-time" } },
|
|
19
|
+
"observation_references": { "type": "array", "items": { "type": "string" } },
|
|
20
|
+
"normalization": { "type": "object", "additionalProperties": false, "required": ["method", "version"], "properties": { "method": { "type": "string", "minLength": 1 }, "version": { "type": "string", "minLength": 1 } } },
|
|
21
|
+
"derivation_references": { "type": "array", "items": { "type": "string" } },
|
|
22
|
+
"coverage": { "type": "object", "additionalProperties": false, "required": ["declared", "retrieved", "evaluated", "unavailable", "failed"], "properties": { "declared": { "type": "integer", "minimum": 0 }, "retrieved": { "type": "integer", "minimum": 0 }, "evaluated": { "type": "integer", "minimum": 0 }, "unavailable": { "type": "integer", "minimum": 0 }, "failed": { "type": "integer", "minimum": 0 } } },
|
|
23
|
+
"coverage_status": { "type": "string", "enum": ["complete_for_declared_population", "partial", "truncated", "indeterminate", "error"] },
|
|
24
|
+
"limitations": { "type": "array", "items": { "type": "string" } },
|
|
25
|
+
"dataset_hash": { "type": "string", "pattern": "^[a-f0-9]{64}$" }
|
|
26
|
+
}
|
|
27
|
+
}
|
package/schemas/run.schema.json
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
"type": "object",
|
|
6
6
|
"required": ["run_id", "command", "tool_version", "skill_version", "timestamp", "target", "status"],
|
|
7
7
|
"properties": {
|
|
8
|
+
"schema_version": { "type": "integer", "enum": [1, 2] },
|
|
8
9
|
"run_id": { "type": "string" },
|
|
9
10
|
"command": { "type": "string" },
|
|
10
11
|
"argv": { "type": "array", "items": { "type": "string" } },
|
|
@@ -31,6 +32,18 @@
|
|
|
31
32
|
"incomplete_checks": { "type": "array", "items": { "type": "string" } },
|
|
32
33
|
"errors": { "type": "array", "items": { "type": "string" } },
|
|
33
34
|
"warnings": { "type": "array", "items": { "type": "string" } },
|
|
34
|
-
"status": { "type": "string", "enum": ["completed", "completed_with_warnings", "incomplete", "failed"] }
|
|
35
|
-
|
|
35
|
+
"status": { "type": "string", "enum": ["completed", "completed_with_warnings", "incomplete", "failed"] },
|
|
36
|
+
"execution_status": { "type": "string", "enum": ["completed", "completed_with_warnings", "failed"] },
|
|
37
|
+
"coverage_status": { "type": "string", "enum": ["complete", "truncated", "indeterminate", "not_applicable"] },
|
|
38
|
+
"determination_status": { "type": "string", "enum": ["supported", "qualified", "indeterminate", "not_applicable"] }
|
|
39
|
+
},
|
|
40
|
+
"allOf": [
|
|
41
|
+
{
|
|
42
|
+
"if": {
|
|
43
|
+
"required": ["schema_version"],
|
|
44
|
+
"properties": { "schema_version": { "const": 2 } }
|
|
45
|
+
},
|
|
46
|
+
"then": { "required": ["execution_status", "coverage_status", "determination_status"] }
|
|
47
|
+
}
|
|
48
|
+
]
|
|
36
49
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$id": "citable://schemas/search-discovery-data.schema.json",
|
|
3
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
4
|
+
"title": "Search discovery observation data",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["query", "page", "interval", "metrics", "request", "coverage_status", "evidence_origin"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"query": { "type": ["string", "null"] },
|
|
10
|
+
"page": { "type": ["string", "null"], "format": "uri" },
|
|
11
|
+
"interval": { "type": "object", "additionalProperties": false, "required": ["start_date", "end_date"], "properties": { "start_date": { "type": "string", "format": "date" }, "end_date": { "type": "string", "format": "date" } } },
|
|
12
|
+
"metrics": { "type": "object", "additionalProperties": false, "required": ["impressions", "clicks", "ctr", "average_position"], "properties": { "impressions": { "type": ["number", "null"], "minimum": 0 }, "clicks": { "type": ["number", "null"], "minimum": 0 }, "ctr": { "type": ["number", "null"], "minimum": 0 }, "average_position": { "type": ["number", "null"], "minimum": 0 } } },
|
|
13
|
+
"dimensions": { "type": "object", "additionalProperties": false, "properties": { "country": { "type": ["string", "null"] }, "device": { "type": ["string", "null"] }, "search_appearance": { "type": ["string", "null"] }, "date": { "type": ["string", "null"], "format": "date" } } },
|
|
14
|
+
"request": { "type": "object", "additionalProperties": false, "required": ["property_id", "dimensions", "filters", "row_limit"], "properties": { "property_id": { "type": "string", "minLength": 1 }, "dimensions": { "type": "array", "items": { "type": "string" } }, "filters": { "type": "object" }, "row_limit": { "type": "integer", "minimum": 1, "maximum": 25000 } } },
|
|
15
|
+
"provider_reported": { "type": "object", "additionalProperties": false, "properties": { "row_count": { "type": ["integer", "null"], "minimum": 0 }, "page_start": { "type": "integer", "minimum": 0 } } },
|
|
16
|
+
"response_hash": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
|
|
17
|
+
"coverage_status": { "type": "string", "enum": ["complete", "truncated", "indeterminate", "provider_bounded"] },
|
|
18
|
+
"evidence_origin": { "type": "string", "enum": ["LIVE_PROVIDER", "RECORDED_FIXTURE", "SYNTHETIC_TEST"] }
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -90,7 +90,14 @@
|
|
|
90
90
|
"source_identifier": { "type": ["string", "null"] },
|
|
91
91
|
"source_findings_count": { "type": "integer", "minimum": 0 },
|
|
92
92
|
"integrity_hash": { "type": ["string", "null"] },
|
|
93
|
-
"synthetic_evidence": { "type": "boolean" }
|
|
93
|
+
"synthetic_evidence": { "type": "boolean" },
|
|
94
|
+
"package_verified": { "type": "boolean" },
|
|
95
|
+
"integrity_mode": { "type": "string" },
|
|
96
|
+
"legacy": { "type": "boolean" },
|
|
97
|
+
"coverage_status": { "type": "string" },
|
|
98
|
+
"determination_status": { "type": "string" },
|
|
99
|
+
"evaluated": { "type": ["integer", "null"], "minimum": 0 },
|
|
100
|
+
"eligible": { "type": ["integer", "null"], "minimum": 0 }
|
|
94
101
|
},
|
|
95
102
|
"additionalProperties": false
|
|
96
103
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$id": "citable://schemas/summary.schema.json",
|
|
3
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
4
|
+
"title": "Run summary",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": ["coverage", "posture"],
|
|
7
|
+
"properties": {
|
|
8
|
+
"coverage": {
|
|
9
|
+
"type": ["object", "null"],
|
|
10
|
+
"required": ["status", "populations", "stop_reason"],
|
|
11
|
+
"properties": {
|
|
12
|
+
"status": { "enum": ["complete", "truncated", "indeterminate", "not_applicable"] },
|
|
13
|
+
"populations": { "$ref": "citable://schemas/audit-coverage.schema.json#/properties/populations" },
|
|
14
|
+
"stop_reason": { "type": ["string", "null"] }
|
|
15
|
+
},
|
|
16
|
+
"additionalProperties": false
|
|
17
|
+
},
|
|
18
|
+
"posture": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"required": ["retrieval_eligibility", "source_extraction_and_support", "observed_citation_behavior"],
|
|
21
|
+
"properties": {
|
|
22
|
+
"retrieval_eligibility": { "$ref": "#/definitions/posture" },
|
|
23
|
+
"source_extraction_and_support": { "$ref": "#/definitions/posture" },
|
|
24
|
+
"observed_citation_behavior": { "$ref": "#/definitions/posture" }
|
|
25
|
+
},
|
|
26
|
+
"additionalProperties": false
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"additionalProperties": true,
|
|
30
|
+
"definitions": {
|
|
31
|
+
"posture": {
|
|
32
|
+
"type": "object",
|
|
33
|
+
"required": ["result"],
|
|
34
|
+
"properties": {
|
|
35
|
+
"result": { "type": "string" },
|
|
36
|
+
"coverage_status": { "enum": ["complete", "truncated", "indeterminate", "not_applicable"] }
|
|
37
|
+
},
|
|
38
|
+
"additionalProperties": true
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
package/skill/SKILL.md
CHANGED
|
@@ -7,7 +7,7 @@ description: >
|
|
|
7
7
|
generative engine optimization, structured data governance, claim substantiation,
|
|
8
8
|
crawler policy, entity consistency, content discoverability, or wants a site audited
|
|
9
9
|
for how search and AI systems will retrieve, understand, cite, or recommend it.
|
|
10
|
-
version: 1.
|
|
10
|
+
version: 1.21.0
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
# Citable — evidence and change control for search and AI citation readiness
|
|
@@ -69,6 +69,15 @@ Every report must keep these top-level states separate:
|
|
|
69
69
|
3. **Observed citation behavior** — only controlled, timestamped provider
|
|
70
70
|
observations; absent observations are `not_evidenced`, never inferred.
|
|
71
71
|
|
|
72
|
+
Presentation language must preserve those boundaries. An empty finding list,
|
|
73
|
+
legacy package, unverified artifact, incomplete crawl, or indeterminate
|
|
74
|
+
determination must not be described as `clean`, `complete`, `verified`,
|
|
75
|
+
`resolved`, `100%`, or `site-wide`. State the evaluated population and the
|
|
76
|
+
limitation instead (for example, "No findings were produced for the 217
|
|
77
|
+
successfully evaluated resources; corpus-wide absence is not established").
|
|
78
|
+
Positive local observations may remain supported, but they must not be widened
|
|
79
|
+
to pages or resources that were not observed.
|
|
80
|
+
|
|
72
81
|
Within retrieval, distinguish `allowed_by_policy`, `synthetic_fetch_succeeded`,
|
|
73
82
|
`observed_in_production_logs`, `indexed`, and `returned_by_retrieval`. Within
|
|
74
83
|
citation testing, distinguish mention, citation, material support, canonical
|
|
@@ -86,7 +95,7 @@ prefer running it over re-deriving its checks by hand:
|
|
|
86
95
|
|
|
87
96
|
```
|
|
88
97
|
citable init # initialize .citable/ (non-destructive)
|
|
89
|
-
citable audit [scope] --target <dir|url> [--base-url <url>] [--ref-date YYYY-MM-DD]
|
|
98
|
+
citable audit [scope] --target <dir|url> [--base-url <url>] [--max-pages <1..10000>] [--time-budget-seconds <1..86400>] [--ref-date YYYY-MM-DD]
|
|
90
99
|
citable plan-audit --target <dir|url> [--base-url <url>]
|
|
91
100
|
citable sweep technical --target <dir|url> # Technical SEO sweep + Core Web Vitals metrics
|
|
92
101
|
citable inspect <page> --target <dir|url>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
1
|
import path from 'node:path';
|
|
3
2
|
import { canonicalJson } from '../release/governance.js';
|
|
4
|
-
import { nowIso, readJson, sha256,
|
|
3
|
+
import { nowIso, readJson, sha256, writeJson } from '../shared/io.js';
|
|
5
4
|
import { validateAgainst } from '../shared/schemaValidator.js';
|
|
5
|
+
import { loadVerifiedRun } from '../shared/verifiedRunLoader.js';
|
|
6
6
|
|
|
7
7
|
const INCLUDED_FIELDS = [
|
|
8
8
|
'property.target', 'property.source_commit', 'property.content_hashes',
|
|
@@ -37,25 +37,6 @@ function normalizedArguments(argv = []) {
|
|
|
37
37
|
return normalized;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
function verifyRunPackage(runDir, manifest) {
|
|
41
|
-
const manifestCheck = validateAgainst('run.schema.json', manifest);
|
|
42
|
-
if (!manifestCheck.valid) throw new Error(`run manifest violates contract: ${manifestCheck.errors.join('; ')}`);
|
|
43
|
-
const checksumsFile = path.join(runDir, 'checksums.json');
|
|
44
|
-
if (!fs.existsSync(checksumsFile)) throw new Error(`run ${manifest.run_id} has no checksums.json`);
|
|
45
|
-
const checksums = readJson(checksumsFile);
|
|
46
|
-
if (!checksums || Array.isArray(checksums) || typeof checksums !== 'object') throw new Error('run checksums must be an object');
|
|
47
|
-
const failures = [];
|
|
48
|
-
for (const [relative, expected] of Object.entries(checksums)) {
|
|
49
|
-
const file = path.resolve(runDir, relative);
|
|
50
|
-
if (path.isAbsolute(relative) || (!file.startsWith(`${path.resolve(runDir)}${path.sep}`))) failures.push(`${relative} escapes the run package`);
|
|
51
|
-
else if (!/^[a-f0-9]{64}$/.test(expected)) failures.push(`${relative} has an invalid checksum`);
|
|
52
|
-
else if (!fs.existsSync(file)) failures.push(`${relative} is missing`);
|
|
53
|
-
else if (sha256File(file) !== expected) failures.push(`${relative} checksum differs`);
|
|
54
|
-
}
|
|
55
|
-
if (failures.length) throw new Error(`run package integrity failed: ${failures.join('; ')}`);
|
|
56
|
-
return checksums;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
40
|
function fingerprintPayload(receipt) {
|
|
60
41
|
return {
|
|
61
42
|
property: { target: receipt.property.target, source_commit: receipt.property.source_commit, content_hashes: receipt.property.content_hashes },
|
|
@@ -74,11 +55,10 @@ export function createAcceptanceReceipt(root, { runId, context = {}, createdAt =
|
|
|
74
55
|
const contextCheck = validateAgainst('acceptance-run-context.schema.json', context);
|
|
75
56
|
if (!contextCheck.valid) throw new Error(`acceptance context violates contract: ${contextCheck.errors.join('; ')}`);
|
|
76
57
|
const runDir = path.join(root, '.citable', 'runs', runId);
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
const manifest = readJson(manifestFile);
|
|
58
|
+
const verified = loadVerifiedRun(runDir, { requireCompletedExecution: false, allowLegacy: true, requireCoverage: false });
|
|
59
|
+
const manifest = verified.manifest;
|
|
80
60
|
if (manifest.run_id !== runId) throw new Error(`run manifest id ${manifest.run_id} does not match requested run ${runId}`);
|
|
81
|
-
const checksums =
|
|
61
|
+
const checksums = verified.artifactHashes;
|
|
82
62
|
const canonicalArtifacts = sortedObject(Object.fromEntries(
|
|
83
63
|
Object.entries(checksums).filter(([name]) => name !== 'manifest.json'),
|
|
84
64
|
));
|
|
@@ -18,10 +18,10 @@ export function buildCroRoadmap({ findings = [], targetDomain = 'example.com', d
|
|
|
18
18
|
'Mobile Tap Sizing: Expand diminutive mobile CTA touch targets to >= 48px standard (CRO-015)',
|
|
19
19
|
],
|
|
20
20
|
target_outcomes: [
|
|
21
|
-
'
|
|
21
|
+
'Conversion funnel continuity observed across the declared paths in scope',
|
|
22
22
|
'Keystroke Effort Index: Form completion friction reduced by >= 40%',
|
|
23
|
-
'Above-the-fold information scent match
|
|
24
|
-
'
|
|
23
|
+
'Above-the-fold information scent match observed on evaluated primary landing pages',
|
|
24
|
+
'No mobile touch-target findings in the evaluated pages',
|
|
25
25
|
],
|
|
26
26
|
measurable_conversion_kpi: 'Form Completion Rate (+8% to +15% expected relative lift)',
|
|
27
27
|
experiments: backlog.experiments.filter((e) => ['CRO-007', 'CRO-005', 'CRO-015', 'CRO-017', 'CRO-018'].includes(e.detector_id) || e.ice_prioritization.effort <= 3),
|
|
@@ -24,9 +24,9 @@ export function buildStrategicRoadmap({ findings = [], initiatives = [], targetD
|
|
|
24
24
|
],
|
|
25
25
|
exit_criteria: [
|
|
26
26
|
'Zero critical-severity technical findings in citable audit technical',
|
|
27
|
-
'Static CLS readiness:
|
|
28
|
-
'
|
|
29
|
-
'Baseline Organization schema live with
|
|
27
|
+
'Static CLS readiness: every evaluated body image has explicit dimensions',
|
|
28
|
+
'Major answer engine bot access observed as allowed in robots directives',
|
|
29
|
+
'Baseline Organization schema live with an observed @id',
|
|
30
30
|
],
|
|
31
31
|
actions: [],
|
|
32
32
|
};
|
|
@@ -5,6 +5,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
5
5
|
import { canonicalJson } from '../release/governance.js';
|
|
6
6
|
import { nowIso, readJson, sha256, sha256File, writeJson } from '../shared/io.js';
|
|
7
7
|
import { validateAgainst } from '../shared/schemaValidator.js';
|
|
8
|
+
import { verifyRunPackage } from '../shared/runPackageVerifier.js';
|
|
8
9
|
|
|
9
10
|
const PACKAGE = readJson(path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../package.json'));
|
|
10
11
|
const ENVELOPE = 'citable-artifact.json';
|
|
@@ -37,18 +38,13 @@ function validateRunPackage(runDir) {
|
|
|
37
38
|
const checksumsFile = path.join(runDir, 'checksums.json');
|
|
38
39
|
if (!fs.existsSync(manifestFile) || !fs.existsSync(checksumsFile)) throw new Error('run package requires manifest.json and checksums.json');
|
|
39
40
|
const manifest = readJson(manifestFile);
|
|
40
|
-
const manifestCheck = validateAgainst('run.schema.json', manifest);
|
|
41
|
-
if (!manifestCheck.valid) throw new Error(`run manifest invalid: ${manifestCheck.errors.join('; ')}`);
|
|
42
41
|
const checksums = readJson(checksumsFile);
|
|
43
|
-
|
|
42
|
+
verifyRunPackage(runDir, { requireFindings: false, requireCompleted: false, requireChecksums: true, ignoredFiles: [ENVELOPE] });
|
|
44
43
|
const actualFiles = filesUnder(runDir).filter((name) => name !== ENVELOPE);
|
|
45
44
|
const expectedFiles = [...Object.keys(checksums), 'checksums.json'].sort();
|
|
46
45
|
if (new Set(expectedFiles).size !== expectedFiles.length) throw new Error('checksums.json contains duplicate package paths');
|
|
47
46
|
for (const rel of Object.keys(checksums)) {
|
|
48
47
|
if (!safeRelativePath(rel) || rel === ENVELOPE || rel === 'checksums.json') throw new Error(`unsafe checksum path: ${rel}`);
|
|
49
|
-
const file = path.join(runDir, ...rel.split('/'));
|
|
50
|
-
if (!fs.existsSync(file) || !fs.statSync(file).isFile()) throw new Error(`checksummed artifact is missing: ${rel}`);
|
|
51
|
-
if (!/^[a-f0-9]{64}$/.test(checksums[rel]) || sha256File(file) !== checksums[rel]) throw new Error(`artifact checksum mismatch: ${rel}`);
|
|
52
48
|
}
|
|
53
49
|
const extras = actualFiles.filter((name) => !expectedFiles.includes(name));
|
|
54
50
|
const missing = expectedFiles.filter((name) => !actualFiles.includes(name));
|
package/src/cli/index.js
CHANGED
|
@@ -185,6 +185,8 @@ Commands
|
|
|
185
185
|
|
|
186
186
|
Options
|
|
187
187
|
--target <dir|url> Built output directory or deployed URL to audit
|
|
188
|
+
--max-pages <count> Maximum unique page URLs attempted for a URL audit (default: 500)
|
|
189
|
+
--time-budget-seconds <seconds> Whole-run URL collection limit (default: 1800)
|
|
188
190
|
--base-url <url> Base URL for path resolution of a built output dir
|
|
189
191
|
--ref-date <YYYY-MM-DD> Reference date for expiry/staleness checks (default: today)
|
|
190
192
|
--input <file> Import evidence, remediation, or browser plan
|
|
@@ -233,7 +235,7 @@ Options
|
|
|
233
235
|
No output of this tool guarantees crawling, indexing, ranking, citation,
|
|
234
236
|
recommendation, inclusion, sentiment, or conversion outcomes.`;
|
|
235
237
|
|
|
236
|
-
function parseArgs(argv) {
|
|
238
|
+
export function parseArgs(argv) {
|
|
237
239
|
const args = { _: [] };
|
|
238
240
|
for (let i = 0; i < argv.length; i++) {
|
|
239
241
|
const a = argv[i];
|
|
@@ -243,6 +245,8 @@ function parseArgs(argv) {
|
|
|
243
245
|
else if (a === '--interactions') args.interactions = true;
|
|
244
246
|
else if (a === '--lighthouse') args.lighthouse = true;
|
|
245
247
|
else if (a === '--target') args.target = argv[++i];
|
|
248
|
+
else if (a === '--max-pages') args.maxPages = Number(argv[++i]);
|
|
249
|
+
else if (a === '--time-budget-seconds') args.timeBudgetSeconds = Number(argv[++i]);
|
|
246
250
|
else if (a === '--base-url') args.baseUrl = argv[++i];
|
|
247
251
|
else if (a === '--ref-date') args.refDate = argv[++i];
|
|
248
252
|
else if (a === '--viewport') args.viewport = argv[++i];
|
|
@@ -411,8 +415,16 @@ ${r.findings.map((f) => ` [${f.rule_id}] (${f.severity}) ${f.summary}\n Fix:
|
|
|
411
415
|
break;
|
|
412
416
|
}
|
|
413
417
|
const scope = args._[0];
|
|
414
|
-
const r = await audit(root, {
|
|
415
|
-
|
|
418
|
+
const r = await audit(root, {
|
|
419
|
+
target: args.target,
|
|
420
|
+
scope,
|
|
421
|
+
baseUrl: args.baseUrl,
|
|
422
|
+
refDate: args.refDate,
|
|
423
|
+
viewport: args.viewport,
|
|
424
|
+
maxPages: args.maxPages,
|
|
425
|
+
timeBudgetSeconds: args.timeBudgetSeconds,
|
|
426
|
+
});
|
|
427
|
+
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}\nExecution: ${r.manifest.execution_status}\nCoverage: ${r.manifest.coverage_status}\nDetermination: ${r.manifest.determination_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, execution_status: r.manifest.execution_status, coverage_status: r.manifest.coverage_status, determination_status: r.manifest.determination_status });
|
|
416
428
|
break;
|
|
417
429
|
}
|
|
418
430
|
case 'plan-audit': {
|
|
@@ -2,7 +2,10 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { readJson, writeJson, sha256, nowIso } from '../shared/io.js';
|
|
4
4
|
import { validateAgainst } from '../shared/schemaValidator.js';
|
|
5
|
+
import { downstreamEnvelope } from '../evidence/downstream.js';
|
|
6
|
+
import { REQUIREMENTS, evaluateRequirement } from '../evidence/determination.js';
|
|
5
7
|
import { checklistItem, toStringArray } from '../shared/checklist.js';
|
|
8
|
+
import { loadVerifiedRun } from '../shared/verifiedRunLoader.js';
|
|
6
9
|
|
|
7
10
|
const SEVERITY = { critical: 0, high: 1, medium: 2, low: 3, informational: 3, experimental: 3 };
|
|
8
11
|
const PHASE = { unblock: 0, governance: 1, content: 2, optimization: 3 };
|
|
@@ -46,6 +49,7 @@ function renderPlan(plan) {
|
|
|
46
49
|
'# Citable action plan', '',
|
|
47
50
|
`- Source audit: \`${plan.source_run_id}\``,
|
|
48
51
|
`- Actions: ${plan.summary.total_actions}; ready: ${plan.summary.ready}; blocked: ${plan.summary.blocked}`,
|
|
52
|
+
`- Evidence coverage: ${plan.source_coverage.coverage_status}; determination: ${plan.source_coverage.determination_status}`,
|
|
49
53
|
'',
|
|
50
54
|
'> This plan prioritizes observed findings. It does not guarantee ranking, citation, recommendation, or conversion outcomes.',
|
|
51
55
|
'',
|
|
@@ -61,6 +65,7 @@ function renderPlan(plan) {
|
|
|
61
65
|
lines.push(`- Decision owner: ${action.decision_owner ?? 'unassigned'}`);
|
|
62
66
|
lines.push(`- Dependencies: ${action.depends_on_action_ids.length ? action.depends_on_action_ids.join(', ') : 'none established'}`);
|
|
63
67
|
if (action.required_input.length) lines.push(`- Required input: ${action.required_input.join(', ')}`);
|
|
68
|
+
if (action.limitations.length) lines.push(`- Evidence limitations: ${action.limitations.join('; ')}`);
|
|
64
69
|
if (action.semantic_gates.length) lines.push(`- Semantic gates: ${action.semantic_gates.join(', ')}`);
|
|
65
70
|
lines.push(`- Failure condition: ${action.failure_condition}`);
|
|
66
71
|
lines.push(`- Leading indicators: ${action.leading_indicators.length ? action.leading_indicators.join(', ') : 'none established'}`);
|
|
@@ -78,13 +83,37 @@ export function actionPlan(root, { runId } = {}) {
|
|
|
78
83
|
const sourceDir = path.join(runsDir, sourceRunId);
|
|
79
84
|
const findingsFile = path.join(sourceDir, 'findings.json');
|
|
80
85
|
if (!fs.existsSync(findingsFile)) throw new Error(`run ${sourceRunId} has no findings.json`);
|
|
81
|
-
const
|
|
82
|
-
const findings =
|
|
83
|
-
const
|
|
86
|
+
const loaded = loadVerifiedRun(sourceDir, { requireCompletedExecution: false, allowLegacy: true, requireCoverage: false });
|
|
87
|
+
const findings = loaded.findings;
|
|
88
|
+
const rawFindings = JSON.stringify(findings);
|
|
89
|
+
const manifest = loaded.manifest;
|
|
90
|
+
const coverage = loaded.coverage;
|
|
91
|
+
const sourceCoverage = downstreamEnvelope(coverage, {
|
|
92
|
+
artifact: coverage ? 'coverage.json' : null,
|
|
93
|
+
});
|
|
84
94
|
const target = manifest.target?.location;
|
|
85
95
|
const actions = findings.map((finding) => {
|
|
86
96
|
const owner = finding.remediation.owner ?? null;
|
|
87
|
-
const
|
|
97
|
+
const findingScope = finding.evidence_scope || {
|
|
98
|
+
requirement: 'evaluated_subset',
|
|
99
|
+
satisfaction: sourceCoverage.determination_status,
|
|
100
|
+
coverage_ref: coverage ? 'coverage.json' : null,
|
|
101
|
+
resource_ids: [],
|
|
102
|
+
};
|
|
103
|
+
const requirement = findingScope.requirement || REQUIREMENTS.EVALUATED_SUBSET;
|
|
104
|
+
let requirementResult;
|
|
105
|
+
try {
|
|
106
|
+
requirementResult = evaluateRequirement(requirement, coverage, finding.subject);
|
|
107
|
+
} catch (error) {
|
|
108
|
+
requirementResult = { status: 'indeterminate', reason: `invalid_evidence_requirement: ${error.message}` };
|
|
109
|
+
}
|
|
110
|
+
const scopeSatisfied = ['supported', 'qualified'].includes(requirementResult.status);
|
|
111
|
+
const effectiveDetermination = sourceCoverage.determination_status === 'indeterminate'
|
|
112
|
+
|| sourceCoverage.determination_status === 'not_applicable'
|
|
113
|
+
|| !scopeSatisfied
|
|
114
|
+
? 'indeterminate'
|
|
115
|
+
: (sourceCoverage.determination_status === 'qualified' || requirementResult.status === 'qualified' ? 'qualified' : 'supported');
|
|
116
|
+
const blocked = (finding.remediation.review_required && !owner) || !scopeSatisfied || effectiveDetermination === 'indeterminate';
|
|
88
117
|
const scope = finding.discipline.length === 1 && ['aeo', 'geo', 'seo'].includes(finding.discipline[0]) ? ` ${finding.discipline[0]}` : '';
|
|
89
118
|
return {
|
|
90
119
|
action_id: `ACT-${finding.finding_id.replace(/^F-/, '')}`,
|
|
@@ -97,7 +126,18 @@ export function actionPlan(root, { runId } = {}) {
|
|
|
97
126
|
owner,
|
|
98
127
|
decision_owner: owner,
|
|
99
128
|
status: blocked ? 'blocked' : 'ready',
|
|
100
|
-
|
|
129
|
+
evidence_scope: { ...findingScope, satisfaction: effectiveDetermination },
|
|
130
|
+
coverage_status: sourceCoverage.coverage_status,
|
|
131
|
+
determination_status: effectiveDetermination,
|
|
132
|
+
limitations: [
|
|
133
|
+
...sourceCoverage.limitations,
|
|
134
|
+
...(finding.reasoning?.limitations || []),
|
|
135
|
+
...(requirementResult.reason ? [`evidence requirement: ${requirementResult.reason}`] : []),
|
|
136
|
+
].filter((item, index, all) => all.indexOf(item) === index),
|
|
137
|
+
required_input: blocked ? toStringArray([
|
|
138
|
+
...(finding.remediation.review_required && !owner ? [checklistItem('owner', 'accountable owner')] : []),
|
|
139
|
+
...(!scopeSatisfied || effectiveDetermination === 'indeterminate' ? ['sufficient comparable evidence for the declared scope'] : []),
|
|
140
|
+
]) : [],
|
|
101
141
|
semantic_gates: semanticGates(finding),
|
|
102
142
|
unsafe_shortcuts: finding.remediation.unsafe_shortcuts || [],
|
|
103
143
|
failure_condition: `${finding.verification.detector_to_rerun} still reports the exact subject, or verification cannot complete with sufficient evidence`,
|
|
@@ -120,6 +160,7 @@ export function actionPlan(root, { runId } = {}) {
|
|
|
120
160
|
ready: actions.filter((action) => action.status === 'ready').length,
|
|
121
161
|
blocked: actions.filter((action) => action.status === 'blocked').length,
|
|
122
162
|
},
|
|
163
|
+
source_coverage: sourceCoverage,
|
|
123
164
|
actions,
|
|
124
165
|
};
|
|
125
166
|
const validation = validateAgainst('action-plan.schema.json', plan);
|
|
@@ -3,6 +3,7 @@ import path from 'node:path';
|
|
|
3
3
|
import { createRun } from '../evidence/run.js';
|
|
4
4
|
import { readJson, sha256 } from '../shared/io.js';
|
|
5
5
|
import { validateAgainst } from '../shared/schemaValidator.js';
|
|
6
|
+
import { loadVerifiedRun } from '../shared/verifiedRunLoader.js';
|
|
6
7
|
|
|
7
8
|
function inside(root, candidate) {
|
|
8
9
|
const base = path.resolve(root) + path.sep;
|
|
@@ -19,11 +20,10 @@ export function applyRemediation(root, { input, write = false } = {}) {
|
|
|
19
20
|
const spec = readJson(input);
|
|
20
21
|
const valid = validateAgainst('remediation-spec.schema.json', spec);
|
|
21
22
|
if (!valid.valid) throw new Error(`remediation spec invalid: ${valid.errors.join('; ')}`);
|
|
22
|
-
const
|
|
23
|
-
if (!fs.existsSync(
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
const sourceFindingIds = new Set(readJson(findingsFile).map((finding) => finding.finding_id));
|
|
23
|
+
const sourceDir = path.join(root, '.citable', 'runs', spec.source_run_id);
|
|
24
|
+
if (!fs.existsSync(sourceDir)) throw new Error(`source run not found: ${spec.source_run_id}`);
|
|
25
|
+
const source = loadVerifiedRun(sourceDir, { requireCompletedExecution: false, allowLegacy: true, requireCoverage: false });
|
|
26
|
+
const sourceFindingIds = new Set(source.findings.map((finding) => finding.finding_id));
|
|
27
27
|
const results = [];
|
|
28
28
|
const pending = [];
|
|
29
29
|
for (const operation of spec.operations) {
|
package/src/commands/audit.js
CHANGED
|
@@ -10,10 +10,16 @@ import { writeJson, sha256 } from '../shared/io.js';
|
|
|
10
10
|
import { extractModified } from '../detectors/lifeMeas.js';
|
|
11
11
|
import { buildEntityGraph } from '../observations/entityGraph.js';
|
|
12
12
|
import { buildSourceIdentityChain } from '../observations/sourceIdentity.js';
|
|
13
|
+
import { pageArtifactRecord } from '../evidence/hashes.js';
|
|
13
14
|
|
|
14
15
|
/** `citable audit [scope]` — run detectors and produce an evidence package. */
|
|
15
|
-
export async function audit(root, {
|
|
16
|
-
|
|
16
|
+
export async function audit(root, {
|
|
17
|
+
target, scope, baseUrl, refDate, viewport = null,
|
|
18
|
+
maxPages, timeBudgetSeconds, fetcher, concurrency = 1,
|
|
19
|
+
} = {}) {
|
|
20
|
+
const ctx = await buildContext(root, {
|
|
21
|
+
target, baseUrl, refDate, viewport, maxPages, timeBudgetSeconds, fetcher, concurrency,
|
|
22
|
+
});
|
|
17
23
|
const detectors = selectDetectors({ scope });
|
|
18
24
|
|
|
19
25
|
const run = createRun(root, {
|
|
@@ -36,10 +42,32 @@ export async function audit(root, { target, scope, baseUrl, refDate, viewport =
|
|
|
36
42
|
if (ctx.site?.fetchErrors?.length) {
|
|
37
43
|
run.manifest.errors.push(...ctx.site.fetchErrors);
|
|
38
44
|
}
|
|
39
|
-
if (ctx.site?.crawl?.
|
|
45
|
+
if (ctx.site?.crawl?.stopReason === 'page_budget_exhausted') {
|
|
40
46
|
run.manifest.incomplete_checks.push(
|
|
41
47
|
`URL collection reached the ${ctx.site.crawl.maxPages}-page limit with ${ctx.site.crawl.pendingUrlCount} discovered URL(s) pending; sitemap absence checks are incomplete.`
|
|
42
48
|
);
|
|
49
|
+
} else if (ctx.site?.crawl?.stopReason === 'time_budget_exhausted') {
|
|
50
|
+
run.manifest.incomplete_checks.push(
|
|
51
|
+
`URL collection reached the ${ctx.site.crawl.timeBudgetSeconds}-second time budget; sitemap absence checks are incomplete.`
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Establish and persist the collection contract before detectors execute.
|
|
56
|
+
// Detectors receive this exact provisional evidence envelope through ctx so
|
|
57
|
+
// they cannot infer completeness from page-array length or legacy crawl data.
|
|
58
|
+
let coverage = null;
|
|
59
|
+
if (ctx.site?.previewCoverage) {
|
|
60
|
+
try {
|
|
61
|
+
coverage = ctx.site.previewCoverage();
|
|
62
|
+
run.manifest.coverage_status = coverage.coverage_status;
|
|
63
|
+
run.writeArtifact('coverage.json', coverage);
|
|
64
|
+
ctx.coverage = coverage;
|
|
65
|
+
} catch (error) {
|
|
66
|
+
run.manifest.execution_status = 'failed';
|
|
67
|
+
run.manifest.errors.push(`coverage: ${error.message}`);
|
|
68
|
+
run.finalize('failed');
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
43
71
|
}
|
|
44
72
|
|
|
45
73
|
const { findings, detectorsRun, detectorsSkipped, errors } = runDetectors(detectors, ctx);
|
|
@@ -47,6 +75,27 @@ export async function audit(root, { target, scope, baseUrl, refDate, viewport =
|
|
|
47
75
|
run.manifest.detectors_skipped = detectorsSkipped;
|
|
48
76
|
run.manifest.errors.push(...errors);
|
|
49
77
|
|
|
78
|
+
// Seal the ledger after detector evaluation so the same artifact records
|
|
79
|
+
// evaluated resources while retaining the pre-detector persistence proof.
|
|
80
|
+
if (ctx.site?.finalizeCoverage) {
|
|
81
|
+
try {
|
|
82
|
+
coverage = ctx.site.finalizeCoverage({ evaluated: true });
|
|
83
|
+
run.manifest.coverage_status = coverage.coverage_status;
|
|
84
|
+
run.manifest.determination_status = coverage.coverage_status === 'complete' ? 'supported' : 'qualified';
|
|
85
|
+
run.writeArtifact('coverage.json', coverage);
|
|
86
|
+
if (coverage.coverage_status !== 'complete') {
|
|
87
|
+
run.manifest.incomplete_checks.push(
|
|
88
|
+
`Coverage is ${coverage.coverage_status}; conclusions are limited to the successfully observed corpus.`,
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
} catch (error) {
|
|
92
|
+
run.manifest.execution_status = 'failed';
|
|
93
|
+
run.manifest.errors.push(`coverage: ${error.message}`);
|
|
94
|
+
run.finalize('failed');
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
50
99
|
// Validate every finding against the data contract; a contract breach fails the run.
|
|
51
100
|
const invalid = [];
|
|
52
101
|
for (const f of findings) {
|
|
@@ -66,6 +115,7 @@ export async function audit(root, { target, scope, baseUrl, refDate, viewport =
|
|
|
66
115
|
detectorsSkipped,
|
|
67
116
|
promptResults: ctx.promptResults || [],
|
|
68
117
|
targetOrigin: ctx.site?.baseUrl ? new URL(ctx.site.baseUrl).origin : null,
|
|
118
|
+
coverage,
|
|
69
119
|
});
|
|
70
120
|
run.writeArtifact('summary.json', summary);
|
|
71
121
|
run.writeArtifact('inputs.json', {
|
|
@@ -73,6 +123,8 @@ export async function audit(root, { target, scope, baseUrl, refDate, viewport =
|
|
|
73
123
|
registry_counts: Object.fromEntries(Object.entries(ctx.registries).map(([k, v]) => [k, v.entries.length])),
|
|
74
124
|
pages_audited: ctx.site?.pages.length ?? 0,
|
|
75
125
|
crawl_coverage: ctx.site?.crawl ?? null,
|
|
126
|
+
coverage_status: coverage?.coverage_status ?? 'not_applicable',
|
|
127
|
+
coverage_populations: coverage?.populations ?? null,
|
|
76
128
|
});
|
|
77
129
|
run.writeArtifact('environment.json', {
|
|
78
130
|
node: process.version, platform: process.platform, cwd: root,
|
|
@@ -80,9 +132,8 @@ export async function audit(root, { target, scope, baseUrl, refDate, viewport =
|
|
|
80
132
|
});
|
|
81
133
|
if (ctx.site) {
|
|
82
134
|
run.writeArtifact('pages/index.json', ctx.site.pages.map((p) => ({
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
contentHash: ctx.hashPage(p),
|
|
135
|
+
...pageArtifactRecord(p),
|
|
136
|
+
artifact_hash: p.artifact_hash ?? null,
|
|
86
137
|
})));
|
|
87
138
|
if (ctx.site.robotsText != null) run.writeArtifact('robots/robots.txt', ctx.site.robotsText);
|
|
88
139
|
for (const sm of ctx.site.sitemaps) {
|
|
@@ -102,14 +153,26 @@ export async function audit(root, { target, scope, baseUrl, refDate, viewport =
|
|
|
102
153
|
}
|
|
103
154
|
}
|
|
104
155
|
|
|
105
|
-
const report = renderMarkdownReport({ findings, manifest: run.manifest, summary, detectorsSkipped });
|
|
156
|
+
const report = renderMarkdownReport({ findings, manifest: run.manifest, summary, detectorsSkipped, coverage });
|
|
106
157
|
run.writeArtifact('report.md', report);
|
|
107
158
|
|
|
108
159
|
// Update the latest page snapshot for regression/freshness comparison
|
|
109
160
|
if (ctx.site) {
|
|
110
161
|
const snap = { taken_at: run.manifest.timestamp, run_id: run.runId, pages: {} };
|
|
111
162
|
for (const p of ctx.site.pages) {
|
|
112
|
-
snap.pages[p.url] = {
|
|
163
|
+
snap.pages[p.url] = {
|
|
164
|
+
contentHash: p.extracted_text_hash ?? ctx.hashPage(p),
|
|
165
|
+
hash_semantics: 'extracted_text_v1',
|
|
166
|
+
extracted_text_hash: p.extracted_text_hash ?? ctx.hashPage(p),
|
|
167
|
+
response_body_hash: p.response_body_hash ?? null,
|
|
168
|
+
structured_data_hash: p.structured_data_hash ?? null,
|
|
169
|
+
evidence_hash: p.evidence_hash ?? null,
|
|
170
|
+
artifact_hash: p.artifact_hash ?? null,
|
|
171
|
+
resource_id: p.urlIdentity?.resource_id ?? null,
|
|
172
|
+
url_identity: p.urlIdentity ?? null,
|
|
173
|
+
dateModified: extractModified(p),
|
|
174
|
+
status: p.status,
|
|
175
|
+
};
|
|
113
176
|
}
|
|
114
177
|
const snapDir = path.join(root, '.citable', 'snapshots');
|
|
115
178
|
fs.mkdirSync(snapDir, { recursive: true });
|
|
@@ -121,6 +184,10 @@ export async function audit(root, { target, scope, baseUrl, refDate, viewport =
|
|
|
121
184
|
|
|
122
185
|
const status = run.manifest.errors.length ? 'completed_with_warnings'
|
|
123
186
|
: run.manifest.incomplete_checks.length ? 'incomplete' : 'completed';
|
|
187
|
+
// Successful persistence/execution is independent from collection coverage
|
|
188
|
+
// and legacy warning status. A run with fetch warnings can still complete as
|
|
189
|
+
// an execution while its coverage remains indeterminate or truncated.
|
|
190
|
+
run.manifest.execution_status = 'completed';
|
|
124
191
|
const dir = run.finalize(status);
|
|
125
192
|
return { runId: run.runId, dir, findings, summary, manifest: run.manifest, report };
|
|
126
193
|
}
|
|
@@ -33,9 +33,14 @@ jobs:
|
|
|
33
33
|
`;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
export function formatPrReviewComment(findings = []) {
|
|
36
|
+
export function formatPrReviewComment(findings = [], determination = null) {
|
|
37
37
|
if (findings.length === 0) {
|
|
38
|
-
|
|
38
|
+
const status = determination?.determination_status || 'indeterminate';
|
|
39
|
+
if (status !== 'supported') {
|
|
40
|
+
const coverage = determination?.coverage_status ? ` (coverage: ${determination.coverage_status})` : '';
|
|
41
|
+
return `### ⚠️ Citable CRO Sentinel: No determination can be made from the available evidence${coverage}; insufficient evidence for a clean determination. No finding was observed in the evaluated subset; this is not a verified result.`;
|
|
42
|
+
}
|
|
43
|
+
return '### ✅ Citable CRO Sentinel: No findings were observed over the supported evidence scope.';
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
const lines = [
|