pen-stack 6.9.1__tar.gz → 6.9.2__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 (493) hide show
  1. {pen_stack-6.9.1 → pen_stack-6.9.2}/CHANGELOG.md +40 -0
  2. {pen_stack-6.9.1 → pen_stack-6.9.2}/CITATION.cff +1 -1
  3. {pen_stack-6.9.1 → pen_stack-6.9.2}/PKG-INFO +13 -5
  4. {pen_stack-6.9.1 → pen_stack-6.9.2}/README.md +12 -4
  5. pen_stack-6.9.2/configs/mhc_epitope_oracle.yaml +296 -0
  6. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/immune_profiler.md +25 -16
  7. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/__init__.py +1 -1
  8. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/atlas/guide_design.py +37 -11
  9. pen_stack-6.9.2/pen_stack/planner/ada_risk.py +64 -0
  10. pen_stack-6.9.2/pen_stack/planner/capsid_epitope_oracle.py +136 -0
  11. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/planner/delivery_immunology.py +3 -2
  12. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/planner/immune_mhc2.py +20 -16
  13. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/planner/immune_profile.py +5 -2
  14. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack.egg-info/PKG-INFO +13 -5
  15. {pen_stack-6.9.1 → pen_stack-6.9.2}/pyproject.toml +1 -1
  16. pen_stack-6.9.1/configs/mhc_epitope_oracle.yaml +0 -239
  17. pen_stack-6.9.1/pen_stack/planner/ada_risk.py +0 -87
  18. pen_stack-6.9.1/pen_stack/planner/capsid_epitope_oracle.py +0 -97
  19. {pen_stack-6.9.1 → pen_stack-6.9.2}/LICENSE +0 -0
  20. {pen_stack-6.9.1 → pen_stack-6.9.2}/MANIFEST.in +0 -0
  21. {pen_stack-6.9.1 → pen_stack-6.9.2}/bench/run.py +0 -0
  22. {pen_stack-6.9.1 → pen_stack-6.9.2}/benchmarks/genome_writing_bench/LEADERBOARD.md +0 -0
  23. {pen_stack-6.9.1 → pen_stack-6.9.2}/benchmarks/genome_writing_bench/README.md +0 -0
  24. {pen_stack-6.9.1 → pen_stack-6.9.2}/benchmarks/genome_writing_bench/SHA256SUMS +0 -0
  25. {pen_stack-6.9.1 → pen_stack-6.9.2}/benchmarks/genome_writing_bench/SUBMISSIONS.md +0 -0
  26. {pen_stack-6.9.1 → pen_stack-6.9.2}/benchmarks/genome_writing_bench/tasks.yaml +0 -0
  27. {pen_stack-6.9.1 → pen_stack-6.9.2}/benchmarks/genome_writing_challenge/README.md +0 -0
  28. {pen_stack-6.9.1 → pen_stack-6.9.2}/benchmarks/genome_writing_challenge/SUBMISSIONS.md +0 -0
  29. {pen_stack-6.9.1 → pen_stack-6.9.2}/benchmarks/position_effect/README.md +0 -0
  30. {pen_stack-6.9.1 → pen_stack-6.9.2}/benchmarks/position_effect/SHA256SUMS +0 -0
  31. {pen_stack-6.9.1 → pen_stack-6.9.2}/benchmarks/writer_efficiency/README.md +0 -0
  32. {pen_stack-6.9.1 → pen_stack-6.9.2}/benchmarks/writer_efficiency/SHA256SUMS +0 -0
  33. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/antipeg.yaml +0 -0
  34. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/atlas_families.yaml +0 -0
  35. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/bridge_offtarget_profile.yaml +0 -0
  36. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/calibration/preexisting_nab_independent.yaml +0 -0
  37. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/capsid_epitope_oracle.yaml +0 -0
  38. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/capsid_sequences.fasta +0 -0
  39. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/cargo_polish.yaml +0 -0
  40. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/cell_types.yaml +0 -0
  41. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/datasets.yaml +0 -0
  42. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/delivery_constraints.yaml +0 -0
  43. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/delivery_rules.yaml +0 -0
  44. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/delivery_vehicles.yaml +0 -0
  45. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/expression/modifiers.yaml +0 -0
  46. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/expression/promoters.yaml +0 -0
  47. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/gates_v3.yaml +0 -0
  48. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/genotoxicity_oracle.yaml +0 -0
  49. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/gsh_validated_heldout.yaml +0 -0
  50. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/intent_weights.yaml +0 -0
  51. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/known_unknowns.yaml +0 -0
  52. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/llm.yaml +0 -0
  53. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/metric_guide.yaml +0 -0
  54. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/monitor_queries.yaml +0 -0
  55. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/oracles/execution.yaml +0 -0
  56. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/oracles/scope_cards.yaml +0 -0
  57. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/rules/delivery.yaml +0 -0
  58. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/rules/fold.yaml +0 -0
  59. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/rules/multiplex.yaml +0 -0
  60. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/rules/payload.yaml +0 -0
  61. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/rules/reachability.yaml +0 -0
  62. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/safety/hazard_registry.yaml +0 -0
  63. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/safety/policy.yaml +0 -0
  64. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/safety/probes.yaml +0 -0
  65. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/score_axes.yaml +0 -0
  66. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/seroprevalence.yaml +0 -0
  67. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/target_sites.yaml +0 -0
  68. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/universe_crosswalk.yaml +0 -0
  69. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/write_types.yaml +0 -0
  70. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/writer_sequences.fasta +0 -0
  71. {pen_stack-6.9.1 → pen_stack-6.9.2}/configs/wtkb_curated.yaml +0 -0
  72. {pen_stack-6.9.1 → pen_stack-6.9.2}/data/curated/bridge_offtarget_energetics.json +0 -0
  73. {pen_stack-6.9.1 → pen_stack-6.9.2}/data/curated/bridge_offtarget_profile_measured.parquet +0 -0
  74. {pen_stack-6.9.1 → pen_stack-6.9.2}/data/curated/gene_coords.parquet +0 -0
  75. {pen_stack-6.9.1 → pen_stack-6.9.2}/data/curated/unified_editor_universe.parquet +0 -0
  76. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/BACKLOG.md +0 -0
  77. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/DEPLOY.md +0 -0
  78. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/INFRA.md +0 -0
  79. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/MCP.md +0 -0
  80. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/RELEASING.md +0 -0
  81. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/REPRO.md +0 -0
  82. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/STABILITY.md +0 -0
  83. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/agent.md +0 -0
  84. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/alphagenome_feasibility.md +0 -0
  85. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/autonomy.md +0 -0
  86. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/benchmark_circularity.md +0 -0
  87. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/biosecurity.md +0 -0
  88. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/build_interface.md +0 -0
  89. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/cards/atlas.md +0 -0
  90. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/cards/durability.md +0 -0
  91. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/cards/position_effect_data.md +0 -0
  92. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/cards/safety.md +0 -0
  93. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/cards/writer_efficiency_data.md +0 -0
  94. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/challenge.md +0 -0
  95. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/closed_loop.md +0 -0
  96. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/co_scientist.md +0 -0
  97. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/co_scientist_loop.md +0 -0
  98. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/delivery.md +0 -0
  99. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/delivery_immunology.md +0 -0
  100. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/digital_twin.md +0 -0
  101. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/dissemination.md +0 -0
  102. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/environment.md +0 -0
  103. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/experiment_design.md +0 -0
  104. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/generative_design.md +0 -0
  105. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/index.md +0 -0
  106. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/integrations.md +0 -0
  107. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/live_oracles.md +0 -0
  108. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/mechanistic_constraints.md +0 -0
  109. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/oracles.md +0 -0
  110. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/position_effect.md +0 -0
  111. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/positioning.md +0 -0
  112. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/private_data_formats.md +0 -0
  113. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/quickstart.md +0 -0
  114. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/responsible_use.md +0 -0
  115. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/rules.md +0 -0
  116. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/scope.md +0 -0
  117. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/scorecard.md +0 -0
  118. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/tpe_bench.md +0 -0
  119. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/tutorials/compare-families.md +0 -0
  120. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/tutorials/score-deliverability.md +0 -0
  121. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/tutorials/where-can-i-write.md +0 -0
  122. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/tutorials/which-writer-reaches-locus.md +0 -0
  123. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/uncertainty.md +0 -0
  124. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/verify.md +0 -0
  125. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/world_model.md +0 -0
  126. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/writer_efficiency.md +0 -0
  127. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/writer_verification.md +0 -0
  128. {pen_stack-6.9.1 → pen_stack-6.9.2}/docs/wtkb.md +0 -0
  129. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/_resources.py +0 -0
  130. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/active/__init__.py +0 -0
  131. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/active/acquire.py +0 -0
  132. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/active/design.py +0 -0
  133. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/active/validate.py +0 -0
  134. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/adapt/__init__.py +0 -0
  135. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/adapt/finetune.py +0 -0
  136. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/adapt/ingest.py +0 -0
  137. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/adapt/pipeline.py +0 -0
  138. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/adapt/recalibrate.py +0 -0
  139. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/adapt/report.py +0 -0
  140. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/agent/__init__.py +0 -0
  141. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/agent/cite.py +0 -0
  142. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/agent/co_scientist.py +0 -0
  143. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/agent/epistemic.py +0 -0
  144. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/agent/guardrails.py +0 -0
  145. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/agent/mcp_server.py +0 -0
  146. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/agent/orchestrator.py +0 -0
  147. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/agent/orchestrator_live.py +0 -0
  148. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/agent/pen_agent.py +0 -0
  149. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/agent/scope.py +0 -0
  150. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/agent/tools.py +0 -0
  151. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/api/__init__.py +0 -0
  152. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/api/manifest.py +0 -0
  153. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/atlas/__init__.py +0 -0
  154. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/atlas/build_wtkb.py +0 -0
  155. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/atlas/crosslink.py +0 -0
  156. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/atlas/expand.py +0 -0
  157. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/atlas/schema.py +0 -0
  158. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/atlas/scorecard.py +0 -0
  159. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/atlas/universe.py +0 -0
  160. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/atlas/variant_propose.py +0 -0
  161. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/atlas/writer_efficiency.py +0 -0
  162. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/atlas/writer_predict.py +0 -0
  163. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/atlas/writer_recommend.py +0 -0
  164. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/atlas/writer_verify.py +0 -0
  165. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/bridge/__init__.py +0 -0
  166. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/bridge/activity.py +0 -0
  167. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/bridge/cli.py +0 -0
  168. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/bridge/fold_qc.py +0 -0
  169. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/bridge/guide_qc.py +0 -0
  170. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/bridge/ingest.py +0 -0
  171. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/bridge/offtarget.py +0 -0
  172. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/bridge/offtarget_energetics.py +0 -0
  173. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/bridge/ortholog_screen.py +0 -0
  174. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/bridge/pipeline.py +0 -0
  175. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/build/__init__.py +0 -0
  176. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/build/ingest.py +0 -0
  177. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/build/protocol.py +0 -0
  178. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/build/simlab.py +0 -0
  179. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/cli.py +0 -0
  180. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/data/__init__.py +0 -0
  181. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/data/encode.py +0 -0
  182. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/data/genome.py +0 -0
  183. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/data/ingest_chromatin.py +0 -0
  184. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/data/ingest_integration.py +0 -0
  185. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/data/ingest_safety_annot.py +0 -0
  186. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/data/ingest_trip.py +0 -0
  187. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/design/__init__.py +0 -0
  188. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/design/generate.py +0 -0
  189. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/design/pareto.py +0 -0
  190. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/design/space.py +0 -0
  191. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/design/writer_variants.py +0 -0
  192. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/env/__init__.py +0 -0
  193. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/env/genome_writing_env.py +0 -0
  194. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/env/policies.py +0 -0
  195. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/graph/__init__.py +0 -0
  196. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/graph/build.py +0 -0
  197. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/graph/cell_types.py +0 -0
  198. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/graph/ingest.py +0 -0
  199. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/graph/query.py +0 -0
  200. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/graph/schema.py +0 -0
  201. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/loop/__init__.py +0 -0
  202. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/loop/continual.py +0 -0
  203. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/loop/cycle.py +0 -0
  204. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/loop/drift.py +0 -0
  205. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/mech/__init__.py +0 -0
  206. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/mech/classify_atlas.py +0 -0
  207. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/mech/whitelist.py +0 -0
  208. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/monitor/__init__.py +0 -0
  209. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/monitor/europepmc.py +0 -0
  210. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/monitor/run.py +0 -0
  211. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/monitor/triage.py +0 -0
  212. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/oracles/__init__.py +0 -0
  213. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/oracles/cache.py +0 -0
  214. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/oracles/energetics.py +0 -0
  215. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/oracles/genome.py +0 -0
  216. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/oracles/protein_design.py +0 -0
  217. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/oracles/rna.py +0 -0
  218. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/oracles/schema.py +0 -0
  219. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/oracles/status.py +0 -0
  220. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/oracles/structure.py +0 -0
  221. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/oracles/vcell.py +0 -0
  222. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/planner/__init__.py +0 -0
  223. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/planner/antipeg_oracle.py +0 -0
  224. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/planner/cargo.py +0 -0
  225. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/planner/cargo_polish.py +0 -0
  226. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/planner/delivery.py +0 -0
  227. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/planner/delivery_constraints.py +0 -0
  228. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/planner/delivery_vehicles.py +0 -0
  229. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/planner/genotoxicity_oracle.py +0 -0
  230. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/planner/innate_sensing.py +0 -0
  231. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/planner/multiplex.py +0 -0
  232. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/planner/optimize.py +0 -0
  233. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/planner/pipeline.py +0 -0
  234. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/planner/report.py +0 -0
  235. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/planner/router.py +0 -0
  236. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/planner/seroprevalence_oracle.py +0 -0
  237. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/planner/target_site.py +0 -0
  238. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/rag/__init__.py +0 -0
  239. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/rag/index.py +0 -0
  240. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/rag/llm.py +0 -0
  241. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/rag/qa.py +0 -0
  242. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/rules/__init__.py +0 -0
  243. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/rules/evaluators.py +0 -0
  244. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/rules/loader.py +0 -0
  245. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/rules/schema.py +0 -0
  246. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/rules/solver.py +0 -0
  247. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/safety/__init__.py +0 -0
  248. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/safety/audit.py +0 -0
  249. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/safety/gate.py +0 -0
  250. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/safety/policy.py +0 -0
  251. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/safety/redteam.py +0 -0
  252. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/safety/registry.py +0 -0
  253. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/safety/screen.py +0 -0
  254. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/score/__init__.py +0 -0
  255. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/score/recalibrate.py +0 -0
  256. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/score/therapeutic.py +0 -0
  257. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/server/__init__.py +0 -0
  258. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/server/api.py +0 -0
  259. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/twin/__init__.py +0 -0
  260. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/twin/calibrate.py +0 -0
  261. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/twin/data/__init__.py +0 -0
  262. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/twin/data/position_effect.py +0 -0
  263. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/twin/mechanistic.py +0 -0
  264. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/twin/outcome.py +0 -0
  265. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/twin/position_effect.py +0 -0
  266. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/ui/__init__.py +0 -0
  267. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/ui/app.py +0 -0
  268. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/__init__.py +0 -0
  269. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/adapt_demo.py +0 -0
  270. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/agent_eval.py +0 -0
  271. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/bench_adversarial_tasks.py +0 -0
  272. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/bench_coscientist_tasks.py +0 -0
  273. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/bench_graph_tasks.py +0 -0
  274. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/bench_rule_tasks.py +0 -0
  275. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/bench_trust_tasks.py +0 -0
  276. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/bench_writetype_tasks.py +0 -0
  277. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/blind_gsh_discovery.py +0 -0
  278. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/cargo_directionality.py +0 -0
  279. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/closed_loop.py +0 -0
  280. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/durability_baselines.py +0 -0
  281. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/experiment_design.py +0 -0
  282. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/expr_controls.py +0 -0
  283. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/forward_hypotheses.py +0 -0
  284. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/generative_design.py +0 -0
  285. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/guide_qc_demo.py +0 -0
  286. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/heldout_celltype_expr.py +0 -0
  287. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/immune_calibration.py +0 -0
  288. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/intent_specification.py +0 -0
  289. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/known_biology_expr.py +0 -0
  290. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/offtarget_energetics_eval.py +0 -0
  291. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/out_of_scope_refusal.py +0 -0
  292. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/outcome_calibration.py +0 -0
  293. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/outcome_prediction.py +0 -0
  294. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/paper3_benchmark.py +0 -0
  295. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/paper4_real_validation.py +0 -0
  296. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/paper4_validation.py +0 -0
  297. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/protocol_safety.py +0 -0
  298. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/safety_screening.py +0 -0
  299. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/selective_prediction.py +0 -0
  300. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/seq_vs_measured.py +0 -0
  301. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/target_site_controls.py +0 -0
  302. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/uncertainty_eval.py +0 -0
  303. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/ungrounded_baseline.py +0 -0
  304. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/within_locus_ranking.py +0 -0
  305. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/validate/writer_recovery.py +0 -0
  306. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/verify/__init__.py +0 -0
  307. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/verify/schema.py +0 -0
  308. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/verify/service.py +0 -0
  309. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/web/__init__.py +0 -0
  310. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/web/guide.py +0 -0
  311. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/web/llm.py +0 -0
  312. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/web/router.py +0 -0
  313. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/web/server.py +0 -0
  314. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/web/tools.py +0 -0
  315. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/wgenome/__init__.py +0 -0
  316. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/wgenome/chromatin_seq.py +0 -0
  317. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/wgenome/durability.py +0 -0
  318. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/wgenome/export_tracks.py +0 -0
  319. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/wgenome/features.py +0 -0
  320. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/wgenome/gsh_baseline.py +0 -0
  321. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/wgenome/mesh_features.py +0 -0
  322. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/wgenome/ood.py +0 -0
  323. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/wgenome/providers.py +0 -0
  324. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/wgenome/safety.py +0 -0
  325. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/wgenome/structure3d.py +0 -0
  326. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/wgenome/uncertainty.py +0 -0
  327. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack/wgenome/writability.py +0 -0
  328. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack.egg-info/SOURCES.txt +0 -0
  329. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack.egg-info/dependency_links.txt +0 -0
  330. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack.egg-info/entry_points.txt +0 -0
  331. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack.egg-info/requires.txt +0 -0
  332. {pen_stack-6.9.1 → pen_stack-6.9.2}/pen_stack.egg-info/top_level.txt +0 -0
  333. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_phase0.json +0 -0
  334. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_phase1_5.json +0 -0
  335. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_phase2.json +0 -0
  336. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_phase3.json +0 -0
  337. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_a.json +0 -0
  338. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_acq.json +0 -0
  339. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_aldesign.json +0 -0
  340. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_alvalidate.json +0 -0
  341. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_atlas.json +0 -0
  342. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_b.json +0 -0
  343. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_ba.json +0 -0
  344. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_ba_v33.json +0 -0
  345. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_ba_v45.json +0 -0
  346. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_bench.json +0 -0
  347. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_c.json +0 -0
  348. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_cal.json +0 -0
  349. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_calib.json +0 -0
  350. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_challenge.json +0 -0
  351. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_chat.json +0 -0
  352. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_cite.json +0 -0
  353. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_continual.json +0 -0
  354. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_cosci2.json +0 -0
  355. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_crit.json +0 -0
  356. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_ct.json +0 -0
  357. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_d.json +0 -0
  358. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_drift.json +0 -0
  359. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_e.json +0 -0
  360. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_env.json +0 -0
  361. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_ep.json +0 -0
  362. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_epitope.json +0 -0
  363. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_expr2.json +0 -0
  364. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_f.json +0 -0
  365. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_frontend.json +0 -0
  366. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_g.json +0 -0
  367. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_gen.json +0 -0
  368. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_genotox.json +0 -0
  369. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_graph.json +0 -0
  370. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_h.json +0 -0
  371. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_hybrid.json +0 -0
  372. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_immune.json +0 -0
  373. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_immune2.json +0 -0
  374. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_ingest.json +0 -0
  375. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_innate.json +0 -0
  376. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_loop.json +0 -0
  377. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_manifest.json +0 -0
  378. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_mc.json +0 -0
  379. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_mcp.json +0 -0
  380. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_mech.json +0 -0
  381. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_mon.json +0 -0
  382. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_o.json +0 -0
  383. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_openapi.json +0 -0
  384. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_orch.json +0 -0
  385. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_outcome.json +0 -0
  386. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_pareto.json +0 -0
  387. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_peg.json +0 -0
  388. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_plan.json +0 -0
  389. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_policy.json +0 -0
  390. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_profile.json +0 -0
  391. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_proto.json +0 -0
  392. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_r.json +0 -0
  393. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_redteam.json +0 -0
  394. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_route.json +0 -0
  395. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_screen.json +0 -0
  396. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_seroprev.json +0 -0
  397. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_simlab.json +0 -0
  398. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_twincal.json +0 -0
  399. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_uq.json +0 -0
  400. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_v.json +0 -0
  401. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_vcell.json +0 -0
  402. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_writer.json +0 -0
  403. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_wv.json +0 -0
  404. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/paper1.yaml +0 -0
  405. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/paper2.yaml +0 -0
  406. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/paper3.yaml +0 -0
  407. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/paper4.yaml +0 -0
  408. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/phase0.yaml +0 -0
  409. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_a.yaml +0 -0
  410. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_acq.yaml +0 -0
  411. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_aldesign.yaml +0 -0
  412. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_alvalidate.yaml +0 -0
  413. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_atlas.yaml +0 -0
  414. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_b.yaml +0 -0
  415. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_ba.yaml +0 -0
  416. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_ba_v33.yaml +0 -0
  417. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_ba_v45.yaml +0 -0
  418. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_bench.yaml +0 -0
  419. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_c.yaml +0 -0
  420. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_cal.yaml +0 -0
  421. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_calib.yaml +0 -0
  422. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_challenge.yaml +0 -0
  423. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_chat.yaml +0 -0
  424. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_cite.yaml +0 -0
  425. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_continual.yaml +0 -0
  426. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_cosci2.yaml +0 -0
  427. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_crit.yaml +0 -0
  428. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_ct.yaml +0 -0
  429. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_d.yaml +0 -0
  430. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_drift.yaml +0 -0
  431. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_e.yaml +0 -0
  432. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_env.yaml +0 -0
  433. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_ep.yaml +0 -0
  434. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_epitope.yaml +0 -0
  435. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_expr2.yaml +0 -0
  436. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_f.yaml +0 -0
  437. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_frontend.yaml +0 -0
  438. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_g.yaml +0 -0
  439. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_gen.yaml +0 -0
  440. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_genotox.yaml +0 -0
  441. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_graph.yaml +0 -0
  442. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_h.yaml +0 -0
  443. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_hybrid.yaml +0 -0
  444. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_immune.yaml +0 -0
  445. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_immune2.yaml +0 -0
  446. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_ingest.yaml +0 -0
  447. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_innate.yaml +0 -0
  448. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_loop.yaml +0 -0
  449. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_manifest.yaml +0 -0
  450. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_mc.yaml +0 -0
  451. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_mcp.yaml +0 -0
  452. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_mech.yaml +0 -0
  453. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_mon.yaml +0 -0
  454. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_o.yaml +0 -0
  455. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_openapi.yaml +0 -0
  456. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_orch.yaml +0 -0
  457. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_outcome.yaml +0 -0
  458. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_pareto.yaml +0 -0
  459. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_peg.yaml +0 -0
  460. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_plan.yaml +0 -0
  461. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_policy.yaml +0 -0
  462. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_profile.yaml +0 -0
  463. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_proto.yaml +0 -0
  464. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_r.yaml +0 -0
  465. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_redteam.yaml +0 -0
  466. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_route.yaml +0 -0
  467. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_screen.yaml +0 -0
  468. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_seroprev.yaml +0 -0
  469. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_simlab.yaml +0 -0
  470. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_twincal.yaml +0 -0
  471. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_uq.yaml +0 -0
  472. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_v.yaml +0 -0
  473. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_vcell.yaml +0 -0
  474. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_writer.yaml +0 -0
  475. {pen_stack-6.9.1 → pen_stack-6.9.2}/prereg/ws_wv.yaml +0 -0
  476. {pen_stack-6.9.1 → pen_stack-6.9.2}/scripts/calibrate_immune_axes.py +0 -0
  477. {pen_stack-6.9.1 → pen_stack-6.9.2}/scripts/fetch_licensed_sources.py +0 -0
  478. {pen_stack-6.9.1 → pen_stack-6.9.2}/scripts/p1_build_atlas.py +0 -0
  479. {pen_stack-6.9.1 → pen_stack-6.9.2}/scripts/p1_build_durability.py +0 -0
  480. {pen_stack-6.9.1 → pen_stack-6.9.2}/scripts/p1_build_position_effect.py +0 -0
  481. {pen_stack-6.9.1 → pen_stack-6.9.2}/scripts/p1_build_writer_eff.py +0 -0
  482. {pen_stack-6.9.1 → pen_stack-6.9.2}/scripts/p1_export_tracks.py +0 -0
  483. {pen_stack-6.9.1 → pen_stack-6.9.2}/scripts/p1_safety_concordance.py +0 -0
  484. {pen_stack-6.9.1 → pen_stack-6.9.2}/scripts/p1_train_safety.py +0 -0
  485. {pen_stack-6.9.1 → pen_stack-6.9.2}/scripts/p1_validation_report.py +0 -0
  486. {pen_stack-6.9.1 → pen_stack-6.9.2}/scripts/p2_build_atlas.py +0 -0
  487. {pen_stack-6.9.1 → pen_stack-6.9.2}/scripts/p3_benchmark_report.py +0 -0
  488. {pen_stack-6.9.1 → pen_stack-6.9.2}/scripts/p4_genome_scan.py +0 -0
  489. {pen_stack-6.9.1 → pen_stack-6.9.2}/scripts/p52_build_genotox_oracle.py +0 -0
  490. {pen_stack-6.9.1 → pen_stack-6.9.2}/scripts/p53_build_epitope_oracle.py +0 -0
  491. {pen_stack-6.9.1 → pen_stack-6.9.2}/scripts/ws_b_report.py +0 -0
  492. {pen_stack-6.9.1 → pen_stack-6.9.2}/scripts/ws_c_report.py +0 -0
  493. {pen_stack-6.9.1 → pen_stack-6.9.2}/setup.cfg +0 -0
@@ -3,6 +3,46 @@
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
+ ## [6.9.2] - 2026-06-19 - WS-IMMUNE2 real-tool rigor pass (no proxies / no heuristics across the immune + writer axes)
7
+
8
+ **PATCH — a top-to-bottom audit replacing every remaining proxy/heuristic in the immune & writer-design stack with
9
+ the real on-VM tool (gold-standard, licensed) or an honest abstention. No silent fallbacks.** Triggered by the
10
+ directive *"use the real on-VM tool. No proxy or heuristics … check previous versions too … re-confirm the MHC-I
11
+ capsid axis against NetMHCpan-4.1."* All licensed binaries stay on the VM — only derived numbers are cached.
12
+
13
+ ### Changed
14
+ - **MHC-I capsid axis re-grounded on NetMHCpan-4.1** (`pen_stack/planner/capsid_epitope_oracle.py`). The PRIMARY
15
+ capsid CD8 predictor is now the gold-standard licensed **NetMHCpan-4.1** (%Rank_EL≤0.5, residue coverage, 12-allele
16
+ panel; `configs/mhc_epitope_oracle.yaml` `mhc1`); the v5.3 **MHCflurry** value is kept as an explicit, reported
17
+ **cross-check** (never silently substituted). Both agree AAV is the least CD8-immunogenic capsid
18
+ (AAV `capsid_immune_score` 0.4585 NetMHCpan / 0.2803 MHCflurry — the predictor disagreement is surfaced, not hidden).
19
+ - **ADA-risk re-grounded** (`pen_stack/planner/ada_risk.py`). `ada_risk = real NetMHCIIpan-4.0 density × foreignness`,
20
+ where **foreignness is the protein ORIGIN** (authoritative central-tolerance signal). Unknown origin / uncached
21
+ density now **ABSTAINS** (no k-mer guess, no heuristic) — replacing the v6.9.0 albumin-only self-tolerance
22
+ heuristic. The **real human-proteome 9-mer self-match** (computed on the VM over the full UniProt reference
23
+ proteome, 20 431 proteins / 10.4 M 9-mers) is reported as a cross-check: human albumin **1.0** (self), the
24
+ foreign writers (SpCas9/ISCro4/Bxb1) and capsids **0.0** (non-self) — clean self/non-self separation.
25
+ - **MHC-II axis no longer falls back to a production proxy** (`pen_stack/planner/immune_mhc2.py`). `mhc2_epitope_load`
26
+ uses the real NetMHCIIpan-4.0 cache by antigen name and otherwise **abstains**; the documented promiscuous-binder
27
+ estimate is retained as `mhc2_proxy_estimate` for **offline triage only** (explicitly labelled, not the production axis).
28
+ - **Real Bxb1 attB written** (`pen_stack/atlas/guide_design.py`). The PASTE/PASSIGE pegRNA 3′ extension now writes the
29
+ **real documented Bxb1 minimal attB** verbatim (FlyBase FBto0000359; Ghosh, Kim & Hatfull, Mol Cell 2003;
30
+ 8-bp common core GCGGTCTC around the central GT crossover) instead of the schematic poly-G/poly-C arms. Integrases
31
+ without a bundled documented site expose only the central core (never a fabricated full sequence).
32
+ - `pen_stack/planner/immune_profile.py` — the writer-as-antigen card surfaces `foreignness`, the real
33
+ `self_match_human_proteome` cross-check, and the MHC-II/ADA backends (was the removed `self_tolerance` field).
34
+
35
+ ### Honest deviations from the v6.9 pre-registration (`prereg/ws_immune2.yaml`)
36
+ - The pre-registered "1 − self_match_fraction from a human-proteome k-mer filter" foreignness *fallback* is
37
+ **dropped**: foreignness is the authoritative origin, and an unknown origin abstains rather than imputing from a
38
+ k-mer match (the real self-match is reported only as a cross-check). This is a strictly more honest rule.
39
+
40
+ ### Data / tests
41
+ - `configs/mhc_epitope_oracle.yaml` — corrected `self_match` (the v6.9.x cache had a FASTA-keying bug that collapsed
42
+ the 20 431-protein proteome to 1 protein, zeroing every self-match incl. albumin); recomputed correctly on the VM.
43
+ - `tests/unit/{test_ws_immune2,test_ws_epitope,test_ws_writer,test_ws_rel}.py` updated for the abstain semantics,
44
+ the NetMHCpan-4.1 primary capsid value + MHCflurry cross-check, the real attB, and the 6.9.2 version pins.
45
+
6
46
  ## [6.9.1] - 2026-06-20 - Real NetMHCIIpan-4.0 / NetMHCpan-4.1 MHC epitope load (replaces the v6.9.0 proxy)
7
47
 
8
48
  **PATCH — rigour upgrade.** v6.9.0's MHC-II axis was a documented *heuristic proxy* (P1-anchor density). The
@@ -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: 6.9.1
4
+ version: 6.9.2
5
5
  date-released: 2026-06-20
6
6
  authors:
7
7
  - family-names: "Mahaboob Ali"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pen-stack
3
- Version: 6.9.1
3
+ Version: 6.9.2
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
@@ -90,7 +90,7 @@ every design against rule-grounded mechanism, reports calibrated confidence, cit
90
90
  [![codecov](https://codecov.io/gh/ahmedanees-m/pen-stack/branch/main/graph/badge.svg)](https://codecov.io/gh/ahmedanees-m/pen-stack)
91
91
  [![License: MIT](https://img.shields.io/badge/License-MIT-informational.svg)](LICENSE)
92
92
  [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/)
93
- [![Version](https://img.shields.io/badge/version-6.9.1-blue.svg)](CHANGELOG.md)
93
+ [![Version](https://img.shields.io/badge/version-6.9.2-blue.svg)](CHANGELOG.md)
94
94
  [![Status](https://img.shields.io/badge/status-1.0%20First%20Stable-success.svg)](docs/STABILITY.md)
95
95
  [![Tests](https://img.shields.io/badge/tests-378%20passing-success.svg)](tests/)
96
96
  [![Lint: ruff](https://img.shields.io/badge/lint-ruff-purple.svg)](https://github.com/astral-sh/ruff)
@@ -161,16 +161,24 @@ are bacterial/phage) — yet Stage G scored only the capsid. v6.9 closes that ga
161
161
  never distributed), with a documented promiscuous-binder proxy as the offline/CI fallback. Population-level proxy
162
162
  (🟡), never a patient-HLA magnitude. *(v6.9.0 used the heuristic proxy; the real tool is more discriminating —
163
163
  human-self albumin 0.066 vs foreign writers 0.11–0.15.)*
164
- - **An ADA-risk axis** (`planner/ada_risk.py`) — **ADA-risk = MHC-II epitope density × foreignness**, with a
165
- **self-tolerance filter** (JanusMatrix-style: self epitopes are tolerated; foreign drive ADA). It **recovers
164
+ - **An ADA-risk axis** (`planner/ada_risk.py`) — **ADA-risk = MHC-II epitope density × foreignness**, where
165
+ **foreignness is the protein ORIGIN** (the authoritative central-tolerance signal). It **recovers
166
166
  immunogenic-vs-tolerated**: the foreign writers (real UniProt SpCas9 / ISCro4 / Bxb1) score **above** the human
167
- self control (albumin), even without the origin label (the k-mer self-match tolerates the human protein).
167
+ self control (albumin). The **real full-human-proteome 9-mer self-match** (computed on the VM, 20 431 proteins) is
168
+ reported as a cross-check (albumin 1.0 self, foreign writers 0.0).
168
169
  - **The writer as a distinct antigen** — the profile now carries a `writer_as_antigen` card and a
169
170
  `writer_dominant_risk` flag: for **non-viral delivery of a bacterial writer there is no capsid antigen, so the
170
171
  WRITER is the dominant immunogen** — the insight the capsid-only profile missed.
171
172
  - **Immuno-Bench** (`benchmarks/immuno/`) — the immunogenic-vs-tolerated recovery track + an honest `calibrate_axis`
172
173
  ADA pass (it stays 🟡 at public-data power — no manufactured ✅, the standing wet-lab bottleneck).
173
174
 
175
+ **v6.9.2 — real-tool rigor pass (no proxies / no heuristics).** A top-to-bottom audit: the **MHC-I capsid axis is
176
+ re-grounded on the gold-standard NetMHCpan-4.1** (MHCflurry kept as a reported cross-check); **ADA foreignness is the
177
+ authoritative origin** and **abstains** when unknown (no k-mer guess); the MHC-II axis **abstains** rather than
178
+ falling back to a production proxy (the promiscuous-binder estimate is offline-triage only); and the PASTE pegRNA
179
+ writes the **real documented Bxb1 minimal attB** (FlyBase / Ghosh 2003) instead of a schematic. Real tool or honest
180
+ abstention — never a silent fallback.
181
+
174
182
  Real UniProt sequences only (no fabricated sequence); the axes are reported as a vector with `collapsed_score: None`;
175
183
  the realized CD4 response / ADA titer stay known-unknowns. See [docs/immune_profiler.md](docs/immune_profiler.md).
176
184
 
@@ -15,7 +15,7 @@ every design against rule-grounded mechanism, reports calibrated confidence, cit
15
15
  [![codecov](https://codecov.io/gh/ahmedanees-m/pen-stack/branch/main/graph/badge.svg)](https://codecov.io/gh/ahmedanees-m/pen-stack)
16
16
  [![License: MIT](https://img.shields.io/badge/License-MIT-informational.svg)](LICENSE)
17
17
  [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/)
18
- [![Version](https://img.shields.io/badge/version-6.9.1-blue.svg)](CHANGELOG.md)
18
+ [![Version](https://img.shields.io/badge/version-6.9.2-blue.svg)](CHANGELOG.md)
19
19
  [![Status](https://img.shields.io/badge/status-1.0%20First%20Stable-success.svg)](docs/STABILITY.md)
20
20
  [![Tests](https://img.shields.io/badge/tests-378%20passing-success.svg)](tests/)
21
21
  [![Lint: ruff](https://img.shields.io/badge/lint-ruff-purple.svg)](https://github.com/astral-sh/ruff)
@@ -86,16 +86,24 @@ are bacterial/phage) — yet Stage G scored only the capsid. v6.9 closes that ga
86
86
  never distributed), with a documented promiscuous-binder proxy as the offline/CI fallback. Population-level proxy
87
87
  (🟡), never a patient-HLA magnitude. *(v6.9.0 used the heuristic proxy; the real tool is more discriminating —
88
88
  human-self albumin 0.066 vs foreign writers 0.11–0.15.)*
89
- - **An ADA-risk axis** (`planner/ada_risk.py`) — **ADA-risk = MHC-II epitope density × foreignness**, with a
90
- **self-tolerance filter** (JanusMatrix-style: self epitopes are tolerated; foreign drive ADA). It **recovers
89
+ - **An ADA-risk axis** (`planner/ada_risk.py`) — **ADA-risk = MHC-II epitope density × foreignness**, where
90
+ **foreignness is the protein ORIGIN** (the authoritative central-tolerance signal). It **recovers
91
91
  immunogenic-vs-tolerated**: the foreign writers (real UniProt SpCas9 / ISCro4 / Bxb1) score **above** the human
92
- self control (albumin), even without the origin label (the k-mer self-match tolerates the human protein).
92
+ self control (albumin). The **real full-human-proteome 9-mer self-match** (computed on the VM, 20 431 proteins) is
93
+ reported as a cross-check (albumin 1.0 self, foreign writers 0.0).
93
94
  - **The writer as a distinct antigen** — the profile now carries a `writer_as_antigen` card and a
94
95
  `writer_dominant_risk` flag: for **non-viral delivery of a bacterial writer there is no capsid antigen, so the
95
96
  WRITER is the dominant immunogen** — the insight the capsid-only profile missed.
96
97
  - **Immuno-Bench** (`benchmarks/immuno/`) — the immunogenic-vs-tolerated recovery track + an honest `calibrate_axis`
97
98
  ADA pass (it stays 🟡 at public-data power — no manufactured ✅, the standing wet-lab bottleneck).
98
99
 
100
+ **v6.9.2 — real-tool rigor pass (no proxies / no heuristics).** A top-to-bottom audit: the **MHC-I capsid axis is
101
+ re-grounded on the gold-standard NetMHCpan-4.1** (MHCflurry kept as a reported cross-check); **ADA foreignness is the
102
+ authoritative origin** and **abstains** when unknown (no k-mer guess); the MHC-II axis **abstains** rather than
103
+ falling back to a production proxy (the promiscuous-binder estimate is offline-triage only); and the PASTE pegRNA
104
+ writes the **real documented Bxb1 minimal attB** (FlyBase / Ghosh 2003) instead of a schematic. Real tool or honest
105
+ abstention — never a silent fallback.
106
+
99
107
  Real UniProt sequences only (no fabricated sequence); the axes are reported as a vector with `collapsed_score: None`;
100
108
  the realized CD4 response / ADA titer stay known-unknowns. See [docs/immune_profiler.md](docs/immune_profiler.md).
101
109
 
@@ -0,0 +1,296 @@
1
+ version: 6.9.2
2
+ method:
3
+ mhc2: NetMHCIIpan-4.0 EL %Rank<=2, residue coverage
4
+ hla2_panel:
5
+ - DRB1_0101
6
+ - DRB1_0301
7
+ - DRB1_0401
8
+ - DRB1_0701
9
+ - DRB1_1101
10
+ - DRB1_1301
11
+ - DRB1_1501
12
+ mhc1: NetMHCpan-4.1 %Rank_EL<=0.5, residue coverage
13
+ hla1_panel:
14
+ - HLA-A01:01
15
+ - HLA-A02:01
16
+ - HLA-A03:01
17
+ - HLA-A11:01
18
+ - HLA-A24:02
19
+ - HLA-A26:01
20
+ - HLA-B07:02
21
+ - HLA-B08:01
22
+ - HLA-B15:01
23
+ - HLA-B40:01
24
+ - HLA-B44:03
25
+ - HLA-B58:01
26
+ metric: residue coverage by strong binders, union over panel (matches v5.3 MHCflurry)
27
+ provenance_dois:
28
+ - 10.1093/nar/gkac1029
29
+ - 10.1093/nar/gkaa379
30
+ note: population-level epitope load (frequent-HLA panel; NOT patient-HLA-specific).
31
+ Licensed NetMHC binaries run locally; only derived fractions cached.
32
+ mhc2:
33
+ SpCas9:
34
+ epitope_fraction_strong: 0.636
35
+ immune_score: 0.364
36
+ metric: residue coverage by strong 15-mers (%Rank<=2.0), union over 7 alleles
37
+ length: 1368
38
+ n_covered: 870
39
+ alleles_used:
40
+ - DRB1_0101
41
+ - DRB1_0301
42
+ - DRB1_0401
43
+ - DRB1_0701
44
+ - DRB1_1101
45
+ - DRB1_1301
46
+ - DRB1_1501
47
+ ISCro4:
48
+ epitope_fraction_strong: 0.5644
49
+ immune_score: 0.4356
50
+ metric: residue coverage by strong 15-mers (%Rank<=2.0), union over 7 alleles
51
+ length: 326
52
+ n_covered: 184
53
+ alleles_used:
54
+ - DRB1_0101
55
+ - DRB1_0301
56
+ - DRB1_0401
57
+ - DRB1_0701
58
+ - DRB1_1101
59
+ - DRB1_1301
60
+ - DRB1_1501
61
+ Bxb1:
62
+ epitope_fraction_strong: 0.6467
63
+ immune_score: 0.3533
64
+ metric: residue coverage by strong 15-mers (%Rank<=2.0), union over 7 alleles
65
+ length: 501
66
+ n_covered: 324
67
+ alleles_used:
68
+ - DRB1_0101
69
+ - DRB1_0301
70
+ - DRB1_0401
71
+ - DRB1_0701
72
+ - DRB1_1101
73
+ - DRB1_1301
74
+ - DRB1_1501
75
+ HumanAlbumin:
76
+ epitope_fraction_strong: 0.3186
77
+ immune_score: 0.6814
78
+ metric: residue coverage by strong 15-mers (%Rank<=2.0), union over 7 alleles
79
+ length: 609
80
+ n_covered: 194
81
+ alleles_used:
82
+ - DRB1_0101
83
+ - DRB1_0301
84
+ - DRB1_0401
85
+ - DRB1_0701
86
+ - DRB1_1101
87
+ - DRB1_1301
88
+ - DRB1_1501
89
+ AAV2_VP1:
90
+ epitope_fraction_strong: 0.5592
91
+ immune_score: 0.4408
92
+ metric: residue coverage by strong 15-mers (%Rank<=2.0), union over 7 alleles
93
+ length: 735
94
+ n_covered: 411
95
+ alleles_used:
96
+ - DRB1_0101
97
+ - DRB1_0301
98
+ - DRB1_0401
99
+ - DRB1_0701
100
+ - DRB1_1101
101
+ - DRB1_1301
102
+ - DRB1_1501
103
+ Ad5_hexon:
104
+ epitope_fraction_strong: 0.6229
105
+ immune_score: 0.3771
106
+ metric: residue coverage by strong 15-mers (%Rank<=2.0), union over 7 alleles
107
+ length: 952
108
+ n_covered: 593
109
+ alleles_used:
110
+ - DRB1_0101
111
+ - DRB1_0301
112
+ - DRB1_0401
113
+ - DRB1_0701
114
+ - DRB1_1101
115
+ - DRB1_1301
116
+ - DRB1_1501
117
+ VSVg_Indiana:
118
+ epitope_fraction_strong: 0.3914
119
+ immune_score: 0.6086
120
+ metric: residue coverage by strong 15-mers (%Rank<=2.0), union over 7 alleles
121
+ length: 511
122
+ n_covered: 200
123
+ alleles_used:
124
+ - DRB1_0101
125
+ - DRB1_0301
126
+ - DRB1_0401
127
+ - DRB1_0701
128
+ - DRB1_1101
129
+ - DRB1_1301
130
+ - DRB1_1501
131
+ HSV1_gD:
132
+ epitope_fraction_strong: 0.5355
133
+ immune_score: 0.4645
134
+ metric: residue coverage by strong 15-mers (%Rank<=2.0), union over 7 alleles
135
+ length: 394
136
+ n_covered: 211
137
+ alleles_used:
138
+ - DRB1_0101
139
+ - DRB1_0301
140
+ - DRB1_0401
141
+ - DRB1_0701
142
+ - DRB1_1101
143
+ - DRB1_1301
144
+ - DRB1_1501
145
+ HSV1_gB:
146
+ epitope_fraction_strong: 0.4746
147
+ immune_score: 0.5254
148
+ metric: residue coverage by strong 15-mers (%Rank<=2.0), union over 7 alleles
149
+ length: 904
150
+ n_covered: 429
151
+ alleles_used:
152
+ - DRB1_0101
153
+ - DRB1_0301
154
+ - DRB1_0401
155
+ - DRB1_0701
156
+ - DRB1_1101
157
+ - DRB1_1301
158
+ - DRB1_1501
159
+ mhc1:
160
+ AAV2_VP1:
161
+ epitope_fraction_strong: 0.5415
162
+ immune_score: 0.4585
163
+ metric: residue coverage by strong 9-mers (%Rank<=0.5), union over 12 alleles
164
+ length: 735
165
+ n_covered: 398
166
+ alleles_used:
167
+ - HLA-A01:01
168
+ - HLA-A02:01
169
+ - HLA-A03:01
170
+ - HLA-A11:01
171
+ - HLA-A24:02
172
+ - HLA-A26:01
173
+ - HLA-B07:02
174
+ - HLA-B08:01
175
+ - HLA-B15:01
176
+ - HLA-B40:01
177
+ - HLA-B44:03
178
+ - HLA-B58:01
179
+ Ad5_hexon:
180
+ epitope_fraction_strong: 0.7216
181
+ immune_score: 0.2784
182
+ metric: residue coverage by strong 9-mers (%Rank<=0.5), union over 12 alleles
183
+ length: 952
184
+ n_covered: 687
185
+ alleles_used:
186
+ - HLA-A01:01
187
+ - HLA-A02:01
188
+ - HLA-A03:01
189
+ - HLA-A11:01
190
+ - HLA-A24:02
191
+ - HLA-A26:01
192
+ - HLA-B07:02
193
+ - HLA-B08:01
194
+ - HLA-B15:01
195
+ - HLA-B40:01
196
+ - HLA-B44:03
197
+ - HLA-B58:01
198
+ VSVg_Indiana:
199
+ epitope_fraction_strong: 0.6223
200
+ immune_score: 0.3777
201
+ metric: residue coverage by strong 9-mers (%Rank<=0.5), union over 12 alleles
202
+ length: 511
203
+ n_covered: 318
204
+ alleles_used:
205
+ - HLA-A01:01
206
+ - HLA-A02:01
207
+ - HLA-A03:01
208
+ - HLA-A11:01
209
+ - HLA-A24:02
210
+ - HLA-A26:01
211
+ - HLA-B07:02
212
+ - HLA-B08:01
213
+ - HLA-B15:01
214
+ - HLA-B40:01
215
+ - HLA-B44:03
216
+ - HLA-B58:01
217
+ HSV1_gD:
218
+ epitope_fraction_strong: 0.6853
219
+ immune_score: 0.3147
220
+ metric: residue coverage by strong 9-mers (%Rank<=0.5), union over 12 alleles
221
+ length: 394
222
+ n_covered: 270
223
+ alleles_used:
224
+ - HLA-A01:01
225
+ - HLA-A02:01
226
+ - HLA-A03:01
227
+ - HLA-A11:01
228
+ - HLA-A24:02
229
+ - HLA-A26:01
230
+ - HLA-B07:02
231
+ - HLA-B08:01
232
+ - HLA-B15:01
233
+ - HLA-B40:01
234
+ - HLA-B44:03
235
+ - HLA-B58:01
236
+ HSV1_gB:
237
+ epitope_fraction_strong: 0.5962
238
+ immune_score: 0.4038
239
+ metric: residue coverage by strong 9-mers (%Rank<=0.5), union over 12 alleles
240
+ length: 904
241
+ n_covered: 539
242
+ alleles_used:
243
+ - HLA-A01:01
244
+ - HLA-A02:01
245
+ - HLA-A03:01
246
+ - HLA-A11:01
247
+ - HLA-A24:02
248
+ - HLA-A26:01
249
+ - HLA-B07:02
250
+ - HLA-B08:01
251
+ - HLA-B15:01
252
+ - HLA-B40:01
253
+ - HLA-B44:03
254
+ - HLA-B58:01
255
+ self_match:
256
+ SpCas9:
257
+ fraction: 0.0
258
+ n: 1360
259
+ n_matched: 0
260
+ ISCro4:
261
+ fraction: 0.0
262
+ n: 318
263
+ n_matched: 0
264
+ Bxb1:
265
+ fraction: 0.0
266
+ n: 493
267
+ n_matched: 0
268
+ HumanAlbumin:
269
+ fraction: 1.0
270
+ n: 601
271
+ n_matched: 601
272
+ AAV2_VP1:
273
+ fraction: 0.0
274
+ n: 727
275
+ n_matched: 0
276
+ Ad5_hexon:
277
+ fraction: 0.0
278
+ n: 944
279
+ n_matched: 0
280
+ VSVg_Indiana:
281
+ fraction: 0.0
282
+ n: 503
283
+ n_matched: 0
284
+ HSV1_gD:
285
+ fraction: 0.0
286
+ n: 386
287
+ n_matched: 0
288
+ HSV1_gB:
289
+ fraction: 0.0
290
+ n: 896
291
+ n_matched: 0
292
+ self_match_meta:
293
+ reference: UniProt reviewed human reference proteome UP000005640 (20431 proteins)
294
+ k: 9
295
+ tool: exact 9-mer identity vs full human proteome (JanusMatrix-style self-similarity
296
+ cross-check)
@@ -9,12 +9,18 @@ adaptive axis was **CD8/MHC-I only** (capsid epitope load via MHCflurry). v6.9 a
9
9
  > **v6.9.1 — real predictor.** The MHC-II epitope load is computed with the **licensed NetMHCIIpan-4.0** (EL
10
10
  > %Rank≤2 over a frequent HLA-II panel; MHC-I via **NetMHCpan-4.1**), run inside `penmhc:tools` Docker on the VM
11
11
  > with the licensed tools **mounted** (never committed). Only the **derived fractions** are cached
12
- > (`configs/mhc_epitope_oracle.yaml`), exactly like the v5.3 MHCflurry cache. The documented proxy below remains as
13
- > the offline/CI fallback for sequences not in the cache. Real result: human-self albumin **0.066** vs foreign
14
- > writers **0.11–0.15** (the gold-standard tool discriminates self from foreign the v6.9.0 proxy gave ~0.08–0.10
15
- > for all). Still a 🟡 population-level proxy (frequent-HLA panel, not a patient-HLA magnitude).
12
+ > (`configs/mhc_epitope_oracle.yaml`), exactly like the v5.3 MHCflurry cache. Computed with the v6.9.2 residue-coverage
13
+ > metric (residues covered by ≥1 strong binder, union over the panel matches the v5.3 MHCflurry convention): the
14
+ > gold-standard tool discriminates self from foreign (human-self albumin **0.319** vs foreign writers **0.56–0.65**;
15
+ > the v6.9.0 heuristic proxy gave ~0.08–0.10 for all). Still a 🟡 population-level proxy (frequent-HLA panel, not a
16
+ > patient-HLA magnitude).
17
+ >
18
+ > **v6.9.2 — no production proxy.** For a sequence **not** in the real cache the axis now **abstains** (an honest
19
+ > known-unknown) rather than emitting a proxy number; the documented promiscuous-binder density below is retained
20
+ > only as `mhc2_proxy_estimate` for **offline triage** (explicitly labelled, never the production axis). The **capsid
21
+ > MHC-I axis** is likewise re-grounded on **NetMHCpan-4.1** as the primary, with MHCflurry kept as a reported cross-check.
16
22
 
17
- A grounded, dependency-free **promiscuous MHC-II binder density** (the offline/CI fallback): MHC-II presents a 9-mer core in an open groove
23
+ A grounded, dependency-free **promiscuous MHC-II binder density** (`mhc2_proxy_estimate`, offline triage only): MHC-II presents a 9-mer core in an open groove
18
24
  whose **P1 pocket is deep and hydrophobic** — the single dominant anchor (M/F/Y/W/L/I/V; Stern & Wiley, *Nature*
19
25
  1994), with secondary pockets at P4/P6/P9. A *promiscuous* epitope (binds many HLA-DR) has a strong P1 anchor +
20
26
  favorable secondaries (Southwood 1998). We count promiscuous-binder cores → an epitope-density proxy, computed over
@@ -29,19 +35,22 @@ Epitope load is necessary but not sufficient — **self** proteins carry MHC-II
29
35
  ADA-risk = MHC-II epitope density × foreignness
30
36
  ```
31
37
 
32
- with a **self-tolerance filter** (JanusMatrix-style: an epitope whose core matches the human proteome is
33
- tolerated). `foreignness` uses the **authoritative protein origin** (self vs bacterial/viral/phage) when known,
34
- else `1 self_match_fraction` from a human-proteome k-mer filter. This **recovers immunogenic-vs-tolerated**:
38
+ where `foreignness` is the **authoritative protein origin** (self vs bacterial/viral/phage) the definitive
39
+ central-tolerance signal. **v6.9.2:** the MHC-II density is the real NetMHCIIpan-4.0 value (by antigen name), and an
40
+ **unknown origin abstains** (no k-mer guess, no heuristic). The **real full-human-proteome 9-mer self-match**
41
+ (computed on the VM over the full UniProt reference proteome, 20 431 proteins / 10.4 M 9-mers) is reported as a
42
+ **cross-check**, not as a foreignness imputation. This **recovers immunogenic-vs-tolerated**:
35
43
 
36
- | Protein (real UniProt) | origin | ADA-risk |
37
- |---|---|---|
38
- | Bxb1 integrase (Q9B086) | foreign | **0.095** |
39
- | SpCas9 (Q99ZW2) | foreign | **0.093** |
40
- | ISCro4 bridge recombinase (D2TGM5) | foreign | **0.082** |
41
- | Human albumin (P02768) | self | **0.0** (tolerated) |
44
+ | Protein (real UniProt) | origin | MHC-II density (NetMHCIIpan-4.0) | ADA-risk | human-proteome self-match |
45
+ |---|---|---|---|---|
46
+ | SpCas9 (Q99ZW2) | foreign | 0.636 | **0.636** | 0.0 (non-self) |
47
+ | Bxb1 integrase (Q9B086) | foreign | 0.647 | **0.647** | 0.0 (non-self) |
48
+ | ISCro4 bridge recombinase (D2TGM5) | foreign | 0.564 | **0.564** | 0.0 (non-self) |
49
+ | Human albumin (P02768) | self | 0.319 | **0.0** (tolerated, × origin) | **1.0** (self) |
42
50
 
43
- The human self control scores 0 **even without the origin label** the k-mer self-match tolerates it. The foreign
44
- writers separate cleanly above it.
51
+ ADA-risk = density × foreignness, so the self control is zeroed by its `self` origin while the foreign writers carry
52
+ their full MHC-II load. The independent human-proteome self-match agrees: albumin is fully self (1.0), the bacterial
53
+ writers are non-self (0.0).
45
54
 
46
55
  ## The writer as a distinct antigen
47
56
 
@@ -1,2 +1,2 @@
1
1
  """PEN-STACK v3.0 - open infrastructure for genome writing."""
2
- __version__ = "6.9.1"
2
+ __version__ = "6.9.2"
@@ -8,8 +8,10 @@ Auto-designs the targeting component each writer family needs, from the DOCUMENT
8
8
  10.1038/s41586-024-07552-4). We compute the loop guide sequences (reverse-complement of the specificity arms,
9
9
  core preserved) and validate by round-trip recovery.
10
10
  * **pegRNA + attB** (PASTE / PASSIGE) — a prime-editing guide whose 3' extension WRITES a serine-integrase
11
- attachment site (e.g. Bxb1 attB, central dinucleotide **GT**) at the nick, so the integrase can then place
12
- large cargo (Yarnall et al., Nat Biotechnol 2023, 10.1038/s41587-022-01527-4; Pandey/Liu, Nat Biomed Eng 2025).
11
+ attachment site at the nick, so the integrase can then place large cargo (Yarnall et al., Nat Biotechnol 2023,
12
+ 10.1038/s41587-022-01527-4; Pandey/Liu, Nat Biomed Eng 2025). v6.9.2 writes the **REAL documented Bxb1 minimal
13
+ attB** (FlyBase FBto0000359; Ghosh, Kim & Hatfull, Mol Cell 2003, 10.1016/S1097-2765(03)00444-1) — not a
14
+ schematic — with the 8-bp common core **GCGGTCTC** around the central **GT** crossover dinucleotide.
13
15
  * **orthogonal att-pair selection** — serine-integrase att sites with distinct central dinucleotides
14
16
  (e.g. **GA vs GT**) recombine only with their cognate partner, enabling multiplexed/orthogonal landing pads
15
17
  (Roelle, Kamath & Matreyek, ACS Synth Biol 2023, 10.1021/acssynbio.3c00355).
@@ -34,6 +36,20 @@ _INTEGRASE_CORE = {
34
36
  # mismatched cores are ~orthogonal.
35
37
  _ORTHOGONAL_BXB1_CORES = ["GT", "GA", "GC", "CT", "TA"]
36
38
 
39
+ # REAL, documented serine-integrase attachment sites (verbatim, never fabricated). Bxb1: FlyBase FBto0000359
40
+ # (attB) / FBto0000358 (attP); Ghosh, Kim & Hatfull, Mol Cell 2003 (10.1016/S1097-2765(03)00444-1) — attB/attP
41
+ # share the 8-bp common core GCGGTCTC around the central GT crossover dinucleotide (the sole determinant of
42
+ # integration orientation). Only integrases with a documented site bundled here get a full attB written.
43
+ _INTEGRASE_ATT = {
44
+ "Bxb1": {
45
+ "attB": "TCGGCCGGCTTGTCGACGACGGCGGTCTCCGTCGTCAGGATCATCCGGGC",
46
+ "attP": "GTCGTGGTTTGTCTGGTCAACCACCGCGGTCTCAGTGGTGTACGGTACAAACCCCGAC",
47
+ "core": "GCGGTCTC", "central_dinucleotide": "GT",
48
+ "source": "FlyBase FBto0000359/358; Ghosh, Kim & Hatfull, Mol Cell 2003",
49
+ "doi": "10.1016/S1097-2765(03)00444-1",
50
+ },
51
+ }
52
+
37
53
 
38
54
  def revcomp(seq: str) -> str:
39
55
  return "".join(_COMP.get(b, "N") for b in reversed(seq))
@@ -92,24 +108,34 @@ class PegRNAAttDesign:
92
108
  note: str = ""
93
109
 
94
110
 
95
- def design_pegrna_attb(target_site: str, integrase: str = "Bxb1", attb_arm: int = 18) -> PegRNAAttDesign:
111
+ def design_pegrna_attb(target_site: str, integrase: str = "Bxb1") -> PegRNAAttDesign:
96
112
  """Design a PASTE/PASSIGE pegRNA that writes a serine-integrase **attB** at `target_site`.
97
113
 
98
- The prime-edit installs a minimal attB (cognate central dinucleotide for the integrase); the integrase then
99
- recombines cargo flanked by attP. We return the spacer + the 3' extension (revcomp of the att template, the
100
- PE convention) and the att site written. Sequences are DESIGN CANDIDATES empirical validation required.
114
+ The prime-edit installs the integrase's minimal attB; the integrase then recombines cargo flanked by the
115
+ cognate attP. We return the spacer + the 3' extension (revcomp of the att template, the PE convention) and the
116
+ att site written. For integrases with a documented site bundled (`_INTEGRASE_ATT`, e.g. Bxb1) the REAL minimal
117
+ attB is written verbatim — never a schematic; integrases without a bundled documented site expose only the
118
+ central core (the full sequence is NOT fabricated). Sequences are DESIGN CANDIDATES — empirical validation
119
+ required.
101
120
  """
102
121
  integrase = integrase if integrase in _INTEGRASE_CORE else "Bxb1"
103
122
  core = _INTEGRASE_CORE[integrase]
104
123
  ts = target_site.upper()
105
124
  spacer = ts[:20] if len(ts) >= 20 else ts
106
- # minimal attB = left arm + core + right arm (schematic minimal site; real arms are integrase-specific)
107
- attb = ("G" * attb_arm) + core + ("C" * attb_arm)
125
+ att = _INTEGRASE_ATT.get(integrase)
126
+ if att:
127
+ attb = att["attB"] # REAL documented minimal attB (verbatim) — no schematic arms
128
+ note = (f"pegRNA 3' extension writes the REAL documented {integrase} minimal attB ({len(attb)} bp; central "
129
+ f"crossover {att['central_dinucleotide']}, 8-bp common core {att['core']}; {att['source']}) at the "
130
+ f"nick; cargo is delivered flanked by the cognate attP. Candidate scaffold — empirical validation "
131
+ "required (Yarnall 2023).")
132
+ else:
133
+ attb = core # no bundled documented site: expose the core only, never fabricate
134
+ note = (f"no bundled documented minimal att sequence for {integrase!r}: only the central core {core} is "
135
+ "asserted (the full site is NOT fabricated). Add a documented attB to design the full scaffold.")
108
136
  return PegRNAAttDesign(
109
137
  integrase=integrase, att_core=core, target_site=ts, pegrna_spacer=spacer,
110
- pe_3prime_extension=revcomp(attb), written_att=attb,
111
- note=(f"pegRNA writes a minimal {integrase} attB (central core {core}) at the nick; cargo is delivered "
112
- "flanked by attP. Arm sequences are integrase-specific; this is a candidate scaffold (Yarnall 2023)."))
138
+ pe_3prime_extension=revcomp(attb), written_att=attb, note=note)
113
139
 
114
140
 
115
141
  def select_orthogonal_att_pairs(n: int, integrase: str = "Bxb1") -> dict:
@@ -0,0 +1,64 @@
1
+ """ADA-risk (v6.9 PEN-IMMUNE, G-WS2; v6.9.2 real-tool re-grounding).
2
+
3
+ A protein's MHC-II epitope load (presentation potential) is necessary but not sufficient for anti-drug antibodies
4
+ (ADA): **self** proteins carry MHC-II epitopes too, yet are tolerated (central tolerance deletes self-reactive T
5
+ cells). What drives ADA is **non-self** (foreign) presentable epitopes. So:
6
+
7
+ ADA-risk = MHC-II epitope density (real, NetMHCIIpan-4.0) x foreignness
8
+
9
+ where **foreignness is the protein ORIGIN** (self vs bacterial/viral/phage) — the authoritative, definitive
10
+ self/non-self signal (central tolerance), not a heuristic. The **real human-proteome 9-mer self-match** (computed
11
+ on the VM against the full UniProt human reference proteome) is reported as a cross-check. NO heuristic fallback:
12
+ when the MHC-II density is not cached (NetMHCIIpan not run) OR the origin is unknown, ADA-risk **abstains** (an
13
+ honest known-unknown) rather than guessing.
14
+
15
+ Honest: a population-level proxy (🟡), never a patient-specific ADA titer (a known-unknown). The calibration
16
+ against a public ADA-incidence set runs through the EXISTING calibrate_axis gate and stays 🟡 at public-data power.
17
+ """
18
+ from __future__ import annotations
19
+
20
+ from pen_stack.planner.immune_mhc2 import _real_cache, mhc2_epitope_load, writer_sequences
21
+
22
+ ADA_DOIS = ["10.1038/s41467-021-25414-9"] # Cas9 MHC-II CD4 immunogenicity (Simhadri 2021)
23
+ _FOREIGN = {"self": 0.0, "foreign": 1.0}
24
+
25
+
26
+ def real_self_match(name: str) -> dict | None:
27
+ """The REAL human-proteome 9-mer self-match for a bundled antigen (cross-check; computed on the VM against the
28
+ full UniProt human reference proteome). Foreign proteins ~0, human ~1. None if not in the cache."""
29
+ rec = (_real_cache().get("self_match") or {}).get(name)
30
+ if rec is None:
31
+ return None
32
+ return {"human_9mer_match_fraction": rec.get("fraction"), "n_9mers": rec.get("n"),
33
+ "reference": (_real_cache().get("self_match_meta") or {}).get("reference",
34
+ "UniProt human reference proteome (full)")}
35
+
36
+
37
+ def ada_risk(seq: str, origin: str | None = None, name: str | None = None) -> dict:
38
+ """ADA-risk = real MHC-II epitope density x foreignness(origin). Abstains (no proxy/heuristic) when the MHC-II
39
+ density is uncached or the origin is unknown. Higher ada_risk_score = MORE ADA risk; ada_immune_score = 1 - it."""
40
+ el = mhc2_epitope_load(seq, name)
41
+ density = el.get("epitope_density")
42
+ foreign = _FOREIGN.get(str(origin)) if origin is not None else None
43
+ sm = real_self_match(name) if name else None
44
+ base = {"epitope_density": density, "foreignness": foreign, "origin": origin,
45
+ "self_match_human_proteome": sm, "dois": ADA_DOIS,
46
+ "filter": "central tolerance: foreign (non-self) MHC-II epitopes drive ADA; self tolerated. Foreignness "
47
+ "= protein origin (authoritative); MHC-II density = NetMHCIIpan-4.0; real human-proteome "
48
+ "self-match reported as cross-check (no heuristic).",
49
+ "status": "population-level (🟡); patient ADA titer / magnitude is a known-unknown"}
50
+ if density is None or foreign is None:
51
+ return {**base, "ada_risk_score": None, "ada_immune_score": None, "backend": "abstain",
52
+ "note": ("abstains (no proxy): " + ("NetMHCIIpan-4.0 not run for this sequence" if density is None
53
+ else "protein origin unknown — foreignness is not guessed"))}
54
+ risk = round(density * foreign, 4)
55
+ return {**base, "ada_risk_score": risk, "ada_immune_score": round(1.0 - risk, 4), "backend": "real"}
56
+
57
+
58
+ def ada_risk_named(name: str) -> dict:
59
+ """ADA-risk for a bundled writer/control protein by name (uses its declared origin + the real MHC-II cache)."""
60
+ rec = writer_sequences().get(name)
61
+ if not rec:
62
+ return {"available": False, "note": f"no bundled sequence {name!r}"}
63
+ return {"available": True, "name": name, "family": rec.get("family"),
64
+ **ada_risk(rec["seq"], rec.get("origin"), name=name)}