pen-stack 6.9.2__tar.gz → 6.10.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 (499) hide show
  1. {pen_stack-6.9.2 → pen_stack-6.10.1}/CHANGELOG.md +70 -0
  2. {pen_stack-6.9.2 → pen_stack-6.10.1}/CITATION.cff +1 -1
  3. {pen_stack-6.9.2 → pen_stack-6.10.1}/PKG-INFO +27 -2
  4. {pen_stack-6.9.2 → pen_stack-6.10.1}/README.md +26 -1
  5. pen_stack-6.10.1/benchmarks/offtarget/SHA256SUMS +4 -0
  6. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/oracles/scope_cards.yaml +17 -0
  7. pen_stack-6.10.1/docs/DEVIATIONS_AND_DISCLOSURES.md +57 -0
  8. pen_stack-6.10.1/docs/cards/offtarget_data.md +69 -0
  9. pen_stack-6.10.1/docs/offtarget.md +52 -0
  10. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/__init__.py +1 -1
  11. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/agent/cite.py +13 -0
  12. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/agent/mcp_server.py +12 -0
  13. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/api/manifest.py +6 -0
  14. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/planner/immune_mhc2.py +13 -9
  15. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/server/api.py +20 -0
  16. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/twin/position_effect.py +2 -1
  17. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/immune_calibration.py +4 -3
  18. pen_stack-6.10.1/pen_stack/wgenome/offtarget_assay.py +55 -0
  19. pen_stack-6.10.1/pen_stack/wgenome/offtarget_data.py +110 -0
  20. pen_stack-6.10.1/pen_stack/wgenome/offtarget_predict.py +233 -0
  21. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack.egg-info/PKG-INFO +27 -2
  22. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack.egg-info/SOURCES.txt +9 -0
  23. pen_stack-6.10.1/prereg/SHA256_LOCK_ws_offtarget.json +8 -0
  24. pen_stack-6.10.1/prereg/ws_offtarget.yaml +42 -0
  25. {pen_stack-6.9.2 → pen_stack-6.10.1}/pyproject.toml +1 -1
  26. {pen_stack-6.9.2 → pen_stack-6.10.1}/LICENSE +0 -0
  27. {pen_stack-6.9.2 → pen_stack-6.10.1}/MANIFEST.in +0 -0
  28. {pen_stack-6.9.2 → pen_stack-6.10.1}/bench/run.py +0 -0
  29. {pen_stack-6.9.2 → pen_stack-6.10.1}/benchmarks/genome_writing_bench/LEADERBOARD.md +0 -0
  30. {pen_stack-6.9.2 → pen_stack-6.10.1}/benchmarks/genome_writing_bench/README.md +0 -0
  31. {pen_stack-6.9.2 → pen_stack-6.10.1}/benchmarks/genome_writing_bench/SHA256SUMS +0 -0
  32. {pen_stack-6.9.2 → pen_stack-6.10.1}/benchmarks/genome_writing_bench/SUBMISSIONS.md +0 -0
  33. {pen_stack-6.9.2 → pen_stack-6.10.1}/benchmarks/genome_writing_bench/tasks.yaml +0 -0
  34. {pen_stack-6.9.2 → pen_stack-6.10.1}/benchmarks/genome_writing_challenge/README.md +0 -0
  35. {pen_stack-6.9.2 → pen_stack-6.10.1}/benchmarks/genome_writing_challenge/SUBMISSIONS.md +0 -0
  36. {pen_stack-6.9.2 → pen_stack-6.10.1}/benchmarks/position_effect/README.md +0 -0
  37. {pen_stack-6.9.2 → pen_stack-6.10.1}/benchmarks/position_effect/SHA256SUMS +0 -0
  38. {pen_stack-6.9.2 → pen_stack-6.10.1}/benchmarks/writer_efficiency/README.md +0 -0
  39. {pen_stack-6.9.2 → pen_stack-6.10.1}/benchmarks/writer_efficiency/SHA256SUMS +0 -0
  40. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/antipeg.yaml +0 -0
  41. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/atlas_families.yaml +0 -0
  42. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/bridge_offtarget_profile.yaml +0 -0
  43. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/calibration/preexisting_nab_independent.yaml +0 -0
  44. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/capsid_epitope_oracle.yaml +0 -0
  45. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/capsid_sequences.fasta +0 -0
  46. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/cargo_polish.yaml +0 -0
  47. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/cell_types.yaml +0 -0
  48. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/datasets.yaml +0 -0
  49. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/delivery_constraints.yaml +0 -0
  50. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/delivery_rules.yaml +0 -0
  51. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/delivery_vehicles.yaml +0 -0
  52. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/expression/modifiers.yaml +0 -0
  53. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/expression/promoters.yaml +0 -0
  54. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/gates_v3.yaml +0 -0
  55. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/genotoxicity_oracle.yaml +0 -0
  56. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/gsh_validated_heldout.yaml +0 -0
  57. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/intent_weights.yaml +0 -0
  58. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/known_unknowns.yaml +0 -0
  59. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/llm.yaml +0 -0
  60. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/metric_guide.yaml +0 -0
  61. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/mhc_epitope_oracle.yaml +0 -0
  62. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/monitor_queries.yaml +0 -0
  63. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/oracles/execution.yaml +0 -0
  64. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/rules/delivery.yaml +0 -0
  65. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/rules/fold.yaml +0 -0
  66. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/rules/multiplex.yaml +0 -0
  67. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/rules/payload.yaml +0 -0
  68. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/rules/reachability.yaml +0 -0
  69. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/safety/hazard_registry.yaml +0 -0
  70. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/safety/policy.yaml +0 -0
  71. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/safety/probes.yaml +0 -0
  72. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/score_axes.yaml +0 -0
  73. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/seroprevalence.yaml +0 -0
  74. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/target_sites.yaml +0 -0
  75. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/universe_crosswalk.yaml +0 -0
  76. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/write_types.yaml +0 -0
  77. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/writer_sequences.fasta +0 -0
  78. {pen_stack-6.9.2 → pen_stack-6.10.1}/configs/wtkb_curated.yaml +0 -0
  79. {pen_stack-6.9.2 → pen_stack-6.10.1}/data/curated/bridge_offtarget_energetics.json +0 -0
  80. {pen_stack-6.9.2 → pen_stack-6.10.1}/data/curated/bridge_offtarget_profile_measured.parquet +0 -0
  81. {pen_stack-6.9.2 → pen_stack-6.10.1}/data/curated/gene_coords.parquet +0 -0
  82. {pen_stack-6.9.2 → pen_stack-6.10.1}/data/curated/unified_editor_universe.parquet +0 -0
  83. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/BACKLOG.md +0 -0
  84. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/DEPLOY.md +0 -0
  85. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/INFRA.md +0 -0
  86. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/MCP.md +0 -0
  87. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/RELEASING.md +0 -0
  88. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/REPRO.md +0 -0
  89. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/STABILITY.md +0 -0
  90. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/agent.md +0 -0
  91. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/alphagenome_feasibility.md +0 -0
  92. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/autonomy.md +0 -0
  93. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/benchmark_circularity.md +0 -0
  94. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/biosecurity.md +0 -0
  95. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/build_interface.md +0 -0
  96. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/cards/atlas.md +0 -0
  97. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/cards/durability.md +0 -0
  98. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/cards/position_effect_data.md +0 -0
  99. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/cards/safety.md +0 -0
  100. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/cards/writer_efficiency_data.md +0 -0
  101. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/challenge.md +0 -0
  102. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/closed_loop.md +0 -0
  103. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/co_scientist.md +0 -0
  104. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/co_scientist_loop.md +0 -0
  105. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/delivery.md +0 -0
  106. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/delivery_immunology.md +0 -0
  107. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/digital_twin.md +0 -0
  108. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/dissemination.md +0 -0
  109. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/environment.md +0 -0
  110. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/experiment_design.md +0 -0
  111. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/generative_design.md +0 -0
  112. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/immune_profiler.md +0 -0
  113. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/index.md +0 -0
  114. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/integrations.md +0 -0
  115. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/live_oracles.md +0 -0
  116. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/mechanistic_constraints.md +0 -0
  117. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/oracles.md +0 -0
  118. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/position_effect.md +0 -0
  119. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/positioning.md +0 -0
  120. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/private_data_formats.md +0 -0
  121. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/quickstart.md +0 -0
  122. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/responsible_use.md +0 -0
  123. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/rules.md +0 -0
  124. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/scope.md +0 -0
  125. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/scorecard.md +0 -0
  126. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/tpe_bench.md +0 -0
  127. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/tutorials/compare-families.md +0 -0
  128. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/tutorials/score-deliverability.md +0 -0
  129. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/tutorials/where-can-i-write.md +0 -0
  130. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/tutorials/which-writer-reaches-locus.md +0 -0
  131. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/uncertainty.md +0 -0
  132. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/verify.md +0 -0
  133. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/world_model.md +0 -0
  134. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/writer_efficiency.md +0 -0
  135. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/writer_verification.md +0 -0
  136. {pen_stack-6.9.2 → pen_stack-6.10.1}/docs/wtkb.md +0 -0
  137. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/_resources.py +0 -0
  138. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/active/__init__.py +0 -0
  139. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/active/acquire.py +0 -0
  140. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/active/design.py +0 -0
  141. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/active/validate.py +0 -0
  142. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/adapt/__init__.py +0 -0
  143. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/adapt/finetune.py +0 -0
  144. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/adapt/ingest.py +0 -0
  145. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/adapt/pipeline.py +0 -0
  146. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/adapt/recalibrate.py +0 -0
  147. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/adapt/report.py +0 -0
  148. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/agent/__init__.py +0 -0
  149. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/agent/co_scientist.py +0 -0
  150. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/agent/epistemic.py +0 -0
  151. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/agent/guardrails.py +0 -0
  152. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/agent/orchestrator.py +0 -0
  153. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/agent/orchestrator_live.py +0 -0
  154. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/agent/pen_agent.py +0 -0
  155. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/agent/scope.py +0 -0
  156. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/agent/tools.py +0 -0
  157. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/api/__init__.py +0 -0
  158. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/atlas/__init__.py +0 -0
  159. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/atlas/build_wtkb.py +0 -0
  160. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/atlas/crosslink.py +0 -0
  161. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/atlas/expand.py +0 -0
  162. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/atlas/guide_design.py +0 -0
  163. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/atlas/schema.py +0 -0
  164. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/atlas/scorecard.py +0 -0
  165. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/atlas/universe.py +0 -0
  166. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/atlas/variant_propose.py +0 -0
  167. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/atlas/writer_efficiency.py +0 -0
  168. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/atlas/writer_predict.py +0 -0
  169. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/atlas/writer_recommend.py +0 -0
  170. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/atlas/writer_verify.py +0 -0
  171. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/bridge/__init__.py +0 -0
  172. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/bridge/activity.py +0 -0
  173. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/bridge/cli.py +0 -0
  174. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/bridge/fold_qc.py +0 -0
  175. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/bridge/guide_qc.py +0 -0
  176. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/bridge/ingest.py +0 -0
  177. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/bridge/offtarget.py +0 -0
  178. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/bridge/offtarget_energetics.py +0 -0
  179. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/bridge/ortholog_screen.py +0 -0
  180. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/bridge/pipeline.py +0 -0
  181. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/build/__init__.py +0 -0
  182. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/build/ingest.py +0 -0
  183. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/build/protocol.py +0 -0
  184. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/build/simlab.py +0 -0
  185. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/cli.py +0 -0
  186. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/data/__init__.py +0 -0
  187. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/data/encode.py +0 -0
  188. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/data/genome.py +0 -0
  189. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/data/ingest_chromatin.py +0 -0
  190. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/data/ingest_integration.py +0 -0
  191. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/data/ingest_safety_annot.py +0 -0
  192. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/data/ingest_trip.py +0 -0
  193. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/design/__init__.py +0 -0
  194. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/design/generate.py +0 -0
  195. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/design/pareto.py +0 -0
  196. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/design/space.py +0 -0
  197. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/design/writer_variants.py +0 -0
  198. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/env/__init__.py +0 -0
  199. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/env/genome_writing_env.py +0 -0
  200. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/env/policies.py +0 -0
  201. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/graph/__init__.py +0 -0
  202. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/graph/build.py +0 -0
  203. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/graph/cell_types.py +0 -0
  204. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/graph/ingest.py +0 -0
  205. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/graph/query.py +0 -0
  206. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/graph/schema.py +0 -0
  207. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/loop/__init__.py +0 -0
  208. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/loop/continual.py +0 -0
  209. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/loop/cycle.py +0 -0
  210. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/loop/drift.py +0 -0
  211. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/mech/__init__.py +0 -0
  212. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/mech/classify_atlas.py +0 -0
  213. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/mech/whitelist.py +0 -0
  214. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/monitor/__init__.py +0 -0
  215. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/monitor/europepmc.py +0 -0
  216. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/monitor/run.py +0 -0
  217. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/monitor/triage.py +0 -0
  218. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/oracles/__init__.py +0 -0
  219. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/oracles/cache.py +0 -0
  220. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/oracles/energetics.py +0 -0
  221. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/oracles/genome.py +0 -0
  222. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/oracles/protein_design.py +0 -0
  223. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/oracles/rna.py +0 -0
  224. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/oracles/schema.py +0 -0
  225. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/oracles/status.py +0 -0
  226. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/oracles/structure.py +0 -0
  227. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/oracles/vcell.py +0 -0
  228. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/planner/__init__.py +0 -0
  229. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/planner/ada_risk.py +0 -0
  230. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/planner/antipeg_oracle.py +0 -0
  231. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/planner/capsid_epitope_oracle.py +0 -0
  232. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/planner/cargo.py +0 -0
  233. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/planner/cargo_polish.py +0 -0
  234. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/planner/delivery.py +0 -0
  235. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/planner/delivery_constraints.py +0 -0
  236. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/planner/delivery_immunology.py +0 -0
  237. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/planner/delivery_vehicles.py +0 -0
  238. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/planner/genotoxicity_oracle.py +0 -0
  239. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/planner/immune_profile.py +0 -0
  240. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/planner/innate_sensing.py +0 -0
  241. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/planner/multiplex.py +0 -0
  242. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/planner/optimize.py +0 -0
  243. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/planner/pipeline.py +0 -0
  244. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/planner/report.py +0 -0
  245. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/planner/router.py +0 -0
  246. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/planner/seroprevalence_oracle.py +0 -0
  247. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/planner/target_site.py +0 -0
  248. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/rag/__init__.py +0 -0
  249. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/rag/index.py +0 -0
  250. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/rag/llm.py +0 -0
  251. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/rag/qa.py +0 -0
  252. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/rules/__init__.py +0 -0
  253. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/rules/evaluators.py +0 -0
  254. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/rules/loader.py +0 -0
  255. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/rules/schema.py +0 -0
  256. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/rules/solver.py +0 -0
  257. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/safety/__init__.py +0 -0
  258. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/safety/audit.py +0 -0
  259. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/safety/gate.py +0 -0
  260. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/safety/policy.py +0 -0
  261. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/safety/redteam.py +0 -0
  262. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/safety/registry.py +0 -0
  263. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/safety/screen.py +0 -0
  264. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/score/__init__.py +0 -0
  265. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/score/recalibrate.py +0 -0
  266. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/score/therapeutic.py +0 -0
  267. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/server/__init__.py +0 -0
  268. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/twin/__init__.py +0 -0
  269. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/twin/calibrate.py +0 -0
  270. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/twin/data/__init__.py +0 -0
  271. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/twin/data/position_effect.py +0 -0
  272. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/twin/mechanistic.py +0 -0
  273. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/twin/outcome.py +0 -0
  274. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/ui/__init__.py +0 -0
  275. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/ui/app.py +0 -0
  276. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/__init__.py +0 -0
  277. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/adapt_demo.py +0 -0
  278. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/agent_eval.py +0 -0
  279. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/bench_adversarial_tasks.py +0 -0
  280. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/bench_coscientist_tasks.py +0 -0
  281. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/bench_graph_tasks.py +0 -0
  282. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/bench_rule_tasks.py +0 -0
  283. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/bench_trust_tasks.py +0 -0
  284. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/bench_writetype_tasks.py +0 -0
  285. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/blind_gsh_discovery.py +0 -0
  286. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/cargo_directionality.py +0 -0
  287. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/closed_loop.py +0 -0
  288. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/durability_baselines.py +0 -0
  289. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/experiment_design.py +0 -0
  290. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/expr_controls.py +0 -0
  291. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/forward_hypotheses.py +0 -0
  292. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/generative_design.py +0 -0
  293. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/guide_qc_demo.py +0 -0
  294. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/heldout_celltype_expr.py +0 -0
  295. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/intent_specification.py +0 -0
  296. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/known_biology_expr.py +0 -0
  297. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/offtarget_energetics_eval.py +0 -0
  298. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/out_of_scope_refusal.py +0 -0
  299. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/outcome_calibration.py +0 -0
  300. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/outcome_prediction.py +0 -0
  301. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/paper3_benchmark.py +0 -0
  302. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/paper4_real_validation.py +0 -0
  303. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/paper4_validation.py +0 -0
  304. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/protocol_safety.py +0 -0
  305. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/safety_screening.py +0 -0
  306. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/selective_prediction.py +0 -0
  307. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/seq_vs_measured.py +0 -0
  308. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/target_site_controls.py +0 -0
  309. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/uncertainty_eval.py +0 -0
  310. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/ungrounded_baseline.py +0 -0
  311. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/within_locus_ranking.py +0 -0
  312. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/validate/writer_recovery.py +0 -0
  313. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/verify/__init__.py +0 -0
  314. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/verify/schema.py +0 -0
  315. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/verify/service.py +0 -0
  316. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/web/__init__.py +0 -0
  317. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/web/guide.py +0 -0
  318. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/web/llm.py +0 -0
  319. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/web/router.py +0 -0
  320. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/web/server.py +0 -0
  321. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/web/tools.py +0 -0
  322. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/wgenome/__init__.py +0 -0
  323. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/wgenome/chromatin_seq.py +0 -0
  324. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/wgenome/durability.py +0 -0
  325. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/wgenome/export_tracks.py +0 -0
  326. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/wgenome/features.py +0 -0
  327. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/wgenome/gsh_baseline.py +0 -0
  328. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/wgenome/mesh_features.py +0 -0
  329. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/wgenome/ood.py +0 -0
  330. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/wgenome/providers.py +0 -0
  331. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/wgenome/safety.py +0 -0
  332. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/wgenome/structure3d.py +0 -0
  333. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/wgenome/uncertainty.py +0 -0
  334. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack/wgenome/writability.py +0 -0
  335. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack.egg-info/dependency_links.txt +0 -0
  336. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack.egg-info/entry_points.txt +0 -0
  337. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack.egg-info/requires.txt +0 -0
  338. {pen_stack-6.9.2 → pen_stack-6.10.1}/pen_stack.egg-info/top_level.txt +0 -0
  339. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_phase0.json +0 -0
  340. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_phase1_5.json +0 -0
  341. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_phase2.json +0 -0
  342. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_phase3.json +0 -0
  343. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_a.json +0 -0
  344. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_acq.json +0 -0
  345. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_aldesign.json +0 -0
  346. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_alvalidate.json +0 -0
  347. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_atlas.json +0 -0
  348. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_b.json +0 -0
  349. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_ba.json +0 -0
  350. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_ba_v33.json +0 -0
  351. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_ba_v45.json +0 -0
  352. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_bench.json +0 -0
  353. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_c.json +0 -0
  354. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_cal.json +0 -0
  355. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_calib.json +0 -0
  356. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_challenge.json +0 -0
  357. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_chat.json +0 -0
  358. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_cite.json +0 -0
  359. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_continual.json +0 -0
  360. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_cosci2.json +0 -0
  361. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_crit.json +0 -0
  362. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_ct.json +0 -0
  363. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_d.json +0 -0
  364. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_drift.json +0 -0
  365. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_e.json +0 -0
  366. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_env.json +0 -0
  367. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_ep.json +0 -0
  368. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_epitope.json +0 -0
  369. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_expr2.json +0 -0
  370. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_f.json +0 -0
  371. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_frontend.json +0 -0
  372. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_g.json +0 -0
  373. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_gen.json +0 -0
  374. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_genotox.json +0 -0
  375. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_graph.json +0 -0
  376. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_h.json +0 -0
  377. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_hybrid.json +0 -0
  378. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_immune.json +0 -0
  379. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_immune2.json +0 -0
  380. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_ingest.json +0 -0
  381. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_innate.json +0 -0
  382. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_loop.json +0 -0
  383. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_manifest.json +0 -0
  384. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_mc.json +0 -0
  385. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_mcp.json +0 -0
  386. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_mech.json +0 -0
  387. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_mon.json +0 -0
  388. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_o.json +0 -0
  389. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_openapi.json +0 -0
  390. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_orch.json +0 -0
  391. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_outcome.json +0 -0
  392. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_pareto.json +0 -0
  393. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_peg.json +0 -0
  394. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_plan.json +0 -0
  395. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_policy.json +0 -0
  396. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_profile.json +0 -0
  397. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_proto.json +0 -0
  398. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_r.json +0 -0
  399. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_redteam.json +0 -0
  400. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_route.json +0 -0
  401. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_screen.json +0 -0
  402. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_seroprev.json +0 -0
  403. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_simlab.json +0 -0
  404. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_twincal.json +0 -0
  405. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_uq.json +0 -0
  406. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_v.json +0 -0
  407. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_vcell.json +0 -0
  408. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_writer.json +0 -0
  409. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/SHA256_LOCK_ws_wv.json +0 -0
  410. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/paper1.yaml +0 -0
  411. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/paper2.yaml +0 -0
  412. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/paper3.yaml +0 -0
  413. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/paper4.yaml +0 -0
  414. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/phase0.yaml +0 -0
  415. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_a.yaml +0 -0
  416. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_acq.yaml +0 -0
  417. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_aldesign.yaml +0 -0
  418. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_alvalidate.yaml +0 -0
  419. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_atlas.yaml +0 -0
  420. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_b.yaml +0 -0
  421. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_ba.yaml +0 -0
  422. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_ba_v33.yaml +0 -0
  423. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_ba_v45.yaml +0 -0
  424. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_bench.yaml +0 -0
  425. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_c.yaml +0 -0
  426. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_cal.yaml +0 -0
  427. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_calib.yaml +0 -0
  428. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_challenge.yaml +0 -0
  429. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_chat.yaml +0 -0
  430. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_cite.yaml +0 -0
  431. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_continual.yaml +0 -0
  432. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_cosci2.yaml +0 -0
  433. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_crit.yaml +0 -0
  434. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_ct.yaml +0 -0
  435. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_d.yaml +0 -0
  436. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_drift.yaml +0 -0
  437. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_e.yaml +0 -0
  438. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_env.yaml +0 -0
  439. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_ep.yaml +0 -0
  440. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_epitope.yaml +0 -0
  441. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_expr2.yaml +0 -0
  442. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_f.yaml +0 -0
  443. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_frontend.yaml +0 -0
  444. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_g.yaml +0 -0
  445. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_gen.yaml +0 -0
  446. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_genotox.yaml +0 -0
  447. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_graph.yaml +0 -0
  448. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_h.yaml +0 -0
  449. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_hybrid.yaml +0 -0
  450. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_immune.yaml +0 -0
  451. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_immune2.yaml +0 -0
  452. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_ingest.yaml +0 -0
  453. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_innate.yaml +0 -0
  454. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_loop.yaml +0 -0
  455. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_manifest.yaml +0 -0
  456. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_mc.yaml +0 -0
  457. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_mcp.yaml +0 -0
  458. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_mech.yaml +0 -0
  459. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_mon.yaml +0 -0
  460. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_o.yaml +0 -0
  461. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_openapi.yaml +0 -0
  462. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_orch.yaml +0 -0
  463. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_outcome.yaml +0 -0
  464. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_pareto.yaml +0 -0
  465. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_peg.yaml +0 -0
  466. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_plan.yaml +0 -0
  467. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_policy.yaml +0 -0
  468. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_profile.yaml +0 -0
  469. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_proto.yaml +0 -0
  470. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_r.yaml +0 -0
  471. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_redteam.yaml +0 -0
  472. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_route.yaml +0 -0
  473. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_screen.yaml +0 -0
  474. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_seroprev.yaml +0 -0
  475. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_simlab.yaml +0 -0
  476. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_twincal.yaml +0 -0
  477. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_uq.yaml +0 -0
  478. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_v.yaml +0 -0
  479. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_vcell.yaml +0 -0
  480. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_writer.yaml +0 -0
  481. {pen_stack-6.9.2 → pen_stack-6.10.1}/prereg/ws_wv.yaml +0 -0
  482. {pen_stack-6.9.2 → pen_stack-6.10.1}/scripts/calibrate_immune_axes.py +0 -0
  483. {pen_stack-6.9.2 → pen_stack-6.10.1}/scripts/fetch_licensed_sources.py +0 -0
  484. {pen_stack-6.9.2 → pen_stack-6.10.1}/scripts/p1_build_atlas.py +0 -0
  485. {pen_stack-6.9.2 → pen_stack-6.10.1}/scripts/p1_build_durability.py +0 -0
  486. {pen_stack-6.9.2 → pen_stack-6.10.1}/scripts/p1_build_position_effect.py +0 -0
  487. {pen_stack-6.9.2 → pen_stack-6.10.1}/scripts/p1_build_writer_eff.py +0 -0
  488. {pen_stack-6.9.2 → pen_stack-6.10.1}/scripts/p1_export_tracks.py +0 -0
  489. {pen_stack-6.9.2 → pen_stack-6.10.1}/scripts/p1_safety_concordance.py +0 -0
  490. {pen_stack-6.9.2 → pen_stack-6.10.1}/scripts/p1_train_safety.py +0 -0
  491. {pen_stack-6.9.2 → pen_stack-6.10.1}/scripts/p1_validation_report.py +0 -0
  492. {pen_stack-6.9.2 → pen_stack-6.10.1}/scripts/p2_build_atlas.py +0 -0
  493. {pen_stack-6.9.2 → pen_stack-6.10.1}/scripts/p3_benchmark_report.py +0 -0
  494. {pen_stack-6.9.2 → pen_stack-6.10.1}/scripts/p4_genome_scan.py +0 -0
  495. {pen_stack-6.9.2 → pen_stack-6.10.1}/scripts/p52_build_genotox_oracle.py +0 -0
  496. {pen_stack-6.9.2 → pen_stack-6.10.1}/scripts/p53_build_epitope_oracle.py +0 -0
  497. {pen_stack-6.9.2 → pen_stack-6.10.1}/scripts/ws_b_report.py +0 -0
  498. {pen_stack-6.9.2 → pen_stack-6.10.1}/scripts/ws_c_report.py +0 -0
  499. {pen_stack-6.9.2 → pen_stack-6.10.1}/setup.cfg +0 -0
@@ -3,6 +3,76 @@
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.10.1] - 2026-06-20 - WS-OFFTARGET rigor pass + retroactive honesty audit (v6.7–v6.9)
7
+
8
+ **PATCH — complete the Stage E plan and disclose every remaining deviation.** Closes the v6.10.0 gaps and adds a
9
+ standing [DEVIATIONS_AND_DISCLOSURES.md](docs/DEVIATIONS_AND_DISCLOSURES.md) ledger; also retro-audited v6.7/v6.8/v6.9
10
+ (plan vs shipped vs code) and fixed/disclosed the findings. No item is reported complete if it is a silent
11
+ substitution/partial/deferral.
12
+
13
+ ### Added / changed (Stage E completion)
14
+ - **Off-Target-Bench expanded to FOUR unbiased assays.** Added **CHANGE-seq** (Lazzarotto 2020, `10.1038/s41587-020-0555-7`)
15
+ + **SITE-seq** (Cameron 2017, `10.1038/nmeth.4284`) on **independent broad guide panels** (20 + 11 guides). The real
16
+ **CRISOT-Score** (MD-physics, **assay-agnostic → leakage-clean**) beats the homology baseline on **all four**:
17
+ AUPRC 0.646/0.520/0.541/0.521 vs 0.467/0.266/0.249/0.233; per-guide bootstrap CI excludes 0 on each.
18
+ - **Chromatin wired to the real Stage B track + relabelled honestly.** `locus_accessibility(chrom, bin, ct)` reads
19
+ `phase_1/features/chromatin_{ct}.parquet` (ATAC/DNase) when present and **abstains** otherwise; the docs now say
20
+ "chromatin-accessibility modifier" (not "chromatin-aware engine") — the bare wheel / deployed atlas do not ship the
21
+ raw track, so the modifier is inactive there (disclosed).
22
+ - **Off-target task added to the Genome-Writing Challenge** (`benchmarks/genome_writing_challenge/harness.py`) —
23
+ non-circular (label = wet-lab Active call), data-gated on the fixture; the reference solver nominates correctly.
24
+ - **Disclosed (not eliminated):** CRISOT is used instead of the plan-named CCLMoff/CRISMER (CRISMER ships no license;
25
+ CCLMoff is GPU + trained on these assays → leakage; CRISOT is the leakage-clean, license-clean, CPU choice). A
26
+ genomic-coordinate **locus split** is not possible (harmonized data is coordinate-free) → held-out-guide + cross-assay.
27
+
28
+ ### Fixed (retroactive honesty audit)
29
+ - **v6.9:** dropped the inaccurate "OOD-gated" claim in the MHC-II axis status (it is **coverage-gated**, abstains
30
+ when uncached — no distributional OOD gate); corrected the stale `AXIS_STATUS["mhc2_writer"].reason` + the
31
+ `immune_mhc2.py` module docstring (they still described the dropped v6.9.0 P1-anchor proxy as "the method" — the
32
+ production axis is the real NetMHCIIpan-4.0). Disclosed: the plan-named MHC-II tool ensemble + IEDB/ImmunoSeq/FVIII
33
+ ADA datasets were not used (single-tool NetMHCIIpan-4.0; the recovery bench is a 4-protein sanity check, not an
34
+ IEDB held-out leaderboard); the 6.9.1→6.9.2 MHC-II metric change (peptide-fraction → residue-coverage).
35
+ - **v6.8:** disclosed that v6.8.0's attB was a poly-G/C **schematic** (fixed with the real Bxb1 attB in v6.9.2);
36
+ inter-curator agreement is N/A (single contributor); "≥1 external submission" is unmet (forward-looking).
37
+ - **v6.7:** corrected the "chromosome-Mondrian" served-interval wording (per-chromosome Mondrian qhats are computed,
38
+ but the **global** qhat is served — correct, since a query has no chromosome at serve time); disclosed the prereg
39
+ consolidation + the deferred HEK293T-OOD demo / scope-manifest entry.
40
+
41
+ See the full ledger in [docs/DEVIATIONS_AND_DISCLOSURES.md](docs/DEVIATIONS_AND_DISCLOSURES.md).
42
+
43
+ ## [6.10.0] - 2026-06-20 - WS-OFFTARGET (PEN-OFFTGT: cross-writer-family off-target nomination)
44
+
45
+ **Series III, Stage E.** Off-target moves from a single-family bridge pseudosite scan to a **cross-writer-family,
46
+ chromatin-aware NOMINATION engine** grounded in unbiased genome-wide assays — completing the safety triad
47
+ (site B + writer C + off-target E). Nomination is scrupulously framed as **not a clearance**: every candidate
48
+ ships with the empirical assay that would confirm it.
49
+
50
+ ### Added
51
+ - **Off-Target-Bench** (`benchmarks/offtarget/`) — a real, leakage-controlled nomination benchmark over canonical
52
+ Cas9 guides (EMX1/VEGFA1-3/FANCF/HEK293) with **experimentally validated off-targets** from GUIDE-seq
53
+ (Tsai 2015, `10.1038/nbt.3117`) and CIRCLE-seq (Tsai 2017, `10.1038/nmeth.4278`). Held-out-guide split, per-assay
54
+ provenance, SHA256SUMS. **Gate E-G2 PASSES on real data + real tool:** the licensed **CRISOT-Score** predictor
55
+ (Chen et al., Nat Commun 2023, `10.1038/s41467-023-42695-4`; XGBoost RNA-DNA fingerprint) BEATS the sequence-
56
+ homology baseline — GUIDE-seq AUPRC **0.646 vs 0.467** (gap +0.179, CI [0.015, 0.340]); CIRCLE-seq **0.520 vs
57
+ 0.266** (gap +0.253, CI [0.140, 0.361]); per-guide bootstrap CI excludes 0 on both assays.
58
+ - `pen_stack/wgenome/offtarget_data.py` — validated assay/predictor provenance, a GROUNDED mismatch→active-fraction
59
+ risk calibration (real-data: GUIDE-seq 0-1mm→100% active, 2mm→76%, 3mm→23%, 4mm→3.3%), the bench fixture loader.
60
+ - `pen_stack/wgenome/offtarget_predict.py` — `nominate_offtargets(writer_family, ...)`: **nuclease** (mismatch-
61
+ calibrated risk band + the real cached CRISOT score + a documented chromatin modifier, Lazzarotto 2020);
62
+ **serine integrase** (cryptic **pseudo-attB** scan on the real documented Bxb1 attB core GCGGTCTC/GT);
63
+ **bridge** (delegates to the existing Perry-DMS pseudosite engine). Abstains without inputs; never fabricates sites.
64
+ - `pen_stack/wgenome/offtarget_assay.py` — validation-assay recommender (GUIDE/CHANGE/CIRCLE-seq for nucleases;
65
+ Cryptic-seq/HIDE-seq for integrases; **honest gap** for bridge recombinases — NO published genome-wide unbiased
66
+ off-target assay or predictor exists, verified).
67
+ - **Surfaces:** REST `POST /offtarget` + `GET /offtarget/assay`, MCP `offtarget_scan`, manifest `nominate_offtargets`
68
+ (fabricates=False), an `offtarget_nomination` scope card, and a web **Off-Target** page.
69
+
70
+ ### Honest limits
71
+ - Nomination is NOT a clearance; genome-wide candidate ENUMERATION needs the on-VM Cas-OFFinder/genome scan (this
72
+ engine SCORES + RANKS + risk-bands supplied candidates). The CRISOT predictor is CC-BY-NC — it runs only on the
73
+ VM and its weights are NEVER redistributed; only derived scores are cached (CI-safe). Bridge/integrase off-target
74
+ is data-thin/unmodeled and is flagged extrapolative; IntQuery (Tome Biosciences) is a paper-only reference.
75
+
6
76
  ## [6.9.2] - 2026-06-19 - WS-IMMUNE2 real-tool rigor pass (no proxies / no heuristics across the immune + writer axes)
7
77
 
8
78
  **PATCH — a top-to-bottom audit replacing every remaining proxy/heuristic in the immune & writer-design stack with
@@ -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.2
4
+ version: 6.10.1
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.2
3
+ Version: 6.10.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
@@ -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.2-blue.svg)](CHANGELOG.md)
93
+ [![Version](https://img.shields.io/badge/version-6.10.1-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)
@@ -148,6 +148,31 @@ demonstrated (v5.12) and the benchmark went public (v5.13).
148
148
  > unknown funnel remains — made legible (scope flags, known-unknowns, honest baselines, no fabrication), not
149
149
  > hidden.
150
150
 
151
+ ## What is new in v6.10 — PEN-OFFTGT (cross-writer-family off-target nomination)
152
+
153
+ Off-target prediction was a single-family bridge pseudosite scan that abstained for nucleases and integrases.
154
+ v6.10 makes it a **cross-writer-family NOMINATION engine** with a real-data-calibrated risk band and a documented
155
+ chromatin-accessibility modifier — completing the safety triad (site + writer + off-target). It is scrupulously
156
+ honest that **nomination is not a clearance**: every candidate ships with the empirical assay that would confirm it.
157
+
158
+ - **A real, validated benchmark** (`benchmarks/offtarget/`) over **experimentally validated off-targets** from
159
+ **four** unbiased assays — GUIDE-seq (Tsai 2015) + CIRCLE-seq (Tsai 2017) on canonical guides, and CHANGE-seq
160
+ (Lazzarotto 2020) + SITE-seq (Cameron 2017) on **independent broad guide panels**. The licensed **CRISOT** predictor
161
+ (Chen et al. *Nat Commun* 2023; MD-physics, assay-agnostic → leakage-clean) **beats the sequence-homology baseline
162
+ on all four** — AUPRC 0.65/0.52/0.54/0.52 vs 0.47/0.27/0.25/0.23; per-guide bootstrap CI excludes 0 on each.
163
+ CRISOT is CC-BY-NC and runs only on the VM — only derived scores are cached (like the licensed MHC tools).
164
+ - **Grounded, calibrated risk** — the risk band IS the real-data fraction of candidates at *k* mismatches that were
165
+ experimentally validated-active (GUIDE-seq: 0–1 mm → 100%, 2 mm → 76%, 3 mm → 23%, 4 mm → 3.3%), not a guessed curve.
166
+ - **Cross-family** — nucleases (mismatch-calibrated risk + the real CRISOT score + a chromatin-accessibility modifier
167
+ that reads the Stage B ATAC/DNase track when present, else abstains), serine integrases (cryptic **pseudo-attB**
168
+ scan on the real documented Bxb1 attB core), bridge recombinases (the existing Perry-DMS engine). Bridge/integrase
169
+ off-target is **honestly flagged data-thin** — there is no published genome-wide unbiased assay or predictor for
170
+ bridge recombinases (verified).
171
+ - **Surfaces** — REST `POST /offtarget`, MCP `offtarget_scan`, manifest `nominate_offtargets`, an Off-Target web
172
+ page, and an off-target task in the Genome-Writing Challenge. Abstains without inputs; never fabricates sites.
173
+ *(Plan deviations — e.g. the CRISOT-for-CCLMoff/CRISMER substitution — are disclosed in
174
+ [docs/DEVIATIONS_AND_DISCLOSURES.md](docs/DEVIATIONS_AND_DISCLOSURES.md).)*
175
+
151
176
  ## What is new in v6.9 — PEN-IMMUNE (MHC-II/CD4 + ADA + the writer enzyme as a distinct antigen)
152
177
 
153
178
  The immune profile did **CD8/MHC-I only** (capsid epitope load via MHCflurry) — but the **dominant** immunogenicity
@@ -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.2-blue.svg)](CHANGELOG.md)
18
+ [![Version](https://img.shields.io/badge/version-6.10.1-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)
@@ -73,6 +73,31 @@ demonstrated (v5.12) and the benchmark went public (v5.13).
73
73
  > unknown funnel remains — made legible (scope flags, known-unknowns, honest baselines, no fabrication), not
74
74
  > hidden.
75
75
 
76
+ ## What is new in v6.10 — PEN-OFFTGT (cross-writer-family off-target nomination)
77
+
78
+ Off-target prediction was a single-family bridge pseudosite scan that abstained for nucleases and integrases.
79
+ v6.10 makes it a **cross-writer-family NOMINATION engine** with a real-data-calibrated risk band and a documented
80
+ chromatin-accessibility modifier — completing the safety triad (site + writer + off-target). It is scrupulously
81
+ honest that **nomination is not a clearance**: every candidate ships with the empirical assay that would confirm it.
82
+
83
+ - **A real, validated benchmark** (`benchmarks/offtarget/`) over **experimentally validated off-targets** from
84
+ **four** unbiased assays — GUIDE-seq (Tsai 2015) + CIRCLE-seq (Tsai 2017) on canonical guides, and CHANGE-seq
85
+ (Lazzarotto 2020) + SITE-seq (Cameron 2017) on **independent broad guide panels**. The licensed **CRISOT** predictor
86
+ (Chen et al. *Nat Commun* 2023; MD-physics, assay-agnostic → leakage-clean) **beats the sequence-homology baseline
87
+ on all four** — AUPRC 0.65/0.52/0.54/0.52 vs 0.47/0.27/0.25/0.23; per-guide bootstrap CI excludes 0 on each.
88
+ CRISOT is CC-BY-NC and runs only on the VM — only derived scores are cached (like the licensed MHC tools).
89
+ - **Grounded, calibrated risk** — the risk band IS the real-data fraction of candidates at *k* mismatches that were
90
+ experimentally validated-active (GUIDE-seq: 0–1 mm → 100%, 2 mm → 76%, 3 mm → 23%, 4 mm → 3.3%), not a guessed curve.
91
+ - **Cross-family** — nucleases (mismatch-calibrated risk + the real CRISOT score + a chromatin-accessibility modifier
92
+ that reads the Stage B ATAC/DNase track when present, else abstains), serine integrases (cryptic **pseudo-attB**
93
+ scan on the real documented Bxb1 attB core), bridge recombinases (the existing Perry-DMS engine). Bridge/integrase
94
+ off-target is **honestly flagged data-thin** — there is no published genome-wide unbiased assay or predictor for
95
+ bridge recombinases (verified).
96
+ - **Surfaces** — REST `POST /offtarget`, MCP `offtarget_scan`, manifest `nominate_offtargets`, an Off-Target web
97
+ page, and an off-target task in the Genome-Writing Challenge. Abstains without inputs; never fabricates sites.
98
+ *(Plan deviations — e.g. the CRISOT-for-CCLMoff/CRISMER substitution — are disclosed in
99
+ [docs/DEVIATIONS_AND_DISCLOSURES.md](docs/DEVIATIONS_AND_DISCLOSURES.md).)*
100
+
76
101
  ## What is new in v6.9 — PEN-IMMUNE (MHC-II/CD4 + ADA + the writer enzyme as a distinct antigen)
77
102
 
78
103
  The immune profile did **CD8/MHC-I only** (capsid epitope load via MHCflurry) — but the **dominant** immunogenicity
@@ -0,0 +1,4 @@
1
+ 8752efa5b6ada36cdf07707999380150f749e819178008be04dcc6b8cd70c084 split.json
2
+ e149d144c5b74499010b062cf9d3a7e2e290e71c8d3720d7b75811bf2ad7dbf3 offtarget_bench_fixture.csv
3
+ e699f399c1c640968aea1d4fe6cc679f035db3a653a5766fed795ab5eec2cecb offtarget_bench_metrics.json
4
+ 42556ae9915037d8a041259daafa93265a5c3eb9f6377245fdb425a4c3418448 offtarget_calibration.json
@@ -139,6 +139,23 @@ oracles:
139
139
  generalizes_to_unseen_loci: false
140
140
  license: "open (this work; MHCflurry 10.1016/j.cels.2020.06.010, HLA-I supertypes 10.1186/1471-2172-9-1)"
141
141
 
142
+ offtarget_nomination: # v6.10 WS-OFFTARGET: cross-family off-target NOMINATION (not clearance)
143
+ family: genome
144
+ version: "crisot+homology-2026"
145
+ output_kind: baseline # ranks/risk-bands CANDIDATE sites, not generative
146
+ valid_for: "RELATIVE off-target NOMINATION for a writer: rank candidate sites so validated off-targets
147
+ surface first, with a mismatch-CALIBRATED empirical risk band (real GUIDE-seq/CIRCLE-seq active fractions).
148
+ Nucleases use the real CRISOT-Score (beats a homology baseline on held-out guides, CI excludes 0); serine
149
+ integrases use a documented pseudo-attB cryptic scan; bridge recombinases delegate to the Perry-DMS engine"
150
+ not_valid_for: "a safety CLEARANCE (nomination != validation; every result ships with the empirical assay
151
+ that would confirm it); genome-wide candidate ENUMERATION (needs the on-VM Cas-OFFinder/genome scan; this
152
+ engine SCORES supplied candidates); a per-site cleavage/recombination PROBABILITY; bridge-recombinase
153
+ off-target magnitude (NO published genome-wide unbiased assay/predictor exists -> extrapolative/abstains);
154
+ structural variants/translocations beyond nominated sites"
155
+ generalizes_to_unseen_loci: false
156
+ license: "open (this work; GUIDE-seq 10.1038/nbt.3117, CIRCLE-seq 10.1038/nmeth.4278, CHANGE-seq
157
+ 10.1038/s41587-020-0555-7, CRISOT 10.1038/s41467-023-42695-4 CC-BY-NC run on the VM only)"
158
+
142
159
  innate_sensing: # v5.4 WS-INNATE: computed nucleic-acid innate-sensing motif load
143
160
  family: genome
144
161
  version: "cpg-oe+dsrna-2026"
@@ -0,0 +1,57 @@
1
+ # PEN-STACK — Deviations & Disclosures Ledger
2
+
3
+ A standing, honest record of every place a shipped release **deviated** from its execution plan — a dataset/model
4
+ that was substituted, a deliverable that was narrowed or deferred, or wording that overclaimed — together with the
5
+ correction or the justification. Maintained from v6.10.1 onward (the rule: *no item is reported complete if it is a
6
+ silent substitution/partial/deferral; it is either fixed or disclosed here*). Audited retroactively for v6.7–v6.9.
7
+
8
+ Legend: **FIXED** = corrected in code/docs · **DISCLOSED** = a justified, permanent deviation · **N/A** = not
9
+ applicable (e.g. single contributor).
10
+
11
+ ---
12
+
13
+ ## v6.10 / v6.10.1 — PEN-OFFTGT (Stage E, off-target nomination)
14
+
15
+ | Item | Status | Detail |
16
+ |---|---|---|
17
+ | Nuclease predictor named in plan (CCLMoff / CRISMER) vs shipped (CRISOT) | **DISCLOSED** | We use **CRISOT-Score** (Chen 2023, CC-BY-NC, CPU), not the plan's CCLMoff/CRISMER. Justified: **CRISMER ships no license** (cannot be redistributed/wrapped); **CCLMoff** is a GPU RNA-language-model stack AND was trained on these very assays (evaluating it on them would be **leakage**), whereas **CRISOT-Score is MD-physics, assay-agnostic → a leakage-clean held-out evaluation**. CRISOT is the more rigorous and license-appropriate choice. A genuine substitution, disclosed. |
18
+ | Assay coverage (plan listed GUIDE/CIRCLE/CHANGE/SITE/SURRO/TTISS/Digenome-seq) | **FIXED (v6.10.1)** | v6.10.0 used GUIDE-seq + CIRCLE-seq only. v6.10.1 adds **CHANGE-seq + SITE-seq** (independent broad guide panels) — CRISOT beats homology on **all four** (per-guide bootstrap CI excludes 0). SURRO-seq is targeted/biased (kept as an orthogonal reference, not genome-wide truth); TTISS/Digenome-seq remain **DISCLOSED** as not-yet-folded-in. |
19
+ | "Chromatin-aware via the Stage B feature store" | **FIXED (v6.10.1)** | v6.10.0 had only a caller-supplied accessibility hook and the docs said "chromatin-aware" (overclaim). v6.10.1 adds a **real** `locus_accessibility(chrom, bin, ct)` that reads the Stage B `chromatin_{ct}.parquet` ATAC/DNase track when present, **abstains** when absent (bare wheel / CI / current deployed atlas do not ship the raw track), and accepts a caller-supplied scalar otherwise. Docs relabelled to "chromatin-accessibility modifier". |
20
+ | Held-out **guide** AND **locus** splits | **DISCLOSED** | Held-out-**guide** is implemented; a genomic-coordinate **locus** split is **not possible** — the harmonized assay data ships sequences, not coordinates. Instead we add **cross-assay generalization** (the assay-agnostic CRISOT-Score evaluated on GUIDE/CIRCLE canonical guides + CHANGE/SITE independent panels). This is the leakage-clean substitute and is stated in `benchmarks/offtarget/split.json`. |
21
+ | Learned **integrase** off-target scorer (plan: "learned on HIDE/Cryptic-seq") | **DISCLOSED** | Shipped as a documented **pseudo-attB cryptic scan** on the real Bxb1 attB core, not a learned model — Cryptic-seq/HIDE-seq are recent preprints and IntQuery has **no public weights**, so a real learned integrase predictor is not groundable. Flagged extrapolative; IntQuery cited as paper-only. |
22
+ | Bench "joins the Challenge" | **FIXED (v6.10.1)** | An `offtarget` nomination task is added to the Genome-Writing Challenge (`benchmarks/genome_writing_challenge/harness.py`) — non-circular (label = wet-lab Active call), data-gated on the fixture. |
23
+ | "≥1 external use" (success criterion) | **DISCLOSED** | Forward-looking; not yet met (no external submission). The surfaces (REST/MCP/manifest/web) exist to enable it. |
24
+ | HIDE-seq / Cryptic-seq integrase **data** | **DISCLOSED** | Validated + cited, **not used as data** (single-company Bxb1-centric preprint; bridge off-target is unmodeled). Used only to ground the assay recommender. |
25
+
26
+ ## v6.9 — PEN-IMMUNE (Stage G) — *audited retroactively, corrected in v6.10.1*
27
+
28
+ | Item | Status | Detail |
29
+ |---|---|---|
30
+ | "OOD-gated" in the MHC-II axis status string | **FIXED (v6.10.1)** | No distributional OOD gate is computed for an in-panel sequence; the axis is **coverage-gated** (abstains when the antigen is uncached). Wording corrected in `immune_mhc2.py`. |
31
+ | Stale `AXIS_STATUS["mhc2_writer"].reason` + module docstring described the dropped v6.9.0 P1-anchor proxy as "the method" | **FIXED (v6.10.1)** | Updated to state the production method is the real **NetMHCIIpan-4.0** (v6.9.1/6.9.2); the P1-anchor density is offline-triage only. |
32
+ | Plan-named MHC-II tools (MixMHC2pred, Graph-pMHC, HLAIIPred, FIONA, iTope) + ADA datasets (IEDB held-out, ImmunoSeq-217, FVIII/ATHN/MLOF inhibitor sets) | **DISCLOSED** | The MHC-II axis is **NetMHCIIpan-4.0 only** (a single real tool, not the named ensemble); the Immuno-Bench panel is the 4 bundled origin-labelled proteins, **not** an IEDB/ADA held-out leaderboard. The named datasets/tools were **not used**. The single-tool result is real; the broader ensemble/benchmark is deferred. |
33
+ | Immuno-Bench "recovery" circularity | **DISCLOSED** | `recovery()` scores 3 foreign + 1 self protein; because `ada_risk = density × foreignness(origin)` and `foreignness(self)=0`, the self control is **zeroed by construction** — "foreign > self" cannot fail. It is a sanity check, not the IEDB/ADA held-out leaderboard the plan named. The ADA-incidence absence (stays 🟡) was already disclosed; this circularity note is new. |
34
+ | MHC-II metric changed (peptide-fraction → residue-coverage) between 6.9.1 and 6.9.2 | **DISCLOSED** | The 4× difference between the §6b (0.153…) and §6c/shipped (0.636…) numbers is a **metric-definition change** (now residue coverage), not a contradiction. No live surface emits the old numbers. |
35
+
36
+ ## v6.8 — PEN-WRITER (Stage C) — *audited retroactively*
37
+
38
+ | Item | Status | Detail |
39
+ |---|---|---|
40
+ | attB was a poly-G/C **schematic** at v6.8.0, surfaced as a design candidate | **FIXED (v6.9.2)** | v6.8.0 emitted `("G"*18)+core+("C"*18)` and only tested the central dinucleotide, never disclosing the attB sequence was a placeholder. The **real documented Bxb1 minimal attB** (FlyBase FBto0000359; Ghosh 2003) replaced it in v6.9.2. Disclosed here as a v6.8.0 limitation. |
41
+ | Inter-curator agreement (pre-registered C-WS1 acceptance) | **N/A** | Single contributor (`ahmedanees-m`) — inter-curator agreement is structurally inapplicable; the curation is single-author with per-row DOI + verbatim quote. |
42
+ | "≥1 external submission" (success criterion) | **DISCLOSED** | Not met; forward-looking. |
43
+ | Writer predictor gate (beats baseline on held-out **family**) | **OK (already disclosed)** | It wins on held-out **locus** only, **not** family; KB ranking retained. Stated verbatim in code/docs — no fix needed. |
44
+
45
+ ## v6.7 — PEN-EXPRESS (Stage H expression) — *audited retroactively*
46
+
47
+ | Item | Status | Detail |
48
+ |---|---|---|
49
+ | TPE-Bench headline: held-out-**cell-type** (plan) vs held-out-**chromosome** (shipped) | **OK (already disclosed)** | The live track is labelled `chrom_holdout` and the cell-type track is labelled `DATA-GATED` everywhere — an honestly-disclosed scope narrowing, not covert. |
50
+ | "chromosome-Mondrian" served interval | **FIXED (v6.10.1)** | Per-chromosome Mondrian qhats are computed, but the **served** band uses the global qhat (a query has no chromosome at serve time — which is correct). Wording corrected in `position_effect.py` to avoid implying per-query Mondrian serving. |
51
+ | Prereg consolidation (`ws_expr_{d,m,u,cal}` → single `ws_expr2.yaml`) | **DISCLOSED** | The four planned preregs were consolidated into one; the `cal` (wet-lab) prereg was dropped with the user-scoped wet-lab omission. |
52
+ | HEK293T-OOD acceptance demo + scope-manifest entry | **DISCLOSED** | Deferred with the data-gated cross-cell-type transfer track (needs a second cell-type epigenome). The OOD detector itself ships and is wired; titer/patient state are registered known-unknowns stack-wide. |
53
+
54
+ ---
55
+
56
+ *This ledger is updated on every release. If you find a deviation not listed here, it is a bug in our honesty, not
57
+ an intended omission — please flag it.*
@@ -0,0 +1,69 @@
1
+ # Data card — Off-Target-Bench (v6.10 PEN-OFFTGT)
2
+
3
+ ## Summary
4
+ A real, leakage-controlled benchmark for cross-writer-family off-target **nomination**: given a guide and its
5
+ candidate sites, rank the candidates so the experimentally validated off-targets surface first. Labels are the
6
+ wet-lab assay calls (NON-circular — the label is the experiment, not a predictor).
7
+
8
+ ## Ground truth (independently verified 2026-06-19; 4 assays as of v6.10.1)
9
+ | Assay | Setting | Guide panel | Citation | DOI |
10
+ |---|---|---|---|---|
11
+ | GUIDE-seq | cell-based, unbiased | canonical (8) | Tsai et al., *Nat Biotechnol* 2015 | `10.1038/nbt.3117` |
12
+ | CIRCLE-seq | in vitro (cell-free), unbiased | canonical (8) | Tsai et al., *Nat Methods* 2017 | `10.1038/nmeth.4278` |
13
+ | CHANGE-seq | in vitro, high-throughput | independent broad (20) | Lazzarotto et al., *Nat Biotechnol* 2020 | `10.1038/s41587-020-0555-7` |
14
+ | SITE-seq | in vitro biochemical | independent broad (11) | Cameron et al., *Nat Methods* 2017 | `10.1038/nmeth.4284` |
15
+
16
+ Canonical Cas9 guides: **EMX1, VEGFA site 1/2/3, FANCF, HEK293 site 2/3/4**. CHANGE/SITE-seq use **independent broad
17
+ guide panels** (not the canonical 8) — a cross-assay generalization test. The harmonized candidate/label tables are
18
+ sourced from the CRISOT data release (Zenodo `10.5281/zenodo.8420032`), which redistributes the public assay
19
+ supplements; PEN-STACK cites the **original assay papers** as the ground-truth provenance.
20
+
21
+ ## Learned predictor (real tool, VM-only)
22
+ **CRISOT-Score** — Chen et al., *Nat Commun* 2023, `10.1038/s41467-023-42695-4`; an XGBoost RNA-DNA interaction
23
+ fingerprint. **License: CC-BY-NC** → it runs only on the VM (`crisot:tools` Docker, `xgboost`/`pandas`/`numpy`);
24
+ its weights are NEVER redistributed. Only DERIVED scores are cached/committed (CI-safe), exactly like the licensed
25
+ NetMHC tools.
26
+
27
+ ## Baseline (pre-registered)
28
+ Sequence-homology nomination = ascending **mismatch count** (Hamming over the 20-nt protospacer).
29
+
30
+ ## Result (E-G2, full real data, on the VM)
31
+ CRISOT-Score is the MD-physics, **assay-agnostic** scorer (not fit on these labels) → a leakage-clean held-out
32
+ evaluation on every assay.
33
+
34
+ | Assay | guide panel | CRISOT AUPRC | homology AUPRC | gap | 95% CI (held-out-guide bootstrap) | beats |
35
+ |---|---|---|---|---|---|---|
36
+ | GUIDE-seq | canonical (8) | 0.646 | 0.467 | +0.179 | [0.014, 0.329] | ✅ |
37
+ | CIRCLE-seq | canonical (8) | 0.520 | 0.266 | +0.253 | [0.146, 0.370] | ✅ |
38
+ | CHANGE-seq | independent (20) | 0.541 | 0.249 | +0.292 | [0.235, 0.348] | ✅ |
39
+ | SITE-seq | independent (11) | 0.521 | 0.233 | +0.287 | [0.239, 0.335] | ✅ |
40
+
41
+ The learned predictor beats the homology baseline on **all four** assays (per-guide bootstrap CI excludes 0),
42
+ including two independent broad guide panels (cross-assay generalization).
43
+
44
+ ## Chromatin-accessibility modifier (honest scope)
45
+ The nominator applies a documented chromatin modifier (open chromatin raises realized off-target activity;
46
+ Lazzarotto 2020). It reads the **real Stage B accessibility track** (`phase_1/features/chromatin_{ct}.parquet`,
47
+ ATAC/DNase) when a candidate's genomic locus + cell type are supplied AND the feature store is present, or accepts a
48
+ caller-supplied scalar; it **abstains** otherwise. The bare wheel / CI / current deployed atlas do **not** ship the
49
+ raw accessibility track, so the modifier is inactive there — this is a documented, honestly-bounded integration, not
50
+ an autonomous "chromatin-aware" guarantee.
51
+
52
+ ## Risk calibration (grounded)
53
+ The nomination risk band IS the empirical fraction of candidates at *k* mismatches that were validated-active
54
+ (full real data): GUIDE-seq 0–1 mm → 1.00, 2 mm → 0.765, 3 mm → 0.231, 4 mm → 0.033, 5 mm → 0.0028, 6 mm → 0.00014.
55
+ Mismatch counts outside the calibrated range abstain rather than extrapolate.
56
+
57
+ ## Files
58
+ - `benchmarks/offtarget/offtarget_bench_fixture.csv` — real validated off-targets + cached CRISOT scores (CI-safe;
59
+ inactives downsampled with a fixed seed for a small committed file).
60
+ - `benchmarks/offtarget/offtarget_bench_metrics.json` — the AUTHORITATIVE full-data metrics.
61
+ - `benchmarks/offtarget/offtarget_calibration.json` — the full-data mismatch / CRISOT-decile calibration.
62
+ - `benchmarks/offtarget/split.json`, `SHA256SUMS` — split definition + checksums.
63
+
64
+ ## Honest limits
65
+ Nomination is **not** a clearance — every result ships with the empirical assay that would confirm it. Genome-wide
66
+ candidate ENUMERATION needs the on-VM Cas-OFFinder/genome scan; this benchmark covers SCORING + RANKING of supplied
67
+ candidates. Bridge/integrase off-target is data-thin: there is **no published genome-wide unbiased off-target assay
68
+ or predictor for bridge recombinases** (verified), and the large-serine-integrase assays (Cryptic-seq/HIDE-seq) and
69
+ predictor (IntQuery) are recent single-company preprints with no public weights.
@@ -0,0 +1,52 @@
1
+ # Stage E — the off-target nomination engine (v6.10 PEN-OFFTGT)
2
+
3
+ Stage E completes the **safety triad** — site (Stage B) + writer (Stage C) + **off-target** (Stage E) — by turning
4
+ off-target from a single-family bridge pseudosite scan into a **cross-writer-family, chromatin-aware NOMINATION
5
+ engine** with a real-data-calibrated risk band. The cardinal honesty invariant: **nomination is not a clearance.**
6
+ A nominated off-target is a candidate, and every result ships with the empirical assay that would confirm it.
7
+
8
+ ## The engine (`pen_stack/wgenome/offtarget_predict.py`)
9
+
10
+ `nominate_offtargets(writer_family, ...)` dispatches by writer family:
11
+
12
+ - **Nuclease (Cas9):** given a guide + candidate sites (e.g. from a Cas-OFFinder scan), each candidate gets a
13
+ **mismatch-calibrated empirical risk** (the real active fraction at *k* mismatches — not a guessed curve), the
14
+ **real CRISOT-Score** when the (guide, site) is in the cached bench, and a documented **chromatin-accessibility
15
+ modifier** (open chromatin raises realized off-target activity; Lazzarotto 2020). The modifier reads the **real
16
+ Stage B accessibility track** (`phase_1/features/chromatin_{ct}.parquet`) when a candidate's genomic locus + cell
17
+ type are supplied and the store is present, accepts a caller-supplied scalar otherwise, and **abstains** when
18
+ neither is available (the bare wheel / current deployed atlas do not ship the raw track).
19
+ - **Serine integrase (Bxb1):** a cryptic **pseudo-attB** scan that seeds on the *real documented* Bxb1 attB core
20
+ (`GCGGTCTC`, central GT; FlyBase FBto0000359, Ghosh 2003) and reports candidate cryptic sites by arm mismatches.
21
+ - **Bridge recombinase:** delegates to the existing Perry-DMS pseudosite engine (`pen_stack.bridge.offtarget`).
22
+
23
+ The engine **abstains without inputs** (no candidate sites → no fabricated sites) and is explicit that genome-wide
24
+ candidate ENUMERATION needs the on-VM scan; this engine SCORES + RANKS + risk-bands supplied candidates.
25
+
26
+ ## The benchmark (E-G2, real data + real tool)
27
+
28
+ `benchmarks/offtarget/` is a held-out-guide nomination benchmark over **four** unbiased assays — GUIDE-seq +
29
+ CIRCLE-seq (canonical guides) and CHANGE-seq + SITE-seq (**independent broad guide panels**, a cross-assay test).
30
+ The licensed **CRISOT-Score** predictor (CC-BY-NC, run on the VM; MD-physics and **assay-agnostic** → leakage-clean)
31
+ beats the sequence-homology baseline on **all four** — AUPRC 0.65/0.52/0.54/0.52 vs 0.47/0.27/0.25/0.23, with the
32
+ per-guide bootstrap CI on the gap excluding 0 on each. The Off-Target-Bench also contributes a nomination task to the
33
+ **Genome-Writing Challenge**. Only derived CRISOT scores are cached/committed; the weights are never redistributed.
34
+ A genomic-coordinate locus split is not possible (the harmonized data ships sequences, not coordinates) — held-out-
35
+ guide + cross-assay is the leakage-clean evaluation. See `docs/cards/offtarget_data.md` and
36
+ `docs/DEVIATIONS_AND_DISCLOSURES.md` for full provenance and disclosed plan deviations.
37
+
38
+ ## Validation-assay recommendation (`pen_stack/wgenome/offtarget_assay.py`)
39
+
40
+ `recommend_assay(writer_family)` maps a writer to the empirical assay(s) that would confirm a nomination —
41
+ GUIDE/CHANGE/CIRCLE-seq for nucleases, Cryptic-seq/HIDE-seq for serine integrases — and is **honest about the gap**
42
+ for bridge recombinases: there is no published genome-wide unbiased off-target assay or predictor for them, so their
43
+ nominations are flagged extrapolative and routed to targeted confirmation, never read as a clearance.
44
+
45
+ ## Surfaces
46
+ REST `POST /offtarget` + `GET /offtarget/assay`, MCP `offtarget_scan`, manifest tool `nominate_offtargets`
47
+ (`fabricates: false`), the `offtarget_nomination` scope card, and the **Off-Target** web page.
48
+
49
+ ## Honest limits
50
+ Nomination ≠ validation. Bridge/integrase off-target is data-thin/unmodeled (verified) and flagged extrapolative.
51
+ Chromatin-awareness depends on target-cell-type data. Translocations/structural variants beyond nominated sites are
52
+ out of scope. The CRISOT learned predictor is CC-BY-NC and runs only on the VM; PEN-STACK ships only derived scores.
@@ -1,2 +1,2 @@
1
1
  """PEN-STACK v3.0 - open infrastructure for genome writing."""
2
- __version__ = "6.9.2"
2
+ __version__ = "6.10.1"
@@ -39,6 +39,19 @@ def curated_dois() -> frozenset[str]:
39
39
  # v5.4 computed innate-sensing provenance (CpG-TLR9 / AAV CpG-depletion / RNA modification)
40
40
  from pen_stack.planner.innate_sensing import PROVENANCE_DOIS as _innate_dois
41
41
  dois.update(_innate_dois)
42
+ # v6.10 off-target nomination provenance (GUIDE/CIRCLE/CHANGE/SITE-seq assays + CRISOT predictor + LSI assays)
43
+ try:
44
+ from pen_stack.wgenome.offtarget_data import (
45
+ ASSAY_PROVENANCE,
46
+ INTEGRASE_ASSAY_PROVENANCE,
47
+ PREDICTOR_PROVENANCE,
48
+ )
49
+ for _src in (ASSAY_PROVENANCE, PREDICTOR_PROVENANCE, INTEGRASE_ASSAY_PROVENANCE):
50
+ for _rec in _src.values():
51
+ if _rec.get("doi"):
52
+ dois.add(_rec["doi"])
53
+ except Exception: # noqa: BLE001
54
+ pass
42
55
  # v5.5 anti-vector seroprevalence provenance (serosurveys)
43
56
  try:
44
57
  sp = yaml.safe_load(resource("configs/seroprevalence.yaml").read_text(encoding="utf-8"))
@@ -91,6 +91,18 @@ def immune_profile(design: dict) -> dict:
91
91
  return _ip(design)
92
92
 
93
93
 
94
+ @mcp.tool()
95
+ def offtarget_scan(writer_family: str, guide: str | None = None, candidate_sites: list | None = None,
96
+ sequence: str | None = None, assay: str = "guideseq") -> dict:
97
+ """v6.10 PEN-OFFTGT cross-family off-target NOMINATION (NOT a clearance). Ranks candidate sites with a
98
+ real-data mismatch-calibrated risk band + the real CRISOT learned score (nuclease), a pseudo-attB scan
99
+ (integrase), or the Perry-DMS pseudosite engine (bridge); ships the validation assay that would confirm
100
+ each candidate. Abstains without inputs; never fabricates sites."""
101
+ from pen_stack.wgenome.offtarget_predict import nominate_offtargets
102
+ return nominate_offtargets(writer_family, guide=guide, candidate_sites=candidate_sites,
103
+ sequence=sequence, assay=assay)
104
+
105
+
94
106
  @mcp.tool()
95
107
  def generate_designs(goal: dict | None = None, candidates: list | None = None, keep: int = 25) -> dict:
96
108
  """v5.8 generative designer (verifier-as-discriminator): hazardous/illegal candidates are DISCARDED;
@@ -46,6 +46,12 @@ _TOOLS = [
46
46
  "efficiency w/ conformal interval + auto-designed guide/att (v6.8 PEN-WRITER)",
47
47
  "input": "write request (write-type, cargo, cell type, optional target/donor seq)", "output": "WriterRanking",
48
48
  "entrypoint": "pen_stack.atlas.writer_recommend.recommend_writers", "fabricates": False},
49
+ {"name": "nominate_offtargets", "summary": "cross-writer-family off-target NOMINATION: rank candidate sites "
50
+ "with a real-data mismatch-calibrated risk band + the real CRISOT learned score (nuclease), pseudo-attB "
51
+ "scan (integrase), Perry-DMS pseudosite engine (bridge); nomination is NOT a clearance (v6.10 PEN-OFFTGT)",
52
+ "input": "writer family + guide/candidate sites (nuclease) or locus sequence (integrase)",
53
+ "output": "ranked off-target candidates + calibrated risk + recommended validation assay",
54
+ "entrypoint": "pen_stack.wgenome.offtarget_predict.nominate_offtargets", "fabricates": False},
49
55
  ]
50
56
 
51
57
  _POLICY = ("outputs outside scope are returned as `out_of_scope` (known-unknown) or `extrapolating` (OOD) and are "
@@ -6,13 +6,16 @@ protein itself is immunogenic** (Cas9 elicits MHC-II-presented CD4 responses, Si
6
6
  10.1038/s41467-021-25414-9; bridge recombinases / serine integrases are bacterial/phage) — yet Stage G scored
7
7
  only the capsid. v6.9 adds an MHC-II epitope-load axis over the **writer** as a distinct antigen.
8
8
 
9
- Method (grounded, dependency-free, allele-agnostic PROMISCUOUS-binder density): MHC-II presents a 9-mer core in an
10
- open groove; the **P1 pocket is deep and hydrophobic**, the single dominant anchor (M/F/Y/W/L/I/V) (Stern & Wiley,
11
- Nature 1994; Jardetzky 1996), with secondary pockets at P4/P6/P9. A *promiscuous* epitope (binds many HLA-DR) is
12
- exactly one with a strong P1 anchor + favorable secondaries (Southwood et al., J Immunol 1998). We count
13
- promiscuous-binder cores -> an epitope-density proxy. This is a **population-level, sequence-intrinsic PROXY (🟡)**,
14
- NOT a trained allele-specific predictor and NOT a patient-HLA-specific magnitude (a known-unknown). Whether those
15
- epitopes drive ADA depends on self-tolerance (foreign vs self) handled in `ada_risk`.
9
+ PRODUCTION method (v6.9.1/6.9.2): the **real, licensed NetMHCIIpan-4.0** eluted-ligand %Rank over a frequent HLA-II
10
+ panel (residue-coverage metric), run on the VM with only the derived fractions cached (`configs/mhc_epitope_oracle.yaml`);
11
+ `mhc2_epitope_load(seq, name)` returns the real value for a cached antigen and otherwise **abstains** (no production
12
+ proxy). A population-level proxy (🟡), never a patient-HLA-specific magnitude (a known-unknown). Whether the epitopes
13
+ drive ADA depends on self-tolerance (foreign vs self) handled in `ada_risk`.
14
+
15
+ OFFLINE-ONLY fallback (`mhc2_proxy_estimate`, NOT the production axis): a documented, dependency-free PROMISCUOUS-
16
+ binder density — MHC-II presents a 9-mer core in an open groove whose **P1 pocket** is the dominant hydrophobic
17
+ anchor (M/F/Y/W/L/I/V; Stern & Wiley, Nature 1994) with secondary pockets at P4/P6/P9 (Southwood 1998). Provided for
18
+ offline triage where NetMHCIIpan cannot be run; the production axis uses the real tool and abstains otherwise.
16
19
  """
17
20
  from __future__ import annotations
18
21
 
@@ -75,8 +78,9 @@ def real_mhc2_load(name: str) -> dict | None:
75
78
  "n_covered": rec.get("n_covered"), "length": rec.get("length"),
76
79
  "method": f"NetMHCIIpan-4.0 EL %Rank<=2, {rec.get('metric', 'residue coverage')}, frequent HLA-II "
77
80
  f"panel ({len(panel)} alleles): {', '.join(panel)}",
78
- "status": "population-level (frequent-HLA panel; NetMHCIIpan-4.0 eluted-ligand), OOD-gated; NOT a "
79
- "patient-HLA-specific magnitude (known-unknown)", "backend": "netmhciipan_cache"}
81
+ "status": "population-level (frequent-HLA panel; NetMHCIIpan-4.0 eluted-ligand), coverage-gated "
82
+ "(abstains for uncached antigens — NOT a distributional OOD gate); NOT a patient-HLA-specific "
83
+ "magnitude (known-unknown)", "backend": "netmhciipan_cache"}
80
84
 
81
85
 
82
86
  def mhc2_epitope_load(seq: str, name: str | None = None) -> dict:
@@ -208,6 +208,26 @@ def immune_endpoint(design: dict):
208
208
  return immune_profile(design)
209
209
 
210
210
 
211
+ @app.post("/offtarget", tags=["v6.10 off-target"])
212
+ def offtarget_endpoint(req: dict):
213
+ """v6.10 PEN-OFFTGT cross-family off-target NOMINATION (NOT a clearance). Body:
214
+ {writer_family, guide?, candidate_sites?, sequence?, accessibility?, assay?}. Returns ranked candidate
215
+ off-targets with a real-data mismatch-calibrated risk band + the recommended validation assay; abstains
216
+ without inputs and never fabricates sites."""
217
+ from pen_stack.wgenome.offtarget_predict import nominate_offtargets
218
+ return nominate_offtargets(
219
+ req.get("writer_family", ""), guide=req.get("guide"), candidate_sites=req.get("candidate_sites"),
220
+ sequence=req.get("sequence"), accessibility=req.get("accessibility"),
221
+ target_core=req.get("target_core"), assay=req.get("assay", "guideseq"))
222
+
223
+
224
+ @app.get("/offtarget/assay", tags=["v6.10 off-target"])
225
+ def offtarget_assay_endpoint(writer_family: str):
226
+ """v6.10 validation-assay recommendation for a writer family (the assay that would confirm a nomination)."""
227
+ from pen_stack.wgenome.offtarget_assay import recommend_assay
228
+ return recommend_assay(writer_family)
229
+
230
+
211
231
  @app.post("/generate", tags=["v6.1 AI surface"])
212
232
  def generate_endpoint(req: dict):
213
233
  """v5.8 generative designer: verifier-as-discriminator. Body: {goal?, candidates?, keep?}. Hazardous/illegal
@@ -150,7 +150,8 @@ class PositionEffectModel:
150
150
  lo, hi = self.conformal.interval(yhat, sigma=widen)
151
151
  return {"yhat": yhat, "lo": lo, "hi": hi, "ood_widen": widen,
152
152
  "nominal_coverage": 1 - self.conformal.alpha,
153
- "interval_kind": "trained split-conformal (chromosome-Mondrian), OOD-widened"}
153
+ "interval_kind": "trained split-conformal (chromosome-blocked OOF; per-chromosome Mondrian qhats "
154
+ "computed, GLOBAL qhat served — a query has no chromosome at serve time), OOD-widened"}
154
155
 
155
156
  # ---- persistence ----------------------------------------------------------------------------
156
157
  def save(self, path: str | Path) -> str:
@@ -96,9 +96,10 @@ AXIS_STATUS: dict[str, dict] = {
96
96
  "rates (and induced post-dose-1 anti-PEG is a separate dynamic)."},
97
97
  "mhc2_writer": { # v6.9 G-WS1 — CD4/MHC-II epitope load over the writer enzyme
98
98
  "status": "mechanistic_proxy",
99
- "label": "mhc2_writer: mechanistic/population proxy — NOT outcome-validated",
100
- "reason": "sequence-intrinsic promiscuous MHC-II binder density (P1-anchor; Stern & Wiley 1994) is a "
101
- "presentation potential, NOT a trained allele-specific predictor or a patient-HLA magnitude."},
99
+ "label": "mhc2_writer: population proxy — NOT outcome-validated",
100
+ "reason": "real NetMHCIIpan-4.0 eluted-ligand MHC-II epitope load over a frequent-HLA panel (v6.9.2; the "
101
+ "v6.9.0 P1-anchor proxy was replaced) — a population-level presentation potential, NOT a "
102
+ "patient-HLA-specific magnitude or an observed-ADA-validated number."},
102
103
  "ada_writer": { # v6.9 G-WS2 — ADA-risk (MHC-II x foreignness, self-tolerance filtered)
103
104
  "status": "mechanistic_proxy",
104
105
  "label": "ada_writer: mechanistic/population proxy — NOT outcome-validated",
@@ -0,0 +1,55 @@
1
+ """Validation-assay recommender for off-target nomination (v6.10 PEN-OFFTGT, E-WS3).
2
+
3
+ Nomination is NOT a clearance — it ships with the empirical assay that would CONFIRM the candidates. This maps a
4
+ writer family to the appropriate unbiased genome-wide assay(s) + their documented applicability, grounded in the
5
+ validated assay literature. For families with no published genome-wide off-target assay (bridge recombinases) it
6
+ says so honestly and recommends targeted confirmation, never implying a clearance exists.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ # assay applicability by writer family (validated citations in offtarget_data.ASSAY_PROVENANCE)
11
+ _NUCLEASE_ASSAYS = [
12
+ {"assay": "GUIDE-seq", "setting": "cell-based (in cellulo)", "doi": "10.1038/nbt.3117",
13
+ "use": "captures off-targets in the actual chromatin/cell context (dsODN tag at DSBs)"},
14
+ {"assay": "CHANGE-seq", "setting": "in vitro, high-throughput", "doi": "10.1038/s41587-020-0555-7",
15
+ "use": "most sensitive genome-wide nomination; pair with a cell-based assay to filter chromatin-masked sites"},
16
+ {"assay": "CIRCLE-seq", "setting": "in vitro (cell-free)", "doi": "10.1038/nmeth.4278",
17
+ "use": "highly sensitive in vitro confirmation; over-nominates vs cell context"},
18
+ ]
19
+
20
+
21
+ def recommend_assay(writer_family: str) -> dict:
22
+ """Recommend the empirical validation assay(s) for a writer family + the documented expected sensitivity, or
23
+ an honest 'no genome-wide assay exists' for data-thin families. Always frames nomination as not a clearance."""
24
+ fam = (writer_family or "").lower()
25
+ if "cas9" in fam or "nuclease" in fam or fam in {"spcas9", "sacas9", "cas12a", "ascas12a", "nickase"}:
26
+ return {"family": writer_family, "writer_class": "RNA-guided nuclease (DSB)",
27
+ "recommended": _NUCLEASE_ASSAYS,
28
+ "strategy": "nominate in vitro (CHANGE-/CIRCLE-seq, high sensitivity) THEN confirm the survivors "
29
+ "in the target cell type (GUIDE-seq) — chromatin masks a fraction of in vitro sites",
30
+ "available": True,
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:
33
+ return {"family": writer_family, "writer_class": "large serine integrase",
34
+ "recommended": [{"assay": "Cryptic-seq / HIDE-seq", "setting": "unbiased LSI off-target discovery",
35
+ "doi": "10.1101/2024.08.23.609471",
36
+ "use": "the genome-wide unbiased assay for serine-integrase cryptic attB sites "
37
+ "(Tome Biosciences, 2024 preprint)"}],
38
+ "strategy": "scan cryptic pseudo-attB (this engine) THEN confirm by Cryptic-seq/HIDE-seq; "
39
+ "quantitative prediction (IntQuery) is paper-only (no public weights)",
40
+ "available": True,
41
+ "note": "LSI off-target assays are recent preprints; coverage is single-company / largely Bxb1."}
42
+ if "bridge" in fam or "is110" in fam or "is621" in fam or "seek" in fam or "iscro4" in fam:
43
+ return {"family": writer_family, "writer_class": "bridge recombinase (IS110/IS621 RNA-guided)",
44
+ "recommended": [{"assay": "targeted amplicon / capture sequencing at nominated pseudosites",
45
+ "setting": "targeted", "doi": None,
46
+ "use": "confirm individual nominated pseudosites (no genome-wide unbiased "
47
+ "off-target assay exists for bridge recombinases yet)"}],
48
+ "strategy": "nominate pseudosites with the Perry-DMS engine THEN confirm by targeted sequencing; "
49
+ "an unbiased genome-wide bridge off-target assay is an open need",
50
+ "available": True,
51
+ "note": "HONEST GAP: bridge-recombinase off-target is essentially unmodeled — there is NO "
52
+ "published genome-wide unbiased assay or predictor (verified). Treat nominations as "
53
+ "high-uncertainty / extrapolative; do not read as clearance."}
54
+ return {"family": writer_family, "available": False,
55
+ "note": f"no off-target assay applicability rule for family {writer_family!r}"}