pen-stack 7.1.8__tar.gz → 7.2.1__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 (581) hide show
  1. {pen_stack-7.1.8 → pen_stack-7.2.1}/CHANGELOG.md +96 -0
  2. {pen_stack-7.1.8 → pen_stack-7.2.1}/CITATION.cff +2 -2
  3. {pen_stack-7.1.8 → pen_stack-7.2.1}/MANIFEST.in +1 -0
  4. {pen_stack-7.1.8 → pen_stack-7.2.1}/PKG-INFO +1 -1
  5. pen_stack-7.2.1/benchmarks/offtarget/integrase/README.md +23 -0
  6. pen_stack-7.2.1/benchmarks/offtarget/integrase/SHA256SUMS +4 -0
  7. pen_stack-7.2.1/data/curated/cast_systems.yaml +59 -0
  8. pen_stack-7.2.1/data/curated/integrase_att.yaml +66 -0
  9. pen_stack-7.2.1/data/offtarget/enumerated_cache.parquet +0 -0
  10. pen_stack-7.2.1/data/offtarget/motif_cache.parquet +0 -0
  11. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/cards/offtarget_data.md +25 -0
  12. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/__init__.py +1 -1
  13. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/agent/mcp_server.py +9 -6
  14. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/api/manifest.py +7 -5
  15. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/server/api.py +23 -5
  16. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/wgenome/offtarget_assay.py +24 -1
  17. pen_stack-7.2.1/pen_stack/wgenome/offtarget_bridge.py +47 -0
  18. pen_stack-7.2.1/pen_stack/wgenome/offtarget_cast.py +97 -0
  19. pen_stack-7.2.1/pen_stack/wgenome/offtarget_enumerate.py +271 -0
  20. pen_stack-7.2.1/pen_stack/wgenome/offtarget_integrase.py +111 -0
  21. pen_stack-7.2.1/pen_stack/wgenome/offtarget_nuclease.py +66 -0
  22. pen_stack-7.2.1/pen_stack/wgenome/offtarget_paste.py +41 -0
  23. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/wgenome/offtarget_predict.py +35 -14
  24. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack.egg-info/PKG-INFO +1 -1
  25. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack.egg-info/SOURCES.txt +14 -0
  26. pen_stack-7.2.1/prereg/SHA256_LOCK_ws_offtarget2.json +9 -0
  27. pen_stack-7.2.1/prereg/ws_offtarget2.yaml +106 -0
  28. {pen_stack-7.1.8 → pen_stack-7.2.1}/pyproject.toml +1 -1
  29. {pen_stack-7.1.8 → pen_stack-7.2.1}/LICENSE +0 -0
  30. {pen_stack-7.1.8 → pen_stack-7.2.1}/README.md +0 -0
  31. {pen_stack-7.1.8 → pen_stack-7.2.1}/bench/run.py +0 -0
  32. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/chat_grounding/README.md +0 -0
  33. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/chat_grounding/SHA256SUMS +0 -0
  34. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/chat_headtohead/README.md +0 -0
  35. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/chat_routing/README.md +0 -0
  36. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/chat_routing/SHA256SUMS +0 -0
  37. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/chat_safety/README.md +0 -0
  38. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/chat_safety/SHA256SUMS +0 -0
  39. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/delivery/SHA256SUMS +0 -0
  40. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/genome_writing_bench/LEADERBOARD.md +0 -0
  41. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/genome_writing_bench/README.md +0 -0
  42. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/genome_writing_bench/SHA256SUMS +0 -0
  43. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/genome_writing_bench/SUBMISSIONS.md +0 -0
  44. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/genome_writing_bench/tasks.yaml +0 -0
  45. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/genome_writing_challenge/README.md +0 -0
  46. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/genome_writing_challenge/SUBMISSIONS.md +0 -0
  47. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/loop/SHA256SUMS +0 -0
  48. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/offtarget/SHA256SUMS +0 -0
  49. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/oracle/SHA256SUMS +0 -0
  50. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/position_effect/README.md +0 -0
  51. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/position_effect/SHA256SUMS +0 -0
  52. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/verify/SHA256SUMS +0 -0
  53. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/writer_efficiency/README.md +0 -0
  54. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/writer_efficiency/SHA256SUMS +0 -0
  55. {pen_stack-7.1.8 → pen_stack-7.2.1}/benchmarks/writespec/SHA256SUMS +0 -0
  56. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/aav_serotype_tropism.yaml +0 -0
  57. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/antipeg.yaml +0 -0
  58. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/atlas_families.yaml +0 -0
  59. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/bridge_offtarget_profile.yaml +0 -0
  60. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/calibration/preexisting_nab_independent.yaml +0 -0
  61. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/capsid_epitope_oracle.yaml +0 -0
  62. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/capsid_sequences.fasta +0 -0
  63. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/cargo_polish.yaml +0 -0
  64. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/cell_types.yaml +0 -0
  65. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/datasets.yaml +0 -0
  66. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/delivery_constraints.yaml +0 -0
  67. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/delivery_rules.yaml +0 -0
  68. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/delivery_vehicles.yaml +0 -0
  69. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/expression/modifiers.yaml +0 -0
  70. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/expression/promoters.yaml +0 -0
  71. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/gates_v3.yaml +0 -0
  72. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/genotoxicity_oracle.yaml +0 -0
  73. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/gsh_validated_heldout.yaml +0 -0
  74. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/intent_weights.yaml +0 -0
  75. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/known_unknowns.yaml +0 -0
  76. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/llm.yaml +0 -0
  77. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/metric_guide.yaml +0 -0
  78. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/mhc_epitope_oracle.yaml +0 -0
  79. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/monitor_queries.yaml +0 -0
  80. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/oracles/execution.yaml +0 -0
  81. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/oracles/reliability.yaml +0 -0
  82. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/oracles/scope_cards.yaml +0 -0
  83. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/rules/compliance.yaml +0 -0
  84. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/rules/delivery.yaml +0 -0
  85. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/rules/fold.yaml +0 -0
  86. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/rules/multiplex.yaml +0 -0
  87. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/rules/payload.yaml +0 -0
  88. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/rules/reachability.yaml +0 -0
  89. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/safety/hazard_registry.yaml +0 -0
  90. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/safety/policy.yaml +0 -0
  91. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/safety/probes.yaml +0 -0
  92. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/score_axes.yaml +0 -0
  93. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/seroprevalence.yaml +0 -0
  94. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/target_sites.yaml +0 -0
  95. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/universe_crosswalk.yaml +0 -0
  96. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/write_types.yaml +0 -0
  97. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/writer_sequences.fasta +0 -0
  98. {pen_stack-7.1.8 → pen_stack-7.2.1}/configs/wtkb_curated.yaml +0 -0
  99. {pen_stack-7.1.8 → pen_stack-7.2.1}/data/curated/bridge_offtarget_energetics.json +0 -0
  100. {pen_stack-7.1.8 → pen_stack-7.2.1}/data/curated/bridge_offtarget_profile_measured.parquet +0 -0
  101. {pen_stack-7.1.8 → pen_stack-7.2.1}/data/curated/gene_coords.parquet +0 -0
  102. {pen_stack-7.1.8 → pen_stack-7.2.1}/data/curated/unified_editor_universe.parquet +0 -0
  103. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/BACKLOG.md +0 -0
  104. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/DEPLOY.md +0 -0
  105. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/INFRA.md +0 -0
  106. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/MCP.md +0 -0
  107. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/RELEASING.md +0 -0
  108. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/REPRO.md +0 -0
  109. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/STABILITY.md +0 -0
  110. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/agent.md +0 -0
  111. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/alphagenome_feasibility.md +0 -0
  112. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/autonomy.md +0 -0
  113. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/benchmark_circularity.md +0 -0
  114. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/biosecurity.md +0 -0
  115. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/build_interface.md +0 -0
  116. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/cards/atlas.md +0 -0
  117. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/cards/durability.md +0 -0
  118. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/cards/position_effect_data.md +0 -0
  119. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/cards/safety.md +0 -0
  120. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/cards/writer_efficiency_data.md +0 -0
  121. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/challenge.md +0 -0
  122. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/closed_loop.md +0 -0
  123. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/co_scientist.md +0 -0
  124. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/co_scientist_loop.md +0 -0
  125. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/delivery.md +0 -0
  126. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/delivery_immunology.md +0 -0
  127. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/delivery_recommender.md +0 -0
  128. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/digital_twin.md +0 -0
  129. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/dissemination.md +0 -0
  130. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/environment.md +0 -0
  131. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/experiment_design.md +0 -0
  132. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/generative_design.md +0 -0
  133. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/immune_profiler.md +0 -0
  134. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/index.md +0 -0
  135. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/integrations.md +0 -0
  136. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/live_oracles.md +0 -0
  137. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/mechanistic_constraints.md +0 -0
  138. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/offtarget.md +0 -0
  139. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/oracle_mesh.md +0 -0
  140. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/oracles.md +0 -0
  141. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/position_effect.md +0 -0
  142. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/positioning.md +0 -0
  143. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/private_data_formats.md +0 -0
  144. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/quickstart.md +0 -0
  145. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/responsible_use.md +0 -0
  146. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/rule_spec.md +0 -0
  147. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/rules.md +0 -0
  148. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/scope.md +0 -0
  149. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/scorecard.md +0 -0
  150. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/tpe_bench.md +0 -0
  151. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/tutorials/compare-families.md +0 -0
  152. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/tutorials/score-deliverability.md +0 -0
  153. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/tutorials/where-can-i-write.md +0 -0
  154. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/tutorials/which-writer-reaches-locus.md +0 -0
  155. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/uncertainty.md +0 -0
  156. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/verify.md +0 -0
  157. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/verify_service.md +0 -0
  158. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/world_model.md +0 -0
  159. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/writer_efficiency.md +0 -0
  160. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/writer_verification.md +0 -0
  161. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/writespec_bench.md +0 -0
  162. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/writespec_profile.md +0 -0
  163. {pen_stack-7.1.8 → pen_stack-7.2.1}/docs/wtkb.md +0 -0
  164. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/_resources.py +0 -0
  165. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/active/__init__.py +0 -0
  166. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/active/acquire.py +0 -0
  167. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/active/brains.py +0 -0
  168. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/active/campaign.py +0 -0
  169. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/active/design.py +0 -0
  170. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/active/validate.py +0 -0
  171. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/adapt/__init__.py +0 -0
  172. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/adapt/finetune.py +0 -0
  173. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/adapt/ingest.py +0 -0
  174. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/adapt/pipeline.py +0 -0
  175. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/adapt/recalibrate.py +0 -0
  176. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/adapt/report.py +0 -0
  177. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/agent/__init__.py +0 -0
  178. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/agent/cite.py +0 -0
  179. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/agent/co_scientist.py +0 -0
  180. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/agent/epistemic.py +0 -0
  181. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/agent/guardrails.py +0 -0
  182. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/agent/orchestrator.py +0 -0
  183. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/agent/orchestrator_live.py +0 -0
  184. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/agent/pen_agent.py +0 -0
  185. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/agent/scope.py +0 -0
  186. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/agent/tools.py +0 -0
  187. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/api/__init__.py +0 -0
  188. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/atlas/__init__.py +0 -0
  189. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/atlas/build_wtkb.py +0 -0
  190. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/atlas/crosslink.py +0 -0
  191. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/atlas/expand.py +0 -0
  192. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/atlas/guide_design.py +0 -0
  193. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/atlas/schema.py +0 -0
  194. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/atlas/scorecard.py +0 -0
  195. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/atlas/universe.py +0 -0
  196. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/atlas/variant_propose.py +0 -0
  197. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/atlas/writer_efficiency.py +0 -0
  198. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/atlas/writer_predict.py +0 -0
  199. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/atlas/writer_recommend.py +0 -0
  200. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/atlas/writer_verify.py +0 -0
  201. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/bridge/__init__.py +0 -0
  202. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/bridge/activity.py +0 -0
  203. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/bridge/cli.py +0 -0
  204. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/bridge/fold_qc.py +0 -0
  205. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/bridge/guide_qc.py +0 -0
  206. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/bridge/ingest.py +0 -0
  207. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/bridge/offtarget.py +0 -0
  208. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/bridge/offtarget_energetics.py +0 -0
  209. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/bridge/ortholog_screen.py +0 -0
  210. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/bridge/pipeline.py +0 -0
  211. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/build/__init__.py +0 -0
  212. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/build/cloudlab.py +0 -0
  213. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/build/ingest.py +0 -0
  214. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/build/protocol.py +0 -0
  215. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/build/simlab.py +0 -0
  216. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/cli.py +0 -0
  217. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/data/__init__.py +0 -0
  218. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/data/encode.py +0 -0
  219. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/data/genome.py +0 -0
  220. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/data/ingest_chromatin.py +0 -0
  221. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/data/ingest_integration.py +0 -0
  222. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/data/ingest_safety_annot.py +0 -0
  223. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/data/ingest_trip.py +0 -0
  224. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/design/__init__.py +0 -0
  225. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/design/capsid_generate.py +0 -0
  226. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/design/generate.py +0 -0
  227. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/design/pareto.py +0 -0
  228. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/design/space.py +0 -0
  229. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/design/writer_variants.py +0 -0
  230. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/env/__init__.py +0 -0
  231. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/env/genome_writing_env.py +0 -0
  232. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/env/policies.py +0 -0
  233. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/graph/__init__.py +0 -0
  234. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/graph/build.py +0 -0
  235. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/graph/cell_types.py +0 -0
  236. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/graph/ingest.py +0 -0
  237. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/graph/query.py +0 -0
  238. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/graph/schema.py +0 -0
  239. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/loop/__init__.py +0 -0
  240. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/loop/continual.py +0 -0
  241. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/loop/cycle.py +0 -0
  242. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/loop/drift.py +0 -0
  243. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/mech/__init__.py +0 -0
  244. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/mech/classify_atlas.py +0 -0
  245. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/mech/whitelist.py +0 -0
  246. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/monitor/__init__.py +0 -0
  247. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/monitor/europepmc.py +0 -0
  248. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/monitor/run.py +0 -0
  249. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/monitor/triage.py +0 -0
  250. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/oracles/__init__.py +0 -0
  251. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/oracles/affinity.py +0 -0
  252. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/oracles/cache.py +0 -0
  253. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/oracles/energetics.py +0 -0
  254. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/oracles/genome.py +0 -0
  255. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/oracles/protein_design.py +0 -0
  256. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/oracles/reliability.py +0 -0
  257. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/oracles/rna.py +0 -0
  258. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/oracles/schema.py +0 -0
  259. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/oracles/status.py +0 -0
  260. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/oracles/structure.py +0 -0
  261. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/oracles/structure_run.py +0 -0
  262. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/oracles/vcell.py +0 -0
  263. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/__init__.py +0 -0
  264. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/ada_risk.py +0 -0
  265. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/antipeg_oracle.py +0 -0
  266. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/capsid_epitope_oracle.py +0 -0
  267. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/cargo.py +0 -0
  268. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/cargo_polish.py +0 -0
  269. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/chromosome.py +0 -0
  270. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/delivery.py +0 -0
  271. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/delivery_constraints.py +0 -0
  272. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/delivery_immune.py +0 -0
  273. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/delivery_immunology.py +0 -0
  274. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/delivery_predict.py +0 -0
  275. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/delivery_vehicles.py +0 -0
  276. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/genotoxicity_oracle.py +0 -0
  277. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/immune_mhc2.py +0 -0
  278. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/immune_profile.py +0 -0
  279. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/innate_sensing.py +0 -0
  280. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/multiplex.py +0 -0
  281. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/optimize.py +0 -0
  282. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/pipeline.py +0 -0
  283. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/report.py +0 -0
  284. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/router.py +0 -0
  285. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/seroprevalence_oracle.py +0 -0
  286. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/planner/target_site.py +0 -0
  287. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/rag/__init__.py +0 -0
  288. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/rag/corpus.py +0 -0
  289. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/rag/embed.py +0 -0
  290. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/rag/ground.py +0 -0
  291. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/rag/index.py +0 -0
  292. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/rag/llm.py +0 -0
  293. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/rag/qa.py +0 -0
  294. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/rag/retrieve.py +0 -0
  295. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/rules/__init__.py +0 -0
  296. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/rules/evaluators.py +0 -0
  297. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/rules/loader.py +0 -0
  298. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/rules/schema.py +0 -0
  299. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/rules/solver.py +0 -0
  300. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/rules/spec.py +0 -0
  301. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/safety/__init__.py +0 -0
  302. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/safety/audit.py +0 -0
  303. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/safety/gate.py +0 -0
  304. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/safety/policy.py +0 -0
  305. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/safety/redteam.py +0 -0
  306. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/safety/registry.py +0 -0
  307. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/safety/screen.py +0 -0
  308. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/safety/standards.py +0 -0
  309. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/score/__init__.py +0 -0
  310. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/score/recalibrate.py +0 -0
  311. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/score/therapeutic.py +0 -0
  312. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/server/__init__.py +0 -0
  313. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/spec/__init__.py +0 -0
  314. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/spec/clarify.py +0 -0
  315. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/spec/extract.py +0 -0
  316. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/spec/resolvers/__init__.py +0 -0
  317. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/spec/resolvers/cell.py +0 -0
  318. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/spec/resolvers/chem.py +0 -0
  319. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/spec/resolvers/feature.py +0 -0
  320. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/spec/resolvers/gene.py +0 -0
  321. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/spec/resolvers/locus.py +0 -0
  322. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/spec/resolvers/phenotype.py +0 -0
  323. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/spec/satisfy.py +0 -0
  324. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/spec/service.py +0 -0
  325. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/spec/writespec.py +0 -0
  326. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/twin/__init__.py +0 -0
  327. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/twin/calibrate.py +0 -0
  328. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/twin/data/__init__.py +0 -0
  329. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/twin/data/position_effect.py +0 -0
  330. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/twin/mechanistic.py +0 -0
  331. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/twin/outcome.py +0 -0
  332. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/twin/position_effect.py +0 -0
  333. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/ui/__init__.py +0 -0
  334. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/ui/app.py +0 -0
  335. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/__init__.py +0 -0
  336. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/adapt_demo.py +0 -0
  337. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/agent_eval.py +0 -0
  338. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/bench_adversarial_tasks.py +0 -0
  339. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/bench_coscientist_tasks.py +0 -0
  340. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/bench_graph_tasks.py +0 -0
  341. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/bench_rule_tasks.py +0 -0
  342. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/bench_trust_tasks.py +0 -0
  343. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/bench_writetype_tasks.py +0 -0
  344. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/blind_gsh_discovery.py +0 -0
  345. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/cargo_directionality.py +0 -0
  346. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/closed_loop.py +0 -0
  347. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/durability_baselines.py +0 -0
  348. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/experiment_design.py +0 -0
  349. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/expr_controls.py +0 -0
  350. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/forward_hypotheses.py +0 -0
  351. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/generative_design.py +0 -0
  352. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/guide_qc_demo.py +0 -0
  353. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/heldout_celltype_expr.py +0 -0
  354. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/immune_calibration.py +0 -0
  355. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/intent_specification.py +0 -0
  356. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/known_biology_expr.py +0 -0
  357. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/offtarget_energetics_eval.py +0 -0
  358. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/out_of_scope_refusal.py +0 -0
  359. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/outcome_calibration.py +0 -0
  360. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/outcome_prediction.py +0 -0
  361. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/paper3_benchmark.py +0 -0
  362. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/paper4_real_validation.py +0 -0
  363. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/paper4_validation.py +0 -0
  364. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/protocol_safety.py +0 -0
  365. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/safety_screening.py +0 -0
  366. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/selective_prediction.py +0 -0
  367. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/seq_vs_measured.py +0 -0
  368. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/target_site_controls.py +0 -0
  369. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/uncertainty_eval.py +0 -0
  370. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/ungrounded_baseline.py +0 -0
  371. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/within_locus_ranking.py +0 -0
  372. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/validate/writer_recovery.py +0 -0
  373. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/verify/__init__.py +0 -0
  374. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/verify/proof.py +0 -0
  375. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/verify/schema.py +0 -0
  376. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/verify/service.py +0 -0
  377. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/web/__init__.py +0 -0
  378. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/web/guide.py +0 -0
  379. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/web/llm.py +0 -0
  380. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/web/llm_provider.py +0 -0
  381. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/web/router.py +0 -0
  382. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/web/server.py +0 -0
  383. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/web/tools.py +0 -0
  384. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/wgenome/__init__.py +0 -0
  385. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/wgenome/chromatin_seq.py +0 -0
  386. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/wgenome/durability.py +0 -0
  387. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/wgenome/export_tracks.py +0 -0
  388. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/wgenome/features.py +0 -0
  389. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/wgenome/gsh_baseline.py +0 -0
  390. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/wgenome/mesh_features.py +0 -0
  391. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/wgenome/offtarget_data.py +0 -0
  392. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/wgenome/ood.py +0 -0
  393. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/wgenome/providers.py +0 -0
  394. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/wgenome/safety.py +0 -0
  395. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/wgenome/structure3d.py +0 -0
  396. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/wgenome/uncertainty.py +0 -0
  397. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack/wgenome/writability.py +0 -0
  398. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack.egg-info/dependency_links.txt +0 -0
  399. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack.egg-info/entry_points.txt +0 -0
  400. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack.egg-info/requires.txt +0 -0
  401. {pen_stack-7.1.8 → pen_stack-7.2.1}/pen_stack.egg-info/top_level.txt +0 -0
  402. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_phase0.json +0 -0
  403. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_phase1_5.json +0 -0
  404. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_phase2.json +0 -0
  405. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_phase3.json +0 -0
  406. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_a.json +0 -0
  407. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_acq.json +0 -0
  408. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_aldesign.json +0 -0
  409. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_alvalidate.json +0 -0
  410. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_atlas.json +0 -0
  411. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_b.json +0 -0
  412. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_ba.json +0 -0
  413. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_ba_v33.json +0 -0
  414. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_ba_v45.json +0 -0
  415. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_bench.json +0 -0
  416. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_c.json +0 -0
  417. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_cal.json +0 -0
  418. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_calib.json +0 -0
  419. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_challenge.json +0 -0
  420. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_chat.json +0 -0
  421. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_cite.json +0 -0
  422. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_closedloop.json +0 -0
  423. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_continual.json +0 -0
  424. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_cosci2.json +0 -0
  425. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_crit.json +0 -0
  426. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_ct.json +0 -0
  427. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_d.json +0 -0
  428. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_delivery.json +0 -0
  429. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_drift.json +0 -0
  430. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_e.json +0 -0
  431. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_env.json +0 -0
  432. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_ep.json +0 -0
  433. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_epitope.json +0 -0
  434. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_expr2.json +0 -0
  435. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_f.json +0 -0
  436. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_frontend.json +0 -0
  437. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_g.json +0 -0
  438. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_gen.json +0 -0
  439. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_genotox.json +0 -0
  440. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_graph.json +0 -0
  441. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_h.json +0 -0
  442. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_hybrid.json +0 -0
  443. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_immune.json +0 -0
  444. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_immune2.json +0 -0
  445. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_ingest.json +0 -0
  446. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_innate.json +0 -0
  447. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_loop.json +0 -0
  448. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_manifest.json +0 -0
  449. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_mc.json +0 -0
  450. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_mcp.json +0 -0
  451. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_mech.json +0 -0
  452. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_mon.json +0 -0
  453. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_o.json +0 -0
  454. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_offtarget.json +0 -0
  455. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_openapi.json +0 -0
  456. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_oracle.json +0 -0
  457. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_orch.json +0 -0
  458. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_outcome.json +0 -0
  459. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_pareto.json +0 -0
  460. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_peg.json +0 -0
  461. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_penchat.json +0 -0
  462. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_plan.json +0 -0
  463. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_policy.json +0 -0
  464. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_profile.json +0 -0
  465. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_proto.json +0 -0
  466. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_r.json +0 -0
  467. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_redteam.json +0 -0
  468. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_route.json +0 -0
  469. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_screen.json +0 -0
  470. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_seroprev.json +0 -0
  471. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_simlab.json +0 -0
  472. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_twincal.json +0 -0
  473. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_uq.json +0 -0
  474. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_v.json +0 -0
  475. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_vcell.json +0 -0
  476. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_verify.json +0 -0
  477. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_writer.json +0 -0
  478. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_writespec.json +0 -0
  479. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/SHA256_LOCK_ws_wv.json +0 -0
  480. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/paper1.yaml +0 -0
  481. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/paper2.yaml +0 -0
  482. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/paper3.yaml +0 -0
  483. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/paper4.yaml +0 -0
  484. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/phase0.yaml +0 -0
  485. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_a.yaml +0 -0
  486. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_acq.yaml +0 -0
  487. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_aldesign.yaml +0 -0
  488. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_alvalidate.yaml +0 -0
  489. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_atlas.yaml +0 -0
  490. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_b.yaml +0 -0
  491. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_ba.yaml +0 -0
  492. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_ba_v33.yaml +0 -0
  493. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_ba_v45.yaml +0 -0
  494. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_bench.yaml +0 -0
  495. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_c.yaml +0 -0
  496. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_cal.yaml +0 -0
  497. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_calib.yaml +0 -0
  498. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_challenge.yaml +0 -0
  499. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_chat.yaml +0 -0
  500. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_cite.yaml +0 -0
  501. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_closedloop.yaml +0 -0
  502. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_continual.yaml +0 -0
  503. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_cosci2.yaml +0 -0
  504. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_crit.yaml +0 -0
  505. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_ct.yaml +0 -0
  506. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_d.yaml +0 -0
  507. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_delivery.yaml +0 -0
  508. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_drift.yaml +0 -0
  509. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_e.yaml +0 -0
  510. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_env.yaml +0 -0
  511. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_ep.yaml +0 -0
  512. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_epitope.yaml +0 -0
  513. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_expr2.yaml +0 -0
  514. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_f.yaml +0 -0
  515. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_frontend.yaml +0 -0
  516. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_g.yaml +0 -0
  517. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_gen.yaml +0 -0
  518. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_genotox.yaml +0 -0
  519. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_graph.yaml +0 -0
  520. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_h.yaml +0 -0
  521. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_hybrid.yaml +0 -0
  522. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_immune.yaml +0 -0
  523. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_immune2.yaml +0 -0
  524. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_ingest.yaml +0 -0
  525. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_innate.yaml +0 -0
  526. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_loop.yaml +0 -0
  527. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_manifest.yaml +0 -0
  528. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_mc.yaml +0 -0
  529. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_mcp.yaml +0 -0
  530. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_mech.yaml +0 -0
  531. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_mon.yaml +0 -0
  532. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_o.yaml +0 -0
  533. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_offtarget.yaml +0 -0
  534. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_openapi.yaml +0 -0
  535. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_oracle.yaml +0 -0
  536. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_orch.yaml +0 -0
  537. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_outcome.yaml +0 -0
  538. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_pareto.yaml +0 -0
  539. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_peg.yaml +0 -0
  540. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_penchat.yaml +0 -0
  541. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_plan.yaml +0 -0
  542. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_policy.yaml +0 -0
  543. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_profile.yaml +0 -0
  544. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_proto.yaml +0 -0
  545. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_r.yaml +0 -0
  546. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_redteam.yaml +0 -0
  547. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_route.yaml +0 -0
  548. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_screen.yaml +0 -0
  549. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_seroprev.yaml +0 -0
  550. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_simlab.yaml +0 -0
  551. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_twincal.yaml +0 -0
  552. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_uq.yaml +0 -0
  553. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_v.yaml +0 -0
  554. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_vcell.yaml +0 -0
  555. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_verify.yaml +0 -0
  556. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_writer.yaml +0 -0
  557. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_writespec.yaml +0 -0
  558. {pen_stack-7.1.8 → pen_stack-7.2.1}/prereg/ws_wv.yaml +0 -0
  559. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/build_capsid_fitness.py +0 -0
  560. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/build_rag_corpus.py +0 -0
  561. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/calibrate_immune_axes.py +0 -0
  562. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/fetch_licensed_sources.py +0 -0
  563. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/offtarget_chromatin_incremental.py +0 -0
  564. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/offtarget_chromatin_matched.py +0 -0
  565. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/offtarget_chromatin_validation.py +0 -0
  566. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/p1_build_atlas.py +0 -0
  567. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/p1_build_durability.py +0 -0
  568. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/p1_build_position_effect.py +0 -0
  569. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/p1_build_writer_eff.py +0 -0
  570. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/p1_export_tracks.py +0 -0
  571. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/p1_safety_concordance.py +0 -0
  572. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/p1_train_safety.py +0 -0
  573. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/p1_validation_report.py +0 -0
  574. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/p2_build_atlas.py +0 -0
  575. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/p3_benchmark_report.py +0 -0
  576. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/p4_genome_scan.py +0 -0
  577. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/p52_build_genotox_oracle.py +0 -0
  578. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/p53_build_epitope_oracle.py +0 -0
  579. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/ws_b_report.py +0 -0
  580. {pen_stack-7.1.8 → pen_stack-7.2.1}/scripts/ws_c_report.py +0 -0
  581. {pen_stack-7.1.8 → pen_stack-7.2.1}/setup.cfg +0 -0
@@ -3,6 +3,102 @@
3
3
  All notable changes to PEN-STACK are documented here. This file follows
4
4
  [Keep a Changelog](https://keepachangelog.com/).
5
5
 
6
+ ## [7.2.1] - 2026-07-02 - PhiC31 integrase: close the O-WS3/O-G2 data gap with verified data + a sealed recall benchmark (honest NEGATIVE)
7
+
8
+ Closes the one genuine open item from v7.2.0 — the PhiC31 integrase data gap — with independently-verified,
9
+ open, citable sequences (no fabrication) and a **sealed recall benchmark whose result is reported verbatim**.
10
+
11
+ ### Added
12
+ - **PhiC31 is now encoded** (`data/curated/integrase_att.yaml`), replacing the v7.2.0 abstain-with-disclosure. All
13
+ data was **independently validated against NCBI/RCSB** (which caught two errors in the completion pack's
14
+ citations, since corrected): att from **PDB 9U2T/9U2S** ("PhiC31 integrase-attB-attP synaptic complex"; the
15
+ canonical Groth-2000 34 bp attB is present in attB53); the documented human pseudo-attP **ψA/ψC/ψD** from
16
+ **GenBank AF333429/AF333430/AF333431** (Thyagarajan 2001, *Mol Cell Biol* 21(12), PMID 11359900,
17
+ DOI `10.1128/MCB.21.12.3926-3934.2001`; chr8/16/15). Corrected DOIs: Groth 2000 `10.1073/pnas.090527097`,
18
+ Chalberg 2006 `10.1016/j.jmb.2005.11.098` (was `...11.108`).
19
+ - **Sealed PhiC31 pseudo-attP recall benchmark** (`benchmarks/offtarget/integrase/`, O-G2): does attP-sequence-
20
+ similarity recover the documented pseudo-attP above length-matched GRCh38 background? **Result — NEGATIVE,
21
+ reported verbatim:** all three sites score 14 mm / 30 bp (53.3% identity), exactly the background **median**
22
+ (60.6% / 77.0% / 82.4% of random windows are as-or-more attP-similar). Sequence identity to attP is **not** a
23
+ validated PhiC31 pseudo-attP predictor — φC31 recognition depends on palindromic architecture (Chalberg 2006) /
24
+ a learned model (IntQuery), not raw identity.
25
+
26
+ ### Changed
27
+ - **Integrase status corrected: `semi_validated` → `mechanism_based_unvalidated` (with a sealed-NEGATIVE benchmark).**
28
+ The v7.2.0 "semi-validated (documented pseudosites as partial ground truth)" implied the sites validated the
29
+ method; the sealed benchmark shows they do not. This is a *stronger, more honest* outcome — a tested negative
30
+ rather than an untested claim. The verified att + documented pseudosites remain grounded facts and are surfaced
31
+ as verified known off-target loci. `nominate_integrase` PhiC31 returns the documented pseudo-attP + the sealed
32
+ benchmark; Bxb1 returns genome-wide similarity candidates carrying the same `similarity_ranking_validated: false`
33
+ caveat. Prereg O-G2 amended + re-SHA-locked; data card + deviations ledger updated; Off-Target page shows the
34
+ documented sites + the benchmark verdict.
35
+
36
+ ## [7.2.0] - 2026-07-01 - PEN-OFFTGT v2: Stage E becomes a genome-wide, per-mechanism off-target FINDER (all 5 writer classes)
37
+
38
+ Stage E was a candidate *scorer* — it ranked off-target sites you supplied. A real off-target tool (CRISPOR /
39
+ CHOPCHOP) takes a guide/target and *finds* the genome-wide off-target set itself. PEN-OFFTGT v2 closes that
40
+ enumeration gap AND applies the **correct off-target mechanism for each writer class**, each carrying a truthful
41
+ per-mechanism validation status (O-WS0–O-WS9 of the plan).
42
+
43
+ ### Per-mechanism paths (O-WS3–O-WS6)
44
+ - **Serine integrase** (`offtarget_integrase.py`, O-WS3): a genome-wide **pseudo-attP** scan — a fixed-sequence
45
+ Cas-OFFinder scan of the attP core window over GRCh38, scored by att-arm similarity. **Bxb1** is fully encoded
46
+ (FlyBase FBto0000359 / Ghosh 2003) and is highly specific. Status **semi-validated**. **PhiC31 is a disclosed
47
+ data gap** (its documented human pseudo-attP set — Chalberg 2006 — could not be verified from an open source in
48
+ this build, so it abstains rather than fabricate). `data/curated/integrase_att.yaml`.
49
+ - **Bridge** (`offtarget_bridge.py`, O-WS4): wraps the existing DMS-scored genome scan (measured Perry-2025
50
+ specificity, held-out ranking AUROC 0.88). Status **hard-locked mechanism-based-unvalidated** — the ranker is
51
+ DMS-validated but **no genome-wide cellular off-target assay exists** for bridge recombinases, so genomic
52
+ recovery is unvalidated (stated in a no-ground-truth disclosure).
53
+ - **CAST** (`offtarget_cast.py` + `data/curated/cast_systems.yaml`, O-WS5) — NEW: guide-directed spacer scan +
54
+ the distinctive **guide-independent untargeted-transposition** background per system (ShCAST/Type V-K high +
55
+ AT-biased; VchCAST/Type I-F >95–99% on-target), all DOI-tagged. Status **mechanism-based-unvalidated**.
56
+ - **PASTE / (ee)PASSIGE** (`offtarget_paste.py`, O-WS6) — NEW: composes the validated nuclease finder (Cas9
57
+ nickase, pegRNA) with the semi-validated integrase pseudo-attP scan (installed att); returns both component sets
58
+ and recommends BOTH a nuclease assay and an integrase assay. Status **composite**.
59
+
60
+ ### Status labels + assay recommender (O-WS7) + disclosures (O-WS8 / gate O-G3)
61
+ - Every nomination carries a per-mechanism status label + the mechanism-appropriate confirm assay; `recommend_assay`
62
+ now covers CAST (transposon insertion-site seq) and PASTE (dual). `docs/cards/offtarget_data.md` documents the
63
+ per-mechanism ground-truth status — **O-G3: every mechanism has either a sealed benchmark (nuclease) or an
64
+ explicit no-ground-truth / data-gap disclosure (integrase-PhiC31, bridge, CAST) — never a fabricated metric.**
65
+ - Disclosed deviations from the plan (no silent substitution): `att_pwm.json` → an att-similarity model in
66
+ `integrase_att.yaml` (a per-position PWM needs aligned pseudosites that do not exist at genome scale);
67
+ `bridge_dms_specificity.parquet` → the existing measured `bridge_offtarget_profile_measured.parquet` is reused;
68
+ `known_pseudosites.parquet` → not created (Bxb1 highly specific; PhiC31 disclosed data gap).
69
+
70
+ ### Nuclease finder (O-WS0–O-WS2)
71
+
72
+ ### Added
73
+ - **Genome-wide enumeration engine** (`pen_stack/wgenome/offtarget_enumerate.py`, O-WS1). Given a guide + enzyme,
74
+ enumerates every genomic site within the mismatch tolerance across GRCh38 via **Cas-OFFinder** (Bae, Park & Kim,
75
+ Bioinformatics 2014, `10.1093/bioinformatics/btu048`), returning coordinates, strand, matched sequence, and
76
+ mismatch count. Supports SpCas9 (NGG), SaCas9 (NNGRRT), and Cas12a (TTTV, 5' PAM). A full scan is heavy, so it
77
+ runs **only on the VM** (`casoffinder:tools` Docker image, `docker/casoffinder.Dockerfile`); the live app
78
+ **replays a committed coordinate cache** for the canonical guides or **abstains honestly** for a novel one
79
+ (never fabricates sites) — the same replay-or-abstain pattern as the heavy structure oracles. The enumerated
80
+ coordinates are facts from the public GRCh38 assembly (no license restriction), so the cache is committed
81
+ (`data/offtarget/enumerated_cache.parquet`, 8 canonical guides, 40,268 sites).
82
+ - **Nuclease off-target FINDER** (`pen_stack/wgenome/offtarget_nuclease.py`, O-WS2): chains enumeration into the
83
+ existing, validated scorer — real CRISOT-Score → mismatch-calibrated risk band → chromatin annotation — so a
84
+ guide returns the genome-wide ranked off-target set *with coordinates*. Scoring is unchanged from v6.10 (still
85
+ validated: CRISOT beats homology on four unbiased assays); v2 adds the enumeration front end.
86
+ - **O-G1 gate PASSED**: enumeration recovers **100%** of EMX1's documented GUIDE-seq off-targets within the ≤5-mm
87
+ tolerance (all 16 validated-active sites, which are all ≤4 mm; the higher-mismatch fixture rows are inactive
88
+ negatives). The on-target is recovered at chr2:72,933,852. `tests/unit/test_ws_offtarget2.py`.
89
+ - **Prereg** `prereg/ws_offtarget2.yaml` (SHA-locked): the mechanism taxonomy, per-enzyme enumeration parameters,
90
+ the truthful per-mechanism status-label rules (validated / semi-validated / mechanism-based-unvalidated), and
91
+ the O-G1/G2/G3 gates.
92
+ - REST: `POST /offtarget` is now a **finder by default** for a nuclease guide with no supplied `candidate_sites`
93
+ (accepts `enzyme`, `max_mismatch`); `GET /offtarget/enumerated` lists the cached guides. The web **Off-Target**
94
+ page is rebuilt as a finder (guide in → genome-wide ranked off-targets with coordinates), with the scorer→finder
95
+ explanation and the VM/cache architecture stated.
96
+
97
+ ### Unchanged / backward compatible
98
+ - Supplying `candidate_sites` keeps the v6.10 score-my-candidates path. The integrase (pseudo-attB sequence scan),
99
+ bridge (Perry-DMS), chromatin annotation, and validation-assay recommender are unchanged. Nomination remains a
100
+ candidate, never a clearance.
101
+
6
102
  ## [7.1.8] - 2026-06-30 - Writer immunogenicity moves to the Writer Atlas; SpCas9 removed from the writer options
7
103
 
8
104
  ### Changed
@@ -1,8 +1,8 @@
1
1
  cff-version: 1.2.0
2
2
  message: "If you use PEN-STACK, please cite it as below."
3
3
  title: "PEN-STACK: open infrastructure for genome writing"
4
- version: 7.1.8
5
- date-released: 2026-06-30
4
+ version: 7.2.1
5
+ date-released: 2026-07-02
6
6
  authors:
7
7
  - family-names: "Mahaboob Ali"
8
8
  given-names: "Anees Ahmed"
@@ -5,6 +5,7 @@ include README.md LICENSE CHANGELOG.md CITATION.cff pyproject.toml
5
5
  recursive-include configs *.yaml *.yml *.txt.example *.fasta
6
6
  recursive-include prereg *.yaml *.json
7
7
  recursive-include data/curated *
8
+ recursive-include data/offtarget *.parquet
8
9
  recursive-include benchmarks *.yaml *.md SHA256SUMS
9
10
  recursive-include bench *.py
10
11
  recursive-include docs *.md
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pen-stack
3
- Version: 7.1.8
3
+ Version: 7.2.1
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
@@ -0,0 +1,23 @@
1
+ # PhiC31 pseudo-attP recall benchmark (O-G2) — SEALED
2
+
3
+ **Question:** does attP-sequence-similarity recover the documented human pseudo-attP above random genomic background?
4
+
5
+ **Data (all independently verified against NCBI/RCSB):**
6
+ - **Positives** — `phic31_pseudo.fasta`: human pseudo-attP ψA/ψC/ψD, GenBank **AF333429/AF333430/AF333431**
7
+ (Thyagarajan 2001, *Mol Cell Biol* 21(12), PMID 11359900, DOI `10.1128/MCB.21.12.3926-3934.2001`; chr8/16/15).
8
+ - **Query** — the phage φC31 attP central 30 bp from **PDB 9U2T (attP60)**, the "PhiC31 integrase-attB-attP synaptic
9
+ complex" structure; the canonical Groth-2000 34 bp attB is present in **PDB 9U2S (attB53)** (Groth 2000, PNAS,
10
+ DOI `10.1073/pnas.090527097`).
11
+ - **Background** — 1000 GC/N-filtered, length-matched random GRCh38 windows per positive.
12
+
13
+ **Result (`phic31_recall_metrics.json`) — NEGATIVE, reported verbatim:** every documented pseudosite scores 14 mm /
14
+ 30 bp (53.3% identity), which is exactly the **background median** (14 mm); 60.6% / 77.0% / 82.4% of random windows
15
+ are as-or-more attP-similar. Sequence identity to attP does **not** recover the documented pseudo-attP above
16
+ background — consistent with the field (φC31 pseudosite recognition depends on palindromic architecture, Chalberg
17
+ 2006 DOI `10.1016/j.jmb.2005.11.098`, / a learned model, IntQuery). The integrase genome-wide pseudo-attP
18
+ **similarity ranking is therefore unvalidated**; the verified att and documented pseudosites remain grounded facts.
19
+
20
+ **Honest limits:** N=3 (the open GenBank subset; the full Chalberg 19-site set is paywalled); tests
21
+ sequence-identity only (no palindrome/learned model); deterministic (seed 20260701), pysam over GRCh38.
22
+
23
+ Run: `docker run --rm --entrypoint bash -v <genomes>:/genome -v $PWD:/work -w /work penstack:phase1.5 -lc 'python harness.py'`
@@ -0,0 +1,4 @@
1
+ 701efce23441ba6ec3865060aa3a749d7165d013628f3ed8010737861b306557 README.md
2
+ 888dd4ba69bbe1eccd323797adc89b242b1c8ec6208a5f9f41df839d641d10e6 harness.py
3
+ fe23827ff34204bc2cd1f903fcd3e32b120c4521787342e6590824249573a4d4 phic31_pseudo.fasta
4
+ 2a0f22d700f0db0bafd1c98b8b8893f14e86ae9574ff789042bd3ad1c7f6a3c0 phic31_recall_metrics.json
@@ -0,0 +1,59 @@
1
+ # CRISPR-associated transposase (CAST) systems — per-system off-target properties (PEN-OFFTGT v2, O-WS5).
2
+ #
3
+ # CAST off-target has TWO distinct modes, and the balance differs by system type:
4
+ # 1. guide-directed — integration at genomic sites matching the crRNA spacer (a sequence-match scan, like a
5
+ # nuclease off-target, but the transposon inserts ~49-66 bp downstream of the protospacer).
6
+ # 2. guide-INDEPENDENT untargeted transposition — the Tn7-like transposase machinery (TnsB/TnsC/TniQ) inserting
7
+ # WITHOUT the CRISPR effector or the guide. This is the DISTINCTIVE, dominant off-target mode
8
+ # for Type V-K systems (ShCAST) and is largely absent in Type I-F systems (VchCAST).
9
+ #
10
+ # All values are DOCUMENTED facts from the primary literature (DOIs below), reported as a qualitative tier plus the
11
+ # published on-target fidelity where a number is stated. This is NOT a genome-wide cellular off-target assay
12
+ # (none exists for CAST at genome scale) -> status is mechanism_based_unvalidated; the confirming assay is
13
+ # transposon insertion-site sequencing.
14
+
15
+ version: "1.0"
16
+
17
+ systems:
18
+ ShCAST:
19
+ full_name: "Scytonema hofmanni CAST"
20
+ cast_type: "V-K"
21
+ effector: "Cas12k"
22
+ untargeted_transposition: high # guide/Cas12k-INDEPENDENT, AT-biased (the dominant off-target mode)
23
+ guide_independent: true
24
+ at_biased_untargeted: true
25
+ on_target_fidelity_note: "up to ~80% integration in E. coli without selection, but LOW fidelity: prone to
26
+ extensive RNA-independent (guide-independent) transposition via TnsB/TnsC/TniQ; improved vectors that
27
+ suppress the RNA-independent pathway raise specificity up to 98.1% (Type V-K)."
28
+ dois:
29
+ - "10.1126/science.aax9181" # Strecker et al. 2019, ShCAST (Science) — RNA-guided DNA insertion with CAST
30
+ - "10.1126/science.adj8543" # Type V-K target-site selection + untargeted mechanism (Science 2024)
31
+ VchCAST:
32
+ full_name: "Vibrio cholerae CAST (Tn6677 / INTEGRATE)"
33
+ cast_type: "I-F"
34
+ effector: "Cascade (Cas6-Cas7-Cas8/Cas5) + TniQ"
35
+ untargeted_transposition: low # high fidelity; guide-independent transposition largely absent
36
+ guide_independent: false
37
+ at_biased_untargeted: false
38
+ on_target_fidelity_note: "remarkable fidelity — the majority of crRNAs direct >95% on-target integration and
39
+ many exceed 99%; up to ~100% integration efficiency of cargo up to ~10 kb in bacteria."
40
+ dois:
41
+ - "10.1038/s41586-019-1323-z" # Klompe et al. 2019, VchCAST / Tn6677 (Nature)
42
+ - "10.1038/s41587-020-00745-y" # Vo et al. 2021, INTEGRATE high-efficiency multiplexed (Nat Biotechnol)
43
+ evoCAST:
44
+ full_name: "evolved Scytonema hofmanni CAST (PACE-evolved)"
45
+ cast_type: "V-K"
46
+ effector: "Cas12k (evolved)"
47
+ untargeted_transposition: moderate # directed evolution improved specificity over WT ShCAST
48
+ guide_independent: true
49
+ at_biased_untargeted: true
50
+ on_target_fidelity_note: "evolved Type V-K CAST with substantially improved on-target integration in human
51
+ cells; guide-independent transposition is reduced relative to WT ShCAST but not eliminated."
52
+ dois:
53
+ - "10.1126/science.adr8492" # Tou et al. 2025, evoCAST (Science) — evolved CAST for human-cell insertion
54
+ - "10.1038/s41587-023-01748-1" # Lampe et al. 2024, targeted integration in human cells without DSBs (Nat Biotechnol)
55
+
56
+ # scope: human-cell CAST is emerging (evoCAST 2025); the untargeted-transposition rates above are characterised in
57
+ # bacteria / biochemically. No genome-wide unbiased CELLULAR off-target assay exists for human-cell CAST -> the
58
+ # genomic predictions are mechanism-based, unvalidated; confirm with transposon insertion-site sequencing.
59
+ confirm_assay: "transposon insertion-site sequencing (e.g. Tn-seq / integration-site amplicon sequencing)"
@@ -0,0 +1,66 @@
1
+ # Serine-integrase attachment sites for the genome-wide pseudo-att off-target scan (PEN-OFFTGT v2, O-WS3).
2
+ #
3
+ # A serine integrase recombines a donor attB with a genomic pseudo-attP resembling the phage attP. The off-target
4
+ # scan enumerates genomic sites similar to the attP core region (a fixed-sequence Cas-OFFinder scan over GRCh38,
5
+ # tolerating mismatches), then scores each by att-arm similarity. Confirming assay: Cryptic-seq / HIDE-seq.
6
+ #
7
+ # HONEST STATUS (v7.2.1): the att sequences and the documented human pseudo-attP are VERIFIED grounded facts, but a
8
+ # SEALED recall benchmark on the best-documented pseudosites (PhiC31 psiA/psiC/psiD) is NEGATIVE — att-sequence-
9
+ # similarity does NOT recover them above random background (see PhiC31.recall_benchmark below). So the genome-wide
10
+ # pseudo-attP SIMILARITY RANKING is a mechanism-based scan that is NOT validated as a predictor; it is honestly
11
+ # labelled as such, not "semi-validated." The documented pseudosites are surfaced as verified known-off-target loci.
12
+ #
13
+ # DEVIATION (disclosed): the prereg named `att_pwm.json`. A position-weight MATRIX requires many aligned pseudosite
14
+ # sequences to estimate per-position tolerance; that alignment does not exist at genome scale for these integrases.
15
+ # So the scan uses att-arm SIMILARITY (mismatch count to the documented att, core-anchored) rather than a fitted
16
+ # PWM — a mechanism-based similarity model, honestly labelled, not a fabricated per-position matrix.
17
+
18
+ version: "1.0"
19
+
20
+ integrases:
21
+ Bxb1:
22
+ origin: "phage Bxb1 (Mycobacterium)"
23
+ attB: "TCGGCCGGCTTGTCGACGACGGCGGTCTCCGTCGTCAGGATCATCCGGGC"
24
+ attP: "GTCGTGGTTTGTCTGGTCAACCACCGCGGTCTCAGTGGTGTACGGTACAAACCCCGAC"
25
+ core: "GCGGTCTC"
26
+ central_dinucleotide: "GT"
27
+ # 34-nt attP window centred on the core — the fixed sequence scanned genome-wide for pseudo-attP
28
+ scan_window: "CTGGTCAACCACCGCGGTCTCAGTGGTGTACGGT"
29
+ scan_max_mismatch: 8
30
+ specificity_note: "Bxb1 is highly specific — very few genomic pseudo-attP in human cells (a reason it is the
31
+ integrase of choice for PASTE/PASSIGE). The scan therefore returns few high-similarity candidates."
32
+ source: "FlyBase FBto0000359/358; Ghosh, Kim & Hatfull, Mol Cell 2003"
33
+ doi: "10.1016/S1097-2765(03)00444-1"
34
+
35
+ # PhiC31 — now ENCODED with independently-verified sequences (v7.2.1, closes the O-WS3 data gap). att from the
36
+ # phiC31 integrase-attB-attP synaptic-complex structure (PDB 9U2T attP60 / 9U2S attB53; the canonical Groth-2000
37
+ # 34 bp attB is present in attB53); documented human pseudo-attP from Thyagarajan 2001 (GenBank AF333429/30/31).
38
+ PhiC31:
39
+ origin: "phage phiC31 (Streptomyces)"
40
+ attB: "GTGCCAGGGCGTGCCCTTGGGCTCCCCGGGCGCG" # canonical 34 bp minimal attB (verified inside PDB 9U2S attB53)
41
+ attP: "CGGGAGTAGTGCCCCAACTGGGGTAACCTTTGAGTTCTCTCAGTTGGGGGCGTAGGGTCG" # PDB 9U2T attP60 (60 bp)
42
+ core: "TTG"
43
+ central_dinucleotide: "TT"
44
+ scan_window: "AACTGGGGTAACCTTTGAGTTCTCTCAGTT" # attP central 30 bp (localises to the psiA recombination core)
45
+ scan_max_mismatch: 8
46
+ source: "Groth et al., PNAS 2000; PDB 9U2T/9U2S (phiC31 integrase-attB-attP synaptic complex)"
47
+ doi: "10.1073/pnas.090527097"
48
+ pdb: ["9U2T", "9U2S"]
49
+ # documented human pseudo-attP positive set (verified GenBank; the integration loci)
50
+ pseudo_attP_positive_set:
51
+ - {name: psiA, genbank: AF333429, chrom: chr8}
52
+ - {name: psiC, genbank: AF333430, chrom: chr16}
53
+ - {name: psiD, genbank: AF333431, chrom: chr15}
54
+ positive_set_source: "Thyagarajan et al., Mol Cell Biol 21(12), 2001"
55
+ positive_set_doi: "10.1128/MCB.21.12.3926-3934.2001"
56
+ # SEALED recall benchmark (O-G2) — result reported VERBATIM: benchmarks/offtarget/integrase/phic31_recall_metrics.json
57
+ recall_benchmark:
58
+ recovered_above_background: false
59
+ verdict: "NEGATIVE — attP-sequence-similarity does NOT recover the documented pseudo-attP above random
60
+ background (all 3 sites at 14 mm / 30 bp = the background median; 60.6/77.0/82.4% of background as-or-more
61
+ similar). Sequence identity alone is not a validated PhiC31 pseudo-attP predictor; recognition depends on
62
+ palindromic architecture (Chalberg 2006, 10.1016/j.jmb.2005.11.098) / a learned model (IntQuery)."
63
+ metrics: "benchmarks/offtarget/integrase/phic31_recall_metrics.json"
64
+ specificity_note: "PhiC31 is a PROMISCUOUS serine integrase with documented human pseudo-attP (unlike Bxb1).
65
+ The sealed recall benchmark (above) is NEGATIVE: the att-similarity scan does not distinguish the documented
66
+ pseudosites from background, so the genome-wide similarity RANKING is unvalidated (honest negative)."
@@ -90,3 +90,28 @@ candidate ENUMERATION needs the on-VM Cas-OFFinder/genome scan; this benchmark c
90
90
  candidates. Bridge/integrase off-target is data-thin: there is **no published genome-wide unbiased off-target assay
91
91
  or predictor for bridge recombinases** (verified), and the large-serine-integrase assays (Cryptic-seq/HIDE-seq) and
92
92
  predictor (IntQuery) are recent single-company preprints with no public weights.
93
+
94
+ ---
95
+
96
+ ## v7.2 (PEN-OFFTGT v2) — per-mechanism ground-truth status (O-WS8 / gate O-G3)
97
+
98
+ Stage E is now a genome-wide **finder** (Cas-OFFinder over GRCh38; heavy scan on the VM, cached coordinates
99
+ replayed by the app). Each writer class applies the correct off-target mechanism and carries a **truthful
100
+ validation status** — a sealed benchmark where ground truth exists, an explicit **no-genome-wide-ground-truth
101
+ disclosure** where it does not. No mechanism is ever presented as validated where the data cannot support it.
102
+
103
+ | Writer class | Mechanism | Enumeration | Status | Ground truth / benchmark |
104
+ |---|---|---|---|---|
105
+ | **Nuclease** (SpCas9/SaCas9/Cas12a) | mismatch-tolerant cleavage at protospacer+PAM | Cas-OFFinder genome scan | ✅ **validated** | 4-assay Off-Target-Bench (above) + **O-G1**: enumeration recovers 100% of EMX1's documented GUIDE-seq off-targets ≤5 mm |
106
+ | **Serine integrase** (Bxb1, PhiC31) | recombination at genomic pseudo-attP | fixed-sequence att-window scan | 🔵 **mechanism-based, sealed-NEGATIVE benchmark** (v7.2.1) | att verified (Bxb1: FlyBase FBto0000359 / Ghosh 2003 `10.1016/S1097-2765(03)00444-1`; PhiC31: **PDB 9U2T/9U2S** + Groth 2000 `10.1073/pnas.090527097`); the PhiC31 human pseudo-attP set is verified (Thyagarajan 2001, **GenBank AF333429/30/31**, `10.1128/MCB.21.12.3926-3934.2001`; chr8/16/15). The v7.2.1 **SEALED recall benchmark** (`benchmarks/offtarget/integrase/`) is **NEGATIVE**: att-sequence-similarity does NOT recover the documented pseudo-attP above random background (all three at 14 mm / 30 bp = the background median). The genome-wide similarity RANKING is therefore **unvalidated** — φC31 recognition needs palindromic architecture (Chalberg 2006, `10.1016/j.jmb.2005.11.098`) / a learned model (IntQuery), not raw identity. Documented pseudosites surfaced as verified known loci; the negative is reported verbatim (a stronger, more honest O-G2 than an untested "semi-validated"). |
107
+ | **Bridge** (IS110/IS621) | recombination at bridge-RNA target-loop matches | core-seeded genome scan (pysam) | 🔵 **mechanism-based, unvalidated** | **NO genome-wide unbiased CELLULAR off-target assay exists** (technology ~2024). The mismatch-tolerance RANKER is validated on the measured Perry-2025 in-vitro DMS specificity (held-out ranking AUROC 0.88), but genomic recovery is unvalidated. |
108
+ | **CAST** (ShCAST V-K / VchCAST I-F) | guide-directed integration + guide-independent untargeted transposition | spacer scan + per-system untargeted background | 🔵 **mechanism-based, unvalidated** | untargeted-transposition rates documented per system (`data/curated/cast_systems.yaml`): ShCAST high/AT-biased (Strecker 2019 `10.1126/science.aax9181`; Science 2024 `10.1126/science.adj8543`), VchCAST >95–99% on-target (Klompe 2019 `10.1038/s41586-019-1323-z`; Vo 2021 `10.1038/s41587-020-00745-y`). No genome-wide cellular assay for human-cell CAST. |
109
+ | **PASTE / (ee)PASSIGE** | Cas9-nickase off-target + integrase pseudo-attP | compose(nuclease, integrase) | composite (✅ nickase + 🟡 integrase) | inherits the nuclease benchmark for the nickase and the integrase status for the installed att; recommends BOTH a nuclease assay AND an integrase assay |
110
+
111
+ **O-G3 satisfied:** every mechanism has either a sealed benchmark (nuclease) or an explicit no-ground-truth /
112
+ data-gap disclosure (integrase-PhiC31, bridge, CAST) — never a fabricated metric. The bridge and CAST paths are
113
+ **hard-locked** to 🔵 unvalidated in code.
114
+
115
+ **Honest limits (v7.2):** enumeration recall depends on the mismatch tolerance (≤5 mm nuclease, ≤8 mm integrase
116
+ att window); very divergent off-targets can be missed (a limitation shared with CRISPOR). DNA/RNA bulges are not
117
+ enumerated in v2.0 (substitutions only). The engine nominates and ranks; it does not clear a design.
@@ -1,2 +1,2 @@
1
1
  """PEN-STACK v3.0 - open infrastructure for genome writing."""
2
- __version__ = "7.1.8"
2
+ __version__ = "7.2.1"
@@ -156,14 +156,17 @@ def immune_profile(design: dict) -> dict:
156
156
 
157
157
  @mcp.tool()
158
158
  def offtarget_scan(writer_family: str, guide: str | None = None, candidate_sites: list | None = None,
159
- sequence: str | None = None, assay: str = "guideseq") -> dict:
160
- """v6.10 PEN-OFFTGT cross-family off-target NOMINATION (NOT a clearance). Ranks candidate sites with a
161
- real-data mismatch-calibrated risk band + the real CRISOT learned score (nuclease), a pseudo-attB scan
162
- (integrase), or the Perry-DMS pseudosite engine (bridge); ships the validation assay that would confirm
163
- each candidate. Abstains without inputs; never fabricates sites."""
159
+ sequence: str | None = None, assay: str = "guideseq", enzyme: str | None = None,
160
+ max_mismatch: int = 5) -> dict:
161
+ """PEN-OFFTGT v2 genome-wide, per-mechanism off-target FINDER (NOT a clearance). For a nuclease guide it
162
+ enumerates the genome-wide off-target set over GRCh38 (Cas-OFFinder, cached) + real CRISOT + risk + chromatin
163
+ (validated); serine integrase = genome-wide pseudo-attP scan (semi-validated); bridge = DMS-scored scan
164
+ (mechanism-based, unvalidated); CAST = guide-directed + untargeted-transposition background (unvalidated);
165
+ PASTE = nuclease + integrase composition. Each carries a truthful status label + the confirming assay.
166
+ Abstains for a novel input (VM scan); never fabricates sites."""
164
167
  from pen_stack.wgenome.offtarget_predict import nominate_offtargets
165
168
  return nominate_offtargets(writer_family, guide=guide, candidate_sites=candidate_sites,
166
- sequence=sequence, assay=assay)
169
+ sequence=sequence, assay=assay, enzyme=enzyme, max_mismatch=max_mismatch)
167
170
 
168
171
 
169
172
  @mcp.tool()
@@ -50,11 +50,13 @@ _TOOLS = [
50
50
  "efficiency w/ conformal interval + auto-designed guide/att (v6.8 PEN-WRITER)",
51
51
  "input": "write request (write-type, cargo, cell type, optional target/donor seq)", "output": "WriterRanking",
52
52
  "entrypoint": "pen_stack.atlas.writer_recommend.recommend_writers", "fabricates": False},
53
- {"name": "nominate_offtargets", "summary": "cross-writer-family off-target NOMINATION: rank candidate sites "
54
- "with a real-data mismatch-calibrated risk band + the real CRISOT learned score (nuclease), pseudo-attB "
55
- "scan (integrase), Perry-DMS pseudosite engine (bridge); nomination is NOT a clearance (v6.10 PEN-OFFTGT)",
56
- "input": "writer family + guide/candidate sites (nuclease) or locus sequence (integrase)",
57
- "output": "ranked off-target candidates + calibrated risk + recommended validation assay",
53
+ {"name": "nominate_offtargets", "summary": "genome-wide, per-mechanism off-target FINDER (v7.2 PEN-OFFTGT v2): "
54
+ "enumerates the off-target set over GRCh38 (Cas-OFFinder) and applies the correct mechanism per writer class "
55
+ "- nuclease cleavage (validated: CRISOT + risk + chromatin), integrase pseudo-attP (semi-validated), bridge "
56
+ "target-specificity (unvalidated), CAST guide + untargeted transposition (unvalidated), PASTE composition - "
57
+ "each with a truthful status label; nomination is NOT a clearance",
58
+ "input": "writer family + guide/target (enumerated genome-wide) or supplied candidate sites",
59
+ "output": "genome-wide ranked off-target candidates + per-mechanism status + calibrated risk + validation assay",
58
60
  "entrypoint": "pen_stack.wgenome.offtarget_predict.nominate_offtargets", "fabricates": False},
59
61
  {"name": "recommend_delivery", "summary": "cross-modality delivery recommender: rank vehicles by cargo-form + "
60
62
  "safety<->efficacy + a grounded serotype->tissue tropism prior (approved therapies) + the learned FLIP-AAV "
@@ -374,15 +374,19 @@ def immune_endpoint(design: dict):
374
374
 
375
375
  @app.post("/offtarget", tags=["v6.10 off-target"])
376
376
  def offtarget_endpoint(req: dict):
377
- """v6.10 PEN-OFFTGT cross-family off-target NOMINATION (NOT a clearance). Body:
378
- {writer_family, guide?, candidate_sites?, sequence?, accessibility?, assay?}. Returns ranked candidate
379
- off-targets with a real-data mismatch-calibrated risk band + the recommended validation assay; abstains
380
- without inputs and never fabricates sites."""
377
+ """PEN-OFFTGT cross-family off-target NOMINATION (NOT a clearance). Body:
378
+ {writer_family, guide?, enzyme?, max_mismatch?, candidate_sites?, sequence?, accessibility?, assay?}.
379
+
380
+ v7.2 (finder): for a nuclease guide with NO ``candidate_sites``, enumerates the genome-wide off-target set
381
+ over GRCh38 (Cas-OFFinder, replayed from the committed cache) and ranks it by the real CRISOT-Score +
382
+ mismatch-calibrated risk + chromatin annotation - the CRISPOR-like default. Supplying ``candidate_sites``
383
+ keeps the v6.10 score-my-candidates path. Abstains (never fabricates) for a novel guide with no VM scan."""
381
384
  from pen_stack.wgenome.offtarget_predict import nominate_offtargets
382
385
  return nominate_offtargets(
383
386
  req.get("writer_family", ""), guide=req.get("guide"), candidate_sites=req.get("candidate_sites"),
384
387
  sequence=req.get("sequence"), accessibility=req.get("accessibility"),
385
- target_core=req.get("target_core"), assay=req.get("assay", "guideseq"))
388
+ target_core=req.get("target_core"), assay=req.get("assay", "guideseq"),
389
+ enzyme=req.get("enzyme"), max_mismatch=int(req.get("max_mismatch", 5)))
386
390
 
387
391
 
388
392
  @app.get("/offtarget/assay", tags=["v6.10 off-target"])
@@ -392,6 +396,20 @@ def offtarget_assay_endpoint(writer_family: str):
392
396
  return recommend_assay(writer_family)
393
397
 
394
398
 
399
+ @app.get("/offtarget/enumerated", tags=["v6.10 off-target"])
400
+ def offtarget_enumerated_endpoint():
401
+ """v7.2: the guides whose genome-wide off-target enumeration is CACHED (so the finder works here without a VM
402
+ scan). A novel guide abstains (its scan runs on the VM). Enumerated coordinates are public-genome facts."""
403
+ from pen_stack.wgenome.offtarget_data import CANONICAL_GUIDES
404
+ from pen_stack.wgenome.offtarget_enumerate import enumerated_guides
405
+ cached = enumerated_guides()
406
+ seq2name = {v: k for k, v in CANONICAL_GUIDES.items()}
407
+ return {"enzyme": "SpCas9",
408
+ "guides": [{"guide": g, "name": seq2name.get(g, g), "enzyme": e} for e, g in cached],
409
+ "note": ("genome-wide enumeration for these guides is replayed from the committed GRCh38 Cas-OFFinder "
410
+ "cache; a novel guide requires an on-VM scan (the finder abstains rather than fabricate).")}
411
+
412
+
395
413
  @app.get("/campaign", tags=["v7.0 closed-loop"])
396
414
  def campaign_endpoint():
397
415
  """v7.0 Stage J: the validation-campaign engine. Returns the expression-validation campaign: the next batch of
@@ -29,7 +29,7 @@ def recommend_assay(writer_family: str) -> dict:
29
29
  "in the target cell type (GUIDE-seq), chromatin masks a fraction of in vitro sites",
30
30
  "available": True,
31
31
  "note": "nomination ranks CANDIDATES; an empirical assay is required for clearance."}
32
- if "integrase" in fam or "paste" in fam or "passige" in fam or "bxb1" in fam or "phic31" in fam:
32
+ if ("integrase" in fam or "bxb1" in fam or "phic31" in fam) and "paste" not in fam and "passige" not in fam:
33
33
  return {"family": writer_family, "writer_class": "large serine integrase",
34
34
  "recommended": [{"assay": "Cryptic-seq / HIDE-seq", "setting": "unbiased LSI off-target discovery",
35
35
  "doi": "10.1101/2024.08.23.609471",
@@ -39,6 +39,29 @@ def recommend_assay(writer_family: str) -> dict:
39
39
  "quantitative prediction (IntQuery) is paper-only (no public weights)",
40
40
  "available": True,
41
41
  "note": "LSI off-target assays are recent preprints; coverage is single-company / largely Bxb1."}
42
+ if "paste" in fam or "passige" in fam:
43
+ return {"family": writer_family, "writer_class": "prime-editing integrase (PASTE / PASSIGE)",
44
+ "recommended": [
45
+ {"assay": "GUIDE-seq / CHANGE-seq", "setting": "nuclease (nickase) off-target", "doi": "10.1038/nbt.3117",
46
+ "use": "confirm the Cas9-nickase off-targets of the pegRNA spacer"},
47
+ {"assay": "Cryptic-seq / HIDE-seq", "setting": "integrase off-target", "doi": "10.1101/2024.08.23.609471",
48
+ "use": "confirm the integrase pseudo-attP sites of the installed att"}],
49
+ "strategy": "PASTE off-target is composite — run BOTH a nuclease assay (for the nickase) AND an "
50
+ "integrase assay (for the installed att); the two components are independent.",
51
+ "available": True,
52
+ "note": "two independent off-target mechanisms; neither assay alone clears a PASTE design."}
53
+ if "cast" in fam or "cas12k" in fam or "shcast" in fam or "vchcast" in fam or "evocast" in fam:
54
+ return {"family": writer_family, "writer_class": "CRISPR-associated transposase (CAST)",
55
+ "recommended": [{"assay": "transposon insertion-site sequencing", "setting": "unbiased integration mapping",
56
+ "doi": "10.1126/science.aax9181",
57
+ "use": "map genome-wide integration sites, including guide-INDEPENDENT untargeted "
58
+ "transposition (the dominant off-target mode for Type V-K, e.g. ShCAST)"}],
59
+ "strategy": "sequence integration sites to capture BOTH guide-directed off-targets and the "
60
+ "guide-independent untargeted-transposition background (Type V-K high; Type I-F low)",
61
+ "available": True,
62
+ "note": "KNOWN GAP: no genome-wide unbiased CELLULAR off-target assay is standardised for human-cell "
63
+ "CAST; untargeted-transposition rates are characterised in bacteria/biochemically. "
64
+ "Mechanism-based, unvalidated."}
42
65
  if "bridge" in fam or "is110" in fam or "is621" in fam or "seek" in fam or "iscro4" in fam:
43
66
  return {"family": writer_family, "writer_class": "bridge recombinase (IS110/IS621 RNA-guided)",
44
67
  "recommended": [{"assay": "targeted amplicon / capture sequencing at nominated pseudosites",
@@ -0,0 +1,47 @@
1
+ """Bridge-recombinase (IS110 / IS621) off-target path (PEN-OFFTGT v2, O-WS4).
2
+
3
+ Bridge recombinases are RNA-guided: the bridge RNA's target-binding loop base-pairs with a bipartite ~14-nt
4
+ genomic target (central CT). Off-target = genomic sites matching that target with tolerated mismatches. This
5
+ wraps the existing genome-wide scanner (`pen_stack.bridge.offtarget`), which seeds on the central core and scores
6
+ each pseudosite by the **measured Perry-2025 DMS specificity landscape** (which target mismatches the recombinase
7
+ tolerates) — a held-out ranking AUROC of 0.88 on that in-vitro DMS data.
8
+
9
+ **Status: mechanism_based_unvalidated (hard-locked).** Crucially, the DMS ranker being validated on *in-vitro
10
+ specificity* does NOT make the *genomic off-target predictions* validated: there is **no published genome-wide
11
+ unbiased CELLULAR off-target assay** for bridge recombinases (the technology is ~2024), so the genomic pseudosite
12
+ calls cannot be validated. The honest report is: a mechanism-based scan with a DMS-grounded mismatch-tolerance
13
+ model, labelled unvalidated, with the no-genome-wide-assay disclosure. Confirm by targeted amplicon /
14
+ integration-site sequencing. Never claims validation.
15
+ """
16
+ from __future__ import annotations
17
+
18
+ _STATUS = "mechanism_based_unvalidated"
19
+ _DISCLOSURE = (
20
+ "NO published genome-wide unbiased CELLULAR off-target assay exists for bridge recombinases (IS110/IS621; the "
21
+ "technology is ~2024). The pseudosite RANKER is validated on the measured Perry-2025 in-vitro DMS specificity "
22
+ "landscape (held-out ranking AUROC 0.88), but genomic recovery is NOT validated. Treat nominations as "
23
+ "high-uncertainty, mechanism-based candidates — never a clearance."
24
+ )
25
+
26
+
27
+ def nominate_bridge(target_core: str | None = None, writer_family: str = "bridge_IS110",
28
+ fasta=None, chroms: list[str] | None = None, top: int = 20) -> dict:
29
+ """Genome-wide bridge off-target scan for a bridge-RNA target core, via the DMS-scored engine. Returns the
30
+ ranked pseudosites when a genome + target core are supplied (VM), else reports the engine is ready and how to
31
+ run the scan. Always carries the hard-locked unvalidated status + the no-genome-wide-assay disclosure."""
32
+ from pen_stack.bridge.offtarget import predict_offtargets
33
+ fam = "seek_IS1111" if ("seek" in (writer_family or "").lower() or "is1111" in (writer_family or "").lower()) \
34
+ else "bridge_IS110"
35
+ res = predict_offtargets(fam, target_core=target_core, fasta=fasta, chroms=chroms, top=top)
36
+ return {"family": "bridge", "writer_family": fam, "status": _STATUS,
37
+ "ranker": "Perry-2025 DMS specificity landscape (measured; held-out ranking AUROC 0.88)",
38
+ "no_ground_truth_disclosure": _DISCLOSURE,
39
+ "confirm_assay": "targeted amplicon / integration-site sequencing at nominated pseudosites",
40
+ "available": res.get("status") == "scanned",
41
+ "abstain": not (res.get("status") == "scanned"),
42
+ "engine": res,
43
+ "method": ("seed on the central core (CT), verify the bipartite ~14-nt target with tolerated "
44
+ "mismatches, score by the measured DMS specificity (position + substitution identity)"),
45
+ "honesty": ("mechanism-based CANDIDATES with a DMS-grounded mismatch-tolerance model; NOT a validated "
46
+ "genome-wide predictor (no cellular assay exists) and NOT a clearance."),
47
+ "nomination_is_not_clearance": True}