pen-stack 7.1.1__tar.gz → 7.1.3__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 (566) hide show
  1. {pen_stack-7.1.1 → pen_stack-7.1.3}/CHANGELOG.md +63 -0
  2. {pen_stack-7.1.1 → pen_stack-7.1.3}/CITATION.cff +2 -2
  3. {pen_stack-7.1.1 → pen_stack-7.1.3}/PKG-INFO +17 -14
  4. {pen_stack-7.1.1 → pen_stack-7.1.3}/README.md +16 -13
  5. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/safety/hazard_registry.yaml +63 -0
  6. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/__init__.py +1 -1
  7. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/design/generate.py +14 -3
  8. pen_stack-7.1.3/pen_stack/design/space.py +136 -0
  9. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/rag/embed.py +19 -0
  10. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/rag/ground.py +3 -2
  11. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/rag/retrieve.py +2 -2
  12. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/safety/registry.py +68 -3
  13. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/safety/screen.py +2 -1
  14. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/server/api.py +22 -3
  15. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/web/llm.py +7 -4
  16. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/web/llm_provider.py +30 -10
  17. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack.egg-info/PKG-INFO +17 -14
  18. {pen_stack-7.1.1 → pen_stack-7.1.3}/pyproject.toml +1 -1
  19. pen_stack-7.1.1/pen_stack/design/space.py +0 -85
  20. {pen_stack-7.1.1 → pen_stack-7.1.3}/LICENSE +0 -0
  21. {pen_stack-7.1.1 → pen_stack-7.1.3}/MANIFEST.in +0 -0
  22. {pen_stack-7.1.1 → pen_stack-7.1.3}/bench/run.py +0 -0
  23. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/chat_grounding/README.md +0 -0
  24. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/chat_grounding/SHA256SUMS +0 -0
  25. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/chat_headtohead/README.md +0 -0
  26. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/chat_routing/README.md +0 -0
  27. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/chat_routing/SHA256SUMS +0 -0
  28. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/chat_safety/README.md +0 -0
  29. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/chat_safety/SHA256SUMS +0 -0
  30. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/delivery/SHA256SUMS +0 -0
  31. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/genome_writing_bench/LEADERBOARD.md +0 -0
  32. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/genome_writing_bench/README.md +0 -0
  33. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/genome_writing_bench/SHA256SUMS +0 -0
  34. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/genome_writing_bench/SUBMISSIONS.md +0 -0
  35. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/genome_writing_bench/tasks.yaml +0 -0
  36. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/genome_writing_challenge/README.md +0 -0
  37. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/genome_writing_challenge/SUBMISSIONS.md +0 -0
  38. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/loop/SHA256SUMS +0 -0
  39. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/offtarget/SHA256SUMS +0 -0
  40. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/oracle/SHA256SUMS +0 -0
  41. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/position_effect/README.md +0 -0
  42. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/position_effect/SHA256SUMS +0 -0
  43. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/verify/SHA256SUMS +0 -0
  44. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/writer_efficiency/README.md +0 -0
  45. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/writer_efficiency/SHA256SUMS +0 -0
  46. {pen_stack-7.1.1 → pen_stack-7.1.3}/benchmarks/writespec/SHA256SUMS +0 -0
  47. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/aav_serotype_tropism.yaml +0 -0
  48. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/antipeg.yaml +0 -0
  49. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/atlas_families.yaml +0 -0
  50. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/bridge_offtarget_profile.yaml +0 -0
  51. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/calibration/preexisting_nab_independent.yaml +0 -0
  52. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/capsid_epitope_oracle.yaml +0 -0
  53. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/capsid_sequences.fasta +0 -0
  54. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/cargo_polish.yaml +0 -0
  55. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/cell_types.yaml +0 -0
  56. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/datasets.yaml +0 -0
  57. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/delivery_constraints.yaml +0 -0
  58. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/delivery_rules.yaml +0 -0
  59. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/delivery_vehicles.yaml +0 -0
  60. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/expression/modifiers.yaml +0 -0
  61. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/expression/promoters.yaml +0 -0
  62. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/gates_v3.yaml +0 -0
  63. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/genotoxicity_oracle.yaml +0 -0
  64. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/gsh_validated_heldout.yaml +0 -0
  65. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/intent_weights.yaml +0 -0
  66. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/known_unknowns.yaml +0 -0
  67. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/llm.yaml +0 -0
  68. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/metric_guide.yaml +0 -0
  69. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/mhc_epitope_oracle.yaml +0 -0
  70. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/monitor_queries.yaml +0 -0
  71. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/oracles/execution.yaml +0 -0
  72. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/oracles/reliability.yaml +0 -0
  73. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/oracles/scope_cards.yaml +0 -0
  74. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/rules/delivery.yaml +0 -0
  75. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/rules/fold.yaml +0 -0
  76. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/rules/multiplex.yaml +0 -0
  77. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/rules/payload.yaml +0 -0
  78. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/rules/reachability.yaml +0 -0
  79. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/safety/policy.yaml +0 -0
  80. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/safety/probes.yaml +0 -0
  81. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/score_axes.yaml +0 -0
  82. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/seroprevalence.yaml +0 -0
  83. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/target_sites.yaml +0 -0
  84. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/universe_crosswalk.yaml +0 -0
  85. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/write_types.yaml +0 -0
  86. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/writer_sequences.fasta +0 -0
  87. {pen_stack-7.1.1 → pen_stack-7.1.3}/configs/wtkb_curated.yaml +0 -0
  88. {pen_stack-7.1.1 → pen_stack-7.1.3}/data/curated/bridge_offtarget_energetics.json +0 -0
  89. {pen_stack-7.1.1 → pen_stack-7.1.3}/data/curated/bridge_offtarget_profile_measured.parquet +0 -0
  90. {pen_stack-7.1.1 → pen_stack-7.1.3}/data/curated/gene_coords.parquet +0 -0
  91. {pen_stack-7.1.1 → pen_stack-7.1.3}/data/curated/unified_editor_universe.parquet +0 -0
  92. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/BACKLOG.md +0 -0
  93. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/DEPLOY.md +0 -0
  94. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/INFRA.md +0 -0
  95. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/MCP.md +0 -0
  96. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/RELEASING.md +0 -0
  97. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/REPRO.md +0 -0
  98. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/STABILITY.md +0 -0
  99. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/agent.md +0 -0
  100. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/alphagenome_feasibility.md +0 -0
  101. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/autonomy.md +0 -0
  102. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/benchmark_circularity.md +0 -0
  103. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/biosecurity.md +0 -0
  104. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/build_interface.md +0 -0
  105. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/cards/atlas.md +0 -0
  106. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/cards/durability.md +0 -0
  107. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/cards/offtarget_data.md +0 -0
  108. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/cards/position_effect_data.md +0 -0
  109. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/cards/safety.md +0 -0
  110. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/cards/writer_efficiency_data.md +0 -0
  111. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/challenge.md +0 -0
  112. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/closed_loop.md +0 -0
  113. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/co_scientist.md +0 -0
  114. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/co_scientist_loop.md +0 -0
  115. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/delivery.md +0 -0
  116. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/delivery_immunology.md +0 -0
  117. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/delivery_recommender.md +0 -0
  118. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/digital_twin.md +0 -0
  119. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/dissemination.md +0 -0
  120. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/environment.md +0 -0
  121. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/experiment_design.md +0 -0
  122. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/generative_design.md +0 -0
  123. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/immune_profiler.md +0 -0
  124. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/index.md +0 -0
  125. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/integrations.md +0 -0
  126. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/live_oracles.md +0 -0
  127. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/mechanistic_constraints.md +0 -0
  128. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/offtarget.md +0 -0
  129. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/oracle_mesh.md +0 -0
  130. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/oracles.md +0 -0
  131. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/position_effect.md +0 -0
  132. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/positioning.md +0 -0
  133. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/private_data_formats.md +0 -0
  134. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/quickstart.md +0 -0
  135. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/responsible_use.md +0 -0
  136. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/rule_spec.md +0 -0
  137. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/rules.md +0 -0
  138. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/scope.md +0 -0
  139. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/scorecard.md +0 -0
  140. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/tpe_bench.md +0 -0
  141. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/tutorials/compare-families.md +0 -0
  142. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/tutorials/score-deliverability.md +0 -0
  143. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/tutorials/where-can-i-write.md +0 -0
  144. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/tutorials/which-writer-reaches-locus.md +0 -0
  145. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/uncertainty.md +0 -0
  146. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/verify.md +0 -0
  147. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/verify_service.md +0 -0
  148. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/world_model.md +0 -0
  149. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/writer_efficiency.md +0 -0
  150. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/writer_verification.md +0 -0
  151. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/writespec_bench.md +0 -0
  152. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/writespec_profile.md +0 -0
  153. {pen_stack-7.1.1 → pen_stack-7.1.3}/docs/wtkb.md +0 -0
  154. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/_resources.py +0 -0
  155. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/active/__init__.py +0 -0
  156. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/active/acquire.py +0 -0
  157. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/active/brains.py +0 -0
  158. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/active/campaign.py +0 -0
  159. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/active/design.py +0 -0
  160. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/active/validate.py +0 -0
  161. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/adapt/__init__.py +0 -0
  162. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/adapt/finetune.py +0 -0
  163. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/adapt/ingest.py +0 -0
  164. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/adapt/pipeline.py +0 -0
  165. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/adapt/recalibrate.py +0 -0
  166. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/adapt/report.py +0 -0
  167. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/agent/__init__.py +0 -0
  168. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/agent/cite.py +0 -0
  169. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/agent/co_scientist.py +0 -0
  170. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/agent/epistemic.py +0 -0
  171. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/agent/guardrails.py +0 -0
  172. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/agent/mcp_server.py +0 -0
  173. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/agent/orchestrator.py +0 -0
  174. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/agent/orchestrator_live.py +0 -0
  175. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/agent/pen_agent.py +0 -0
  176. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/agent/scope.py +0 -0
  177. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/agent/tools.py +0 -0
  178. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/api/__init__.py +0 -0
  179. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/api/manifest.py +0 -0
  180. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/atlas/__init__.py +0 -0
  181. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/atlas/build_wtkb.py +0 -0
  182. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/atlas/crosslink.py +0 -0
  183. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/atlas/expand.py +0 -0
  184. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/atlas/guide_design.py +0 -0
  185. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/atlas/schema.py +0 -0
  186. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/atlas/scorecard.py +0 -0
  187. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/atlas/universe.py +0 -0
  188. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/atlas/variant_propose.py +0 -0
  189. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/atlas/writer_efficiency.py +0 -0
  190. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/atlas/writer_predict.py +0 -0
  191. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/atlas/writer_recommend.py +0 -0
  192. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/atlas/writer_verify.py +0 -0
  193. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/bridge/__init__.py +0 -0
  194. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/bridge/activity.py +0 -0
  195. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/bridge/cli.py +0 -0
  196. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/bridge/fold_qc.py +0 -0
  197. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/bridge/guide_qc.py +0 -0
  198. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/bridge/ingest.py +0 -0
  199. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/bridge/offtarget.py +0 -0
  200. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/bridge/offtarget_energetics.py +0 -0
  201. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/bridge/ortholog_screen.py +0 -0
  202. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/bridge/pipeline.py +0 -0
  203. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/build/__init__.py +0 -0
  204. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/build/cloudlab.py +0 -0
  205. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/build/ingest.py +0 -0
  206. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/build/protocol.py +0 -0
  207. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/build/simlab.py +0 -0
  208. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/cli.py +0 -0
  209. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/data/__init__.py +0 -0
  210. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/data/encode.py +0 -0
  211. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/data/genome.py +0 -0
  212. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/data/ingest_chromatin.py +0 -0
  213. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/data/ingest_integration.py +0 -0
  214. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/data/ingest_safety_annot.py +0 -0
  215. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/data/ingest_trip.py +0 -0
  216. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/design/__init__.py +0 -0
  217. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/design/capsid_generate.py +0 -0
  218. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/design/pareto.py +0 -0
  219. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/design/writer_variants.py +0 -0
  220. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/env/__init__.py +0 -0
  221. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/env/genome_writing_env.py +0 -0
  222. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/env/policies.py +0 -0
  223. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/graph/__init__.py +0 -0
  224. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/graph/build.py +0 -0
  225. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/graph/cell_types.py +0 -0
  226. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/graph/ingest.py +0 -0
  227. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/graph/query.py +0 -0
  228. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/graph/schema.py +0 -0
  229. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/loop/__init__.py +0 -0
  230. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/loop/continual.py +0 -0
  231. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/loop/cycle.py +0 -0
  232. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/loop/drift.py +0 -0
  233. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/mech/__init__.py +0 -0
  234. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/mech/classify_atlas.py +0 -0
  235. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/mech/whitelist.py +0 -0
  236. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/monitor/__init__.py +0 -0
  237. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/monitor/europepmc.py +0 -0
  238. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/monitor/run.py +0 -0
  239. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/monitor/triage.py +0 -0
  240. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/oracles/__init__.py +0 -0
  241. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/oracles/affinity.py +0 -0
  242. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/oracles/cache.py +0 -0
  243. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/oracles/energetics.py +0 -0
  244. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/oracles/genome.py +0 -0
  245. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/oracles/protein_design.py +0 -0
  246. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/oracles/reliability.py +0 -0
  247. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/oracles/rna.py +0 -0
  248. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/oracles/schema.py +0 -0
  249. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/oracles/status.py +0 -0
  250. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/oracles/structure.py +0 -0
  251. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/oracles/structure_run.py +0 -0
  252. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/oracles/vcell.py +0 -0
  253. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/__init__.py +0 -0
  254. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/ada_risk.py +0 -0
  255. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/antipeg_oracle.py +0 -0
  256. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/capsid_epitope_oracle.py +0 -0
  257. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/cargo.py +0 -0
  258. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/cargo_polish.py +0 -0
  259. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/delivery.py +0 -0
  260. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/delivery_constraints.py +0 -0
  261. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/delivery_immune.py +0 -0
  262. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/delivery_immunology.py +0 -0
  263. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/delivery_predict.py +0 -0
  264. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/delivery_vehicles.py +0 -0
  265. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/genotoxicity_oracle.py +0 -0
  266. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/immune_mhc2.py +0 -0
  267. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/immune_profile.py +0 -0
  268. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/innate_sensing.py +0 -0
  269. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/multiplex.py +0 -0
  270. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/optimize.py +0 -0
  271. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/pipeline.py +0 -0
  272. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/report.py +0 -0
  273. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/router.py +0 -0
  274. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/seroprevalence_oracle.py +0 -0
  275. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/planner/target_site.py +0 -0
  276. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/rag/__init__.py +0 -0
  277. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/rag/corpus.py +0 -0
  278. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/rag/index.py +0 -0
  279. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/rag/llm.py +0 -0
  280. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/rag/qa.py +0 -0
  281. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/rules/__init__.py +0 -0
  282. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/rules/evaluators.py +0 -0
  283. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/rules/loader.py +0 -0
  284. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/rules/schema.py +0 -0
  285. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/rules/solver.py +0 -0
  286. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/rules/spec.py +0 -0
  287. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/safety/__init__.py +0 -0
  288. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/safety/audit.py +0 -0
  289. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/safety/gate.py +0 -0
  290. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/safety/policy.py +0 -0
  291. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/safety/redteam.py +0 -0
  292. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/safety/standards.py +0 -0
  293. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/score/__init__.py +0 -0
  294. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/score/recalibrate.py +0 -0
  295. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/score/therapeutic.py +0 -0
  296. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/server/__init__.py +0 -0
  297. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/spec/__init__.py +0 -0
  298. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/spec/clarify.py +0 -0
  299. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/spec/extract.py +0 -0
  300. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/spec/resolvers/__init__.py +0 -0
  301. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/spec/resolvers/cell.py +0 -0
  302. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/spec/resolvers/chem.py +0 -0
  303. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/spec/resolvers/feature.py +0 -0
  304. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/spec/resolvers/gene.py +0 -0
  305. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/spec/resolvers/locus.py +0 -0
  306. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/spec/resolvers/phenotype.py +0 -0
  307. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/spec/satisfy.py +0 -0
  308. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/spec/service.py +0 -0
  309. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/spec/writespec.py +0 -0
  310. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/twin/__init__.py +0 -0
  311. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/twin/calibrate.py +0 -0
  312. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/twin/data/__init__.py +0 -0
  313. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/twin/data/position_effect.py +0 -0
  314. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/twin/mechanistic.py +0 -0
  315. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/twin/outcome.py +0 -0
  316. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/twin/position_effect.py +0 -0
  317. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/ui/__init__.py +0 -0
  318. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/ui/app.py +0 -0
  319. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/__init__.py +0 -0
  320. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/adapt_demo.py +0 -0
  321. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/agent_eval.py +0 -0
  322. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/bench_adversarial_tasks.py +0 -0
  323. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/bench_coscientist_tasks.py +0 -0
  324. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/bench_graph_tasks.py +0 -0
  325. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/bench_rule_tasks.py +0 -0
  326. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/bench_trust_tasks.py +0 -0
  327. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/bench_writetype_tasks.py +0 -0
  328. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/blind_gsh_discovery.py +0 -0
  329. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/cargo_directionality.py +0 -0
  330. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/closed_loop.py +0 -0
  331. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/durability_baselines.py +0 -0
  332. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/experiment_design.py +0 -0
  333. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/expr_controls.py +0 -0
  334. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/forward_hypotheses.py +0 -0
  335. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/generative_design.py +0 -0
  336. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/guide_qc_demo.py +0 -0
  337. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/heldout_celltype_expr.py +0 -0
  338. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/immune_calibration.py +0 -0
  339. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/intent_specification.py +0 -0
  340. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/known_biology_expr.py +0 -0
  341. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/offtarget_energetics_eval.py +0 -0
  342. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/out_of_scope_refusal.py +0 -0
  343. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/outcome_calibration.py +0 -0
  344. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/outcome_prediction.py +0 -0
  345. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/paper3_benchmark.py +0 -0
  346. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/paper4_real_validation.py +0 -0
  347. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/paper4_validation.py +0 -0
  348. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/protocol_safety.py +0 -0
  349. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/safety_screening.py +0 -0
  350. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/selective_prediction.py +0 -0
  351. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/seq_vs_measured.py +0 -0
  352. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/target_site_controls.py +0 -0
  353. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/uncertainty_eval.py +0 -0
  354. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/ungrounded_baseline.py +0 -0
  355. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/within_locus_ranking.py +0 -0
  356. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/validate/writer_recovery.py +0 -0
  357. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/verify/__init__.py +0 -0
  358. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/verify/proof.py +0 -0
  359. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/verify/schema.py +0 -0
  360. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/verify/service.py +0 -0
  361. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/web/__init__.py +0 -0
  362. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/web/guide.py +0 -0
  363. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/web/router.py +0 -0
  364. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/web/server.py +0 -0
  365. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/web/tools.py +0 -0
  366. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/wgenome/__init__.py +0 -0
  367. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/wgenome/chromatin_seq.py +0 -0
  368. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/wgenome/durability.py +0 -0
  369. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/wgenome/export_tracks.py +0 -0
  370. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/wgenome/features.py +0 -0
  371. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/wgenome/gsh_baseline.py +0 -0
  372. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/wgenome/mesh_features.py +0 -0
  373. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/wgenome/offtarget_assay.py +0 -0
  374. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/wgenome/offtarget_data.py +0 -0
  375. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/wgenome/offtarget_predict.py +0 -0
  376. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/wgenome/ood.py +0 -0
  377. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/wgenome/providers.py +0 -0
  378. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/wgenome/safety.py +0 -0
  379. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/wgenome/structure3d.py +0 -0
  380. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/wgenome/uncertainty.py +0 -0
  381. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack/wgenome/writability.py +0 -0
  382. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack.egg-info/SOURCES.txt +0 -0
  383. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack.egg-info/dependency_links.txt +0 -0
  384. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack.egg-info/entry_points.txt +0 -0
  385. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack.egg-info/requires.txt +0 -0
  386. {pen_stack-7.1.1 → pen_stack-7.1.3}/pen_stack.egg-info/top_level.txt +0 -0
  387. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_phase0.json +0 -0
  388. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_phase1_5.json +0 -0
  389. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_phase2.json +0 -0
  390. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_phase3.json +0 -0
  391. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_a.json +0 -0
  392. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_acq.json +0 -0
  393. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_aldesign.json +0 -0
  394. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_alvalidate.json +0 -0
  395. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_atlas.json +0 -0
  396. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_b.json +0 -0
  397. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_ba.json +0 -0
  398. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_ba_v33.json +0 -0
  399. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_ba_v45.json +0 -0
  400. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_bench.json +0 -0
  401. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_c.json +0 -0
  402. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_cal.json +0 -0
  403. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_calib.json +0 -0
  404. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_challenge.json +0 -0
  405. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_chat.json +0 -0
  406. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_cite.json +0 -0
  407. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_closedloop.json +0 -0
  408. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_continual.json +0 -0
  409. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_cosci2.json +0 -0
  410. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_crit.json +0 -0
  411. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_ct.json +0 -0
  412. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_d.json +0 -0
  413. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_delivery.json +0 -0
  414. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_drift.json +0 -0
  415. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_e.json +0 -0
  416. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_env.json +0 -0
  417. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_ep.json +0 -0
  418. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_epitope.json +0 -0
  419. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_expr2.json +0 -0
  420. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_f.json +0 -0
  421. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_frontend.json +0 -0
  422. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_g.json +0 -0
  423. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_gen.json +0 -0
  424. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_genotox.json +0 -0
  425. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_graph.json +0 -0
  426. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_h.json +0 -0
  427. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_hybrid.json +0 -0
  428. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_immune.json +0 -0
  429. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_immune2.json +0 -0
  430. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_ingest.json +0 -0
  431. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_innate.json +0 -0
  432. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_loop.json +0 -0
  433. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_manifest.json +0 -0
  434. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_mc.json +0 -0
  435. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_mcp.json +0 -0
  436. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_mech.json +0 -0
  437. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_mon.json +0 -0
  438. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_o.json +0 -0
  439. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_offtarget.json +0 -0
  440. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_openapi.json +0 -0
  441. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_oracle.json +0 -0
  442. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_orch.json +0 -0
  443. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_outcome.json +0 -0
  444. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_pareto.json +0 -0
  445. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_peg.json +0 -0
  446. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_penchat.json +0 -0
  447. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_plan.json +0 -0
  448. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_policy.json +0 -0
  449. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_profile.json +0 -0
  450. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_proto.json +0 -0
  451. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_r.json +0 -0
  452. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_redteam.json +0 -0
  453. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_route.json +0 -0
  454. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_screen.json +0 -0
  455. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_seroprev.json +0 -0
  456. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_simlab.json +0 -0
  457. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_twincal.json +0 -0
  458. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_uq.json +0 -0
  459. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_v.json +0 -0
  460. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_vcell.json +0 -0
  461. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_verify.json +0 -0
  462. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_writer.json +0 -0
  463. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_writespec.json +0 -0
  464. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/SHA256_LOCK_ws_wv.json +0 -0
  465. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/paper1.yaml +0 -0
  466. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/paper2.yaml +0 -0
  467. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/paper3.yaml +0 -0
  468. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/paper4.yaml +0 -0
  469. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/phase0.yaml +0 -0
  470. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_a.yaml +0 -0
  471. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_acq.yaml +0 -0
  472. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_aldesign.yaml +0 -0
  473. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_alvalidate.yaml +0 -0
  474. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_atlas.yaml +0 -0
  475. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_b.yaml +0 -0
  476. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_ba.yaml +0 -0
  477. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_ba_v33.yaml +0 -0
  478. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_ba_v45.yaml +0 -0
  479. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_bench.yaml +0 -0
  480. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_c.yaml +0 -0
  481. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_cal.yaml +0 -0
  482. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_calib.yaml +0 -0
  483. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_challenge.yaml +0 -0
  484. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_chat.yaml +0 -0
  485. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_cite.yaml +0 -0
  486. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_closedloop.yaml +0 -0
  487. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_continual.yaml +0 -0
  488. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_cosci2.yaml +0 -0
  489. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_crit.yaml +0 -0
  490. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_ct.yaml +0 -0
  491. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_d.yaml +0 -0
  492. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_delivery.yaml +0 -0
  493. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_drift.yaml +0 -0
  494. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_e.yaml +0 -0
  495. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_env.yaml +0 -0
  496. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_ep.yaml +0 -0
  497. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_epitope.yaml +0 -0
  498. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_expr2.yaml +0 -0
  499. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_f.yaml +0 -0
  500. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_frontend.yaml +0 -0
  501. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_g.yaml +0 -0
  502. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_gen.yaml +0 -0
  503. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_genotox.yaml +0 -0
  504. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_graph.yaml +0 -0
  505. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_h.yaml +0 -0
  506. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_hybrid.yaml +0 -0
  507. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_immune.yaml +0 -0
  508. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_immune2.yaml +0 -0
  509. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_ingest.yaml +0 -0
  510. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_innate.yaml +0 -0
  511. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_loop.yaml +0 -0
  512. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_manifest.yaml +0 -0
  513. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_mc.yaml +0 -0
  514. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_mcp.yaml +0 -0
  515. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_mech.yaml +0 -0
  516. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_mon.yaml +0 -0
  517. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_o.yaml +0 -0
  518. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_offtarget.yaml +0 -0
  519. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_openapi.yaml +0 -0
  520. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_oracle.yaml +0 -0
  521. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_orch.yaml +0 -0
  522. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_outcome.yaml +0 -0
  523. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_pareto.yaml +0 -0
  524. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_peg.yaml +0 -0
  525. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_penchat.yaml +0 -0
  526. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_plan.yaml +0 -0
  527. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_policy.yaml +0 -0
  528. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_profile.yaml +0 -0
  529. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_proto.yaml +0 -0
  530. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_r.yaml +0 -0
  531. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_redteam.yaml +0 -0
  532. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_route.yaml +0 -0
  533. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_screen.yaml +0 -0
  534. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_seroprev.yaml +0 -0
  535. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_simlab.yaml +0 -0
  536. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_twincal.yaml +0 -0
  537. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_uq.yaml +0 -0
  538. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_v.yaml +0 -0
  539. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_vcell.yaml +0 -0
  540. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_verify.yaml +0 -0
  541. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_writer.yaml +0 -0
  542. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_writespec.yaml +0 -0
  543. {pen_stack-7.1.1 → pen_stack-7.1.3}/prereg/ws_wv.yaml +0 -0
  544. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/build_capsid_fitness.py +0 -0
  545. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/build_rag_corpus.py +0 -0
  546. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/calibrate_immune_axes.py +0 -0
  547. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/fetch_licensed_sources.py +0 -0
  548. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/offtarget_chromatin_incremental.py +0 -0
  549. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/offtarget_chromatin_matched.py +0 -0
  550. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/offtarget_chromatin_validation.py +0 -0
  551. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/p1_build_atlas.py +0 -0
  552. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/p1_build_durability.py +0 -0
  553. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/p1_build_position_effect.py +0 -0
  554. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/p1_build_writer_eff.py +0 -0
  555. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/p1_export_tracks.py +0 -0
  556. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/p1_safety_concordance.py +0 -0
  557. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/p1_train_safety.py +0 -0
  558. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/p1_validation_report.py +0 -0
  559. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/p2_build_atlas.py +0 -0
  560. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/p3_benchmark_report.py +0 -0
  561. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/p4_genome_scan.py +0 -0
  562. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/p52_build_genotox_oracle.py +0 -0
  563. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/p53_build_epitope_oracle.py +0 -0
  564. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/ws_b_report.py +0 -0
  565. {pen_stack-7.1.1 → pen_stack-7.1.3}/scripts/ws_c_report.py +0 -0
  566. {pen_stack-7.1.1 → pen_stack-7.1.3}/setup.cfg +0 -0
@@ -3,6 +3,69 @@
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.3] - 2026-06-26 - Designer correctness: Guardian biosecurity + calibrated confidence
7
+
8
+ ### Fixed
9
+ - **CRITICAL (Designer / Guardian biosecurity):** Hazardous cargo functions (e.g. furin-cleavage viral
10
+ tropism-enhancement, dominant-negative tumor-suppressor ablation) passed the Designer as "Safety: Clear" with
11
+ full survivor tables. Several root causes, all fixed:
12
+ - The hazard registry (`configs/safety/hazard_registry.yaml`) had **no signatures** for engineered viral tropism
13
+ enhancement or oncogenic tumor-suppressor ablation. Added `FUNC-VIRAL-TROPISM-ENHANCE` (furin cleavage /
14
+ receptor-binding / tropism, high severity) and `FUNC-ONCOGENIC-SUPPRESSOR` (dominant-negative TP53 / RB / PTEN,
15
+ apoptosis-checkpoint ablation, high severity), both DURC / HHS-P3CO categories.
16
+ - **Oncogenic-manipulation PATTERN screen** (`oncogenic_manipulation` in the registry +
17
+ `HazardRegistry.oncogenic_flags`): a flat keyword list is brittle to paraphrase — a red-team pass found the
18
+ Guardian caught only **1/8** mechanism/synonym phrasings ("R175H p53 abolishing transactivation", "PTEN
19
+ knockout", "RAS G12D constitutive activation", "hTERT immortalization", "APC frameshift", "EGFR
20
+ ligand-independent activation", "NF1+BAX/BAK knockout"). The pattern screen flags the *combination*
21
+ `(tumor-suppressor + disruptive verb)` OR `(oncogene + activating signature)` OR `immortalization`, which
22
+ catches **8/8** while the deliberate asymmetry spares therapy with **no allow-list** — restoring a suppressor or
23
+ silencing an oncogene matches neither, so "p53 correction to restore apoptosis", "TRAC/CCR5 knockout",
24
+ "knock-down of mutant KRAS" stay clear (**11/11** benign). Disposition is escalate (dual-use → human review).
25
+ - **Keyword matcher hardened** (`_kw_match`): a plain substring test made the ricin abbreviation `"rip"` fire
26
+ inside **"transc-rip-tion"** (a word in almost every editing design → benign cassettes false-refused as ricin),
27
+ and let a hyphenated `"furin-cleavage"` slip past the space-form keyword. Matching is now separator-insensitive
28
+ (`-`/`_`/space unified) and word-boundary anchored, fixing both the false positive and the evasion.
29
+ - The goal-based candidate path (`pen_stack/design/space.py::candidate_space`) **dropped** the goal's
30
+ `cargo_function`, so the Guardian in `verify()` screened nothing. It is now propagated onto every swept
31
+ candidate. The `/generate` endpoint additionally screens the goal's cargo function FIRST and returns an explicit
32
+ biosecurity refusal (`refused: true` + the safety verdict) so an empty table is correctly attributed to a
33
+ refusal, not a silent "no candidates".
34
+ - **CRITICAL (Designer / calibration):** Confidence was a constant `1.00 · [0.56, 0.71]` for every input because the
35
+ page hardcoded fake planner scores (0.7 / 0.6 / 0.5) on each candidate. The page now submits the design GOAL and
36
+ the engine plans real writable sites with grounded per-locus safety / durability / writer-activity, so the
37
+ confidence band is genuinely calibrated (it differs by locus/vehicle, e.g. F9 → `[0.866, 0.972]`, and is absent
38
+ for a refused design). `web/src/pages/Designer.jsx` rewritten to send a goal and render the refused / empty /
39
+ survivor states distinctly.
40
+ - **Designer (cell types without a measured atlas):** a goal in a cell type with no writability atlas (cd8_t /
41
+ pbmc / h1_hesc / ipsc) returned an empty table, because the planner-backed `candidate_space` needs `plan_write`.
42
+ `generate_designs` now falls back to `space.vehicle_sweep(goal)`: it sweeps the capacity-compatible vehicles,
43
+ carries `cargo_function` (the Guardian still screens), runs full legality + biosecurity discrimination, and
44
+ ABSTAINS on the calibrated confidence (no fabricated band) — surfaced as "abstained, no measured atlas for this
45
+ cell type". `candidate_space` still returns `[]` without the atlas; `generate_designs(candidates=[])` still
46
+ returns `[]`.
47
+ - **Designer (administration context):** the vehicle sweep now filters by the goal's `in_vivo` flag using the
48
+ curated `in_vivo` / `ex_vivo` route flags in `configs/delivery_vehicles.yaml` (an ex-vivo goal keeps
49
+ lentivirus / electroporation / eVLP; an in-vivo goal keeps AAV / LNP / HDAd / HSV / eVLP). Grounded from the
50
+ curated palette, not a clinical claim; `in_vivo=None` keeps all (existing callers/tests unchanged).
51
+
52
+ ## [7.1.2] - 2026-06-25 - PEN-CHAT: chat-response latency fix
53
+
54
+ ### Fixed
55
+ - Chat response time was unnecessarily high because every General-lane request paid for an Ollama embedding
56
+ round-trip on the query side, and the LLM call ran with a generous 150 s timeout / 450-token cap suited to the
57
+ engine-grounded design lane, not a textbook answer. Three minimal changes, no behaviour change for the grounded
58
+ lanes:
59
+ - `pen_stack/rag/embed.py` adds an LRU-cached `embed_query()` (256 entries) so a repeated phrasing skips the
60
+ embedder; `pen_stack/rag/retrieve.py` uses it.
61
+ - `pen_stack/web/llm_provider.py` now accepts `kind="general"`, which selects `PEN_STACK_LLM_TIMEOUT_GENERAL`
62
+ (45 s default, was 150 s) and `OLLAMA_NUM_PREDICT_GENERAL` / `NEMOTRON_MAX_TOKENS_GENERAL` (280 / 400, was
63
+ 450 / 700). The default-kind path used by the engine-grounded design / explain / meta lanes is unchanged
64
+ (`PEN_STACK_LLM_TIMEOUT` default lowered 150 → 90).
65
+ - The General-lane and PEN-RAG cited-answer callers (`pen_stack/rag/ground.py`, `pen_stack/web/llm.py`) now pass
66
+ `kind="general"`.
67
+ - No grounding-guard change; the LLM stays non-load-bearing and the per-lane provenance labels are unchanged.
68
+
6
69
  ## [7.1.1] - 2026-06-24 - PEN-CHAT: General-lane helpfulness fix + benchmark-validity correction
7
70
 
8
71
  ### Fixed
@@ -1,8 +1,8 @@
1
1
  cff-version: 1.2.0
2
2
  message: "If you use PEN-STACK, please cite it as below."
3
3
  title: "PEN-STACK: open infrastructure for genome writing"
4
- version: 7.1.1
5
- date-released: 2026-06-24
4
+ version: 7.1.3
5
+ date-released: 2026-06-26
6
6
  authors:
7
7
  - family-names: "Mahaboob Ali"
8
8
  given-names: "Anees Ahmed"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pen-stack
3
- Version: 7.1.1
3
+ Version: 7.1.3
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
@@ -162,9 +162,10 @@ flowchart TB
162
162
  | Generative designer | `pen_stack.design` | Proposes candidate writing systems and keeps only those that pass safety, legality, and calibration, returning a Pareto frontier. |
163
163
  | Digital twin | `pen_stack.twin` | Calibrated, out-of-distribution-gated outcome prediction, bounded at phenotype. |
164
164
  | Experiment designer | `pen_stack.active` | Active learning by expected information gain, with a retrospective active-versus-random evaluation. |
165
- | Build interface | `pen_stack.build` | Safety-gated protocol export (draft only, never auto-run) and gated ingestion of results. |
166
- | Closed loop | `pen_stack.loop` | A gated design, build, test, learn loop with drift detection and versioned, reversible recalibration. |
167
- | Agent and co-scientist | `pen_stack.agent` | Goal to cited, auditable plan; MCP server; the co-scientist that drives the loop. |
165
+ | Build interface | `pen_stack.build` | Safety-gated protocol export (draft only, never auto-run) and gated ingestion of results, with a cloud-lab connector that runs the biosecurity gate before any submission. |
166
+ | Closed loop | `pen_stack.loop`, `pen_stack.active` | A gated design, build, test, learn loop with drift detection and versioned, reversible recalibration; an SDL-brain benchmark and a validation-campaign engine that orders the most-informative next measurements by expected information gain. |
167
+ | Write intent (WriteSpec) | `pen_stack.spec` | A typed, ontology-backed `WriteRequest` (an SBOL3 profile) with a grounded extractor that resolves free text to verified ontology ids, asks clarifying questions on ambiguity, and runs a SAT feasibility check. |
168
+ | Agent, co-scientist, and chat | `pen_stack.agent`, `pen_stack.web`, `pen_stack.rag` | Goal to cited, auditable plan; MCP server; the co-scientist that drives the loop; and the grounded conversational chat (four lanes: design, explain, meta, general; provenance-tagged retrieval; a swappable LLM provider). |
168
169
  | Bridge off-target engine | `pen_stack.bridge` | Off-target nomination and guide QC for bridge recombinases. |
169
170
  | Interfaces | `pen_stack.server`, `pen_stack.web`, `pen_stack.ui`, `pen_stack.cli` | REST API, web application, and command-line tools. |
170
171
 
@@ -249,20 +250,22 @@ A single assembly path (`pen_stack/atlas/universe.py`) feeds the classifier, the
249
250
  ```
250
251
  pen-stack/
251
252
  pen_stack/ the installable package
252
- wgenome/ Writable Genome: features, safety, durability, writability, uncertainty, structure3d
253
- atlas/ Writer Atlas, knowledge base, cross-link, variant proposal, canonical universe
253
+ spec/ WriteSpec: typed SBOL3-profile intent layer, grounded extractor, ontology resolvers, SAT feasibility
254
+ wgenome/ Writable Genome: features, safety, durability, writability, uncertainty, structure3d, off-target nomination
255
+ atlas/ Writer Atlas, knowledge base, cross-link, variant proposal, canonical universe, writer-efficiency predictor
254
256
  mech/ score/ mechanism classification at scale; re-grounded therapeutic-readiness axes
255
- planner/ Write Planner: optimisation, cargo, routing, delivery palette, delivery immunology
257
+ planner/ Write Planner: optimisation, cargo, routing, delivery palette, delivery immunology, capsid fitness
256
258
  bridge/ bridge off-target engine and guide QC
257
- oracles/ oracle mesh: the OracleResult contract and adapters over the foundation models
259
+ oracles/ oracle mesh: the OracleResult contract and adapters over the foundation models, with binding-affinity and per-oracle reliability
258
260
  graph/ living world-model knowledge graph (gated, propose-only)
259
- rules/ verify/ machine-readable rule base and the verify(design) service
260
- safety/ the biosecurity and dual-use gate
261
- design/ twin/ generative designer; calibrated digital twin
262
- active/ build/ experiment designer; safety-gated build interface
261
+ rules/ verify/ machine-readable rule base, the verify(design) service, and the proof-object with repair hints
262
+ safety/ the biosecurity and dual-use gate, with standards concordance
263
+ design/ twin/ generative designer; calibrated digital twin with a learned position-effect model
264
+ active/ build/ experiment designer with the SDL-brain benchmark and validation-campaign engine; safety-gated build interface and cloud-lab connector
263
265
  loop/ the gated design-build-test-learn loop
266
+ rag/ PEN-CHAT: provenance-tagged retrieval corpus, embedder, and four-branch ground router (social, cited, general, abstained)
264
267
  agent/ agent platform, co-scientist, MCP server
265
- api/ web/ server/ ui/ cli.py AI integration surface, web platform, REST API, CLI
268
+ api/ web/ server/ ui/ cli.py AI integration surface, web platform with the grounded chat and swappable LLM provider, REST API, CLI
266
269
  benchmarks/ Genome-Writing Bench and the public Genome-Writing Challenge
267
270
  scripts/ reproducible pipeline drivers
268
271
  configs/ pinned datasets, thresholds, and curation (YAML)
@@ -296,7 +299,7 @@ All public: hg38 (UCSC); ENCODE and Roadmap chromatin (ATAC/DNase and histone ma
296
299
  author = {Mahaboob Ali, Anees Ahmed},
297
300
  title = {PEN-STACK: open infrastructure for genome writing (The Writable Genome)},
298
301
  year = {2026},
299
- version = {6.11.0},
302
+ version = {7.1.2},
300
303
  url = {https://github.com/ahmedanees-m/pen-stack}
301
304
  }
302
305
  ```
@@ -85,9 +85,10 @@ flowchart TB
85
85
  | Generative designer | `pen_stack.design` | Proposes candidate writing systems and keeps only those that pass safety, legality, and calibration, returning a Pareto frontier. |
86
86
  | Digital twin | `pen_stack.twin` | Calibrated, out-of-distribution-gated outcome prediction, bounded at phenotype. |
87
87
  | Experiment designer | `pen_stack.active` | Active learning by expected information gain, with a retrospective active-versus-random evaluation. |
88
- | Build interface | `pen_stack.build` | Safety-gated protocol export (draft only, never auto-run) and gated ingestion of results. |
89
- | Closed loop | `pen_stack.loop` | A gated design, build, test, learn loop with drift detection and versioned, reversible recalibration. |
90
- | Agent and co-scientist | `pen_stack.agent` | Goal to cited, auditable plan; MCP server; the co-scientist that drives the loop. |
88
+ | Build interface | `pen_stack.build` | Safety-gated protocol export (draft only, never auto-run) and gated ingestion of results, with a cloud-lab connector that runs the biosecurity gate before any submission. |
89
+ | Closed loop | `pen_stack.loop`, `pen_stack.active` | A gated design, build, test, learn loop with drift detection and versioned, reversible recalibration; an SDL-brain benchmark and a validation-campaign engine that orders the most-informative next measurements by expected information gain. |
90
+ | Write intent (WriteSpec) | `pen_stack.spec` | A typed, ontology-backed `WriteRequest` (an SBOL3 profile) with a grounded extractor that resolves free text to verified ontology ids, asks clarifying questions on ambiguity, and runs a SAT feasibility check. |
91
+ | Agent, co-scientist, and chat | `pen_stack.agent`, `pen_stack.web`, `pen_stack.rag` | Goal to cited, auditable plan; MCP server; the co-scientist that drives the loop; and the grounded conversational chat (four lanes: design, explain, meta, general; provenance-tagged retrieval; a swappable LLM provider). |
91
92
  | Bridge off-target engine | `pen_stack.bridge` | Off-target nomination and guide QC for bridge recombinases. |
92
93
  | Interfaces | `pen_stack.server`, `pen_stack.web`, `pen_stack.ui`, `pen_stack.cli` | REST API, web application, and command-line tools. |
93
94
 
@@ -172,20 +173,22 @@ A single assembly path (`pen_stack/atlas/universe.py`) feeds the classifier, the
172
173
  ```
173
174
  pen-stack/
174
175
  pen_stack/ the installable package
175
- wgenome/ Writable Genome: features, safety, durability, writability, uncertainty, structure3d
176
- atlas/ Writer Atlas, knowledge base, cross-link, variant proposal, canonical universe
176
+ spec/ WriteSpec: typed SBOL3-profile intent layer, grounded extractor, ontology resolvers, SAT feasibility
177
+ wgenome/ Writable Genome: features, safety, durability, writability, uncertainty, structure3d, off-target nomination
178
+ atlas/ Writer Atlas, knowledge base, cross-link, variant proposal, canonical universe, writer-efficiency predictor
177
179
  mech/ score/ mechanism classification at scale; re-grounded therapeutic-readiness axes
178
- planner/ Write Planner: optimisation, cargo, routing, delivery palette, delivery immunology
180
+ planner/ Write Planner: optimisation, cargo, routing, delivery palette, delivery immunology, capsid fitness
179
181
  bridge/ bridge off-target engine and guide QC
180
- oracles/ oracle mesh: the OracleResult contract and adapters over the foundation models
182
+ oracles/ oracle mesh: the OracleResult contract and adapters over the foundation models, with binding-affinity and per-oracle reliability
181
183
  graph/ living world-model knowledge graph (gated, propose-only)
182
- rules/ verify/ machine-readable rule base and the verify(design) service
183
- safety/ the biosecurity and dual-use gate
184
- design/ twin/ generative designer; calibrated digital twin
185
- active/ build/ experiment designer; safety-gated build interface
184
+ rules/ verify/ machine-readable rule base, the verify(design) service, and the proof-object with repair hints
185
+ safety/ the biosecurity and dual-use gate, with standards concordance
186
+ design/ twin/ generative designer; calibrated digital twin with a learned position-effect model
187
+ active/ build/ experiment designer with the SDL-brain benchmark and validation-campaign engine; safety-gated build interface and cloud-lab connector
186
188
  loop/ the gated design-build-test-learn loop
189
+ rag/ PEN-CHAT: provenance-tagged retrieval corpus, embedder, and four-branch ground router (social, cited, general, abstained)
187
190
  agent/ agent platform, co-scientist, MCP server
188
- api/ web/ server/ ui/ cli.py AI integration surface, web platform, REST API, CLI
191
+ api/ web/ server/ ui/ cli.py AI integration surface, web platform with the grounded chat and swappable LLM provider, REST API, CLI
189
192
  benchmarks/ Genome-Writing Bench and the public Genome-Writing Challenge
190
193
  scripts/ reproducible pipeline drivers
191
194
  configs/ pinned datasets, thresholds, and curation (YAML)
@@ -219,7 +222,7 @@ All public: hg38 (UCSC); ENCODE and Roadmap chromatin (ATAC/DNase and histone ma
219
222
  author = {Mahaboob Ali, Anees Ahmed},
220
223
  title = {PEN-STACK: open infrastructure for genome writing (The Writable Genome)},
221
224
  year = {2026},
222
- version = {6.11.0},
225
+ version = {7.1.2},
223
226
  url = {https://github.com/ahmedanees-m/pen-stack}
224
227
  }
225
228
  ```
@@ -133,6 +133,69 @@ controlled_functions:
133
133
  keywords: ["pathogen_essential", "virulence_factor", "pathogen essential"]
134
134
  control_ref: "DURC policy"
135
135
  severity: medium
136
+ - id: FUNC-VIRAL-TROPISM-ENHANCE
137
+ # v7.1.2 CRITICAL: Added to catch furin-cleavage and other viral enhancement modifications.
138
+ # Furin is a ubiquitous human protease; inserting furin cleavage sites increases proteolytic
139
+ # activation of viral glycoproteins, broadening cell tropism and transmissibility (GOF concern).
140
+ name: "engineered enhancement of viral cell tropism / proteolytic activation (furin cleavage, PRRA inserts)"
141
+ keywords: ["furin cleavage", "furin_cleavage", "protease activation", "receptor binding enhancement",
142
+ "tropism enhancement", "tropism_expansion", "virulence enhancement"]
143
+ control_ref: "DURC policy (GOF concern, HHS P3CO oversight)"
144
+ severity: high
145
+ - id: FUNC-ONCOGENIC-SUPPRESSOR
146
+ # v7.1.2 CRITICAL: Added to catch dominant-negative tumor suppressors and oncogenic manipulations.
147
+ # Deleting or inhibiting tumor suppressors (TP53, RB, PTEN) ablates apoptosis/cell-cycle checkpoints,
148
+ # enabling unrestricted proliferation and malignant transformation (oncogenic context).
149
+ name: "dominant-negative / ablation of tumor-suppressor checkpoints (TP53, RB, PTEN, APC)"
150
+ keywords: ["dominant-negative", "dominant negative", "tp53_suppressor", "p53_ablation", "rb_suppressor",
151
+ "pten_suppressor", "apc_suppressor", "apoptosis_checkpoint_ablation", "cell_cycle_checkpoint_ablation",
152
+ "tumor_suppressor_knockout", "unrestricted_proliferation", "apoptosis_evasion"]
153
+ control_ref: "DURC policy (oncogenic context, malignant transformation risk)"
154
+ severity: high
155
+
156
+ # --- Oncogenic-manipulation PATTERN screen (v7.1.2). -----------------------------------
157
+ # A flat keyword list (FUNC-ONCOGENIC-SUPPRESSOR above) catches only literal phrasings; an adversary (or an
158
+ # honest user) describing the same edit by MECHANISM or SYNONYM evades it ("R175H p53 that abolishes
159
+ # transactivation", "PTEN knockout", "RAS G12D constitutive activation", "hTERT immortalization"). This pattern
160
+ # screen flags the COMBINATION rather than a fixed phrase:
161
+ # (tumor-suppressor gene token + a disruptive verb) -> losing a growth/apoptosis brake
162
+ # (oncogene token + an activating signature) -> flooring a growth accelerator
163
+ # (an immortalization signature) -> bypassing replicative senescence
164
+ # The asymmetry is deliberate and is what spares legitimate therapy WITHOUT an explicit allow-list: RESTORING a
165
+ # suppressor or SILENCING/knocking-down an oncogene does not match (restoration verbs are not disruptive; silencing
166
+ # is not an activating signature), so "wild-type p53 correction to restore apoptosis" or "knock down mutant KRAS"
167
+ # stay clear. Disposition is ESCALATE (medium): deliberate oncogenic transformation is dual-use, but cancer-model
168
+ # research is legitimate and has an IBC/oversight path, so it routes to human review rather than a blanket refuse;
169
+ # the blatant dominant-negative phrasings still REFUSE via FUNC-ONCOGENIC-SUPPRESSOR. Tokens are public gene
170
+ # symbols / standard molecular-biology verbs - no exploit detail.
171
+ oncogenic_manipulation:
172
+ id: FUNC-ONCOGENIC-PATTERN
173
+ name: "engineered oncogenic transformation (tumor-suppressor disruption / oncogene activation / immortalization)"
174
+ control_ref: "DURC policy (oncogenic transformation); cancer-model research has a legitimate IBC/oversight path"
175
+ severity: medium
176
+ tumor_suppressors: ["tp53", "trp53", " p53", "rb1", "retinoblastoma protein", "pten", " apc ", "cdkn2a",
177
+ "ink4a", " p16", " arf ", " nf1", "neurofibromin", "brca1", "brca2", " vhl", "smad4",
178
+ "stk11", " lkb1", " bax", " bak", "pro-apoptotic", "tumor suppressor", "tumour suppressor"]
179
+ oncogenes: ["kras", "nras", "hras", "k-ras", "n-ras", "h-ras", " ras ", " myc", "c-myc", "mycn", "braf",
180
+ "egfr", "erbb2", " her2", "pik3ca", " akt ", " alk ", " met ", " ret ", "bcr-abl", "ccnd1",
181
+ "cyclin d", " mdm2", "ezh2", "beta-catenin", "wnt-target", "mapk flux", "pi3k/akt"]
182
+ disrupt_verbs: ["knockout", "knock out", "knock-out", "knocked out", "disrupt", "ablat", "dominant-negative",
183
+ "dominant negative", "frameshift", "inactivat", "abolish", "sequester", "loss-of-function",
184
+ "loss of function", "null allele", "truncat", "silence the suppressor", "remove the",
185
+ "release the", "derepress", "lipid-phosphatase brake"]
186
+ activate_signatures: ["constitutive activ", "constitutively active", "gain-of-function", "gain of function",
187
+ "activating mutation", "oncogenic mutation", "ligand-independent", "ligand independent",
188
+ "autoinhibition", "g12d", "g12v", "g12c", "g13d", "q61", "v600e", "gtp-bound active",
189
+ "switch in its gtp", "constitutive mapk", "constitutive wnt", "constitutive signaling",
190
+ "constitutive survival", "hyperactivat", "independent of ligand", "sustain constitutive"]
191
+ immortalization: ["immortaliz", "telomerase", "htert", "unlimited replicative", "unlimited proliferat",
192
+ "unrestricted proliferat", "indefinite proliferat", "replicative lifespan", "bypass senescence",
193
+ "evade senescence", "escape senescence"]
194
+ # restoration verbs that, when no disruptive/activating/immortalization signal is present, keep a suppressor /
195
+ # oncogene mention CLEAR (therapeutic gene correction). Belt-and-braces on top of the asymmetric logic.
196
+ therapy_context: ["restore", "restoration", "correct the", "gene correction", "wild-type replacement",
197
+ "replace the defective", "reconstitute the wild-type", "functional copy", "supplementation",
198
+ "wild-type p53 gene correction"]
136
199
 
137
200
  # --- Chimera / context rules: hazardous ASSEMBLY of individually-benign parts. ---------
138
201
  chimera_rules:
@@ -1,2 +1,2 @@
1
1
  """PEN-STACK v3.0 - open infrastructure for genome writing."""
2
- __version__ = "7.1.1"
2
+ __version__ = "7.1.3"
@@ -10,7 +10,7 @@ from __future__ import annotations
10
10
 
11
11
  from typing import Any
12
12
 
13
- from pen_stack.design.space import candidate_space
13
+ from pen_stack.design.space import candidate_space, vehicle_sweep
14
14
  from pen_stack.verify import verify
15
15
 
16
16
  # a survivor must be legal AND safe (cleared or low-severity advisory); refuse/escalate are discarded.
@@ -29,8 +29,19 @@ def generate_designs(goal: dict | None = None, *, candidates: list[dict] | None
29
29
  by confidence. Hazardous (refuse/escalate) or illegal proposals are discarded, never returned.
30
30
 
31
31
  Pass an explicit ``candidates`` list to discriminate a known pool (atlas-independent); otherwise candidates
32
- are enumerated from ``goal`` via the planner-backed candidate space."""
33
- pool = candidates if candidates is not None else candidate_space(goal or {}, n=n)
32
+ are enumerated from ``goal`` via the planner-backed candidate space.
33
+
34
+ v7.1.2: when the goal's cell type has NO measured writability atlas (so the planner-backed candidate_space
35
+ yields nothing), fall back to an atlas-free vehicle sweep so the legality + biosecurity discrimination still
36
+ runs; those survivors carry no calibrated confidence (it abstains honestly, surfaced in the UI) rather than
37
+ the page showing an empty table for a perfectly legal, screened design. The explicit-``candidates`` path is
38
+ untouched (``generate_designs(candidates=[])`` still returns [])."""
39
+ if candidates is not None:
40
+ pool = candidates
41
+ else:
42
+ pool = candidate_space(goal or {}, n=n)
43
+ if not pool and goal: # atlas absent for this cell type -> atlas-free sweep (confidence will abstain)
44
+ pool = vehicle_sweep(goal, n=n)
34
45
  survivors: list[dict] = []
35
46
  for d in pool:
36
47
  v = verify(dict(d), actor=actor)
@@ -0,0 +1,136 @@
1
+ """Candidate-space generation for the generative designer (v5.8, WS-GEN support).
2
+
3
+ `candidate_space(goal)` enumerates candidate end-to-end writing systems, writer x site x cargo x delivery,
4
+ by wrapping the validated Phase-3 inverse-design planner (`plan_write`) for the site x writer x scores, then
5
+ pairing each with every *compatible* delivery vehicle from the curated palette (cargo fits the vehicle
6
+ capacity). Every candidate carries the planner's grounded scores (safety / p_durable / writer_activity) so the
7
+ verifier-as-discriminator can compute a calibrated confidence and the v5.6 immune profile downstream.
8
+
9
+ Atlas-dependent: when the Phase-1 writability atlas is absent (e.g. a bare laptop checkout), `plan_write`
10
+ yields nothing and `candidate_space` returns []. The discriminator/Pareto logic is independent of the atlas and
11
+ is exercised on explicit candidates (tests/bench fixtures); the atlas path runs on the VM/with data.
12
+ """
13
+ from __future__ import annotations
14
+
15
+ from typing import Any
16
+
17
+ from pen_stack.planner.delivery_vehicles import names as _vehicle_names
18
+ from pen_stack.planner.delivery_vehicles import vehicle as _vehicle
19
+
20
+ # edit-intent -> write_type (the router/verifier dispatches on write_type)
21
+ _INTENT_WRITE_TYPE = {
22
+ "safe_harbour_insertion": "insertion",
23
+ "high_durability_insertion": "insertion",
24
+ "knock_in_with_disruption": "insertion",
25
+ "landing_pad_insertion": "landing_pad",
26
+ "regulatory_element_excision": "excision",
27
+ "repeat_excision": "excision",
28
+ "regulatory_rewrite": "regulatory_rewrite",
29
+ }
30
+
31
+
32
+ def _compatible_vehicles(cargo_bp: int, in_vivo: bool | None = None) -> list[str]:
33
+ """Vehicles whose curated cargo capacity fits the cargo (capacity None = no DNA-packaging limit).
34
+
35
+ v7.1.2: when an administration ``in_vivo`` context is given, also filter by the vehicle's curated route
36
+ (the `in_vivo` / `ex_vivo` flags in configs/delivery_vehicles.yaml) - an in-vivo goal keeps the in-vivo-capable
37
+ vehicles, an ex-vivo goal keeps the ex-vivo-capable ones (e.g. lentivirus / electroporation / eVLP). This is a
38
+ grounded compatibility filter from the curated palette, not a clinical claim. ``in_vivo=None`` keeps all."""
39
+ out = []
40
+ for n in _vehicle_names():
41
+ v = _vehicle(n) or {}
42
+ cap = v.get("cargo_capacity_bp")
43
+ if cap is not None and cargo_bp > cap:
44
+ continue
45
+ if in_vivo is True and not v.get("in_vivo"):
46
+ continue
47
+ if in_vivo is False and not v.get("ex_vivo"):
48
+ continue
49
+ out.append(n)
50
+ return out
51
+
52
+
53
+ def deliverability_score(vehicle_name: str, cargo_bp: int) -> float:
54
+ """Grounded deliverability proxy: capacity headroom (more spare capacity = more deliverable),
55
+ clipped to [0,1]. Vehicles with no packaging limit score 1.0. NOT a clinical claim."""
56
+ cap = (_vehicle(vehicle_name) or {}).get("cargo_capacity_bp")
57
+ if cap is None:
58
+ return 1.0
59
+ if cargo_bp > cap:
60
+ return 0.0
61
+ return max(0.0, min(1.0, (cap - cargo_bp) / cap))
62
+
63
+
64
+ def candidate_space(goal: dict, *, n: int = 200, k: int = 8) -> list[dict[str, Any]]:
65
+ """Enumerate candidate designs for a goal {gene, intent, cargo_bp, cell_type, cargo_function?}. Each candidate
66
+ is a plain dict consumable by `verify()` and carries the planner's grounded scores. Returns [] if the atlas is
67
+ absent.
68
+
69
+ v7.1.2: the goal's screening-relevant fields (cargo_function, cargo_seq, in_vivo, delivery_tropism,
70
+ replication_competent) are PROPAGATED onto every candidate so the Guardian biosecurity gate in verify() screens
71
+ the cargo function for each swept vehicle. Previously these were dropped here, so a hazardous cargo function
72
+ reached NO screen on the goal-based path."""
73
+ gene = goal["gene"]
74
+ intent = goal.get("intent") or goal.get("edit_intent") or "safe_harbour_insertion"
75
+ cargo_bp = int(goal.get("cargo_bp") or goal.get("payload_bp") or 3000)
76
+ ct = goal.get("cell_type") or goal.get("ct") or "k562"
77
+ write_type = _INTENT_WRITE_TYPE.get(intent, "insertion")
78
+ # screening-relevant goal fields propagated onto every candidate (the Guardian reads cargo_function).
79
+ screen_extra = {f: goal[f] for f in ("cargo_function", "cargo_seq", "in_vivo", "delivery_tropism",
80
+ "replication_competent") if goal.get(f) is not None}
81
+
82
+ from pen_stack.planner.pipeline import plan_write
83
+ try:
84
+ plans = plan_write(gene, intent, cargo_bp, ct, k=k)
85
+ except Exception: # atlas/data absent -> no candidates (discriminator/Pareto unaffected)
86
+ return []
87
+
88
+ vehicles = _compatible_vehicles(cargo_bp, in_vivo=goal.get("in_vivo"))
89
+ cands: list[dict] = []
90
+ for p in plans:
91
+ for veh in vehicles:
92
+ cands.append({
93
+ **screen_extra, # v7.1.2: cargo_function et al. so the Guardian screens this candidate
94
+ "write_type": write_type, "gene": gene, "chrom": p["site"]["chrom"],
95
+ "edit_intent": intent, "writer_family": p["writer"], "cargo_bp": cargo_bp,
96
+ "cell_type": ct, "delivery_vehicle": veh,
97
+ # grounded planner scores (model_extra) -> verify() calibrated confidence + downstream:
98
+ "safety": p["safety"], "p_durable": p["durability"], "writer_activity": p["writer_activity"],
99
+ "on_target": p["on_target"], "reachability_tier": p.get("reachability_tier"),
100
+ "deliverability": deliverability_score(veh, cargo_bp),
101
+ "_planner_score": p["score"],
102
+ "provenance": {**p.get("provenance", {}), "candidate_space": "v5.8 plan_write x delivery palette"},
103
+ })
104
+ if len(cands) >= n:
105
+ return cands
106
+ return cands
107
+
108
+
109
+ def vehicle_sweep(goal: dict, *, n: int = 200) -> list[dict[str, Any]]:
110
+ """Atlas-FREE candidate enumeration: sweep the compatible delivery vehicles for the goal WITHOUT planner
111
+ scores. Used when the writability atlas has no coverage for the requested cell type (e.g. cd8_t / pbmc /
112
+ h1_hesc), so `candidate_space` (which needs `plan_write`) yields nothing.
113
+
114
+ Each candidate carries the goal's cargo_function (so the Guardian still screens it), the cargo size (so the
115
+ capacity rules still filter oversize vehicles), and NO safety/p_durable/writer_activity (so verify() honestly
116
+ ABSTAINS on the calibrated confidence rather than inventing one). The legality + biosecurity discrimination is
117
+ fully exercised; only the calibrated-confidence column is left uncomputed (and labelled as such in the UI)."""
118
+ intent = goal.get("intent") or goal.get("edit_intent") or "safe_harbour_insertion"
119
+ cargo_bp = int(goal.get("cargo_bp") or goal.get("payload_bp") or 3000)
120
+ ct = goal.get("cell_type") or goal.get("ct") or "k562"
121
+ write_type = _INTENT_WRITE_TYPE.get(intent, "insertion")
122
+ screen_extra = {f: goal[f] for f in ("cargo_function", "cargo_seq", "in_vivo", "delivery_tropism",
123
+ "replication_competent") if goal.get(f) is not None}
124
+ cands: list[dict] = []
125
+ for veh in _compatible_vehicles(cargo_bp, in_vivo=goal.get("in_vivo")):
126
+ cands.append({
127
+ **screen_extra,
128
+ "write_type": write_type, "gene": goal.get("gene"), "chrom": goal.get("chrom"),
129
+ "edit_intent": intent, "cargo_bp": cargo_bp, "cell_type": ct, "delivery_vehicle": veh,
130
+ "deliverability": deliverability_score(veh, cargo_bp),
131
+ "provenance": {"candidate_space": "v7.1.2 atlas-free vehicle sweep "
132
+ "(no measured writability atlas for this cell type; confidence abstains)"},
133
+ })
134
+ if len(cands) >= n:
135
+ break
136
+ return cands
@@ -10,6 +10,7 @@ from __future__ import annotations
10
10
  import json
11
11
  import os
12
12
  import urllib.request
13
+ from functools import lru_cache
13
14
 
14
15
  import numpy as np
15
16
 
@@ -39,6 +40,24 @@ def embed_text(text: str, task: str = "query") -> np.ndarray | None:
39
40
  return None
40
41
 
41
42
 
43
+ # v7.1.2 latency fix: cache live query embeddings in-process. The chat embeds the user's message on every General-lane
44
+ # request; repeat phrasings ("hi", "what is DNA", "what is gene editing") would otherwise hit Ollama every time. The
45
+ # document side is unaffected - corpus embeddings are computed once at build time and committed.
46
+ @lru_cache(maxsize=256)
47
+ def _embed_query_cached(text: str) -> tuple | None:
48
+ v = embed_text(text, task="query")
49
+ return tuple(float(x) for x in v) if v is not None else None
50
+
51
+
52
+ def embed_query(text: str) -> np.ndarray | None:
53
+ """Cached query-side embedding. Identical to `embed_text(text, task='query')` but memoised by text."""
54
+ t = (text or "").strip()
55
+ if not t:
56
+ return embed_text(t, task="query")
57
+ cached = _embed_query_cached(t)
58
+ return np.asarray(cached, dtype="float32") if cached is not None else None
59
+
60
+
42
61
  def embed_corpus(texts: list[str]) -> np.ndarray:
43
62
  """Embed the corpus DOCUMENTS at BUILD time. Raises if the embedder is unreachable (the build must be
44
63
  deterministic and must never silently fall back to a different representation)."""
@@ -90,7 +90,8 @@ def _cited_answer(message: str, r: dict, allow_llm: bool) -> dict:
90
90
  system = ("You answer ONLY from the SOURCES provided. After each claim, cite the bracketed [n] it came from. "
91
91
  "If the sources do not cover the question, say so. Never add a number, name, or vehicle that is "
92
92
  "not in the sources. Never present anything as a PEN-STACK-computed result.")
93
- text, backend = _run_llm(f"SOURCES:\n{ctx}\n\nQUESTION: {message}\n\nAnswer concisely, citing [n].", system)
93
+ text, backend = _run_llm(f"SOURCES:\n{ctx}\n\nQUESTION: {message}\n\nAnswer concisely, citing [n].", system,
94
+ kind="general") # v7.1.2 fast-path: short timeout + token cap for cited answers
94
95
  if text:
95
96
  allow = extract_grounded_numbers({"hits": [h["text"] for h in grounded_hits]})
96
97
  return {**base, "reply": _LABEL + "\n\n" + _enforce_grounding(text.strip(), allow), "backend": backend}
@@ -119,7 +120,7 @@ def ground_general(message: str, *, allow_llm: bool = True) -> dict:
119
120
  from pen_stack.web.llm import SYSTEM_GENERAL, _GENERAL_LABEL, _run_llm
120
121
  text, backend = _run_llm(
121
122
  f"USER: {msg}\n\nAnswer from general knowledge, clearly and at a graduate level. Do not present anything "
122
- f"as a PEN-STACK result.", SYSTEM_GENERAL)
123
+ f"as a PEN-STACK result.", SYSTEM_GENERAL, kind="general") # v7.1.2: fast-path timeout
123
124
  if text:
124
125
  return {"status": "general", "reply": _GENERAL_LABEL + "\n\n" + text.strip(), "sources": [],
125
126
  "provenance": "general", "grounded": False, "backend": backend, "retrieval": r["method"],
@@ -12,7 +12,7 @@ from functools import lru_cache
12
12
  import numpy as np
13
13
 
14
14
  from pen_stack.rag.corpus import emb_path, load_corpus
15
- from pen_stack.rag.embed import embed_text, lexical_scores
15
+ from pen_stack.rag.embed import embed_query, lexical_scores
16
16
 
17
17
 
18
18
  @lru_cache(maxsize=1)
@@ -30,7 +30,7 @@ def _load():
30
30
  def retrieve(query: str, k: int = 4) -> dict:
31
31
  df, emb = _load()
32
32
  texts = df["text"].tolist()
33
- qv = embed_text(query) if emb is not None else None
33
+ qv = embed_query(query) if emb is not None else None # v7.1.2: LRU-cached query embedding
34
34
  if qv is not None and emb is not None:
35
35
  scores = emb @ qv # both L2-normalised -> dot product is cosine
36
36
  method = "semantic (nomic-embed-text)"