pen-stack 5.0.0__tar.gz → 5.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (306) hide show
  1. {pen_stack-5.0.0 → pen_stack-5.1.0}/CHANGELOG.md +32 -0
  2. {pen_stack-5.0.0 → pen_stack-5.1.0}/CITATION.cff +2 -2
  3. {pen_stack-5.0.0 → pen_stack-5.1.0}/PKG-INFO +24 -5
  4. {pen_stack-5.0.0 → pen_stack-5.1.0}/README.md +23 -4
  5. pen_stack-5.1.0/configs/delivery_vehicles.yaml +185 -0
  6. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/__init__.py +1 -1
  7. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/agent/cite.py +1 -0
  8. pen_stack-5.1.0/pen_stack/planner/delivery_immunology.py +160 -0
  9. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/verify/schema.py +2 -0
  10. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/verify/service.py +16 -1
  11. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack.egg-info/PKG-INFO +24 -5
  12. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack.egg-info/SOURCES.txt +3 -0
  13. pen_stack-5.1.0/prereg/SHA256_LOCK_ws_immune.json +8 -0
  14. pen_stack-5.1.0/prereg/ws_immune.yaml +43 -0
  15. {pen_stack-5.0.0 → pen_stack-5.1.0}/pyproject.toml +1 -1
  16. pen_stack-5.0.0/configs/delivery_vehicles.yaml +0 -105
  17. {pen_stack-5.0.0 → pen_stack-5.1.0}/LICENSE +0 -0
  18. {pen_stack-5.0.0 → pen_stack-5.1.0}/MANIFEST.in +0 -0
  19. {pen_stack-5.0.0 → pen_stack-5.1.0}/bench/run.py +0 -0
  20. {pen_stack-5.0.0 → pen_stack-5.1.0}/benchmarks/genome_writing_bench/LEADERBOARD.md +0 -0
  21. {pen_stack-5.0.0 → pen_stack-5.1.0}/benchmarks/genome_writing_bench/README.md +0 -0
  22. {pen_stack-5.0.0 → pen_stack-5.1.0}/benchmarks/genome_writing_bench/SHA256SUMS +0 -0
  23. {pen_stack-5.0.0 → pen_stack-5.1.0}/benchmarks/genome_writing_bench/SUBMISSIONS.md +0 -0
  24. {pen_stack-5.0.0 → pen_stack-5.1.0}/benchmarks/genome_writing_bench/tasks.yaml +0 -0
  25. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/atlas_families.yaml +0 -0
  26. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/bridge_offtarget_profile.yaml +0 -0
  27. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/cargo_polish.yaml +0 -0
  28. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/cell_types.yaml +0 -0
  29. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/datasets.yaml +0 -0
  30. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/delivery_constraints.yaml +0 -0
  31. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/delivery_rules.yaml +0 -0
  32. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/gates_v3.yaml +0 -0
  33. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/gsh_validated_heldout.yaml +0 -0
  34. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/intent_weights.yaml +0 -0
  35. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/known_unknowns.yaml +0 -0
  36. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/llm.yaml +0 -0
  37. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/monitor_queries.yaml +0 -0
  38. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/oracles/scope_cards.yaml +0 -0
  39. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/rules/delivery.yaml +0 -0
  40. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/rules/fold.yaml +0 -0
  41. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/rules/multiplex.yaml +0 -0
  42. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/rules/payload.yaml +0 -0
  43. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/rules/reachability.yaml +0 -0
  44. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/score_axes.yaml +0 -0
  45. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/target_sites.yaml +0 -0
  46. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/universe_crosswalk.yaml +0 -0
  47. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/write_types.yaml +0 -0
  48. {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/wtkb_curated.yaml +0 -0
  49. {pen_stack-5.0.0 → pen_stack-5.1.0}/data/curated/bridge_offtarget_energetics.json +0 -0
  50. {pen_stack-5.0.0 → pen_stack-5.1.0}/data/curated/bridge_offtarget_profile_measured.parquet +0 -0
  51. {pen_stack-5.0.0 → pen_stack-5.1.0}/data/curated/gene_coords.parquet +0 -0
  52. {pen_stack-5.0.0 → pen_stack-5.1.0}/data/curated/unified_editor_universe.parquet +0 -0
  53. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/BACKLOG.md +0 -0
  54. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/DEPLOY.md +0 -0
  55. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/INFRA.md +0 -0
  56. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/MCP.md +0 -0
  57. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/RELEASING.md +0 -0
  58. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/REPRO.md +0 -0
  59. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/agent.md +0 -0
  60. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/alphagenome_feasibility.md +0 -0
  61. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/benchmark_circularity.md +0 -0
  62. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/cards/atlas.md +0 -0
  63. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/cards/durability.md +0 -0
  64. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/cards/safety.md +0 -0
  65. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/co_scientist.md +0 -0
  66. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/delivery.md +0 -0
  67. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/dissemination.md +0 -0
  68. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/environment.md +0 -0
  69. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/index.md +0 -0
  70. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/mechanistic_constraints.md +0 -0
  71. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/oracles.md +0 -0
  72. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/positioning.md +0 -0
  73. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/private_data_formats.md +0 -0
  74. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/quickstart.md +0 -0
  75. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/rules.md +0 -0
  76. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/scope.md +0 -0
  77. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/scorecard.md +0 -0
  78. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/tutorials/compare-families.md +0 -0
  79. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/tutorials/score-deliverability.md +0 -0
  80. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/tutorials/where-can-i-write.md +0 -0
  81. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/tutorials/which-writer-reaches-locus.md +0 -0
  82. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/uncertainty.md +0 -0
  83. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/verify.md +0 -0
  84. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/world_model.md +0 -0
  85. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/writer_verification.md +0 -0
  86. {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/wtkb.md +0 -0
  87. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/_resources.py +0 -0
  88. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/adapt/__init__.py +0 -0
  89. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/adapt/finetune.py +0 -0
  90. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/adapt/ingest.py +0 -0
  91. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/adapt/pipeline.py +0 -0
  92. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/adapt/recalibrate.py +0 -0
  93. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/adapt/report.py +0 -0
  94. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/agent/__init__.py +0 -0
  95. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/agent/co_scientist.py +0 -0
  96. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/agent/epistemic.py +0 -0
  97. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/agent/guardrails.py +0 -0
  98. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/agent/mcp_server.py +0 -0
  99. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/agent/orchestrator.py +0 -0
  100. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/agent/pen_agent.py +0 -0
  101. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/agent/scope.py +0 -0
  102. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/agent/tools.py +0 -0
  103. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/atlas/__init__.py +0 -0
  104. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/atlas/build_wtkb.py +0 -0
  105. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/atlas/crosslink.py +0 -0
  106. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/atlas/expand.py +0 -0
  107. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/atlas/schema.py +0 -0
  108. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/atlas/scorecard.py +0 -0
  109. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/atlas/universe.py +0 -0
  110. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/atlas/variant_propose.py +0 -0
  111. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/atlas/writer_verify.py +0 -0
  112. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/bridge/__init__.py +0 -0
  113. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/bridge/activity.py +0 -0
  114. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/bridge/cli.py +0 -0
  115. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/bridge/fold_qc.py +0 -0
  116. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/bridge/guide_qc.py +0 -0
  117. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/bridge/ingest.py +0 -0
  118. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/bridge/offtarget.py +0 -0
  119. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/bridge/offtarget_energetics.py +0 -0
  120. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/bridge/ortholog_screen.py +0 -0
  121. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/bridge/pipeline.py +0 -0
  122. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/cli.py +0 -0
  123. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/data/__init__.py +0 -0
  124. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/data/encode.py +0 -0
  125. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/data/genome.py +0 -0
  126. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/data/ingest_chromatin.py +0 -0
  127. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/data/ingest_integration.py +0 -0
  128. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/data/ingest_safety_annot.py +0 -0
  129. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/data/ingest_trip.py +0 -0
  130. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/env/__init__.py +0 -0
  131. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/env/genome_writing_env.py +0 -0
  132. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/env/policies.py +0 -0
  133. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/graph/__init__.py +0 -0
  134. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/graph/build.py +0 -0
  135. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/graph/cell_types.py +0 -0
  136. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/graph/ingest.py +0 -0
  137. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/graph/query.py +0 -0
  138. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/graph/schema.py +0 -0
  139. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/mech/__init__.py +0 -0
  140. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/mech/classify_atlas.py +0 -0
  141. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/mech/whitelist.py +0 -0
  142. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/monitor/__init__.py +0 -0
  143. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/monitor/europepmc.py +0 -0
  144. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/monitor/run.py +0 -0
  145. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/monitor/triage.py +0 -0
  146. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/oracles/__init__.py +0 -0
  147. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/oracles/cache.py +0 -0
  148. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/oracles/energetics.py +0 -0
  149. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/oracles/genome.py +0 -0
  150. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/oracles/protein_design.py +0 -0
  151. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/oracles/rna.py +0 -0
  152. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/oracles/schema.py +0 -0
  153. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/oracles/structure.py +0 -0
  154. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/__init__.py +0 -0
  155. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/cargo.py +0 -0
  156. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/cargo_polish.py +0 -0
  157. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/delivery.py +0 -0
  158. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/delivery_constraints.py +0 -0
  159. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/delivery_vehicles.py +0 -0
  160. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/multiplex.py +0 -0
  161. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/optimize.py +0 -0
  162. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/pipeline.py +0 -0
  163. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/report.py +0 -0
  164. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/router.py +0 -0
  165. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/target_site.py +0 -0
  166. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/rag/__init__.py +0 -0
  167. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/rag/index.py +0 -0
  168. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/rag/llm.py +0 -0
  169. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/rag/qa.py +0 -0
  170. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/rules/__init__.py +0 -0
  171. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/rules/evaluators.py +0 -0
  172. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/rules/loader.py +0 -0
  173. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/rules/schema.py +0 -0
  174. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/rules/solver.py +0 -0
  175. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/score/__init__.py +0 -0
  176. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/score/recalibrate.py +0 -0
  177. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/score/therapeutic.py +0 -0
  178. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/server/__init__.py +0 -0
  179. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/server/api.py +0 -0
  180. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/ui/__init__.py +0 -0
  181. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/ui/app.py +0 -0
  182. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/__init__.py +0 -0
  183. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/adapt_demo.py +0 -0
  184. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/agent_eval.py +0 -0
  185. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/bench_adversarial_tasks.py +0 -0
  186. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/bench_coscientist_tasks.py +0 -0
  187. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/bench_graph_tasks.py +0 -0
  188. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/bench_rule_tasks.py +0 -0
  189. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/bench_trust_tasks.py +0 -0
  190. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/bench_writetype_tasks.py +0 -0
  191. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/blind_gsh_discovery.py +0 -0
  192. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/cargo_directionality.py +0 -0
  193. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/durability_baselines.py +0 -0
  194. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/forward_hypotheses.py +0 -0
  195. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/guide_qc_demo.py +0 -0
  196. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/intent_specification.py +0 -0
  197. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/offtarget_energetics_eval.py +0 -0
  198. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/out_of_scope_refusal.py +0 -0
  199. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/outcome_calibration.py +0 -0
  200. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/paper3_benchmark.py +0 -0
  201. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/paper4_real_validation.py +0 -0
  202. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/paper4_validation.py +0 -0
  203. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/selective_prediction.py +0 -0
  204. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/seq_vs_measured.py +0 -0
  205. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/target_site_controls.py +0 -0
  206. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/uncertainty_eval.py +0 -0
  207. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/ungrounded_baseline.py +0 -0
  208. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/within_locus_ranking.py +0 -0
  209. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/writer_recovery.py +0 -0
  210. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/verify/__init__.py +0 -0
  211. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/__init__.py +0 -0
  212. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/chromatin_seq.py +0 -0
  213. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/durability.py +0 -0
  214. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/export_tracks.py +0 -0
  215. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/features.py +0 -0
  216. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/gsh_baseline.py +0 -0
  217. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/mesh_features.py +0 -0
  218. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/ood.py +0 -0
  219. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/providers.py +0 -0
  220. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/safety.py +0 -0
  221. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/structure3d.py +0 -0
  222. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/uncertainty.py +0 -0
  223. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/writability.py +0 -0
  224. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack.egg-info/dependency_links.txt +0 -0
  225. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack.egg-info/entry_points.txt +0 -0
  226. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack.egg-info/requires.txt +0 -0
  227. {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack.egg-info/top_level.txt +0 -0
  228. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_phase0.json +0 -0
  229. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_phase1_5.json +0 -0
  230. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_phase2.json +0 -0
  231. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_phase3.json +0 -0
  232. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_a.json +0 -0
  233. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_atlas.json +0 -0
  234. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_b.json +0 -0
  235. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_ba.json +0 -0
  236. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_ba_v33.json +0 -0
  237. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_ba_v45.json +0 -0
  238. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_bench.json +0 -0
  239. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_c.json +0 -0
  240. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_cal.json +0 -0
  241. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_cite.json +0 -0
  242. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_crit.json +0 -0
  243. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_ct.json +0 -0
  244. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_d.json +0 -0
  245. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_e.json +0 -0
  246. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_env.json +0 -0
  247. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_ep.json +0 -0
  248. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_f.json +0 -0
  249. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_g.json +0 -0
  250. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_graph.json +0 -0
  251. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_h.json +0 -0
  252. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_mc.json +0 -0
  253. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_mon.json +0 -0
  254. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_o.json +0 -0
  255. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_plan.json +0 -0
  256. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_r.json +0 -0
  257. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_route.json +0 -0
  258. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_uq.json +0 -0
  259. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_v.json +0 -0
  260. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_wv.json +0 -0
  261. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/paper1.yaml +0 -0
  262. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/paper2.yaml +0 -0
  263. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/paper3.yaml +0 -0
  264. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/paper4.yaml +0 -0
  265. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/phase0.yaml +0 -0
  266. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_a.yaml +0 -0
  267. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_atlas.yaml +0 -0
  268. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_b.yaml +0 -0
  269. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_ba.yaml +0 -0
  270. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_ba_v33.yaml +0 -0
  271. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_ba_v45.yaml +0 -0
  272. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_bench.yaml +0 -0
  273. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_c.yaml +0 -0
  274. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_cal.yaml +0 -0
  275. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_cite.yaml +0 -0
  276. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_crit.yaml +0 -0
  277. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_ct.yaml +0 -0
  278. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_d.yaml +0 -0
  279. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_e.yaml +0 -0
  280. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_env.yaml +0 -0
  281. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_ep.yaml +0 -0
  282. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_f.yaml +0 -0
  283. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_g.yaml +0 -0
  284. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_graph.yaml +0 -0
  285. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_h.yaml +0 -0
  286. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_mc.yaml +0 -0
  287. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_mon.yaml +0 -0
  288. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_o.yaml +0 -0
  289. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_plan.yaml +0 -0
  290. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_r.yaml +0 -0
  291. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_route.yaml +0 -0
  292. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_uq.yaml +0 -0
  293. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_v.yaml +0 -0
  294. {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_wv.yaml +0 -0
  295. {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/p1_build_atlas.py +0 -0
  296. {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/p1_build_durability.py +0 -0
  297. {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/p1_export_tracks.py +0 -0
  298. {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/p1_safety_concordance.py +0 -0
  299. {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/p1_train_safety.py +0 -0
  300. {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/p1_validation_report.py +0 -0
  301. {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/p2_build_atlas.py +0 -0
  302. {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/p3_benchmark_report.py +0 -0
  303. {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/p4_genome_scan.py +0 -0
  304. {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/ws_b_report.py +0 -0
  305. {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/ws_c_report.py +0 -0
  306. {pen_stack-5.0.0 → pen_stack-5.1.0}/setup.cfg +0 -0
@@ -3,6 +3,38 @@
3
3
  All notable changes to PEN-STACK are documented here. This file follows
4
4
  [Keep a Changelog](https://keepachangelog.com/) and the program's phase structure.
5
5
 
6
+ ## [5.1.0] - 2026-06-10 - v5.1 release: Delivery immunology (the safety↔efficacy balance)
7
+
8
+ The delivery palette gains a **documented, cited, qualitative immune + safety + efficacy profile** per vehicle,
9
+ so the substrate can make the safety↔efficacy tradeoff legible and user-weightable — without ever predicting an
10
+ immune magnitude (that stays a declared known-unknown). Workstream WS-IMMUNE, SHA-locked.
11
+
12
+ ### Added
13
+ - **WS-IMMUNE config** — `configs/delivery_vehicles.yaml` (v1.1): an `immune_safety` block on all 8 vehicles
14
+ (`preexisting_immunity`, `neutralizing_antibody`, `innate_immune`, `adaptive_immune`, `genotoxicity`,
15
+ `efficacy`, `tradeoff`, `immune_dois`) — DOCUMENTED ordinal low/moderate/high priors, every `immune_doi`
16
+ Crossref-verified and in the curated-DOI set (citations resolve by construction).
17
+ - **WS-IMMUNE planner** — `pen_stack/planner/delivery_immunology.py`: `safety_efficacy_profile()` reports two
18
+ **separate** safety sub-axes — `immune_score` (immunogenicity; reversible, eligibility/re-dosing) and
19
+ `genotox_score` (insertional/oncogenic; permanent) — never collapsed, with headline
20
+ `safety_score = min(immune_score, genotox_score)` (precautionary worst-axis). `recommend_delivery(cargo_form,
21
+ cargo_bp, safety_weight, in_vivo)` ranks the eligible palette along the safety↔efficacy frontier by a
22
+ user-supplied weight. Reproduces the stated tradeoff: AAV is dinged on immunogenicity, lentivirus on
23
+ genotoxicity. `prereg/ws_immune.yaml`.
24
+ - **WS-IMMUNE verify** — `Verdict.delivery_profile` + a `delivery_immune_profile` scope flag: `verify()` now
25
+ surfaces the documented profile and tradeoff for a chosen vehicle, always attaching the standing
26
+ `in_vivo_immunogenicity` known-unknown flag — never adding confidence, never predicting a magnitude.
27
+
28
+ ### Changed
29
+ - Version 5.0.0 -> 5.1.0 (minor — additive delivery-immunology layer); `cite.curated_dois()` now also ingests
30
+ the per-vehicle `immune_dois`.
31
+
32
+ ### Honesty invariant (unchanged)
33
+ - The in-vivo immune MAGNITUDE (patient/construct-specific response) remains a declared known-unknown
34
+ (`configs/known_unknowns.yaml: in_vivo_immunogenicity`) and is **never** predicted. v5.1 exposes only
35
+ documented ordinal priors plus a transparent, user-weighted ranking — it makes the boundary legible, it does
36
+ not close it.
37
+
6
38
  ## [5.0.0] - 2026-06-09 - v5.0 release: the Co-Scientist (capstone — smart because it is grounded)
7
39
 
8
40
  The reasoning ceiling rises while the grounding floor stays fixed: a co-scientist that proposes multiple
@@ -1,8 +1,8 @@
1
1
  cff-version: 1.2.0
2
2
  message: "If you use PEN-STACK, please cite it as below."
3
3
  title: "PEN-STACK: open infrastructure for genome writing"
4
- version: 5.0.0
5
- date-released: 2026-06-01
4
+ version: 5.1.0
5
+ date-released: 2026-06-10
6
6
  authors:
7
7
  - family-names: "Mahaboob Ali"
8
8
  given-names: "Anees Ahmed"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pen-stack
3
- Version: 5.0.0
3
+ Version: 5.1.0
4
4
  Summary: Open infrastructure for genome writing: the Writable Genome atlas, the Writer Atlas, and the Write Planner.
5
5
  Author-email: Anees Ahmed Mahaboob Ali <ahmedaneesm@gmail.com>
6
6
  License: MIT
@@ -77,10 +77,12 @@ Dynamic: license-file
77
77
 
78
78
  # PEN-STACK
79
79
 
80
- ### The Writable Genome - open infrastructure for genome *writing*
80
+ ### The verification & grounding substrate for genome-writing AI — matured into a co-scientist
81
81
 
82
- *Editing tools tell you **how** to change a base. PEN-STACK tells you **where** in the genome you can safely
83
- and durably write new DNA, **which enzyme** can write it there, and **how** to design the write end-to-end.*
82
+ *The foundation models *generate*; PEN-STACK *checks*. It tells you **where** in the genome you can safely and
83
+ durably write, **which enzyme** can write it there, and **how** to design the write end-to-end — then verifies
84
+ every design against rule-grounded mechanism, reports calibrated confidence, cites its reasoning, and says
85
+ "out of scope" rather than guess. Every number comes from a validated tool; nothing is fabricated.*
84
86
 
85
87
  [![PyPI](https://img.shields.io/pypi/v/pen-stack.svg)](https://pypi.org/project/pen-stack/)
86
88
  [![CI](https://github.com/ahmedanees-m/pen-stack/actions/workflows/ci.yml/badge.svg)](https://github.com/ahmedanees-m/pen-stack/actions/workflows/ci.yml)
@@ -89,7 +91,7 @@ and durably write new DNA, **which enzyme** can write it there, and **how** to d
89
91
  [![codecov](https://codecov.io/gh/ahmedanees-m/pen-stack/branch/main/graph/badge.svg)](https://codecov.io/gh/ahmedanees-m/pen-stack)
90
92
  [![License: MIT](https://img.shields.io/badge/License-MIT-informational.svg)](LICENSE)
91
93
  [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/)
92
- [![Version](https://img.shields.io/badge/version-5.0.0-blue.svg)](CHANGELOG.md)
94
+ [![Version](https://img.shields.io/badge/version-5.1.0-blue.svg)](CHANGELOG.md)
93
95
  [![Tests](https://img.shields.io/badge/tests-240%20passing-success.svg)](tests/)
94
96
  [![Lint: ruff](https://img.shields.io/badge/lint-ruff-purple.svg)](https://github.com/astral-sh/ruff)
95
97
  [![Runtime: Docker](https://img.shields.io/badge/runtime-docker-2496ED.svg)](docker/)
@@ -133,6 +135,23 @@ Two questions gate every genome-writing project, and before PEN-STACK no resourc
133
135
  Everything is built on bulk-downloadable public data, runs on a single GPU, and is validated **blind** against
134
136
  a pre-registered, honest baseline before release.
135
137
 
138
+ ## What is new in v5.1 — Delivery immunology (the safety↔efficacy balance)
139
+
140
+ v5.1 makes the delivery palette's **safety↔efficacy tradeoff legible and user-weightable**. Every vehicle now
141
+ carries a documented, cited, qualitative immune + safety + efficacy profile — so you can ask for a *balance*
142
+ (AAV is safe by integration but neutralizing-antibody/pre-existing-immunity limited; lentivirus is a highly
143
+ efficacious integrator but its genotoxicity is the dominant concern). Crucially, the in-vivo immune
144
+ **magnitude** stays a declared known-unknown — v5.1 surfaces documented priors, it does **not** predict a
145
+ patient-specific immune response.
146
+
147
+ | Workstream | What it adds | Result |
148
+ |---|---|---|
149
+ | **IMMUNE config** | `immune_safety` block on all 8 vehicles in `configs/delivery_vehicles.yaml` | documented ordinal (low/moderate/high) priors for pre-existing immunity, neutralizing antibody, innate/adaptive immune, **genotoxicity**, efficacy — every `immune_doi` Crossref-verified and in the curated-DOI set |
150
+ | **IMMUNE planner** | `planner/delivery_immunology.py` — `safety_efficacy_profile()` / `recommend_delivery()` | two **separate** safety sub-axes (`immune_score` reversible vs `genotox_score` permanent), never collapsed; headline `safety_score = min(...)` (worst-axis); ranks the palette along the safety↔efficacy frontier by a **user weight** |
151
+ | **IMMUNE verify** | `Verdict.delivery_profile` + `delivery_immune_profile` scope flag | `verify()` surfaces the documented tradeoff for a chosen vehicle, always attaching the `in_vivo_immunogenicity` known-unknown flag — never adding confidence, never predicting a magnitude |
152
+
153
+ See `prereg/ws_immune.yaml`.
154
+
136
155
  ## What is new in v5.0 — the Co-Scientist (smart because it is grounded)
137
156
 
138
157
  v5.0 matures the reasoning layer on top of everything beneath it. Given a goal and an intent, PEN-STACK
@@ -2,10 +2,12 @@
2
2
 
3
3
  # PEN-STACK
4
4
 
5
- ### The Writable Genome - open infrastructure for genome *writing*
5
+ ### The verification & grounding substrate for genome-writing AI — matured into a co-scientist
6
6
 
7
- *Editing tools tell you **how** to change a base. PEN-STACK tells you **where** in the genome you can safely
8
- and durably write new DNA, **which enzyme** can write it there, and **how** to design the write end-to-end.*
7
+ *The foundation models *generate*; PEN-STACK *checks*. It tells you **where** in the genome you can safely and
8
+ durably write, **which enzyme** can write it there, and **how** to design the write end-to-end — then verifies
9
+ every design against rule-grounded mechanism, reports calibrated confidence, cites its reasoning, and says
10
+ "out of scope" rather than guess. Every number comes from a validated tool; nothing is fabricated.*
9
11
 
10
12
  [![PyPI](https://img.shields.io/pypi/v/pen-stack.svg)](https://pypi.org/project/pen-stack/)
11
13
  [![CI](https://github.com/ahmedanees-m/pen-stack/actions/workflows/ci.yml/badge.svg)](https://github.com/ahmedanees-m/pen-stack/actions/workflows/ci.yml)
@@ -14,7 +16,7 @@ and durably write new DNA, **which enzyme** can write it there, and **how** to d
14
16
  [![codecov](https://codecov.io/gh/ahmedanees-m/pen-stack/branch/main/graph/badge.svg)](https://codecov.io/gh/ahmedanees-m/pen-stack)
15
17
  [![License: MIT](https://img.shields.io/badge/License-MIT-informational.svg)](LICENSE)
16
18
  [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/)
17
- [![Version](https://img.shields.io/badge/version-5.0.0-blue.svg)](CHANGELOG.md)
19
+ [![Version](https://img.shields.io/badge/version-5.1.0-blue.svg)](CHANGELOG.md)
18
20
  [![Tests](https://img.shields.io/badge/tests-240%20passing-success.svg)](tests/)
19
21
  [![Lint: ruff](https://img.shields.io/badge/lint-ruff-purple.svg)](https://github.com/astral-sh/ruff)
20
22
  [![Runtime: Docker](https://img.shields.io/badge/runtime-docker-2496ED.svg)](docker/)
@@ -58,6 +60,23 @@ Two questions gate every genome-writing project, and before PEN-STACK no resourc
58
60
  Everything is built on bulk-downloadable public data, runs on a single GPU, and is validated **blind** against
59
61
  a pre-registered, honest baseline before release.
60
62
 
63
+ ## What is new in v5.1 — Delivery immunology (the safety↔efficacy balance)
64
+
65
+ v5.1 makes the delivery palette's **safety↔efficacy tradeoff legible and user-weightable**. Every vehicle now
66
+ carries a documented, cited, qualitative immune + safety + efficacy profile — so you can ask for a *balance*
67
+ (AAV is safe by integration but neutralizing-antibody/pre-existing-immunity limited; lentivirus is a highly
68
+ efficacious integrator but its genotoxicity is the dominant concern). Crucially, the in-vivo immune
69
+ **magnitude** stays a declared known-unknown — v5.1 surfaces documented priors, it does **not** predict a
70
+ patient-specific immune response.
71
+
72
+ | Workstream | What it adds | Result |
73
+ |---|---|---|
74
+ | **IMMUNE config** | `immune_safety` block on all 8 vehicles in `configs/delivery_vehicles.yaml` | documented ordinal (low/moderate/high) priors for pre-existing immunity, neutralizing antibody, innate/adaptive immune, **genotoxicity**, efficacy — every `immune_doi` Crossref-verified and in the curated-DOI set |
75
+ | **IMMUNE planner** | `planner/delivery_immunology.py` — `safety_efficacy_profile()` / `recommend_delivery()` | two **separate** safety sub-axes (`immune_score` reversible vs `genotox_score` permanent), never collapsed; headline `safety_score = min(...)` (worst-axis); ranks the palette along the safety↔efficacy frontier by a **user weight** |
76
+ | **IMMUNE verify** | `Verdict.delivery_profile` + `delivery_immune_profile` scope flag | `verify()` surfaces the documented tradeoff for a chosen vehicle, always attaching the `in_vivo_immunogenicity` known-unknown flag — never adding confidence, never predicting a magnitude |
77
+
78
+ See `prereg/ws_immune.yaml`.
79
+
61
80
  ## What is new in v5.0 — the Co-Scientist (smart because it is grounded)
62
81
 
63
82
  v5.0 matures the reasoning layer on top of everything beneath it. Given a goal and an intent, PEN-STACK
@@ -0,0 +1,185 @@
1
+ # PEN-STACK v3.3 — Delivery vehicle palette (WS-D / North-Star §4). The substrate must score and constrain
2
+ # the WHOLE delivery palette, not just dual-AAV. Each row: cargo capacity, integration, division dependence,
3
+ # immunogenicity PRIOR (qualitative; MAGNITUDE is a known-unknown — never predicted), re-dosability, tropism,
4
+ # ex/in-vivo, compatible cargo form {DNA, mRNA, RNP}, and >=1 DOI. Values cited to 2026 sources.
5
+ # `constraint_key` maps to configs/delivery_constraints.yaml for the sequence-level scan.
6
+ #
7
+ # v5.1 — `immune_safety`: a DOCUMENTED, CITED, QUALITATIVE (low/moderate/high) immune + safety + efficacy
8
+ # profile per vehicle, for the safety<->efficacy balance (planner/delivery_immunology.py). These are ordinal
9
+ # DOCUMENTED PRIORS from the literature — NOT a predicted, patient- or construct-specific immune magnitude
10
+ # (that stays a known-unknown / scope flag, `in_vivo_immunogenicity`, never predicted). `genotoxicity` = the
11
+ # integration / insertional-mutagenesis risk; `efficacy` = transduction/integration efficiency.
12
+
13
+ version: "1.1"
14
+
15
+ vehicles:
16
+ AAV_single:
17
+ cargo_capacity_bp: 4700
18
+ integrating: false # episomal
19
+ division_dependent: false
20
+ immunogenicity_prior: "moderate-high; pre-existing NAbs exclude 30-60% of patients"
21
+ re_dosable: false
22
+ tropism: "serotype-dependent (liver, muscle, CNS, retina)"
23
+ in_vivo: true
24
+ compatible_cargo_form: [DNA]
25
+ constraint_key: AAV
26
+ dois: ["10.1038/s41573-019-0012-9"]
27
+ immune_safety:
28
+ preexisting_immunity: high # serotype-dependent; seroprevalence ~30-60% of patients
29
+ neutralizing_antibody: high # pre-existing + vector-elicited NAbs; exclude/relapse risk
30
+ innate_immune: low
31
+ adaptive_immune: moderate # capsid-directed CD8 T-cell responses
32
+ genotoxicity: low # episomal, non-integrating
33
+ efficacy: high # efficient in-vivo transduction (cargo-limited ~4.7 kb)
34
+ tradeoff: "safe vector (non-integrating, low genotoxicity) BUT pre-existing/elicited NAbs limit eligibility and prevent re-dosing"
35
+ immune_dois: ["10.1182/blood-2013-01-306647", "10.1089/hum.2009.182", "10.1016/j.ymthe.2019.12.010"]
36
+
37
+ AAV_dual:
38
+ cargo_capacity_bp: 9000 # split across 2 capsids (~9 kb); efficiency drops sharply
39
+ integrating: false
40
+ division_dependent: false
41
+ immunogenicity_prior: "as AAV; split lowers efficiency"
42
+ re_dosable: false
43
+ tropism: "serotype-dependent"
44
+ in_vivo: true
45
+ compatible_cargo_form: [DNA]
46
+ constraint_key: AAV
47
+ dois: ["10.1128/JVI.79.15.9933-9944.2005"] # Grieger & Samulski 2005, AAV packaging capacity
48
+ immune_safety:
49
+ preexisting_immunity: high # same AAV capsid immunology as single
50
+ neutralizing_antibody: high
51
+ innate_immune: low
52
+ adaptive_immune: moderate
53
+ genotoxicity: low # episomal
54
+ efficacy: moderate # split across 2 capsids -> co-transduction needed, efficiency drops
55
+ tradeoff: "as AAV (non-integrating, NAb-limited) AND split-capsid co-transduction lowers efficiency"
56
+ immune_dois: ["10.1182/blood-2013-01-306647", "10.1089/hum.2009.182"]
57
+
58
+ lentivirus:
59
+ cargo_capacity_bp: 8000
60
+ integrating: true # semi-random integration
61
+ division_dependent: false # integrates in non-dividing too; strong in dividing
62
+ immunogenicity_prior: "moderate"
63
+ re_dosable: false
64
+ tropism: "broad (VSV-G pseudotyped)"
65
+ ex_vivo: true
66
+ compatible_cargo_form: [DNA]
67
+ constraint_key: lentiviral
68
+ dois: ["10.1126/science.1233151"]
69
+ immune_safety:
70
+ preexisting_immunity: low # pseudotyped, typically ex-vivo (no host pre-immunity to the vector)
71
+ neutralizing_antibody: low # ex-vivo use avoids humoral neutralisation
72
+ innate_immune: low # ex-vivo
73
+ adaptive_immune: low # ex-vivo
74
+ genotoxicity: moderate # INTEGRATING: insertional-mutagenesis risk; SIN-LTR + gene-body bias reduce but do not eliminate it (gamma-retro LMO2 precedent)
75
+ efficacy: high # efficient, STABLE integration; large-ish cargo (~8 kb); transduces non-dividing cells
76
+ tradeoff: "highly efficacious STABLE integration BUT insertional-mutagenesis / genotoxicity is the dominant safety concern (mitigated by SIN design, not eliminated)"
77
+ immune_dois: ["10.1038/s41375-018-0106-0", "10.1038/nbt1216", "10.1126/science.1088547"]
78
+
79
+ helper_dependent_adenovirus:
80
+ cargo_capacity_bp: 35000 # "gutless" HDAd, up to ~35 kb
81
+ integrating: false
82
+ division_dependent: false
83
+ immunogenicity_prior: "high (innate + adaptive)"
84
+ re_dosable: false
85
+ tropism: "liver and others"
86
+ in_vivo: true
87
+ compatible_cargo_form: [DNA]
88
+ constraint_key: plasmid
89
+ dois: ["10.1128/JVI.72.2.926-933.1998"] # multiply-deleted (gutless-class) adenovirus vectors
90
+ immune_safety:
91
+ preexisting_immunity: high # widespread prior adenovirus exposure in the population
92
+ neutralizing_antibody: high # anti-Ad NAbs common; limit systemic in-vivo dosing
93
+ innate_immune: high # potent acute innate/inflammatory response to the capsid
94
+ adaptive_immune: high # strong anti-vector adaptive response
95
+ genotoxicity: low # non-integrating, episomal "gutless" genome
96
+ efficacy: high # very large cargo (~35 kb), efficient hepatic transduction
97
+ tradeoff: "huge cargo + non-integrating BUT strong innate+adaptive anti-Ad immunity and pre-existing NAbs are the dominant safety limit for systemic use"
98
+ immune_dois: ["10.1089/hum.2004.15.1157"]
99
+
100
+ hsv_amplicon:
101
+ cargo_capacity_bp: 100000 # >100 kb
102
+ integrating: false
103
+ division_dependent: false
104
+ immunogenicity_prior: "high; neurotropic"
105
+ re_dosable: false
106
+ tropism: "neurotropic (CNS)"
107
+ in_vivo: true
108
+ compatible_cargo_form: [DNA]
109
+ constraint_key: plasmid
110
+ dois: ["10.1038/nbt1101-1067"] # Wade-Martins 2001, HSV-1 amplicon (iBAC) large genomic-DNA transfer
111
+ immune_safety:
112
+ preexisting_immunity: moderate # prior HSV exposure common, but helper-free amplicon is gene-free of HSV ORFs
113
+ neutralizing_antibody: moderate # anti-HSV humoral immunity in seropositive hosts
114
+ innate_immune: high # immunogenic / inflammatory in CNS
115
+ adaptive_immune: high
116
+ genotoxicity: low # non-integrating, episomal
117
+ efficacy: moderate # massive cargo (>100 kb) + neurotropism, but transient/variable expression
118
+ tradeoff: "unmatched cargo (>100 kb) and CNS tropism BUT immunogenic/inflammatory and expression is transient"
119
+ immune_dois: ["10.1089/hum.2004.15.1157"]
120
+
121
+ lnp_mrna:
122
+ cargo_capacity_bp: 15000 # large RNA payload (mRNA encoding the writer/RNP)
123
+ integrating: false # transient
124
+ division_dependent: false
125
+ immunogenicity_prior: "low/transient"
126
+ re_dosable: true
127
+ tropism: "liver-tropic by default"
128
+ in_vivo: true
129
+ compatible_cargo_form: [mRNA, RNP]
130
+ constraint_key: lnp_mrna
131
+ dois: ["10.1038/s41578-021-00358-0"]
132
+ immune_safety:
133
+ preexisting_immunity: low # no widespread pre-existing immunity to the LNP (anti-PEG is an emerging exception)
134
+ neutralizing_antibody: low # anti-PEG antibodies emerging; can accelerate clearance on repeat dosing
135
+ innate_immune: moderate # transient innate sensing of mRNA / ionizable lipid (mitigated by mod-nucleosides)
136
+ adaptive_immune: low # no anti-vector adaptive memory to a protein capsid
137
+ genotoxicity: low # NON-integrating, transient (no insertional risk)
138
+ efficacy: moderate # transient expression; potent for hepatic RNP/mRNA but durability is short
139
+ re_dosable: yes # repeatable dosing is the key advantage
140
+ tradeoff: "SAFEST profile (non-integrating, transient, re-dosable, low pre-existing immunity) BUT expression is transient and anti-PEG immunity can blunt repeat doses"
141
+ immune_dois: ["10.1016/j.addr.2020.07.024"]
142
+
143
+ evlp:
144
+ cargo_capacity_bp: null # RNP payload (not a DNA packaging limit)
145
+ integrating: false
146
+ division_dependent: false
147
+ immunogenicity_prior: "low (transient, no DNA)"
148
+ re_dosable: true
149
+ tropism: "engineerable (T cells, retina)"
150
+ in_vivo: true
151
+ ex_vivo: true
152
+ compatible_cargo_form: [RNP]
153
+ constraint_key: evlp
154
+ dois: ["10.1016/j.cell.2022.03.045"]
155
+ immune_safety:
156
+ preexisting_immunity: low # protein/RNP payload, no viral capsid; transient
157
+ neutralizing_antibody: low
158
+ innate_immune: low # no DNA, transient delivery
159
+ adaptive_immune: low
160
+ genotoxicity: low # non-integrating RNP, transient nuclease exposure
161
+ efficacy: moderate # engineerable tropism; emerging modality, in-vivo efficiency still maturing
162
+ re_dosable: yes
163
+ tradeoff: "low-immunogenicity transient RNP delivery with engineerable tropism BUT an emerging modality with still-maturing in-vivo efficiency"
164
+ immune_dois: ["10.1016/j.ymthe.2019.12.010"]
165
+
166
+ electroporation:
167
+ cargo_capacity_bp: null # physical; no packaging limit
168
+ integrating: false # depends on cargo
169
+ division_dependent: false
170
+ immunogenicity_prior: "n/a (ex vivo)"
171
+ re_dosable: false
172
+ tropism: "n/a (ex vivo)"
173
+ ex_vivo: true
174
+ compatible_cargo_form: [DNA, mRNA, RNP]
175
+ constraint_key: electroporation
176
+ dois: ["10.1038/nprot.2014.157"]
177
+ immune_safety:
178
+ preexisting_immunity: low # ex-vivo, physical method; no vector immunology
179
+ neutralizing_antibody: low # ex-vivo (n/a in host)
180
+ innate_immune: low # ex-vivo
181
+ adaptive_immune: low # ex-vivo
182
+ genotoxicity: low # cargo-dependent; RNP/transient cargo carries no insertional risk
183
+ efficacy: high # high ex-vivo delivery efficiency across DNA/mRNA/RNP
184
+ tradeoff: "no vector immunology and high ex-vivo efficiency BUT EX-VIVO ONLY (cell harvest/manufacture required) and cytotoxic at high field strength"
185
+ immune_dois: ["10.1016/j.ymthe.2019.12.010"]
@@ -1,2 +1,2 @@
1
1
  """PEN-STACK v3.0 - open infrastructure for genome writing."""
2
- __version__ = "5.0.0"
2
+ __version__ = "5.1.0"
@@ -28,6 +28,7 @@ def curated_dois() -> frozenset[str]:
28
28
  veh = yaml.safe_load(resource("configs/delivery_vehicles.yaml").read_text(encoding="utf-8"))["vehicles"]
29
29
  for v in veh.values():
30
30
  dois.update(v.get("dois", []) or [])
31
+ dois.update((v.get("immune_safety") or {}).get("immune_dois", []) or []) # v5.1 immune priors
31
32
  gsh = yaml.safe_load(resource("configs/gsh_validated_heldout.yaml").read_text(encoding="utf-8"))["gsh"]
32
33
  for g in gsh:
33
34
  if g.get("doi"):
@@ -0,0 +1,160 @@
1
+ """Delivery safety<->efficacy balance over DOCUMENTED immune priors (v5.1, WS-IMMUNE).
2
+
3
+ Motivation (user, v5.1): "we should be able to give a good balance between safety and efficacy. AAV is
4
+ safe but neutralizing antibodies / pre-existing immunity will be there; lentivirus is highly efficacious at
5
+ integrating but its safety is bad." This module turns the per-vehicle ``immune_safety`` block in
6
+ configs/delivery_vehicles.yaml into a transparent, user-weightable ranking of the delivery palette.
7
+
8
+ THE HONESTY INVARIANT (unchanged across the program): the immune MAGNITUDE — how strongly a given patient or
9
+ construct will react in vivo — is a declared known-unknown (configs/known_unknowns.yaml: ``in_vivo_immunogenicity``)
10
+ and is NEVER predicted here. What this module exposes is strictly:
11
+
12
+ * the DOCUMENTED, CITED, ORDINAL (low/moderate/high) literature priors per vehicle, and
13
+ * a transparent ranking that combines those ordinal tiers under a USER-SUPPLIED safety<->efficacy weight.
14
+
15
+ The composite scores are an explicit, reproducible function of the documented tiers and the user's weight — not
16
+ a learned or predicted immunogenicity. Every profile carries the scope flag that the magnitude is out of scope,
17
+ plus the curated DOIs so the prior is auditable.
18
+ """
19
+ from __future__ import annotations
20
+
21
+ from functools import lru_cache
22
+
23
+ from pen_stack.planner.delivery_vehicles import load_vehicles, names, vehicle
24
+
25
+ # Ordinal map for the documented qualitative tiers. Higher = more of the named property.
26
+ # For the BURDEN axes (immunity / NAb / innate / adaptive / genotoxicity) higher = worse (less safe);
27
+ # for the EFFICACY axis higher = better.
28
+ _TIER = {"low": 0.0, "moderate": 1.0, "high": 2.0}
29
+ # Two DISTINCT safety sub-axes are kept separate, never collapsed into one mean, because they are different
30
+ # KINDS of risk: immunogenicity is (largely) reversible and bears on eligibility/re-dosing, whereas
31
+ # genotoxicity (insertional mutagenesis) is a permanent, potentially oncogenic risk. This is exactly the
32
+ # tradeoff the v5.1 request is about ("AAV is safe but NAbs; LV is highly efficacious at integrating but its
33
+ # safety is bad") — so genotoxicity must be a first-class, separately-visible axis, not 1/5 of an average.
34
+ _IMMUNE_AXES = ("preexisting_immunity", "neutralizing_antibody", "innate_immune", "adaptive_immune")
35
+ _GENOTOX_AXIS = "genotoxicity"
36
+ # magnitude is NEVER predicted; this is the known-unknown the profile points back to.
37
+ _MAGNITUDE_SCOPE_ID = "in_vivo_immunogenicity"
38
+
39
+
40
+ def _tier(val) -> float | None:
41
+ if val is None:
42
+ return None
43
+ return _TIER.get(str(val).strip().lower())
44
+
45
+
46
+ def safety_efficacy_profile(name: str) -> dict | None:
47
+ """Documented safety<->efficacy profile for one vehicle, derived ONLY from its ``immune_safety`` block.
48
+
49
+ Reports the ordinal tiers verbatim and THREE normalised sub-scores (1 = best):
50
+ * ``immune_score`` = 1 - mean(immune-burden axes)/2 (1 = least immunogenic)
51
+ * ``genotox_score`` = 1 - genotoxicity/2 (1 = least insertional/oncogenic risk)
52
+ * ``efficacy_score`` = efficacy/2 (1 = most efficacious)
53
+ plus a headline ``safety_score = min(immune_score, genotox_score)`` — a precautionary worst-axis aggregation
54
+ so a vehicle is only as "safe" as its WORST safety dimension (a non-immunogenic but genotoxic vector is not
55
+ called safe). Also returns the documented tradeoff sentence, curated DOIs, and the standing scope flag that
56
+ the immune MAGNITUDE is not predicted. Returns ``None`` for an unknown vehicle; invents no number."""
57
+ rec = vehicle(name)
58
+ if rec is None:
59
+ return None
60
+ imm = rec.get("immune_safety") or {}
61
+ immune_present = [t for ax in _IMMUNE_AXES if (t := _tier(imm.get(ax))) is not None]
62
+ immune_score = (1.0 - (sum(immune_present) / len(immune_present)) / 2.0) if immune_present else None
63
+ gtox = _tier(imm.get(_GENOTOX_AXIS))
64
+ genotox_score = (1.0 - gtox / 2.0) if gtox is not None else None
65
+ sub = [s for s in (immune_score, genotox_score) if s is not None]
66
+ safety_score = min(sub) if sub else None # worst-axis; abstain if neither documented
67
+ eff = _tier(imm.get("efficacy"))
68
+ efficacy_score = (eff / 2.0) if eff is not None else None
69
+ _r = lambda x: None if x is None else round(x, 3) # noqa: E731
70
+ return {
71
+ "vehicle": name,
72
+ "tiers": {ax: imm.get(ax) for ax in (*_IMMUNE_AXES, _GENOTOX_AXIS)} | {"efficacy": imm.get("efficacy")},
73
+ "immune_score": _r(immune_score),
74
+ "genotox_score": _r(genotox_score),
75
+ "safety_score": _r(safety_score),
76
+ "efficacy_score": _r(efficacy_score),
77
+ "re_dosable": imm.get("re_dosable", rec.get("re_dosable")),
78
+ "integrating": rec.get("integrating"),
79
+ "tradeoff": imm.get("tradeoff"),
80
+ "immune_dois": list(imm.get("immune_dois", []) or []),
81
+ "magnitude_scope_flag": {
82
+ "kind": "known_unknown", "id": _MAGNITUDE_SCOPE_ID,
83
+ "reason": "the in-vivo immune MAGNITUDE (patient/construct-specific response) is a known-unknown; "
84
+ "only documented ordinal priors are surfaced, never a predicted magnitude"},
85
+ "note": "safety_score = min(immune_score, genotox_score) over DOCUMENTED ordinal tiers — a precautionary "
86
+ "worst-axis aggregation, not a predicted immunogenicity.",
87
+ }
88
+
89
+
90
+ @lru_cache(maxsize=1)
91
+ def all_profiles() -> tuple:
92
+ """All vehicle profiles (tuple so it is hashable/cacheable)."""
93
+ return tuple(p for n in names() if (p := safety_efficacy_profile(n)) is not None)
94
+
95
+
96
+ def _balance(profile: dict, safety_weight: float) -> float | None:
97
+ """Composite = safety_weight * safety_score + (1 - safety_weight) * efficacy_score. None if either axis is
98
+ undocumented (abstain rather than impute)."""
99
+ s, e = profile["safety_score"], profile["efficacy_score"]
100
+ if s is None or e is None:
101
+ return None
102
+ w = min(max(float(safety_weight), 0.0), 1.0)
103
+ return round(w * s + (1.0 - w) * e, 4)
104
+
105
+
106
+ def recommend_delivery(cargo_form: str, cargo_bp: int | None = None, *, safety_weight: float = 0.5,
107
+ in_vivo: bool | None = None) -> dict:
108
+ """Rank the delivery palette for a cargo by a USER-WEIGHTED safety<->efficacy balance over documented priors.
109
+
110
+ Args:
111
+ cargo_form: required cargo form (DNA / mRNA / RNP) — only vehicles compatible with it are considered.
112
+ cargo_bp: if given, vehicles whose ``cargo_capacity_bp`` is smaller are excluded (hard packaging limit).
113
+ safety_weight: in [0, 1]. 1.0 = rank purely on documented safety; 0.0 = purely on efficacy; 0.5 = balance.
114
+ in_vivo: if True, exclude ex-vivo-only vehicles (and vice-versa) when the field is documented.
115
+
116
+ Returns a dict with the eligible vehicles ranked best-first by the composite, each carrying its documented
117
+ tiers, tradeoff, and curated DOIs, plus the standing magnitude scope flag. No magnitude is predicted; the
118
+ composite is an explicit function of the documented ordinal tiers and the caller's weight."""
119
+ form = (cargo_form or "").strip()
120
+ veh = load_vehicles()
121
+ eligible: list[dict] = []
122
+ excluded: list[dict] = []
123
+ for n, rec in veh.items():
124
+ forms = rec.get("compatible_cargo_form", []) or []
125
+ if form and form not in forms:
126
+ continue
127
+ if cargo_bp is not None and rec.get("cargo_capacity_bp") is not None \
128
+ and int(cargo_bp) > int(rec["cargo_capacity_bp"]):
129
+ excluded.append({"vehicle": n, "reason": f"cargo {cargo_bp} bp exceeds capacity "
130
+ f"{rec['cargo_capacity_bp']} bp"})
131
+ continue
132
+ if in_vivo is True and rec.get("ex_vivo") and not rec.get("in_vivo"):
133
+ excluded.append({"vehicle": n, "reason": "ex-vivo-only; an in-vivo route was required"})
134
+ continue
135
+ if in_vivo is False and rec.get("in_vivo") and not rec.get("ex_vivo"):
136
+ excluded.append({"vehicle": n, "reason": "in-vivo-only; an ex-vivo route was required"})
137
+ continue
138
+ prof = safety_efficacy_profile(n)
139
+ if prof is None:
140
+ continue
141
+ prof = dict(prof)
142
+ prof["balance"] = _balance(prof, safety_weight)
143
+ eligible.append(prof)
144
+
145
+ # rank: documented balance first (None last); tie-break by efficacy then safety.
146
+ eligible.sort(key=lambda p: (p["balance"] is None, -(p["balance"] or 0.0),
147
+ -(p["efficacy_score"] or 0.0), -(p["safety_score"] or 0.0)))
148
+ return {
149
+ "cargo_form": form, "cargo_bp": cargo_bp, "safety_weight": min(max(float(safety_weight), 0.0), 1.0),
150
+ "in_vivo": in_vivo,
151
+ "ranked": eligible,
152
+ "recommended": eligible[0]["vehicle"] if eligible else None,
153
+ "excluded": excluded,
154
+ "scope_flags": [{"kind": "known_unknown", "id": _MAGNITUDE_SCOPE_ID,
155
+ "reason": "ranking is over DOCUMENTED ordinal immune priors; the patient/construct-"
156
+ "specific immune MAGNITUDE is a known-unknown and is not predicted"}],
157
+ "no_fabrication": True,
158
+ "note": "balance = safety_weight*safety + (1-safety_weight)*efficacy over documented low/moderate/high "
159
+ "tiers; change safety_weight to move along the safety<->efficacy frontier.",
160
+ }
@@ -26,6 +26,8 @@ class Verdict(BaseModel):
26
26
  no_fabrication: bool = True
27
27
  writer_critique: dict[str, Any] | None = None # v4.0 WS-WV: critique of a generated candidate writer
28
28
  # (pass/flag + reasons); NEVER a claim that it works
29
+ delivery_profile: dict[str, Any] | None = None # v5.1 WS-IMMUNE: documented ordinal immune/safety/efficacy
30
+ # priors for the chosen vehicle (NEVER a predicted magnitude)
29
31
 
30
32
  def summary(self) -> str:
31
33
  if self.deferred:
@@ -92,6 +92,21 @@ def verify(design: Design | dict, question: str | None = None) -> Verdict:
92
92
  "flags": writer_critique["flags"],
93
93
  "reason": "generated writer is critiqued, never claimed to work (v4.0 WS-WV)"})
94
94
 
95
+ # v5.1 WS-IMMUNE: if the design names a delivery vehicle, surface its DOCUMENTED ordinal immune/safety/
96
+ # efficacy priors (with the standing "magnitude is a known-unknown" scope flag). This never adds confidence
97
+ # and never predicts a magnitude — it exposes the curated qualitative tradeoff so safety can be weighed.
98
+ delivery_profile = None
99
+ if design.delivery_vehicle:
100
+ from pen_stack.planner.delivery_immunology import safety_efficacy_profile
101
+ delivery_profile = safety_efficacy_profile(design.delivery_vehicle)
102
+ if delivery_profile and delivery_profile.get("tradeoff"):
103
+ scope_flags.append({"kind": "delivery_immune_profile",
104
+ "vehicle": delivery_profile["vehicle"],
105
+ "tradeoff": delivery_profile["tradeoff"],
106
+ "magnitude_id": delivery_profile["magnitude_scope_flag"]["id"],
107
+ "reason": "documented ordinal immune/safety priors surfaced; the in-vivo immune "
108
+ "MAGNITUDE remains a known-unknown (not predicted)"})
109
+
95
110
  return Verdict(
96
111
  legal=routed["legal"], deferred=False, write_type=design.write_type, routing=routing,
97
112
  rule_results=results,
@@ -101,4 +116,4 @@ def verify(design: Design | dict, question: str | None = None) -> Verdict:
101
116
  scope_flags=scope_flags,
102
117
  confidence=pc["confidence"], interval=pc["interval"], epistemic_status=verdict.status,
103
118
  provenance={"rules_version": RULES_VERSION, "source": "rules.solver + L4(uncertainty/scope/epistemic)"},
104
- no_fabrication=True, writer_critique=writer_critique)
119
+ no_fabrication=True, writer_critique=writer_critique, delivery_profile=delivery_profile)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pen-stack
3
- Version: 5.0.0
3
+ Version: 5.1.0
4
4
  Summary: Open infrastructure for genome writing: the Writable Genome atlas, the Writer Atlas, and the Write Planner.
5
5
  Author-email: Anees Ahmed Mahaboob Ali <ahmedaneesm@gmail.com>
6
6
  License: MIT
@@ -77,10 +77,12 @@ Dynamic: license-file
77
77
 
78
78
  # PEN-STACK
79
79
 
80
- ### The Writable Genome - open infrastructure for genome *writing*
80
+ ### The verification & grounding substrate for genome-writing AI — matured into a co-scientist
81
81
 
82
- *Editing tools tell you **how** to change a base. PEN-STACK tells you **where** in the genome you can safely
83
- and durably write new DNA, **which enzyme** can write it there, and **how** to design the write end-to-end.*
82
+ *The foundation models *generate*; PEN-STACK *checks*. It tells you **where** in the genome you can safely and
83
+ durably write, **which enzyme** can write it there, and **how** to design the write end-to-end — then verifies
84
+ every design against rule-grounded mechanism, reports calibrated confidence, cites its reasoning, and says
85
+ "out of scope" rather than guess. Every number comes from a validated tool; nothing is fabricated.*
84
86
 
85
87
  [![PyPI](https://img.shields.io/pypi/v/pen-stack.svg)](https://pypi.org/project/pen-stack/)
86
88
  [![CI](https://github.com/ahmedanees-m/pen-stack/actions/workflows/ci.yml/badge.svg)](https://github.com/ahmedanees-m/pen-stack/actions/workflows/ci.yml)
@@ -89,7 +91,7 @@ and durably write new DNA, **which enzyme** can write it there, and **how** to d
89
91
  [![codecov](https://codecov.io/gh/ahmedanees-m/pen-stack/branch/main/graph/badge.svg)](https://codecov.io/gh/ahmedanees-m/pen-stack)
90
92
  [![License: MIT](https://img.shields.io/badge/License-MIT-informational.svg)](LICENSE)
91
93
  [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/)
92
- [![Version](https://img.shields.io/badge/version-5.0.0-blue.svg)](CHANGELOG.md)
94
+ [![Version](https://img.shields.io/badge/version-5.1.0-blue.svg)](CHANGELOG.md)
93
95
  [![Tests](https://img.shields.io/badge/tests-240%20passing-success.svg)](tests/)
94
96
  [![Lint: ruff](https://img.shields.io/badge/lint-ruff-purple.svg)](https://github.com/astral-sh/ruff)
95
97
  [![Runtime: Docker](https://img.shields.io/badge/runtime-docker-2496ED.svg)](docker/)
@@ -133,6 +135,23 @@ Two questions gate every genome-writing project, and before PEN-STACK no resourc
133
135
  Everything is built on bulk-downloadable public data, runs on a single GPU, and is validated **blind** against
134
136
  a pre-registered, honest baseline before release.
135
137
 
138
+ ## What is new in v5.1 — Delivery immunology (the safety↔efficacy balance)
139
+
140
+ v5.1 makes the delivery palette's **safety↔efficacy tradeoff legible and user-weightable**. Every vehicle now
141
+ carries a documented, cited, qualitative immune + safety + efficacy profile — so you can ask for a *balance*
142
+ (AAV is safe by integration but neutralizing-antibody/pre-existing-immunity limited; lentivirus is a highly
143
+ efficacious integrator but its genotoxicity is the dominant concern). Crucially, the in-vivo immune
144
+ **magnitude** stays a declared known-unknown — v5.1 surfaces documented priors, it does **not** predict a
145
+ patient-specific immune response.
146
+
147
+ | Workstream | What it adds | Result |
148
+ |---|---|---|
149
+ | **IMMUNE config** | `immune_safety` block on all 8 vehicles in `configs/delivery_vehicles.yaml` | documented ordinal (low/moderate/high) priors for pre-existing immunity, neutralizing antibody, innate/adaptive immune, **genotoxicity**, efficacy — every `immune_doi` Crossref-verified and in the curated-DOI set |
150
+ | **IMMUNE planner** | `planner/delivery_immunology.py` — `safety_efficacy_profile()` / `recommend_delivery()` | two **separate** safety sub-axes (`immune_score` reversible vs `genotox_score` permanent), never collapsed; headline `safety_score = min(...)` (worst-axis); ranks the palette along the safety↔efficacy frontier by a **user weight** |
151
+ | **IMMUNE verify** | `Verdict.delivery_profile` + `delivery_immune_profile` scope flag | `verify()` surfaces the documented tradeoff for a chosen vehicle, always attaching the `in_vivo_immunogenicity` known-unknown flag — never adding confidence, never predicting a magnitude |
152
+
153
+ See `prereg/ws_immune.yaml`.
154
+
136
155
  ## What is new in v5.0 — the Co-Scientist (smart because it is grounded)
137
156
 
138
157
  v5.0 matures the reasoning layer on top of everything beneath it. Given a goal and an intent, PEN-STACK
@@ -153,6 +153,7 @@ pen_stack/planner/cargo.py
153
153
  pen_stack/planner/cargo_polish.py
154
154
  pen_stack/planner/delivery.py
155
155
  pen_stack/planner/delivery_constraints.py
156
+ pen_stack/planner/delivery_immunology.py
156
157
  pen_stack/planner/delivery_vehicles.py
157
158
  pen_stack/planner/multiplex.py
158
159
  pen_stack/planner/optimize.py
@@ -244,6 +245,7 @@ prereg/SHA256_LOCK_ws_f.json
244
245
  prereg/SHA256_LOCK_ws_g.json
245
246
  prereg/SHA256_LOCK_ws_graph.json
246
247
  prereg/SHA256_LOCK_ws_h.json
248
+ prereg/SHA256_LOCK_ws_immune.json
247
249
  prereg/SHA256_LOCK_ws_mc.json
248
250
  prereg/SHA256_LOCK_ws_mon.json
249
251
  prereg/SHA256_LOCK_ws_o.json
@@ -278,6 +280,7 @@ prereg/ws_f.yaml
278
280
  prereg/ws_g.yaml
279
281
  prereg/ws_graph.yaml
280
282
  prereg/ws_h.yaml
283
+ prereg/ws_immune.yaml
281
284
  prereg/ws_mc.yaml
282
285
  prereg/ws_mon.yaml
283
286
  prereg/ws_o.yaml