pen-stack 6.9.0__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.0 → pen_stack-6.9.2}/CHANGELOG.md +66 -0
  2. {pen_stack-6.9.0 → pen_stack-6.9.2}/CITATION.cff +1 -1
  3. {pen_stack-6.9.0 → pen_stack-6.9.2}/PKG-INFO +19 -8
  4. {pen_stack-6.9.0 → pen_stack-6.9.2}/README.md +18 -7
  5. pen_stack-6.9.2/configs/mhc_epitope_oracle.yaml +296 -0
  6. pen_stack-6.9.2/docs/immune_profiler.md +70 -0
  7. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/__init__.py +1 -1
  8. {pen_stack-6.9.0 → 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.0 → pen_stack-6.9.2}/pen_stack/planner/delivery_immunology.py +3 -2
  12. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/planner/immune_mhc2.py +48 -12
  13. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/planner/immune_profile.py +8 -4
  14. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack.egg-info/PKG-INFO +19 -8
  15. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack.egg-info/SOURCES.txt +1 -0
  16. {pen_stack-6.9.0 → pen_stack-6.9.2}/pyproject.toml +1 -1
  17. pen_stack-6.9.0/docs/immune_profiler.md +0 -53
  18. pen_stack-6.9.0/pen_stack/planner/ada_risk.py +0 -84
  19. pen_stack-6.9.0/pen_stack/planner/capsid_epitope_oracle.py +0 -97
  20. {pen_stack-6.9.0 → pen_stack-6.9.2}/LICENSE +0 -0
  21. {pen_stack-6.9.0 → pen_stack-6.9.2}/MANIFEST.in +0 -0
  22. {pen_stack-6.9.0 → pen_stack-6.9.2}/bench/run.py +0 -0
  23. {pen_stack-6.9.0 → pen_stack-6.9.2}/benchmarks/genome_writing_bench/LEADERBOARD.md +0 -0
  24. {pen_stack-6.9.0 → pen_stack-6.9.2}/benchmarks/genome_writing_bench/README.md +0 -0
  25. {pen_stack-6.9.0 → pen_stack-6.9.2}/benchmarks/genome_writing_bench/SHA256SUMS +0 -0
  26. {pen_stack-6.9.0 → pen_stack-6.9.2}/benchmarks/genome_writing_bench/SUBMISSIONS.md +0 -0
  27. {pen_stack-6.9.0 → pen_stack-6.9.2}/benchmarks/genome_writing_bench/tasks.yaml +0 -0
  28. {pen_stack-6.9.0 → pen_stack-6.9.2}/benchmarks/genome_writing_challenge/README.md +0 -0
  29. {pen_stack-6.9.0 → pen_stack-6.9.2}/benchmarks/genome_writing_challenge/SUBMISSIONS.md +0 -0
  30. {pen_stack-6.9.0 → pen_stack-6.9.2}/benchmarks/position_effect/README.md +0 -0
  31. {pen_stack-6.9.0 → pen_stack-6.9.2}/benchmarks/position_effect/SHA256SUMS +0 -0
  32. {pen_stack-6.9.0 → pen_stack-6.9.2}/benchmarks/writer_efficiency/README.md +0 -0
  33. {pen_stack-6.9.0 → pen_stack-6.9.2}/benchmarks/writer_efficiency/SHA256SUMS +0 -0
  34. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/antipeg.yaml +0 -0
  35. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/atlas_families.yaml +0 -0
  36. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/bridge_offtarget_profile.yaml +0 -0
  37. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/calibration/preexisting_nab_independent.yaml +0 -0
  38. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/capsid_epitope_oracle.yaml +0 -0
  39. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/capsid_sequences.fasta +0 -0
  40. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/cargo_polish.yaml +0 -0
  41. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/cell_types.yaml +0 -0
  42. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/datasets.yaml +0 -0
  43. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/delivery_constraints.yaml +0 -0
  44. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/delivery_rules.yaml +0 -0
  45. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/delivery_vehicles.yaml +0 -0
  46. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/expression/modifiers.yaml +0 -0
  47. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/expression/promoters.yaml +0 -0
  48. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/gates_v3.yaml +0 -0
  49. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/genotoxicity_oracle.yaml +0 -0
  50. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/gsh_validated_heldout.yaml +0 -0
  51. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/intent_weights.yaml +0 -0
  52. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/known_unknowns.yaml +0 -0
  53. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/llm.yaml +0 -0
  54. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/metric_guide.yaml +0 -0
  55. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/monitor_queries.yaml +0 -0
  56. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/oracles/execution.yaml +0 -0
  57. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/oracles/scope_cards.yaml +0 -0
  58. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/rules/delivery.yaml +0 -0
  59. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/rules/fold.yaml +0 -0
  60. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/rules/multiplex.yaml +0 -0
  61. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/rules/payload.yaml +0 -0
  62. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/rules/reachability.yaml +0 -0
  63. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/safety/hazard_registry.yaml +0 -0
  64. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/safety/policy.yaml +0 -0
  65. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/safety/probes.yaml +0 -0
  66. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/score_axes.yaml +0 -0
  67. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/seroprevalence.yaml +0 -0
  68. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/target_sites.yaml +0 -0
  69. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/universe_crosswalk.yaml +0 -0
  70. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/write_types.yaml +0 -0
  71. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/writer_sequences.fasta +0 -0
  72. {pen_stack-6.9.0 → pen_stack-6.9.2}/configs/wtkb_curated.yaml +0 -0
  73. {pen_stack-6.9.0 → pen_stack-6.9.2}/data/curated/bridge_offtarget_energetics.json +0 -0
  74. {pen_stack-6.9.0 → pen_stack-6.9.2}/data/curated/bridge_offtarget_profile_measured.parquet +0 -0
  75. {pen_stack-6.9.0 → pen_stack-6.9.2}/data/curated/gene_coords.parquet +0 -0
  76. {pen_stack-6.9.0 → pen_stack-6.9.2}/data/curated/unified_editor_universe.parquet +0 -0
  77. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/BACKLOG.md +0 -0
  78. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/DEPLOY.md +0 -0
  79. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/INFRA.md +0 -0
  80. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/MCP.md +0 -0
  81. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/RELEASING.md +0 -0
  82. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/REPRO.md +0 -0
  83. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/STABILITY.md +0 -0
  84. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/agent.md +0 -0
  85. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/alphagenome_feasibility.md +0 -0
  86. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/autonomy.md +0 -0
  87. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/benchmark_circularity.md +0 -0
  88. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/biosecurity.md +0 -0
  89. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/build_interface.md +0 -0
  90. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/cards/atlas.md +0 -0
  91. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/cards/durability.md +0 -0
  92. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/cards/position_effect_data.md +0 -0
  93. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/cards/safety.md +0 -0
  94. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/cards/writer_efficiency_data.md +0 -0
  95. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/challenge.md +0 -0
  96. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/closed_loop.md +0 -0
  97. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/co_scientist.md +0 -0
  98. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/co_scientist_loop.md +0 -0
  99. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/delivery.md +0 -0
  100. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/delivery_immunology.md +0 -0
  101. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/digital_twin.md +0 -0
  102. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/dissemination.md +0 -0
  103. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/environment.md +0 -0
  104. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/experiment_design.md +0 -0
  105. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/generative_design.md +0 -0
  106. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/index.md +0 -0
  107. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/integrations.md +0 -0
  108. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/live_oracles.md +0 -0
  109. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/mechanistic_constraints.md +0 -0
  110. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/oracles.md +0 -0
  111. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/position_effect.md +0 -0
  112. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/positioning.md +0 -0
  113. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/private_data_formats.md +0 -0
  114. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/quickstart.md +0 -0
  115. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/responsible_use.md +0 -0
  116. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/rules.md +0 -0
  117. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/scope.md +0 -0
  118. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/scorecard.md +0 -0
  119. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/tpe_bench.md +0 -0
  120. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/tutorials/compare-families.md +0 -0
  121. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/tutorials/score-deliverability.md +0 -0
  122. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/tutorials/where-can-i-write.md +0 -0
  123. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/tutorials/which-writer-reaches-locus.md +0 -0
  124. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/uncertainty.md +0 -0
  125. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/verify.md +0 -0
  126. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/world_model.md +0 -0
  127. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/writer_efficiency.md +0 -0
  128. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/writer_verification.md +0 -0
  129. {pen_stack-6.9.0 → pen_stack-6.9.2}/docs/wtkb.md +0 -0
  130. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/_resources.py +0 -0
  131. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/active/__init__.py +0 -0
  132. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/active/acquire.py +0 -0
  133. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/active/design.py +0 -0
  134. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/active/validate.py +0 -0
  135. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/adapt/__init__.py +0 -0
  136. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/adapt/finetune.py +0 -0
  137. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/adapt/ingest.py +0 -0
  138. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/adapt/pipeline.py +0 -0
  139. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/adapt/recalibrate.py +0 -0
  140. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/adapt/report.py +0 -0
  141. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/agent/__init__.py +0 -0
  142. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/agent/cite.py +0 -0
  143. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/agent/co_scientist.py +0 -0
  144. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/agent/epistemic.py +0 -0
  145. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/agent/guardrails.py +0 -0
  146. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/agent/mcp_server.py +0 -0
  147. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/agent/orchestrator.py +0 -0
  148. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/agent/orchestrator_live.py +0 -0
  149. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/agent/pen_agent.py +0 -0
  150. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/agent/scope.py +0 -0
  151. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/agent/tools.py +0 -0
  152. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/api/__init__.py +0 -0
  153. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/api/manifest.py +0 -0
  154. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/atlas/__init__.py +0 -0
  155. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/atlas/build_wtkb.py +0 -0
  156. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/atlas/crosslink.py +0 -0
  157. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/atlas/expand.py +0 -0
  158. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/atlas/schema.py +0 -0
  159. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/atlas/scorecard.py +0 -0
  160. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/atlas/universe.py +0 -0
  161. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/atlas/variant_propose.py +0 -0
  162. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/atlas/writer_efficiency.py +0 -0
  163. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/atlas/writer_predict.py +0 -0
  164. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/atlas/writer_recommend.py +0 -0
  165. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/atlas/writer_verify.py +0 -0
  166. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/bridge/__init__.py +0 -0
  167. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/bridge/activity.py +0 -0
  168. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/bridge/cli.py +0 -0
  169. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/bridge/fold_qc.py +0 -0
  170. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/bridge/guide_qc.py +0 -0
  171. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/bridge/ingest.py +0 -0
  172. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/bridge/offtarget.py +0 -0
  173. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/bridge/offtarget_energetics.py +0 -0
  174. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/bridge/ortholog_screen.py +0 -0
  175. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/bridge/pipeline.py +0 -0
  176. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/build/__init__.py +0 -0
  177. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/build/ingest.py +0 -0
  178. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/build/protocol.py +0 -0
  179. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/build/simlab.py +0 -0
  180. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/cli.py +0 -0
  181. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/data/__init__.py +0 -0
  182. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/data/encode.py +0 -0
  183. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/data/genome.py +0 -0
  184. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/data/ingest_chromatin.py +0 -0
  185. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/data/ingest_integration.py +0 -0
  186. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/data/ingest_safety_annot.py +0 -0
  187. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/data/ingest_trip.py +0 -0
  188. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/design/__init__.py +0 -0
  189. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/design/generate.py +0 -0
  190. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/design/pareto.py +0 -0
  191. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/design/space.py +0 -0
  192. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/design/writer_variants.py +0 -0
  193. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/env/__init__.py +0 -0
  194. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/env/genome_writing_env.py +0 -0
  195. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/env/policies.py +0 -0
  196. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/graph/__init__.py +0 -0
  197. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/graph/build.py +0 -0
  198. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/graph/cell_types.py +0 -0
  199. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/graph/ingest.py +0 -0
  200. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/graph/query.py +0 -0
  201. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/graph/schema.py +0 -0
  202. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/loop/__init__.py +0 -0
  203. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/loop/continual.py +0 -0
  204. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/loop/cycle.py +0 -0
  205. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/loop/drift.py +0 -0
  206. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/mech/__init__.py +0 -0
  207. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/mech/classify_atlas.py +0 -0
  208. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/mech/whitelist.py +0 -0
  209. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/monitor/__init__.py +0 -0
  210. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/monitor/europepmc.py +0 -0
  211. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/monitor/run.py +0 -0
  212. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/monitor/triage.py +0 -0
  213. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/oracles/__init__.py +0 -0
  214. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/oracles/cache.py +0 -0
  215. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/oracles/energetics.py +0 -0
  216. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/oracles/genome.py +0 -0
  217. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/oracles/protein_design.py +0 -0
  218. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/oracles/rna.py +0 -0
  219. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/oracles/schema.py +0 -0
  220. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/oracles/status.py +0 -0
  221. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/oracles/structure.py +0 -0
  222. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/oracles/vcell.py +0 -0
  223. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/planner/__init__.py +0 -0
  224. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/planner/antipeg_oracle.py +0 -0
  225. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/planner/cargo.py +0 -0
  226. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/planner/cargo_polish.py +0 -0
  227. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/planner/delivery.py +0 -0
  228. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/planner/delivery_constraints.py +0 -0
  229. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/planner/delivery_vehicles.py +0 -0
  230. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/planner/genotoxicity_oracle.py +0 -0
  231. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/planner/innate_sensing.py +0 -0
  232. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/planner/multiplex.py +0 -0
  233. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/planner/optimize.py +0 -0
  234. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/planner/pipeline.py +0 -0
  235. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/planner/report.py +0 -0
  236. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/planner/router.py +0 -0
  237. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/planner/seroprevalence_oracle.py +0 -0
  238. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/planner/target_site.py +0 -0
  239. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/rag/__init__.py +0 -0
  240. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/rag/index.py +0 -0
  241. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/rag/llm.py +0 -0
  242. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/rag/qa.py +0 -0
  243. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/rules/__init__.py +0 -0
  244. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/rules/evaluators.py +0 -0
  245. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/rules/loader.py +0 -0
  246. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/rules/schema.py +0 -0
  247. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/rules/solver.py +0 -0
  248. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/safety/__init__.py +0 -0
  249. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/safety/audit.py +0 -0
  250. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/safety/gate.py +0 -0
  251. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/safety/policy.py +0 -0
  252. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/safety/redteam.py +0 -0
  253. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/safety/registry.py +0 -0
  254. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/safety/screen.py +0 -0
  255. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/score/__init__.py +0 -0
  256. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/score/recalibrate.py +0 -0
  257. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/score/therapeutic.py +0 -0
  258. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/server/__init__.py +0 -0
  259. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/server/api.py +0 -0
  260. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/twin/__init__.py +0 -0
  261. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/twin/calibrate.py +0 -0
  262. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/twin/data/__init__.py +0 -0
  263. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/twin/data/position_effect.py +0 -0
  264. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/twin/mechanistic.py +0 -0
  265. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/twin/outcome.py +0 -0
  266. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/twin/position_effect.py +0 -0
  267. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/ui/__init__.py +0 -0
  268. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/ui/app.py +0 -0
  269. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/__init__.py +0 -0
  270. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/adapt_demo.py +0 -0
  271. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/agent_eval.py +0 -0
  272. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/bench_adversarial_tasks.py +0 -0
  273. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/bench_coscientist_tasks.py +0 -0
  274. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/bench_graph_tasks.py +0 -0
  275. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/bench_rule_tasks.py +0 -0
  276. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/bench_trust_tasks.py +0 -0
  277. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/bench_writetype_tasks.py +0 -0
  278. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/blind_gsh_discovery.py +0 -0
  279. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/cargo_directionality.py +0 -0
  280. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/closed_loop.py +0 -0
  281. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/durability_baselines.py +0 -0
  282. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/experiment_design.py +0 -0
  283. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/expr_controls.py +0 -0
  284. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/forward_hypotheses.py +0 -0
  285. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/generative_design.py +0 -0
  286. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/guide_qc_demo.py +0 -0
  287. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/heldout_celltype_expr.py +0 -0
  288. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/immune_calibration.py +0 -0
  289. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/intent_specification.py +0 -0
  290. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/known_biology_expr.py +0 -0
  291. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/offtarget_energetics_eval.py +0 -0
  292. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/out_of_scope_refusal.py +0 -0
  293. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/outcome_calibration.py +0 -0
  294. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/outcome_prediction.py +0 -0
  295. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/paper3_benchmark.py +0 -0
  296. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/paper4_real_validation.py +0 -0
  297. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/paper4_validation.py +0 -0
  298. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/protocol_safety.py +0 -0
  299. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/safety_screening.py +0 -0
  300. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/selective_prediction.py +0 -0
  301. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/seq_vs_measured.py +0 -0
  302. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/target_site_controls.py +0 -0
  303. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/uncertainty_eval.py +0 -0
  304. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/ungrounded_baseline.py +0 -0
  305. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/within_locus_ranking.py +0 -0
  306. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/validate/writer_recovery.py +0 -0
  307. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/verify/__init__.py +0 -0
  308. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/verify/schema.py +0 -0
  309. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/verify/service.py +0 -0
  310. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/web/__init__.py +0 -0
  311. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/web/guide.py +0 -0
  312. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/web/llm.py +0 -0
  313. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/web/router.py +0 -0
  314. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/web/server.py +0 -0
  315. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/web/tools.py +0 -0
  316. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/wgenome/__init__.py +0 -0
  317. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/wgenome/chromatin_seq.py +0 -0
  318. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/wgenome/durability.py +0 -0
  319. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/wgenome/export_tracks.py +0 -0
  320. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/wgenome/features.py +0 -0
  321. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/wgenome/gsh_baseline.py +0 -0
  322. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/wgenome/mesh_features.py +0 -0
  323. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/wgenome/ood.py +0 -0
  324. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/wgenome/providers.py +0 -0
  325. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/wgenome/safety.py +0 -0
  326. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/wgenome/structure3d.py +0 -0
  327. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/wgenome/uncertainty.py +0 -0
  328. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack/wgenome/writability.py +0 -0
  329. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack.egg-info/dependency_links.txt +0 -0
  330. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack.egg-info/entry_points.txt +0 -0
  331. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack.egg-info/requires.txt +0 -0
  332. {pen_stack-6.9.0 → pen_stack-6.9.2}/pen_stack.egg-info/top_level.txt +0 -0
  333. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_phase0.json +0 -0
  334. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_phase1_5.json +0 -0
  335. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_phase2.json +0 -0
  336. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_phase3.json +0 -0
  337. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_a.json +0 -0
  338. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_acq.json +0 -0
  339. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_aldesign.json +0 -0
  340. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_alvalidate.json +0 -0
  341. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_atlas.json +0 -0
  342. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_b.json +0 -0
  343. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_ba.json +0 -0
  344. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_ba_v33.json +0 -0
  345. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_ba_v45.json +0 -0
  346. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_bench.json +0 -0
  347. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_c.json +0 -0
  348. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_cal.json +0 -0
  349. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_calib.json +0 -0
  350. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_challenge.json +0 -0
  351. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_chat.json +0 -0
  352. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_cite.json +0 -0
  353. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_continual.json +0 -0
  354. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_cosci2.json +0 -0
  355. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_crit.json +0 -0
  356. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_ct.json +0 -0
  357. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_d.json +0 -0
  358. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_drift.json +0 -0
  359. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_e.json +0 -0
  360. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_env.json +0 -0
  361. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_ep.json +0 -0
  362. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_epitope.json +0 -0
  363. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_expr2.json +0 -0
  364. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_f.json +0 -0
  365. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_frontend.json +0 -0
  366. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_g.json +0 -0
  367. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_gen.json +0 -0
  368. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_genotox.json +0 -0
  369. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_graph.json +0 -0
  370. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_h.json +0 -0
  371. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_hybrid.json +0 -0
  372. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_immune.json +0 -0
  373. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_immune2.json +0 -0
  374. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_ingest.json +0 -0
  375. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_innate.json +0 -0
  376. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_loop.json +0 -0
  377. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_manifest.json +0 -0
  378. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_mc.json +0 -0
  379. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_mcp.json +0 -0
  380. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_mech.json +0 -0
  381. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_mon.json +0 -0
  382. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_o.json +0 -0
  383. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_openapi.json +0 -0
  384. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_orch.json +0 -0
  385. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_outcome.json +0 -0
  386. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_pareto.json +0 -0
  387. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_peg.json +0 -0
  388. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_plan.json +0 -0
  389. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_policy.json +0 -0
  390. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_profile.json +0 -0
  391. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_proto.json +0 -0
  392. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_r.json +0 -0
  393. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_redteam.json +0 -0
  394. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_route.json +0 -0
  395. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_screen.json +0 -0
  396. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_seroprev.json +0 -0
  397. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_simlab.json +0 -0
  398. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_twincal.json +0 -0
  399. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_uq.json +0 -0
  400. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_v.json +0 -0
  401. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_vcell.json +0 -0
  402. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_writer.json +0 -0
  403. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/SHA256_LOCK_ws_wv.json +0 -0
  404. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/paper1.yaml +0 -0
  405. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/paper2.yaml +0 -0
  406. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/paper3.yaml +0 -0
  407. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/paper4.yaml +0 -0
  408. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/phase0.yaml +0 -0
  409. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_a.yaml +0 -0
  410. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_acq.yaml +0 -0
  411. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_aldesign.yaml +0 -0
  412. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_alvalidate.yaml +0 -0
  413. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_atlas.yaml +0 -0
  414. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_b.yaml +0 -0
  415. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_ba.yaml +0 -0
  416. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_ba_v33.yaml +0 -0
  417. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_ba_v45.yaml +0 -0
  418. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_bench.yaml +0 -0
  419. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_c.yaml +0 -0
  420. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_cal.yaml +0 -0
  421. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_calib.yaml +0 -0
  422. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_challenge.yaml +0 -0
  423. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_chat.yaml +0 -0
  424. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_cite.yaml +0 -0
  425. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_continual.yaml +0 -0
  426. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_cosci2.yaml +0 -0
  427. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_crit.yaml +0 -0
  428. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_ct.yaml +0 -0
  429. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_d.yaml +0 -0
  430. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_drift.yaml +0 -0
  431. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_e.yaml +0 -0
  432. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_env.yaml +0 -0
  433. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_ep.yaml +0 -0
  434. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_epitope.yaml +0 -0
  435. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_expr2.yaml +0 -0
  436. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_f.yaml +0 -0
  437. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_frontend.yaml +0 -0
  438. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_g.yaml +0 -0
  439. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_gen.yaml +0 -0
  440. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_genotox.yaml +0 -0
  441. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_graph.yaml +0 -0
  442. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_h.yaml +0 -0
  443. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_hybrid.yaml +0 -0
  444. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_immune.yaml +0 -0
  445. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_immune2.yaml +0 -0
  446. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_ingest.yaml +0 -0
  447. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_innate.yaml +0 -0
  448. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_loop.yaml +0 -0
  449. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_manifest.yaml +0 -0
  450. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_mc.yaml +0 -0
  451. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_mcp.yaml +0 -0
  452. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_mech.yaml +0 -0
  453. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_mon.yaml +0 -0
  454. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_o.yaml +0 -0
  455. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_openapi.yaml +0 -0
  456. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_orch.yaml +0 -0
  457. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_outcome.yaml +0 -0
  458. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_pareto.yaml +0 -0
  459. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_peg.yaml +0 -0
  460. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_plan.yaml +0 -0
  461. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_policy.yaml +0 -0
  462. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_profile.yaml +0 -0
  463. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_proto.yaml +0 -0
  464. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_r.yaml +0 -0
  465. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_redteam.yaml +0 -0
  466. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_route.yaml +0 -0
  467. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_screen.yaml +0 -0
  468. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_seroprev.yaml +0 -0
  469. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_simlab.yaml +0 -0
  470. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_twincal.yaml +0 -0
  471. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_uq.yaml +0 -0
  472. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_v.yaml +0 -0
  473. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_vcell.yaml +0 -0
  474. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_writer.yaml +0 -0
  475. {pen_stack-6.9.0 → pen_stack-6.9.2}/prereg/ws_wv.yaml +0 -0
  476. {pen_stack-6.9.0 → pen_stack-6.9.2}/scripts/calibrate_immune_axes.py +0 -0
  477. {pen_stack-6.9.0 → pen_stack-6.9.2}/scripts/fetch_licensed_sources.py +0 -0
  478. {pen_stack-6.9.0 → pen_stack-6.9.2}/scripts/p1_build_atlas.py +0 -0
  479. {pen_stack-6.9.0 → pen_stack-6.9.2}/scripts/p1_build_durability.py +0 -0
  480. {pen_stack-6.9.0 → pen_stack-6.9.2}/scripts/p1_build_position_effect.py +0 -0
  481. {pen_stack-6.9.0 → pen_stack-6.9.2}/scripts/p1_build_writer_eff.py +0 -0
  482. {pen_stack-6.9.0 → pen_stack-6.9.2}/scripts/p1_export_tracks.py +0 -0
  483. {pen_stack-6.9.0 → pen_stack-6.9.2}/scripts/p1_safety_concordance.py +0 -0
  484. {pen_stack-6.9.0 → pen_stack-6.9.2}/scripts/p1_train_safety.py +0 -0
  485. {pen_stack-6.9.0 → pen_stack-6.9.2}/scripts/p1_validation_report.py +0 -0
  486. {pen_stack-6.9.0 → pen_stack-6.9.2}/scripts/p2_build_atlas.py +0 -0
  487. {pen_stack-6.9.0 → pen_stack-6.9.2}/scripts/p3_benchmark_report.py +0 -0
  488. {pen_stack-6.9.0 → pen_stack-6.9.2}/scripts/p4_genome_scan.py +0 -0
  489. {pen_stack-6.9.0 → pen_stack-6.9.2}/scripts/p52_build_genotox_oracle.py +0 -0
  490. {pen_stack-6.9.0 → pen_stack-6.9.2}/scripts/p53_build_epitope_oracle.py +0 -0
  491. {pen_stack-6.9.0 → pen_stack-6.9.2}/scripts/ws_b_report.py +0 -0
  492. {pen_stack-6.9.0 → pen_stack-6.9.2}/scripts/ws_c_report.py +0 -0
  493. {pen_stack-6.9.0 → pen_stack-6.9.2}/setup.cfg +0 -0
@@ -3,6 +3,72 @@
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
+
46
+ ## [6.9.1] - 2026-06-20 - Real NetMHCIIpan-4.0 / NetMHCpan-4.1 MHC epitope load (replaces the v6.9.0 proxy)
47
+
48
+ **PATCH — rigour upgrade.** v6.9.0's MHC-II axis was a documented *heuristic proxy* (P1-anchor density). The
49
+ gold-standard licensed predictors were already on the VM — so v6.9.1 computes the MHC-II epitope load with **real
50
+ NetMHCIIpan-4.0** (and MHC-I with **NetMHCpan-4.1**) over a frequent HLA panel, and re-grounds the axis on the real
51
+ values. Honest: the licensed binaries are **never committed/distributed** — only the **derived fractions** are
52
+ cached (`configs/mhc_epitope_oracle.yaml`), exactly like the v5.3 MHCflurry cache.
53
+
54
+ ### Changed
55
+ - `pen_stack/planner/immune_mhc2.py` — `mhc2_epitope_load(seq, name)` now uses the **real NetMHCIIpan-4.0 EL
56
+ %Rank≤2** cache (over 7 frequent HLA-II alleles) when the antigen is cached; the documented promiscuous-binder
57
+ proxy remains only as the **offline/CI fallback** for uncached sequences. `real_mhc2_load(name)` exposes the cache.
58
+ - `ada_risk` + `immune_profile` (writer-as-antigen) + `benchmarks/immuno` thread the antigen name → real values.
59
+ - `configs/mhc_epitope_oracle.yaml` (committed) — derived epitope fractions for the writer + capsid antigens.
60
+
61
+ ### Result (real tool is more discriminating than the proxy)
62
+ - Real NetMHCIIpan-4.0 strong-binder fraction: SpCas9 **0.153**, Bxb1 **0.152**, ISCro4 **0.112**, AAV2 0.114 vs
63
+ **human albumin (self) 0.066 — the lowest**. The gold-standard tool shows the self protein has a genuinely lower
64
+ MHC-II load and the foreign writers higher — a signal the heuristic proxy flattened (~0.08–0.10 for all). The
65
+ immunogenic-vs-tolerated recovery is unchanged (foreign ≫ self) but now on real predictions.
66
+
67
+ ### How it ran (no host install; per the VM Docker rule)
68
+ - `penmhc:tools` (debian + tcsh + gawk + perl) with `~/netmhc` (the licensed tools) **mounted**, NMHOME fixed at
69
+ runtime; `scratch/v691_mhc_compute.py` runs both predictors and writes the derived cache. The axis stays a 🟡
70
+ population-level proxy (frequent-HLA panel, not a patient-HLA magnitude — a known-unknown).
71
+
6
72
  ## [6.9.0] - 2026-06-20 - PEN-IMMUNE: MHC-II/CD4 + ADA + writer-as-antigen
7
73
 
8
74
  **MINOR feature release.** Extends the immune profile from CD8/MHC-I-only to a full T-cell profile — MHC-I +
@@ -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.0
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.0
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.0-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)
@@ -155,19 +155,30 @@ driver is **MHC-II / CD4 help → anti-drug antibodies (ADA)**, and the **writer
155
155
  (Cas9 elicits MHC-II-presented CD4 responses, Simhadri *Nat Commun* 2021; bridge recombinases / serine integrases
156
156
  are bacterial/phage) — yet Stage G scored only the capsid. v6.9 closes that gap, **never collapsing** the axes:
157
157
 
158
- - **A CD4/MHC-II epitope-load axis** (`planner/immune_mhc2.py`) — a grounded, dependency-free **promiscuous MHC-II
159
- binder density** over the documented P1 hydrophobic anchor (Stern & Wiley 1994) + secondary pockets, scored over
160
- **capsid AND writer** sequences. Population-level proxy (🟡), never a patient-HLA magnitude.
161
- - **An ADA-risk axis** (`planner/ada_risk.py`) — **ADA-risk = MHC-II epitope density × foreignness**, with a
162
- **self-tolerance filter** (JanusMatrix-style: self epitopes are tolerated; foreign drive ADA). It **recovers
158
+ - **A CD4/MHC-II epitope-load axis** (`planner/immune_mhc2.py`) — **v6.9.1 computes it with the real, licensed
159
+ NetMHCIIpan-4.0** (EL %Rank≤2 over a frequent HLA-II panel; MHC-I via NetMHCpan-4.1), scored over **capsid AND
160
+ writer** sequences; only the derived fractions are cached (`configs/mhc_epitope_oracle.yaml`, the binaries are
161
+ never distributed), with a documented promiscuous-binder proxy as the offline/CI fallback. Population-level proxy
162
+ (🟡), never a patient-HLA magnitude. *(v6.9.0 used the heuristic proxy; the real tool is more discriminating —
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**, where
165
+ **foreignness is the protein ORIGIN** (the authoritative central-tolerance signal). It **recovers
163
166
  immunogenic-vs-tolerated**: the foreign writers (real UniProt SpCas9 / ISCro4 / Bxb1) score **above** the human
164
- 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).
165
169
  - **The writer as a distinct antigen** — the profile now carries a `writer_as_antigen` card and a
166
170
  `writer_dominant_risk` flag: for **non-viral delivery of a bacterial writer there is no capsid antigen, so the
167
171
  WRITER is the dominant immunogen** — the insight the capsid-only profile missed.
168
172
  - **Immuno-Bench** (`benchmarks/immuno/`) — the immunogenic-vs-tolerated recovery track + an honest `calibrate_axis`
169
173
  ADA pass (it stays 🟡 at public-data power — no manufactured ✅, the standing wet-lab bottleneck).
170
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
+
171
182
  Real UniProt sequences only (no fabricated sequence); the axes are reported as a vector with `collapsed_score: None`;
172
183
  the realized CD4 response / ADA titer stay known-unknowns. See [docs/immune_profiler.md](docs/immune_profiler.md).
173
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.0-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)
@@ -80,19 +80,30 @@ driver is **MHC-II / CD4 help → anti-drug antibodies (ADA)**, and the **writer
80
80
  (Cas9 elicits MHC-II-presented CD4 responses, Simhadri *Nat Commun* 2021; bridge recombinases / serine integrases
81
81
  are bacterial/phage) — yet Stage G scored only the capsid. v6.9 closes that gap, **never collapsing** the axes:
82
82
 
83
- - **A CD4/MHC-II epitope-load axis** (`planner/immune_mhc2.py`) — a grounded, dependency-free **promiscuous MHC-II
84
- binder density** over the documented P1 hydrophobic anchor (Stern & Wiley 1994) + secondary pockets, scored over
85
- **capsid AND writer** sequences. Population-level proxy (🟡), never a patient-HLA magnitude.
86
- - **An ADA-risk axis** (`planner/ada_risk.py`) — **ADA-risk = MHC-II epitope density × foreignness**, with a
87
- **self-tolerance filter** (JanusMatrix-style: self epitopes are tolerated; foreign drive ADA). It **recovers
83
+ - **A CD4/MHC-II epitope-load axis** (`planner/immune_mhc2.py`) — **v6.9.1 computes it with the real, licensed
84
+ NetMHCIIpan-4.0** (EL %Rank≤2 over a frequent HLA-II panel; MHC-I via NetMHCpan-4.1), scored over **capsid AND
85
+ writer** sequences; only the derived fractions are cached (`configs/mhc_epitope_oracle.yaml`, the binaries are
86
+ never distributed), with a documented promiscuous-binder proxy as the offline/CI fallback. Population-level proxy
87
+ (🟡), never a patient-HLA magnitude. *(v6.9.0 used the heuristic proxy; the real tool is more discriminating —
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**, where
90
+ **foreignness is the protein ORIGIN** (the authoritative central-tolerance signal). It **recovers
88
91
  immunogenic-vs-tolerated**: the foreign writers (real UniProt SpCas9 / ISCro4 / Bxb1) score **above** the human
89
- 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).
90
94
  - **The writer as a distinct antigen** — the profile now carries a `writer_as_antigen` card and a
91
95
  `writer_dominant_risk` flag: for **non-viral delivery of a bacterial writer there is no capsid antigen, so the
92
96
  WRITER is the dominant immunogen** — the insight the capsid-only profile missed.
93
97
  - **Immuno-Bench** (`benchmarks/immuno/`) — the immunogenic-vs-tolerated recovery track + an honest `calibrate_axis`
94
98
  ADA pass (it stays 🟡 at public-data power — no manufactured ✅, the standing wet-lab bottleneck).
95
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
+
96
107
  Real UniProt sequences only (no fabricated sequence); the axes are reported as a vector with `collapsed_score: None`;
97
108
  the realized CD4 response / ADA titer stay known-unknowns. See [docs/immune_profiler.md](docs/immune_profiler.md).
98
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)
@@ -0,0 +1,70 @@
1
+ # Stage G — the immune profiler (v6.9 PEN-IMMUNE)
2
+
3
+ Stage G profiles a design's immunogenicity/toxicity across **separate, never-collapsed axes**. Through v6.8 the
4
+ adaptive axis was **CD8/MHC-I only** (capsid epitope load via MHCflurry). v6.9 adds the **dominant** driver —
5
+ **MHC-II/CD4 → ADA** — and scores the **writer enzyme as a distinct antigen**.
6
+
7
+ ## The MHC-II/CD4 axis (`planner/immune_mhc2.py`)
8
+
9
+ > **v6.9.1 — real predictor.** The MHC-II epitope load is computed with the **licensed NetMHCIIpan-4.0** (EL
10
+ > %Rank≤2 over a frequent HLA-II panel; MHC-I via **NetMHCpan-4.1**), run inside `penmhc:tools` Docker on the VM
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. 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.
22
+
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
24
+ whose **P1 pocket is deep and hydrophobic** — the single dominant anchor (M/F/Y/W/L/I/V; Stern & Wiley, *Nature*
25
+ 1994), with secondary pockets at P4/P6/P9. A *promiscuous* epitope (binds many HLA-DR) has a strong P1 anchor +
26
+ favorable secondaries (Southwood 1998). We count promiscuous-binder cores → an epitope-density proxy, computed over
27
+ **capsid AND writer** sequences. It is a **population-level, sequence-intrinsic proxy (🟡)** — not a trained
28
+ allele-specific predictor, not a patient-HLA magnitude (a known-unknown).
29
+
30
+ ## The ADA-risk axis + self-tolerance (`planner/ada_risk.py`)
31
+
32
+ Epitope load is necessary but not sufficient — **self** proteins carry MHC-II epitopes yet are tolerated. So:
33
+
34
+ ```
35
+ ADA-risk = MHC-II epitope density × foreignness
36
+ ```
37
+
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**:
43
+
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) |
50
+
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).
54
+
55
+ ## The writer as a distinct antigen
56
+
57
+ `immune_profile` now carries a `writer_as_antigen` card and a `writer_dominant_risk` flag. The insight the
58
+ capsid-only profile missed: **for non-viral delivery (LNP/mRNA, eVLP) of a bacterial writer there is no capsid
59
+ antigen — so the WRITER is the dominant immunogen.** The flag fires accordingly; the axes are reported as a vector
60
+ with `collapsed_score: None` (never fused).
61
+
62
+ ## Honest limits
63
+ - Population-level proxies (🟡), never a patient-specific ADA titer / realized CD4 magnitude (known-unknowns).
64
+ - The MHC-II method is presentation potential, not a trained allele-specific predictor.
65
+ - The self-tolerance k-mer filter is seeded by the bundled human reference; the **full human proteome** is
66
+ substitutable on the VM (the authoritative foreignness signal is the protein origin).
67
+ - The ADA axis's `calibrate_axis` pass **stays 🟡** — no public observed-incidence set at N≥6 power (the standing
68
+ wet-lab/clinical-data bottleneck), reported, never manufactured.
69
+
70
+ See `benchmarks/immuno/` (Immuno-Bench) and `prereg/ws_immune2.yaml`.
@@ -1,2 +1,2 @@
1
1
  """PEN-STACK v3.0 - open infrastructure for genome writing."""
2
- __version__ = "6.9.0"
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: