@nebulacomponents/citable 1.12.0 → 1.13.1
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 +163 -0
- package/README.md +23 -1
- package/dist/universal/.agents/skills/citable/SKILL.md +12 -1
- package/dist/universal/.agents/skills/citable/VERSION +1 -1
- package/dist/universal/.agents/skills/citable/commands/README.md +2 -1
- package/dist/universal/.agents/skills/citable/commands/artifact-interchange.md +28 -0
- package/dist/universal/.agents/skills/citable/commands/field-validation.md +71 -0
- package/dist/universal/.agents/skills/citable/commands/observe-and-act.md +5 -0
- package/dist/universal/.agents/skills/citable/manifest.json +30 -10
- package/dist/universal/.agents/skills/citable/references/aeo-geo-validation.md +1 -1
- package/dist/universal/.agents/skills/citable/references/capability-boundaries.md +1 -0
- package/dist/universal/.agents/skills/citable/schemas/acceptance-corpus.schema.json +168 -0
- package/dist/universal/.agents/skills/citable/schemas/acceptance-run-context.schema.json +17 -0
- package/dist/universal/.agents/skills/citable/schemas/acceptance-run-receipt.schema.json +88 -0
- package/dist/universal/.agents/skills/citable/schemas/artifact-interchange.schema.json +58 -0
- package/dist/universal/.agents/skills/citable/schemas/assumption.schema.json +119 -0
- package/dist/universal/.agents/skills/citable/schemas/browser-evidence-plan.schema.json +76 -0
- package/dist/universal/.agents/skills/citable/schemas/corpus-publication-receipt.schema.json +24 -0
- package/dist/universal/.agents/skills/citable/schemas/customer-outcome.schema.json +119 -0
- package/dist/universal/.agents/skills/citable/schemas/decision.schema.json +154 -0
- package/dist/universal/.agents/skills/citable/schemas/deployment-receipt.schema.json +51 -0
- package/dist/universal/.agents/skills/citable/schemas/field-validation-metrics.schema.json +15 -0
- package/dist/universal/.agents/skills/citable/schemas/initiative.schema.json +185 -0
- package/dist/universal/.agents/skills/citable/schemas/kpi.schema.json +108 -0
- package/dist/universal/.agents/skills/citable/schemas/observation.schema.json +1 -1
- package/dist/universal/.agents/skills/citable/schemas/release-manifest.schema.json +74 -0
- package/dist/universal/.agents/skills/citable/schemas/release-state.schema.json +40 -0
- package/dist/universal/.agents/skills/citable/schemas/risk.schema.json +172 -0
- package/dist/universal/.agents/skills/citable/schemas/scenario.schema.json +165 -0
- package/dist/universal/.agents/skills/citable/schemas/variance.schema.json +112 -0
- package/dist/universal/.claude/skills/citable/SKILL.md +12 -1
- package/dist/universal/.claude/skills/citable/VERSION +1 -1
- package/dist/universal/.claude/skills/citable/commands/README.md +2 -1
- package/dist/universal/.claude/skills/citable/commands/artifact-interchange.md +28 -0
- package/dist/universal/.claude/skills/citable/commands/field-validation.md +71 -0
- package/dist/universal/.claude/skills/citable/commands/observe-and-act.md +5 -0
- package/dist/universal/.claude/skills/citable/manifest.json +30 -10
- package/dist/universal/.claude/skills/citable/references/aeo-geo-validation.md +1 -1
- package/dist/universal/.claude/skills/citable/references/capability-boundaries.md +1 -0
- package/dist/universal/.claude/skills/citable/schemas/acceptance-corpus.schema.json +168 -0
- package/dist/universal/.claude/skills/citable/schemas/acceptance-run-context.schema.json +17 -0
- package/dist/universal/.claude/skills/citable/schemas/acceptance-run-receipt.schema.json +88 -0
- package/dist/universal/.claude/skills/citable/schemas/artifact-interchange.schema.json +58 -0
- package/dist/universal/.claude/skills/citable/schemas/assumption.schema.json +119 -0
- package/dist/universal/.claude/skills/citable/schemas/browser-evidence-plan.schema.json +76 -0
- package/dist/universal/.claude/skills/citable/schemas/corpus-publication-receipt.schema.json +24 -0
- package/dist/universal/.claude/skills/citable/schemas/customer-outcome.schema.json +119 -0
- package/dist/universal/.claude/skills/citable/schemas/decision.schema.json +154 -0
- package/dist/universal/.claude/skills/citable/schemas/deployment-receipt.schema.json +51 -0
- package/dist/universal/.claude/skills/citable/schemas/field-validation-metrics.schema.json +15 -0
- package/dist/universal/.claude/skills/citable/schemas/initiative.schema.json +185 -0
- package/dist/universal/.claude/skills/citable/schemas/kpi.schema.json +108 -0
- package/dist/universal/.claude/skills/citable/schemas/observation.schema.json +1 -1
- package/dist/universal/.claude/skills/citable/schemas/release-manifest.schema.json +74 -0
- package/dist/universal/.claude/skills/citable/schemas/release-state.schema.json +40 -0
- package/dist/universal/.claude/skills/citable/schemas/risk.schema.json +172 -0
- package/dist/universal/.claude/skills/citable/schemas/scenario.schema.json +165 -0
- package/dist/universal/.claude/skills/citable/schemas/variance.schema.json +112 -0
- package/dist/universal/.cursor/skills/citable/SKILL.md +12 -1
- package/dist/universal/.cursor/skills/citable/VERSION +1 -1
- package/dist/universal/.cursor/skills/citable/commands/README.md +2 -1
- package/dist/universal/.cursor/skills/citable/commands/artifact-interchange.md +28 -0
- package/dist/universal/.cursor/skills/citable/commands/field-validation.md +71 -0
- package/dist/universal/.cursor/skills/citable/commands/observe-and-act.md +5 -0
- package/dist/universal/.cursor/skills/citable/manifest.json +30 -10
- package/dist/universal/.cursor/skills/citable/references/aeo-geo-validation.md +1 -1
- package/dist/universal/.cursor/skills/citable/references/capability-boundaries.md +1 -0
- package/dist/universal/.cursor/skills/citable/schemas/acceptance-corpus.schema.json +168 -0
- package/dist/universal/.cursor/skills/citable/schemas/acceptance-run-context.schema.json +17 -0
- package/dist/universal/.cursor/skills/citable/schemas/acceptance-run-receipt.schema.json +88 -0
- package/dist/universal/.cursor/skills/citable/schemas/artifact-interchange.schema.json +58 -0
- package/dist/universal/.cursor/skills/citable/schemas/assumption.schema.json +119 -0
- package/dist/universal/.cursor/skills/citable/schemas/browser-evidence-plan.schema.json +76 -0
- package/dist/universal/.cursor/skills/citable/schemas/corpus-publication-receipt.schema.json +24 -0
- package/dist/universal/.cursor/skills/citable/schemas/customer-outcome.schema.json +119 -0
- package/dist/universal/.cursor/skills/citable/schemas/decision.schema.json +154 -0
- package/dist/universal/.cursor/skills/citable/schemas/deployment-receipt.schema.json +51 -0
- package/dist/universal/.cursor/skills/citable/schemas/field-validation-metrics.schema.json +15 -0
- package/dist/universal/.cursor/skills/citable/schemas/initiative.schema.json +185 -0
- package/dist/universal/.cursor/skills/citable/schemas/kpi.schema.json +108 -0
- package/dist/universal/.cursor/skills/citable/schemas/observation.schema.json +1 -1
- package/dist/universal/.cursor/skills/citable/schemas/release-manifest.schema.json +74 -0
- package/dist/universal/.cursor/skills/citable/schemas/release-state.schema.json +40 -0
- package/dist/universal/.cursor/skills/citable/schemas/risk.schema.json +172 -0
- package/dist/universal/.cursor/skills/citable/schemas/scenario.schema.json +165 -0
- package/dist/universal/.cursor/skills/citable/schemas/variance.schema.json +112 -0
- package/dist/universal/.gemini/skills/citable/SKILL.md +12 -1
- package/dist/universal/.gemini/skills/citable/VERSION +1 -1
- package/dist/universal/.gemini/skills/citable/commands/README.md +2 -1
- package/dist/universal/.gemini/skills/citable/commands/artifact-interchange.md +28 -0
- package/dist/universal/.gemini/skills/citable/commands/field-validation.md +71 -0
- package/dist/universal/.gemini/skills/citable/commands/observe-and-act.md +5 -0
- package/dist/universal/.gemini/skills/citable/manifest.json +30 -10
- package/dist/universal/.gemini/skills/citable/references/aeo-geo-validation.md +1 -1
- package/dist/universal/.gemini/skills/citable/references/capability-boundaries.md +1 -0
- package/dist/universal/.gemini/skills/citable/schemas/acceptance-corpus.schema.json +168 -0
- package/dist/universal/.gemini/skills/citable/schemas/acceptance-run-context.schema.json +17 -0
- package/dist/universal/.gemini/skills/citable/schemas/acceptance-run-receipt.schema.json +88 -0
- package/dist/universal/.gemini/skills/citable/schemas/artifact-interchange.schema.json +58 -0
- package/dist/universal/.gemini/skills/citable/schemas/assumption.schema.json +119 -0
- package/dist/universal/.gemini/skills/citable/schemas/browser-evidence-plan.schema.json +76 -0
- package/dist/universal/.gemini/skills/citable/schemas/corpus-publication-receipt.schema.json +24 -0
- package/dist/universal/.gemini/skills/citable/schemas/customer-outcome.schema.json +119 -0
- package/dist/universal/.gemini/skills/citable/schemas/decision.schema.json +154 -0
- package/dist/universal/.gemini/skills/citable/schemas/deployment-receipt.schema.json +51 -0
- package/dist/universal/.gemini/skills/citable/schemas/field-validation-metrics.schema.json +15 -0
- package/dist/universal/.gemini/skills/citable/schemas/initiative.schema.json +185 -0
- package/dist/universal/.gemini/skills/citable/schemas/kpi.schema.json +108 -0
- package/dist/universal/.gemini/skills/citable/schemas/observation.schema.json +1 -1
- package/dist/universal/.gemini/skills/citable/schemas/release-manifest.schema.json +74 -0
- package/dist/universal/.gemini/skills/citable/schemas/release-state.schema.json +40 -0
- package/dist/universal/.gemini/skills/citable/schemas/risk.schema.json +172 -0
- package/dist/universal/.gemini/skills/citable/schemas/scenario.schema.json +165 -0
- package/dist/universal/.gemini/skills/citable/schemas/variance.schema.json +112 -0
- package/dist/universal/.github/skills/citable/SKILL.md +12 -1
- package/dist/universal/.github/skills/citable/VERSION +1 -1
- package/dist/universal/.github/skills/citable/commands/README.md +2 -1
- package/dist/universal/.github/skills/citable/commands/artifact-interchange.md +28 -0
- package/dist/universal/.github/skills/citable/commands/field-validation.md +71 -0
- package/dist/universal/.github/skills/citable/commands/observe-and-act.md +5 -0
- package/dist/universal/.github/skills/citable/manifest.json +30 -10
- package/dist/universal/.github/skills/citable/references/aeo-geo-validation.md +1 -1
- package/dist/universal/.github/skills/citable/references/capability-boundaries.md +1 -0
- package/dist/universal/.github/skills/citable/schemas/acceptance-corpus.schema.json +168 -0
- package/dist/universal/.github/skills/citable/schemas/acceptance-run-context.schema.json +17 -0
- package/dist/universal/.github/skills/citable/schemas/acceptance-run-receipt.schema.json +88 -0
- package/dist/universal/.github/skills/citable/schemas/artifact-interchange.schema.json +58 -0
- package/dist/universal/.github/skills/citable/schemas/assumption.schema.json +119 -0
- package/dist/universal/.github/skills/citable/schemas/browser-evidence-plan.schema.json +76 -0
- package/dist/universal/.github/skills/citable/schemas/corpus-publication-receipt.schema.json +24 -0
- package/dist/universal/.github/skills/citable/schemas/customer-outcome.schema.json +119 -0
- package/dist/universal/.github/skills/citable/schemas/decision.schema.json +154 -0
- package/dist/universal/.github/skills/citable/schemas/deployment-receipt.schema.json +51 -0
- package/dist/universal/.github/skills/citable/schemas/field-validation-metrics.schema.json +15 -0
- package/dist/universal/.github/skills/citable/schemas/initiative.schema.json +185 -0
- package/dist/universal/.github/skills/citable/schemas/kpi.schema.json +108 -0
- package/dist/universal/.github/skills/citable/schemas/observation.schema.json +1 -1
- package/dist/universal/.github/skills/citable/schemas/release-manifest.schema.json +74 -0
- package/dist/universal/.github/skills/citable/schemas/release-state.schema.json +40 -0
- package/dist/universal/.github/skills/citable/schemas/risk.schema.json +172 -0
- package/dist/universal/.github/skills/citable/schemas/scenario.schema.json +165 -0
- package/dist/universal/.github/skills/citable/schemas/variance.schema.json +112 -0
- package/dist/universal/.kiro/skills/citable/SKILL.md +12 -1
- package/dist/universal/.kiro/skills/citable/VERSION +1 -1
- package/dist/universal/.kiro/skills/citable/commands/README.md +2 -1
- package/dist/universal/.kiro/skills/citable/commands/artifact-interchange.md +28 -0
- package/dist/universal/.kiro/skills/citable/commands/field-validation.md +71 -0
- package/dist/universal/.kiro/skills/citable/commands/observe-and-act.md +5 -0
- package/dist/universal/.kiro/skills/citable/manifest.json +30 -10
- package/dist/universal/.kiro/skills/citable/references/aeo-geo-validation.md +1 -1
- package/dist/universal/.kiro/skills/citable/references/capability-boundaries.md +1 -0
- package/dist/universal/.kiro/skills/citable/schemas/acceptance-corpus.schema.json +168 -0
- package/dist/universal/.kiro/skills/citable/schemas/acceptance-run-context.schema.json +17 -0
- package/dist/universal/.kiro/skills/citable/schemas/acceptance-run-receipt.schema.json +88 -0
- package/dist/universal/.kiro/skills/citable/schemas/artifact-interchange.schema.json +58 -0
- package/dist/universal/.kiro/skills/citable/schemas/assumption.schema.json +119 -0
- package/dist/universal/.kiro/skills/citable/schemas/browser-evidence-plan.schema.json +76 -0
- package/dist/universal/.kiro/skills/citable/schemas/corpus-publication-receipt.schema.json +24 -0
- package/dist/universal/.kiro/skills/citable/schemas/customer-outcome.schema.json +119 -0
- package/dist/universal/.kiro/skills/citable/schemas/decision.schema.json +154 -0
- package/dist/universal/.kiro/skills/citable/schemas/deployment-receipt.schema.json +51 -0
- package/dist/universal/.kiro/skills/citable/schemas/field-validation-metrics.schema.json +15 -0
- package/dist/universal/.kiro/skills/citable/schemas/initiative.schema.json +185 -0
- package/dist/universal/.kiro/skills/citable/schemas/kpi.schema.json +108 -0
- package/dist/universal/.kiro/skills/citable/schemas/observation.schema.json +1 -1
- package/dist/universal/.kiro/skills/citable/schemas/release-manifest.schema.json +74 -0
- package/dist/universal/.kiro/skills/citable/schemas/release-state.schema.json +40 -0
- package/dist/universal/.kiro/skills/citable/schemas/risk.schema.json +172 -0
- package/dist/universal/.kiro/skills/citable/schemas/scenario.schema.json +165 -0
- package/dist/universal/.kiro/skills/citable/schemas/variance.schema.json +112 -0
- package/dist/universal/.opencode/skills/citable/SKILL.md +12 -1
- package/dist/universal/.opencode/skills/citable/VERSION +1 -1
- package/dist/universal/.opencode/skills/citable/commands/README.md +2 -1
- package/dist/universal/.opencode/skills/citable/commands/artifact-interchange.md +28 -0
- package/dist/universal/.opencode/skills/citable/commands/field-validation.md +71 -0
- package/dist/universal/.opencode/skills/citable/commands/observe-and-act.md +5 -0
- package/dist/universal/.opencode/skills/citable/manifest.json +30 -10
- package/dist/universal/.opencode/skills/citable/references/aeo-geo-validation.md +1 -1
- package/dist/universal/.opencode/skills/citable/references/capability-boundaries.md +1 -0
- package/dist/universal/.opencode/skills/citable/schemas/acceptance-corpus.schema.json +168 -0
- package/dist/universal/.opencode/skills/citable/schemas/acceptance-run-context.schema.json +17 -0
- package/dist/universal/.opencode/skills/citable/schemas/acceptance-run-receipt.schema.json +88 -0
- package/dist/universal/.opencode/skills/citable/schemas/artifact-interchange.schema.json +58 -0
- package/dist/universal/.opencode/skills/citable/schemas/assumption.schema.json +119 -0
- package/dist/universal/.opencode/skills/citable/schemas/browser-evidence-plan.schema.json +76 -0
- package/dist/universal/.opencode/skills/citable/schemas/corpus-publication-receipt.schema.json +24 -0
- package/dist/universal/.opencode/skills/citable/schemas/customer-outcome.schema.json +119 -0
- package/dist/universal/.opencode/skills/citable/schemas/decision.schema.json +154 -0
- package/dist/universal/.opencode/skills/citable/schemas/deployment-receipt.schema.json +51 -0
- package/dist/universal/.opencode/skills/citable/schemas/field-validation-metrics.schema.json +15 -0
- package/dist/universal/.opencode/skills/citable/schemas/initiative.schema.json +185 -0
- package/dist/universal/.opencode/skills/citable/schemas/kpi.schema.json +108 -0
- package/dist/universal/.opencode/skills/citable/schemas/observation.schema.json +1 -1
- package/dist/universal/.opencode/skills/citable/schemas/release-manifest.schema.json +74 -0
- package/dist/universal/.opencode/skills/citable/schemas/release-state.schema.json +40 -0
- package/dist/universal/.opencode/skills/citable/schemas/risk.schema.json +172 -0
- package/dist/universal/.opencode/skills/citable/schemas/scenario.schema.json +165 -0
- package/dist/universal/.opencode/skills/citable/schemas/variance.schema.json +112 -0
- package/dist/universal/.pi/agent/skills/citable/SKILL.md +12 -1
- package/dist/universal/.pi/agent/skills/citable/VERSION +1 -1
- package/dist/universal/.pi/agent/skills/citable/commands/README.md +2 -1
- package/dist/universal/.pi/agent/skills/citable/commands/artifact-interchange.md +28 -0
- package/dist/universal/.pi/agent/skills/citable/commands/field-validation.md +71 -0
- package/dist/universal/.pi/agent/skills/citable/commands/observe-and-act.md +5 -0
- package/dist/universal/.pi/agent/skills/citable/manifest.json +30 -10
- package/dist/universal/.pi/agent/skills/citable/references/aeo-geo-validation.md +1 -1
- package/dist/universal/.pi/agent/skills/citable/references/capability-boundaries.md +1 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/acceptance-corpus.schema.json +168 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/acceptance-run-context.schema.json +17 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/acceptance-run-receipt.schema.json +88 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/artifact-interchange.schema.json +58 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/assumption.schema.json +119 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/browser-evidence-plan.schema.json +76 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/corpus-publication-receipt.schema.json +24 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/customer-outcome.schema.json +119 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/decision.schema.json +154 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/deployment-receipt.schema.json +51 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/field-validation-metrics.schema.json +15 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/initiative.schema.json +185 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/kpi.schema.json +108 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/observation.schema.json +1 -1
- package/dist/universal/.pi/agent/skills/citable/schemas/release-manifest.schema.json +74 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/release-state.schema.json +40 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/risk.schema.json +172 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/scenario.schema.json +165 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/variance.schema.json +112 -0
- package/dist/universal/.qoder/skills/citable/SKILL.md +12 -1
- package/dist/universal/.qoder/skills/citable/VERSION +1 -1
- package/dist/universal/.qoder/skills/citable/commands/README.md +2 -1
- package/dist/universal/.qoder/skills/citable/commands/artifact-interchange.md +28 -0
- package/dist/universal/.qoder/skills/citable/commands/field-validation.md +71 -0
- package/dist/universal/.qoder/skills/citable/commands/observe-and-act.md +5 -0
- package/dist/universal/.qoder/skills/citable/manifest.json +30 -10
- package/dist/universal/.qoder/skills/citable/references/aeo-geo-validation.md +1 -1
- package/dist/universal/.qoder/skills/citable/references/capability-boundaries.md +1 -0
- package/dist/universal/.qoder/skills/citable/schemas/acceptance-corpus.schema.json +168 -0
- package/dist/universal/.qoder/skills/citable/schemas/acceptance-run-context.schema.json +17 -0
- package/dist/universal/.qoder/skills/citable/schemas/acceptance-run-receipt.schema.json +88 -0
- package/dist/universal/.qoder/skills/citable/schemas/artifact-interchange.schema.json +58 -0
- package/dist/universal/.qoder/skills/citable/schemas/assumption.schema.json +119 -0
- package/dist/universal/.qoder/skills/citable/schemas/browser-evidence-plan.schema.json +76 -0
- package/dist/universal/.qoder/skills/citable/schemas/corpus-publication-receipt.schema.json +24 -0
- package/dist/universal/.qoder/skills/citable/schemas/customer-outcome.schema.json +119 -0
- package/dist/universal/.qoder/skills/citable/schemas/decision.schema.json +154 -0
- package/dist/universal/.qoder/skills/citable/schemas/deployment-receipt.schema.json +51 -0
- package/dist/universal/.qoder/skills/citable/schemas/field-validation-metrics.schema.json +15 -0
- package/dist/universal/.qoder/skills/citable/schemas/initiative.schema.json +185 -0
- package/dist/universal/.qoder/skills/citable/schemas/kpi.schema.json +108 -0
- package/dist/universal/.qoder/skills/citable/schemas/observation.schema.json +1 -1
- package/dist/universal/.qoder/skills/citable/schemas/release-manifest.schema.json +74 -0
- package/dist/universal/.qoder/skills/citable/schemas/release-state.schema.json +40 -0
- package/dist/universal/.qoder/skills/citable/schemas/risk.schema.json +172 -0
- package/dist/universal/.qoder/skills/citable/schemas/scenario.schema.json +165 -0
- package/dist/universal/.qoder/skills/citable/schemas/variance.schema.json +112 -0
- package/dist/universal/.rovodev/skills/citable/SKILL.md +12 -1
- package/dist/universal/.rovodev/skills/citable/VERSION +1 -1
- package/dist/universal/.rovodev/skills/citable/commands/README.md +2 -1
- package/dist/universal/.rovodev/skills/citable/commands/artifact-interchange.md +28 -0
- package/dist/universal/.rovodev/skills/citable/commands/field-validation.md +71 -0
- package/dist/universal/.rovodev/skills/citable/commands/observe-and-act.md +5 -0
- package/dist/universal/.rovodev/skills/citable/manifest.json +30 -10
- package/dist/universal/.rovodev/skills/citable/references/aeo-geo-validation.md +1 -1
- package/dist/universal/.rovodev/skills/citable/references/capability-boundaries.md +1 -0
- package/dist/universal/.rovodev/skills/citable/schemas/acceptance-corpus.schema.json +168 -0
- package/dist/universal/.rovodev/skills/citable/schemas/acceptance-run-context.schema.json +17 -0
- package/dist/universal/.rovodev/skills/citable/schemas/acceptance-run-receipt.schema.json +88 -0
- package/dist/universal/.rovodev/skills/citable/schemas/artifact-interchange.schema.json +58 -0
- package/dist/universal/.rovodev/skills/citable/schemas/assumption.schema.json +119 -0
- package/dist/universal/.rovodev/skills/citable/schemas/browser-evidence-plan.schema.json +76 -0
- package/dist/universal/.rovodev/skills/citable/schemas/corpus-publication-receipt.schema.json +24 -0
- package/dist/universal/.rovodev/skills/citable/schemas/customer-outcome.schema.json +119 -0
- package/dist/universal/.rovodev/skills/citable/schemas/decision.schema.json +154 -0
- package/dist/universal/.rovodev/skills/citable/schemas/deployment-receipt.schema.json +51 -0
- package/dist/universal/.rovodev/skills/citable/schemas/field-validation-metrics.schema.json +15 -0
- package/dist/universal/.rovodev/skills/citable/schemas/initiative.schema.json +185 -0
- package/dist/universal/.rovodev/skills/citable/schemas/kpi.schema.json +108 -0
- package/dist/universal/.rovodev/skills/citable/schemas/observation.schema.json +1 -1
- package/dist/universal/.rovodev/skills/citable/schemas/release-manifest.schema.json +74 -0
- package/dist/universal/.rovodev/skills/citable/schemas/release-state.schema.json +40 -0
- package/dist/universal/.rovodev/skills/citable/schemas/risk.schema.json +172 -0
- package/dist/universal/.rovodev/skills/citable/schemas/scenario.schema.json +165 -0
- package/dist/universal/.rovodev/skills/citable/schemas/variance.schema.json +112 -0
- package/dist/universal/.trae/skills/citable/SKILL.md +12 -1
- package/dist/universal/.trae/skills/citable/VERSION +1 -1
- package/dist/universal/.trae/skills/citable/commands/README.md +2 -1
- package/dist/universal/.trae/skills/citable/commands/artifact-interchange.md +28 -0
- package/dist/universal/.trae/skills/citable/commands/field-validation.md +71 -0
- package/dist/universal/.trae/skills/citable/commands/observe-and-act.md +5 -0
- package/dist/universal/.trae/skills/citable/manifest.json +30 -10
- package/dist/universal/.trae/skills/citable/references/aeo-geo-validation.md +1 -1
- package/dist/universal/.trae/skills/citable/references/capability-boundaries.md +1 -0
- package/dist/universal/.trae/skills/citable/schemas/acceptance-corpus.schema.json +168 -0
- package/dist/universal/.trae/skills/citable/schemas/acceptance-run-context.schema.json +17 -0
- package/dist/universal/.trae/skills/citable/schemas/acceptance-run-receipt.schema.json +88 -0
- package/dist/universal/.trae/skills/citable/schemas/artifact-interchange.schema.json +58 -0
- package/dist/universal/.trae/skills/citable/schemas/assumption.schema.json +119 -0
- package/dist/universal/.trae/skills/citable/schemas/browser-evidence-plan.schema.json +76 -0
- package/dist/universal/.trae/skills/citable/schemas/corpus-publication-receipt.schema.json +24 -0
- package/dist/universal/.trae/skills/citable/schemas/customer-outcome.schema.json +119 -0
- package/dist/universal/.trae/skills/citable/schemas/decision.schema.json +154 -0
- package/dist/universal/.trae/skills/citable/schemas/deployment-receipt.schema.json +51 -0
- package/dist/universal/.trae/skills/citable/schemas/field-validation-metrics.schema.json +15 -0
- package/dist/universal/.trae/skills/citable/schemas/initiative.schema.json +185 -0
- package/dist/universal/.trae/skills/citable/schemas/kpi.schema.json +108 -0
- package/dist/universal/.trae/skills/citable/schemas/observation.schema.json +1 -1
- package/dist/universal/.trae/skills/citable/schemas/release-manifest.schema.json +74 -0
- package/dist/universal/.trae/skills/citable/schemas/release-state.schema.json +40 -0
- package/dist/universal/.trae/skills/citable/schemas/risk.schema.json +172 -0
- package/dist/universal/.trae/skills/citable/schemas/scenario.schema.json +165 -0
- package/dist/universal/.trae/skills/citable/schemas/variance.schema.json +112 -0
- package/dist/universal/.trae-cn/skills/citable/SKILL.md +12 -1
- package/dist/universal/.trae-cn/skills/citable/VERSION +1 -1
- package/dist/universal/.trae-cn/skills/citable/commands/README.md +2 -1
- package/dist/universal/.trae-cn/skills/citable/commands/artifact-interchange.md +28 -0
- package/dist/universal/.trae-cn/skills/citable/commands/field-validation.md +71 -0
- package/dist/universal/.trae-cn/skills/citable/commands/observe-and-act.md +5 -0
- package/dist/universal/.trae-cn/skills/citable/manifest.json +30 -10
- package/dist/universal/.trae-cn/skills/citable/references/aeo-geo-validation.md +1 -1
- package/dist/universal/.trae-cn/skills/citable/references/capability-boundaries.md +1 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/acceptance-corpus.schema.json +168 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/acceptance-run-context.schema.json +17 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/acceptance-run-receipt.schema.json +88 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/artifact-interchange.schema.json +58 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/assumption.schema.json +119 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/browser-evidence-plan.schema.json +76 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/corpus-publication-receipt.schema.json +24 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/customer-outcome.schema.json +119 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/decision.schema.json +154 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/deployment-receipt.schema.json +51 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/field-validation-metrics.schema.json +15 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/initiative.schema.json +185 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/kpi.schema.json +108 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/observation.schema.json +1 -1
- package/dist/universal/.trae-cn/skills/citable/schemas/release-manifest.schema.json +74 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/release-state.schema.json +40 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/risk.schema.json +172 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/scenario.schema.json +165 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/variance.schema.json +112 -0
- package/dist/universal/manifest.json +363 -123
- package/package.json +4 -1
- package/release/surfaces.json +21 -0
- package/schemas/acceptance-corpus.schema.json +168 -0
- package/schemas/acceptance-run-context.schema.json +17 -0
- package/schemas/acceptance-run-receipt.schema.json +88 -0
- package/schemas/artifact-interchange.schema.json +58 -0
- package/schemas/assumption.schema.json +119 -0
- package/schemas/browser-evidence-plan.schema.json +76 -0
- package/schemas/corpus-publication-receipt.schema.json +24 -0
- package/schemas/customer-outcome.schema.json +119 -0
- package/schemas/decision.schema.json +154 -0
- package/schemas/deployment-receipt.schema.json +51 -0
- package/schemas/field-validation-metrics.schema.json +15 -0
- package/schemas/initiative.schema.json +185 -0
- package/schemas/kpi.schema.json +108 -0
- package/schemas/observation.schema.json +1 -1
- package/schemas/release-manifest.schema.json +74 -0
- package/schemas/release-state.schema.json +40 -0
- package/schemas/risk.schema.json +172 -0
- package/schemas/scenario.schema.json +165 -0
- package/schemas/variance.schema.json +112 -0
- package/scripts/release-governance.js +123 -0
- package/skill/SKILL.md +12 -1
- package/skill/commands/README.md +2 -1
- package/skill/commands/artifact-interchange.md +28 -0
- package/skill/commands/field-validation.md +71 -0
- package/skill/commands/observe-and-act.md +5 -0
- package/skill/references/aeo-geo-validation.md +1 -1
- package/skill/references/capability-boundaries.md +1 -0
- package/src/acceptance/reproducibility.js +180 -0
- package/src/artifacts/interchange.js +179 -0
- package/src/cli/index.js +143 -4
- package/src/commands/assumptionAudit.js +111 -0
- package/src/commands/audit.js +6 -0
- package/src/commands/boardReport.js +251 -0
- package/src/commands/competitiveIntel.js +124 -0
- package/src/commands/corpus.js +322 -0
- package/src/commands/decisionMemo.js +202 -0
- package/src/commands/executive.js +167 -0
- package/src/commands/executiveReview.js +206 -0
- package/src/commands/init.js +14 -1
- package/src/commands/kpi.js +86 -0
- package/src/commands/monitor.js +9 -0
- package/src/commands/observe.js +84 -2
- package/src/commands/outcomes.js +113 -0
- package/src/commands/prioritize.js +108 -0
- package/src/commands/risk.js +104 -0
- package/src/commands/scenario.js +98 -0
- package/src/commands/variance.js +102 -0
- package/src/detectors/framework.js +37 -0
- package/src/detectors/page.js +10 -10
- package/src/detectors/tech.js +5 -3
- package/src/extractor/site.js +21 -6
- package/src/observations/browserJourney.js +167 -0
- package/src/observations/media.js +8 -1
- package/src/registries/index.js +107 -6
- package/src/release/governance.js +331 -0
- package/src/shared/asOf.js +18 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* executive command — Chief-of-Staff Router
|
|
3
|
+
*
|
|
4
|
+
* Routes reporting and decision requests to the correct specialized skill.
|
|
5
|
+
* Built last deliberately — orchestration without strong underlying skills
|
|
6
|
+
* only coordinates weak outputs.
|
|
7
|
+
*
|
|
8
|
+
* Routing table:
|
|
9
|
+
* quarterly reporting → board-report
|
|
10
|
+
* monthly reporting → executive-review
|
|
11
|
+
* bounded decision → decision-memo
|
|
12
|
+
* material uncertainty → scenario
|
|
13
|
+
* risk request → risk
|
|
14
|
+
* metric dispute → kpi
|
|
15
|
+
* commercial premise → assumption-audit
|
|
16
|
+
* customer value question → outcomes
|
|
17
|
+
* roadmap priority → prioritize
|
|
18
|
+
* competitor change → competitive-intel
|
|
19
|
+
*
|
|
20
|
+
* Controls:
|
|
21
|
+
* - Max orchestration depth: 1 (no recursive routing)
|
|
22
|
+
* - Circular-call prevention: command registry checked before dispatch
|
|
23
|
+
* - Explicit conflict surfacing — conflicts not smoothed over
|
|
24
|
+
* - Decision logging to .citable/executive-log.yaml
|
|
25
|
+
*
|
|
26
|
+
* Usage:
|
|
27
|
+
* citable executive <request>
|
|
28
|
+
* citable executive --route <command> Force a specific route
|
|
29
|
+
* citable executive --log Show recent routing decisions
|
|
30
|
+
*/
|
|
31
|
+
import { contextDir } from '../registries/index.js';
|
|
32
|
+
import { readYaml, writeYaml, nowIso } from '../shared/io.js';
|
|
33
|
+
import path from 'node:path';
|
|
34
|
+
import fs from 'node:fs';
|
|
35
|
+
|
|
36
|
+
const ROUTES = [
|
|
37
|
+
{ patterns: [/quarterly|board.pack|board.report/i], command: 'board-report', reason: 'Quarterly board pack' },
|
|
38
|
+
{ patterns: [/monthly|operating.review|exec.review/i], command: 'executive-review', reason: 'Monthly executive operating review' },
|
|
39
|
+
{ patterns: [/decision|decide|approve|memo/i], command: 'decision-memo', reason: 'Bounded decision record' },
|
|
40
|
+
{ patterns: [/scenario|war.room|compound.risk|cascade/i], command: 'scenario', reason: 'Compound risk scenario' },
|
|
41
|
+
{ patterns: [/risk.register|residual.risk|risk.list/i], command: 'risk', reason: 'Risk register' },
|
|
42
|
+
{ patterns: [/kpi|metric.definition|metric.dispute/i], command: 'kpi', reason: 'KPI architecture' },
|
|
43
|
+
{ patterns: [/assumption|premise|still.valid/i], command: 'assumption-audit', reason: 'Assumption validity' },
|
|
44
|
+
{ patterns: [/customer.outcome|customer.value|impact/i], command: 'outcomes', reason: 'Customer outcomes' },
|
|
45
|
+
{ patterns: [/variance|miss|why.did.we/i], command: 'variance', reason: 'Variance analysis' },
|
|
46
|
+
{ patterns: [/prioriti|roadmap|what.to.build|rank/i], command: 'prioritize', reason: 'Initiative prioritization' },
|
|
47
|
+
{ patterns: [/competitor|competitive|market.change/i], command: 'competitive-intel', reason: 'Competitive intelligence' },
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
const MAX_DEPTH = 1;
|
|
51
|
+
let _callDepth = 0;
|
|
52
|
+
|
|
53
|
+
export async function executiveCommand(args, root = process.cwd()) {
|
|
54
|
+
const forceRoute = argVal(args, '--route');
|
|
55
|
+
const showLog = args.includes('--log');
|
|
56
|
+
|
|
57
|
+
if (showLog) return executiveLog(root);
|
|
58
|
+
|
|
59
|
+
if (_callDepth >= MAX_DEPTH) {
|
|
60
|
+
return { error: 'Maximum orchestration depth reached — circular routing prevented' };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const request = args.filter(a => !a.startsWith('--')).join(' ');
|
|
64
|
+
|
|
65
|
+
const route = forceRoute
|
|
66
|
+
? ROUTES.find(r => r.command === forceRoute)
|
|
67
|
+
: resolveRoute(request);
|
|
68
|
+
|
|
69
|
+
if (!route) {
|
|
70
|
+
return {
|
|
71
|
+
unresolved: true,
|
|
72
|
+
request,
|
|
73
|
+
available_commands: ROUTES.map(r => ({ command: r.command, reason: r.reason })),
|
|
74
|
+
message: 'Could not determine the appropriate skill. Use --route <command> to force a route, or run the specific command directly.',
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Log the routing decision
|
|
79
|
+
logDecision(root, { request, routed_to: route.command, reason: route.reason, at: nowIso() });
|
|
80
|
+
|
|
81
|
+
_callDepth++;
|
|
82
|
+
try {
|
|
83
|
+
// Lazy-import to avoid circular deps — commands are imported at call time
|
|
84
|
+
const mod = await import(`./${commandToModule(route.command)}.js`);
|
|
85
|
+
const fn = mod[commandToExport(route.command)];
|
|
86
|
+
if (!fn) {
|
|
87
|
+
return { error: `No handler for command: ${route.command}` };
|
|
88
|
+
}
|
|
89
|
+
const downstreamArgs = args.filter((arg, index) => arg !== '--route' && args[index - 1] !== '--route');
|
|
90
|
+
const result = await fn(downstreamArgs, root);
|
|
91
|
+
return {
|
|
92
|
+
routed_to: route.command,
|
|
93
|
+
reason: route.reason,
|
|
94
|
+
result,
|
|
95
|
+
};
|
|
96
|
+
} finally {
|
|
97
|
+
_callDepth--;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function resolveRoute(request) {
|
|
102
|
+
if (!request) return null;
|
|
103
|
+
for (const route of ROUTES) {
|
|
104
|
+
if (route.patterns.some(p => p.test(request))) return route;
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function commandToModule(cmd) {
|
|
110
|
+
const MAP = {
|
|
111
|
+
'board-report': 'boardReport',
|
|
112
|
+
'executive-review': 'executiveReview',
|
|
113
|
+
'decision-memo': 'decisionMemo',
|
|
114
|
+
'scenario': 'scenario',
|
|
115
|
+
'risk': 'risk',
|
|
116
|
+
'kpi': 'kpi',
|
|
117
|
+
'assumption-audit': 'assumptionAudit',
|
|
118
|
+
'outcomes': 'outcomes',
|
|
119
|
+
'variance': 'variance',
|
|
120
|
+
'prioritize': 'prioritize',
|
|
121
|
+
'competitive-intel': 'competitiveIntel',
|
|
122
|
+
};
|
|
123
|
+
return MAP[cmd] ?? cmd;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function commandToExport(cmd) {
|
|
127
|
+
const MAP = {
|
|
128
|
+
'board-report': 'boardReportCommand',
|
|
129
|
+
'executive-review': 'executiveReviewCommand',
|
|
130
|
+
'decision-memo': 'decisionMemoCommand',
|
|
131
|
+
'scenario': 'scenarioCommand',
|
|
132
|
+
'risk': 'riskCommand',
|
|
133
|
+
'kpi': 'kpiCommand',
|
|
134
|
+
'assumption-audit': 'assumptionAuditCommand',
|
|
135
|
+
'outcomes': 'outcomesCommand',
|
|
136
|
+
'variance': 'varianceCommand',
|
|
137
|
+
'prioritize': 'prioritizeCommand',
|
|
138
|
+
'competitive-intel': 'competitiveIntelCommand',
|
|
139
|
+
};
|
|
140
|
+
return MAP[cmd] ?? cmd + 'Command';
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function logDecision(root, entry) {
|
|
144
|
+
const dir = contextDir(root);
|
|
145
|
+
const logFile = path.join(dir, 'executive-log.yaml');
|
|
146
|
+
let log = { version: 1, kind: 'executive-log', entries: [] };
|
|
147
|
+
if (fs.existsSync(logFile)) {
|
|
148
|
+
try { log = readYaml(logFile) ?? log; } catch {}
|
|
149
|
+
}
|
|
150
|
+
log.entries.push(entry);
|
|
151
|
+
// Keep last 100 entries
|
|
152
|
+
if (log.entries.length > 100) log.entries = log.entries.slice(-100);
|
|
153
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
154
|
+
writeYaml(logFile, { ...log, updated: nowIso() });
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function executiveLog(root) {
|
|
158
|
+
const logFile = path.join(contextDir(root), 'executive-log.yaml');
|
|
159
|
+
if (!fs.existsSync(logFile)) return { log: [], message: 'No routing decisions logged yet.' };
|
|
160
|
+
const log = readYaml(logFile) ?? { entries: [] };
|
|
161
|
+
return { log: (log.entries ?? []).slice(-20) };
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function argVal(args, flag) {
|
|
165
|
+
const i = args.indexOf(flag);
|
|
166
|
+
return i >= 0 ? args[i + 1] : null;
|
|
167
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* executive-review command — Monthly Executive Operating Review
|
|
3
|
+
*
|
|
4
|
+
* Generates an evidence-first operating review. Produces an evidence
|
|
5
|
+
* ledger first, then derives the narrative. Never generates a polished
|
|
6
|
+
* positive summary when data is absent or ungoverned.
|
|
7
|
+
*
|
|
8
|
+
* Four-act invariant (mandatory):
|
|
9
|
+
* 1. Where management said the company would be
|
|
10
|
+
* 2. Where it actually is
|
|
11
|
+
* 3. Why the variance exists
|
|
12
|
+
* 4. What management is doing about it
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* citable executive-review [--period <YYYY-MM>] [--json]
|
|
16
|
+
*/
|
|
17
|
+
import { checkReferentialIntegrity, loadRegistries } from '../registries/index.js';
|
|
18
|
+
import { nowIso } from '../shared/io.js';
|
|
19
|
+
import { validateAgainst } from '../shared/schemaValidator.js';
|
|
20
|
+
import { dateOnly, parseAsOf } from '../shared/asOf.js';
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
/** Filter registry entries to only those that pass schema validation. */
|
|
24
|
+
function validEntries(entries, schemaName) {
|
|
25
|
+
if (!entries?.length) return [];
|
|
26
|
+
return entries.filter(e => {
|
|
27
|
+
const { valid } = validateAgainst(schemaName, { version: 1, kind: schemaName.replace('.schema.json','s'), entries: [e] });
|
|
28
|
+
return valid;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function validReferences(entries, kind, idField, problems) {
|
|
33
|
+
return entries.filter(entry => !problems.some(problem => problem.startsWith(`${kind}/${entry[idField]}:`)));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function executiveReviewCommand(args, root = process.cwd()) {
|
|
37
|
+
const asOf = parseAsOf(args);
|
|
38
|
+
const period = argVal(args, '--period') ?? currentPeriod(asOf);
|
|
39
|
+
const asJson = args.includes('--json');
|
|
40
|
+
|
|
41
|
+
const { registries, problems: regProblems } = loadRegistries(root);
|
|
42
|
+
const refProblems = checkReferentialIntegrity(registries);
|
|
43
|
+
|
|
44
|
+
const report = buildReview(registries, period, [...regProblems, ...refProblems], refProblems);
|
|
45
|
+
report.generated_at = nowIso();
|
|
46
|
+
report.as_of = dateOnly(asOf);
|
|
47
|
+
|
|
48
|
+
return asJson ? report : formatReview(report);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function buildReview(registries, period, regProblems, refProblems) {
|
|
52
|
+
// Filter to schema-valid and referentially valid governed evidence.
|
|
53
|
+
const kpis = validReferences(validEntries(registries.kpis?.entries, 'kpi.schema.json'), 'kpis', 'metric_id', refProblems);
|
|
54
|
+
const validVariances = validReferences(validEntries(registries.variances?.entries, 'variance.schema.json'), 'variances', 'variance_id', refProblems);
|
|
55
|
+
const variances = validVariances.filter(v => v.period === period);
|
|
56
|
+
const outcomes = validReferences(validEntries(registries['customer-outcomes']?.entries, 'customer-outcome.schema.json'), 'customer-outcomes', 'outcome_id', refProblems);
|
|
57
|
+
const risks = validReferences(validEntries(registries.risks?.entries, 'risk.schema.json'), 'risks', 'risk_id', refProblems);
|
|
58
|
+
const decisions = validReferences(validEntries(registries.decisions?.entries, 'decision.schema.json'), 'decisions', 'decision_id', refProblems);
|
|
59
|
+
|
|
60
|
+
const invalidTotal =
|
|
61
|
+
((registries.kpis?.entries?.length ?? 0) - kpis.length) +
|
|
62
|
+
((registries.variances?.entries?.length ?? 0) - validVariances.length) +
|
|
63
|
+
((registries['customer-outcomes']?.entries?.length ?? 0) - outcomes.length) +
|
|
64
|
+
((registries.risks?.entries?.length ?? 0) - risks.length) +
|
|
65
|
+
((registries.decisions?.entries?.length ?? 0) - decisions.length);
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
// Evidence ledger — raw facts before narrative
|
|
69
|
+
const ledger = {
|
|
70
|
+
period,
|
|
71
|
+
governed_metrics: kpis.length,
|
|
72
|
+
variances_this_period: variances.length,
|
|
73
|
+
material_variances: variances.filter(v => ['material','critical'].includes(v.materiality)).length,
|
|
74
|
+
customer_outcomes_total: outcomes.length,
|
|
75
|
+
outcomes_customer_confirmed: outcomes.filter(o => o.customer_confirmed).length,
|
|
76
|
+
outcomes_causal_established: outcomes.filter(o => o.outcome_stage === 'causal_relationship_established').length,
|
|
77
|
+
board_visible_risks: risks.filter(r => r.board_visibility).length,
|
|
78
|
+
critical_risks: risks.filter(r => r.residual_exposure === 'critical').length,
|
|
79
|
+
deteriorating_risks: risks.filter(r => r.trend === 'deteriorating').length,
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// Commercial section
|
|
83
|
+
const commercial = buildSection('commercial', kpis, variances, [
|
|
84
|
+
'ARR','MRR','bookings','pipeline_coverage','win_rate','sales_cycle','customer_concentration',
|
|
85
|
+
]);
|
|
86
|
+
|
|
87
|
+
// Customer section
|
|
88
|
+
const customer = buildSection('customer', kpis, variances, [
|
|
89
|
+
'active_customers','onboarding_time','renewal_risk','findings_acted_upon','unresolved_escalations',
|
|
90
|
+
]);
|
|
91
|
+
|
|
92
|
+
// Product section
|
|
93
|
+
const product = buildSection('product', kpis, variances, [
|
|
94
|
+
'active_properties','audits_run','completed_valid_audits','installation_success','feature_adoption',
|
|
95
|
+
]);
|
|
96
|
+
|
|
97
|
+
// Quality section — Citable-specific
|
|
98
|
+
const quality = buildSection('quality', kpis, variances, [
|
|
99
|
+
'detector_precision','confirmed_false_positives','known_false_negatives','expired_evidence','stale_registries',
|
|
100
|
+
]);
|
|
101
|
+
|
|
102
|
+
// Operations section
|
|
103
|
+
const operations = buildSection('operations', kpis, variances, [
|
|
104
|
+
'failed_runs','incomplete_evidence_packages','crawler_access_failures','release_regressions',
|
|
105
|
+
]);
|
|
106
|
+
|
|
107
|
+
// Management section
|
|
108
|
+
const openDecisions = decisions.filter(d => d.status === 'open');
|
|
109
|
+
const management = {
|
|
110
|
+
open_decisions: openDecisions.length,
|
|
111
|
+
decisions_requiring_action: openDecisions.map(d => ({
|
|
112
|
+
id: d.decision_id, title: d.title, owner: d.owner, deadline: d.deadline,
|
|
113
|
+
})),
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
report_type: 'executive-operating-review',
|
|
118
|
+
period,
|
|
119
|
+
registry_problems: regProblems,
|
|
120
|
+
invalid_entries_excluded: invalidTotal > 0 ? invalidTotal : undefined,
|
|
121
|
+
ledger,
|
|
122
|
+
four_act_required: buildFourActPrompt(variances),
|
|
123
|
+
sections: { commercial, customer, product, quality, operations, management },
|
|
124
|
+
ungoverned_warning: ledger.governed_metrics === 0
|
|
125
|
+
? 'BLOCKED: No governed KPIs. Register metrics with `citable kpi add` before generating narrative.'
|
|
126
|
+
: null,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function buildSection(name, kpis, variances, relevantNames) {
|
|
131
|
+
const sectionKpis = kpis.filter(k =>
|
|
132
|
+
relevantNames.some(n => k.metric_id?.toLowerCase().includes(n.toLowerCase()) || k.name?.toLowerCase().includes(n.toLowerCase()))
|
|
133
|
+
);
|
|
134
|
+
const sectionVariances = variances.filter(v =>
|
|
135
|
+
sectionKpis.some(k => k.metric_id === v.metric_id)
|
|
136
|
+
);
|
|
137
|
+
return {
|
|
138
|
+
section: name,
|
|
139
|
+
governed_metrics: sectionKpis.length,
|
|
140
|
+
variances: sectionVariances.length,
|
|
141
|
+
material_variances: sectionVariances.filter(v => ['material','critical'].includes(v.materiality)).length,
|
|
142
|
+
ungoverned_warning: sectionKpis.length === 0
|
|
143
|
+
? `No governed KPIs for ${name} — narrative cannot be generated from ungoverned data`
|
|
144
|
+
: null,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function buildFourActPrompt(variances) {
|
|
149
|
+
if (variances.length === 0) return { status: 'no_variances_this_period' };
|
|
150
|
+
const material = variances.filter(v => ['material','critical'].includes(v.materiality));
|
|
151
|
+
return {
|
|
152
|
+
status: 'required',
|
|
153
|
+
material_variances: material.length,
|
|
154
|
+
template: {
|
|
155
|
+
act_1: 'Where management said the company would be: [state targets and forecasts from KPI registry]',
|
|
156
|
+
act_2: 'Where it actually is: [state actuals from variance records]',
|
|
157
|
+
act_3: 'Why the variance exists: [state primary_driver from each material variance — vague causes rejected]',
|
|
158
|
+
act_4: 'What management is doing about it: [state management_response from each material variance]',
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function formatReview(report) {
|
|
164
|
+
const lines = [
|
|
165
|
+
`# Executive Operating Review — ${report.period}`,
|
|
166
|
+
`Generated: ${report.generated_at}`,
|
|
167
|
+
'',
|
|
168
|
+
];
|
|
169
|
+
if (report.ungoverned_warning) {
|
|
170
|
+
lines.push(`⛔ ${report.ungoverned_warning}`, '');
|
|
171
|
+
}
|
|
172
|
+
if (report.registry_problems?.length) {
|
|
173
|
+
lines.push(`⚠️ Registry problems (${report.registry_problems.length}):`);
|
|
174
|
+
for (const p of report.registry_problems.slice(0, 5)) lines.push(` ${p}`);
|
|
175
|
+
lines.push('');
|
|
176
|
+
}
|
|
177
|
+
const l = report.ledger;
|
|
178
|
+
lines.push(
|
|
179
|
+
'## Evidence Ledger',
|
|
180
|
+
`- Governed metrics: ${l.governed_metrics}`,
|
|
181
|
+
`- Variances this period: ${l.variances_this_period} (${l.material_variances} material)`,
|
|
182
|
+
`- Customer outcomes: ${l.customer_outcomes_total} (${l.outcomes_customer_confirmed} confirmed, ${l.outcomes_causal_established} causal)`,
|
|
183
|
+
`- Board-visible risks: ${l.board_visible_risks} (${l.critical_risks} critical, ${l.deteriorating_risks} deteriorating)`,
|
|
184
|
+
'',
|
|
185
|
+
'## Four-Act Reporting Requirement',
|
|
186
|
+
);
|
|
187
|
+
const fa = report.four_act_required;
|
|
188
|
+
if (fa.status === 'required') {
|
|
189
|
+
for (const [act, text] of Object.entries(fa.template)) {
|
|
190
|
+
lines.push(`**${act.replace('_',' ').toUpperCase()}:** ${text}`);
|
|
191
|
+
}
|
|
192
|
+
} else {
|
|
193
|
+
lines.push('No variances registered for this period.');
|
|
194
|
+
}
|
|
195
|
+
return lines.join('\n');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function currentPeriod(asOf) {
|
|
199
|
+
const d = asOf ?? new Date();
|
|
200
|
+
return `${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, '0')}`;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function argVal(args, flag) {
|
|
204
|
+
const i = args.indexOf(flag);
|
|
205
|
+
return i >= 0 ? args[i + 1] : null;
|
|
206
|
+
}
|
package/src/commands/init.js
CHANGED
|
@@ -15,6 +15,19 @@ const DEFAULT_CRAWLERS = [
|
|
|
15
15
|
['CRAWLER-CLAUDEBOT', 'ClaudeBot', 'Anthropic', 'model_training'],
|
|
16
16
|
];
|
|
17
17
|
|
|
18
|
+
function hasSchemaSignal(text) {
|
|
19
|
+
if (/application\/ld\+json/i.test(text)) return true;
|
|
20
|
+
for (const match of text.matchAll(/https?:\/\/[^\s"'<>]+/gi)) {
|
|
21
|
+
try {
|
|
22
|
+
const hostname = new URL(match[0]).hostname.toLowerCase();
|
|
23
|
+
if (hostname === 'schema.org' || hostname === 'www.schema.org') return true;
|
|
24
|
+
} catch {
|
|
25
|
+
// Ignore malformed URL-like source text during best-effort project discovery.
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
|
|
18
31
|
function detectFramework(root) {
|
|
19
32
|
const detected = {
|
|
20
33
|
framework: null, rendering_model: null, package_manager: null,
|
|
@@ -47,7 +60,7 @@ function detectFramework(root) {
|
|
|
47
60
|
for (const f of listFiles(root, (p) => /sitemap.*\.(xml|ts|js|mjs)$/.test(p))) detected.sitemap_sources.push(path.relative(root, f));
|
|
48
61
|
for (const f of listFiles(root, (p) => /\.(html|jsx?|tsx?|astro|vue|svelte)$/.test(p)).slice(0, 400)) {
|
|
49
62
|
const text = fs.readFileSync(f, 'utf8');
|
|
50
|
-
if (
|
|
63
|
+
if (hasSchemaSignal(text)) detected.schema_sources.push(path.relative(root, f));
|
|
51
64
|
if (/gtag\(|googletagmanager|plausible|posthog|umami|matomo/i.test(text)) detected.analytics.push(path.relative(root, f));
|
|
52
65
|
}
|
|
53
66
|
if (detected.rendering_model === null) unresolved.push('Rendering model could not be determined from manifests.');
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kpi command — KPI Architecture registry management
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* citable kpi list List all governed metrics
|
|
6
|
+
* citable kpi show <id> Show a single KPI
|
|
7
|
+
* citable kpi validate Validate all KPI records
|
|
8
|
+
*/
|
|
9
|
+
import { loadRegistries, contextDir } from '../registries/index.js';
|
|
10
|
+
import { readYaml, writeYaml, nowIso } from '../shared/io.js';
|
|
11
|
+
import { validateAgainst } from '../shared/schemaValidator.js';
|
|
12
|
+
import path from 'node:path';
|
|
13
|
+
import fs from 'node:fs';
|
|
14
|
+
|
|
15
|
+
const REQUIRED_COMPARISON = true; // every KPI must have a comparison basis
|
|
16
|
+
|
|
17
|
+
export async function kpiCommand(args, root = process.cwd()) {
|
|
18
|
+
const [subcommand, ...rest] = args;
|
|
19
|
+
const dir = contextDir(root);
|
|
20
|
+
const file = path.join(dir, 'kpis.yaml');
|
|
21
|
+
|
|
22
|
+
switch (subcommand) {
|
|
23
|
+
case 'list': return kpiList(file);
|
|
24
|
+
case 'show': return kpiShow(file, rest[0]);
|
|
25
|
+
case 'validate': return kpiValidate(file);
|
|
26
|
+
case 'add': return { error: '`citable kpi add` is not yet implemented; edit kpis.yaml directly and run `citable kpi validate`' };
|
|
27
|
+
default:
|
|
28
|
+
return kpiList(file);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function loadKpis(file) {
|
|
33
|
+
if (!fs.existsSync(file)) return { version: 1, kind: 'kpis', entries: [] };
|
|
34
|
+
return readYaml(file) ?? { version: 1, kind: 'kpis', entries: [] };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function kpiList(file) {
|
|
38
|
+
const data = loadKpis(file);
|
|
39
|
+
if (!data.entries.length) return { kpis: [], message: 'No KPIs registered. Edit .citable/kpis.yaml, then run `citable kpi validate`.' };
|
|
40
|
+
return {
|
|
41
|
+
kpis: data.entries.map(k => ({
|
|
42
|
+
metric_id: k.metric_id,
|
|
43
|
+
name: k.name,
|
|
44
|
+
owner: k.owner,
|
|
45
|
+
cadence: k.reporting_cadence,
|
|
46
|
+
target: k.target ?? 'NOT SET',
|
|
47
|
+
comparison_required: k.comparison_required ?? REQUIRED_COMPARISON,
|
|
48
|
+
limitations: (k.known_limitations ?? []).length,
|
|
49
|
+
})),
|
|
50
|
+
total: data.entries.length,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function kpiShow(file, id) {
|
|
55
|
+
if (!id) return { error: 'metric_id required' };
|
|
56
|
+
const data = loadKpis(file);
|
|
57
|
+
const kpi = data.entries.find(k => k.metric_id === id);
|
|
58
|
+
if (!kpi) return { error: `KPI not found: ${id}` };
|
|
59
|
+
return { kpi };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function kpiValidate(file) {
|
|
63
|
+
const data = loadKpis(file);
|
|
64
|
+
const problems = [];
|
|
65
|
+
const { valid, errors } = validateAgainst('kpi.schema.json', data);
|
|
66
|
+
if (!valid) problems.push(...errors);
|
|
67
|
+
// Citable-specific checks
|
|
68
|
+
for (const k of data.entries) {
|
|
69
|
+
if (!k.known_limitations || k.known_limitations.length === 0)
|
|
70
|
+
problems.push(`${k.metric_id}: known_limitations is empty — every metric must document its measurement constraints`);
|
|
71
|
+
if (k.comparison_required !== false && !k.comparison_basis)
|
|
72
|
+
problems.push(`${k.metric_id}: comparison_basis required when comparison_required is true`);
|
|
73
|
+
if (!k.restatement_policy)
|
|
74
|
+
problems.push(`${k.metric_id}: restatement_policy missing — how will historical data be corrected?`);
|
|
75
|
+
// Citable metric distinction checks
|
|
76
|
+
if (/installs?/i.test(k.name) && !/active/i.test(k.name))
|
|
77
|
+
problems.push(`${k.metric_id}: "installs" vs "active_installations" must be distinct metrics`);
|
|
78
|
+
if (/audit/i.test(k.name) && !/valid|complete/i.test(k.executive_definition ?? ''))
|
|
79
|
+
problems.push(`${k.metric_id}: audits_run vs completed_valid_audits must be distinguished in executive_definition`);
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
valid: problems.length === 0,
|
|
83
|
+
problems,
|
|
84
|
+
checked: data.entries.length,
|
|
85
|
+
};
|
|
86
|
+
}
|
package/src/commands/monitor.js
CHANGED
|
@@ -11,6 +11,7 @@ function observations(dir) {
|
|
|
11
11
|
function key(item) {
|
|
12
12
|
const d = item.data || {};
|
|
13
13
|
if (item.kind === 'citation') return [item.kind, d.provider, d.product_mode, d.prompt_id, d.run_index].join(':');
|
|
14
|
+
if (item.kind === 'representation_drift') return [item.kind, d.manifest_hash, d.surface_id, d.retrieval_path, d.region, d.request_identity].join(':');
|
|
14
15
|
return [item.kind, d.url || d.citation_url || d.prompt_id || d.timestamp || item.observation_id].join(':');
|
|
15
16
|
}
|
|
16
17
|
|
|
@@ -30,6 +31,14 @@ export function monitor(root, { runA, runB } = {}) {
|
|
|
30
31
|
if (current.kind === 'index' && previous?.data?.indexed === true && current.data.indexed === false) alerts.push({ severity: 'high', type: 'index_loss', key: k });
|
|
31
32
|
if (current.kind === 'canonical_freshness' && previous?.data?.canonical_consensus === true && current.data.canonical_consensus === false) alerts.push({ severity: 'high', type: 'canonical_regression', key: k });
|
|
32
33
|
if (current.kind === 'citation' && previous?.data?.property_cited === true && current.data.property_cited === false) alerts.push({ severity: 'medium', type: 'citation_presence_change', key: k });
|
|
34
|
+
if (current.kind === 'representation_drift' && previous) {
|
|
35
|
+
const from = previous.data.representation_state, to = current.data.representation_state;
|
|
36
|
+
if (from !== 'divergent' && to === 'divergent') alerts.push({ severity: 'high', type: 'representation_divergence_observed', key: k, previous_state: from, current_state: to, authority: 'external_unverified', gates_release_finalization: false });
|
|
37
|
+
if (from === 'divergent' && to === 'consistent') {
|
|
38
|
+
const duration = new Date(current.collected_at) - new Date(previous.collected_at);
|
|
39
|
+
alerts.push({ severity: 'informational', type: 'representation_convergence_observed', key: k, previous_state: from, current_state: to, observed_interval_ms: Number.isFinite(duration) && duration >= 0 ? duration : null, authority: 'external_unverified', gates_release_finalization: false });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
33
42
|
}
|
|
34
43
|
for (const k of before.keys()) if (!after.has(k)) alerts.push({ severity: 'medium', type: 'observation_missing', key: k });
|
|
35
44
|
const result = { generated_at: nowIso(), run_a: a, run_b: b, summary: { alerts: alerts.length, critical_or_high: alerts.filter((x) => ['critical', 'high'].includes(x.severity)).length }, alerts };
|
package/src/commands/observe.js
CHANGED
|
@@ -8,11 +8,20 @@ import { parse as parseCsv } from 'csv-parse/sync';
|
|
|
8
8
|
import { crawlerIdentity } from '../observations/crawlerIdentity.js';
|
|
9
9
|
import { validateAgainst } from '../shared/schemaValidator.js';
|
|
10
10
|
import { observeMedia } from '../observations/media.js';
|
|
11
|
+
import { parse as parseHtml } from 'node-html-parser';
|
|
12
|
+
import { verifyManifestIntegrity } from '../release/governance.js';
|
|
13
|
+
import { observeBrowserPlan } from '../observations/browserJourney.js';
|
|
11
14
|
|
|
12
15
|
const originOf = (value) => { try { return new URL(value).origin; } catch { return null; } };
|
|
13
16
|
const words = (text) => String(text || '').trim().split(/\s+/).filter(Boolean);
|
|
14
17
|
const strictDate = (value) => /^\d{4}-\d{2}-\d{2}$/.test(value || '') && new Date(`${value}T00:00:00Z`).toISOString().slice(0, 10) === value;
|
|
15
18
|
|
|
19
|
+
function visibleHtmlText(html) {
|
|
20
|
+
const document = parseHtml(String(html || ''));
|
|
21
|
+
for (const node of document.querySelectorAll('script,style')) node.remove();
|
|
22
|
+
return document.textContent.replace(/\s+/g, ' ').trim();
|
|
23
|
+
}
|
|
24
|
+
|
|
16
25
|
function canonicalReview(raw, targetOrigin) {
|
|
17
26
|
const citations = raw.citations || [];
|
|
18
27
|
return citations.map((citation, index) => {
|
|
@@ -31,6 +40,7 @@ function canonicalReview(raw, targetOrigin) {
|
|
|
31
40
|
}
|
|
32
41
|
|
|
33
42
|
async function observeRender(root, options) {
|
|
43
|
+
if (options.input) return observeBrowserPlan(root, options);
|
|
34
44
|
if (!options.target || !/^https?:\/\//.test(options.target)) throw new Error('render requires --target <http(s) URL>');
|
|
35
45
|
const profileNames = ['desktop', 'mobile', 'javascript_disabled'];
|
|
36
46
|
let reused = [], previousRaw = null;
|
|
@@ -74,7 +84,7 @@ async function observeRender(root, options) {
|
|
|
74
84
|
};
|
|
75
85
|
}
|
|
76
86
|
const initial = await (options.fetchUrl || fetchUrl)(options.target, { timeoutMs: options.timeout || 30000, maxRetries: 1 });
|
|
77
|
-
const initialText = initial.body
|
|
87
|
+
const initialText = visibleHtmlText(initial.body);
|
|
78
88
|
const observations = [...reused], artifacts = { 'initial/response.html': initial.body }, incomplete = [];
|
|
79
89
|
const profiles = [{ name: 'desktop', viewport: { width: 1280, height: 900 } }, { name: 'mobile', viewport: { width: 390, height: 844 }, settings: { isMobile: true } }, { name: 'javascript_disabled', viewport: { width: 1280, height: 900 }, settings: { javaScriptEnabled: false } }];
|
|
80
90
|
for (const profile of profiles.filter((item) => !reused.some((old) => old.data.profile === item.name))) {
|
|
@@ -369,6 +379,77 @@ function observeCorroboration(root, options) {
|
|
|
369
379
|
return observationRun(root, 'observe corroboration', input.file, observations, { rawInputs: { corroboration_export: input.raw } });
|
|
370
380
|
}
|
|
371
381
|
|
|
382
|
+
async function observeRepresentation(root, options) {
|
|
383
|
+
const input = readInput(options.input);
|
|
384
|
+
const manifest = input.value;
|
|
385
|
+
const integrity = verifyManifestIntegrity(manifest);
|
|
386
|
+
if (!integrity.ok) throw new Error(`release manifest is invalid: ${integrity.failures.join('; ')}`);
|
|
387
|
+
if (!options.target) throw new Error('representation observation requires --target <controlled surface URL>');
|
|
388
|
+
const surface = manifest.controlled_surfaces.find((item) => item.url === options.target || item.surface_id === options.surfaceId);
|
|
389
|
+
if (!surface) throw new Error('target is not a controlled surface in the release manifest');
|
|
390
|
+
const expected = manifest.projections.find((item) => item.projection_id === surface.projection_id);
|
|
391
|
+
if (!expected) throw new Error(`expected projection ${surface.projection_id} is missing`);
|
|
392
|
+
const collector = options.fetchUrl || fetchUrl;
|
|
393
|
+
const paths = [
|
|
394
|
+
{ path: 'direct', url: surface.url },
|
|
395
|
+
{ path: 'cache_busted', url: `${surface.url}${surface.url.includes('?') ? '&' : '?'}citable_manifest=${manifest.manifest_hash.slice(0, 16)}` },
|
|
396
|
+
];
|
|
397
|
+
const observations = [];
|
|
398
|
+
const artifacts = {};
|
|
399
|
+
const incomplete = [];
|
|
400
|
+
for (const item of paths) {
|
|
401
|
+
try {
|
|
402
|
+
const response = await collector(item.url, { userAgent: options.userAgent || 'CitableRepresentationProbe/1.0', maxRetries: 1 });
|
|
403
|
+
const responseHash = sha256(response.body);
|
|
404
|
+
const observedProjectionHash = surface.verification_method === 'exact_response_body'
|
|
405
|
+
? responseHash
|
|
406
|
+
: response.headers?.[surface.verification_header] || null;
|
|
407
|
+
const representationState = response.status >= 200 && response.status < 300
|
|
408
|
+
? !observedProjectionHash ? 'insufficient_evidence' : observedProjectionHash === expected.sha256 ? 'consistent' : 'divergent'
|
|
409
|
+
: response.status === 403 || response.status === 429 ? 'challenged' : 'failed';
|
|
410
|
+
const data = {
|
|
411
|
+
release_id: manifest.release_id,
|
|
412
|
+
manifest_hash: manifest.manifest_hash,
|
|
413
|
+
surface_id: surface.surface_id,
|
|
414
|
+
projection_id: expected.projection_id,
|
|
415
|
+
retrieval_path: item.path,
|
|
416
|
+
requested_url: item.url,
|
|
417
|
+
final_url: response.url,
|
|
418
|
+
status: response.status,
|
|
419
|
+
redirect_chain: response.redirectChain || [],
|
|
420
|
+
headers: response.headers || {},
|
|
421
|
+
verification_method: surface.verification_method,
|
|
422
|
+
verification_header: surface.verification_header,
|
|
423
|
+
expected_projection_hash: expected.sha256,
|
|
424
|
+
observed_projection_hash: observedProjectionHash,
|
|
425
|
+
observed_response_hash: responseHash,
|
|
426
|
+
representation_state: representationState,
|
|
427
|
+
authority_label: 'external_unverified',
|
|
428
|
+
gates_release_finalization: false,
|
|
429
|
+
request_identity: options.userAgent || 'CitableRepresentationProbe/1.0',
|
|
430
|
+
region: options.region || 'local_unspecified',
|
|
431
|
+
};
|
|
432
|
+
observations.push(envelope('representation_drift', data, {
|
|
433
|
+
method: 'synthetic_fetch', source: item.url, raw: response.body,
|
|
434
|
+
confidence: 'confirmed',
|
|
435
|
+
limitations: ['One synthetic retrieval does not represent all caches, indexes, products, accounts, geographies, or users.'],
|
|
436
|
+
authority: { source_authority: 'unknown', collection_authority: 'synthetic_probe', authenticity_status: 'unverified', representativeness: 'single_observation' },
|
|
437
|
+
}));
|
|
438
|
+
artifacts[`representation/${item.path}-response.txt`] = response.body;
|
|
439
|
+
artifacts[`representation/${item.path}-headers.json`] = response.headers || {};
|
|
440
|
+
} catch (error) {
|
|
441
|
+
incomplete.push(`${item.path} representation retrieval failed: ${error.message}`);
|
|
442
|
+
observations.push(envelope('representation_drift', {
|
|
443
|
+
release_id: manifest.release_id, manifest_hash: manifest.manifest_hash, surface_id: surface.surface_id,
|
|
444
|
+
projection_id: expected.projection_id, retrieval_path: item.path, requested_url: item.url,
|
|
445
|
+
representation_state: 'failed', authority_label: 'external_unverified', gates_release_finalization: false,
|
|
446
|
+
request_identity: options.userAgent || 'CitableRepresentationProbe/1.0', region: options.region || 'local_unspecified',
|
|
447
|
+
}, { method: 'synthetic_fetch', source: item.url, state: 'failed', confidence: 'confirmed', raw: error.message, limitations: [error.message], authority: { source_authority: 'unknown', collection_authority: 'synthetic_probe', authenticity_status: 'unverified', representativeness: 'single_observation' } }));
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
return observationRun(root, 'observe representation', surface.url, observations, { rawInputs: { release_manifest: input.raw }, incomplete, artifacts });
|
|
451
|
+
}
|
|
452
|
+
|
|
372
453
|
export async function observe(root, mode, options = {}) {
|
|
373
454
|
switch (mode) {
|
|
374
455
|
case 'render': return observeRender(root, options);
|
|
@@ -381,6 +462,7 @@ export async function observe(root, mode, options = {}) {
|
|
|
381
462
|
case 'performance': return observePerformance(root, options);
|
|
382
463
|
case 'corroboration': return observeCorroboration(root, options);
|
|
383
464
|
case 'media': return observeMedia(root, options);
|
|
384
|
-
|
|
465
|
+
case 'representation': return observeRepresentation(root, options);
|
|
466
|
+
default: throw new Error('observe mode must be render, index, citations, logs, bing, passages, consensus, performance, corroboration, media, or representation');
|
|
385
467
|
}
|
|
386
468
|
}
|