attestation 0.2.0__tar.gz

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 (510) hide show
  1. attestation-0.2.0/.claude/agents/attestation-feed.md +26 -0
  2. attestation-0.2.0/.claude/agents/attestation-knowledge.md +23 -0
  3. attestation-0.2.0/.claude/agents/attestation-provenance.md +25 -0
  4. attestation-0.2.0/.claude/agents/attestation-symbolic.md +22 -0
  5. attestation-0.2.0/.env.sample +124 -0
  6. attestation-0.2.0/.github/workflows/ci.yml +160 -0
  7. attestation-0.2.0/.github/workflows/docs.yml +50 -0
  8. attestation-0.2.0/.github/workflows/release.yml +64 -0
  9. attestation-0.2.0/.gitignore +48 -0
  10. attestation-0.2.0/.notes.txt.swp +0 -0
  11. attestation-0.2.0/.pre-commit-config.yaml +100 -0
  12. attestation-0.2.0/.python-version +1 -0
  13. attestation-0.2.0/CHANGELOG.md +213 -0
  14. attestation-0.2.0/CLAUDE.md +118 -0
  15. attestation-0.2.0/CONTRIBUTING.md +350 -0
  16. attestation-0.2.0/LICENSE +21 -0
  17. attestation-0.2.0/PKG-INFO +238 -0
  18. attestation-0.2.0/README.md +200 -0
  19. attestation-0.2.0/datasette.yml +146 -0
  20. attestation-0.2.0/demos/README.md +73 -0
  21. attestation-0.2.0/demos/claims/README.md +23 -0
  22. attestation-0.2.0/demos/claims/narrate.sh +26 -0
  23. attestation-0.2.0/demos/claims/record.sh +14 -0
  24. attestation-0.2.0/demos/feed/README.md +28 -0
  25. attestation-0.2.0/demos/feed/record.py +111 -0
  26. attestation-0.2.0/demos/feed/seed_feed_db.py +43 -0
  27. attestation-0.2.0/demos/hermes/README.md +81 -0
  28. attestation-0.2.0/demos/hermes/narrate-feed.sh +11 -0
  29. attestation-0.2.0/demos/hermes/record-feed.sh +27 -0
  30. attestation-0.2.0/demos/hermes/record-provenance.sh +31 -0
  31. attestation-0.2.0/demos/kg-symbolic/README.md +32 -0
  32. attestation-0.2.0/demos/kg-symbolic/demo.py +141 -0
  33. attestation-0.2.0/demos/kg-symbolic/record.sh +20 -0
  34. attestation-0.2.0/demos/kg-symbolic/seed_kg_db.py +57 -0
  35. attestation-0.2.0/demos/ledger/README.md +21 -0
  36. attestation-0.2.0/demos/ledger/narrate.sh +27 -0
  37. attestation-0.2.0/demos/ledger/record.sh +16 -0
  38. attestation-0.2.0/docs/CHANGELOG.md +1 -0
  39. attestation-0.2.0/docs/CONTRIBUTING.md +1 -0
  40. attestation-0.2.0/docs/_hooks.py +27 -0
  41. attestation-0.2.0/docs/architecture/README.md +34 -0
  42. attestation-0.2.0/docs/architecture/agent-flows.html +388 -0
  43. attestation-0.2.0/docs/architecture/research-profile.md +50 -0
  44. attestation-0.2.0/docs/architecture/structure-and-integration-points.md +163 -0
  45. attestation-0.2.0/docs/bundled-skills-research.md +433 -0
  46. attestation-0.2.0/docs/concepts.md +86 -0
  47. attestation-0.2.0/docs/examples/README.md +24 -0
  48. attestation-0.2.0/docs/examples/agents/README.md +104 -0
  49. attestation-0.2.0/docs/examples/agents/run.sh +9 -0
  50. attestation-0.2.0/docs/examples/citations/DRAFT.md +39 -0
  51. attestation-0.2.0/docs/examples/citations/README.md +159 -0
  52. attestation-0.2.0/docs/examples/citations/check_citations.py +93 -0
  53. attestation-0.2.0/docs/examples/citations/generate.py +113 -0
  54. attestation-0.2.0/docs/examples/citations/references.bib +36 -0
  55. attestation-0.2.0/docs/examples/citations/run.sh +10 -0
  56. attestation-0.2.0/docs/examples/dvc/.dvc/config +2 -0
  57. attestation-0.2.0/docs/examples/dvc/README.md +137 -0
  58. attestation-0.2.0/docs/examples/dvc/dvc.lock +58 -0
  59. attestation-0.2.0/docs/examples/dvc/dvc.yaml +9 -0
  60. attestation-0.2.0/docs/examples/dvc/generate.sh +57 -0
  61. attestation-0.2.0/docs/examples/dvc/metrics/0.01.json +6 -0
  62. attestation-0.2.0/docs/examples/dvc/metrics/0.1.json +6 -0
  63. attestation-0.2.0/docs/examples/dvc/metrics/1.json +6 -0
  64. attestation-0.2.0/docs/examples/dvc/metrics/10.json +6 -0
  65. attestation-0.2.0/docs/examples/dvc/params.yaml +1 -0
  66. attestation-0.2.0/docs/examples/dvc/run.sh +9 -0
  67. attestation-0.2.0/docs/examples/dvc/train.py +63 -0
  68. attestation-0.2.0/docs/examples/flows/README.md +120 -0
  69. attestation-0.2.0/docs/examples/flows/RESULTS.md +155 -0
  70. attestation-0.2.0/docs/examples/flows/_common.py +59 -0
  71. attestation-0.2.0/docs/examples/flows/corpus/labelled.xml +287 -0
  72. attestation-0.2.0/docs/examples/flows/corpus/labels.json +162 -0
  73. attestation-0.2.0/docs/examples/flows/corpus/personas.toml +14 -0
  74. attestation-0.2.0/docs/examples/flows/mcp_e2e.py +417 -0
  75. attestation-0.2.0/docs/examples/flows/persona_eval.py +178 -0
  76. attestation-0.2.0/docs/examples/flows/run.sh +7 -0
  77. attestation-0.2.0/docs/examples/flows/run_all.py +163 -0
  78. attestation-0.2.0/docs/examples/flows/stub_openai.py +179 -0
  79. attestation-0.2.0/docs/examples/flows/training/FINDINGS.md +13 -0
  80. attestation-0.2.0/docs/examples/flows/training/mlruns/0/meta.yaml +9 -0
  81. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/06f405c125804496876ebfa098ad4c94/meta.yaml +14 -0
  82. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/06f405c125804496876ebfa098ad4c94/metrics/accuracy +1 -0
  83. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/06f405c125804496876ebfa098ad4c94/metrics/auc +1 -0
  84. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/06f405c125804496876ebfa098ad4c94/metrics/precision +1 -0
  85. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/06f405c125804496876ebfa098ad4c94/metrics/recall +1 -0
  86. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/06f405c125804496876ebfa098ad4c94/metrics/train_loss +10 -0
  87. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/06f405c125804496876ebfa098ad4c94/params/C +1 -0
  88. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/06f405c125804496876ebfa098ad4c94/params/dataset +1 -0
  89. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/06f405c125804496876ebfa098ad4c94/params/seed +1 -0
  90. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/06f405c125804496876ebfa098ad4c94/tags/mlflow.runName +1 -0
  91. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/06f405c125804496876ebfa098ad4c94/tags/mlflow.source.type +1 -0
  92. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/55f000a468ec4cf5a47c2b3b479a4b5c/meta.yaml +14 -0
  93. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/55f000a468ec4cf5a47c2b3b479a4b5c/metrics/accuracy +1 -0
  94. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/55f000a468ec4cf5a47c2b3b479a4b5c/metrics/auc +1 -0
  95. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/55f000a468ec4cf5a47c2b3b479a4b5c/metrics/precision +1 -0
  96. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/55f000a468ec4cf5a47c2b3b479a4b5c/metrics/recall +1 -0
  97. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/55f000a468ec4cf5a47c2b3b479a4b5c/metrics/train_loss +10 -0
  98. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/55f000a468ec4cf5a47c2b3b479a4b5c/params/C +1 -0
  99. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/55f000a468ec4cf5a47c2b3b479a4b5c/params/dataset +1 -0
  100. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/55f000a468ec4cf5a47c2b3b479a4b5c/params/seed +1 -0
  101. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/55f000a468ec4cf5a47c2b3b479a4b5c/tags/mlflow.runName +1 -0
  102. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/55f000a468ec4cf5a47c2b3b479a4b5c/tags/mlflow.source.type +1 -0
  103. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/80a3f280dbe94e9e9a45742b8e2d9e7b/meta.yaml +14 -0
  104. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/80a3f280dbe94e9e9a45742b8e2d9e7b/metrics/accuracy +1 -0
  105. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/80a3f280dbe94e9e9a45742b8e2d9e7b/metrics/auc +1 -0
  106. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/80a3f280dbe94e9e9a45742b8e2d9e7b/metrics/precision +1 -0
  107. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/80a3f280dbe94e9e9a45742b8e2d9e7b/metrics/recall +1 -0
  108. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/80a3f280dbe94e9e9a45742b8e2d9e7b/metrics/train_loss +10 -0
  109. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/80a3f280dbe94e9e9a45742b8e2d9e7b/params/C +1 -0
  110. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/80a3f280dbe94e9e9a45742b8e2d9e7b/params/dataset +1 -0
  111. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/80a3f280dbe94e9e9a45742b8e2d9e7b/params/seed +1 -0
  112. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/80a3f280dbe94e9e9a45742b8e2d9e7b/tags/mlflow.runName +1 -0
  113. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/80a3f280dbe94e9e9a45742b8e2d9e7b/tags/mlflow.source.type +1 -0
  114. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/bbb3a3901807470c9cba6f332d8c5106/meta.yaml +14 -0
  115. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/bbb3a3901807470c9cba6f332d8c5106/metrics/accuracy +1 -0
  116. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/bbb3a3901807470c9cba6f332d8c5106/metrics/auc +1 -0
  117. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/bbb3a3901807470c9cba6f332d8c5106/metrics/precision +1 -0
  118. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/bbb3a3901807470c9cba6f332d8c5106/metrics/recall +1 -0
  119. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/bbb3a3901807470c9cba6f332d8c5106/metrics/train_loss +10 -0
  120. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/bbb3a3901807470c9cba6f332d8c5106/params/C +1 -0
  121. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/bbb3a3901807470c9cba6f332d8c5106/params/dataset +1 -0
  122. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/bbb3a3901807470c9cba6f332d8c5106/params/seed +1 -0
  123. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/bbb3a3901807470c9cba6f332d8c5106/tags/mlflow.runName +1 -0
  124. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/bbb3a3901807470c9cba6f332d8c5106/tags/mlflow.source.type +1 -0
  125. attestation-0.2.0/docs/examples/flows/training/mlruns/260449967480221589/meta.yaml +9 -0
  126. attestation-0.2.0/docs/examples/flows/training/train_mlflow.py +246 -0
  127. attestation-0.2.0/docs/examples/hydra/README.md +165 -0
  128. attestation-0.2.0/docs/examples/hydra/conf/config.yaml +5 -0
  129. attestation-0.2.0/docs/examples/hydra/generate.sh +58 -0
  130. attestation-0.2.0/docs/examples/hydra/multirun/2026-08-28/23-45-43/0/.hydra/config.yaml +1 -0
  131. attestation-0.2.0/docs/examples/hydra/multirun/2026-08-28/23-45-43/0/.hydra/hydra.yaml +156 -0
  132. attestation-0.2.0/docs/examples/hydra/multirun/2026-08-28/23-45-43/0/.hydra/overrides.yaml +1 -0
  133. attestation-0.2.0/docs/examples/hydra/multirun/2026-08-28/23-45-43/0/metrics.json +6 -0
  134. attestation-0.2.0/docs/examples/hydra/multirun/2026-08-28/23-45-43/1/.hydra/config.yaml +1 -0
  135. attestation-0.2.0/docs/examples/hydra/multirun/2026-08-28/23-45-43/1/.hydra/hydra.yaml +156 -0
  136. attestation-0.2.0/docs/examples/hydra/multirun/2026-08-28/23-45-43/1/.hydra/overrides.yaml +1 -0
  137. attestation-0.2.0/docs/examples/hydra/multirun/2026-08-28/23-45-43/1/metrics.json +6 -0
  138. attestation-0.2.0/docs/examples/hydra/multirun/2026-08-28/23-45-43/2/.hydra/config.yaml +1 -0
  139. attestation-0.2.0/docs/examples/hydra/multirun/2026-08-28/23-45-43/2/.hydra/hydra.yaml +156 -0
  140. attestation-0.2.0/docs/examples/hydra/multirun/2026-08-28/23-45-43/2/.hydra/overrides.yaml +1 -0
  141. attestation-0.2.0/docs/examples/hydra/multirun/2026-08-28/23-45-43/2/metrics.json +6 -0
  142. attestation-0.2.0/docs/examples/hydra/multirun/2026-08-28/23-45-43/3/.hydra/config.yaml +1 -0
  143. attestation-0.2.0/docs/examples/hydra/multirun/2026-08-28/23-45-43/3/.hydra/hydra.yaml +156 -0
  144. attestation-0.2.0/docs/examples/hydra/multirun/2026-08-28/23-45-43/3/.hydra/overrides.yaml +1 -0
  145. attestation-0.2.0/docs/examples/hydra/multirun/2026-08-28/23-45-43/3/metrics.json +6 -0
  146. attestation-0.2.0/docs/examples/hydra/run.sh +9 -0
  147. attestation-0.2.0/docs/examples/hydra/scrub.py +79 -0
  148. attestation-0.2.0/docs/examples/hydra/train.py +70 -0
  149. attestation-0.2.0/docs/examples/mlflow/README.md +120 -0
  150. attestation-0.2.0/docs/examples/mlflow/run.sh +10 -0
  151. attestation-0.2.0/docs/examples/model-servers/README.md +92 -0
  152. attestation-0.2.0/docs/examples/model-servers/run.sh +7 -0
  153. attestation-0.2.0/docs/examples/model-servers/with_server.py +48 -0
  154. attestation-0.2.0/docs/examples/molecular-ai/README.md +235 -0
  155. attestation-0.2.0/docs/examples/molecular-ai/generate.py +282 -0
  156. attestation-0.2.0/docs/examples/molecular-ai/references.bib +651 -0
  157. attestation-0.2.0/docs/examples/molecular-ai/run.sh +11 -0
  158. attestation-0.2.0/docs/examples/molecular-ai/seeds.toml +248 -0
  159. attestation-0.2.0/docs/examples/prompt-evals/README.md +167 -0
  160. attestation-0.2.0/docs/examples/prompt-evals/run.sh +12 -0
  161. attestation-0.2.0/docs/examples/ranking/README.md +77 -0
  162. attestation-0.2.0/docs/examples/ranking/rank_rows.py +132 -0
  163. attestation-0.2.0/docs/examples/ranking/run.sh +6 -0
  164. attestation-0.2.0/docs/examples/sacred/README.md +132 -0
  165. attestation-0.2.0/docs/examples/sacred/generate.py +213 -0
  166. attestation-0.2.0/docs/examples/sacred/run.sh +9 -0
  167. attestation-0.2.0/docs/examples/sacred/sacred_runs/1/config.json +4 -0
  168. attestation-0.2.0/docs/examples/sacred/sacred_runs/1/metrics.json +51 -0
  169. attestation-0.2.0/docs/examples/sacred/sacred_runs/1/run.json +47 -0
  170. attestation-0.2.0/docs/examples/sacred/sacred_runs/2/config.json +4 -0
  171. attestation-0.2.0/docs/examples/sacred/sacred_runs/2/metrics.json +51 -0
  172. attestation-0.2.0/docs/examples/sacred/sacred_runs/2/run.json +47 -0
  173. attestation-0.2.0/docs/examples/sacred/sacred_runs/3/config.json +4 -0
  174. attestation-0.2.0/docs/examples/sacred/sacred_runs/3/metrics.json +51 -0
  175. attestation-0.2.0/docs/examples/sacred/sacred_runs/3/run.json +47 -0
  176. attestation-0.2.0/docs/examples/sacred/sacred_runs/4/config.json +4 -0
  177. attestation-0.2.0/docs/examples/sacred/sacred_runs/4/metrics.json +51 -0
  178. attestation-0.2.0/docs/examples/sacred/sacred_runs/4/run.json +47 -0
  179. attestation-0.2.0/docs/examples/tensorflow/README.md +155 -0
  180. attestation-0.2.0/docs/examples/tensorflow/generate.py +204 -0
  181. attestation-0.2.0/docs/examples/tensorflow/results/lr_0.001.csv +6 -0
  182. attestation-0.2.0/docs/examples/tensorflow/results/lr_0.001.json +6 -0
  183. attestation-0.2.0/docs/examples/tensorflow/results/lr_0.003.csv +6 -0
  184. attestation-0.2.0/docs/examples/tensorflow/results/lr_0.003.json +6 -0
  185. attestation-0.2.0/docs/examples/tensorflow/results/lr_0.01.csv +6 -0
  186. attestation-0.2.0/docs/examples/tensorflow/results/lr_0.01.json +6 -0
  187. attestation-0.2.0/docs/examples/tensorflow/results/lr_0.03.csv +6 -0
  188. attestation-0.2.0/docs/examples/tensorflow/results/lr_0.03.json +6 -0
  189. attestation-0.2.0/docs/examples/tensorflow/run.sh +9 -0
  190. attestation-0.2.0/docs/examples/tensorflow/tb/train/events.out.tfevents.1787973060.v2 +0 -0
  191. attestation-0.2.0/docs/examples/tensorflow/tb/validation/events.out.tfevents.1787973060.v2 +0 -0
  192. attestation-0.2.0/docs/examples/wandb/README.md +138 -0
  193. attestation-0.2.0/docs/examples/wandb/generate.py +330 -0
  194. attestation-0.2.0/docs/examples/wandb/run.sh +9 -0
  195. attestation-0.2.0/docs/examples/wandb/wandb/offline-run-20260828_213302-d9o76utt/files/config.yaml +15 -0
  196. attestation-0.2.0/docs/examples/wandb/wandb/offline-run-20260828_213302-d9o76utt/files/wandb-metadata.json +102 -0
  197. attestation-0.2.0/docs/examples/wandb/wandb/offline-run-20260828_213302-d9o76utt/files/wandb-summary.json +1 -0
  198. attestation-0.2.0/docs/examples/wandb/wandb/offline-run-20260828_213303-fsecp1k3/files/config.yaml +15 -0
  199. attestation-0.2.0/docs/examples/wandb/wandb/offline-run-20260828_213303-fsecp1k3/files/wandb-metadata.json +102 -0
  200. attestation-0.2.0/docs/examples/wandb/wandb/offline-run-20260828_213303-fsecp1k3/files/wandb-summary.json +1 -0
  201. attestation-0.2.0/docs/examples/wandb/wandb/offline-run-20260828_213305-h2ythad2/files/config.yaml +15 -0
  202. attestation-0.2.0/docs/examples/wandb/wandb/offline-run-20260828_213305-h2ythad2/files/wandb-metadata.json +102 -0
  203. attestation-0.2.0/docs/examples/wandb/wandb/offline-run-20260828_213305-h2ythad2/files/wandb-summary.json +1 -0
  204. attestation-0.2.0/docs/examples/wandb/wandb/offline-run-20260828_213308-92ajmw2l/files/config.yaml +15 -0
  205. attestation-0.2.0/docs/examples/wandb/wandb/offline-run-20260828_213308-92ajmw2l/files/wandb-metadata.json +102 -0
  206. attestation-0.2.0/docs/examples/wandb/wandb/offline-run-20260828_213308-92ajmw2l/files/wandb-summary.json +1 -0
  207. attestation-0.2.0/docs/examples/workspace/README.md +97 -0
  208. attestation-0.2.0/docs/examples/workspace/retrieval-ablation/configs/planned_colbert.yaml +6 -0
  209. attestation-0.2.0/docs/examples/workspace/retrieval-ablation/results/rank_method_bm25.json +6 -0
  210. attestation-0.2.0/docs/examples/workspace/retrieval-ablation/results/rank_method_dense.json +6 -0
  211. attestation-0.2.0/docs/examples/workspace/retrieval-ablation/results/rank_method_dense2.json +6 -0
  212. attestation-0.2.0/docs/examples/workspace/retrieval-ablation/results/rank_method_hybrid.json +6 -0
  213. attestation-0.2.0/docs/examples/workspace/run.sh +12 -0
  214. attestation-0.2.0/docs/examples/workspace/speech-distill/FINDINGS.md +53 -0
  215. attestation-0.2.0/docs/examples/workspace/speech-distill/corpus.toml +14 -0
  216. attestation-0.2.0/docs/examples/workspace/speech-distill/logs/kdsweep_t4.log +20 -0
  217. attestation-0.2.0/docs/examples/workspace/speech-distill/results/kdsweep_baseline.json +12 -0
  218. attestation-0.2.0/docs/examples/workspace/speech-distill/results/kdsweep_t2.json +12 -0
  219. attestation-0.2.0/docs/examples/workspace/speech-distill/results/kdsweep_t4.json +12 -0
  220. attestation-0.2.0/docs/examples/workspace/speech-distill/results/kdsweep_t4b.json +12 -0
  221. attestation-0.2.0/docs/getting-started.md +4 -0
  222. attestation-0.2.0/docs/guides/agents.md +435 -0
  223. attestation-0.2.0/docs/guides/claims-and-citations.md +101 -0
  224. attestation-0.2.0/docs/guides/demos.md +127 -0
  225. attestation-0.2.0/docs/guides/evals.md +22 -0
  226. attestation-0.2.0/docs/guides/feed.md +93 -0
  227. attestation-0.2.0/docs/guides/install.md +233 -0
  228. attestation-0.2.0/docs/guides/ledger.md +172 -0
  229. attestation-0.2.0/docs/guides/testing.md +44 -0
  230. attestation-0.2.0/docs/hermes-agent-plugin-research.md +287 -0
  231. attestation-0.2.0/docs/index.md +3 -0
  232. attestation-0.2.0/docs/measurement-lessons.md +353 -0
  233. attestation-0.2.0/docs/media/claims.gif +0 -0
  234. attestation-0.2.0/docs/media/feed.webm +0 -0
  235. attestation-0.2.0/docs/media/hermes-feed.gif +0 -0
  236. attestation-0.2.0/docs/media/hermes-prov.gif +0 -0
  237. attestation-0.2.0/docs/media/kg-symbolic.gif +0 -0
  238. attestation-0.2.0/docs/media/ledger.gif +0 -0
  239. attestation-0.2.0/docs/recommendation-literature-review.md +617 -0
  240. attestation-0.2.0/docs/recommendation-refinements.md +400 -0
  241. attestation-0.2.0/docs/reference/api/citations.md +3 -0
  242. attestation-0.2.0/docs/reference/api/claims.md +3 -0
  243. attestation-0.2.0/docs/reference/api/db.md +3 -0
  244. attestation-0.2.0/docs/reference/api/embed.md +3 -0
  245. attestation-0.2.0/docs/reference/api/emit.md +3 -0
  246. attestation-0.2.0/docs/reference/api/explain.md +3 -0
  247. attestation-0.2.0/docs/reference/api/features.md +3 -0
  248. attestation-0.2.0/docs/reference/api/ingest.md +3 -0
  249. attestation-0.2.0/docs/reference/api/install.md +3 -0
  250. attestation-0.2.0/docs/reference/api/kg.md +3 -0
  251. attestation-0.2.0/docs/reference/api/ledger.md +3 -0
  252. attestation-0.2.0/docs/reference/api/llm.md +3 -0
  253. attestation-0.2.0/docs/reference/api/ports.md +3 -0
  254. attestation-0.2.0/docs/reference/api/rank.md +3 -0
  255. attestation-0.2.0/docs/reference/api/simulate.md +3 -0
  256. attestation-0.2.0/docs/reference/api/symbolic.md +3 -0
  257. attestation-0.2.0/docs/reference/cli.md +400 -0
  258. attestation-0.2.0/docs/site/specs.md +41 -0
  259. attestation-0.2.0/docs/superpowers/plans/2026-08-04-hermes-rss.md +1854 -0
  260. attestation-0.2.0/docs/superpowers/plans/2026-08-05-feature-extraction.md +1044 -0
  261. attestation-0.2.0/docs/superpowers/plans/2026-08-05-hermes-install.md +140 -0
  262. attestation-0.2.0/docs/superpowers/plans/2026-08-05-llm-client-extraction.md +1000 -0
  263. attestation-0.2.0/docs/superpowers/plans/2026-08-06-knowledge-graph.md +1136 -0
  264. attestation-0.2.0/docs/superpowers/plans/2026-08-06-persona-and-feed-mcp-tools.md +1477 -0
  265. attestation-0.2.0/docs/superpowers/plans/2026-08-06-sympy-mcp-tools.md +1131 -0
  266. attestation-0.2.0/docs/superpowers/plans/2026-08-28-example-flows.md +1852 -0
  267. attestation-0.2.0/docs/superpowers/plans/2026-08-28-golden-paths.md +390 -0
  268. attestation-0.2.0/docs/superpowers/plans/2026-08-28-task-corpora.md +71 -0
  269. attestation-0.2.0/docs/superpowers/plans/2026-08-29-docs-for-collaborators.md +43 -0
  270. attestation-0.2.0/docs/superpowers/plans/2026-08-29-onion-seams.md +586 -0
  271. attestation-0.2.0/docs/superpowers/plans/2026-08-29-package-docs.md +56 -0
  272. attestation-0.2.0/docs/superpowers/plans/2026-08-29-round-two.md +302 -0
  273. attestation-0.2.0/docs/superpowers/plans/2026-09-05-library-graph-and-molecular-ai.md +413 -0
  274. attestation-0.2.0/docs/superpowers/plans/2026-09-05-library-store.md +1959 -0
  275. attestation-0.2.0/docs/superpowers/plans/2026-09-10-paper-research.md +2907 -0
  276. attestation-0.2.0/docs/superpowers/specs/2026-08-04-hermes-rss-design.md +194 -0
  277. attestation-0.2.0/docs/superpowers/specs/2026-08-05-feature-extraction-design.md +157 -0
  278. attestation-0.2.0/docs/superpowers/specs/2026-08-05-hermes-install-design.md +122 -0
  279. attestation-0.2.0/docs/superpowers/specs/2026-08-05-llm-client-extraction-design.md +168 -0
  280. attestation-0.2.0/docs/superpowers/specs/2026-08-06-knowledge-graph-design.md +199 -0
  281. attestation-0.2.0/docs/superpowers/specs/2026-08-06-persona-and-feed-mcp-tools-design.md +214 -0
  282. attestation-0.2.0/docs/superpowers/specs/2026-08-06-sympy-mcp-tools-design.md +196 -0
  283. attestation-0.2.0/docs/superpowers/specs/2026-08-06-web-ui-tidy-design.md +172 -0
  284. attestation-0.2.0/docs/superpowers/specs/2026-08-12-claim-checker-design.md +135 -0
  285. attestation-0.2.0/docs/superpowers/specs/2026-08-12-run-ledger-design.md +137 -0
  286. attestation-0.2.0/docs/superpowers/specs/2026-08-13-digest-design.md +97 -0
  287. attestation-0.2.0/docs/superpowers/specs/2026-08-20-corpus-ledger-design.md +291 -0
  288. attestation-0.2.0/docs/superpowers/specs/2026-08-21-architecture-roadmap.md +250 -0
  289. attestation-0.2.0/docs/superpowers/specs/2026-08-21-onion-refactor-design.md +421 -0
  290. attestation-0.2.0/docs/superpowers/specs/2026-08-21-tool-surface-design.md +259 -0
  291. attestation-0.2.0/docs/superpowers/specs/2026-08-22-agent-surfaces-design.md +161 -0
  292. attestation-0.2.0/docs/superpowers/specs/2026-08-22-citations-domain-design.md +215 -0
  293. attestation-0.2.0/docs/superpowers/specs/2026-08-22-config-emitters-design.md +164 -0
  294. attestation-0.2.0/docs/superpowers/specs/2026-08-22-swarm-refutation.md +153 -0
  295. attestation-0.2.0/docs/superpowers/specs/2026-08-22-tracker-adapters-design.md +404 -0
  296. attestation-0.2.0/docs/superpowers/specs/2026-08-23-claim-suggestion-design.md +102 -0
  297. attestation-0.2.0/docs/superpowers/specs/2026-08-23-dspy-prompt-optimization-design.md +196 -0
  298. attestation-0.2.0/docs/superpowers/specs/2026-08-23-scheduled-refresh-design.md +111 -0
  299. attestation-0.2.0/docs/superpowers/specs/2026-08-28-example-flows-design.md +344 -0
  300. attestation-0.2.0/docs/superpowers/specs/2026-08-28-golden-paths-design.md +270 -0
  301. attestation-0.2.0/docs/superpowers/specs/2026-08-28-task-corpora-design.md +152 -0
  302. attestation-0.2.0/docs/superpowers/specs/2026-08-29-docs-for-collaborators-design.md +138 -0
  303. attestation-0.2.0/docs/superpowers/specs/2026-08-29-onion-seams-design.md +451 -0
  304. attestation-0.2.0/docs/superpowers/specs/2026-08-29-package-docs-design.md +247 -0
  305. attestation-0.2.0/docs/superpowers/specs/2026-08-29-round-two-design.md +491 -0
  306. attestation-0.2.0/docs/superpowers/specs/2026-08-30-latex-and-reviewer-audits-design.md +289 -0
  307. attestation-0.2.0/docs/superpowers/specs/2026-09-01-attest-record-design.md +149 -0
  308. attestation-0.2.0/docs/superpowers/specs/2026-09-01-write-side-skills-design.md +159 -0
  309. attestation-0.2.0/docs/superpowers/specs/2026-09-05-library-graph-and-molecular-ai-design.md +293 -0
  310. attestation-0.2.0/docs/superpowers/specs/2026-09-05-library-store-design.md +417 -0
  311. attestation-0.2.0/docs/superpowers/specs/2026-09-05-skill-optimization-agentopt-design.md +334 -0
  312. attestation-0.2.0/docs/superpowers/specs/2026-09-10-paper-research-design.md +482 -0
  313. attestation-0.2.0/evals/annotate_cases.json +218 -0
  314. attestation-0.2.0/evals/annotate_eval.py +137 -0
  315. attestation-0.2.0/evals/explanation_cases.json +533 -0
  316. attestation-0.2.0/evals/explanation_eval.py +211 -0
  317. attestation-0.2.0/evals/optimize_skill_triggers.py +273 -0
  318. attestation-0.2.0/evals/optimize_tagging.py +261 -0
  319. attestation-0.2.0/evals/prompts/annotate-trigger-2026-09-03.json +59 -0
  320. attestation-0.2.0/evals/prompts/feed-trigger-2026-09-03.json +68 -0
  321. attestation-0.2.0/evals/prompts/hand-written.json +11 -0
  322. attestation-0.2.0/evals/prompts/knowledge-trigger-2026-09-03.json +59 -0
  323. attestation-0.2.0/evals/prompts/provenance-trigger-2026-09-03.json +65 -0
  324. attestation-0.2.0/evals/prompts/record-trigger-2026-09-03.json +56 -0
  325. attestation-0.2.0/evals/prompts/strict.json +6 -0
  326. attestation-0.2.0/evals/prompts/symbolic-trigger-2026-09-03.json +59 -0
  327. attestation-0.2.0/evals/prompts/tagging-2026-08-27.json +209 -0
  328. attestation-0.2.0/evals/prompts/terse.json +6 -0
  329. attestation-0.2.0/evals/prompts/transfer-2026-08-27.json +15 -0
  330. attestation-0.2.0/evals/prompts/transfer-2026-08-27.md +16 -0
  331. attestation-0.2.0/evals/prompts/transfer-2026-08-28.md +21 -0
  332. attestation-0.2.0/evals/prompts/transfer-feed-2026-09-03.json +16 -0
  333. attestation-0.2.0/evals/prompts/transfer-feed-2026-09-03.md +14 -0
  334. attestation-0.2.0/evals/prompts/transfer-symbolic-2026-09-03.json +16 -0
  335. attestation-0.2.0/evals/prompts/transfer-symbolic-2026-09-03.md +14 -0
  336. attestation-0.2.0/evals/prompts/write-side-2026-09-01.answers.json +1917 -0
  337. attestation-0.2.0/evals/prompts/write-side-2026-09-01.md +78 -0
  338. attestation-0.2.0/evals/prompts/write-side-2026-09-02.answers.json +405 -0
  339. attestation-0.2.0/evals/prompts/write-side-2026-09-02.md +26 -0
  340. attestation-0.2.0/evals/reaction_cases.json +1002 -0
  341. attestation-0.2.0/evals/reaction_eval.py +230 -0
  342. attestation-0.2.0/evals/record_cases.json +312 -0
  343. attestation-0.2.0/evals/record_eval.py +254 -0
  344. attestation-0.2.0/evals/run_annotate_eval.py +251 -0
  345. attestation-0.2.0/evals/run_explanation_eval.py +79 -0
  346. attestation-0.2.0/evals/run_reaction_eval.py +96 -0
  347. attestation-0.2.0/evals/run_record_eval.py +393 -0
  348. attestation-0.2.0/evals/run_skill_trigger_eval.py +178 -0
  349. attestation-0.2.0/evals/run_tagging_eval.py +74 -0
  350. attestation-0.2.0/evals/skill_trigger_cases.json +393 -0
  351. attestation-0.2.0/evals/skill_trigger_eval.py +246 -0
  352. attestation-0.2.0/evals/tagging_cases.json +1149 -0
  353. attestation-0.2.0/evals/tagging_eval.py +279 -0
  354. attestation-0.2.0/evals/transfer_matrix.py +125 -0
  355. attestation-0.2.0/evals/transfer_skill_triggers.py +130 -0
  356. attestation-0.2.0/mkdocs.yml +124 -0
  357. attestation-0.2.0/pyproject.toml +142 -0
  358. attestation-0.2.0/scripts/check_complexity.py +96 -0
  359. attestation-0.2.0/scripts/mutate.py +65 -0
  360. attestation-0.2.0/scripts/render_cli_reference.py +90 -0
  361. attestation-0.2.0/scripts/render_spec_index.py +58 -0
  362. attestation-0.2.0/src/attestation/__init__.py +38 -0
  363. attestation-0.2.0/src/attestation/citations.py +534 -0
  364. attestation-0.2.0/src/attestation/claims.py +515 -0
  365. attestation-0.2.0/src/attestation/cli.py +1595 -0
  366. attestation-0.2.0/src/attestation/corpus.py +279 -0
  367. attestation-0.2.0/src/attestation/db.py +949 -0
  368. attestation-0.2.0/src/attestation/embed.py +73 -0
  369. attestation-0.2.0/src/attestation/emit.py +229 -0
  370. attestation-0.2.0/src/attestation/explain.py +239 -0
  371. attestation-0.2.0/src/attestation/features.py +726 -0
  372. attestation-0.2.0/src/attestation/feed_candidates.toml +42 -0
  373. attestation-0.2.0/src/attestation/feeds.py +253 -0
  374. attestation-0.2.0/src/attestation/feeds.toml +51 -0
  375. attestation-0.2.0/src/attestation/implicit.py +105 -0
  376. attestation-0.2.0/src/attestation/ingest.py +438 -0
  377. attestation-0.2.0/src/attestation/install.py +1231 -0
  378. attestation-0.2.0/src/attestation/kg.py +513 -0
  379. attestation-0.2.0/src/attestation/kg_aliases.toml +117 -0
  380. attestation-0.2.0/src/attestation/ledger.py +1330 -0
  381. attestation-0.2.0/src/attestation/ledger_adapters/__init__.py +26 -0
  382. attestation-0.2.0/src/attestation/ledger_adapters/generic.py +1607 -0
  383. attestation-0.2.0/src/attestation/library.py +1149 -0
  384. attestation-0.2.0/src/attestation/library_readers.py +775 -0
  385. attestation-0.2.0/src/attestation/llm.py +203 -0
  386. attestation-0.2.0/src/attestation/manifest.py +181 -0
  387. attestation-0.2.0/src/attestation/mcp/__init__.py +218 -0
  388. attestation-0.2.0/src/attestation/mcp/_shared.py +135 -0
  389. attestation-0.2.0/src/attestation/mcp/_tool.py +299 -0
  390. attestation-0.2.0/src/attestation/mcp/ask.py +516 -0
  391. attestation-0.2.0/src/attestation/mcp/citation.py +353 -0
  392. attestation-0.2.0/src/attestation/mcp/claims_tools.py +108 -0
  393. attestation-0.2.0/src/attestation/mcp/disclosure.py +79 -0
  394. attestation-0.2.0/src/attestation/mcp/feed.py +1043 -0
  395. attestation-0.2.0/src/attestation/mcp/knowledge.py +237 -0
  396. attestation-0.2.0/src/attestation/mcp/personas.py +128 -0
  397. attestation-0.2.0/src/attestation/mcp/provenance.py +635 -0
  398. attestation-0.2.0/src/attestation/mcp/research.py +140 -0
  399. attestation-0.2.0/src/attestation/mcp/routing.py +365 -0
  400. attestation-0.2.0/src/attestation/mcp/routing_research.py +190 -0
  401. attestation-0.2.0/src/attestation/mcp/subscriptions.py +122 -0
  402. attestation-0.2.0/src/attestation/mcp/symbolic.py +180 -0
  403. attestation-0.2.0/src/attestation/mcp_server.py +102 -0
  404. attestation-0.2.0/src/attestation/paths.py +57 -0
  405. attestation-0.2.0/src/attestation/personas.py +286 -0
  406. attestation-0.2.0/src/attestation/ports.py +162 -0
  407. attestation-0.2.0/src/attestation/py.typed +0 -0
  408. attestation-0.2.0/src/attestation/rank.py +1116 -0
  409. attestation-0.2.0/src/attestation/record.py +552 -0
  410. attestation-0.2.0/src/attestation/research.py +719 -0
  411. attestation-0.2.0/src/attestation/server.py +414 -0
  412. attestation-0.2.0/src/attestation/simulate.py +209 -0
  413. attestation-0.2.0/src/attestation/skills/attestation-annotate/SKILL.md +175 -0
  414. attestation-0.2.0/src/attestation/skills/attestation-feed/SKILL.md +293 -0
  415. attestation-0.2.0/src/attestation/skills/attestation-knowledge/SKILL.md +156 -0
  416. attestation-0.2.0/src/attestation/skills/attestation-provenance/SKILL.md +174 -0
  417. attestation-0.2.0/src/attestation/skills/attestation-record/SKILL.md +169 -0
  418. attestation-0.2.0/src/attestation/skills/attestation-setup/SKILL.md +181 -0
  419. attestation-0.2.0/src/attestation/skills/attestation-setup/scripts/setup.sh +63 -0
  420. attestation-0.2.0/src/attestation/skills/attestation-symbolic/SKILL.md +92 -0
  421. attestation-0.2.0/src/attestation/static/htmx.min.js +1 -0
  422. attestation-0.2.0/src/attestation/symbolic.py +295 -0
  423. attestation-0.2.0/src/attestation/symbolic_ops.py +331 -0
  424. attestation-0.2.0/tests/conftest.py +89 -0
  425. attestation-0.2.0/tests/fixtures/arxiv.xml +20 -0
  426. attestation-0.2.0/tests/fixtures/blog.xml +10 -0
  427. attestation-0.2.0/tests/fixtures/golden_vectors.npz +0 -0
  428. attestation-0.2.0/tests/fixtures/library/arxiv_query.xml +22 -0
  429. attestation-0.2.0/tests/fixtures/library/crossref_work.json +16 -0
  430. attestation-0.2.0/tests/fixtures/library/s2_paper.json +11 -0
  431. attestation-0.2.0/tests/fixtures/library/sample.bib +16 -0
  432. attestation-0.2.0/tests/fixtures/research/arxiv_search.xml +27 -0
  433. attestation-0.2.0/tests/fixtures/research/crossref_journals.json +27 -0
  434. attestation-0.2.0/tests/fixtures/research/crossref_journals_empty.json +1 -0
  435. attestation-0.2.0/tests/fixtures/research/crossref_works.json +7 -0
  436. attestation-0.2.0/tests/fixtures/research/crossref_works_mixed.json +120 -0
  437. attestation-0.2.0/tests/fixtures/research/make_one_page_pdf.py +48 -0
  438. attestation-0.2.0/tests/fixtures/research/one_page.pdf +32 -0
  439. attestation-0.2.0/tests/fixtures/research/pubmed_efetch.xml +22 -0
  440. attestation-0.2.0/tests/fixtures/research/pubmed_esearch.xml +3 -0
  441. attestation-0.2.0/tests/fixtures/research/pubmed_esearch_empty.xml +1 -0
  442. attestation-0.2.0/tests/test_agent_surfaces.py +185 -0
  443. attestation-0.2.0/tests/test_annotate_eval.py +247 -0
  444. attestation-0.2.0/tests/test_architecture.py +1440 -0
  445. attestation-0.2.0/tests/test_ask_routing.py +511 -0
  446. attestation-0.2.0/tests/test_citations.py +482 -0
  447. attestation-0.2.0/tests/test_claims.py +584 -0
  448. attestation-0.2.0/tests/test_cli.py +1487 -0
  449. attestation-0.2.0/tests/test_db.py +859 -0
  450. attestation-0.2.0/tests/test_digest.py +292 -0
  451. attestation-0.2.0/tests/test_docs_site.py +226 -0
  452. attestation-0.2.0/tests/test_docstring_ratchet.py +223 -0
  453. attestation-0.2.0/tests/test_embed.py +157 -0
  454. attestation-0.2.0/tests/test_emit.py +393 -0
  455. attestation-0.2.0/tests/test_examples.py +323 -0
  456. attestation-0.2.0/tests/test_explain.py +321 -0
  457. attestation-0.2.0/tests/test_explanation_eval.py +330 -0
  458. attestation-0.2.0/tests/test_features.py +632 -0
  459. attestation-0.2.0/tests/test_feeds.py +231 -0
  460. attestation-0.2.0/tests/test_flows_fixture.py +64 -0
  461. attestation-0.2.0/tests/test_flows_mcp_plan.py +120 -0
  462. attestation-0.2.0/tests/test_flows_runner.py +74 -0
  463. attestation-0.2.0/tests/test_flows_scoring.py +72 -0
  464. attestation-0.2.0/tests/test_flows_stub.py +149 -0
  465. attestation-0.2.0/tests/test_golden_paths.py +308 -0
  466. attestation-0.2.0/tests/test_implicit_feedback.py +320 -0
  467. attestation-0.2.0/tests/test_ingest.py +661 -0
  468. attestation-0.2.0/tests/test_install.py +1973 -0
  469. attestation-0.2.0/tests/test_install_e2e.py +381 -0
  470. attestation-0.2.0/tests/test_install_skills.py +159 -0
  471. attestation-0.2.0/tests/test_kg.py +366 -0
  472. attestation-0.2.0/tests/test_kg_algorithms.py +282 -0
  473. attestation-0.2.0/tests/test_kg_mcp.py +413 -0
  474. attestation-0.2.0/tests/test_ledger.py +1789 -0
  475. attestation-0.2.0/tests/test_ledger_adapters.py +171 -0
  476. attestation-0.2.0/tests/test_ledger_mcp.py +949 -0
  477. attestation-0.2.0/tests/test_library.py +481 -0
  478. attestation-0.2.0/tests/test_library_db.py +181 -0
  479. attestation-0.2.0/tests/test_library_readers.py +271 -0
  480. attestation-0.2.0/tests/test_library_review.py +459 -0
  481. attestation-0.2.0/tests/test_library_review2.py +390 -0
  482. attestation-0.2.0/tests/test_library_tools.py +249 -0
  483. attestation-0.2.0/tests/test_llm.py +295 -0
  484. attestation-0.2.0/tests/test_manifest.py +143 -0
  485. attestation-0.2.0/tests/test_mcp_server.py +388 -0
  486. attestation-0.2.0/tests/test_package_surface.py +69 -0
  487. attestation-0.2.0/tests/test_paths.py +151 -0
  488. attestation-0.2.0/tests/test_persona_autocreate.py +129 -0
  489. attestation-0.2.0/tests/test_persona_hygiene.py +336 -0
  490. attestation-0.2.0/tests/test_ports.py +121 -0
  491. attestation-0.2.0/tests/test_rank.py +1268 -0
  492. attestation-0.2.0/tests/test_rank_relevance.py +198 -0
  493. attestation-0.2.0/tests/test_reaction_eval.py +271 -0
  494. attestation-0.2.0/tests/test_record.py +643 -0
  495. attestation-0.2.0/tests/test_record_eval.py +344 -0
  496. attestation-0.2.0/tests/test_research.py +379 -0
  497. attestation-0.2.0/tests/test_research_tools.py +113 -0
  498. attestation-0.2.0/tests/test_response_size.py +912 -0
  499. attestation-0.2.0/tests/test_search.py +638 -0
  500. attestation-0.2.0/tests/test_server.py +617 -0
  501. attestation-0.2.0/tests/test_simulate.py +171 -0
  502. attestation-0.2.0/tests/test_skill_files.py +532 -0
  503. attestation-0.2.0/tests/test_symbolic.py +214 -0
  504. attestation-0.2.0/tests/test_symbolic_mcp.py +79 -0
  505. attestation-0.2.0/tests/test_symbolic_ops.py +214 -0
  506. attestation-0.2.0/tests/test_tag_prompt.py +222 -0
  507. attestation-0.2.0/tests/test_tagging_eval.py +309 -0
  508. attestation-0.2.0/tests/test_tool_envelope.py +467 -0
  509. attestation-0.2.0/tests/test_tracker_adapters.py +1404 -0
  510. attestation-0.2.0/uv.lock +3764 -0
@@ -0,0 +1,26 @@
1
+ ---
2
+ name: attestation-feed
3
+ description: Read and search the science feed, and manage what it subscribes to.
4
+ tools: feed
5
+ ---
6
+
7
+ <!-- Generated by `attest emit` from attestation.mcp.AGENT_SURFACES. Edits here are reported by `attest emit`, never overwritten. -->
8
+
9
+ ## Your job
10
+
11
+ Help this reader keep up with the literature. The corpus is their own
12
+ subscribed feeds -- mostly arXiv, plus Nature, Scientific Reports, Hugging
13
+ Face and HN -- so questions like "find me recent papers on X", "what should
14
+ I read this week" and "what's new in Y" are YOURS to answer, locally,
15
+ without any network call. Reach for feed.ask when the question is in plain
16
+ words. Reading an item is itself feedback: it trains the ranker, so open
17
+ what looks relevant rather than only listing titles.
18
+
19
+ ## Why this agent is separate
20
+
21
+ Conversational; a wrong guess costs a retry.
22
+
23
+ Run with `ATTEST_TOOLS=feed`. Tools outside `feed` are not
24
+ registered for this agent: they are absent rather than merely
25
+ undocumented, because a model that can see a tool will eventually
26
+ call it.
@@ -0,0 +1,23 @@
1
+ ---
2
+ name: attestation-knowledge
3
+ description: Explore the reading knowledge graph, the items behind it, and the references they cite.
4
+ tools: cite, feed.search, kg
5
+ ---
6
+
7
+ <!-- Generated by `attest emit` from attestation.mcp.AGENT_SURFACES. Edits here are reported by `attest emit`, never overwritten. -->
8
+
9
+ ## Your job
10
+
11
+ Answer "what have I been reading about", "how do these two topics connect"
12
+ and "what are my main research areas", from the concept graph built out of
13
+ this reader's own items. Concept names are lowercase and hyphenated; turn a
14
+ user's phrasing into one with kg.concepts before looking it up.
15
+
16
+ ## Why this agent is separate
17
+
18
+ Exploratory, read-only.
19
+
20
+ Run with `ATTEST_TOOLS=knowledge`. Tools outside `cite, feed.search, kg` are not
21
+ registered for this agent: they are absent rather than merely
22
+ undocumented, because a model that can see a tool will eventually
23
+ call it.
@@ -0,0 +1,25 @@
1
+ ---
2
+ name: attestation-provenance
3
+ description: Scan experiment runs, compare arms, and check claims against them.
4
+ tools: cite.check, runs
5
+ ---
6
+
7
+ <!-- Generated by `attest emit` from attestation.mcp.AGENT_SURFACES. Edits here are reported by `attest emit`, never overwritten. -->
8
+
9
+ ## Your job
10
+
11
+ Answer "which arm actually won, and on what evidence" and "is what my draft
12
+ says still true". You read experiment artifacts already on disk -- no
13
+ instrumentation, no re-running anything. The caveats you return are the
14
+ product, not a disclaimer: relay them verbatim. When a comparison refuses,
15
+ the refusal is the right answer and it names what to do next; do not work
16
+ around it by picking a metric yourself.
17
+
18
+ ## Why this agent is separate
19
+
20
+ Verification: a wrong answer reaches a manuscript, and the caveats are the product.
21
+
22
+ Run with `ATTEST_TOOLS=provenance`. Tools outside `cite.check, runs` are not
23
+ registered for this agent: they are absent rather than merely
24
+ undocumented, because a model that can see a tool will eventually
25
+ call it.
@@ -0,0 +1,22 @@
1
+ ---
2
+ name: attestation-symbolic
3
+ description: Symbolic algebra and calculus, in a sandboxed subprocess.
4
+ tools: sym
5
+ ---
6
+
7
+ <!-- Generated by `attest emit` from attestation.mcp.AGENT_SURFACES. Edits here are reported by `attest emit`, never overwritten. -->
8
+
9
+ ## Your job
10
+
11
+ Do the algebra and calculus exactly, so a derivation in a paper can be
12
+ checked rather than eyeballed. `^` and `2x` both parse. sym.verify reports
13
+ unproven as unproven -- it is never a disproof.
14
+
15
+ ## Why this agent is separate
16
+
17
+ Sandboxed subprocess, touches no database.
18
+
19
+ Run with `ATTEST_TOOLS=symbolic`. Tools outside `sym` are not
20
+ registered for this agent: they are absent rather than merely
21
+ undocumented, because a model that can see a tool will eventually
22
+ call it.
@@ -0,0 +1,124 @@
1
+ # attestation configuration — copy to .env and edit: cp .env.sample .env
2
+ # Loaded at startup by the `attest` CLI and the MCP server (attest-mcp).
3
+ # Real environment variables always win over values in this file.
4
+
5
+ # OpenAI-compatible endpoint serving chat + embeddings (Ollama's /v1 by default).
6
+ # Swap backends by pointing this elsewhere (vLLM, llama.cpp server, OpenRouter...).
7
+ LLM_BASE_URL=http://localhost:11434/v1
8
+
9
+ # API key, sent as a Bearer token when set. Ollama ignores auth; needed for
10
+ # OpenRouter / authenticated vLLM / OpenAI.
11
+ #LLM_API_KEY=
12
+
13
+ # --- Hosted models instead of Ollama (no GPU, no 7.8 GB download) -------------
14
+ # Any OpenAI-compatible endpoint works. NVIDIA NIM, for example:
15
+ #LLM_BASE_URL=https://integrate.api.nvidia.com/v1
16
+ #LLM_API_KEY=nvapi-...
17
+ #CHAT_MODEL=<a chat model your account can call -- see below>
18
+ #EMBED_MODEL=nvidia/nemotron-3-embed-1b
19
+ # `attest install --check` makes one embedding and one one-token chat request
20
+ # and reports the server's own reason when a model fails. MEASURED 2026-09-11:
21
+ # NIM listed 82 models; nemotron-3-embed-1b answered (2048 dims) while every
22
+ # chat model tried answered 410 (end of life) or 404 (not enabled for the
23
+ # account) -- so pick a chat model from /v1/models and let --check confirm it
24
+ # rather than trusting the catalogue.
25
+ # EMBED_DIMS is a client-side truncation, so a 2048-dim model stores 256 dims
26
+ # unchanged; a model NARROWER than EMBED_DIMS is refused. Switching embedding
27
+ # models means a fresh database (get_db refuses a mismatched reopen).
28
+ # Hosted models send your titles, abstracts and interests text off the machine;
29
+ # the ledger and claim checker never touch a model and stay local either way.
30
+
31
+ # Chat model for explanations + tagging.
32
+ # gemma4:e2b measured on 2x GTX 1080 (8 GB each), ollama 0.32.9: 2.2 GB
33
+ # resident, 100% GPU, ~2.2s per tagging call, and clean canonical tags.
34
+ # hermes3:3b is smaller but emitted a malformed tag on 40% of items, and
35
+ # gemma4:12b partially CPU-offloads on 8 GB-class cards (~60-90s/call).
36
+ # NB: gemma4:e2b needs ollama >= 0.32.9 (earlier builds abort with
37
+ # GGML_ASSERT in the graph scheduler). This is a MANUAL requirement: nothing
38
+ # in this repo checks the daemon version (`attest install`/`--check` verify
39
+ # model presence, not Ollama's version) -- run `ollama --version` yourself.
40
+ CHAT_MODEL=gemma4:e2b-it-q4_K_M
41
+
42
+ # Embedding model.
43
+ #EMBED_MODEL=embeddinggemma
44
+
45
+ # Stored embedding dimensionality (Matryoshka truncation, client-side).
46
+ # WARNING: changing this invalidates every stored vector — delete the database
47
+ # and re-ingest. get_db() refuses to open a mismatched database.
48
+ #EMBED_DIMS=256
49
+
50
+ # Database path override (default resolution order is documented in the README).
51
+ # RSS_DB, the pre-rename name, is still honoured when ATTEST_DB is unset.
52
+ #ATTEST_DB=/home/you/.hermes/skills/science-recommendations/data/hermes.db
53
+ #RSS_DB=
54
+
55
+ # The agent home every other path hangs off: skills, the refresh script and its
56
+ # lock, the citation cache, the ledger's config fallback, and where a legacy
57
+ # skill-data database is looked for. Unset, ~/.hermes -- which is right on a
58
+ # laptop with one agent and wrong on a provisioned box, where `attest install`
59
+ # would otherwise write into the operator's real Hermes home.
60
+ # ATTEST_DB above still wins for the database specifically.
61
+ #HERMES_HOME=/home/you/.agent37-pilots/instances/research/.hermes
62
+
63
+ # Which libraries feed citations and `attest library sync`. Unset, every *.bib
64
+ # in the current directory and Zotero's default ~/Zotero/zotero.sqlite.
65
+ # ATTEST_BIB_PATHS is os.pathsep-separated (":" on Linux/macOS).
66
+ #ATTEST_BIB_PATHS=/home/you/papers/refs.bib:/home/you/thesis/thesis.bib
67
+ #ATTEST_ZOTERO_PATH=/home/you/Zotero/zotero.sqlite
68
+
69
+ # The settings that allow a network call. Unset, every citation lookup and
70
+ # library sync is local (Zotero + *.bib + the feed). ATTEST_CITATION_WEB
71
+ # (anything but 0/false) arms CrossRef and the arXiv API: metadata for
72
+ # references the library already holds -- they never add a paper on their
73
+ # own. ATTEST_CITATION_SCHOLAR arms Semantic Scholar reference lists, a second flag
74
+ # because it is a larger, rate-limited surface (one request per second,
75
+ # cached forever). Both are read when readers are BUILT, not per call;
76
+ # `cite.sources()` reports what is live.
77
+ #ATTEST_CITATION_WEB=1
78
+ #ATTEST_CITATION_SCHOLAR=1
79
+
80
+ # Paper research (standing topics as research: feeds, the feed.research tool
81
+ # and full text) reaches arXiv, PubMed and CrossRef. ON by default: `attest
82
+ # ingest` already fetches RSS over the network and a topic query is the same
83
+ # class of call in the same command. Set to 0 to make every research client a
84
+ # no-op that reports `offline`. Read once when the clients are built.
85
+ #ATTEST_RESEARCH_WEB=1
86
+ # Optional NCBI key: PubMed allows 3 requests/s without one, 10 with.
87
+ #NCBI_API_KEY=
88
+
89
+ # Where `attest runs scan` looks for experiment artifacts when no path is
90
+ # given. The ledger reads finished runs off disk and needs no model, so this is
91
+ # the one setting that matters for the provenance half of the tool.
92
+ #RESEARCH_ROOT=/home/you/projects
93
+
94
+ # --- Agent surface selection (set per MCP server entry, not usually here) -----
95
+ # ATTEST_TOOLS restricts a session to ONE namespace, so a tool outside its
96
+ # remit is absent rather than merely undocumented. Measured on gemma4:e2b: one
97
+ # agent choosing among the full flat surface answered 8/15; four restricted
98
+ # agents plus deterministic routers answered 13/15. `attest emit` generates the
99
+ # per-surface config entries, so you rarely set this by hand.
100
+ # feed | provenance | knowledge | symbolic (an unknown value RAISES)
101
+ #ATTEST_TOOLS=feed
102
+
103
+ # Reveal a surface's specific tools from the start instead of only its `.ask`
104
+ # router. Measured: with the specifics visible the model picked the router 1
105
+ # time in 26; with only the router visible, 26 in 26. Leave unset unless a
106
+ # caller already knows exactly which tool it wants.
107
+ #ATTEST_EXPAND=1
108
+
109
+ # --- Ollama SERVER settings (read by the ollama daemon, NOT by hermes) --------
110
+ # Set these in the environment that launches `ollama serve` (e.g. its systemd
111
+ # unit), not here. /v1 requests cannot pin models or set context length, so
112
+ # these replace the per-request keep_alive/num_ctx knobs of the native API.
113
+ #OLLAMA_MAX_LOADED_MODELS=2 # keep chat + embed models co-resident
114
+ #OLLAMA_KEEP_ALIVE=30m # hold models this long (matches `attest warmup`)
115
+ # NOT -1. That pins models until the year 2318: measured at 5.4GB held and OOM
116
+ # kills on a 23GB box, because nothing ever releases them.
117
+ #OLLAMA_CONTEXT_LENGTH=32768 # context window for /v1 requests
118
+ # 32768 is a floor, not a suggestion. Ollama defaults to 4096, which silently
119
+ # truncates the tool list mid-JSON -- the tools then appear not to exist rather
120
+ # than failing, which is far harder to diagnose than an error.
121
+
122
+ # An optimized tagging-prompt artifact (evals/prompts/*.json) for `attest tag`.
123
+ # Unset = the hand-written prompt. Produced offline by evals/optimize_tagging.py.
124
+ #ATTEST_TAG_PROMPT=
@@ -0,0 +1,160 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ gates:
10
+ name: gates (${{ matrix.os }}, py${{ matrix.python-version }})
11
+ runs-on: ${{ matrix.os }}
12
+ env:
13
+ # macos-latest ships a python.org framework build at
14
+ # /Library/Frameworks/Python.framework, and uv picks it over its own
15
+ # managed CPython when the version matches. That build has no
16
+ # sqlite3 loadable-extension support, so sqlite-vec cannot load and
17
+ # db.get_db() dies at conn.enable_load_extension (254 failures on the
18
+ # first CI run, 2026-08-28). uv's managed builds enable it on every OS.
19
+ UV_PYTHON_PREFERENCE: only-managed
20
+ strategy:
21
+ fail-fast: false
22
+ matrix:
23
+ os: [ubuntu-latest, macos-latest]
24
+ python-version: ["3.12", "3.13"]
25
+ steps:
26
+ - uses: actions/checkout@v4
27
+
28
+ - name: Install uv
29
+ uses: astral-sh/setup-uv@v5
30
+ with:
31
+ python-version: ${{ matrix.python-version }}
32
+
33
+ - name: Sync dependencies
34
+ run: uv sync --all-extras --dev
35
+
36
+ - name: ruff format --check
37
+ run: uv run ruff format --check .
38
+
39
+ - name: ruff check
40
+ run: uv run ruff check .
41
+
42
+ - name: ty check
43
+ run: uv run ty check src/
44
+
45
+ - name: uv.lock is in sync with pyproject.toml
46
+ run: uv lock --check
47
+
48
+ - name: complexity ratchet (radon)
49
+ run: uv run python scripts/check_complexity.py
50
+
51
+ - name: bandit (security)
52
+ run: uv run bandit -q -c pyproject.toml -r src/attestation --severity-level medium
53
+
54
+ - name: xenon (maintainability)
55
+ run: uv run xenon --max-modules B --max-average A src/attestation
56
+
57
+ - name: pytest
58
+ run: uv run pytest -q
59
+
60
+ wheel-smoke:
61
+ name: wheel smoke test
62
+ runs-on: ubuntu-latest
63
+ steps:
64
+ - uses: actions/checkout@v4
65
+
66
+ - name: Install uv
67
+ uses: astral-sh/setup-uv@v5
68
+ with:
69
+ python-version: "3.12"
70
+
71
+ - name: Build wheel
72
+ run: uv build
73
+
74
+ - name: Install wheel into a clean venv
75
+ run: |
76
+ python3 -m venv /tmp/wheel-venv
77
+ /tmp/wheel-venv/bin/pip install --quiet dist/*.whl
78
+
79
+ - name: attest --help exits 0
80
+ run: /tmp/wheel-venv/bin/attest --help
81
+
82
+ - name: attestation.server imports cleanly
83
+ run: /tmp/wheel-venv/bin/python -c "import attestation.server"
84
+
85
+ - name: feeds.toml is packaged
86
+ # Regression insurance: the advertised `uvx --from git+... attest ingest`
87
+ # on-ramp reads attestation/feeds.toml out of the installed package, so
88
+ # a repackaging that drops it breaks first-run ingest silently.
89
+ run: |
90
+ /tmp/wheel-venv/bin/python -c "
91
+ import importlib.resources as r
92
+ p = r.files('attestation').joinpath('feeds.toml')
93
+ assert p.is_file(), 'attestation/feeds.toml missing from installed wheel'
94
+ print('feeds.toml present in wheel:', p)
95
+ "
96
+
97
+ - name: py.typed is packaged
98
+ # Same regression insurance as feeds.toml above: a downstream type
99
+ # checker treats a package with no py.typed as untyped and ignores
100
+ # its annotations, silently, even though this repo checks them with
101
+ # `ty` on every commit.
102
+ run: |
103
+ /tmp/wheel-venv/bin/python -c "
104
+ import importlib.resources as r
105
+ p = r.files('attestation').joinpath('py.typed')
106
+ assert p.is_file(), 'attestation/py.typed missing from installed wheel'
107
+ print('py.typed present in wheel:', p)
108
+ "
109
+
110
+ flows:
111
+ name: example flows (offline)
112
+ runs-on: ubuntu-latest
113
+ env:
114
+ UV_PYTHON_PREFERENCE: only-managed
115
+ steps:
116
+ - uses: actions/checkout@v4
117
+
118
+ - name: Install uv
119
+ uses: astral-sh/setup-uv@v5
120
+ with:
121
+ python-version: "3.12"
122
+
123
+ - name: Sync dependencies (with the examples group)
124
+ run: uv sync --all-extras --dev --group examples
125
+
126
+ - name: Every flow, against the stub model server
127
+ # The demonstration in examples/flows, end to end: the MLflow family,
128
+ # the persona eval, and every MCP tool over stdio. No Ollama, no
129
+ # network. Its numbers are about the stub and say so; the point is
130
+ # that the flows cannot rot.
131
+ run: uv run python examples/flows/run_all.py --offline
132
+
133
+ docs:
134
+ name: docs site
135
+ runs-on: ubuntu-latest
136
+ env:
137
+ UV_PYTHON_PREFERENCE: only-managed
138
+ steps:
139
+ - uses: actions/checkout@v4
140
+
141
+ - name: Install uv
142
+ uses: astral-sh/setup-uv@v5
143
+ with:
144
+ python-version: "3.12"
145
+
146
+ - name: Sync dependencies (with the docs group)
147
+ run: uv sync --all-extras --dev --group docs
148
+
149
+ - name: mkdocs build --strict
150
+ # A docstring that breaks a cross-reference, or a nav entry in
151
+ # mkdocs.yml that points nowhere, fails the push here rather than
152
+ # rotting silently. The `gates` job does not install the docs group,
153
+ # so this job runs the real build itself.
154
+ run: uv run --group docs mkdocs build --strict
155
+
156
+ - name: Upload built site
157
+ uses: actions/upload-artifact@v4
158
+ with:
159
+ name: docs-site
160
+ path: site/
@@ -0,0 +1,50 @@
1
+ # Deploys the docs site to GitHub Pages from main. The build is the same
2
+ # command the `docs site` job in ci.yml runs (`mkdocs build --strict`), so
3
+ # a page that would fail CI never deploys; this workflow only adds the
4
+ # Pages upload and deploy steps behind it. Pages must be set to deploy from
5
+ # GitHub Actions in the repository settings (done once with
6
+ # `gh api -X POST repos/<owner>/<repo>/pages -f build_type=workflow`).
7
+ name: docs
8
+
9
+ on:
10
+ push:
11
+ branches: [main]
12
+ workflow_dispatch:
13
+
14
+ permissions:
15
+ contents: read
16
+ pages: write
17
+ id-token: write
18
+
19
+ concurrency:
20
+ group: pages
21
+ cancel-in-progress: true
22
+
23
+ jobs:
24
+ build:
25
+ runs-on: ubuntu-latest
26
+ env:
27
+ UV_PYTHON_PREFERENCE: only-managed
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+ - name: Install uv
31
+ uses: astral-sh/setup-uv@v5
32
+ with:
33
+ python-version: "3.12"
34
+ - name: Sync dependencies (with the docs group)
35
+ run: uv sync --all-extras --dev --group docs
36
+ - name: mkdocs build --strict
37
+ run: uv run --group docs mkdocs build --strict
38
+ - uses: actions/upload-pages-artifact@v3
39
+ with:
40
+ path: site/
41
+
42
+ deploy:
43
+ needs: build
44
+ runs-on: ubuntu-latest
45
+ environment:
46
+ name: github-pages
47
+ url: ${{ steps.deployment.outputs.page_url }}
48
+ steps:
49
+ - id: deployment
50
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,64 @@
1
+ name: Release
2
+
3
+ # Tag-triggered PyPI publish through trusted publishing (OIDC): no API token
4
+ # lives in this repo. One-time setup on pypi.org -> project "attestation" ->
5
+ # Publishing -> add a GitHub publisher with owner mgoldey, repository
6
+ # attestation, workflow release.yml, environment pypi. Then:
7
+ #
8
+ # git tag v0.2.0 && git push origin v0.2.0
9
+ #
10
+ # The build job refuses a tag that does not match pyproject's version, so a
11
+ # release cannot ship under a number the package does not carry.
12
+
13
+ on:
14
+ push:
15
+ tags: ["v*"]
16
+
17
+ jobs:
18
+ build:
19
+ name: build + smoke
20
+ runs-on: ubuntu-latest
21
+ steps:
22
+ - uses: actions/checkout@v4
23
+
24
+ - name: Install uv
25
+ uses: astral-sh/setup-uv@v5
26
+ with:
27
+ python-version: "3.12"
28
+
29
+ - name: Tag matches pyproject version
30
+ run: |
31
+ tag="${GITHUB_REF_NAME#v}"
32
+ version="$(python3 -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")"
33
+ test "$tag" = "$version" || { echo "tag v$tag != pyproject version $version" >&2; exit 1; }
34
+
35
+ - name: Build sdist + wheel
36
+ run: uv build
37
+
38
+ - name: Wheel installs and both console scripts answer
39
+ run: |
40
+ python3 -m venv /tmp/wheel-venv
41
+ /tmp/wheel-venv/bin/pip install --quiet dist/*.whl
42
+ /tmp/wheel-venv/bin/attest --help >/dev/null
43
+ /tmp/wheel-venv/bin/attestation --help >/dev/null
44
+ /tmp/wheel-venv/bin/attest-mcp --help >/dev/null 2>&1 || true
45
+
46
+ - uses: actions/upload-artifact@v4
47
+ with:
48
+ name: dist
49
+ path: dist/
50
+
51
+ publish:
52
+ name: publish to PyPI
53
+ needs: build
54
+ runs-on: ubuntu-latest
55
+ environment: pypi
56
+ permissions:
57
+ id-token: write
58
+ steps:
59
+ - uses: actions/download-artifact@v4
60
+ with:
61
+ name: dist
62
+ path: dist/
63
+
64
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,48 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.db
4
+ *.db-wal
5
+ *.db-shm
6
+ # Retag/migration snapshots: `*.db` does not match a .bak-retag-<stamp>
7
+ # suffix, so an 8MB copy of the database was one `git add .` from the
8
+ # history it can never be removed from.
9
+ *.db.bak*
10
+ .ruff_cache/
11
+ .pytest_cache/
12
+ .env
13
+ # Credential-bearing env files (neon.env holds a live Postgres password and S3
14
+ # secret keys). `.env` alone does not match `neon.env` or `*.env`.
15
+ *.env
16
+
17
+ # Local demo recordings: a 5.5MB .webm plus stills, never committed. Kept out
18
+ # of the repo so a clone stays small -- a binary that large is permanent
19
+ # history once added. Host it externally and link from the README if it needs to
20
+ # be shared. demos/*/record.sh and record.py write here by default.
21
+ demo/
22
+
23
+ # demos/: recording scripts are committed, their .cast/.gif/.webm output and
24
+ # the scratch databases seed_*_db.py builds are not (same reasoning as
25
+ # demo/ above -- regenerable, and a real .cast is a transcript that can
26
+ # carry whatever path ran it). demos/ lives at the repo root, not under
27
+ # examples/, on purpose -- see CLAUDE.md's Golden paths note.
28
+ demos/**/*.cast
29
+ demos/**/*.gif
30
+ demos/**/*.webm
31
+ demos/**/*.db
32
+
33
+ # Build artifacts: `uv build` / CI wheel smoke test write here.
34
+ dist/
35
+ build/
36
+ .mutate-backup/
37
+
38
+ # `mkdocs build` output. Built, not deployed; CI's `docs` job uploads it as
39
+ # an artifact instead of committing it. Anchored to the root: `docs/site/`
40
+ # holds a committed, generated page (the design-records index) and must not
41
+ # be swept up by an unanchored `site/`.
42
+ /site/
43
+
44
+ # Process logs from the superpowers plugin (design/plan transcripts) and a uv
45
+ # cache left by a run with HOME pointed at a fake path: both sat untracked-but-
46
+ # unignored, one `git add .` from becoming permanent history.
47
+ .superpowers/
48
+ nonexistent-home/
Binary file
@@ -0,0 +1,100 @@
1
+ # Local hooks only: every tool is already a declared dev dependency, so they
2
+ # run against the versions this project pins. The alternative (pre-commit's own
3
+ # isolated envs) would install a *second* copy of ruff at a version nothing
4
+ # else uses, and drift silently.
5
+ #
6
+ # Entries call `uv run --frozen ...` rather than `.venv/bin/...`: `.venv/` is
7
+ # gitignored, so those paths do not exist on a fresh clone until `uv sync`, and
8
+ # a CI runner using astral-sh/setup-uv need not put its venv at `.venv` at all
9
+ # -- which is the environment .github/workflows/ci.yml runs in. `--frozen`
10
+ # keeps these hooks from ever mutating uv.lock as a side effect.
11
+ #
12
+ # These hooks once called `.venv/bin/...` to route around what looked like a uv
13
+ # bug under pre-commit's scrubbed environment. It was not: the venv had been
14
+ # built at the project's old path and 26 of its console scripts still pointed
15
+ # their shebang at an interpreter that no longer existed. `uv sync` fixed it.
16
+ # See CLAUDE.md "Working here".
17
+ #
18
+ # uv run pre-commit install # activate
19
+ # uv run pre-commit run --all-files
20
+ # git commit --no-verify # bypass once, deliberately
21
+ repos:
22
+ - repo: local
23
+ hooks:
24
+ - id: ruff-format
25
+ name: ruff format
26
+ entry: uv run --frozen ruff format
27
+ language: system
28
+ types_or: [python, pyi]
29
+
30
+ - id: ruff-check
31
+ name: ruff check
32
+ entry: uv run --frozen ruff check --fix
33
+ language: system
34
+ types_or: [python, pyi]
35
+
36
+ - id: ty
37
+ name: ty (type check)
38
+ entry: uv run --frozen ty check src/
39
+ language: system
40
+ types_or: [python, pyi]
41
+ # src/ only, and always the whole tree: ty resolves imports across
42
+ # modules, so checking just the staged files reports errors that a
43
+ # full run does not, and misses ones it would catch.
44
+ pass_filenames: false
45
+
46
+ - id: uv-lock
47
+ name: uv.lock matches pyproject.toml
48
+ entry: uv lock --check
49
+ language: system
50
+ files: ^(pyproject\.toml|uv\.lock)$
51
+ pass_filenames: false
52
+
53
+ - id: complexity
54
+ name: complexity ratchet (radon)
55
+ entry: uv run --frozen python scripts/check_complexity.py
56
+ language: system
57
+ types: [python]
58
+ pass_filenames: false
59
+ # Per-file, not global. A single --max-absolute threshold set loose
60
+ # enough to pass a clean checkout also permits any file to grow a
61
+ # function at that rank -- verified by adding a 17-branch function and
62
+ # watching a global gate return 0. Each file is pinned at its own
63
+ # measured worst instead, so getting worse requires editing the list.
64
+
65
+ - id: bandit
66
+ name: bandit (security)
67
+ entry: uv run --frozen bandit -q -c pyproject.toml -r src/attestation --severity-level medium
68
+ language: system
69
+ types: [python]
70
+ pass_filenames: false
71
+ # Medium and above only. At LOW, bandit reports every `import
72
+ # subprocess` and every partial executable path, which here are 8
73
+ # deliberate calls with static argv and no shell -- noise that trains
74
+ # people to ignore the hook. Baseline at adoption: 0 findings at
75
+ # medium, 0 at high.
76
+
77
+ - id: xenon
78
+ name: xenon (maintainability)
79
+ entry: uv run --frozen xenon --max-modules B --max-average A src/attestation
80
+ language: system
81
+ types: [python]
82
+ pass_filenames: false
83
+ # Module and average grades only -- NOT --max-absolute, which was tried
84
+ # here and found hollow: `--max-absolute D` returned exit 0 against a
85
+ # 26-branch function. Per-function complexity is enforced by the radon
86
+ # ratchet above, which pins each file at its own measured worst. This
87
+ # hook covers what that one does not: a module whose total complexity
88
+ # creeps up while no single function crosses its own line.
89
+
90
+ - id: pytest
91
+ name: pytest
92
+ entry: uv run --frozen pytest -q
93
+ language: system
94
+ types: [python]
95
+ pass_filenames: false
96
+ # The suite is ~50s. That is slow for a hook and worth it here: this
97
+ # repo's recurring failure has been tests that pass against the bug
98
+ # they were written to catch, so a green suite is the one signal that
99
+ # has repeatedly mattered. Drop this hook if it starts being bypassed.
100
+ stages: [pre-commit]
@@ -0,0 +1 @@
1
+ 3.12.12