pen-stack 8.0.3__tar.gz → 8.0.5__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 (1072) hide show
  1. pen_stack-8.0.5/CHANGELOG.md +2549 -0
  2. pen_stack-8.0.5/CITATION.cff +24 -0
  3. pen_stack-8.0.5/PKG-INFO +382 -0
  4. pen_stack-8.0.5/README.md +296 -0
  5. pen_stack-8.0.5/bench/run.py +173 -0
  6. pen_stack-8.0.5/benchmarks/chat_grounding/README.md +26 -0
  7. pen_stack-8.0.5/benchmarks/chat_grounding/SHA256SUMS +1 -0
  8. pen_stack-8.0.5/benchmarks/chat_headtohead/README.md +29 -0
  9. pen_stack-8.0.5/benchmarks/chat_routing/README.md +35 -0
  10. pen_stack-8.0.5/benchmarks/chat_routing/SHA256SUMS +1 -0
  11. pen_stack-8.0.5/benchmarks/chat_safety/README.md +23 -0
  12. pen_stack-8.0.5/benchmarks/chat_safety/SHA256SUMS +1 -0
  13. pen_stack-8.0.5/benchmarks/genome_writing_bench/LEADERBOARD.md +67 -0
  14. pen_stack-8.0.5/benchmarks/genome_writing_bench/README.md +87 -0
  15. pen_stack-8.0.5/benchmarks/genome_writing_bench/SUBMISSIONS.md +53 -0
  16. pen_stack-8.0.5/benchmarks/genome_writing_challenge/SUBMISSIONS.md +16 -0
  17. pen_stack-8.0.5/benchmarks/genotox_panel/README.md +125 -0
  18. pen_stack-8.0.5/benchmarks/grounding_llm_on/README.md +58 -0
  19. pen_stack-8.0.5/benchmarks/loop/SHA256SUMS +2 -0
  20. pen_stack-8.0.5/benchmarks/offtarget/integrase/README.md +23 -0
  21. pen_stack-8.0.5/benchmarks/offtarget/integrase/SHA256SUMS +4 -0
  22. pen_stack-8.0.5/benchmarks/offtarget/integrase_chalberg/README.md +55 -0
  23. pen_stack-8.0.5/benchmarks/oracle/SHA256SUMS +5 -0
  24. pen_stack-8.0.5/benchmarks/position_effect/README.md +68 -0
  25. pen_stack-8.0.5/benchmarks/position_effect/SHA256SUMS +1 -0
  26. pen_stack-8.0.5/benchmarks/position_effect_human/README.md +115 -0
  27. pen_stack-8.0.5/benchmarks/priorart/epridict/README.md +62 -0
  28. pen_stack-8.0.5/benchmarks/priorart/epridict/SHA256SUMS +5 -0
  29. pen_stack-8.0.5/benchmarks/priorart/gsh_recovery/README.md +66 -0
  30. pen_stack-8.0.5/benchmarks/priorart/gsh_recovery/SHA256SUMS +4 -0
  31. pen_stack-8.0.5/benchmarks/writer_efficiency/README.md +54 -0
  32. pen_stack-8.0.5/benchmarks/writer_efficiency/SHA256SUMS +2 -0
  33. pen_stack-8.0.5/benchmarks/writespec/SHA256SUMS +4 -0
  34. pen_stack-8.0.5/configs/aav_serotype_tropism.yaml +81 -0
  35. pen_stack-8.0.5/configs/antipeg.yaml +28 -0
  36. pen_stack-8.0.5/configs/cargo_polish.yaml +45 -0
  37. pen_stack-8.0.5/configs/cell_types.yaml +56 -0
  38. pen_stack-8.0.5/configs/datasets.yaml +99 -0
  39. pen_stack-8.0.5/configs/expression/modifiers.yaml +59 -0
  40. pen_stack-8.0.5/configs/expression/promoters.yaml +52 -0
  41. pen_stack-8.0.5/configs/intent_weights.yaml +57 -0
  42. pen_stack-8.0.5/configs/llm.yaml +72 -0
  43. pen_stack-8.0.5/configs/monitor_queries.yaml +33 -0
  44. pen_stack-8.0.5/configs/oracles/execution.yaml +95 -0
  45. pen_stack-8.0.5/configs/oracles/scope_cards.yaml +250 -0
  46. pen_stack-8.0.5/configs/rules/delivery.yaml +49 -0
  47. pen_stack-8.0.5/configs/seroprevalence.yaml +64 -0
  48. pen_stack-8.0.5/configs/writer_sequences.fasta +12 -0
  49. pen_stack-8.0.5/data/curated/bridge_offtarget_energetics.json +202 -0
  50. pen_stack-8.0.5/data/curated/cast_systems.yaml +59 -0
  51. pen_stack-8.0.5/data/curated/integrase_att.yaml +66 -0
  52. pen_stack-8.0.5/docs/DEPLOY.md +39 -0
  53. pen_stack-8.0.5/docs/INFRA.md +64 -0
  54. pen_stack-8.0.5/docs/MCP.md +24 -0
  55. pen_stack-8.0.5/docs/RELEASING.md +60 -0
  56. pen_stack-8.0.5/docs/REPRO.md +46 -0
  57. pen_stack-8.0.5/docs/agent.md +78 -0
  58. pen_stack-8.0.5/docs/benchmark_circularity.md +64 -0
  59. pen_stack-8.0.5/docs/biosecurity.md +101 -0
  60. pen_stack-8.0.5/docs/cards/atlas.md +41 -0
  61. pen_stack-8.0.5/docs/cards/durability.md +43 -0
  62. pen_stack-8.0.5/docs/cards/offtarget_data.md +117 -0
  63. pen_stack-8.0.5/docs/cards/position_effect_data.md +36 -0
  64. pen_stack-8.0.5/docs/cards/priorart.md +66 -0
  65. pen_stack-8.0.5/docs/cards/safety.md +39 -0
  66. pen_stack-8.0.5/docs/cards/writer_efficiency_data.md +48 -0
  67. pen_stack-8.0.5/docs/closed_loop.md +79 -0
  68. pen_stack-8.0.5/docs/delivery_recommender.md +54 -0
  69. pen_stack-8.0.5/docs/dissemination.md +34 -0
  70. pen_stack-8.0.5/docs/environment.md +59 -0
  71. pen_stack-8.0.5/docs/generative_design.md +63 -0
  72. pen_stack-8.0.5/docs/immune_profiler.md +70 -0
  73. pen_stack-8.0.5/docs/index.md +48 -0
  74. pen_stack-8.0.5/docs/offtarget.md +59 -0
  75. pen_stack-8.0.5/docs/oracles.md +51 -0
  76. pen_stack-8.0.5/docs/position_effect.md +57 -0
  77. pen_stack-8.0.5/docs/positioning.md +55 -0
  78. pen_stack-8.0.5/docs/private_data_formats.md +61 -0
  79. pen_stack-8.0.5/docs/quickstart.md +64 -0
  80. pen_stack-8.0.5/docs/responsible_use.md +96 -0
  81. pen_stack-8.0.5/docs/scope.md +50 -0
  82. pen_stack-8.0.5/docs/scorecard.md +54 -0
  83. pen_stack-8.0.5/docs/tpe_bench.md +48 -0
  84. pen_stack-8.0.5/docs/tutorials/score-deliverability.md +36 -0
  85. pen_stack-8.0.5/docs/tutorials/where-can-i-write.md +45 -0
  86. pen_stack-8.0.5/docs/tutorials/which-writer-reaches-locus.md +41 -0
  87. pen_stack-8.0.5/docs/uncertainty.md +84 -0
  88. pen_stack-8.0.5/docs/world_model.md +49 -0
  89. pen_stack-8.0.5/docs/writer_efficiency.md +59 -0
  90. pen_stack-8.0.5/docs/writer_verification.md +46 -0
  91. pen_stack-8.0.5/docs/writespec_bench.md +44 -0
  92. pen_stack-8.0.5/docs/writespec_profile.md +58 -0
  93. pen_stack-8.0.5/docs/wtkb.md +25 -0
  94. pen_stack-8.0.5/pen_stack/__init__.py +2 -0
  95. pen_stack-8.0.5/pen_stack/active/acquire.py +165 -0
  96. pen_stack-8.0.5/pen_stack/active/brains.py +74 -0
  97. pen_stack-8.0.5/pen_stack/active/campaign.py +109 -0
  98. pen_stack-8.0.5/pen_stack/active/design.py +66 -0
  99. pen_stack-8.0.5/pen_stack/active/validate.py +104 -0
  100. pen_stack-8.0.5/pen_stack/adapt/__init__.py +14 -0
  101. pen_stack-8.0.5/pen_stack/adapt/finetune.py +33 -0
  102. pen_stack-8.0.5/pen_stack/adapt/ingest.py +86 -0
  103. pen_stack-8.0.5/pen_stack/adapt/pipeline.py +101 -0
  104. pen_stack-8.0.5/pen_stack/adapt/recalibrate.py +58 -0
  105. pen_stack-8.0.5/pen_stack/adapt/report.py +130 -0
  106. pen_stack-8.0.5/pen_stack/agent/__init__.py +1 -0
  107. pen_stack-8.0.5/pen_stack/agent/cite.py +175 -0
  108. pen_stack-8.0.5/pen_stack/agent/co_scientist.py +262 -0
  109. pen_stack-8.0.5/pen_stack/agent/epistemic.py +102 -0
  110. pen_stack-8.0.5/pen_stack/agent/guardrails.py +67 -0
  111. pen_stack-8.0.5/pen_stack/agent/mcp_server.py +215 -0
  112. pen_stack-8.0.5/pen_stack/agent/orchestrator.py +112 -0
  113. pen_stack-8.0.5/pen_stack/agent/orchestrator_live.py +56 -0
  114. pen_stack-8.0.5/pen_stack/agent/pen_agent.py +242 -0
  115. pen_stack-8.0.5/pen_stack/agent/scope.py +60 -0
  116. pen_stack-8.0.5/pen_stack/agent/tools.py +130 -0
  117. pen_stack-8.0.5/pen_stack/api/manifest.py +160 -0
  118. pen_stack-8.0.5/pen_stack/atlas/__init__.py +1 -0
  119. pen_stack-8.0.5/pen_stack/atlas/atlas.parquet +0 -0
  120. pen_stack-8.0.5/pen_stack/atlas/build_wtkb.py +80 -0
  121. pen_stack-8.0.5/pen_stack/atlas/crosslink.py +179 -0
  122. pen_stack-8.0.5/pen_stack/atlas/expand.py +190 -0
  123. pen_stack-8.0.5/pen_stack/atlas/guide_design.py +178 -0
  124. pen_stack-8.0.5/pen_stack/atlas/schema.py +59 -0
  125. pen_stack-8.0.5/pen_stack/atlas/scorecard.py +134 -0
  126. pen_stack-8.0.5/pen_stack/atlas/scorecard_v3.parquet +0 -0
  127. pen_stack-8.0.5/pen_stack/atlas/universe.py +75 -0
  128. pen_stack-8.0.5/pen_stack/atlas/universe_v3.parquet +0 -0
  129. pen_stack-8.0.5/pen_stack/atlas/variant_propose.py +155 -0
  130. pen_stack-8.0.5/pen_stack/atlas/writer_efficiency.py +184 -0
  131. pen_stack-8.0.5/pen_stack/atlas/writer_predict.py +225 -0
  132. pen_stack-8.0.5/pen_stack/atlas/writer_recommend.py +165 -0
  133. pen_stack-8.0.5/pen_stack/atlas/writer_verify.py +167 -0
  134. pen_stack-8.0.5/pen_stack/atlas/wtkb.parquet +0 -0
  135. pen_stack-8.0.5/pen_stack/bridge/__init__.py +1 -0
  136. pen_stack-8.0.5/pen_stack/bridge/activity.py +52 -0
  137. pen_stack-8.0.5/pen_stack/bridge/cli.py +65 -0
  138. pen_stack-8.0.5/pen_stack/bridge/fold_qc.py +53 -0
  139. pen_stack-8.0.5/pen_stack/bridge/guide_qc.py +87 -0
  140. pen_stack-8.0.5/pen_stack/bridge/ingest.py +139 -0
  141. pen_stack-8.0.5/pen_stack/bridge/offtarget.py +191 -0
  142. pen_stack-8.0.5/pen_stack/bridge/offtarget_energetics.py +105 -0
  143. pen_stack-8.0.5/pen_stack/bridge/ortholog_screen.py +73 -0
  144. pen_stack-8.0.5/pen_stack/bridge/pipeline.py +83 -0
  145. pen_stack-8.0.5/pen_stack/build/cloudlab.py +74 -0
  146. pen_stack-8.0.5/pen_stack/build/ingest.py +47 -0
  147. pen_stack-8.0.5/pen_stack/build/protocol.py +82 -0
  148. pen_stack-8.0.5/pen_stack/build/simlab.py +30 -0
  149. pen_stack-8.0.5/pen_stack/cli.py +126 -0
  150. pen_stack-8.0.5/pen_stack/data/__init__.py +1 -0
  151. pen_stack-8.0.5/pen_stack/data/encode.py +84 -0
  152. pen_stack-8.0.5/pen_stack/data/genome.py +71 -0
  153. pen_stack-8.0.5/pen_stack/data/ingest_chromatin.py +119 -0
  154. pen_stack-8.0.5/pen_stack/data/ingest_integration.py +112 -0
  155. pen_stack-8.0.5/pen_stack/data/ingest_safety_annot.py +201 -0
  156. pen_stack-8.0.5/pen_stack/data/ingest_trip.py +76 -0
  157. pen_stack-8.0.5/pen_stack/design/capsid_generate.py +62 -0
  158. pen_stack-8.0.5/pen_stack/design/generate.py +70 -0
  159. pen_stack-8.0.5/pen_stack/design/pareto.py +70 -0
  160. pen_stack-8.0.5/pen_stack/design/space.py +137 -0
  161. pen_stack-8.0.5/pen_stack/design/writer_variants.py +121 -0
  162. pen_stack-8.0.5/pen_stack/env/__init__.py +1 -0
  163. pen_stack-8.0.5/pen_stack/env/genome_writing_env.py +248 -0
  164. pen_stack-8.0.5/pen_stack/env/policies.py +94 -0
  165. pen_stack-8.0.5/pen_stack/graph/__init__.py +21 -0
  166. pen_stack-8.0.5/pen_stack/graph/build.py +133 -0
  167. pen_stack-8.0.5/pen_stack/graph/cell_types.py +58 -0
  168. pen_stack-8.0.5/pen_stack/graph/ingest.py +132 -0
  169. pen_stack-8.0.5/pen_stack/graph/query.py +148 -0
  170. pen_stack-8.0.5/pen_stack/graph/schema.py +100 -0
  171. pen_stack-8.0.5/pen_stack/loop/continual.py +61 -0
  172. pen_stack-8.0.5/pen_stack/loop/cycle.py +84 -0
  173. pen_stack-8.0.5/pen_stack/loop/drift.py +41 -0
  174. pen_stack-8.0.5/pen_stack/mech/__init__.py +1 -0
  175. pen_stack-8.0.5/pen_stack/mech/classify_atlas.py +71 -0
  176. pen_stack-8.0.5/pen_stack/mech/pfam_whitelist.yaml +247 -0
  177. pen_stack-8.0.5/pen_stack/mech/whitelist.py +66 -0
  178. pen_stack-8.0.5/pen_stack/monitor/__init__.py +1 -0
  179. pen_stack-8.0.5/pen_stack/monitor/europepmc.py +32 -0
  180. pen_stack-8.0.5/pen_stack/monitor/run.py +57 -0
  181. pen_stack-8.0.5/pen_stack/monitor/triage.py +63 -0
  182. pen_stack-8.0.5/pen_stack/oracles/__init__.py +65 -0
  183. pen_stack-8.0.5/pen_stack/oracles/affinity.py +116 -0
  184. pen_stack-8.0.5/pen_stack/oracles/cache.py +53 -0
  185. pen_stack-8.0.5/pen_stack/oracles/energetics.py +33 -0
  186. pen_stack-8.0.5/pen_stack/oracles/genome.py +167 -0
  187. pen_stack-8.0.5/pen_stack/oracles/protein_design.py +136 -0
  188. pen_stack-8.0.5/pen_stack/oracles/reliability.py +64 -0
  189. pen_stack-8.0.5/pen_stack/oracles/rna.py +28 -0
  190. pen_stack-8.0.5/pen_stack/oracles/schema.py +77 -0
  191. pen_stack-8.0.5/pen_stack/oracles/structure.py +42 -0
  192. pen_stack-8.0.5/pen_stack/oracles/structure_run.py +76 -0
  193. pen_stack-8.0.5/pen_stack/oracles/vcell.py +74 -0
  194. pen_stack-8.0.5/pen_stack/planner/__init__.py +1 -0
  195. pen_stack-8.0.5/pen_stack/planner/ada_risk.py +64 -0
  196. pen_stack-8.0.5/pen_stack/planner/antipeg_oracle.py +75 -0
  197. pen_stack-8.0.5/pen_stack/planner/capsid_epitope_oracle.py +135 -0
  198. pen_stack-8.0.5/pen_stack/planner/cargo.py +56 -0
  199. pen_stack-8.0.5/pen_stack/planner/cargo_polish.py +146 -0
  200. pen_stack-8.0.5/pen_stack/planner/chromosome.py +106 -0
  201. pen_stack-8.0.5/pen_stack/planner/delivery.py +55 -0
  202. pen_stack-8.0.5/pen_stack/planner/delivery_constraints.py +110 -0
  203. pen_stack-8.0.5/pen_stack/planner/delivery_immune.py +61 -0
  204. pen_stack-8.0.5/pen_stack/planner/delivery_immunology.py +208 -0
  205. pen_stack-8.0.5/pen_stack/planner/delivery_predict.py +196 -0
  206. pen_stack-8.0.5/pen_stack/planner/delivery_vehicles.py +37 -0
  207. pen_stack-8.0.5/pen_stack/planner/genotoxicity_oracle.py +112 -0
  208. pen_stack-8.0.5/pen_stack/planner/immune_mhc2.py +154 -0
  209. pen_stack-8.0.5/pen_stack/planner/immune_profile.py +292 -0
  210. pen_stack-8.0.5/pen_stack/planner/innate_sensing.py +135 -0
  211. pen_stack-8.0.5/pen_stack/planner/multiplex.py +110 -0
  212. pen_stack-8.0.5/pen_stack/planner/optimize.py +278 -0
  213. pen_stack-8.0.5/pen_stack/planner/pipeline.py +87 -0
  214. pen_stack-8.0.5/pen_stack/planner/report.py +26 -0
  215. pen_stack-8.0.5/pen_stack/planner/router.py +57 -0
  216. pen_stack-8.0.5/pen_stack/planner/seroprevalence_oracle.py +92 -0
  217. pen_stack-8.0.5/pen_stack/planner/target_site.py +118 -0
  218. pen_stack-8.0.5/pen_stack/rag/__init__.py +1 -0
  219. pen_stack-8.0.5/pen_stack/rag/corpus.py +133 -0
  220. pen_stack-8.0.5/pen_stack/rag/embed.py +98 -0
  221. pen_stack-8.0.5/pen_stack/rag/ground.py +131 -0
  222. pen_stack-8.0.5/pen_stack/rag/index.py +53 -0
  223. pen_stack-8.0.5/pen_stack/rag/llm.py +215 -0
  224. pen_stack-8.0.5/pen_stack/rag/qa.py +105 -0
  225. pen_stack-8.0.5/pen_stack/rag/retrieve.py +48 -0
  226. pen_stack-8.0.5/pen_stack/rules/__init__.py +9 -0
  227. pen_stack-8.0.5/pen_stack/rules/evaluators.py +318 -0
  228. pen_stack-8.0.5/pen_stack/rules/loader.py +31 -0
  229. pen_stack-8.0.5/pen_stack/rules/schema.py +99 -0
  230. pen_stack-8.0.5/pen_stack/rules/solver.py +43 -0
  231. pen_stack-8.0.5/pen_stack/rules/spec.py +78 -0
  232. pen_stack-8.0.5/pen_stack/safety/__init__.py +21 -0
  233. pen_stack-8.0.5/pen_stack/safety/audit.py +90 -0
  234. pen_stack-8.0.5/pen_stack/safety/gate.py +58 -0
  235. pen_stack-8.0.5/pen_stack/safety/pfam_scan.py +157 -0
  236. pen_stack-8.0.5/pen_stack/safety/policy.py +69 -0
  237. pen_stack-8.0.5/pen_stack/safety/redteam.py +71 -0
  238. pen_stack-8.0.5/pen_stack/safety/registry.py +255 -0
  239. pen_stack-8.0.5/pen_stack/safety/screen.py +59 -0
  240. pen_stack-8.0.5/pen_stack/safety/standards.py +141 -0
  241. pen_stack-8.0.5/pen_stack/score/__init__.py +1 -0
  242. pen_stack-8.0.5/pen_stack/score/recalibrate.py +77 -0
  243. pen_stack-8.0.5/pen_stack/score/therapeutic.py +85 -0
  244. pen_stack-8.0.5/pen_stack/server/__init__.py +1 -0
  245. pen_stack-8.0.5/pen_stack/server/api.py +647 -0
  246. pen_stack-8.0.5/pen_stack/spec/__init__.py +18 -0
  247. pen_stack-8.0.5/pen_stack/spec/clarify.py +42 -0
  248. pen_stack-8.0.5/pen_stack/spec/extract.py +254 -0
  249. pen_stack-8.0.5/pen_stack/spec/resolvers/__init__.py +17 -0
  250. pen_stack-8.0.5/pen_stack/spec/resolvers/cell.py +51 -0
  251. pen_stack-8.0.5/pen_stack/spec/resolvers/chem.py +32 -0
  252. pen_stack-8.0.5/pen_stack/spec/resolvers/feature.py +36 -0
  253. pen_stack-8.0.5/pen_stack/spec/resolvers/gene.py +43 -0
  254. pen_stack-8.0.5/pen_stack/spec/resolvers/locus.py +29 -0
  255. pen_stack-8.0.5/pen_stack/spec/resolvers/phenotype.py +37 -0
  256. pen_stack-8.0.5/pen_stack/spec/satisfy.py +114 -0
  257. pen_stack-8.0.5/pen_stack/spec/service.py +33 -0
  258. pen_stack-8.0.5/pen_stack/spec/writespec.py +244 -0
  259. pen_stack-8.0.5/pen_stack/twin/__init__.py +14 -0
  260. pen_stack-8.0.5/pen_stack/twin/calibrate.py +61 -0
  261. pen_stack-8.0.5/pen_stack/twin/data/__init__.py +12 -0
  262. pen_stack-8.0.5/pen_stack/twin/data/position_effect.py +245 -0
  263. pen_stack-8.0.5/pen_stack/twin/mechanistic.py +136 -0
  264. pen_stack-8.0.5/pen_stack/twin/outcome.py +132 -0
  265. pen_stack-8.0.5/pen_stack/twin/position_effect.py +454 -0
  266. pen_stack-8.0.5/pen_stack/ui/__init__.py +1 -0
  267. pen_stack-8.0.5/pen_stack/ui/app.py +713 -0
  268. pen_stack-8.0.5/pen_stack/validate/__init__.py +1 -0
  269. pen_stack-8.0.5/pen_stack/validate/adapt_demo.py +69 -0
  270. pen_stack-8.0.5/pen_stack/validate/agent_eval.py +117 -0
  271. pen_stack-8.0.5/pen_stack/validate/bench_adversarial_tasks.py +118 -0
  272. pen_stack-8.0.5/pen_stack/validate/bench_coscientist_tasks.py +60 -0
  273. pen_stack-8.0.5/pen_stack/validate/bench_graph_tasks.py +64 -0
  274. pen_stack-8.0.5/pen_stack/validate/bench_rule_tasks.py +84 -0
  275. pen_stack-8.0.5/pen_stack/validate/bench_trust_tasks.py +92 -0
  276. pen_stack-8.0.5/pen_stack/validate/bench_writetype_tasks.py +101 -0
  277. pen_stack-8.0.5/pen_stack/validate/blind_gsh_discovery.py +261 -0
  278. pen_stack-8.0.5/pen_stack/validate/cargo_directionality.py +57 -0
  279. pen_stack-8.0.5/pen_stack/validate/closed_loop.py +63 -0
  280. pen_stack-8.0.5/pen_stack/validate/durability_baselines.py +185 -0
  281. pen_stack-8.0.5/pen_stack/validate/experiment_design.py +65 -0
  282. pen_stack-8.0.5/pen_stack/validate/expr_controls.py +39 -0
  283. pen_stack-8.0.5/pen_stack/validate/forward_hypotheses.py +104 -0
  284. pen_stack-8.0.5/pen_stack/validate/generative_design.py +62 -0
  285. pen_stack-8.0.5/pen_stack/validate/guide_qc_demo.py +69 -0
  286. pen_stack-8.0.5/pen_stack/validate/heldout_celltype_expr.py +32 -0
  287. pen_stack-8.0.5/pen_stack/validate/immune_calibration.py +133 -0
  288. pen_stack-8.0.5/pen_stack/validate/intent_specification.py +82 -0
  289. pen_stack-8.0.5/pen_stack/validate/known_biology_expr.py +38 -0
  290. pen_stack-8.0.5/pen_stack/validate/offtarget_energetics_eval.py +144 -0
  291. pen_stack-8.0.5/pen_stack/validate/out_of_scope_refusal.py +82 -0
  292. pen_stack-8.0.5/pen_stack/validate/outcome_calibration.py +194 -0
  293. pen_stack-8.0.5/pen_stack/validate/outcome_prediction.py +76 -0
  294. pen_stack-8.0.5/pen_stack/validate/paper3_benchmark.py +165 -0
  295. pen_stack-8.0.5/pen_stack/validate/paper4_real_validation.py +144 -0
  296. pen_stack-8.0.5/pen_stack/validate/paper4_validation.py +82 -0
  297. pen_stack-8.0.5/pen_stack/validate/protocol_safety.py +62 -0
  298. pen_stack-8.0.5/pen_stack/validate/safety_screening.py +72 -0
  299. pen_stack-8.0.5/pen_stack/validate/selective_prediction.py +104 -0
  300. pen_stack-8.0.5/pen_stack/validate/seq_vs_measured.py +134 -0
  301. pen_stack-8.0.5/pen_stack/validate/target_site_controls.py +65 -0
  302. pen_stack-8.0.5/pen_stack/validate/uncertainty_eval.py +244 -0
  303. pen_stack-8.0.5/pen_stack/validate/ungrounded_baseline.py +234 -0
  304. pen_stack-8.0.5/pen_stack/validate/within_locus_ranking.py +84 -0
  305. pen_stack-8.0.5/pen_stack/validate/writer_recovery.py +91 -0
  306. pen_stack-8.0.5/pen_stack/verify/__init__.py +5 -0
  307. pen_stack-8.0.5/pen_stack/verify/proof.py +206 -0
  308. pen_stack-8.0.5/pen_stack/verify/schema.py +53 -0
  309. pen_stack-8.0.5/pen_stack/verify/service.py +191 -0
  310. pen_stack-8.0.5/pen_stack/web/llm.py +393 -0
  311. pen_stack-8.0.5/pen_stack/web/llm_provider.py +119 -0
  312. pen_stack-8.0.5/pen_stack/web/server.py +96 -0
  313. pen_stack-8.0.5/pen_stack/web/tools.py +197 -0
  314. pen_stack-8.0.5/pen_stack/wgenome/__init__.py +1 -0
  315. pen_stack-8.0.5/pen_stack/wgenome/chromatin_seq.py +83 -0
  316. pen_stack-8.0.5/pen_stack/wgenome/durability.py +108 -0
  317. pen_stack-8.0.5/pen_stack/wgenome/export_tracks.py +52 -0
  318. pen_stack-8.0.5/pen_stack/wgenome/features.py +82 -0
  319. pen_stack-8.0.5/pen_stack/wgenome/genotoxic_blocklist.py +88 -0
  320. pen_stack-8.0.5/pen_stack/wgenome/gsh_baseline.py +154 -0
  321. pen_stack-8.0.5/pen_stack/wgenome/mesh_features.py +61 -0
  322. pen_stack-8.0.5/pen_stack/wgenome/offtarget_assay.py +80 -0
  323. pen_stack-8.0.5/pen_stack/wgenome/offtarget_bridge.py +47 -0
  324. pen_stack-8.0.5/pen_stack/wgenome/offtarget_cast.py +97 -0
  325. pen_stack-8.0.5/pen_stack/wgenome/offtarget_data.py +148 -0
  326. pen_stack-8.0.5/pen_stack/wgenome/offtarget_enumerate.py +271 -0
  327. pen_stack-8.0.5/pen_stack/wgenome/offtarget_integrase.py +155 -0
  328. pen_stack-8.0.5/pen_stack/wgenome/offtarget_nuclease.py +98 -0
  329. pen_stack-8.0.5/pen_stack/wgenome/offtarget_paste.py +41 -0
  330. pen_stack-8.0.5/pen_stack/wgenome/offtarget_predict.py +264 -0
  331. pen_stack-8.0.5/pen_stack/wgenome/ood.py +135 -0
  332. pen_stack-8.0.5/pen_stack/wgenome/providers.py +278 -0
  333. pen_stack-8.0.5/pen_stack/wgenome/safety.py +69 -0
  334. pen_stack-8.0.5/pen_stack/wgenome/structure3d.py +212 -0
  335. pen_stack-8.0.5/pen_stack/wgenome/uncertainty.py +250 -0
  336. pen_stack-8.0.5/pen_stack/wgenome/writability.py +72 -0
  337. pen_stack-8.0.5/pen_stack.egg-info/PKG-INFO +382 -0
  338. pen_stack-8.0.5/pen_stack.egg-info/SOURCES.txt +605 -0
  339. pen_stack-8.0.5/prereg/SHA256_LOCK_phase0.json +9 -0
  340. pen_stack-8.0.5/prereg/SHA256_LOCK_phase1_5.json +11 -0
  341. pen_stack-8.0.5/prereg/SHA256_LOCK_phase2.json +12 -0
  342. pen_stack-8.0.5/prereg/SHA256_LOCK_phase3.json +11 -0
  343. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_a.json +11 -0
  344. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_acq.json +8 -0
  345. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_aldesign.json +8 -0
  346. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_alvalidate.json +8 -0
  347. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_atlas.json +8 -0
  348. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_b.json +11 -0
  349. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_ba.json +9 -0
  350. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_ba_v33.json +9 -0
  351. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_ba_v45.json +8 -0
  352. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_bench.json +8 -0
  353. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_c.json +9 -0
  354. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_cal.json +8 -0
  355. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_calib.json +8 -0
  356. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_challenge.json +8 -0
  357. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_chat.json +8 -0
  358. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_cite.json +8 -0
  359. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_closedloop.json +8 -0
  360. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_continual.json +8 -0
  361. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_cosci2.json +8 -0
  362. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_crit.json +8 -0
  363. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_ct.json +8 -0
  364. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_d.json +10 -0
  365. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_delivery.json +8 -0
  366. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_drift.json +8 -0
  367. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_e.json +9 -0
  368. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_env.json +8 -0
  369. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_ep.json +9 -0
  370. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_epitope.json +8 -0
  371. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_expr2.json +8 -0
  372. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_f.json +8 -0
  373. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_frontend.json +8 -0
  374. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_g.json +8 -0
  375. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_gen.json +8 -0
  376. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_genotox.json +8 -0
  377. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_graph.json +8 -0
  378. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_h.json +8 -0
  379. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_hybrid.json +8 -0
  380. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_immune.json +8 -0
  381. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_immune2.json +8 -0
  382. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_ingest.json +8 -0
  383. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_innate.json +8 -0
  384. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_loop.json +8 -0
  385. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_manifest.json +8 -0
  386. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_mc.json +10 -0
  387. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_mcp.json +8 -0
  388. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_mech.json +8 -0
  389. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_mon.json +8 -0
  390. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_o.json +8 -0
  391. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_offtarget.json +8 -0
  392. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_offtarget2.json +9 -0
  393. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_openapi.json +8 -0
  394. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_oracle.json +8 -0
  395. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_orch.json +8 -0
  396. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_outcome.json +8 -0
  397. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_pareto.json +8 -0
  398. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_peg.json +8 -0
  399. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_penchat.json +10 -0
  400. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_plan.json +8 -0
  401. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_policy.json +9 -0
  402. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_priorart.json +10 -0
  403. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_profile.json +8 -0
  404. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_proto.json +8 -0
  405. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_r.json +14 -0
  406. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_redteam.json +9 -0
  407. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_route.json +9 -0
  408. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_screen.json +10 -0
  409. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_seroprev.json +8 -0
  410. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_simlab.json +8 -0
  411. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_twincal.json +8 -0
  412. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_uq.json +9 -0
  413. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_v.json +8 -0
  414. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_vcell.json +8 -0
  415. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_verify.json +8 -0
  416. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_writer.json +8 -0
  417. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_writespec.json +8 -0
  418. pen_stack-8.0.5/prereg/SHA256_LOCK_ws_wv.json +8 -0
  419. pen_stack-8.0.5/prereg/paper1.yaml +60 -0
  420. pen_stack-8.0.5/prereg/paper2.yaml +74 -0
  421. pen_stack-8.0.5/prereg/paper3.yaml +64 -0
  422. pen_stack-8.0.5/prereg/paper4.yaml +71 -0
  423. pen_stack-8.0.5/prereg/phase0.yaml +28 -0
  424. pen_stack-8.0.5/prereg/ws_a.yaml +57 -0
  425. pen_stack-8.0.5/prereg/ws_atlas.yaml +18 -0
  426. pen_stack-8.0.5/prereg/ws_b.yaml +50 -0
  427. pen_stack-8.0.5/prereg/ws_ba.yaml +45 -0
  428. pen_stack-8.0.5/prereg/ws_ba_v33.yaml +12 -0
  429. pen_stack-8.0.5/prereg/ws_bench.yaml +25 -0
  430. pen_stack-8.0.5/prereg/ws_chat.yaml +20 -0
  431. pen_stack-8.0.5/prereg/ws_crit.yaml +16 -0
  432. pen_stack-8.0.5/prereg/ws_d.yaml +11 -0
  433. pen_stack-8.0.5/prereg/ws_ep.yaml +40 -0
  434. pen_stack-8.0.5/prereg/ws_expr2.yaml +39 -0
  435. pen_stack-8.0.5/prereg/ws_f.yaml +38 -0
  436. pen_stack-8.0.5/prereg/ws_frontend.yaml +21 -0
  437. pen_stack-8.0.5/prereg/ws_g.yaml +37 -0
  438. pen_stack-8.0.5/prereg/ws_h.yaml +32 -0
  439. pen_stack-8.0.5/prereg/ws_mc.yaml +51 -0
  440. pen_stack-8.0.5/prereg/ws_mon.yaml +21 -0
  441. pen_stack-8.0.5/prereg/ws_offtarget2.yaml +106 -0
  442. pen_stack-8.0.5/prereg/ws_priorart.yaml +169 -0
  443. pen_stack-8.0.5/prereg/ws_route.yaml +9 -0
  444. pen_stack-8.0.5/prereg/ws_seroprev.yaml +40 -0
  445. pen_stack-8.0.5/prereg/ws_uq.yaml +62 -0
  446. pen_stack-8.0.5/prereg/ws_wv.yaml +20 -0
  447. pen_stack-8.0.5/pyproject.toml +121 -0
  448. pen_stack-8.0.5/scripts/build_capsid_fitness.py +98 -0
  449. pen_stack-8.0.5/scripts/build_rag_corpus.py +39 -0
  450. pen_stack-8.0.5/scripts/fetch_licensed_sources.py +57 -0
  451. pen_stack-8.0.5/scripts/offtarget_chromatin_matched.py +135 -0
  452. pen_stack-8.0.5/scripts/offtarget_chromatin_validation.py +115 -0
  453. pen_stack-8.0.5/scripts/p1_build_atlas.py +87 -0
  454. pen_stack-8.0.5/scripts/p1_build_durability.py +61 -0
  455. pen_stack-8.0.5/scripts/p1_build_position_effect.py +103 -0
  456. pen_stack-8.0.5/scripts/p1_build_writer_eff.py +66 -0
  457. pen_stack-8.0.5/scripts/p1_export_tracks.py +22 -0
  458. pen_stack-8.0.5/scripts/p1_safety_concordance.py +82 -0
  459. pen_stack-8.0.5/scripts/p1_train_safety.py +48 -0
  460. pen_stack-8.0.5/scripts/p1_validation_report.py +80 -0
  461. pen_stack-8.0.5/scripts/p2_build_atlas.py +36 -0
  462. pen_stack-8.0.5/scripts/p3_benchmark_report.py +82 -0
  463. pen_stack-8.0.5/scripts/p4_genome_scan.py +43 -0
  464. pen_stack-8.0.5/scripts/p52_build_genotox_oracle.py +115 -0
  465. pen_stack-8.0.5/scripts/p53_build_epitope_oracle.py +120 -0
  466. pen_stack-8.0.5/scripts/reproduce.py +115 -0
  467. pen_stack-8.0.5/scripts/validate_components.py +158 -0
  468. pen_stack-8.0.5/scripts/ws_b_report.py +104 -0
  469. pen_stack-8.0.5/scripts/ws_c_report.py +75 -0
  470. pen_stack-8.0.5/setup.cfg +4 -0
  471. pen_stack-8.0.3/CHANGELOG.md +0 -2529
  472. pen_stack-8.0.3/CITATION.cff +0 -24
  473. pen_stack-8.0.3/PKG-INFO +0 -382
  474. pen_stack-8.0.3/README.md +0 -296
  475. pen_stack-8.0.3/bench/run.py +0 -173
  476. pen_stack-8.0.3/benchmarks/chat_grounding/README.md +0 -26
  477. pen_stack-8.0.3/benchmarks/chat_grounding/SHA256SUMS +0 -1
  478. pen_stack-8.0.3/benchmarks/chat_headtohead/README.md +0 -29
  479. pen_stack-8.0.3/benchmarks/chat_routing/README.md +0 -35
  480. pen_stack-8.0.3/benchmarks/chat_routing/SHA256SUMS +0 -1
  481. pen_stack-8.0.3/benchmarks/chat_safety/README.md +0 -23
  482. pen_stack-8.0.3/benchmarks/chat_safety/SHA256SUMS +0 -1
  483. pen_stack-8.0.3/benchmarks/genome_writing_bench/LEADERBOARD.md +0 -67
  484. pen_stack-8.0.3/benchmarks/genome_writing_bench/README.md +0 -87
  485. pen_stack-8.0.3/benchmarks/genome_writing_bench/SUBMISSIONS.md +0 -53
  486. pen_stack-8.0.3/benchmarks/genome_writing_challenge/SUBMISSIONS.md +0 -16
  487. pen_stack-8.0.3/benchmarks/genotox_panel/README.md +0 -130
  488. pen_stack-8.0.3/benchmarks/grounding_llm_on/README.md +0 -58
  489. pen_stack-8.0.3/benchmarks/loop/SHA256SUMS +0 -2
  490. pen_stack-8.0.3/benchmarks/offtarget/integrase/README.md +0 -23
  491. pen_stack-8.0.3/benchmarks/offtarget/integrase/SHA256SUMS +0 -4
  492. pen_stack-8.0.3/benchmarks/offtarget/integrase_chalberg/README.md +0 -61
  493. pen_stack-8.0.3/benchmarks/oracle/SHA256SUMS +0 -5
  494. pen_stack-8.0.3/benchmarks/position_effect/README.md +0 -68
  495. pen_stack-8.0.3/benchmarks/position_effect/SHA256SUMS +0 -1
  496. pen_stack-8.0.3/benchmarks/position_effect_human/README.md +0 -119
  497. pen_stack-8.0.3/benchmarks/priorart/epridict/README.md +0 -62
  498. pen_stack-8.0.3/benchmarks/priorart/epridict/SHA256SUMS +0 -5
  499. pen_stack-8.0.3/benchmarks/priorart/gsh_recovery/README.md +0 -66
  500. pen_stack-8.0.3/benchmarks/priorart/gsh_recovery/SHA256SUMS +0 -4
  501. pen_stack-8.0.3/benchmarks/writer_efficiency/README.md +0 -54
  502. pen_stack-8.0.3/benchmarks/writer_efficiency/SHA256SUMS +0 -2
  503. pen_stack-8.0.3/benchmarks/writespec/SHA256SUMS +0 -4
  504. pen_stack-8.0.3/configs/aav_serotype_tropism.yaml +0 -81
  505. pen_stack-8.0.3/configs/antipeg.yaml +0 -28
  506. pen_stack-8.0.3/configs/cargo_polish.yaml +0 -45
  507. pen_stack-8.0.3/configs/cell_types.yaml +0 -56
  508. pen_stack-8.0.3/configs/datasets.yaml +0 -99
  509. pen_stack-8.0.3/configs/expression/modifiers.yaml +0 -59
  510. pen_stack-8.0.3/configs/expression/promoters.yaml +0 -52
  511. pen_stack-8.0.3/configs/intent_weights.yaml +0 -57
  512. pen_stack-8.0.3/configs/llm.yaml +0 -72
  513. pen_stack-8.0.3/configs/monitor_queries.yaml +0 -33
  514. pen_stack-8.0.3/configs/oracles/execution.yaml +0 -95
  515. pen_stack-8.0.3/configs/oracles/scope_cards.yaml +0 -250
  516. pen_stack-8.0.3/configs/rules/delivery.yaml +0 -49
  517. pen_stack-8.0.3/configs/seroprevalence.yaml +0 -64
  518. pen_stack-8.0.3/configs/writer_sequences.fasta +0 -12
  519. pen_stack-8.0.3/data/curated/bridge_offtarget_energetics.json +0 -202
  520. pen_stack-8.0.3/data/curated/cast_systems.yaml +0 -59
  521. pen_stack-8.0.3/data/curated/integrase_att.yaml +0 -66
  522. pen_stack-8.0.3/docs/DEPLOY.md +0 -39
  523. pen_stack-8.0.3/docs/INFRA.md +0 -64
  524. pen_stack-8.0.3/docs/MCP.md +0 -24
  525. pen_stack-8.0.3/docs/RELEASING.md +0 -60
  526. pen_stack-8.0.3/docs/REPRO.md +0 -46
  527. pen_stack-8.0.3/docs/agent.md +0 -78
  528. pen_stack-8.0.3/docs/benchmark_circularity.md +0 -64
  529. pen_stack-8.0.3/docs/biosecurity.md +0 -102
  530. pen_stack-8.0.3/docs/cards/atlas.md +0 -41
  531. pen_stack-8.0.3/docs/cards/durability.md +0 -43
  532. pen_stack-8.0.3/docs/cards/offtarget_data.md +0 -117
  533. pen_stack-8.0.3/docs/cards/position_effect_data.md +0 -36
  534. pen_stack-8.0.3/docs/cards/priorart.md +0 -66
  535. pen_stack-8.0.3/docs/cards/safety.md +0 -39
  536. pen_stack-8.0.3/docs/cards/writer_efficiency_data.md +0 -48
  537. pen_stack-8.0.3/docs/closed_loop.md +0 -79
  538. pen_stack-8.0.3/docs/delivery_recommender.md +0 -54
  539. pen_stack-8.0.3/docs/dissemination.md +0 -34
  540. pen_stack-8.0.3/docs/environment.md +0 -59
  541. pen_stack-8.0.3/docs/generative_design.md +0 -63
  542. pen_stack-8.0.3/docs/immune_profiler.md +0 -70
  543. pen_stack-8.0.3/docs/index.md +0 -48
  544. pen_stack-8.0.3/docs/offtarget.md +0 -59
  545. pen_stack-8.0.3/docs/oracles.md +0 -51
  546. pen_stack-8.0.3/docs/position_effect.md +0 -57
  547. pen_stack-8.0.3/docs/positioning.md +0 -55
  548. pen_stack-8.0.3/docs/private_data_formats.md +0 -61
  549. pen_stack-8.0.3/docs/quickstart.md +0 -64
  550. pen_stack-8.0.3/docs/responsible_use.md +0 -96
  551. pen_stack-8.0.3/docs/scope.md +0 -50
  552. pen_stack-8.0.3/docs/scorecard.md +0 -54
  553. pen_stack-8.0.3/docs/tpe_bench.md +0 -48
  554. pen_stack-8.0.3/docs/tutorials/score-deliverability.md +0 -36
  555. pen_stack-8.0.3/docs/tutorials/where-can-i-write.md +0 -45
  556. pen_stack-8.0.3/docs/tutorials/which-writer-reaches-locus.md +0 -41
  557. pen_stack-8.0.3/docs/uncertainty.md +0 -84
  558. pen_stack-8.0.3/docs/world_model.md +0 -49
  559. pen_stack-8.0.3/docs/writer_efficiency.md +0 -59
  560. pen_stack-8.0.3/docs/writer_verification.md +0 -46
  561. pen_stack-8.0.3/docs/writespec_bench.md +0 -44
  562. pen_stack-8.0.3/docs/writespec_profile.md +0 -58
  563. pen_stack-8.0.3/docs/wtkb.md +0 -25
  564. pen_stack-8.0.3/pen_stack/__init__.py +0 -2
  565. pen_stack-8.0.3/pen_stack/active/acquire.py +0 -165
  566. pen_stack-8.0.3/pen_stack/active/brains.py +0 -74
  567. pen_stack-8.0.3/pen_stack/active/campaign.py +0 -109
  568. pen_stack-8.0.3/pen_stack/active/design.py +0 -66
  569. pen_stack-8.0.3/pen_stack/active/validate.py +0 -104
  570. pen_stack-8.0.3/pen_stack/adapt/__init__.py +0 -14
  571. pen_stack-8.0.3/pen_stack/adapt/finetune.py +0 -33
  572. pen_stack-8.0.3/pen_stack/adapt/ingest.py +0 -86
  573. pen_stack-8.0.3/pen_stack/adapt/pipeline.py +0 -101
  574. pen_stack-8.0.3/pen_stack/adapt/recalibrate.py +0 -58
  575. pen_stack-8.0.3/pen_stack/adapt/report.py +0 -130
  576. pen_stack-8.0.3/pen_stack/agent/__init__.py +0 -1
  577. pen_stack-8.0.3/pen_stack/agent/cite.py +0 -175
  578. pen_stack-8.0.3/pen_stack/agent/co_scientist.py +0 -268
  579. pen_stack-8.0.3/pen_stack/agent/epistemic.py +0 -102
  580. pen_stack-8.0.3/pen_stack/agent/guardrails.py +0 -67
  581. pen_stack-8.0.3/pen_stack/agent/mcp_server.py +0 -215
  582. pen_stack-8.0.3/pen_stack/agent/orchestrator.py +0 -112
  583. pen_stack-8.0.3/pen_stack/agent/orchestrator_live.py +0 -56
  584. pen_stack-8.0.3/pen_stack/agent/pen_agent.py +0 -242
  585. pen_stack-8.0.3/pen_stack/agent/scope.py +0 -60
  586. pen_stack-8.0.3/pen_stack/agent/tools.py +0 -130
  587. pen_stack-8.0.3/pen_stack/api/manifest.py +0 -161
  588. pen_stack-8.0.3/pen_stack/atlas/__init__.py +0 -1
  589. pen_stack-8.0.3/pen_stack/atlas/build_wtkb.py +0 -80
  590. pen_stack-8.0.3/pen_stack/atlas/crosslink.py +0 -179
  591. pen_stack-8.0.3/pen_stack/atlas/expand.py +0 -190
  592. pen_stack-8.0.3/pen_stack/atlas/guide_design.py +0 -178
  593. pen_stack-8.0.3/pen_stack/atlas/schema.py +0 -59
  594. pen_stack-8.0.3/pen_stack/atlas/scorecard.py +0 -134
  595. pen_stack-8.0.3/pen_stack/atlas/universe.py +0 -75
  596. pen_stack-8.0.3/pen_stack/atlas/variant_propose.py +0 -155
  597. pen_stack-8.0.3/pen_stack/atlas/writer_efficiency.py +0 -184
  598. pen_stack-8.0.3/pen_stack/atlas/writer_predict.py +0 -225
  599. pen_stack-8.0.3/pen_stack/atlas/writer_recommend.py +0 -165
  600. pen_stack-8.0.3/pen_stack/atlas/writer_verify.py +0 -167
  601. pen_stack-8.0.3/pen_stack/bridge/__init__.py +0 -1
  602. pen_stack-8.0.3/pen_stack/bridge/activity.py +0 -52
  603. pen_stack-8.0.3/pen_stack/bridge/cli.py +0 -65
  604. pen_stack-8.0.3/pen_stack/bridge/fold_qc.py +0 -53
  605. pen_stack-8.0.3/pen_stack/bridge/guide_qc.py +0 -87
  606. pen_stack-8.0.3/pen_stack/bridge/ingest.py +0 -139
  607. pen_stack-8.0.3/pen_stack/bridge/offtarget.py +0 -191
  608. pen_stack-8.0.3/pen_stack/bridge/offtarget_energetics.py +0 -105
  609. pen_stack-8.0.3/pen_stack/bridge/ortholog_screen.py +0 -73
  610. pen_stack-8.0.3/pen_stack/bridge/pipeline.py +0 -83
  611. pen_stack-8.0.3/pen_stack/build/cloudlab.py +0 -74
  612. pen_stack-8.0.3/pen_stack/build/ingest.py +0 -47
  613. pen_stack-8.0.3/pen_stack/build/protocol.py +0 -82
  614. pen_stack-8.0.3/pen_stack/build/simlab.py +0 -30
  615. pen_stack-8.0.3/pen_stack/cli.py +0 -126
  616. pen_stack-8.0.3/pen_stack/data/__init__.py +0 -1
  617. pen_stack-8.0.3/pen_stack/data/encode.py +0 -84
  618. pen_stack-8.0.3/pen_stack/data/genome.py +0 -71
  619. pen_stack-8.0.3/pen_stack/data/ingest_chromatin.py +0 -119
  620. pen_stack-8.0.3/pen_stack/data/ingest_integration.py +0 -112
  621. pen_stack-8.0.3/pen_stack/data/ingest_safety_annot.py +0 -201
  622. pen_stack-8.0.3/pen_stack/data/ingest_trip.py +0 -76
  623. pen_stack-8.0.3/pen_stack/design/capsid_generate.py +0 -62
  624. pen_stack-8.0.3/pen_stack/design/generate.py +0 -70
  625. pen_stack-8.0.3/pen_stack/design/pareto.py +0 -70
  626. pen_stack-8.0.3/pen_stack/design/space.py +0 -137
  627. pen_stack-8.0.3/pen_stack/design/writer_variants.py +0 -122
  628. pen_stack-8.0.3/pen_stack/env/__init__.py +0 -1
  629. pen_stack-8.0.3/pen_stack/env/genome_writing_env.py +0 -248
  630. pen_stack-8.0.3/pen_stack/env/policies.py +0 -94
  631. pen_stack-8.0.3/pen_stack/graph/__init__.py +0 -21
  632. pen_stack-8.0.3/pen_stack/graph/build.py +0 -133
  633. pen_stack-8.0.3/pen_stack/graph/cell_types.py +0 -58
  634. pen_stack-8.0.3/pen_stack/graph/ingest.py +0 -132
  635. pen_stack-8.0.3/pen_stack/graph/query.py +0 -148
  636. pen_stack-8.0.3/pen_stack/graph/schema.py +0 -100
  637. pen_stack-8.0.3/pen_stack/loop/continual.py +0 -61
  638. pen_stack-8.0.3/pen_stack/loop/cycle.py +0 -84
  639. pen_stack-8.0.3/pen_stack/loop/drift.py +0 -41
  640. pen_stack-8.0.3/pen_stack/mech/__init__.py +0 -1
  641. pen_stack-8.0.3/pen_stack/mech/classify_atlas.py +0 -71
  642. pen_stack-8.0.3/pen_stack/mech/whitelist.py +0 -66
  643. pen_stack-8.0.3/pen_stack/monitor/__init__.py +0 -1
  644. pen_stack-8.0.3/pen_stack/monitor/europepmc.py +0 -32
  645. pen_stack-8.0.3/pen_stack/monitor/run.py +0 -57
  646. pen_stack-8.0.3/pen_stack/monitor/triage.py +0 -63
  647. pen_stack-8.0.3/pen_stack/oracles/__init__.py +0 -65
  648. pen_stack-8.0.3/pen_stack/oracles/affinity.py +0 -116
  649. pen_stack-8.0.3/pen_stack/oracles/cache.py +0 -53
  650. pen_stack-8.0.3/pen_stack/oracles/energetics.py +0 -33
  651. pen_stack-8.0.3/pen_stack/oracles/genome.py +0 -167
  652. pen_stack-8.0.3/pen_stack/oracles/protein_design.py +0 -136
  653. pen_stack-8.0.3/pen_stack/oracles/reliability.py +0 -64
  654. pen_stack-8.0.3/pen_stack/oracles/rna.py +0 -28
  655. pen_stack-8.0.3/pen_stack/oracles/schema.py +0 -77
  656. pen_stack-8.0.3/pen_stack/oracles/structure.py +0 -42
  657. pen_stack-8.0.3/pen_stack/oracles/structure_run.py +0 -76
  658. pen_stack-8.0.3/pen_stack/oracles/vcell.py +0 -74
  659. pen_stack-8.0.3/pen_stack/planner/__init__.py +0 -1
  660. pen_stack-8.0.3/pen_stack/planner/ada_risk.py +0 -64
  661. pen_stack-8.0.3/pen_stack/planner/antipeg_oracle.py +0 -75
  662. pen_stack-8.0.3/pen_stack/planner/capsid_epitope_oracle.py +0 -136
  663. pen_stack-8.0.3/pen_stack/planner/cargo.py +0 -56
  664. pen_stack-8.0.3/pen_stack/planner/cargo_polish.py +0 -146
  665. pen_stack-8.0.3/pen_stack/planner/chromosome.py +0 -106
  666. pen_stack-8.0.3/pen_stack/planner/delivery.py +0 -55
  667. pen_stack-8.0.3/pen_stack/planner/delivery_constraints.py +0 -110
  668. pen_stack-8.0.3/pen_stack/planner/delivery_immune.py +0 -61
  669. pen_stack-8.0.3/pen_stack/planner/delivery_immunology.py +0 -208
  670. pen_stack-8.0.3/pen_stack/planner/delivery_predict.py +0 -196
  671. pen_stack-8.0.3/pen_stack/planner/delivery_vehicles.py +0 -37
  672. pen_stack-8.0.3/pen_stack/planner/genotoxicity_oracle.py +0 -112
  673. pen_stack-8.0.3/pen_stack/planner/immune_mhc2.py +0 -154
  674. pen_stack-8.0.3/pen_stack/planner/immune_profile.py +0 -292
  675. pen_stack-8.0.3/pen_stack/planner/innate_sensing.py +0 -135
  676. pen_stack-8.0.3/pen_stack/planner/multiplex.py +0 -110
  677. pen_stack-8.0.3/pen_stack/planner/optimize.py +0 -278
  678. pen_stack-8.0.3/pen_stack/planner/pipeline.py +0 -87
  679. pen_stack-8.0.3/pen_stack/planner/report.py +0 -26
  680. pen_stack-8.0.3/pen_stack/planner/router.py +0 -57
  681. pen_stack-8.0.3/pen_stack/planner/seroprevalence_oracle.py +0 -92
  682. pen_stack-8.0.3/pen_stack/planner/target_site.py +0 -118
  683. pen_stack-8.0.3/pen_stack/rag/__init__.py +0 -1
  684. pen_stack-8.0.3/pen_stack/rag/corpus.py +0 -133
  685. pen_stack-8.0.3/pen_stack/rag/embed.py +0 -98
  686. pen_stack-8.0.3/pen_stack/rag/ground.py +0 -131
  687. pen_stack-8.0.3/pen_stack/rag/index.py +0 -53
  688. pen_stack-8.0.3/pen_stack/rag/llm.py +0 -215
  689. pen_stack-8.0.3/pen_stack/rag/qa.py +0 -105
  690. pen_stack-8.0.3/pen_stack/rag/retrieve.py +0 -48
  691. pen_stack-8.0.3/pen_stack/rules/__init__.py +0 -9
  692. pen_stack-8.0.3/pen_stack/rules/evaluators.py +0 -330
  693. pen_stack-8.0.3/pen_stack/rules/loader.py +0 -31
  694. pen_stack-8.0.3/pen_stack/rules/schema.py +0 -99
  695. pen_stack-8.0.3/pen_stack/rules/solver.py +0 -43
  696. pen_stack-8.0.3/pen_stack/rules/spec.py +0 -78
  697. pen_stack-8.0.3/pen_stack/safety/__init__.py +0 -21
  698. pen_stack-8.0.3/pen_stack/safety/audit.py +0 -90
  699. pen_stack-8.0.3/pen_stack/safety/gate.py +0 -58
  700. pen_stack-8.0.3/pen_stack/safety/pfam_scan.py +0 -157
  701. pen_stack-8.0.3/pen_stack/safety/policy.py +0 -69
  702. pen_stack-8.0.3/pen_stack/safety/redteam.py +0 -71
  703. pen_stack-8.0.3/pen_stack/safety/registry.py +0 -255
  704. pen_stack-8.0.3/pen_stack/safety/screen.py +0 -59
  705. pen_stack-8.0.3/pen_stack/safety/standards.py +0 -141
  706. pen_stack-8.0.3/pen_stack/score/__init__.py +0 -1
  707. pen_stack-8.0.3/pen_stack/score/recalibrate.py +0 -77
  708. pen_stack-8.0.3/pen_stack/score/therapeutic.py +0 -85
  709. pen_stack-8.0.3/pen_stack/server/__init__.py +0 -1
  710. pen_stack-8.0.3/pen_stack/server/api.py +0 -647
  711. pen_stack-8.0.3/pen_stack/spec/__init__.py +0 -18
  712. pen_stack-8.0.3/pen_stack/spec/clarify.py +0 -42
  713. pen_stack-8.0.3/pen_stack/spec/extract.py +0 -254
  714. pen_stack-8.0.3/pen_stack/spec/resolvers/__init__.py +0 -17
  715. pen_stack-8.0.3/pen_stack/spec/resolvers/cell.py +0 -51
  716. pen_stack-8.0.3/pen_stack/spec/resolvers/chem.py +0 -32
  717. pen_stack-8.0.3/pen_stack/spec/resolvers/feature.py +0 -36
  718. pen_stack-8.0.3/pen_stack/spec/resolvers/gene.py +0 -43
  719. pen_stack-8.0.3/pen_stack/spec/resolvers/locus.py +0 -29
  720. pen_stack-8.0.3/pen_stack/spec/resolvers/phenotype.py +0 -37
  721. pen_stack-8.0.3/pen_stack/spec/satisfy.py +0 -114
  722. pen_stack-8.0.3/pen_stack/spec/service.py +0 -33
  723. pen_stack-8.0.3/pen_stack/spec/writespec.py +0 -244
  724. pen_stack-8.0.3/pen_stack/twin/__init__.py +0 -14
  725. pen_stack-8.0.3/pen_stack/twin/calibrate.py +0 -61
  726. pen_stack-8.0.3/pen_stack/twin/data/__init__.py +0 -12
  727. pen_stack-8.0.3/pen_stack/twin/data/position_effect.py +0 -251
  728. pen_stack-8.0.3/pen_stack/twin/mechanistic.py +0 -136
  729. pen_stack-8.0.3/pen_stack/twin/outcome.py +0 -132
  730. pen_stack-8.0.3/pen_stack/twin/position_effect.py +0 -454
  731. pen_stack-8.0.3/pen_stack/ui/__init__.py +0 -1
  732. pen_stack-8.0.3/pen_stack/ui/app.py +0 -713
  733. pen_stack-8.0.3/pen_stack/validate/__init__.py +0 -1
  734. pen_stack-8.0.3/pen_stack/validate/adapt_demo.py +0 -69
  735. pen_stack-8.0.3/pen_stack/validate/agent_eval.py +0 -117
  736. pen_stack-8.0.3/pen_stack/validate/bench_adversarial_tasks.py +0 -118
  737. pen_stack-8.0.3/pen_stack/validate/bench_coscientist_tasks.py +0 -60
  738. pen_stack-8.0.3/pen_stack/validate/bench_graph_tasks.py +0 -64
  739. pen_stack-8.0.3/pen_stack/validate/bench_rule_tasks.py +0 -84
  740. pen_stack-8.0.3/pen_stack/validate/bench_trust_tasks.py +0 -92
  741. pen_stack-8.0.3/pen_stack/validate/bench_writetype_tasks.py +0 -101
  742. pen_stack-8.0.3/pen_stack/validate/blind_gsh_discovery.py +0 -261
  743. pen_stack-8.0.3/pen_stack/validate/cargo_directionality.py +0 -57
  744. pen_stack-8.0.3/pen_stack/validate/closed_loop.py +0 -63
  745. pen_stack-8.0.3/pen_stack/validate/durability_baselines.py +0 -185
  746. pen_stack-8.0.3/pen_stack/validate/experiment_design.py +0 -65
  747. pen_stack-8.0.3/pen_stack/validate/expr_controls.py +0 -39
  748. pen_stack-8.0.3/pen_stack/validate/forward_hypotheses.py +0 -104
  749. pen_stack-8.0.3/pen_stack/validate/generative_design.py +0 -62
  750. pen_stack-8.0.3/pen_stack/validate/guide_qc_demo.py +0 -69
  751. pen_stack-8.0.3/pen_stack/validate/heldout_celltype_expr.py +0 -32
  752. pen_stack-8.0.3/pen_stack/validate/immune_calibration.py +0 -133
  753. pen_stack-8.0.3/pen_stack/validate/intent_specification.py +0 -82
  754. pen_stack-8.0.3/pen_stack/validate/known_biology_expr.py +0 -38
  755. pen_stack-8.0.3/pen_stack/validate/offtarget_energetics_eval.py +0 -144
  756. pen_stack-8.0.3/pen_stack/validate/out_of_scope_refusal.py +0 -82
  757. pen_stack-8.0.3/pen_stack/validate/outcome_calibration.py +0 -194
  758. pen_stack-8.0.3/pen_stack/validate/outcome_prediction.py +0 -76
  759. pen_stack-8.0.3/pen_stack/validate/paper3_benchmark.py +0 -165
  760. pen_stack-8.0.3/pen_stack/validate/paper4_real_validation.py +0 -144
  761. pen_stack-8.0.3/pen_stack/validate/paper4_validation.py +0 -82
  762. pen_stack-8.0.3/pen_stack/validate/protocol_safety.py +0 -62
  763. pen_stack-8.0.3/pen_stack/validate/safety_screening.py +0 -72
  764. pen_stack-8.0.3/pen_stack/validate/selective_prediction.py +0 -104
  765. pen_stack-8.0.3/pen_stack/validate/seq_vs_measured.py +0 -134
  766. pen_stack-8.0.3/pen_stack/validate/target_site_controls.py +0 -65
  767. pen_stack-8.0.3/pen_stack/validate/uncertainty_eval.py +0 -244
  768. pen_stack-8.0.3/pen_stack/validate/ungrounded_baseline.py +0 -234
  769. pen_stack-8.0.3/pen_stack/validate/within_locus_ranking.py +0 -84
  770. pen_stack-8.0.3/pen_stack/validate/writer_recovery.py +0 -91
  771. pen_stack-8.0.3/pen_stack/verify/__init__.py +0 -5
  772. pen_stack-8.0.3/pen_stack/verify/proof.py +0 -206
  773. pen_stack-8.0.3/pen_stack/verify/schema.py +0 -53
  774. pen_stack-8.0.3/pen_stack/verify/service.py +0 -191
  775. pen_stack-8.0.3/pen_stack/web/llm.py +0 -393
  776. pen_stack-8.0.3/pen_stack/web/llm_provider.py +0 -119
  777. pen_stack-8.0.3/pen_stack/web/server.py +0 -96
  778. pen_stack-8.0.3/pen_stack/web/tools.py +0 -197
  779. pen_stack-8.0.3/pen_stack/wgenome/__init__.py +0 -1
  780. pen_stack-8.0.3/pen_stack/wgenome/chromatin_seq.py +0 -83
  781. pen_stack-8.0.3/pen_stack/wgenome/durability.py +0 -108
  782. pen_stack-8.0.3/pen_stack/wgenome/export_tracks.py +0 -52
  783. pen_stack-8.0.3/pen_stack/wgenome/features.py +0 -82
  784. pen_stack-8.0.3/pen_stack/wgenome/genotoxic_blocklist.py +0 -88
  785. pen_stack-8.0.3/pen_stack/wgenome/gsh_baseline.py +0 -154
  786. pen_stack-8.0.3/pen_stack/wgenome/mesh_features.py +0 -61
  787. pen_stack-8.0.3/pen_stack/wgenome/offtarget_assay.py +0 -80
  788. pen_stack-8.0.3/pen_stack/wgenome/offtarget_bridge.py +0 -47
  789. pen_stack-8.0.3/pen_stack/wgenome/offtarget_cast.py +0 -97
  790. pen_stack-8.0.3/pen_stack/wgenome/offtarget_data.py +0 -148
  791. pen_stack-8.0.3/pen_stack/wgenome/offtarget_enumerate.py +0 -271
  792. pen_stack-8.0.3/pen_stack/wgenome/offtarget_integrase.py +0 -155
  793. pen_stack-8.0.3/pen_stack/wgenome/offtarget_nuclease.py +0 -98
  794. pen_stack-8.0.3/pen_stack/wgenome/offtarget_paste.py +0 -41
  795. pen_stack-8.0.3/pen_stack/wgenome/offtarget_predict.py +0 -264
  796. pen_stack-8.0.3/pen_stack/wgenome/ood.py +0 -135
  797. pen_stack-8.0.3/pen_stack/wgenome/providers.py +0 -278
  798. pen_stack-8.0.3/pen_stack/wgenome/safety.py +0 -69
  799. pen_stack-8.0.3/pen_stack/wgenome/structure3d.py +0 -212
  800. pen_stack-8.0.3/pen_stack/wgenome/uncertainty.py +0 -260
  801. pen_stack-8.0.3/pen_stack/wgenome/writability.py +0 -72
  802. pen_stack-8.0.3/pen_stack.egg-info/PKG-INFO +0 -382
  803. pen_stack-8.0.3/pen_stack.egg-info/SOURCES.txt +0 -600
  804. pen_stack-8.0.3/prereg/SHA256_LOCK_phase0.json +0 -9
  805. pen_stack-8.0.3/prereg/SHA256_LOCK_phase1_5.json +0 -11
  806. pen_stack-8.0.3/prereg/SHA256_LOCK_phase2.json +0 -12
  807. pen_stack-8.0.3/prereg/SHA256_LOCK_phase3.json +0 -11
  808. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_a.json +0 -11
  809. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_acq.json +0 -8
  810. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_aldesign.json +0 -8
  811. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_alvalidate.json +0 -8
  812. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_atlas.json +0 -8
  813. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_b.json +0 -11
  814. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_ba.json +0 -9
  815. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_ba_v33.json +0 -9
  816. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_ba_v45.json +0 -8
  817. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_bench.json +0 -8
  818. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_c.json +0 -9
  819. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_cal.json +0 -8
  820. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_calib.json +0 -8
  821. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_challenge.json +0 -8
  822. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_chat.json +0 -8
  823. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_cite.json +0 -8
  824. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_closedloop.json +0 -8
  825. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_continual.json +0 -8
  826. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_cosci2.json +0 -8
  827. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_crit.json +0 -8
  828. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_ct.json +0 -8
  829. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_d.json +0 -10
  830. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_delivery.json +0 -8
  831. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_drift.json +0 -8
  832. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_e.json +0 -9
  833. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_env.json +0 -8
  834. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_ep.json +0 -9
  835. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_epitope.json +0 -8
  836. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_expr2.json +0 -8
  837. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_f.json +0 -8
  838. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_frontend.json +0 -8
  839. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_g.json +0 -8
  840. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_gen.json +0 -8
  841. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_genotox.json +0 -8
  842. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_graph.json +0 -8
  843. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_h.json +0 -8
  844. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_hybrid.json +0 -8
  845. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_immune.json +0 -8
  846. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_immune2.json +0 -8
  847. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_ingest.json +0 -8
  848. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_innate.json +0 -8
  849. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_loop.json +0 -8
  850. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_manifest.json +0 -8
  851. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_mc.json +0 -10
  852. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_mcp.json +0 -8
  853. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_mech.json +0 -8
  854. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_mon.json +0 -8
  855. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_o.json +0 -8
  856. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_offtarget.json +0 -8
  857. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_offtarget2.json +0 -9
  858. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_openapi.json +0 -8
  859. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_oracle.json +0 -8
  860. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_orch.json +0 -8
  861. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_outcome.json +0 -8
  862. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_pareto.json +0 -8
  863. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_peg.json +0 -8
  864. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_penchat.json +0 -10
  865. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_plan.json +0 -8
  866. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_policy.json +0 -9
  867. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_priorart.json +0 -10
  868. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_profile.json +0 -8
  869. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_proto.json +0 -8
  870. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_r.json +0 -14
  871. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_redteam.json +0 -9
  872. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_route.json +0 -9
  873. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_screen.json +0 -10
  874. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_seroprev.json +0 -8
  875. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_simlab.json +0 -8
  876. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_twincal.json +0 -8
  877. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_uq.json +0 -9
  878. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_v.json +0 -8
  879. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_vcell.json +0 -8
  880. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_verify.json +0 -8
  881. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_writer.json +0 -8
  882. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_writespec.json +0 -8
  883. pen_stack-8.0.3/prereg/SHA256_LOCK_ws_wv.json +0 -8
  884. pen_stack-8.0.3/prereg/paper1.yaml +0 -60
  885. pen_stack-8.0.3/prereg/paper2.yaml +0 -74
  886. pen_stack-8.0.3/prereg/paper3.yaml +0 -64
  887. pen_stack-8.0.3/prereg/paper4.yaml +0 -71
  888. pen_stack-8.0.3/prereg/phase0.yaml +0 -28
  889. pen_stack-8.0.3/prereg/ws_a.yaml +0 -57
  890. pen_stack-8.0.3/prereg/ws_atlas.yaml +0 -18
  891. pen_stack-8.0.3/prereg/ws_b.yaml +0 -50
  892. pen_stack-8.0.3/prereg/ws_ba.yaml +0 -45
  893. pen_stack-8.0.3/prereg/ws_ba_v33.yaml +0 -12
  894. pen_stack-8.0.3/prereg/ws_bench.yaml +0 -25
  895. pen_stack-8.0.3/prereg/ws_chat.yaml +0 -20
  896. pen_stack-8.0.3/prereg/ws_crit.yaml +0 -16
  897. pen_stack-8.0.3/prereg/ws_d.yaml +0 -11
  898. pen_stack-8.0.3/prereg/ws_ep.yaml +0 -40
  899. pen_stack-8.0.3/prereg/ws_expr2.yaml +0 -39
  900. pen_stack-8.0.3/prereg/ws_f.yaml +0 -38
  901. pen_stack-8.0.3/prereg/ws_frontend.yaml +0 -21
  902. pen_stack-8.0.3/prereg/ws_g.yaml +0 -37
  903. pen_stack-8.0.3/prereg/ws_h.yaml +0 -32
  904. pen_stack-8.0.3/prereg/ws_mc.yaml +0 -51
  905. pen_stack-8.0.3/prereg/ws_mon.yaml +0 -21
  906. pen_stack-8.0.3/prereg/ws_offtarget2.yaml +0 -106
  907. pen_stack-8.0.3/prereg/ws_priorart.yaml +0 -169
  908. pen_stack-8.0.3/prereg/ws_route.yaml +0 -9
  909. pen_stack-8.0.3/prereg/ws_seroprev.yaml +0 -40
  910. pen_stack-8.0.3/prereg/ws_uq.yaml +0 -62
  911. pen_stack-8.0.3/prereg/ws_wv.yaml +0 -20
  912. pen_stack-8.0.3/pyproject.toml +0 -118
  913. pen_stack-8.0.3/scripts/build_capsid_fitness.py +0 -98
  914. pen_stack-8.0.3/scripts/build_rag_corpus.py +0 -39
  915. pen_stack-8.0.3/scripts/fetch_licensed_sources.py +0 -57
  916. pen_stack-8.0.3/scripts/offtarget_chromatin_matched.py +0 -135
  917. pen_stack-8.0.3/scripts/offtarget_chromatin_validation.py +0 -115
  918. pen_stack-8.0.3/scripts/p1_build_atlas.py +0 -87
  919. pen_stack-8.0.3/scripts/p1_build_durability.py +0 -61
  920. pen_stack-8.0.3/scripts/p1_build_position_effect.py +0 -103
  921. pen_stack-8.0.3/scripts/p1_build_writer_eff.py +0 -66
  922. pen_stack-8.0.3/scripts/p1_export_tracks.py +0 -22
  923. pen_stack-8.0.3/scripts/p1_safety_concordance.py +0 -82
  924. pen_stack-8.0.3/scripts/p1_train_safety.py +0 -48
  925. pen_stack-8.0.3/scripts/p1_validation_report.py +0 -80
  926. pen_stack-8.0.3/scripts/p2_build_atlas.py +0 -36
  927. pen_stack-8.0.3/scripts/p3_benchmark_report.py +0 -82
  928. pen_stack-8.0.3/scripts/p4_genome_scan.py +0 -43
  929. pen_stack-8.0.3/scripts/p52_build_genotox_oracle.py +0 -115
  930. pen_stack-8.0.3/scripts/p53_build_epitope_oracle.py +0 -120
  931. pen_stack-8.0.3/scripts/reproduce.py +0 -115
  932. pen_stack-8.0.3/scripts/validate_components.py +0 -158
  933. pen_stack-8.0.3/scripts/ws_b_report.py +0 -104
  934. pen_stack-8.0.3/scripts/ws_c_report.py +0 -75
  935. pen_stack-8.0.3/setup.cfg +0 -4
  936. {pen_stack-8.0.3 → pen_stack-8.0.5}/LICENSE +0 -0
  937. {pen_stack-8.0.3 → pen_stack-8.0.5}/MANIFEST.in +0 -0
  938. {pen_stack-8.0.3 → pen_stack-8.0.5}/benchmarks/agentic_baseline/README.md +0 -0
  939. {pen_stack-8.0.3 → pen_stack-8.0.5}/benchmarks/delivery/SHA256SUMS +0 -0
  940. {pen_stack-8.0.3 → pen_stack-8.0.5}/benchmarks/genome_writing_bench/SHA256SUMS +0 -0
  941. {pen_stack-8.0.3 → pen_stack-8.0.5}/benchmarks/genome_writing_bench/tasks.yaml +0 -0
  942. {pen_stack-8.0.3 → pen_stack-8.0.5}/benchmarks/genome_writing_challenge/README.md +0 -0
  943. {pen_stack-8.0.3 → pen_stack-8.0.5}/benchmarks/offtarget/SHA256SUMS +0 -0
  944. {pen_stack-8.0.3 → pen_stack-8.0.5}/benchmarks/position_effect_human/SHA256SUMS +0 -0
  945. {pen_stack-8.0.3 → pen_stack-8.0.5}/benchmarks/verify/SHA256SUMS +0 -0
  946. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/atlas_families.yaml +0 -0
  947. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/bridge_offtarget_profile.yaml +0 -0
  948. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/calibration/preexisting_nab_independent.yaml +0 -0
  949. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/capsid_epitope_oracle.yaml +0 -0
  950. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/capsid_sequences.fasta +0 -0
  951. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/delivery_constraints.yaml +0 -0
  952. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/delivery_rules.yaml +0 -0
  953. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/delivery_vehicles.yaml +0 -0
  954. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/gates_v3.yaml +0 -0
  955. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/genotoxicity_oracle.yaml +0 -0
  956. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/gsh_validated_heldout.yaml +0 -0
  957. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/known_unknowns.yaml +0 -0
  958. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/metric_guide.yaml +0 -0
  959. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/mhc_epitope_oracle.yaml +0 -0
  960. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/oracles/reliability.yaml +0 -0
  961. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/rules/compliance.yaml +0 -0
  962. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/rules/fold.yaml +0 -0
  963. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/rules/multiplex.yaml +0 -0
  964. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/rules/payload.yaml +0 -0
  965. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/rules/reachability.yaml +0 -0
  966. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/safety/genotoxic_loci.yaml +0 -0
  967. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/safety/hazard_registry.yaml +0 -0
  968. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/safety/policy.yaml +0 -0
  969. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/safety/probes.yaml +0 -0
  970. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/score_axes.yaml +0 -0
  971. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/target_sites.yaml +0 -0
  972. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/universe_crosswalk.yaml +0 -0
  973. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/write_types.yaml +0 -0
  974. {pen_stack-8.0.3 → pen_stack-8.0.5}/configs/wtkb_curated.yaml +0 -0
  975. {pen_stack-8.0.3 → pen_stack-8.0.5}/data/curated/bridge_offtarget_profile_measured.parquet +0 -0
  976. {pen_stack-8.0.3 → pen_stack-8.0.5}/data/curated/gene_coords.parquet +0 -0
  977. {pen_stack-8.0.3 → pen_stack-8.0.5}/data/curated/unified_editor_universe.parquet +0 -0
  978. {pen_stack-8.0.3 → pen_stack-8.0.5}/data/offtarget/enumerated_cache.parquet +0 -0
  979. {pen_stack-8.0.3 → pen_stack-8.0.5}/data/offtarget/motif_cache.parquet +0 -0
  980. {pen_stack-8.0.3 → pen_stack-8.0.5}/docs/BACKLOG.md +0 -0
  981. {pen_stack-8.0.3 → pen_stack-8.0.5}/docs/STABILITY.md +0 -0
  982. {pen_stack-8.0.3 → pen_stack-8.0.5}/docs/alphagenome_feasibility.md +0 -0
  983. {pen_stack-8.0.3 → pen_stack-8.0.5}/docs/autonomy.md +0 -0
  984. {pen_stack-8.0.3 → pen_stack-8.0.5}/docs/build_interface.md +0 -0
  985. {pen_stack-8.0.3 → pen_stack-8.0.5}/docs/challenge.md +0 -0
  986. {pen_stack-8.0.3 → pen_stack-8.0.5}/docs/co_scientist.md +0 -0
  987. {pen_stack-8.0.3 → pen_stack-8.0.5}/docs/co_scientist_loop.md +0 -0
  988. {pen_stack-8.0.3 → pen_stack-8.0.5}/docs/delivery.md +0 -0
  989. {pen_stack-8.0.3 → pen_stack-8.0.5}/docs/delivery_immunology.md +0 -0
  990. {pen_stack-8.0.3 → pen_stack-8.0.5}/docs/digital_twin.md +0 -0
  991. {pen_stack-8.0.3 → pen_stack-8.0.5}/docs/experiment_design.md +0 -0
  992. {pen_stack-8.0.3 → pen_stack-8.0.5}/docs/integrations.md +0 -0
  993. {pen_stack-8.0.3 → pen_stack-8.0.5}/docs/live_oracles.md +0 -0
  994. {pen_stack-8.0.3 → pen_stack-8.0.5}/docs/mechanistic_constraints.md +0 -0
  995. {pen_stack-8.0.3 → pen_stack-8.0.5}/docs/oracle_mesh.md +0 -0
  996. {pen_stack-8.0.3 → pen_stack-8.0.5}/docs/rule_spec.md +0 -0
  997. {pen_stack-8.0.3 → pen_stack-8.0.5}/docs/rules.md +0 -0
  998. {pen_stack-8.0.3 → pen_stack-8.0.5}/docs/tutorials/compare-families.md +0 -0
  999. {pen_stack-8.0.3 → pen_stack-8.0.5}/docs/verify.md +0 -0
  1000. {pen_stack-8.0.3 → pen_stack-8.0.5}/docs/verify_service.md +0 -0
  1001. {pen_stack-8.0.3 → pen_stack-8.0.5}/pen_stack/_resources.py +0 -0
  1002. {pen_stack-8.0.3 → pen_stack-8.0.5}/pen_stack/active/__init__.py +0 -0
  1003. {pen_stack-8.0.3 → pen_stack-8.0.5}/pen_stack/api/__init__.py +0 -0
  1004. {pen_stack-8.0.3 → pen_stack-8.0.5}/pen_stack/build/__init__.py +0 -0
  1005. {pen_stack-8.0.3 → pen_stack-8.0.5}/pen_stack/design/__init__.py +0 -0
  1006. {pen_stack-8.0.3 → pen_stack-8.0.5}/pen_stack/loop/__init__.py +0 -0
  1007. {pen_stack-8.0.3 → pen_stack-8.0.5}/pen_stack/oracles/status.py +0 -0
  1008. {pen_stack-8.0.3 → pen_stack-8.0.5}/pen_stack/web/__init__.py +0 -0
  1009. {pen_stack-8.0.3 → pen_stack-8.0.5}/pen_stack/web/guide.py +0 -0
  1010. {pen_stack-8.0.3 → pen_stack-8.0.5}/pen_stack/web/router.py +0 -0
  1011. {pen_stack-8.0.3 → pen_stack-8.0.5}/pen_stack.egg-info/dependency_links.txt +0 -0
  1012. {pen_stack-8.0.3 → pen_stack-8.0.5}/pen_stack.egg-info/entry_points.txt +0 -0
  1013. {pen_stack-8.0.3 → pen_stack-8.0.5}/pen_stack.egg-info/requires.txt +0 -0
  1014. {pen_stack-8.0.3 → pen_stack-8.0.5}/pen_stack.egg-info/top_level.txt +0 -0
  1015. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_acq.yaml +0 -0
  1016. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_aldesign.yaml +0 -0
  1017. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_alvalidate.yaml +0 -0
  1018. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_ba_v45.yaml +0 -0
  1019. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_c.yaml +0 -0
  1020. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_cal.yaml +0 -0
  1021. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_calib.yaml +0 -0
  1022. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_challenge.yaml +0 -0
  1023. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_cite.yaml +0 -0
  1024. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_closedloop.yaml +0 -0
  1025. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_continual.yaml +0 -0
  1026. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_cosci2.yaml +0 -0
  1027. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_ct.yaml +0 -0
  1028. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_delivery.yaml +0 -0
  1029. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_drift.yaml +0 -0
  1030. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_e.yaml +0 -0
  1031. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_env.yaml +0 -0
  1032. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_epitope.yaml +0 -0
  1033. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_gen.yaml +0 -0
  1034. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_genotox.yaml +0 -0
  1035. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_graph.yaml +0 -0
  1036. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_hybrid.yaml +0 -0
  1037. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_immune.yaml +0 -0
  1038. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_immune2.yaml +0 -0
  1039. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_ingest.yaml +0 -0
  1040. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_innate.yaml +0 -0
  1041. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_loop.yaml +0 -0
  1042. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_manifest.yaml +0 -0
  1043. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_mcp.yaml +0 -0
  1044. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_mech.yaml +0 -0
  1045. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_o.yaml +0 -0
  1046. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_offtarget.yaml +0 -0
  1047. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_openapi.yaml +0 -0
  1048. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_oracle.yaml +0 -0
  1049. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_orch.yaml +0 -0
  1050. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_outcome.yaml +0 -0
  1051. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_pareto.yaml +0 -0
  1052. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_peg.yaml +0 -0
  1053. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_penchat.yaml +0 -0
  1054. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_plan.yaml +0 -0
  1055. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_policy.yaml +0 -0
  1056. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_profile.yaml +0 -0
  1057. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_proto.yaml +0 -0
  1058. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_r.yaml +0 -0
  1059. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_redteam.yaml +0 -0
  1060. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_screen.yaml +0 -0
  1061. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_simlab.yaml +0 -0
  1062. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_twincal.yaml +0 -0
  1063. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_v.yaml +0 -0
  1064. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_vcell.yaml +0 -0
  1065. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_verify.yaml +0 -0
  1066. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_writer.yaml +0 -0
  1067. {pen_stack-8.0.3 → pen_stack-8.0.5}/prereg/ws_writespec.yaml +0 -0
  1068. {pen_stack-8.0.3 → pen_stack-8.0.5}/scripts/calibrate_immune_axes.py +0 -0
  1069. {pen_stack-8.0.3 → pen_stack-8.0.5}/scripts/fetch_artifacts.sh +0 -0
  1070. {pen_stack-8.0.3 → pen_stack-8.0.5}/scripts/offtarget_chromatin_incremental.py +0 -0
  1071. {pen_stack-8.0.3 → pen_stack-8.0.5}/scripts/p2_build_human_head.py +0 -0
  1072. {pen_stack-8.0.3 → pen_stack-8.0.5}/scripts/pa_epridict_distinctness.py +0 -0
@@ -0,0 +1,2549 @@
1
+ # Changelog
2
+
3
+ All notable changes to PEN-STACK are documented here. This file follows
4
+ [Keep a Changelog](https://keepachangelog.com/).
5
+
6
+ ## [8.0.5] - 2026-07-16
7
+
8
+ A documentation and readability release. No public function signatures change and no scientific results change.
9
+
10
+ ### Changed
11
+ - Docstrings and comments across the package describe each component in plain terms. Internal development
12
+ labels and per-component version stamps were removed from the shipped source, the test suite, the served
13
+ API, CLI, and interface text, and the documentation, and the test modules were renamed to describe what
14
+ they cover. The pre-registration records and the sealed benchmark specifications are unchanged, so every
15
+ integrity checksum still verifies.
16
+
17
+ ## [8.0.4] - 2026-07-16
18
+
19
+ A packaging fix. No public function signature changes.
20
+
21
+ ### Fixed
22
+ - **The wheel now ships the data files the package reads at runtime.** `pen_stack/mech/pfam_whitelist.yaml`
23
+ and the `pen_stack/atlas/*.parquet` tables live inside the package and are loaded on first use, but the
24
+ build declared no package data, so `pip install pen-stack` produced a wheel without them and
25
+ `PfamWhitelist()` raised `FileNotFoundError`. A `[tool.setuptools.package-data]` entry now includes them.
26
+ An editable install resolves to the source tree, which masked the gap.
27
+
28
+ ### Changed
29
+ - Documentation and docstrings describe each component in plain terms. Internal work-stream labels,
30
+ per-component version stamps, status-legend glyphs, and pointers to local-only working files were removed
31
+ from the published prose, the benchmark READMEs, and the doc cards.
32
+
33
+ ## [8.0.3] - 2026-07-15
34
+
35
+ A safety patch from the results audit. No public function signature changes.
36
+
37
+ ### Fixed
38
+ - **The genotoxicity safety filter no longer has false negatives on documented clinical loci.** The learned
39
+ `safety` score scored documented clinical insertional-oncogenesis loci as safe (BMI1 at the 99.9th
40
+ writability percentile, plus SETBP1 and MN1) because its label covered only six genes. A deterministic
41
+ **reject-known-bad blocklist** (`configs/safety/genotoxic_loci.yaml`, `pen_stack/wgenome/genotoxic_blocklist.py`,
42
+ applied in the atlas) now flags any locus within the window of one of the eight documented clinical loci as
43
+ unsafe by rule, overriding the soft score. The list is sourced independently from the trial literature (the
44
+ 2025 *Leukemia* vector-genotoxicity review and the primary trial reports), not from the benchmark. It is a
45
+ reject-known-bad blocklist, not a novel-locus genotoxicity predictor.
46
+ - **The chance-level silencing prediction is flagged.** `p_silenced` (AUROC 0.50 on the human K562 head) now
47
+ carries a `silencing_classifier_not_validated` scope flag so a chance-level number is never presented as a
48
+ validated result; the expression head is what ships.
49
+
50
+ ## [8.0.2] - 2026-07-13
51
+
52
+ A documentation-correctness and reproducibility-enforcement patch. No scientific result and no public
53
+ function signature changes.
54
+
55
+ ### Fixed
56
+ - **Corrected the MCP tool count.** The MCP server exposes twenty-two tools; the README, CHANGELOG, and
57
+ manuscript are corrected from "twenty," and a guard test now fails if the registered count ever diverges
58
+ from the documented one.
59
+ - **Synced the Docker image version** to the package version, enforced by the release version-consistency
60
+ test so the image label cannot drift again.
61
+
62
+ ### Changed
63
+ - **CI enforces reproducibility on every commit.** `make repro` now runs in CI on each Python version, so the
64
+ two headline recomputations, the frozen-input integrity check, and the no-fabrication gate are verified
65
+ rather than assumed.
66
+
67
+ ## [8.0.1] - 2026-07-13
68
+
69
+ A reproducibility and API-hardening patch. No scientific result and no public function signature changes.
70
+
71
+ ### Changed
72
+ - **Result, verdict, and safety types are now immutable (frozen).** `OracleResult` and its nested
73
+ `Provenance`, `Verdict`, `SafetyVerdict`, `ScreenHit`, `Rule`, and `RuleResult` can no longer be mutated
74
+ after construction, so a result's provenance and scope, a verdict's legality, or a screen hit's severity
75
+ cannot be edited downstream. Build a changed copy with `model_copy(update=...)`.
76
+ - **The REST, MCP, and Gymnasium-environment tests and the SBOL3/GenBank round-trip run by default.**
77
+ `fastapi`, `uvicorn`, `httpx`, `fastmcp`, `gymnasium`, `sbol3`, and `biopython` are in the `[dev]` extra, so
78
+ the full suite exercises these features rather than skipping them. Heavy compiled extras stay opt-in.
79
+ - **The one-command reproduction recomputes a second headline from committed source.**
80
+ `scripts/pa_epridict_distinctness.py` (wired into `make repro`) re-derives the durability-vs-ePRIDICT
81
+ distinctness result, and `scripts/reproduce.py` now distinguishes recomputed headlines from echoed sealed
82
+ metrics.
83
+
84
+ ### Fixed
85
+ - **An abstention is no longer reported as high confidence.** A design verified with no calibrated confidence
86
+ is now `not-computable`, not `grounded-confident`.
87
+ - **The frozen-input integrity check works on a fresh checkout.** `python bench/run.py --verify` parses the
88
+ standard `sha256sum` manifest format (two-space, CRLF-tolerant); the manifest re-seals only on explicit
89
+ `--seal`; a `.gitattributes` pins the hashed inputs to LF for cross-platform stability.
90
+ - **The reproduction harness can fail.** `scripts/reproduce.py` exits non-zero if any block fails instead of
91
+ always reporting success.
92
+ - Corrected the ePRIDICT variance figure in the README (R-squared 0.041, matching the committed metrics).
93
+
94
+ ## [8.0.0] - 2026-07-13 - Stable release of record
95
+
96
+ The first stable, citable release. The major version marks a committed public API surface (the SDK
97
+ functions, the REST endpoints, and the twenty-two MCP tools) governed by a one-minor-version deprecation policy.
98
+ It consolidates the gated 7.x development trail rather than replacing it: the pre-registrations, SHA-locked
99
+ benchmarks, and disclosed negatives that trail documents remain intact and referenced. Stable surfaces
100
+ carry calibrated uncertainty and validation status; the mechanism-based paths (serine-integrase, bridge, and
101
+ CAST off-target) are marked experimental and may change.
102
+
103
+ ### Added
104
+ - **A one-chromosome demo atlas** (`data/demo/atlas_k562.parquet`, chr19). A fresh clone can run the
105
+ safe-harbour quickstart without first fetching the full release: `PEN_ATLAS_DIR=data/demo pen-stack
106
+ writable --gene AAVS1 --ct k562` returns the ranked writable bins of the AAVS1 (PPP1R12C) locus. Opt-in via
107
+ `PEN_ATLAS_DIR`, so the atlas-gated test suite is unchanged. Full genome-wide atlases come from Zenodo via
108
+ `scripts/fetch_artifacts.sh`.
109
+ - **An Anthropic (Claude) provider in the LLM layer.** `pen_stack/rag/llm.py` now supports three provider
110
+ styles (OpenAI-compatible, Ollama, Anthropic Messages), including multi-turn tool calling, so the
111
+ conversational agent and the evaluations run provider-agnostically across hosted-frontier and local models.
112
+ Keys are read from an env var or a gitignored file and are never committed.
113
+ - **A measured, LLM-on grounding evaluation** (`benchmarks/grounding_llm_on/`). The ungrounded-baseline
114
+ contrast ships a committed metrics file and an adversarial probe set, run with the model live across three
115
+ model families: with no tools an ungrounded model emits concrete tool-only quantities (fabrication), while
116
+ the grounded agent, which routes every quantity through a validated tool, emits none. Transcripts are cached
117
+ and replay offline in CI.
118
+ - **An agentic baseline** (`benchmarks/agentic_baseline/`). A real external LLM agent drives the validated
119
+ tools and every number in its trace is audited to a direct tool call. Verified across three models spanning
120
+ a small local model to hosted-frontier models; the no-fabrication audit passes for all.
121
+ - **A one-command reproduction path.** `make repro` reproduces every result that runs on the committed data
122
+ and the demo atlas on a fresh clone, with no download and no API key (`scripts/reproduce.py`); `make fetch`
123
+ then `make repro-full` add the genome-wide atlas benchmarks from the Zenodo release. Verified end to end in
124
+ a clean `python:3.12-slim` container.
125
+ - **Committed metrics for the three headline analyses** (`benchmarks/position_effect_human/`,
126
+ `offtarget/integrase_chalberg/`, `genotox_panel/`), so the paper's central numbers reproduce directly from
127
+ the repository.
128
+
129
+ ### Changed
130
+ - Benchmark provenance references relative paths only. The license (MIT), MCP tool count (twenty-two), and
131
+ Verify-Bench rule count (eleven) are reconciled across the package metadata, the repository, and the
132
+ manuscript. The repository was confirmed free of hardcoded credentials, addresses, and absolute local paths.
133
+
134
+ ## [7.3.21] - 2026-07-11 - World-model graph: resolve any locus (not just exact GSH names)
135
+
136
+ ### Fixed
137
+ - **The world-model graph query resolved only the exact curated safe-harbour node names.** The graph materialises
138
+ a `locus:` node for each curated GSH locus and matched the query string exactly, so `PPP1R12C` (AAVS1's anchor
139
+ gene), `ROSA26` (whose node is `hRosa26`), and real genes such as TRAC, HBB, and LMO2 all returned nothing. The
140
+ query now resolves in three tiers:
141
+ - A curated node is matched by **GSH name, anchor gene, or alias, case-insensitively** (AAVS1 ≡ aavs1 ≡
142
+ PPP1R12C; ROSA26 ≡ hRosa26; HIPP11 ≡ H11), returning the same DOI-provenanced answer.
143
+ - A query that is not a curated safe harbour but resolves to a **real gene** returns the **tier-1 reprogrammable
144
+ writers**, which engage any locus at the locus level (the documented crosslink property), flagged as a
145
+ candidate rather than a curated safe harbour (per-site reachability and safety remain the Planner's and
146
+ Guardian's responsibility).
147
+ - Anything else returns an explained empty result rather than an error.
148
+ The response carries `resolved_locus` and `is_curated_safe_harbour`, and the Closed Loop page shows the resolved
149
+ locus and a curated-vs-candidate badge.
150
+
151
+ ## [7.3.20] - 2026-07-11 - Closed loop: a UI surface + /cloudlab 500-on-bad-provider fix
152
+
153
+ ### Fixed
154
+ - **`POST /api/cloudlab` returned an unhandled 500 for any `provider` other than "mock".** `submit()` raises
155
+ `CloudLabError` for a provider outside the wired set, but `submit_gated()` caught only the safety refusal
156
+ (`ProtocolExportError`), so it propagated. The endpoint now returns a **422** with the valid-provider list for an
157
+ unknown provider, and a null/empty/missing provider falls back to the wired `mock` dry-run path.
158
+
159
+ ### Added
160
+ - **A "Closed Loop" page.** Three closed-loop capabilities previously reachable only via the API are now
161
+ surfaced (the fourth, the validation campaign, is already on Experiments):
162
+ - **Build & submit (cloud-lab)**: a design form plus provider select drives the verify-first flow: a cleared
163
+ design returns a DRAFT protocol preview and a mock/dry-run job receipt (Level 3, human-in-control); a hazardous
164
+ cargo (e.g. ricin) is refused with no protocol emitted.
165
+ - **SDL-brain benchmark**: the EIG/VOI designer versus random/greedy (curve-area gap with CI), BayBE/Atlas
166
+ cited, with a "BayBE not installed in this deployment" note when the optional dependency is absent.
167
+ - **World-model graph**: a locus/cargo-form query returns the provenanced writer→locus→vehicle paths.
168
+ Wired into the left-rail nav (Build & learn) and the router at `/closed-loop`.
169
+
170
+ ## [7.3.19] - 2026-07-11 - Experiment designer: expected information gain varies with cell-type coverage
171
+
172
+ ### Changed
173
+ - **`expected_info_gain` now varies across candidates** instead of reducing to the twin's fixed ±0.20 uncertainty
174
+ band (which read a near-constant ~0.0202 for every candidate). EIG folds in the design-varying uncertainty the
175
+ fixed band understates: an unmeasured cell type (no atlas data, so more reducible uncertainty) and an
176
+ out-of-distribution design widen the effective standard deviation. EIG is ~0.02 in a fully-measured cell
177
+ (K562/HepG2), ~0.43 partially-measured (HSPC), ~0.71 unmeasured (iPSC/PBMC/…), and ~1.5 out-of-distribution; it
178
+ is constant across gene/vehicle/cargo within one cell type, since the mechanistic twin carries no per-gene
179
+ uncertainty. Coverage and OOD are folded into EIG rather than double-counted as separate acquisition terms.
180
+
181
+ ## [7.3.18] - 2026-07-11 - Experiment designer: acquisition rebuilt on design-varying signals
182
+
183
+ ### Changed
184
+ - **The experiment-suggestion acquisition is rebuilt on design-varying signals.** Expected information gain derives
185
+ entirely from the twin's fixed ±0.20 uncertainty band, so the suggested batch scored a near-constant ~0.02 for
186
+ almost every candidate, and the pool varied only vehicle × cargo at one cell type, where relative expression is
187
+ per-copy (cargo-independent). The acquisition now combines:
188
+ - **Coverage novelty**: an experiment in an unmeasured cell type reduces more uncertainty; the measured-atlas
189
+ roster (K562/HepG2 full, HSPC partial, others none) drives it.
190
+ - **Feasibility gate**: an experiment that cannot be built as specified (cargo overflowing the vehicle) is
191
+ down-weighted.
192
+ - **Immune value-of-information**, counting only **in-scope** proxy axes, so it varies by vehicle (a PEGylated
193
+ LNP puts the anti-PEG axis in scope; AAV does not).
194
+ - **Marginal gain**: the submodular greedy objective (informativeness minus overlap with the picks already
195
+ scheduled), distinct per experiment and decreasing down the batch.
196
+ The candidate pool spans all cell types × 4 vehicles so the coverage/feasibility/immune signals differ across it;
197
+ the batch is scored per candidate cell, and each experiment is returned with its full breakdown. The Experiments
198
+ page shows the marginal-gain ranking with a "why" line (coverage, immune-VOI, buildability) and states that the
199
+ mechanistic twin cannot finely rank two experiments in the same regime, the ranking is coverage + buildability +
200
+ immune-VOI + diversity. `select_batch` scores each candidate once.
201
+ - The "Load expression-validation campaign" plan is a fixed pre-registered 48-row campaign, independent of the
202
+ candidate-pool form; the scores panel notes this.
203
+
204
+ ## [7.3.17] - 2026-07-10 - App-wide input-validation sweep (out-of-domain values are flagged everywhere)
205
+
206
+ ### Added
207
+ - **A consistent input-validation pass across every page.** Shared helpers in `lib/format.js`
208
+ (`invalidNucleotides`, `clampInt`) and a reusable `SeqWarning` component in `ui.jsx`:
209
+ - **Nucleotide sequence fields** warn on characters outside A/C/G/T/U/N (kept, not silently accepted):
210
+ Design Studio / Twin / Guardian cargo sequence, Off-Target guide / crRNA spacer / bridge target-core, Writer
211
+ Atlas guide-design target and donor.
212
+ - **Writer Atlas "Cargo bp"** now shows the same "clamped to X (allowed 1–300,000)" note Site Finder uses,
213
+ instead of clamping silently.
214
+ - **Design Studio multiplex edits**: the free-text chromosome flags an invalid value (chr1–chr22, chrX/Y/M)
215
+ and the genomic position clamps to a non-negative coordinate (was `parseInt || 0`, accepting negatives).
216
+ - Twin chromatin marks (0–1) and cargo-size vehicle cap + non-positive (from 7.3.16) complete the set.
217
+
218
+ ### Fixed
219
+ - **Twin chromatin-mark fields no longer mangle a typed negative** (`"-5"` had become `"05"`). The value was
220
+ coerced with `parseFloat || 0` on every keystroke, collapsing a lone leading `-` to `0`. The fields now hold
221
+ the raw string while editing (coerced to a number only at predict time) and drop the native `min`/`max`, so an
222
+ out-of-range value, including a negative, can be entered and is flagged rather than silently blocked.
223
+ Free-text NL fields (co-scientist chat, WriteSpec brief), amino-acid / SMILES fields (capsid, oracles), and the
224
+ free-form model-feature fields are intentionally left unconstrained, since client-side validation would false-warn.
225
+
226
+ ## [7.3.16] - 2026-07-10 - Vehicle-aware cargo hint, OOD-widen scope, input range warnings
227
+
228
+ ### Fixed
229
+ - **The "Cargo size (bp)" hint reflects the selected delivery vehicle.** It was hardcoded to "AAV single-vector
230
+ payload caps near ~4.7 kb" for every vehicle; it now reflects the selected vehicle's real capacity (AAV dual
231
+ ~9 kb, lentivirus ~8 kb, LNP ~15 kb, HDAd ~35 kb, HSV ~100 kb, electroporation = no packaging limit), sourced
232
+ from a `VEHICLE_CAP_BP` map mirroring `configs/delivery_vehicles.yaml`, with an inline over-capacity warning when
233
+ the entered cargo exceeds the cap.
234
+ - **The position-effect model's "OOD widen" factor and its presentation.** The factor reads near its ×3 ceiling for most realistic
235
+ chromatin input. It is genuinely computed (near-zero input ≈ ×1, mid-range ≈ ×2.4–×2.8, cap ×3), but the
236
+ position-effect head was trained on normalized exact-site features, so typical 0–1 histone values at the app's
237
+ coarse 1 kb resolution sit outside that distribution and the widen flags them as out-of-distribution (near the
238
+ cap). The stat caption, the not-outcome-validated banner, and the scores panel now explain that a high widen at
239
+ this resolution is the signal working, the same cause as `outcome_validated: false`, rather than a fixed value.
240
+
241
+ ### Added
242
+ - **Range warnings on out-of-domain inputs.** The five chromatin marks are documented normalized signal in [0,1];
243
+ the fields previously accepted e.g. -5 and fed it to the model unflagged. They are now bordered and warned when
244
+ outside 0–1 (value kept, not clamped, so the OOD signal still reflects it). A non-positive cargo size is flagged
245
+ (`feasibility.buildable=False` + `cargo_size_nonpositive` scope flag) instead of reading as buildable.
246
+ - **A promoter/cell-type note.** Selecting a tissue-specific promoter (e.g. TBG = liver) surfaces that the
247
+ mechanistic estimate is cell-type-agnostic and applies the same strength regardless of tissue match, so a
248
+ maximally-optimistic score for a biologically inappropriate promoter/cell-type pairing is not misread.
249
+
250
+ ## [7.3.15] - 2026-07-09 - Health check surfaces writability-atlas presence (deploy-mount visibility)
251
+
252
+ ### Fixed
253
+ - **`/api/health` reports whether the per-cell-type writability atlases are present,** not just the bundled
254
+ writer atlas. A deploy that drops the runtime `-v ~/data/out:/work/data/out` mount leaves the container with no
255
+ per-cell-type atlas parquets, so Site Finder returns `atlas_<ct>.parquet not found` and the cell-type dropdown
256
+ shows "no atlas" for every cell type (including the measured K562/HepG2/HSPC), yet `/api/health` stayed green
257
+ because `atlas_present` checks only the bundled writer atlas. Health now includes `writability_atlas:
258
+ {measured_count, measured, ok}`; `measured_count == 0` makes a dropped-mount deploy immediately visible.
259
+
260
+ ## [7.3.14] - 2026-07-09 - Digital Twin: surface the model's OWN OOD signal + disambiguate the two OOD checks
261
+
262
+ ### Fixed
263
+ - **The Twin page's top-level "OOD" flag is disambiguated from the position-effect model's own OOD signal.** The
264
+ top-level flag is bound to the **virtual-cell response oracle's** scope card (its list of in-distribution cell
265
+ types and perturbation kinds), and every cell type the dropdown offers is on that list, so it reads "no" through
266
+ this UI by construction, not a broken gate. The **position-effect** model has its own separate
267
+ out-of-distribution signal (`ood_widen`, a Mahalanobis distance over the 5 supplied chromatin marks) that the
268
+ API returned but the UI never surfaced (×2.09 at typical marks, saturating at ×3.0 for marks pushed to 10–100).
269
+ Changes:
270
+ - The position-effect card shows an **"OOD widen (this head)"** stat (×1 typical → ×3 cap), colour-graded, so the
271
+ position-effect model's own OOD signal is visible and moves with the chromatin context.
272
+ - The top-level stat is relabelled **"OOD (response model)"** with an inline note that it is the response
273
+ oracle's scope-card check (expected to read "no" for any dropdown cell type), a different signal from the
274
+ position-effect widen factor.
275
+ - The "How to read these scores" panel documents both OOD checks separately.
276
+ - A regression test locks in that `position_effect.ood_widen` widens for out-of-range chromatin marks.
277
+
278
+ ## [7.3.13] - 2026-07-09 - Guardian: FASTA-header robustness fix + Design Studio Proof detail parity
279
+
280
+ ### Fixed
281
+ - **A sequence pasted straight from a database (a `>accession description` FASTA header plus wrapped sequence
282
+ lines) is now screened correctly.** `_looks_like_nucleotide()` ran on the raw pasted text, header included; the
283
+ header's non-nucleotide characters diluted the nucleotide fraction below the classification threshold, so the
284
+ header+sequence blob was misclassified as protein and scanned as one string, with no 6-frame translation. The
285
+ screen now strips FASTA/GenBank header lines (`>`, `;`) and whitespace before the nucleotide-vs-protein decision
286
+ (`_strip_headers_and_whitespace`) and cleans stray non-amino-acid characters in the protein branch. A
287
+ FASTA-formatted toxin sequence that previously returned zero hits now refuses.
288
+ - **Design Studio's Proof object (`/api/verify/proof`) carries the full hazard detail.** A hazard hit was reduced
289
+ to a bare `{signature, kind, severity}` with no reason, citation, or (for a sequence-domain hit) the Pfam
290
+ accession/bit score that Guardian's `/api/safety` view already showed. `_biosecurity_axis()` now carries `reason`
291
+ (the matched signature name), `citation` (the control-list reference), and `pfam_accession`/`bit_score` when the
292
+ hit came from the sequence screen; the Proof panel renders them as Guardian's hit list does.
293
+
294
+ ## [7.3.12] - 2026-07-09 - Guardian: local Pfam/HMMER sequence-domain screen (the Cargo sequence box is now screened)
295
+
296
+ ### Added
297
+ - **A raw Cargo sequence (DNA/RNA/protein) is screened for the curated toxin families, not only a declared
298
+ Cargo function.** `sequence_homology()` was previously a no-op in this deployment (its `external_hook` was an
299
+ unwired extension point). `HazardRegistry` now has a `.default()` registry that wires
300
+ `pen_stack/safety/pfam_scan.py` as that hook: a cargo sequence is 6-frame-translated (DNA/RNA) or scanned
301
+ directly (protein) against bundled public Pfam profile HMMs for the same 17 accessions already in
302
+ `configs/safety/hazard_registry.yaml` (ricin/RIP, botulinum, diphtheria, anthrax, cholera, staph/strep
303
+ enterotoxin, conotoxin), using each profile's Pfam gathering (GA) cutoff, the threshold Pfam's own annotation
304
+ pipeline uses to call a family match. No hazard sequences are bundled: profile HMMs are public statistical
305
+ models built from many aligned sequences, not any one organism's sequence, consistent with the registry's
306
+ existing no-hazard-sequences policy. The screen reaches every entry point unchanged (`/api/safety`,
307
+ `/api/verify`, `/api/generate`, the Co-Scientist chat's design lane), since all funnel through `screen_design()`
308
+ → the default registry: a sequence for a curated family refuses with no cargo_function declared, while benign
309
+ cargo (a GFP CDS fragment, a Factor IX fragment) stays clear. Scope: this covers the curated family list only
310
+ and is not a substitute for a full external homology screener (IBBIS Common Mechanism / SecureDNA) over a larger
311
+ reference set; an integrator can override via `HazardRegistry.load(external_hook=...)`.
312
+ - `provenance.declared_signal` (v7.3.11) now counts a submitted `cargo_seq`/`cargo_sequence` as signal, since it
313
+ is genuinely screened.
314
+
315
+ ## [7.3.11] - 2026-07-09 - Guardian: distinguish an empty submission from a screened-clear result + Cargo function autofill fix
316
+
317
+ ### Fixed
318
+ - **An empty Guardian submission is distinguished from a screened benign design.** With no cargo function, domain
319
+ tag, or taxon declared, `safety_gate` has no signal and correctly decides `clear`, but the badge and reason
320
+ ("no hazard signal") were indistinguishable from a benign design ("human factor IX") that was actually checked.
321
+ `SafetyVerdict.provenance` now carries `declared_signal` (whether anything screenable was submitted); the reason
322
+ text reads "nothing was screened" when it is `False`, and the Guardian page renders a caveat: *"Nothing was
323
+ screened. 'Clear' here means there was no input to check, not a verified-safe result."*
324
+ - **Cargo function field text duplication.** The field had no `autoComplete` attribute, leaving it open to the
325
+ browser's autofill/suggestion heuristics interfering with a controlled input. `autoComplete="off"` is set on the
326
+ Cargo function and Gene/target inputs and the Cargo sequence textarea (the app's React state is the single source
327
+ of truth for these fields).
328
+
329
+ ## [7.3.10] - 2026-07-08 - Promoter selector + cargo-capacity feasibility + mechanistic/learned transparency; multiplex verify fix
330
+
331
+ ### Fixed
332
+ - **The multiplex plan (v7.3.9) now triggers its rule.** A multi-edit plan was sent with the original
333
+ `write_type` (e.g. `insertion`), whose rule categories exclude `multiplex`, so `multiplex.translocation_risk`
334
+ never ran (empty `soft_flags`). The plan now routes as `write_type="multiplex"`, so the translocation screen
335
+ fires (two DSB nucleases on different chromosomes → risk 0.64 flag; a DSB-free plan → ~zero).
336
+ - **The Digital Twin's top-level "Relative expression" reflects promoter and vehicle changes; its
337
+ cell-type-agnostic, per-copy basis is now explicit.** The mechanistic estimate is
338
+ `promoter × copy-number × accessibility × pre-existing-NAb`, with accessibility neutral (no cell-type chromatin
339
+ track mounted), **cell-type-agnostic** (the cell-type position effect is the learned position-effect head) and
340
+ **per-copy** (independent of cargo size), so it did not move with cell type or cargo size. The page now (a)
341
+ exposes the **31-promoter palette** as a selector, a live lever the estimate reacts to (`GET /twin/promoters`,
342
+ `design.promoter`); (b) surfaces the **learned head's cell-type-aware relative expression** next to the
343
+ mechanistic headline, so a cell-type change is visible; (c) flags **cargo-over-capacity** as not-buildable
344
+ (`feasibility` in `/predict`); (d) states the mechanistic basis inline.
345
+
346
+ ## [7.3.9] - 2026-07-08 - Design Studio: multiplex-plan UI + advisory (soft-penalty) flags surfaced
347
+
348
+ ### Added
349
+ - **A "Plan multiple simultaneous edits" section on Design Studio** builds a 2–5-edit plan (chromosome / position /
350
+ writer-family rows) and sends it as `design.edits`, making the `multiplex.translocation_risk` legality rule
351
+ (implemented and rule-spec-published since v3.1, but with no UI path to `design.edits`) reachable. The default
352
+ two-row example matches the rule's own test fixture (two DSB nucleases on different chromosomes) and reproduces a
353
+ "flag" on first Verify.
354
+ - **Advisory (soft-penalty) flags are rendered on the Verify result.** `Verdict.soft_flags` was always computed
355
+ (multiplex translocation risk, AAV packaging margin, delivery sequence constraints, fold cross-loop
356
+ complementarity) but never rendered, since soft penalties do not fail legality and the Proof object's legality
357
+ axis never carried them. A new "Advisory flags" panel shows the rule id, reason, and value for any soft-penalty
358
+ rule that fires, labelled non-blocking.
359
+
360
+ ## [7.3.8] - 2026-07-08 - not_evaluated state under biosecurity refuse + standards concordance surfaced
361
+
362
+ ### Fixed
363
+ - **The legality and confidence proof axes no longer report a verdict when biosecurity refuses a design.**
364
+ `verify.service.verify()` short-circuits on a biosecurity refuse and returns *before* the rules engine or
365
+ confidence calibration run (`legal=None`, `violations=[]`), a security-first fail-fast posture. `verify_proof()`'s
366
+ legality axis previously read that state as `status="fail"` with an empty violated list and no repair hint, and
367
+ the confidence axis read it as `status="abstain"` with a repair hint suggesting "supply the soft per-axis scores
368
+ to calibrate", which would not help. Both axes now report **`status="not_evaluated"`**, `ok=True` (an
369
+ unevaluated axis does not itself block; biosecurity already blocks `passable`), with an explanatory,
370
+ non-actionable repair hint. A genuine legality failure with no biosecurity hazard is unaffected (regression-tested).
371
+
372
+ ### Added
373
+ - **Standards concordance (v6.12) is reachable via REST and rendered on the Guardian page.**
374
+ `concordance_report()` and `align_to_common_mechanism()` were implemented and unit-tested since v6.12 but had no
375
+ API endpoint or UI surface. `GET /safety/concordance` serves the labelled-probe-set report (8/8 concordant);
376
+ `POST /safety` additively carries a per-decision `standards` field (Common Mechanism ScreenStatus + SecureDNA
377
+ outcome), leaving the underlying decision unchanged. Guardian.jsx renders the per-screen standards alignment and
378
+ a concordance-benchmark card.
379
+
380
+ ## [7.3.7] - 2026-07-08 - Writer immunogenicity: surface the human self control so the ADA foreignness term is visible
381
+
382
+ ### Added
383
+ - **The Writer Atlas immunogenicity table surfaces the human self control (albumin) as a labelled reference
384
+ row.** Every genome writer is foreign (foreignness = 1), so the shipped rows could not show that
385
+ `ada_risk = MHC-II density × foreignness(origin)` is multiplicative, the numbers were indistinguishable from
386
+ `ada_risk = MHC-II load`. The self control (origin = self → foreignness 0) has a non-zero MHC-II density (0.32)
387
+ yet ADA-risk 0, so ADA decouples from the load: the row demonstrates that the foreignness term does real work
388
+ (central tolerance). `writer_immunogenicity_table()` appends it with `is_control: True`; the UI highlights it and
389
+ explains the decoupling; a test asserts control ada_risk 0 versus foreign writers ada_risk > 0.
390
+
391
+ ## [7.3.6] - 2026-07-08 - Design Studio: immune-risk profile no longer shows stale numbers when the main vehicle changes
392
+
393
+ ### Fixed
394
+ - **The Immune-risk profile card no longer desyncs from the main form's Delivery vehicle.** Changing the main-form
395
+ vehicle dropdown moved the profile card's highlighted vehicle chip (it tracked `design.delivery_vehicle`) while
396
+ the axis numbers stayed on the previously-profiled vehicle, so AAV numbers could be read as if they were LNP's.
397
+ The chip highlight now tracks the vehicle the profile was actually **computed for** (`immVehicle`), so chip and
398
+ numbers agree, and a banner appears when the main-form vehicle diverges ("These axes are for X … click its chip
399
+ or press Profile again to recompute for Y").
400
+
401
+ ## [7.3.5] - 2026-07-08 - Off-Target auto-scroll hotfix (instant, not smooth)
402
+
403
+ ### Fixed
404
+ - **The v7.3.4 auto-scroll-to-result now moves the viewport.** `scrollIntoView({behavior:"smooth"})` no-ops on
405
+ this app's scroll container; dropping `behavior:"smooth"` makes the Off-Target result reliably scroll into view
406
+ on the first click.
407
+
408
+ ## [7.3.4] - 2026-07-08 - Off-Target page: scroll the result into view + guard rapid writer-class switches
409
+
410
+ ### Fixed
411
+ - **The Off-Target finder result scrolls into view when it renders.** The page was the only finder missing the
412
+ shared auto-scroll-to-result pattern, so a result rendered below the tall explainer cards read as "no visible
413
+ output" on the first click. Adds a `resultsRef` and a `scrollIntoView` effect on busy/result/error, matching
414
+ Site Finder / Write Spec / Writer Atlas.
415
+ - **A slow previous-writer-class response can no longer clobber the current one.** `run()` tags each request and
416
+ only the latest may write `res`/`error`/`busy` (a request-id guard), so switching writer class and clicking in
417
+ quick succession renders the current selection's result.
418
+
419
+ ## [7.3.3] - 2026-07-07 - Off-Target page copy: reflect SITE-seq, the chromatin annotation, and Cas12a in the on-page description and score guide
420
+
421
+ ### Changed
422
+ - **Off-Target page `WhatYouGet` / `ScoreGuide` copy now documents the v7.3.1 capabilities** that were shipped in
423
+ the mechanics but not the descriptions: SITE-seq is named as the fourth grounding/confirming assay; the chromatin
424
+ accessibility annotation is described (validated, HEK293T DNase GUIDE-seq AUROC 0.671, annotation-only, not a
425
+ re-ranker); and Cas12a is noted as enumeration-supported but SpCas9-scorer-scoped (the finder abstains rather than
426
+ mis-scoring). No behavior change, copy only.
427
+
428
+ ## [7.3.2] - 2026-07-07 - Digital Twin: surface the learned position-effect head (served model + resolution-aware validation state)
429
+
430
+ ### Added
431
+ - **The position-effect head surfaced on the Digital Twin page (`Twin.jsx`).** When a chromatin context is
432
+ supplied, the page shows which learned head served (human K562, Leemans 2019 / mESC TRIP), the served feature
433
+ resolution, and the `outcome_validated` flag, plus the learned log2-expression, its conformal interval and
434
+ p(silenced). An optional chromatin-context input (the head's five histone marks) enables the learned head from the
435
+ page. The human K562 head's validated regime (ρ≈0.57 at exact-site per-locus features) is distinguished from the
436
+ app's coarse 1 kb serving resolution, at which the head serves with `outcome_validated: false`.
437
+ - The `stage_h_mode` (learned vs heuristic) is shown as a pill on the predicted-outcome card.
438
+ - The human K562 position-effect head (`models/position_effect_human_k562.pkl`, Leemans 2019) and the mESC head
439
+ (`models/position_effect.pkl`) are staged into the served image so the v7.3.0 head loads at serve time (it was
440
+ wired in v7.3.0 but its artifact was not mounted); the artifacts are re-serialized in the serving image
441
+ (scikit-learn 1.9.0).
442
+
443
+ ### Changed
444
+ - The Digital Twin `WhatYouGet` / `ScoreGuide` copy documents the learned position-effect head and the exact-site vs coarse
445
+ 1 kb resolution distinction.
446
+
447
+ ## [7.3.1] - 2026-07-07 - Off-Target finder: SITE-seq in the assay recommender, chromatin-annotation surfacing, and Cas12a scoping
448
+
449
+ ### Added
450
+ - **SITE-seq in the nuclease validation-assay recommender.** `offtarget_assay.recommend_assay` now lists SITE-seq
451
+ (Cameron et al., Nat Methods 2017; DOI 10.1038/nmeth.4284) alongside GUIDE-/CHANGE-/CIRCLE-seq, completing the
452
+ four unbiased assays the mismatch-calibrated risk band is grounded on.
453
+ - **Cas12a in the Off-Target finder writer-class selector (AsCas12a).** Genome-wide enumeration supports the Cas12a
454
+ TTTV 5' PAM, but the validated CRISOT-Score and the mismatch-calibrated risk band are SpCas9-specific; the finder
455
+ therefore reports that a validated Cas12a off-target scorer is not available rather than scoring Cas12a sites with
456
+ the SpCas9 model.
457
+ - **Chromatin-accessibility annotation surfaced on the nuclease finder result**: its standalone validation
458
+ (cell-type-matched HEK293T DNase; GUIDE-seq AUROC 0.671) plus a per-site accessibility column when the
459
+ accessibility track is mounted.
460
+
461
+ ### Changed
462
+ - **The nuclease off-target `method` string and the `nominate_offtargets` capability manifest now describe the
463
+ chromatin layer precisely**, a validated annotation surfaced when the accessibility track is mounted (annotation-only,
464
+ not a re-ranker), instead of describing it unconditionally.
465
+
466
+ ### Fixed
467
+ - **The nuclease finder no longer returns a chromatin field with no context when the accessibility track is
468
+ absent.** The result now carries `chromatin_available` and a note stating the annotation is track-gated and the
469
+ CRISOT-driven ranking is unaffected, in place of a silent null.
470
+
471
+ ## [7.3.0] - 2026-07-04 - A cell-type-matched position-effect head for human K562 (Leemans 2019), replacing the non-transferring cross-species axis; served claim is resolution-aware
472
+
473
+ ### Added
474
+ - **Human K562 position-effect head.** `twin.data.position_effect` now wires the **Leemans 2019**
475
+ human K562 dataset (Cell; PMID 30982597; DOI 10.1016/j.cell.2019.03.009) with a real loader (`_load_leemans`),
476
+ per-barcode coordinates fetched from the Cell supplement Dataset S2 joined to the van Steensel feature set.
477
+ `twin.position_effect.load_human_k562_model` + cell-type routing in `predict_stage_h` serve a `PositionEffectModel`
478
+ trained on human K562 for human K562 designs, falling back to the mESC model otherwise.
479
+ - Held-out validation (chromosome-blocked 5-fold OOF; n=9,298; 5 shared histone marks): expression Spearman
480
+ **ρ ≈ 0.59**, split-conformal held-out coverage **0.90** (nominal 0.90, within tolerance). This beats the mESC
481
+ model applied cross-species, which is a null result on human K562 (held-out ρ ≈ 0.13, does not beat the
482
+ lamina/heterochromatin baseline ρ ≈ 0.39), and the trivial "avoid heterochromatin" baseline.
483
+
484
+ ### Changed
485
+ - **The v6.7 cross-cell-type transfer axis is no longer data-gated.** With a human cell type now fetched, a human
486
+ K562 design's provenance/scope reflect **human K562 supervision** instead of "single_context_supervision
487
+ (mESC), cross-cell-type transfer data-gated". `predict_stage_h` gains a `cell_type` argument (default `None`;
488
+ backward compatible; `twin.outcome` passes the cell state through).
489
+
490
+ ### Serve-time scope, resolution-aware `outcome_validated` scope
491
+ - The head's held-out validation (ρ ≈ 0.57 / +0.065 over a learned-heterochromatin baseline, CI [0.026, 0.103])
492
+ holds at **exact-site per-integration** chromatin-feature resolution. On coarse 1 kb-binned features even a
493
+ human-trained model realizes only **ρ ≈ 0.16** (P2_MATCHED_TRANSFER). `predict_stage_h` therefore stamps the
494
+ `human_K562_outcome_validated` scope **only when the caller declares exact-site features** (`feature_resolution`
495
+ / `chromatin_features_resolution`, or `chromatin_ctx.resolution` ∈ exact-site set). Otherwise, including
496
+ undeclared resolution (conservative default), it returns `outcome_validated: False` and a downgraded flag
497
+ (`human_K562_head_served_UNVALIDATED_RESOLUTION …`) naming both numbers and the requirement. The prediction is
498
+ still served; only the validation claim is withheld until the served resolution matches the validated regime.
499
+ The output gains `served_feature_resolution` and `outcome_validated` fields.
500
+ - **Deferred to v7.4:** exact-site chromatin-feature extraction *at serve time* (point-query ChIP for an arbitrary
501
+ locus), so the served path realizes the validated ρ ≈ 0.57 directly and auto-earns the `outcome_validated` scope.
502
+
503
+ ### Notes (scope)
504
+ - The cassette factorization (`f_cassette + g_context`) adds no value on Leemans' 6 similar promoters (factored
505
+ ρ 0.588 vs context-only ρ 0.592); additive suffices, reported not hidden. The served silenced (escaper/repressed)
506
+ call is promoter-driven, not a position signal. The head's validated output is steady-state **position-effect
507
+ expression in K562**, not temporal durability or other cell types.
508
+ - **Cross-species transfer is poor** (matched-source mouse↔human ρ ~0.08–0.20; P2_MATCHED_TRANSFER). The axis is
509
+ cell-type-specific; train a head per target cell type. An earlier draft over-read a feature-source-confounded
510
+ ρ 0.505 as transfer; corrected.
511
+ - The model artifact + Leemans parquet are deployment data (git-ignored under `data/`/`models/`, per the data
512
+ policy), not shipped in the wheel. Absent them, the human loader returns `None` and the position-effect head is unchanged.
513
+
514
+ ## [7.2.3] - 2026-07-02 - Off-Target: professional wording (self-contained, no external-tool comparisons) + a plain-language explainer
515
+
516
+ ### Changed
517
+ - **Removed all external-tool comparisons** ("like CRISPOR / CHOPCHOP", "CRISPOR-class", "CRISPOR-comparable") from
518
+ every off-target surface, the Off-Target page, nav, code docstrings, REST docstring, the data card, `positioning.md`,
519
+ the prereg (re-SHA-locked), paper-4 prereg, and the v7.2.0 CHANGELOG entry. The capability is now described on its
520
+ own terms: a genome-wide off-target *finder*. Given a guide/target, it enumerates and ranks the off-target sites
521
+ itself. No functional change.
522
+ - **Off-Target page now explains off-target effects in plain language**: a new top card covers *what an off-target
523
+ effect is*, *what you enter* (per writer class), and *what you get back* (ranked genome-wide sites with
524
+ coordinates + a risk band + the confirming assay), plus a "how it works" line (scan GRCh38 within the mismatch
525
+ tolerance → score → rank; heavy scan on the VM, replayed or abstain). The per-metric ScoreGuide was
526
+ reworded to match.
527
+
528
+ ## [7.2.2] - 2026-07-02 - Integrase: precise capability framing (the negative is about a method, not the biology)
529
+
530
+ A framing/presentation refinement of the v7.2.1 sealed-negative result: no science changes; the number is
531
+ unchanged and the negative stands.
532
+
533
+ ### Changed
534
+ - **Precise claim, everywhere:** what the sealed PhiC31 benchmark showed is that a specific *method* (attP
535
+ sequence-similarity scanning) is insufficient, **NOT** that pseudosites are unpredictable. The signal is real
536
+ (Chalberg's palindromic consensus; IntQuery's success on 410,776 cryptic attB), just not capturable by simple
537
+ identity. So the narrow claim is "sequence similarity is insufficient," and this negative is the
538
+ empirical justification for a learned/DMS model (the indicated next step). Sharpened in `offtarget_integrase.py`,
539
+ `phic31_recall_metrics.json`, and the data card so nothing reads as "unpredictable."
540
+ - **App presentation:** `nominate_integrase` now returns a `capability` disclosure (badge + plain microcopy). The
541
+ Off-Target page shows a badge reading **"mechanism-based · not predictive by sequence alone"** (not a bare red
542
+ flag) plus one line, *"φC31 pseudosite activity is sequence-guided but not predictable from similarity alone
543
+ (sealed benchmark, negative); confirm empirically"*, separating the grounded facts (verified att + documented
544
+ pseudo-attP with GenBank accessions) from the capability limit. A trust-building disclosure, not an alarm.
545
+
546
+ ## [7.2.1] - 2026-07-02 - PhiC31 integrase: close the serine-integrase data gap with verified data + a sealed recall benchmark (negative result)
547
+
548
+ Closes the one genuine open item from v7.2.0, the PhiC31 integrase data gap, with independently-verified,
549
+ open, citable sequences (no fabrication) and a **sealed recall benchmark whose result is reported verbatim**.
550
+
551
+ ### Added
552
+ - **PhiC31 is now encoded** (`data/curated/integrase_att.yaml`), replacing the v7.2.0 abstain-with-disclosure. All
553
+ data was **independently validated against NCBI/RCSB** (which caught two errors in the completion pack's
554
+ citations, since corrected): att from **PDB 9U2T/9U2S** ("PhiC31 integrase-attB-attP synaptic complex"; the
555
+ canonical Groth-2000 34 bp attB is present in attB53); the documented human pseudo-attP **ψA/ψC/ψD** from
556
+ **GenBank AF333429/AF333430/AF333431** (Thyagarajan 2001, *Mol Cell Biol* 21(12), PMID 11359900,
557
+ DOI `10.1128/MCB.21.12.3926-3934.2001`; chr8/16/15). Corrected DOIs: Groth 2000 `10.1073/pnas.090527097`,
558
+ Chalberg 2006 `10.1016/j.jmb.2005.11.098` (was `...11.108`).
559
+ - **Sealed PhiC31 pseudo-attP recall benchmark** (`benchmarks/offtarget/integrase/`): does attP-sequence-
560
+ similarity recover the documented pseudo-attP above length-matched GRCh38 background? **Result: NEGATIVE,
561
+ reported verbatim:** all three sites score 14 mm / 30 bp (53.3% identity), exactly the background **median**
562
+ (60.6% / 77.0% / 82.4% of random windows are as-or-more attP-similar). Sequence identity to attP is **not** a
563
+ validated PhiC31 pseudo-attP predictor; φC31 recognition depends on palindromic architecture (Chalberg 2006) /
564
+ a learned model (IntQuery), not raw identity.
565
+
566
+ ### Changed
567
+ - **Integrase status corrected: `semi_validated` → `mechanism_based_unvalidated` (with a sealed-NEGATIVE benchmark).**
568
+ The v7.2.0 "semi-validated (documented pseudosites as partial ground truth)" implied the sites validated the
569
+ method; the sealed benchmark shows they do not. This is a *stronger* outcome, a tested negative
570
+ rather than an untested claim. The verified att + documented pseudosites remain grounded facts and are surfaced
571
+ as verified known off-target loci. `nominate_integrase` PhiC31 returns the documented pseudo-attP + the sealed
572
+ benchmark; Bxb1 returns genome-wide similarity candidates carrying the same `similarity_ranking_validated: false`
573
+ caveat. The pre-registration was amended + re-SHA-locked; data card + deviations ledger updated; Off-Target page shows the
574
+ documented sites + the benchmark verdict.
575
+
576
+ ## [7.2.0] - 2026-07-01 - The off-target engine becomes a genome-wide, per-mechanism off-target finder (all 5 writer classes)
577
+
578
+ The off-target engine was a candidate *scorer*; it ranked off-target sites you supplied. An off-target *finder* instead takes
579
+ a guide/target and enumerates the genome-wide off-target sites itself. The finder closes that enumeration gap
580
+ AND applies the **correct off-target mechanism for each writer class**, each carrying a truthful per-mechanism
581
+ validation status.
582
+
583
+ ### Per-mechanism paths
584
+ - **Serine integrase** (`offtarget_integrase.py`): a genome-wide **pseudo-attP** scan, a fixed-sequence
585
+ Cas-OFFinder scan of the attP core window over GRCh38, scored by att-arm similarity. **Bxb1** is fully encoded
586
+ (FlyBase FBto0000359 / Ghosh 2003) and is highly specific. Status **semi-validated**. **PhiC31 is a disclosed
587
+ data gap** (its documented human pseudo-attP set, Chalberg 2006, could not be verified from an open source in
588
+ this build, so it abstains rather than fabricate). `data/curated/integrase_att.yaml`.
589
+ - **Bridge** (`offtarget_bridge.py`): wraps the existing DMS-scored genome scan (measured Perry-2025
590
+ specificity, held-out ranking AUROC 0.88). Status **hard-locked mechanism-based-unvalidated**; the ranker is
591
+ DMS-validated but **no genome-wide cellular off-target assay exists** for bridge recombinases, so genomic
592
+ recovery is unvalidated (stated in a no-ground-truth disclosure).
593
+ - **CAST** (`offtarget_cast.py` + `data/curated/cast_systems.yaml`), NEW: guide-directed spacer scan +
594
+ the distinctive **guide-independent untargeted-transposition** background per system (ShCAST/Type V-K high +
595
+ AT-biased; VchCAST/Type I-F >95–99% on-target), all DOI-tagged. Status **mechanism-based-unvalidated**.
596
+ - **PASTE / (ee)PASSIGE** (`offtarget_paste.py`), NEW: composes the validated nuclease finder (Cas9
597
+ nickase, pegRNA) with the semi-validated integrase pseudo-attP scan (installed att); returns both component sets
598
+ and recommends BOTH a nuclease assay and an integrase assay. Status **composite**.
599
+
600
+ ### Status labels + assay recommender + disclosures
601
+ - Every nomination carries a per-mechanism status label + the mechanism-appropriate confirm assay; `recommend_assay`
602
+ now covers CAST (transposon insertion-site seq) and PASTE (dual). `docs/cards/offtarget_data.md` documents the
603
+ per-mechanism ground-truth status: **every mechanism has either a sealed benchmark (nuclease) or an
604
+ explicit no-ground-truth / data-gap disclosure (integrase-PhiC31, bridge, CAST), never a fabricated metric.**
605
+ - Disclosed deviations from the plan (no silent substitution): `att_pwm.json` → an att-similarity model in
606
+ `integrase_att.yaml` (a per-position PWM needs aligned pseudosites that do not exist at genome scale);
607
+ `bridge_dms_specificity.parquet` → the existing measured `bridge_offtarget_profile_measured.parquet` is reused;
608
+ `known_pseudosites.parquet` → not created (Bxb1 highly specific; PhiC31 disclosed data gap).
609
+
610
+ ### Nuclease finder
611
+
612
+ ### Added
613
+ - **Genome-wide enumeration engine** (`pen_stack/wgenome/offtarget_enumerate.py`). Given a guide + enzyme,
614
+ enumerates every genomic site within the mismatch tolerance across GRCh38 via **Cas-OFFinder** (Bae, Park & Kim,
615
+ Bioinformatics 2014, `10.1093/bioinformatics/btu048`), returning coordinates, strand, matched sequence, and
616
+ mismatch count. Supports SpCas9 (NGG), SaCas9 (NNGRRT), and Cas12a (TTTV, 5' PAM). A full scan is heavy, so it
617
+ runs **only on the VM** (`casoffinder:tools` Docker image, `docker/casoffinder.Dockerfile`); the live app
618
+ **replays a committed coordinate cache** for the canonical guides or **abstains** for a novel one
619
+ (never fabricates sites), the same replay-or-abstain pattern as the heavy structure oracles. The enumerated
620
+ coordinates are facts from the public GRCh38 assembly (no license restriction), so the cache is committed
621
+ (`data/offtarget/enumerated_cache.parquet`, 8 canonical guides, 40,268 sites).
622
+ - **Nuclease off-target FINDER** (`pen_stack/wgenome/offtarget_nuclease.py`): chains enumeration into the
623
+ existing, validated scorer, real CRISOT-Score → mismatch-calibrated risk band → chromatin annotation, so a
624
+ guide returns the genome-wide ranked off-target set *with coordinates*. Scoring is unchanged from v6.10 (still
625
+ validated: CRISOT beats homology on four unbiased assays); v2 adds the enumeration front end.
626
+ - **The enumeration gate passed**: enumeration recovers **100%** of EMX1's documented GUIDE-seq off-targets within the ≤5-mm
627
+ tolerance (all 16 validated-active sites, which are all ≤4 mm; the higher-mismatch fixture rows are inactive
628
+ negatives). The on-target is recovered at chr2:72,933,852. `tests/unit/test_offtarget_enumeration.py`.
629
+ - **Prereg** `prereg/ws_offtarget2.yaml` (SHA-locked): the mechanism taxonomy, per-enzyme enumeration parameters,
630
+ the truthful per-mechanism status-label rules (validated / semi-validated / mechanism-based-unvalidated), and
631
+ the acceptance gates.
632
+ - REST: `POST /offtarget` is now a **finder by default** for a nuclease guide with no supplied `candidate_sites`
633
+ (accepts `enzyme`, `max_mismatch`); `GET /offtarget/enumerated` lists the cached guides. The web **Off-Target**
634
+ page is rebuilt as a finder (guide in → genome-wide ranked off-targets with coordinates), with the scorer→finder
635
+ explanation and the VM/cache architecture stated.
636
+
637
+ ### Unchanged / backward compatible
638
+ - Supplying `candidate_sites` keeps the v6.10 score-my-candidates path. The integrase (pseudo-attB sequence scan),
639
+ bridge (Perry-DMS), chromatin annotation, and validation-assay recommender are unchanged. Nomination remains a
640
+ candidate, never a clearance.
641
+
642
+ ## [7.1.8] - 2026-06-30 - Writer immunogenicity moves to the Writer Atlas; SpCas9 removed from the writer options
643
+
644
+ ### Changed
645
+ - **The writer enzyme is no longer chosen in the Design Studio; its immunogenicity moves to the Writer Atlas, where
646
+ writers belong.** The Design Studio's writer dropdown existed only to feed the two writer-as-antigen immune axes
647
+ (MHC-II + ADA); that duplicated the dedicated Writer Atlas page. Now:
648
+ - The **Writer enzyme dropdown is removed** from `DesignForm` (and `DEFAULT_DESIGN`). The Design Studio's "Profile
649
+ immune & delivery" action correctly scopes to the **delivery/vehicle** axes (genotoxicity, CD8 capsid, innate,
650
+ pre-existing NAb, anti-PEG). `ImmuneProfileCard` hides the writer axes by default (`hideWriterAxes`).
651
+ - A new **Writer immunogenicity** card on the **Writer Atlas** surfaces each genome writer's MHC-II/CD4 epitope
652
+ load + ADA risk + human self-match, read from the **committed NetMHCIIpan-4.0 cache, not recomputed**
653
+ (`GET /api/writer/immune`, `immune_profile.writer_immunogenicity_table()`).
654
+ - **SpCas9 is removed** from the writer set: it is a nuclease/editor, not a large-cargo genome writer. The Writer
655
+ Atlas immunogenicity covers the actual writers, **Bxb1** (serine integrase) and **ISCro4** (bridge recombinase);
656
+ the Cas9 nuclease and the human self control are excluded. (The engine retains SpCas9 in its cache for other
657
+ uses; only the user-facing writer list drops it.)
658
+ - The engine still returns the `mhc2_writer` / `ada_writer` axes from `immune_profile()` for API/MCP callers that
659
+ pass a `writer_family`; only the web UI moved the writer profiling to the Writer Atlas. No data was recomputed.
660
+
661
+ ### Added
662
+ - `test_immune_profile.py`: `test_writer_immunogenicity_table_for_the_writer_atlas` (covers Bxb1 + ISCro4 from the
663
+ cache; SpCas9 and the self control excluded; grounded MHC-II + ADA values).
664
+
665
+ ## [7.1.7] - 2026-06-30 - Administration context (in-vivo / ex-vivo) now drives the immune profile
666
+
667
+ ### Fixed
668
+ - **The in-vivo / ex-vivo "Context" toggle had no effect on the immune profile.** It already drove the Generate
669
+ vehicle sweep (route-compatible vehicles) and the Verify germline-prohibition legality rule, but `immune_profile()`
670
+ ignored it, so the per-axis immune profile was identical for in-vivo and ex-vivo. It now applies a documented,
671
+ grounded administration modifier (`immune_profile._administration_modifier` / `_apply_administration`):
672
+ - **Pre-existing NAb is muted to "no barrier" (1.0) ex vivo.** Ex-vivo delivery (cells transduced in a dish and
673
+ washed before transplant) never exposes the vector to the patient's circulating antibodies, so pre-existing
674
+ anti-vector NAb does not gate eligibility; the eligibility fraction is 1.0 regardless of titer. The original
675
+ seroprevalence value is preserved (`pre_admin_value`) and the muting is explained in the axis note. This is the
676
+ same in-vivo/ex-vivo distinction the v5.1 `delivery_immunology` profile already encodes (`computed_ex_vivo_muted`).
677
+ - **CD8 capsid is flagged muted ex vivo** (systemic anti-capsid response minimal), but its intrinsic presentability
678
+ value is kept; transduced cells can still present capsid epitopes, a real residual concern, so no number is
679
+ fabricated.
680
+ - **Genotoxicity, innate, anti-PEG and the writer axes are unchanged** by administration context (insertional risk
681
+ and cargo/writer immunogenicity are intrinsic, not a function of circulating-antibody exposure).
682
+ - A `administration_modifier` block (parallel to the existing `route_modifier`) is added to the profile; the
683
+ `ImmuneProfileCard` shows an in-vivo/ex-vivo chip, a per-axis "ex-vivo muted" badge with the reason, and the
684
+ administration effect line. In-vivo and unspecified contexts leave every axis untouched (backward compatible).
685
+
686
+ ### Added
687
+ - `test_immune_profile.py`: `test_administration_context_mutes_vector_facing_axes_ex_vivo` (ex-vivo mutes pre-existing
688
+ NAb to 1.0 and flags CD8; in-vivo/unspecified are unchanged; genotoxicity is never muted by administration).
689
+
690
+ ## [7.1.6] - 2026-06-30 - Immune axes wired end-to-end + Delivery folded into Design Studio
691
+
692
+ ### Fixed
693
+ - **Four immune-risk axes were unreachable from the web UI and showed as out-of-scope**: innate sensing, anti-PEG,
694
+ and the writer-as-antigen MHC-II + ADA axes abstained on every web design because the design form never collected
695
+ their inputs (the engine computed them correctly when called directly; this was a wiring gap, not a model gap):
696
+ - **`innate`** needs a cargo sequence. The design form now has an optional **Cargo sequence** field; the cargo
697
+ nucleic-acid form (DNA -> CpG/TLR9, mRNA -> U-content + dsRNA, RNP -> transient) is derived from the vehicle's
698
+ defining cargo class (`immune_profile._vehicle_cargo_form`) so the axis computes for any caller (chat / MCP /
699
+ REST) once a sequence is supplied. Empty sequence still abstains; an explicit `cargo_form` still wins. No
700
+ fabrication: an unknown vehicle returns no form and the axis abstains.
701
+ - **`mhc2_writer` / `ada_writer`** need a writer protein. The design form now has a **Writer enzyme** selector
702
+ (the three grounded families with a bundled UniProt sequence + committed NetMHCIIpan-4.0 cache: serine integrase
703
+ Bxb1, bridge recombinase ISCro4, Cas9 SpCas9); `DEFAULT_DESIGN` ships a serine integrase so the two axes populate
704
+ out of the box. No writer selected -> the two axes abstain (never fabricated).
705
+ - **`anti_peg`** applies only to PEGylated vehicles; selecting `lnp_mrna` now surfaces it (with an inline hint),
706
+ and it correctly abstains for non-PEG vehicles.
707
+ - `ImmuneProfileCard` now shows the **writer-as-antigen** summary (representative writer, foreign/self, dominant
708
+ antigen) so the writer axes are self-explanatory.
709
+
710
+ ### Changed
711
+ - **Delivery & Immunity folded into Design Studio.** The standalone Delivery page duplicated the same design form and
712
+ immune profile, so it is merged into Design Studio as a third action - **Profile immune & delivery** - with the
713
+ per-axis immune ScoreGuide, the vehicle quick-switch, the `ImmuneProfileCard` and the scope ledger. Design Studio is
714
+ now one design surface with three actions (Verify / Generate / Profile immune & delivery). `/delivery` redirects to
715
+ `/design`; the nav drops the separate item; old links keep working.
716
+
717
+ ### Added
718
+ - `test_immune_profile.py`: tests for the vehicle-derived cargo form (innate computes for a DNA vehicle with a cargo
719
+ sequence; abstains without one; explicit form overrides) and for the writer axes computing when a grounded writer
720
+ is supplied (and abstaining otherwise).
721
+
722
+ ## [7.1.5] - 2026-06-29 - Chromosome field: validation, gene concordance, context
723
+
724
+ ### Added
725
+ - The `chrom` design field was a free-text pass-through with no validation and no downstream effect. It is now
726
+ meaningful (`pen_stack/planner/chromosome.py`):
727
+ - **Validation**: the web form's Chromosome input is a controlled dropdown (chr1–chr22, chrX, chrY, chrM), so
728
+ an impossible value like `chrZZZ` can no longer be entered; `canonical_chromosome()` normalises/validates on
729
+ the backend (`chrX`/`X`/`x`, `chr1`/`1`, `chrM`/`chrMT`/`MT`, `23`→X, `24`→Y; rejects the rest).
730
+ - **Gene/chromosome concordance**: `verify()` now flags `chromosome_mismatch` when the entered chromosome does
731
+ not match the named gene's canonical location (e.g. *BRCA1 is on chr17, not chr1*), `chromosome_invalid` for a
732
+ non-standard value, and `chromosome_unverifiable` for an unknown gene. The web form shows the warning inline
733
+ with a one-click fix, driven by the new `GET /api/gene/location` endpoint. This closes the silent-mismatch gap.
734
+ - **Chromosome context**: `chromosome_context()` adds grounded, chromosome-driven advisories surfaced as scope
735
+ flags: **chrM** is not addressable by nuclear genome-writing tools (mtDNA needs DdCBE/TALED, out of scope),
736
+ **chrY** is male-specific with ampliconic repeats, **chrX** is hemizygous in 46,XY vs X-inactivated in 46,XX.
737
+ - The Design Studio **cell-type dropdown now shows writability-atlas coverage** (from `/api/celltypes`): K562 /
738
+ HepG2 / HSPC are labelled measured (full / full / partial), while h1_hesc / iPSC / CD8 T / PBMC are labelled
739
+ "no atlas", so a data-gated cell type is no longer silently indistinguishable from a measured one (the same
740
+ disclosure principle as the chromosome field). The 7 cell types are unchanged and already matched the backend.
741
+
742
+ ### Note (scoping)
743
+ - The free-text chromosome does **not** move the scored locus: per-locus safety / durability / accessibility /
744
+ off-target are indexed by the gene's *resolved genomic coordinates* via the writability atlas, so a bare
745
+ chromosome string with no position cannot refine them. Rather than fabricate a per-chromosome score delta, the
746
+ field's grounded effect is validation + gene concordance (ensuring the score is read for the right locus, and
747
+ flagging when the entered chromosome disagrees with the gene) + the chromosome-context advisories above.
748
+
749
+ ## [7.1.4] - 2026-06-29 - Germline-prohibition legality rule
750
+
751
+ ### Added
752
+ - **Compliance rule category + `compliance.germline_prohibition` (hard_reject).** A heritable / germline edit
753
+ previously passed the Legality axis because no rule existed for it (the only germline handling was a
754
+ known-unknown scope matcher for *questions*, not *designs*). The new rule fails legality for: a reproductive
755
+ germline target cell (embryo / zygote / oocyte / sperm / gamete - unconditional), a declared reproductive-use
756
+ intent (gametes / assisted reproduction / implantation / "for reproduction"), a declared heritable intent
757
+ (germline / heritable / "transmitted to offspring"), or a germline-competent cell type (hESC / iPSC) edited in a
758
+ heritable context (in vivo, or a reproductive/heritable intent). It is cited (Lander et al. 2019 moratorium,
759
+ `10.1038/d41586-019-00726-5`; US National Academies 2017, `10.17226/24623`) and emits a proof-object repair hint
760
+ (restrict to somatic / ex-vivo editing). It is a scope-of-use legality bound, reported on the LEGALITY axis,
761
+ separate from the Biosecurity axis. The category is wired into every write type; `rule_spec.json` is now 11 rules.
762
+ - **Paraphrase + negation robustness** (red-team-hardened). The free-text intent match is NEGATION-aware
763
+ (negated-span detection), so a somatic design that explicitly says "somatic, not germline" / "no germline
764
+ transmission" / "NOT for reproduction or implantation" is not false-flagged, while paraphrased reproductive
765
+ intent (e.g. "generate gametes for assisted reproduction", "embryo intended for uterine transfer") with no
766
+ literal "germline"/"heritable" word still fails. Validated against a 30-design adversarial set: 0 evasions,
767
+ 0 false positives.
768
+
769
+ ### Fixed
770
+ - The Verify page's Legality description claimed it adjudicates "jurisdiction / list-agent / IP", which it does
771
+ not. Corrected to describe the actual legality axis (physical feasibility + germline scope-of-use compliance),
772
+ noting that dual-use hazard is the separate Biosecurity axis.
773
+
774
+ ## [7.1.3] - 2026-06-26 - Designer correctness: Guardian biosecurity + calibrated confidence
775
+
776
+ ### Fixed
777
+ - **CRITICAL (Designer / Guardian biosecurity):** Hazardous cargo functions (e.g. furin-cleavage viral
778
+ tropism-enhancement, dominant-negative tumor-suppressor ablation) passed the Designer as "Safety: Clear" with
779
+ full survivor tables. Several root causes, all fixed:
780
+ - The hazard registry (`configs/safety/hazard_registry.yaml`) had **no signatures** for engineered viral tropism
781
+ enhancement or oncogenic tumor-suppressor ablation. Added `FUNC-VIRAL-TROPISM-ENHANCE` (furin cleavage /
782
+ receptor-binding / tropism, high severity) and `FUNC-ONCOGENIC-SUPPRESSOR` (dominant-negative TP53 / RB / PTEN,
783
+ apoptosis-checkpoint ablation, high severity), both DURC / HHS-P3CO categories.
784
+ - **Oncogenic-manipulation PATTERN screen** (`oncogenic_manipulation` in the registry +
785
+ `HazardRegistry.oncogenic_flags`): a flat keyword list is brittle to paraphrase; a red-team pass found the
786
+ Guardian caught only **1/8** mechanism/synonym phrasings ("R175H p53 abolishing transactivation", "PTEN
787
+ knockout", "RAS G12D constitutive activation", "hTERT immortalization", "APC frameshift", "EGFR
788
+ ligand-independent activation", "NF1+BAX/BAK knockout"). The pattern screen flags the *combination*
789
+ `(tumor-suppressor + disruptive verb)` OR `(oncogene + activating signature)` OR `immortalization`, which
790
+ catches **8/8** while the deliberate asymmetry spares therapy with **no allow-list**: restoring a suppressor or
791
+ silencing an oncogene matches neither, so "p53 correction to restore apoptosis", "TRAC/CCR5 knockout",
792
+ "knock-down of mutant KRAS" stay clear (**11/11** benign). Disposition is escalate (dual-use → human review).
793
+ - **Keyword matcher hardened** (`_kw_match`): a plain substring test made the ricin abbreviation `"rip"` fire
794
+ inside **"transc-rip-tion"** (a word in almost every editing design → benign cassettes false-refused as ricin),
795
+ and let a hyphenated `"furin-cleavage"` slip past the space-form keyword. Matching is now separator-insensitive
796
+ (`-`/`_`/space unified) and word-boundary anchored, fixing both the false positive and the evasion.
797
+ - The goal-based candidate path (`pen_stack/design/space.py::candidate_space`) **dropped** the goal's
798
+ `cargo_function`, so the Guardian in `verify()` screened nothing. It is now propagated onto every swept
799
+ candidate. The `/generate` endpoint additionally screens the goal's cargo function FIRST and returns an explicit
800
+ biosecurity refusal (`refused: true` + the safety verdict) so an empty table is correctly attributed to a
801
+ refusal, not a silent "no candidates".
802
+ - **CRITICAL (Designer / calibration):** Confidence was a constant `1.00 · [0.56, 0.71]` for every input because the
803
+ page hardcoded fake planner scores (0.7 / 0.6 / 0.5) on each candidate. The page now submits the design GOAL and
804
+ the engine plans real writable sites with grounded per-locus safety / durability / writer-activity, so the
805
+ confidence band is genuinely calibrated (it differs by locus/vehicle, e.g. F9 → `[0.866, 0.972]`, and is absent
806
+ for a refused design). `web/src/pages/Designer.jsx` rewritten to send a goal and render the refused / empty /
807
+ survivor states distinctly.
808
+ - **Designer (cell types without a measured atlas):** a goal in a cell type with no writability atlas (cd8_t /
809
+ pbmc / h1_hesc / ipsc) returned an empty table, because the planner-backed `candidate_space` needs `plan_write`.
810
+ `generate_designs` now falls back to `space.vehicle_sweep(goal)`: it sweeps the capacity-compatible vehicles,
811
+ carries `cargo_function` (the Guardian still screens), runs full legality + biosecurity discrimination, and
812
+ ABSTAINS on the calibrated confidence (no fabricated band), surfaced as "abstained, no measured atlas for this
813
+ cell type". `candidate_space` still returns `[]` without the atlas; `generate_designs(candidates=[])` still
814
+ returns `[]`.
815
+ - **Designer (administration context):** the vehicle sweep now filters by the goal's `in_vivo` flag using the
816
+ curated `in_vivo` / `ex_vivo` route flags in `configs/delivery_vehicles.yaml` (an ex-vivo goal keeps
817
+ lentivirus / electroporation / eVLP; an in-vivo goal keeps AAV / LNP / HDAd / HSV / eVLP). Grounded from the
818
+ curated palette, not a clinical claim; `in_vivo=None` keeps all (existing callers/tests unchanged).
819
+
820
+ ## [7.1.2] - 2026-06-25 - Chat response latency fix
821
+
822
+ ### Fixed
823
+ - Chat response time was unnecessarily high because every General-lane request paid for an Ollama embedding
824
+ round-trip on the query side, and the LLM call ran with a generous 150 s timeout / 450-token cap suited to the
825
+ engine-grounded design lane, not a textbook answer. Three minimal changes, no behaviour change for the grounded
826
+ lanes:
827
+ - `pen_stack/rag/embed.py` adds an LRU-cached `embed_query()` (256 entries) so a repeated phrasing skips the
828
+ embedder; `pen_stack/rag/retrieve.py` uses it.
829
+ - `pen_stack/web/llm_provider.py` now accepts `kind="general"`, which selects `PEN_STACK_LLM_TIMEOUT_GENERAL`
830
+ (45 s default, was 150 s) and `OLLAMA_NUM_PREDICT_GENERAL` / `NEMOTRON_MAX_TOKENS_GENERAL` (280 / 400, was
831
+ 450 / 700). The default-kind path used by the engine-grounded design / explain / meta lanes is unchanged
832
+ (`PEN_STACK_LLM_TIMEOUT` default lowered 150 → 90).
833
+ - The General-lane and RAG cited-answer callers (`pen_stack/rag/ground.py`, `pen_stack/web/llm.py`) now pass
834
+ `kind="general"`.
835
+ - No grounding-guard change; the LLM stays non-load-bearing and the per-lane provenance labels are unchanged.
836
+
837
+ ## [7.1.1] - 2026-06-24 - Chat General-lane helpfulness fix + benchmark-validity correction
838
+
839
+ ### Fixed
840
+ - The General lane over-abstained: it declined simple/social ("hi") and general-knowledge ("what is DNA")
841
+ questions because P-WS1 made corpus retrieval a GATE on the whole lane. Retrieval is now **additive**
842
+ (`pen_stack/rag/ground.py`): the lane ANSWERS general + social questions, clearly labelled
843
+ "general - not PEN-STACK-verified" (a labelled general answer is not a fabrication); a corpus hit
844
+ upgrades to "literature-cited"; abstention is reserved for a SPECIFIC unsourceable empirical claim. The "general"
845
+ provenance chip is restored in the web chat.
846
+
847
+ ### Changed
848
+ - Benchmark-validity correction: the head-to-head headline moves from "answers-without-grounding" (which rewarded
849
+ over-abstention) to the **false-grounding rate** (a non-engine fact presented as a PEN-STACK result; 0.0 by
850
+ construction). Abstention is re-scoped to specific unsourceable empirical claims; the routing/grounding/safety
851
+ sets now include positive general + social cases that require a helpful, labelled answer (a regression guard).
852
+ `prereg/ws_penchat.yaml` amended + re-locked accordingly.
853
+
854
+ ## [7.1.0] - 2026-06-24 - The grounded conversational chat system
855
+
856
+ Consolidates the four-lane chat with RAG into a fully-grounded, provenance-partitioned
857
+ conversational agent: every surfaced fact is engine-computed or retrieved-and-cited, no claim originates from
858
+ model weights, and the property is MEASURED, not asserted. The LLM is a swappable, non-load-bearing narrator.
859
+
860
+ ### Added
861
+ - **Grounded General lane (RAG)** (`pen_stack/rag/{corpus,embed,retrieve,ground}.py`). The general lane no
862
+ longer answers from unsourced trained knowledge: it retrieves over a provenance-tagged corpus
863
+ (`data/rag_corpus.parquet`, built only from real DOI-backed repo content) with a committed embedding matrix
864
+ (`nomic-embed-text` via Ollama; exact cosine, no FAISS at this scale) and a deterministic lexical fallback,
865
+ answers under citation-or-silence, and **abstains** below a retrieval-confidence threshold. General answers are
866
+ labelled `literature-cited` or `abstained`, never a PEN-STACK-computed result.
867
+ - **Swappable LLM provider abstraction** (`pen_stack/web/llm_provider.py`): one interface over local Ollama / cloud
868
+ Nemotron; the grounded result (lane, provenance, sources, numbers) is invariant to the provider.
869
+ - **Lane + provenance memory**: a follow-up to a grounded answer stays grounded.
870
+ - **Evaluation suite** measuring the no-fabrication claim: `benchmarks/chat_{routing,grounding,safety,headtohead}`
871
+ (routing-safety 0.0, citation coverage 1.0, 0 unsupported claims, false-grounding 0.0, dual-use refusal 1.0,
872
+ injection-hold 1.0). Pre-registered + SHA-locked in `prereg/ws_penchat.yaml`.
873
+ - The chat is registered as a capability (`chat_answer`, `fabricates: False`); provenance / citation / abstention /
874
+ refusal chips in the web chat.
875
+
876
+ ### Changed
877
+ - The pre-route biosecurity screen now escalates a build/express intent over any flagged dual-use hazard term even
878
+ when the specific agent is not catalogued; the router was made conservative so a write request never leaks to the
879
+ ungrounded lane.
880
+
881
+ ## [7.0.0] - 2026-06-22 - Closed loop: a biosecurity-gated, Level-3 self-driving-lab engine
882
+
883
+ The capstone. Turns the in-silico closed loop into a genome-writing-specific, biosecurity-gated, autonomy-bounded
884
+ (Level 3) self-driving-lab engine: a cloud-lab connector, a benchmark of the experiment designer against the
885
+ public optimizers, and a validation-campaign engine that points active learning at the measurements which would
886
+ earn the program's first outcome-validated axis. It consumes the WriteSpec and pairs with the biosecurity gate.
887
+ Full autonomy is not claimed; the wet run is the named bottleneck.
888
+
889
+ ### Added
890
+ - **Cloud-lab connector** (`pen_stack/build/cloudlab.py`). `submit_gated` bridges the build interface to a cloud
891
+ lab. The biosecurity gate runs BEFORE any submission: a flagged or illegal design raises and emits no protocol
892
+ (a ricin design is refused), returning a structured refusal an agent can branch on; a cleared design returns a
893
+ mock / dry-run job receipt. A returned readout is admitted only through an explicit human-in-control gate.
894
+ - **SDL-brain benchmark** (`pen_stack/active/brains.py`). Benchmarks the EIG/VOI experiment designer against the
895
+ public self-driving-lab optimizers BayBE (Apache-2.0) and Atlas on a shared acquisition task, reported verbatim
896
+ with both cited. The designer shows a positive mean information-gain advantage over random whose bootstrap CI is
897
+ rep-sensitive and includes 0 at higher rep counts; reported as not-CI-significant, not hidden.
898
+ - **Validation-campaign engine** (`pen_stack/active/campaign.py`). Orders the candidate
899
+ (cassette x locus x cell type) expression measurements by expected information gain, names the
900
+ `validate.calibrate_axis` gate they would flip, and emits an executable, cloud-lab-submittable campaign spec.
901
+ The campaign measures independent data, never the model's own outputs.
902
+ - **Loop-Bench** (`benchmarks/loop/`) reporting the three gates, and surfaces: REST `GET /api/campaign`,
903
+ `POST /api/cloudlab`, `GET /api/brains`; MCP `validation_campaign`, `cloudlab_submit`; `docs/closed_loop.md`.
904
+
905
+ ### Notes
906
+ - The loop is Level 3 (human in control); Level 4-5 is not claimed. The biosecurity gate is necessary, not
907
+ sufficient (the full sequence screen is the downstream BioFirewall).
908
+ - A real wet run, and thus the first outcome-validated axis, needs a cloud-lab partner and budget; the connector
909
+ and the executable campaign are the mechanism, the partner is the bottleneck, surfaced not hidden.
910
+
911
+ ## [6.14.0] - 2026-06-22 - WriteSpec: a typed, ontology-backed intent layer with a grounded extractor and a feasibility check
912
+
913
+ Replaces the keyword parser with a typed, machine-checkable genome-writing request (an SBOL3 profile), a grounded
914
+ prose-to-spec extractor that labels every inference and never fabricates intent, and a feasibility check. This is
915
+ the agentic front-end: one contract the whole stack consumes. A WriteSpec is a request, not a claim.
916
+
917
+ ### Added
918
+ - **The WriteRequest type** (`pen_stack/spec/writespec.py`, `schemas/writespec.json`). A typed model carrying the
919
+ write semantics (write-type, cargo with Sequence-Ontology roles, target gene/locus/att-site/phenotype, cell
920
+ type, constraints) plus a per-field provenance map (explicit / inferred / user / unresolved). Lossless JSON
921
+ round-trip; SBOL3 round-trip via the real `sbol3` library (the `[spec]` extra; native Components + SO roles for
922
+ interoperability); GenBank export for a cargo with a sequence; and `to_legacy_design`, the adapter that lets
923
+ every existing stage consume a WriteRequest without a rewrite.
924
+ - **Vocabulary resolvers** (`pen_stack/spec/resolvers/`). Free text to canonical id: HGNC genes (atlas-grounded),
925
+ Cellosaurus / Cell Ontology cell types, Sequence Ontology feature roles, MONDO phenotypes, ChEBI molecules,
926
+ GRCh38 coordinates. Every curated id was verified against the live ontology services before commit; an
927
+ unresolved term stays null, never invented.
928
+ - **Grounded extractor + clarifying-question planner** (`pen_stack/spec/extract.py`, `clarify.py`). A
929
+ deterministic backbone (so the benchmark is reproducible) that labels every inferred field, asks a clarifying
930
+ question for anything underspecified or ambiguous, and keeps unresolved terms null.
931
+ - **Feasibility check** (`pen_stack/spec/satisfy.py`). Wraps reachability (the atlas), deliverability (the
932
+ delivery recommender), and legality (the verification proof object) into feasible / infeasible plus named
933
+ blocking constraints and repair hints; feasibility is necessary, not sufficient (not efficacy).
934
+ - **WriteSpec-Bench** (`benchmarks/writespec/`). The first prose-to-write-spec corpus, grounded in real
935
+ experiments, with an ambiguity subset and a sealed held-out. Reported verbatim: sealed-test structural fidelity
936
+ 1.0 and value accuracy 0.96 versus a 0.46 keyword-dict baseline; inferred-field labelling recall 1.0.
937
+ - **Surfaces**: REST `POST /api/writespec`, MCP `writespec_parse`, the manifest tool, the web "Describe a Write"
938
+ builder page, and `docs/writespec_profile.md` + `docs/writespec_bench.md`.
939
+
940
+ ### Notes
941
+ - Feasibility rules out unreachable / undeliverable / illegal, not whether the write will work.
942
+ - The extractor backbone is deterministic; an LLM pass is optional and adds no ground truth (it may only propose
943
+ values that still pass the resolvers).
944
+
945
+ ## [6.13.0] - 2026-06-22 - Oracle mesh: binding-affinity dimension, per-oracle reliability, disagreement-to-uncertainty
946
+
947
+ Hardens the foundation-model oracle mesh under one result contract. Adds a binding-affinity dimension
948
+ (Boltz-2), surfaces each oracle's published reliability reported verbatim from public benchmarks, and makes
949
+ cross-oracle disagreement widen the reported interval. Every oracle output stays a candidate, never ground
950
+ truth.
951
+
952
+ ### Added
953
+ - **Binding-affinity oracle** (`pen_stack/oracles/affinity.py`). Wraps the Boltz-2 protein-ligand affinity head
954
+ (MIT, `10.1101/2025.06.14.659707`): a binder probability and a predicted affinity value with native
955
+ uncertainty taken from the model's own outputs. The head is protein-small-molecule only, so protein-protein
956
+ and protein-DNA pairs are returned as out-of-scope (extrapolating). The backend runs off the request path and
957
+ is cached; an uncached request defers (cache-or-abstain) rather than blocking or fabricating. A grounded,
958
+ in-domain example is committed: 4-hydroxytamoxifen binding the ERT2 ligand-binding domain (the inducible-writer
959
+ switch), predicted as a high-confidence binder (binder probability 0.99, complex pLDDT 0.94).
960
+ - **Per-oracle reliability registry** (`pen_stack/oracles/reliability.py`, `configs/oracles/reliability.yaml`).
961
+ Each oracle's published benchmark accuracy, reported verbatim with citation: the Boltz-2 affinity head's
962
+ FEP+ Pearson r of about 0.62 (paper-reported) is the verified anchor. These are the wrapped models' published
963
+ numbers, not a claim about this stack's accuracy and not re-computed; where a verbatim score was not verified
964
+ the value is left null with the cited benchmark as the pointer.
965
+ - **Disagreement to uncertainty.** Cross-oracle disagreement widens the reported interval (native uncertainty
966
+ plus half the cross-oracle spread); a check confirms the widening is monotonic in the spread.
967
+ - **Held-oracle runner** (`pen_stack/oracles/structure_run.py`) for the structure oracles over writer-substrate
968
+ and att-site complexes: off the request path, cache-or-abstain.
969
+ - **Oracle-Bench** (`benchmarks/oracle/`) reporting the three gates, and surfaces: `GET /api/oracles` extended
970
+ with reliability and the disagreement check, `POST /api/oracle/affinity`, MCP `oracle_query`, the manifest
971
+ `oracle_query` tool, the web Oracle Mesh page, and `docs/oracle_mesh.md`.
972
+
973
+ ### Notes
974
+ - Affinity predictions are candidates with native uncertainty, not measured binding constants; reliability is
975
+ surfaced so a confident-looking value is not over-trusted.
976
+ - The structure oracles over full complexes (AlphaFold3 / Boltz-2 / Chai-1 / Protenix) remain held: run
977
+ separately on GPU or cloud and cached, never inline on the request path.
978
+
979
+ ## [6.12.0] - 2026-06-21 - Verification service: published rule spec, proof object, standards-aligned biosecurity
980
+
981
+ Hardens `verify(design)` into a formal verification service. The rule base becomes a published, citable spec;
982
+ `verify_proof()` returns a repair-oriented proof object an agent can fix a failed design from; and the
983
+ biosecurity gate is mapped to the community synthesis-screening standards.
984
+
985
+ ### Added
986
+ - **Published rule spec** (`pen_stack/rules/spec.py`, `benchmarks/verify/rule_spec.json`, `docs/rule_spec.md`).
987
+ The rule base exports as a machine-readable, citable document. A parity check confirms the exported spec
988
+ round-trips to the exact ruleset the solver loads (0 mismatches), every rule names a registered evaluator,
989
+ and every rule carries a DOI or a note.
990
+ - **Repair-oriented proof object** (`pen_stack/verify/proof.py`). `verify_proof(design)` returns three axes,
991
+ legality, confidence and biosecurity, reported separately, each with a status, the rule or signature that
992
+ fired, evidence, and a repair hint; the collapsed verdict is `None`. `repair_from_proof` fixes a
993
+ failed-on-legality design using only the proof object and re-verifies it. Biosecurity hazards are
994
+ acknowledged and routed to human review, never auto-repaired.
995
+ - **Biosecurity standards alignment** (`pen_stack/safety/standards.py`). Maps the Guardian screen kinds and
996
+ decisions onto the IBBIS Common Mechanism categories and `ScreenStatus` (Pass / Warning / Flag) and onto
997
+ SecureDNA's pass/deny outcome, with a concordance report (8/8 concordant on the labelled probe set).
998
+ References: Common Mechanism (Wheeler et al. 2024, `10.1089/apb.2023.0034`); SecureDNA (`arXiv:2403.14023`).
999
+ - **Verify-Bench** (`benchmarks/verify/`) reporting the three gates, and surfaces: REST `POST /api/verify/proof`,
1000
+ MCP `verify_proof`, manifest tool `verify_proof`, the web Verify page (per-axis green/amber/red with the
1001
+ violated rule, its citation, and the suggested fix), and `docs/verify_service.md`.
1002
+
1003
+ ### Notes
1004
+ - The verdict covers legality, feasibility and biosecurity, not efficacy (efficacy stays a downstream
1005
+ prediction with its own uncertainty). The biosecurity hook is the in-design gate; the full sequence-screening
1006
+ pipeline is BioFirewall, and the standard alignment is a concordance, not a certification.
1007
+
1008
+ ## [6.11.0] - 2026-06-20 - Cross-modality deliverability and a learned capsid-fitness model
1009
+
1010
+ Delivery moves from an 8-vehicle rule palette to a cross-modality recommender. It adds a learned,
1011
+ benchmarked AAV capsid-fitness model, a serotype-to-tissue tropism prior grounded in approved therapies, and an
1012
+ immune-coupled dose tradeoff, without fabricating tropism. All datasets were independently verified.
1013
+
1014
+ ### Added
1015
+ - **Learned AAV capsid-fitness on FLIP-AAV** (`pen_stack/planner/delivery_predict.py`, `scripts/build_capsid_fitness.py`,
1016
+ `benchmarks/delivery/`). Trained on the FLIP-AAV benchmark (Dallago 2021; Bryant 2021 packaging fitness,
1017
+ `10.1038/s41587-020-00793-4`; Ogden 2019 `10.1126/science.aaw2900`). It beats a mutation-burden baseline on
1018
+ both held-out splits: `sampled` Spearman 0.920 vs 0.522 (CI [0.387, 0.411]); `mut_des`
1019
+ (mutant to designed) 0.814 vs 0.752 (CI [0.061, 0.064]). The 217 MB/split FLIP data stays on the VM; the derived
1020
+ metrics and the reproducible build script are committed. The ~3 MB model itself is gitignored, regenerated via
1021
+ `scripts/build_capsid_fitness.py` and mounted into the deployed app (like `position_effect.pkl`); the axis abstains
1022
+ gracefully when absent. Predicted fitness is a candidate for the measured packaging axis, not in-vivo tropism.
1023
+ - **Serotype-to-tissue tropism priors** (`configs/aav_serotype_tropism.yaml`) from approved AAV therapies (AAV9 to CNS,
1024
+ AAVrh74 to skeletal muscle vs AAVRh74var to liver: different capsids, kept separate; AAV5 to liver; AAV2 to retina/
1025
+ putamen via local injection). This is a grounded prior for an approved serotype and a known-unknown (abstain) for a novel
1026
+ capsid. Casgevy/Lyfgenia carry no serotype prior (not-AAV controls).
1027
+ - **Immune-coupled dose tradeoff** (`pen_stack/planner/delivery_immune.py`) fuses deliverability with the
1028
+ immune profile and surfaces dose vs immunogenicity per vehicle as a vector (`collapsed_score=None`, never fused).
1029
+ - **Verify-gated generative capsids** (`pen_stack/design/capsid_generate.py`): fitness-filtered VP1 variants,
1030
+ candidates only; abstains without the model.
1031
+ - **Surfaces:** REST `POST /delivery`, `POST /capsid_fitness`, and `GET /delivery/tropism`; MCP `delivery_recommend`;
1032
+ manifest `recommend_delivery` and `capsid_fitness`; a `capsid_fitness` scope card; a `delivery` Challenge task
1033
+ (serotype to tissue); preregistration `ws_delivery.yaml`.
1034
+
1035
+ ### Limitations
1036
+ - The capsid-fitness model is a one-hot gradient-boosting model, not a protein-LM (it passes the gate; a protein-LM is
1037
+ the upgrade path). Capsid-fitness covers AAV only (VLP/LNP data is thinner). In-vivo human tropism is
1038
+ a known-unknown except for the approved-therapy priors; novel capsids abstain on tropism. alpha-retro-VLP is exploratory.
1039
+
1040
+ ## [6.10.4] - 2026-06-20 - Chromatin incremental-value test (annotation, not a re-ranker)
1041
+
1042
+ This patch closes out the chromatin work. v6.10.3 validated accessibility as a moderate standalone
1043
+ predictor; v6.10.4 tests whether it adds incremental value on top of the CRISOT sequence score, i.e. whether
1044
+ it should re-rank.
1045
+
1046
+ ### Added
1047
+ - **Incremental-value analysis** (`scripts/offtarget_chromatin_incremental.py`; result in
1048
+ `benchmarks/offtarget/chromatin_incremental.json`). On GUIDE-seq (HEK293T-matched), per off-target CRISOT plus
1049
+ accessibility: (A) a conditional logistic regression `active ~ z(CRISOT) + z(accessibility)` and (B) a
1050
+ leave-one-guide-out held-out AUPRC of CRISOT-only vs a CRISOT+accessibility combiner, tested at two candidate
1051
+ imbalances (1:16 and a realistic 1:123). Result: accessibility carries a small, real conditional signal
1052
+ (coef ~0.35, bootstrap CI excludes 0 at both imbalances) but adds no held-out ranking improvement over CRISOT
1053
+ (AUPRC gap CI includes 0 at both: -0.0025 [-0.011, +0.005] and +0.0027 [-0.014, +0.021]).
1054
+
1055
+ ### Decision
1056
+ - Chromatin is a validated annotation, not a re-ranker. The CRISOT sequence score already captures the
1057
+ practically-relevant nomination ranking; a CRISOT+accessibility combiner does not improve held-out AUPRC, so it is
1058
+ not wired into the numeric risk score (`CHROMATIN_VALIDATION.changes_numeric_risk_score = False`). The fitted
1059
+ combiner coefficients are recorded but intentionally not applied. Ledger and docs updated.
1060
+ - This completes the chromatin context work (v6.10.1 wired it, v6.10.2 cross-cell weak, v6.10.3 cell-type-matched
1061
+ validated moderate, v6.10.4 incremental tested, annotation-only). Nothing about chromatin remains open or
1062
+ undisclosed.
1063
+
1064
+ ## [6.10.3] - 2026-06-20 - Chromatin context: cell-type-matched validation (validated, moderate)
1065
+
1066
+ This patch settles the chromatin test. v6.10.2's controlled experiment was ambiguous (GUIDE-seq positive, TTISS
1067
+ reversed) on a cross-cell-type K562 proxy; v6.10.3 re-runs it with a cell-type-matched track.
1068
+
1069
+ ### Added / changed
1070
+ - **Cell-type-matched validation** (`scripts/offtarget_chromatin_matched.py`; result in
1071
+ `benchmarks/offtarget/chromatin_validation.json` phase2). Downloaded the matched ENCODE HEK293T DNase-seq track
1072
+ (`ENCFF529BOG`; HEK293T matches GUIDE-seq's HEK293 and TTISS's HEK293T), queried it at each off-target's 1 kb bin
1073
+ (pyBigWig), and recomputed the AUROC. Cell-type matching lifts the canonical WT-Cas9 cell-based assay GUIDE-seq
1074
+ from AUROC 0.58 (cross-cell K562) to 0.671 (matched, CI [0.642, 0.701]); the in-vitro negative control stays null
1075
+ (0.494). The cross-cell proxy was dampening a real effect.
1076
+ - Verdict: chromatin is validated (moderate, cell-type-matched) for WT-Cas9 cell-based off-target activity
1077
+ (`offtarget_data.CHROMATIN_VALIDATION` now `validated=True`, `effect="moderate"`). The caveats, all in-code and
1078
+ in the docs: the effect is moderate (the sequence/CRISOT score still dominates nomination); it does not
1079
+ transfer to TTISS (0.383, the expected outlier, a Cas9-variant specificity assay driven by variant fidelity, not
1080
+ WT chromatin); and chromatin is still surfaced as a validated annotation that does not yet change the numeric
1081
+ risk score (a calibrated CRISOT+accessibility combination is the remaining, deferred refinement).
1082
+ - Reclassified the chromatin axis from "weak/inconsistent" to "validated (moderate, cell-type-matched)" with the
1083
+ matched evidence and the caveats.
1084
+
1085
+ ## [6.10.2] - 2026-06-20 - Chromatin context: controlled validation (weak/inconsistent result)
1086
+
1087
+ This patch validates the chromatin axis, then scopes it to what the data supports. v6.10.1 wired a real
1088
+ accessibility read but had not demonstrated it carries signal. v6.10.2 runs a controlled experiment and
1089
+ reports the result: it is not a clean win.
1090
+
1091
+ ### Added
1092
+ - **A controlled chromatin validation** (`benchmarks/offtarget/chromatin_validation.json`,
1093
+ `scripts/offtarget_chromatin_validation.py`). Off-target protospacers mapped to hg38 (GRCh38.fa, exact match both
1094
+ strands, 98.5% mapped); AUROC of the K562 ATAC/DNase accessibility for active-vs-inactive off-targets per
1095
+ assay, with in-vitro assays as a negative control (cell-free, so no chromatin). Result: the in-vitro controls hug
1096
+ 0.5 (method sound, no spurious signal); the canonical cell-based assay GUIDE-seq is a textbook modest positive
1097
+ (AUROC 0.58, CI [0.550, 0.613]) even with a cross-cell-type K562 proxy; but the second cell-based assay TTISS
1098
+ reverses (0.346). Verdict: weak and inconsistent, chromatin is not a validated quantitative axis on this data
1099
+ (the cross-cell-type proxy is the likely cause; a cell-type-matched accessibility track would settle it, deferred).
1100
+
1101
+ ### Changed
1102
+ - The chromatin-accessibility modifier is now an explicit annotation only, labelled `validated=false`: it reads
1103
+ the real accessibility track (or a caller-supplied scalar) and notes the qualitative Lazzarotto-2020 direction, but it
1104
+ does not change the numeric off-target risk score. `offtarget_data.CHROMATIN_VALIDATION` carries the result.
1105
+ - Corrected the v6.10.1 entry that had marked chromatin "FIXED"; that was too strong. It is now recorded as
1106
+ tested, weak/inconsistent, documented annotation, not a validated axis.
1107
+
1108
+ This is a negative result reported in full.
1109
+
1110
+ ## [6.10.1] - 2026-06-20 - Off-target rigor pass and retroactive audit (v6.7-v6.9)
1111
+
1112
+ This patch closes the v6.10.0 gaps, re-audits v6.7/v6.8/v6.9, and corrects the findings. No item is reported
1113
+ complete if it is a silent substitution, partial, or deferral.
1114
+
1115
+ ### Added / changed
1116
+ - **Off-Target-Bench expanded to four unbiased assays.** Added CHANGE-seq (Lazzarotto 2020, `10.1038/s41587-020-0555-7`)
1117
+ and SITE-seq (Cameron 2017, `10.1038/nmeth.4284`) on independent broad guide panels (20 and 11 guides). The real
1118
+ CRISOT-Score (MD-physics, assay-agnostic so leakage-clean) beats the homology baseline on all four:
1119
+ AUPRC 0.646/0.520/0.541/0.521 vs 0.467/0.266/0.249/0.233; per-guide bootstrap CI excludes 0 on each.
1120
+ - **Chromatin wired to the real accessibility track and relabelled.** `locus_accessibility(chrom, bin, ct)` reads
1121
+ `phase_1/features/chromatin_{ct}.parquet` (ATAC/DNase) when present and abstains otherwise; the docs now say
1122
+ "chromatin-accessibility modifier" (not "chromatin-aware engine"), since the bare wheel and the deployed atlas do not ship the
1123
+ raw track, so the modifier is inactive there.
1124
+ - **Off-target task added to the Genome-Writing Challenge** (`benchmarks/genome_writing_challenge/harness.py`):
1125
+ non-circular (label = wet-lab Active call), data-gated on the fixture; the reference solver nominates correctly.
1126
+ - **Substitutions:** CRISOT is used instead of the plan-named CCLMoff/CRISMER (CRISMER ships no license;
1127
+ CCLMoff is GPU and trained on these assays, so it leaks; CRISOT is the leakage-clean, license-clean, CPU choice). A
1128
+ genomic-coordinate locus split is not possible (harmonized data is coordinate-free), so held-out-guide and cross-assay are used.
1129
+
1130
+ ### Fixed (retroactive audit)
1131
+ - **v6.9:** dropped the inaccurate "OOD-gated" claim in the MHC-II axis status (it is coverage-gated, abstains
1132
+ when uncached, with no distributional OOD gate); corrected the stale `AXIS_STATUS["mhc2_writer"].reason` and the
1133
+ `immune_mhc2.py` module docstring (they still described the dropped v6.9.0 P1-anchor proxy as "the method"; the
1134
+ production axis is the real NetMHCIIpan-4.0). The plan-named MHC-II tool ensemble and the IEDB/ImmunoSeq/FVIII
1135
+ ADA datasets were not used (single-tool NetMHCIIpan-4.0; the recovery bench is a 4-protein sanity check, not an
1136
+ IEDB held-out leaderboard); the 6.9.1 to 6.9.2 MHC-II metric changed from peptide-fraction to residue-coverage.
1137
+ - **v6.8:** v6.8.0's attB was a poly-G/C schematic (replaced with the real Bxb1 attB in v6.9.2);
1138
+ inter-curator agreement is N/A (single contributor); "at least 1 external submission" is unmet (forward-looking).
1139
+ - **v6.7:** corrected the "chromosome-Mondrian" served-interval wording (per-chromosome Mondrian qhats are computed,
1140
+ but the global qhat is served, which is correct since a query has no chromosome at serve time); recorded the prereg
1141
+ consolidation and the deferred HEK293T-OOD demo / scope-manifest entry.
1142
+
1143
+ ## [6.10.0] - 2026-06-20 - Cross-writer-family off-target nomination
1144
+
1145
+ Off-target moves from a single-family bridge pseudosite scan to a cross-writer-family,
1146
+ chromatin-aware nomination engine grounded in unbiased genome-wide assays, completing the safety triad
1147
+ (site B, writer C, off-target E). Nomination is framed as not a clearance: every candidate
1148
+ ships with the empirical assay that would confirm it.
1149
+
1150
+ ### Added
1151
+ - **Off-Target-Bench** (`benchmarks/offtarget/`): a real, leakage-controlled nomination benchmark over canonical
1152
+ Cas9 guides (EMX1/VEGFA1-3/FANCF/HEK293) with experimentally validated off-targets from GUIDE-seq
1153
+ (Tsai 2015, `10.1038/nbt.3117`) and CIRCLE-seq (Tsai 2017, `10.1038/nmeth.4278`). Held-out-guide split, per-assay
1154
+ provenance, SHA256SUMS. On real data with a real tool, the licensed CRISOT-Score predictor
1155
+ (Chen et al., Nat Commun 2023, `10.1038/s41467-023-42695-4`; XGBoost RNA-DNA fingerprint) beats the sequence-
1156
+ homology baseline: GUIDE-seq AUPRC 0.646 vs 0.467 (gap +0.179, CI [0.015, 0.340]); CIRCLE-seq 0.520 vs
1157
+ 0.266 (gap +0.253, CI [0.140, 0.361]); per-guide bootstrap CI excludes 0 on both assays.
1158
+ - `pen_stack/wgenome/offtarget_data.py`: validated assay/predictor provenance, a grounded mismatch-to-active-fraction
1159
+ risk calibration (real-data: GUIDE-seq 0-1mm to 100% active, 2mm to 76%, 3mm to 23%, 4mm to 3.3%), the bench fixture loader.
1160
+ - `pen_stack/wgenome/offtarget_predict.py`: `nominate_offtargets(writer_family, ...)`. Nuclease (mismatch-
1161
+ calibrated risk band plus the real cached CRISOT score plus a documented chromatin modifier, Lazzarotto 2020);
1162
+ serine integrase (cryptic pseudo-attB scan on the real documented Bxb1 attB core GCGGTCTC/GT);
1163
+ bridge (delegates to the existing Perry-DMS pseudosite engine). Abstains without inputs; never fabricates sites.
1164
+ - `pen_stack/wgenome/offtarget_assay.py`: validation-assay recommender (GUIDE/CHANGE/CIRCLE-seq for nucleases;
1165
+ Cryptic-seq/HIDE-seq for integrases; a documented gap for bridge recombinases, since no published genome-wide
1166
+ unbiased off-target assay or predictor exists, verified).
1167
+ - **Surfaces:** REST `POST /offtarget` and `GET /offtarget/assay`; MCP `offtarget_scan`; manifest `nominate_offtargets`
1168
+ (fabricates=False); an `offtarget_nomination` scope card; and a web Off-Target page.
1169
+
1170
+ ### Limitations
1171
+ - Nomination is not a clearance; genome-wide candidate enumeration needs the on-VM Cas-OFFinder/genome scan (this
1172
+ engine scores, ranks, and risk-bands supplied candidates). The CRISOT predictor is CC-BY-NC: it runs only on the
1173
+ VM and its weights are never redistributed; only derived scores are cached (CI-safe). Bridge/integrase off-target
1174
+ is data-thin and unmodeled and is flagged extrapolative; IntQuery (Tome Biosciences) is a paper-only reference.
1175
+
1176
+ ## [6.9.2] - 2026-06-19 - Real-tool rigor pass across the immune and writer axes (no proxies, no heuristics)
1177
+
1178
+ A top-to-bottom audit replaces every remaining proxy/heuristic in the immune and writer-design stack with
1179
+ the real on-VM tool (gold-standard, licensed) or an abstention. No silent fallbacks. All licensed binaries stay on
1180
+ the VM; only derived numbers are cached.
1181
+
1182
+ ### Changed
1183
+ - **MHC-I capsid axis re-grounded on NetMHCpan-4.1** (`pen_stack/planner/capsid_epitope_oracle.py`). The primary
1184
+ capsid CD8 predictor is now the gold-standard licensed NetMHCpan-4.1 (%Rank_EL<=0.5, residue coverage, 12-allele
1185
+ panel; `configs/mhc_epitope_oracle.yaml` `mhc1`); the v5.3 MHCflurry value is kept as an explicit, reported
1186
+ cross-check (never silently substituted). Both agree AAV is the least CD8-immunogenic capsid
1187
+ (AAV `capsid_immune_score` 0.4585 NetMHCpan / 0.2803 MHCflurry; the predictor disagreement is surfaced, not hidden).
1188
+ - **ADA-risk re-grounded** (`pen_stack/planner/ada_risk.py`). `ada_risk = real NetMHCIIpan-4.0 density x foreignness`,
1189
+ where foreignness is the protein origin (the authoritative central-tolerance signal). Unknown origin or uncached
1190
+ density now abstains (no k-mer guess, no heuristic), replacing the v6.9.0 albumin-only self-tolerance
1191
+ heuristic. The real human-proteome 9-mer self-match (computed on the VM over the full UniProt reference
1192
+ proteome, 20,431 proteins / 10.4 M 9-mers) is reported as a cross-check: human albumin 1.0 (self), the
1193
+ foreign writers (SpCas9/ISCro4/Bxb1) and capsids 0.0 (non-self), a clean self/non-self separation.
1194
+ - **MHC-II axis no longer falls back to a production proxy** (`pen_stack/planner/immune_mhc2.py`). `mhc2_epitope_load`
1195
+ uses the real NetMHCIIpan-4.0 cache by antigen name and otherwise abstains; the documented promiscuous-binder
1196
+ estimate is retained as `mhc2_proxy_estimate` for offline triage only (explicitly labelled, not the production axis).
1197
+ - **Real Bxb1 attB written** (`pen_stack/atlas/guide_design.py`). The PASTE/PASSIGE pegRNA 3' extension now writes the
1198
+ real documented Bxb1 minimal attB verbatim (FlyBase FBto0000359; Ghosh, Kim & Hatfull, Mol Cell 2003;
1199
+ 8-bp common core GCGGTCTC around the central GT crossover) instead of the schematic poly-G/poly-C arms. Integrases
1200
+ without a bundled documented site expose only the central core (never a fabricated full sequence).
1201
+ - `pen_stack/planner/immune_profile.py`: the writer-as-antigen card surfaces `foreignness`, the real
1202
+ `self_match_human_proteome` cross-check, and the MHC-II/ADA backends (this replaces the removed `self_tolerance` field).
1203
+
1204
+ ### Deviations from the v6.9 pre-registration (`prereg/ws_immune2.yaml`)
1205
+ - The pre-registered "1 - self_match_fraction from a human-proteome k-mer filter" foreignness fallback is
1206
+ dropped: foreignness is the authoritative origin, and an unknown origin abstains rather than imputing from a
1207
+ k-mer match (the real self-match is reported only as a cross-check). This is a stricter rule.
1208
+
1209
+ ### Data / tests
1210
+ - `configs/mhc_epitope_oracle.yaml`: corrected `self_match` (the v6.9.x cache had a FASTA-keying bug that collapsed
1211
+ the 20,431-protein proteome to 1 protein, zeroing every self-match including albumin); recomputed correctly on the VM.
1212
+ - `tests/unit/{test_ws_immune2,test_ws_epitope,test_ws_writer,test_ws_rel}.py` updated for the abstain semantics,
1213
+ the NetMHCpan-4.1 primary capsid value plus MHCflurry cross-check, the real attB, and the 6.9.2 version pins.
1214
+
1215
+ ## [6.9.1] - 2026-06-20 - Real NetMHCIIpan-4.0 / NetMHCpan-4.1 MHC epitope load (replaces the v6.9.0 proxy)
1216
+
1217
+ This patch is a rigour upgrade. v6.9.0's MHC-II axis was a documented heuristic proxy (P1-anchor density). The
1218
+ gold-standard licensed predictors were already on the VM, so v6.9.1 computes the MHC-II epitope load with real
1219
+ NetMHCIIpan-4.0 (and MHC-I with NetMHCpan-4.1) over a frequent HLA panel, and re-grounds the axis on the real
1220
+ values. The licensed binaries are never committed or distributed; only the derived fractions are
1221
+ cached (`configs/mhc_epitope_oracle.yaml`), exactly like the v5.3 MHCflurry cache.
1222
+
1223
+ ### Changed
1224
+ - `pen_stack/planner/immune_mhc2.py`: `mhc2_epitope_load(seq, name)` now uses the real NetMHCIIpan-4.0 EL
1225
+ %Rank<=2 cache (over 7 frequent HLA-II alleles) when the antigen is cached; the documented promiscuous-binder
1226
+ proxy remains only as the offline/CI fallback for uncached sequences. `real_mhc2_load(name)` exposes the cache.
1227
+ - `ada_risk`, `immune_profile` (writer-as-antigen), and `benchmarks/immuno` thread the antigen name to real values.
1228
+ - `configs/mhc_epitope_oracle.yaml` (committed): derived epitope fractions for the writer and capsid antigens.
1229
+
1230
+ ### Result (the real tool is more discriminating than the proxy)
1231
+ - Real NetMHCIIpan-4.0 strong-binder fraction: SpCas9 0.153, Bxb1 0.152, ISCro4 0.112, AAV2 0.114 vs
1232
+ human albumin (self) 0.066, the lowest. The gold-standard tool shows the self protein has a genuinely lower
1233
+ MHC-II load and the foreign writers higher, a signal the heuristic proxy flattened (~0.08-0.10 for all). The
1234
+ immunogenic-vs-tolerated recovery is unchanged (foreign well above self) but now on real predictions.
1235
+
1236
+ ### How it ran (no host install; per the VM Docker rule)
1237
+ - `penmhc:tools` (debian + tcsh + gawk + perl) with `~/netmhc` (the licensed tools) mounted, NMHOME fixed at
1238
+ runtime; `scratch/v691_mhc_compute.py` runs both predictors and writes the derived cache. The axis stays a
1239
+ population-level proxy (frequent-HLA panel, not a patient-HLA magnitude, a known-unknown).
1240
+
1241
+ ## [6.9.0] - 2026-06-20 - Immune profile: MHC-II/CD4, ADA, and writer-as-antigen
1242
+
1243
+ This minor feature release extends the immune profile from CD8/MHC-I-only to a full T-cell profile: MHC-I plus
1244
+ MHC-II/CD4 plus ADA risk with self-tolerance filtering, scored over the writer enzyme as a distinct antigen,
1245
+ still population-level, OOD-gated, and never collapsed. It wraps the v5.6 unified profile. No fabrication: real
1246
+ UniProt sequences, a grounded documented method, proxy-labelled axes.
1247
+
1248
+ ### Added: the MHC-II and ADA axes
1249
+ - `pen_stack/planner/immune_mhc2.py`: a grounded, dependency-free promiscuous MHC-II binder density (documented
1250
+ P1 hydrophobic anchor, Stern & Wiley 1994; secondary pockets, Southwood 1998) over capsid and writer sequences plus
1251
+ the bundled real writer/control FASTA. `configs/writer_sequences.fasta`: real UniProt for SpCas9 (Q99ZW2), ISCro4
1252
+ bridge recombinase (D2TGM5), Bxb1 integrase (Q9B086), human albumin self control (P02768).
1253
+ - `pen_stack/planner/ada_risk.py`: ADA-risk = MHC-II epitope density x foreignness with a JanusMatrix-style
1254
+ self-tolerance filter (origin authoritative; human-proteome k-mer filter otherwise). It recovers
1255
+ immunogenic-vs-tolerated: foreign writers score above the human self control (clean separation).
1256
+
1257
+ ### Changed: the unified profile
1258
+ - `pen_stack/planner/immune_profile.py`: adds `mhc2_writer` and `ada_writer` axes and a `writer_as_antigen` card
1259
+ with `dominant_antigen` and `writer_dominant_risk` (which fires for a foreign writer, especially non-viral delivery
1260
+ where there is no capsid antigen). `collapsed_score` stays `None` (asserted). `immune_calibration.AXIS_STATUS`
1261
+ registers the two new axes as mechanistic/population proxies.
1262
+
1263
+ ### Added: Immuno-Bench and calibration
1264
+ - `benchmarks/immuno/harness.py`: the immunogenic-vs-tolerated recovery track (non-circular: label = protein
1265
+ origin) plus a `calibrate_axis` ADA pass that remains a proxy at public-data power (no manufactured validation).
1266
+ - `tests/unit/test_mhc2_ada.py` (CI-safe; pure-Python method plus committed sequences). `prereg/ws_immune2.yaml`.
1267
+
1268
+ ### Limitations
1269
+ - Every axis is a population-level proxy, never a patient-specific ADA titer or realized CD4 magnitude (known-
1270
+ unknowns). The MHC-II method is sequence-intrinsic presentation potential, not a trained allele-specific predictor.
1271
+ The self-tolerance k-mer filter is seeded by the bundled human reference (the full human proteome is substitutable on the
1272
+ VM); the authoritative foreignness signal is the protein origin. Axes are a vector, never fused.
1273
+
1274
+ ## [6.8.0] - 2026-06-20 - Cross-family writer-efficiency engine and Writer-Efficiency Bench
1275
+
1276
+ This minor feature release upgrades the writer-selection step (pick the writer) from a curated-KB ranking to a prediction plus
1277
+ design layer: the first curated writer-efficiency benchmark, a learned cross-family efficiency predictor,
1278
+ integrated guide/att design, and serine-integrase variant critique. It wraps the Writer Atlas and v4.0 writer-verification.
1279
+ No fabrication: every efficiency is a real published number with a DOI and a verbatim quote.
1280
+
1281
+ ### Added: the curated dataset and benchmark
1282
+ - `pen_stack/atlas/writer_efficiency.py` plus `data/writer_efficiency.parquet` (SHA-locked): ~45 records / 9 DOIs /
1283
+ 4 families, each row with a DOI, a verbatim quote, and a source-access grade (39 pmc_verbatim, 1 abstract, 5 secondary).
1284
+ Sources: PASTE (Yarnall *Nat Biotechnol* 2023), (ee)PASSIGE (Pandey/Liu *Nat Biomed Eng* 2025), hyperactive
1285
+ integrases (Hew *Nucleic Acids Res* 2024 e64), evoCAST (*Science* 2025), ShCAST (*Science* 2019), enIS621
1286
+ (*Nat Commun* 2026), ISCro4 (*Science*).
1287
+ - `benchmarks/writer_efficiency/`: the Writer-Efficiency Bench, a sealed, SHA-locked held-out-family plus
1288
+ held-out-locus track set plus a baseline leaderboard plus a submission harness. `docs/cards/writer_efficiency_data.md`.
1289
+
1290
+ ### Added: the learned predictor and the gate
1291
+ - `pen_stack/atlas/writer_predict.py`: interpretable-feature HistGradientBoosting plus a family-blocked split-conformal
1292
+ interval, candidate-flagged. The pre-registered gate: it beats the KB family-mean baseline on held-out
1293
+ locus (MAE 11.7 vs 15.2, paired-bootstrap CI excludes 0; rho +0.38 vs -0.26) and ranks families better on
1294
+ held-out family (rho +0.52 vs -0.20), but the held-out-family MAE gain is not significant at N=42/4-families, so
1295
+ the KB ranking is retained as primary, the predictor ships candidate-flagged, and the dataset plus bench are the
1296
+ contribution. The negative is reported.
1297
+
1298
+ ### Added: guide design and variant critique
1299
+ - `pen_stack/atlas/guide_design.py`: bridge-RNA TBL/DBL loops (Durrant 2024), pegRNA+attB (Yarnall 2023; Bxb1
1300
+ core GT), orthogonal att-pair selection (Roelle 2023 GA/GT), with round-trip and invariant recovery tests.
1301
+ - `pen_stack/design/writer_variants.py`: extends v4.0 writer-verification to serine-integrase hyperactive mutants
1302
+ (Hew 2024 / Keravala 2009); recovers Bxb1 `c22` and PhiC31 P2/P3 retrospectively; defers the
1303
+ LM-vs-conservation blind claim (LM naturalness is not engineered hyperactivity).
1304
+
1305
+ ### Added: the recommender surface
1306
+ - `pen_stack/atlas/writer_recommend.py` plus manifest tool `recommend_writers`: ranks families (KB-grounded primary)
1307
+ plus candidate predicted efficiency with a conformal interval plus an auto-designed guide. Efficiency is never extrapolated
1308
+ to a family absent from the dataset (KB-only there).
1309
+
1310
+ ### Limitations
1311
+ - Predicted efficiencies are candidates with intervals, never asserted activity. 4 families is the binding
1312
+ statistical limit, reported. Range efficiencies stored as midpoints (raw string retained);
1313
+ secondary-source rows flagged and droppable (strict subset).
1314
+
1315
+ ## [6.7.0] - 2026-06-19 - Learned, trained-conformal position-effect head and TPE-Bench
1316
+
1317
+ This minor feature release upgrades the digital twin's expression/outcome layer from a validation-failing
1318
+ closed-form heuristic to a learned, trained-conformal, decomposable position-effect model, and ships the
1319
+ held-out benchmark the expression capability never had. Wrap, don't rebuild: it extends `twin`, `wgenome.uncertainty`,
1320
+ `wgenome.ood`, and `benchmarks`. No fabrication: every metric is from a real CV run on real TRIP supervision, and
1321
+ the cross-cell-type transfer claim is data-gated, never faked.
1322
+
1323
+ ### Added: the learned model and trained conformal
1324
+ - `pen_stack/twin/data/position_effect.py`: a unified position-effect schema plus a dataset registry with verified
1325
+ accessions/DOIs (TRIP live; PatchMPRA/MPIRE/lentiMPRA/Leemans registered and recorded `available=False` until
1326
+ fetched), z-normalization within (dataset x cassette), domain-blocked plus held-out-cell-type splits, a leakage check.
1327
+ - `pen_stack/twin/position_effect.py`: `PositionEffectModel` (factored `f_cassette` plus `g_context`, LightGBM),
1328
+ `evaluate()` (chromosome-blocked CV vs the v3.x durability head plus cassette-only, paired-bootstrap CIs,
1329
+ separability), split-conformal calibration (`ConformalRegressor`, chromosome-Mondrian, OOD-widened),
1330
+ `predict_stage_h()` serving seam. Result (real TRIP): expression rho 0.428 to 0.469 (CI excludes 0);
1331
+ held-out conformal coverage 0.885 vs 0.90 nominal.
1332
+ - `configs/twin/position_effect_conformal.json`: the shipped calibration (qhat plus N plus held-out coverage).
1333
+ - `scripts/p1_build_position_effect.py`: regenerates the model plus conformal artifacts (real CV report).
1334
+
1335
+ ### Changed: position-effect head integration
1336
+ - `pen_stack/twin/outcome.py`: when a chromatin context is supplied and the artifact is present, `predict_outcome`
1337
+ serves the learned trained-conformal interval plus `p_silenced` plus an OOD tier (`position_effect` block,
1338
+ `stage_h_mode`); with no context/artifact it falls back to the heuristic band, backward compatible (the
1339
+ v5.9 relative-scale contract is intact).
1340
+
1341
+ ### Added: TPE-Bench and controls
1342
+ - `benchmarks/position_effect/`: TPE-Bench, a sealed, SHA-locked held-out-chromosome track plus a baseline
1343
+ leaderboard (cassette-only / durability head / factored). The leave-one-cell-type-out
1344
+ transfer track is scaffolded and data-gated (no fabricated transfer number).
1345
+ - `pen_stack/validate/{expr_controls,known_biology_expr,heldout_celltype_expr}.py`: a label-shuffle-to-chance control,
1346
+ an H3K9me3-heterochromatin-to-silencing recovery, and the data-gated transfer harness.
1347
+ - `tests/unit/test_position_effect.py`: CI-safe (synthetic planted signal); the real-TRIP claim runs on a checkout, skips in CI.
1348
+
1349
+ ### Limitations
1350
+ - Public data cannot flip expression to outcome-validated (the v6.5 wall); v6.7 ships the learned and calibrated
1351
+ upgrade plus the benchmark plus the data-gating, not a manufactured result. Cross-cell-type transfer needs the additional
1352
+ human datasets (a data-acquisition step), reported as such. Wet-lab validation omitted by scope.
1353
+
1354
+ ## [6.6.0] - 2026-06-16 - License-clean provenance (COSMIC to CancerMine)
1355
+
1356
+ This minor release is a provenance refactor: no new science, no capability lost. The shipped artifact now sources the
1357
+ oncogene/TSG/driver list from CancerMine (CC0) instead of COSMIC Cancer Gene Census (free for academia but
1358
+ no-redistribution). Copyright protects the compiled database, not the fact that a gene is an oncogene, so
1359
+ sourcing the list from a CC0 compilation removes all licensing doubt while keeping the same capability. This is prep for
1360
+ the BioFirewall release, whose open repo vendors PEN-STACK's hazard data.
1361
+
1362
+ ### Changed
1363
+ - `pen_stack/data/ingest_safety_annot.py`: `load_cancermine()` (CC0) is the default oncogene/TSG source
1364
+ (HUGO to coords via GENCODE, `--min-citations` precision knob); `load_cosmic()` stays available but off by
1365
+ default (bring-your-own-license, local enrichment only).
1366
+ - `configs/genotoxicity_oracle.yaml`: regenerated from CancerMine; provenance and DOIs updated (CancerMine
1367
+ 10.1038/s41592-019-0422-y). `safety_{ct}.pkl` plus the Writable-Genome atlas regenerated on CancerMine features
1368
+ (re-deposited on Zenodo, superseding the COSMIC-derived deposit).
1369
+
1370
+ ### Added
1371
+ - **`DATA_LICENSES.md`**: every source by license by redistribution-status by where-used.
1372
+ - `tests/unit/test_data_licenses.py`: a CI license gate that fails if a restricted source (COSMIC/OncoKB) is the
1373
+ shipped derived-data source or a raw restricted gene-list is committed; CancerMine is the default.
1374
+ - `scripts/fetch_licensed_sources.py`: a bring-your-own-license fetcher for COSMIC/OncoKB (local-only, validation).
1375
+
1376
+ ### Notes
1377
+ - Metrics may shift (CancerMine has broader coverage than CGC), reported. The genotoxicity axis is a
1378
+ mechanism-grounded proxy (not outcome-validated) before and after; the swap changes only the source.
1379
+
1380
+ ## [6.5.0] - 2026-06-15 - Comprehensive expression model and proxy-validation pass
1381
+
1382
+ This minor feature release has two threads, one principle (no fabrication):
1383
+
1384
+ ### Added: a comprehensive, literature-cited expression model
1385
+ - `configs/expression/promoters.yaml`: the twin's promoter palette expands from 5 to 31 promoters (constitutive plus
1386
+ tissue-specific: liver TBG/LP1/hAAT, neuron hSyn/CaMKIIa, muscle MHCK7/MCK/CK8, astrocyte GfaABC1D, SFFV/MND/
1387
+ MSCV/RSV, and more). Each entry carries `strength` plus context plus assay plus citation plus confidence, because promoter
1388
+ strength has no universal scalar (it depends on cell type by vector by readout), so a single number is encoded
1389
+ with its context, never as a universal truth.
1390
+ - `configs/expression/modifiers.yaml`: a modifier layer (WPRE, intron, polyA, Kozak, codon-optimization/CAI,
1391
+ CpG-silencing) as literature priors/ranges, applied as a bounded uplift range (never a point multiplier, since
1392
+ the chimeric intron is ~20x for one transgene, ~3x for another). `twin/mechanistic.py` consumes both.
1393
+
1394
+ ### Added: a proxy-to-outcome validation harness
1395
+ - `scripts/calibrate_immune_axes.py` plus `configs/calibration/preexisting_nab_independent.yaml`: runs the existing
1396
+ `calibrate_axis` gate (N>=6 AND bootstrap Spearman CI excludes 0) against independent measured data.
1397
+
1398
+ ### Result (the deliverable)
1399
+ - No immune or expression axis flips to outcome-validated. Pre-existing NAb tested vs an independent cohort
1400
+ (Navarro-Oliveros 2024, Basque): rho=0.12, CI includes 0, geography-dependent. Relative-expression tested vs an
1401
+ independent promoter study (Damdindorj 2014): rho=0.12, CI includes 0, promoter strength is context-dependent
1402
+ (Damdindorj found CMV strongest; Qin found the opposite). Genotoxicity (3 vectors), CD8 (5 capsids), anti-PEG
1403
+ (1), and innate (0 fixed) are structurally below the N>=6 gate. The labels stay proxy with empirical backing;
1404
+ flipping them would require measured-outcome data at a statistical power the public literature does not provide.
1405
+
1406
+ ### Tests
1407
+ - `tests/unit/test_expression_model.py`: the palette is comprehensive and cited; context is encoded; the modifier profile is a
1408
+ bounded range; the proxy does not falsely claim cross-study validation (the no-fabrication gate holds).
1409
+
1410
+ ## [6.4.3] - 2026-06-12 - Chat vehicle-parse fix (AAVS1 no longer hijacks the vehicle)
1411
+
1412
+ This patch fixes a parsing bug. `web/tools.py::parse_goal` matched the delivery vehicle by substring, so the safe-harbour nickname
1413
+ AAVS1 (which contains "aav") wrongly selected the AAV vehicle even when the user said lentivirus or
1414
+ LNP, producing the wrong immune profile (e.g. genotoxicity 1.0 instead of lentivirus's 0.481). Fix: strip the
1415
+ safe-harbour nicknames (AAVS1/H11/HIPP11/ROSA26) from the vehicle-search text before matching, so the user's
1416
+ stated vehicle wins. Explicit "AAV" still selects AAV. A new test locks all three cases.
1417
+
1418
+ ## [6.4.2] - 2026-06-12 - Co-Scientist chat: real writer recommendations and self-explanatory values
1419
+
1420
+ This patch fixes a stale/confusing chat experience reported from the live app. Three problems, three fixes:
1421
+
1422
+ 1. **The chat dossier was generic and barely changed per query.** `web/tools.py::parse_goal` hardcoded
1423
+ `chrom="chr19"` (so a goal about ITGB2, chr21, was mis-located) and `run_tools` never called the planner,
1424
+ so a "which writer can integrate N kb in GENE" question got a vehicle-keyed immune profile but no named
1425
+ writer. Fix: `parse_goal` now resolves the gene's real chromosome (`planner.gene_region`, atlas-gated,
1426
+ falls back offline), and `run_tools` runs the planner and attaches a `plan` block: the recommended writer
1427
+ family, top site, safety/durability/score, cargo-capacity fit, and delivery, all engine-computed. It says so
1428
+ when the gene isn't in the atlas ("not found, check the HGNC symbol"); never fabricated.
1429
+ 2. **The LLM narration produced `[unverified]` spam.** With no writer in the tool results, the model invented
1430
+ one (`AAV9-CRISPR` plus made-up numbers) and the grounding guard struck them all. Fix: the system prompt now
1431
+ forbids inventing a writer/vehicle/table/number, and if the guard still strikes 2 or more numbers the reply falls
1432
+ back to the fully-grounded deterministic narration, so the spam never reaches the user.
1433
+ 3. **Values and the "extrapolating" badge weren't self-explanatory.** Each immune axis now carries a
1434
+ plain-language `meaning` ("0.55 on a 0-1 scale, moderate; higher = fewer patients excluded; this is a
1435
+ proxy, not validated against a measured outcome"), the deterministic narration uses it, and
1436
+ `ImmuneProfileCard` renders it plus a one-line legend explaining that "extrapolating" means a proxy estimate.
1437
+
1438
+ ### Added
1439
+ - `tests/unit/test_grounded_chat.py`: chrom resolution, axis-meaning, real writer plan, and the no-`[unverified]`-spam
1440
+ fallback are locked by new tests.
1441
+
1442
+ ## [6.4.1] - 2026-06-12 - Defence-in-depth: pre-route safety screen
1443
+
1444
+ This patch closes a screening gap. The grounded co-scientist chat ran the Guardian (biosecurity gate) only in the design lane (via
1445
+ `run_tools`); a hazardous request with no design signal (no vehicle/locus) routed to `general`/`explain`/`meta`
1446
+ and was never screened. Fix: `pen_stack/web/llm.py::_pre_route_safety` runs the Guardian, framing-stripped, the
1447
+ authority on the decision, at the top of `grounded_reply()`, before lane routing. A `refuse`/`escalate`
1448
+ verdict short-circuits to a clear decline (`mode="safety"`, with the decision in `tool_results`). Benign
1449
+ hazard-adjacent biology (vaccines, generic pathogen questions) is not blocked: the Guardian clears it and
1450
+ routing continues. A broad regex only decides whether to invoke the Guardian; a false trigger is harmless.
1451
+
1452
+ ### Added
1453
+ - `tests/unit/test_grounded_chat.py`: `test_pre_route_safety_screens_a_hazardous_general_query` and
1454
+ `test_pre_route_safety_does_not_over_refuse_benign_questions` lock both sides of the screen.
1455
+
1456
+ ## [6.4.0] - 2026-06-12 - Live Oracles (the foundation models actually execute)
1457
+
1458
+ The oracle mesh goes live. The foundation-model adapters that were deferred contracts now run real backends,
1459
+ without touching the no-fabrication invariant (generated outputs stay candidates, OOD inputs are flagged, a down
1460
+ backend defers). Live execution is opt-in via `PEN_STACK_ORACLE_NET=1`; with the flag unset (CI/offline) every
1461
+ oracle behaves exactly as before. This is a minor feature release on the stable 6.x API.
1462
+
1463
+ ### Added: live oracles
1464
+ - **Evo2-40B (hosted):** `oracles/genome.py::generate_dna` calls NVIDIA's hosted Evo2-40B (real generated DNA plus
1465
+ per-token probability). ~1-3 s.
1466
+ - **AlphaGenome (hosted):** `oracles/genome.py::variant_effect` connected to the existing v3.1
1467
+ `wgenome.AlphaGenomeProvider` (added `score_variant`; no duplicate client), a real regulatory variant-effect
1468
+ magnitude. ~2-10 s. (AlphaGenome already ran live in v3.1 for expression/tracks/contact, 416 cached predictions.)
1469
+ - **ProteinMPNN / ESM3-open / RFdiffusion (local GPU):** `model_servers/{proteinmpnn,esm3,rfdiffusion}` small
1470
+ FastAPI servers on the VM GPU (reuse `penstack:phase1.5` / `rfdiffusion:base`); `oracles/protein_design.py`
1471
+ HTTP-calls them. ProteinMPNN ~1-9 s, ESM3 ~1-2 s warm, RFdiffusion ~1-2 min. `docker-compose.models.yml` starts
1472
+ them on demand.
1473
+ - **Execution and latency surface:** `configs/oracles/execution.yaml` plus `oracles/status.py` (`oracle_status`,
1474
+ `summary`) plus `GET /oracles` plus the chat meta facts: per-oracle execution, latency class
1475
+ (instant/seconds/slow/long_job), and live status, so the assistant states the cost before running anything.
1476
+
1477
+ ### Held / deferred
1478
+ - **AlphaFold3, Boltz-2, Chai-1, Protenix:** held, they need a rented A100/H100 (24-80 GB; AF3 also ~1 TB
1479
+ databases). They run separately on cloud, never on the 16 GB VM and never in the request path.
1480
+ - **Arc STATE / scGPT:** the package is verified installable (`pip install arc-state`; SE-600M embeds cells), but a
1481
+ trustworthy perturbation outcome needs the State-Transition model plus a reference scRNA pipeline, and even
1482
+ SOTA doesn't beat naive baselines (Arc VCC), so the magnitude stays a known-unknown, deferred
1483
+ (a uniform gated hook is added via `PEN_STACK_VCELL_URL` for when an ST server is stood up).
1484
+
1485
+ ### Verified on the VM (RTX A4000)
1486
+ Evo2-40B generation ~1.2 s; AlphaGenome variant score `chr22:36201698 A>C` max|effect| 3.15 over 14,652 tracks
1487
+ in 3.6 s; ProteinMPNN designed real ubiquitin-fold sequences (global_score ~0.80) in ~9 s; ESM3-open completed the
1488
+ ubiquitin sequence from a partial prompt in 1.4 s warm; RFdiffusion diffused a real 60-residue backbone in ~105 s.
1489
+ All generated outputs remain candidates (`as_claim()` raises).
1490
+
1491
+ ## [6.3.1] - 2026-06-12 - Router fix: general "how does it work" no longer misrouted to the meta lane
1492
+
1493
+ This patch corrects routing. It was found by a full-stack test pass (every oracle plus every endpoint plus the 4
1494
+ chat lanes plus general/biological-intelligence questions).
1495
+
1496
+ ### Fixed
1497
+ - **Router meta-lane over-capture.** A general-biology question phrased "and how does it work / cut DNA?"
1498
+ (e.g. *"what is CRISPR-Cas9 and how does it cut DNA?"*) matched the meta pattern `how (do|does) (you|it|this|pen)`
1499
+ and was answered from PEN-STACK capability facts instead of general knowledge. Narrowed the bare-pronoun meta
1500
+ trigger to `how (do|does) (you|pen)` so a general "how does it ..." routes to the general lane (labelled,
1501
+ with an engine pointer); a pen-stack-scoped "how do you compute X" stays meta (the verb-qualified pattern is
1502
+ unchanged). Regression cases added to `tests/unit/test_grounded_chat.py::test_router_classifies_the_four_lanes`.
1503
+
1504
+ ### Verified (v6.3 test pass)
1505
+ - **Oracle mesh (42/42, engine-direct):** ViennaRNA computes a real MFE fold (-38.3 kcal/mol); AlphaGenome,
1506
+ Evo2, vcell (Arc-STATE), AF3/Boltz/Chai/Protenix, and RFdiffusion/ProteinMPNN/ESM3 either compute or defer
1507
+ with the OOD gate plus provenance intact, never fabricate; the generative-candidate `as_claim()` guard
1508
+ raises. Computed immune layers reproduce orderings from data: genotoxicity LV 0.481 < gammaretro 0.177
1509
+ (LMO2/SCID-X1), capsid AAV 0.28 > Ad 0.18, CpG O/E rich > poor, seroprevalence AAV 0.55 / Ad5 0.35, anti-PEG
1510
+ 0.515; full `verify()` clears a clean design, rejects a 7 kb single-AAV (alt lentivirus legal), refuses ricin,
1511
+ rejects an RNP-over-AAV, and flags multiplex translocation risk 0.95.
1512
+ - **App surface (live, LLM on):** every endpoint 200 plus a grounded shape; the 4 chat lanes route correctly with the
1513
+ grounding guard clean on the grounded lanes (0 ungrounded numbers, Nemotron backend).
1514
+
1515
+ ## [6.3.0] - 2026-06-12 - The Hybrid Co-Scientist (grounded engine plus general intelligence)
1516
+
1517
+ The chat gains general and biological intelligence without loosening the no-fabrication core. A 4-lane router
1518
+ keeps grounded engine output and general trained-knowledge in separate, explicitly-labelled lanes, so a
1519
+ general-knowledge fact can never be mistaken for a PEN-STACK result. Numbers now come with their meaning,
1520
+ reference range, and how they were computed; the conversation has memory. This is a minor feature release on the stable
1521
+ 6.x API, SHA-locked.
1522
+
1523
+ ### Added
1524
+ - A deterministic 4-lane chat surface: `pen_stack/web/router.py` (classifier: `design` / `explain` / `meta` /
1525
+ `general`, biased to the engine whenever a design signal is present) plus `pen_stack/web/guide.py`
1526
+ (`metric_guide()` interpretation cards plus `pen_stack_facts()` assembled from live engine data) plus a rewritten
1527
+ `pen_stack/web/llm.py::grounded_reply` that dispatches per lane and returns `{mode, provenance, grounded, ...}`.
1528
+ - **`configs/metric_guide.yaml`:** grounded interpretation for every engine number (genotoxicity, CD8 epitope,
1529
+ innate, pre-existing NAb, anti-PEG, confidence, relative expression, and the safety decisions): what it means, the
1530
+ scale plus direction, reference bands, how it is computed, and its validation status. The chat now explains a value
1531
+ (scale / what's good-or-bad / reference range / method), not just prints it.
1532
+ - **Lanes and provenance:** `design`/`explain`/`meta` are engine-grounded (the grounding guard runs over the tool
1533
+ results, the metric guide, or the live facts); `general` answers from the LLM's trained knowledge, is labelled
1534
+ "General knowledge, not PEN-STACK-verified", attributes no number to PEN-STACK, and points to the engine
1535
+ wherever PEN-STACK could compute a concrete answer (`pen_stack_angles`).
1536
+ - **Conversation memory:** the last turns are passed to every lane so follow-ups ("what does that 0.55 mean?")
1537
+ resolve against the prior dossier; the frontend keeps history in-session until refresh and renders a per-message
1538
+ provenance badge (grounded vs general) plus the "PEN-STACK can compute this" pointers.
1539
+ - Tests: `tests/unit/test_grounded_chat.py` covers the 4-lane router, the general lane labelled/unattributed/pointered, the
1540
+ meta lane grounded in live facts, the explain lane interpreting prior values without a fresh design, the metric
1541
+ guide complete. Preregistration `ws_hybrid` plus SHA lock; deposit `phase_6.3/`.
1542
+
1543
+ ### Notes
1544
+ - The core is untouched. The guard still runs on every PEN-STACK-attributed number; we added a general lane,
1545
+ we did not loosen the grounded lane. The cost is that general-lane answers carry the LLM's fallibility,
1546
+ made safe by the explicit label and by redirecting to the engine for anything computable.
1547
+
1548
+ ## [6.2.4] - 2026-06-12 - Faster grounded narration (LLM backends) (patch)
1549
+
1550
+ Performance plus a real fix, from benchmarking the narration backends on the deployment GPU (RTX A4000). The
1551
+ LLM only narrates over engine tool results (the grounding guard runs regardless), so latency is the thing to
1552
+ tune. Measured (real grounded prompt): Ollama qwen2.5:7b = ~50s warm / 120s cold (3.4 tok/s, a workstation
1553
+ GPU is slow for an LLM); qwen2.5:3b = ~27s; llama3.2:3b = ~17s; hosted Nemotron-49B = ~5s. All keep the
1554
+ grounding guard clean (0 ungrounded). The old Nemotron fallback model (`llama-3.1-nemotron-70b-instruct`) now
1555
+ 404s, i.e. the fallback was silently broken.
1556
+
1557
+ ### Fixed / changed (`pen_stack/web/llm.py`)
1558
+ - **Nemotron model corrected** to `nvidia/llama-3.3-nemotron-super-49b-v1` (the 70B name was retired, so the
1559
+ fallback 404'd). Restores a working, ~5s hosted backend.
1560
+ - **Default local model qwen2.5:7b to qwen2.5:3b-instruct** (~2x faster narration, grounding unchanged).
1561
+ - **`keep_alive` (default 30m)** so the model stays resident on the GPU and idle calls don't pay the cold start.
1562
+ - **Configurable backend order** `PEN_STACK_LLM_ORDER` (default `ollama,nemotron` = local/private-first;
1563
+ `nemotron,ollama` = speed-first ~5s). `web/.env.example` documents all knobs.
1564
+
1565
+ ## [6.2.3] - 2026-06-12 - Scope matcher covers functional titer and durability (patch)
1566
+
1567
+ A coverage fix (from the 20-query acceptance suite, `phase_6.2/PEN-STACK_ACCEPTANCE_TESTS.md`). The
1568
+ known-unknowns matcher (`configs/known_unknowns.yaml`) had no entry for functional titer / absolute in-vivo
1569
+ expression magnitude and its durability terms were too narrow ("how long will it last in a patient"), so
1570
+ common measured-endpoint questions ("what functional titer (% of normal)?", "how long will episomal AAV
1571
+ expression last?") were not explicitly deferred. The no-fabrication spine already held (no titer/half-life was
1572
+ ever emitted, and the immune profile lists `patient_specific_titer`), but the matcher should flag these
1573
+ proactively.
1574
+
1575
+ ### Added / Fixed
1576
+ - `configs/known_unknowns.yaml`: a new known-unknown `in_vivo_expression_magnitude` (functional titer / % of normal
1577
+ / absolute expression, a measured clinical endpoint, never predicted; PEN-STACK gives the relative mechanistic
1578
+ proxy plus immune context); broadened `long_term_clinical_durability` match-terms/patterns to catch "how long will
1579
+ ... last/persist", "durability", "half-life". Regression test
1580
+ `tests/unit/test_api_surface.py::test_scope_defers_titer_and_durability_questions`.
1581
+
1582
+ ### Acceptance suite result
1583
+ - 20/20 behave as specified at the engine level: grounded where earned, refusing where unsafe (ricin/botulinum),
1584
+ abstaining/deferring where appropriate (titer, durability, phenotype), no fabricated number. T10 (RNP/AAV) and T12
1585
+ (multiplex translocation) are enforced via `delivery.cargo_form_compatible` and `multiplex.translocation_risk`
1586
+ on the structured design fields (`writer_output_form`, `edits`).
1587
+
1588
+ ## [6.2.2] - 2026-06-12 - Safe-harbour locus-nickname resolution (patch)
1589
+
1590
+ A usability fix. Site Finder / `/plan` / `/writable` returned 0 plans for `AAVS1` because it is a genomic
1591
+ safe-harbour locus nickname, not an HGNC gene symbol, so the gene-to-coordinate lookup (`gene_coords`, 60,888
1592
+ symbols) could not resolve it: an empty result, but unhelpful for the most-typed safe harbour. (The cell-type
1593
+ atlases are complete; real symbols like `PCSK9`/`HBB`/`CCR5`/`CLYBL` resolved fine.)
1594
+
1595
+ ### Fixed
1596
+ - `pen_stack/planner/optimize.py`: `resolve_gene()` maps well-documented safe-harbour nicknames to their host
1597
+ gene (`AAVS1` to `PPP1R12C` 19q13.42; `H11`/`Hipp11` to `EIF4ENIF1` 22q12) at every gene-to-coordinate lookup
1598
+ (`gene_region`, `plan`, `crosslink.loci_for_gene`); real symbols pass through unchanged. Regression test
1599
+ `tests/unit/test_api_surface.py::test_safe_harbour_nickname_resolves_to_host_gene`.
1600
+
1601
+ ## [6.2.1] - 2026-06-12 - JSON-safe atlas/crosslink endpoints (patch)
1602
+
1603
+ A bug fix. The `/atlas`, `/writable`, and `/crosslink/loci` endpoints returned raw DataFrame records, which
1604
+ leak non-finite floats (`NaN`/`inf`) present in `atlas.parquet`; the JSON encoder rejects these
1605
+ (`ValueError: Out of range float values are not JSON compliant`, so HTTP 500). Surfaced on the v6.2 Web Platform's
1606
+ Writer Atlas and Site Finder pages.
1607
+
1608
+ ### Fixed
1609
+ - `pen_stack/server/api.py`: a `_records()` helper serializes DataFrame rows JSON-safely (via pandas `to_json`,
1610
+ so `NaN`/`inf` become `null` and numpy scalars become native), applied to `/atlas`, `/writable`, `/crosslink/loci`.
1611
+ Regression test `tests/unit/test_api_surface.py::test_records_helper_is_json_safe_with_non_finite_floats`.
1612
+
1613
+ ## [6.2.0] - 2026-06-11 - The Web Platform (the human surface)
1614
+
1615
+ A post-1.0 adoption surface for bench scientists. A complete, friendly web application: a grounded co-scientist
1616
+ chat plus structured feature pages, over the same typed v6.1 API the AI surface uses. The LLM narrates and
1617
+ routes but never sources a number; every quantitative answer renders with its confidence band, provenance, and
1618
+ an explicit ledger of what PEN-STACK can't tell you. This is a minor release on the stable 6.0 API, SHA-locked.
1619
+
1620
+ ### Added
1621
+ - **Backend:** `pen_stack/web/server.py`, one FastAPI gateway that mounts the v6.1 engine surface under
1622
+ `/api` (so the frontend has one base URL and one OpenAPI) and adds the grounded `/chat` (plus SSE `/chat/stream`),
1623
+ CORS, and static serving of the built frontend (`web/dist`). A `/health` for the live grounded indicator.
1624
+ - **Chat (the hard gate):** `pen_stack/web/tools.py` (the deterministic engine tool-runner: parse a goal,
1625
+ run `verify`/`safety`/`immune_profile`/scope, return a grounded dossier; `extract_grounded_numbers` is the allow-list)
1626
+ and `pen_stack/web/llm.py` (the grounded co-scientist: Ollama, then Nemotron, then deterministic narrator, with
1627
+ `_enforce_grounding` striking any numeric token the model can't trace to a tool result). A reply's numbers are
1628
+ always engine-sourced; `tests/unit/test_grounded_chat.py` asserts no number in a reply is absent from the tool
1629
+ results, and that the deterministic narrator works with both LLMs offline.
1630
+ - **Frontend:** `web/` (React/Vite plus Tailwind): the UX component library (`ConfidenceBand`,
1631
+ `ProvenanceChip`, `ScopeLedger`, `SafetyBadge`, `ImmuneProfileCard`), so a number is never shown without its
1632
+ uncertainty plus provenance, and the scope ledger appears on every answer.
1633
+ - **Pages:** 11 feature pages over the typed API: Co-Scientist, Site Finder, Writer Atlas, Designer,
1634
+ Verify, Delivery & Immunity, Digital Twin, Guardian, Experiments, Challenge, Scope & About. Each renders
1635
+ through the UX library and degrades gracefully when the LLM is offline.
1636
+ - **Deploy:** `docker/web.Dockerfile` (multi-stage: a node:20 stage builds the frontend, a slim Python
1637
+ serves UI plus API from one origin) plus a `web` service in `docker-compose.yml`: one-command self-host
1638
+ (`docker compose up web ollama`, open `http://localhost:8000`). `web/.env.example`, `web/README.md` quickstart.
1639
+ - Read-only Challenge surface for the web page: `GET /api/challenge/{tasks,leaderboard}` (public tasks plus the
1640
+ PEN-STACK reference leaderboard; submissions are still scored offline, never accepted over HTTP).
1641
+ - Preregistration `ws_{chat,frontend}` plus SHA locks; deposit `phase_6.2/`.
1642
+
1643
+ ### Notes
1644
+ - The LLM never sources a number. It explains, compares, and routes over the engine's tool outputs; the
1645
+ grounding guard strips any value it can't trace, and the app runs in a deterministic, no-LLM mode (the science
1646
+ lives in the engine, not the model). This cycle improves usability/adoption, not validation; a real-data
1647
+ result and a first lab user remain the standing bottleneck. No new science; contracts under the 1.0 commitment.
1648
+
1649
+ ## [6.1.0] - 2026-06-11 - The AI Integration Surface
1650
+
1651
+ A post-1.0 adoption surface for AI builders. Not new capability: the introspectable, documented, dependable
1652
+ contract that lets an external agent discover what PEN-STACK offers and what it refuses to answer. This is a minor
1653
+ release on the stable 6.0 API, SHA-locked.
1654
+
1655
+ ### Added
1656
+ - **Capability and scope manifests (the differentiator):** `pen_stack/api/manifest.py`: `capability_manifest()`
1657
+ (machine-readable: the stable tools, inputs/outputs, all `fabricates=False`, guarantees, stability) and `scope_manifest()`
1658
+ (machine-readable: the known-unknowns registry plus every oracle scope card, i.e. what PEN-STACK refuses to
1659
+ answer). Generated from the live registry/scope cards (never hand-written); internal matcher fields not leaked.
1660
+ - **OpenAPI:** `pen_stack/server/api.py`: `GET /capabilities` plus `GET /scope` plus `POST /verify /safety /immune
1661
+ /generate /predict /suggest /session`; FastAPI auto-generates the OpenAPI 3.1 spec at `/openapi.json`.
1662
+ - **MCP:** `pen_stack/agent/mcp_server.py`: the self-describing resources `pen-stack://capabilities` plus
1663
+ `pen-stack://scope`, plus the engine tools (`safety_screen`, `immune_profile`, `generate_designs`,
1664
+ `predict_outcome`, `suggest_experiment`, `co_scientist_session`). A hazardous design returns a structured
1665
+ refusal an agent branches on.
1666
+ - **Examples:** a runnable golden path: `examples/external_agent.py` (REST: discover scope, submit, branch on
1667
+ safety/legality), `examples/mcp_client.py` (MCP), `examples/agent_tools.py` (framework-agnostic tool specs built
1668
+ from the live manifest plus an in-process dispatcher to the validated engine).
1669
+ - Docs: `docs/integrations.md` rewritten as "Integrate PEN-STACK in your AI" (the four guarantees plus the scope
1670
+ contract plus REST/MCP/framework quickstarts); preregistration `ws_{manifest,openapi,mcp}` plus SHA locks; deposit `phase_6.1/`.
1671
+
1672
+ ### Notes
1673
+ - Scope is data, not a disclaimer. The scope manifest makes the scope machinery itself an API, the thing
1674
+ that makes trustworthy autonomy something another system can build on. This cycle lowers the barrier to
1675
+ adoption; it does not, by itself, create it: outreach plus a real result remain the standing bottleneck. No new
1676
+ science or validation; contracts versioned plus deprecation-policed under the 1.0 commitment.
1677
+
1678
+ ## [6.0.0] - 2026-06-11 - 1.0, First Stable (the graduation)
1679
+
1680
+ The Closed-Loop arc is complete (7/7), and PEN-STACK graduates to "1.0, First Stable." The public API,
1681
+ exercised across every surface (verify, safety, generative design, twin, experiment design, build interface,
1682
+ closed loop, co-scientist, and the Genome-Writing Challenge), is documented and frozen with a deprecation
1683
+ policy. "First Stable" is earned, not declared: it is cut only after the closed loop is demonstrated (v5.12),
1684
+ the benchmark is public (v5.13), and the integration surface ships.
1685
+
1686
+ ### Changed
1687
+ - **`Development Status :: 5 - Production/Stable`** (was Beta). Version 6.0.0 (MAJOR).
1688
+ - The public API is documented and frozen with a deprecation policy: **`docs/STABILITY.md`** (semver from 6.0.0;
1689
+ deprecations warn at least 1 MINOR before removal in a MAJOR; the `OracleResult`/`Verdict`/`SafetyVerdict`/immune-profile
1690
+ contracts and invariants, including `collapsed_score is None` and the no-fabrication guard, are stable across 6.x).
1691
+ - The Genome-Writing Challenge is public.
1692
+
1693
+ ### Notes
1694
+ - "1.0, First Stable" is a commitment to API stability, not a claim of solving genetic engineering. The
1695
+ unknown funnel remains, made legible (scope flags, known-unknowns, baselines, no fabrication), not
1696
+ hidden. The high version numbers of the program's fast youth finally meet a real stability commitment.
1697
+
1698
+ ## [5.13.0] - 2026-06-11 - The Standard (Genome-Writing Challenge plus Co-Scientist II)
1699
+
1700
+ This cycle aims to make PEN-STACK the field's reference: an open, recurring, held-out benchmark
1701
+ others build to, and to give scientists a co-scientist that drives the whole loop with immune-risk first-class.
1702
+ SHA-locked. (The v6.0.0 "1.0, First Stable" graduation follows.)
1703
+
1704
+ ### Added
1705
+ - **The Genome-Writing Challenge** (`benchmarks/genome_writing_challenge/`): an open,
1706
+ recurring, held-out leaderboard (the CASP / Virtual-Cell-Challenge model). `evaluate(Submission, round_id)`
1707
+ scores an external `predict_fn(public_input) -> answer` on a held-out round whose labels it never sees; labels
1708
+ are computed by the validated PEN-STACK layers (rules / v5.7 Guardian / v5.6 immune profile) so no task uses a
1709
+ circular label; a no-fabrication audit runs on every submission; task families include an immune-risk
1710
+ task grounded in the v5.6 oracles. A one-command runner (`run.py`); a reference submission anchors the leaderboard.
1711
+ - **The matured co-scientist** (`pen_stack/agent/co_scientist.py::co_scientist_session(goal, cell_state)`)
1712
+ drives the whole loop: safe, legal, calibrated designs, then predicted outcomes, then suggested
1713
+ experiments, then exportable protocols, returning the Pareto strategies, calibrated `predicted_outcomes`,
1714
+ per-axis immune profiles (first-class), `suggested_experiments`, citations (resolve by construction),
1715
+ a complete scope ledger, and the per-design safety decision. The scientist/lab decides; the co-scientist
1716
+ drives. No number is fabricated; hazardous candidates are discarded.
1717
+ - **The integration surface:** MCP server tools, the Challenge submission API, and a worked reference
1718
+ example (`docs/integrations.md`). The standing adoption criterion (at least 1 external integration plus at least 1 external
1719
+ submission) depends on outreach, the non-code bottleneck flagged since v3.1; the surface is shipped.
1720
+ - Docs: `docs/{challenge,co_scientist_loop,integrations}.md`; preregistration `ws_{challenge,cosci2}` plus SHA locks.
1721
+
1722
+ ### Notes
1723
+ - A standard requires a community: PEN-STACK provides the open, reproducible, held-out benchmark and the
1724
+ integration surface; adoption depends on outreach. The co-scientist drives and presents (including the
1725
+ immune-risk profile with its known-unknowns); the scientist and lab decide.
1726
+
1727
+ ## [5.12.0] - 2026-06-11 - The Closed Loop (autonomy Level 3)
1728
+
1729
+ This release integrates everything into one continual design/build/test/learn cycle,
1730
+ humans/lab in control, no fabrication, drift-aware. It reaches autonomy Level 3 (the program's ceiling).
1731
+ SHA-locked.
1732
+
1733
+ ### Added
1734
+ - **The loop** (`pen_stack/loop/cycle.py`): `run_loop(goal, cell_state, ...)` orchestrates every prior cycle each
1735
+ round: generate (v5.8), decide/batch (v5.10), safety-gated export (v5.7 plus v5.11), run (sim-lab v5.11 /
1736
+ real lab), ingest (v4.5 gate), drift (v5.12), continual learn (v5.12). Gated: safety, build, and
1737
+ belief-admission each await the `approver`. Returns `autonomy_level=3`, `human_in_control=True`,
1738
+ `no_fabrication=True`. A hazardous candidate is discarded by the safety-gated pipeline before it is ever run.
1739
+ - **Drift** (`pen_stack/loop/drift.py`): `detect_drift(designs, results)` compares the v5.9 twin's predictions
1740
+ vs observed readouts; growing miscalibration leads to `severity:"high"` and `inflate_intervals` (widen, don't over-trust).
1741
+ - **Continual learning** (`pen_stack/loop/continual.py`): `continual_update(...)` recalibrates trust plus twin plus immune
1742
+ proxies on admitted outcomes only; each update is versioned and reversible (`rollback_to`); high drift
1743
+ widens intervals; an admitted immune measurement with a CI can graduate a v5.6 proxy to outcome-validated.
1744
+ This is recalibration, not foundation-model retraining.
1745
+ - **Demo and autonomy criteria:** `loop_converges_faster_than_random` reports the active-vs-random convergence with a
1746
+ bootstrap CI (retrospective/simulated, reported either way); `docs/autonomy.md` asserts the Level-3 criteria
1747
+ (closed loop, human in control at every gate, anomaly flagging, no fabrication) and that Levels 4/5 are
1748
+ not claimed.
1749
+ - **Bench v0.3.8:** a new `closed_loop` hard-gate task. The gate is the loop's integrity (gated
1750
+ end-to-end run plus no-fabrication plus Level-3 human-in-control plus drift detection plus versioned/reversible continual
1751
+ learning); an ungated autopilot fails by construction. Convergence reported informationally.
1752
+ - Docs: `docs/{closed_loop,autonomy}.md`; preregistration `ws_{loop,continual,drift}` plus SHA locks.
1753
+
1754
+ ### Notes
1755
+ - The loop is Level 3: closed, but with humans/lab in control at every gate, not autonomous. It runs in
1756
+ silico via the sim-lab (a real lab attaches at the same interface); continual learning recalibrates rather than
1757
+ retrains; drift covers calibration/residual shift, not all failures; the convergence demo is retrospective/
1758
+ simulated, reported with CIs.
1759
+
1760
+ ## [5.11.0] - 2026-06-11 - The Build Interface (digital-to-physical bridge)
1761
+
1762
+ This release makes designs executable and results ingestible: loop-ready, lab-optional,
1763
+ safety-gated, with the immune-risk profile attached as protocol metadata. SHA-locked.
1764
+
1765
+ ### Added
1766
+ - **Protocol export** (`pen_stack/build/protocol.py`): `export_protocol(design, experiment, target, actor)` for
1767
+ Opentrons / PyLabRobot / cloud-lab. It runs `verify()` first: a safety-`refuse` or illegal design raises
1768
+ `ProtocolExportError` (no export path for a flagged design); a cleared design is emitted as a DRAFT
1769
+ ("human/lab review required") carrying the v5.6 immune profile plus provenance in its metadata. Never auto-run.
1770
+ - **Ingest** (`pen_stack/build/ingest.py`): `ingest_result(result, ...)` validates a result (assay / readout /
1771
+ provenance) and turns it into a quarantined measured edge Candidate; the only path into the curated
1772
+ world-model is the v4.5 gate (`gate_admit`): automated checks AND explicit human approval. No auto-edit
1773
+ (Principle 1). Immune measurements can begin validating the v5.6 proxies on a later pass.
1774
+ - **Sim-lab** (`pen_stack/build/simlab.py`): `run_simulated(protocol_ir, design, cell_state)` executes a
1775
+ protocol in silico (samples from the v5.9 twin plus measurement noise), labelled `SIMULATED`, so the closed
1776
+ loop (v5.12) runs end-to-end (export, sim, ingest) without hardware; it never enters the world-model as
1777
+ measured truth.
1778
+ - **Bench v0.3.7:** a new `protocol_safety` hard-gate task (`pen_stack/validate/protocol_safety.py`):
1779
+ a cleared design exports with immune metadata, a safety-refused/illegal design is blocked, and the simulated
1780
+ loop completes with quarantined SIMULATED results; an ungated exporter (which would emit the hazardous protocol)
1781
+ fails by construction.
1782
+ - Docs: `docs/build_interface.md`; preregistration `ws_{proto,ingest,simlab}` plus SHA locks.
1783
+
1784
+ ### Notes
1785
+ - PEN-STACK emits protocols and ingests results; it does not run experiments. Protocols are drafts requiring
1786
+ human/lab review, results enter only through the gate, and the simulated lab is for development / loop-validation,
1787
+ never a substitute for real data. Export is hard-blocked for anything the safety gate flags.
1788
+
1789
+ ## [5.10.0] - 2026-06-11 - The Experiment Designer (active learning / EIG)
1790
+
1791
+ The "Learn" brain of a self-driving lab: turn "I'm uncertain" into "run
1792
+ this experiment next." It reads the calibrated v5.9 twin's uncertainty plus the v5.6 immune labels, scores each
1793
+ candidate experiment by expected information gain, assembles a diverse batch, and proves on held-out data, with
1794
+ CIs, that this learns faster than random/greedy (reporting plainly when it does not). SHA-locked.
1795
+
1796
+ ### Added
1797
+ - **Acquisition** (`pen_stack/active/acquire.py`): `expected_information_gain` (reducible uncertainty from the twin's
1798
+ predictive distribution; `>= 0`, monotone in uncertainty), `predictive_entropy` (from the twin's interval width),
1799
+ and `immune_voi` (value of information for validating an immune proxy axis, v5.6): an experiment that
1800
+ would measure a still-proxy axis is high-VOI (it turns proxy to outcome-validated). `acquisition_score` is fully
1801
+ traceable to twin quantities plus v5.6 labels; deterministic; no fabricated values.
1802
+ - **Batch design** (`pen_stack/active/design.py`): `select_batch` greedily maximises acquisition minus a
1803
+ redundancy penalty (shared design facets), giving a diverse batch (not k copies of the most-uncertain point);
1804
+ each experiment carries its expected info gain.
1805
+ - **Validation** (`pen_stack/active/validate.py`): `retrospective_active_learning` simulates active vs random vs
1806
+ greedy campaigns on a held-out split, reports mean±CI learning curves and a bootstrap CI on the curve-area
1807
+ gap; `active_beats_random` only when the CI excludes zero, else the not-yet-useful negative is reported.
1808
+ - **Bench v0.3.6:** a new `experiment_design` hard-gate task. The gate is the Learn engine's
1809
+ properties (twin-sourced EIG monotone in uncertainty plus immune-VOI for proxy validation plus a diverse
1810
+ batch plus retrospective active-vs-random with reps and CI); a random selector fails by construction. Active-beats-
1811
+ random is reported informationally.
1812
+ - Docs: `docs/experiment_design.md`; preregistration `ws_{acq,aldesign,alvalidate}` plus SHA locks.
1813
+
1814
+ ### Notes
1815
+ - The experiment designer is only as good as the v5.9 twin plus the v5.6 labels it queries; its advantage is validated
1816
+ retrospectively with CIs and reported plainly when absent. It chooses informative experiments but does
1817
+ not run them; prospective benefit awaits a lab partner (v5.11+). No autonomy claim.
1818
+
1819
+ ## [5.9.0] - 2026-06-11 - The Digital Twin (calibrated outcome prediction)
1820
+
1821
+ The missing layer: what does the cell do after the write? Predicted with
1822
+ calibrated uncertainty. The twin computes what mechanism allows, adds an in-distribution virtual-cell estimate
1823
+ (OOD-gated), screens immune outcome from the v5.6 profile, and is explicit about its boundary at phenotype.
1824
+ SHA-locked.
1825
+
1826
+ ### Added
1827
+ - **Virtual cell** (`pen_stack/oracles/vcell.py` plus scope cards `state`/`scgpt`): `predict_response(cell_state,
1828
+ perturbation, model)` wraps Arc STATE / scGPT under the v4.0 `OracleResult` contract. A
1829
+ perturbation-response prediction is a candidate, OOD-gated (a context outside the documented envelope is marked
1830
+ `extrapolating`), cached/deferred (value `None` when absent, never fabricated). It encodes the field's own result
1831
+ (Arc Virtual Cell Challenge): perturbation models don't yet consistently beat naive baselines.
1832
+ - **Mechanism** (`pen_stack/twin/mechanistic.py`): `cassette_expression` = `promoter_strength x copy_number x
1833
+ accessibility` (closed-form steady state); assumptions plus scope flags attached; physics where computable, not
1834
+ a phenotype.
1835
+ - **Outcome** (`pen_stack/twin/outcome.py`): `predict_outcome(design, cell_state)` fuses mechanism plus an
1836
+ in-distribution virtual-cell response plus the v5.6 immune profile into one prediction with an interval that
1837
+ widens under OOD, an immune-outcome dimension, and an explicit phenotype / in-vivo-magnitude boundary.
1838
+ In-vivo durability may be conditioned on the grounded pre-existing-NAb axis (no invented immune numbers);
1839
+ `output_kind="candidate"`.
1840
+ - **Calibration** (`pen_stack/twin/calibrate.py`): `calibrate_outcome(...)` reports calibration two-sided: interval
1841
+ coverage plus a bootstrap CI on the MAE gap vs a naive mean baseline; the twin "beats" naive only when the CI
1842
+ excludes zero, else the negative is reported verbatim; it abstains at `N < 3`.
1843
+ - **Bench v0.3.5:** a new `outcome_prediction` hard-gate task (`pen_stack/validate/outcome_prediction.py`):
1844
+ the gate is the twin's calibration properties (two-sided calibration plus OOD widening plus immune dimension plus
1845
+ phenotype out-of-scope), which an overconfident predictor fails by construction; twin-vs-naive skill is reported
1846
+ informationally on a labelled synthetic stream (no public perturbation-outcome calibration set exists).
1847
+ - Docs: `docs/digital_twin.md`; preregistration `ws_{vcell,mech,outcome,twincal}` plus SHA locks.
1848
+
1849
+ ### Notes
1850
+ - The twin is a hypothesis engine, not an oracle of truth: predictions are candidates with intervals;
1851
+ phenotype, in-vivo behaviour, immunogenicity magnitude, and durability beyond the computable stay
1852
+ scope-flagged. The interval is a heuristic band, not a trained conformal interval (no public outcome
1853
+ calibration set). Immune-outcome is sourced from v5.6, never invented.
1854
+
1855
+ ## [5.8.0] - 2026-06-11 - The Live Agent and Generative Designer
1856
+
1857
+ PEN-STACK turns from a checker into a grounded designer: it generates
1858
+ candidate end-to-end writing systems, keeps only those that pass safety plus legality plus calibration
1859
+ (verifier-as-discriminator), and returns the Pareto frontier of real tradeoffs, in which immunogenicity-risk
1860
+ is, for the first time, a grounded axis sourced from the v5.6 profile rather than a placeholder. SHA-locked.
1861
+
1862
+ ### Added
1863
+ - **Generation** (`pen_stack/design/{space,generate}.py`): `generate_designs(goal|candidates)` proposes candidates
1864
+ (`candidate_space` = the validated planner by the compatible delivery palette) and the v3.3 `verify()`,
1865
+ now safety-gated (v5.7) plus legality plus calibration plus immune-profiled, disposes. A candidate survives only
1866
+ if legal AND safe (`clear`/`flag`); hazardous (`refuse`/`escalate`) and illegal proposals are discarded,
1867
+ never returned (the `as_claim()` guard generalised to whole designs). Survivors carry calibrated confidence,
1868
+ the v5.6 immune profile, the safety decision, and `output_kind="candidate"`, never asserted to work.
1869
+ - **Pareto** (`pen_stack/design/pareto.py`): `pareto_front(designs)` over `(efficiency, durability, safety,
1870
+ deliverability, neg_immune_risk, neg_cost)`. `neg_immune_risk` is grounded by the v5.6 profile: the
1871
+ worst-case per-axis in-scope score with the per-axis uncertainty carried as a band; the profile is never
1872
+ collapsed into one number and the in-vivo magnitude stays scope-flagged (`in_vivo_magnitude_unknown`).
1873
+ - **Orchestration** (`pen_stack/agent/orchestrator_live.py`): `orchestrate(goal)`: plan, generate, call an oracle
1874
+ (cache-first/replayable) for a critique signal, dispose via `verify()`, refine. Every number is tool-sourced;
1875
+ a seed-locked replay reproduces the trace (replay is the CI default); no fabrication.
1876
+ - **Bench v0.3.4:** a new `generative_design` hard-gate task (`pen_stack/validate/generative_design.py`):
1877
+ on a frozen mixed pool (benign plus a hazardous ricin payload plus illegal oversize/mRNA-incompatible), the grounded
1878
+ designer returns only legal, safe, calibrated, immune-profiled survivors on a grounded-immune-axis Pareto frontier,
1879
+ while an ungrounded generator ships hazardous/illegal designs and fails by construction.
1880
+ - Docs: `docs/generative_design.md`; preregistration `ws_{gen,pareto,orch}` plus SHA locks.
1881
+
1882
+ ### Notes
1883
+ - A generated output is a candidate, never a claim; novelty is bounded by the oracles' validity and the
1884
+ rules' legality, and never asserted to work. The immune-risk Pareto axis is a worst-case screen; the
1885
+ per-axis v5.6 profile (with its validation labels) remains authoritative; in-vivo magnitude is a known-unknown.
1886
+
1887
+ ## [5.7.0] - 2026-06-11 - The Guardian (biosecurity / dual-use safety gate)
1888
+
1889
+ This release makes PEN-STACK safe by
1890
+ construction before it moves toward "build": every design submitted to `verify()` first passes a biosecurity / dual-use screening gate that
1891
+ refuses or escalates select-agent, pandemic-pathogen, and controlled-toxin signatures, with function-based and
1892
+ chimera checks that catch AI-designed homologs that homology alone would miss, while legitimate therapeutic designs
1893
+ pass untouched. It is orthogonal to (and complementary with) the v5.1-v5.6 immune-risk profile. SHA-locked.
1894
+
1895
+ ### Added
1896
+ - **Screens** (`pen_stack/safety/{registry,screen}.py` plus `configs/safety/hazard_registry.yaml`): a curated,
1897
+ version-pinned `HazardRegistry` (`registry_version`) and three or more screens returning typed, provenanced
1898
+ `ScreenHit`s: `function_flag` (toxin / pathogen-essential functions, the screen that catches AI-homologs
1899
+ at low identity), `taxon_flag` (regulated-pathogen taxa), `chimera_context` (hazardous assembly of benign
1900
+ parts plus split-hazard), and `sequence_homology` (delegated to a wrappable external screener: IBBIS Common
1901
+ Mechanism / SecureDNA-style; the in-repo baseline is a no-op). Signatures are function/family/taxon-level
1902
+ only (public Pfam accessions plus public control-list references: 42 CFR 73 / 7 CFR 331 / 9 CFR 121 / Australia
1903
+ Group / HHS P3CO/DURC), no hazard sequences, no synthesis/enhancement detail. All 14+ Pfam accessions were
1904
+ independently verified against EBI InterPro before reliance; one error (PF01375, mislabeled anthrax, which is
1905
+ heat-labile/cholera enterotoxin) was caught and corrected; anthrax PA was re-sourced from UniProt P13423.
1906
+ - **Policy** (`pen_stack/safety/{policy,gate,audit}.py` plus `configs/safety/policy.yaml`): `SafetyVerdict`
1907
+ {clear, flag, refuse, escalate}; `safety_gate(design, actor=...)` = strip-framing, screen, decide, audit;
1908
+ ambiguous dual-use (gain-of-function) escalates to human review (HHS P3CO/DURC), not auto-refuse; an
1909
+ append-only, hash-chained, tamper-evident `audit_log` (plus `verify_chain`) storing a design digest, not the
1910
+ design. Re-framing as "defensive research" cannot flip refuse to clear (the artifact decides, not the wording).
1911
+ - **Integration:** `Verdict.safety: SafetyVerdict`; `verify(design, actor=...)` runs the gate first and a
1912
+ `refuse` short-circuits (the design is returned un-evaluated, not scored/critiqued). No-fabrication holds:
1913
+ hits come only from the versioned registry.
1914
+ - **Red team** (`pen_stack/safety/redteam.py`): an adversarial harness (AI-homolog, split-hazard, reframing,
1915
+ chimera) plus reframing-stability pairs; reports set size plus caught count.
1916
+ - **Bench v0.3.3:** a new `safety_screening` hard-gate task (`pen_stack/validate/safety_screening.py`):
1917
+ benign therapeutics 0 false refusals, hazards refused/escalated at correct severity, evasions never `clear`;
1918
+ beats a no-safety baseline (1.0 vs 0.33) by construction. Frozen probes/registry/policy SHA-locked into the
1919
+ bench. The bench is now 17/17 available, planner beats naive on 13/13.
1920
+ - Docs: `docs/responsible_use.md` plus `docs/biosecurity.md`; preregistration `ws_{screen,policy,redteam}` plus SHA locks; the Zenodo deposit adds an execution summary and an independent data/ID verification record.
1921
+
1922
+ ### Notes
1923
+ - The safety gate is a defensive safeguard, not a guarantee, and not a substitute for institutional
1924
+ biosafety / IBC review; signatures are versioned and exploit detail is intentionally not published.
1925
+ - It is orthogonal to the immune-risk profile: the Guardian asks "is this design hazardous/dual-use?"; the immune
1926
+ profile asks "will the patient react?". Both attach to every `Verdict`; neither subsumes the other.
1927
+
1928
+ ## [5.6.0] - 2026-06-11 - Immunology completion and calibration (anti-PEG, proxy labels, unified profile)
1929
+
1930
+ This release finishes the delivery-immunology arc (v5.1-v5.5): it adds the missing anti-PEG axis, calibrates the
1931
+ proxies, and exposes a unified per-design immune-risk profile that never collapses into one number.
1932
+ SHA-locked.
1933
+
1934
+ ### Added
1935
+ - **Anti-PEG** (`pen_stack/planner/antipeg_oracle.py` plus `configs/antipeg.yaml`): pre-existing/induced anti-PEG
1936
+ antibodies gate re-dosing of PEGylated LNP. Population prevalence range (25-72%) gives
1937
+ `preexisting_antipeg_score = 1 - midpoint/100`, range surfaced as `native_uncertainty`; abstains for
1938
+ non-PEGylated vehicles. Serosurvey DOIs Crossref-verified (Chen 2016 `10.1021/acs.analchem.6b03109`, Yang &
1939
+ Lai `10.1002/wnan.1339`, Armstrong `10.1002/cncr.22739`, Kozma `10.1016/j.addr.2020.07.024`). Scope card `antipeg`.
1940
+ - **Calibration** (`pen_stack/validate/immune_calibration.py`): `calibrate_axis()` (Spearman rho plus percentile
1941
+ bootstrap CI) labels an axis outcome-validated only when the CI excludes zero, else `weak_proxy`, and
1942
+ `mechanistic_proxy` when N < 6. With no sufficient public paired (proxy, observed) dataset, every axis is
1943
+ labelled a mechanistic/population proxy; the label travels with the profile. (No fabricated
1944
+ outcome data; the machinery is proven on synthetic input.)
1945
+ - **Profile** (`pen_stack/planner/immune_profile.py` plus `Verdict.immune_profile`): a per-design vector
1946
+ of all axes (genotoxicity, CD8 epitope, innate, pre-existing NAb, anti-PEG), each with its own value plus
1947
+ uncertainty plus scope plus validation label. `collapsed_score is None` (never fused, asserted); known-unknowns
1948
+ listed; abstaining axes report `None`.
1949
+ - **Extras:** a documented qualitative route/immune-privilege modifier (eye/CNS lower realized
1950
+ immunogenicity vs systemic; Streilein 2003 `10.1038/nri1224`; no fabricated magnitude); CD4/MHC-II helper
1951
+ epitopes, pre-existing capsid-specific T-cell immunity, and complement/CARPA registered as
1952
+ known-unknowns. `prereg/ws_{peg,calib,profile}.yaml` plus SHA locks.
1953
+
1954
+ ### Changed
1955
+ - Version 5.5.0 to 5.6.0 (minor, additive); `cite.curated_dois()` ingests the anti-PEG plus immune-privilege DOIs.
1956
+
1957
+ ### Scope invariant (unchanged)
1958
+ - Every axis is a relative-risk screen (sequence/mechanistic or population proxy), labelled as such until
1959
+ outcome-validated; the profile is never collapsed into one number; patient-specific titer, post-dose-1
1960
+ induced immunity, and exact in-vivo magnitude stay known-unknowns.
1961
+
1962
+ ## [5.5.0] - 2026-06-10 - Anti-vector seroprevalence oracle (the last immune axis, from data)
1963
+
1964
+ This release completes the computable delivery-immunology axes. Pre-existing humoral immunity (B-cell /
1965
+ neutralizing antibody) to a viral capsid is the one immune axis that cannot be computed from sequence: it is a population
1966
+ prevalence from natural exposure. v5.5 grounds it in published serosurvey data. SHA-locked.
1967
+
1968
+ ### Added
1969
+ - **Seroprevalence table** (`configs/seroprevalence.yaml`): curated population NAb/IgG seroprevalence per serotype
1970
+ as ranges (region/age/assay variation) with DOIs: AAV (Calcedo 2009, Boutin 2010), adenovirus type 5
1971
+ (Mast 2010), HSV-1 (Looker 2015), VSV (negligible).
1972
+ - **Seroprevalence oracle** (`pen_stack/planner/seroprevalence_oracle.py`): `seroprevalence_oracle(vehicle,
1973
+ serotype=None)` returns an `OracleResult`. `preexisting_score = 1 - midpoint(seroprevalence)/100`; the range width is
1974
+ surfaced as `native_uncertainty`. Non-viral becomes 1.0 by mechanism; unknown abstains.
1975
+ - **Wired into the pre-existing axis:** `safety_efficacy_profile()` folds the computed seroprevalence score
1976
+ into the `preexisting_immunity` sub-axis only for in-vivo vehicles (serum NAb neutralises the vector in
1977
+ vivo; ex-vivo transduction in a dish is not reached by host antibody, so it is reported but muted). `seroprevalence_score`
1978
+ surfaces the raw value.
1979
+ - **Result (from data):** adenovirus has the highest pre-existing seroprevalence (40-90%, score 0.35), AAV
1980
+ intermediate (30-60%, 0.55), VSV/lentivirus negligible (0-5%, 0.975), the documented ordering quantified
1981
+ from serosurveys. `prereg/ws_seroprev.yaml`.
1982
+
1983
+ ### Changed
1984
+ - Version 5.4.0 to 5.5.0 (minor, additive data-grounded oracle); `cite.curated_dois()` ingests the
1985
+ seroprevalence DOIs.
1986
+
1987
+ ### Scope invariant (unchanged)
1988
+ - This is a population prevalence (a range; region/age/assay-dependent), not a given patient's NAb titer /
1989
+ sero-status (a clinical test, patient-specific, a known-unknown); the humoral (B-cell) axis only,
1990
+ distinct from the v5.3 T-cell epitope load. No patient-specific magnitude predicted.
1991
+
1992
+ ## [5.4.0] - 2026-06-10 - Computed innate-sensing scorer (completes the computable immune axes)
1993
+
1994
+ The third computed delivery-immunology signal, after v5.2 genotoxicity and v5.3 capsid epitope load. Innate
1995
+ sensing of a delivered nucleic acid is computed directly from the cargo sequence: CpG O/E for DNA (TLR9),
1996
+ U-richness plus dsRNA for mRNA (TLR7/RIG-I), covering every cargo form. SHA-locked.
1997
+
1998
+ ### Added
1999
+ - **Innate scorer** (`pen_stack/planner/innate_sensing.py`): `cpg_observed_expected()` (Gardiner-Garden &
2000
+ Frommer) plus `innate_sensing(seq, cargo_form)` returning an `OracleResult`. DNA gives CpG O/E (vertebrate genome ~0.2
2001
+ tolerated; non-depleted DNA is TLR9-stimulatory), `innate_score = max(0, 1 - CpG_O/E)`. mRNA gives uridine
2002
+ fraction plus ViennaRNA dsRNA pairing (graceful when ViennaRNA absent), flagged partial/`extrapolating`.
2003
+ RNP is minimal/transient. Abstains on empty / unrecognised input (never fabricates). Pure sequence
2004
+ computation, no external data, runs in CI.
2005
+ - **Surfaced in `verify()`:** when a design supplies `cargo_seq`, the computed innate load is attached as a
2006
+ `cargo_innate_sensing` scope flag (cargo form from the writer output form, else the vehicle's first
2007
+ compatible form) and added to `delivery_profile.cargo_innate`. No confidence added; the realized in-vivo
2008
+ innate response stays a known-unknown.
2009
+ - Scope card `innate_sensing`; `prereg/ws_innate.yaml`. `cite.curated_dois()` ingests the innate provenance
2010
+ DOIs (CpG-TLR9 10.1073/pnas.161293498, CpG-depleted AAV 10.1172/JCI68205, RNA modification
2011
+ 10.1016/j.immuni.2005.06.008, plus Krieg 1995 / Hornung 2006).
2012
+
2013
+ ### Changed
2014
+ - Version 5.3.0 to 5.4.0 (minor, additive computed scorer).
2015
+
2016
+ ### Scope invariant (unchanged)
2017
+ - This is a sequence-intrinsic motif-load signal. The realized in-vivo innate response magnitude in a patient is
2018
+ not modelled (known-unknown); the mRNA score is partial because the dominant evasion lever,
2019
+ nucleoside modification (m1-pseudouridine), is a manufacturing choice not derivable from sequence; DNA
2020
+ methylation state is likewise out of scope. No magnitude predicted.
2021
+
2022
+ ## [5.3.0] - 2026-06-10 - Computed capsid epitope-load oracle (covers all vectors)
2023
+
2024
+ v5.2 computed genotoxicity only meaningfully touches integrating vectors. v5.3 brings the NetMHC-style
2025
+ calculation to the adaptive (CD8 T-cell) axis: the fraction of a viral vector's capsid/envelope that is
2026
+ presentable across a frequent HLA-I panel (MHCflurry), so the computed immune signal covers all 8 vehicles
2027
+ (5 viral computed, 3 non-viral by mechanism). SHA-locked.
2028
+
2029
+ ### Added
2030
+ - **Build** (`scripts/p53_build_epitope_oracle.py`, runs in a dedicated `penstack:mhcflurry` image):
2031
+ slides 9-mers across each capsid/envelope antigen and predicts MHCflurry 2.0 affinity %rank per allele across
2032
+ 12 frequent HLA-I alleles; `epitope_fraction_strong` = residues covered by a strong binder (%rank <= 0.5);
2033
+ `capsid_immune_score = 1 - epitope_fraction_strong`. Sequences UniProt-verified and committed
2034
+ (`configs/capsid_sequences.fasta`): AAV2 VP1 P03135, Ad5 hexon P04133, VSV-G P03522, HSV-1 gD P57083 plus gB
2035
+ P06437. Emits the small committed summary `configs/capsid_epitope_oracle.yaml` (MHCflurry plus raw sequences stay
2036
+ on the VM, CI-safe).
2037
+ - **Oracle** (`pen_stack/planner/capsid_epitope_oracle.py`): `capsid_epitope_oracle(vehicle)` returns
2038
+ an `OracleResult` (`output_kind="baseline"`, scope card `capsid_epitope`). Non-viral vehicles become 1.0 by
2039
+ mechanism; unknown / sequence-less abstains.
2040
+ - **Wired into the adaptive axis:** `safety_efficacy_profile()` folds the computed capsid score into the
2041
+ adaptive (CD8) sub-axis only for in-vivo vehicles. The computed score is intrinsic antigen
2042
+ presentability; for ex-vivo lentivirus (whose VSV-G envelope is intrinsically epitope-dense but barely
2043
+ seen by the host ex vivo) it is reported but not folded (`adaptive_source = computed_ex_vivo_muted`), the
2044
+ documented tier kept. `capsid_presentability_score` surfaces the raw computed value.
2045
+ - **Result:** the AAV2 capsid is the least epitope-dense (0.72) and Ad5 hexon among the most (0.82); HDAd's in-vivo
2046
+ immune score drops accordingly, the documented adaptive ordering reproduced from sequence. `prereg/ws_epitope.yaml`.
2047
+
2048
+ ### Changed
2049
+ - Version 5.2.0 to 5.3.0 (minor, additive computed oracle); `cite.curated_dois()` ingests the epitope
2050
+ provenance DOIs (MHCflurry 10.1016/j.cels.2020.06.010, HLA-I supertypes 10.1186/1471-2172-9-1).
2051
+
2052
+ ### Scope invariant (unchanged)
2053
+ - This is a population-level, sequence-intrinsic presentation signal (does the capsid contain HLA binders), not
2054
+ the realized in-vivo / patient-HLA-specific T-cell response (a known-unknown), and CD8/MHC-I only (not
2055
+ antibody / neutralizing-antibody). No magnitude predicted.
2056
+
2057
+ ## [5.2.0] - 2026-06-10 - Computed genotoxicity oracle (data, not a documented tier)
2058
+
2059
+ The v5.1 genotoxicity axis was a documented ordinal tier; for integrating vectors that signal is in fact
2060
+ computable from data the stack already holds. v5.2 adds a computed genotoxicity oracle: the observed
2061
+ enrichment of a vector class's integration sites near COSMIC oncogenes, answering through the v4.0
2062
+ OracleResult contract. SHA-locked.
2063
+
2064
+ ### Added
2065
+ - **Build** (`scripts/p52_build_genotox_oracle.py`, runs on the VM where the data lives): computes,
2066
+ per integrating vector class, `P(integration site within 50 kb of a COSMIC Cancer-Gene-Census oncogene)` and
2067
+ its enrichment over genome background, from VISDB per-virus catalogues by the oncogene annotation
2068
+ (COSMIC CGC v104). Emits the small, auditable, committed summary `configs/genotoxicity_oracle.yaml` (raw
2069
+ catalogues stay on the VM; only the statistics ship, CI-safe).
2070
+ - **Oracle** (`pen_stack/planner/genotoxicity_oracle.py`): `genotoxicity_oracle(vehicle)` returns an
2071
+ `OracleResult` (`output_kind="baseline"`) with `genotox_score = min(1, 1/enrichment)`, native uncertainty
2072
+ (CI on the observed fraction), the `delivery_genotoxicity` scope card, and `extrapolating` for small-n
2073
+ classes. Non-integrating vehicles become 1.0 by mechanism; no computed class abstains (never fabricates).
2074
+ - **Wired into the v5.1 balance:** `safety_efficacy_profile()` now prefers the computed genotox_score for
2075
+ integrating vectors and falls back to the documented tier otherwise (`genotox_source` records which).
2076
+ - **Result (from data):** lentiviral (HIV) integration is 2.08x enriched near oncogenes (n=88,743, robust)
2077
+ vs 5.65x for gammaretroviral (MLV, the LMO2/SCID-X1 comparator, small-n flagged), reproducing the
2078
+ lentivirus-safer-than-gammaretrovirus ordering from VISDB by COSMIC, and the computed lentivirus score
2079
+ (0.48) validates the v5.1 documented "moderate" tier (0.5). `prereg/ws_genotox.yaml`.
2080
+
2081
+ ### Changed
2082
+ - Version 5.1.0 to 5.2.0 (minor, additive computed oracle); `cite.curated_dois()` ingests the genotox
2083
+ provenance DOIs (VISDB 10.1093/nar/gkz867, COSMIC CGC 10.1038/s41568-018-0060-1, HIV/MLV integration biology).
2084
+
2085
+ ### Scope invariant (unchanged)
2086
+ - This is a relative integration-preference signal. The in-vivo clonal-expansion / leukemogenesis outcome
2087
+ in a patient is not modelled and stays a known-unknown (`delivery_genotoxicity` scope card); the immune
2088
+ magnitude likewise stays `in_vivo_immunogenicity`. No magnitude is predicted.
2089
+
2090
+ ## [5.1.0] - 2026-06-10 - Delivery immunology (the safety/efficacy balance)
2091
+
2092
+ The delivery palette gains a documented, cited, qualitative immune plus safety plus efficacy profile per vehicle,
2093
+ so the substrate can make the safety/efficacy tradeoff legible and user-weightable, without ever predicting an
2094
+ immune magnitude (that stays a declared known-unknown). SHA-locked.
2095
+
2096
+ ### Added
2097
+ - **Config** (`configs/delivery_vehicles.yaml` v1.1): an `immune_safety` block on all 8 vehicles
2098
+ (`preexisting_immunity`, `neutralizing_antibody`, `innate_immune`, `adaptive_immune`, `genotoxicity`,
2099
+ `efficacy`, `tradeoff`, `immune_dois`): documented ordinal low/moderate/high priors, every `immune_doi`
2100
+ Crossref-verified and in the curated-DOI set (citations resolve by construction).
2101
+ - **Planner** (`pen_stack/planner/delivery_immunology.py`): `safety_efficacy_profile()` reports two
2102
+ separate safety sub-axes: `immune_score` (immunogenicity; reversible, eligibility/re-dosing) and
2103
+ `genotox_score` (insertional/oncogenic; permanent), never collapsed, with a top-line
2104
+ `safety_score = min(immune_score, genotox_score)` (precautionary worst-axis). `recommend_delivery(cargo_form,
2105
+ cargo_bp, safety_weight, in_vivo)` ranks the eligible palette along the safety/efficacy frontier by a
2106
+ user-supplied weight. It reproduces the stated tradeoff: AAV is dinged on immunogenicity, lentivirus on
2107
+ genotoxicity. `prereg/ws_immune.yaml`.
2108
+ - **Verify** (`Verdict.delivery_profile` plus a `delivery_immune_profile` scope flag): `verify()` now
2109
+ surfaces the documented profile and tradeoff for a chosen vehicle, always attaching the standing
2110
+ `in_vivo_immunogenicity` known-unknown flag, never adding confidence, never predicting a magnitude.
2111
+
2112
+ ### Changed
2113
+ - Version 5.0.0 to 5.1.0 (minor, additive delivery-immunology layer); `cite.curated_dois()` now also ingests
2114
+ the per-vehicle `immune_dois`.
2115
+
2116
+ ### Scope invariant (unchanged)
2117
+ - The in-vivo immune magnitude (patient/construct-specific response) remains a declared known-unknown
2118
+ (`configs/known_unknowns.yaml: in_vivo_immunogenicity`) and is never predicted. v5.1 exposes only
2119
+ documented ordinal priors plus a transparent, user-weighted ranking; it makes the boundary legible, it does
2120
+ not close it.
2121
+
2122
+ ## [5.0.0] - 2026-06-09 - The Co-Scientist (capstone)
2123
+
2124
+ The reasoning ceiling rises while the grounding floor stays fixed: a co-scientist that proposes multiple
2125
+ distinct strategies, critiques and revises its own plans, cites its reasoning, and itemises what it cannot
2126
+ assess, with no-fabrication holding across the full reasoning stack (the central gate). Each component is SHA-locked.
2127
+
2128
+ ### Added
2129
+ - **Planning and multi-strategy** (`pen_stack/agent/co_scientist.py`): `propose_strategies()` returns 2-3 materially
2130
+ distinct strategies (at least 2 design axes differ, measured by `distinctness()`, not reworded), each
2131
+ independently legal plus confidence-tagged; `deliberate()` benchmarks the deliberative planner vs the
2132
+ deterministic baseline. `prereg/ws_plan.yaml`.
2133
+ - **Critique and scope:** `critique()` / `critique_and_revise()` (the critic only flags plus swaps a design
2134
+ choice, never invents a number; revisions re-verified) plus `critique_falsifiability()` (improves flawed plans
2135
+ illegal to legal, 0 spurious revisions on clean) plus `scope_ledger()` (per-recommendation: what was/wasn't
2136
+ assessed, the known-unknowns itemised). `prereg/ws_crit.yaml`.
2137
+ - **Citation and generalisation** (`pen_stack/agent/cite.py`): `cited_rationale()` (citations drawn from the curated
2138
+ world-model, resolve by construction) plus `citations_grounded()` guard (rejects any DOI not in the curated
2139
+ set) plus `generalise()` (adjacent tasks grounded-or-refused). `prereg/ws_cite.yaml`.
2140
+ - **Bench v0.3.2:** a `co_scientist_grounded` reference-solver task: grounded rate 1.0 vs ungrounded 0.0;
2141
+ no-fabrication across the full stack. `docs/co_scientist.md`.
2142
+
2143
+ ### Changed
2144
+ - Version 4.5.1 to 5.0.0 (major, the substrate matured into a grounded co-scientist); bench 0.3.1 to 0.3.2.
2145
+
2146
+ ## [4.5.1] - 2026-06-09 - ID-correctness patch: cell-type ontology IDs
2147
+
2148
+ ### Fixed
2149
+ Two of the three new v4.5 Tier-A cell-type ontology IDs in `configs/cell_types.yaml` were wrong (verified via
2150
+ EBI-OLS): `EFO:0002322` resolved to the RPMI8226 myeloma line (not a T cell) and `EFO:0004146` to an
2151
+ obsolete myopathy term (not hepatocyte). Corrected to the canonical, non-obsolete Cell Ontology terms:
2152
+ primary_T_cell to `CL:0000084` (T cell), hepatocyte to `CL:0000182` (hepatocyte). iPSC (`EFO:0004905`),
2153
+ K562 (`EFO:0002067`), HepG2 (`EFO:0001187`) verified correct, as was the ISPpu10 back-test record (Europe PMC
2154
+ PPR1218813, "ISPpu10 is a structure-gated bridge RNA recombinase..."). No result/test change (the IDs are
2155
+ coverage-card metadata; `cell_types.py` reads coverage, not the ontology id).
2156
+
2157
+ ## [4.5.0] - 2026-06-09 - The Living World-Model (knowledge graph plus gated living loop)
2158
+
2159
+ v4.5 promotes the flat tables into a queryable knowledge graph that keeps itself current. Each component is
2160
+ SHA-locked. The agent proposes; a gate disposes, so no process auto-edits curated truth.
2161
+
2162
+ ### Added
2163
+ - **Knowledge graph.** `pen_stack/graph/{schema,build,query}.py`: typed nodes
2164
+ (writer/locus/cargo/vehicle/cell_type/write_type/outcome) plus typed edges
2165
+ (reaches/deliverable_by/performs/durable_in/carries/used_writer/observed_at), each carrying evidence kind
2166
+ (measured > curated > predicted) plus confidence plus scope plus provenance. Built deterministically from the v4.0
2167
+ curated tables (94 nodes / 288 edges), a pure-Python JSON store. Multi-hop queries return provenanced paths;
2168
+ `deliverable_by` reproduces the v3.3 verifier (0 parity mismatches). REST `POST /graph/query` plus MCP
2169
+ `graph_query`. `docs/world_model.md`; `prereg/ws_graph.yaml`.
2170
+ - **Gated living loop.** `pen_stack/graph/ingest.py`: Candidate plus Quarantine (propose never mutates
2171
+ a graph), `automated_checks` plus `gate_admit(approved, admitted_by)` as the sole admission path with versioned
2172
+ records; the back-test surfaces ISPpu10 (Europe PMC PPR1218813). No auto-edit path (asserted). `prereg/ws_mon.yaml`.
2173
+ - **Cell-type expansion.** `configs/cell_types.yaml` Tier-A (iPSC/ESC, primary T cells, hepatocytes)
2174
+ with coverage cards plus a Tier-B roadmap; `pen_stack/graph/cell_types.py` graceful degradation (partial coverage
2175
+ caps confidence) plus cross-cell-type OOD labelling. `prereg/ws_ct.yaml`.
2176
+ - **Graph reasoning bench.** `graph_multihop_reasoning` (bench v0.3.1): graph reasoning accuracy 1.0
2177
+ vs ungrounded 0.0, every answer a provenanced path. `prereg/ws_ba_v45.yaml`.
2178
+
2179
+ ### Changed
2180
+ - Version 4.0.3 to 4.5.0; bench 0.3 to 0.3.1; README updated for v4.5; M1/M2 plus world-model note updates.
2181
+
2182
+ ## [4.0.3] - 2026-06-09 - ID-correctness patch: UniProt plus Pfam plus ontology audit
2183
+
2184
+ ### Fixed
2185
+ A whole-repo audit of structured IDs (verified against InterPro, UniProt, EBI-OLS, mygene):
2186
+ - **`pen_stack/mech/pfam_whitelist.yaml` (v1.2.1 to v1.2.2):** the 26 Pfam accessions were all correct, but
2187
+ 13 of 22 `example_uniprot` proteins did not actually contain their claimed domain (membership checked
2188
+ against each protein's UniProt Pfam cross-references), including a marine-worm Histone H3 (PF13586), a
2189
+ mouse mannosyltransferase (PF05621/TniB), I-AniI (a LAGLIDADG enzyme) mislabelled HNH (PF01844), a
2190
+ glycine-betaine transporter and a Tn3 transposase mis-filed as rve, and an obsolete 404 accession
2191
+ (PF08721), despite the header claiming a spot-check. All corrected to reviewed/curated proteins whose
2192
+ UniProt entry genuinely carries the domain (e.g. ISCro4 `D2TGM5`, Tn5 `Q46731`, Tn7-TnsA `P13988`, Bxb1
2193
+ integrase `Q9B086`, McrA `P24200`); the audit-status header was corrected to stop over-claiming.
2194
+ - **`configs/atlas_families.yaml`** (drives family expansion in `expand.py`): IS621 `A0A0F6B5L8` (a
2195
+ betaine transporter) to `A0A2X3M8B0` (IS621 transposase); phiC31 `Q9T2A6` (a plant NAD(P)H
2196
+ oxidoreductase) to `Q9T221` (phiC31 integrase). The Pfam-query signatures and discovery DOIs were
2197
+ already correct.
2198
+
2199
+ ### Verified clean
2200
+ The 4 EFO cell-type IDs map correctly (EFO:0002067=K562, EFO:0001187=HepG2, EFO:0002784=GM12878,
2201
+ EFO:0005483=ES-Bruce4); all GSH gene symbols are valid HGNC symbols; all 26 Pfam accessions resolve with the
2202
+ correct domain name.
2203
+
2204
+ ## [4.0.2] - 2026-06-09 - Citation-correctness patch: full-repo DOI audit
2205
+
2206
+ ### Fixed
2207
+ A full sweep of all 56 DOIs in the repo (verified via Crossref plus doi.org) found six incorrect or
2208
+ non-existent citations, all now corrected to verified, topically-correct references:
2209
+ - `configs/gsh_validated_heldout.yaml` H11 locus: `10.1371/journal.pone.0113481` (resolved to an unrelated
2210
+ cardiology paper) to `10.1093/nar/gkt1290` (Zhu et al. 2014, *DICE*, NAR 42:e34, the paper that
2211
+ characterized human H11 on chr22q12.2 between DRG1 and EIF4ENIF1).
2212
+ - `configs/delivery_vehicles.yaml` plus `configs/rules/{delivery,payload}.yaml`: `10.1089/hum.2017.084`
2213
+ (non-existent), `10.1089/hum.2009.213` (non-existent), `10.1038/sj.gt.3302529` (unrelated erratum) to
2214
+ `10.1128/JVI.79.15.9933-9944.2005` (Grieger & Samulski, AAV packaging capacity),
2215
+ `10.1128/JVI.72.2.926-933.1998` (multiply-deleted adenovirus vectors), `10.1038/nbt1101-1067`
2216
+ (Wade-Martins, HSV-1 amplicon large-capacity).
2217
+ - `pen_stack/validate/bench_writetype_tasks.py` provenance: `10.1038/s41586-023-06756-4` (diabetes program)
2218
+ and `10.1126/science.abm1123` (freshwater fish) to `10.1016/j.cell.2022.03.045` and
2219
+ `10.1128/JVI.79.15.9933-9944.2005`.
2220
+
2221
+ The remaining 50 DOIs resolve correctly; three legacy DOIs in `mech/pfam_whitelist.yaml` (Rice 1995 Cell,
2222
+ Kholodii 1997 Res Microbiol, Prudhomme 2002 J Bacteriol) carry full author/year/journal references and are
2223
+ real classic papers whose pre-modern DOIs do not resolve at doi.org, left unchanged (a registration artifact,
2224
+ not an error).
2225
+
2226
+ ## [4.0.1] - 2026-06-09 - Data-correctness patch: writer-verification panel verified against Perry 2025
2227
+
2228
+ ### Fixed
2229
+ - **The frozen writer-verification panel is now verbatim from the measured Perry 2025 ISCro4 DMS.** The offline-fallback panel
2230
+ in `atlas/writer_verify.py` previously used illustrative Z-scores (2.6/2.1/1.7) and invented control
2231
+ variants (G15D/P88R/L120E), and `_CORE_RESIDUES` used illustrative arginines. Replaced with the real values
2232
+ from `science.adz0276` Table S3: the top-3 enhancers N322P (Z 0.754), H50K (0.742), R278M (0.709), real
2233
+ near-neutral variants (V21R, S312Q, G286T), the most-deleterious variants (R132E -5.40, R137E -5.12,
2234
+ R195D -4.98), and the documented catalytic residues D11/E60/D102/D105/S241 ("Residue Groups" sheet). The
2235
+ real-DMS path (on the VM/Drive) was already correct; only the offline fallback constants were illustrative.
2236
+ Added `test_writer_verification.py::test_frozen_panel_matches_real_perry_dms_table_s3` to guard against drift.
2237
+
2238
+ ## [4.0.0] - 2026-06-09 - The Oracle Mesh (on top of the foundation models) plus writer verification
2239
+
2240
+ A major bump: the substrate now composes the biomolecular foundation models under one contract and verifies
2241
+ the writer enzyme itself. Each component is SHA-locked. No de-novo writer invention: score
2242
+ and critique only (the pen-assemble lesson).
2243
+
2244
+ ### Added
2245
+ - **The oracle mesh.** `pen_stack/oracles/` with `OracleResult{value, provenance(model+version),
2246
+ native_uncertainty, scope_card, in_scope, extrapolating, output_kind, available, cached}`. Adapters:
2247
+ `genome.py` (AlphaGenome OOD-gated; Evo2 likelihood=claim / generation=candidate; ChromBPNet/Borzoi
2248
+ baseline), `structure.py` (AlphaFold3/Boltz-2/Chai-1/Protenix plus `consensus()` that widens the interval on
2249
+ cross-oracle disagreement), `protein_design.py` (RFdiffusion/ProteinMPNN/ESM3, all candidates), `rna.py`
2250
+ (ViennaRNA, real, hard fold-legality), `energetics.py` (bridge off-target, MC3 gate >=0.77).
2251
+ `configs/oracles/scope_cards.yaml` (11 models); deterministic version-pinned `oracle_cache/`. Guard:
2252
+ the generative candidate `as_claim()` raises. `docs/oracles.md`; `prereg/ws_o.yaml`.
2253
+ - **Writer verification.** `pen_stack/atlas/writer_verify.py`: DMS- and structure-grounded variant
2254
+ scoring (measured=claimable, unmeasured=not), `blind_recovery` recovers N322P/H50K/R278M above
2255
+ measured-worse controls, and `critique_candidate` (fold/active-site/deliverable/reachable) wired into
2256
+ `verify()` as `Verdict.writer_critique`, always `no_claim=True`. `docs/writer_verification.md`;
2257
+ `prereg/ws_wv.yaml`.
2258
+ - **Mesh upgrade plus delivery oracle.** `wgenome/mesh_features.py` (OOD-gated feature hook plus blind
2259
+ re-validation reporting parity vs v3.x when oracles are deferred) plus a computable
2260
+ `delivery.aav_packaging_margin` soft rule (titre drops near the AAV capsid limit). `prereg/ws_atlas.yaml`.
2261
+
2262
+ ### Changed
2263
+ - Version 3.4.0 to 4.0.0; `Verdict` gains `writer_critique`; M1 plus writer-verification note plus M2 updates.
2264
+
2265
+ ## [3.4.0] - 2026-06-09 - The Environment (train/eval surface plus bench v0.3 plus outcome-calibration)
2266
+
2267
+ v3.4 turns the thin Gym interface into a full environment an AI agent can be trained and graded in, ships
2268
+ Genome-Writing Bench v0.3 (multi-write-type plus adversarial robustness), and tests whether plan-confidence
2269
+ actually predicts documented outcomes. Each component is SHA-locked. The environment is an
2270
+ interface plus an evaluation harness (a near-one-shot decision), no RL-superiority claim.
2271
+
2272
+ ### Added
2273
+ - **The genome-writing environment.** `pen_stack/env/genome_writing_env.py` upgraded to a full
2274
+ `gymnasium.Env`: a 5-stage MDP (write_type, site, writer, cargo, delivery) whose step validity comes
2275
+ from the v3.3 verifier and whose reward is the legality gate times the L4 calibrated plan confidence, with a
2276
+ reserved abstain action for a justified refusal. `pen_stack/env/policies.py` (random plus greedy-planner).
2277
+ Passes `gymnasium.utils.env_checker.check_env`; greedy(planner) >= random and greedy-legal on the frozen
2278
+ seed set. `docs/environment.md`; `prereg/ws_env.yaml` plus lock.
2279
+ - **Genome-Writing Bench v0.3.** `multi_write_type_legality` routes plus judges legality across all 6
2280
+ non-insertion write types (accuracy 1.0, ungrounded 0.0); `adversarial_robustness` probes T13-T16
2281
+ (out-of-scope-in-disguise, contradictory constraints, prompt-injection, distribution-shift): the
2282
+ verifier-backed agent passes 4/4 vs an over-confident baseline 0/4, no-fabrication holds including under
2283
+ injection. Leaderboard v0.3 robustness contrast. `prereg/ws_bench.yaml` plus lock.
2284
+ - **Plan-confidence calibrated against documented outcomes.** `pen_stack/validate/outcome_calibration.py`:
2285
+ a plan-level reliability diagram plus ECE plus bootstrap-CI selective prediction on the DOI writer panel. The
2286
+ result: useful for ranking (high-confidence 0.30 vs low-confidence 0.0 documented-choice recovery, gap
2287
+ CI95 [0.17, 0.43], monotone) but poorly calibrated in absolute terms (ECE 0.71). Feeds M-UQ.
2288
+ `prereg/ws_cal.yaml` plus lock.
2289
+
2290
+ ### Changed
2291
+ - Version 3.3.0 to 3.4.0; bench 0.2.1 to 0.3; README updated for v3.4; M2/M-UQ manuscript updates.
2292
+
2293
+ ## [3.3.0] - 2026-06-09 - The Verifier (a type checker for genome writes)
2294
+
2295
+ v3.3 lifts the laws of genome writing into a versioned, machine-readable rule base and exposes a single
2296
+ `verify(design) -> Verdict` call (legal/illegal plus named rule plus calibrated confidence plus scope) over Python,
2297
+ REST, and MCP. Each component is SHA-locked.
2298
+
2299
+ ### Added
2300
+ - **Rule base plus solver.** `pen_stack/rules/{schema,evaluators,loader,solver}.py` plus `configs/rules/*.yaml`
2301
+ (9 rules across reachability/fold/payload/multiplex/delivery), each id/kind/mechanism/param/provenance(DOI)/
2302
+ test. Evaluators delegate to the existing validated functions; a parity test proves no decision changed.
2303
+ Legality and confidence are kept as distinct axes.
2304
+ - **Delivery palette.** `configs/delivery_vehicles.yaml` plus `planner/delivery_vehicles.py`: 8 vehicles
2305
+ (AAV single/dual, lentivirus, HDAd, HSV amplicon, LNP-mRNA, eVLP, electroporation) with capacity/integration/
2306
+ cargo-form/DOIs; delivery rules (hard rejects plus soft penalties plus an immunogenicity-magnitude scope flag).
2307
+ - **Write-type router.** `planner/router.py` plus `configs/write_types.yaml`: dispatches insertion/
2308
+ excision/inversion/replacement/regulatory_rewrite/landing_pad_install/multiplex; unsupported types defer.
2309
+ - **Verification service.** `pen_stack/verify/{service,schema}.py`: `verify(design) -> Verdict`; `POST
2310
+ /verify` plus MCP `verify_write`; `docs/verify.md`. No fabrication (every number tool-sourced).
2311
+ - **Bench v0.2.1 plus agent.** T12 rule-grounded legality-with-explanation (verifier reason accuracy 1.0
2312
+ vs ungrounded 0.0); the agent submits its plan to the verifier. Bench 12/12 available, planner beats baseline
2313
+ 8/8.
2314
+ - **Docs:** `docs/verify.md`, `docs/rules.md`, `docs/delivery.md`.
2315
+
2316
+ ### Changed
2317
+ - Version 3.2.0 to 3.3.0 (pyproject, `__init__`, CITATION.cff). README updated for v3.3; bench badge v0.2.1.
2318
+
2319
+ ## [3.2.0] - 2026-06-08 - A calibrated, self-aware co-scientist
2320
+
2321
+ The v3.2 cycle makes the genome-writing funnel trustworthy: every value carries a calibrated confidence,
2322
+ an extrapolation flag, and, where the biology is beyond any tool here, an explicit out-of-scope deferral.
2323
+ Each workstream is pre-registered (`prereg/ws_{uq,ep,mc,ba}.yaml`, SHA-locked) and reports its
2324
+ negatives. The Genome-Writing Bench bumps to v0.2.
2325
+
2326
+ ### Added
2327
+ - **Calibrated uncertainty plus OOD.** Conformal prediction intervals (durability expression) and APS /
2328
+ Mondrian prediction sets (safety, silenced) wrapping the existing heads with no retraining
2329
+ (`pen_stack.wgenome.uncertainty`); an OOD detector that widens intervals out-of-distribution
2330
+ (`pen_stack.wgenome.ood`); selective prediction plus plan-level confidence
2331
+ (`pen_stack.validate.selective_prediction`). Held-out coverage 0.895 vs 0.90 nominal; risk-coverage accuracy
2332
+ 0.739 to 0.930 under abstention. OOD across human cell types is weak (0.65-0.73), reported as a heuristic.
2333
+ - **Epistemic scoping.** A three-tier status (grounded-confident / grounded-extrapolating /
2334
+ not-computable) on every agent output (`pen_stack.agent.epistemic`); a known-unknowns registry plus a scope
2335
+ matcher (`configs/known_unknowns.yaml`, `pen_stack.agent.scope`, `docs/scope.md`) that defers out-of-scope
2336
+ questions (deferral 1.0, false-defer 0.0); abstention in the agent. The no-fabrication gate is intact.
2337
+ - **Mechanistic filters.** A hard target-site/PAM/att-site reachability reject
2338
+ (`pen_stack.planner.target_site`, `configs/target_sites.yaml`; controls 9/9); vehicle-specific
2339
+ delivery-sequence penalties (`pen_stack.planner.delivery_constraints`); and an off-target energetics
2340
+ model (`pen_stack.bridge.offtarget_energetics`) that beats the 0.77 baseline at held-out AUROC 0.88 on the
2341
+ comparable (core-disrupted) construction and ships as the default ranker. A reviewer-driven re-run
2342
+ (`by_negative_construction`) shows that gap is mostly the core-penalisation artifact; with the core held
2343
+ matched the non-core substitution-identity gain is real but modest (delta ~0.04, 0.687 vs 0.646). Both AUROCs
2344
+ carry a favourable-negative-set caveat (decoys derived from real off-targets; no non-recombining background).
2345
+ - **Bench v0.2 plus uncertainty-aware agent.** Four trust tasks (T8 calibration, T9 selective prediction,
2346
+ T10 OOD honesty, T11 out-of-scope refusal) contrasting the uncertainty-aware agent with an over-confident
2347
+ baseline (4/4); PEN-Agent emits confidence plus epistemic status plus abstains; UI surfaces them. Bench re-SHA-locked.
2348
+ - **Gymnasium interface (optional).** A thin `gymnasium.Env` over the planner (`pen_stack.env`,
2349
+ `[env]` extra) for agent-developer interoperability, interface only, no RL superiority claimed.
2350
+ - **Docs:** `docs/uncertainty.md`, `docs/scope.md`, `docs/mechanistic_constraints.md`; M-UQ methods note plus
2351
+ M1/M2 manuscript updates. The Opentrons workstream is deferred to `docs/BACKLOG.md`.
2352
+
2353
+ ### Changed
2354
+ - Version 3.1.0 to 3.2.0 (pyproject, `__init__`, CITATION.cff). README updated for v3.2; badges plus bench
2355
+ v0.2. The bridge off-target default ranker is now the energetics model when its penalty table is present.
2356
+
2357
+ ## [3.1.0] - 2026-06-04 - Publishable contributions plus an adopted benchmark
2358
+
2359
+ The v3.1 cycle completes (workstreams A-H). It hardens the planning benchmark, surrounds the
2360
+ models with strong baselines, adds a predicted-structure safety axis, and ships the first benchmark and
2361
+ grounded agent for the genome-writing side. Every workstream is pre-registered (`prereg/ws_*.yaml`,
2362
+ SHA-locked) and reports its negatives.
2363
+
2364
+ ### Added
2365
+ - **Strong baselines plus safety primary-metric switch.** An endogenous-expression baseline (TRIP-trained
2366
+ Spearman 0.51 vs AlphaGenome ES-Bruce4 proxy 0.43), a multi-mark ablation (all-marks >= best single), and a
2367
+ published GSH rule-set: safe-harbour discrimination (learned 0.92, 95% CI [0.82, 0.98] vs distance-rule
2368
+ 0.38, delta CI excludes zero) is now the primary safety metric; the circular `genotoxic_cis` AUROC is a
2369
+ labeled diagnostic. (`pen_stack.wgenome.gsh_baseline`, `pen_stack.validate.durability_baselines`.)
2370
+ - **AlphaGenome integration.** A hosted-API provider with an offline cache; predicted-vs-measured track
2371
+ validation (HepG2 ATAC Pearson 0.85) with a score-level low-confidence flag; a 3D structural-risk
2372
+ axis from contact-map deltas (`pen_stack.wgenome.{providers,chromatin_seq,structure3d}`,
2373
+ `pen_stack.validate.seq_vs_measured`).
2374
+ - **Cargo Polish.** A cargo-sequence silencing-risk scan (`pen_stack.planner.cargo_polish`).
2375
+ - **Genome-Writing Bench v0.1 plus PEN-Agent.** The first writing-side benchmark (`benchmarks/`,
2376
+ `bench/run.py`) with deterministic scorers, a leaderboard, and a real LLM-agent baseline; a grounded
2377
+ write-planning state machine with a no-fabrication hard gate (`pen_stack.agent.pen_agent`).
2378
+ - **Local recalibration / private-data adaptation.** Gated recalibration / fine-tuning on private
2379
+ data, in-container; the adapted model activates only if it beats the released model AND a no-skill
2380
+ baseline; the released model is provably unchanged (`pen_stack.adapt`).
2381
+ - **Multiplex plus guide QC.** A pairwise translocation-risk screen (`pen_stack.planner.multiplex`,
2382
+ surfaced in PEN-Agent) and a bridge-RNA guide ranker (`pen_stack.bridge.guide_qc`).
2383
+ - **Release plus dissemination.** README/badges updated for v3.1, `docs/quickstart.md`,
2384
+ `docs/positioning.md`, the leaderboard submission guide, the dissemination log, and version 3.1.0.
2385
+
2386
+ ### Changed
2387
+ - The planning benchmark's `recovery_at_k` ranking is now deterministic (stable sort plus tie-breakers).
2388
+ - The LLM stack defaults to the local Ollama model on the compute tier with an automatic hosted-Nemotron
2389
+ fallback, a cooldown cache, and bounded timeouts (no more multi-minute stalls when a provider is absent).
2390
+
2391
+ ## [3.1.0a0] - 2026-06-04 - De-circularize the planning benchmark (gate)
2392
+
2393
+ This release opens with de-circularizing the
2394
+ planning benchmark before anything builds on it.
2395
+
2396
+ ### Changed
2397
+ - **The "discriminating-stratum recovery@10 = 1.00 vs 0.00 (McNemar p, CI)" is now labeled
2398
+ definitional, not predictive,** everywhere (README, manuscript abstract, `prereg/paper3.yaml`,
2399
+ `validate/paper3_benchmark.py` docstring). An on-target identity term dominates the score, so the planner
2400
+ ranks the goal's own gene first by construction. Documented in `docs/benchmark_circularity.md`.
2401
+ - The intent result is reframed as a specification-compliance correctness table (`validate/intent_specification.py`,
2402
+ 7/7), with no recovery/p-value/CI language.
2403
+
2404
+ ### Added (the non-circular replacements)
2405
+ - **Blind safe-harbour site discovery (the new lead result):** `validate/blind_gsh_discovery.py` plus
2406
+ `configs/gsh_validated_heldout.yaml` (5 DOI-validated held-out GSH, gene-anchored to hg38) plus a
2407
+ frozen/SHA-locked `data/gsh_matched_controls.parquet`. Run genome-wide (no on-target term), the planner's
2408
+ writability separates validated GSH from matched-context controls at AUROC 0.92 (safety-only 0.50).
2409
+ - **Diversified writer-family recovery:** `validate/writer_recovery.py` plus `data/writer_panel.csv` (8 writes,
2410
+ 4 families, DOIs). recovery@1 = 1.0 vs prevalence 0.25 (smallest-capacity DSB-free writer that fits
2411
+ the cargo).
2412
+ - **Within-locus ranking** (descriptive): `validate/within_locus_ranking.py`, AAVS1 documented bin at the
2413
+ 93rd within-locus percentile (top quartile); CLYBL at the 34th (a negative result).
2414
+ - **Consolidated report** `scripts/p3_benchmark_report.py` to `out/ws_a_report.md`; `prereg/ws_a.yaml` plus
2415
+ SHA lock. Blind AUROC reported, no circular claims remain.
2416
+
2417
+ ## [Unreleased] - 2026-06-03 - Reframing, repository polish, coverage, hybrid LLM
2418
+
2419
+ ### Added
2420
+ - **Hybrid LLM backend** (`pen_stack/rag/llm.py`, `configs/llm.yaml`): a strong hosted model for
2421
+ reasoning/agent/Q&A (NVIDIA Nemotron, OpenAI-compatible, free) with automatic fallback to the local
2422
+ Ollama model, then to the deterministic no-LLM path. One `provider` switch. The agent and RAG were
2423
+ refactored onto a single provider-agnostic `chat()` (NVIDIA tool-call IDs and Ollama native message
2424
+ threading both handled). The LLM stays non-load-bearing (every number/citation still comes from
2425
+ validated tools), so the model choice does not affect scientific reproducibility; it only improves
2426
+ orchestration (Nemotron planned a goal in 2 tool calls vs the local 7B's 8-call loop). Core scientific
2427
+ compute stays local/VM and uses no LLM. API keys are read from an env var or a gitignored file and
2428
+ are never committed.
2429
+
2430
+ ### Changed
2431
+ - **The bridge tool reframed to its scope.** `pen-bridge` is positioned as the first measured-data-validated
2432
+ tool that nominates and ranks candidate off-target locations for bridge recombinases, a
2433
+ screening tool, not a quantitative safety calculator. The AUROC 0.77 vs 0.62 result is stated with
2434
+ its caveat (favourable negative set; mostly tests core integrity), and the magnitude limitation
2435
+ (sequence-risk does not rank recombination amount, rho ~0.30) is named as the single most important
2436
+ limitation. Application-Note tier, first-of-its-kind for an unoccupied gap; the Writable Genome remains
2437
+ the flagship. Manuscript plus `prereg/paper4.yaml` plus summaries updated.
2438
+ - **Variant-effect reframed:** the DMS recovers KNOWN enhancers (a catalogue feature), it is not a novel
2439
+ variant-design method; EVOLVEpro is the engine to wrap when generating new variants.
2440
+ - **Repository made clean ASCII:** removed all decorative emojis and em/en dashes and other non-ASCII
2441
+ punctuation across code, docs, configs, and manuscripts (box-drawing tree characters kept).
2442
+
2443
+ ### Added
2444
+ - 72-system ortholog characterisation (`bridge/ortholog_screen.py`), explicitly descriptive (Table S1 has
2445
+ no activity label): sequence-similarity organisation vs the validated standout ISCro4 (IS621 ranks most
2446
+ similar, a sanity check). Exploratory secondary result, N ~72.
2447
+ - Coverage: CI runs `pytest --cov`, uploads to Codecov, and publishes a self-hosted coverage badge
2448
+ (`tools/make_coverage_badge.py` to `.github/badges/coverage.svg`). Unit-test coverage of the core logic
2449
+ is 69% (integration-only modules that need GPU/VM/network/LLM are excluded via `[tool.coverage.run]`).
2450
+ - Professional, emoji-free README with connected-repo badges (genome-atlas / mech-class / pen-score /
2451
+ pen-assemble / pen-compare), an architecture diagram, and the problem/gaps explanation.
2452
+
2453
+ ## [3.0.0a5] - 2026-06-02 - Bridge-recombinase off-target engine
2454
+
2455
+ The first public instrument: a bridge-recombinase off-target screening tool.
2456
+
2457
+ ### Added
2458
+ - **Off-target engine** (`pen_stack/bridge/offtarget.py` plus `configs/bridge_offtarget_profile.yaml`):
2459
+ a genome-wide hg38 pseudosite scan (CT-core seed, per-chromosome, memory-bounded) plus a position-weight
2460
+ risk model grounded in the published mechanism. Beats naive Hamming: AUROC 1.00 vs 0.59 at
2461
+ separating core-preserving (real-risk) from core-disrupting (abolished) sites. Exposes
2462
+ `predict_offtargets(family, site)`, completing the planner cargo hook.
2463
+ - **Fold / cross-loop QC** (`bridge/fold_qc.py`): a ViennaRNA fold (verified MFE on a 190-nt design) plus
2464
+ TBL/DBL cross-loop complementarity.
2465
+ - **Activity framework** (`bridge/activity.py`): an exploratory DMS plus 72-system trainer (deferred; data paywalled).
2466
+ - **`pen-bridge`** (`bridge/pipeline.py`, `bridge/cli.py`, `/bridge/design` API): wraps the Arc
2467
+ BridgeRNADesigner (verified) and adds the off-target plus QC layer.
2468
+ - `validate/paper4_validation.py` plus `scripts/p4_genome_scan.py`; `prereg/paper4.yaml` plus SHA lock.
2469
+
2470
+ ### Notes
2471
+ - The pre-registered criteria were met (or gated): the off-target engine,
2472
+ the ViennaRNA fold, and the designer wrap are verified on the VM (real hg38 scan: chr22 in ~21 s). The blind
2473
+ recall of Perry 2025's measured off-targets and the DMS/activity model are gated on the paywalled
2474
+ Perry 2025 supplementary (drop in via `ingest.load_offtarget_profile`). 68 tests green; ruff clean.
2475
+
2476
+ ## [3.0.0a4] - 2026-06-02 - The write planner and agentic platform
2477
+
2478
+ Inverse design plus the paper-defining recovery@k benchmark plus the agentic platform.
2479
+
2480
+ ### Added
2481
+ - **Inverse-design optimiser** (`pen_stack/planner/optimize.py`, `configs/intent_weights.yaml`): an
2482
+ `edit_intent`-conditioned objective whose `target_gene_sign` flips whether hitting the target gene is
2483
+ penalised or rewarded, so the same TRAC site ranks #1 (knock-in) vs #101 (safe-harbour).
2484
+ - **Cargo/delivery** (`planner/cargo.py`, `planner/delivery.py`): a donor spec plus size check plus a delivery rule
2485
+ table; bridge/seek off-target via an optional off-target hook.
2486
+ - **End-to-end Planner** (`planner/pipeline.py`, `report.py`, `/plan` API, `pen-stack plan` CLI): ranked,
2487
+ fully traceable plans with per-field provenance.
2488
+ - **Two-stratum recovery@k benchmark** (`validate/paper3_benchmark.py`, `data/benchmark_panel.csv`,
2489
+ `prereg/paper3.yaml`): discriminating stratum planner 1.00 vs baseline 0.00, McNemar p=0.0156, gap CI
2490
+ [1.0,1.0] excludes zero; control tie 0.67=0.67. The panel is cited to Europe-PMC-verified sources.
2491
+ - **Forward hypotheses** (`validate/forward_hypotheses.py`): date-stamped novel F8/SERPINA1/CISH/HBA1
2492
+ proposals plus a grounded cited ranking.
2493
+ - **Agentic platform:** `agent/tools.py` plus `agent/orchestrator.py` (Ollama tool-calling, an auditable trace,
2494
+ no-fabrication, refusals), `agent/mcp_server.py` (fastmcp), `docker-compose.yml` plus `docker/ui.Dockerfile`
2495
+ plus a Streamlit Agent page plus `docs/DEPLOY.md`/`docs/MCP.md`, `validate/agent_eval.py`.
2496
+ - Shipped `data/curated/gene_coords.parquet` (GENCODE-derived) so tools work in any container.
2497
+
2498
+ ### Notes
2499
+ - The pre-registered criteria were met (`prereg/paper3.yaml` plus `SHA256_LOCK_phase3.json`).
2500
+ The agent is verified on the VM in LLM mode (no-fabrication plus plan-equivalence plus refusals all pass). 63 tests
2501
+ green; ruff clean. Wet-lab (3.7) skipped, non-gating. The bridge off-target hook completes separately.
2502
+
2503
+ ## [3.0.0a3] - 2026-06-02 - The Writer Atlas and unified stack
2504
+
2505
+ The broad, cross-family Writer Atlas, the writer-to-locus cross-link, and the installable platform.
2506
+
2507
+ ### Added
2508
+ - **Writer Atlas** (`pen_stack/atlas/expand.py`, `atlas.parquet`): 33,370 systems across 8 families
2509
+ (31,885 IS110/IS1111 orthologs plus curated cores/reps), every row confidence-tagged plus at least 1 source DOI,
2510
+ targeting metadata inherited from the WT-KB. `configs/atlas_families.yaml` drives the UniProt queries.
2511
+ - **Mechanism at scale** (`pen_stack/mech/`): ported the audited 18-family Pfam whitelist v1.2.1; composite
2512
+ co-occurrence rules; core agreement 1.00 vs audited labels; conflicting calls go to a review queue.
2513
+ - **Therapeutic readiness** (`pen_stack/score/therapeutic.py`): deliverability/cargo/human-cell axes,
2514
+ components retained (ISCro4 326aa to AAV).
2515
+ - **Cross-link** (`pen_stack/atlas/crosslink.py`): bidirectional writer-to-locus queries; AAVS1 held-out
2516
+ check passes (0.90 writability plus bridge-reachable). Per-family caches for k562/hepg2/hspc.
2517
+ - **Variant proposal** (`pen_stack/atlas/variant_propose.py`): a point-mutation framework plus a retrospective
2518
+ harness, no chimeras; DMS model pluggable.
2519
+ - **Living-literature monitor** (`pen_stack/monitor/`): a Europe PMC living-database engine; the back-test surfaces ISPpu10;
2520
+ never auto-edits the atlas; every candidate cited.
2521
+ - **Grounded RAG** (`pen_stack/rag/`, `pen_stack/agent/guardrails.py`): numbers from tool calls, claims
2522
+ cited, clinical directives refused; an optional Ollama/Qwen phrasing layer (presentation only).
2523
+ - **Stack:** unified CLI subcommands, a FastAPI server (`pen_stack/server/api.py`), a Streamlit platform UI
2524
+ (Writer Atlas plus Ask pages), an mkdocs site plus 4 use-case tutorials. 46 tests green; ruff clean.
2525
+
2526
+ ### Notes
2527
+ - The pre-registered criteria were met (`prereg/paper2.yaml` plus `SHA256_LOCK_phase2.json`);
2528
+ the atlas Zenodo DOI is pending author upload. Verified on the VM (Docker): API, UI (:8501), RAG with Qwen.
2529
+
2530
+ ## [3.0.0a0] - 2026-06-01 - Initial monorepo
2531
+
2532
+ A fresh v3.0 monorepo. It supersedes the v1.0 platform repository (archived) and consolidates the five prior
2533
+ repositories (`genome-atlas`, `mech-class`, `pen-score`, `pen-assemble`, `pen-compare`) as provenance.
2534
+
2535
+ ### Added
2536
+ - A monorepo scaffold: 13 modules (`atlas`, `mech`, `score`, `wgenome`, `planner`, `bridge`, `monitor`,
2537
+ `rag`, `agent`, `ui`, `data`, `validate`, `server`), `pyproject.toml`, a Docker image spec, the `penctl`
2538
+ laptop-to-VM orchestrator, CI, `configs/`, `prereg/`.
2539
+ - `docs/INFRA.md`: the three-tier (laptop / VM / Drive) Docker-only, SFTP-only workflow.
2540
+ - `configs/llm.yaml`: a single LLM switch (Ollama plus Qwen2.5-7B-Instruct, Apache-2.0).
2541
+ - `configs/datasets.yaml`: pinned dataset accessions plus verified IDs (see VERIFICATION_REPORT_v3.0).
2542
+ - **WT-KB** (`pen_stack/atlas/`): 8 fully-sourced writer families with reachability tiers; the schema enforces the at-least-1-DOI sourcing rule.
2543
+ - **Re-grounded axes** (`pen_stack/score/recalibrate.py`, `configs/score_axes.yaml`): `S_Cargo` from measured bp, `S_Prog` from targeting modality, `length_aa` backfilled, no per-enzyme overrides.
2544
+ - **Canonical universe** (`pen_stack/atlas/universe.py::assemble`): one path joining the 1,058-entity universe plus WT-KB plus crosswalk; a cross-module consistency test.
2545
+ - **Descriptive scorecard** (`pen_stack/atlas/scorecard.py`): reframed from the circular certification; blind concordance recovers ISCro4 as the bridge standout without naming it. 21 tests green.
2546
+
2547
+ ### Notes
2548
+ - Independent verification of all datasets/IDs/DOIs/tools completed: no critical errors in the v3.0 plan.
2549
+ - All pre-registered success criteria were met (`prereg/phase0.yaml` plus SHA lock).