@nebulacomponents/citable 1.13.1 → 1.15.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 (359) hide show
  1. package/CHANGELOG.md +312 -0
  2. package/README.md +44 -6
  3. package/dist/universal/.agents/skills/citable/SKILL.md +22 -8
  4. package/dist/universal/.agents/skills/citable/VERSION +1 -1
  5. package/dist/universal/.agents/skills/citable/agents/citable-auditor.md +64 -0
  6. package/dist/universal/.agents/skills/citable/agents/citable-semantic-reviewer.md +66 -0
  7. package/dist/universal/.agents/skills/citable/commands/README.md +4 -1
  8. package/dist/universal/.agents/skills/citable/commands/action-findings.md +9 -1
  9. package/dist/universal/.agents/skills/citable/commands/observe-and-act.md +62 -8
  10. package/dist/universal/.agents/skills/citable/commands/plan-audit.md +35 -0
  11. package/dist/universal/.agents/skills/citable/commands/reporting.md +57 -0
  12. package/dist/universal/.agents/skills/citable/manifest.json +29 -16
  13. package/dist/universal/.agents/skills/citable/schemas/action-plan.schema.json +13 -0
  14. package/dist/universal/.agents/skills/citable/schemas/browser-evidence-plan.schema.json +14 -0
  15. package/dist/universal/.agents/skills/citable/schemas/canonical-index-import.schema.json +30 -0
  16. package/dist/universal/.agents/skills/citable/schemas/common.defs.json +12 -1
  17. package/dist/universal/.agents/skills/citable/schemas/corroboration-import.schema.json +48 -0
  18. package/dist/universal/.agents/skills/citable/schemas/entity-graph.schema.json +75 -0
  19. package/dist/universal/.agents/skills/citable/schemas/entity.schema.json +13 -0
  20. package/dist/universal/.agents/skills/citable/schemas/observation.schema.json +1 -1
  21. package/dist/universal/.agents/skills/citable/schemas/page.schema.json +3 -0
  22. package/dist/universal/.agents/skills/citable/schemas/regional-network-import.schema.json +55 -0
  23. package/dist/universal/.agents/skills/citable/schemas/schedule.schema.json +1 -1
  24. package/dist/universal/.agents/skills/citable/schemas/source-identity-chain.schema.json +83 -0
  25. package/dist/universal/.agents/skills/citable/scripts/README.md +3 -1
  26. package/dist/universal/.claude/agents/citable/citable-auditor.md +64 -0
  27. package/dist/universal/.claude/agents/citable/citable-semantic-reviewer.md +66 -0
  28. package/dist/universal/.claude/agents/citable/manifest.json +12 -0
  29. package/dist/universal/.claude/skills/citable/SKILL.md +22 -8
  30. package/dist/universal/.claude/skills/citable/VERSION +1 -1
  31. package/dist/universal/.claude/skills/citable/agents/citable-auditor.md +64 -0
  32. package/dist/universal/.claude/skills/citable/agents/citable-semantic-reviewer.md +66 -0
  33. package/dist/universal/.claude/skills/citable/commands/README.md +4 -1
  34. package/dist/universal/.claude/skills/citable/commands/action-findings.md +9 -1
  35. package/dist/universal/.claude/skills/citable/commands/observe-and-act.md +62 -8
  36. package/dist/universal/.claude/skills/citable/commands/plan-audit.md +35 -0
  37. package/dist/universal/.claude/skills/citable/commands/reporting.md +57 -0
  38. package/dist/universal/.claude/skills/citable/manifest.json +34 -16
  39. package/dist/universal/.claude/skills/citable/schemas/action-plan.schema.json +13 -0
  40. package/dist/universal/.claude/skills/citable/schemas/browser-evidence-plan.schema.json +14 -0
  41. package/dist/universal/.claude/skills/citable/schemas/canonical-index-import.schema.json +30 -0
  42. package/dist/universal/.claude/skills/citable/schemas/common.defs.json +12 -1
  43. package/dist/universal/.claude/skills/citable/schemas/corroboration-import.schema.json +48 -0
  44. package/dist/universal/.claude/skills/citable/schemas/entity-graph.schema.json +75 -0
  45. package/dist/universal/.claude/skills/citable/schemas/entity.schema.json +13 -0
  46. package/dist/universal/.claude/skills/citable/schemas/observation.schema.json +1 -1
  47. package/dist/universal/.claude/skills/citable/schemas/page.schema.json +3 -0
  48. package/dist/universal/.claude/skills/citable/schemas/regional-network-import.schema.json +55 -0
  49. package/dist/universal/.claude/skills/citable/schemas/schedule.schema.json +1 -1
  50. package/dist/universal/.claude/skills/citable/schemas/source-identity-chain.schema.json +83 -0
  51. package/dist/universal/.claude/skills/citable/scripts/README.md +3 -1
  52. package/dist/universal/.cursor/skills/citable/SKILL.md +22 -8
  53. package/dist/universal/.cursor/skills/citable/VERSION +1 -1
  54. package/dist/universal/.cursor/skills/citable/agents/citable-auditor.md +64 -0
  55. package/dist/universal/.cursor/skills/citable/agents/citable-semantic-reviewer.md +66 -0
  56. package/dist/universal/.cursor/skills/citable/commands/README.md +4 -1
  57. package/dist/universal/.cursor/skills/citable/commands/action-findings.md +9 -1
  58. package/dist/universal/.cursor/skills/citable/commands/observe-and-act.md +62 -8
  59. package/dist/universal/.cursor/skills/citable/commands/plan-audit.md +35 -0
  60. package/dist/universal/.cursor/skills/citable/commands/reporting.md +57 -0
  61. package/dist/universal/.cursor/skills/citable/manifest.json +29 -16
  62. package/dist/universal/.cursor/skills/citable/schemas/action-plan.schema.json +13 -0
  63. package/dist/universal/.cursor/skills/citable/schemas/browser-evidence-plan.schema.json +14 -0
  64. package/dist/universal/.cursor/skills/citable/schemas/canonical-index-import.schema.json +30 -0
  65. package/dist/universal/.cursor/skills/citable/schemas/common.defs.json +12 -1
  66. package/dist/universal/.cursor/skills/citable/schemas/corroboration-import.schema.json +48 -0
  67. package/dist/universal/.cursor/skills/citable/schemas/entity-graph.schema.json +75 -0
  68. package/dist/universal/.cursor/skills/citable/schemas/entity.schema.json +13 -0
  69. package/dist/universal/.cursor/skills/citable/schemas/observation.schema.json +1 -1
  70. package/dist/universal/.cursor/skills/citable/schemas/page.schema.json +3 -0
  71. package/dist/universal/.cursor/skills/citable/schemas/regional-network-import.schema.json +55 -0
  72. package/dist/universal/.cursor/skills/citable/schemas/schedule.schema.json +1 -1
  73. package/dist/universal/.cursor/skills/citable/schemas/source-identity-chain.schema.json +83 -0
  74. package/dist/universal/.cursor/skills/citable/scripts/README.md +3 -1
  75. package/dist/universal/.gemini/skills/citable/SKILL.md +22 -8
  76. package/dist/universal/.gemini/skills/citable/VERSION +1 -1
  77. package/dist/universal/.gemini/skills/citable/agents/citable-auditor.md +64 -0
  78. package/dist/universal/.gemini/skills/citable/agents/citable-semantic-reviewer.md +66 -0
  79. package/dist/universal/.gemini/skills/citable/commands/README.md +4 -1
  80. package/dist/universal/.gemini/skills/citable/commands/action-findings.md +9 -1
  81. package/dist/universal/.gemini/skills/citable/commands/observe-and-act.md +62 -8
  82. package/dist/universal/.gemini/skills/citable/commands/plan-audit.md +35 -0
  83. package/dist/universal/.gemini/skills/citable/commands/reporting.md +57 -0
  84. package/dist/universal/.gemini/skills/citable/manifest.json +29 -16
  85. package/dist/universal/.gemini/skills/citable/schemas/action-plan.schema.json +13 -0
  86. package/dist/universal/.gemini/skills/citable/schemas/browser-evidence-plan.schema.json +14 -0
  87. package/dist/universal/.gemini/skills/citable/schemas/canonical-index-import.schema.json +30 -0
  88. package/dist/universal/.gemini/skills/citable/schemas/common.defs.json +12 -1
  89. package/dist/universal/.gemini/skills/citable/schemas/corroboration-import.schema.json +48 -0
  90. package/dist/universal/.gemini/skills/citable/schemas/entity-graph.schema.json +75 -0
  91. package/dist/universal/.gemini/skills/citable/schemas/entity.schema.json +13 -0
  92. package/dist/universal/.gemini/skills/citable/schemas/observation.schema.json +1 -1
  93. package/dist/universal/.gemini/skills/citable/schemas/page.schema.json +3 -0
  94. package/dist/universal/.gemini/skills/citable/schemas/regional-network-import.schema.json +55 -0
  95. package/dist/universal/.gemini/skills/citable/schemas/schedule.schema.json +1 -1
  96. package/dist/universal/.gemini/skills/citable/schemas/source-identity-chain.schema.json +83 -0
  97. package/dist/universal/.gemini/skills/citable/scripts/README.md +3 -1
  98. package/dist/universal/.github/skills/citable/SKILL.md +22 -8
  99. package/dist/universal/.github/skills/citable/VERSION +1 -1
  100. package/dist/universal/.github/skills/citable/agents/citable-auditor.md +64 -0
  101. package/dist/universal/.github/skills/citable/agents/citable-semantic-reviewer.md +66 -0
  102. package/dist/universal/.github/skills/citable/commands/README.md +4 -1
  103. package/dist/universal/.github/skills/citable/commands/action-findings.md +9 -1
  104. package/dist/universal/.github/skills/citable/commands/observe-and-act.md +62 -8
  105. package/dist/universal/.github/skills/citable/commands/plan-audit.md +35 -0
  106. package/dist/universal/.github/skills/citable/commands/reporting.md +57 -0
  107. package/dist/universal/.github/skills/citable/manifest.json +29 -16
  108. package/dist/universal/.github/skills/citable/schemas/action-plan.schema.json +13 -0
  109. package/dist/universal/.github/skills/citable/schemas/browser-evidence-plan.schema.json +14 -0
  110. package/dist/universal/.github/skills/citable/schemas/canonical-index-import.schema.json +30 -0
  111. package/dist/universal/.github/skills/citable/schemas/common.defs.json +12 -1
  112. package/dist/universal/.github/skills/citable/schemas/corroboration-import.schema.json +48 -0
  113. package/dist/universal/.github/skills/citable/schemas/entity-graph.schema.json +75 -0
  114. package/dist/universal/.github/skills/citable/schemas/entity.schema.json +13 -0
  115. package/dist/universal/.github/skills/citable/schemas/observation.schema.json +1 -1
  116. package/dist/universal/.github/skills/citable/schemas/page.schema.json +3 -0
  117. package/dist/universal/.github/skills/citable/schemas/regional-network-import.schema.json +55 -0
  118. package/dist/universal/.github/skills/citable/schemas/schedule.schema.json +1 -1
  119. package/dist/universal/.github/skills/citable/schemas/source-identity-chain.schema.json +83 -0
  120. package/dist/universal/.github/skills/citable/scripts/README.md +3 -1
  121. package/dist/universal/.kiro/skills/citable/SKILL.md +22 -8
  122. package/dist/universal/.kiro/skills/citable/VERSION +1 -1
  123. package/dist/universal/.kiro/skills/citable/agents/citable-auditor.md +64 -0
  124. package/dist/universal/.kiro/skills/citable/agents/citable-semantic-reviewer.md +66 -0
  125. package/dist/universal/.kiro/skills/citable/commands/README.md +4 -1
  126. package/dist/universal/.kiro/skills/citable/commands/action-findings.md +9 -1
  127. package/dist/universal/.kiro/skills/citable/commands/observe-and-act.md +62 -8
  128. package/dist/universal/.kiro/skills/citable/commands/plan-audit.md +35 -0
  129. package/dist/universal/.kiro/skills/citable/commands/reporting.md +57 -0
  130. package/dist/universal/.kiro/skills/citable/manifest.json +29 -16
  131. package/dist/universal/.kiro/skills/citable/schemas/action-plan.schema.json +13 -0
  132. package/dist/universal/.kiro/skills/citable/schemas/browser-evidence-plan.schema.json +14 -0
  133. package/dist/universal/.kiro/skills/citable/schemas/canonical-index-import.schema.json +30 -0
  134. package/dist/universal/.kiro/skills/citable/schemas/common.defs.json +12 -1
  135. package/dist/universal/.kiro/skills/citable/schemas/corroboration-import.schema.json +48 -0
  136. package/dist/universal/.kiro/skills/citable/schemas/entity-graph.schema.json +75 -0
  137. package/dist/universal/.kiro/skills/citable/schemas/entity.schema.json +13 -0
  138. package/dist/universal/.kiro/skills/citable/schemas/observation.schema.json +1 -1
  139. package/dist/universal/.kiro/skills/citable/schemas/page.schema.json +3 -0
  140. package/dist/universal/.kiro/skills/citable/schemas/regional-network-import.schema.json +55 -0
  141. package/dist/universal/.kiro/skills/citable/schemas/schedule.schema.json +1 -1
  142. package/dist/universal/.kiro/skills/citable/schemas/source-identity-chain.schema.json +83 -0
  143. package/dist/universal/.kiro/skills/citable/scripts/README.md +3 -1
  144. package/dist/universal/.opencode/skills/citable/SKILL.md +22 -8
  145. package/dist/universal/.opencode/skills/citable/VERSION +1 -1
  146. package/dist/universal/.opencode/skills/citable/agents/citable-auditor.md +64 -0
  147. package/dist/universal/.opencode/skills/citable/agents/citable-semantic-reviewer.md +66 -0
  148. package/dist/universal/.opencode/skills/citable/commands/README.md +4 -1
  149. package/dist/universal/.opencode/skills/citable/commands/action-findings.md +9 -1
  150. package/dist/universal/.opencode/skills/citable/commands/observe-and-act.md +62 -8
  151. package/dist/universal/.opencode/skills/citable/commands/plan-audit.md +35 -0
  152. package/dist/universal/.opencode/skills/citable/commands/reporting.md +57 -0
  153. package/dist/universal/.opencode/skills/citable/manifest.json +29 -16
  154. package/dist/universal/.opencode/skills/citable/schemas/action-plan.schema.json +13 -0
  155. package/dist/universal/.opencode/skills/citable/schemas/browser-evidence-plan.schema.json +14 -0
  156. package/dist/universal/.opencode/skills/citable/schemas/canonical-index-import.schema.json +30 -0
  157. package/dist/universal/.opencode/skills/citable/schemas/common.defs.json +12 -1
  158. package/dist/universal/.opencode/skills/citable/schemas/corroboration-import.schema.json +48 -0
  159. package/dist/universal/.opencode/skills/citable/schemas/entity-graph.schema.json +75 -0
  160. package/dist/universal/.opencode/skills/citable/schemas/entity.schema.json +13 -0
  161. package/dist/universal/.opencode/skills/citable/schemas/observation.schema.json +1 -1
  162. package/dist/universal/.opencode/skills/citable/schemas/page.schema.json +3 -0
  163. package/dist/universal/.opencode/skills/citable/schemas/regional-network-import.schema.json +55 -0
  164. package/dist/universal/.opencode/skills/citable/schemas/schedule.schema.json +1 -1
  165. package/dist/universal/.opencode/skills/citable/schemas/source-identity-chain.schema.json +83 -0
  166. package/dist/universal/.opencode/skills/citable/scripts/README.md +3 -1
  167. package/dist/universal/.pi/agent/skills/citable/SKILL.md +22 -8
  168. package/dist/universal/.pi/agent/skills/citable/VERSION +1 -1
  169. package/dist/universal/.pi/agent/skills/citable/agents/citable-auditor.md +64 -0
  170. package/dist/universal/.pi/agent/skills/citable/agents/citable-semantic-reviewer.md +66 -0
  171. package/dist/universal/.pi/agent/skills/citable/commands/README.md +4 -1
  172. package/dist/universal/.pi/agent/skills/citable/commands/action-findings.md +9 -1
  173. package/dist/universal/.pi/agent/skills/citable/commands/observe-and-act.md +62 -8
  174. package/dist/universal/.pi/agent/skills/citable/commands/plan-audit.md +35 -0
  175. package/dist/universal/.pi/agent/skills/citable/commands/reporting.md +57 -0
  176. package/dist/universal/.pi/agent/skills/citable/manifest.json +29 -16
  177. package/dist/universal/.pi/agent/skills/citable/schemas/action-plan.schema.json +13 -0
  178. package/dist/universal/.pi/agent/skills/citable/schemas/browser-evidence-plan.schema.json +14 -0
  179. package/dist/universal/.pi/agent/skills/citable/schemas/canonical-index-import.schema.json +30 -0
  180. package/dist/universal/.pi/agent/skills/citable/schemas/common.defs.json +12 -1
  181. package/dist/universal/.pi/agent/skills/citable/schemas/corroboration-import.schema.json +48 -0
  182. package/dist/universal/.pi/agent/skills/citable/schemas/entity-graph.schema.json +75 -0
  183. package/dist/universal/.pi/agent/skills/citable/schemas/entity.schema.json +13 -0
  184. package/dist/universal/.pi/agent/skills/citable/schemas/observation.schema.json +1 -1
  185. package/dist/universal/.pi/agent/skills/citable/schemas/page.schema.json +3 -0
  186. package/dist/universal/.pi/agent/skills/citable/schemas/regional-network-import.schema.json +55 -0
  187. package/dist/universal/.pi/agent/skills/citable/schemas/schedule.schema.json +1 -1
  188. package/dist/universal/.pi/agent/skills/citable/schemas/source-identity-chain.schema.json +83 -0
  189. package/dist/universal/.pi/agent/skills/citable/scripts/README.md +3 -1
  190. package/dist/universal/.qoder/skills/citable/SKILL.md +22 -8
  191. package/dist/universal/.qoder/skills/citable/VERSION +1 -1
  192. package/dist/universal/.qoder/skills/citable/agents/citable-auditor.md +64 -0
  193. package/dist/universal/.qoder/skills/citable/agents/citable-semantic-reviewer.md +66 -0
  194. package/dist/universal/.qoder/skills/citable/commands/README.md +4 -1
  195. package/dist/universal/.qoder/skills/citable/commands/action-findings.md +9 -1
  196. package/dist/universal/.qoder/skills/citable/commands/observe-and-act.md +62 -8
  197. package/dist/universal/.qoder/skills/citable/commands/plan-audit.md +35 -0
  198. package/dist/universal/.qoder/skills/citable/commands/reporting.md +57 -0
  199. package/dist/universal/.qoder/skills/citable/manifest.json +29 -16
  200. package/dist/universal/.qoder/skills/citable/schemas/action-plan.schema.json +13 -0
  201. package/dist/universal/.qoder/skills/citable/schemas/browser-evidence-plan.schema.json +14 -0
  202. package/dist/universal/.qoder/skills/citable/schemas/canonical-index-import.schema.json +30 -0
  203. package/dist/universal/.qoder/skills/citable/schemas/common.defs.json +12 -1
  204. package/dist/universal/.qoder/skills/citable/schemas/corroboration-import.schema.json +48 -0
  205. package/dist/universal/.qoder/skills/citable/schemas/entity-graph.schema.json +75 -0
  206. package/dist/universal/.qoder/skills/citable/schemas/entity.schema.json +13 -0
  207. package/dist/universal/.qoder/skills/citable/schemas/observation.schema.json +1 -1
  208. package/dist/universal/.qoder/skills/citable/schemas/page.schema.json +3 -0
  209. package/dist/universal/.qoder/skills/citable/schemas/regional-network-import.schema.json +55 -0
  210. package/dist/universal/.qoder/skills/citable/schemas/schedule.schema.json +1 -1
  211. package/dist/universal/.qoder/skills/citable/schemas/source-identity-chain.schema.json +83 -0
  212. package/dist/universal/.qoder/skills/citable/scripts/README.md +3 -1
  213. package/dist/universal/.rovodev/skills/citable/SKILL.md +22 -8
  214. package/dist/universal/.rovodev/skills/citable/VERSION +1 -1
  215. package/dist/universal/.rovodev/skills/citable/agents/citable-auditor.md +64 -0
  216. package/dist/universal/.rovodev/skills/citable/agents/citable-semantic-reviewer.md +66 -0
  217. package/dist/universal/.rovodev/skills/citable/commands/README.md +4 -1
  218. package/dist/universal/.rovodev/skills/citable/commands/action-findings.md +9 -1
  219. package/dist/universal/.rovodev/skills/citable/commands/observe-and-act.md +62 -8
  220. package/dist/universal/.rovodev/skills/citable/commands/plan-audit.md +35 -0
  221. package/dist/universal/.rovodev/skills/citable/commands/reporting.md +57 -0
  222. package/dist/universal/.rovodev/skills/citable/manifest.json +29 -16
  223. package/dist/universal/.rovodev/skills/citable/schemas/action-plan.schema.json +13 -0
  224. package/dist/universal/.rovodev/skills/citable/schemas/browser-evidence-plan.schema.json +14 -0
  225. package/dist/universal/.rovodev/skills/citable/schemas/canonical-index-import.schema.json +30 -0
  226. package/dist/universal/.rovodev/skills/citable/schemas/common.defs.json +12 -1
  227. package/dist/universal/.rovodev/skills/citable/schemas/corroboration-import.schema.json +48 -0
  228. package/dist/universal/.rovodev/skills/citable/schemas/entity-graph.schema.json +75 -0
  229. package/dist/universal/.rovodev/skills/citable/schemas/entity.schema.json +13 -0
  230. package/dist/universal/.rovodev/skills/citable/schemas/observation.schema.json +1 -1
  231. package/dist/universal/.rovodev/skills/citable/schemas/page.schema.json +3 -0
  232. package/dist/universal/.rovodev/skills/citable/schemas/regional-network-import.schema.json +55 -0
  233. package/dist/universal/.rovodev/skills/citable/schemas/schedule.schema.json +1 -1
  234. package/dist/universal/.rovodev/skills/citable/schemas/source-identity-chain.schema.json +83 -0
  235. package/dist/universal/.rovodev/skills/citable/scripts/README.md +3 -1
  236. package/dist/universal/.trae/skills/citable/SKILL.md +22 -8
  237. package/dist/universal/.trae/skills/citable/VERSION +1 -1
  238. package/dist/universal/.trae/skills/citable/agents/citable-auditor.md +64 -0
  239. package/dist/universal/.trae/skills/citable/agents/citable-semantic-reviewer.md +66 -0
  240. package/dist/universal/.trae/skills/citable/commands/README.md +4 -1
  241. package/dist/universal/.trae/skills/citable/commands/action-findings.md +9 -1
  242. package/dist/universal/.trae/skills/citable/commands/observe-and-act.md +62 -8
  243. package/dist/universal/.trae/skills/citable/commands/plan-audit.md +35 -0
  244. package/dist/universal/.trae/skills/citable/commands/reporting.md +57 -0
  245. package/dist/universal/.trae/skills/citable/manifest.json +29 -16
  246. package/dist/universal/.trae/skills/citable/schemas/action-plan.schema.json +13 -0
  247. package/dist/universal/.trae/skills/citable/schemas/browser-evidence-plan.schema.json +14 -0
  248. package/dist/universal/.trae/skills/citable/schemas/canonical-index-import.schema.json +30 -0
  249. package/dist/universal/.trae/skills/citable/schemas/common.defs.json +12 -1
  250. package/dist/universal/.trae/skills/citable/schemas/corroboration-import.schema.json +48 -0
  251. package/dist/universal/.trae/skills/citable/schemas/entity-graph.schema.json +75 -0
  252. package/dist/universal/.trae/skills/citable/schemas/entity.schema.json +13 -0
  253. package/dist/universal/.trae/skills/citable/schemas/observation.schema.json +1 -1
  254. package/dist/universal/.trae/skills/citable/schemas/page.schema.json +3 -0
  255. package/dist/universal/.trae/skills/citable/schemas/regional-network-import.schema.json +55 -0
  256. package/dist/universal/.trae/skills/citable/schemas/schedule.schema.json +1 -1
  257. package/dist/universal/.trae/skills/citable/schemas/source-identity-chain.schema.json +83 -0
  258. package/dist/universal/.trae/skills/citable/scripts/README.md +3 -1
  259. package/dist/universal/.trae-cn/skills/citable/SKILL.md +22 -8
  260. package/dist/universal/.trae-cn/skills/citable/VERSION +1 -1
  261. package/dist/universal/.trae-cn/skills/citable/agents/citable-auditor.md +64 -0
  262. package/dist/universal/.trae-cn/skills/citable/agents/citable-semantic-reviewer.md +66 -0
  263. package/dist/universal/.trae-cn/skills/citable/commands/README.md +4 -1
  264. package/dist/universal/.trae-cn/skills/citable/commands/action-findings.md +9 -1
  265. package/dist/universal/.trae-cn/skills/citable/commands/observe-and-act.md +62 -8
  266. package/dist/universal/.trae-cn/skills/citable/commands/plan-audit.md +35 -0
  267. package/dist/universal/.trae-cn/skills/citable/commands/reporting.md +57 -0
  268. package/dist/universal/.trae-cn/skills/citable/manifest.json +29 -16
  269. package/dist/universal/.trae-cn/skills/citable/schemas/action-plan.schema.json +13 -0
  270. package/dist/universal/.trae-cn/skills/citable/schemas/browser-evidence-plan.schema.json +14 -0
  271. package/dist/universal/.trae-cn/skills/citable/schemas/canonical-index-import.schema.json +30 -0
  272. package/dist/universal/.trae-cn/skills/citable/schemas/common.defs.json +12 -1
  273. package/dist/universal/.trae-cn/skills/citable/schemas/corroboration-import.schema.json +48 -0
  274. package/dist/universal/.trae-cn/skills/citable/schemas/entity-graph.schema.json +75 -0
  275. package/dist/universal/.trae-cn/skills/citable/schemas/entity.schema.json +13 -0
  276. package/dist/universal/.trae-cn/skills/citable/schemas/observation.schema.json +1 -1
  277. package/dist/universal/.trae-cn/skills/citable/schemas/page.schema.json +3 -0
  278. package/dist/universal/.trae-cn/skills/citable/schemas/regional-network-import.schema.json +55 -0
  279. package/dist/universal/.trae-cn/skills/citable/schemas/schedule.schema.json +1 -1
  280. package/dist/universal/.trae-cn/skills/citable/schemas/source-identity-chain.schema.json +83 -0
  281. package/dist/universal/.trae-cn/skills/citable/scripts/README.md +3 -1
  282. package/dist/universal/manifest.json +306 -195
  283. package/package.json +1 -1
  284. package/schemas/action-plan.schema.json +13 -0
  285. package/schemas/browser-evidence-plan.schema.json +14 -0
  286. package/schemas/canonical-index-import.schema.json +30 -0
  287. package/schemas/common.defs.json +12 -1
  288. package/schemas/corroboration-import.schema.json +48 -0
  289. package/schemas/entity-graph.schema.json +75 -0
  290. package/schemas/entity.schema.json +13 -0
  291. package/schemas/observation.schema.json +1 -1
  292. package/schemas/page.schema.json +3 -0
  293. package/schemas/regional-network-import.schema.json +55 -0
  294. package/schemas/schedule.schema.json +1 -1
  295. package/schemas/source-identity-chain.schema.json +83 -0
  296. package/scripts/build-dist.js +36 -3
  297. package/skill/SKILL.md +22 -8
  298. package/skill/agents/citable-auditor.md +64 -0
  299. package/skill/agents/citable-semantic-reviewer.md +66 -0
  300. package/skill/commands/README.md +4 -1
  301. package/skill/commands/action-findings.md +9 -1
  302. package/skill/commands/observe-and-act.md +62 -8
  303. package/skill/commands/plan-audit.md +35 -0
  304. package/skill/commands/reporting.md +57 -0
  305. package/src/cli/index.js +115 -15
  306. package/src/commands/actionPlan.js +12 -1
  307. package/src/commands/audit.js +4 -0
  308. package/src/commands/connect.js +29 -0
  309. package/src/commands/context.js +15 -0
  310. package/src/commands/delivery.js +86 -2
  311. package/src/commands/demo.js +36 -0
  312. package/src/commands/fixtures/demo/.citable/claims.yaml +27 -0
  313. package/src/commands/fixtures/demo/.citable/competitors.yaml +3 -0
  314. package/src/commands/fixtures/demo/.citable/config.yaml +18 -0
  315. package/src/commands/fixtures/demo/.citable/crawlers.yaml +30 -0
  316. package/src/commands/fixtures/demo/.citable/entities.yaml +28 -0
  317. package/src/commands/fixtures/demo/.citable/evidence.yaml +19 -0
  318. package/src/commands/fixtures/demo/.citable/experiments.yaml +3 -0
  319. package/src/commands/fixtures/demo/.citable/pages.yaml +54 -0
  320. package/src/commands/fixtures/demo/.citable/prompts.yaml +11 -0
  321. package/src/commands/fixtures/demo/.citable/queries.yaml +10 -0
  322. package/src/commands/fixtures/demo/site/index.html +12 -0
  323. package/src/commands/fixtures/demo/site/learn/execution-governance/index.html +14 -0
  324. package/src/commands/fixtures/demo/site/pricing/index.html +10 -0
  325. package/src/commands/fixtures/demo/site/products/gatekeeper/index.html +15 -0
  326. package/src/commands/fixtures/demo/site/robots.txt +7 -0
  327. package/src/commands/fixtures/demo/site/sitemap.xml +7 -0
  328. package/src/commands/init.js +5 -2
  329. package/src/commands/monitor.js +35 -0
  330. package/src/commands/observe.js +315 -15
  331. package/src/commands/planAudit.js +151 -0
  332. package/src/commands/reportDashboard.js +21 -0
  333. package/src/commands/reportShareOfVoice.js +60 -0
  334. package/src/commands/schemaCmd.js +5 -1
  335. package/src/commands/substantiate.js +22 -10
  336. package/src/connectors/http.js +6 -3
  337. package/src/connectors/index.js +3 -1
  338. package/src/connectors/webflow.js +224 -0
  339. package/src/connectors/wordpress.js +226 -0
  340. package/src/crawler/fetch.js +34 -6
  341. package/src/detectors/geoReco.js +101 -0
  342. package/src/extractor/page.js +17 -0
  343. package/src/installer/index.js +282 -28
  344. package/src/installer/providers.js +11 -0
  345. package/src/monitoring/alertDelivery.js +98 -0
  346. package/src/observations/browserJourney.js +15 -7
  347. package/src/observations/claimDiff.js +83 -0
  348. package/src/observations/common.js +25 -0
  349. package/src/observations/entityGraph.js +89 -0
  350. package/src/observations/renderParity.js +49 -0
  351. package/src/observations/sourceIdentity.js +62 -0
  352. package/src/observations/stance.js +261 -0
  353. package/src/registries/seed.js +95 -0
  354. package/src/registries/seeds/saas-pricing/claims.yaml +18 -0
  355. package/src/registries/seeds/saas-pricing/entities.yaml +20 -0
  356. package/src/registries/seeds/saas-pricing/seed.json +6 -0
  357. package/src/reporting/dashboard.js +254 -0
  358. package/src/reporting/shareOfVoice.js +362 -0
  359. package/src/shared/checklist.js +19 -0
@@ -7,8 +7,10 @@ export const PROVIDERS = Object.freeze({
7
7
  aliases: ['claude-code', 'claudecode'],
8
8
  projectDir: '.claude',
9
9
  projectSkillsDir: '.claude/skills',
10
+ projectAgentProfilesDir: '.claude/agents',
10
11
  globalHints: ['.claude'],
11
12
  globalSkillsDir: '.claude/skills',
13
+ globalAgentProfilesDir: '.claude/agents',
12
14
  },
13
15
  codex: {
14
16
  id: 'codex',
@@ -162,3 +164,12 @@ export function providerBundleSkillPath(providerId) {
162
164
  if (!provider) throw new Error(`unknown provider: ${providerId}`);
163
165
  return path.join('dist', 'universal', provider.projectSkillsDir, 'citable');
164
166
  }
167
+
168
+ export function providerAgentProfilesDestination(providerId, scope, roots) {
169
+ const provider = PROVIDERS[providerId];
170
+ if (!provider) throw new Error(`unknown provider: ${providerId}`);
171
+ const dir = scope === 'project' ? provider.projectAgentProfilesDir : provider.globalAgentProfilesDir;
172
+ if (!dir) return null;
173
+ const root = scope === 'project' ? roots.projectRoot : roots.home;
174
+ return path.join(root, dir, 'citable');
175
+ }
@@ -0,0 +1,98 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import crypto from 'node:crypto';
4
+ import { validatePublicUrl } from '../crawler/fetch.js';
5
+ import { nowIso, sha256, writeJson } from '../shared/io.js';
6
+
7
+ export const SEVERITY_ORDER = {
8
+ informational: 1,
9
+ medium: 2,
10
+ high: 3,
11
+ critical: 4,
12
+ };
13
+
14
+ export function filterAlerts(alerts = [], minSeverity = 'informational') {
15
+ const minRank = SEVERITY_ORDER[minSeverity] ?? SEVERITY_ORDER.informational;
16
+ return alerts.filter((item) => (SEVERITY_ORDER[item.severity] ?? 0) >= minRank);
17
+ }
18
+
19
+ export function buildAlertPayload({ runA, runB, source = 'monitor', summary = {}, alerts = [], timestamp = nowIso() } = {}) {
20
+ const critOrHigh = alerts.filter((a) => ['critical', 'high'].includes(a.severity)).length;
21
+ return {
22
+ event: 'citable.regression_alert',
23
+ source,
24
+ generated_at: timestamp,
25
+ run_a: runA ?? null,
26
+ run_b: runB,
27
+ summary: {
28
+ total_alerts: alerts.length,
29
+ critical_or_high: critOrHigh,
30
+ ...summary,
31
+ },
32
+ alerts,
33
+ };
34
+ }
35
+
36
+ export async function dispatchAlertWebhook(root, payload, {
37
+ webhookUrl,
38
+ headers = {},
39
+ timeoutMs = 10000,
40
+ fetchImpl = globalThis.fetch,
41
+ lookup,
42
+ allowPrivateForTest = false,
43
+ } = {}) {
44
+ if (!webhookUrl) throw new Error('webhookUrl is required for alert dispatch');
45
+ if (!allowPrivateForTest) {
46
+ await validatePublicUrl(webhookUrl, { lookup });
47
+ }
48
+
49
+ const deliveryId = `DELIVERY-${nowIso().replace(/[:.]/g, '')}-${crypto.randomBytes(4).toString('hex')}`;
50
+ const payloadString = JSON.stringify(payload);
51
+ const payloadHash = sha256(Buffer.from(payloadString));
52
+ const deliveriesDir = path.join(root, '.citable', 'monitoring', 'deliveries');
53
+ const receiptFile = path.join(deliveriesDir, `${deliveryId}.json`);
54
+
55
+ const controller = new AbortController();
56
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
57
+
58
+ let statusCode = null;
59
+ let success = false;
60
+ let errorMessage = null;
61
+
62
+ try {
63
+ const res = await fetchImpl(webhookUrl, {
64
+ method: 'POST',
65
+ headers: {
66
+ 'content-type': 'application/json',
67
+ 'x-citable-event': 'citable.regression_alert',
68
+ 'x-citable-delivery': deliveryId,
69
+ ...headers,
70
+ },
71
+ body: payloadString,
72
+ signal: controller.signal,
73
+ });
74
+ clearTimeout(timer);
75
+ statusCode = res.status;
76
+ success = res.ok;
77
+ if (!res.ok) {
78
+ errorMessage = `HTTP ${res.status} ${res.statusText || 'Error'}`;
79
+ }
80
+ } catch (err) {
81
+ clearTimeout(timer);
82
+ errorMessage = err.name === 'AbortError' ? `Request timed out after ${timeoutMs}ms` : err.message;
83
+ }
84
+
85
+ const receipt = {
86
+ delivery_id: deliveryId,
87
+ target_url: webhookUrl,
88
+ delivered_at: nowIso(),
89
+ status_code: statusCode,
90
+ success,
91
+ payload_hash: payloadHash,
92
+ error: errorMessage,
93
+ summary: payload.summary,
94
+ };
95
+
96
+ writeJson(receiptFile, receipt);
97
+ return { ...receipt, receipt_file: receiptFile };
98
+ }
@@ -1,11 +1,15 @@
1
1
  import { envelope, observationRun, readInput } from './common.js';
2
- import { fetchUrl } from '../crawler/fetch.js';
2
+ import { fetchUrl, handlePublicBrowserRoute, validatePublicUrl } from '../crawler/fetch.js';
3
3
  import { sha256 } from '../shared/io.js';
4
4
  import { validateAgainst } from '../shared/schemaValidator.js';
5
+ import { analyzeRenderParity } from './renderParity.js';
5
6
 
6
- async function executeStep(page, step) {
7
+ async function executeStep(page, step, lookup) {
7
8
  const locator = step.locator ? page.locator(step.locator).first() : null;
8
- if (step.action === 'navigate') await page.goto(step.url, { waitUntil: 'networkidle' });
9
+ if (step.action === 'navigate') {
10
+ await validatePublicUrl(step.url, lookup ? { lookup } : {});
11
+ await page.goto(step.url, { waitUntil: 'networkidle' });
12
+ }
9
13
  else if (step.action === 'click') await locator.click();
10
14
  else if (step.action === 'fill') {
11
15
  const value = process.env[step.value_env];
@@ -22,7 +26,7 @@ async function executeStep(page, step) {
22
26
  else if (step.action === 'scroll') await locator.scrollIntoViewIfNeeded();
23
27
  }
24
28
 
25
- async function playwrightCapture(profile, plan, playwright) {
29
+ async function playwrightCapture(profile, plan, playwright, lookup) {
26
30
  if (profile.authentication_state !== 'anonymous') throw new Error(`authentication state ${profile.authentication_state} requires a disclosed custom adapter`);
27
31
  const browserType = playwright[profile.browser.engine];
28
32
  if (!browserType) throw new Error(`Playwright engine ${profile.browser.engine} is unavailable`);
@@ -35,6 +39,7 @@ async function playwrightCapture(profile, plan, playwright) {
35
39
  locale: profile.locale,
36
40
  });
37
41
  try {
42
+ await context.route('**/*', (route) => handlePublicBrowserRoute(route, lookup ? { lookup } : {}));
38
43
  const page = await context.newPage();
39
44
  const consoleErrors = [], networkFailures = [], steps = [], stepScreenshots = {};
40
45
  page.on('console', (message) => { if (message.type() === 'error') consoleErrors.push(message.text()); });
@@ -43,7 +48,7 @@ async function playwrightCapture(profile, plan, playwright) {
43
48
  for (const step of profile.steps) {
44
49
  const record = { step_id: step.step_id, action: step.action, status: 'completed', failure: null, screenshot_ref: null };
45
50
  try {
46
- await executeStep(page, step);
51
+ await executeStep(page, step, lookup);
47
52
  if (step.capture_screenshot) {
48
53
  record.screenshot_ref = `journeys/${profile.profile_id}/steps/${step.step_id}.png`;
49
54
  stepScreenshots[record.screenshot_ref] = await page.screenshot({ fullPage: true });
@@ -79,6 +84,7 @@ export async function observeBrowserPlan(root, options) {
79
84
  const check = validateAgainst('browser-evidence-plan.schema.json', plan);
80
85
  if (!check.valid) throw new Error(`browser evidence plan violates contract: ${check.errors.join('; ')}`);
81
86
  if (options.target && options.target !== plan.target) throw new Error('browser evidence target differs from the plan target');
87
+ await validatePublicUrl(plan.target, options.lookup ? { lookup: options.lookup } : {});
82
88
  const profileIds = plan.profiles.map((item) => item.profile_id);
83
89
  if (new Set(profileIds).size !== profileIds.length) throw new Error('browser evidence plan contains duplicate profile ids');
84
90
  const targetOrigin = new URL(plan.target).origin;
@@ -113,7 +119,7 @@ export async function observeBrowserPlan(root, options) {
113
119
  try {
114
120
  const capture = options.captureJourney
115
121
  ? await options.captureJourney(profile, plan)
116
- : await playwrightCapture(profile, plan, playwright);
122
+ : await playwrightCapture(profile, plan, playwright, options.lookup);
117
123
  if (!capture || typeof capture.dom !== 'string' || typeof capture.text !== 'string' || typeof capture.browser_version !== 'string' || capture.screenshot == null) {
118
124
  throw new Error('browser adapter returned an incomplete capture contract');
119
125
  }
@@ -137,6 +143,7 @@ export async function observeBrowserPlan(root, options) {
137
143
  artifacts[name] = value;
138
144
  }
139
145
  const versionMatches = profile.browser.expected_version == null || profile.browser.expected_version === capture.browser_version;
146
+ const renderParity = analyzeRenderParity(initial.body, capture.dom, plan.semantic_impact_policy || null);
140
147
  const data = {
141
148
  plan_id: plan.plan_id, target: plan.target, profile_id: profile.profile_id,
142
149
  browser: { ...profile.browser, observed_version: capture.browser_version, version_matches_expectation: versionMatches },
@@ -144,9 +151,10 @@ export async function observeBrowserPlan(root, options) {
144
151
  consent_state: profile.consent_state, authentication_state: profile.authentication_state,
145
152
  final_url: capture.final_url, status: capture.status, dom_hash: sha256(capture.dom), text_hash: sha256(capture.text),
146
153
  steps: capture.steps || [], artifact_refs: refs,
154
+ render_parity: renderParity,
147
155
  interpretation_boundary: 'Observed differences do not establish semantic, retrieval, citation, ranking, or business impact.',
148
156
  };
149
- const limitations = [...plan.limitations, ...profile.limitations];
157
+ const limitations = [...plan.limitations, ...profile.limitations, ...(plan.semantic_impact_policy?.limitations || [])];
150
158
  if (!versionMatches) limitations.push('Observed browser version differs from the planned version.');
151
159
  observations.push(envelope('browser_journey', data, { method: 'browser', source: `playwright/${profile.browser.engine}`, raw: capture.dom, limitations }));
152
160
  } catch (error) {
@@ -0,0 +1,83 @@
1
+ import { substantiate } from '../commands/substantiate.js';
2
+ import { loadRegistries } from '../registries/index.js';
3
+
4
+ function keyTerms(text) {
5
+ return (String(text || '').toLowerCase().match(/[a-z][a-z-]{4,}/g) || []).slice(0, 8);
6
+ }
7
+
8
+ function escapeRegExp(s) {
9
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
10
+ }
11
+
12
+ function overlapScore(assertionText, claimText) {
13
+ const terms = keyTerms(assertionText);
14
+ if (terms.length < 3) return 0;
15
+ const target = String(claimText || '').toLowerCase();
16
+ // Whole-word boundaries only — a raw substring test would match "test" inside
17
+ // "greatest" and misassign a substantiation status to the wrong claim.
18
+ const present = terms.filter((t) => new RegExp(`\\b${escapeRegExp(t)}\\b`).test(target)).length;
19
+ return present / terms.length;
20
+ }
21
+
22
+ function surfaceMatches(citationUrl, surface) {
23
+ try {
24
+ const url = new URL(citationUrl);
25
+ // Path-boundary comparison, not raw substring — a query string or fragment
26
+ // containing the surface text must not count as a match.
27
+ return url.pathname === surface || url.pathname.startsWith(surface.endsWith('/') ? surface : `${surface}/`);
28
+ } catch {
29
+ return false;
30
+ }
31
+ }
32
+
33
+ /** Find the best-matching registry claim for one AI answer assertion (token-overlap heuristic, adapted from CLAIM-008). */
34
+ export function matchClaim(assertionText, claims, citationUrl) {
35
+ let best = null;
36
+ let bestScore = 0;
37
+ for (const c of claims.filter((c) => c.status !== 'retired')) {
38
+ let score = overlapScore(assertionText, c.claim);
39
+ if (citationUrl && (c.publication_surfaces || []).some((s) => surfaceMatches(citationUrl, s))) score += 0.1;
40
+ if (score > bestScore) {
41
+ bestScore = score;
42
+ best = c;
43
+ }
44
+ }
45
+ return bestScore >= 0.4 ? best : null;
46
+ }
47
+
48
+ const OUTCOME_TO_STATUS = {
49
+ verified: 'confirmed',
50
+ verified_narrowed: 'confirmed',
51
+ contradicted: 'contradicted',
52
+ expired: 'stale',
53
+ };
54
+
55
+ /**
56
+ * Diff one answer-engine assertion against the caller's own claim/evidence registry.
57
+ * Never asserts the AI is wrong — only confirmed/contradicted/stale/unsupported relative
58
+ * to the caller's own evidence. Never implies a live query happened.
59
+ */
60
+ export function diffAssertion(assertionText, citationUrl, { claims, assessmentByClaimId }) {
61
+ if (!assertionText) return null;
62
+ const matched = matchClaim(assertionText, claims, citationUrl);
63
+ if (!matched) {
64
+ return { status: 'unsupported', matched_claim_id: null, reasons: ['no claim in your registry covers this assertion; it could not be checked'] };
65
+ }
66
+ const assessment = assessmentByClaimId.get(matched.claim_id);
67
+ const status = OUTCOME_TO_STATUS[assessment?.outcome] ?? 'unsupported';
68
+ return { status, matched_claim_id: matched.claim_id, reasons: assessment?.reasons ?? [] };
69
+ }
70
+
71
+ /**
72
+ * Precompute the shared claim/evidence lookups once per `observe citations` run.
73
+ * `problems` surfaces registry schema-validation issues (malformed but parseable
74
+ * YAML) so the caller can report them as warnings rather than silently diffing
75
+ * against data that failed its own contract.
76
+ */
77
+ export function buildClaimDiffContext(root, refDate) {
78
+ const { registries, problems } = loadRegistries(root);
79
+ const claims = Array.isArray(registries.claims?.entries) ? registries.claims.entries : [];
80
+ const { assessments } = substantiate(root, { write: false, refDate });
81
+ const assessmentByClaimId = new Map(assessments.map((a) => [a.claim_id, a]));
82
+ return { claims, assessmentByClaimId, problems };
83
+ }
@@ -42,6 +42,8 @@ export function summarizeObservations(items) {
42
42
  for (const item of items) { byKind[item.kind] = (byKind[item.kind] || 0) + 1; byState[item.state] = (byState[item.state] || 0) + 1; }
43
43
  const citations = items.filter((item) => item.kind === 'citation');
44
44
  const reviews = items.filter((item) => item.kind === 'citation_review');
45
+ const claimDiffCounts = { confirmed: 0, contradicted: 0, stale: 0, unsupported: 0, not_checked: 0 };
46
+ for (const review of reviews) claimDiffCounts[review.data.claim_diff?.status ?? 'not_checked']++;
45
47
  const providers = {};
46
48
  for (const item of citations) {
47
49
  const provider = item.data.provider || 'unknown';
@@ -49,6 +51,18 @@ export function summarizeObservations(items) {
49
51
  providers[provider].runs++;
50
52
  if (item.data.property_cited) providers[provider].property_cited++;
51
53
  }
54
+ const competitiveSourceMap = new Map();
55
+ for (const review of reviews.filter((item) => !item.data.first_party)) {
56
+ let domain;
57
+ try { domain = new URL(review.data.canonical_url).hostname; } catch { continue; }
58
+ const current = competitiveSourceMap.get(domain) || { domain, citation_count: 0, declared_profiles: [] };
59
+ current.citation_count++;
60
+ if (review.data.source_profile && !current.declared_profiles.some((item) => JSON.stringify(item) === JSON.stringify(review.data.source_profile))) {
61
+ current.declared_profiles.push(review.data.source_profile);
62
+ }
63
+ competitiveSourceMap.set(domain, current);
64
+ }
65
+ const stances = items.filter((item) => item.kind === 'stance');
52
66
  return {
53
67
  total: items.length, by_kind: byKind, by_state: byState,
54
68
  citation_metrics: citations.length ? {
@@ -56,8 +70,19 @@ export function summarizeObservations(items) {
56
70
  citation_presence_rate: citations.filter((x) => x.data.property_cited).length / citations.length,
57
71
  supported_citation_rate: reviews.length ? reviews.filter((x) => x.data.support_status === 'supported').length / reviews.length : null,
58
72
  review_required: reviews.filter((x) => x.state === 'review_required').length,
73
+ claim_diff: claimDiffCounts,
59
74
  provider_results: providers,
60
75
  competitive_domains: [...new Set(reviews.filter((x) => !x.data.first_party).map((x) => { try { return new URL(x.data.canonical_url).hostname; } catch { return null; } }).filter(Boolean))].sort(),
76
+ competitive_sources: [...competitiveSourceMap.values()].sort((a, b) => a.domain.localeCompare(b.domain)),
77
+ } : null,
78
+ stance_metrics: stances.length ? {
79
+ total: stances.length,
80
+ favorable: stances.filter((x) => x.data.stance === 'favorable').length,
81
+ neutral: stances.filter((x) => x.data.stance === 'neutral').length,
82
+ unfavorable: stances.filter((x) => x.data.stance === 'unfavorable').length,
83
+ mixed: stances.filter((x) => x.data.stance === 'mixed').length,
84
+ ambiguous: stances.filter((x) => x.data.stance === 'ambiguous').length,
85
+ review_required: stances.filter((x) => x.state === 'review_required').length,
61
86
  } : null,
62
87
  };
63
88
  }
@@ -0,0 +1,89 @@
1
+ import { sha256 } from '../shared/io.js';
2
+ import { validateAgainst } from '../shared/schemaValidator.js';
3
+
4
+ const list = (value) => Array.isArray(value) ? value : value == null ? [] : [value];
5
+
6
+ function visibleSupport(node, page) {
7
+ const candidates = [
8
+ ...list(node.name).map((value) => ['name', value]),
9
+ ...list(node.headline).map((value) => ['headline', value]),
10
+ ...list(node.description).map((value) => ['description', value]),
11
+ ].filter(([, value]) => typeof value === 'string' && value.trim());
12
+ if (!candidates.length) return { status: 'not_testable', matched_fields: [] };
13
+ const visible = `${page.title || ''} ${page.text || ''}`.toLocaleLowerCase();
14
+ const matchedFields = [...new Set(candidates
15
+ .filter(([, value]) => visible.includes(value.trim().toLocaleLowerCase()))
16
+ .map(([field]) => field))].sort();
17
+ return { status: matchedFields.length ? 'supported' : 'not_observed', matched_fields: matchedFields };
18
+ }
19
+
20
+ function referencedIds(value, relation, out = []) {
21
+ if (Array.isArray(value)) {
22
+ for (const item of value) referencedIds(item, relation, out);
23
+ } else if (value && typeof value === 'object') {
24
+ if (typeof value['@id'] === 'string') out.push({ relation, target_id: value['@id'] });
25
+ else for (const [key, nested] of Object.entries(value)) referencedIds(nested, key, out);
26
+ }
27
+ return out;
28
+ }
29
+
30
+ export function buildEntityGraph(pages) {
31
+ const nodeMap = new Map();
32
+ const pendingEdges = [];
33
+ const parseFailures = [];
34
+ for (const page of pages) {
35
+ for (const script of page.jsonLd) {
36
+ if (script.parseError) {
37
+ parseFailures.push({ url: page.url, error: script.parseError, raw_hash: sha256(script.raw) });
38
+ continue;
39
+ }
40
+ for (const block of script.blocks) {
41
+ if (!block || typeof block !== 'object' || Array.isArray(block)) continue;
42
+ const blockHash = sha256(JSON.stringify(block));
43
+ const nodeId = typeof block['@id'] === 'string' && block['@id'].trim()
44
+ ? block['@id']
45
+ : `urn:citable:jsonld:${blockHash}`;
46
+ const prior = nodeMap.get(nodeId) || {
47
+ node_id: nodeId, types: [], names: [], source_blocks: [],
48
+ visible_support: { status: 'not_testable', matched_fields: [] },
49
+ };
50
+ prior.types = [...new Set([...prior.types, ...list(block['@type']).filter((value) => typeof value === 'string')])].sort();
51
+ prior.names = [...new Set([...prior.names, ...list(block.name).filter((value) => typeof value === 'string' && value.trim())])].sort();
52
+ prior.source_blocks.push({ url: page.url, block_hash: blockHash });
53
+ const support = visibleSupport(block, page);
54
+ prior.visible_support = {
55
+ status: prior.visible_support.status === 'supported' || support.status === 'supported'
56
+ ? 'supported'
57
+ : prior.visible_support.status === 'not_observed' || support.status === 'not_observed'
58
+ ? 'not_observed'
59
+ : 'not_testable',
60
+ matched_fields: [...new Set([...prior.visible_support.matched_fields, ...support.matched_fields])].sort(),
61
+ };
62
+ nodeMap.set(nodeId, prior);
63
+ for (const [relation, value] of Object.entries(block)) {
64
+ if (relation.startsWith('@')) continue;
65
+ for (const ref of referencedIds(value, relation)) {
66
+ pendingEdges.push({ source_id: nodeId, relation: ref.relation, target_id: ref.target_id, source_url: page.url });
67
+ }
68
+ }
69
+ }
70
+ }
71
+ }
72
+ const nodes = [...nodeMap.values()].sort((a, b) => a.node_id.localeCompare(b.node_id));
73
+ const nodeIds = new Set(nodes.map((node) => node.node_id));
74
+ const allEdges = pendingEdges.map((edge) => ({ ...edge, target_declared: nodeIds.has(edge.target_id) }))
75
+ .sort((a, b) => `${a.source_id}:${a.relation}:${a.target_id}`.localeCompare(`${b.source_id}:${b.relation}:${b.target_id}`));
76
+ const graph = {
77
+ version: 1,
78
+ nodes,
79
+ edges: allEdges.filter((edge) => edge.target_declared),
80
+ unresolved_references: allEdges.filter((edge) => !edge.target_declared),
81
+ parse_failures: parseFailures,
82
+ limitations: [
83
+ 'Normalization reports declared JSON-LD structure and literal visible-text matches; it does not establish semantic correctness, eligibility, search-engine recognition, or ranking impact.',
84
+ ],
85
+ };
86
+ const check = validateAgainst('entity-graph.schema.json', graph);
87
+ if (!check.valid) throw new Error(`entity graph violates contract: ${check.errors.join('; ')}`);
88
+ return graph;
89
+ }
@@ -0,0 +1,49 @@
1
+ import { parse } from 'node-html-parser';
2
+ import { sha256 } from '../shared/io.js';
3
+
4
+ function profile(html) {
5
+ const root = parse(String(html || ''));
6
+ for (const node of root.querySelectorAll('script,style,noscript,nav,footer,header[role=banner]')) node.remove();
7
+ const text = root.textContent.replace(/\s+/g, ' ').trim();
8
+ const tokens = new Set(text.toLocaleLowerCase().split(/\s+/).filter(Boolean));
9
+ const headings = root.querySelectorAll('h1,h2,h3,h4,h5,h6').map((node) => node.text.replace(/\s+/g, ' ').trim()).filter(Boolean).sort();
10
+ const links = root.querySelectorAll('a[href]').map((node) => node.getAttribute('href')).filter(Boolean).sort();
11
+ const structuredData = parse(String(html || '')).querySelectorAll('script[type="application/ld+json"]').map((node) => sha256(node.text)).sort();
12
+ return { text, tokens, headings, links, structuredData };
13
+ }
14
+
15
+ const missing = (before, after) => before.filter((value) => !after.includes(value));
16
+
17
+ export function analyzeRenderParity(initialHtml, renderedHtml, policy = null) {
18
+ const initial = profile(initialHtml);
19
+ const rendered = profile(renderedHtml);
20
+ const retained = [...initial.tokens].filter((token) => rendered.tokens.has(token)).length;
21
+ const textRetentionRatio = initial.tokens.size ? Number((retained / initial.tokens.size).toFixed(3)) : null;
22
+ const removedHeadings = missing(initial.headings, rendered.headings);
23
+ const removedLinks = missing(initial.links, rendered.links);
24
+ const structuredDataMatches = JSON.stringify(initial.structuredData) === JSON.stringify(rendered.structuredData);
25
+ const violations = [];
26
+ if (policy) {
27
+ if (textRetentionRatio != null && textRetentionRatio < policy.min_text_retention_ratio) {
28
+ violations.push({ check: 'text_retention', observed: textRetentionRatio, required: policy.min_text_retention_ratio });
29
+ }
30
+ if (policy.require_heading_parity && removedHeadings.length) violations.push({ check: 'heading_parity', observed: removedHeadings.length, required: 0 });
31
+ if (policy.require_link_parity && removedLinks.length) violations.push({ check: 'link_parity', observed: removedLinks.length, required: 0 });
32
+ if (policy.require_structured_data_parity && !structuredDataMatches) violations.push({ check: 'structured_data_parity', observed: false, required: true });
33
+ }
34
+ return {
35
+ policy_id: policy?.policy_id || null,
36
+ review_owner: policy?.review_owner || null,
37
+ initial_text_hash: sha256(initial.text),
38
+ rendered_text_hash: sha256(rendered.text),
39
+ text_retention_ratio: textRetentionRatio,
40
+ removed_headings: removedHeadings,
41
+ added_headings: missing(rendered.headings, initial.headings),
42
+ removed_links: removedLinks,
43
+ added_links: missing(rendered.links, initial.links),
44
+ structured_data_matches: structuredDataMatches,
45
+ policy_violations: violations,
46
+ semantic_review_status: policy ? 'review_required' : 'not_evidenced',
47
+ interpretation_boundary: 'Deterministic parity and policy checks do not establish semantic, retrieval, citation, ranking, or business impact.',
48
+ };
49
+ }
@@ -0,0 +1,62 @@
1
+ import { validateAgainst } from '../shared/schemaValidator.js';
2
+
3
+ export function buildSourceIdentityChain(registries) {
4
+ const entities = new Map((registries.entities?.entries || []).map((item) => [item.entity_id, item]));
5
+ const evidence = new Map((registries.evidence?.entries || []).map((item) => [item.evidence_id, item]));
6
+ const pages = (registries.pages?.entries || []).map((page) => {
7
+ const publisherEntity = entities.get(page.publisher_entity);
8
+ const publisher = publisherEntity ? {
9
+ entity_id: publisherEntity.entity_id,
10
+ name: publisherEntity.canonical_name,
11
+ canonical_url: publisherEntity.canonical_url || null,
12
+ status: publisherEntity.status,
13
+ } : null;
14
+ const authors = (page.author_entities || []).map((id) => {
15
+ const entity = entities.get(id);
16
+ return entity ? {
17
+ entity_id: entity.entity_id,
18
+ name: entity.canonical_name,
19
+ canonical_url: entity.canonical_url || null,
20
+ affiliations: (entity.affiliations || []).map((affiliation) => ({
21
+ ...affiliation,
22
+ entity_name: entities.get(affiliation.entity_id)?.canonical_name || null,
23
+ })),
24
+ status: entity.status,
25
+ } : { entity_id: id, name: null, canonical_url: null, affiliations: [], status: 'missing' };
26
+ });
27
+ const evidenceOwners = (page.evidence_references || []).map((id) => {
28
+ const item = evidence.get(id);
29
+ return { evidence_id: id, owner: item?.source_owner || null, verification_status: item?.verification_status || 'missing' };
30
+ });
31
+ const missing = [];
32
+ if (!publisher) missing.push('publisher_entity');
33
+ if (!authors.length) missing.push('author_entities');
34
+ else if (authors.some((author) => !author.affiliations.length)) missing.push('author_affiliations');
35
+ if (!page.content_owner) missing.push('content_owner');
36
+ if (!page.factual_reviewer) missing.push('factual_reviewer');
37
+ if (!page.correction_path) missing.push('correction_path');
38
+ if (evidenceOwners.some((item) => !item.owner)) missing.push('evidence_owner');
39
+ return {
40
+ page_id: page.page_id,
41
+ url: page.url,
42
+ publisher,
43
+ authors,
44
+ content_owner: page.content_owner || null,
45
+ factual_reviewer: page.factual_reviewer || null,
46
+ evidence_owners: evidenceOwners,
47
+ correction_path: page.correction_path || null,
48
+ status: missing.length ? 'incomplete' : 'complete',
49
+ missing_fields: [...new Set(missing)].sort(),
50
+ };
51
+ });
52
+ const chain = {
53
+ version: 1,
54
+ pages,
55
+ limitations: [
56
+ 'Registry linkage records declared identity and governance relationships; it does not establish that disclosures are visible, current, independent, or recognized by external systems.',
57
+ ],
58
+ };
59
+ const check = validateAgainst('source-identity-chain.schema.json', chain);
60
+ if (!check.valid) throw new Error(`source identity chain violates contract: ${check.errors.join('; ')}`);
61
+ return chain;
62
+ }