pen-stack 7.1.3__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.
- {pen_stack-7.1.3 → pen_stack-7.1.5}/CHANGELOG.md +52 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/CITATION.cff +2 -2
- {pen_stack-7.1.3 → pen_stack-7.1.5}/PKG-INFO +1 -1
- pen_stack-7.1.5/configs/rules/compliance.yaml +44 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/write_types.yaml +7 -7
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/rule_spec.md +2 -1
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/__init__.py +1 -1
- pen_stack-7.1.5/pen_stack/planner/chromosome.py +106 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/rules/evaluators.py +90 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/rules/loader.py +1 -1
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/rules/schema.py +1 -1
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/server/api.py +17 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/verify/proof.py +7 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/verify/service.py +12 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack.egg-info/PKG-INFO +1 -1
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack.egg-info/SOURCES.txt +2 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pyproject.toml +1 -1
- {pen_stack-7.1.3 → pen_stack-7.1.5}/LICENSE +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/MANIFEST.in +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/README.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/bench/run.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/chat_grounding/README.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/chat_grounding/SHA256SUMS +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/chat_headtohead/README.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/chat_routing/README.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/chat_routing/SHA256SUMS +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/chat_safety/README.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/chat_safety/SHA256SUMS +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/delivery/SHA256SUMS +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/genome_writing_bench/LEADERBOARD.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/genome_writing_bench/README.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/genome_writing_bench/SHA256SUMS +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/genome_writing_bench/SUBMISSIONS.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/genome_writing_bench/tasks.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/genome_writing_challenge/README.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/genome_writing_challenge/SUBMISSIONS.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/loop/SHA256SUMS +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/offtarget/SHA256SUMS +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/oracle/SHA256SUMS +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/position_effect/README.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/position_effect/SHA256SUMS +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/verify/SHA256SUMS +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/writer_efficiency/README.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/writer_efficiency/SHA256SUMS +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/benchmarks/writespec/SHA256SUMS +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/aav_serotype_tropism.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/antipeg.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/atlas_families.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/bridge_offtarget_profile.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/calibration/preexisting_nab_independent.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/capsid_epitope_oracle.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/capsid_sequences.fasta +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/cargo_polish.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/cell_types.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/datasets.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/delivery_constraints.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/delivery_rules.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/delivery_vehicles.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/expression/modifiers.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/expression/promoters.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/gates_v3.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/genotoxicity_oracle.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/gsh_validated_heldout.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/intent_weights.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/known_unknowns.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/llm.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/metric_guide.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/mhc_epitope_oracle.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/monitor_queries.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/oracles/execution.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/oracles/reliability.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/oracles/scope_cards.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/rules/delivery.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/rules/fold.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/rules/multiplex.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/rules/payload.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/rules/reachability.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/safety/hazard_registry.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/safety/policy.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/safety/probes.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/score_axes.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/seroprevalence.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/target_sites.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/universe_crosswalk.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/writer_sequences.fasta +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/configs/wtkb_curated.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/data/curated/bridge_offtarget_energetics.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/data/curated/bridge_offtarget_profile_measured.parquet +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/data/curated/gene_coords.parquet +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/data/curated/unified_editor_universe.parquet +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/BACKLOG.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/DEPLOY.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/INFRA.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/MCP.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/RELEASING.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/REPRO.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/STABILITY.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/agent.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/alphagenome_feasibility.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/autonomy.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/benchmark_circularity.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/biosecurity.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/build_interface.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/cards/atlas.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/cards/durability.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/cards/offtarget_data.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/cards/position_effect_data.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/cards/safety.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/cards/writer_efficiency_data.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/challenge.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/closed_loop.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/co_scientist.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/co_scientist_loop.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/delivery.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/delivery_immunology.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/delivery_recommender.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/digital_twin.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/dissemination.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/environment.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/experiment_design.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/generative_design.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/immune_profiler.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/index.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/integrations.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/live_oracles.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/mechanistic_constraints.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/offtarget.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/oracle_mesh.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/oracles.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/position_effect.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/positioning.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/private_data_formats.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/quickstart.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/responsible_use.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/rules.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/scope.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/scorecard.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/tpe_bench.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/tutorials/compare-families.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/tutorials/score-deliverability.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/tutorials/where-can-i-write.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/tutorials/which-writer-reaches-locus.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/uncertainty.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/verify.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/verify_service.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/world_model.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/writer_efficiency.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/writer_verification.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/writespec_bench.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/writespec_profile.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/docs/wtkb.md +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/_resources.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/active/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/active/acquire.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/active/brains.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/active/campaign.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/active/design.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/active/validate.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/adapt/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/adapt/finetune.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/adapt/ingest.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/adapt/pipeline.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/adapt/recalibrate.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/adapt/report.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/agent/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/agent/cite.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/agent/co_scientist.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/agent/epistemic.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/agent/guardrails.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/agent/mcp_server.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/agent/orchestrator.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/agent/orchestrator_live.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/agent/pen_agent.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/agent/scope.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/agent/tools.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/api/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/api/manifest.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/atlas/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/atlas/build_wtkb.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/atlas/crosslink.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/atlas/expand.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/atlas/guide_design.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/atlas/schema.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/atlas/scorecard.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/atlas/universe.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/atlas/variant_propose.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/atlas/writer_efficiency.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/atlas/writer_predict.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/atlas/writer_recommend.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/atlas/writer_verify.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/bridge/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/bridge/activity.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/bridge/cli.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/bridge/fold_qc.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/bridge/guide_qc.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/bridge/ingest.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/bridge/offtarget.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/bridge/offtarget_energetics.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/bridge/ortholog_screen.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/bridge/pipeline.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/build/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/build/cloudlab.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/build/ingest.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/build/protocol.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/build/simlab.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/cli.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/data/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/data/encode.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/data/genome.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/data/ingest_chromatin.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/data/ingest_integration.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/data/ingest_safety_annot.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/data/ingest_trip.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/design/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/design/capsid_generate.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/design/generate.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/design/pareto.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/design/space.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/design/writer_variants.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/env/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/env/genome_writing_env.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/env/policies.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/graph/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/graph/build.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/graph/cell_types.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/graph/ingest.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/graph/query.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/graph/schema.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/loop/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/loop/continual.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/loop/cycle.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/loop/drift.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/mech/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/mech/classify_atlas.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/mech/whitelist.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/monitor/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/monitor/europepmc.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/monitor/run.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/monitor/triage.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/oracles/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/oracles/affinity.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/oracles/cache.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/oracles/energetics.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/oracles/genome.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/oracles/protein_design.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/oracles/reliability.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/oracles/rna.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/oracles/schema.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/oracles/status.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/oracles/structure.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/oracles/structure_run.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/oracles/vcell.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/ada_risk.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/antipeg_oracle.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/capsid_epitope_oracle.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/cargo.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/cargo_polish.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/delivery.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/delivery_constraints.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/delivery_immune.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/delivery_immunology.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/delivery_predict.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/delivery_vehicles.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/genotoxicity_oracle.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/immune_mhc2.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/immune_profile.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/innate_sensing.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/multiplex.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/optimize.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/pipeline.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/report.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/router.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/seroprevalence_oracle.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/planner/target_site.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/rag/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/rag/corpus.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/rag/embed.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/rag/ground.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/rag/index.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/rag/llm.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/rag/qa.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/rag/retrieve.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/rules/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/rules/solver.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/rules/spec.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/safety/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/safety/audit.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/safety/gate.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/safety/policy.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/safety/redteam.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/safety/registry.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/safety/screen.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/safety/standards.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/score/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/score/recalibrate.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/score/therapeutic.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/server/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/spec/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/spec/clarify.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/spec/extract.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/spec/resolvers/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/spec/resolvers/cell.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/spec/resolvers/chem.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/spec/resolvers/feature.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/spec/resolvers/gene.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/spec/resolvers/locus.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/spec/resolvers/phenotype.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/spec/satisfy.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/spec/service.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/spec/writespec.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/twin/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/twin/calibrate.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/twin/data/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/twin/data/position_effect.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/twin/mechanistic.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/twin/outcome.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/twin/position_effect.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/ui/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/ui/app.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/adapt_demo.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/agent_eval.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/bench_adversarial_tasks.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/bench_coscientist_tasks.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/bench_graph_tasks.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/bench_rule_tasks.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/bench_trust_tasks.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/bench_writetype_tasks.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/blind_gsh_discovery.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/cargo_directionality.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/closed_loop.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/durability_baselines.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/experiment_design.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/expr_controls.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/forward_hypotheses.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/generative_design.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/guide_qc_demo.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/heldout_celltype_expr.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/immune_calibration.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/intent_specification.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/known_biology_expr.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/offtarget_energetics_eval.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/out_of_scope_refusal.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/outcome_calibration.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/outcome_prediction.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/paper3_benchmark.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/paper4_real_validation.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/paper4_validation.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/protocol_safety.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/safety_screening.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/selective_prediction.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/seq_vs_measured.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/target_site_controls.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/uncertainty_eval.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/ungrounded_baseline.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/within_locus_ranking.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/validate/writer_recovery.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/verify/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/verify/schema.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/web/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/web/guide.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/web/llm.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/web/llm_provider.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/web/router.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/web/server.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/web/tools.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/wgenome/__init__.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/wgenome/chromatin_seq.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/wgenome/durability.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/wgenome/export_tracks.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/wgenome/features.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/wgenome/gsh_baseline.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/wgenome/mesh_features.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/wgenome/offtarget_assay.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/wgenome/offtarget_data.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/wgenome/offtarget_predict.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/wgenome/ood.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/wgenome/providers.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/wgenome/safety.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/wgenome/structure3d.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/wgenome/uncertainty.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack/wgenome/writability.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack.egg-info/dependency_links.txt +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack.egg-info/entry_points.txt +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack.egg-info/requires.txt +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/pen_stack.egg-info/top_level.txt +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_phase0.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_phase1_5.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_phase2.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_phase3.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_a.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_acq.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_aldesign.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_alvalidate.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_atlas.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_b.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_ba.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_ba_v33.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_ba_v45.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_bench.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_c.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_cal.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_calib.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_challenge.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_chat.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_cite.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_closedloop.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_continual.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_cosci2.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_crit.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_ct.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_d.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_delivery.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_drift.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_e.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_env.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_ep.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_epitope.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_expr2.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_f.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_frontend.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_g.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_gen.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_genotox.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_graph.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_h.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_hybrid.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_immune.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_immune2.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_ingest.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_innate.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_loop.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_manifest.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_mc.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_mcp.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_mech.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_mon.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_o.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_offtarget.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_openapi.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_oracle.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_orch.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_outcome.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_pareto.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_peg.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_penchat.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_plan.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_policy.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_profile.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_proto.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_r.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_redteam.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_route.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_screen.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_seroprev.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_simlab.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_twincal.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_uq.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_v.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_vcell.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_verify.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_writer.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_writespec.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/SHA256_LOCK_ws_wv.json +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/paper1.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/paper2.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/paper3.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/paper4.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/phase0.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_a.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_acq.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_aldesign.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_alvalidate.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_atlas.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_b.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_ba.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_ba_v33.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_ba_v45.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_bench.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_c.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_cal.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_calib.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_challenge.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_chat.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_cite.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_closedloop.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_continual.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_cosci2.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_crit.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_ct.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_d.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_delivery.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_drift.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_e.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_env.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_ep.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_epitope.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_expr2.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_f.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_frontend.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_g.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_gen.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_genotox.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_graph.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_h.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_hybrid.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_immune.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_immune2.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_ingest.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_innate.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_loop.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_manifest.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_mc.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_mcp.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_mech.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_mon.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_o.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_offtarget.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_openapi.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_oracle.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_orch.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_outcome.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_pareto.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_peg.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_penchat.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_plan.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_policy.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_profile.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_proto.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_r.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_redteam.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_route.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_screen.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_seroprev.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_simlab.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_twincal.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_uq.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_v.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_vcell.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_verify.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_writer.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_writespec.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/prereg/ws_wv.yaml +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/build_capsid_fitness.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/build_rag_corpus.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/calibrate_immune_axes.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/fetch_licensed_sources.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/offtarget_chromatin_incremental.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/offtarget_chromatin_matched.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/offtarget_chromatin_validation.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/p1_build_atlas.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/p1_build_durability.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/p1_build_position_effect.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/p1_build_writer_eff.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/p1_export_tracks.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/p1_safety_concordance.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/p1_train_safety.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/p1_validation_report.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/p2_build_atlas.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/p3_benchmark_report.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/p4_genome_scan.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/p52_build_genotox_oracle.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/p53_build_epitope_oracle.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/ws_b_report.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/scripts/ws_c_report.py +0 -0
- {pen_stack-7.1.3 → pen_stack-7.1.5}/setup.cfg +0 -0
|
@@ -3,6 +3,58 @@
|
|
|
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
|
+
|
|
33
|
+
## [7.1.4] - 2026-06-29 - Germline-prohibition legality rule
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
- **Compliance rule category + `compliance.germline_prohibition` (hard_reject).** A heritable / germline edit
|
|
37
|
+
previously passed the Legality axis because no rule existed for it (the only germline handling was a
|
|
38
|
+
known-unknown scope matcher for *questions*, not *designs*). The new rule fails legality for: a reproductive
|
|
39
|
+
germline target cell (embryo / zygote / oocyte / sperm / gamete - unconditional), a declared reproductive-use
|
|
40
|
+
intent (gametes / assisted reproduction / implantation / "for reproduction"), a declared heritable intent
|
|
41
|
+
(germline / heritable / "transmitted to offspring"), or a germline-competent cell type (hESC / iPSC) edited in a
|
|
42
|
+
heritable context (in vivo, or a reproductive/heritable intent). It is cited (Lander et al. 2019 moratorium,
|
|
43
|
+
`10.1038/d41586-019-00726-5`; US National Academies 2017, `10.17226/24623`) and emits a proof-object repair hint
|
|
44
|
+
(restrict to somatic / ex-vivo editing). It is a scope-of-use legality bound, reported on the LEGALITY axis,
|
|
45
|
+
separate from the Biosecurity axis. The category is wired into every write type; `rule_spec.json` is now 11 rules.
|
|
46
|
+
- **Paraphrase + negation robustness** (red-team-hardened). The free-text intent match is NEGATION-aware
|
|
47
|
+
(negated-span detection), so a somatic design that explicitly says "somatic, not germline" / "no germline
|
|
48
|
+
transmission" / "NOT for reproduction or implantation" is not false-flagged, while paraphrased reproductive
|
|
49
|
+
intent (e.g. "generate gametes for assisted reproduction", "embryo intended for uterine transfer") with no
|
|
50
|
+
literal "germline"/"heritable" word still fails. Validated against a 30-design adversarial set: 0 evasions,
|
|
51
|
+
0 false positives.
|
|
52
|
+
|
|
53
|
+
### Fixed
|
|
54
|
+
- The Verify page's Legality description claimed it adjudicates "jurisdiction / list-agent / IP", which it does
|
|
55
|
+
not. Corrected to describe the actual legality axis (physical feasibility + germline scope-of-use compliance),
|
|
56
|
+
noting that dual-use hazard is the separate Biosecurity axis.
|
|
57
|
+
|
|
6
58
|
## [7.1.3] - 2026-06-26 - Designer correctness: Guardian biosecurity + calibrated confidence
|
|
7
59
|
|
|
8
60
|
### 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.
|
|
5
|
-
date-released: 2026-06-
|
|
4
|
+
version: 7.1.5
|
|
5
|
+
date-released: 2026-06-29
|
|
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.
|
|
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
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Compliance / scope-of-use legality (v7.1.4). PEN-STACK is a SOMATIC genome-writing design tool: it does not
|
|
2
|
+
# model germline transmission, embryonic development, or heritable outcomes, and it does not support designing a
|
|
3
|
+
# heritable human germline edit. A design that declares a heritable / germline-editing intent, OR that targets a
|
|
4
|
+
# reproductive germline cell, OR that edits a germline-competent cell type in vivo, is a HARD legality reject -
|
|
5
|
+
# heritable human germline genome editing is broadly prohibited / under international moratorium (it is NOT a
|
|
6
|
+
# biosecurity-hazard signature, so it must fail on the LEGALITY axis, leaving biosecurity to its own screen).
|
|
7
|
+
category: compliance
|
|
8
|
+
rules:
|
|
9
|
+
- id: compliance.germline_prohibition
|
|
10
|
+
kind: hard_reject
|
|
11
|
+
category: compliance
|
|
12
|
+
mechanism: "heritable human germline editing is out of scope for this somatic tool and broadly prohibited: a declared germline/heritable intent, a reproductive germline target cell, or an in-vivo edit of a germline-competent cell type is rejected"
|
|
13
|
+
evaluator: germline_prohibition
|
|
14
|
+
param:
|
|
15
|
+
# reproductive germline cells: editing these IS germline (always reject, any context; matched on the
|
|
16
|
+
# structured cell_type field, so no negation handling needed).
|
|
17
|
+
germline_cell_types: ["embryo", "zygote", "oocyte", "ovum", "egg cell", "sperm", "spermatozoa",
|
|
18
|
+
"spermatocyte", "spermatogonia", "spermatogonial", "gamete", "germ cell", "germline",
|
|
19
|
+
"primordial germ", "pgc", "blastocyst", "conceptus", "morula", "preimplantation"]
|
|
20
|
+
# germline-competent pluripotent cells: editing these in a HERITABLE context (in vivo, or a reproductive /
|
|
21
|
+
# heritable intent) is a germ-lineage edit; an ex-vivo SOMATIC use of the same research line is in scope.
|
|
22
|
+
germline_competent_cell_types: ["h1_hesc", "hesc", "embryonic stem", "ipsc", "ips cell", "ipscs",
|
|
23
|
+
"pluripotent stem", "epiblast", "inner cell mass"]
|
|
24
|
+
# STRONG reproductive-use intent: describes a reproductive PURPOSE; matched negation-aware in the free text.
|
|
25
|
+
reproductive_intent_terms: ["gamete", "gametes", "generate gametes", "derive gametes", "primordial germ",
|
|
26
|
+
"germ lineage", "germ-line", "germ line", "for reproduction", "reproductive use",
|
|
27
|
+
"reproductive purpose", "assisted reproduction", "ivf", "in vitro fertilization",
|
|
28
|
+
"implantation", "uterine transfer", "fertilized egg", "for pregnancy",
|
|
29
|
+
"destined for transfer", "slated for transfer", "scheduled for implantation",
|
|
30
|
+
"intended for pregnancy", "reproductive editing"]
|
|
31
|
+
# WEAKER heritable-transmission intent: can also appear inside a negated somatic disclaimer, so matched
|
|
32
|
+
# negation-aware (a design that says "not heritable" / "no germline transmission" does not fire on these).
|
|
33
|
+
heritable_terms: ["germline", "heritable", "inheritable", "inherited by", "inherit the", "heritably",
|
|
34
|
+
"pass to offspring", "passed to offspring", "passed down to", "transmit to offspring",
|
|
35
|
+
"transmit the fix to", "transmissible to progeny", "transmitted to the", "to progeny",
|
|
36
|
+
"to descendants", "to the patient's children", "to the man's offspring",
|
|
37
|
+
"future generations", "future generation", "next generation edit", "germ cell editing",
|
|
38
|
+
"embryo editing", "embryonic editing", "carried by the resulting child",
|
|
39
|
+
"inheritable by future"]
|
|
40
|
+
provenance:
|
|
41
|
+
doi: ["10.1038/d41586-019-00726-5", "10.17226/24623"]
|
|
42
|
+
note: "Heritable human germline genome editing is broadly prohibited / under moratorium: Lander et al. 2019 international call for a moratorium (Nature 567:165); US National Academies 2017 'Human Genome Editing: Science, Ethics, and Governance'; WHO Expert Advisory Committee framework (2021); US FDA is barred from considering heritable-germline clinical applications (Consolidated Appropriations Act rider); Council of Europe Oviedo Convention Art. 13. PEN-STACK is a SOMATIC tool and takes no position on germline editing beyond declaring it out of scope."
|
|
43
|
+
test_ref: "tests/unit/test_ws_r.py::test_germline_edit_fails_legality"
|
|
44
|
+
scope: "a scope-of-use / regulatory legality bound, not a biosecurity-hazard signature and not an efficacy claim"
|
|
@@ -9,35 +9,35 @@ write_types:
|
|
|
9
9
|
insertion:
|
|
10
10
|
status: supported
|
|
11
11
|
description: "insert a cargo at a safe/durable locus"
|
|
12
|
-
rule_categories: [reachability, fold, payload, delivery]
|
|
12
|
+
rule_categories: [reachability, fold, payload, delivery, compliance]
|
|
13
13
|
steps: [site_selection, writer_selection, cargo_design, offtarget, structural_risk, verify]
|
|
14
14
|
writer_classes: [bridge, cast, serine_integrase, pe_integrase]
|
|
15
15
|
|
|
16
16
|
excision:
|
|
17
17
|
status: coverage_only
|
|
18
18
|
description: "excise a segment (e.g. BCL11A enhancer, FXN GAA repeat) via a recombinase/nuclease pair"
|
|
19
|
-
rule_categories: [reachability, multiplex, delivery]
|
|
19
|
+
rule_categories: [reachability, multiplex, delivery, compliance]
|
|
20
20
|
steps: [breakpoint_reachability, pair_safety, delivery, verify]
|
|
21
21
|
writer_classes: [serine_integrase, recombinase, nuclease_pair]
|
|
22
22
|
|
|
23
23
|
inversion:
|
|
24
24
|
status: coverage_only
|
|
25
25
|
description: "invert a segment between two recombination sites"
|
|
26
|
-
rule_categories: [reachability, multiplex, delivery]
|
|
26
|
+
rule_categories: [reachability, multiplex, delivery, compliance]
|
|
27
27
|
steps: [site_pair_reachability, orientation_check, delivery, verify]
|
|
28
28
|
writer_classes: [serine_integrase, recombinase]
|
|
29
29
|
|
|
30
30
|
replacement:
|
|
31
31
|
status: coverage_only
|
|
32
32
|
description: "replace a segment (excise + insert)"
|
|
33
|
-
rule_categories: [reachability, fold, payload, multiplex, delivery]
|
|
33
|
+
rule_categories: [reachability, fold, payload, multiplex, delivery, compliance]
|
|
34
34
|
steps: [excision_reachability, insertion_reachability, payload, delivery, verify]
|
|
35
35
|
writer_classes: [pe_integrase, serine_integrase, cast]
|
|
36
36
|
|
|
37
37
|
regulatory_rewrite:
|
|
38
38
|
status: coverage_only
|
|
39
39
|
description: "edit a regulatory element (enhancer/silencer); routes to AlphaGenome variant-effect + scope"
|
|
40
|
-
rule_categories: [reachability, delivery]
|
|
40
|
+
rule_categories: [reachability, delivery, compliance]
|
|
41
41
|
steps: [variant_effect_oracle, regulatory_scope, delivery, verify]
|
|
42
42
|
writer_classes: [base_editor, pe, nuclease]
|
|
43
43
|
scope_note: "regulatory-element function change is partly out of scope (structure->phenotype); flagged"
|
|
@@ -45,13 +45,13 @@ write_types:
|
|
|
45
45
|
landing_pad_install:
|
|
46
46
|
status: coverage_only
|
|
47
47
|
description: "install an att landing pad (PE), then a deterministic integrase step"
|
|
48
|
-
rule_categories: [reachability, payload, delivery]
|
|
48
|
+
rule_categories: [reachability, payload, delivery, compliance]
|
|
49
49
|
steps: [pe_installability, integrase_step, payload, delivery, verify]
|
|
50
50
|
writer_classes: [pe_integrase]
|
|
51
51
|
|
|
52
52
|
multiplex:
|
|
53
53
|
status: supported
|
|
54
54
|
description: "multiple concurrent edits; routes to the translocation screen"
|
|
55
|
-
rule_categories: [reachability, multiplex, delivery]
|
|
55
|
+
rule_categories: [reachability, multiplex, delivery, compliance]
|
|
56
56
|
steps: [per_edit_reachability, translocation_screen, delivery, verify]
|
|
57
57
|
writer_classes: [any]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Genome-writing rule spec
|
|
2
2
|
|
|
3
|
-
Version 1.0.
|
|
3
|
+
Version 1.0. 11 rules across 6 categories (compliance, delivery, fold, multiplex, payload, reachability). A rule is data, not code: each record names the evaluator that executes it against a Design, so the rules are enumerable, queryable, and citation-backed without changing any decision (proven by the parity tests).
|
|
4
4
|
|
|
5
5
|
Generated from `pen_stack/rules/spec.py::export_spec`. Machine-readable form: `benchmarks/verify/rule_spec.json`.
|
|
6
6
|
|
|
@@ -16,3 +16,4 @@ Generated from `pen_stack/rules/spec.py::export_spec`. Machine-readable form: `b
|
|
|
16
16
|
| `delivery.sequence_constraints` | soft_penalty | vehicle-specific construct hazards (lentiviral internal poly(A), AAV inverted-repeat/homopolymer, recombinogenic direct repeats, GC extremes) lower titre/yield | 10.1128/JVI.79.15.9933-9944.2005 | labeled heuristic, directional; not a titre predictor |
|
|
17
17
|
| `delivery.aav_packaging_margin` | soft_penalty | AAV packaging efficiency / titre drops sharply as the cargo approaches the capsid limit (computable from cargo_bp vs vehicle capacity), even while still under capacity (v4.0 delivery-oracle refinement) | 10.1089/hum.2010.245 | computable efficiency margin, directional; not a titre predictor |
|
|
18
18
|
| `delivery.immunogenicity_magnitude` | scope_flag | the MAGNITUDE of immunogenicity and the precise in-vivo tropism of a vehicle are not modeled | known-unknown; surfaced, never predicted (Invariant 2) | declared out of scope; never a hard reject dressed as physics |
|
|
19
|
+
| `compliance.germline_prohibition` | hard_reject | heritable human germline editing is out of scope for this somatic tool and broadly prohibited: a declared germline/heritable intent, a reproductive germline target cell, or an in-vivo edit of a germline-competent cell type is rejected (somatic/ex-vivo use of a germline-competent research line is in scope) | 10.1038/d41586-019-00726-5, 10.17226/24623 | a scope-of-use / regulatory legality bound, not a biosecurity-hazard signature and not an efficacy claim |
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""PEN-STACK v3.0 - open infrastructure for genome writing."""
|
|
2
|
-
__version__ = "7.1.
|
|
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
|
|
@@ -11,6 +11,7 @@ YAML record + (if new) one evaluator here, never scattered ``if`` checks in the
|
|
|
11
11
|
"""
|
|
12
12
|
from __future__ import annotations
|
|
13
13
|
|
|
14
|
+
import re
|
|
14
15
|
from collections.abc import Callable
|
|
15
16
|
|
|
16
17
|
from pen_stack.rules.schema import Design, Rule, RuleResult
|
|
@@ -204,6 +205,95 @@ def delivery_immunogenicity_scope(design: Design, rule: Rule) -> RuleResult:
|
|
|
204
205
|
"(declared out of scope, never predicted)")
|
|
205
206
|
|
|
206
207
|
|
|
208
|
+
# --------------------------------------------------------------------------------------------------
|
|
209
|
+
# compliance / scope-of-use legality (v7.1.4): heritable human germline editing is out of scope + prohibited
|
|
210
|
+
# --------------------------------------------------------------------------------------------------
|
|
211
|
+
# A term in declared free text counts only if it is NOT inside a NEGATED span, so a somatic design that says
|
|
212
|
+
# "no germline transmission", "not heritable", "somatic, not germline", or "NOT for reproduction or implantation"
|
|
213
|
+
# (a distributed negation over a list) does not false-fire on the negated word. A negator opens a span that runs
|
|
214
|
+
# across list connectors (or / and / ,) until a clause break (. ; but however yet) or ~60 chars.
|
|
215
|
+
_NEGATOR = re.compile(r"\b(not|non|no|never|without|isn'?t|aren'?t|rather than|as opposed to)\b")
|
|
216
|
+
_CLAUSE_BREAK = re.compile(r"[;.]|\bbut\b|\bhowever\b|\byet\b|\bexcept\b")
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def _negated_spans(text: str) -> list[tuple[int, int]]:
|
|
220
|
+
spans = []
|
|
221
|
+
for m in _NEGATOR.finditer(text):
|
|
222
|
+
rest = text[m.end():m.end() + 60]
|
|
223
|
+
brk = _CLAUSE_BREAK.search(rest)
|
|
224
|
+
spans.append((m.start(), m.end() + (brk.start() if brk else len(rest))))
|
|
225
|
+
return spans
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def _intent_present(term: str, text: str, spans: list[tuple[int, int]]) -> bool:
|
|
229
|
+
t = str(term or "").strip().lower()
|
|
230
|
+
if not t:
|
|
231
|
+
return False
|
|
232
|
+
idx = text.find(t)
|
|
233
|
+
while idx != -1:
|
|
234
|
+
if not any(s <= idx < e for s, e in spans):
|
|
235
|
+
return True # a non-negated occurrence
|
|
236
|
+
idx = text.find(t, idx + 1)
|
|
237
|
+
return False
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
@evaluator("germline_prohibition")
|
|
241
|
+
def germline_prohibition(design: Design, rule: Rule) -> RuleResult:
|
|
242
|
+
"""Hard legality reject for a heritable / germline edit. Fires on (a) a reproductive germline TARGET cell
|
|
243
|
+
(embryo/zygote/oocyte/sperm/gamete - structured, unconditional), (b) a declared REPRODUCTIVE-USE intent
|
|
244
|
+
(gametes / assisted reproduction / implantation / 'for reproduction'), (c) a declared HERITABLE intent
|
|
245
|
+
(germline / heritable / transmitted to offspring), or (d) a germline-COMPETENT cell type (hESC/iPSC) in a
|
|
246
|
+
heritable context (in vivo, or a reproductive/heritable intent). The free-text intent matches are NEGATION-
|
|
247
|
+
aware, so a SOMATIC design that explicitly says 'somatic, not germline' / 'no germline transmission' / 'not
|
|
248
|
+
heritable' is NOT false-flagged, and an ex-vivo somatic use of a germline-competent research line stays in
|
|
249
|
+
scope. The screen reads the declared design artifact only (not any free-text justification)."""
|
|
250
|
+
extra = design.model_extra or {}
|
|
251
|
+
|
|
252
|
+
def _norm(x) -> str:
|
|
253
|
+
return str(x or "").strip().lower()
|
|
254
|
+
|
|
255
|
+
text = " ".join(_norm(x) for x in (design.edit_intent, extra.get("cargo_function"),
|
|
256
|
+
extra.get("goal_function"), extra.get("function_annotation"),
|
|
257
|
+
extra.get("notes")) if x)
|
|
258
|
+
ct = _norm(design.cell_type)
|
|
259
|
+
in_vivo = bool(extra.get("in_vivo")) and _norm(extra.get("in_vivo")) not in ("false", "0", "no")
|
|
260
|
+
p = rule.param
|
|
261
|
+
|
|
262
|
+
spans = _negated_spans(text)
|
|
263
|
+
repro_ct = [c for c in p.get("germline_cell_types", []) if _norm(c) in ct]
|
|
264
|
+
competent_ct = [c for c in p.get("germline_competent_cell_types", []) if _norm(c) in ct]
|
|
265
|
+
repro_intent = [t for t in p.get("reproductive_intent_terms", []) if _intent_present(_norm(t), text, spans)]
|
|
266
|
+
heritable = [t for t in p.get("heritable_terms", []) if _intent_present(_norm(t), text, spans)]
|
|
267
|
+
|
|
268
|
+
triggers = []
|
|
269
|
+
if repro_ct:
|
|
270
|
+
triggers.append(f"a reproductive germline target cell ('{repro_ct[0]}')")
|
|
271
|
+
if repro_intent:
|
|
272
|
+
triggers.append(f"a declared reproductive-use intent ('{repro_intent[0]}')")
|
|
273
|
+
if heritable:
|
|
274
|
+
triggers.append(f"a declared heritable/germline-editing intent ('{heritable[0]}')")
|
|
275
|
+
if competent_ct and (in_vivo or repro_intent or heritable):
|
|
276
|
+
ctx = "in vivo" if in_vivo else (repro_intent or heritable)[0]
|
|
277
|
+
triggers.append(f"a germline-competent cell type ('{competent_ct[0]}') edited in a heritable context "
|
|
278
|
+
f"('{ctx}')")
|
|
279
|
+
if triggers:
|
|
280
|
+
# de-duplicate while preserving order, then report
|
|
281
|
+
seen, uniq = set(), []
|
|
282
|
+
for t in triggers:
|
|
283
|
+
if t not in seen:
|
|
284
|
+
seen.add(t)
|
|
285
|
+
uniq.append(t)
|
|
286
|
+
return _result(rule, "violate",
|
|
287
|
+
"heritable human germline editing is out of scope for this somatic tool and is broadly "
|
|
288
|
+
"prohibited (international moratorium): " + "; ".join(uniq)
|
|
289
|
+
+ ". Restrict to somatic editing (ex vivo, or a somatic cell type / somatic context).")
|
|
290
|
+
note = ""
|
|
291
|
+
if competent_ct:
|
|
292
|
+
note = (f" (cell type '{competent_ct[0]}' is germline-competent; somatic/ex-vivo editing of it is in "
|
|
293
|
+
"scope, but an in-vivo or reproductive heritable edit would not be)")
|
|
294
|
+
return _result(rule, "pass", "no heritable/germline-editing intent or germline target declared" + note)
|
|
295
|
+
|
|
296
|
+
|
|
207
297
|
# --------------------------------------------------------------------------------------------------
|
|
208
298
|
# multiplex translocation (delegates to planner.multiplex, soft penalty)
|
|
209
299
|
# --------------------------------------------------------------------------------------------------
|
|
@@ -10,7 +10,7 @@ from pen_stack._resources import resource
|
|
|
10
10
|
from pen_stack.rules.schema import Rule, Ruleset
|
|
11
11
|
|
|
12
12
|
RULES_VERSION = "1.0"
|
|
13
|
-
_CATEGORIES = ("reachability", "fold", "payload", "multiplex", "delivery")
|
|
13
|
+
_CATEGORIES = ("reachability", "fold", "payload", "multiplex", "delivery", "compliance")
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
@lru_cache(maxsize=1)
|
|
@@ -18,7 +18,7 @@ from pydantic import BaseModel, Field
|
|
|
18
18
|
|
|
19
19
|
RuleKind = Literal["hard_reject", "soft_penalty", "scope_flag"]
|
|
20
20
|
RuleStatus = Literal["pass", "violate", "flag", "scope", "not_applicable"]
|
|
21
|
-
RuleCategory = Literal["reachability", "fold", "payload", "multiplex", "delivery"]
|
|
21
|
+
RuleCategory = Literal["reachability", "fold", "payload", "multiplex", "delivery", "compliance"]
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
class Rule(BaseModel):
|
|
@@ -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)):
|
|
@@ -88,6 +88,13 @@ def _repair_for_violation(d: Design, rule_id: str) -> dict[str, Any] | None:
|
|
|
88
88
|
return {"text": "the writer cannot reach the target as specified; declare a pre-installed landing pad "
|
|
89
89
|
"(installed_att) or choose a writer family whose target element is present.",
|
|
90
90
|
"repair": {"field": "installed_att", "set_to": True}}
|
|
91
|
+
if rule_id == "compliance.germline_prohibition":
|
|
92
|
+
return {"text": "this is a heritable / germline edit, which is out of scope for this somatic-editing "
|
|
93
|
+
"tool and is broadly prohibited (international moratorium); restrict to SOMATIC editing - "
|
|
94
|
+
"move to ex vivo (in_vivo = false) and/or a somatic cell type (e.g. hepatocytes / HepG2, "
|
|
95
|
+
"HSPCs), and drop any germline/heritable intent. (Not auto-repairable: a germline edit is "
|
|
96
|
+
"a change of intent, not a field fix.)",
|
|
97
|
+
"repair": None}
|
|
91
98
|
return None
|
|
92
99
|
|
|
93
100
|
|
|
@@ -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.
|
|
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
|
|
@@ -63,6 +63,7 @@ configs/expression/promoters.yaml
|
|
|
63
63
|
configs/oracles/execution.yaml
|
|
64
64
|
configs/oracles/reliability.yaml
|
|
65
65
|
configs/oracles/scope_cards.yaml
|
|
66
|
+
configs/rules/compliance.yaml
|
|
66
67
|
configs/rules/delivery.yaml
|
|
67
68
|
configs/rules/fold.yaml
|
|
68
69
|
configs/rules/multiplex.yaml
|
|
@@ -251,6 +252,7 @@ pen_stack/planner/antipeg_oracle.py
|
|
|
251
252
|
pen_stack/planner/capsid_epitope_oracle.py
|
|
252
253
|
pen_stack/planner/cargo.py
|
|
253
254
|
pen_stack/planner/cargo_polish.py
|
|
255
|
+
pen_stack/planner/chromosome.py
|
|
254
256
|
pen_stack/planner/delivery.py
|
|
255
257
|
pen_stack/planner/delivery_constraints.py
|
|
256
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.
|
|
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
|