pen-stack 7.1.4__tar.gz → 7.1.5__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 (567) hide show
  1. {pen_stack-7.1.4 → pen_stack-7.1.5}/CHANGELOG.md +27 -0
  2. {pen_stack-7.1.4 → pen_stack-7.1.5}/CITATION.cff +1 -1
  3. {pen_stack-7.1.4 → pen_stack-7.1.5}/PKG-INFO +1 -1
  4. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/__init__.py +1 -1
  5. pen_stack-7.1.5/pen_stack/planner/chromosome.py +106 -0
  6. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/server/api.py +17 -0
  7. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/verify/service.py +12 -0
  8. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack.egg-info/PKG-INFO +1 -1
  9. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack.egg-info/SOURCES.txt +1 -0
  10. {pen_stack-7.1.4 → pen_stack-7.1.5}/pyproject.toml +1 -1
  11. {pen_stack-7.1.4 → pen_stack-7.1.5}/LICENSE +0 -0
  12. {pen_stack-7.1.4 → pen_stack-7.1.5}/MANIFEST.in +0 -0
  13. {pen_stack-7.1.4 → pen_stack-7.1.5}/README.md +0 -0
  14. {pen_stack-7.1.4 → pen_stack-7.1.5}/bench/run.py +0 -0
  15. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/chat_grounding/README.md +0 -0
  16. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/chat_grounding/SHA256SUMS +0 -0
  17. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/chat_headtohead/README.md +0 -0
  18. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/chat_routing/README.md +0 -0
  19. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/chat_routing/SHA256SUMS +0 -0
  20. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/chat_safety/README.md +0 -0
  21. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/chat_safety/SHA256SUMS +0 -0
  22. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/delivery/SHA256SUMS +0 -0
  23. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/genome_writing_bench/LEADERBOARD.md +0 -0
  24. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/genome_writing_bench/README.md +0 -0
  25. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/genome_writing_bench/SHA256SUMS +0 -0
  26. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/genome_writing_bench/SUBMISSIONS.md +0 -0
  27. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/genome_writing_bench/tasks.yaml +0 -0
  28. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/genome_writing_challenge/README.md +0 -0
  29. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/genome_writing_challenge/SUBMISSIONS.md +0 -0
  30. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/loop/SHA256SUMS +0 -0
  31. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/offtarget/SHA256SUMS +0 -0
  32. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/oracle/SHA256SUMS +0 -0
  33. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/position_effect/README.md +0 -0
  34. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/position_effect/SHA256SUMS +0 -0
  35. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/verify/SHA256SUMS +0 -0
  36. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/writer_efficiency/README.md +0 -0
  37. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/writer_efficiency/SHA256SUMS +0 -0
  38. {pen_stack-7.1.4 → pen_stack-7.1.5}/benchmarks/writespec/SHA256SUMS +0 -0
  39. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/aav_serotype_tropism.yaml +0 -0
  40. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/antipeg.yaml +0 -0
  41. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/atlas_families.yaml +0 -0
  42. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/bridge_offtarget_profile.yaml +0 -0
  43. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/calibration/preexisting_nab_independent.yaml +0 -0
  44. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/capsid_epitope_oracle.yaml +0 -0
  45. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/capsid_sequences.fasta +0 -0
  46. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/cargo_polish.yaml +0 -0
  47. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/cell_types.yaml +0 -0
  48. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/datasets.yaml +0 -0
  49. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/delivery_constraints.yaml +0 -0
  50. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/delivery_rules.yaml +0 -0
  51. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/delivery_vehicles.yaml +0 -0
  52. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/expression/modifiers.yaml +0 -0
  53. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/expression/promoters.yaml +0 -0
  54. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/gates_v3.yaml +0 -0
  55. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/genotoxicity_oracle.yaml +0 -0
  56. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/gsh_validated_heldout.yaml +0 -0
  57. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/intent_weights.yaml +0 -0
  58. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/known_unknowns.yaml +0 -0
  59. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/llm.yaml +0 -0
  60. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/metric_guide.yaml +0 -0
  61. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/mhc_epitope_oracle.yaml +0 -0
  62. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/monitor_queries.yaml +0 -0
  63. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/oracles/execution.yaml +0 -0
  64. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/oracles/reliability.yaml +0 -0
  65. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/oracles/scope_cards.yaml +0 -0
  66. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/rules/compliance.yaml +0 -0
  67. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/rules/delivery.yaml +0 -0
  68. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/rules/fold.yaml +0 -0
  69. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/rules/multiplex.yaml +0 -0
  70. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/rules/payload.yaml +0 -0
  71. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/rules/reachability.yaml +0 -0
  72. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/safety/hazard_registry.yaml +0 -0
  73. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/safety/policy.yaml +0 -0
  74. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/safety/probes.yaml +0 -0
  75. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/score_axes.yaml +0 -0
  76. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/seroprevalence.yaml +0 -0
  77. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/target_sites.yaml +0 -0
  78. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/universe_crosswalk.yaml +0 -0
  79. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/write_types.yaml +0 -0
  80. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/writer_sequences.fasta +0 -0
  81. {pen_stack-7.1.4 → pen_stack-7.1.5}/configs/wtkb_curated.yaml +0 -0
  82. {pen_stack-7.1.4 → pen_stack-7.1.5}/data/curated/bridge_offtarget_energetics.json +0 -0
  83. {pen_stack-7.1.4 → pen_stack-7.1.5}/data/curated/bridge_offtarget_profile_measured.parquet +0 -0
  84. {pen_stack-7.1.4 → pen_stack-7.1.5}/data/curated/gene_coords.parquet +0 -0
  85. {pen_stack-7.1.4 → pen_stack-7.1.5}/data/curated/unified_editor_universe.parquet +0 -0
  86. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/BACKLOG.md +0 -0
  87. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/DEPLOY.md +0 -0
  88. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/INFRA.md +0 -0
  89. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/MCP.md +0 -0
  90. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/RELEASING.md +0 -0
  91. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/REPRO.md +0 -0
  92. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/STABILITY.md +0 -0
  93. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/agent.md +0 -0
  94. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/alphagenome_feasibility.md +0 -0
  95. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/autonomy.md +0 -0
  96. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/benchmark_circularity.md +0 -0
  97. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/biosecurity.md +0 -0
  98. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/build_interface.md +0 -0
  99. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/cards/atlas.md +0 -0
  100. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/cards/durability.md +0 -0
  101. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/cards/offtarget_data.md +0 -0
  102. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/cards/position_effect_data.md +0 -0
  103. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/cards/safety.md +0 -0
  104. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/cards/writer_efficiency_data.md +0 -0
  105. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/challenge.md +0 -0
  106. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/closed_loop.md +0 -0
  107. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/co_scientist.md +0 -0
  108. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/co_scientist_loop.md +0 -0
  109. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/delivery.md +0 -0
  110. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/delivery_immunology.md +0 -0
  111. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/delivery_recommender.md +0 -0
  112. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/digital_twin.md +0 -0
  113. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/dissemination.md +0 -0
  114. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/environment.md +0 -0
  115. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/experiment_design.md +0 -0
  116. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/generative_design.md +0 -0
  117. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/immune_profiler.md +0 -0
  118. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/index.md +0 -0
  119. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/integrations.md +0 -0
  120. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/live_oracles.md +0 -0
  121. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/mechanistic_constraints.md +0 -0
  122. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/offtarget.md +0 -0
  123. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/oracle_mesh.md +0 -0
  124. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/oracles.md +0 -0
  125. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/position_effect.md +0 -0
  126. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/positioning.md +0 -0
  127. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/private_data_formats.md +0 -0
  128. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/quickstart.md +0 -0
  129. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/responsible_use.md +0 -0
  130. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/rule_spec.md +0 -0
  131. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/rules.md +0 -0
  132. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/scope.md +0 -0
  133. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/scorecard.md +0 -0
  134. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/tpe_bench.md +0 -0
  135. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/tutorials/compare-families.md +0 -0
  136. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/tutorials/score-deliverability.md +0 -0
  137. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/tutorials/where-can-i-write.md +0 -0
  138. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/tutorials/which-writer-reaches-locus.md +0 -0
  139. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/uncertainty.md +0 -0
  140. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/verify.md +0 -0
  141. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/verify_service.md +0 -0
  142. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/world_model.md +0 -0
  143. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/writer_efficiency.md +0 -0
  144. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/writer_verification.md +0 -0
  145. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/writespec_bench.md +0 -0
  146. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/writespec_profile.md +0 -0
  147. {pen_stack-7.1.4 → pen_stack-7.1.5}/docs/wtkb.md +0 -0
  148. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/_resources.py +0 -0
  149. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/active/__init__.py +0 -0
  150. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/active/acquire.py +0 -0
  151. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/active/brains.py +0 -0
  152. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/active/campaign.py +0 -0
  153. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/active/design.py +0 -0
  154. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/active/validate.py +0 -0
  155. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/adapt/__init__.py +0 -0
  156. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/adapt/finetune.py +0 -0
  157. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/adapt/ingest.py +0 -0
  158. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/adapt/pipeline.py +0 -0
  159. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/adapt/recalibrate.py +0 -0
  160. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/adapt/report.py +0 -0
  161. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/agent/__init__.py +0 -0
  162. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/agent/cite.py +0 -0
  163. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/agent/co_scientist.py +0 -0
  164. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/agent/epistemic.py +0 -0
  165. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/agent/guardrails.py +0 -0
  166. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/agent/mcp_server.py +0 -0
  167. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/agent/orchestrator.py +0 -0
  168. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/agent/orchestrator_live.py +0 -0
  169. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/agent/pen_agent.py +0 -0
  170. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/agent/scope.py +0 -0
  171. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/agent/tools.py +0 -0
  172. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/api/__init__.py +0 -0
  173. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/api/manifest.py +0 -0
  174. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/atlas/__init__.py +0 -0
  175. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/atlas/build_wtkb.py +0 -0
  176. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/atlas/crosslink.py +0 -0
  177. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/atlas/expand.py +0 -0
  178. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/atlas/guide_design.py +0 -0
  179. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/atlas/schema.py +0 -0
  180. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/atlas/scorecard.py +0 -0
  181. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/atlas/universe.py +0 -0
  182. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/atlas/variant_propose.py +0 -0
  183. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/atlas/writer_efficiency.py +0 -0
  184. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/atlas/writer_predict.py +0 -0
  185. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/atlas/writer_recommend.py +0 -0
  186. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/atlas/writer_verify.py +0 -0
  187. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/bridge/__init__.py +0 -0
  188. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/bridge/activity.py +0 -0
  189. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/bridge/cli.py +0 -0
  190. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/bridge/fold_qc.py +0 -0
  191. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/bridge/guide_qc.py +0 -0
  192. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/bridge/ingest.py +0 -0
  193. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/bridge/offtarget.py +0 -0
  194. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/bridge/offtarget_energetics.py +0 -0
  195. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/bridge/ortholog_screen.py +0 -0
  196. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/bridge/pipeline.py +0 -0
  197. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/build/__init__.py +0 -0
  198. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/build/cloudlab.py +0 -0
  199. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/build/ingest.py +0 -0
  200. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/build/protocol.py +0 -0
  201. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/build/simlab.py +0 -0
  202. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/cli.py +0 -0
  203. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/data/__init__.py +0 -0
  204. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/data/encode.py +0 -0
  205. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/data/genome.py +0 -0
  206. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/data/ingest_chromatin.py +0 -0
  207. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/data/ingest_integration.py +0 -0
  208. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/data/ingest_safety_annot.py +0 -0
  209. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/data/ingest_trip.py +0 -0
  210. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/design/__init__.py +0 -0
  211. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/design/capsid_generate.py +0 -0
  212. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/design/generate.py +0 -0
  213. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/design/pareto.py +0 -0
  214. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/design/space.py +0 -0
  215. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/design/writer_variants.py +0 -0
  216. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/env/__init__.py +0 -0
  217. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/env/genome_writing_env.py +0 -0
  218. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/env/policies.py +0 -0
  219. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/graph/__init__.py +0 -0
  220. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/graph/build.py +0 -0
  221. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/graph/cell_types.py +0 -0
  222. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/graph/ingest.py +0 -0
  223. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/graph/query.py +0 -0
  224. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/graph/schema.py +0 -0
  225. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/loop/__init__.py +0 -0
  226. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/loop/continual.py +0 -0
  227. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/loop/cycle.py +0 -0
  228. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/loop/drift.py +0 -0
  229. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/mech/__init__.py +0 -0
  230. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/mech/classify_atlas.py +0 -0
  231. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/mech/whitelist.py +0 -0
  232. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/monitor/__init__.py +0 -0
  233. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/monitor/europepmc.py +0 -0
  234. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/monitor/run.py +0 -0
  235. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/monitor/triage.py +0 -0
  236. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/oracles/__init__.py +0 -0
  237. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/oracles/affinity.py +0 -0
  238. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/oracles/cache.py +0 -0
  239. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/oracles/energetics.py +0 -0
  240. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/oracles/genome.py +0 -0
  241. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/oracles/protein_design.py +0 -0
  242. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/oracles/reliability.py +0 -0
  243. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/oracles/rna.py +0 -0
  244. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/oracles/schema.py +0 -0
  245. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/oracles/status.py +0 -0
  246. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/oracles/structure.py +0 -0
  247. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/oracles/structure_run.py +0 -0
  248. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/oracles/vcell.py +0 -0
  249. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/__init__.py +0 -0
  250. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/ada_risk.py +0 -0
  251. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/antipeg_oracle.py +0 -0
  252. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/capsid_epitope_oracle.py +0 -0
  253. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/cargo.py +0 -0
  254. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/cargo_polish.py +0 -0
  255. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/delivery.py +0 -0
  256. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/delivery_constraints.py +0 -0
  257. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/delivery_immune.py +0 -0
  258. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/delivery_immunology.py +0 -0
  259. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/delivery_predict.py +0 -0
  260. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/delivery_vehicles.py +0 -0
  261. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/genotoxicity_oracle.py +0 -0
  262. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/immune_mhc2.py +0 -0
  263. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/immune_profile.py +0 -0
  264. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/innate_sensing.py +0 -0
  265. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/multiplex.py +0 -0
  266. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/optimize.py +0 -0
  267. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/pipeline.py +0 -0
  268. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/report.py +0 -0
  269. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/router.py +0 -0
  270. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/seroprevalence_oracle.py +0 -0
  271. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/planner/target_site.py +0 -0
  272. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/rag/__init__.py +0 -0
  273. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/rag/corpus.py +0 -0
  274. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/rag/embed.py +0 -0
  275. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/rag/ground.py +0 -0
  276. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/rag/index.py +0 -0
  277. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/rag/llm.py +0 -0
  278. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/rag/qa.py +0 -0
  279. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/rag/retrieve.py +0 -0
  280. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/rules/__init__.py +0 -0
  281. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/rules/evaluators.py +0 -0
  282. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/rules/loader.py +0 -0
  283. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/rules/schema.py +0 -0
  284. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/rules/solver.py +0 -0
  285. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/rules/spec.py +0 -0
  286. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/safety/__init__.py +0 -0
  287. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/safety/audit.py +0 -0
  288. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/safety/gate.py +0 -0
  289. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/safety/policy.py +0 -0
  290. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/safety/redteam.py +0 -0
  291. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/safety/registry.py +0 -0
  292. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/safety/screen.py +0 -0
  293. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/safety/standards.py +0 -0
  294. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/score/__init__.py +0 -0
  295. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/score/recalibrate.py +0 -0
  296. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/score/therapeutic.py +0 -0
  297. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/server/__init__.py +0 -0
  298. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/spec/__init__.py +0 -0
  299. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/spec/clarify.py +0 -0
  300. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/spec/extract.py +0 -0
  301. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/spec/resolvers/__init__.py +0 -0
  302. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/spec/resolvers/cell.py +0 -0
  303. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/spec/resolvers/chem.py +0 -0
  304. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/spec/resolvers/feature.py +0 -0
  305. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/spec/resolvers/gene.py +0 -0
  306. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/spec/resolvers/locus.py +0 -0
  307. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/spec/resolvers/phenotype.py +0 -0
  308. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/spec/satisfy.py +0 -0
  309. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/spec/service.py +0 -0
  310. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/spec/writespec.py +0 -0
  311. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/twin/__init__.py +0 -0
  312. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/twin/calibrate.py +0 -0
  313. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/twin/data/__init__.py +0 -0
  314. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/twin/data/position_effect.py +0 -0
  315. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/twin/mechanistic.py +0 -0
  316. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/twin/outcome.py +0 -0
  317. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/twin/position_effect.py +0 -0
  318. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/ui/__init__.py +0 -0
  319. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/ui/app.py +0 -0
  320. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/__init__.py +0 -0
  321. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/adapt_demo.py +0 -0
  322. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/agent_eval.py +0 -0
  323. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/bench_adversarial_tasks.py +0 -0
  324. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/bench_coscientist_tasks.py +0 -0
  325. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/bench_graph_tasks.py +0 -0
  326. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/bench_rule_tasks.py +0 -0
  327. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/bench_trust_tasks.py +0 -0
  328. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/bench_writetype_tasks.py +0 -0
  329. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/blind_gsh_discovery.py +0 -0
  330. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/cargo_directionality.py +0 -0
  331. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/closed_loop.py +0 -0
  332. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/durability_baselines.py +0 -0
  333. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/experiment_design.py +0 -0
  334. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/expr_controls.py +0 -0
  335. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/forward_hypotheses.py +0 -0
  336. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/generative_design.py +0 -0
  337. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/guide_qc_demo.py +0 -0
  338. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/heldout_celltype_expr.py +0 -0
  339. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/immune_calibration.py +0 -0
  340. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/intent_specification.py +0 -0
  341. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/known_biology_expr.py +0 -0
  342. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/offtarget_energetics_eval.py +0 -0
  343. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/out_of_scope_refusal.py +0 -0
  344. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/outcome_calibration.py +0 -0
  345. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/outcome_prediction.py +0 -0
  346. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/paper3_benchmark.py +0 -0
  347. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/paper4_real_validation.py +0 -0
  348. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/paper4_validation.py +0 -0
  349. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/protocol_safety.py +0 -0
  350. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/safety_screening.py +0 -0
  351. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/selective_prediction.py +0 -0
  352. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/seq_vs_measured.py +0 -0
  353. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/target_site_controls.py +0 -0
  354. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/uncertainty_eval.py +0 -0
  355. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/ungrounded_baseline.py +0 -0
  356. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/within_locus_ranking.py +0 -0
  357. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/validate/writer_recovery.py +0 -0
  358. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/verify/__init__.py +0 -0
  359. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/verify/proof.py +0 -0
  360. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/verify/schema.py +0 -0
  361. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/web/__init__.py +0 -0
  362. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/web/guide.py +0 -0
  363. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/web/llm.py +0 -0
  364. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/web/llm_provider.py +0 -0
  365. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/web/router.py +0 -0
  366. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/web/server.py +0 -0
  367. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/web/tools.py +0 -0
  368. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/wgenome/__init__.py +0 -0
  369. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/wgenome/chromatin_seq.py +0 -0
  370. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/wgenome/durability.py +0 -0
  371. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/wgenome/export_tracks.py +0 -0
  372. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/wgenome/features.py +0 -0
  373. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/wgenome/gsh_baseline.py +0 -0
  374. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/wgenome/mesh_features.py +0 -0
  375. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/wgenome/offtarget_assay.py +0 -0
  376. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/wgenome/offtarget_data.py +0 -0
  377. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/wgenome/offtarget_predict.py +0 -0
  378. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/wgenome/ood.py +0 -0
  379. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/wgenome/providers.py +0 -0
  380. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/wgenome/safety.py +0 -0
  381. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/wgenome/structure3d.py +0 -0
  382. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/wgenome/uncertainty.py +0 -0
  383. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack/wgenome/writability.py +0 -0
  384. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack.egg-info/dependency_links.txt +0 -0
  385. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack.egg-info/entry_points.txt +0 -0
  386. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack.egg-info/requires.txt +0 -0
  387. {pen_stack-7.1.4 → pen_stack-7.1.5}/pen_stack.egg-info/top_level.txt +0 -0
  388. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_phase0.json +0 -0
  389. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_phase1_5.json +0 -0
  390. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_phase2.json +0 -0
  391. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_phase3.json +0 -0
  392. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_a.json +0 -0
  393. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_acq.json +0 -0
  394. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_aldesign.json +0 -0
  395. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_alvalidate.json +0 -0
  396. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_atlas.json +0 -0
  397. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_b.json +0 -0
  398. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_ba.json +0 -0
  399. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_ba_v33.json +0 -0
  400. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_ba_v45.json +0 -0
  401. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_bench.json +0 -0
  402. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_c.json +0 -0
  403. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_cal.json +0 -0
  404. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_calib.json +0 -0
  405. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_challenge.json +0 -0
  406. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_chat.json +0 -0
  407. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_cite.json +0 -0
  408. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_closedloop.json +0 -0
  409. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_continual.json +0 -0
  410. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_cosci2.json +0 -0
  411. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_crit.json +0 -0
  412. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_ct.json +0 -0
  413. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_d.json +0 -0
  414. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_delivery.json +0 -0
  415. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_drift.json +0 -0
  416. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_e.json +0 -0
  417. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_env.json +0 -0
  418. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_ep.json +0 -0
  419. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_epitope.json +0 -0
  420. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_expr2.json +0 -0
  421. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_f.json +0 -0
  422. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_frontend.json +0 -0
  423. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_g.json +0 -0
  424. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_gen.json +0 -0
  425. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_genotox.json +0 -0
  426. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_graph.json +0 -0
  427. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_h.json +0 -0
  428. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_hybrid.json +0 -0
  429. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_immune.json +0 -0
  430. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_immune2.json +0 -0
  431. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_ingest.json +0 -0
  432. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_innate.json +0 -0
  433. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_loop.json +0 -0
  434. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_manifest.json +0 -0
  435. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_mc.json +0 -0
  436. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_mcp.json +0 -0
  437. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_mech.json +0 -0
  438. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_mon.json +0 -0
  439. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_o.json +0 -0
  440. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_offtarget.json +0 -0
  441. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_openapi.json +0 -0
  442. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_oracle.json +0 -0
  443. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_orch.json +0 -0
  444. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_outcome.json +0 -0
  445. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_pareto.json +0 -0
  446. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_peg.json +0 -0
  447. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_penchat.json +0 -0
  448. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_plan.json +0 -0
  449. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_policy.json +0 -0
  450. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_profile.json +0 -0
  451. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_proto.json +0 -0
  452. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_r.json +0 -0
  453. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_redteam.json +0 -0
  454. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_route.json +0 -0
  455. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_screen.json +0 -0
  456. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_seroprev.json +0 -0
  457. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_simlab.json +0 -0
  458. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_twincal.json +0 -0
  459. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_uq.json +0 -0
  460. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_v.json +0 -0
  461. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_vcell.json +0 -0
  462. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_verify.json +0 -0
  463. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_writer.json +0 -0
  464. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_writespec.json +0 -0
  465. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_wv.json +0 -0
  466. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/paper1.yaml +0 -0
  467. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/paper2.yaml +0 -0
  468. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/paper3.yaml +0 -0
  469. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/paper4.yaml +0 -0
  470. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/phase0.yaml +0 -0
  471. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_a.yaml +0 -0
  472. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_acq.yaml +0 -0
  473. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_aldesign.yaml +0 -0
  474. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_alvalidate.yaml +0 -0
  475. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_atlas.yaml +0 -0
  476. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_b.yaml +0 -0
  477. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_ba.yaml +0 -0
  478. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_ba_v33.yaml +0 -0
  479. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_ba_v45.yaml +0 -0
  480. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_bench.yaml +0 -0
  481. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_c.yaml +0 -0
  482. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_cal.yaml +0 -0
  483. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_calib.yaml +0 -0
  484. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_challenge.yaml +0 -0
  485. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_chat.yaml +0 -0
  486. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_cite.yaml +0 -0
  487. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_closedloop.yaml +0 -0
  488. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_continual.yaml +0 -0
  489. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_cosci2.yaml +0 -0
  490. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_crit.yaml +0 -0
  491. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_ct.yaml +0 -0
  492. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_d.yaml +0 -0
  493. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_delivery.yaml +0 -0
  494. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_drift.yaml +0 -0
  495. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_e.yaml +0 -0
  496. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_env.yaml +0 -0
  497. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_ep.yaml +0 -0
  498. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_epitope.yaml +0 -0
  499. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_expr2.yaml +0 -0
  500. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_f.yaml +0 -0
  501. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_frontend.yaml +0 -0
  502. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_g.yaml +0 -0
  503. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_gen.yaml +0 -0
  504. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_genotox.yaml +0 -0
  505. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_graph.yaml +0 -0
  506. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_h.yaml +0 -0
  507. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_hybrid.yaml +0 -0
  508. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_immune.yaml +0 -0
  509. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_immune2.yaml +0 -0
  510. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_ingest.yaml +0 -0
  511. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_innate.yaml +0 -0
  512. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_loop.yaml +0 -0
  513. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_manifest.yaml +0 -0
  514. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_mc.yaml +0 -0
  515. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_mcp.yaml +0 -0
  516. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_mech.yaml +0 -0
  517. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_mon.yaml +0 -0
  518. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_o.yaml +0 -0
  519. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_offtarget.yaml +0 -0
  520. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_openapi.yaml +0 -0
  521. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_oracle.yaml +0 -0
  522. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_orch.yaml +0 -0
  523. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_outcome.yaml +0 -0
  524. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_pareto.yaml +0 -0
  525. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_peg.yaml +0 -0
  526. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_penchat.yaml +0 -0
  527. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_plan.yaml +0 -0
  528. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_policy.yaml +0 -0
  529. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_profile.yaml +0 -0
  530. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_proto.yaml +0 -0
  531. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_r.yaml +0 -0
  532. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_redteam.yaml +0 -0
  533. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_route.yaml +0 -0
  534. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_screen.yaml +0 -0
  535. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_seroprev.yaml +0 -0
  536. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_simlab.yaml +0 -0
  537. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_twincal.yaml +0 -0
  538. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_uq.yaml +0 -0
  539. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_v.yaml +0 -0
  540. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_vcell.yaml +0 -0
  541. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_verify.yaml +0 -0
  542. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_writer.yaml +0 -0
  543. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_writespec.yaml +0 -0
  544. {pen_stack-7.1.4 → pen_stack-7.1.5}/prereg/ws_wv.yaml +0 -0
  545. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/build_capsid_fitness.py +0 -0
  546. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/build_rag_corpus.py +0 -0
  547. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/calibrate_immune_axes.py +0 -0
  548. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/fetch_licensed_sources.py +0 -0
  549. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/offtarget_chromatin_incremental.py +0 -0
  550. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/offtarget_chromatin_matched.py +0 -0
  551. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/offtarget_chromatin_validation.py +0 -0
  552. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/p1_build_atlas.py +0 -0
  553. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/p1_build_durability.py +0 -0
  554. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/p1_build_position_effect.py +0 -0
  555. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/p1_build_writer_eff.py +0 -0
  556. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/p1_export_tracks.py +0 -0
  557. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/p1_safety_concordance.py +0 -0
  558. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/p1_train_safety.py +0 -0
  559. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/p1_validation_report.py +0 -0
  560. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/p2_build_atlas.py +0 -0
  561. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/p3_benchmark_report.py +0 -0
  562. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/p4_genome_scan.py +0 -0
  563. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/p52_build_genotox_oracle.py +0 -0
  564. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/p53_build_epitope_oracle.py +0 -0
  565. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/ws_b_report.py +0 -0
  566. {pen_stack-7.1.4 → pen_stack-7.1.5}/scripts/ws_c_report.py +0 -0
  567. {pen_stack-7.1.4 → pen_stack-7.1.5}/setup.cfg +0 -0
@@ -3,6 +3,33 @@
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.1.5] - 2026-06-29 - Chromosome field: validation, gene concordance, context
7
+
8
+ ### Added
9
+ - The `chrom` design field was a free-text pass-through with no validation and no downstream effect. It is now
10
+ meaningful (`pen_stack/planner/chromosome.py`):
11
+ - **Validation** — the web form's Chromosome input is a controlled dropdown (chr1–chr22, chrX, chrY, chrM), so
12
+ an impossible value like `chrZZZ` can no longer be entered; `canonical_chromosome()` normalises/validates on
13
+ the backend (`chrX`/`X`/`x`, `chr1`/`1`, `chrM`/`chrMT`/`MT`, `23`→X, `24`→Y; rejects the rest).
14
+ - **Gene/chromosome concordance** — `verify()` now flags `chromosome_mismatch` when the entered chromosome does
15
+ not match the named gene's canonical location (e.g. *BRCA1 is on chr17, not chr1*), `chromosome_invalid` for a
16
+ non-standard value, and `chromosome_unverifiable` for an unknown gene. The web form shows the warning inline
17
+ with a one-click fix, driven by the new `GET /api/gene/location` endpoint. This closes the silent-mismatch gap.
18
+ - **Chromosome context** — `chromosome_context()` adds grounded, chromosome-driven advisories surfaced as scope
19
+ flags: **chrM** is not addressable by nuclear genome-writing tools (mtDNA needs DdCBE/TALED — out of scope),
20
+ **chrY** is male-specific with ampliconic repeats, **chrX** is hemizygous in 46,XY vs X-inactivated in 46,XX.
21
+ - The Design Studio **cell-type dropdown now shows writability-atlas coverage** (from `/api/celltypes`): K562 /
22
+ HepG2 / HSPC are labelled measured (full / full / partial), while h1_hesc / iPSC / CD8 T / PBMC are labelled
23
+ "no atlas" — so a data-gated cell type is no longer silently indistinguishable from a measured one (the same
24
+ honest-field principle as the chromosome field). The 7 cell types are unchanged and already matched the backend.
25
+
26
+ ### Note (honest scoping)
27
+ - The free-text chromosome does **not** move the scored locus: per-locus safety / durability / accessibility /
28
+ off-target are indexed by the gene's *resolved genomic coordinates* via the writability atlas, so a bare
29
+ chromosome string with no position cannot refine them. Rather than fabricate a per-chromosome score delta, the
30
+ field's grounded effect is validation + gene concordance (ensuring the score is read for the right locus, and
31
+ flagging when the entered chromosome disagrees with the gene) + the chromosome-context advisories above.
32
+
6
33
  ## [7.1.4] - 2026-06-29 - Germline-prohibition legality rule
7
34
 
8
35
  ### Added
@@ -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: 7.1.4
4
+ version: 7.1.5
5
5
  date-released: 2026-06-29
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: 7.1.4
3
+ Version: 7.1.5
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
@@ -1,2 +1,2 @@
1
1
  """PEN-STACK v3.0 - open infrastructure for genome writing."""
2
- __version__ = "7.1.4"
2
+ __version__ = "7.1.5"
@@ -0,0 +1,106 @@
1
+ """Chromosome validation, gene/chromosome concordance, and chromosome-context advisories (v7.1.5).
2
+
3
+ The `chrom` field on a design was previously a free-text pass-through with no validation and no downstream
4
+ effect. This module makes it meaningful WITHOUT fabricating a score: the engine's per-locus safety / durability /
5
+ accessibility / off-target numbers are indexed by the GENE's resolved genomic coordinates via the writability
6
+ atlas (`planner.optimize.gene_region`), not by a free-text chromosome string - a bare "chrX" with no position
7
+ cannot index a specific locus value. So the honest, grounded use of the field is:
8
+
9
+ * `canonical_chromosome` - validate / normalise to a standard human chromosome (chr1-chr22, chrX, chrY, chrM);
10
+ * `gene_chromosome` - the gene's canonical chromosome from the gene-coordinate table;
11
+ * `chromosome_concordance` - flag when the entered chromosome does not match the named gene's real location
12
+ (the "BRCA1 is on chr17, not chr1" case), making explicit that scoring uses the gene's canonical locus;
13
+ * `chromosome_context` - chromosome-driven advisories that ARE grounded in biology: chrM is not addressable by
14
+ nuclear genome-writing tools (mtDNA needs DdCBE/TALED - out of scope), chrY is male-specific with ampliconic
15
+ repeats, chrX is hemizygous in 46,XY vs X-inactivated in 46,XX.
16
+ """
17
+ from __future__ import annotations
18
+
19
+ import re
20
+
21
+ STANDARD_CHROMOSOMES = [f"chr{i}" for i in range(1, 23)] + ["chrX", "chrY", "chrM"]
22
+
23
+
24
+ def canonical_chromosome(chrom: str | None) -> str | None:
25
+ """Normalise a chromosome string to canonical UCSC form (chr1..chr22, chrX, chrY, chrM), or None if it is not
26
+ a standard human chromosome. Accepts 'chrX'/'X'/'x', 'chr1'/'1', 'chrM'/'chrMT'/'MT', '23'->X, '24'->Y."""
27
+ if chrom is None:
28
+ return None
29
+ c = re.sub(r"\s+", "", str(chrom)).lower()
30
+ if not c:
31
+ return None
32
+ if c.startswith("chr"):
33
+ c = c[3:]
34
+ c = {"mt": "m", "23": "x", "24": "y", "25": "m"}.get(c, c)
35
+ if c in {"x", "y", "m"}:
36
+ return "chr" + c.upper()
37
+ if c.isdigit() and 1 <= int(c) <= 22:
38
+ return "chr" + c
39
+ return None
40
+
41
+
42
+ def gene_chromosome(gene: str | None) -> str | None:
43
+ """The canonical chromosome of a gene (or safe-harbour locus nickname), from the gene-coordinate table; None
44
+ if the gene is unknown."""
45
+ if not gene:
46
+ return None
47
+ try:
48
+ from pen_stack.planner.optimize import gene_region
49
+ reg = gene_region(gene)
50
+ except Exception: # noqa: BLE001 - coords table absent (bare checkout) -> cannot resolve, do not fabricate
51
+ return None
52
+ return canonical_chromosome(reg[0]) if reg else None
53
+
54
+
55
+ def chromosome_concordance(gene: str | None, chrom: str | None) -> dict:
56
+ """Validate the entered chromosome and check it against the named gene's canonical location.
57
+
58
+ status is one of:
59
+ * 'invalid' - the entered string is not a standard human chromosome;
60
+ * 'mismatch' - valid, but does not match the gene's canonical chromosome (the silent-mismatch case);
61
+ * 'match' - matches the gene's canonical chromosome;
62
+ * 'unverifiable' - valid chromosome but the gene's location is unknown (cannot confirm);
63
+ * 'none' - no chromosome supplied.
64
+ """
65
+ entered = canonical_chromosome(chrom)
66
+ gchrom = gene_chromosome(gene)
67
+ out = {"entered_raw": chrom, "entered": entered, "valid": entered is not None,
68
+ "gene": gene, "gene_chrom": gchrom}
69
+ if chrom in (None, "") or str(chrom).strip() == "":
70
+ out["status"] = "none"
71
+ out["message"] = None
72
+ elif entered is None:
73
+ out["status"] = "invalid"
74
+ out["message"] = (f"'{chrom}' is not a standard human chromosome. Use chr1-chr22, chrX, chrY, or chrM.")
75
+ elif gchrom and entered != gchrom:
76
+ out["status"] = "mismatch"
77
+ out["message"] = (f"{gene} is on {gchrom}, not {entered}. Locus scoring uses {gene}'s canonical location "
78
+ f"({gchrom}); the entered chromosome does not move the locus.")
79
+ elif gchrom and entered == gchrom:
80
+ out["status"] = "match"
81
+ out["message"] = f"{entered} matches the canonical location of {gene}."
82
+ else:
83
+ out["status"] = "unverifiable"
84
+ out["message"] = (f"{entered} is a valid chromosome, but {gene or 'the gene'} is not in the coordinate "
85
+ "table, so the gene/chromosome match cannot be confirmed.")
86
+ return out
87
+
88
+
89
+ def chromosome_context(chrom: str | None) -> dict | None:
90
+ """A grounded, chromosome-driven advisory (or None for an autosome). These are real biological constraints
91
+ the chromosome identity alone implies; magnitudes remain locus/subject-dependent (not predicted here)."""
92
+ c = canonical_chromosome(chrom)
93
+ if c == "chrM":
94
+ return {"chrom": "chrM", "severity": "high",
95
+ "note": ("the mitochondrial genome is NOT addressable by nuclear genome-writing tools "
96
+ "(integrases / recombinases / nuclear-targeted Cas9); mtDNA editing requires "
97
+ "mitochondrially-targeted base editors (DdCBE / TALED) - out of scope for this tool.")}
98
+ if c == "chrY":
99
+ return {"chrom": "chrY", "severity": "medium",
100
+ "note": ("the Y chromosome is male-specific (absent in 46,XX) and rich in ampliconic / palindromic "
101
+ "repeats, so confirm the target is single-copy before trusting a unique-site assumption.")}
102
+ if c == "chrX":
103
+ return {"chrom": "chrX", "severity": "low",
104
+ "note": ("the X chromosome is hemizygous in 46,XY (one copy) but subject to X-inactivation in "
105
+ "46,XX (mosaic expression); dosage and durability are sex- and locus-dependent.")}
106
+ return None
@@ -119,6 +119,23 @@ def crosslink_loci(request: Request, family: str, ct: str = "k562", cell_type: s
119
119
  return {"family": family, "ct": ct, "loci": _records(loci), "disclaimer": _DISCLAIMER}
120
120
 
121
121
 
122
+ @app.get("/gene/location")
123
+ def gene_location(gene: str):
124
+ """v7.1.5: the canonical chromosome of a gene (or safe-harbour locus nickname), for the UI's gene/chromosome
125
+ concordance check. found=False when the gene is not in the coordinate table (no fabrication)."""
126
+ from pen_stack.planner.chromosome import canonical_chromosome
127
+ from pen_stack.planner.optimize import gene_region, resolve_gene
128
+ try:
129
+ reg = gene_region(gene)
130
+ except Exception: # noqa: BLE001 - coords table absent -> cannot resolve
131
+ reg = None
132
+ resolved = resolve_gene(gene)
133
+ if reg is None:
134
+ return {"gene": gene, "resolved": resolved, "found": False, "chrom": None}
135
+ return {"gene": gene, "resolved": resolved, "found": True, "chrom": canonical_chromosome(reg[0]),
136
+ "start": int(reg[1]), "end": int(reg[2])}
137
+
138
+
122
139
  @app.get("/writable")
123
140
  def writable(request: Request, gene: str, ct: str = "k562", cell_type: str | None = None,
124
141
  top: int = Query(20, le=200)):
@@ -98,6 +98,18 @@ def verify(design: Design | dict, question: str | None = None, *, actor: str = "
98
98
  for r in results if r["kind"] == "scope_flag" and r["status"] == "scope"]
99
99
  scope_flags += rule_scope
100
100
 
101
+ # v7.1.5: chromosome validation + gene/chromosome concordance + chromosome-context advisory. The free-text
102
+ # chrom field does not move the scored locus (scoring is indexed by the gene's resolved coordinates), so a
103
+ # mismatch / invalid value / chromosome-context note is surfaced as a scope flag, never silently ignored.
104
+ from pen_stack.planner.chromosome import chromosome_concordance, chromosome_context
105
+ conc = chromosome_concordance(design.gene, getattr(design, "chrom", None))
106
+ if conc["status"] in ("invalid", "mismatch", "unverifiable"):
107
+ scope_flags.append({"kind": f"chromosome_{conc['status']}", "reason": conc["message"],
108
+ "entered": conc["entered"], "gene_chrom": conc["gene_chrom"]})
109
+ ctx = chromosome_context(getattr(design, "chrom", None))
110
+ if ctx:
111
+ scope_flags.append({"kind": "chromosome_context", "chrom": ctx["chrom"], "reason": ctx["note"]})
112
+
101
113
  pc = _plan_confidence(design)
102
114
  verdict = classify(grounded=True, confidence=pc["confidence"], out_of_scope=oos_hit)
103
115
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pen-stack
3
- Version: 7.1.4
3
+ Version: 7.1.5
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
@@ -252,6 +252,7 @@ pen_stack/planner/antipeg_oracle.py
252
252
  pen_stack/planner/capsid_epitope_oracle.py
253
253
  pen_stack/planner/cargo.py
254
254
  pen_stack/planner/cargo_polish.py
255
+ pen_stack/planner/chromosome.py
255
256
  pen_stack/planner/delivery.py
256
257
  pen_stack/planner/delivery_constraints.py
257
258
  pen_stack/planner/delivery_immune.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pen-stack"
7
- version = "7.1.4"
7
+ version = "7.1.5"
8
8
  description = "Open infrastructure for genome writing: the Writable Genome atlas, the Writer Atlas, and the Write Planner."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes