pen-stack 5.0.0__tar.gz → 5.1.0__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-5.0.0 → pen_stack-5.1.0}/CHANGELOG.md +32 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/CITATION.cff +2 -2
- {pen_stack-5.0.0 → pen_stack-5.1.0}/PKG-INFO +24 -5
- {pen_stack-5.0.0 → pen_stack-5.1.0}/README.md +23 -4
- pen_stack-5.1.0/configs/delivery_vehicles.yaml +185 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/__init__.py +1 -1
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/agent/cite.py +1 -0
- pen_stack-5.1.0/pen_stack/planner/delivery_immunology.py +160 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/verify/schema.py +2 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/verify/service.py +16 -1
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack.egg-info/PKG-INFO +24 -5
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack.egg-info/SOURCES.txt +3 -0
- pen_stack-5.1.0/prereg/SHA256_LOCK_ws_immune.json +8 -0
- pen_stack-5.1.0/prereg/ws_immune.yaml +43 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pyproject.toml +1 -1
- pen_stack-5.0.0/configs/delivery_vehicles.yaml +0 -105
- {pen_stack-5.0.0 → pen_stack-5.1.0}/LICENSE +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/MANIFEST.in +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/bench/run.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/benchmarks/genome_writing_bench/LEADERBOARD.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/benchmarks/genome_writing_bench/README.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/benchmarks/genome_writing_bench/SHA256SUMS +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/benchmarks/genome_writing_bench/SUBMISSIONS.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/benchmarks/genome_writing_bench/tasks.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/atlas_families.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/bridge_offtarget_profile.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/cargo_polish.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/cell_types.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/datasets.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/delivery_constraints.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/delivery_rules.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/gates_v3.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/gsh_validated_heldout.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/intent_weights.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/known_unknowns.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/llm.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/monitor_queries.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/oracles/scope_cards.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/rules/delivery.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/rules/fold.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/rules/multiplex.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/rules/payload.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/rules/reachability.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/score_axes.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/target_sites.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/universe_crosswalk.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/write_types.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/configs/wtkb_curated.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/data/curated/bridge_offtarget_energetics.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/data/curated/bridge_offtarget_profile_measured.parquet +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/data/curated/gene_coords.parquet +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/data/curated/unified_editor_universe.parquet +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/BACKLOG.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/DEPLOY.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/INFRA.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/MCP.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/RELEASING.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/REPRO.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/agent.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/alphagenome_feasibility.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/benchmark_circularity.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/cards/atlas.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/cards/durability.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/cards/safety.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/co_scientist.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/delivery.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/dissemination.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/environment.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/index.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/mechanistic_constraints.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/oracles.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/positioning.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/private_data_formats.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/quickstart.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/rules.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/scope.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/scorecard.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/tutorials/compare-families.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/tutorials/score-deliverability.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/tutorials/where-can-i-write.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/tutorials/which-writer-reaches-locus.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/uncertainty.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/verify.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/world_model.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/writer_verification.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/docs/wtkb.md +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/_resources.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/adapt/__init__.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/adapt/finetune.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/adapt/ingest.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/adapt/pipeline.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/adapt/recalibrate.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/adapt/report.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/agent/__init__.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/agent/co_scientist.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/agent/epistemic.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/agent/guardrails.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/agent/mcp_server.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/agent/orchestrator.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/agent/pen_agent.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/agent/scope.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/agent/tools.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/atlas/__init__.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/atlas/build_wtkb.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/atlas/crosslink.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/atlas/expand.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/atlas/schema.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/atlas/scorecard.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/atlas/universe.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/atlas/variant_propose.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/atlas/writer_verify.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/bridge/__init__.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/bridge/activity.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/bridge/cli.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/bridge/fold_qc.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/bridge/guide_qc.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/bridge/ingest.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/bridge/offtarget.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/bridge/offtarget_energetics.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/bridge/ortholog_screen.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/bridge/pipeline.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/cli.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/data/__init__.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/data/encode.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/data/genome.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/data/ingest_chromatin.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/data/ingest_integration.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/data/ingest_safety_annot.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/data/ingest_trip.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/env/__init__.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/env/genome_writing_env.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/env/policies.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/graph/__init__.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/graph/build.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/graph/cell_types.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/graph/ingest.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/graph/query.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/graph/schema.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/mech/__init__.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/mech/classify_atlas.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/mech/whitelist.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/monitor/__init__.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/monitor/europepmc.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/monitor/run.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/monitor/triage.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/oracles/__init__.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/oracles/cache.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/oracles/energetics.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/oracles/genome.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/oracles/protein_design.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/oracles/rna.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/oracles/schema.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/oracles/structure.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/__init__.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/cargo.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/cargo_polish.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/delivery.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/delivery_constraints.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/delivery_vehicles.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/multiplex.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/optimize.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/pipeline.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/report.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/router.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/planner/target_site.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/rag/__init__.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/rag/index.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/rag/llm.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/rag/qa.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/rules/__init__.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/rules/evaluators.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/rules/loader.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/rules/schema.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/rules/solver.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/score/__init__.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/score/recalibrate.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/score/therapeutic.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/server/__init__.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/server/api.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/ui/__init__.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/ui/app.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/__init__.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/adapt_demo.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/agent_eval.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/bench_adversarial_tasks.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/bench_coscientist_tasks.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/bench_graph_tasks.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/bench_rule_tasks.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/bench_trust_tasks.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/bench_writetype_tasks.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/blind_gsh_discovery.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/cargo_directionality.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/durability_baselines.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/forward_hypotheses.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/guide_qc_demo.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/intent_specification.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/offtarget_energetics_eval.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/out_of_scope_refusal.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/outcome_calibration.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/paper3_benchmark.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/paper4_real_validation.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/paper4_validation.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/selective_prediction.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/seq_vs_measured.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/target_site_controls.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/uncertainty_eval.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/ungrounded_baseline.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/within_locus_ranking.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/validate/writer_recovery.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/verify/__init__.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/__init__.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/chromatin_seq.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/durability.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/export_tracks.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/features.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/gsh_baseline.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/mesh_features.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/ood.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/providers.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/safety.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/structure3d.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/uncertainty.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack/wgenome/writability.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack.egg-info/dependency_links.txt +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack.egg-info/entry_points.txt +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack.egg-info/requires.txt +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/pen_stack.egg-info/top_level.txt +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_phase0.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_phase1_5.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_phase2.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_phase3.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_a.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_atlas.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_b.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_ba.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_ba_v33.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_ba_v45.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_bench.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_c.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_cal.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_cite.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_crit.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_ct.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_d.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_e.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_env.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_ep.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_f.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_g.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_graph.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_h.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_mc.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_mon.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_o.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_plan.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_r.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_route.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_uq.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_v.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/SHA256_LOCK_ws_wv.json +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/paper1.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/paper2.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/paper3.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/paper4.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/phase0.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_a.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_atlas.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_b.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_ba.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_ba_v33.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_ba_v45.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_bench.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_c.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_cal.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_cite.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_crit.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_ct.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_d.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_e.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_env.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_ep.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_f.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_g.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_graph.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_h.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_mc.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_mon.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_o.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_plan.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_r.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_route.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_uq.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_v.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/prereg/ws_wv.yaml +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/p1_build_atlas.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/p1_build_durability.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/p1_export_tracks.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/p1_safety_concordance.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/p1_train_safety.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/p1_validation_report.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/p2_build_atlas.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/p3_benchmark_report.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/p4_genome_scan.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/ws_b_report.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/scripts/ws_c_report.py +0 -0
- {pen_stack-5.0.0 → pen_stack-5.1.0}/setup.cfg +0 -0
|
@@ -3,6 +3,38 @@
|
|
|
3
3
|
All notable changes to PEN-STACK are documented here. This file follows
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/) and the program's phase structure.
|
|
5
5
|
|
|
6
|
+
## [5.1.0] - 2026-06-10 - v5.1 release: Delivery immunology (the safety↔efficacy balance)
|
|
7
|
+
|
|
8
|
+
The delivery palette gains a **documented, cited, qualitative immune + safety + efficacy profile** per vehicle,
|
|
9
|
+
so the substrate can make the safety↔efficacy tradeoff legible and user-weightable — without ever predicting an
|
|
10
|
+
immune magnitude (that stays a declared known-unknown). Workstream WS-IMMUNE, SHA-locked.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **WS-IMMUNE config** — `configs/delivery_vehicles.yaml` (v1.1): an `immune_safety` block on all 8 vehicles
|
|
14
|
+
(`preexisting_immunity`, `neutralizing_antibody`, `innate_immune`, `adaptive_immune`, `genotoxicity`,
|
|
15
|
+
`efficacy`, `tradeoff`, `immune_dois`) — DOCUMENTED ordinal low/moderate/high priors, every `immune_doi`
|
|
16
|
+
Crossref-verified and in the curated-DOI set (citations resolve by construction).
|
|
17
|
+
- **WS-IMMUNE planner** — `pen_stack/planner/delivery_immunology.py`: `safety_efficacy_profile()` reports two
|
|
18
|
+
**separate** safety sub-axes — `immune_score` (immunogenicity; reversible, eligibility/re-dosing) and
|
|
19
|
+
`genotox_score` (insertional/oncogenic; permanent) — never collapsed, with headline
|
|
20
|
+
`safety_score = min(immune_score, genotox_score)` (precautionary worst-axis). `recommend_delivery(cargo_form,
|
|
21
|
+
cargo_bp, safety_weight, in_vivo)` ranks the eligible palette along the safety↔efficacy frontier by a
|
|
22
|
+
user-supplied weight. Reproduces the stated tradeoff: AAV is dinged on immunogenicity, lentivirus on
|
|
23
|
+
genotoxicity. `prereg/ws_immune.yaml`.
|
|
24
|
+
- **WS-IMMUNE verify** — `Verdict.delivery_profile` + a `delivery_immune_profile` scope flag: `verify()` now
|
|
25
|
+
surfaces the documented profile and tradeoff for a chosen vehicle, always attaching the standing
|
|
26
|
+
`in_vivo_immunogenicity` known-unknown flag — never adding confidence, never predicting a magnitude.
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
- Version 5.0.0 -> 5.1.0 (minor — additive delivery-immunology layer); `cite.curated_dois()` now also ingests
|
|
30
|
+
the per-vehicle `immune_dois`.
|
|
31
|
+
|
|
32
|
+
### Honesty invariant (unchanged)
|
|
33
|
+
- The in-vivo immune MAGNITUDE (patient/construct-specific response) remains a declared known-unknown
|
|
34
|
+
(`configs/known_unknowns.yaml: in_vivo_immunogenicity`) and is **never** predicted. v5.1 exposes only
|
|
35
|
+
documented ordinal priors plus a transparent, user-weighted ranking — it makes the boundary legible, it does
|
|
36
|
+
not close it.
|
|
37
|
+
|
|
6
38
|
## [5.0.0] - 2026-06-09 - v5.0 release: the Co-Scientist (capstone — smart because it is grounded)
|
|
7
39
|
|
|
8
40
|
The reasoning ceiling rises while the grounding floor stays fixed: a co-scientist that proposes multiple
|
|
@@ -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: 5.
|
|
5
|
-
date-released: 2026-06-
|
|
4
|
+
version: 5.1.0
|
|
5
|
+
date-released: 2026-06-10
|
|
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: 5.
|
|
3
|
+
Version: 5.1.0
|
|
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
|
|
@@ -77,10 +77,12 @@ Dynamic: license-file
|
|
|
77
77
|
|
|
78
78
|
# PEN-STACK
|
|
79
79
|
|
|
80
|
-
### The
|
|
80
|
+
### The verification & grounding substrate for genome-writing AI — matured into a co-scientist
|
|
81
81
|
|
|
82
|
-
*
|
|
83
|
-
|
|
82
|
+
*The foundation models *generate*; PEN-STACK *checks*. It tells you **where** in the genome you can safely and
|
|
83
|
+
durably write, **which enzyme** can write it there, and **how** to design the write end-to-end — then verifies
|
|
84
|
+
every design against rule-grounded mechanism, reports calibrated confidence, cites its reasoning, and says
|
|
85
|
+
"out of scope" rather than guess. Every number comes from a validated tool; nothing is fabricated.*
|
|
84
86
|
|
|
85
87
|
[](https://pypi.org/project/pen-stack/)
|
|
86
88
|
[](https://github.com/ahmedanees-m/pen-stack/actions/workflows/ci.yml)
|
|
@@ -89,7 +91,7 @@ and durably write new DNA, **which enzyme** can write it there, and **how** to d
|
|
|
89
91
|
[](https://codecov.io/gh/ahmedanees-m/pen-stack)
|
|
90
92
|
[](LICENSE)
|
|
91
93
|
[](https://www.python.org/)
|
|
92
|
-
[](CHANGELOG.md)
|
|
93
95
|
[](tests/)
|
|
94
96
|
[](https://github.com/astral-sh/ruff)
|
|
95
97
|
[](docker/)
|
|
@@ -133,6 +135,23 @@ Two questions gate every genome-writing project, and before PEN-STACK no resourc
|
|
|
133
135
|
Everything is built on bulk-downloadable public data, runs on a single GPU, and is validated **blind** against
|
|
134
136
|
a pre-registered, honest baseline before release.
|
|
135
137
|
|
|
138
|
+
## What is new in v5.1 — Delivery immunology (the safety↔efficacy balance)
|
|
139
|
+
|
|
140
|
+
v5.1 makes the delivery palette's **safety↔efficacy tradeoff legible and user-weightable**. Every vehicle now
|
|
141
|
+
carries a documented, cited, qualitative immune + safety + efficacy profile — so you can ask for a *balance*
|
|
142
|
+
(AAV is safe by integration but neutralizing-antibody/pre-existing-immunity limited; lentivirus is a highly
|
|
143
|
+
efficacious integrator but its genotoxicity is the dominant concern). Crucially, the in-vivo immune
|
|
144
|
+
**magnitude** stays a declared known-unknown — v5.1 surfaces documented priors, it does **not** predict a
|
|
145
|
+
patient-specific immune response.
|
|
146
|
+
|
|
147
|
+
| Workstream | What it adds | Result |
|
|
148
|
+
|---|---|---|
|
|
149
|
+
| **IMMUNE config** | `immune_safety` block on all 8 vehicles in `configs/delivery_vehicles.yaml` | documented ordinal (low/moderate/high) priors for pre-existing immunity, neutralizing antibody, innate/adaptive immune, **genotoxicity**, efficacy — every `immune_doi` Crossref-verified and in the curated-DOI set |
|
|
150
|
+
| **IMMUNE planner** | `planner/delivery_immunology.py` — `safety_efficacy_profile()` / `recommend_delivery()` | two **separate** safety sub-axes (`immune_score` reversible vs `genotox_score` permanent), never collapsed; headline `safety_score = min(...)` (worst-axis); ranks the palette along the safety↔efficacy frontier by a **user weight** |
|
|
151
|
+
| **IMMUNE verify** | `Verdict.delivery_profile` + `delivery_immune_profile` scope flag | `verify()` surfaces the documented tradeoff for a chosen vehicle, always attaching the `in_vivo_immunogenicity` known-unknown flag — never adding confidence, never predicting a magnitude |
|
|
152
|
+
|
|
153
|
+
See `prereg/ws_immune.yaml`.
|
|
154
|
+
|
|
136
155
|
## What is new in v5.0 — the Co-Scientist (smart because it is grounded)
|
|
137
156
|
|
|
138
157
|
v5.0 matures the reasoning layer on top of everything beneath it. Given a goal and an intent, PEN-STACK
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
# PEN-STACK
|
|
4
4
|
|
|
5
|
-
### The
|
|
5
|
+
### The verification & grounding substrate for genome-writing AI — matured into a co-scientist
|
|
6
6
|
|
|
7
|
-
*
|
|
8
|
-
|
|
7
|
+
*The foundation models *generate*; PEN-STACK *checks*. It tells you **where** in the genome you can safely and
|
|
8
|
+
durably write, **which enzyme** can write it there, and **how** to design the write end-to-end — then verifies
|
|
9
|
+
every design against rule-grounded mechanism, reports calibrated confidence, cites its reasoning, and says
|
|
10
|
+
"out of scope" rather than guess. Every number comes from a validated tool; nothing is fabricated.*
|
|
9
11
|
|
|
10
12
|
[](https://pypi.org/project/pen-stack/)
|
|
11
13
|
[](https://github.com/ahmedanees-m/pen-stack/actions/workflows/ci.yml)
|
|
@@ -14,7 +16,7 @@ and durably write new DNA, **which enzyme** can write it there, and **how** to d
|
|
|
14
16
|
[](https://codecov.io/gh/ahmedanees-m/pen-stack)
|
|
15
17
|
[](LICENSE)
|
|
16
18
|
[](https://www.python.org/)
|
|
17
|
-
[](CHANGELOG.md)
|
|
18
20
|
[](tests/)
|
|
19
21
|
[](https://github.com/astral-sh/ruff)
|
|
20
22
|
[](docker/)
|
|
@@ -58,6 +60,23 @@ Two questions gate every genome-writing project, and before PEN-STACK no resourc
|
|
|
58
60
|
Everything is built on bulk-downloadable public data, runs on a single GPU, and is validated **blind** against
|
|
59
61
|
a pre-registered, honest baseline before release.
|
|
60
62
|
|
|
63
|
+
## What is new in v5.1 — Delivery immunology (the safety↔efficacy balance)
|
|
64
|
+
|
|
65
|
+
v5.1 makes the delivery palette's **safety↔efficacy tradeoff legible and user-weightable**. Every vehicle now
|
|
66
|
+
carries a documented, cited, qualitative immune + safety + efficacy profile — so you can ask for a *balance*
|
|
67
|
+
(AAV is safe by integration but neutralizing-antibody/pre-existing-immunity limited; lentivirus is a highly
|
|
68
|
+
efficacious integrator but its genotoxicity is the dominant concern). Crucially, the in-vivo immune
|
|
69
|
+
**magnitude** stays a declared known-unknown — v5.1 surfaces documented priors, it does **not** predict a
|
|
70
|
+
patient-specific immune response.
|
|
71
|
+
|
|
72
|
+
| Workstream | What it adds | Result |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| **IMMUNE config** | `immune_safety` block on all 8 vehicles in `configs/delivery_vehicles.yaml` | documented ordinal (low/moderate/high) priors for pre-existing immunity, neutralizing antibody, innate/adaptive immune, **genotoxicity**, efficacy — every `immune_doi` Crossref-verified and in the curated-DOI set |
|
|
75
|
+
| **IMMUNE planner** | `planner/delivery_immunology.py` — `safety_efficacy_profile()` / `recommend_delivery()` | two **separate** safety sub-axes (`immune_score` reversible vs `genotox_score` permanent), never collapsed; headline `safety_score = min(...)` (worst-axis); ranks the palette along the safety↔efficacy frontier by a **user weight** |
|
|
76
|
+
| **IMMUNE verify** | `Verdict.delivery_profile` + `delivery_immune_profile` scope flag | `verify()` surfaces the documented tradeoff for a chosen vehicle, always attaching the `in_vivo_immunogenicity` known-unknown flag — never adding confidence, never predicting a magnitude |
|
|
77
|
+
|
|
78
|
+
See `prereg/ws_immune.yaml`.
|
|
79
|
+
|
|
61
80
|
## What is new in v5.0 — the Co-Scientist (smart because it is grounded)
|
|
62
81
|
|
|
63
82
|
v5.0 matures the reasoning layer on top of everything beneath it. Given a goal and an intent, PEN-STACK
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# PEN-STACK v3.3 — Delivery vehicle palette (WS-D / North-Star §4). The substrate must score and constrain
|
|
2
|
+
# the WHOLE delivery palette, not just dual-AAV. Each row: cargo capacity, integration, division dependence,
|
|
3
|
+
# immunogenicity PRIOR (qualitative; MAGNITUDE is a known-unknown — never predicted), re-dosability, tropism,
|
|
4
|
+
# ex/in-vivo, compatible cargo form {DNA, mRNA, RNP}, and >=1 DOI. Values cited to 2026 sources.
|
|
5
|
+
# `constraint_key` maps to configs/delivery_constraints.yaml for the sequence-level scan.
|
|
6
|
+
#
|
|
7
|
+
# v5.1 — `immune_safety`: a DOCUMENTED, CITED, QUALITATIVE (low/moderate/high) immune + safety + efficacy
|
|
8
|
+
# profile per vehicle, for the safety<->efficacy balance (planner/delivery_immunology.py). These are ordinal
|
|
9
|
+
# DOCUMENTED PRIORS from the literature — NOT a predicted, patient- or construct-specific immune magnitude
|
|
10
|
+
# (that stays a known-unknown / scope flag, `in_vivo_immunogenicity`, never predicted). `genotoxicity` = the
|
|
11
|
+
# integration / insertional-mutagenesis risk; `efficacy` = transduction/integration efficiency.
|
|
12
|
+
|
|
13
|
+
version: "1.1"
|
|
14
|
+
|
|
15
|
+
vehicles:
|
|
16
|
+
AAV_single:
|
|
17
|
+
cargo_capacity_bp: 4700
|
|
18
|
+
integrating: false # episomal
|
|
19
|
+
division_dependent: false
|
|
20
|
+
immunogenicity_prior: "moderate-high; pre-existing NAbs exclude 30-60% of patients"
|
|
21
|
+
re_dosable: false
|
|
22
|
+
tropism: "serotype-dependent (liver, muscle, CNS, retina)"
|
|
23
|
+
in_vivo: true
|
|
24
|
+
compatible_cargo_form: [DNA]
|
|
25
|
+
constraint_key: AAV
|
|
26
|
+
dois: ["10.1038/s41573-019-0012-9"]
|
|
27
|
+
immune_safety:
|
|
28
|
+
preexisting_immunity: high # serotype-dependent; seroprevalence ~30-60% of patients
|
|
29
|
+
neutralizing_antibody: high # pre-existing + vector-elicited NAbs; exclude/relapse risk
|
|
30
|
+
innate_immune: low
|
|
31
|
+
adaptive_immune: moderate # capsid-directed CD8 T-cell responses
|
|
32
|
+
genotoxicity: low # episomal, non-integrating
|
|
33
|
+
efficacy: high # efficient in-vivo transduction (cargo-limited ~4.7 kb)
|
|
34
|
+
tradeoff: "safe vector (non-integrating, low genotoxicity) BUT pre-existing/elicited NAbs limit eligibility and prevent re-dosing"
|
|
35
|
+
immune_dois: ["10.1182/blood-2013-01-306647", "10.1089/hum.2009.182", "10.1016/j.ymthe.2019.12.010"]
|
|
36
|
+
|
|
37
|
+
AAV_dual:
|
|
38
|
+
cargo_capacity_bp: 9000 # split across 2 capsids (~9 kb); efficiency drops sharply
|
|
39
|
+
integrating: false
|
|
40
|
+
division_dependent: false
|
|
41
|
+
immunogenicity_prior: "as AAV; split lowers efficiency"
|
|
42
|
+
re_dosable: false
|
|
43
|
+
tropism: "serotype-dependent"
|
|
44
|
+
in_vivo: true
|
|
45
|
+
compatible_cargo_form: [DNA]
|
|
46
|
+
constraint_key: AAV
|
|
47
|
+
dois: ["10.1128/JVI.79.15.9933-9944.2005"] # Grieger & Samulski 2005, AAV packaging capacity
|
|
48
|
+
immune_safety:
|
|
49
|
+
preexisting_immunity: high # same AAV capsid immunology as single
|
|
50
|
+
neutralizing_antibody: high
|
|
51
|
+
innate_immune: low
|
|
52
|
+
adaptive_immune: moderate
|
|
53
|
+
genotoxicity: low # episomal
|
|
54
|
+
efficacy: moderate # split across 2 capsids -> co-transduction needed, efficiency drops
|
|
55
|
+
tradeoff: "as AAV (non-integrating, NAb-limited) AND split-capsid co-transduction lowers efficiency"
|
|
56
|
+
immune_dois: ["10.1182/blood-2013-01-306647", "10.1089/hum.2009.182"]
|
|
57
|
+
|
|
58
|
+
lentivirus:
|
|
59
|
+
cargo_capacity_bp: 8000
|
|
60
|
+
integrating: true # semi-random integration
|
|
61
|
+
division_dependent: false # integrates in non-dividing too; strong in dividing
|
|
62
|
+
immunogenicity_prior: "moderate"
|
|
63
|
+
re_dosable: false
|
|
64
|
+
tropism: "broad (VSV-G pseudotyped)"
|
|
65
|
+
ex_vivo: true
|
|
66
|
+
compatible_cargo_form: [DNA]
|
|
67
|
+
constraint_key: lentiviral
|
|
68
|
+
dois: ["10.1126/science.1233151"]
|
|
69
|
+
immune_safety:
|
|
70
|
+
preexisting_immunity: low # pseudotyped, typically ex-vivo (no host pre-immunity to the vector)
|
|
71
|
+
neutralizing_antibody: low # ex-vivo use avoids humoral neutralisation
|
|
72
|
+
innate_immune: low # ex-vivo
|
|
73
|
+
adaptive_immune: low # ex-vivo
|
|
74
|
+
genotoxicity: moderate # INTEGRATING: insertional-mutagenesis risk; SIN-LTR + gene-body bias reduce but do not eliminate it (gamma-retro LMO2 precedent)
|
|
75
|
+
efficacy: high # efficient, STABLE integration; large-ish cargo (~8 kb); transduces non-dividing cells
|
|
76
|
+
tradeoff: "highly efficacious STABLE integration BUT insertional-mutagenesis / genotoxicity is the dominant safety concern (mitigated by SIN design, not eliminated)"
|
|
77
|
+
immune_dois: ["10.1038/s41375-018-0106-0", "10.1038/nbt1216", "10.1126/science.1088547"]
|
|
78
|
+
|
|
79
|
+
helper_dependent_adenovirus:
|
|
80
|
+
cargo_capacity_bp: 35000 # "gutless" HDAd, up to ~35 kb
|
|
81
|
+
integrating: false
|
|
82
|
+
division_dependent: false
|
|
83
|
+
immunogenicity_prior: "high (innate + adaptive)"
|
|
84
|
+
re_dosable: false
|
|
85
|
+
tropism: "liver and others"
|
|
86
|
+
in_vivo: true
|
|
87
|
+
compatible_cargo_form: [DNA]
|
|
88
|
+
constraint_key: plasmid
|
|
89
|
+
dois: ["10.1128/JVI.72.2.926-933.1998"] # multiply-deleted (gutless-class) adenovirus vectors
|
|
90
|
+
immune_safety:
|
|
91
|
+
preexisting_immunity: high # widespread prior adenovirus exposure in the population
|
|
92
|
+
neutralizing_antibody: high # anti-Ad NAbs common; limit systemic in-vivo dosing
|
|
93
|
+
innate_immune: high # potent acute innate/inflammatory response to the capsid
|
|
94
|
+
adaptive_immune: high # strong anti-vector adaptive response
|
|
95
|
+
genotoxicity: low # non-integrating, episomal "gutless" genome
|
|
96
|
+
efficacy: high # very large cargo (~35 kb), efficient hepatic transduction
|
|
97
|
+
tradeoff: "huge cargo + non-integrating BUT strong innate+adaptive anti-Ad immunity and pre-existing NAbs are the dominant safety limit for systemic use"
|
|
98
|
+
immune_dois: ["10.1089/hum.2004.15.1157"]
|
|
99
|
+
|
|
100
|
+
hsv_amplicon:
|
|
101
|
+
cargo_capacity_bp: 100000 # >100 kb
|
|
102
|
+
integrating: false
|
|
103
|
+
division_dependent: false
|
|
104
|
+
immunogenicity_prior: "high; neurotropic"
|
|
105
|
+
re_dosable: false
|
|
106
|
+
tropism: "neurotropic (CNS)"
|
|
107
|
+
in_vivo: true
|
|
108
|
+
compatible_cargo_form: [DNA]
|
|
109
|
+
constraint_key: plasmid
|
|
110
|
+
dois: ["10.1038/nbt1101-1067"] # Wade-Martins 2001, HSV-1 amplicon (iBAC) large genomic-DNA transfer
|
|
111
|
+
immune_safety:
|
|
112
|
+
preexisting_immunity: moderate # prior HSV exposure common, but helper-free amplicon is gene-free of HSV ORFs
|
|
113
|
+
neutralizing_antibody: moderate # anti-HSV humoral immunity in seropositive hosts
|
|
114
|
+
innate_immune: high # immunogenic / inflammatory in CNS
|
|
115
|
+
adaptive_immune: high
|
|
116
|
+
genotoxicity: low # non-integrating, episomal
|
|
117
|
+
efficacy: moderate # massive cargo (>100 kb) + neurotropism, but transient/variable expression
|
|
118
|
+
tradeoff: "unmatched cargo (>100 kb) and CNS tropism BUT immunogenic/inflammatory and expression is transient"
|
|
119
|
+
immune_dois: ["10.1089/hum.2004.15.1157"]
|
|
120
|
+
|
|
121
|
+
lnp_mrna:
|
|
122
|
+
cargo_capacity_bp: 15000 # large RNA payload (mRNA encoding the writer/RNP)
|
|
123
|
+
integrating: false # transient
|
|
124
|
+
division_dependent: false
|
|
125
|
+
immunogenicity_prior: "low/transient"
|
|
126
|
+
re_dosable: true
|
|
127
|
+
tropism: "liver-tropic by default"
|
|
128
|
+
in_vivo: true
|
|
129
|
+
compatible_cargo_form: [mRNA, RNP]
|
|
130
|
+
constraint_key: lnp_mrna
|
|
131
|
+
dois: ["10.1038/s41578-021-00358-0"]
|
|
132
|
+
immune_safety:
|
|
133
|
+
preexisting_immunity: low # no widespread pre-existing immunity to the LNP (anti-PEG is an emerging exception)
|
|
134
|
+
neutralizing_antibody: low # anti-PEG antibodies emerging; can accelerate clearance on repeat dosing
|
|
135
|
+
innate_immune: moderate # transient innate sensing of mRNA / ionizable lipid (mitigated by mod-nucleosides)
|
|
136
|
+
adaptive_immune: low # no anti-vector adaptive memory to a protein capsid
|
|
137
|
+
genotoxicity: low # NON-integrating, transient (no insertional risk)
|
|
138
|
+
efficacy: moderate # transient expression; potent for hepatic RNP/mRNA but durability is short
|
|
139
|
+
re_dosable: yes # repeatable dosing is the key advantage
|
|
140
|
+
tradeoff: "SAFEST profile (non-integrating, transient, re-dosable, low pre-existing immunity) BUT expression is transient and anti-PEG immunity can blunt repeat doses"
|
|
141
|
+
immune_dois: ["10.1016/j.addr.2020.07.024"]
|
|
142
|
+
|
|
143
|
+
evlp:
|
|
144
|
+
cargo_capacity_bp: null # RNP payload (not a DNA packaging limit)
|
|
145
|
+
integrating: false
|
|
146
|
+
division_dependent: false
|
|
147
|
+
immunogenicity_prior: "low (transient, no DNA)"
|
|
148
|
+
re_dosable: true
|
|
149
|
+
tropism: "engineerable (T cells, retina)"
|
|
150
|
+
in_vivo: true
|
|
151
|
+
ex_vivo: true
|
|
152
|
+
compatible_cargo_form: [RNP]
|
|
153
|
+
constraint_key: evlp
|
|
154
|
+
dois: ["10.1016/j.cell.2022.03.045"]
|
|
155
|
+
immune_safety:
|
|
156
|
+
preexisting_immunity: low # protein/RNP payload, no viral capsid; transient
|
|
157
|
+
neutralizing_antibody: low
|
|
158
|
+
innate_immune: low # no DNA, transient delivery
|
|
159
|
+
adaptive_immune: low
|
|
160
|
+
genotoxicity: low # non-integrating RNP, transient nuclease exposure
|
|
161
|
+
efficacy: moderate # engineerable tropism; emerging modality, in-vivo efficiency still maturing
|
|
162
|
+
re_dosable: yes
|
|
163
|
+
tradeoff: "low-immunogenicity transient RNP delivery with engineerable tropism BUT an emerging modality with still-maturing in-vivo efficiency"
|
|
164
|
+
immune_dois: ["10.1016/j.ymthe.2019.12.010"]
|
|
165
|
+
|
|
166
|
+
electroporation:
|
|
167
|
+
cargo_capacity_bp: null # physical; no packaging limit
|
|
168
|
+
integrating: false # depends on cargo
|
|
169
|
+
division_dependent: false
|
|
170
|
+
immunogenicity_prior: "n/a (ex vivo)"
|
|
171
|
+
re_dosable: false
|
|
172
|
+
tropism: "n/a (ex vivo)"
|
|
173
|
+
ex_vivo: true
|
|
174
|
+
compatible_cargo_form: [DNA, mRNA, RNP]
|
|
175
|
+
constraint_key: electroporation
|
|
176
|
+
dois: ["10.1038/nprot.2014.157"]
|
|
177
|
+
immune_safety:
|
|
178
|
+
preexisting_immunity: low # ex-vivo, physical method; no vector immunology
|
|
179
|
+
neutralizing_antibody: low # ex-vivo (n/a in host)
|
|
180
|
+
innate_immune: low # ex-vivo
|
|
181
|
+
adaptive_immune: low # ex-vivo
|
|
182
|
+
genotoxicity: low # cargo-dependent; RNP/transient cargo carries no insertional risk
|
|
183
|
+
efficacy: high # high ex-vivo delivery efficiency across DNA/mRNA/RNP
|
|
184
|
+
tradeoff: "no vector immunology and high ex-vivo efficiency BUT EX-VIVO ONLY (cell harvest/manufacture required) and cytotoxic at high field strength"
|
|
185
|
+
immune_dois: ["10.1016/j.ymthe.2019.12.010"]
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""PEN-STACK v3.0 - open infrastructure for genome writing."""
|
|
2
|
-
__version__ = "5.
|
|
2
|
+
__version__ = "5.1.0"
|
|
@@ -28,6 +28,7 @@ def curated_dois() -> frozenset[str]:
|
|
|
28
28
|
veh = yaml.safe_load(resource("configs/delivery_vehicles.yaml").read_text(encoding="utf-8"))["vehicles"]
|
|
29
29
|
for v in veh.values():
|
|
30
30
|
dois.update(v.get("dois", []) or [])
|
|
31
|
+
dois.update((v.get("immune_safety") or {}).get("immune_dois", []) or []) # v5.1 immune priors
|
|
31
32
|
gsh = yaml.safe_load(resource("configs/gsh_validated_heldout.yaml").read_text(encoding="utf-8"))["gsh"]
|
|
32
33
|
for g in gsh:
|
|
33
34
|
if g.get("doi"):
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""Delivery safety<->efficacy balance over DOCUMENTED immune priors (v5.1, WS-IMMUNE).
|
|
2
|
+
|
|
3
|
+
Motivation (user, v5.1): "we should be able to give a good balance between safety and efficacy. AAV is
|
|
4
|
+
safe but neutralizing antibodies / pre-existing immunity will be there; lentivirus is highly efficacious at
|
|
5
|
+
integrating but its safety is bad." This module turns the per-vehicle ``immune_safety`` block in
|
|
6
|
+
configs/delivery_vehicles.yaml into a transparent, user-weightable ranking of the delivery palette.
|
|
7
|
+
|
|
8
|
+
THE HONESTY INVARIANT (unchanged across the program): the immune MAGNITUDE — how strongly a given patient or
|
|
9
|
+
construct will react in vivo — is a declared known-unknown (configs/known_unknowns.yaml: ``in_vivo_immunogenicity``)
|
|
10
|
+
and is NEVER predicted here. What this module exposes is strictly:
|
|
11
|
+
|
|
12
|
+
* the DOCUMENTED, CITED, ORDINAL (low/moderate/high) literature priors per vehicle, and
|
|
13
|
+
* a transparent ranking that combines those ordinal tiers under a USER-SUPPLIED safety<->efficacy weight.
|
|
14
|
+
|
|
15
|
+
The composite scores are an explicit, reproducible function of the documented tiers and the user's weight — not
|
|
16
|
+
a learned or predicted immunogenicity. Every profile carries the scope flag that the magnitude is out of scope,
|
|
17
|
+
plus the curated DOIs so the prior is auditable.
|
|
18
|
+
"""
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
from functools import lru_cache
|
|
22
|
+
|
|
23
|
+
from pen_stack.planner.delivery_vehicles import load_vehicles, names, vehicle
|
|
24
|
+
|
|
25
|
+
# Ordinal map for the documented qualitative tiers. Higher = more of the named property.
|
|
26
|
+
# For the BURDEN axes (immunity / NAb / innate / adaptive / genotoxicity) higher = worse (less safe);
|
|
27
|
+
# for the EFFICACY axis higher = better.
|
|
28
|
+
_TIER = {"low": 0.0, "moderate": 1.0, "high": 2.0}
|
|
29
|
+
# Two DISTINCT safety sub-axes are kept separate, never collapsed into one mean, because they are different
|
|
30
|
+
# KINDS of risk: immunogenicity is (largely) reversible and bears on eligibility/re-dosing, whereas
|
|
31
|
+
# genotoxicity (insertional mutagenesis) is a permanent, potentially oncogenic risk. This is exactly the
|
|
32
|
+
# tradeoff the v5.1 request is about ("AAV is safe but NAbs; LV is highly efficacious at integrating but its
|
|
33
|
+
# safety is bad") — so genotoxicity must be a first-class, separately-visible axis, not 1/5 of an average.
|
|
34
|
+
_IMMUNE_AXES = ("preexisting_immunity", "neutralizing_antibody", "innate_immune", "adaptive_immune")
|
|
35
|
+
_GENOTOX_AXIS = "genotoxicity"
|
|
36
|
+
# magnitude is NEVER predicted; this is the known-unknown the profile points back to.
|
|
37
|
+
_MAGNITUDE_SCOPE_ID = "in_vivo_immunogenicity"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _tier(val) -> float | None:
|
|
41
|
+
if val is None:
|
|
42
|
+
return None
|
|
43
|
+
return _TIER.get(str(val).strip().lower())
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def safety_efficacy_profile(name: str) -> dict | None:
|
|
47
|
+
"""Documented safety<->efficacy profile for one vehicle, derived ONLY from its ``immune_safety`` block.
|
|
48
|
+
|
|
49
|
+
Reports the ordinal tiers verbatim and THREE normalised sub-scores (1 = best):
|
|
50
|
+
* ``immune_score`` = 1 - mean(immune-burden axes)/2 (1 = least immunogenic)
|
|
51
|
+
* ``genotox_score`` = 1 - genotoxicity/2 (1 = least insertional/oncogenic risk)
|
|
52
|
+
* ``efficacy_score`` = efficacy/2 (1 = most efficacious)
|
|
53
|
+
plus a headline ``safety_score = min(immune_score, genotox_score)`` — a precautionary worst-axis aggregation
|
|
54
|
+
so a vehicle is only as "safe" as its WORST safety dimension (a non-immunogenic but genotoxic vector is not
|
|
55
|
+
called safe). Also returns the documented tradeoff sentence, curated DOIs, and the standing scope flag that
|
|
56
|
+
the immune MAGNITUDE is not predicted. Returns ``None`` for an unknown vehicle; invents no number."""
|
|
57
|
+
rec = vehicle(name)
|
|
58
|
+
if rec is None:
|
|
59
|
+
return None
|
|
60
|
+
imm = rec.get("immune_safety") or {}
|
|
61
|
+
immune_present = [t for ax in _IMMUNE_AXES if (t := _tier(imm.get(ax))) is not None]
|
|
62
|
+
immune_score = (1.0 - (sum(immune_present) / len(immune_present)) / 2.0) if immune_present else None
|
|
63
|
+
gtox = _tier(imm.get(_GENOTOX_AXIS))
|
|
64
|
+
genotox_score = (1.0 - gtox / 2.0) if gtox is not None else None
|
|
65
|
+
sub = [s for s in (immune_score, genotox_score) if s is not None]
|
|
66
|
+
safety_score = min(sub) if sub else None # worst-axis; abstain if neither documented
|
|
67
|
+
eff = _tier(imm.get("efficacy"))
|
|
68
|
+
efficacy_score = (eff / 2.0) if eff is not None else None
|
|
69
|
+
_r = lambda x: None if x is None else round(x, 3) # noqa: E731
|
|
70
|
+
return {
|
|
71
|
+
"vehicle": name,
|
|
72
|
+
"tiers": {ax: imm.get(ax) for ax in (*_IMMUNE_AXES, _GENOTOX_AXIS)} | {"efficacy": imm.get("efficacy")},
|
|
73
|
+
"immune_score": _r(immune_score),
|
|
74
|
+
"genotox_score": _r(genotox_score),
|
|
75
|
+
"safety_score": _r(safety_score),
|
|
76
|
+
"efficacy_score": _r(efficacy_score),
|
|
77
|
+
"re_dosable": imm.get("re_dosable", rec.get("re_dosable")),
|
|
78
|
+
"integrating": rec.get("integrating"),
|
|
79
|
+
"tradeoff": imm.get("tradeoff"),
|
|
80
|
+
"immune_dois": list(imm.get("immune_dois", []) or []),
|
|
81
|
+
"magnitude_scope_flag": {
|
|
82
|
+
"kind": "known_unknown", "id": _MAGNITUDE_SCOPE_ID,
|
|
83
|
+
"reason": "the in-vivo immune MAGNITUDE (patient/construct-specific response) is a known-unknown; "
|
|
84
|
+
"only documented ordinal priors are surfaced, never a predicted magnitude"},
|
|
85
|
+
"note": "safety_score = min(immune_score, genotox_score) over DOCUMENTED ordinal tiers — a precautionary "
|
|
86
|
+
"worst-axis aggregation, not a predicted immunogenicity.",
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@lru_cache(maxsize=1)
|
|
91
|
+
def all_profiles() -> tuple:
|
|
92
|
+
"""All vehicle profiles (tuple so it is hashable/cacheable)."""
|
|
93
|
+
return tuple(p for n in names() if (p := safety_efficacy_profile(n)) is not None)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _balance(profile: dict, safety_weight: float) -> float | None:
|
|
97
|
+
"""Composite = safety_weight * safety_score + (1 - safety_weight) * efficacy_score. None if either axis is
|
|
98
|
+
undocumented (abstain rather than impute)."""
|
|
99
|
+
s, e = profile["safety_score"], profile["efficacy_score"]
|
|
100
|
+
if s is None or e is None:
|
|
101
|
+
return None
|
|
102
|
+
w = min(max(float(safety_weight), 0.0), 1.0)
|
|
103
|
+
return round(w * s + (1.0 - w) * e, 4)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def recommend_delivery(cargo_form: str, cargo_bp: int | None = None, *, safety_weight: float = 0.5,
|
|
107
|
+
in_vivo: bool | None = None) -> dict:
|
|
108
|
+
"""Rank the delivery palette for a cargo by a USER-WEIGHTED safety<->efficacy balance over documented priors.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
cargo_form: required cargo form (DNA / mRNA / RNP) — only vehicles compatible with it are considered.
|
|
112
|
+
cargo_bp: if given, vehicles whose ``cargo_capacity_bp`` is smaller are excluded (hard packaging limit).
|
|
113
|
+
safety_weight: in [0, 1]. 1.0 = rank purely on documented safety; 0.0 = purely on efficacy; 0.5 = balance.
|
|
114
|
+
in_vivo: if True, exclude ex-vivo-only vehicles (and vice-versa) when the field is documented.
|
|
115
|
+
|
|
116
|
+
Returns a dict with the eligible vehicles ranked best-first by the composite, each carrying its documented
|
|
117
|
+
tiers, tradeoff, and curated DOIs, plus the standing magnitude scope flag. No magnitude is predicted; the
|
|
118
|
+
composite is an explicit function of the documented ordinal tiers and the caller's weight."""
|
|
119
|
+
form = (cargo_form or "").strip()
|
|
120
|
+
veh = load_vehicles()
|
|
121
|
+
eligible: list[dict] = []
|
|
122
|
+
excluded: list[dict] = []
|
|
123
|
+
for n, rec in veh.items():
|
|
124
|
+
forms = rec.get("compatible_cargo_form", []) or []
|
|
125
|
+
if form and form not in forms:
|
|
126
|
+
continue
|
|
127
|
+
if cargo_bp is not None and rec.get("cargo_capacity_bp") is not None \
|
|
128
|
+
and int(cargo_bp) > int(rec["cargo_capacity_bp"]):
|
|
129
|
+
excluded.append({"vehicle": n, "reason": f"cargo {cargo_bp} bp exceeds capacity "
|
|
130
|
+
f"{rec['cargo_capacity_bp']} bp"})
|
|
131
|
+
continue
|
|
132
|
+
if in_vivo is True and rec.get("ex_vivo") and not rec.get("in_vivo"):
|
|
133
|
+
excluded.append({"vehicle": n, "reason": "ex-vivo-only; an in-vivo route was required"})
|
|
134
|
+
continue
|
|
135
|
+
if in_vivo is False and rec.get("in_vivo") and not rec.get("ex_vivo"):
|
|
136
|
+
excluded.append({"vehicle": n, "reason": "in-vivo-only; an ex-vivo route was required"})
|
|
137
|
+
continue
|
|
138
|
+
prof = safety_efficacy_profile(n)
|
|
139
|
+
if prof is None:
|
|
140
|
+
continue
|
|
141
|
+
prof = dict(prof)
|
|
142
|
+
prof["balance"] = _balance(prof, safety_weight)
|
|
143
|
+
eligible.append(prof)
|
|
144
|
+
|
|
145
|
+
# rank: documented balance first (None last); tie-break by efficacy then safety.
|
|
146
|
+
eligible.sort(key=lambda p: (p["balance"] is None, -(p["balance"] or 0.0),
|
|
147
|
+
-(p["efficacy_score"] or 0.0), -(p["safety_score"] or 0.0)))
|
|
148
|
+
return {
|
|
149
|
+
"cargo_form": form, "cargo_bp": cargo_bp, "safety_weight": min(max(float(safety_weight), 0.0), 1.0),
|
|
150
|
+
"in_vivo": in_vivo,
|
|
151
|
+
"ranked": eligible,
|
|
152
|
+
"recommended": eligible[0]["vehicle"] if eligible else None,
|
|
153
|
+
"excluded": excluded,
|
|
154
|
+
"scope_flags": [{"kind": "known_unknown", "id": _MAGNITUDE_SCOPE_ID,
|
|
155
|
+
"reason": "ranking is over DOCUMENTED ordinal immune priors; the patient/construct-"
|
|
156
|
+
"specific immune MAGNITUDE is a known-unknown and is not predicted"}],
|
|
157
|
+
"no_fabrication": True,
|
|
158
|
+
"note": "balance = safety_weight*safety + (1-safety_weight)*efficacy over documented low/moderate/high "
|
|
159
|
+
"tiers; change safety_weight to move along the safety<->efficacy frontier.",
|
|
160
|
+
}
|
|
@@ -26,6 +26,8 @@ class Verdict(BaseModel):
|
|
|
26
26
|
no_fabrication: bool = True
|
|
27
27
|
writer_critique: dict[str, Any] | None = None # v4.0 WS-WV: critique of a generated candidate writer
|
|
28
28
|
# (pass/flag + reasons); NEVER a claim that it works
|
|
29
|
+
delivery_profile: dict[str, Any] | None = None # v5.1 WS-IMMUNE: documented ordinal immune/safety/efficacy
|
|
30
|
+
# priors for the chosen vehicle (NEVER a predicted magnitude)
|
|
29
31
|
|
|
30
32
|
def summary(self) -> str:
|
|
31
33
|
if self.deferred:
|
|
@@ -92,6 +92,21 @@ def verify(design: Design | dict, question: str | None = None) -> Verdict:
|
|
|
92
92
|
"flags": writer_critique["flags"],
|
|
93
93
|
"reason": "generated writer is critiqued, never claimed to work (v4.0 WS-WV)"})
|
|
94
94
|
|
|
95
|
+
# v5.1 WS-IMMUNE: if the design names a delivery vehicle, surface its DOCUMENTED ordinal immune/safety/
|
|
96
|
+
# efficacy priors (with the standing "magnitude is a known-unknown" scope flag). This never adds confidence
|
|
97
|
+
# and never predicts a magnitude — it exposes the curated qualitative tradeoff so safety can be weighed.
|
|
98
|
+
delivery_profile = None
|
|
99
|
+
if design.delivery_vehicle:
|
|
100
|
+
from pen_stack.planner.delivery_immunology import safety_efficacy_profile
|
|
101
|
+
delivery_profile = safety_efficacy_profile(design.delivery_vehicle)
|
|
102
|
+
if delivery_profile and delivery_profile.get("tradeoff"):
|
|
103
|
+
scope_flags.append({"kind": "delivery_immune_profile",
|
|
104
|
+
"vehicle": delivery_profile["vehicle"],
|
|
105
|
+
"tradeoff": delivery_profile["tradeoff"],
|
|
106
|
+
"magnitude_id": delivery_profile["magnitude_scope_flag"]["id"],
|
|
107
|
+
"reason": "documented ordinal immune/safety priors surfaced; the in-vivo immune "
|
|
108
|
+
"MAGNITUDE remains a known-unknown (not predicted)"})
|
|
109
|
+
|
|
95
110
|
return Verdict(
|
|
96
111
|
legal=routed["legal"], deferred=False, write_type=design.write_type, routing=routing,
|
|
97
112
|
rule_results=results,
|
|
@@ -101,4 +116,4 @@ def verify(design: Design | dict, question: str | None = None) -> Verdict:
|
|
|
101
116
|
scope_flags=scope_flags,
|
|
102
117
|
confidence=pc["confidence"], interval=pc["interval"], epistemic_status=verdict.status,
|
|
103
118
|
provenance={"rules_version": RULES_VERSION, "source": "rules.solver + L4(uncertainty/scope/epistemic)"},
|
|
104
|
-
no_fabrication=True, writer_critique=writer_critique)
|
|
119
|
+
no_fabrication=True, writer_critique=writer_critique, delivery_profile=delivery_profile)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pen-stack
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.1.0
|
|
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
|
|
@@ -77,10 +77,12 @@ Dynamic: license-file
|
|
|
77
77
|
|
|
78
78
|
# PEN-STACK
|
|
79
79
|
|
|
80
|
-
### The
|
|
80
|
+
### The verification & grounding substrate for genome-writing AI — matured into a co-scientist
|
|
81
81
|
|
|
82
|
-
*
|
|
83
|
-
|
|
82
|
+
*The foundation models *generate*; PEN-STACK *checks*. It tells you **where** in the genome you can safely and
|
|
83
|
+
durably write, **which enzyme** can write it there, and **how** to design the write end-to-end — then verifies
|
|
84
|
+
every design against rule-grounded mechanism, reports calibrated confidence, cites its reasoning, and says
|
|
85
|
+
"out of scope" rather than guess. Every number comes from a validated tool; nothing is fabricated.*
|
|
84
86
|
|
|
85
87
|
[](https://pypi.org/project/pen-stack/)
|
|
86
88
|
[](https://github.com/ahmedanees-m/pen-stack/actions/workflows/ci.yml)
|
|
@@ -89,7 +91,7 @@ and durably write new DNA, **which enzyme** can write it there, and **how** to d
|
|
|
89
91
|
[](https://codecov.io/gh/ahmedanees-m/pen-stack)
|
|
90
92
|
[](LICENSE)
|
|
91
93
|
[](https://www.python.org/)
|
|
92
|
-
[](CHANGELOG.md)
|
|
93
95
|
[](tests/)
|
|
94
96
|
[](https://github.com/astral-sh/ruff)
|
|
95
97
|
[](docker/)
|
|
@@ -133,6 +135,23 @@ Two questions gate every genome-writing project, and before PEN-STACK no resourc
|
|
|
133
135
|
Everything is built on bulk-downloadable public data, runs on a single GPU, and is validated **blind** against
|
|
134
136
|
a pre-registered, honest baseline before release.
|
|
135
137
|
|
|
138
|
+
## What is new in v5.1 — Delivery immunology (the safety↔efficacy balance)
|
|
139
|
+
|
|
140
|
+
v5.1 makes the delivery palette's **safety↔efficacy tradeoff legible and user-weightable**. Every vehicle now
|
|
141
|
+
carries a documented, cited, qualitative immune + safety + efficacy profile — so you can ask for a *balance*
|
|
142
|
+
(AAV is safe by integration but neutralizing-antibody/pre-existing-immunity limited; lentivirus is a highly
|
|
143
|
+
efficacious integrator but its genotoxicity is the dominant concern). Crucially, the in-vivo immune
|
|
144
|
+
**magnitude** stays a declared known-unknown — v5.1 surfaces documented priors, it does **not** predict a
|
|
145
|
+
patient-specific immune response.
|
|
146
|
+
|
|
147
|
+
| Workstream | What it adds | Result |
|
|
148
|
+
|---|---|---|
|
|
149
|
+
| **IMMUNE config** | `immune_safety` block on all 8 vehicles in `configs/delivery_vehicles.yaml` | documented ordinal (low/moderate/high) priors for pre-existing immunity, neutralizing antibody, innate/adaptive immune, **genotoxicity**, efficacy — every `immune_doi` Crossref-verified and in the curated-DOI set |
|
|
150
|
+
| **IMMUNE planner** | `planner/delivery_immunology.py` — `safety_efficacy_profile()` / `recommend_delivery()` | two **separate** safety sub-axes (`immune_score` reversible vs `genotox_score` permanent), never collapsed; headline `safety_score = min(...)` (worst-axis); ranks the palette along the safety↔efficacy frontier by a **user weight** |
|
|
151
|
+
| **IMMUNE verify** | `Verdict.delivery_profile` + `delivery_immune_profile` scope flag | `verify()` surfaces the documented tradeoff for a chosen vehicle, always attaching the `in_vivo_immunogenicity` known-unknown flag — never adding confidence, never predicting a magnitude |
|
|
152
|
+
|
|
153
|
+
See `prereg/ws_immune.yaml`.
|
|
154
|
+
|
|
136
155
|
## What is new in v5.0 — the Co-Scientist (smart because it is grounded)
|
|
137
156
|
|
|
138
157
|
v5.0 matures the reasoning layer on top of everything beneath it. Given a goal and an intent, PEN-STACK
|
|
@@ -153,6 +153,7 @@ pen_stack/planner/cargo.py
|
|
|
153
153
|
pen_stack/planner/cargo_polish.py
|
|
154
154
|
pen_stack/planner/delivery.py
|
|
155
155
|
pen_stack/planner/delivery_constraints.py
|
|
156
|
+
pen_stack/planner/delivery_immunology.py
|
|
156
157
|
pen_stack/planner/delivery_vehicles.py
|
|
157
158
|
pen_stack/planner/multiplex.py
|
|
158
159
|
pen_stack/planner/optimize.py
|
|
@@ -244,6 +245,7 @@ prereg/SHA256_LOCK_ws_f.json
|
|
|
244
245
|
prereg/SHA256_LOCK_ws_g.json
|
|
245
246
|
prereg/SHA256_LOCK_ws_graph.json
|
|
246
247
|
prereg/SHA256_LOCK_ws_h.json
|
|
248
|
+
prereg/SHA256_LOCK_ws_immune.json
|
|
247
249
|
prereg/SHA256_LOCK_ws_mc.json
|
|
248
250
|
prereg/SHA256_LOCK_ws_mon.json
|
|
249
251
|
prereg/SHA256_LOCK_ws_o.json
|
|
@@ -278,6 +280,7 @@ prereg/ws_f.yaml
|
|
|
278
280
|
prereg/ws_g.yaml
|
|
279
281
|
prereg/ws_graph.yaml
|
|
280
282
|
prereg/ws_h.yaml
|
|
283
|
+
prereg/ws_immune.yaml
|
|
281
284
|
prereg/ws_mc.yaml
|
|
282
285
|
prereg/ws_mon.yaml
|
|
283
286
|
prereg/ws_o.yaml
|