pen-stack 3.4.0__tar.gz → 4.0.1__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-3.4.0 → pen_stack-4.0.1}/CHANGELOG.md +39 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/CITATION.cff +1 -1
- {pen_stack-3.4.0 → pen_stack-4.0.1}/PKG-INFO +24 -4
- {pen_stack-3.4.0 → pen_stack-4.0.1}/README.md +23 -3
- pen_stack-4.0.1/configs/oracles/scope_cards.yaml +114 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/rules/delivery.yaml +9 -0
- pen_stack-4.0.1/docs/oracles.md +51 -0
- pen_stack-4.0.1/docs/writer_verification.md +46 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/__init__.py +1 -1
- pen_stack-4.0.1/pen_stack/atlas/writer_verify.py +167 -0
- pen_stack-4.0.1/pen_stack/oracles/__init__.py +65 -0
- pen_stack-4.0.1/pen_stack/oracles/cache.py +53 -0
- pen_stack-4.0.1/pen_stack/oracles/energetics.py +33 -0
- pen_stack-4.0.1/pen_stack/oracles/genome.py +68 -0
- pen_stack-4.0.1/pen_stack/oracles/protein_design.py +45 -0
- pen_stack-4.0.1/pen_stack/oracles/rna.py +28 -0
- pen_stack-4.0.1/pen_stack/oracles/schema.py +63 -0
- pen_stack-4.0.1/pen_stack/oracles/structure.py +43 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/rules/evaluators.py +25 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/verify/schema.py +2 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/verify/service.py +15 -1
- pen_stack-4.0.1/pen_stack/wgenome/mesh_features.py +61 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack.egg-info/PKG-INFO +24 -4
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack.egg-info/SOURCES.txt +19 -0
- pen_stack-4.0.1/prereg/SHA256_LOCK_ws_atlas.json +8 -0
- pen_stack-4.0.1/prereg/SHA256_LOCK_ws_o.json +8 -0
- pen_stack-4.0.1/prereg/SHA256_LOCK_ws_wv.json +8 -0
- pen_stack-4.0.1/prereg/ws_atlas.yaml +18 -0
- pen_stack-4.0.1/prereg/ws_o.yaml +33 -0
- pen_stack-4.0.1/prereg/ws_wv.yaml +20 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pyproject.toml +1 -1
- {pen_stack-3.4.0 → pen_stack-4.0.1}/LICENSE +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/MANIFEST.in +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/bench/run.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/benchmarks/genome_writing_bench/LEADERBOARD.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/benchmarks/genome_writing_bench/README.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/benchmarks/genome_writing_bench/SHA256SUMS +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/benchmarks/genome_writing_bench/SUBMISSIONS.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/benchmarks/genome_writing_bench/tasks.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/atlas_families.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/bridge_offtarget_profile.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/cargo_polish.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/datasets.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/delivery_constraints.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/delivery_rules.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/delivery_vehicles.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/gates_v3.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/gsh_validated_heldout.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/intent_weights.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/known_unknowns.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/llm.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/monitor_queries.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/rules/fold.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/rules/multiplex.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/rules/payload.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/rules/reachability.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/score_axes.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/target_sites.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/universe_crosswalk.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/write_types.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/configs/wtkb_curated.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/data/curated/bridge_offtarget_energetics.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/data/curated/bridge_offtarget_profile_measured.parquet +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/data/curated/gene_coords.parquet +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/data/curated/unified_editor_universe.parquet +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/BACKLOG.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/DEPLOY.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/INFRA.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/MCP.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/RELEASING.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/REPRO.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/agent.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/alphagenome_feasibility.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/benchmark_circularity.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/cards/atlas.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/cards/durability.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/cards/safety.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/delivery.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/dissemination.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/environment.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/index.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/mechanistic_constraints.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/positioning.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/private_data_formats.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/quickstart.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/rules.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/scope.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/scorecard.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/tutorials/compare-families.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/tutorials/score-deliverability.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/tutorials/where-can-i-write.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/tutorials/which-writer-reaches-locus.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/uncertainty.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/verify.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/docs/wtkb.md +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/_resources.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/adapt/__init__.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/adapt/finetune.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/adapt/ingest.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/adapt/pipeline.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/adapt/recalibrate.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/adapt/report.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/agent/__init__.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/agent/epistemic.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/agent/guardrails.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/agent/mcp_server.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/agent/orchestrator.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/agent/pen_agent.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/agent/scope.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/agent/tools.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/atlas/__init__.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/atlas/build_wtkb.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/atlas/crosslink.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/atlas/expand.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/atlas/schema.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/atlas/scorecard.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/atlas/universe.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/atlas/variant_propose.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/bridge/__init__.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/bridge/activity.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/bridge/cli.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/bridge/fold_qc.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/bridge/guide_qc.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/bridge/ingest.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/bridge/offtarget.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/bridge/offtarget_energetics.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/bridge/ortholog_screen.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/bridge/pipeline.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/cli.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/data/__init__.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/data/encode.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/data/genome.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/data/ingest_chromatin.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/data/ingest_integration.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/data/ingest_safety_annot.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/data/ingest_trip.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/env/__init__.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/env/genome_writing_env.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/env/policies.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/mech/__init__.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/mech/classify_atlas.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/mech/whitelist.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/monitor/__init__.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/monitor/europepmc.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/monitor/run.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/monitor/triage.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/planner/__init__.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/planner/cargo.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/planner/cargo_polish.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/planner/delivery.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/planner/delivery_constraints.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/planner/delivery_vehicles.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/planner/multiplex.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/planner/optimize.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/planner/pipeline.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/planner/report.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/planner/router.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/planner/target_site.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/rag/__init__.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/rag/index.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/rag/llm.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/rag/qa.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/rules/__init__.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/rules/loader.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/rules/schema.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/rules/solver.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/score/__init__.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/score/recalibrate.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/score/therapeutic.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/server/__init__.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/server/api.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/ui/__init__.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/ui/app.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/__init__.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/adapt_demo.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/agent_eval.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/bench_adversarial_tasks.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/bench_rule_tasks.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/bench_trust_tasks.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/bench_writetype_tasks.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/blind_gsh_discovery.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/cargo_directionality.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/durability_baselines.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/forward_hypotheses.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/guide_qc_demo.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/intent_specification.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/offtarget_energetics_eval.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/out_of_scope_refusal.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/outcome_calibration.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/paper3_benchmark.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/paper4_real_validation.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/paper4_validation.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/selective_prediction.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/seq_vs_measured.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/target_site_controls.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/uncertainty_eval.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/ungrounded_baseline.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/within_locus_ranking.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/validate/writer_recovery.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/verify/__init__.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/wgenome/__init__.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/wgenome/chromatin_seq.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/wgenome/durability.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/wgenome/export_tracks.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/wgenome/features.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/wgenome/gsh_baseline.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/wgenome/ood.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/wgenome/providers.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/wgenome/safety.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/wgenome/structure3d.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/wgenome/uncertainty.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack/wgenome/writability.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack.egg-info/dependency_links.txt +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack.egg-info/entry_points.txt +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack.egg-info/requires.txt +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/pen_stack.egg-info/top_level.txt +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_phase0.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_phase1_5.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_phase2.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_phase3.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_ws_a.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_ws_b.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_ws_ba.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_ws_ba_v33.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_ws_bench.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_ws_c.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_ws_cal.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_ws_d.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_ws_e.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_ws_env.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_ws_ep.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_ws_f.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_ws_g.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_ws_h.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_ws_mc.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_ws_r.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_ws_route.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_ws_uq.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/SHA256_LOCK_ws_v.json +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/paper1.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/paper2.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/paper3.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/paper4.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/phase0.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/ws_a.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/ws_b.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/ws_ba.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/ws_ba_v33.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/ws_bench.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/ws_c.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/ws_cal.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/ws_d.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/ws_e.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/ws_env.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/ws_ep.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/ws_f.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/ws_g.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/ws_h.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/ws_mc.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/ws_r.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/ws_route.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/ws_uq.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/prereg/ws_v.yaml +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/scripts/p1_build_atlas.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/scripts/p1_build_durability.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/scripts/p1_export_tracks.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/scripts/p1_safety_concordance.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/scripts/p1_train_safety.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/scripts/p1_validation_report.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/scripts/p2_build_atlas.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/scripts/p3_benchmark_report.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/scripts/p4_genome_scan.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/scripts/ws_b_report.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/scripts/ws_c_report.py +0 -0
- {pen_stack-3.4.0 → pen_stack-4.0.1}/setup.cfg +0 -0
|
@@ -3,6 +3,45 @@
|
|
|
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
|
+
## [4.0.1] - 2026-06-09 - data-correctness patch: writer-verification panel verified against Perry 2025
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
- **WS-WV frozen panel is now verbatim from the measured Perry 2025 ISCro4 DMS.** The offline-fallback panel
|
|
10
|
+
in `atlas/writer_verify.py` previously used *illustrative* Z-scores (2.6/2.1/1.7) and invented control
|
|
11
|
+
variants (G15D/P88R/L120E), and `_CORE_RESIDUES` used illustrative arginines. Replaced with the REAL values
|
|
12
|
+
from `science.adz0276` Table S3: the top-3 enhancers **N322P (Z 0.754), H50K (0.742), R278M (0.709)**, real
|
|
13
|
+
near-neutral variants (V21R, S312Q, G286T), the most-deleterious variants (R132E −5.40, R137E −5.12,
|
|
14
|
+
R195D −4.98), and the documented catalytic residues **D11/E60/D102/D105/S241** ("Residue Groups" sheet). The
|
|
15
|
+
real-DMS path (on the VM/Drive) was already correct; only the offline fallback constants were illustrative.
|
|
16
|
+
Added `test_ws_wv.py::test_frozen_panel_matches_real_perry_dms_table_s3` to guard against drift.
|
|
17
|
+
|
|
18
|
+
## [4.0.0] - 2026-06-09 - v4.0 release: the Oracle Mesh (on top of the foundation models) + writer verification
|
|
19
|
+
|
|
20
|
+
A major bump: the substrate now *composes* the biomolecular foundation models under one contract and verifies
|
|
21
|
+
the writer enzyme itself. Workstreams WS-{O,WV,ATLAS}, each SHA-locked. No de-novo writer invention — score
|
|
22
|
+
and critique only (the pen-assemble lesson).
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
- **WS-O - the oracle mesh.** `pen_stack/oracles/` with `OracleResult{value, provenance(model+version),
|
|
26
|
+
native_uncertainty, scope_card, in_scope, extrapolating, output_kind, available, cached}`. Adapters:
|
|
27
|
+
`genome.py` (AlphaGenome OOD-gated; Evo2 likelihood=claim / generation=candidate; ChromBPNet·Borzoi
|
|
28
|
+
baseline), `structure.py` (AlphaFold3/Boltz-2/Chai-1/Protenix + `consensus()` that widens the interval on
|
|
29
|
+
cross-oracle disagreement), `protein_design.py` (RFdiffusion/ProteinMPNN/ESM3 - all candidates), `rna.py`
|
|
30
|
+
(ViennaRNA - real, hard fold-legality), `energetics.py` (bridge off-target, MC3 gate ≥0.77).
|
|
31
|
+
`configs/oracles/scope_cards.yaml` (11 models); deterministic version-pinned `oracle_cache/`. Guard:
|
|
32
|
+
generative candidate `as_claim()` raises. `docs/oracles.md`; `prereg/ws_o.yaml`.
|
|
33
|
+
- **WS-WV - writer verification.** `pen_stack/atlas/writer_verify.py`: DMS- + structure-grounded variant
|
|
34
|
+
scoring (measured=claimable, unmeasured=not), `blind_recovery` recovers N322P/H50K/R278M above
|
|
35
|
+
measured-worse controls, and `critique_candidate` (fold/active-site/deliverable/reachable) wired into
|
|
36
|
+
`verify()` as `Verdict.writer_critique` - always `no_claim=True`. `docs/writer_verification.md`;
|
|
37
|
+
`prereg/ws_wv.yaml`.
|
|
38
|
+
- **WS-ATLAS - mesh upgrade + delivery oracle.** `wgenome/mesh_features.py` (OOD-gated feature hook + honest
|
|
39
|
+
blind re-validation reporting parity vs v3.x when oracles are deferred) + a computable
|
|
40
|
+
`delivery.aav_packaging_margin` soft rule (titre drops near the AAV capsid limit). `prereg/ws_atlas.yaml`.
|
|
41
|
+
|
|
42
|
+
### Changed
|
|
43
|
+
- Version 3.4.0 -> 4.0.0; `Verdict` gains `writer_critique`; M1 + writer-verification note + M2 updates.
|
|
44
|
+
|
|
6
45
|
## [3.4.0] - 2026-06-09 - v3.4 release: the Environment (train/eval surface + bench v0.3 + outcome-calibration)
|
|
7
46
|
|
|
8
47
|
v3.4 turns the thin Gym interface into a full environment an AI agent can be trained and graded in, ships
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pen-stack
|
|
3
|
-
Version:
|
|
3
|
+
Version: 4.0.1
|
|
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
|
|
@@ -89,8 +89,8 @@ and durably write new DNA, **which enzyme** can write it there, and **how** to d
|
|
|
89
89
|
[](https://codecov.io/gh/ahmedanees-m/pen-stack)
|
|
90
90
|
[](LICENSE)
|
|
91
91
|
[](https://www.python.org/)
|
|
92
|
-
[](CHANGELOG.md)
|
|
93
|
+
[](tests/)
|
|
94
94
|
[](https://github.com/astral-sh/ruff)
|
|
95
95
|
[](docker/)
|
|
96
96
|
[](prereg/)
|
|
@@ -133,6 +133,25 @@ Two questions gate every genome-writing project, and before PEN-STACK no resourc
|
|
|
133
133
|
Everything is built on bulk-downloadable public data, runs on a single GPU, and is validated **blind** against
|
|
134
134
|
a pre-registered, honest baseline before release.
|
|
135
135
|
|
|
136
|
+
## What is new in v4.0 — the Oracle Mesh (sitting on top of the foundation models)
|
|
137
|
+
|
|
138
|
+
v4.0 makes PEN-STACK the **composition + verification layer over the biomolecular foundation models**. It
|
|
139
|
+
wraps AlphaGenome, Evo2, AlphaFold3, Boltz-2, Chai-1, Protenix, ESM3, RFdiffusion and ProteinMPNN under one
|
|
140
|
+
contract that carries each model's provenance, native uncertainty, and a **scope card** stating what it is
|
|
141
|
+
valid for — then routes their outputs through the rule-grounded verifier and the calibrated trust layer. A
|
|
142
|
+
generated sequence or structure is always a **candidate to be checked, never a claim**. For the writer enzyme
|
|
143
|
+
itself, v4.0 builds **verification, not invention**: proposed/variant writers are scored against measured DMS
|
|
144
|
+
data and predicted structure, recovering known enhanced variants blind and refusing to assert activity for
|
|
145
|
+
anything unsupported.
|
|
146
|
+
|
|
147
|
+
| Workstream | What it adds | Result |
|
|
148
|
+
|---|---|---|
|
|
149
|
+
| **O — the oracle mesh** | `pen_stack/oracles/` — `OracleResult{value, provenance(model+version), native_uncertainty, scope_card, output_kind}`; adapters for genome / structure / protein-design / RNA / energetics; deterministic version-pinned cache | one contract; **generative output = candidate** (`as_claim()` raises — the pen-assemble lesson in code); AlphaGenome **OOD-gated**; cross-oracle **disagreement widens the interval**; ViennaRNA + energetics real |
|
|
150
|
+
| **WV — writer verification** | `atlas/writer_verify.py` — DMS- + structure-grounded variant scoring; candidate **critique** wired into `verify()` | recovers the known enhancers (**N322P / H50K / R278M**) above measured-worse controls; unmeasured variants flagged, **not claimable**; a generated writer is critiqued (fold/active-site/deliverable/reachable), **never returned as a working pen** |
|
|
151
|
+
| **ATLAS — mesh + delivery oracle** | `wgenome/mesh_features.py` (OOD-gated feature hook + honest blind re-validation) + a computable **AAV packaging-margin** delivery rule | atlas re-validation reports **parity** vs v3.x when oracles are deferred (delta 0.0, never hidden); titre-margin flag fires near the AAV capsid limit; immunogenicity magnitude stays a scope flag |
|
|
152
|
+
|
|
153
|
+
See `docs/oracles.md`, `docs/writer_verification.md`, and `prereg/ws_{o,wv,atlas}.yaml`.
|
|
154
|
+
|
|
136
155
|
## What is new in v3.4 — the Environment (a place to train and grade genome-writing AI)
|
|
137
156
|
|
|
138
157
|
v3.4 makes PEN-STACK the surface an AI agent can be **trained and graded** in, the counterpart to v3.3's
|
|
@@ -377,8 +396,9 @@ pen-stack/
|
|
|
377
396
|
│ │ + v3.2 offtarget_energetics (position x substitution; held-out 0.88, ships)
|
|
378
397
|
│ ├── agent/ agentic platform: tools / orchestrator / pen_agent / mcp_server / guardrails
|
|
379
398
|
│ │ + v3.2 epistemic (3-tier status) / scope (known-unknowns matcher)
|
|
399
|
+
│ ├── oracles/ v4.0 L1 oracle mesh: OracleResult contract + adapters (genome/structure/protein_design/rna/energetics) over the foundation models; version-pinned cache
|
|
380
400
|
│ ├── rules/ v3.3 machine-readable rules engine (schema/evaluators/loader/solver) over configs/rules/*.yaml
|
|
381
|
-
│ ├── verify/ v3.3 verification service: verify(design) -> Verdict (legal+reasons+confidence+scope)
|
|
401
|
+
│ ├── verify/ v3.3 verification service: verify(design) -> Verdict (legal+reasons+confidence+scope; v4.0 writer_critique)
|
|
382
402
|
│ ├── adapt/ local recalibration / private-data adaptation behind a gate (v3.1, WS-F)
|
|
383
403
|
│ ├── env/ v3.4 full Gymnasium environment over router+verifier (genome_writing_env + policies; [env] extra)
|
|
384
404
|
│ ├── monitor/ PEN-MONITOR living database (Europe PMC)
|
|
@@ -14,8 +14,8 @@ and durably write new DNA, **which enzyme** can write it there, and **how** to d
|
|
|
14
14
|
[](https://codecov.io/gh/ahmedanees-m/pen-stack)
|
|
15
15
|
[](LICENSE)
|
|
16
16
|
[](https://www.python.org/)
|
|
17
|
-
[](CHANGELOG.md)
|
|
18
|
+
[](tests/)
|
|
19
19
|
[](https://github.com/astral-sh/ruff)
|
|
20
20
|
[](docker/)
|
|
21
21
|
[](prereg/)
|
|
@@ -58,6 +58,25 @@ Two questions gate every genome-writing project, and before PEN-STACK no resourc
|
|
|
58
58
|
Everything is built on bulk-downloadable public data, runs on a single GPU, and is validated **blind** against
|
|
59
59
|
a pre-registered, honest baseline before release.
|
|
60
60
|
|
|
61
|
+
## What is new in v4.0 — the Oracle Mesh (sitting on top of the foundation models)
|
|
62
|
+
|
|
63
|
+
v4.0 makes PEN-STACK the **composition + verification layer over the biomolecular foundation models**. It
|
|
64
|
+
wraps AlphaGenome, Evo2, AlphaFold3, Boltz-2, Chai-1, Protenix, ESM3, RFdiffusion and ProteinMPNN under one
|
|
65
|
+
contract that carries each model's provenance, native uncertainty, and a **scope card** stating what it is
|
|
66
|
+
valid for — then routes their outputs through the rule-grounded verifier and the calibrated trust layer. A
|
|
67
|
+
generated sequence or structure is always a **candidate to be checked, never a claim**. For the writer enzyme
|
|
68
|
+
itself, v4.0 builds **verification, not invention**: proposed/variant writers are scored against measured DMS
|
|
69
|
+
data and predicted structure, recovering known enhanced variants blind and refusing to assert activity for
|
|
70
|
+
anything unsupported.
|
|
71
|
+
|
|
72
|
+
| Workstream | What it adds | Result |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| **O — the oracle mesh** | `pen_stack/oracles/` — `OracleResult{value, provenance(model+version), native_uncertainty, scope_card, output_kind}`; adapters for genome / structure / protein-design / RNA / energetics; deterministic version-pinned cache | one contract; **generative output = candidate** (`as_claim()` raises — the pen-assemble lesson in code); AlphaGenome **OOD-gated**; cross-oracle **disagreement widens the interval**; ViennaRNA + energetics real |
|
|
75
|
+
| **WV — writer verification** | `atlas/writer_verify.py` — DMS- + structure-grounded variant scoring; candidate **critique** wired into `verify()` | recovers the known enhancers (**N322P / H50K / R278M**) above measured-worse controls; unmeasured variants flagged, **not claimable**; a generated writer is critiqued (fold/active-site/deliverable/reachable), **never returned as a working pen** |
|
|
76
|
+
| **ATLAS — mesh + delivery oracle** | `wgenome/mesh_features.py` (OOD-gated feature hook + honest blind re-validation) + a computable **AAV packaging-margin** delivery rule | atlas re-validation reports **parity** vs v3.x when oracles are deferred (delta 0.0, never hidden); titre-margin flag fires near the AAV capsid limit; immunogenicity magnitude stays a scope flag |
|
|
77
|
+
|
|
78
|
+
See `docs/oracles.md`, `docs/writer_verification.md`, and `prereg/ws_{o,wv,atlas}.yaml`.
|
|
79
|
+
|
|
61
80
|
## What is new in v3.4 — the Environment (a place to train and grade genome-writing AI)
|
|
62
81
|
|
|
63
82
|
v3.4 makes PEN-STACK the surface an AI agent can be **trained and graded** in, the counterpart to v3.3's
|
|
@@ -302,8 +321,9 @@ pen-stack/
|
|
|
302
321
|
│ │ + v3.2 offtarget_energetics (position x substitution; held-out 0.88, ships)
|
|
303
322
|
│ ├── agent/ agentic platform: tools / orchestrator / pen_agent / mcp_server / guardrails
|
|
304
323
|
│ │ + v3.2 epistemic (3-tier status) / scope (known-unknowns matcher)
|
|
324
|
+
│ ├── oracles/ v4.0 L1 oracle mesh: OracleResult contract + adapters (genome/structure/protein_design/rna/energetics) over the foundation models; version-pinned cache
|
|
305
325
|
│ ├── rules/ v3.3 machine-readable rules engine (schema/evaluators/loader/solver) over configs/rules/*.yaml
|
|
306
|
-
│ ├── verify/ v3.3 verification service: verify(design) -> Verdict (legal+reasons+confidence+scope)
|
|
326
|
+
│ ├── verify/ v3.3 verification service: verify(design) -> Verdict (legal+reasons+confidence+scope; v4.0 writer_critique)
|
|
307
327
|
│ ├── adapt/ local recalibration / private-data adaptation behind a gate (v3.1, WS-F)
|
|
308
328
|
│ ├── env/ v3.4 full Gymnasium environment over router+verifier (genome_writing_env + policies; [env] extra)
|
|
309
329
|
│ ├── monitor/ PEN-MONITOR living database (Europe PMC)
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# PEN-STACK v4.0 — oracle scope cards (WS-O0). What each wrapped foundation model is VALID for, and what it
|
|
2
|
+
# is NOT — so the substrate can gate and label outputs (the field's evidence that these models do not
|
|
3
|
+
# generalize to unseen loci is made legible here, not hidden). `output_kind`: claim (a checkable prediction),
|
|
4
|
+
# candidate (a generative proposal that must pass writer-verification), baseline (an honest comparator).
|
|
5
|
+
version: "1.0"
|
|
6
|
+
|
|
7
|
+
oracles:
|
|
8
|
+
alphagenome:
|
|
9
|
+
family: genome
|
|
10
|
+
version: "2025.1"
|
|
11
|
+
output_kind: claim
|
|
12
|
+
valid_for: "regulatory-track + variant-effect prediction at IN-DISTRIBUTION loci (trained tracks/tissues)"
|
|
13
|
+
not_valid_for: "unseen loci / cell types outside training; does NOT generalize to novel regulatory contexts"
|
|
14
|
+
generalizes_to_unseen_loci: false
|
|
15
|
+
license: "non-commercial (Google DeepMind terms)"
|
|
16
|
+
|
|
17
|
+
evo2:
|
|
18
|
+
family: genome
|
|
19
|
+
version: "40b-2025"
|
|
20
|
+
output_kind: candidate # generative DNA + likelihood; sequences are proposals, never claims
|
|
21
|
+
valid_for: "genomic sequence likelihood / zero-shot variant scoring; generative DNA candidates"
|
|
22
|
+
not_valid_for: "accessibility/expression QTLs; quantitative regulatory tracks; asserting a sequence WORKS"
|
|
23
|
+
generalizes_to_unseen_loci: false
|
|
24
|
+
license: "Apache-2.0 (Arc Institute)"
|
|
25
|
+
|
|
26
|
+
chrombpnet_borzoi:
|
|
27
|
+
family: genome
|
|
28
|
+
version: "borzoi-2024"
|
|
29
|
+
output_kind: baseline # kept as an honest comparator to AlphaGenome
|
|
30
|
+
valid_for: "accessibility / expression baseline tracks (honest comparator)"
|
|
31
|
+
not_valid_for: "variant effects beyond trained assays"
|
|
32
|
+
generalizes_to_unseen_loci: false
|
|
33
|
+
license: "open"
|
|
34
|
+
|
|
35
|
+
alphafold3:
|
|
36
|
+
family: structure
|
|
37
|
+
version: "3.0-2024"
|
|
38
|
+
output_kind: claim
|
|
39
|
+
valid_for: "protein / protein-NA complex structure at confidence (pLDDT/PAE) within trained fold space"
|
|
40
|
+
not_valid_for: "absolute binding free energies; novel folds far from the PDB; in-vivo behaviour"
|
|
41
|
+
generalizes_to_unseen_loci: true # structure prediction is not locus-bound
|
|
42
|
+
license: "non-commercial weights (DeepMind terms)"
|
|
43
|
+
|
|
44
|
+
boltz-2:
|
|
45
|
+
family: structure
|
|
46
|
+
version: "2.0-2025"
|
|
47
|
+
output_kind: claim
|
|
48
|
+
valid_for: "structure + binding-affinity prediction (open weights); cross-oracle consistency comparator"
|
|
49
|
+
not_valid_for: "guaranteed affinities; designs outside trained chemical space"
|
|
50
|
+
generalizes_to_unseen_loci: true
|
|
51
|
+
license: "MIT"
|
|
52
|
+
|
|
53
|
+
chai-1:
|
|
54
|
+
family: structure
|
|
55
|
+
version: "1.0-2024"
|
|
56
|
+
output_kind: claim
|
|
57
|
+
valid_for: "structure prediction; cross-oracle self-consistency"
|
|
58
|
+
not_valid_for: "absolute affinities; far-OOD complexes"
|
|
59
|
+
generalizes_to_unseen_loci: true
|
|
60
|
+
license: "Apache-2.0"
|
|
61
|
+
|
|
62
|
+
protenix:
|
|
63
|
+
family: structure
|
|
64
|
+
version: "0.5-2025"
|
|
65
|
+
output_kind: claim
|
|
66
|
+
valid_for: "AF3-style structure prediction (open); cross-oracle self-consistency"
|
|
67
|
+
not_valid_for: "absolute affinities; far-OOD complexes"
|
|
68
|
+
generalizes_to_unseen_loci: true
|
|
69
|
+
license: "Apache-2.0"
|
|
70
|
+
|
|
71
|
+
esm3:
|
|
72
|
+
family: protein_design
|
|
73
|
+
version: "sm-2024"
|
|
74
|
+
output_kind: candidate
|
|
75
|
+
valid_for: "protein representation + generative protein design CANDIDATES; variant likelihoods"
|
|
76
|
+
not_valid_for: "asserting a designed protein FOLDS or is ACTIVE without verification"
|
|
77
|
+
generalizes_to_unseen_loci: true
|
|
78
|
+
license: "non-commercial / community"
|
|
79
|
+
|
|
80
|
+
rfdiffusion:
|
|
81
|
+
family: protein_design
|
|
82
|
+
version: "aa-2024"
|
|
83
|
+
output_kind: candidate
|
|
84
|
+
valid_for: "backbone generation CANDIDATES (RFdiffusion / RFdiffusion-AA)"
|
|
85
|
+
not_valid_for: "asserting function; a backbone is a proposal, not a working enzyme"
|
|
86
|
+
generalizes_to_unseen_loci: true
|
|
87
|
+
license: "open (BSD-style)"
|
|
88
|
+
|
|
89
|
+
proteinmpnn:
|
|
90
|
+
family: protein_design
|
|
91
|
+
version: "ligandmpnn-2024"
|
|
92
|
+
output_kind: candidate
|
|
93
|
+
valid_for: "sequence design for a fixed backbone CANDIDATES (ProteinMPNN / LigandMPNN)"
|
|
94
|
+
not_valid_for: "asserting activity/specificity; must be scored against measured data"
|
|
95
|
+
generalizes_to_unseen_loci: true
|
|
96
|
+
license: "MIT"
|
|
97
|
+
|
|
98
|
+
viennarna:
|
|
99
|
+
family: rna
|
|
100
|
+
version: "2.6"
|
|
101
|
+
output_kind: claim
|
|
102
|
+
valid_for: "RNA secondary-structure MFE fold (a HARD legality input for bridge-RNA QC)"
|
|
103
|
+
not_valid_for: "tertiary structure; in-cell folding kinetics"
|
|
104
|
+
generalizes_to_unseen_loci: true
|
|
105
|
+
license: "open"
|
|
106
|
+
|
|
107
|
+
bridge_energetics:
|
|
108
|
+
family: energetics
|
|
109
|
+
version: "v3.2-mc3"
|
|
110
|
+
output_kind: claim
|
|
111
|
+
valid_for: "bridge IS110/ISCro4 off-target relative-risk ranking (beats the 0.77 position-weight baseline)"
|
|
112
|
+
not_valid_for: "absolute off-target rates; non-bridge writers; a non-recombining background"
|
|
113
|
+
generalizes_to_unseen_loci: false
|
|
114
|
+
license: "open (this work)"
|
|
@@ -29,6 +29,15 @@ rules:
|
|
|
29
29
|
provenance: { doi: ["10.1089/hum.2017.084"], note: "v3.2 MC2 delivery_constraints scan" }
|
|
30
30
|
test_ref: "tests/unit/test_ws_r.py::test_delivery_controls"
|
|
31
31
|
scope: "labeled heuristic, directional; not a titre predictor"
|
|
32
|
+
- id: delivery.aav_packaging_margin
|
|
33
|
+
kind: soft_penalty
|
|
34
|
+
category: delivery
|
|
35
|
+
mechanism: "AAV packaging efficiency / titre drops sharply as the cargo approaches the capsid limit (computable from cargo_bp vs vehicle capacity), even while still under capacity (v4.0 delivery-oracle refinement)"
|
|
36
|
+
evaluator: delivery_aav_packaging
|
|
37
|
+
param: { margin_frac: 0.9 }
|
|
38
|
+
provenance: { doi: ["10.1089/hum.2010.245"], note: "AAV genome-size vs packaging-efficiency relationship" }
|
|
39
|
+
test_ref: "tests/unit/test_ws_atlas.py::test_aav_packaging_margin"
|
|
40
|
+
scope: "computable efficiency margin, directional; not a titre predictor"
|
|
32
41
|
- id: delivery.immunogenicity_magnitude
|
|
33
42
|
kind: scope_flag
|
|
34
43
|
category: delivery
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# The oracle mesh (v4.0, WS-O)
|
|
2
|
+
|
|
3
|
+
PEN-STACK v4.0 sits **on top of** the biomolecular foundation models. `pen_stack.oracles` wraps them under one
|
|
4
|
+
contract so their outputs can be composed, checked by the rule-grounded verifier, and trust-calibrated —
|
|
5
|
+
without losing provenance, native uncertainty, or scope.
|
|
6
|
+
|
|
7
|
+
## One contract: `OracleResult`
|
|
8
|
+
|
|
9
|
+
Every adapter returns an `OracleResult`:
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
OracleResult{oracle, value, provenance{model, version, source, cache_key},
|
|
13
|
+
native_uncertainty, scope_card, in_scope, extrapolating,
|
|
14
|
+
output_kind ∈ {claim, candidate, baseline}, available, cached}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Three invariants are encoded in the type:
|
|
18
|
+
|
|
19
|
+
1. **A generative output is a candidate, never a claim.** `output_kind="candidate"` (Evo2 generation, ESM3,
|
|
20
|
+
RFdiffusion, ProteinMPNN) → `as_claim()` **raises**. A candidate must pass writer-verification (WS-WV)
|
|
21
|
+
before any claim. (The pen-assemble lesson — 0 validatable de-novo writers — encoded in code.)
|
|
22
|
+
2. **One contract for every oracle.** Provenance (model + version) and the model's *native* uncertainty are
|
|
23
|
+
always carried; every call is cache-keyed on `(oracle, model, version, inputs)` and replayable offline.
|
|
24
|
+
3. **Scope is explicit.** Each result carries its scope-card id and an `extrapolating` flag; the field's
|
|
25
|
+
evidence that these models do not generalize to unseen loci is **labelled**, not hidden.
|
|
26
|
+
|
|
27
|
+
## Wrapped models (scope cards in `configs/oracles/scope_cards.yaml`)
|
|
28
|
+
|
|
29
|
+
| Family | Models | Output kind |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| `genome` | AlphaGenome (OOD-gated), Evo2 (likelihood=claim / generation=candidate), ChromBPNet·Borzoi (baseline) | claim / candidate / baseline |
|
|
32
|
+
| `structure` | AlphaFold3, Boltz-2, Chai-1, Protenix + `consistency()` | claim |
|
|
33
|
+
| `protein_design` | ESM3, RFdiffusion(-AA), ProteinMPNN·LigandMPNN | **candidate** |
|
|
34
|
+
| `rna` | ViennaRNA (real; hard fold-legality input) | claim |
|
|
35
|
+
| `energetics` | bridge off-target (MC3 gate ≥ 0.77) | claim |
|
|
36
|
+
|
|
37
|
+
## Cross-oracle consistency
|
|
38
|
+
|
|
39
|
+
`structure.consistency(seq)` runs the available structure predictors and combines them with `consensus()`:
|
|
40
|
+
agreement is a confidence signal, and **disagreement widens the reported interval** (`native_uncertainty`
|
|
41
|
+
grows with the cross-oracle spread) — v4.0 Principle 3.
|
|
42
|
+
|
|
43
|
+
## Compute / offline policy
|
|
44
|
+
|
|
45
|
+
Heavy backends (AF3, Evo2, ESM3, …) run on-demand (hosted API / local GPU) and are cached + version-pinned
|
|
46
|
+
under `oracle_cache/` (committed for offline CI). When a backend and a cache entry are both absent, the
|
|
47
|
+
adapter returns a **deferred** result (`available=False`) — it never fabricates a value. ViennaRNA and the
|
|
48
|
+
bridge energetics model are real and run locally / on the VM.
|
|
49
|
+
|
|
50
|
+
See `docs/writer_verification.md` (scoring/critiquing writers through the mesh), `prereg/ws_o.yaml`, and
|
|
51
|
+
`pen_stack/oracles/`.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Writer verification (v4.0, WS-WV) — the honest "better pen"
|
|
2
|
+
|
|
3
|
+
PEN-STACK does **not** invent writer enzymes de-novo. The earlier `pen-assemble` direction produced **0
|
|
4
|
+
validatable de-novo writers** and could not be checked computationally. v4.0 builds the honest alternative:
|
|
5
|
+
**score and critique** proposed or variant writers against measured data — never assert novel function.
|
|
6
|
+
|
|
7
|
+
## WV1 — variant scoring (DMS- + structure-grounded)
|
|
8
|
+
|
|
9
|
+
`pen_stack.atlas.writer_verify.score_variants(variants)` returns, per variant, a **calibrated activity score**
|
|
10
|
+
in [0, 1] with an interval and a scope flag:
|
|
11
|
+
|
|
12
|
+
- A variant present in the **Perry-2025 ISCro4 deep mutational scan** is scored from its *measured* activity
|
|
13
|
+
Z-score → `claimable=True`, finite interval.
|
|
14
|
+
- A variant **out of the DMS distribution** → `extrapolating=True`, `claimable=False` — a plausibility screen
|
|
15
|
+
only, **no activity claim**.
|
|
16
|
+
|
|
17
|
+
`blind_recovery()` is the deterministic retrospective criterion: ranking the documented panel, the known
|
|
18
|
+
enhancers **N322P / H50K / R278M** land on top, above the measured-worse controls. `real_dms_recovery()`
|
|
19
|
+
reports the same against the full Perry DMS when it is present (on the VM). This is a *catalogue* feature that
|
|
20
|
+
recovers known enhancers — **not** a blind sequence-only predictor, and stated as such.
|
|
21
|
+
|
|
22
|
+
## WV2 — critique, not invention
|
|
23
|
+
|
|
24
|
+
`critique_candidate(seq, ...)` takes a **generated** candidate writer (e.g. from `oracles.protein_design`,
|
|
25
|
+
which only ever returns `candidate` outputs) and critiques it:
|
|
26
|
+
|
|
27
|
+
| Check | Source |
|
|
28
|
+
|---|---|
|
|
29
|
+
| folds? | structure oracle (`oracles.structure.consistency`) — deferred → flagged, never asserted |
|
|
30
|
+
| plausible active site? | retains conserved core residues (heuristic) |
|
|
31
|
+
| deliverable form? | the rule-grounded verifier (delivery rules) |
|
|
32
|
+
| reachable target? | the rule-grounded verifier (reachability rules) |
|
|
33
|
+
|
|
34
|
+
It returns `pass`/flags + reasons, and **always** `no_claim=True`, `claimable=False`. A generated writer is
|
|
35
|
+
never returned as "a working new pen." The verifier surfaces this as `Verdict.writer_critique` (a scope flag,
|
|
36
|
+
never a confidence): the legality of the write *plan* and the activity *claim* for the candidate are distinct
|
|
37
|
+
axes — a legal plan does not make an unverified candidate claimable.
|
|
38
|
+
|
|
39
|
+
## Scope & honesty
|
|
40
|
+
|
|
41
|
+
- Deep DMS exists for **few** enzymes (bridge recombinases); elsewhere WV1 is a labelled plausibility screen.
|
|
42
|
+
- Generative designs are **proposals**; they are scored/critiqued, never asserted active.
|
|
43
|
+
- Structure verification is deferred without an AF3/Boltz/Chai/Protenix backend or a committed cache entry —
|
|
44
|
+
the candidate is then explicitly *fold-unverified*, not assumed to fold.
|
|
45
|
+
|
|
46
|
+
See `docs/oracles.md` (the mesh), `prereg/ws_wv.yaml`, and `pen_stack/atlas/writer_verify.py`.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""PEN-STACK v3.0 - open infrastructure for genome writing."""
|
|
2
|
-
__version__ = "
|
|
2
|
+
__version__ = "4.0.1"
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"""Writer-verification branch (v4.0, WS-WV) — the honest "better pen".
|
|
2
|
+
|
|
3
|
+
We do **not** invent writer enzymes de-novo (pen-assemble produced 0 validatable de-novo writers and could not
|
|
4
|
+
be checked computationally). We **score and critique** proposed/variant writers against measured data:
|
|
5
|
+
|
|
6
|
+
* **WV1 — variant scoring head.** Combine the MEASURED DMS effect (Perry-2025 ISCro4 deep mutational scan,
|
|
7
|
+
via the existing `atlas.variant_propose` model) with structural plausibility (the structure oracle) into a
|
|
8
|
+
*calibrated* activity score + interval + scope flag. On held-out variants it ranks measured-better above
|
|
9
|
+
measured-worse above a baseline, and **recovers the known enhanced variants blind** (N322P / H50K / R278M).
|
|
10
|
+
It asserts **no activity** for a variant lacking measured or in-distribution support.
|
|
11
|
+
* **WV2 — critique, not invention.** A generated candidate writer (from `oracles.protein_design`) is
|
|
12
|
+
*critiqued* — does it fold? plausible active site? deliverable form? reachable target? — returning
|
|
13
|
+
pass/flag + reasons; it is **never** returned as "a working new pen" (`no_claim=True`, `claimable=False`).
|
|
14
|
+
|
|
15
|
+
When the Perry DMS is absent (off the VM) a small **frozen documented panel** keeps WV1 exercisable and the
|
|
16
|
+
blind-recovery criterion deterministic — labelled as a retrospective panel, never presented as a blind
|
|
17
|
+
sequence predictor.
|
|
18
|
+
"""
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import math
|
|
22
|
+
from dataclasses import dataclass
|
|
23
|
+
|
|
24
|
+
# A FROZEN retrospective panel of REAL values from the Perry 2025 ISCro4 deep mutational scan
|
|
25
|
+
# (science.adz0276 Table S3, sheet "L2FC_Relative_Z-Scores", column Z_Score_wrt_WT) — the three top-ranked
|
|
26
|
+
# enhancers, three near-neutral variants, and the three most-deleterious variants, copied verbatim from the
|
|
27
|
+
# measured table. Used only when the full Perry DMS is absent (offline/CI); never fabricated.
|
|
28
|
+
_FROZEN_DMS_Z = {
|
|
29
|
+
"N322P": 0.754, "H50K": 0.742, "R278M": 0.709, # top-3 enhancers (measured Z, ranks 1-3)
|
|
30
|
+
"V21R": -0.000, "S312Q": -0.001, "G286T": -0.001, # near-neutral (|Z| ~ 0)
|
|
31
|
+
"R132E": -5.400, "R137E": -5.115, "R195D": -4.984, # most-deleterious (measured worst by Z)
|
|
32
|
+
}
|
|
33
|
+
KNOWN_ISCRO4_ENHANCERS = ["N322P", "H50K", "R278M"]
|
|
34
|
+
_WORSE_CONTROLS = ["R132E", "R137E", "R195D"] # measured-worst variants (Perry Table S3)
|
|
35
|
+
# the catalytic residues a plausible ISCro4-family candidate must retain (Perry Table S3, sheet
|
|
36
|
+
# "Residue Groups", Catalytic_Residues == "Catalytic"): D11, E60, D102, D105, S241 (1-based) -> 0-based below
|
|
37
|
+
_CORE_RESIDUES = {10: "D", 59: "E", 101: "D", 104: "D", 240: "S"}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _sigmoid(x: float) -> float:
|
|
41
|
+
return 1.0 / (1.0 + math.exp(-x))
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass
|
|
45
|
+
class VariantScore:
|
|
46
|
+
variant: str
|
|
47
|
+
effect: float | None # measured/predicted activity effect (higher = better)
|
|
48
|
+
score: float | None # calibrated activity score in [0,1]
|
|
49
|
+
interval: tuple[float, float] | None
|
|
50
|
+
in_dms: bool # backed by measured DMS
|
|
51
|
+
extrapolating: bool # out of DMS distribution
|
|
52
|
+
claimable: bool # may an activity claim be made? (only with measured/in-dist support)
|
|
53
|
+
note: str
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _dms_lookup():
|
|
57
|
+
"""Return (model_name, {variant: z}) — the real Perry DMS if present, else the frozen panel (labelled)."""
|
|
58
|
+
try:
|
|
59
|
+
from pen_stack.atlas.variant_propose import DMSVariantEffectModel
|
|
60
|
+
m = DMSVariantEffectModel()
|
|
61
|
+
return m.name, m._z
|
|
62
|
+
except Exception: # noqa: BLE001 - Perry tables absent off the VM
|
|
63
|
+
return "frozen_retrospective_panel", dict(_FROZEN_DMS_Z)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def score_variants(variants: list[str], structure_uncertainty: float | None = None) -> list[VariantScore]:
|
|
67
|
+
"""Calibrated activity score per variant. Measured (DMS) variants are claimable with a tight interval;
|
|
68
|
+
unmeasured variants are flagged extrapolating and are NOT claimable (no activity asserted)."""
|
|
69
|
+
model_name, z = _dms_lookup()
|
|
70
|
+
out: list[VariantScore] = []
|
|
71
|
+
# interval half-width: wider when the structure oracle is uncertain/deferred (no structural support)
|
|
72
|
+
su = 0.25 if structure_uncertainty is None else float(structure_uncertainty)
|
|
73
|
+
half = 0.10 + 0.5 * su
|
|
74
|
+
for v in variants:
|
|
75
|
+
if v in z:
|
|
76
|
+
eff = float(z[v])
|
|
77
|
+
score = _sigmoid(eff) # monotone map of the measured Z-score
|
|
78
|
+
lo, hi = max(0.0, score - half), min(1.0, score + half)
|
|
79
|
+
out.append(VariantScore(v, eff, round(score, 3), (round(lo, 3), round(hi, 3)),
|
|
80
|
+
in_dms=True, extrapolating=False, claimable=True,
|
|
81
|
+
note=f"measured DMS effect ({model_name})"))
|
|
82
|
+
else:
|
|
83
|
+
out.append(VariantScore(v, None, None, None, in_dms=False, extrapolating=True, claimable=False,
|
|
84
|
+
note="OUT of DMS distribution — plausibility screen only, NO activity "
|
|
85
|
+
"claim (v4.0 WS-WV)"))
|
|
86
|
+
return out
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def blind_recovery(top_k: int = 5) -> dict:
|
|
90
|
+
"""Deterministic blind-validation over the FROZEN documented panel (the same published enhancers,
|
|
91
|
+
measured-neutral, and measured-worse controls): the known enhancers must rank on top, above the
|
|
92
|
+
measured-worse variants. This is a retrospective catalogue criterion, NOT a blind sequence predictor —
|
|
93
|
+
labelled as such. (The full-Perry-DMS recovery is reported separately by `real_dms_recovery`.)"""
|
|
94
|
+
scores = {v: _sigmoid(zz) for v, zz in _FROZEN_DMS_Z.items()}
|
|
95
|
+
ranked = sorted(scores, key=scores.get, reverse=True)
|
|
96
|
+
top = ranked[:top_k]
|
|
97
|
+
recovered = {e: (e in top) for e in KNOWN_ISCRO4_ENHANCERS}
|
|
98
|
+
enh_min = min(scores[e] for e in KNOWN_ISCRO4_ENHANCERS)
|
|
99
|
+
worse_max = max(scores[w] for w in _WORSE_CONTROLS)
|
|
100
|
+
return {"available": True, "model": "frozen_retrospective_panel", "n": len(_FROZEN_DMS_Z), "top_k": top_k,
|
|
101
|
+
"top": top, "recovered": recovered, "all_enhancers_recovered": all(recovered.values()),
|
|
102
|
+
"enhancers_outrank_worse": bool(enh_min > worse_max),
|
|
103
|
+
"note": "recovers KNOWN enhancers (N322P/H50K/R278M) above measured-worse controls — a "
|
|
104
|
+
"retrospective catalogue criterion, NOT a blind sequence-only predictor."}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def real_dms_recovery(top: int = 20) -> dict:
|
|
108
|
+
"""Recovery against the FULL Perry-2025 ISCro4 DMS via the existing validated harness; deferred (and the
|
|
109
|
+
frozen panel stands in) when the Perry tables are absent off the VM."""
|
|
110
|
+
try:
|
|
111
|
+
from pen_stack.atlas.variant_propose import iscro4_dms_recovery
|
|
112
|
+
rep = iscro4_dms_recovery(top=top)
|
|
113
|
+
if rep.get("available", True) is not False and "recovered" in rep:
|
|
114
|
+
return {"available": True, **rep}
|
|
115
|
+
except Exception: # noqa: BLE001
|
|
116
|
+
pass
|
|
117
|
+
return {"available": False, "note": "Perry 2025 DMS absent (runs on the VM); see blind_recovery (frozen)"}
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def critique_candidate(candidate_seq: str, writer_family: str = "bridge_IS110",
|
|
121
|
+
delivery_vehicle: str | None = None, no_integration: bool = False,
|
|
122
|
+
site_seq: str | None = None) -> dict:
|
|
123
|
+
"""Critique a GENERATED candidate writer (WV2) — folds? plausible active site? deliverable? reachable? —
|
|
124
|
+
returning pass/flag + reasons. NEVER returns 'a working new pen' (no_claim=True, claimable=False)."""
|
|
125
|
+
flags, reasons = [], []
|
|
126
|
+
|
|
127
|
+
# 1. structural plausibility (structure oracle; deferred without a backend -> flagged, not asserted)
|
|
128
|
+
from pen_stack.oracles import structure
|
|
129
|
+
st = structure.consistency(candidate_seq)
|
|
130
|
+
fold_ok = bool(st.available and st.value is not None and float(st.value) >= 0.7)
|
|
131
|
+
if not st.available:
|
|
132
|
+
flags.append("fold_unverified")
|
|
133
|
+
reasons.append("structure oracle deferred (no AF3/Boltz/Chai/Protenix backend or cache) — fold not "
|
|
134
|
+
"verified; candidate cannot be claimed to fold")
|
|
135
|
+
|
|
136
|
+
# 2. active-site plausibility (heuristic: retains conserved core residues)
|
|
137
|
+
active_site_ok = all(0 <= i < len(candidate_seq) and candidate_seq[i] == aa
|
|
138
|
+
for i, aa in _CORE_RESIDUES.items())
|
|
139
|
+
if not active_site_ok:
|
|
140
|
+
flags.append("active_site_implausible")
|
|
141
|
+
reasons.append("candidate does not retain the conserved core residues expected of the writer family")
|
|
142
|
+
|
|
143
|
+
# 3. deliverability + 4. reachability — reuse the rule-grounded verifier where inputs are present
|
|
144
|
+
deliverable = reachable = None
|
|
145
|
+
if delivery_vehicle or site_seq:
|
|
146
|
+
from pen_stack.verify import verify
|
|
147
|
+
v = verify(dict(write_type="insertion", writer_family=writer_family, site_seq=site_seq,
|
|
148
|
+
delivery_vehicle=delivery_vehicle, no_integration=no_integration))
|
|
149
|
+
named = [x["rule_id"] for x in v.violations]
|
|
150
|
+
deliverable = not any(r.startswith("delivery.") for r in named)
|
|
151
|
+
reachable = not any(r.startswith("reachability.") for r in named)
|
|
152
|
+
if not deliverable:
|
|
153
|
+
flags.append("not_deliverable")
|
|
154
|
+
reasons.append("; ".join(x["reason"] for x in v.violations if x["rule_id"].startswith("delivery.")))
|
|
155
|
+
if not reachable:
|
|
156
|
+
flags.append("not_reachable")
|
|
157
|
+
reasons.append("; ".join(x["reason"] for x in v.violations if x["rule_id"].startswith("reachability.")))
|
|
158
|
+
|
|
159
|
+
passed = active_site_ok and fold_ok and (deliverable is not False) and (reachable is not False)
|
|
160
|
+
return {
|
|
161
|
+
"writer_family": writer_family, "fold_ok": fold_ok, "active_site_ok": active_site_ok,
|
|
162
|
+
"deliverable": deliverable, "reachable": reachable, "pass": bool(passed), "flags": flags,
|
|
163
|
+
"reasons": reasons,
|
|
164
|
+
"no_claim": True, "claimable": False, # WV2 NEVER asserts a generated writer works
|
|
165
|
+
"note": "critique only — a generated writer is scored/critiqued against structure + rules, never "
|
|
166
|
+
"returned as a working new pen (v4.0 Principle 1 + the pen-assemble lesson).",
|
|
167
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""The L1 oracle mesh (v4.0, WS-O) — one contract over the biomolecular foundation models.
|
|
2
|
+
|
|
3
|
+
`pen_stack.oracles` wraps AlphaGenome / Evo2 / structure predictors (AF3, Boltz-2, Chai-1, Protenix) /
|
|
4
|
+
protein-design models (ESM3, RFdiffusion, ProteinMPNN) / ViennaRNA / the bridge energetics model under a
|
|
5
|
+
single `OracleResult` contract (value + provenance + native uncertainty + scope card). Heavy backends run
|
|
6
|
+
on-demand (hosted API / local GPU) and are cached + version-pinned; when a backend is absent the adapter
|
|
7
|
+
returns a *deferred* result (available=False) — the core stays runnable offline from cache.
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from pen_stack.oracles.cache import cache_get, cache_key, cache_put, scope_card
|
|
14
|
+
from pen_stack.oracles.schema import OracleResult, Provenance
|
|
15
|
+
|
|
16
|
+
__all__ = ["OracleResult", "Provenance", "build_result", "consensus", "assert_claimable",
|
|
17
|
+
"cache_get", "cache_key", "cache_put", "scope_card"]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def build_result(oracle: str, model: str, *, value: Any = None, inputs: dict | None = None,
|
|
21
|
+
native_uncertainty: float | None = None, available: bool = True, cached: bool = False,
|
|
22
|
+
source: str = "adapter", extrapolating: bool = False, in_scope: bool = True,
|
|
23
|
+
output_kind: str | None = None, note: str | None = None) -> OracleResult:
|
|
24
|
+
"""Assemble an `OracleResult`, filling version / output_kind / scope from the model's scope card.
|
|
25
|
+
|
|
26
|
+
`output_kind` defaults to the scope card's, but may be overridden per call (e.g. an Evo2 *likelihood*
|
|
27
|
+
score is a claim-scope scalar, while an Evo2 *generated sequence* is a candidate)."""
|
|
28
|
+
card = scope_card(model) or {}
|
|
29
|
+
key = cache_key(oracle, model, card.get("version", "0"), inputs or {})
|
|
30
|
+
return OracleResult(
|
|
31
|
+
oracle=oracle, value=value,
|
|
32
|
+
provenance=Provenance(model=model, version=card.get("version", "0"), source=source, cache_key=key),
|
|
33
|
+
native_uncertainty=native_uncertainty,
|
|
34
|
+
scope_card=model, in_scope=in_scope, extrapolating=extrapolating,
|
|
35
|
+
output_kind=output_kind or card.get("output_kind", "claim"),
|
|
36
|
+
available=available, cached=cached, note=note)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def assert_claimable(result: OracleResult) -> OracleResult:
|
|
40
|
+
"""Guard: a generative candidate cannot enter a claim path without writer-verification (Principle 1)."""
|
|
41
|
+
return result.as_claim()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def consensus(results: list[OracleResult], oracle: str = "structure") -> OracleResult:
|
|
45
|
+
"""Cross-oracle self-consistency (v4.0 Principle 3): agreement is a confidence signal, **divergence
|
|
46
|
+
widens the interval**. Combines redundant numeric oracles (e.g. AF3 / Boltz-2 / Chai-1 / Protenix); the
|
|
47
|
+
reported native_uncertainty is increased by the spread across the available oracles."""
|
|
48
|
+
avail = [r for r in results if r.available and isinstance(r.value, (int, float))]
|
|
49
|
+
if not avail:
|
|
50
|
+
return build_result(oracle, "consensus", available=False,
|
|
51
|
+
note="no available numeric oracle to combine")
|
|
52
|
+
vals = [float(r.value) for r in avail]
|
|
53
|
+
mean = sum(vals) / len(vals)
|
|
54
|
+
spread = (max(vals) - min(vals)) if len(vals) > 1 else 0.0
|
|
55
|
+
base_unc = max((r.native_uncertainty or 0.0) for r in avail)
|
|
56
|
+
card = scope_card("boltz-2") or {}
|
|
57
|
+
return OracleResult(
|
|
58
|
+
oracle=oracle, value=round(mean, 4),
|
|
59
|
+
provenance=Provenance(model="consensus", version=card.get("version", "0"), source="adapter",
|
|
60
|
+
extra={"members": [r.provenance.model for r in avail], "spread": round(spread, 4)}),
|
|
61
|
+
# disagreement widens the interval: native uncertainty + half the cross-oracle spread
|
|
62
|
+
native_uncertainty=round(base_unc + 0.5 * spread, 4),
|
|
63
|
+
scope_card="boltz-2", in_scope=all(r.in_scope for r in avail),
|
|
64
|
+
extrapolating=any(r.extrapolating for r in avail), output_kind="claim",
|
|
65
|
+
available=True, note=f"consensus of {len(avail)} oracles; spread {round(spread, 4)} widens the interval")
|