@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.
Files changed (360) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +12 -1
  3. package/dist/universal/.agents/skills/citable/SKILL.md +11 -2
  4. package/dist/universal/.agents/skills/citable/VERSION +1 -1
  5. package/dist/universal/.agents/skills/citable/manifest.json +24 -12
  6. package/dist/universal/.agents/skills/citable/schemas/action-plan.schema.json +38 -1
  7. package/dist/universal/.agents/skills/citable/schemas/audit-coverage.schema.json +118 -0
  8. package/dist/universal/.agents/skills/citable/schemas/claim-evidence.schema.json +21 -0
  9. package/dist/universal/.agents/skills/citable/schemas/claim-verification.schema.json +18 -0
  10. package/dist/universal/.agents/skills/citable/schemas/collection-result.schema.json +35 -0
  11. package/dist/universal/.agents/skills/citable/schemas/config.schema.json +2 -0
  12. package/dist/universal/.agents/skills/citable/schemas/cro-report.schema.json +8 -1
  13. package/dist/universal/.agents/skills/citable/schemas/derivation.schema.json +18 -0
  14. package/dist/universal/.agents/skills/citable/schemas/external-comparison.schema.json +16 -0
  15. package/dist/universal/.agents/skills/citable/schemas/external-observation.schema.json +32 -0
  16. package/dist/universal/.agents/skills/citable/schemas/finding.schema.json +105 -2
  17. package/dist/universal/.agents/skills/citable/schemas/prompt-set.schema.json +47 -0
  18. package/dist/universal/.agents/skills/citable/schemas/remediation-verification.schema.json +12 -1
  19. package/dist/universal/.agents/skills/citable/schemas/representation-data.schema.json +21 -0
  20. package/dist/universal/.agents/skills/citable/schemas/research-dataset.schema.json +27 -0
  21. package/dist/universal/.agents/skills/citable/schemas/run.schema.json +15 -2
  22. package/dist/universal/.agents/skills/citable/schemas/search-discovery-data.schema.json +20 -0
  23. package/dist/universal/.agents/skills/citable/schemas/search-report.schema.json +8 -1
  24. package/dist/universal/.agents/skills/citable/schemas/summary.schema.json +41 -0
  25. package/dist/universal/.claude/agents/citable/manifest.json +2 -2
  26. package/dist/universal/.claude/skills/citable/SKILL.md +11 -2
  27. package/dist/universal/.claude/skills/citable/VERSION +1 -1
  28. package/dist/universal/.claude/skills/citable/manifest.json +24 -12
  29. package/dist/universal/.claude/skills/citable/schemas/action-plan.schema.json +38 -1
  30. package/dist/universal/.claude/skills/citable/schemas/audit-coverage.schema.json +118 -0
  31. package/dist/universal/.claude/skills/citable/schemas/claim-evidence.schema.json +21 -0
  32. package/dist/universal/.claude/skills/citable/schemas/claim-verification.schema.json +18 -0
  33. package/dist/universal/.claude/skills/citable/schemas/collection-result.schema.json +35 -0
  34. package/dist/universal/.claude/skills/citable/schemas/config.schema.json +2 -0
  35. package/dist/universal/.claude/skills/citable/schemas/cro-report.schema.json +8 -1
  36. package/dist/universal/.claude/skills/citable/schemas/derivation.schema.json +18 -0
  37. package/dist/universal/.claude/skills/citable/schemas/external-comparison.schema.json +16 -0
  38. package/dist/universal/.claude/skills/citable/schemas/external-observation.schema.json +32 -0
  39. package/dist/universal/.claude/skills/citable/schemas/finding.schema.json +105 -2
  40. package/dist/universal/.claude/skills/citable/schemas/prompt-set.schema.json +47 -0
  41. package/dist/universal/.claude/skills/citable/schemas/remediation-verification.schema.json +12 -1
  42. package/dist/universal/.claude/skills/citable/schemas/representation-data.schema.json +21 -0
  43. package/dist/universal/.claude/skills/citable/schemas/research-dataset.schema.json +27 -0
  44. package/dist/universal/.claude/skills/citable/schemas/run.schema.json +15 -2
  45. package/dist/universal/.claude/skills/citable/schemas/search-discovery-data.schema.json +20 -0
  46. package/dist/universal/.claude/skills/citable/schemas/search-report.schema.json +8 -1
  47. package/dist/universal/.claude/skills/citable/schemas/summary.schema.json +41 -0
  48. package/dist/universal/.cursor/skills/citable/SKILL.md +11 -2
  49. package/dist/universal/.cursor/skills/citable/VERSION +1 -1
  50. package/dist/universal/.cursor/skills/citable/manifest.json +24 -12
  51. package/dist/universal/.cursor/skills/citable/schemas/action-plan.schema.json +38 -1
  52. package/dist/universal/.cursor/skills/citable/schemas/audit-coverage.schema.json +118 -0
  53. package/dist/universal/.cursor/skills/citable/schemas/claim-evidence.schema.json +21 -0
  54. package/dist/universal/.cursor/skills/citable/schemas/claim-verification.schema.json +18 -0
  55. package/dist/universal/.cursor/skills/citable/schemas/collection-result.schema.json +35 -0
  56. package/dist/universal/.cursor/skills/citable/schemas/config.schema.json +2 -0
  57. package/dist/universal/.cursor/skills/citable/schemas/cro-report.schema.json +8 -1
  58. package/dist/universal/.cursor/skills/citable/schemas/derivation.schema.json +18 -0
  59. package/dist/universal/.cursor/skills/citable/schemas/external-comparison.schema.json +16 -0
  60. package/dist/universal/.cursor/skills/citable/schemas/external-observation.schema.json +32 -0
  61. package/dist/universal/.cursor/skills/citable/schemas/finding.schema.json +105 -2
  62. package/dist/universal/.cursor/skills/citable/schemas/prompt-set.schema.json +47 -0
  63. package/dist/universal/.cursor/skills/citable/schemas/remediation-verification.schema.json +12 -1
  64. package/dist/universal/.cursor/skills/citable/schemas/representation-data.schema.json +21 -0
  65. package/dist/universal/.cursor/skills/citable/schemas/research-dataset.schema.json +27 -0
  66. package/dist/universal/.cursor/skills/citable/schemas/run.schema.json +15 -2
  67. package/dist/universal/.cursor/skills/citable/schemas/search-discovery-data.schema.json +20 -0
  68. package/dist/universal/.cursor/skills/citable/schemas/search-report.schema.json +8 -1
  69. package/dist/universal/.cursor/skills/citable/schemas/summary.schema.json +41 -0
  70. package/dist/universal/.gemini/skills/citable/SKILL.md +11 -2
  71. package/dist/universal/.gemini/skills/citable/VERSION +1 -1
  72. package/dist/universal/.gemini/skills/citable/manifest.json +24 -12
  73. package/dist/universal/.gemini/skills/citable/schemas/action-plan.schema.json +38 -1
  74. package/dist/universal/.gemini/skills/citable/schemas/audit-coverage.schema.json +118 -0
  75. package/dist/universal/.gemini/skills/citable/schemas/claim-evidence.schema.json +21 -0
  76. package/dist/universal/.gemini/skills/citable/schemas/claim-verification.schema.json +18 -0
  77. package/dist/universal/.gemini/skills/citable/schemas/collection-result.schema.json +35 -0
  78. package/dist/universal/.gemini/skills/citable/schemas/config.schema.json +2 -0
  79. package/dist/universal/.gemini/skills/citable/schemas/cro-report.schema.json +8 -1
  80. package/dist/universal/.gemini/skills/citable/schemas/derivation.schema.json +18 -0
  81. package/dist/universal/.gemini/skills/citable/schemas/external-comparison.schema.json +16 -0
  82. package/dist/universal/.gemini/skills/citable/schemas/external-observation.schema.json +32 -0
  83. package/dist/universal/.gemini/skills/citable/schemas/finding.schema.json +105 -2
  84. package/dist/universal/.gemini/skills/citable/schemas/prompt-set.schema.json +47 -0
  85. package/dist/universal/.gemini/skills/citable/schemas/remediation-verification.schema.json +12 -1
  86. package/dist/universal/.gemini/skills/citable/schemas/representation-data.schema.json +21 -0
  87. package/dist/universal/.gemini/skills/citable/schemas/research-dataset.schema.json +27 -0
  88. package/dist/universal/.gemini/skills/citable/schemas/run.schema.json +15 -2
  89. package/dist/universal/.gemini/skills/citable/schemas/search-discovery-data.schema.json +20 -0
  90. package/dist/universal/.gemini/skills/citable/schemas/search-report.schema.json +8 -1
  91. package/dist/universal/.gemini/skills/citable/schemas/summary.schema.json +41 -0
  92. package/dist/universal/.github/skills/citable/SKILL.md +11 -2
  93. package/dist/universal/.github/skills/citable/VERSION +1 -1
  94. package/dist/universal/.github/skills/citable/manifest.json +24 -12
  95. package/dist/universal/.github/skills/citable/schemas/action-plan.schema.json +38 -1
  96. package/dist/universal/.github/skills/citable/schemas/audit-coverage.schema.json +118 -0
  97. package/dist/universal/.github/skills/citable/schemas/claim-evidence.schema.json +21 -0
  98. package/dist/universal/.github/skills/citable/schemas/claim-verification.schema.json +18 -0
  99. package/dist/universal/.github/skills/citable/schemas/collection-result.schema.json +35 -0
  100. package/dist/universal/.github/skills/citable/schemas/config.schema.json +2 -0
  101. package/dist/universal/.github/skills/citable/schemas/cro-report.schema.json +8 -1
  102. package/dist/universal/.github/skills/citable/schemas/derivation.schema.json +18 -0
  103. package/dist/universal/.github/skills/citable/schemas/external-comparison.schema.json +16 -0
  104. package/dist/universal/.github/skills/citable/schemas/external-observation.schema.json +32 -0
  105. package/dist/universal/.github/skills/citable/schemas/finding.schema.json +105 -2
  106. package/dist/universal/.github/skills/citable/schemas/prompt-set.schema.json +47 -0
  107. package/dist/universal/.github/skills/citable/schemas/remediation-verification.schema.json +12 -1
  108. package/dist/universal/.github/skills/citable/schemas/representation-data.schema.json +21 -0
  109. package/dist/universal/.github/skills/citable/schemas/research-dataset.schema.json +27 -0
  110. package/dist/universal/.github/skills/citable/schemas/run.schema.json +15 -2
  111. package/dist/universal/.github/skills/citable/schemas/search-discovery-data.schema.json +20 -0
  112. package/dist/universal/.github/skills/citable/schemas/search-report.schema.json +8 -1
  113. package/dist/universal/.github/skills/citable/schemas/summary.schema.json +41 -0
  114. package/dist/universal/.kiro/skills/citable/SKILL.md +11 -2
  115. package/dist/universal/.kiro/skills/citable/VERSION +1 -1
  116. package/dist/universal/.kiro/skills/citable/manifest.json +24 -12
  117. package/dist/universal/.kiro/skills/citable/schemas/action-plan.schema.json +38 -1
  118. package/dist/universal/.kiro/skills/citable/schemas/audit-coverage.schema.json +118 -0
  119. package/dist/universal/.kiro/skills/citable/schemas/claim-evidence.schema.json +21 -0
  120. package/dist/universal/.kiro/skills/citable/schemas/claim-verification.schema.json +18 -0
  121. package/dist/universal/.kiro/skills/citable/schemas/collection-result.schema.json +35 -0
  122. package/dist/universal/.kiro/skills/citable/schemas/config.schema.json +2 -0
  123. package/dist/universal/.kiro/skills/citable/schemas/cro-report.schema.json +8 -1
  124. package/dist/universal/.kiro/skills/citable/schemas/derivation.schema.json +18 -0
  125. package/dist/universal/.kiro/skills/citable/schemas/external-comparison.schema.json +16 -0
  126. package/dist/universal/.kiro/skills/citable/schemas/external-observation.schema.json +32 -0
  127. package/dist/universal/.kiro/skills/citable/schemas/finding.schema.json +105 -2
  128. package/dist/universal/.kiro/skills/citable/schemas/prompt-set.schema.json +47 -0
  129. package/dist/universal/.kiro/skills/citable/schemas/remediation-verification.schema.json +12 -1
  130. package/dist/universal/.kiro/skills/citable/schemas/representation-data.schema.json +21 -0
  131. package/dist/universal/.kiro/skills/citable/schemas/research-dataset.schema.json +27 -0
  132. package/dist/universal/.kiro/skills/citable/schemas/run.schema.json +15 -2
  133. package/dist/universal/.kiro/skills/citable/schemas/search-discovery-data.schema.json +20 -0
  134. package/dist/universal/.kiro/skills/citable/schemas/search-report.schema.json +8 -1
  135. package/dist/universal/.kiro/skills/citable/schemas/summary.schema.json +41 -0
  136. package/dist/universal/.opencode/skills/citable/SKILL.md +11 -2
  137. package/dist/universal/.opencode/skills/citable/VERSION +1 -1
  138. package/dist/universal/.opencode/skills/citable/manifest.json +24 -12
  139. package/dist/universal/.opencode/skills/citable/schemas/action-plan.schema.json +38 -1
  140. package/dist/universal/.opencode/skills/citable/schemas/audit-coverage.schema.json +118 -0
  141. package/dist/universal/.opencode/skills/citable/schemas/claim-evidence.schema.json +21 -0
  142. package/dist/universal/.opencode/skills/citable/schemas/claim-verification.schema.json +18 -0
  143. package/dist/universal/.opencode/skills/citable/schemas/collection-result.schema.json +35 -0
  144. package/dist/universal/.opencode/skills/citable/schemas/config.schema.json +2 -0
  145. package/dist/universal/.opencode/skills/citable/schemas/cro-report.schema.json +8 -1
  146. package/dist/universal/.opencode/skills/citable/schemas/derivation.schema.json +18 -0
  147. package/dist/universal/.opencode/skills/citable/schemas/external-comparison.schema.json +16 -0
  148. package/dist/universal/.opencode/skills/citable/schemas/external-observation.schema.json +32 -0
  149. package/dist/universal/.opencode/skills/citable/schemas/finding.schema.json +105 -2
  150. package/dist/universal/.opencode/skills/citable/schemas/prompt-set.schema.json +47 -0
  151. package/dist/universal/.opencode/skills/citable/schemas/remediation-verification.schema.json +12 -1
  152. package/dist/universal/.opencode/skills/citable/schemas/representation-data.schema.json +21 -0
  153. package/dist/universal/.opencode/skills/citable/schemas/research-dataset.schema.json +27 -0
  154. package/dist/universal/.opencode/skills/citable/schemas/run.schema.json +15 -2
  155. package/dist/universal/.opencode/skills/citable/schemas/search-discovery-data.schema.json +20 -0
  156. package/dist/universal/.opencode/skills/citable/schemas/search-report.schema.json +8 -1
  157. package/dist/universal/.opencode/skills/citable/schemas/summary.schema.json +41 -0
  158. package/dist/universal/.pi/agent/skills/citable/SKILL.md +11 -2
  159. package/dist/universal/.pi/agent/skills/citable/VERSION +1 -1
  160. package/dist/universal/.pi/agent/skills/citable/manifest.json +24 -12
  161. package/dist/universal/.pi/agent/skills/citable/schemas/action-plan.schema.json +38 -1
  162. package/dist/universal/.pi/agent/skills/citable/schemas/audit-coverage.schema.json +118 -0
  163. package/dist/universal/.pi/agent/skills/citable/schemas/claim-evidence.schema.json +21 -0
  164. package/dist/universal/.pi/agent/skills/citable/schemas/claim-verification.schema.json +18 -0
  165. package/dist/universal/.pi/agent/skills/citable/schemas/collection-result.schema.json +35 -0
  166. package/dist/universal/.pi/agent/skills/citable/schemas/config.schema.json +2 -0
  167. package/dist/universal/.pi/agent/skills/citable/schemas/cro-report.schema.json +8 -1
  168. package/dist/universal/.pi/agent/skills/citable/schemas/derivation.schema.json +18 -0
  169. package/dist/universal/.pi/agent/skills/citable/schemas/external-comparison.schema.json +16 -0
  170. package/dist/universal/.pi/agent/skills/citable/schemas/external-observation.schema.json +32 -0
  171. package/dist/universal/.pi/agent/skills/citable/schemas/finding.schema.json +105 -2
  172. package/dist/universal/.pi/agent/skills/citable/schemas/prompt-set.schema.json +47 -0
  173. package/dist/universal/.pi/agent/skills/citable/schemas/remediation-verification.schema.json +12 -1
  174. package/dist/universal/.pi/agent/skills/citable/schemas/representation-data.schema.json +21 -0
  175. package/dist/universal/.pi/agent/skills/citable/schemas/research-dataset.schema.json +27 -0
  176. package/dist/universal/.pi/agent/skills/citable/schemas/run.schema.json +15 -2
  177. package/dist/universal/.pi/agent/skills/citable/schemas/search-discovery-data.schema.json +20 -0
  178. package/dist/universal/.pi/agent/skills/citable/schemas/search-report.schema.json +8 -1
  179. package/dist/universal/.pi/agent/skills/citable/schemas/summary.schema.json +41 -0
  180. package/dist/universal/.qoder/skills/citable/SKILL.md +11 -2
  181. package/dist/universal/.qoder/skills/citable/VERSION +1 -1
  182. package/dist/universal/.qoder/skills/citable/manifest.json +24 -12
  183. package/dist/universal/.qoder/skills/citable/schemas/action-plan.schema.json +38 -1
  184. package/dist/universal/.qoder/skills/citable/schemas/audit-coverage.schema.json +118 -0
  185. package/dist/universal/.qoder/skills/citable/schemas/claim-evidence.schema.json +21 -0
  186. package/dist/universal/.qoder/skills/citable/schemas/claim-verification.schema.json +18 -0
  187. package/dist/universal/.qoder/skills/citable/schemas/collection-result.schema.json +35 -0
  188. package/dist/universal/.qoder/skills/citable/schemas/config.schema.json +2 -0
  189. package/dist/universal/.qoder/skills/citable/schemas/cro-report.schema.json +8 -1
  190. package/dist/universal/.qoder/skills/citable/schemas/derivation.schema.json +18 -0
  191. package/dist/universal/.qoder/skills/citable/schemas/external-comparison.schema.json +16 -0
  192. package/dist/universal/.qoder/skills/citable/schemas/external-observation.schema.json +32 -0
  193. package/dist/universal/.qoder/skills/citable/schemas/finding.schema.json +105 -2
  194. package/dist/universal/.qoder/skills/citable/schemas/prompt-set.schema.json +47 -0
  195. package/dist/universal/.qoder/skills/citable/schemas/remediation-verification.schema.json +12 -1
  196. package/dist/universal/.qoder/skills/citable/schemas/representation-data.schema.json +21 -0
  197. package/dist/universal/.qoder/skills/citable/schemas/research-dataset.schema.json +27 -0
  198. package/dist/universal/.qoder/skills/citable/schemas/run.schema.json +15 -2
  199. package/dist/universal/.qoder/skills/citable/schemas/search-discovery-data.schema.json +20 -0
  200. package/dist/universal/.qoder/skills/citable/schemas/search-report.schema.json +8 -1
  201. package/dist/universal/.qoder/skills/citable/schemas/summary.schema.json +41 -0
  202. package/dist/universal/.rovodev/skills/citable/SKILL.md +11 -2
  203. package/dist/universal/.rovodev/skills/citable/VERSION +1 -1
  204. package/dist/universal/.rovodev/skills/citable/manifest.json +24 -12
  205. package/dist/universal/.rovodev/skills/citable/schemas/action-plan.schema.json +38 -1
  206. package/dist/universal/.rovodev/skills/citable/schemas/audit-coverage.schema.json +118 -0
  207. package/dist/universal/.rovodev/skills/citable/schemas/claim-evidence.schema.json +21 -0
  208. package/dist/universal/.rovodev/skills/citable/schemas/claim-verification.schema.json +18 -0
  209. package/dist/universal/.rovodev/skills/citable/schemas/collection-result.schema.json +35 -0
  210. package/dist/universal/.rovodev/skills/citable/schemas/config.schema.json +2 -0
  211. package/dist/universal/.rovodev/skills/citable/schemas/cro-report.schema.json +8 -1
  212. package/dist/universal/.rovodev/skills/citable/schemas/derivation.schema.json +18 -0
  213. package/dist/universal/.rovodev/skills/citable/schemas/external-comparison.schema.json +16 -0
  214. package/dist/universal/.rovodev/skills/citable/schemas/external-observation.schema.json +32 -0
  215. package/dist/universal/.rovodev/skills/citable/schemas/finding.schema.json +105 -2
  216. package/dist/universal/.rovodev/skills/citable/schemas/prompt-set.schema.json +47 -0
  217. package/dist/universal/.rovodev/skills/citable/schemas/remediation-verification.schema.json +12 -1
  218. package/dist/universal/.rovodev/skills/citable/schemas/representation-data.schema.json +21 -0
  219. package/dist/universal/.rovodev/skills/citable/schemas/research-dataset.schema.json +27 -0
  220. package/dist/universal/.rovodev/skills/citable/schemas/run.schema.json +15 -2
  221. package/dist/universal/.rovodev/skills/citable/schemas/search-discovery-data.schema.json +20 -0
  222. package/dist/universal/.rovodev/skills/citable/schemas/search-report.schema.json +8 -1
  223. package/dist/universal/.rovodev/skills/citable/schemas/summary.schema.json +41 -0
  224. package/dist/universal/.trae/skills/citable/SKILL.md +11 -2
  225. package/dist/universal/.trae/skills/citable/VERSION +1 -1
  226. package/dist/universal/.trae/skills/citable/manifest.json +24 -12
  227. package/dist/universal/.trae/skills/citable/schemas/action-plan.schema.json +38 -1
  228. package/dist/universal/.trae/skills/citable/schemas/audit-coverage.schema.json +118 -0
  229. package/dist/universal/.trae/skills/citable/schemas/claim-evidence.schema.json +21 -0
  230. package/dist/universal/.trae/skills/citable/schemas/claim-verification.schema.json +18 -0
  231. package/dist/universal/.trae/skills/citable/schemas/collection-result.schema.json +35 -0
  232. package/dist/universal/.trae/skills/citable/schemas/config.schema.json +2 -0
  233. package/dist/universal/.trae/skills/citable/schemas/cro-report.schema.json +8 -1
  234. package/dist/universal/.trae/skills/citable/schemas/derivation.schema.json +18 -0
  235. package/dist/universal/.trae/skills/citable/schemas/external-comparison.schema.json +16 -0
  236. package/dist/universal/.trae/skills/citable/schemas/external-observation.schema.json +32 -0
  237. package/dist/universal/.trae/skills/citable/schemas/finding.schema.json +105 -2
  238. package/dist/universal/.trae/skills/citable/schemas/prompt-set.schema.json +47 -0
  239. package/dist/universal/.trae/skills/citable/schemas/remediation-verification.schema.json +12 -1
  240. package/dist/universal/.trae/skills/citable/schemas/representation-data.schema.json +21 -0
  241. package/dist/universal/.trae/skills/citable/schemas/research-dataset.schema.json +27 -0
  242. package/dist/universal/.trae/skills/citable/schemas/run.schema.json +15 -2
  243. package/dist/universal/.trae/skills/citable/schemas/search-discovery-data.schema.json +20 -0
  244. package/dist/universal/.trae/skills/citable/schemas/search-report.schema.json +8 -1
  245. package/dist/universal/.trae/skills/citable/schemas/summary.schema.json +41 -0
  246. package/dist/universal/.trae-cn/skills/citable/SKILL.md +11 -2
  247. package/dist/universal/.trae-cn/skills/citable/VERSION +1 -1
  248. package/dist/universal/.trae-cn/skills/citable/manifest.json +24 -12
  249. package/dist/universal/.trae-cn/skills/citable/schemas/action-plan.schema.json +38 -1
  250. package/dist/universal/.trae-cn/skills/citable/schemas/audit-coverage.schema.json +118 -0
  251. package/dist/universal/.trae-cn/skills/citable/schemas/claim-evidence.schema.json +21 -0
  252. package/dist/universal/.trae-cn/skills/citable/schemas/claim-verification.schema.json +18 -0
  253. package/dist/universal/.trae-cn/skills/citable/schemas/collection-result.schema.json +35 -0
  254. package/dist/universal/.trae-cn/skills/citable/schemas/config.schema.json +2 -0
  255. package/dist/universal/.trae-cn/skills/citable/schemas/cro-report.schema.json +8 -1
  256. package/dist/universal/.trae-cn/skills/citable/schemas/derivation.schema.json +18 -0
  257. package/dist/universal/.trae-cn/skills/citable/schemas/external-comparison.schema.json +16 -0
  258. package/dist/universal/.trae-cn/skills/citable/schemas/external-observation.schema.json +32 -0
  259. package/dist/universal/.trae-cn/skills/citable/schemas/finding.schema.json +105 -2
  260. package/dist/universal/.trae-cn/skills/citable/schemas/prompt-set.schema.json +47 -0
  261. package/dist/universal/.trae-cn/skills/citable/schemas/remediation-verification.schema.json +12 -1
  262. package/dist/universal/.trae-cn/skills/citable/schemas/representation-data.schema.json +21 -0
  263. package/dist/universal/.trae-cn/skills/citable/schemas/research-dataset.schema.json +27 -0
  264. package/dist/universal/.trae-cn/skills/citable/schemas/run.schema.json +15 -2
  265. package/dist/universal/.trae-cn/skills/citable/schemas/search-discovery-data.schema.json +20 -0
  266. package/dist/universal/.trae-cn/skills/citable/schemas/search-report.schema.json +8 -1
  267. package/dist/universal/.trae-cn/skills/citable/schemas/summary.schema.json +41 -0
  268. package/dist/universal/manifest.json +292 -148
  269. package/package.json +1 -1
  270. package/schemas/action-plan.schema.json +38 -1
  271. package/schemas/audit-coverage.schema.json +118 -0
  272. package/schemas/claim-evidence.schema.json +21 -0
  273. package/schemas/claim-verification.schema.json +18 -0
  274. package/schemas/collection-result.schema.json +35 -0
  275. package/schemas/config.schema.json +2 -0
  276. package/schemas/cro-report.schema.json +8 -1
  277. package/schemas/derivation.schema.json +18 -0
  278. package/schemas/external-comparison.schema.json +16 -0
  279. package/schemas/external-observation.schema.json +32 -0
  280. package/schemas/finding.schema.json +105 -2
  281. package/schemas/prompt-set.schema.json +47 -0
  282. package/schemas/remediation-verification.schema.json +12 -1
  283. package/schemas/representation-data.schema.json +21 -0
  284. package/schemas/research-dataset.schema.json +27 -0
  285. package/schemas/run.schema.json +15 -2
  286. package/schemas/search-discovery-data.schema.json +20 -0
  287. package/schemas/search-report.schema.json +8 -1
  288. package/schemas/summary.schema.json +41 -0
  289. package/skill/SKILL.md +11 -2
  290. package/src/acceptance/reproducibility.js +5 -25
  291. package/src/analysis/croRoadmap.js +3 -3
  292. package/src/analysis/strategicRoadmap.js +3 -3
  293. package/src/artifacts/interchange.js +2 -6
  294. package/src/cli/index.js +15 -3
  295. package/src/commands/actionPlan.js +46 -5
  296. package/src/commands/applyRemediation.js +5 -5
  297. package/src/commands/audit.js +75 -8
  298. package/src/commands/ciWorkflow.js +7 -2
  299. package/src/commands/compareSnapshots.js +155 -47
  300. package/src/commands/connect.js +24 -4
  301. package/src/commands/context.js +41 -2
  302. package/src/commands/croSuite.js +51 -13
  303. package/src/commands/delivery.js +7 -7
  304. package/src/commands/governance.js +9 -10
  305. package/src/commands/implementationKit.js +2 -1
  306. package/src/commands/init.js +8 -1
  307. package/src/commands/previewCro.js +1 -1
  308. package/src/commands/prioritize.js +3 -2
  309. package/src/commands/reviews.js +31 -5
  310. package/src/commands/roadmapCmd.js +7 -13
  311. package/src/commands/sweep.js +15 -2
  312. package/src/commands/verifyRemediation.js +94 -19
  313. package/src/connectors/collectionResult.js +80 -0
  314. package/src/connectors/ga4.js +46 -11
  315. package/src/connectors/gsc.js +45 -6
  316. package/src/connectors/index.js +1 -1
  317. package/src/connectors/webflow.js +140 -10
  318. package/src/connectors/wordpress.js +92 -8
  319. package/src/crawler/fetch.js +220 -24
  320. package/src/crawler/resourceValidity.js +119 -0
  321. package/src/crawler/sitemap.js +435 -16
  322. package/src/crawler/sitemapCollector.js +364 -0
  323. package/src/crawler/urlIdentity.js +97 -0
  324. package/src/detectors/agent.js +11 -0
  325. package/src/detectors/ans.js +16 -1
  326. package/src/detectors/arch.js +6 -0
  327. package/src/detectors/claim.js +9 -0
  328. package/src/detectors/crawl.js +7 -0
  329. package/src/detectors/cro.js +21 -0
  330. package/src/detectors/cwv.js +4 -0
  331. package/src/detectors/entity.js +7 -0
  332. package/src/detectors/evd.js +9 -0
  333. package/src/detectors/framework.js +28 -2
  334. package/src/detectors/geoReco.js +16 -0
  335. package/src/detectors/hreflang.js +3 -0
  336. package/src/detectors/lifeMeas.js +9 -0
  337. package/src/detectors/link.js +6 -1
  338. package/src/detectors/page.js +11 -0
  339. package/src/detectors/schemaData.js +16 -1
  340. package/src/detectors/tech.js +34 -3
  341. package/src/discovery/searchConsole.js +186 -0
  342. package/src/evidence/coverage.js +448 -0
  343. package/src/evidence/determination.js +157 -0
  344. package/src/evidence/downstream.js +110 -0
  345. package/src/evidence/external.js +251 -0
  346. package/src/evidence/hashes.js +109 -0
  347. package/src/evidence/run.js +68 -8
  348. package/src/extractor/page.js +29 -2
  349. package/src/extractor/site.js +298 -50
  350. package/src/reporting/executiveCroReport.js +36 -13
  351. package/src/reporting/executiveExport.js +45 -16
  352. package/src/reporting/executiveSearchReport.js +56 -22
  353. package/src/reporting/report.js +56 -9
  354. package/src/representation/prompts.js +117 -0
  355. package/src/representation/representation.js +186 -0
  356. package/src/shared/epistemicLanguage.js +86 -0
  357. package/src/shared/evidenceSourceResolver.js +48 -17
  358. package/src/shared/htmlEscape.js +8 -4
  359. package/src/shared/runPackageVerifier.js +99 -8
  360. package/src/shared/verifiedRunLoader.js +129 -0
@@ -31,6 +31,7 @@ import {
31
31
  } from '../shared/htmlEscape.js';
32
32
  import { extractHostname } from '../shared/domainUtils.js';
33
33
  import { validateAgainst } from '../shared/schemaValidator.js';
34
+ import { assertEpistemicLanguage, hasVerifiedEvidenceScope } from '../shared/epistemicLanguage.js';
34
35
 
35
36
  function formatVal(v, suffix = '') {
36
37
  if (v === null || v === undefined) return 'NOT OBSERVED';
@@ -620,6 +621,13 @@ export async function buildExecutiveSearchReport(root, options = {}) {
620
621
  source_findings_count: findings.length,
621
622
  integrity_hash: resolved.integrity_hash,
622
623
  synthetic_evidence: isSample,
624
+ package_verified: resolved.package_verified === true,
625
+ integrity_mode: resolved.integrity_mode || 'unknown',
626
+ legacy: resolved.legacy === true,
627
+ coverage_status: resolved.coverage_status || 'indeterminate',
628
+ determination_status: resolved.determination_status || 'indeterminate',
629
+ evaluated: resolved.coverage?.populations?.evaluated ?? null,
630
+ eligible: resolved.coverage?.populations?.eligible ?? null,
623
631
  };
624
632
 
625
633
  const report = {
@@ -667,7 +675,15 @@ export async function buildExecutiveSearchReport(root, options = {}) {
667
675
  /**
668
676
  * Render Search Executive Report as GitHub-flavored Markdown
669
677
  */
670
- export function renderSearchReportMarkdown(report) {
678
+ export function renderSearchReportMarkdown(report, evidenceContext = null) {
679
+ const context = evidenceContext || report.generation_provenance || {};
680
+ const verifiedScope = hasVerifiedEvidenceScope(context);
681
+ const scopedValue = (value) => {
682
+ if (!verifiedScope && typeof value === 'string' && /\b(?:verified|clean|resolved|optimal|passed)\b|(?:verified_source|clean_profile)/i.test(value)) return 'NOT ESTABLISHED';
683
+ return value;
684
+ };
685
+ const scopedFormat = (value, suffix = '') => scopedValue(formatVal(value, suffix));
686
+ const evidenceRegisterTitle = `${verifiedScope ? 'Verified Evidence Register' : 'Evidence Register (scope-limited; verified status not established)'} (Traceability Engine)`;
671
687
  const p = report.pillars;
672
688
  const lines = [
673
689
  `# ${sanitizeForMarkdown(report.report_title)}`,
@@ -675,7 +691,7 @@ export function renderSearchReportMarkdown(report) {
675
691
  `- **Client / Property**: \`${sanitizeForMarkdown(report.client_name)}\` (\`${sanitizeForMarkdown(report.target_domain)}\`)`,
676
692
  `- **Generated At**: \`${report.generated_at}\``,
677
693
  `- **Overall Search & AEO Readiness Score**: **${report.overall_readiness_score} / 100**`,
678
- `- **Evidence Register Traceability**: ${report.evidence_register.length} verified evidence references`,
694
+ `- **Evidence Register Traceability**: ${report.evidence_register.length} evidence references (authority and scope recorded below)`,
679
695
  `- **Generation Mode**: \`${report.generation_provenance.generation_mode}\`${report.generation_provenance.synthetic_evidence ? ' *(Synthetic Demo Evidence)*' : ''}`,
680
696
  ``,
681
697
  `> **Operating Premise & Governance Notice**: This executive report presents observable technical search infrastructure, content extraction posture, and controlled citation behavior. In adherence to Citable governance principles, **no search ranking, AI citation, or conversion outcomes are guaranteed**.`,
@@ -684,7 +700,7 @@ export function renderSearchReportMarkdown(report) {
684
700
  `## Executive Decision Summary (Traceable Conclusions)`,
685
701
  ``,
686
702
  `### 1. Confirmed Findings (Deterministic Observations)`,
687
- ...report.decision_summary.confirmed_findings.map((f) => `- [x] **[VERIFIED]** ${sanitizeForMarkdown(f)}`),
703
+ ...report.decision_summary.confirmed_findings.map((f) => `- [x] **[OBSERVED]** ${sanitizeForMarkdown(f)}`),
688
704
  ``,
689
705
  `### 2. Inferred Opportunities (Modeled Projections)`,
690
706
  ...report.decision_summary.inferred_opportunities.map((o) => `- [ ] **[OPPORTUNITY]** ${sanitizeForMarkdown(o)}`),
@@ -703,13 +719,13 @@ export function renderSearchReportMarkdown(report) {
703
719
  `- **Evidence Link**: \`${p[1].data.evidence_ref}\``,
704
720
  `- **Google Organic Indexing**: ${formatVal(p[1].data.google_organic?.indexed_status).toUpperCase()}`,
705
721
  `- **Google AI Overviews**: ${formatVal(p[1].data.google_ai_overviews?.inclusion_rate_pct, '%')} inclusion rate (Risk: \`${formatVal(p[1].data.google_ai_overviews?.risk_exposure)}\`)`,
706
- `- **AI Engine Presence**: Perplexity (\`${formatVal(p[1].data.ai_answer_engines?.perplexity)}\`), ChatGPT (\`${formatVal(p[1].data.ai_answer_engines?.chatgpt_search)}\`), Copilot (\`${formatVal(p[1].data.ai_answer_engines?.copilot)}\`)`,
722
+ `- **AI Engine Presence**: Perplexity (\`${scopedFormat(p[1].data.ai_answer_engines?.perplexity)}\`), ChatGPT (\`${scopedFormat(p[1].data.ai_answer_engines?.chatgpt_search)}\`), Copilot (\`${scopedFormat(p[1].data.ai_answer_engines?.copilot)}\`)`,
707
723
  ``,
708
724
  `## 2. Technical Search Infrastructure & Core Web Vitals`,
709
725
  `- **Evidence Link**: \`${p[2].data.evidence_ref}\``,
710
- `- **Crawlability & Canonicals**: ${formatVal(p[2].data.canonical_integrity).toUpperCase()}`,
711
- `- **LCP Readiness**: ${formatVal(p[2].data.core_web_vitals?.lcp_status).toUpperCase()} (${formatVal(p[2].data.core_web_vitals?.render_blocking_scripts)} render-blocking assets)`,
712
- `- **CLS Readiness**: ${formatVal(p[2].data.core_web_vitals?.cls_status).toUpperCase()} (${formatVal(p[2].data.core_web_vitals?.unsized_images)} unsized images)`,
726
+ `- **Crawlability & Canonicals**: ${scopedFormat(p[2].data.canonical_integrity).toUpperCase()}`,
727
+ `- **LCP Readiness**: ${scopedFormat(p[2].data.core_web_vitals?.lcp_status).toUpperCase()} (${formatVal(p[2].data.core_web_vitals?.render_blocking_scripts)} render-blocking assets)`,
728
+ `- **CLS Readiness**: ${scopedFormat(p[2].data.core_web_vitals?.cls_status).toUpperCase()} (${formatVal(p[2].data.core_web_vitals?.unsized_images)} unsized images)`,
713
729
  ``,
714
730
  `## 3. Organic Performance & Search Intent Analysis`,
715
731
  `- **Evidence Link**: \`${p[3].data.evidence_ref}\``,
@@ -724,7 +740,7 @@ export function renderSearchReportMarkdown(report) {
724
740
  ``,
725
741
  `## 5. AEO Readiness Assessment (Answer Engine Optimization)`,
726
742
  `- **Evidence Link**: \`${p[5].data.evidence_ref}\``,
727
- `- **Overall AEO Readiness Score**: **${formatVal(p[5].data.readiness_score)} / 100** (${formatVal(p[5].data.status).toUpperCase()})`,
743
+ `- **Overall AEO Readiness Score**: **${formatVal(p[5].data.readiness_score)} / 100** (${scopedFormat(p[5].data.status).toUpperCase()})`,
728
744
  `- **Direct Answer Density**: ${formatVal(p[5].data.direct_extract_density)}`,
729
745
  ``,
730
746
  `## 6. GEO Assessment (Generative Engine Optimization)`,
@@ -743,7 +759,7 @@ export function renderSearchReportMarkdown(report) {
743
759
  `## 8. Entity & Knowledge Graph Integrity`,
744
760
  `- **Evidence Link**: \`${p[8].data.evidence_ref}\``,
745
761
  `- **Organization Node Resolved**: ${p[8].data.organization_node_resolved ? 'YES' : 'NO'}`,
746
- `- **External Corroboration**: ${formatVal(p[8].data.wikidata_corroboration).toUpperCase()}`,
762
+ `- **External Corroboration**: ${scopedFormat(p[8].data.wikidata_corroboration).toUpperCase()}`,
747
763
  ``,
748
764
  `## 9. Structured-Data & Schema Architecture`,
749
765
  `- **Evidence Link**: \`${p[9].data.evidence_ref}\``,
@@ -753,12 +769,12 @@ export function renderSearchReportMarkdown(report) {
753
769
  `## 10. Competitive Search Intelligence & Share of Voice`,
754
770
  `- **Evidence Link**: \`${p[10].data.evidence_ref}\``,
755
771
  `- **1st-Party Citation Share**: **${formatVal(p[10].data.first_party_citation_share_pct, '%')}** vs Competitors (${formatVal(p[10].data.top_competitor_share_pct, '%')})`,
756
- `- **Primary Gap**: ${formatVal(p[10].data.primary_authority_gap)}`,
772
+ `- **Primary Gap**: ${scopedFormat(p[10].data.primary_authority_gap)}`,
757
773
  ``,
758
774
  `## 11. Backlink & Off-Page Authority Profile`,
759
775
  `- **Evidence Link**: \`${p[11].data.evidence_ref}\``,
760
776
  `- **Referring Domains**: ${formatVal(p[11].data.referring_domains)} (Authority Score: ${formatVal(p[11].data.authority_score)}/100)`,
761
- `- **Toxic Domains**: ${formatVal(p[11].data.toxic_domain_count)} flagged (\`${formatVal(p[11].data.disavow_recommendation)}\`)`,
777
+ `- **Toxic Domains**: ${formatVal(p[11].data.toxic_domain_count)} flagged (\`${scopedFormat(p[11].data.disavow_recommendation)}\`)`,
762
778
  ``,
763
779
  `## 12. Search Demand & Addressable Market Opportunity`,
764
780
  ];
@@ -782,11 +798,11 @@ export function renderSearchReportMarkdown(report) {
782
798
  `- **Assisted Conversions Share**: ${formatVal(p[13].data.assisted_conversions_share_pct, '%')}`,
783
799
  ``,
784
800
  `## 14. Measurement Integrity & Analytics Instrumentation`,
785
- `- **GA4 & GSC**: ${formatVal(p[14].data.ga4_instrumentation).toUpperCase()} / ${formatVal(p[14].data.gsc_property_binding).toUpperCase()}`,
801
+ `- **GA4 & GSC**: ${formatVal(scopedValue(p[14].data.ga4_instrumentation)).toUpperCase()} / ${formatVal(scopedValue(p[14].data.gsc_property_binding)).toUpperCase()}`,
786
802
  `- **Consent Mode Data Loss**: ${formatVal(p[14].data.consent_mode_v2_loss_pct, '%')}`,
787
803
  `- **Limitations**: ${(p[14].data.known_limitations || []).map((l) => sanitizeForMarkdown(l)).join('; ')}`,
788
804
  ``,
789
- `## 15. Verified Evidence Register (Traceability Engine)`,
805
+ `## 15. ${evidenceRegisterTitle}`,
790
806
  `| Evidence ID | Source | Methodology | Confidence | Observation Date |`,
791
807
  `| :--- | :--- | :--- | :--- | :--- |`,
792
808
  ...report.evidence_register.map((e) => `| **${e.evidence_id}** | \`${escapeMarkdownTableCell(e.source)}\` | ${escapeMarkdownTableCell((e.methodology || '').slice(0, 50))}... | \`${e.confidence_level}\` | ${e.observation_date} |`),
@@ -806,15 +822,30 @@ export function renderSearchReportMarkdown(report) {
806
822
  ``
807
823
  );
808
824
 
809
- return lines.join('\n');
825
+ const rendered = lines.join('\n');
826
+ assertEpistemicLanguage(rendered, { ...context, package_verified: context.package_verified === true });
827
+ return rendered;
810
828
  }
811
829
 
812
830
  /**
813
831
  * Render Search Executive Report as Standalone Enterprise HTML
814
832
  */
815
- export function renderSearchReportHtml(report) {
833
+ export function renderSearchReportHtml(report, evidenceContext = null) {
816
834
  const p = report.pillars;
817
- return `<!DOCTYPE html>
835
+ const context = evidenceContext || report.generation_provenance || {};
836
+ const verifiedScope = hasVerifiedEvidenceScope(context);
837
+ const evidenceRegisterTitle = verifiedScope
838
+ ? 'Verified Evidence Register'
839
+ : 'Evidence Register (scope-limited; verified status not established)';
840
+ const readinessLabel = verifiedScope ? (report.overall_readiness_score >= 70 ? 'Strong observed posture' : 'Needs optimization') : 'Not established';
841
+ const cwvLabel = verifiedScope && p[2].data.core_web_vitals?.render_blocking_scripts === 0 ? 'No flagged blockers' : 'Not established';
842
+ const scopedFormat = (value, suffix = '') => {
843
+ const rendered = formatVal(value, suffix);
844
+ return !verifiedScope && typeof rendered === 'string' && /\b(?:verified|clean|resolved|optimal|passed)\b|(?:verified_source|clean_profile)/i.test(rendered)
845
+ ? 'NOT ESTABLISHED'
846
+ : rendered;
847
+ };
848
+ const rendered = `<!DOCTYPE html>
818
849
  <html lang="en">
819
850
  <head>
820
851
  <meta charset="UTF-8">
@@ -861,12 +892,12 @@ export function renderSearchReportHtml(report) {
861
892
  <div class="card">
862
893
  <div style="font-size:12px; color:var(--muted); text-transform:uppercase;">Composite Search Readiness</div>
863
894
  <div class="card-num">${report.overall_readiness_score} / 100</div>
864
- <span class="badge ${report.overall_readiness_score >= 70 ? 'badge-success' : 'badge-warning'}">${report.overall_readiness_score >= 70 ? 'Optimal' : 'Needs Optimization'}</span>
895
+ <span class="badge ${verifiedScope && report.overall_readiness_score >= 70 ? 'badge-success' : 'badge-warning'}">${readinessLabel}</span>
865
896
  </div>
866
897
  <div class="card">
867
898
  <div style="font-size:12px; color:var(--muted); text-transform:uppercase;">AEO Direct Extraction</div>
868
899
  <div class="card-num">${formatVal(p[5].data.readiness_score)}</div>
869
- <span class="badge badge-success">${formatVal(p[5].data.status).toUpperCase()}</span>
900
+ <span class="badge badge-success">${scopedFormat(p[5].data.status).toUpperCase()}</span>
870
901
  </div>
871
902
  <div class="card">
872
903
  <div style="font-size:12px; color:var(--muted); text-transform:uppercase;">E-E-A-T Quality Score</div>
@@ -876,11 +907,11 @@ export function renderSearchReportHtml(report) {
876
907
  <div class="card">
877
908
  <div style="font-size:12px; color:var(--muted); text-transform:uppercase;">Core Web Vitals Blockers</div>
878
909
  <div class="card-num">${formatVal(p[2].data.core_web_vitals?.render_blocking_scripts)}</div>
879
- <span class="badge ${p[2].data.core_web_vitals?.render_blocking_scripts === 0 ? 'badge-success' : 'badge-danger'}">${p[2].data.core_web_vitals?.render_blocking_scripts === 0 ? 'Clean' : 'Action Required'}</span>
910
+ <span class="badge ${verifiedScope && p[2].data.core_web_vitals?.render_blocking_scripts === 0 ? 'badge-success' : 'badge-danger'}">${cwvLabel}</span>
880
911
  </div>
881
912
  </div>
882
913
 
883
- <h2 class="section-title">Verified Evidence Register (${report.evidence_register.length} Observations)</h2>
914
+ <h2 class="section-title">${evidenceRegisterTitle} (${report.evidence_register.length} Observations)</h2>
884
915
  <table>
885
916
  <thead>
886
917
  <tr>
@@ -915,6 +946,8 @@ export function renderSearchReportHtml(report) {
915
946
  </div>
916
947
  </body>
917
948
  </html>`;
949
+ assertEpistemicLanguage(rendered, { ...context, package_verified: context.package_verified === true });
950
+ return rendered;
918
951
  }
919
952
 
920
953
  /**
@@ -922,15 +955,16 @@ export function renderSearchReportHtml(report) {
922
955
  */
923
956
  export async function exportExecutiveSearchReport(root, options = {}) {
924
957
  const report = await buildExecutiveSearchReport(root, options);
958
+ const evidenceContext = report.generation_provenance;
925
959
  const format = options.format || 'markdown';
926
960
  let content = '';
927
961
 
928
962
  if (format === 'html' || format === 'html-brief') {
929
- content = renderSearchReportHtml(report);
963
+ content = renderSearchReportHtml(report, evidenceContext);
930
964
  } else if (format === 'json') {
931
965
  content = JSON.stringify(report, null, 2);
932
966
  } else {
933
- content = renderSearchReportMarkdown(report);
967
+ content = renderSearchReportMarkdown(report, evidenceContext);
934
968
  }
935
969
 
936
970
  let outputPath = null;
@@ -1,3 +1,5 @@
1
+ import { assertEpistemicLanguage, evidenceScopeStatement } from '../shared/epistemicLanguage.js';
2
+
1
3
  const SEV_ORDER = { critical: 0, high: 1, medium: 2, low: 3, informational: 4, experimental: 5 };
2
4
 
3
5
  const RETRIEVAL_NAMESPACES = new Set(['TECH', 'CRAWL', 'LINK', 'HREFLANG']);
@@ -39,7 +41,7 @@ function citationPosture(promptResults, targetOrigin) {
39
41
  };
40
42
  }
41
43
 
42
- export function summarize(findings, { detectorsRun = [], detectorsSkipped = [], promptResults = [], targetOrigin = null } = {}) {
44
+ export function summarize(findings, { detectorsRun = [], detectorsSkipped = [], promptResults = [], targetOrigin = null, coverage = null } = {}) {
43
45
  const bySeverity = {};
44
46
  const byNamespace = {};
45
47
  const byDiscipline = { seo: 0, aeo: 0, geo: 0 };
@@ -51,6 +53,18 @@ export function summarize(findings, { detectorsRun = [], detectorsSkipped = [],
51
53
  for (const d of f.discipline) byDiscipline[d] = (byDiscipline[d] || 0) + 1;
52
54
  if (f.classification.deterministic) deterministic++;
53
55
  }
56
+ const coverageIncomplete = coverage && coverage.coverage_status !== 'complete';
57
+ const posture = {
58
+ retrieval_eligibility: readinessPosture(findings, detectorsRun, detectorsSkipped, RETRIEVAL_NAMESPACES),
59
+ source_extraction_and_support: readinessPosture(findings, detectorsRun, detectorsSkipped, SOURCE_NAMESPACES),
60
+ observed_citation_behavior: citationPosture(promptResults, targetOrigin),
61
+ };
62
+ if (coverageIncomplete) {
63
+ for (const key of ['retrieval_eligibility', 'source_extraction_and_support']) {
64
+ posture[key].result = 'qualified';
65
+ posture[key].coverage_status = coverage.coverage_status;
66
+ }
67
+ }
54
68
  return {
55
69
  total: findings.length,
56
70
  deterministic_observations: deterministic,
@@ -58,15 +72,22 @@ export function summarize(findings, { detectorsRun = [], detectorsSkipped = [],
58
72
  by_severity: bySeverity,
59
73
  by_namespace: byNamespace,
60
74
  by_discipline: byDiscipline,
61
- posture: {
62
- retrieval_eligibility: readinessPosture(findings, detectorsRun, detectorsSkipped, RETRIEVAL_NAMESPACES),
63
- source_extraction_and_support: readinessPosture(findings, detectorsRun, detectorsSkipped, SOURCE_NAMESPACES),
64
- observed_citation_behavior: citationPosture(promptResults, targetOrigin),
65
- },
75
+ coverage: coverage ? {
76
+ status: coverage.coverage_status,
77
+ populations: coverage.populations,
78
+ stop_reason: coverage.stop_reason,
79
+ } : null,
80
+ posture,
66
81
  };
67
82
  }
68
83
 
69
- export function renderMarkdownReport({ findings, manifest, summary, detectorsSkipped = [] }) {
84
+ export function renderMarkdownReport({ findings, manifest, summary, detectorsSkipped = [], coverage = null, verifiedRun = null }) {
85
+ // Only the verified loader can establish package integrity. Manifest flags
86
+ // are part of the package input and therefore cannot establish their own
87
+ // trustworthiness when this renderer is called directly.
88
+ const packageVerified = verifiedRun?.verified === true
89
+ && verifiedRun?.integrity_mode === 'sealed'
90
+ && typeof verifiedRun?.verification_version === 'string';
70
91
  const lines = [];
71
92
  lines.push(`# Citable audit report`);
72
93
  lines.push('');
@@ -85,10 +106,18 @@ export function renderMarkdownReport({ findings, manifest, summary, detectorsSki
85
106
  lines.push(`| Total findings | ${summary.total} |`);
86
107
  lines.push(`| Deterministic observations | ${summary.deterministic_observations} |`);
87
108
  lines.push(`| Heuristic / semantic findings | ${summary.semantic_or_heuristic} |`);
109
+ if (coverage) {
110
+ lines.push(`| Coverage status | ${coverage.coverage_status} |`);
111
+ lines.push(`| Evaluated resources | ${coverage.populations.evaluated} of ${coverage.populations.discovered - coverage.populations.excluded} eligible |`);
112
+ }
88
113
  for (const [sev, n] of Object.entries(summary.by_severity).sort((a, b) => SEV_ORDER[a[0]] - SEV_ORDER[b[0]])) {
89
114
  lines.push(`| ${sev} | ${n} |`);
90
115
  }
91
116
  lines.push('');
117
+ if (coverage && coverage.coverage_status !== 'complete') {
118
+ lines.push(`> Coverage status: **${coverage.coverage_status}**. This report describes the observed corpus and does not establish a complete site-wide determination.`);
119
+ lines.push('');
120
+ }
92
121
  lines.push('## Separate eligibility and observation states');
93
122
  lines.push('');
94
123
  lines.push('| Dimension | Result | Evidence |');
@@ -132,8 +161,26 @@ export function renderMarkdownReport({ findings, manifest, summary, detectorsSki
132
161
  lines.push('');
133
162
  }
134
163
  if (findings.length === 0) {
135
- lines.push(`No findings from the executed detectors. Absence of findings is not proof of eligibility — see skipped and incomplete checks above.`);
164
+ const population = coverage?.populations?.evaluated ?? 0;
165
+ lines.push(population > 0
166
+ ? `No findings were produced for the ${population} successfully evaluated resource(s). Absence of findings is not proof of eligibility — see skipped and incomplete checks above.`
167
+ : evidenceScopeStatement({
168
+ coverage_status: coverage?.coverage_status || 'indeterminate',
169
+ determination_status: summary?.posture?.source_extraction_and_support?.result === 'pass' ? 'supported' : 'indeterminate',
170
+ evaluated: 0,
171
+ eligible: coverage?.populations?.eligible ?? 0,
172
+ legacy: !coverage,
173
+ }));
136
174
  lines.push('');
137
175
  }
138
- return lines.join('\n');
176
+ const rendered = lines.join('\n');
177
+ assertEpistemicLanguage(rendered, {
178
+ coverage_status: coverage?.coverage_status || 'indeterminate',
179
+ determination_status: coverage?.coverage_status === 'complete' ? 'supported' : 'indeterminate',
180
+ evaluated: coverage?.populations?.evaluated ?? 0,
181
+ eligible: coverage?.populations?.eligible ?? 0,
182
+ package_verified: packageVerified,
183
+ legacy: verifiedRun?.legacy === true || !coverage,
184
+ });
185
+ return rendered;
139
186
  }
@@ -0,0 +1,117 @@
1
+ import { canonicalEvidenceJson } from '../evidence/hashes.js';
2
+ import { sha256 } from '../shared/io.js';
3
+ import { validateAgainst } from '../shared/schemaValidator.js';
4
+
5
+ const PROMPT_SCHEMA = 'prompt-set.schema.json';
6
+
7
+ function without(value, key) {
8
+ const copy = { ...value };
9
+ delete copy[key];
10
+ return copy;
11
+ }
12
+
13
+ function promptId({ prompt_text, context = null, locale = null }) {
14
+ return `PROMPT-${sha256(canonicalEvidenceJson({ prompt_text, context, locale })).slice(0, 24)}`;
15
+ }
16
+
17
+ export function createPrompt(input) {
18
+ if (!input || typeof input.prompt_text !== 'string' || !input.prompt_text.trim()) throw new TypeError('prompt_text is required');
19
+ const prompt = {
20
+ prompt_id: input.prompt_id || promptId(input),
21
+ prompt_text: input.prompt_text,
22
+ ...(input.context == null ? {} : { context: input.context }),
23
+ ...(input.locale == null ? {} : { locale: input.locale }),
24
+ };
25
+ return prompt;
26
+ }
27
+
28
+ function normalizeIncluded(prompts = []) {
29
+ if (!Array.isArray(prompts)) throw new TypeError('included_prompts must be an array');
30
+ const normalized = prompts.map(createPrompt);
31
+ const ids = new Set();
32
+ for (const item of normalized) {
33
+ if (ids.has(item.prompt_id)) throw new Error(`duplicate prompt_id: ${item.prompt_id}`);
34
+ ids.add(item.prompt_id);
35
+ }
36
+ return normalized.sort((left, right) => left.prompt_id.localeCompare(right.prompt_id));
37
+ }
38
+
39
+ function normalizeExcluded(prompts = []) {
40
+ if (!Array.isArray(prompts)) throw new TypeError('excluded_prompts must be an array');
41
+ return prompts.map((item) => ({
42
+ prompt_id: item.prompt_id || promptId(item),
43
+ ...(item.prompt_text == null ? {} : { prompt_text: item.prompt_text }),
44
+ exclusion_reason: item.exclusion_reason,
45
+ })).sort((left, right) => left.prompt_id.localeCompare(right.prompt_id));
46
+ }
47
+
48
+ function hashPromptSet(item) {
49
+ const value = without(item, 'prompt_set_hash');
50
+ return sha256(canonicalEvidenceJson({
51
+ ...value,
52
+ included_prompts: [...(value.included_prompts || [])].sort((left, right) => left.prompt_id.localeCompare(right.prompt_id)),
53
+ excluded_prompts: [...(value.excluded_prompts || [])].sort((left, right) => left.prompt_id.localeCompare(right.prompt_id)),
54
+ }));
55
+ }
56
+
57
+ export function createPromptSet(input, { previous = null } = {}) {
58
+ if (!input || typeof input.prompt_set_id !== 'string' || !input.prompt_set_id) throw new TypeError('prompt_set_id is required');
59
+ if (!Number.isInteger(input.prompt_set_version) || input.prompt_set_version < 1) throw new TypeError('prompt_set_version must be a positive integer');
60
+ const included = normalizeIncluded(input.included_prompts);
61
+ const excluded = normalizeExcluded(input.excluded_prompts || []);
62
+ const item = {
63
+ prompt_set_id: input.prompt_set_id,
64
+ prompt_set_version: input.prompt_set_version,
65
+ purpose: input.purpose,
66
+ generation_method: input.generation_method,
67
+ generation_method_version: input.generation_method_version ?? null,
68
+ generation_input: input.generation_input ?? null,
69
+ generated_at: input.generated_at,
70
+ population_size: included.length,
71
+ sampling_method: input.sampling_method,
72
+ included_prompts: included,
73
+ excluded_prompts: excluded,
74
+ intended_population: input.intended_population,
75
+ limitations: [...new Set(input.limitations || [])],
76
+ };
77
+ item.prompt_set_hash = hashPromptSet(item);
78
+ const check = validateAgainst(PROMPT_SCHEMA, item);
79
+ if (!check.valid) throw new TypeError(`prompt set violates contract: ${check.errors.join('; ')}`);
80
+ if (previous && previous.prompt_set_id === item.prompt_set_id && previous.prompt_set_version === item.prompt_set_version && previous.prompt_set_hash !== item.prompt_set_hash) {
81
+ throw new Error('prompt set version is immutable; create a new prompt_set_version');
82
+ }
83
+ return item;
84
+ }
85
+
86
+ export function verifyPromptSet(item, { previous = null } = {}) {
87
+ const failures = [];
88
+ const check = validateAgainst(PROMPT_SCHEMA, item);
89
+ if (!check.valid) failures.push(...check.errors);
90
+ if (item?.prompt_set_hash !== hashPromptSet(item || {})) failures.push('prompt set hash is inconsistent');
91
+ if (previous && previous.prompt_set_id === item?.prompt_set_id && previous.prompt_set_version === item?.prompt_set_version && previous.prompt_set_hash !== item?.prompt_set_hash) failures.push('prompt set version is immutable');
92
+ return { valid: failures.length === 0, failures };
93
+ }
94
+
95
+ export function promptReference(promptSet, promptIdValue) {
96
+ if (!verifyPromptSet(promptSet).valid) throw new Error('cannot reference an unverifiable prompt set');
97
+ const prompt = promptSet.included_prompts.find((item) => item.prompt_id === promptIdValue);
98
+ if (!prompt) throw new Error(`prompt ${promptIdValue} is not included in prompt set ${promptSet.prompt_set_id}@${promptSet.prompt_set_version}`);
99
+ return `${promptSet.prompt_set_id}@${promptSet.prompt_set_version}:${prompt.prompt_id}`;
100
+ }
101
+
102
+ export function comparePromptSets(left, right) {
103
+ const validLeft = verifyPromptSet(left).valid;
104
+ const validRight = verifyPromptSet(right).valid;
105
+ if (!validLeft || !validRight) return { status: 'INDETERMINATE', dimensions: {}, limitations: ['Prompt-set integrity could not be verified.'] };
106
+ const dimensions = {
107
+ prompt_set_id: left.prompt_set_id === right.prompt_set_id ? 'match' : 'mismatch',
108
+ prompt_set_version: left.prompt_set_version === right.prompt_set_version ? 'match' : 'mismatch',
109
+ population: left.population_size === right.population_size ? 'match' : 'mismatch',
110
+ sampling_method: left.sampling_method === right.sampling_method ? 'match' : 'mismatch',
111
+ };
112
+ const status = dimensions.prompt_set_id === 'match' && dimensions.prompt_set_version === 'match' && dimensions.population === 'match' && dimensions.sampling_method === 'match'
113
+ ? 'COMPARABLE' : 'NOT_COMPARABLE';
114
+ return { status, left_reference: `${left.prompt_set_id}@${left.prompt_set_version}`, right_reference: `${right.prompt_set_id}@${right.prompt_set_version}`, dimensions, limitations: status === 'COMPARABLE' ? [] : ['Prompt population, sampling, or version changed; no denominator is reused silently.'] };
115
+ }
116
+
117
+ export { promptId };
@@ -0,0 +1,186 @@
1
+ import { createExternalObservation, verifyExternalObservation } from '../evidence/external.js';
2
+ import { canonicalEvidenceJson } from '../evidence/hashes.js';
3
+ import { sha256, nowIso } from '../shared/io.js';
4
+ import { validateAgainst } from '../shared/schemaValidator.js';
5
+ import { verifyPromptSet, promptReference } from './prompts.js';
6
+
7
+ const REPRESENTATION_SCHEMA = 'representation-data.schema.json';
8
+ const COLLECTOR = { id: 'citable-representation-observations', version: '1.0.0' };
9
+ const PARSER = { id: 'provider-neutral-representation-parser', version: '1.0.0' };
10
+
11
+ function responseHash(rawResponse, response) {
12
+ return sha256(typeof rawResponse === 'string' ? rawResponse : canonicalEvidenceJson(response ?? null));
13
+ }
14
+
15
+ function modelIdentity(model) {
16
+ if (model && typeof model === 'string') return { value: model, status: 'known' };
17
+ if (model && typeof model === 'object' && ['known', 'UNKNOWN', 'UNAVAILABLE', 'NOT_DISCLOSED'].includes(model.status)) return { value: model.value ?? null, status: model.status };
18
+ return { value: null, status: 'UNKNOWN' };
19
+ }
20
+
21
+ function hostOf(value) {
22
+ try { return new URL(value).hostname.toLowerCase(); } catch { return null; }
23
+ }
24
+
25
+ function normalizeUrls(value) {
26
+ if (!Array.isArray(value)) throw new TypeError('provider citations must be an array');
27
+ const urls = value.map((item) => typeof item === 'string' ? item : item?.url);
28
+ if (urls.some((item) => typeof item !== 'string' || !hostOf(item))) throw new TypeError('provider citation URL is malformed');
29
+ return [...new Set(urls)];
30
+ }
31
+
32
+ const SENSITIVE_KEY = /(^|[-_])(authorization|cookie|set-cookie|access[-_]?token|refresh[-_]?token|api[-_]?key|password|secret)($|[-_])/i;
33
+
34
+ function safeMetadata(value, depth = 0) {
35
+ if (depth > 4 || value == null) return value == null ? null : '[bounded]';
36
+ if (Array.isArray(value)) return value.slice(0, 50).map((item) => safeMetadata(item, depth + 1));
37
+ if (typeof value !== 'object') return typeof value === 'string' ? value.slice(0, 500) : value;
38
+ return Object.fromEntries(Object.entries(value).slice(0, 50).filter(([key]) => !SENSITIVE_KEY.test(key)).map(([key, item]) => [key, safeMetadata(item, depth + 1)]));
39
+ }
40
+
41
+ function executionStatusFor(status) {
42
+ if (status === 'succeeded') return { observation_status: 'observed', retrieval_status: 'retrieved' };
43
+ if (status === 'malformed' || status === 'parser_failed') return { observation_status: 'indeterminate', retrieval_status: 'indeterminate' };
44
+ return { observation_status: 'failed', retrieval_status: 'failed' };
45
+ }
46
+
47
+ function parserErrorObservation({ provider, product, surface, prompt, promptSet, executionConfiguration, model, evidenceOrigin, executedAt, rawResponse, status, errorMessage }) {
48
+ const hash = responseHash(rawResponse, null);
49
+ const execution = executionConfiguration || { id: 'default', version: '1.0.0' };
50
+ const state = executionStatusFor(status);
51
+ return createRepresentationObservation({
52
+ provider, product, surface, prompt, promptSet, executionConfiguration: execution, model, evidenceOrigin, executedAt,
53
+ response: { status, response_hash: hash, parser: PARSER, raw_response_retained: false, provider_metadata: {} },
54
+ representation: { brand_mentioned: null, domain_mentioned: null, domain_cited: null, cited_urls: [], mentioned_entities: [], cited_domains: [] },
55
+ observationStatus: state.observation_status, retrievalStatus: state.retrieval_status,
56
+ limitations: [`Representation response could not be normalized: ${String(errorMessage || status).slice(0, 240)}`, 'Raw provider response is not retained; response_hash is retained for identity.'],
57
+ });
58
+ }
59
+
60
+ export function createRepresentationObservation({ provider, product, surface, prompt, promptSet, executionConfiguration, model, evidenceOrigin, executedAt = nowIso(), response, representation, observationStatus = 'observed', retrievalStatus = 'retrieved', limitations = [] }) {
61
+ if (!provider || !product || !surface) throw new TypeError('provider, product, and surface are required');
62
+ if (!prompt || !prompt.prompt_id || !prompt.prompt_text) throw new TypeError('prompt identity and text are required');
63
+ if (!promptSet || !verifyPromptSet(promptSet).valid) throw new TypeError('prompt set is missing or unverifiable');
64
+ if (!promptSet.included_prompts.some((item) => item.prompt_id === prompt.prompt_id)) throw new Error(`prompt ${prompt.prompt_id} is not included in the prompt set`);
65
+ if (!['LIVE_PROVIDER', 'RECORDED_FIXTURE', 'SYNTHETIC_TEST'].includes(evidenceOrigin)) throw new TypeError('evidenceOrigin is invalid');
66
+ const config = executionConfiguration || { id: 'default', version: '1.0.0' };
67
+ const normalizedModel = modelIdentity(model);
68
+ const data = {
69
+ provider,
70
+ product,
71
+ surface,
72
+ model: normalizedModel,
73
+ prompt: { prompt_id: prompt.prompt_id, prompt_version: promptSet.prompt_set_version, prompt_text: prompt.prompt_text },
74
+ prompt_set: { prompt_set_id: promptSet.prompt_set_id, prompt_set_version: promptSet.prompt_set_version },
75
+ execution: { executed_at: executedAt, configuration: config },
76
+ response,
77
+ representation,
78
+ evidence_origin: evidenceOrigin,
79
+ limitations: [...new Set(limitations)],
80
+ };
81
+ const check = validateAgainst(REPRESENTATION_SCHEMA, data);
82
+ if (!check.valid) throw new TypeError(`representation data violates contract: ${check.errors.join('; ')}`);
83
+ const state = executionStatusFor(response.status);
84
+ const observation = createExternalObservation({
85
+ observation_id: `REP-${sha256(canonicalEvidenceJson({ provider, product, surface, prompt, promptSet: promptSet.prompt_set_hash, executedAt, response })).slice(0, 24)}`,
86
+ observation_type: 'EXTERNAL_OBSERVATION',
87
+ subject: { type: 'prompt_execution', id: promptReference(promptSet, prompt.prompt_id) },
88
+ source: { provider, method: 'representation_adapter', authority: 'external_provider' },
89
+ collector: COLLECTOR,
90
+ parser: PARSER,
91
+ configuration: config,
92
+ observed_at: executedAt,
93
+ retrieved_at: executedAt,
94
+ executed_at: executedAt,
95
+ population: { declared: { id: `${promptSet.prompt_set_id}@${promptSet.prompt_set_version}`, size: promptSet.population_size }, observed: 1, retrieved: response.status === 'succeeded' ? 1 : 0, evaluated: response.status === 'succeeded' ? 1 : 0, unavailable: response.status === 'unavailable' ? 1 : 0, failed: response.status === 'succeeded' ? 0 : 1 },
96
+ observation_status: observationStatus || state.observation_status,
97
+ retrieval_status: retrievalStatus || state.retrieval_status,
98
+ data,
99
+ lineage: { source_evidence: response.response_hash ? [response.response_hash] : [] },
100
+ limitations: data.limitations,
101
+ });
102
+ return observation;
103
+ }
104
+
105
+ export function normalizeRepresentationResponse({ provider, product, surface, prompt, promptSet, executionConfiguration, model, response, rawResponse = null, evidenceOrigin = 'RECORDED_FIXTURE', executedAt = nowIso(), brand = null, firstPartyDomains = [], retainRawResponse = false }) {
106
+ const base = { provider, product, surface, prompt, promptSet, executionConfiguration, model, evidenceOrigin, executedAt };
107
+ const rawHash = responseHash(rawResponse, response);
108
+ try {
109
+ if (!response || typeof response !== 'object' || Array.isArray(response)) throw new TypeError('provider response must be an object');
110
+ const answerText = response.answer_text ?? response.answer ?? response.text;
111
+ if (typeof answerText !== 'string') throw new TypeError('provider response requires answer_text');
112
+ const citations = normalizeUrls(response.citations || []);
113
+ const mentionedEntities = Array.isArray(response.mentions) ? response.mentions.filter((item) => typeof item === 'string') : [];
114
+ const firstParty = new Set(firstPartyDomains.map((item) => String(item).toLowerCase()));
115
+ const citedDomains = [...new Set(citations.map(hostOf).filter(Boolean))];
116
+ const domainMentioned = firstParty.size ? [...firstParty].some((domain) => answerText.toLowerCase().includes(domain)) : null;
117
+ const domainCited = firstParty.size ? citedDomains.some((domain) => firstParty.has(domain)) : null;
118
+ const brandMentioned = typeof brand === 'string' ? answerText.toLowerCase().includes(brand.toLowerCase()) : null;
119
+ return createRepresentationObservation({
120
+ ...base,
121
+ response: { status: 'succeeded', response_hash: rawHash, parser: PARSER, raw_response_retained: retainRawResponse, provider_metadata: { ...safeMetadata(response.provider_metadata || {}), ...(retainRawResponse ? { raw_response: rawResponse ?? response } : {}) } },
122
+ representation: { brand_mentioned: brandMentioned, domain_mentioned: domainMentioned, domain_cited: domainCited, cited_urls: citations, mentioned_entities: mentionedEntities, cited_domains: citedDomains },
123
+ limitations: retainRawResponse ? [] : ['Raw provider response is not retained; response_hash is retained for identity.'],
124
+ });
125
+ } catch (error) {
126
+ return parserErrorObservation({ ...base, rawResponse, status: 'parser_failed', errorMessage: error.message });
127
+ }
128
+ }
129
+
130
+ export async function collectRepresentationObservations({ promptSet, adapter, provider, product = 'unknown', surface = 'unknown', model = null, executionConfiguration = { id: 'default', version: '1.0.0' }, evidenceOrigin = 'LIVE_PROVIDER', brand = null, firstPartyDomains = [] } = {}) {
131
+ if (!promptSet || !verifyPromptSet(promptSet).valid) throw new TypeError('prompt set is missing or unverifiable');
132
+ if (typeof adapter !== 'function') throw new TypeError('representation adapter is required');
133
+ const observations = [];
134
+ for (const prompt of promptSet.included_prompts) {
135
+ const executedAt = nowIso();
136
+ try {
137
+ const result = await adapter(prompt, { provider, product, surface, model, promptSet, executionConfiguration });
138
+ if (!result || typeof result !== 'object') throw new Error('adapter returned an invalid result');
139
+ const status = result.status || 'succeeded';
140
+ if (status !== 'succeeded') {
141
+ observations.push(parserErrorObservation({ provider, product, surface, prompt, promptSet, executionConfiguration, model, evidenceOrigin, executedAt, rawResponse: result.raw ?? result.body ?? null, status, errorMessage: result.error || status }));
142
+ } else {
143
+ observations.push(normalizeRepresentationResponse({ provider, product, surface, prompt, promptSet, executionConfiguration, model, response: result.body ?? result.response ?? result, rawResponse: result.raw ?? null, evidenceOrigin, executedAt, brand, firstPartyDomains }));
144
+ }
145
+ } catch (error) {
146
+ observations.push(parserErrorObservation({ provider, product, surface, prompt, promptSet, executionConfiguration, model, evidenceOrigin, executedAt, rawResponse: null, status: error.connectorState === 'quota_limited' ? 'rate_limited' : error.name === 'AbortError' ? 'timeout' : 'error', errorMessage: error.message }));
147
+ }
148
+ }
149
+ return { observations, coverage: { declared: promptSet.population_size, executed: observations.filter((item) => item.data.response.status === 'succeeded').length, failed: observations.filter((item) => item.data.response.status !== 'succeeded').length, coverage_status: observations.every((item) => item.data.response.status === 'succeeded') ? 'complete_for_declared_prompt_set' : 'incomplete' }, prompt_set_reference: `${promptSet.prompt_set_id}@${promptSet.prompt_set_version}` };
150
+ }
151
+
152
+ export function createHttpRepresentationAdapter({ endpoint, fetchImpl = globalThis.fetch, accessToken = null } = {}) {
153
+ if (typeof endpoint !== 'string' || !/^https:\/\//.test(endpoint)) throw new TypeError('representation adapter endpoint must use HTTPS');
154
+ return async (prompt) => {
155
+ const response = await fetchImpl(endpoint, { method: 'POST', redirect: 'error', headers: { accept: 'application/json', 'content-type': 'application/json', ...(accessToken ? { authorization: `Bearer ${accessToken}` } : {}) }, body: JSON.stringify({ prompt_id: prompt.prompt_id, prompt_text: prompt.prompt_text }) });
156
+ const raw = await response.text();
157
+ if (!response.ok) {
158
+ const status = response.status === 429 ? 'rate_limited' : response.status === 408 ? 'timeout' : response.status >= 500 ? 'unavailable' : 'refused';
159
+ return { status, raw, error: `provider returned ${response.status}` };
160
+ }
161
+ let body;
162
+ try { body = JSON.parse(raw); } catch { return { status: 'malformed', raw, error: 'provider response was not valid JSON' }; }
163
+ return { status: 'succeeded', body, raw };
164
+ };
165
+ }
166
+
167
+ export function verifyRepresentationObservation(item) {
168
+ return verifyExternalObservation(item);
169
+ }
170
+
171
+ export function compareRepresentationObservations(left, right) {
172
+ if (!verifyExternalObservation(left).valid || !verifyExternalObservation(right).valid) return { status: 'INDETERMINATE', dimensions: {}, limitations: ['Representation observation integrity could not be verified.'] };
173
+ const dimensions = {
174
+ provider: left.data.provider === right.data.provider ? 'match' : 'mismatch',
175
+ product: left.data.product === right.data.product ? 'match' : 'mismatch',
176
+ surface: left.data.surface === right.data.surface ? 'match' : 'mismatch',
177
+ model: left.data.model.status !== 'known' || right.data.model.status !== 'known' ? 'missing' : left.data.model.value === right.data.model.value ? 'match' : 'mismatch',
178
+ prompt: left.data.prompt.prompt_id === right.data.prompt.prompt_id && left.data.prompt.prompt_text === right.data.prompt.prompt_text ? 'match' : 'mismatch',
179
+ prompt_set: left.data.prompt_set.prompt_set_id === right.data.prompt_set.prompt_set_id && left.data.prompt_set.prompt_set_version === right.data.prompt_set.prompt_set_version ? 'match' : 'mismatch',
180
+ configuration: left.data.execution.configuration.id === right.data.execution.configuration.id && left.data.execution.configuration.version === right.data.execution.configuration.version ? 'match' : 'mismatch',
181
+ parser: left.data.response.parser.id === right.data.response.parser.id && left.data.response.parser.version === right.data.response.parser.version ? 'match' : 'mismatch',
182
+ };
183
+ const hardMismatch = ['provider', 'product', 'surface', 'prompt', 'prompt_set', 'configuration', 'parser'].some((key) => dimensions[key] === 'mismatch');
184
+ const status = hardMismatch ? 'NOT_COMPARABLE' : dimensions.model === 'mismatch' ? 'NOT_COMPARABLE' : dimensions.model === 'missing' ? 'PARTIALLY_COMPARABLE' : 'COMPARABLE';
185
+ return { comparison_id: `REP-CMP-${sha256(canonicalEvidenceJson({ left: left.observation_id, right: right.observation_id, dimensions })).slice(0, 16)}`, left_reference: left.observation_id, right_reference: right.observation_id, status, dimensions, limitations: status === 'COMPARABLE' ? [] : ['Provider, model, prompt, execution, and parser identity remain explicit; no visibility delta is inferred from non-comparable observations.'] };
186
+ }