pen-stack 6.8.0__tar.gz → 6.9.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-6.8.0 → pen_stack-6.9.0}/CHANGELOG.md +33 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/CITATION.cff +1 -1
- {pen_stack-6.8.0 → pen_stack-6.9.0}/PKG-INFO +25 -2
- {pen_stack-6.8.0 → pen_stack-6.9.0}/README.md +24 -1
- pen_stack-6.9.0/configs/writer_sequences.fasta +12 -0
- pen_stack-6.9.0/docs/immune_profiler.md +53 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/__init__.py +1 -1
- pen_stack-6.9.0/pen_stack/planner/ada_risk.py +84 -0
- pen_stack-6.9.0/pen_stack/planner/immune_mhc2.py +114 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/planner/immune_profile.py +58 -4
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/immune_calibration.py +10 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack.egg-info/PKG-INFO +25 -2
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack.egg-info/SOURCES.txt +6 -0
- pen_stack-6.9.0/prereg/SHA256_LOCK_ws_immune2.json +8 -0
- pen_stack-6.9.0/prereg/ws_immune2.yaml +36 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pyproject.toml +1 -1
- {pen_stack-6.8.0 → pen_stack-6.9.0}/LICENSE +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/MANIFEST.in +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/bench/run.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/benchmarks/genome_writing_bench/LEADERBOARD.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/benchmarks/genome_writing_bench/README.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/benchmarks/genome_writing_bench/SHA256SUMS +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/benchmarks/genome_writing_bench/SUBMISSIONS.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/benchmarks/genome_writing_bench/tasks.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/benchmarks/genome_writing_challenge/README.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/benchmarks/genome_writing_challenge/SUBMISSIONS.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/benchmarks/position_effect/README.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/benchmarks/position_effect/SHA256SUMS +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/benchmarks/writer_efficiency/README.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/benchmarks/writer_efficiency/SHA256SUMS +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/antipeg.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/atlas_families.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/bridge_offtarget_profile.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/calibration/preexisting_nab_independent.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/capsid_epitope_oracle.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/capsid_sequences.fasta +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/cargo_polish.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/cell_types.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/datasets.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/delivery_constraints.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/delivery_rules.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/delivery_vehicles.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/expression/modifiers.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/expression/promoters.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/gates_v3.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/genotoxicity_oracle.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/gsh_validated_heldout.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/intent_weights.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/known_unknowns.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/llm.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/metric_guide.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/monitor_queries.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/oracles/execution.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/oracles/scope_cards.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/rules/delivery.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/rules/fold.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/rules/multiplex.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/rules/payload.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/rules/reachability.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/safety/hazard_registry.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/safety/policy.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/safety/probes.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/score_axes.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/seroprevalence.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/target_sites.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/universe_crosswalk.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/write_types.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/configs/wtkb_curated.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/data/curated/bridge_offtarget_energetics.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/data/curated/bridge_offtarget_profile_measured.parquet +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/data/curated/gene_coords.parquet +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/data/curated/unified_editor_universe.parquet +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/BACKLOG.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/DEPLOY.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/INFRA.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/MCP.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/RELEASING.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/REPRO.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/STABILITY.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/agent.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/alphagenome_feasibility.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/autonomy.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/benchmark_circularity.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/biosecurity.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/build_interface.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/cards/atlas.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/cards/durability.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/cards/position_effect_data.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/cards/safety.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/cards/writer_efficiency_data.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/challenge.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/closed_loop.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/co_scientist.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/co_scientist_loop.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/delivery.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/delivery_immunology.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/digital_twin.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/dissemination.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/environment.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/experiment_design.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/generative_design.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/index.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/integrations.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/live_oracles.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/mechanistic_constraints.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/oracles.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/position_effect.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/positioning.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/private_data_formats.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/quickstart.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/responsible_use.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/rules.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/scope.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/scorecard.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/tpe_bench.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/tutorials/compare-families.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/tutorials/score-deliverability.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/tutorials/where-can-i-write.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/tutorials/which-writer-reaches-locus.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/uncertainty.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/verify.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/world_model.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/writer_efficiency.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/writer_verification.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/docs/wtkb.md +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/_resources.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/active/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/active/acquire.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/active/design.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/active/validate.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/adapt/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/adapt/finetune.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/adapt/ingest.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/adapt/pipeline.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/adapt/recalibrate.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/adapt/report.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/agent/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/agent/cite.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/agent/co_scientist.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/agent/epistemic.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/agent/guardrails.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/agent/mcp_server.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/agent/orchestrator.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/agent/orchestrator_live.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/agent/pen_agent.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/agent/scope.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/agent/tools.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/api/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/api/manifest.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/atlas/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/atlas/build_wtkb.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/atlas/crosslink.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/atlas/expand.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/atlas/guide_design.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/atlas/schema.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/atlas/scorecard.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/atlas/universe.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/atlas/variant_propose.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/atlas/writer_efficiency.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/atlas/writer_predict.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/atlas/writer_recommend.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/atlas/writer_verify.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/bridge/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/bridge/activity.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/bridge/cli.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/bridge/fold_qc.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/bridge/guide_qc.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/bridge/ingest.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/bridge/offtarget.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/bridge/offtarget_energetics.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/bridge/ortholog_screen.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/bridge/pipeline.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/build/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/build/ingest.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/build/protocol.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/build/simlab.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/cli.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/data/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/data/encode.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/data/genome.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/data/ingest_chromatin.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/data/ingest_integration.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/data/ingest_safety_annot.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/data/ingest_trip.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/design/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/design/generate.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/design/pareto.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/design/space.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/design/writer_variants.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/env/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/env/genome_writing_env.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/env/policies.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/graph/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/graph/build.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/graph/cell_types.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/graph/ingest.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/graph/query.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/graph/schema.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/loop/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/loop/continual.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/loop/cycle.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/loop/drift.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/mech/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/mech/classify_atlas.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/mech/whitelist.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/monitor/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/monitor/europepmc.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/monitor/run.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/monitor/triage.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/oracles/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/oracles/cache.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/oracles/energetics.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/oracles/genome.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/oracles/protein_design.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/oracles/rna.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/oracles/schema.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/oracles/status.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/oracles/structure.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/oracles/vcell.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/planner/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/planner/antipeg_oracle.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/planner/capsid_epitope_oracle.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/planner/cargo.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/planner/cargo_polish.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/planner/delivery.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/planner/delivery_constraints.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/planner/delivery_immunology.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/planner/delivery_vehicles.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/planner/genotoxicity_oracle.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/planner/innate_sensing.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/planner/multiplex.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/planner/optimize.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/planner/pipeline.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/planner/report.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/planner/router.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/planner/seroprevalence_oracle.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/planner/target_site.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/rag/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/rag/index.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/rag/llm.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/rag/qa.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/rules/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/rules/evaluators.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/rules/loader.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/rules/schema.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/rules/solver.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/safety/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/safety/audit.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/safety/gate.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/safety/policy.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/safety/redteam.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/safety/registry.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/safety/screen.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/score/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/score/recalibrate.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/score/therapeutic.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/server/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/server/api.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/twin/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/twin/calibrate.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/twin/data/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/twin/data/position_effect.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/twin/mechanistic.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/twin/outcome.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/twin/position_effect.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/ui/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/ui/app.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/adapt_demo.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/agent_eval.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/bench_adversarial_tasks.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/bench_coscientist_tasks.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/bench_graph_tasks.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/bench_rule_tasks.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/bench_trust_tasks.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/bench_writetype_tasks.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/blind_gsh_discovery.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/cargo_directionality.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/closed_loop.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/durability_baselines.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/experiment_design.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/expr_controls.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/forward_hypotheses.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/generative_design.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/guide_qc_demo.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/heldout_celltype_expr.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/intent_specification.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/known_biology_expr.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/offtarget_energetics_eval.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/out_of_scope_refusal.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/outcome_calibration.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/outcome_prediction.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/paper3_benchmark.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/paper4_real_validation.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/paper4_validation.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/protocol_safety.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/safety_screening.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/selective_prediction.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/seq_vs_measured.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/target_site_controls.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/uncertainty_eval.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/ungrounded_baseline.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/within_locus_ranking.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/validate/writer_recovery.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/verify/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/verify/schema.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/verify/service.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/web/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/web/guide.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/web/llm.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/web/router.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/web/server.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/web/tools.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/wgenome/__init__.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/wgenome/chromatin_seq.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/wgenome/durability.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/wgenome/export_tracks.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/wgenome/features.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/wgenome/gsh_baseline.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/wgenome/mesh_features.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/wgenome/ood.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/wgenome/providers.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/wgenome/safety.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/wgenome/structure3d.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/wgenome/uncertainty.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack/wgenome/writability.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack.egg-info/dependency_links.txt +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack.egg-info/entry_points.txt +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack.egg-info/requires.txt +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/pen_stack.egg-info/top_level.txt +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_phase0.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_phase1_5.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_phase2.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_phase3.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_a.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_acq.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_aldesign.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_alvalidate.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_atlas.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_b.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_ba.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_ba_v33.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_ba_v45.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_bench.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_c.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_cal.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_calib.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_challenge.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_chat.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_cite.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_continual.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_cosci2.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_crit.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_ct.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_d.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_drift.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_e.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_env.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_ep.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_epitope.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_expr2.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_f.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_frontend.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_g.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_gen.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_genotox.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_graph.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_h.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_hybrid.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_immune.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_ingest.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_innate.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_loop.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_manifest.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_mc.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_mcp.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_mech.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_mon.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_o.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_openapi.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_orch.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_outcome.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_pareto.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_peg.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_plan.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_policy.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_profile.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_proto.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_r.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_redteam.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_route.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_screen.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_seroprev.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_simlab.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_twincal.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_uq.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_v.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_vcell.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_writer.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/SHA256_LOCK_ws_wv.json +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/paper1.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/paper2.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/paper3.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/paper4.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/phase0.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_a.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_acq.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_aldesign.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_alvalidate.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_atlas.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_b.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_ba.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_ba_v33.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_ba_v45.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_bench.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_c.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_cal.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_calib.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_challenge.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_chat.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_cite.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_continual.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_cosci2.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_crit.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_ct.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_d.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_drift.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_e.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_env.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_ep.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_epitope.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_expr2.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_f.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_frontend.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_g.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_gen.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_genotox.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_graph.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_h.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_hybrid.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_immune.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_ingest.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_innate.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_loop.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_manifest.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_mc.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_mcp.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_mech.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_mon.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_o.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_openapi.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_orch.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_outcome.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_pareto.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_peg.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_plan.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_policy.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_profile.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_proto.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_r.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_redteam.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_route.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_screen.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_seroprev.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_simlab.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_twincal.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_uq.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_v.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_vcell.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_writer.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/prereg/ws_wv.yaml +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/scripts/calibrate_immune_axes.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/scripts/fetch_licensed_sources.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/scripts/p1_build_atlas.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/scripts/p1_build_durability.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/scripts/p1_build_position_effect.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/scripts/p1_build_writer_eff.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/scripts/p1_export_tracks.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/scripts/p1_safety_concordance.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/scripts/p1_train_safety.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/scripts/p1_validation_report.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/scripts/p2_build_atlas.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/scripts/p3_benchmark_report.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/scripts/p4_genome_scan.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/scripts/p52_build_genotox_oracle.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/scripts/p53_build_epitope_oracle.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/scripts/ws_b_report.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/scripts/ws_c_report.py +0 -0
- {pen_stack-6.8.0 → pen_stack-6.9.0}/setup.cfg +0 -0
|
@@ -3,6 +3,39 @@
|
|
|
3
3
|
All notable changes to PEN-STACK are documented here. This file follows
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/) and the program's phase structure.
|
|
5
5
|
|
|
6
|
+
## [6.9.0] - 2026-06-20 - PEN-IMMUNE: MHC-II/CD4 + ADA + writer-as-antigen
|
|
7
|
+
|
|
8
|
+
**MINOR feature release.** Extends the immune profile from CD8/MHC-I-only to a full T-cell profile — MHC-I +
|
|
9
|
+
**MHC-II/CD4 + ADA risk with self-tolerance filtering** — scored over the **writer enzyme as a distinct antigen**,
|
|
10
|
+
still population-level, OOD-gated, and **never collapsed**. Wraps the v5.6 unified profile. No fabrication: real
|
|
11
|
+
UniProt sequences, grounded documented method, honest 🟡 labels.
|
|
12
|
+
|
|
13
|
+
### Added — the MHC-II + ADA axes (WS-IMMUNE2: G-WS1, G-WS2)
|
|
14
|
+
- `pen_stack/planner/immune_mhc2.py` — grounded, dependency-free **promiscuous MHC-II binder density** (documented
|
|
15
|
+
P1 hydrophobic anchor, Stern & Wiley 1994; secondary pockets, Southwood 1998) over capsid AND writer sequences +
|
|
16
|
+
the bundled real writer/control FASTA. `configs/writer_sequences.fasta` — real UniProt: SpCas9 (Q99ZW2), ISCro4
|
|
17
|
+
bridge recombinase (D2TGM5), Bxb1 integrase (Q9B086), human albumin self control (P02768).
|
|
18
|
+
- `pen_stack/planner/ada_risk.py` — **ADA-risk = MHC-II epitope density × foreignness** with a JanusMatrix-style
|
|
19
|
+
**self-tolerance filter** (origin authoritative; human-proteome k-mer filter otherwise). Recovers
|
|
20
|
+
immunogenic-vs-tolerated: foreign writers score above the human self control (clean separation).
|
|
21
|
+
|
|
22
|
+
### Changed — the unified profile (G-WS3)
|
|
23
|
+
- `pen_stack/planner/immune_profile.py` — adds `mhc2_writer` + `ada_writer` axes and a `writer_as_antigen` card
|
|
24
|
+
with `dominant_antigen` + `writer_dominant_risk` (fires for a foreign writer, especially non-viral delivery
|
|
25
|
+
where there is no capsid antigen). `collapsed_score` stays `None` (asserted). `immune_calibration.AXIS_STATUS`
|
|
26
|
+
registers the two new axes as mechanistic/population proxies.
|
|
27
|
+
|
|
28
|
+
### Added — Immuno-Bench + honest calibration (G-WS4)
|
|
29
|
+
- `benchmarks/immuno/harness.py` — the immunogenic-vs-tolerated recovery track (non-circular: label = protein
|
|
30
|
+
origin) + an honest `calibrate_axis` ADA pass that **stays 🟡** at public-data power (no manufactured ✅).
|
|
31
|
+
- `tests/unit/test_ws_immune2.py` (CI-safe; pure-Python method + committed sequences). `prereg/ws_immune2.yaml`.
|
|
32
|
+
|
|
33
|
+
### Honesty
|
|
34
|
+
- Every axis is a population-level proxy, never a patient-specific ADA titer / realized CD4 magnitude (known-
|
|
35
|
+
unknowns). The MHC-II method is sequence-intrinsic presentation potential, not a trained allele-specific predictor.
|
|
36
|
+
The self-tolerance k-mer filter is seeded by the bundled human reference (full human proteome substitutable on the
|
|
37
|
+
VM); the authoritative foreignness signal is the protein origin. Axes are a vector, never fused.
|
|
38
|
+
|
|
6
39
|
## [6.8.0] - 2026-06-20 - PEN-WRITER: cross-family writer-efficiency engine + Writer-Efficiency Bench
|
|
7
40
|
|
|
8
41
|
**MINOR feature release.** Upgrades Stage C (pick the writer) from a curated-KB **ranking** to a prediction +
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pen-stack
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.9.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
|
|
@@ -90,7 +90,7 @@ every design against rule-grounded mechanism, reports calibrated confidence, cit
|
|
|
90
90
|
[](https://codecov.io/gh/ahmedanees-m/pen-stack)
|
|
91
91
|
[](LICENSE)
|
|
92
92
|
[](https://www.python.org/)
|
|
93
|
-
[](CHANGELOG.md)
|
|
94
94
|
[](docs/STABILITY.md)
|
|
95
95
|
[](tests/)
|
|
96
96
|
[](https://github.com/astral-sh/ruff)
|
|
@@ -148,6 +148,29 @@ demonstrated (v5.12) and the benchmark went public (v5.13).
|
|
|
148
148
|
> unknown funnel remains — made legible (scope flags, known-unknowns, honest baselines, no fabrication), not
|
|
149
149
|
> hidden.
|
|
150
150
|
|
|
151
|
+
## What is new in v6.9 — PEN-IMMUNE (MHC-II/CD4 + ADA + the writer enzyme as a distinct antigen)
|
|
152
|
+
|
|
153
|
+
The immune profile did **CD8/MHC-I only** (capsid epitope load via MHCflurry) — but the **dominant** immunogenicity
|
|
154
|
+
driver is **MHC-II / CD4 help → anti-drug antibodies (ADA)**, and the **writer enzyme itself is immunogenic**
|
|
155
|
+
(Cas9 elicits MHC-II-presented CD4 responses, Simhadri *Nat Commun* 2021; bridge recombinases / serine integrases
|
|
156
|
+
are bacterial/phage) — yet Stage G scored only the capsid. v6.9 closes that gap, **never collapsing** the axes:
|
|
157
|
+
|
|
158
|
+
- **A CD4/MHC-II epitope-load axis** (`planner/immune_mhc2.py`) — a grounded, dependency-free **promiscuous MHC-II
|
|
159
|
+
binder density** over the documented P1 hydrophobic anchor (Stern & Wiley 1994) + secondary pockets, scored over
|
|
160
|
+
**capsid AND writer** sequences. Population-level proxy (🟡), never a patient-HLA magnitude.
|
|
161
|
+
- **An ADA-risk axis** (`planner/ada_risk.py`) — **ADA-risk = MHC-II epitope density × foreignness**, with a
|
|
162
|
+
**self-tolerance filter** (JanusMatrix-style: self epitopes are tolerated; foreign drive ADA). It **recovers
|
|
163
|
+
immunogenic-vs-tolerated**: the foreign writers (real UniProt SpCas9 / ISCro4 / Bxb1) score **above** the human
|
|
164
|
+
self control (albumin), even without the origin label (the k-mer self-match tolerates the human protein).
|
|
165
|
+
- **The writer as a distinct antigen** — the profile now carries a `writer_as_antigen` card and a
|
|
166
|
+
`writer_dominant_risk` flag: for **non-viral delivery of a bacterial writer there is no capsid antigen, so the
|
|
167
|
+
WRITER is the dominant immunogen** — the insight the capsid-only profile missed.
|
|
168
|
+
- **Immuno-Bench** (`benchmarks/immuno/`) — the immunogenic-vs-tolerated recovery track + an honest `calibrate_axis`
|
|
169
|
+
ADA pass (it stays 🟡 at public-data power — no manufactured ✅, the standing wet-lab bottleneck).
|
|
170
|
+
|
|
171
|
+
Real UniProt sequences only (no fabricated sequence); the axes are reported as a vector with `collapsed_score: None`;
|
|
172
|
+
the realized CD4 response / ADA titer stay known-unknowns. See [docs/immune_profiler.md](docs/immune_profiler.md).
|
|
173
|
+
|
|
151
174
|
## What is new in v6.8 — PEN-WRITER (a cross-family writer-efficiency engine + the first writer-efficiency benchmark)
|
|
152
175
|
|
|
153
176
|
Stage C (pick the writer) was **retrieval** — the curated Writer Atlas ranks 8 families but predicts no
|
|
@@ -15,7 +15,7 @@ every design against rule-grounded mechanism, reports calibrated confidence, cit
|
|
|
15
15
|
[](https://codecov.io/gh/ahmedanees-m/pen-stack)
|
|
16
16
|
[](LICENSE)
|
|
17
17
|
[](https://www.python.org/)
|
|
18
|
-
[](CHANGELOG.md)
|
|
19
19
|
[](docs/STABILITY.md)
|
|
20
20
|
[](tests/)
|
|
21
21
|
[](https://github.com/astral-sh/ruff)
|
|
@@ -73,6 +73,29 @@ demonstrated (v5.12) and the benchmark went public (v5.13).
|
|
|
73
73
|
> unknown funnel remains — made legible (scope flags, known-unknowns, honest baselines, no fabrication), not
|
|
74
74
|
> hidden.
|
|
75
75
|
|
|
76
|
+
## What is new in v6.9 — PEN-IMMUNE (MHC-II/CD4 + ADA + the writer enzyme as a distinct antigen)
|
|
77
|
+
|
|
78
|
+
The immune profile did **CD8/MHC-I only** (capsid epitope load via MHCflurry) — but the **dominant** immunogenicity
|
|
79
|
+
driver is **MHC-II / CD4 help → anti-drug antibodies (ADA)**, and the **writer enzyme itself is immunogenic**
|
|
80
|
+
(Cas9 elicits MHC-II-presented CD4 responses, Simhadri *Nat Commun* 2021; bridge recombinases / serine integrases
|
|
81
|
+
are bacterial/phage) — yet Stage G scored only the capsid. v6.9 closes that gap, **never collapsing** the axes:
|
|
82
|
+
|
|
83
|
+
- **A CD4/MHC-II epitope-load axis** (`planner/immune_mhc2.py`) — a grounded, dependency-free **promiscuous MHC-II
|
|
84
|
+
binder density** over the documented P1 hydrophobic anchor (Stern & Wiley 1994) + secondary pockets, scored over
|
|
85
|
+
**capsid AND writer** sequences. Population-level proxy (🟡), never a patient-HLA magnitude.
|
|
86
|
+
- **An ADA-risk axis** (`planner/ada_risk.py`) — **ADA-risk = MHC-II epitope density × foreignness**, with a
|
|
87
|
+
**self-tolerance filter** (JanusMatrix-style: self epitopes are tolerated; foreign drive ADA). It **recovers
|
|
88
|
+
immunogenic-vs-tolerated**: the foreign writers (real UniProt SpCas9 / ISCro4 / Bxb1) score **above** the human
|
|
89
|
+
self control (albumin), even without the origin label (the k-mer self-match tolerates the human protein).
|
|
90
|
+
- **The writer as a distinct antigen** — the profile now carries a `writer_as_antigen` card and a
|
|
91
|
+
`writer_dominant_risk` flag: for **non-viral delivery of a bacterial writer there is no capsid antigen, so the
|
|
92
|
+
WRITER is the dominant immunogen** — the insight the capsid-only profile missed.
|
|
93
|
+
- **Immuno-Bench** (`benchmarks/immuno/`) — the immunogenic-vs-tolerated recovery track + an honest `calibrate_axis`
|
|
94
|
+
ADA pass (it stays 🟡 at public-data power — no manufactured ✅, the standing wet-lab bottleneck).
|
|
95
|
+
|
|
96
|
+
Real UniProt sequences only (no fabricated sequence); the axes are reported as a vector with `collapsed_score: None`;
|
|
97
|
+
the realized CD4 response / ADA titer stay known-unknowns. See [docs/immune_profiler.md](docs/immune_profiler.md).
|
|
98
|
+
|
|
76
99
|
## What is new in v6.8 — PEN-WRITER (a cross-family writer-efficiency engine + the first writer-efficiency benchmark)
|
|
77
100
|
|
|
78
101
|
Stage C (pick the writer) was **retrieval** — the curated Writer Atlas ranks 8 families but predicts no
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Writer-enzyme + control protein sequences for the v6.9 writer-as-antigen immunogenicity profiler (Stage G).
|
|
2
|
+
# Real UniProt sequences, verbatim, each with its accession + ORIGIN (foreign | self). The writer enzymes are
|
|
3
|
+
# bacterial/phage proteins (FOREIGN -> non-self -> ADA-driving); human albumin is the SELF/tolerated control.
|
|
4
|
+
# Header convention: >NAME|ACCESSION origin=foreign|self family=... (DOIs/provenance in configs/immune_sequences.yaml)
|
|
5
|
+
>SpCas9|Q99ZW2 origin=foreign family=Cas9 organism=S.pyogenes
|
|
6
|
+
MDKKYSIGLDIGTNSVGWAVITDEYKVPSKKFKVLGNTDRHSIKKNLIGALLFDSGETAEATRLKRTARRRYTRRKNRICYLQEIFSNEMAKVDDSFFHRLEESFLVEEDKKHERHPIFGNIVDEVAYHEKYPTIYHLRKKLVDSTDKADLRLIYLALAHMIKFRGHFLIEGDLNPDNSDVDKLFIQLVQTYNQLFEENPINASGVDAKAILSARLSKSRRLENLIAQLPGEKKNGLFGNLIALSLGLTPNFKSNFDLAEDAKLQLSKDTYDDDLDNLLAQIGDQYADLFLAAKNLSDAILLSDILRVNTEITKAPLSASMIKRYDEHHQDLTLLKALVRQQLPEKYKEIFFDQSKNGYAGYIDGGASQEEFYKFIKPILEKMDGTEELLVKLNREDLLRKQRTFDNGSIPHQIHLGELHAILRRQEDFYPFLKDNREKIEKILTFRIPYYVGPLARGNSRFAWMTRKSEETITPWNFEEVVDKGASAQSFIERMTNFDKNLPNEKVLPKHSLLYEYFTVYNELTKVKYVTEGMRKPAFLSGEQKKAIVDLLFKTNRKVTVKQLKEDYFKKIECFDSVEISGVEDRFNASLGTYHDLLKIIKDKDFLDNEENEDILEDIVLTLTLFEDREMIEERLKTYAHLFDDKVMKQLKRRRYTGWGRLSRKLINGIRDKQSGKTILDFLKSDGFANRNFMQLIHDDSLTFKEDIQKAQVSGQGDSLHEHIANLAGSPAIKKGILQTVKVVDELVKVMGRHKPENIVIEMARENQTTQKGQKNSRERMKRIEEGIKELGSQILKEHPVENTQLQNEKLYLYYLQNGRDMYVDQELDINRLSDYDVDHIVPQSFLKDDSIDNKVLTRSDKNRGKSDNVPSEEVVKKMKNYWRQLLNAKLITQRKFDNLTKAERGGLSELDKAGFIKRQLVETRQITKHVAQILDSRMNTKYDENDKLIREVKVITLKSKLVSDFRKDFQFYKVREINNYHHAHDAYLNAVVGTALIKKYPKLESEFVYGDYKVYDVRKMIAKSEQEIGKATAKYFFYSNIMNFFKTEITLANGEIRKRPLIETNGETGEIVWDKGRDFATVRKVLSMPQVNIVKKTEVQTGGFSKESILPKRNSDKLIARKKDWDPKKYGGFDSPTVAYSVLVVAKVEKGKSKKLKSVKELLGITIMERSSFEKNPIDFLEAKGYKEVKKDLIIKLPKYSLFELENGRKRMLASAGELQKGNELALPSKYVNFLYLASHYEKLKGSPEDNEQKQLFVEQHKHYLDEIIEQISEFSKRVILADANLDKVLSAYNKHRDKPIREQAENIIHLFTLTNLGAPAAFKYFDTTIDRKRYTSTKEVLDATLIHQSITGLYETRIDLSQLGGD
|
|
7
|
+
>ISCro4|D2TGM5 origin=foreign family=bridge_IS110 organism=C.rodentium
|
|
8
|
+
MEQELHFIGIDVSKAKLDVDVLRPDGRHRSKKFANTPKGHDELLRWLSGHRVAPAHICMEATSTYMEDVAAHLSDAGYTVSVINPALGKAFAQSEGLRSKTDAVDARMLAEFCRQKRPPAWEAPHPVERALRALVLRHQSLTDMHTQELNRLETAREVQRPSIDAHLLWLHAELKRIEKQIKDLTDDDPDMKHRRKLLESIPGIGEKTSAVLLAYTGLKERFTHARQFAAFAGLTPRRYESGSSVNRASRMSKAGHASLRRALYMPAMVAVSKTEWGRAFRDRLAGNGKKGKVIIGAMMRKLAQVAYGVLKSGVPFDASRHNPVAA
|
|
9
|
+
>Bxb1|Q9B086 origin=foreign family=serine_integrase organism=phage_Bxb1
|
|
10
|
+
MRALVVIRLSRVTDATTSPERQLESCQQLCAQRGWDVVGVAEDLDVSGAVDPFDRKRRPNLARWLAFEEQPFDVIVAYRVDRLTRSIRHLQQLVHWAEDHKKLVVSATEAHFDTTTPFAAVVIALMGTVAQMELEAIKERNRSAAHFNIRAGKYRGSLPPWGYLPTRVDGEWRLVPDPVQRERILEVYHRVVDNHEPLHLVAHDLNRRGVLSPKDYFAQLQGREPQGREWSATALKRSMISEAMLGYATLNGKTVRDDDGAPLVRAEPILTREQLEALRAELVKTSRAKPAVSTPSLLLRVLFCAVCGEPAYKFAGGGRKHPRYRCRSMGFPKHCGNGTVAMAEWDAFCEEQVLDLLGDAAERLEKVWVAGSDSAVELAEVNAELVDLTSLIGSPAYRAGSPQREALDARIAALAARQEELEGLEARPSGWEWRETGQRFGDWWREQDTAAKNTWLRSMNVRLTFDVRGGLTRTIDFGDLQEYEQHLRLGSVVERLHTGMS
|
|
11
|
+
>HumanAlbumin|P02768 origin=self family=human_control organism=H.sapiens
|
|
12
|
+
MKWVTFISLLFLFSSAYSRGVFRRDAHKSEVAHRFKDLGEENFKALVLIAFAQYLQQCPFEDHVKLVNEVTEFAKTCVADESAENCDKSLHTLFGDKLCTVATLRETYGEMADCCAKQEPERNECFLQHKDDNPNLPRLVRPEVDVMCTAFHDNEETFLKKYLYEIARRHPYFYAPELLFFAKRYKAAFTECCQAADKAACLLPKLDELRDEGKASSAKQRLKCASLQKFGERAFKAWAVARLSQRFPKAEFAEVSKLVTDLTKVHTECCHGDLLECADDRADLAKYICENQDSISSKLKECCEKPLLEKSHCIAEVENDEMPADLPSLAADFVESKDVCKNYAEAKDVFLGMFLYEYARRHPDYSVVLLLRLAKTYETTLEKCCAAADPHECYAKVFDEFKPLVEEPQNLIKQNCELFEQLGEYKFQNALLVRYTKKVPQVSTPTLVEVSRNLGKVGSKCCKHPEAKRMPCAEDYLSVVLNQLCVLHEKTPVSDRVTKCCTESLVNRRPCFSALEVDETYVPKEFNAETFTFHADICTLSEKERQIKKQTALVELVKHKPKATKEQLKAVMDDFAAFVEKCCKADDKETCFAEEGKKLVAASQAALGL
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Stage G — the immune profiler (v6.9 PEN-IMMUNE)
|
|
2
|
+
|
|
3
|
+
Stage G profiles a design's immunogenicity/toxicity across **separate, never-collapsed axes**. Through v6.8 the
|
|
4
|
+
adaptive axis was **CD8/MHC-I only** (capsid epitope load via MHCflurry). v6.9 adds the **dominant** driver —
|
|
5
|
+
**MHC-II/CD4 → ADA** — and scores the **writer enzyme as a distinct antigen**.
|
|
6
|
+
|
|
7
|
+
## The MHC-II/CD4 axis (`planner/immune_mhc2.py`)
|
|
8
|
+
|
|
9
|
+
A grounded, dependency-free **promiscuous MHC-II binder density**: MHC-II presents a 9-mer core in an open groove
|
|
10
|
+
whose **P1 pocket is deep and hydrophobic** — the single dominant anchor (M/F/Y/W/L/I/V; Stern & Wiley, *Nature*
|
|
11
|
+
1994), with secondary pockets at P4/P6/P9. A *promiscuous* epitope (binds many HLA-DR) has a strong P1 anchor +
|
|
12
|
+
favorable secondaries (Southwood 1998). We count promiscuous-binder cores → an epitope-density proxy, computed over
|
|
13
|
+
**capsid AND writer** sequences. It is a **population-level, sequence-intrinsic proxy (🟡)** — not a trained
|
|
14
|
+
allele-specific predictor, not a patient-HLA magnitude (a known-unknown).
|
|
15
|
+
|
|
16
|
+
## The ADA-risk axis + self-tolerance (`planner/ada_risk.py`)
|
|
17
|
+
|
|
18
|
+
Epitope load is necessary but not sufficient — **self** proteins carry MHC-II epitopes yet are tolerated. So:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
ADA-risk = MHC-II epitope density × foreignness
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
with a **self-tolerance filter** (JanusMatrix-style: an epitope whose core matches the human proteome is
|
|
25
|
+
tolerated). `foreignness` uses the **authoritative protein origin** (self vs bacterial/viral/phage) when known,
|
|
26
|
+
else `1 − self_match_fraction` from a human-proteome k-mer filter. This **recovers immunogenic-vs-tolerated**:
|
|
27
|
+
|
|
28
|
+
| Protein (real UniProt) | origin | ADA-risk |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| Bxb1 integrase (Q9B086) | foreign | **0.095** |
|
|
31
|
+
| SpCas9 (Q99ZW2) | foreign | **0.093** |
|
|
32
|
+
| ISCro4 bridge recombinase (D2TGM5) | foreign | **0.082** |
|
|
33
|
+
| Human albumin (P02768) | self | **0.0** (tolerated) |
|
|
34
|
+
|
|
35
|
+
The human self control scores 0 **even without the origin label** — the k-mer self-match tolerates it. The foreign
|
|
36
|
+
writers separate cleanly above it.
|
|
37
|
+
|
|
38
|
+
## The writer as a distinct antigen
|
|
39
|
+
|
|
40
|
+
`immune_profile` now carries a `writer_as_antigen` card and a `writer_dominant_risk` flag. The insight the
|
|
41
|
+
capsid-only profile missed: **for non-viral delivery (LNP/mRNA, eVLP) of a bacterial writer there is no capsid
|
|
42
|
+
antigen — so the WRITER is the dominant immunogen.** The flag fires accordingly; the axes are reported as a vector
|
|
43
|
+
with `collapsed_score: None` (never fused).
|
|
44
|
+
|
|
45
|
+
## Honest limits
|
|
46
|
+
- Population-level proxies (🟡), never a patient-specific ADA titer / realized CD4 magnitude (known-unknowns).
|
|
47
|
+
- The MHC-II method is presentation potential, not a trained allele-specific predictor.
|
|
48
|
+
- The self-tolerance k-mer filter is seeded by the bundled human reference; the **full human proteome** is
|
|
49
|
+
substitutable on the VM (the authoritative foreignness signal is the protein origin).
|
|
50
|
+
- The ADA axis's `calibrate_axis` pass **stays 🟡** — no public observed-incidence set at N≥6 power (the standing
|
|
51
|
+
wet-lab/clinical-data bottleneck), reported, never manufactured.
|
|
52
|
+
|
|
53
|
+
See `benchmarks/immuno/` (Immuno-Bench) and `prereg/ws_immune2.yaml`.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""PEN-STACK v3.0 - open infrastructure for genome writing."""
|
|
2
|
-
__version__ = "6.
|
|
2
|
+
__version__ = "6.9.0"
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""ADA-risk + self-tolerance filter (v6.9 PEN-IMMUNE, G-WS2).
|
|
2
|
+
|
|
3
|
+
A protein's MHC-II epitope load (presentation potential) is necessary but not sufficient for anti-drug antibodies
|
|
4
|
+
(ADA): **self** proteins carry MHC-II epitopes too, yet are tolerated (central tolerance deletes self-reactive T
|
|
5
|
+
cells). What drives ADA is **non-self** (foreign) presentable epitopes. So:
|
|
6
|
+
|
|
7
|
+
ADA-risk = MHC-II epitope density x foreignness
|
|
8
|
+
|
|
9
|
+
with a **self-tolerance filter** (JanusMatrix-style: an epitope whose core matches the human proteome is
|
|
10
|
+
tolerated; EpiVax JanusMatrix, De Groot et al.). `foreignness` uses the AUTHORITATIVE protein origin (self vs
|
|
11
|
+
bacterial/viral/phage) when known; otherwise it is `1 - self_match_fraction` from a human-proteome k-mer filter
|
|
12
|
+
(seeded here by the bundled human self-reference; the FULL human proteome is substitutable on the VM via the build
|
|
13
|
+
script). This recovers immunogenic (Cas9, bridge recombinase, serine integrase — all foreign) above tolerated
|
|
14
|
+
(human self) — the immunogenic-vs-tolerated benchmark.
|
|
15
|
+
|
|
16
|
+
Honest: a **population-level proxy (🟡)**, never a patient-specific ADA titer (a known-unknown). The calibration
|
|
17
|
+
attempt against a public ADA set runs through the EXISTING `calibrate_axis` gate; it flips to ✅ only if the gate
|
|
18
|
+
passes (it does not, at the public-data power available — reported, not manufactured).
|
|
19
|
+
"""
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
from functools import lru_cache
|
|
23
|
+
|
|
24
|
+
from pen_stack.planner.immune_mhc2 import _clean, mhc2_binder_cores, mhc2_epitope_load, writer_sequences
|
|
25
|
+
|
|
26
|
+
ADA_DOIS = ["10.1038/s41467-021-25414-9"] # Cas9 MHC-II CD4 immunogenicity (Simhadri 2021)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@lru_cache(maxsize=1)
|
|
30
|
+
def human_self_kmers(k: int = 9) -> frozenset:
|
|
31
|
+
"""9-mer set of the bundled human SELF reference proteins (the self-tolerance reference). On the VM the full
|
|
32
|
+
human proteome is substitutable (scripts/p1_build_immuno.py --human-proteome); here the bundled human
|
|
33
|
+
control(s) seed it, so the AUTHORITATIVE foreignness signal is the protein `origin`."""
|
|
34
|
+
refs = [v["seq"] for v in writer_sequences().values() if v.get("origin") == "self"]
|
|
35
|
+
ks: set = set()
|
|
36
|
+
for s in refs:
|
|
37
|
+
s = _clean(s)
|
|
38
|
+
for i in range(len(s) - k + 1):
|
|
39
|
+
ks.add(s[i:i + k])
|
|
40
|
+
return frozenset(ks)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def self_tolerance(seq: str, human_kmers: frozenset | None = None) -> dict:
|
|
44
|
+
"""Fraction of a protein's MHC-II binder cores that match the human self reference (tolerated)."""
|
|
45
|
+
human = human_kmers if human_kmers is not None else human_self_kmers()
|
|
46
|
+
cores = [c for _, c, _ in mhc2_binder_cores(seq)]
|
|
47
|
+
if not cores:
|
|
48
|
+
return {"self_match_fraction": None, "n_binder_cores": 0, "n_self_matched": 0}
|
|
49
|
+
matched = sum(1 for c in cores if c in human)
|
|
50
|
+
return {"self_match_fraction": round(matched / len(cores), 4), "n_binder_cores": len(cores),
|
|
51
|
+
"n_self_matched": matched,
|
|
52
|
+
"reference": "bundled human self proteins (full human proteome substitutable on VM)"}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def ada_risk(seq: str, origin: str | None = None, human_kmers: frozenset | None = None) -> dict:
|
|
56
|
+
"""ADA-risk = MHC-II epitope density x foreignness, with the self-tolerance filter. Higher ada_risk_score =
|
|
57
|
+
MORE anti-drug-antibody risk; `ada_immune_score = 1 - ada_risk_score` (higher = safer) for profile parity."""
|
|
58
|
+
el = mhc2_epitope_load(seq)
|
|
59
|
+
st = self_tolerance(seq, human_kmers)
|
|
60
|
+
sm = st["self_match_fraction"] or 0.0
|
|
61
|
+
if origin == "self":
|
|
62
|
+
foreign = 0.0
|
|
63
|
+
else: # foreign or unknown -> use the self-match filter
|
|
64
|
+
foreign = round(1.0 - sm, 4)
|
|
65
|
+
risk = round(el["epitope_density"] * foreign, 4)
|
|
66
|
+
return {
|
|
67
|
+
"ada_risk_score": risk, "ada_immune_score": round(1.0 - risk, 4),
|
|
68
|
+
"epitope_density": el["epitope_density"], "foreignness": foreign, "origin": origin,
|
|
69
|
+
"self_tolerance": st,
|
|
70
|
+
"direction": "ada_risk_score: higher = MORE ADA risk; ada_immune_score: higher = safer",
|
|
71
|
+
"filter": "JanusMatrix-style self-tolerance: foreign non-self MHC-II epitopes drive ADA; self epitopes are "
|
|
72
|
+
"tolerated (central tolerance). Origin is authoritative when known; else the human-proteome "
|
|
73
|
+
"k-mer filter.",
|
|
74
|
+
"status": "population-level proxy (🟡); patient ADA titer / magnitude is a known-unknown",
|
|
75
|
+
"dois": ADA_DOIS,
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def ada_risk_named(name: str) -> dict:
|
|
80
|
+
"""ADA-risk for a bundled writer/control protein by name (uses its declared origin)."""
|
|
81
|
+
rec = writer_sequences().get(name)
|
|
82
|
+
if not rec:
|
|
83
|
+
return {"available": False, "note": f"no bundled sequence {name!r}"}
|
|
84
|
+
return {"available": True, "name": name, "family": rec.get("family"), **ada_risk(rec["seq"], rec.get("origin"))}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""CD4 / MHC-II epitope-load axis for the writer enzyme AND the capsid (v6.9 PEN-IMMUNE, G-WS1).
|
|
2
|
+
|
|
3
|
+
The dominant immunogenicity driver for a protein therapeutic is **MHC-II / CD4 help -> anti-drug antibodies
|
|
4
|
+
(ADA)** — exactly what the v5.x immune profile omitted (it did CD8/MHC-I via MHCflurry only). And the **editor
|
|
5
|
+
protein itself is immunogenic** (Cas9 elicits MHC-II-presented CD4 responses, Simhadri et al., Nat Commun 2021,
|
|
6
|
+
10.1038/s41467-021-25414-9; bridge recombinases / serine integrases are bacterial/phage) — yet Stage G scored
|
|
7
|
+
only the capsid. v6.9 adds an MHC-II epitope-load axis over the **writer** as a distinct antigen.
|
|
8
|
+
|
|
9
|
+
Method (grounded, dependency-free, allele-agnostic PROMISCUOUS-binder density): MHC-II presents a 9-mer core in an
|
|
10
|
+
open groove; the **P1 pocket is deep and hydrophobic**, the single dominant anchor (M/F/Y/W/L/I/V) (Stern & Wiley,
|
|
11
|
+
Nature 1994; Jardetzky 1996), with secondary pockets at P4/P6/P9. A *promiscuous* epitope (binds many HLA-DR) is
|
|
12
|
+
exactly one with a strong P1 anchor + favorable secondaries (Southwood et al., J Immunol 1998). We count
|
|
13
|
+
promiscuous-binder cores -> an epitope-density proxy. This is a **population-level, sequence-intrinsic PROXY (🟡)**,
|
|
14
|
+
NOT a trained allele-specific predictor and NOT a patient-HLA-specific magnitude (a known-unknown). Whether those
|
|
15
|
+
epitopes drive ADA depends on self-tolerance (foreign vs self) — handled in `ada_risk`.
|
|
16
|
+
"""
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from functools import lru_cache
|
|
20
|
+
|
|
21
|
+
from pen_stack._resources import resource
|
|
22
|
+
|
|
23
|
+
_AA = set("ACDEFGHIKLMNPQRSTVWY")
|
|
24
|
+
P1_ANCHOR = set("MFYWLIV") # large hydrophobic — the dominant MHC-II P1 anchor (Stern & Wiley 1994)
|
|
25
|
+
_FAVORABLE = set("AVLIMFYWSTNQGC") # favorable at secondary pockets (hydrophobic / small / polar-uncharged)
|
|
26
|
+
_DISFAVORED = set("DEKRP") # charged / proline disfavored at anchor positions
|
|
27
|
+
MHC2_DOIS = ["10.1038/35030019", "10.1038/s41467-021-25414-9"] # Stern&Wiley groove; Cas9 MHC-II (Simhadri 2021)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _clean(seq: str) -> str:
|
|
31
|
+
return "".join(c for c in str(seq).upper() if c in _AA)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _core_is_binder(core: str) -> tuple[bool, float]:
|
|
35
|
+
"""A 9-mer core is a promiscuous-binder candidate iff P1 (pos0) is a strong hydrophobic anchor AND >=2 of the
|
|
36
|
+
secondary pockets P4/P6/P9 are favorable with no disfavored residue at an anchor position."""
|
|
37
|
+
if core[0] not in P1_ANCHOR:
|
|
38
|
+
return False, 0.0
|
|
39
|
+
sec = sum(1 for p in (3, 5, 8) if core[p] in _FAVORABLE)
|
|
40
|
+
pen = sum(1 for p in (0, 3, 5, 8) if core[p] in _DISFAVORED)
|
|
41
|
+
score = 1.0 + 0.5 * sec - 0.5 * pen
|
|
42
|
+
return (sec >= 2 and pen == 0), round(score, 3)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def mhc2_binder_cores(seq: str) -> list[tuple[int, str, float]]:
|
|
46
|
+
"""All promiscuous-binder 9-mer cores in the sequence: (start_index, core, score)."""
|
|
47
|
+
s = _clean(seq)
|
|
48
|
+
out = []
|
|
49
|
+
for i in range(len(s) - 8):
|
|
50
|
+
ok, sc = _core_is_binder(s[i:i + 9])
|
|
51
|
+
if ok:
|
|
52
|
+
out.append((i, s[i:i + 9], sc))
|
|
53
|
+
return out
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def mhc2_epitope_load(seq: str) -> dict:
|
|
57
|
+
"""Sequence-intrinsic MHC-II promiscuous-binder density + an immune score (1 = least presentable), 🟡 proxy."""
|
|
58
|
+
s = _clean(seq)
|
|
59
|
+
n_cores = max(0, len(s) - 8)
|
|
60
|
+
binders = mhc2_binder_cores(s)
|
|
61
|
+
density = (len(binders) / n_cores) if n_cores else 0.0
|
|
62
|
+
return {
|
|
63
|
+
"n_residues": len(s), "n_cores": n_cores, "n_promiscuous_binders": len(binders),
|
|
64
|
+
"epitope_density": round(density, 4),
|
|
65
|
+
"mhc2_immune_score": round(1.0 - min(density, 1.0), 4), # 1 = least presentable (MHC-I convention)
|
|
66
|
+
"method": "promiscuous MHC-II binder density (P1 hydrophobic anchor + P4/P6/P9 secondary pockets; "
|
|
67
|
+
"Stern & Wiley 1994; Southwood 1998)",
|
|
68
|
+
"status": "population-level sequence-intrinsic proxy (🟡); NOT a trained allele-specific predictor, NOT a "
|
|
69
|
+
"patient-HLA-specific magnitude (known-unknown)",
|
|
70
|
+
"binder_cores": [c for _, c, _ in binders[:50]],
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
# ---- bundled writer / control sequences (real UniProt, configs/writer_sequences.fasta) --------
|
|
75
|
+
@lru_cache(maxsize=1)
|
|
76
|
+
def writer_sequences() -> dict:
|
|
77
|
+
"""Parse the bundled writer/control FASTA -> {name: {seq, origin, family, accession}}."""
|
|
78
|
+
txt = resource("configs/writer_sequences.fasta").read_text(encoding="utf-8")
|
|
79
|
+
out: dict = {}
|
|
80
|
+
name = seq = origin = family = acc = None
|
|
81
|
+
|
|
82
|
+
def _flush():
|
|
83
|
+
if name:
|
|
84
|
+
out[name] = {"seq": seq, "origin": origin, "family": family, "accession": acc}
|
|
85
|
+
for line in txt.splitlines():
|
|
86
|
+
if line.startswith("#"):
|
|
87
|
+
continue
|
|
88
|
+
if line.startswith(">"):
|
|
89
|
+
_flush()
|
|
90
|
+
head = line[1:].strip()
|
|
91
|
+
tok = head.split()
|
|
92
|
+
name, acc = (tok[0].split("|") + [None])[:2]
|
|
93
|
+
kv = dict(p.split("=", 1) for p in tok[1:] if "=" in p)
|
|
94
|
+
origin, family, seq = kv.get("origin"), kv.get("family"), ""
|
|
95
|
+
else:
|
|
96
|
+
seq = (seq or "") + line.strip()
|
|
97
|
+
_flush()
|
|
98
|
+
return out
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def writer_family_to_sequence(writer_family: str) -> dict | None:
|
|
102
|
+
"""Map a design's writer family (e.g. 'bridge_IS110', 'serine_integrase', 'Cas9') to a bundled writer
|
|
103
|
+
sequence record, or None when no representative sequence is bundled (then the axis abstains)."""
|
|
104
|
+
fam = (writer_family or "").lower()
|
|
105
|
+
seqs = writer_sequences()
|
|
106
|
+
for name, rec in seqs.items():
|
|
107
|
+
f = (rec.get("family") or "").lower()
|
|
108
|
+
if rec.get("origin") == "self":
|
|
109
|
+
continue
|
|
110
|
+
if fam and (fam in f or f in fam or fam in name.lower()):
|
|
111
|
+
return {"name": name, **rec}
|
|
112
|
+
if "cas9" in fam or "nuclease" in fam:
|
|
113
|
+
return {"name": "SpCas9", **seqs.get("SpCas9", {})} if "SpCas9" in seqs else None
|
|
114
|
+
return None
|
|
@@ -12,8 +12,10 @@ not a patient-level prediction.
|
|
|
12
12
|
from __future__ import annotations
|
|
13
13
|
|
|
14
14
|
from pen_stack.planner.antipeg_oracle import antipeg_oracle
|
|
15
|
+
from pen_stack.planner.ada_risk import ada_risk
|
|
15
16
|
from pen_stack.planner.capsid_epitope_oracle import capsid_epitope_oracle
|
|
16
17
|
from pen_stack.planner.genotoxicity_oracle import genotoxicity_oracle
|
|
18
|
+
from pen_stack.planner.immune_mhc2 import mhc2_epitope_load, writer_family_to_sequence
|
|
17
19
|
from pen_stack.planner.innate_sensing import innate_sensing
|
|
18
20
|
from pen_stack.planner.seroprevalence_oracle import seroprevalence_oracle
|
|
19
21
|
from pen_stack.validate.immune_calibration import axis_label
|
|
@@ -67,6 +69,32 @@ def _axis(result, axis: str) -> dict:
|
|
|
67
69
|
"note": result.note}
|
|
68
70
|
|
|
69
71
|
|
|
72
|
+
def _proxy_axis(value, note: str, axis: str = "mhc2_writer") -> dict:
|
|
73
|
+
"""An axis record for the v6.9 sequence-intrinsic proxies (MHC-II / ADA). Value None = abstained (no writer
|
|
74
|
+
sequence). Population-level proxy until WS-CALIB validates — never a patient magnitude."""
|
|
75
|
+
return {"value": value, "uncertainty": None, "in_scope": value is not None, "available": value is not None,
|
|
76
|
+
"validation": axis_label(axis), "scope_card": axis, "note": note}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _writer_antigen_card(design: dict) -> dict | None:
|
|
80
|
+
"""The WRITER enzyme as a distinct antigen (v6.9 G-WS3): MHC-II epitope load + ADA-risk over the writer's real
|
|
81
|
+
sequence. Returns None when no representative writer sequence is bundled (axis then abstains)."""
|
|
82
|
+
wf = design.get("writer_family") or design.get("writer")
|
|
83
|
+
rec = writer_family_to_sequence(wf) if wf else None
|
|
84
|
+
if not rec or not rec.get("seq"):
|
|
85
|
+
return None
|
|
86
|
+
el = mhc2_epitope_load(rec["seq"])
|
|
87
|
+
ad = ada_risk(rec["seq"], rec.get("origin"))
|
|
88
|
+
return {"writer_family": wf, "representative": rec.get("name"), "accession": rec.get("accession"),
|
|
89
|
+
"origin": rec.get("origin"), "is_foreign": rec.get("origin") == "foreign",
|
|
90
|
+
"mhc2_immune_score": el["mhc2_immune_score"], "epitope_density": el["epitope_density"],
|
|
91
|
+
"ada_risk_score": ad["ada_risk_score"], "ada_immune_score": ad["ada_immune_score"],
|
|
92
|
+
"self_tolerance": ad["self_tolerance"],
|
|
93
|
+
"note": "the WRITER enzyme scored as a distinct antigen (MHC-II/CD4 + ADA, self-tolerance filtered); "
|
|
94
|
+
"bacterial/phage writers are foreign -> ADA-driving (Cas9 MHC-II: Simhadri 2021). "
|
|
95
|
+
"Population-level proxy (🟡); realized CD4 response / ADA titer is a known-unknown."}
|
|
96
|
+
|
|
97
|
+
|
|
70
98
|
def immune_profile(design: dict) -> dict:
|
|
71
99
|
"""Per-design immune-risk profile across all axes. ``design`` keys: ``delivery_vehicle`` (or ``vehicle``),
|
|
72
100
|
``serotype``, ``cargo_seq``, ``writer_output_form`` (or ``cargo_form``), ``pegylated``.
|
|
@@ -79,20 +107,46 @@ def immune_profile(design: dict) -> dict:
|
|
|
79
107
|
form = design.get("writer_output_form") or design.get("cargo_form") or ""
|
|
80
108
|
peg = design.get("pegylated")
|
|
81
109
|
|
|
110
|
+
capsid_cd8 = capsid_epitope_oracle(veh)
|
|
111
|
+
writer_card = _writer_antigen_card(design) # v6.9 — the writer enzyme as a distinct antigen
|
|
112
|
+
|
|
82
113
|
axes = {
|
|
83
114
|
"genotoxicity": _axis(genotoxicity_oracle(veh), "genotoxicity"),
|
|
84
|
-
"cd8_epitope": _axis(
|
|
115
|
+
"cd8_epitope": _axis(capsid_cd8, "cd8_epitope"), # capsid CD8/MHC-I (v5.3)
|
|
85
116
|
"innate": _axis(innate_sensing(cargo_seq, form), "innate"),
|
|
86
117
|
"preexisting_nab": _axis(seroprevalence_oracle(veh, sero), "preexisting_nab"),
|
|
87
118
|
"anti_peg": _axis(antipeg_oracle(veh, peg), "anti_peg"),
|
|
119
|
+
# v6.9 — CD4/MHC-II + ADA over the WRITER enzyme (the dominant immunogenicity driver, previously omitted)
|
|
120
|
+
"mhc2_writer": _proxy_axis(writer_card["mhc2_immune_score"] if writer_card else None,
|
|
121
|
+
(writer_card or {}).get("note", "no bundled writer sequence -> abstains"),
|
|
122
|
+
"mhc2_writer"),
|
|
123
|
+
"ada_writer": _proxy_axis(writer_card["ada_immune_score"] if writer_card else None,
|
|
124
|
+
"ADA-risk (higher ada_immune_score = safer) over the writer enzyme, self-"
|
|
125
|
+
"tolerance filtered; population proxy" if writer_card else
|
|
126
|
+
"no bundled writer sequence -> abstains", "ada_writer"),
|
|
88
127
|
}
|
|
128
|
+
|
|
129
|
+
# writer-as-antigen comparison: for non-viral delivery (no foreign capsid) or a foreign writer outscoring the
|
|
130
|
+
# capsid, the WRITER is the dominant antigen — the v6.9 insight, never collapsed into the other axes.
|
|
131
|
+
dominant = None
|
|
132
|
+
writer_dominant_risk = False
|
|
133
|
+
if writer_card:
|
|
134
|
+
capsid_present = bool(capsid_cd8.available and capsid_cd8.value
|
|
135
|
+
and (capsid_cd8.value.get("capsid_immune_score") or 1.0) < 1.0)
|
|
136
|
+
writer_risk = writer_card["ada_risk_score"]
|
|
137
|
+
capsid_risk = (1.0 - (capsid_cd8.value or {}).get("capsid_immune_score", 1.0)) if capsid_present else 0.0
|
|
138
|
+
writer_dominant_risk = bool(writer_card["is_foreign"] and (not capsid_present or writer_risk >= capsid_risk))
|
|
139
|
+
dominant = "writer" if writer_dominant_risk else ("capsid" if capsid_present else "writer")
|
|
140
|
+
|
|
89
141
|
return {
|
|
90
142
|
"axes": axes,
|
|
91
143
|
"collapsed_score": None, # deliberately None — a profile, never a fused number
|
|
144
|
+
"writer_as_antigen": ({**writer_card, "dominant_antigen": dominant,
|
|
145
|
+
"writer_dominant_risk": writer_dominant_risk} if writer_card else None),
|
|
92
146
|
"route_modifier": _route_modifier(design.get("route")), # v5.6 WS-EXT documented route modifier (or None)
|
|
93
147
|
"known_unknowns": KNOWN_UNKNOWNS,
|
|
94
148
|
"no_fabrication": True,
|
|
95
|
-
"note": ("relative immune-risk SCREEN across axes
|
|
96
|
-
"+ validation label; NOT a patient-
|
|
97
|
-
"
|
|
149
|
+
"note": ("relative immune-risk SCREEN across axes (now incl. CD4/MHC-II + ADA over the writer enzyme); each "
|
|
150
|
+
"axis keeps its own value + uncertainty + scope + validation label; NEVER fused. NOT a patient-"
|
|
151
|
+
"level prediction. The realized CD4 response / ADA titer / in-vivo magnitude are known-unknowns."),
|
|
98
152
|
}
|
|
@@ -94,6 +94,16 @@ AXIS_STATUS: dict[str, dict] = {
|
|
|
94
94
|
"label": "anti_peg: population proxy — gates re-dosing, not calibrated to re-dosing failure",
|
|
95
95
|
"reason": "anti-PEG seroprevalence gates re-dosing; not calibrated against observed re-dosing-failure "
|
|
96
96
|
"rates (and induced post-dose-1 anti-PEG is a separate dynamic)."},
|
|
97
|
+
"mhc2_writer": { # v6.9 G-WS1 — CD4/MHC-II epitope load over the writer enzyme
|
|
98
|
+
"status": "mechanistic_proxy",
|
|
99
|
+
"label": "mhc2_writer: mechanistic/population proxy — NOT outcome-validated",
|
|
100
|
+
"reason": "sequence-intrinsic promiscuous MHC-II binder density (P1-anchor; Stern & Wiley 1994) is a "
|
|
101
|
+
"presentation potential, NOT a trained allele-specific predictor or a patient-HLA magnitude."},
|
|
102
|
+
"ada_writer": { # v6.9 G-WS2 — ADA-risk (MHC-II x foreignness, self-tolerance filtered)
|
|
103
|
+
"status": "mechanistic_proxy",
|
|
104
|
+
"label": "ada_writer: mechanistic/population proxy — NOT outcome-validated",
|
|
105
|
+
"reason": "ADA-risk = MHC-II epitope density x foreignness (self-tolerance filtered) recovers immunogenic-"
|
|
106
|
+
"vs-tolerated, but is not calibrated against observed ADA incidence at public-data power."},
|
|
97
107
|
}
|
|
98
108
|
|
|
99
109
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pen-stack
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.9.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
|
|
@@ -90,7 +90,7 @@ every design against rule-grounded mechanism, reports calibrated confidence, cit
|
|
|
90
90
|
[](https://codecov.io/gh/ahmedanees-m/pen-stack)
|
|
91
91
|
[](LICENSE)
|
|
92
92
|
[](https://www.python.org/)
|
|
93
|
-
[](CHANGELOG.md)
|
|
94
94
|
[](docs/STABILITY.md)
|
|
95
95
|
[](tests/)
|
|
96
96
|
[](https://github.com/astral-sh/ruff)
|
|
@@ -148,6 +148,29 @@ demonstrated (v5.12) and the benchmark went public (v5.13).
|
|
|
148
148
|
> unknown funnel remains — made legible (scope flags, known-unknowns, honest baselines, no fabrication), not
|
|
149
149
|
> hidden.
|
|
150
150
|
|
|
151
|
+
## What is new in v6.9 — PEN-IMMUNE (MHC-II/CD4 + ADA + the writer enzyme as a distinct antigen)
|
|
152
|
+
|
|
153
|
+
The immune profile did **CD8/MHC-I only** (capsid epitope load via MHCflurry) — but the **dominant** immunogenicity
|
|
154
|
+
driver is **MHC-II / CD4 help → anti-drug antibodies (ADA)**, and the **writer enzyme itself is immunogenic**
|
|
155
|
+
(Cas9 elicits MHC-II-presented CD4 responses, Simhadri *Nat Commun* 2021; bridge recombinases / serine integrases
|
|
156
|
+
are bacterial/phage) — yet Stage G scored only the capsid. v6.9 closes that gap, **never collapsing** the axes:
|
|
157
|
+
|
|
158
|
+
- **A CD4/MHC-II epitope-load axis** (`planner/immune_mhc2.py`) — a grounded, dependency-free **promiscuous MHC-II
|
|
159
|
+
binder density** over the documented P1 hydrophobic anchor (Stern & Wiley 1994) + secondary pockets, scored over
|
|
160
|
+
**capsid AND writer** sequences. Population-level proxy (🟡), never a patient-HLA magnitude.
|
|
161
|
+
- **An ADA-risk axis** (`planner/ada_risk.py`) — **ADA-risk = MHC-II epitope density × foreignness**, with a
|
|
162
|
+
**self-tolerance filter** (JanusMatrix-style: self epitopes are tolerated; foreign drive ADA). It **recovers
|
|
163
|
+
immunogenic-vs-tolerated**: the foreign writers (real UniProt SpCas9 / ISCro4 / Bxb1) score **above** the human
|
|
164
|
+
self control (albumin), even without the origin label (the k-mer self-match tolerates the human protein).
|
|
165
|
+
- **The writer as a distinct antigen** — the profile now carries a `writer_as_antigen` card and a
|
|
166
|
+
`writer_dominant_risk` flag: for **non-viral delivery of a bacterial writer there is no capsid antigen, so the
|
|
167
|
+
WRITER is the dominant immunogen** — the insight the capsid-only profile missed.
|
|
168
|
+
- **Immuno-Bench** (`benchmarks/immuno/`) — the immunogenic-vs-tolerated recovery track + an honest `calibrate_axis`
|
|
169
|
+
ADA pass (it stays 🟡 at public-data power — no manufactured ✅, the standing wet-lab bottleneck).
|
|
170
|
+
|
|
171
|
+
Real UniProt sequences only (no fabricated sequence); the axes are reported as a vector with `collapsed_score: None`;
|
|
172
|
+
the realized CD4 response / ADA titer stay known-unknowns. See [docs/immune_profiler.md](docs/immune_profiler.md).
|
|
173
|
+
|
|
151
174
|
## What is new in v6.8 — PEN-WRITER (a cross-family writer-efficiency engine + the first writer-efficiency benchmark)
|
|
152
175
|
|
|
153
176
|
Stage C (pick the writer) was **retrieval** — the curated Writer Atlas ranks 8 families but predicts no
|
|
@@ -40,6 +40,7 @@ configs/seroprevalence.yaml
|
|
|
40
40
|
configs/target_sites.yaml
|
|
41
41
|
configs/universe_crosswalk.yaml
|
|
42
42
|
configs/write_types.yaml
|
|
43
|
+
configs/writer_sequences.fasta
|
|
43
44
|
configs/wtkb_curated.yaml
|
|
44
45
|
configs/calibration/preexisting_nab_independent.yaml
|
|
45
46
|
configs/expression/modifiers.yaml
|
|
@@ -82,6 +83,7 @@ docs/dissemination.md
|
|
|
82
83
|
docs/environment.md
|
|
83
84
|
docs/experiment_design.md
|
|
84
85
|
docs/generative_design.md
|
|
86
|
+
docs/immune_profiler.md
|
|
85
87
|
docs/index.md
|
|
86
88
|
docs/integrations.md
|
|
87
89
|
docs/live_oracles.md
|
|
@@ -213,6 +215,7 @@ pen_stack/oracles/status.py
|
|
|
213
215
|
pen_stack/oracles/structure.py
|
|
214
216
|
pen_stack/oracles/vcell.py
|
|
215
217
|
pen_stack/planner/__init__.py
|
|
218
|
+
pen_stack/planner/ada_risk.py
|
|
216
219
|
pen_stack/planner/antipeg_oracle.py
|
|
217
220
|
pen_stack/planner/capsid_epitope_oracle.py
|
|
218
221
|
pen_stack/planner/cargo.py
|
|
@@ -222,6 +225,7 @@ pen_stack/planner/delivery_constraints.py
|
|
|
222
225
|
pen_stack/planner/delivery_immunology.py
|
|
223
226
|
pen_stack/planner/delivery_vehicles.py
|
|
224
227
|
pen_stack/planner/genotoxicity_oracle.py
|
|
228
|
+
pen_stack/planner/immune_mhc2.py
|
|
225
229
|
pen_stack/planner/immune_profile.py
|
|
226
230
|
pen_stack/planner/innate_sensing.py
|
|
227
231
|
pen_stack/planner/multiplex.py
|
|
@@ -361,6 +365,7 @@ prereg/SHA256_LOCK_ws_graph.json
|
|
|
361
365
|
prereg/SHA256_LOCK_ws_h.json
|
|
362
366
|
prereg/SHA256_LOCK_ws_hybrid.json
|
|
363
367
|
prereg/SHA256_LOCK_ws_immune.json
|
|
368
|
+
prereg/SHA256_LOCK_ws_immune2.json
|
|
364
369
|
prereg/SHA256_LOCK_ws_ingest.json
|
|
365
370
|
prereg/SHA256_LOCK_ws_innate.json
|
|
366
371
|
prereg/SHA256_LOCK_ws_loop.json
|
|
@@ -432,6 +437,7 @@ prereg/ws_graph.yaml
|
|
|
432
437
|
prereg/ws_h.yaml
|
|
433
438
|
prereg/ws_hybrid.yaml
|
|
434
439
|
prereg/ws_immune.yaml
|
|
440
|
+
prereg/ws_immune2.yaml
|
|
435
441
|
prereg/ws_ingest.yaml
|
|
436
442
|
prereg/ws_innate.yaml
|
|
437
443
|
prereg/ws_loop.yaml
|