pen-stack 5.2.0__tar.gz → 5.3.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 (316) hide show
  1. {pen_stack-5.2.0 → pen_stack-5.3.0}/CHANGELOG.md +35 -0
  2. {pen_stack-5.2.0 → pen_stack-5.3.0}/CITATION.cff +1 -1
  3. {pen_stack-5.2.0 → pen_stack-5.3.0}/MANIFEST.in +1 -1
  4. {pen_stack-5.2.0 → pen_stack-5.3.0}/PKG-INFO +18 -2
  5. {pen_stack-5.2.0 → pen_stack-5.3.0}/README.md +17 -1
  6. pen_stack-5.3.0/configs/capsid_epitope_oracle.yaml +85 -0
  7. pen_stack-5.3.0/configs/capsid_sequences.fasta +66 -0
  8. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/oracles/scope_cards.yaml +13 -0
  9. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/__init__.py +1 -1
  10. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/agent/cite.py +7 -6
  11. pen_stack-5.3.0/pen_stack/planner/capsid_epitope_oracle.py +97 -0
  12. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/planner/delivery_immunology.py +25 -2
  13. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack.egg-info/PKG-INFO +18 -2
  14. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack.egg-info/SOURCES.txt +6 -0
  15. pen_stack-5.3.0/prereg/SHA256_LOCK_ws_epitope.json +8 -0
  16. pen_stack-5.3.0/prereg/ws_epitope.yaml +47 -0
  17. {pen_stack-5.2.0 → pen_stack-5.3.0}/pyproject.toml +1 -1
  18. pen_stack-5.3.0/scripts/p53_build_epitope_oracle.py +120 -0
  19. {pen_stack-5.2.0 → pen_stack-5.3.0}/LICENSE +0 -0
  20. {pen_stack-5.2.0 → pen_stack-5.3.0}/bench/run.py +0 -0
  21. {pen_stack-5.2.0 → pen_stack-5.3.0}/benchmarks/genome_writing_bench/LEADERBOARD.md +0 -0
  22. {pen_stack-5.2.0 → pen_stack-5.3.0}/benchmarks/genome_writing_bench/README.md +0 -0
  23. {pen_stack-5.2.0 → pen_stack-5.3.0}/benchmarks/genome_writing_bench/SHA256SUMS +0 -0
  24. {pen_stack-5.2.0 → pen_stack-5.3.0}/benchmarks/genome_writing_bench/SUBMISSIONS.md +0 -0
  25. {pen_stack-5.2.0 → pen_stack-5.3.0}/benchmarks/genome_writing_bench/tasks.yaml +0 -0
  26. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/atlas_families.yaml +0 -0
  27. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/bridge_offtarget_profile.yaml +0 -0
  28. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/cargo_polish.yaml +0 -0
  29. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/cell_types.yaml +0 -0
  30. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/datasets.yaml +0 -0
  31. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/delivery_constraints.yaml +0 -0
  32. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/delivery_rules.yaml +0 -0
  33. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/delivery_vehicles.yaml +0 -0
  34. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/gates_v3.yaml +0 -0
  35. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/genotoxicity_oracle.yaml +0 -0
  36. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/gsh_validated_heldout.yaml +0 -0
  37. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/intent_weights.yaml +0 -0
  38. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/known_unknowns.yaml +0 -0
  39. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/llm.yaml +0 -0
  40. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/monitor_queries.yaml +0 -0
  41. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/rules/delivery.yaml +0 -0
  42. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/rules/fold.yaml +0 -0
  43. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/rules/multiplex.yaml +0 -0
  44. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/rules/payload.yaml +0 -0
  45. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/rules/reachability.yaml +0 -0
  46. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/score_axes.yaml +0 -0
  47. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/target_sites.yaml +0 -0
  48. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/universe_crosswalk.yaml +0 -0
  49. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/write_types.yaml +0 -0
  50. {pen_stack-5.2.0 → pen_stack-5.3.0}/configs/wtkb_curated.yaml +0 -0
  51. {pen_stack-5.2.0 → pen_stack-5.3.0}/data/curated/bridge_offtarget_energetics.json +0 -0
  52. {pen_stack-5.2.0 → pen_stack-5.3.0}/data/curated/bridge_offtarget_profile_measured.parquet +0 -0
  53. {pen_stack-5.2.0 → pen_stack-5.3.0}/data/curated/gene_coords.parquet +0 -0
  54. {pen_stack-5.2.0 → pen_stack-5.3.0}/data/curated/unified_editor_universe.parquet +0 -0
  55. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/BACKLOG.md +0 -0
  56. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/DEPLOY.md +0 -0
  57. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/INFRA.md +0 -0
  58. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/MCP.md +0 -0
  59. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/RELEASING.md +0 -0
  60. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/REPRO.md +0 -0
  61. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/agent.md +0 -0
  62. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/alphagenome_feasibility.md +0 -0
  63. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/benchmark_circularity.md +0 -0
  64. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/cards/atlas.md +0 -0
  65. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/cards/durability.md +0 -0
  66. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/cards/safety.md +0 -0
  67. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/co_scientist.md +0 -0
  68. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/delivery.md +0 -0
  69. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/dissemination.md +0 -0
  70. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/environment.md +0 -0
  71. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/index.md +0 -0
  72. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/mechanistic_constraints.md +0 -0
  73. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/oracles.md +0 -0
  74. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/positioning.md +0 -0
  75. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/private_data_formats.md +0 -0
  76. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/quickstart.md +0 -0
  77. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/rules.md +0 -0
  78. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/scope.md +0 -0
  79. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/scorecard.md +0 -0
  80. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/tutorials/compare-families.md +0 -0
  81. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/tutorials/score-deliverability.md +0 -0
  82. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/tutorials/where-can-i-write.md +0 -0
  83. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/tutorials/which-writer-reaches-locus.md +0 -0
  84. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/uncertainty.md +0 -0
  85. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/verify.md +0 -0
  86. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/world_model.md +0 -0
  87. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/writer_verification.md +0 -0
  88. {pen_stack-5.2.0 → pen_stack-5.3.0}/docs/wtkb.md +0 -0
  89. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/_resources.py +0 -0
  90. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/adapt/__init__.py +0 -0
  91. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/adapt/finetune.py +0 -0
  92. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/adapt/ingest.py +0 -0
  93. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/adapt/pipeline.py +0 -0
  94. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/adapt/recalibrate.py +0 -0
  95. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/adapt/report.py +0 -0
  96. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/agent/__init__.py +0 -0
  97. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/agent/co_scientist.py +0 -0
  98. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/agent/epistemic.py +0 -0
  99. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/agent/guardrails.py +0 -0
  100. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/agent/mcp_server.py +0 -0
  101. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/agent/orchestrator.py +0 -0
  102. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/agent/pen_agent.py +0 -0
  103. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/agent/scope.py +0 -0
  104. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/agent/tools.py +0 -0
  105. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/atlas/__init__.py +0 -0
  106. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/atlas/build_wtkb.py +0 -0
  107. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/atlas/crosslink.py +0 -0
  108. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/atlas/expand.py +0 -0
  109. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/atlas/schema.py +0 -0
  110. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/atlas/scorecard.py +0 -0
  111. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/atlas/universe.py +0 -0
  112. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/atlas/variant_propose.py +0 -0
  113. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/atlas/writer_verify.py +0 -0
  114. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/bridge/__init__.py +0 -0
  115. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/bridge/activity.py +0 -0
  116. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/bridge/cli.py +0 -0
  117. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/bridge/fold_qc.py +0 -0
  118. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/bridge/guide_qc.py +0 -0
  119. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/bridge/ingest.py +0 -0
  120. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/bridge/offtarget.py +0 -0
  121. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/bridge/offtarget_energetics.py +0 -0
  122. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/bridge/ortholog_screen.py +0 -0
  123. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/bridge/pipeline.py +0 -0
  124. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/cli.py +0 -0
  125. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/data/__init__.py +0 -0
  126. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/data/encode.py +0 -0
  127. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/data/genome.py +0 -0
  128. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/data/ingest_chromatin.py +0 -0
  129. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/data/ingest_integration.py +0 -0
  130. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/data/ingest_safety_annot.py +0 -0
  131. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/data/ingest_trip.py +0 -0
  132. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/env/__init__.py +0 -0
  133. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/env/genome_writing_env.py +0 -0
  134. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/env/policies.py +0 -0
  135. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/graph/__init__.py +0 -0
  136. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/graph/build.py +0 -0
  137. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/graph/cell_types.py +0 -0
  138. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/graph/ingest.py +0 -0
  139. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/graph/query.py +0 -0
  140. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/graph/schema.py +0 -0
  141. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/mech/__init__.py +0 -0
  142. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/mech/classify_atlas.py +0 -0
  143. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/mech/whitelist.py +0 -0
  144. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/monitor/__init__.py +0 -0
  145. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/monitor/europepmc.py +0 -0
  146. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/monitor/run.py +0 -0
  147. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/monitor/triage.py +0 -0
  148. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/oracles/__init__.py +0 -0
  149. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/oracles/cache.py +0 -0
  150. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/oracles/energetics.py +0 -0
  151. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/oracles/genome.py +0 -0
  152. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/oracles/protein_design.py +0 -0
  153. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/oracles/rna.py +0 -0
  154. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/oracles/schema.py +0 -0
  155. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/oracles/structure.py +0 -0
  156. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/planner/__init__.py +0 -0
  157. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/planner/cargo.py +0 -0
  158. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/planner/cargo_polish.py +0 -0
  159. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/planner/delivery.py +0 -0
  160. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/planner/delivery_constraints.py +0 -0
  161. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/planner/delivery_vehicles.py +0 -0
  162. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/planner/genotoxicity_oracle.py +0 -0
  163. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/planner/multiplex.py +0 -0
  164. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/planner/optimize.py +0 -0
  165. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/planner/pipeline.py +0 -0
  166. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/planner/report.py +0 -0
  167. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/planner/router.py +0 -0
  168. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/planner/target_site.py +0 -0
  169. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/rag/__init__.py +0 -0
  170. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/rag/index.py +0 -0
  171. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/rag/llm.py +0 -0
  172. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/rag/qa.py +0 -0
  173. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/rules/__init__.py +0 -0
  174. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/rules/evaluators.py +0 -0
  175. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/rules/loader.py +0 -0
  176. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/rules/schema.py +0 -0
  177. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/rules/solver.py +0 -0
  178. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/score/__init__.py +0 -0
  179. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/score/recalibrate.py +0 -0
  180. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/score/therapeutic.py +0 -0
  181. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/server/__init__.py +0 -0
  182. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/server/api.py +0 -0
  183. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/ui/__init__.py +0 -0
  184. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/ui/app.py +0 -0
  185. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/__init__.py +0 -0
  186. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/adapt_demo.py +0 -0
  187. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/agent_eval.py +0 -0
  188. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/bench_adversarial_tasks.py +0 -0
  189. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/bench_coscientist_tasks.py +0 -0
  190. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/bench_graph_tasks.py +0 -0
  191. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/bench_rule_tasks.py +0 -0
  192. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/bench_trust_tasks.py +0 -0
  193. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/bench_writetype_tasks.py +0 -0
  194. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/blind_gsh_discovery.py +0 -0
  195. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/cargo_directionality.py +0 -0
  196. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/durability_baselines.py +0 -0
  197. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/forward_hypotheses.py +0 -0
  198. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/guide_qc_demo.py +0 -0
  199. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/intent_specification.py +0 -0
  200. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/offtarget_energetics_eval.py +0 -0
  201. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/out_of_scope_refusal.py +0 -0
  202. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/outcome_calibration.py +0 -0
  203. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/paper3_benchmark.py +0 -0
  204. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/paper4_real_validation.py +0 -0
  205. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/paper4_validation.py +0 -0
  206. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/selective_prediction.py +0 -0
  207. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/seq_vs_measured.py +0 -0
  208. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/target_site_controls.py +0 -0
  209. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/uncertainty_eval.py +0 -0
  210. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/ungrounded_baseline.py +0 -0
  211. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/within_locus_ranking.py +0 -0
  212. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/validate/writer_recovery.py +0 -0
  213. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/verify/__init__.py +0 -0
  214. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/verify/schema.py +0 -0
  215. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/verify/service.py +0 -0
  216. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/wgenome/__init__.py +0 -0
  217. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/wgenome/chromatin_seq.py +0 -0
  218. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/wgenome/durability.py +0 -0
  219. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/wgenome/export_tracks.py +0 -0
  220. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/wgenome/features.py +0 -0
  221. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/wgenome/gsh_baseline.py +0 -0
  222. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/wgenome/mesh_features.py +0 -0
  223. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/wgenome/ood.py +0 -0
  224. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/wgenome/providers.py +0 -0
  225. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/wgenome/safety.py +0 -0
  226. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/wgenome/structure3d.py +0 -0
  227. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/wgenome/uncertainty.py +0 -0
  228. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack/wgenome/writability.py +0 -0
  229. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack.egg-info/dependency_links.txt +0 -0
  230. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack.egg-info/entry_points.txt +0 -0
  231. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack.egg-info/requires.txt +0 -0
  232. {pen_stack-5.2.0 → pen_stack-5.3.0}/pen_stack.egg-info/top_level.txt +0 -0
  233. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_phase0.json +0 -0
  234. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_phase1_5.json +0 -0
  235. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_phase2.json +0 -0
  236. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_phase3.json +0 -0
  237. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_a.json +0 -0
  238. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_atlas.json +0 -0
  239. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_b.json +0 -0
  240. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_ba.json +0 -0
  241. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_ba_v33.json +0 -0
  242. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_ba_v45.json +0 -0
  243. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_bench.json +0 -0
  244. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_c.json +0 -0
  245. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_cal.json +0 -0
  246. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_cite.json +0 -0
  247. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_crit.json +0 -0
  248. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_ct.json +0 -0
  249. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_d.json +0 -0
  250. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_e.json +0 -0
  251. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_env.json +0 -0
  252. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_ep.json +0 -0
  253. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_f.json +0 -0
  254. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_g.json +0 -0
  255. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_genotox.json +0 -0
  256. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_graph.json +0 -0
  257. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_h.json +0 -0
  258. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_immune.json +0 -0
  259. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_mc.json +0 -0
  260. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_mon.json +0 -0
  261. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_o.json +0 -0
  262. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_plan.json +0 -0
  263. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_r.json +0 -0
  264. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_route.json +0 -0
  265. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_uq.json +0 -0
  266. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_v.json +0 -0
  267. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/SHA256_LOCK_ws_wv.json +0 -0
  268. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/paper1.yaml +0 -0
  269. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/paper2.yaml +0 -0
  270. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/paper3.yaml +0 -0
  271. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/paper4.yaml +0 -0
  272. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/phase0.yaml +0 -0
  273. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_a.yaml +0 -0
  274. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_atlas.yaml +0 -0
  275. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_b.yaml +0 -0
  276. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_ba.yaml +0 -0
  277. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_ba_v33.yaml +0 -0
  278. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_ba_v45.yaml +0 -0
  279. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_bench.yaml +0 -0
  280. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_c.yaml +0 -0
  281. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_cal.yaml +0 -0
  282. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_cite.yaml +0 -0
  283. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_crit.yaml +0 -0
  284. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_ct.yaml +0 -0
  285. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_d.yaml +0 -0
  286. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_e.yaml +0 -0
  287. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_env.yaml +0 -0
  288. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_ep.yaml +0 -0
  289. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_f.yaml +0 -0
  290. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_g.yaml +0 -0
  291. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_genotox.yaml +0 -0
  292. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_graph.yaml +0 -0
  293. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_h.yaml +0 -0
  294. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_immune.yaml +0 -0
  295. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_mc.yaml +0 -0
  296. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_mon.yaml +0 -0
  297. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_o.yaml +0 -0
  298. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_plan.yaml +0 -0
  299. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_r.yaml +0 -0
  300. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_route.yaml +0 -0
  301. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_uq.yaml +0 -0
  302. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_v.yaml +0 -0
  303. {pen_stack-5.2.0 → pen_stack-5.3.0}/prereg/ws_wv.yaml +0 -0
  304. {pen_stack-5.2.0 → pen_stack-5.3.0}/scripts/p1_build_atlas.py +0 -0
  305. {pen_stack-5.2.0 → pen_stack-5.3.0}/scripts/p1_build_durability.py +0 -0
  306. {pen_stack-5.2.0 → pen_stack-5.3.0}/scripts/p1_export_tracks.py +0 -0
  307. {pen_stack-5.2.0 → pen_stack-5.3.0}/scripts/p1_safety_concordance.py +0 -0
  308. {pen_stack-5.2.0 → pen_stack-5.3.0}/scripts/p1_train_safety.py +0 -0
  309. {pen_stack-5.2.0 → pen_stack-5.3.0}/scripts/p1_validation_report.py +0 -0
  310. {pen_stack-5.2.0 → pen_stack-5.3.0}/scripts/p2_build_atlas.py +0 -0
  311. {pen_stack-5.2.0 → pen_stack-5.3.0}/scripts/p3_benchmark_report.py +0 -0
  312. {pen_stack-5.2.0 → pen_stack-5.3.0}/scripts/p4_genome_scan.py +0 -0
  313. {pen_stack-5.2.0 → pen_stack-5.3.0}/scripts/p52_build_genotox_oracle.py +0 -0
  314. {pen_stack-5.2.0 → pen_stack-5.3.0}/scripts/ws_b_report.py +0 -0
  315. {pen_stack-5.2.0 → pen_stack-5.3.0}/scripts/ws_c_report.py +0 -0
  316. {pen_stack-5.2.0 → pen_stack-5.3.0}/setup.cfg +0 -0
@@ -3,6 +3,41 @@
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.3.0] - 2026-06-10 - v5.3 release: Computed capsid epitope-load oracle (covers all vectors)
7
+
8
+ v5.2 computed genotoxicity only meaningfully touches integrating vectors. v5.3 brings the **NetMHC-style
9
+ calculation** to the **adaptive (CD8 T-cell)** axis — the fraction of a viral vector's capsid/envelope that is
10
+ presentable across a frequent HLA-I panel (MHCflurry) — so the computed immune signal **covers all 8 vehicles**
11
+ (5 viral computed, 3 non-viral by mechanism). Workstream WS-EPITOPE, SHA-locked.
12
+
13
+ ### Added
14
+ - **WS-EPITOPE build** — `scripts/p53_build_epitope_oracle.py` (runs in a dedicated `penstack:mhcflurry` image)
15
+ slides 9-mers across each capsid/envelope antigen and predicts MHCflurry 2.0 affinity %rank per allele across
16
+ 12 frequent HLA-I alleles; `epitope_fraction_strong` = residues covered by a strong binder (%rank ≤ 0.5);
17
+ `capsid_immune_score = 1 − epitope_fraction_strong`. Sequences UniProt-verified and committed
18
+ (`configs/capsid_sequences.fasta`): AAV2 VP1 P03135, Ad5 hexon P04133, VSV-G P03522, HSV-1 gD P57083 + gB
19
+ P06437. Emits the small committed summary `configs/capsid_epitope_oracle.yaml` (MHCflurry + raw sequences stay
20
+ on the VM → CI-safe).
21
+ - **WS-EPITOPE oracle** — `pen_stack/planner/capsid_epitope_oracle.py`: `capsid_epitope_oracle(vehicle)` returns
22
+ an `OracleResult` (`output_kind="baseline"`, scope card `capsid_epitope`). Non-viral vehicles → 1.0 by
23
+ mechanism; unknown / sequence-less → **abstains**.
24
+ - **Wired into the adaptive axis** — `safety_efficacy_profile()` folds the computed capsid score into the
25
+ adaptive (CD8) sub-axis **only for in-vivo vehicles**. The computed score is *intrinsic* antigen
26
+ presentability; for **ex-vivo** lentivirus (whose VSV-G envelope is intrinsically epitope-dense but barely
27
+ seen by the host ex vivo) it is **reported but not folded** (`adaptive_source = computed_ex_vivo_muted`), the
28
+ documented tier kept. `capsid_presentability_score` surfaces the raw computed value.
29
+ - **Result:** AAV2 capsid is the *least* epitope-dense (0.72) and Ad5 hexon among the most (0.82); HDAd's in-vivo
30
+ immune score drops accordingly — the documented adaptive ordering reproduced from sequence. `prereg/ws_epitope.yaml`.
31
+
32
+ ### Changed
33
+ - Version 5.2.0 -> 5.3.0 (minor — additive computed oracle); `cite.curated_dois()` ingests the epitope
34
+ provenance DOIs (MHCflurry 10.1016/j.cels.2020.06.010, HLA-I supertypes 10.1186/1471-2172-9-1).
35
+
36
+ ### Honesty invariant (unchanged)
37
+ - Population-level, **sequence-intrinsic presentation** signal (does the capsid contain HLA binders) — **not**
38
+ the realized in-vivo / **patient-HLA-specific** T-cell response (a known-unknown), and **CD8/MHC-I only** (not
39
+ antibody / neutralizing-antibody). No magnitude predicted.
40
+
6
41
  ## [5.2.0] - 2026-06-10 - v5.2 release: Computed genotoxicity oracle (data, not a documented tier)
7
42
 
8
43
  The v5.1 genotoxicity axis was a documented ordinal tier; for **integrating** vectors that signal is in fact
@@ -1,7 +1,7 @@
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.2.0
4
+ version: 5.3.0
5
5
  date-released: 2026-06-10
6
6
  authors:
7
7
  - family-names: "Mahaboob Ali"
@@ -2,7 +2,7 @@
2
2
  # source build is reproducible. Large artifacts (atlases, BigWig, models) are NOT shipped - they are on
3
3
  # Zenodo (DOI) per the data policy; clone the repo + fetch Zenodo for the full pipeline.
4
4
  include README.md LICENSE CHANGELOG.md CITATION.cff pyproject.toml
5
- recursive-include configs *.yaml *.yml *.txt.example
5
+ recursive-include configs *.yaml *.yml *.txt.example *.fasta
6
6
  recursive-include prereg *.yaml *.json
7
7
  recursive-include data/curated *
8
8
  recursive-include benchmarks *.yaml *.md SHA256SUMS
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pen-stack
3
- Version: 5.2.0
3
+ Version: 5.3.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
@@ -91,7 +91,7 @@ every design against rule-grounded mechanism, reports calibrated confidence, cit
91
91
  [![codecov](https://codecov.io/gh/ahmedanees-m/pen-stack/branch/main/graph/badge.svg)](https://codecov.io/gh/ahmedanees-m/pen-stack)
92
92
  [![License: MIT](https://img.shields.io/badge/License-MIT-informational.svg)](LICENSE)
93
93
  [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/)
94
- [![Version](https://img.shields.io/badge/version-5.2.0-blue.svg)](CHANGELOG.md)
94
+ [![Version](https://img.shields.io/badge/version-5.3.0-blue.svg)](CHANGELOG.md)
95
95
  [![Tests](https://img.shields.io/badge/tests-240%20passing-success.svg)](tests/)
96
96
  [![Lint: ruff](https://img.shields.io/badge/lint-ruff-purple.svg)](https://github.com/astral-sh/ruff)
97
97
  [![Runtime: Docker](https://img.shields.io/badge/runtime-docker-2496ED.svg)](docker/)
@@ -135,6 +135,22 @@ Two questions gate every genome-writing project, and before PEN-STACK no resourc
135
135
  Everything is built on bulk-downloadable public data, runs on a single GPU, and is validated **blind** against
136
136
  a pre-registered, honest baseline before release.
137
137
 
138
+ ## What is new in v5.3 — Computed capsid epitope-load oracle (covers all vectors)
139
+
140
+ v5.2 computed genotoxicity only touches integrating vectors. v5.3 brings the **NetMHC-style calculation** to the
141
+ **adaptive (CD8 T-cell)** axis: the fraction of a viral vector's capsid/envelope presentable across a frequent
142
+ HLA-I panel (MHCflurry), so the computed immune signal now **covers all 8 vehicles** — 5 viral computed, 3
143
+ non-viral by mechanism. It is a population-level, *sequence-intrinsic* presentation signal; the realized
144
+ patient-HLA-specific T-cell response stays a known-unknown (and it is CD8/MHC-I only, not antibody).
145
+
146
+ | Workstream | What it adds | Result |
147
+ |---|---|---|
148
+ | **EPITOPE build** | `scripts/p53_build_epitope_oracle.py` → committed `configs/capsid_epitope_oracle.yaml` | per viral capsid: `epitope_fraction_strong` over 9-mers × 12 HLA-I alleles (MHCflurry %rank ≤ 0.5), from UniProt-verified sequences (AAV2 VP1, Ad5 hexon, VSV-G, HSV gD/gB); MHCflurry stays on the VM, only the summary ships |
149
+ | **EPITOPE oracle** | `planner/capsid_epitope_oracle.py` (`OracleResult`) | `capsid_immune_score = 1 − epitope_fraction_strong`; non-viral → 1.0 by mechanism; abstains when no sequence |
150
+ | **wired into the adaptive axis** | folded **only for in-vivo** vehicles | AAV2 least epitope-dense (0.72), Ad5 hexon among the most (0.82) — documented adaptive ordering reproduced from sequence; **ex-vivo** lentivirus's intrinsic VSV-G load is *reported but muted* (host barely sees it ex vivo) |
151
+
152
+ See `prereg/ws_epitope.yaml` and the `capsid_epitope` scope card.
153
+
138
154
  ## What is new in v5.2 — Computed genotoxicity oracle (data, not a documented tier)
139
155
 
140
156
  v5.1 scored genotoxicity as a documented `low/moderate/high` tier. v5.2 makes it **computed from data** for
@@ -16,7 +16,7 @@ every design against rule-grounded mechanism, reports calibrated confidence, cit
16
16
  [![codecov](https://codecov.io/gh/ahmedanees-m/pen-stack/branch/main/graph/badge.svg)](https://codecov.io/gh/ahmedanees-m/pen-stack)
17
17
  [![License: MIT](https://img.shields.io/badge/License-MIT-informational.svg)](LICENSE)
18
18
  [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/)
19
- [![Version](https://img.shields.io/badge/version-5.2.0-blue.svg)](CHANGELOG.md)
19
+ [![Version](https://img.shields.io/badge/version-5.3.0-blue.svg)](CHANGELOG.md)
20
20
  [![Tests](https://img.shields.io/badge/tests-240%20passing-success.svg)](tests/)
21
21
  [![Lint: ruff](https://img.shields.io/badge/lint-ruff-purple.svg)](https://github.com/astral-sh/ruff)
22
22
  [![Runtime: Docker](https://img.shields.io/badge/runtime-docker-2496ED.svg)](docker/)
@@ -60,6 +60,22 @@ Two questions gate every genome-writing project, and before PEN-STACK no resourc
60
60
  Everything is built on bulk-downloadable public data, runs on a single GPU, and is validated **blind** against
61
61
  a pre-registered, honest baseline before release.
62
62
 
63
+ ## What is new in v5.3 — Computed capsid epitope-load oracle (covers all vectors)
64
+
65
+ v5.2 computed genotoxicity only touches integrating vectors. v5.3 brings the **NetMHC-style calculation** to the
66
+ **adaptive (CD8 T-cell)** axis: the fraction of a viral vector's capsid/envelope presentable across a frequent
67
+ HLA-I panel (MHCflurry), so the computed immune signal now **covers all 8 vehicles** — 5 viral computed, 3
68
+ non-viral by mechanism. It is a population-level, *sequence-intrinsic* presentation signal; the realized
69
+ patient-HLA-specific T-cell response stays a known-unknown (and it is CD8/MHC-I only, not antibody).
70
+
71
+ | Workstream | What it adds | Result |
72
+ |---|---|---|
73
+ | **EPITOPE build** | `scripts/p53_build_epitope_oracle.py` → committed `configs/capsid_epitope_oracle.yaml` | per viral capsid: `epitope_fraction_strong` over 9-mers × 12 HLA-I alleles (MHCflurry %rank ≤ 0.5), from UniProt-verified sequences (AAV2 VP1, Ad5 hexon, VSV-G, HSV gD/gB); MHCflurry stays on the VM, only the summary ships |
74
+ | **EPITOPE oracle** | `planner/capsid_epitope_oracle.py` (`OracleResult`) | `capsid_immune_score = 1 − epitope_fraction_strong`; non-viral → 1.0 by mechanism; abstains when no sequence |
75
+ | **wired into the adaptive axis** | folded **only for in-vivo** vehicles | AAV2 least epitope-dense (0.72), Ad5 hexon among the most (0.82) — documented adaptive ordering reproduced from sequence; **ex-vivo** lentivirus's intrinsic VSV-G load is *reported but muted* (host barely sees it ex vivo) |
76
+
77
+ See `prereg/ws_epitope.yaml` and the `capsid_epitope` scope card.
78
+
63
79
  ## What is new in v5.2 — Computed genotoxicity oracle (data, not a documented tier)
64
80
 
65
81
  v5.1 scored genotoxicity as a documented `low/moderate/high` tier. v5.2 makes it **computed from data** for
@@ -0,0 +1,85 @@
1
+ version: '1.0'
2
+ built: '2026-06-10'
3
+ description: 'computed capsid/envelope CD8 T-cell epitope-load oracle: fraction of
4
+ the antigen presentable (MHCflurry %rank<=0.5) across a frequent HLA-I panel. capsid_immune_score
5
+ = 1 - epitope_fraction_strong. Patient-HLA-specific response is NOT modelled (known-unknown);
6
+ this is a population-level sequence-intrinsic signal.'
7
+ method:
8
+ predictor: MHCflurry 2.0 Class1AffinityPredictor (per-allele %rank)
9
+ peptide_len: 9
10
+ strong_rank: 0.5
11
+ binder_rank: 2.0
12
+ hla_panel:
13
+ - HLA-A*01:01
14
+ - HLA-A*02:01
15
+ - HLA-A*03:01
16
+ - HLA-A*11:01
17
+ - HLA-A*24:02
18
+ - HLA-A*26:01
19
+ - HLA-B*07:02
20
+ - HLA-B*08:01
21
+ - HLA-B*15:01
22
+ - HLA-B*40:01
23
+ - HLA-B*44:03
24
+ - HLA-B*58:01
25
+ provenance_dois:
26
+ - 10.1016/j.cels.2020.06.010
27
+ - 10.1186/1471-2172-9-1
28
+ proteins:
29
+ AAV2_VP1:
30
+ length: 735
31
+ n_9mers: 727
32
+ epitope_fraction_strong: 0.7197
33
+ epitope_fraction_binder: 0.9755
34
+ strong_binder_density: 0.01433
35
+ Ad5_hexon:
36
+ length: 952
37
+ n_9mers: 944
38
+ epitope_fraction_strong: 0.8204
39
+ epitope_fraction_binder: 0.979
40
+ strong_binder_density: 0.02127
41
+ VSVg_Indiana:
42
+ length: 511
43
+ n_9mers: 503
44
+ epitope_fraction_strong: 0.8356
45
+ epitope_fraction_binder: 0.9922
46
+ strong_binder_density: 0.0174
47
+ HSV1_gD:
48
+ length: 394
49
+ n_9mers: 386
50
+ epitope_fraction_strong: 0.7893
51
+ epitope_fraction_binder: 0.9822
52
+ strong_binder_density: 0.01619
53
+ HSV1_gB:
54
+ length: 904
55
+ n_9mers: 896
56
+ epitope_fraction_strong: 0.7965
57
+ epitope_fraction_binder: 0.979
58
+ strong_binder_density: 0.01851
59
+ vehicles:
60
+ AAV_single:
61
+ antigens:
62
+ - AAV2_VP1
63
+ epitope_fraction_strong: 0.7197
64
+ capsid_immune_score: 0.2803
65
+ AAV_dual:
66
+ antigens:
67
+ - AAV2_VP1
68
+ epitope_fraction_strong: 0.7197
69
+ capsid_immune_score: 0.2803
70
+ lentivirus:
71
+ antigens:
72
+ - VSVg_Indiana
73
+ epitope_fraction_strong: 0.8356
74
+ capsid_immune_score: 0.1644
75
+ helper_dependent_adenovirus:
76
+ antigens:
77
+ - Ad5_hexon
78
+ epitope_fraction_strong: 0.8204
79
+ capsid_immune_score: 0.1796
80
+ hsv_amplicon:
81
+ antigens:
82
+ - HSV1_gD
83
+ - HSV1_gB
84
+ epitope_fraction_strong: 0.7929
85
+ capsid_immune_score: 0.2071
@@ -0,0 +1,66 @@
1
+ >AAV2_VP1|P03135 len=735
2
+ MAADGYLPDWLEDTLSEGIRQWWKLKPGPPPPKPAERHKDDSRGLVLPGYKYLGPFNGLD
3
+ KGEPVNEADAAALEHDKAYDRQLDSGDNPYLKYNHADAEFQERLKEDTSFGGNLGRAVFQ
4
+ AKKRVLEPLGLVEEPVKTAPGKKRPVEHSPVEPDSSSGTGKAGQQPARKRLNFGQTGDAD
5
+ SVPDPQPLGQPPAAPSGLGTNTMATGSGAPMADNNEGADGVGNSSGNWHCDSTWMGDRVI
6
+ TTSTRTWALPTYNNHLYKQISSQSGASNDNHYFGYSTPWGYFDFNRFHCHFSPRDWQRLI
7
+ NNNWGFRPKRLNFKLFNIQVKEVTQNDGTTTIANNLTSTVQVFTDSEYQLPYVLGSAHQG
8
+ CLPPFPADVFMVPQYGYLTLNNGSQAVGRSSFYCLEYFPSQMLRTGNNFTFSYTFEDVPF
9
+ HSSYAHSQSLDRLMNPLIDQYLYYLSRTNTPSGTTTQSRLQFSQAGASDIRDQSRNWLPG
10
+ PCYRQQRVSKTSADNNNSEYSWTGATKYHLNGRDSLVNPGPAMASHKDDEEKFFPQSGVL
11
+ IFGKQGSEKTNVDIEKVMITDEEEIRTTNPVATEQYGSVSTNLQRGNRQAATADVNTQGV
12
+ LPGMVWQDRDVYLQGPIWAKIPHTDGHFHPSPLMGGFGLKHPPPQILIKNTPVPANPSTT
13
+ FSAAKFASFITQYSTGQVSVEIEWELQKENSKRWNPEIQYTSNYNKSVNVDFTVDTNGVY
14
+ SEPRPIGTRYLTRNL
15
+ >Ad5_hexon|P04133 len=952
16
+ MATPSMMPQWSYMHISGQDASEYLSPGLVQFARATETYFSLNNKFRNPTVAPTHDVTTDR
17
+ SQRLTLRFIPVDREDTAYSYKARFTLAVGDNRVLDMASTYFDIRGVLDRGPTFKPYSGTA
18
+ YNALAPKGAPNPCEWDEAATALEINLEEEDDDNEDEVDEQAEQQKTHVFGQAPYSGINIT
19
+ KEGIQIGVEGQTPKYADKTFQPEPQIGESQWYETEINHAAGRVLKKTTPMKPCYGSYAKP
20
+ TNENGGQGILVKQQNGKLESQVEMQFFSTTEATAGNGDNLTPKVVLYSEDVDIETPDTHI
21
+ SYMPTIKEGNSRELMGQQSMPNRPNYIAFRDNFIGLMYYNSTGNMGVLAGQASQLNAVVD
22
+ LQDRNTELSYQLLLDSIGDRTRYFSMWNQAVDSYDPDVRIIENHGTEDELPNYCFPLGGV
23
+ INTETLTKVKPKTGQENGWEKDATEFSDKNEIRVGNNFAMEINLNANLWRNFLYSNIALY
24
+ LPDKLKYSPSNVKISDNPNTYDYMNKRVVAPGLVDCYINLGARWSLDYMDNVNPFNHHRN
25
+ AGLRYRSMLLGNGRYVPFHIQVPQKFFAIKNLLLLPGSYTYEWNFRKDVNMVLQSSLGND
26
+ LRVDGASIKFDSICLYATFFPMAHNTASTLEAMLRNDTNDQSFNDYLSAANMLYPIPANA
27
+ TNVPISIPSRNWAAFRGWAFTRLKTKETPSLGSGYDPYYTYSGSIPYLDGTFYLNHTFKK
28
+ VAITFDSSVSWPGNDRLLTPNEFEIKRSVDGEGYNVAQCNMTKDWFLVQMLANYNIGYQG
29
+ FYIPESYKDRMYSFFRNFQPMSRQVVDDTKYKDYQQVGILHQHNNSGFVGYLAPTMREGQ
30
+ AYPANFPYPLIGKTAVDSITQKKFLCDRTLWRIPFSSNFMSMGALTDLGQNLLYANSAHA
31
+ LDMTFEVDPMDEPTLLYVLFEVFDVVRVHRPHRGVIETVYLRTPFSAGNATT
32
+ >VSVg_Indiana|P03522 len=511
33
+ MKCLLYLAFLFIGVNCKFTIVFPHNQKGNWKNVPSNYHYCPSSSDLNWHNDLIGTAIQVK
34
+ MPKSHKAIQADGWMCHASKWVTTCDFRWYGPKYITQSIRSFTPSVEQCKESIEQTKQGTW
35
+ LNPGFPPQSCGYATVTDAEAVIVQVTPHHVLVDEYTGEWVDSQFINGKCSNYICPTVHNS
36
+ TTWHSDYKVKGLCDSNLISMDITFFSEDGELSSLGKEGTGFRSNYFAYETGGKACKMQYC
37
+ KHWGVRLPSGVWFEMADKDLFAAARFPECPEGSSISAPSQTSVDVSLIQDVERILDYSLC
38
+ QETWSKIRAGLPISPVDLSYLAPKNPGTGPAFTIINGTLKYFETRYIRVDIAAPILSRMV
39
+ GMISGTTTERELWDDWAPYEDVEIGPNGVLRTSSGYKFPLYMIGHGMLDSDLHLSSKAQV
40
+ FEHPHIQDAASQLPDDESLFFGDTGLSKNPIELVEGWFSSWKSSIASFFFIIGLIIGLFL
41
+ VLRVGIHLCIKLKHTKKRQIYTDIEMNRLGK
42
+ >HSV1_gD|P57083 len=394
43
+ MGGTAARLGAVILFVVIVGLHGVRGKYALADASLKMADPNRFRGKDLPVLDQLTDPPGVR
44
+ RVYHIQAGLPDPFQPPSLPITVYYAVLERACRSVLLNAPSEAPQIVRGASEDVRKQPYNL
45
+ TIAWFRMGGNCAIPITVMEYTECSYNKSLGACPIRTQPRWNYYDSFSAVSEDNLGFLMHA
46
+ PAFETAGTYLRLVKINDWTEITQFILEHRAKGSCKYALPLRIPPSACLSPQAYQQGVTVD
47
+ SIGMLPRFIPENQRTVAVYSLKIAGWHGPKAPYTSTLLPPELSETPNATQPELAPEDPED
48
+ SALLEDPVGTVAPQIPPNWHIPSIQDAATPYHPPATPNNMGLIAGAVGGSLLAALVICGI
49
+ VYWMHRRTRKAPKRIRLPHIREDDQPSSHQPLFY
50
+ >HSV1_gB|P06437 len=904
51
+ MHQGAPSWGRRWFVVWALLGLTLGVLVASAAPTSPGTPGVAAATQAANGGPATPAPPPLG
52
+ AAPTGDPKPKKNKKPKNPTPPRPAGDNATVAAGHATLREHLRDIKAENTDANFYVCPPPT
53
+ GATVVQFEQPRRCPTRPEGQNYTEGIAVVFKENIAPYKFKATMYYKDVTVSQVWFGHRYS
54
+ QFMGIFEDRAPVPFEEVIDKINAKGVCRSTAKYVRNNLETTAFHRDDHETDMELKPANAA
55
+ TRTSRGWHTTDLKYNPSRVEAFHRYGTTVNCIVEEVDARSVYPYDEFVLATGDFVYMSPF
56
+ YGYREGSHTEHTTYAADRFKQVDGFYARDLTTKARATAPTTRNLLTTPKFTVAWDWVPKR
57
+ PSVCTMTKWQEVDEMLRSEYGGSFRFSSDAISTTFTTNLTEYPLSRVDLGDCIGKDARDA
58
+ MDRIFARRYNATHIKVGQPQYYQANGGFLIAYQPLLSNTLAELYVREHLREQSRKPPNPT
59
+ PPPPGASANASVERIKTTSSIEFARLQFTYNHIQRHVNDMLGRVAIAWCELQNHELTLWN
60
+ EARKLNPNAIASVTVGRRVSARMLGDVMAVSTCVPVAADNVIVQNSMRISSRPGACYSRP
61
+ LVSFRYEDQGPLVEGQLGENNELRLTRDAIEPCTVGHRRYFTFGGGYVYFEEYAYSHQLS
62
+ RADITTVSTFIDLNITMLEDHEFVPLEVYTRHEIKDSGLLDYTEVQRRNQLHDLRFADID
63
+ TVIHADANAAMFAGLGAFFEGMGDLGRAVGKVVMGIVGGVVSAVSGVSSFMSNPFGALAV
64
+ GLLVLAGLAAAFFAFRYVMRLQSNPMKALYPLTTKELKNPTNPDASGEGEEGGDFDEAKL
65
+ AEAREMIRYMALVSAMERTEHKAKKKGTSALLSAKVTDMVMRKRRNTNYTQVPNKDGDAD
66
+ EDDL
@@ -125,3 +125,16 @@ oracles:
125
125
  classes with too few catalogued sites (flagged extrapolating)"
126
126
  generalizes_to_unseen_loci: false
127
127
  license: "open (this work; VISDB 10.1093/nar/gkz867, COSMIC CGC 10.1038/s41568-018-0060-1)"
128
+
129
+ capsid_epitope: # v5.3 WS-EPITOPE: computed capsid/envelope CD8 T-cell epitope load
130
+ family: protein_design
131
+ version: "mhcflurry2.0-2026"
132
+ output_kind: baseline # sequence-intrinsic presentation comparator, not generative
133
+ valid_for: "RELATIVE adaptive (CD8 / MHC-I) immunogenicity ordering of VIRAL vector capsids/envelopes via
134
+ the fraction of the antigen presentable across a frequent HLA-I panel (MHCflurry %rank<=0.5), from
135
+ UniProt-sourced sequences; population-level, sequence-intrinsic"
136
+ not_valid_for: "the realized in-vivo / PATIENT-HLA-specific T-cell response (a known-unknown); antibody /
137
+ neutralizing-antibody (B-cell) immunity (this is CD8/MHC-I only); non-viral vehicles (no capsid protein);
138
+ a viral vehicle whose antigen sequence is not committed (abstains)"
139
+ generalizes_to_unseen_loci: false
140
+ license: "open (this work; MHCflurry 10.1016/j.cels.2020.06.010, HLA-I supertypes 10.1186/1471-2172-9-1)"
@@ -1,2 +1,2 @@
1
1
  """PEN-STACK v3.0 - open infrastructure for genome writing."""
2
- __version__ = "5.2.0"
2
+ __version__ = "5.3.0"
@@ -29,12 +29,13 @@ def curated_dois() -> frozenset[str]:
29
29
  for v in veh.values():
30
30
  dois.update(v.get("dois", []) or [])
31
31
  dois.update((v.get("immune_safety") or {}).get("immune_dois", []) or []) # v5.1 immune priors
32
- # v5.2 computed-genotoxicity oracle provenance (VISDB, COSMIC CGC, integration-biology refs)
33
- try:
34
- gt = yaml.safe_load(resource("configs/genotoxicity_oracle.yaml").read_text(encoding="utf-8"))
35
- dois.update(gt.get("provenance_dois", []) or [])
36
- except FileNotFoundError:
37
- pass
32
+ # v5.2/v5.3 computed-oracle provenance (genotoxicity: VISDB/COSMIC; capsid epitope: MHCflurry/HLA)
33
+ for _art in ("configs/genotoxicity_oracle.yaml", "configs/capsid_epitope_oracle.yaml"):
34
+ try:
35
+ a = yaml.safe_load(resource(_art).read_text(encoding="utf-8"))
36
+ dois.update(a.get("provenance_dois", []) or [])
37
+ except FileNotFoundError:
38
+ pass
38
39
  gsh = yaml.safe_load(resource("configs/gsh_validated_heldout.yaml").read_text(encoding="utf-8"))["gsh"]
39
40
  for g in gsh:
40
41
  if g.get("doi"):
@@ -0,0 +1,97 @@
1
+ """Computed capsid/envelope T-cell epitope-load oracle for viral delivery vectors (v5.3, WS-EPITOPE).
2
+
3
+ Refines the documented `adaptive_immune` (CD8 T-cell) tier with a DATA-COMPUTED signal for VIRAL vectors: the
4
+ fraction of the capsid/envelope antigen that is presentable across a frequent HLA-I panel (MHCflurry %rank
5
+ <= 0.5), from configs/capsid_epitope_oracle.yaml (built by scripts/p53_build_epitope_oracle.py in the dedicated
6
+ `penstack:mhcflurry` image over UniProt-sourced sequences).
7
+
8
+ capsid_immune_score = 1 - epitope_fraction_strong # 1 = least presentable / least immunogenic
9
+
10
+ This is the NetMHC-style calculation the user asked for, made population-level (averaged over a frequent-allele
11
+ panel) so it is NOT a patient-HLA-specific magnitude. Answers through the v4.0 OracleResult contract
12
+ (output_kind="baseline").
13
+
14
+ Coverage of the whole palette: VIRAL vectors (AAV, lentivirus[VSV-G], HDAd, HSV) get a computed score;
15
+ NON-VIRAL vectors (LNP-mRNA, eVLP, electroporation) have no foreign capsid protein -> score 1.0 by mechanism;
16
+ a viral vector with no committed antigen sequence -> ABSTAINS (never fabricates).
17
+
18
+ HONESTY: this is a population-level, sequence-intrinsic PRESENTATION signal (does the capsid contain HLA
19
+ binders), NOT the realized in-vivo / patient-HLA-specific T-cell response (a known-unknown); it is also CD8
20
+ (MHC-I) only - it does not model antibody / neutralizing-antibody (B-cell) immunity.
21
+ """
22
+ from __future__ import annotations
23
+
24
+ from functools import lru_cache
25
+
26
+ import yaml
27
+
28
+ from pen_stack._resources import resource
29
+ from pen_stack.oracles.schema import OracleResult, Provenance
30
+ from pen_stack.planner.delivery_vehicles import vehicle
31
+
32
+ _SCOPE_CARD = "capsid_epitope"
33
+ # non-viral vehicles have no foreign capsid/envelope protein -> no capsid CD8 epitope load (1.0 by mechanism).
34
+ _NON_VIRAL = {"lnp_mrna", "evlp", "electroporation"}
35
+
36
+
37
+ @lru_cache(maxsize=1)
38
+ def _artifact() -> dict:
39
+ return yaml.safe_load(resource("configs/capsid_epitope_oracle.yaml").read_text(encoding="utf-8"))
40
+
41
+
42
+ def _prov(**extra) -> Provenance:
43
+ art = _artifact()
44
+ return Provenance(model="mhcflurry_capsid_epitope", version=str(art.get("version", "1.0")), source="cache",
45
+ extra={"built": art.get("built"), "predictor": art.get("method", {}).get("predictor"),
46
+ "provenance_dois": art.get("provenance_dois", []), **extra})
47
+
48
+
49
+ def capsid_epitope_oracle(vehicle_name: str) -> OracleResult:
50
+ """Computed capsid CD8 epitope load for a delivery vehicle, as an OracleResult (v4.0 contract).
51
+
52
+ - viral vehicle with a committed antigen -> computed `capsid_immune_score` from MHCflurry x HLA panel.
53
+ - non-viral vehicle -> 1.0 by mechanism (no foreign capsid protein).
54
+ - unknown vehicle / viral-without-sequence -> available=False (caller falls back to the documented
55
+ adaptive_immune tier; no number fabricated)."""
56
+ rec = vehicle(vehicle_name)
57
+ if rec is None:
58
+ return OracleResult(oracle="protein_design", value=None, provenance=_prov(), scope_card=_SCOPE_CARD,
59
+ in_scope=False, available=False, output_kind="baseline",
60
+ note=f"unknown vehicle {vehicle_name!r}")
61
+
62
+ vehs = _artifact().get("vehicles") or {}
63
+ if vehicle_name in vehs:
64
+ v = vehs[vehicle_name]
65
+ ef = v["epitope_fraction_strong"]
66
+ return OracleResult(
67
+ oracle="protein_design",
68
+ value={"capsid_immune_score": v["capsid_immune_score"], "epitope_fraction_strong": ef,
69
+ "antigens": v.get("antigens"),
70
+ "hla_panel_size": len(_artifact().get("method", {}).get("hla_panel", []))},
71
+ provenance=_prov(antigens=v.get("antigens")), native_uncertainty=None,
72
+ scope_card=_SCOPE_CARD, in_scope=True, extrapolating=False, output_kind="baseline", available=True,
73
+ note=(f"{ef:.1%} of the {'/'.join(v.get('antigens', []))} antigen is presentable (MHCflurry "
74
+ f"%rank<=0.5) across a frequent HLA-I panel; capsid_immune_score=1-epitope_fraction. "
75
+ "Patient-HLA-specific T-cell response is a known-unknown (not modelled); CD8/MHC-I only "
76
+ "(not antibody/NAb)."))
77
+
78
+ if vehicle_name in _NON_VIRAL:
79
+ return OracleResult(
80
+ oracle="protein_design",
81
+ value={"capsid_immune_score": 1.0, "epitope_fraction_strong": 0.0, "mechanism": "non-viral"},
82
+ provenance=_prov(), native_uncertainty=0.0, scope_card=_SCOPE_CARD, in_scope=True,
83
+ extrapolating=False, output_kind="baseline", available=True,
84
+ note="non-viral vehicle: no foreign capsid/envelope protein -> no capsid CD8 epitope load (1.0).")
85
+
86
+ return OracleResult(oracle="protein_design", value=None, provenance=_prov(), scope_card=_SCOPE_CARD,
87
+ in_scope=False, available=False, output_kind="baseline",
88
+ note=f"viral vehicle {vehicle_name!r} has no committed antigen sequence; "
89
+ "fall back to the documented adaptive_immune tier.")
90
+
91
+
92
+ def computed_capsid_immune_score(vehicle_name: str) -> tuple[float | None, OracleResult]:
93
+ """Convenience: (capsid_immune_score or None, full OracleResult). None when the oracle abstains (caller
94
+ then uses the documented adaptive_immune tier). Never fabricates."""
95
+ r = capsid_epitope_oracle(vehicle_name)
96
+ val = (r.value or {}).get("capsid_immune_score") if (r.available and r.value) else None
97
+ return val, r
@@ -58,8 +58,28 @@ def safety_efficacy_profile(name: str) -> dict | None:
58
58
  if rec is None:
59
59
  return None
60
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
61
+ # per immune axis -> a 0..1 "safety" score (1 = least immunogenic). The ADAPTIVE (CD8 T-cell) axis can be
62
+ # COMPUTED from the capsid epitope load (v5.3 WS-EPITOPE: MHCflurry x HLA panel over the capsid/envelope
63
+ # antigen). The computed signal is INTRINSIC antigen presentability; it only translates to a realized host
64
+ # response when the host is actually exposed to the capsid (IN-VIVO use). So it is folded into the adaptive
65
+ # axis only for in-vivo vehicles; for EX-VIVO-only viral vectors (e.g. lentivirus, whose VSV-G envelope is
66
+ # intrinsically epitope-dense but barely seen by the host ex vivo) it is surfaced but NOT folded, and the
67
+ # documented tier is kept. The other three axes stay documented ordinal tiers. No number is fabricated.
68
+ from pen_stack.planner.capsid_epitope_oracle import computed_capsid_immune_score
69
+ cap_score, cap_oracle = computed_capsid_immune_score(name)
70
+ in_vivo = bool(rec.get("in_vivo"))
71
+ axis_scores: dict[str, float | None] = {}
72
+ for ax in _IMMUNE_AXES:
73
+ t = _tier(imm.get(ax))
74
+ axis_scores[ax] = (1.0 - t / 2.0) if t is not None else None
75
+ adaptive_source = "documented"
76
+ if cap_score is not None and in_vivo:
77
+ axis_scores["adaptive_immune"] = cap_score # in-vivo: host sees the capsid -> fold computed
78
+ adaptive_source = "computed"
79
+ elif cap_score is not None and not in_vivo:
80
+ adaptive_source = "computed_ex_vivo_muted" # reported, but ex-vivo mutes the realized response
81
+ immune_present = [s for s in axis_scores.values() if s is not None]
82
+ immune_score = (sum(immune_present) / len(immune_present)) if immune_present else None
63
83
  # genotoxicity: prefer the COMPUTED oracle (v5.2 WS-GENOTOX: integration-site x COSMIC-oncogene
64
84
  # enrichment, from VISDB) for integrating vectors; fall back to the documented ordinal tier when the
65
85
  # oracle abstains. No number is fabricated either way.
@@ -79,6 +99,9 @@ def safety_efficacy_profile(name: str) -> dict | None:
79
99
  "vehicle": name,
80
100
  "tiers": {ax: imm.get(ax) for ax in (*_IMMUNE_AXES, _GENOTOX_AXIS)} | {"efficacy": imm.get("efficacy")},
81
101
  "immune_score": _r(immune_score),
102
+ "adaptive_source": adaptive_source, # computed | computed_ex_vivo_muted | documented
103
+ "capsid_presentability_score": _r(cap_score), # computed intrinsic capsid CD8 presentability (or None)
104
+ "adaptive_provenance": (cap_oracle.note if cap_score is not None else None),
82
105
  "genotox_score": _r(genotox_score),
83
106
  "genotox_source": genotox_source, # "computed" (VISDBxCOSMIC oracle) | "documented" (ordinal tier)
84
107
  "genotox_provenance": (gtox_oracle.note if genotox_source == "computed" else None),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pen-stack
3
- Version: 5.2.0
3
+ Version: 5.3.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
@@ -91,7 +91,7 @@ every design against rule-grounded mechanism, reports calibrated confidence, cit
91
91
  [![codecov](https://codecov.io/gh/ahmedanees-m/pen-stack/branch/main/graph/badge.svg)](https://codecov.io/gh/ahmedanees-m/pen-stack)
92
92
  [![License: MIT](https://img.shields.io/badge/License-MIT-informational.svg)](LICENSE)
93
93
  [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/)
94
- [![Version](https://img.shields.io/badge/version-5.2.0-blue.svg)](CHANGELOG.md)
94
+ [![Version](https://img.shields.io/badge/version-5.3.0-blue.svg)](CHANGELOG.md)
95
95
  [![Tests](https://img.shields.io/badge/tests-240%20passing-success.svg)](tests/)
96
96
  [![Lint: ruff](https://img.shields.io/badge/lint-ruff-purple.svg)](https://github.com/astral-sh/ruff)
97
97
  [![Runtime: Docker](https://img.shields.io/badge/runtime-docker-2496ED.svg)](docker/)
@@ -135,6 +135,22 @@ Two questions gate every genome-writing project, and before PEN-STACK no resourc
135
135
  Everything is built on bulk-downloadable public data, runs on a single GPU, and is validated **blind** against
136
136
  a pre-registered, honest baseline before release.
137
137
 
138
+ ## What is new in v5.3 — Computed capsid epitope-load oracle (covers all vectors)
139
+
140
+ v5.2 computed genotoxicity only touches integrating vectors. v5.3 brings the **NetMHC-style calculation** to the
141
+ **adaptive (CD8 T-cell)** axis: the fraction of a viral vector's capsid/envelope presentable across a frequent
142
+ HLA-I panel (MHCflurry), so the computed immune signal now **covers all 8 vehicles** — 5 viral computed, 3
143
+ non-viral by mechanism. It is a population-level, *sequence-intrinsic* presentation signal; the realized
144
+ patient-HLA-specific T-cell response stays a known-unknown (and it is CD8/MHC-I only, not antibody).
145
+
146
+ | Workstream | What it adds | Result |
147
+ |---|---|---|
148
+ | **EPITOPE build** | `scripts/p53_build_epitope_oracle.py` → committed `configs/capsid_epitope_oracle.yaml` | per viral capsid: `epitope_fraction_strong` over 9-mers × 12 HLA-I alleles (MHCflurry %rank ≤ 0.5), from UniProt-verified sequences (AAV2 VP1, Ad5 hexon, VSV-G, HSV gD/gB); MHCflurry stays on the VM, only the summary ships |
149
+ | **EPITOPE oracle** | `planner/capsid_epitope_oracle.py` (`OracleResult`) | `capsid_immune_score = 1 − epitope_fraction_strong`; non-viral → 1.0 by mechanism; abstains when no sequence |
150
+ | **wired into the adaptive axis** | folded **only for in-vivo** vehicles | AAV2 least epitope-dense (0.72), Ad5 hexon among the most (0.82) — documented adaptive ordering reproduced from sequence; **ex-vivo** lentivirus's intrinsic VSV-G load is *reported but muted* (host barely sees it ex vivo) |
151
+
152
+ See `prereg/ws_epitope.yaml` and the `capsid_epitope` scope card.
153
+
138
154
  ## What is new in v5.2 — Computed genotoxicity oracle (data, not a documented tier)
139
155
 
140
156
  v5.1 scored genotoxicity as a documented `low/moderate/high` tier. v5.2 makes it **computed from data** for
@@ -12,6 +12,8 @@ benchmarks/genome_writing_bench/SUBMISSIONS.md
12
12
  benchmarks/genome_writing_bench/tasks.yaml
13
13
  configs/atlas_families.yaml
14
14
  configs/bridge_offtarget_profile.yaml
15
+ configs/capsid_epitope_oracle.yaml
16
+ configs/capsid_sequences.fasta
15
17
  configs/cargo_polish.yaml
16
18
  configs/cell_types.yaml
17
19
  configs/datasets.yaml
@@ -150,6 +152,7 @@ pen_stack/oracles/rna.py
150
152
  pen_stack/oracles/schema.py
151
153
  pen_stack/oracles/structure.py
152
154
  pen_stack/planner/__init__.py
155
+ pen_stack/planner/capsid_epitope_oracle.py
153
156
  pen_stack/planner/cargo.py
154
157
  pen_stack/planner/cargo_polish.py
155
158
  pen_stack/planner/delivery.py
@@ -243,6 +246,7 @@ prereg/SHA256_LOCK_ws_d.json
243
246
  prereg/SHA256_LOCK_ws_e.json
244
247
  prereg/SHA256_LOCK_ws_env.json
245
248
  prereg/SHA256_LOCK_ws_ep.json
249
+ prereg/SHA256_LOCK_ws_epitope.json
246
250
  prereg/SHA256_LOCK_ws_f.json
247
251
  prereg/SHA256_LOCK_ws_g.json
248
252
  prereg/SHA256_LOCK_ws_genotox.json
@@ -279,6 +283,7 @@ prereg/ws_d.yaml
279
283
  prereg/ws_e.yaml
280
284
  prereg/ws_env.yaml
281
285
  prereg/ws_ep.yaml
286
+ prereg/ws_epitope.yaml
282
287
  prereg/ws_f.yaml
283
288
  prereg/ws_g.yaml
284
289
  prereg/ws_genotox.yaml
@@ -304,5 +309,6 @@ scripts/p2_build_atlas.py
304
309
  scripts/p3_benchmark_report.py
305
310
  scripts/p4_genome_scan.py
306
311
  scripts/p52_build_genotox_oracle.py
312
+ scripts/p53_build_epitope_oracle.py
307
313
  scripts/ws_b_report.py
308
314
  scripts/ws_c_report.py
@@ -0,0 +1,8 @@
1
+ {
2
+ "cycle": "v5.3",
3
+ "workstream": "WS-EPITOPE",
4
+ "prepared": "2026-06-10",
5
+ "sha256": {
6
+ "prereg/ws_epitope.yaml": "d69f145f8cfe80ae2c0bccbde17dc85ccdff31f354b0db0a6a9a10910d6b31e3"
7
+ }
8
+ }
@@ -0,0 +1,47 @@
1
+ # PEN-STACK v5.3 - WS-EPITOPE (computed capsid CD8 T-cell epitope-load oracle). Directional.
2
+ cycle: "v5.3"
3
+ workstream: "WS-EPITOPE"
4
+ prepared: "2026-06-10"
5
+
6
+ motivation: >
7
+ User: "continue. Also, we need to cover ALL the vectors." v5.2 computed genotoxicity only meaningfully
8
+ touches integrating vectors (lentivirus). The IMMUNE axis is where the rest of the palette has computable
9
+ signal. This adds the NetMHC-style calculation (the user's reference) for the adaptive (CD8 / MHC-I) axis,
10
+ covering every vehicle.
11
+
12
+ deliverable: >
13
+ scripts/p53_build_epitope_oracle.py (VM, dedicated penstack:mhcflurry image) -> committed
14
+ configs/capsid_epitope_oracle.yaml; pen_stack/planner/capsid_epitope_oracle.py (OracleResult); wired into
15
+ delivery_immunology.safety_efficacy_profile adaptive axis; scope card `capsid_epitope`;
16
+ configs/capsid_sequences.fasta (UniProt-sourced, committed).
17
+
18
+ method: >
19
+ For each VIRAL vector's capsid/envelope antigen, slide overlapping 9-mers and predict MHCflurry 2.0 affinity
20
+ percentile rank PER allele across a frequent HLA-I panel (12 alleles, Sidney 2008 supertypes); a 9-mer is a
21
+ STRONG binder for an allele at %rank <= 0.5; epitope_fraction_strong = residues covered by >=1 strong-binder
22
+ 9-mer / length; capsid_immune_score = 1 - epitope_fraction_strong. Sequences (UniProt, verified): AAV2 VP1
23
+ P03135; Ad5 hexon P04133; VSV-G Indiana P03522 (lentivirus pseudotyping antigen); HSV-1 gD P57083 + gB P06437
24
+ (averaged). Population-level (panel-averaged), NOT patient-HLA-specific. MHCflurry [10.1016/j.cels.2020.06.010];
25
+ HLA-I supertypes [10.1186/1471-2172-9-1]. Committed sequences -> reproducible, no network at build. v4.0
26
+ OracleResult (output_kind="baseline").
27
+
28
+ INTRINSIC vs REALIZED: the computed score is INTRINSIC antigen presentability. It is folded into the adaptive
29
+ axis ONLY for IN-VIVO vehicles (host is exposed to the capsid). For EX-VIVO-only viral vectors (lentivirus,
30
+ whose VSV-G envelope is intrinsically epitope-dense but barely seen ex vivo) the score is REPORTED but NOT
31
+ folded (adaptive_source = computed_ex_vivo_muted); the documented tier is kept.
32
+
33
+ acceptance: >
34
+ (1) every VIRAL vector gets a computed capsid_immune_score from MHCflurry x HLA panel; non-viral vectors are
35
+ 1.0 by mechanism; ALL 8 vehicles covered (available). (2) the computed ordering is consistent with the
36
+ documented tiers (AAV2 capsid less epitope-dense than Ad5 hexon -> AAV less immunogenic than HDAd). (3) the
37
+ computed score folds into the adaptive axis for in-vivo vehicles and is muted (reported, not folded) for
38
+ ex-vivo lentivirus. (4) the oracle ABSTAINS for an unknown / sequence-less vehicle (never fabricates).
39
+ (5) provenance + accessions verified (UniProt) / curated (DOIs).
40
+
41
+ honesty_invariant: >
42
+ Population-level, sequence-intrinsic PRESENTATION signal (does the capsid contain HLA binders) - NOT the
43
+ realized in-vivo / PATIENT-HLA-specific T-cell response (a known-unknown), and CD8 / MHC-I ONLY (not antibody
44
+ / neutralizing-antibody / B-cell). The immune MAGNITUDE stays `in_vivo_immunogenicity`. No magnitude predicted.
45
+
46
+ gate: "all 8 vehicles covered (5 viral computed + 3 non-viral by mechanism); AAV<Ad epitope ordering; in-vivo folds / ex-vivo muted; abstains not fabricates; provenance verified; no-fabrication intact."
47
+ locked_files: [prereg/ws_epitope.yaml]
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pen-stack"
7
- version = "5.2.0"
7
+ version = "5.3.0"
8
8
  description = "Open infrastructure for genome writing: the Writable Genome atlas, the Writer Atlas, and the Write Planner."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"