pen-stack 8.0.4__tar.gz → 8.0.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pen_stack-8.0.5/CHANGELOG.md +2549 -0
- pen_stack-8.0.5/CITATION.cff +24 -0
- pen_stack-8.0.5/PKG-INFO +382 -0
- pen_stack-8.0.5/README.md +296 -0
- pen_stack-8.0.5/bench/run.py +173 -0
- pen_stack-8.0.5/benchmarks/chat_grounding/README.md +26 -0
- pen_stack-8.0.5/benchmarks/chat_headtohead/README.md +29 -0
- pen_stack-8.0.5/benchmarks/chat_routing/README.md +35 -0
- pen_stack-8.0.5/benchmarks/chat_safety/README.md +23 -0
- pen_stack-8.0.5/benchmarks/genome_writing_bench/LEADERBOARD.md +67 -0
- pen_stack-8.0.5/benchmarks/genome_writing_bench/README.md +87 -0
- pen_stack-8.0.5/benchmarks/genome_writing_bench/SUBMISSIONS.md +53 -0
- pen_stack-8.0.5/benchmarks/genome_writing_challenge/SUBMISSIONS.md +16 -0
- pen_stack-8.0.5/benchmarks/position_effect/README.md +68 -0
- pen_stack-8.0.5/benchmarks/position_effect_human/README.md +115 -0
- pen_stack-8.0.5/benchmarks/writer_efficiency/README.md +54 -0
- pen_stack-8.0.5/configs/aav_serotype_tropism.yaml +81 -0
- pen_stack-8.0.5/configs/antipeg.yaml +28 -0
- pen_stack-8.0.5/configs/cargo_polish.yaml +45 -0
- pen_stack-8.0.5/configs/cell_types.yaml +56 -0
- pen_stack-8.0.5/configs/datasets.yaml +99 -0
- pen_stack-8.0.5/configs/expression/modifiers.yaml +59 -0
- pen_stack-8.0.5/configs/expression/promoters.yaml +52 -0
- pen_stack-8.0.5/configs/llm.yaml +72 -0
- pen_stack-8.0.5/configs/oracles/execution.yaml +95 -0
- pen_stack-8.0.5/configs/oracles/scope_cards.yaml +250 -0
- pen_stack-8.0.5/configs/seroprevalence.yaml +64 -0
- pen_stack-8.0.5/configs/writer_sequences.fasta +12 -0
- pen_stack-8.0.5/data/curated/cast_systems.yaml +59 -0
- pen_stack-8.0.5/data/curated/integrase_att.yaml +66 -0
- pen_stack-8.0.5/docs/DEPLOY.md +39 -0
- pen_stack-8.0.5/docs/INFRA.md +64 -0
- pen_stack-8.0.5/docs/RELEASING.md +60 -0
- pen_stack-8.0.5/docs/REPRO.md +46 -0
- pen_stack-8.0.5/docs/agent.md +78 -0
- pen_stack-8.0.5/docs/benchmark_circularity.md +64 -0
- pen_stack-8.0.5/docs/biosecurity.md +101 -0
- pen_stack-8.0.5/docs/cards/atlas.md +41 -0
- pen_stack-8.0.5/docs/cards/durability.md +43 -0
- pen_stack-8.0.5/docs/cards/offtarget_data.md +117 -0
- pen_stack-8.0.5/docs/cards/position_effect_data.md +36 -0
- pen_stack-8.0.5/docs/cards/safety.md +39 -0
- pen_stack-8.0.5/docs/cards/writer_efficiency_data.md +48 -0
- pen_stack-8.0.5/docs/closed_loop.md +79 -0
- pen_stack-8.0.5/docs/delivery_recommender.md +54 -0
- pen_stack-8.0.5/docs/environment.md +59 -0
- pen_stack-8.0.5/docs/generative_design.md +63 -0
- pen_stack-8.0.5/docs/immune_profiler.md +70 -0
- pen_stack-8.0.5/docs/index.md +48 -0
- pen_stack-8.0.5/docs/offtarget.md +59 -0
- pen_stack-8.0.5/docs/oracles.md +51 -0
- pen_stack-8.0.5/docs/position_effect.md +57 -0
- pen_stack-8.0.5/docs/quickstart.md +64 -0
- pen_stack-8.0.5/docs/responsible_use.md +96 -0
- pen_stack-8.0.5/docs/scorecard.md +54 -0
- pen_stack-8.0.5/docs/tpe_bench.md +48 -0
- pen_stack-8.0.5/docs/tutorials/which-writer-reaches-locus.md +41 -0
- pen_stack-8.0.5/docs/uncertainty.md +84 -0
- pen_stack-8.0.5/docs/world_model.md +49 -0
- pen_stack-8.0.5/docs/writer_efficiency.md +59 -0
- pen_stack-8.0.5/docs/writespec_bench.md +44 -0
- pen_stack-8.0.5/docs/writespec_profile.md +58 -0
- pen_stack-8.0.5/pen_stack/__init__.py +2 -0
- pen_stack-8.0.5/pen_stack/active/acquire.py +165 -0
- pen_stack-8.0.5/pen_stack/active/brains.py +74 -0
- pen_stack-8.0.5/pen_stack/active/campaign.py +109 -0
- pen_stack-8.0.5/pen_stack/active/design.py +66 -0
- pen_stack-8.0.5/pen_stack/active/validate.py +104 -0
- pen_stack-8.0.5/pen_stack/adapt/__init__.py +14 -0
- pen_stack-8.0.5/pen_stack/adapt/finetune.py +33 -0
- pen_stack-8.0.5/pen_stack/adapt/ingest.py +86 -0
- pen_stack-8.0.5/pen_stack/adapt/pipeline.py +101 -0
- pen_stack-8.0.5/pen_stack/adapt/recalibrate.py +58 -0
- pen_stack-8.0.5/pen_stack/adapt/report.py +130 -0
- pen_stack-8.0.5/pen_stack/agent/cite.py +175 -0
- pen_stack-8.0.5/pen_stack/agent/co_scientist.py +262 -0
- pen_stack-8.0.5/pen_stack/agent/epistemic.py +102 -0
- pen_stack-8.0.5/pen_stack/agent/guardrails.py +67 -0
- pen_stack-8.0.5/pen_stack/agent/mcp_server.py +215 -0
- pen_stack-8.0.5/pen_stack/agent/orchestrator.py +112 -0
- pen_stack-8.0.5/pen_stack/agent/orchestrator_live.py +56 -0
- pen_stack-8.0.5/pen_stack/agent/pen_agent.py +242 -0
- pen_stack-8.0.5/pen_stack/agent/scope.py +60 -0
- pen_stack-8.0.5/pen_stack/agent/tools.py +130 -0
- pen_stack-8.0.5/pen_stack/api/manifest.py +160 -0
- pen_stack-8.0.5/pen_stack/atlas/__init__.py +1 -0
- pen_stack-8.0.5/pen_stack/atlas/build_wtkb.py +80 -0
- pen_stack-8.0.5/pen_stack/atlas/crosslink.py +179 -0
- pen_stack-8.0.5/pen_stack/atlas/expand.py +190 -0
- pen_stack-8.0.5/pen_stack/atlas/guide_design.py +178 -0
- pen_stack-8.0.5/pen_stack/atlas/schema.py +59 -0
- pen_stack-8.0.5/pen_stack/atlas/scorecard.py +134 -0
- pen_stack-8.0.5/pen_stack/atlas/universe.py +75 -0
- pen_stack-8.0.5/pen_stack/atlas/variant_propose.py +155 -0
- pen_stack-8.0.5/pen_stack/atlas/writer_efficiency.py +184 -0
- pen_stack-8.0.5/pen_stack/atlas/writer_predict.py +225 -0
- pen_stack-8.0.5/pen_stack/atlas/writer_recommend.py +165 -0
- pen_stack-8.0.5/pen_stack/atlas/writer_verify.py +167 -0
- pen_stack-8.0.5/pen_stack/bridge/__init__.py +1 -0
- pen_stack-8.0.5/pen_stack/bridge/activity.py +52 -0
- pen_stack-8.0.5/pen_stack/bridge/cli.py +65 -0
- pen_stack-8.0.5/pen_stack/bridge/fold_qc.py +53 -0
- pen_stack-8.0.5/pen_stack/bridge/guide_qc.py +87 -0
- pen_stack-8.0.5/pen_stack/bridge/ingest.py +139 -0
- pen_stack-8.0.5/pen_stack/bridge/offtarget.py +191 -0
- pen_stack-8.0.5/pen_stack/bridge/offtarget_energetics.py +105 -0
- pen_stack-8.0.5/pen_stack/bridge/ortholog_screen.py +73 -0
- pen_stack-8.0.5/pen_stack/bridge/pipeline.py +83 -0
- pen_stack-8.0.5/pen_stack/build/cloudlab.py +74 -0
- pen_stack-8.0.5/pen_stack/build/ingest.py +47 -0
- pen_stack-8.0.5/pen_stack/build/protocol.py +82 -0
- pen_stack-8.0.5/pen_stack/build/simlab.py +30 -0
- pen_stack-8.0.5/pen_stack/cli.py +126 -0
- pen_stack-8.0.5/pen_stack/data/encode.py +84 -0
- pen_stack-8.0.5/pen_stack/data/genome.py +71 -0
- pen_stack-8.0.5/pen_stack/data/ingest_chromatin.py +119 -0
- pen_stack-8.0.5/pen_stack/data/ingest_integration.py +112 -0
- pen_stack-8.0.5/pen_stack/data/ingest_safety_annot.py +201 -0
- pen_stack-8.0.5/pen_stack/data/ingest_trip.py +76 -0
- pen_stack-8.0.5/pen_stack/design/capsid_generate.py +62 -0
- pen_stack-8.0.5/pen_stack/design/generate.py +70 -0
- pen_stack-8.0.5/pen_stack/design/pareto.py +70 -0
- pen_stack-8.0.5/pen_stack/design/space.py +137 -0
- pen_stack-8.0.5/pen_stack/design/writer_variants.py +121 -0
- pen_stack-8.0.5/pen_stack/env/__init__.py +1 -0
- pen_stack-8.0.5/pen_stack/env/genome_writing_env.py +248 -0
- pen_stack-8.0.5/pen_stack/env/policies.py +94 -0
- pen_stack-8.0.5/pen_stack/graph/__init__.py +21 -0
- pen_stack-8.0.5/pen_stack/graph/build.py +133 -0
- pen_stack-8.0.5/pen_stack/graph/cell_types.py +58 -0
- pen_stack-8.0.5/pen_stack/graph/ingest.py +132 -0
- pen_stack-8.0.5/pen_stack/graph/query.py +148 -0
- pen_stack-8.0.5/pen_stack/graph/schema.py +100 -0
- pen_stack-8.0.5/pen_stack/loop/continual.py +61 -0
- pen_stack-8.0.5/pen_stack/loop/cycle.py +84 -0
- pen_stack-8.0.5/pen_stack/loop/drift.py +41 -0
- pen_stack-8.0.5/pen_stack/mech/classify_atlas.py +71 -0
- pen_stack-8.0.5/pen_stack/mech/whitelist.py +66 -0
- pen_stack-8.0.5/pen_stack/monitor/europepmc.py +32 -0
- pen_stack-8.0.5/pen_stack/monitor/run.py +57 -0
- pen_stack-8.0.5/pen_stack/monitor/triage.py +63 -0
- pen_stack-8.0.5/pen_stack/oracles/__init__.py +65 -0
- pen_stack-8.0.5/pen_stack/oracles/affinity.py +116 -0
- pen_stack-8.0.5/pen_stack/oracles/cache.py +53 -0
- pen_stack-8.0.5/pen_stack/oracles/energetics.py +33 -0
- pen_stack-8.0.5/pen_stack/oracles/genome.py +167 -0
- pen_stack-8.0.5/pen_stack/oracles/protein_design.py +136 -0
- pen_stack-8.0.5/pen_stack/oracles/reliability.py +64 -0
- pen_stack-8.0.5/pen_stack/oracles/rna.py +28 -0
- pen_stack-8.0.5/pen_stack/oracles/schema.py +77 -0
- pen_stack-8.0.5/pen_stack/oracles/structure.py +42 -0
- pen_stack-8.0.5/pen_stack/oracles/structure_run.py +76 -0
- pen_stack-8.0.5/pen_stack/oracles/vcell.py +74 -0
- pen_stack-8.0.5/pen_stack/planner/__init__.py +1 -0
- pen_stack-8.0.5/pen_stack/planner/ada_risk.py +64 -0
- pen_stack-8.0.5/pen_stack/planner/antipeg_oracle.py +75 -0
- pen_stack-8.0.5/pen_stack/planner/capsid_epitope_oracle.py +135 -0
- pen_stack-8.0.5/pen_stack/planner/cargo.py +56 -0
- pen_stack-8.0.5/pen_stack/planner/cargo_polish.py +146 -0
- pen_stack-8.0.5/pen_stack/planner/chromosome.py +106 -0
- pen_stack-8.0.5/pen_stack/planner/delivery.py +55 -0
- pen_stack-8.0.5/pen_stack/planner/delivery_constraints.py +110 -0
- pen_stack-8.0.5/pen_stack/planner/delivery_immune.py +61 -0
- pen_stack-8.0.5/pen_stack/planner/delivery_immunology.py +208 -0
- pen_stack-8.0.5/pen_stack/planner/delivery_predict.py +196 -0
- pen_stack-8.0.5/pen_stack/planner/delivery_vehicles.py +37 -0
- pen_stack-8.0.5/pen_stack/planner/genotoxicity_oracle.py +112 -0
- pen_stack-8.0.5/pen_stack/planner/immune_mhc2.py +154 -0
- pen_stack-8.0.5/pen_stack/planner/immune_profile.py +292 -0
- pen_stack-8.0.5/pen_stack/planner/innate_sensing.py +135 -0
- pen_stack-8.0.5/pen_stack/planner/multiplex.py +110 -0
- pen_stack-8.0.5/pen_stack/planner/optimize.py +278 -0
- pen_stack-8.0.5/pen_stack/planner/pipeline.py +87 -0
- pen_stack-8.0.5/pen_stack/planner/report.py +26 -0
- pen_stack-8.0.5/pen_stack/planner/router.py +57 -0
- pen_stack-8.0.5/pen_stack/planner/seroprevalence_oracle.py +92 -0
- pen_stack-8.0.5/pen_stack/planner/target_site.py +118 -0
- pen_stack-8.0.5/pen_stack/rag/corpus.py +133 -0
- pen_stack-8.0.5/pen_stack/rag/embed.py +98 -0
- pen_stack-8.0.5/pen_stack/rag/ground.py +131 -0
- pen_stack-8.0.5/pen_stack/rag/index.py +53 -0
- pen_stack-8.0.5/pen_stack/rag/llm.py +215 -0
- pen_stack-8.0.5/pen_stack/rag/qa.py +105 -0
- pen_stack-8.0.5/pen_stack/rag/retrieve.py +48 -0
- pen_stack-8.0.5/pen_stack/rules/__init__.py +9 -0
- pen_stack-8.0.5/pen_stack/rules/evaluators.py +318 -0
- pen_stack-8.0.5/pen_stack/rules/loader.py +31 -0
- pen_stack-8.0.5/pen_stack/rules/schema.py +99 -0
- pen_stack-8.0.5/pen_stack/rules/solver.py +43 -0
- pen_stack-8.0.5/pen_stack/rules/spec.py +78 -0
- pen_stack-8.0.5/pen_stack/safety/__init__.py +21 -0
- pen_stack-8.0.5/pen_stack/safety/audit.py +90 -0
- pen_stack-8.0.5/pen_stack/safety/gate.py +58 -0
- pen_stack-8.0.5/pen_stack/safety/pfam_scan.py +157 -0
- pen_stack-8.0.5/pen_stack/safety/policy.py +69 -0
- pen_stack-8.0.5/pen_stack/safety/redteam.py +71 -0
- pen_stack-8.0.5/pen_stack/safety/registry.py +255 -0
- pen_stack-8.0.5/pen_stack/safety/screen.py +59 -0
- pen_stack-8.0.5/pen_stack/safety/standards.py +141 -0
- pen_stack-8.0.5/pen_stack/score/recalibrate.py +77 -0
- pen_stack-8.0.5/pen_stack/score/therapeutic.py +85 -0
- pen_stack-8.0.5/pen_stack/server/api.py +647 -0
- pen_stack-8.0.5/pen_stack/spec/__init__.py +18 -0
- pen_stack-8.0.5/pen_stack/spec/clarify.py +42 -0
- pen_stack-8.0.5/pen_stack/spec/extract.py +254 -0
- pen_stack-8.0.5/pen_stack/spec/resolvers/__init__.py +17 -0
- pen_stack-8.0.5/pen_stack/spec/resolvers/cell.py +51 -0
- pen_stack-8.0.5/pen_stack/spec/resolvers/chem.py +32 -0
- pen_stack-8.0.5/pen_stack/spec/resolvers/feature.py +36 -0
- pen_stack-8.0.5/pen_stack/spec/resolvers/gene.py +43 -0
- pen_stack-8.0.5/pen_stack/spec/resolvers/locus.py +29 -0
- pen_stack-8.0.5/pen_stack/spec/resolvers/phenotype.py +37 -0
- pen_stack-8.0.5/pen_stack/spec/satisfy.py +114 -0
- pen_stack-8.0.5/pen_stack/spec/service.py +33 -0
- pen_stack-8.0.5/pen_stack/spec/writespec.py +244 -0
- pen_stack-8.0.5/pen_stack/twin/__init__.py +14 -0
- pen_stack-8.0.5/pen_stack/twin/calibrate.py +61 -0
- pen_stack-8.0.5/pen_stack/twin/data/__init__.py +12 -0
- pen_stack-8.0.5/pen_stack/twin/data/position_effect.py +245 -0
- pen_stack-8.0.5/pen_stack/twin/mechanistic.py +136 -0
- pen_stack-8.0.5/pen_stack/twin/outcome.py +132 -0
- pen_stack-8.0.5/pen_stack/twin/position_effect.py +454 -0
- pen_stack-8.0.5/pen_stack/ui/app.py +713 -0
- pen_stack-8.0.5/pen_stack/validate/adapt_demo.py +69 -0
- pen_stack-8.0.5/pen_stack/validate/agent_eval.py +117 -0
- pen_stack-8.0.5/pen_stack/validate/bench_adversarial_tasks.py +118 -0
- pen_stack-8.0.5/pen_stack/validate/bench_coscientist_tasks.py +60 -0
- pen_stack-8.0.5/pen_stack/validate/bench_graph_tasks.py +64 -0
- pen_stack-8.0.5/pen_stack/validate/bench_rule_tasks.py +84 -0
- pen_stack-8.0.5/pen_stack/validate/bench_trust_tasks.py +92 -0
- pen_stack-8.0.5/pen_stack/validate/bench_writetype_tasks.py +101 -0
- pen_stack-8.0.5/pen_stack/validate/blind_gsh_discovery.py +261 -0
- pen_stack-8.0.5/pen_stack/validate/cargo_directionality.py +57 -0
- pen_stack-8.0.5/pen_stack/validate/closed_loop.py +63 -0
- pen_stack-8.0.5/pen_stack/validate/durability_baselines.py +185 -0
- pen_stack-8.0.5/pen_stack/validate/experiment_design.py +65 -0
- pen_stack-8.0.5/pen_stack/validate/expr_controls.py +39 -0
- pen_stack-8.0.5/pen_stack/validate/forward_hypotheses.py +104 -0
- pen_stack-8.0.5/pen_stack/validate/generative_design.py +62 -0
- pen_stack-8.0.5/pen_stack/validate/guide_qc_demo.py +69 -0
- pen_stack-8.0.5/pen_stack/validate/heldout_celltype_expr.py +32 -0
- pen_stack-8.0.5/pen_stack/validate/immune_calibration.py +133 -0
- pen_stack-8.0.5/pen_stack/validate/intent_specification.py +82 -0
- pen_stack-8.0.5/pen_stack/validate/known_biology_expr.py +38 -0
- pen_stack-8.0.5/pen_stack/validate/offtarget_energetics_eval.py +144 -0
- pen_stack-8.0.5/pen_stack/validate/out_of_scope_refusal.py +82 -0
- pen_stack-8.0.5/pen_stack/validate/outcome_calibration.py +194 -0
- pen_stack-8.0.5/pen_stack/validate/outcome_prediction.py +76 -0
- pen_stack-8.0.5/pen_stack/validate/paper3_benchmark.py +165 -0
- pen_stack-8.0.5/pen_stack/validate/paper4_real_validation.py +144 -0
- pen_stack-8.0.5/pen_stack/validate/paper4_validation.py +82 -0
- pen_stack-8.0.5/pen_stack/validate/protocol_safety.py +62 -0
- pen_stack-8.0.5/pen_stack/validate/safety_screening.py +72 -0
- pen_stack-8.0.5/pen_stack/validate/selective_prediction.py +104 -0
- pen_stack-8.0.5/pen_stack/validate/seq_vs_measured.py +134 -0
- pen_stack-8.0.5/pen_stack/validate/target_site_controls.py +65 -0
- pen_stack-8.0.5/pen_stack/validate/uncertainty_eval.py +244 -0
- pen_stack-8.0.5/pen_stack/validate/ungrounded_baseline.py +234 -0
- pen_stack-8.0.5/pen_stack/validate/within_locus_ranking.py +84 -0
- pen_stack-8.0.5/pen_stack/validate/writer_recovery.py +91 -0
- pen_stack-8.0.5/pen_stack/verify/__init__.py +5 -0
- pen_stack-8.0.5/pen_stack/verify/proof.py +206 -0
- pen_stack-8.0.5/pen_stack/verify/schema.py +53 -0
- pen_stack-8.0.5/pen_stack/verify/service.py +191 -0
- pen_stack-8.0.5/pen_stack/web/llm.py +393 -0
- pen_stack-8.0.5/pen_stack/web/llm_provider.py +119 -0
- pen_stack-8.0.5/pen_stack/web/server.py +96 -0
- pen_stack-8.0.5/pen_stack/web/tools.py +197 -0
- pen_stack-8.0.5/pen_stack/wgenome/chromatin_seq.py +83 -0
- pen_stack-8.0.5/pen_stack/wgenome/durability.py +108 -0
- pen_stack-8.0.5/pen_stack/wgenome/export_tracks.py +52 -0
- pen_stack-8.0.5/pen_stack/wgenome/features.py +82 -0
- pen_stack-8.0.5/pen_stack/wgenome/genotoxic_blocklist.py +88 -0
- pen_stack-8.0.5/pen_stack/wgenome/gsh_baseline.py +154 -0
- pen_stack-8.0.5/pen_stack/wgenome/mesh_features.py +61 -0
- pen_stack-8.0.5/pen_stack/wgenome/offtarget_assay.py +80 -0
- pen_stack-8.0.5/pen_stack/wgenome/offtarget_bridge.py +47 -0
- pen_stack-8.0.5/pen_stack/wgenome/offtarget_cast.py +97 -0
- pen_stack-8.0.5/pen_stack/wgenome/offtarget_data.py +148 -0
- pen_stack-8.0.5/pen_stack/wgenome/offtarget_enumerate.py +271 -0
- pen_stack-8.0.5/pen_stack/wgenome/offtarget_integrase.py +155 -0
- pen_stack-8.0.5/pen_stack/wgenome/offtarget_nuclease.py +98 -0
- pen_stack-8.0.5/pen_stack/wgenome/offtarget_paste.py +41 -0
- pen_stack-8.0.5/pen_stack/wgenome/offtarget_predict.py +264 -0
- pen_stack-8.0.5/pen_stack/wgenome/ood.py +135 -0
- pen_stack-8.0.5/pen_stack/wgenome/providers.py +278 -0
- pen_stack-8.0.5/pen_stack/wgenome/safety.py +69 -0
- pen_stack-8.0.5/pen_stack/wgenome/structure3d.py +212 -0
- pen_stack-8.0.5/pen_stack/wgenome/uncertainty.py +250 -0
- pen_stack-8.0.5/pen_stack/wgenome/writability.py +72 -0
- pen_stack-8.0.5/pen_stack.egg-info/PKG-INFO +382 -0
- pen_stack-8.0.5/pyproject.toml +121 -0
- pen_stack-8.0.5/scripts/build_capsid_fitness.py +98 -0
- pen_stack-8.0.5/scripts/build_rag_corpus.py +39 -0
- pen_stack-8.0.5/scripts/fetch_licensed_sources.py +57 -0
- pen_stack-8.0.5/scripts/offtarget_chromatin_matched.py +135 -0
- pen_stack-8.0.5/scripts/offtarget_chromatin_validation.py +115 -0
- pen_stack-8.0.5/scripts/p1_build_atlas.py +87 -0
- pen_stack-8.0.5/scripts/p1_build_durability.py +61 -0
- pen_stack-8.0.5/scripts/p1_build_position_effect.py +103 -0
- pen_stack-8.0.5/scripts/p1_build_writer_eff.py +66 -0
- pen_stack-8.0.5/scripts/p1_export_tracks.py +22 -0
- pen_stack-8.0.5/scripts/p1_safety_concordance.py +82 -0
- pen_stack-8.0.5/scripts/p1_train_safety.py +48 -0
- pen_stack-8.0.5/scripts/p1_validation_report.py +80 -0
- pen_stack-8.0.5/scripts/p2_build_atlas.py +36 -0
- pen_stack-8.0.5/scripts/p3_benchmark_report.py +82 -0
- pen_stack-8.0.5/scripts/p4_genome_scan.py +43 -0
- pen_stack-8.0.5/scripts/p52_build_genotox_oracle.py +115 -0
- pen_stack-8.0.5/scripts/p53_build_epitope_oracle.py +120 -0
- pen_stack-8.0.5/scripts/reproduce.py +115 -0
- pen_stack-8.0.5/scripts/validate_components.py +158 -0
- pen_stack-8.0.5/scripts/ws_b_report.py +104 -0
- pen_stack-8.0.5/scripts/ws_c_report.py +75 -0
- pen_stack-8.0.4/CHANGELOG.md +0 -2542
- pen_stack-8.0.4/CITATION.cff +0 -24
- pen_stack-8.0.4/PKG-INFO +0 -382
- pen_stack-8.0.4/README.md +0 -296
- pen_stack-8.0.4/bench/run.py +0 -173
- pen_stack-8.0.4/benchmarks/chat_grounding/README.md +0 -26
- pen_stack-8.0.4/benchmarks/chat_headtohead/README.md +0 -29
- pen_stack-8.0.4/benchmarks/chat_routing/README.md +0 -35
- pen_stack-8.0.4/benchmarks/chat_safety/README.md +0 -23
- pen_stack-8.0.4/benchmarks/genome_writing_bench/LEADERBOARD.md +0 -67
- pen_stack-8.0.4/benchmarks/genome_writing_bench/README.md +0 -87
- pen_stack-8.0.4/benchmarks/genome_writing_bench/SUBMISSIONS.md +0 -53
- pen_stack-8.0.4/benchmarks/genome_writing_challenge/SUBMISSIONS.md +0 -16
- pen_stack-8.0.4/benchmarks/position_effect/README.md +0 -68
- pen_stack-8.0.4/benchmarks/position_effect_human/README.md +0 -115
- pen_stack-8.0.4/benchmarks/writer_efficiency/README.md +0 -54
- pen_stack-8.0.4/configs/aav_serotype_tropism.yaml +0 -81
- pen_stack-8.0.4/configs/antipeg.yaml +0 -28
- pen_stack-8.0.4/configs/cargo_polish.yaml +0 -45
- pen_stack-8.0.4/configs/cell_types.yaml +0 -56
- pen_stack-8.0.4/configs/datasets.yaml +0 -99
- pen_stack-8.0.4/configs/expression/modifiers.yaml +0 -59
- pen_stack-8.0.4/configs/expression/promoters.yaml +0 -52
- pen_stack-8.0.4/configs/llm.yaml +0 -72
- pen_stack-8.0.4/configs/oracles/execution.yaml +0 -95
- pen_stack-8.0.4/configs/oracles/scope_cards.yaml +0 -250
- pen_stack-8.0.4/configs/seroprevalence.yaml +0 -64
- pen_stack-8.0.4/configs/writer_sequences.fasta +0 -12
- pen_stack-8.0.4/data/curated/cast_systems.yaml +0 -59
- pen_stack-8.0.4/data/curated/integrase_att.yaml +0 -66
- pen_stack-8.0.4/docs/DEPLOY.md +0 -39
- pen_stack-8.0.4/docs/INFRA.md +0 -64
- pen_stack-8.0.4/docs/RELEASING.md +0 -60
- pen_stack-8.0.4/docs/REPRO.md +0 -46
- pen_stack-8.0.4/docs/agent.md +0 -78
- pen_stack-8.0.4/docs/benchmark_circularity.md +0 -64
- pen_stack-8.0.4/docs/biosecurity.md +0 -102
- pen_stack-8.0.4/docs/cards/atlas.md +0 -41
- pen_stack-8.0.4/docs/cards/durability.md +0 -43
- pen_stack-8.0.4/docs/cards/offtarget_data.md +0 -117
- pen_stack-8.0.4/docs/cards/position_effect_data.md +0 -36
- pen_stack-8.0.4/docs/cards/safety.md +0 -39
- pen_stack-8.0.4/docs/cards/writer_efficiency_data.md +0 -48
- pen_stack-8.0.4/docs/closed_loop.md +0 -79
- pen_stack-8.0.4/docs/delivery_recommender.md +0 -54
- pen_stack-8.0.4/docs/environment.md +0 -59
- pen_stack-8.0.4/docs/generative_design.md +0 -63
- pen_stack-8.0.4/docs/immune_profiler.md +0 -70
- pen_stack-8.0.4/docs/index.md +0 -48
- pen_stack-8.0.4/docs/offtarget.md +0 -59
- pen_stack-8.0.4/docs/oracles.md +0 -51
- pen_stack-8.0.4/docs/position_effect.md +0 -57
- pen_stack-8.0.4/docs/quickstart.md +0 -64
- pen_stack-8.0.4/docs/responsible_use.md +0 -96
- pen_stack-8.0.4/docs/scorecard.md +0 -54
- pen_stack-8.0.4/docs/tpe_bench.md +0 -48
- pen_stack-8.0.4/docs/tutorials/which-writer-reaches-locus.md +0 -41
- pen_stack-8.0.4/docs/uncertainty.md +0 -84
- pen_stack-8.0.4/docs/world_model.md +0 -49
- pen_stack-8.0.4/docs/writer_efficiency.md +0 -59
- pen_stack-8.0.4/docs/writespec_bench.md +0 -44
- pen_stack-8.0.4/docs/writespec_profile.md +0 -58
- pen_stack-8.0.4/pen_stack/__init__.py +0 -2
- pen_stack-8.0.4/pen_stack/active/acquire.py +0 -165
- pen_stack-8.0.4/pen_stack/active/brains.py +0 -74
- pen_stack-8.0.4/pen_stack/active/campaign.py +0 -109
- pen_stack-8.0.4/pen_stack/active/design.py +0 -66
- pen_stack-8.0.4/pen_stack/active/validate.py +0 -104
- pen_stack-8.0.4/pen_stack/adapt/__init__.py +0 -14
- pen_stack-8.0.4/pen_stack/adapt/finetune.py +0 -33
- pen_stack-8.0.4/pen_stack/adapt/ingest.py +0 -86
- pen_stack-8.0.4/pen_stack/adapt/pipeline.py +0 -101
- pen_stack-8.0.4/pen_stack/adapt/recalibrate.py +0 -58
- pen_stack-8.0.4/pen_stack/adapt/report.py +0 -130
- pen_stack-8.0.4/pen_stack/agent/cite.py +0 -175
- pen_stack-8.0.4/pen_stack/agent/co_scientist.py +0 -262
- pen_stack-8.0.4/pen_stack/agent/epistemic.py +0 -102
- pen_stack-8.0.4/pen_stack/agent/guardrails.py +0 -67
- pen_stack-8.0.4/pen_stack/agent/mcp_server.py +0 -215
- pen_stack-8.0.4/pen_stack/agent/orchestrator.py +0 -112
- pen_stack-8.0.4/pen_stack/agent/orchestrator_live.py +0 -56
- pen_stack-8.0.4/pen_stack/agent/pen_agent.py +0 -242
- pen_stack-8.0.4/pen_stack/agent/scope.py +0 -60
- pen_stack-8.0.4/pen_stack/agent/tools.py +0 -130
- pen_stack-8.0.4/pen_stack/api/manifest.py +0 -161
- pen_stack-8.0.4/pen_stack/atlas/__init__.py +0 -1
- pen_stack-8.0.4/pen_stack/atlas/build_wtkb.py +0 -80
- pen_stack-8.0.4/pen_stack/atlas/crosslink.py +0 -179
- pen_stack-8.0.4/pen_stack/atlas/expand.py +0 -190
- pen_stack-8.0.4/pen_stack/atlas/guide_design.py +0 -178
- pen_stack-8.0.4/pen_stack/atlas/schema.py +0 -59
- pen_stack-8.0.4/pen_stack/atlas/scorecard.py +0 -134
- pen_stack-8.0.4/pen_stack/atlas/universe.py +0 -75
- pen_stack-8.0.4/pen_stack/atlas/variant_propose.py +0 -155
- pen_stack-8.0.4/pen_stack/atlas/writer_efficiency.py +0 -184
- pen_stack-8.0.4/pen_stack/atlas/writer_predict.py +0 -225
- pen_stack-8.0.4/pen_stack/atlas/writer_recommend.py +0 -165
- pen_stack-8.0.4/pen_stack/atlas/writer_verify.py +0 -167
- pen_stack-8.0.4/pen_stack/bridge/__init__.py +0 -1
- pen_stack-8.0.4/pen_stack/bridge/activity.py +0 -52
- pen_stack-8.0.4/pen_stack/bridge/cli.py +0 -65
- pen_stack-8.0.4/pen_stack/bridge/fold_qc.py +0 -53
- pen_stack-8.0.4/pen_stack/bridge/guide_qc.py +0 -87
- pen_stack-8.0.4/pen_stack/bridge/ingest.py +0 -139
- pen_stack-8.0.4/pen_stack/bridge/offtarget.py +0 -191
- pen_stack-8.0.4/pen_stack/bridge/offtarget_energetics.py +0 -105
- pen_stack-8.0.4/pen_stack/bridge/ortholog_screen.py +0 -73
- pen_stack-8.0.4/pen_stack/bridge/pipeline.py +0 -83
- pen_stack-8.0.4/pen_stack/build/cloudlab.py +0 -74
- pen_stack-8.0.4/pen_stack/build/ingest.py +0 -47
- pen_stack-8.0.4/pen_stack/build/protocol.py +0 -82
- pen_stack-8.0.4/pen_stack/build/simlab.py +0 -30
- pen_stack-8.0.4/pen_stack/cli.py +0 -126
- pen_stack-8.0.4/pen_stack/data/encode.py +0 -84
- pen_stack-8.0.4/pen_stack/data/genome.py +0 -71
- pen_stack-8.0.4/pen_stack/data/ingest_chromatin.py +0 -119
- pen_stack-8.0.4/pen_stack/data/ingest_integration.py +0 -112
- pen_stack-8.0.4/pen_stack/data/ingest_safety_annot.py +0 -201
- pen_stack-8.0.4/pen_stack/data/ingest_trip.py +0 -76
- pen_stack-8.0.4/pen_stack/design/capsid_generate.py +0 -62
- pen_stack-8.0.4/pen_stack/design/generate.py +0 -70
- pen_stack-8.0.4/pen_stack/design/pareto.py +0 -70
- pen_stack-8.0.4/pen_stack/design/space.py +0 -137
- pen_stack-8.0.4/pen_stack/design/writer_variants.py +0 -122
- pen_stack-8.0.4/pen_stack/env/__init__.py +0 -1
- pen_stack-8.0.4/pen_stack/env/genome_writing_env.py +0 -248
- pen_stack-8.0.4/pen_stack/env/policies.py +0 -94
- pen_stack-8.0.4/pen_stack/graph/__init__.py +0 -21
- pen_stack-8.0.4/pen_stack/graph/build.py +0 -133
- pen_stack-8.0.4/pen_stack/graph/cell_types.py +0 -58
- pen_stack-8.0.4/pen_stack/graph/ingest.py +0 -132
- pen_stack-8.0.4/pen_stack/graph/query.py +0 -148
- pen_stack-8.0.4/pen_stack/graph/schema.py +0 -100
- pen_stack-8.0.4/pen_stack/loop/continual.py +0 -61
- pen_stack-8.0.4/pen_stack/loop/cycle.py +0 -84
- pen_stack-8.0.4/pen_stack/loop/drift.py +0 -41
- pen_stack-8.0.4/pen_stack/mech/classify_atlas.py +0 -71
- pen_stack-8.0.4/pen_stack/mech/whitelist.py +0 -66
- pen_stack-8.0.4/pen_stack/monitor/europepmc.py +0 -32
- pen_stack-8.0.4/pen_stack/monitor/run.py +0 -57
- pen_stack-8.0.4/pen_stack/monitor/triage.py +0 -63
- pen_stack-8.0.4/pen_stack/oracles/__init__.py +0 -65
- pen_stack-8.0.4/pen_stack/oracles/affinity.py +0 -116
- pen_stack-8.0.4/pen_stack/oracles/cache.py +0 -53
- pen_stack-8.0.4/pen_stack/oracles/energetics.py +0 -33
- pen_stack-8.0.4/pen_stack/oracles/genome.py +0 -167
- pen_stack-8.0.4/pen_stack/oracles/protein_design.py +0 -136
- pen_stack-8.0.4/pen_stack/oracles/reliability.py +0 -64
- pen_stack-8.0.4/pen_stack/oracles/rna.py +0 -28
- pen_stack-8.0.4/pen_stack/oracles/schema.py +0 -77
- pen_stack-8.0.4/pen_stack/oracles/structure.py +0 -42
- pen_stack-8.0.4/pen_stack/oracles/structure_run.py +0 -76
- pen_stack-8.0.4/pen_stack/oracles/vcell.py +0 -74
- pen_stack-8.0.4/pen_stack/planner/__init__.py +0 -1
- pen_stack-8.0.4/pen_stack/planner/ada_risk.py +0 -64
- pen_stack-8.0.4/pen_stack/planner/antipeg_oracle.py +0 -75
- pen_stack-8.0.4/pen_stack/planner/capsid_epitope_oracle.py +0 -136
- pen_stack-8.0.4/pen_stack/planner/cargo.py +0 -56
- pen_stack-8.0.4/pen_stack/planner/cargo_polish.py +0 -146
- pen_stack-8.0.4/pen_stack/planner/chromosome.py +0 -106
- pen_stack-8.0.4/pen_stack/planner/delivery.py +0 -55
- pen_stack-8.0.4/pen_stack/planner/delivery_constraints.py +0 -110
- pen_stack-8.0.4/pen_stack/planner/delivery_immune.py +0 -61
- pen_stack-8.0.4/pen_stack/planner/delivery_immunology.py +0 -208
- pen_stack-8.0.4/pen_stack/planner/delivery_predict.py +0 -196
- pen_stack-8.0.4/pen_stack/planner/delivery_vehicles.py +0 -37
- pen_stack-8.0.4/pen_stack/planner/genotoxicity_oracle.py +0 -112
- pen_stack-8.0.4/pen_stack/planner/immune_mhc2.py +0 -154
- pen_stack-8.0.4/pen_stack/planner/immune_profile.py +0 -292
- pen_stack-8.0.4/pen_stack/planner/innate_sensing.py +0 -135
- pen_stack-8.0.4/pen_stack/planner/multiplex.py +0 -110
- pen_stack-8.0.4/pen_stack/planner/optimize.py +0 -278
- pen_stack-8.0.4/pen_stack/planner/pipeline.py +0 -87
- pen_stack-8.0.4/pen_stack/planner/report.py +0 -26
- pen_stack-8.0.4/pen_stack/planner/router.py +0 -57
- pen_stack-8.0.4/pen_stack/planner/seroprevalence_oracle.py +0 -92
- pen_stack-8.0.4/pen_stack/planner/target_site.py +0 -118
- pen_stack-8.0.4/pen_stack/rag/corpus.py +0 -133
- pen_stack-8.0.4/pen_stack/rag/embed.py +0 -98
- pen_stack-8.0.4/pen_stack/rag/ground.py +0 -131
- pen_stack-8.0.4/pen_stack/rag/index.py +0 -53
- pen_stack-8.0.4/pen_stack/rag/llm.py +0 -215
- pen_stack-8.0.4/pen_stack/rag/qa.py +0 -105
- pen_stack-8.0.4/pen_stack/rag/retrieve.py +0 -48
- pen_stack-8.0.4/pen_stack/rules/__init__.py +0 -9
- pen_stack-8.0.4/pen_stack/rules/evaluators.py +0 -318
- pen_stack-8.0.4/pen_stack/rules/loader.py +0 -31
- pen_stack-8.0.4/pen_stack/rules/schema.py +0 -99
- pen_stack-8.0.4/pen_stack/rules/solver.py +0 -43
- pen_stack-8.0.4/pen_stack/rules/spec.py +0 -78
- pen_stack-8.0.4/pen_stack/safety/__init__.py +0 -21
- pen_stack-8.0.4/pen_stack/safety/audit.py +0 -90
- pen_stack-8.0.4/pen_stack/safety/gate.py +0 -58
- pen_stack-8.0.4/pen_stack/safety/pfam_scan.py +0 -157
- pen_stack-8.0.4/pen_stack/safety/policy.py +0 -69
- pen_stack-8.0.4/pen_stack/safety/redteam.py +0 -71
- pen_stack-8.0.4/pen_stack/safety/registry.py +0 -255
- pen_stack-8.0.4/pen_stack/safety/screen.py +0 -59
- pen_stack-8.0.4/pen_stack/safety/standards.py +0 -141
- pen_stack-8.0.4/pen_stack/score/recalibrate.py +0 -77
- pen_stack-8.0.4/pen_stack/score/therapeutic.py +0 -85
- pen_stack-8.0.4/pen_stack/server/api.py +0 -647
- pen_stack-8.0.4/pen_stack/spec/__init__.py +0 -18
- pen_stack-8.0.4/pen_stack/spec/clarify.py +0 -42
- pen_stack-8.0.4/pen_stack/spec/extract.py +0 -254
- pen_stack-8.0.4/pen_stack/spec/resolvers/__init__.py +0 -17
- pen_stack-8.0.4/pen_stack/spec/resolvers/cell.py +0 -51
- pen_stack-8.0.4/pen_stack/spec/resolvers/chem.py +0 -32
- pen_stack-8.0.4/pen_stack/spec/resolvers/feature.py +0 -36
- pen_stack-8.0.4/pen_stack/spec/resolvers/gene.py +0 -43
- pen_stack-8.0.4/pen_stack/spec/resolvers/locus.py +0 -29
- pen_stack-8.0.4/pen_stack/spec/resolvers/phenotype.py +0 -37
- pen_stack-8.0.4/pen_stack/spec/satisfy.py +0 -114
- pen_stack-8.0.4/pen_stack/spec/service.py +0 -33
- pen_stack-8.0.4/pen_stack/spec/writespec.py +0 -244
- pen_stack-8.0.4/pen_stack/twin/__init__.py +0 -14
- pen_stack-8.0.4/pen_stack/twin/calibrate.py +0 -61
- pen_stack-8.0.4/pen_stack/twin/data/__init__.py +0 -12
- pen_stack-8.0.4/pen_stack/twin/data/position_effect.py +0 -245
- pen_stack-8.0.4/pen_stack/twin/mechanistic.py +0 -136
- pen_stack-8.0.4/pen_stack/twin/outcome.py +0 -132
- pen_stack-8.0.4/pen_stack/twin/position_effect.py +0 -454
- pen_stack-8.0.4/pen_stack/ui/app.py +0 -713
- pen_stack-8.0.4/pen_stack/validate/adapt_demo.py +0 -69
- pen_stack-8.0.4/pen_stack/validate/agent_eval.py +0 -117
- pen_stack-8.0.4/pen_stack/validate/bench_adversarial_tasks.py +0 -118
- pen_stack-8.0.4/pen_stack/validate/bench_coscientist_tasks.py +0 -60
- pen_stack-8.0.4/pen_stack/validate/bench_graph_tasks.py +0 -64
- pen_stack-8.0.4/pen_stack/validate/bench_rule_tasks.py +0 -84
- pen_stack-8.0.4/pen_stack/validate/bench_trust_tasks.py +0 -92
- pen_stack-8.0.4/pen_stack/validate/bench_writetype_tasks.py +0 -101
- pen_stack-8.0.4/pen_stack/validate/blind_gsh_discovery.py +0 -261
- pen_stack-8.0.4/pen_stack/validate/cargo_directionality.py +0 -57
- pen_stack-8.0.4/pen_stack/validate/closed_loop.py +0 -63
- pen_stack-8.0.4/pen_stack/validate/durability_baselines.py +0 -185
- pen_stack-8.0.4/pen_stack/validate/experiment_design.py +0 -65
- pen_stack-8.0.4/pen_stack/validate/expr_controls.py +0 -39
- pen_stack-8.0.4/pen_stack/validate/forward_hypotheses.py +0 -104
- pen_stack-8.0.4/pen_stack/validate/generative_design.py +0 -62
- pen_stack-8.0.4/pen_stack/validate/guide_qc_demo.py +0 -69
- pen_stack-8.0.4/pen_stack/validate/heldout_celltype_expr.py +0 -32
- pen_stack-8.0.4/pen_stack/validate/immune_calibration.py +0 -133
- pen_stack-8.0.4/pen_stack/validate/intent_specification.py +0 -82
- pen_stack-8.0.4/pen_stack/validate/known_biology_expr.py +0 -38
- pen_stack-8.0.4/pen_stack/validate/offtarget_energetics_eval.py +0 -144
- pen_stack-8.0.4/pen_stack/validate/out_of_scope_refusal.py +0 -82
- pen_stack-8.0.4/pen_stack/validate/outcome_calibration.py +0 -194
- pen_stack-8.0.4/pen_stack/validate/outcome_prediction.py +0 -76
- pen_stack-8.0.4/pen_stack/validate/paper3_benchmark.py +0 -165
- pen_stack-8.0.4/pen_stack/validate/paper4_real_validation.py +0 -144
- pen_stack-8.0.4/pen_stack/validate/paper4_validation.py +0 -82
- pen_stack-8.0.4/pen_stack/validate/protocol_safety.py +0 -62
- pen_stack-8.0.4/pen_stack/validate/safety_screening.py +0 -72
- pen_stack-8.0.4/pen_stack/validate/selective_prediction.py +0 -104
- pen_stack-8.0.4/pen_stack/validate/seq_vs_measured.py +0 -134
- pen_stack-8.0.4/pen_stack/validate/target_site_controls.py +0 -65
- pen_stack-8.0.4/pen_stack/validate/uncertainty_eval.py +0 -244
- pen_stack-8.0.4/pen_stack/validate/ungrounded_baseline.py +0 -234
- pen_stack-8.0.4/pen_stack/validate/within_locus_ranking.py +0 -84
- pen_stack-8.0.4/pen_stack/validate/writer_recovery.py +0 -91
- pen_stack-8.0.4/pen_stack/verify/__init__.py +0 -5
- pen_stack-8.0.4/pen_stack/verify/proof.py +0 -206
- pen_stack-8.0.4/pen_stack/verify/schema.py +0 -53
- pen_stack-8.0.4/pen_stack/verify/service.py +0 -191
- pen_stack-8.0.4/pen_stack/web/llm.py +0 -393
- pen_stack-8.0.4/pen_stack/web/llm_provider.py +0 -119
- pen_stack-8.0.4/pen_stack/web/server.py +0 -96
- pen_stack-8.0.4/pen_stack/web/tools.py +0 -197
- pen_stack-8.0.4/pen_stack/wgenome/chromatin_seq.py +0 -83
- pen_stack-8.0.4/pen_stack/wgenome/durability.py +0 -108
- pen_stack-8.0.4/pen_stack/wgenome/export_tracks.py +0 -52
- pen_stack-8.0.4/pen_stack/wgenome/features.py +0 -82
- pen_stack-8.0.4/pen_stack/wgenome/genotoxic_blocklist.py +0 -88
- pen_stack-8.0.4/pen_stack/wgenome/gsh_baseline.py +0 -154
- pen_stack-8.0.4/pen_stack/wgenome/mesh_features.py +0 -61
- pen_stack-8.0.4/pen_stack/wgenome/offtarget_assay.py +0 -80
- pen_stack-8.0.4/pen_stack/wgenome/offtarget_bridge.py +0 -47
- pen_stack-8.0.4/pen_stack/wgenome/offtarget_cast.py +0 -97
- pen_stack-8.0.4/pen_stack/wgenome/offtarget_data.py +0 -148
- pen_stack-8.0.4/pen_stack/wgenome/offtarget_enumerate.py +0 -271
- pen_stack-8.0.4/pen_stack/wgenome/offtarget_integrase.py +0 -155
- pen_stack-8.0.4/pen_stack/wgenome/offtarget_nuclease.py +0 -98
- pen_stack-8.0.4/pen_stack/wgenome/offtarget_paste.py +0 -41
- pen_stack-8.0.4/pen_stack/wgenome/offtarget_predict.py +0 -264
- pen_stack-8.0.4/pen_stack/wgenome/ood.py +0 -135
- pen_stack-8.0.4/pen_stack/wgenome/providers.py +0 -278
- pen_stack-8.0.4/pen_stack/wgenome/safety.py +0 -69
- pen_stack-8.0.4/pen_stack/wgenome/structure3d.py +0 -212
- pen_stack-8.0.4/pen_stack/wgenome/uncertainty.py +0 -250
- pen_stack-8.0.4/pen_stack/wgenome/writability.py +0 -72
- pen_stack-8.0.4/pen_stack.egg-info/PKG-INFO +0 -382
- pen_stack-8.0.4/pyproject.toml +0 -121
- pen_stack-8.0.4/scripts/build_capsid_fitness.py +0 -98
- pen_stack-8.0.4/scripts/build_rag_corpus.py +0 -39
- pen_stack-8.0.4/scripts/fetch_licensed_sources.py +0 -57
- pen_stack-8.0.4/scripts/offtarget_chromatin_matched.py +0 -135
- pen_stack-8.0.4/scripts/offtarget_chromatin_validation.py +0 -115
- pen_stack-8.0.4/scripts/p1_build_atlas.py +0 -87
- pen_stack-8.0.4/scripts/p1_build_durability.py +0 -61
- pen_stack-8.0.4/scripts/p1_build_position_effect.py +0 -103
- pen_stack-8.0.4/scripts/p1_build_writer_eff.py +0 -66
- pen_stack-8.0.4/scripts/p1_export_tracks.py +0 -22
- pen_stack-8.0.4/scripts/p1_safety_concordance.py +0 -82
- pen_stack-8.0.4/scripts/p1_train_safety.py +0 -48
- pen_stack-8.0.4/scripts/p1_validation_report.py +0 -80
- pen_stack-8.0.4/scripts/p2_build_atlas.py +0 -36
- pen_stack-8.0.4/scripts/p3_benchmark_report.py +0 -82
- pen_stack-8.0.4/scripts/p4_genome_scan.py +0 -43
- pen_stack-8.0.4/scripts/p52_build_genotox_oracle.py +0 -115
- pen_stack-8.0.4/scripts/p53_build_epitope_oracle.py +0 -120
- pen_stack-8.0.4/scripts/reproduce.py +0 -115
- pen_stack-8.0.4/scripts/validate_components.py +0 -158
- pen_stack-8.0.4/scripts/ws_b_report.py +0 -104
- pen_stack-8.0.4/scripts/ws_c_report.py +0 -75
- {pen_stack-8.0.4 → pen_stack-8.0.5}/LICENSE +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/MANIFEST.in +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/agentic_baseline/README.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/chat_grounding/SHA256SUMS +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/chat_routing/SHA256SUMS +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/chat_safety/SHA256SUMS +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/delivery/SHA256SUMS +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/genome_writing_bench/SHA256SUMS +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/genome_writing_bench/tasks.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/genome_writing_challenge/README.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/genotox_panel/README.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/grounding_llm_on/README.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/loop/SHA256SUMS +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/offtarget/SHA256SUMS +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/offtarget/integrase/README.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/offtarget/integrase/SHA256SUMS +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/offtarget/integrase_chalberg/README.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/oracle/SHA256SUMS +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/position_effect/SHA256SUMS +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/position_effect_human/SHA256SUMS +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/priorart/epridict/README.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/priorart/epridict/SHA256SUMS +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/priorart/gsh_recovery/README.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/priorart/gsh_recovery/SHA256SUMS +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/verify/SHA256SUMS +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/writer_efficiency/SHA256SUMS +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/benchmarks/writespec/SHA256SUMS +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/atlas_families.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/bridge_offtarget_profile.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/calibration/preexisting_nab_independent.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/capsid_epitope_oracle.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/capsid_sequences.fasta +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/delivery_constraints.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/delivery_rules.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/delivery_vehicles.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/gates_v3.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/genotoxicity_oracle.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/gsh_validated_heldout.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/intent_weights.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/known_unknowns.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/metric_guide.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/mhc_epitope_oracle.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/monitor_queries.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/oracles/reliability.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/rules/compliance.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/rules/delivery.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/rules/fold.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/rules/multiplex.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/rules/payload.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/rules/reachability.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/safety/genotoxic_loci.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/safety/hazard_registry.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/safety/policy.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/safety/probes.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/score_axes.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/target_sites.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/universe_crosswalk.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/write_types.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/configs/wtkb_curated.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/data/curated/bridge_offtarget_energetics.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/data/curated/bridge_offtarget_profile_measured.parquet +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/data/curated/gene_coords.parquet +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/data/curated/unified_editor_universe.parquet +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/data/offtarget/enumerated_cache.parquet +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/data/offtarget/motif_cache.parquet +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/BACKLOG.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/MCP.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/STABILITY.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/alphagenome_feasibility.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/autonomy.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/build_interface.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/cards/priorart.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/challenge.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/co_scientist.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/co_scientist_loop.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/delivery.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/delivery_immunology.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/digital_twin.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/dissemination.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/experiment_design.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/integrations.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/live_oracles.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/mechanistic_constraints.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/oracle_mesh.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/positioning.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/private_data_formats.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/rule_spec.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/rules.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/scope.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/tutorials/compare-families.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/tutorials/score-deliverability.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/tutorials/where-can-i-write.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/verify.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/verify_service.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/writer_verification.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/docs/wtkb.md +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/_resources.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/active/__init__.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/agent/__init__.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/api/__init__.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/atlas/atlas.parquet +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/atlas/scorecard_v3.parquet +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/atlas/universe_v3.parquet +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/atlas/wtkb.parquet +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/build/__init__.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/data/__init__.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/design/__init__.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/loop/__init__.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/mech/__init__.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/mech/pfam_whitelist.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/monitor/__init__.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/oracles/status.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/rag/__init__.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/score/__init__.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/server/__init__.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/ui/__init__.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/validate/__init__.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/web/__init__.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/web/guide.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/web/router.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack/wgenome/__init__.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack.egg-info/SOURCES.txt +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack.egg-info/dependency_links.txt +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack.egg-info/entry_points.txt +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack.egg-info/requires.txt +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/pen_stack.egg-info/top_level.txt +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_phase0.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_phase1_5.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_phase2.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_phase3.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_a.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_acq.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_aldesign.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_alvalidate.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_atlas.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_b.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_ba.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_ba_v33.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_ba_v45.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_bench.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_c.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_cal.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_calib.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_challenge.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_chat.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_cite.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_closedloop.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_continual.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_cosci2.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_crit.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_ct.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_d.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_delivery.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_drift.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_e.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_env.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_ep.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_epitope.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_expr2.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_f.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_frontend.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_g.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_gen.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_genotox.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_graph.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_h.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_hybrid.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_immune.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_immune2.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_ingest.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_innate.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_loop.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_manifest.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_mc.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_mcp.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_mech.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_mon.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_o.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_offtarget.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_offtarget2.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_openapi.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_oracle.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_orch.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_outcome.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_pareto.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_peg.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_penchat.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_plan.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_policy.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_priorart.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_profile.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_proto.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_r.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_redteam.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_route.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_screen.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_seroprev.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_simlab.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_twincal.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_uq.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_v.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_vcell.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_verify.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_writer.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_writespec.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/SHA256_LOCK_ws_wv.json +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/paper1.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/paper2.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/paper3.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/paper4.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/phase0.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_a.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_acq.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_aldesign.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_alvalidate.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_atlas.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_b.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_ba.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_ba_v33.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_ba_v45.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_bench.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_c.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_cal.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_calib.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_challenge.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_chat.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_cite.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_closedloop.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_continual.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_cosci2.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_crit.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_ct.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_d.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_delivery.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_drift.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_e.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_env.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_ep.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_epitope.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_expr2.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_f.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_frontend.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_g.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_gen.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_genotox.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_graph.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_h.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_hybrid.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_immune.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_immune2.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_ingest.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_innate.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_loop.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_manifest.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_mc.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_mcp.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_mech.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_mon.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_o.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_offtarget.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_offtarget2.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_openapi.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_oracle.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_orch.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_outcome.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_pareto.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_peg.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_penchat.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_plan.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_policy.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_priorart.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_profile.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_proto.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_r.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_redteam.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_route.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_screen.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_seroprev.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_simlab.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_twincal.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_uq.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_v.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_vcell.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_verify.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_writer.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_writespec.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/prereg/ws_wv.yaml +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/scripts/calibrate_immune_axes.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/scripts/fetch_artifacts.sh +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/scripts/offtarget_chromatin_incremental.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/scripts/p2_build_human_head.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/scripts/pa_epridict_distinctness.py +0 -0
- {pen_stack-8.0.4 → pen_stack-8.0.5}/setup.cfg +0 -0
|
@@ -0,0 +1,2549 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to PEN-STACK are documented here. This file follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/).
|
|
5
|
+
|
|
6
|
+
## [8.0.5] - 2026-07-16
|
|
7
|
+
|
|
8
|
+
A documentation and readability release. No public function signatures change and no scientific results change.
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- Docstrings and comments across the package describe each component in plain terms. Internal development
|
|
12
|
+
labels and per-component version stamps were removed from the shipped source, the test suite, the served
|
|
13
|
+
API, CLI, and interface text, and the documentation, and the test modules were renamed to describe what
|
|
14
|
+
they cover. The pre-registration records and the sealed benchmark specifications are unchanged, so every
|
|
15
|
+
integrity checksum still verifies.
|
|
16
|
+
|
|
17
|
+
## [8.0.4] - 2026-07-16
|
|
18
|
+
|
|
19
|
+
A packaging fix. No public function signature changes.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
- **The wheel now ships the data files the package reads at runtime.** `pen_stack/mech/pfam_whitelist.yaml`
|
|
23
|
+
and the `pen_stack/atlas/*.parquet` tables live inside the package and are loaded on first use, but the
|
|
24
|
+
build declared no package data, so `pip install pen-stack` produced a wheel without them and
|
|
25
|
+
`PfamWhitelist()` raised `FileNotFoundError`. A `[tool.setuptools.package-data]` entry now includes them.
|
|
26
|
+
An editable install resolves to the source tree, which masked the gap.
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
- Documentation and docstrings describe each component in plain terms. Internal work-stream labels,
|
|
30
|
+
per-component version stamps, status-legend glyphs, and pointers to local-only working files were removed
|
|
31
|
+
from the published prose, the benchmark READMEs, and the doc cards.
|
|
32
|
+
|
|
33
|
+
## [8.0.3] - 2026-07-15
|
|
34
|
+
|
|
35
|
+
A safety patch from the results audit. No public function signature changes.
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
- **The genotoxicity safety filter no longer has false negatives on documented clinical loci.** The learned
|
|
39
|
+
`safety` score scored documented clinical insertional-oncogenesis loci as safe (BMI1 at the 99.9th
|
|
40
|
+
writability percentile, plus SETBP1 and MN1) because its label covered only six genes. A deterministic
|
|
41
|
+
**reject-known-bad blocklist** (`configs/safety/genotoxic_loci.yaml`, `pen_stack/wgenome/genotoxic_blocklist.py`,
|
|
42
|
+
applied in the atlas) now flags any locus within the window of one of the eight documented clinical loci as
|
|
43
|
+
unsafe by rule, overriding the soft score. The list is sourced independently from the trial literature (the
|
|
44
|
+
2025 *Leukemia* vector-genotoxicity review and the primary trial reports), not from the benchmark. It is a
|
|
45
|
+
reject-known-bad blocklist, not a novel-locus genotoxicity predictor.
|
|
46
|
+
- **The chance-level silencing prediction is flagged.** `p_silenced` (AUROC 0.50 on the human K562 head) now
|
|
47
|
+
carries a `silencing_classifier_not_validated` scope flag so a chance-level number is never presented as a
|
|
48
|
+
validated result; the expression head is what ships.
|
|
49
|
+
|
|
50
|
+
## [8.0.2] - 2026-07-13
|
|
51
|
+
|
|
52
|
+
A documentation-correctness and reproducibility-enforcement patch. No scientific result and no public
|
|
53
|
+
function signature changes.
|
|
54
|
+
|
|
55
|
+
### Fixed
|
|
56
|
+
- **Corrected the MCP tool count.** The MCP server exposes twenty-two tools; the README, CHANGELOG, and
|
|
57
|
+
manuscript are corrected from "twenty," and a guard test now fails if the registered count ever diverges
|
|
58
|
+
from the documented one.
|
|
59
|
+
- **Synced the Docker image version** to the package version, enforced by the release version-consistency
|
|
60
|
+
test so the image label cannot drift again.
|
|
61
|
+
|
|
62
|
+
### Changed
|
|
63
|
+
- **CI enforces reproducibility on every commit.** `make repro` now runs in CI on each Python version, so the
|
|
64
|
+
two headline recomputations, the frozen-input integrity check, and the no-fabrication gate are verified
|
|
65
|
+
rather than assumed.
|
|
66
|
+
|
|
67
|
+
## [8.0.1] - 2026-07-13
|
|
68
|
+
|
|
69
|
+
A reproducibility and API-hardening patch. No scientific result and no public function signature changes.
|
|
70
|
+
|
|
71
|
+
### Changed
|
|
72
|
+
- **Result, verdict, and safety types are now immutable (frozen).** `OracleResult` and its nested
|
|
73
|
+
`Provenance`, `Verdict`, `SafetyVerdict`, `ScreenHit`, `Rule`, and `RuleResult` can no longer be mutated
|
|
74
|
+
after construction, so a result's provenance and scope, a verdict's legality, or a screen hit's severity
|
|
75
|
+
cannot be edited downstream. Build a changed copy with `model_copy(update=...)`.
|
|
76
|
+
- **The REST, MCP, and Gymnasium-environment tests and the SBOL3/GenBank round-trip run by default.**
|
|
77
|
+
`fastapi`, `uvicorn`, `httpx`, `fastmcp`, `gymnasium`, `sbol3`, and `biopython` are in the `[dev]` extra, so
|
|
78
|
+
the full suite exercises these features rather than skipping them. Heavy compiled extras stay opt-in.
|
|
79
|
+
- **The one-command reproduction recomputes a second headline from committed source.**
|
|
80
|
+
`scripts/pa_epridict_distinctness.py` (wired into `make repro`) re-derives the durability-vs-ePRIDICT
|
|
81
|
+
distinctness result, and `scripts/reproduce.py` now distinguishes recomputed headlines from echoed sealed
|
|
82
|
+
metrics.
|
|
83
|
+
|
|
84
|
+
### Fixed
|
|
85
|
+
- **An abstention is no longer reported as high confidence.** A design verified with no calibrated confidence
|
|
86
|
+
is now `not-computable`, not `grounded-confident`.
|
|
87
|
+
- **The frozen-input integrity check works on a fresh checkout.** `python bench/run.py --verify` parses the
|
|
88
|
+
standard `sha256sum` manifest format (two-space, CRLF-tolerant); the manifest re-seals only on explicit
|
|
89
|
+
`--seal`; a `.gitattributes` pins the hashed inputs to LF for cross-platform stability.
|
|
90
|
+
- **The reproduction harness can fail.** `scripts/reproduce.py` exits non-zero if any block fails instead of
|
|
91
|
+
always reporting success.
|
|
92
|
+
- Corrected the ePRIDICT variance figure in the README (R-squared 0.041, matching the committed metrics).
|
|
93
|
+
|
|
94
|
+
## [8.0.0] - 2026-07-13 - Stable release of record
|
|
95
|
+
|
|
96
|
+
The first stable, citable release. The major version marks a committed public API surface (the SDK
|
|
97
|
+
functions, the REST endpoints, and the twenty-two MCP tools) governed by a one-minor-version deprecation policy.
|
|
98
|
+
It consolidates the gated 7.x development trail rather than replacing it: the pre-registrations, SHA-locked
|
|
99
|
+
benchmarks, and disclosed negatives that trail documents remain intact and referenced. Stable surfaces
|
|
100
|
+
carry calibrated uncertainty and validation status; the mechanism-based paths (serine-integrase, bridge, and
|
|
101
|
+
CAST off-target) are marked experimental and may change.
|
|
102
|
+
|
|
103
|
+
### Added
|
|
104
|
+
- **A one-chromosome demo atlas** (`data/demo/atlas_k562.parquet`, chr19). A fresh clone can run the
|
|
105
|
+
safe-harbour quickstart without first fetching the full release: `PEN_ATLAS_DIR=data/demo pen-stack
|
|
106
|
+
writable --gene AAVS1 --ct k562` returns the ranked writable bins of the AAVS1 (PPP1R12C) locus. Opt-in via
|
|
107
|
+
`PEN_ATLAS_DIR`, so the atlas-gated test suite is unchanged. Full genome-wide atlases come from Zenodo via
|
|
108
|
+
`scripts/fetch_artifacts.sh`.
|
|
109
|
+
- **An Anthropic (Claude) provider in the LLM layer.** `pen_stack/rag/llm.py` now supports three provider
|
|
110
|
+
styles (OpenAI-compatible, Ollama, Anthropic Messages), including multi-turn tool calling, so the
|
|
111
|
+
conversational agent and the evaluations run provider-agnostically across hosted-frontier and local models.
|
|
112
|
+
Keys are read from an env var or a gitignored file and are never committed.
|
|
113
|
+
- **A measured, LLM-on grounding evaluation** (`benchmarks/grounding_llm_on/`). The ungrounded-baseline
|
|
114
|
+
contrast ships a committed metrics file and an adversarial probe set, run with the model live across three
|
|
115
|
+
model families: with no tools an ungrounded model emits concrete tool-only quantities (fabrication), while
|
|
116
|
+
the grounded agent, which routes every quantity through a validated tool, emits none. Transcripts are cached
|
|
117
|
+
and replay offline in CI.
|
|
118
|
+
- **An agentic baseline** (`benchmarks/agentic_baseline/`). A real external LLM agent drives the validated
|
|
119
|
+
tools and every number in its trace is audited to a direct tool call. Verified across three models spanning
|
|
120
|
+
a small local model to hosted-frontier models; the no-fabrication audit passes for all.
|
|
121
|
+
- **A one-command reproduction path.** `make repro` reproduces every result that runs on the committed data
|
|
122
|
+
and the demo atlas on a fresh clone, with no download and no API key (`scripts/reproduce.py`); `make fetch`
|
|
123
|
+
then `make repro-full` add the genome-wide atlas benchmarks from the Zenodo release. Verified end to end in
|
|
124
|
+
a clean `python:3.12-slim` container.
|
|
125
|
+
- **Committed metrics for the three headline analyses** (`benchmarks/position_effect_human/`,
|
|
126
|
+
`offtarget/integrase_chalberg/`, `genotox_panel/`), so the paper's central numbers reproduce directly from
|
|
127
|
+
the repository.
|
|
128
|
+
|
|
129
|
+
### Changed
|
|
130
|
+
- Benchmark provenance references relative paths only. The license (MIT), MCP tool count (twenty-two), and
|
|
131
|
+
Verify-Bench rule count (eleven) are reconciled across the package metadata, the repository, and the
|
|
132
|
+
manuscript. The repository was confirmed free of hardcoded credentials, addresses, and absolute local paths.
|
|
133
|
+
|
|
134
|
+
## [7.3.21] - 2026-07-11 - World-model graph: resolve any locus (not just exact GSH names)
|
|
135
|
+
|
|
136
|
+
### Fixed
|
|
137
|
+
- **The world-model graph query resolved only the exact curated safe-harbour node names.** The graph materialises
|
|
138
|
+
a `locus:` node for each curated GSH locus and matched the query string exactly, so `PPP1R12C` (AAVS1's anchor
|
|
139
|
+
gene), `ROSA26` (whose node is `hRosa26`), and real genes such as TRAC, HBB, and LMO2 all returned nothing. The
|
|
140
|
+
query now resolves in three tiers:
|
|
141
|
+
- A curated node is matched by **GSH name, anchor gene, or alias, case-insensitively** (AAVS1 ≡ aavs1 ≡
|
|
142
|
+
PPP1R12C; ROSA26 ≡ hRosa26; HIPP11 ≡ H11), returning the same DOI-provenanced answer.
|
|
143
|
+
- A query that is not a curated safe harbour but resolves to a **real gene** returns the **tier-1 reprogrammable
|
|
144
|
+
writers**, which engage any locus at the locus level (the documented crosslink property), flagged as a
|
|
145
|
+
candidate rather than a curated safe harbour (per-site reachability and safety remain the Planner's and
|
|
146
|
+
Guardian's responsibility).
|
|
147
|
+
- Anything else returns an explained empty result rather than an error.
|
|
148
|
+
The response carries `resolved_locus` and `is_curated_safe_harbour`, and the Closed Loop page shows the resolved
|
|
149
|
+
locus and a curated-vs-candidate badge.
|
|
150
|
+
|
|
151
|
+
## [7.3.20] - 2026-07-11 - Closed loop: a UI surface + /cloudlab 500-on-bad-provider fix
|
|
152
|
+
|
|
153
|
+
### Fixed
|
|
154
|
+
- **`POST /api/cloudlab` returned an unhandled 500 for any `provider` other than "mock".** `submit()` raises
|
|
155
|
+
`CloudLabError` for a provider outside the wired set, but `submit_gated()` caught only the safety refusal
|
|
156
|
+
(`ProtocolExportError`), so it propagated. The endpoint now returns a **422** with the valid-provider list for an
|
|
157
|
+
unknown provider, and a null/empty/missing provider falls back to the wired `mock` dry-run path.
|
|
158
|
+
|
|
159
|
+
### Added
|
|
160
|
+
- **A "Closed Loop" page.** Three closed-loop capabilities previously reachable only via the API are now
|
|
161
|
+
surfaced (the fourth, the validation campaign, is already on Experiments):
|
|
162
|
+
- **Build & submit (cloud-lab)**: a design form plus provider select drives the verify-first flow: a cleared
|
|
163
|
+
design returns a DRAFT protocol preview and a mock/dry-run job receipt (Level 3, human-in-control); a hazardous
|
|
164
|
+
cargo (e.g. ricin) is refused with no protocol emitted.
|
|
165
|
+
- **SDL-brain benchmark**: the EIG/VOI designer versus random/greedy (curve-area gap with CI), BayBE/Atlas
|
|
166
|
+
cited, with a "BayBE not installed in this deployment" note when the optional dependency is absent.
|
|
167
|
+
- **World-model graph**: a locus/cargo-form query returns the provenanced writer→locus→vehicle paths.
|
|
168
|
+
Wired into the left-rail nav (Build & learn) and the router at `/closed-loop`.
|
|
169
|
+
|
|
170
|
+
## [7.3.19] - 2026-07-11 - Experiment designer: expected information gain varies with cell-type coverage
|
|
171
|
+
|
|
172
|
+
### Changed
|
|
173
|
+
- **`expected_info_gain` now varies across candidates** instead of reducing to the twin's fixed ±0.20 uncertainty
|
|
174
|
+
band (which read a near-constant ~0.0202 for every candidate). EIG folds in the design-varying uncertainty the
|
|
175
|
+
fixed band understates: an unmeasured cell type (no atlas data, so more reducible uncertainty) and an
|
|
176
|
+
out-of-distribution design widen the effective standard deviation. EIG is ~0.02 in a fully-measured cell
|
|
177
|
+
(K562/HepG2), ~0.43 partially-measured (HSPC), ~0.71 unmeasured (iPSC/PBMC/…), and ~1.5 out-of-distribution; it
|
|
178
|
+
is constant across gene/vehicle/cargo within one cell type, since the mechanistic twin carries no per-gene
|
|
179
|
+
uncertainty. Coverage and OOD are folded into EIG rather than double-counted as separate acquisition terms.
|
|
180
|
+
|
|
181
|
+
## [7.3.18] - 2026-07-11 - Experiment designer: acquisition rebuilt on design-varying signals
|
|
182
|
+
|
|
183
|
+
### Changed
|
|
184
|
+
- **The experiment-suggestion acquisition is rebuilt on design-varying signals.** Expected information gain derives
|
|
185
|
+
entirely from the twin's fixed ±0.20 uncertainty band, so the suggested batch scored a near-constant ~0.02 for
|
|
186
|
+
almost every candidate, and the pool varied only vehicle × cargo at one cell type, where relative expression is
|
|
187
|
+
per-copy (cargo-independent). The acquisition now combines:
|
|
188
|
+
- **Coverage novelty**: an experiment in an unmeasured cell type reduces more uncertainty; the measured-atlas
|
|
189
|
+
roster (K562/HepG2 full, HSPC partial, others none) drives it.
|
|
190
|
+
- **Feasibility gate**: an experiment that cannot be built as specified (cargo overflowing the vehicle) is
|
|
191
|
+
down-weighted.
|
|
192
|
+
- **Immune value-of-information**, counting only **in-scope** proxy axes, so it varies by vehicle (a PEGylated
|
|
193
|
+
LNP puts the anti-PEG axis in scope; AAV does not).
|
|
194
|
+
- **Marginal gain**: the submodular greedy objective (informativeness minus overlap with the picks already
|
|
195
|
+
scheduled), distinct per experiment and decreasing down the batch.
|
|
196
|
+
The candidate pool spans all cell types × 4 vehicles so the coverage/feasibility/immune signals differ across it;
|
|
197
|
+
the batch is scored per candidate cell, and each experiment is returned with its full breakdown. The Experiments
|
|
198
|
+
page shows the marginal-gain ranking with a "why" line (coverage, immune-VOI, buildability) and states that the
|
|
199
|
+
mechanistic twin cannot finely rank two experiments in the same regime, the ranking is coverage + buildability +
|
|
200
|
+
immune-VOI + diversity. `select_batch` scores each candidate once.
|
|
201
|
+
- The "Load expression-validation campaign" plan is a fixed pre-registered 48-row campaign, independent of the
|
|
202
|
+
candidate-pool form; the scores panel notes this.
|
|
203
|
+
|
|
204
|
+
## [7.3.17] - 2026-07-10 - App-wide input-validation sweep (out-of-domain values are flagged everywhere)
|
|
205
|
+
|
|
206
|
+
### Added
|
|
207
|
+
- **A consistent input-validation pass across every page.** Shared helpers in `lib/format.js`
|
|
208
|
+
(`invalidNucleotides`, `clampInt`) and a reusable `SeqWarning` component in `ui.jsx`:
|
|
209
|
+
- **Nucleotide sequence fields** warn on characters outside A/C/G/T/U/N (kept, not silently accepted):
|
|
210
|
+
Design Studio / Twin / Guardian cargo sequence, Off-Target guide / crRNA spacer / bridge target-core, Writer
|
|
211
|
+
Atlas guide-design target and donor.
|
|
212
|
+
- **Writer Atlas "Cargo bp"** now shows the same "clamped to X (allowed 1–300,000)" note Site Finder uses,
|
|
213
|
+
instead of clamping silently.
|
|
214
|
+
- **Design Studio multiplex edits**: the free-text chromosome flags an invalid value (chr1–chr22, chrX/Y/M)
|
|
215
|
+
and the genomic position clamps to a non-negative coordinate (was `parseInt || 0`, accepting negatives).
|
|
216
|
+
- Twin chromatin marks (0–1) and cargo-size vehicle cap + non-positive (from 7.3.16) complete the set.
|
|
217
|
+
|
|
218
|
+
### Fixed
|
|
219
|
+
- **Twin chromatin-mark fields no longer mangle a typed negative** (`"-5"` had become `"05"`). The value was
|
|
220
|
+
coerced with `parseFloat || 0` on every keystroke, collapsing a lone leading `-` to `0`. The fields now hold
|
|
221
|
+
the raw string while editing (coerced to a number only at predict time) and drop the native `min`/`max`, so an
|
|
222
|
+
out-of-range value, including a negative, can be entered and is flagged rather than silently blocked.
|
|
223
|
+
Free-text NL fields (co-scientist chat, WriteSpec brief), amino-acid / SMILES fields (capsid, oracles), and the
|
|
224
|
+
free-form model-feature fields are intentionally left unconstrained, since client-side validation would false-warn.
|
|
225
|
+
|
|
226
|
+
## [7.3.16] - 2026-07-10 - Vehicle-aware cargo hint, OOD-widen scope, input range warnings
|
|
227
|
+
|
|
228
|
+
### Fixed
|
|
229
|
+
- **The "Cargo size (bp)" hint reflects the selected delivery vehicle.** It was hardcoded to "AAV single-vector
|
|
230
|
+
payload caps near ~4.7 kb" for every vehicle; it now reflects the selected vehicle's real capacity (AAV dual
|
|
231
|
+
~9 kb, lentivirus ~8 kb, LNP ~15 kb, HDAd ~35 kb, HSV ~100 kb, electroporation = no packaging limit), sourced
|
|
232
|
+
from a `VEHICLE_CAP_BP` map mirroring `configs/delivery_vehicles.yaml`, with an inline over-capacity warning when
|
|
233
|
+
the entered cargo exceeds the cap.
|
|
234
|
+
- **The position-effect model's "OOD widen" factor and its presentation.** The factor reads near its ×3 ceiling for most realistic
|
|
235
|
+
chromatin input. It is genuinely computed (near-zero input ≈ ×1, mid-range ≈ ×2.4–×2.8, cap ×3), but the
|
|
236
|
+
position-effect head was trained on normalized exact-site features, so typical 0–1 histone values at the app's
|
|
237
|
+
coarse 1 kb resolution sit outside that distribution and the widen flags them as out-of-distribution (near the
|
|
238
|
+
cap). The stat caption, the not-outcome-validated banner, and the scores panel now explain that a high widen at
|
|
239
|
+
this resolution is the signal working, the same cause as `outcome_validated: false`, rather than a fixed value.
|
|
240
|
+
|
|
241
|
+
### Added
|
|
242
|
+
- **Range warnings on out-of-domain inputs.** The five chromatin marks are documented normalized signal in [0,1];
|
|
243
|
+
the fields previously accepted e.g. -5 and fed it to the model unflagged. They are now bordered and warned when
|
|
244
|
+
outside 0–1 (value kept, not clamped, so the OOD signal still reflects it). A non-positive cargo size is flagged
|
|
245
|
+
(`feasibility.buildable=False` + `cargo_size_nonpositive` scope flag) instead of reading as buildable.
|
|
246
|
+
- **A promoter/cell-type note.** Selecting a tissue-specific promoter (e.g. TBG = liver) surfaces that the
|
|
247
|
+
mechanistic estimate is cell-type-agnostic and applies the same strength regardless of tissue match, so a
|
|
248
|
+
maximally-optimistic score for a biologically inappropriate promoter/cell-type pairing is not misread.
|
|
249
|
+
|
|
250
|
+
## [7.3.15] - 2026-07-09 - Health check surfaces writability-atlas presence (deploy-mount visibility)
|
|
251
|
+
|
|
252
|
+
### Fixed
|
|
253
|
+
- **`/api/health` reports whether the per-cell-type writability atlases are present,** not just the bundled
|
|
254
|
+
writer atlas. A deploy that drops the runtime `-v ~/data/out:/work/data/out` mount leaves the container with no
|
|
255
|
+
per-cell-type atlas parquets, so Site Finder returns `atlas_<ct>.parquet not found` and the cell-type dropdown
|
|
256
|
+
shows "no atlas" for every cell type (including the measured K562/HepG2/HSPC), yet `/api/health` stayed green
|
|
257
|
+
because `atlas_present` checks only the bundled writer atlas. Health now includes `writability_atlas:
|
|
258
|
+
{measured_count, measured, ok}`; `measured_count == 0` makes a dropped-mount deploy immediately visible.
|
|
259
|
+
|
|
260
|
+
## [7.3.14] - 2026-07-09 - Digital Twin: surface the model's OWN OOD signal + disambiguate the two OOD checks
|
|
261
|
+
|
|
262
|
+
### Fixed
|
|
263
|
+
- **The Twin page's top-level "OOD" flag is disambiguated from the position-effect model's own OOD signal.** The
|
|
264
|
+
top-level flag is bound to the **virtual-cell response oracle's** scope card (its list of in-distribution cell
|
|
265
|
+
types and perturbation kinds), and every cell type the dropdown offers is on that list, so it reads "no" through
|
|
266
|
+
this UI by construction, not a broken gate. The **position-effect** model has its own separate
|
|
267
|
+
out-of-distribution signal (`ood_widen`, a Mahalanobis distance over the 5 supplied chromatin marks) that the
|
|
268
|
+
API returned but the UI never surfaced (×2.09 at typical marks, saturating at ×3.0 for marks pushed to 10–100).
|
|
269
|
+
Changes:
|
|
270
|
+
- The position-effect card shows an **"OOD widen (this head)"** stat (×1 typical → ×3 cap), colour-graded, so the
|
|
271
|
+
position-effect model's own OOD signal is visible and moves with the chromatin context.
|
|
272
|
+
- The top-level stat is relabelled **"OOD (response model)"** with an inline note that it is the response
|
|
273
|
+
oracle's scope-card check (expected to read "no" for any dropdown cell type), a different signal from the
|
|
274
|
+
position-effect widen factor.
|
|
275
|
+
- The "How to read these scores" panel documents both OOD checks separately.
|
|
276
|
+
- A regression test locks in that `position_effect.ood_widen` widens for out-of-range chromatin marks.
|
|
277
|
+
|
|
278
|
+
## [7.3.13] - 2026-07-09 - Guardian: FASTA-header robustness fix + Design Studio Proof detail parity
|
|
279
|
+
|
|
280
|
+
### Fixed
|
|
281
|
+
- **A sequence pasted straight from a database (a `>accession description` FASTA header plus wrapped sequence
|
|
282
|
+
lines) is now screened correctly.** `_looks_like_nucleotide()` ran on the raw pasted text, header included; the
|
|
283
|
+
header's non-nucleotide characters diluted the nucleotide fraction below the classification threshold, so the
|
|
284
|
+
header+sequence blob was misclassified as protein and scanned as one string, with no 6-frame translation. The
|
|
285
|
+
screen now strips FASTA/GenBank header lines (`>`, `;`) and whitespace before the nucleotide-vs-protein decision
|
|
286
|
+
(`_strip_headers_and_whitespace`) and cleans stray non-amino-acid characters in the protein branch. A
|
|
287
|
+
FASTA-formatted toxin sequence that previously returned zero hits now refuses.
|
|
288
|
+
- **Design Studio's Proof object (`/api/verify/proof`) carries the full hazard detail.** A hazard hit was reduced
|
|
289
|
+
to a bare `{signature, kind, severity}` with no reason, citation, or (for a sequence-domain hit) the Pfam
|
|
290
|
+
accession/bit score that Guardian's `/api/safety` view already showed. `_biosecurity_axis()` now carries `reason`
|
|
291
|
+
(the matched signature name), `citation` (the control-list reference), and `pfam_accession`/`bit_score` when the
|
|
292
|
+
hit came from the sequence screen; the Proof panel renders them as Guardian's hit list does.
|
|
293
|
+
|
|
294
|
+
## [7.3.12] - 2026-07-09 - Guardian: local Pfam/HMMER sequence-domain screen (the Cargo sequence box is now screened)
|
|
295
|
+
|
|
296
|
+
### Added
|
|
297
|
+
- **A raw Cargo sequence (DNA/RNA/protein) is screened for the curated toxin families, not only a declared
|
|
298
|
+
Cargo function.** `sequence_homology()` was previously a no-op in this deployment (its `external_hook` was an
|
|
299
|
+
unwired extension point). `HazardRegistry` now has a `.default()` registry that wires
|
|
300
|
+
`pen_stack/safety/pfam_scan.py` as that hook: a cargo sequence is 6-frame-translated (DNA/RNA) or scanned
|
|
301
|
+
directly (protein) against bundled public Pfam profile HMMs for the same 17 accessions already in
|
|
302
|
+
`configs/safety/hazard_registry.yaml` (ricin/RIP, botulinum, diphtheria, anthrax, cholera, staph/strep
|
|
303
|
+
enterotoxin, conotoxin), using each profile's Pfam gathering (GA) cutoff, the threshold Pfam's own annotation
|
|
304
|
+
pipeline uses to call a family match. No hazard sequences are bundled: profile HMMs are public statistical
|
|
305
|
+
models built from many aligned sequences, not any one organism's sequence, consistent with the registry's
|
|
306
|
+
existing no-hazard-sequences policy. The screen reaches every entry point unchanged (`/api/safety`,
|
|
307
|
+
`/api/verify`, `/api/generate`, the Co-Scientist chat's design lane), since all funnel through `screen_design()`
|
|
308
|
+
→ the default registry: a sequence for a curated family refuses with no cargo_function declared, while benign
|
|
309
|
+
cargo (a GFP CDS fragment, a Factor IX fragment) stays clear. Scope: this covers the curated family list only
|
|
310
|
+
and is not a substitute for a full external homology screener (IBBIS Common Mechanism / SecureDNA) over a larger
|
|
311
|
+
reference set; an integrator can override via `HazardRegistry.load(external_hook=...)`.
|
|
312
|
+
- `provenance.declared_signal` (v7.3.11) now counts a submitted `cargo_seq`/`cargo_sequence` as signal, since it
|
|
313
|
+
is genuinely screened.
|
|
314
|
+
|
|
315
|
+
## [7.3.11] - 2026-07-09 - Guardian: distinguish an empty submission from a screened-clear result + Cargo function autofill fix
|
|
316
|
+
|
|
317
|
+
### Fixed
|
|
318
|
+
- **An empty Guardian submission is distinguished from a screened benign design.** With no cargo function, domain
|
|
319
|
+
tag, or taxon declared, `safety_gate` has no signal and correctly decides `clear`, but the badge and reason
|
|
320
|
+
("no hazard signal") were indistinguishable from a benign design ("human factor IX") that was actually checked.
|
|
321
|
+
`SafetyVerdict.provenance` now carries `declared_signal` (whether anything screenable was submitted); the reason
|
|
322
|
+
text reads "nothing was screened" when it is `False`, and the Guardian page renders a caveat: *"Nothing was
|
|
323
|
+
screened. 'Clear' here means there was no input to check, not a verified-safe result."*
|
|
324
|
+
- **Cargo function field text duplication.** The field had no `autoComplete` attribute, leaving it open to the
|
|
325
|
+
browser's autofill/suggestion heuristics interfering with a controlled input. `autoComplete="off"` is set on the
|
|
326
|
+
Cargo function and Gene/target inputs and the Cargo sequence textarea (the app's React state is the single source
|
|
327
|
+
of truth for these fields).
|
|
328
|
+
|
|
329
|
+
## [7.3.10] - 2026-07-08 - Promoter selector + cargo-capacity feasibility + mechanistic/learned transparency; multiplex verify fix
|
|
330
|
+
|
|
331
|
+
### Fixed
|
|
332
|
+
- **The multiplex plan (v7.3.9) now triggers its rule.** A multi-edit plan was sent with the original
|
|
333
|
+
`write_type` (e.g. `insertion`), whose rule categories exclude `multiplex`, so `multiplex.translocation_risk`
|
|
334
|
+
never ran (empty `soft_flags`). The plan now routes as `write_type="multiplex"`, so the translocation screen
|
|
335
|
+
fires (two DSB nucleases on different chromosomes → risk 0.64 flag; a DSB-free plan → ~zero).
|
|
336
|
+
- **The Digital Twin's top-level "Relative expression" reflects promoter and vehicle changes; its
|
|
337
|
+
cell-type-agnostic, per-copy basis is now explicit.** The mechanistic estimate is
|
|
338
|
+
`promoter × copy-number × accessibility × pre-existing-NAb`, with accessibility neutral (no cell-type chromatin
|
|
339
|
+
track mounted), **cell-type-agnostic** (the cell-type position effect is the learned position-effect head) and
|
|
340
|
+
**per-copy** (independent of cargo size), so it did not move with cell type or cargo size. The page now (a)
|
|
341
|
+
exposes the **31-promoter palette** as a selector, a live lever the estimate reacts to (`GET /twin/promoters`,
|
|
342
|
+
`design.promoter`); (b) surfaces the **learned head's cell-type-aware relative expression** next to the
|
|
343
|
+
mechanistic headline, so a cell-type change is visible; (c) flags **cargo-over-capacity** as not-buildable
|
|
344
|
+
(`feasibility` in `/predict`); (d) states the mechanistic basis inline.
|
|
345
|
+
|
|
346
|
+
## [7.3.9] - 2026-07-08 - Design Studio: multiplex-plan UI + advisory (soft-penalty) flags surfaced
|
|
347
|
+
|
|
348
|
+
### Added
|
|
349
|
+
- **A "Plan multiple simultaneous edits" section on Design Studio** builds a 2–5-edit plan (chromosome / position /
|
|
350
|
+
writer-family rows) and sends it as `design.edits`, making the `multiplex.translocation_risk` legality rule
|
|
351
|
+
(implemented and rule-spec-published since v3.1, but with no UI path to `design.edits`) reachable. The default
|
|
352
|
+
two-row example matches the rule's own test fixture (two DSB nucleases on different chromosomes) and reproduces a
|
|
353
|
+
"flag" on first Verify.
|
|
354
|
+
- **Advisory (soft-penalty) flags are rendered on the Verify result.** `Verdict.soft_flags` was always computed
|
|
355
|
+
(multiplex translocation risk, AAV packaging margin, delivery sequence constraints, fold cross-loop
|
|
356
|
+
complementarity) but never rendered, since soft penalties do not fail legality and the Proof object's legality
|
|
357
|
+
axis never carried them. A new "Advisory flags" panel shows the rule id, reason, and value for any soft-penalty
|
|
358
|
+
rule that fires, labelled non-blocking.
|
|
359
|
+
|
|
360
|
+
## [7.3.8] - 2026-07-08 - not_evaluated state under biosecurity refuse + standards concordance surfaced
|
|
361
|
+
|
|
362
|
+
### Fixed
|
|
363
|
+
- **The legality and confidence proof axes no longer report a verdict when biosecurity refuses a design.**
|
|
364
|
+
`verify.service.verify()` short-circuits on a biosecurity refuse and returns *before* the rules engine or
|
|
365
|
+
confidence calibration run (`legal=None`, `violations=[]`), a security-first fail-fast posture. `verify_proof()`'s
|
|
366
|
+
legality axis previously read that state as `status="fail"` with an empty violated list and no repair hint, and
|
|
367
|
+
the confidence axis read it as `status="abstain"` with a repair hint suggesting "supply the soft per-axis scores
|
|
368
|
+
to calibrate", which would not help. Both axes now report **`status="not_evaluated"`**, `ok=True` (an
|
|
369
|
+
unevaluated axis does not itself block; biosecurity already blocks `passable`), with an explanatory,
|
|
370
|
+
non-actionable repair hint. A genuine legality failure with no biosecurity hazard is unaffected (regression-tested).
|
|
371
|
+
|
|
372
|
+
### Added
|
|
373
|
+
- **Standards concordance (v6.12) is reachable via REST and rendered on the Guardian page.**
|
|
374
|
+
`concordance_report()` and `align_to_common_mechanism()` were implemented and unit-tested since v6.12 but had no
|
|
375
|
+
API endpoint or UI surface. `GET /safety/concordance` serves the labelled-probe-set report (8/8 concordant);
|
|
376
|
+
`POST /safety` additively carries a per-decision `standards` field (Common Mechanism ScreenStatus + SecureDNA
|
|
377
|
+
outcome), leaving the underlying decision unchanged. Guardian.jsx renders the per-screen standards alignment and
|
|
378
|
+
a concordance-benchmark card.
|
|
379
|
+
|
|
380
|
+
## [7.3.7] - 2026-07-08 - Writer immunogenicity: surface the human self control so the ADA foreignness term is visible
|
|
381
|
+
|
|
382
|
+
### Added
|
|
383
|
+
- **The Writer Atlas immunogenicity table surfaces the human self control (albumin) as a labelled reference
|
|
384
|
+
row.** Every genome writer is foreign (foreignness = 1), so the shipped rows could not show that
|
|
385
|
+
`ada_risk = MHC-II density × foreignness(origin)` is multiplicative, the numbers were indistinguishable from
|
|
386
|
+
`ada_risk = MHC-II load`. The self control (origin = self → foreignness 0) has a non-zero MHC-II density (0.32)
|
|
387
|
+
yet ADA-risk 0, so ADA decouples from the load: the row demonstrates that the foreignness term does real work
|
|
388
|
+
(central tolerance). `writer_immunogenicity_table()` appends it with `is_control: True`; the UI highlights it and
|
|
389
|
+
explains the decoupling; a test asserts control ada_risk 0 versus foreign writers ada_risk > 0.
|
|
390
|
+
|
|
391
|
+
## [7.3.6] - 2026-07-08 - Design Studio: immune-risk profile no longer shows stale numbers when the main vehicle changes
|
|
392
|
+
|
|
393
|
+
### Fixed
|
|
394
|
+
- **The Immune-risk profile card no longer desyncs from the main form's Delivery vehicle.** Changing the main-form
|
|
395
|
+
vehicle dropdown moved the profile card's highlighted vehicle chip (it tracked `design.delivery_vehicle`) while
|
|
396
|
+
the axis numbers stayed on the previously-profiled vehicle, so AAV numbers could be read as if they were LNP's.
|
|
397
|
+
The chip highlight now tracks the vehicle the profile was actually **computed for** (`immVehicle`), so chip and
|
|
398
|
+
numbers agree, and a banner appears when the main-form vehicle diverges ("These axes are for X … click its chip
|
|
399
|
+
or press Profile again to recompute for Y").
|
|
400
|
+
|
|
401
|
+
## [7.3.5] - 2026-07-08 - Off-Target auto-scroll hotfix (instant, not smooth)
|
|
402
|
+
|
|
403
|
+
### Fixed
|
|
404
|
+
- **The v7.3.4 auto-scroll-to-result now moves the viewport.** `scrollIntoView({behavior:"smooth"})` no-ops on
|
|
405
|
+
this app's scroll container; dropping `behavior:"smooth"` makes the Off-Target result reliably scroll into view
|
|
406
|
+
on the first click.
|
|
407
|
+
|
|
408
|
+
## [7.3.4] - 2026-07-08 - Off-Target page: scroll the result into view + guard rapid writer-class switches
|
|
409
|
+
|
|
410
|
+
### Fixed
|
|
411
|
+
- **The Off-Target finder result scrolls into view when it renders.** The page was the only finder missing the
|
|
412
|
+
shared auto-scroll-to-result pattern, so a result rendered below the tall explainer cards read as "no visible
|
|
413
|
+
output" on the first click. Adds a `resultsRef` and a `scrollIntoView` effect on busy/result/error, matching
|
|
414
|
+
Site Finder / Write Spec / Writer Atlas.
|
|
415
|
+
- **A slow previous-writer-class response can no longer clobber the current one.** `run()` tags each request and
|
|
416
|
+
only the latest may write `res`/`error`/`busy` (a request-id guard), so switching writer class and clicking in
|
|
417
|
+
quick succession renders the current selection's result.
|
|
418
|
+
|
|
419
|
+
## [7.3.3] - 2026-07-07 - Off-Target page copy: reflect SITE-seq, the chromatin annotation, and Cas12a in the on-page description and score guide
|
|
420
|
+
|
|
421
|
+
### Changed
|
|
422
|
+
- **Off-Target page `WhatYouGet` / `ScoreGuide` copy now documents the v7.3.1 capabilities** that were shipped in
|
|
423
|
+
the mechanics but not the descriptions: SITE-seq is named as the fourth grounding/confirming assay; the chromatin
|
|
424
|
+
accessibility annotation is described (validated, HEK293T DNase GUIDE-seq AUROC 0.671, annotation-only, not a
|
|
425
|
+
re-ranker); and Cas12a is noted as enumeration-supported but SpCas9-scorer-scoped (the finder abstains rather than
|
|
426
|
+
mis-scoring). No behavior change, copy only.
|
|
427
|
+
|
|
428
|
+
## [7.3.2] - 2026-07-07 - Digital Twin: surface the learned position-effect head (served model + resolution-aware validation state)
|
|
429
|
+
|
|
430
|
+
### Added
|
|
431
|
+
- **The position-effect head surfaced on the Digital Twin page (`Twin.jsx`).** When a chromatin context is
|
|
432
|
+
supplied, the page shows which learned head served (human K562, Leemans 2019 / mESC TRIP), the served feature
|
|
433
|
+
resolution, and the `outcome_validated` flag, plus the learned log2-expression, its conformal interval and
|
|
434
|
+
p(silenced). An optional chromatin-context input (the head's five histone marks) enables the learned head from the
|
|
435
|
+
page. The human K562 head's validated regime (ρ≈0.57 at exact-site per-locus features) is distinguished from the
|
|
436
|
+
app's coarse 1 kb serving resolution, at which the head serves with `outcome_validated: false`.
|
|
437
|
+
- The `stage_h_mode` (learned vs heuristic) is shown as a pill on the predicted-outcome card.
|
|
438
|
+
- The human K562 position-effect head (`models/position_effect_human_k562.pkl`, Leemans 2019) and the mESC head
|
|
439
|
+
(`models/position_effect.pkl`) are staged into the served image so the v7.3.0 head loads at serve time (it was
|
|
440
|
+
wired in v7.3.0 but its artifact was not mounted); the artifacts are re-serialized in the serving image
|
|
441
|
+
(scikit-learn 1.9.0).
|
|
442
|
+
|
|
443
|
+
### Changed
|
|
444
|
+
- The Digital Twin `WhatYouGet` / `ScoreGuide` copy documents the learned position-effect head and the exact-site vs coarse
|
|
445
|
+
1 kb resolution distinction.
|
|
446
|
+
|
|
447
|
+
## [7.3.1] - 2026-07-07 - Off-Target finder: SITE-seq in the assay recommender, chromatin-annotation surfacing, and Cas12a scoping
|
|
448
|
+
|
|
449
|
+
### Added
|
|
450
|
+
- **SITE-seq in the nuclease validation-assay recommender.** `offtarget_assay.recommend_assay` now lists SITE-seq
|
|
451
|
+
(Cameron et al., Nat Methods 2017; DOI 10.1038/nmeth.4284) alongside GUIDE-/CHANGE-/CIRCLE-seq, completing the
|
|
452
|
+
four unbiased assays the mismatch-calibrated risk band is grounded on.
|
|
453
|
+
- **Cas12a in the Off-Target finder writer-class selector (AsCas12a).** Genome-wide enumeration supports the Cas12a
|
|
454
|
+
TTTV 5' PAM, but the validated CRISOT-Score and the mismatch-calibrated risk band are SpCas9-specific; the finder
|
|
455
|
+
therefore reports that a validated Cas12a off-target scorer is not available rather than scoring Cas12a sites with
|
|
456
|
+
the SpCas9 model.
|
|
457
|
+
- **Chromatin-accessibility annotation surfaced on the nuclease finder result**: its standalone validation
|
|
458
|
+
(cell-type-matched HEK293T DNase; GUIDE-seq AUROC 0.671) plus a per-site accessibility column when the
|
|
459
|
+
accessibility track is mounted.
|
|
460
|
+
|
|
461
|
+
### Changed
|
|
462
|
+
- **The nuclease off-target `method` string and the `nominate_offtargets` capability manifest now describe the
|
|
463
|
+
chromatin layer precisely**, a validated annotation surfaced when the accessibility track is mounted (annotation-only,
|
|
464
|
+
not a re-ranker), instead of describing it unconditionally.
|
|
465
|
+
|
|
466
|
+
### Fixed
|
|
467
|
+
- **The nuclease finder no longer returns a chromatin field with no context when the accessibility track is
|
|
468
|
+
absent.** The result now carries `chromatin_available` and a note stating the annotation is track-gated and the
|
|
469
|
+
CRISOT-driven ranking is unaffected, in place of a silent null.
|
|
470
|
+
|
|
471
|
+
## [7.3.0] - 2026-07-04 - A cell-type-matched position-effect head for human K562 (Leemans 2019), replacing the non-transferring cross-species axis; served claim is resolution-aware
|
|
472
|
+
|
|
473
|
+
### Added
|
|
474
|
+
- **Human K562 position-effect head.** `twin.data.position_effect` now wires the **Leemans 2019**
|
|
475
|
+
human K562 dataset (Cell; PMID 30982597; DOI 10.1016/j.cell.2019.03.009) with a real loader (`_load_leemans`),
|
|
476
|
+
per-barcode coordinates fetched from the Cell supplement Dataset S2 joined to the van Steensel feature set.
|
|
477
|
+
`twin.position_effect.load_human_k562_model` + cell-type routing in `predict_stage_h` serve a `PositionEffectModel`
|
|
478
|
+
trained on human K562 for human K562 designs, falling back to the mESC model otherwise.
|
|
479
|
+
- Held-out validation (chromosome-blocked 5-fold OOF; n=9,298; 5 shared histone marks): expression Spearman
|
|
480
|
+
**ρ ≈ 0.59**, split-conformal held-out coverage **0.90** (nominal 0.90, within tolerance). This beats the mESC
|
|
481
|
+
model applied cross-species, which is a null result on human K562 (held-out ρ ≈ 0.13, does not beat the
|
|
482
|
+
lamina/heterochromatin baseline ρ ≈ 0.39), and the trivial "avoid heterochromatin" baseline.
|
|
483
|
+
|
|
484
|
+
### Changed
|
|
485
|
+
- **The v6.7 cross-cell-type transfer axis is no longer data-gated.** With a human cell type now fetched, a human
|
|
486
|
+
K562 design's provenance/scope reflect **human K562 supervision** instead of "single_context_supervision
|
|
487
|
+
(mESC), cross-cell-type transfer data-gated". `predict_stage_h` gains a `cell_type` argument (default `None`;
|
|
488
|
+
backward compatible; `twin.outcome` passes the cell state through).
|
|
489
|
+
|
|
490
|
+
### Serve-time scope, resolution-aware `outcome_validated` scope
|
|
491
|
+
- The head's held-out validation (ρ ≈ 0.57 / +0.065 over a learned-heterochromatin baseline, CI [0.026, 0.103])
|
|
492
|
+
holds at **exact-site per-integration** chromatin-feature resolution. On coarse 1 kb-binned features even a
|
|
493
|
+
human-trained model realizes only **ρ ≈ 0.16** (P2_MATCHED_TRANSFER). `predict_stage_h` therefore stamps the
|
|
494
|
+
`human_K562_outcome_validated` scope **only when the caller declares exact-site features** (`feature_resolution`
|
|
495
|
+
/ `chromatin_features_resolution`, or `chromatin_ctx.resolution` ∈ exact-site set). Otherwise, including
|
|
496
|
+
undeclared resolution (conservative default), it returns `outcome_validated: False` and a downgraded flag
|
|
497
|
+
(`human_K562_head_served_UNVALIDATED_RESOLUTION …`) naming both numbers and the requirement. The prediction is
|
|
498
|
+
still served; only the validation claim is withheld until the served resolution matches the validated regime.
|
|
499
|
+
The output gains `served_feature_resolution` and `outcome_validated` fields.
|
|
500
|
+
- **Deferred to v7.4:** exact-site chromatin-feature extraction *at serve time* (point-query ChIP for an arbitrary
|
|
501
|
+
locus), so the served path realizes the validated ρ ≈ 0.57 directly and auto-earns the `outcome_validated` scope.
|
|
502
|
+
|
|
503
|
+
### Notes (scope)
|
|
504
|
+
- The cassette factorization (`f_cassette + g_context`) adds no value on Leemans' 6 similar promoters (factored
|
|
505
|
+
ρ 0.588 vs context-only ρ 0.592); additive suffices, reported not hidden. The served silenced (escaper/repressed)
|
|
506
|
+
call is promoter-driven, not a position signal. The head's validated output is steady-state **position-effect
|
|
507
|
+
expression in K562**, not temporal durability or other cell types.
|
|
508
|
+
- **Cross-species transfer is poor** (matched-source mouse↔human ρ ~0.08–0.20; P2_MATCHED_TRANSFER). The axis is
|
|
509
|
+
cell-type-specific; train a head per target cell type. An earlier draft over-read a feature-source-confounded
|
|
510
|
+
ρ 0.505 as transfer; corrected.
|
|
511
|
+
- The model artifact + Leemans parquet are deployment data (git-ignored under `data/`/`models/`, per the data
|
|
512
|
+
policy), not shipped in the wheel. Absent them, the human loader returns `None` and the position-effect head is unchanged.
|
|
513
|
+
|
|
514
|
+
## [7.2.3] - 2026-07-02 - Off-Target: professional wording (self-contained, no external-tool comparisons) + a plain-language explainer
|
|
515
|
+
|
|
516
|
+
### Changed
|
|
517
|
+
- **Removed all external-tool comparisons** ("like CRISPOR / CHOPCHOP", "CRISPOR-class", "CRISPOR-comparable") from
|
|
518
|
+
every off-target surface, the Off-Target page, nav, code docstrings, REST docstring, the data card, `positioning.md`,
|
|
519
|
+
the prereg (re-SHA-locked), paper-4 prereg, and the v7.2.0 CHANGELOG entry. The capability is now described on its
|
|
520
|
+
own terms: a genome-wide off-target *finder*. Given a guide/target, it enumerates and ranks the off-target sites
|
|
521
|
+
itself. No functional change.
|
|
522
|
+
- **Off-Target page now explains off-target effects in plain language**: a new top card covers *what an off-target
|
|
523
|
+
effect is*, *what you enter* (per writer class), and *what you get back* (ranked genome-wide sites with
|
|
524
|
+
coordinates + a risk band + the confirming assay), plus a "how it works" line (scan GRCh38 within the mismatch
|
|
525
|
+
tolerance → score → rank; heavy scan on the VM, replayed or abstain). The per-metric ScoreGuide was
|
|
526
|
+
reworded to match.
|
|
527
|
+
|
|
528
|
+
## [7.2.2] - 2026-07-02 - Integrase: precise capability framing (the negative is about a method, not the biology)
|
|
529
|
+
|
|
530
|
+
A framing/presentation refinement of the v7.2.1 sealed-negative result: no science changes; the number is
|
|
531
|
+
unchanged and the negative stands.
|
|
532
|
+
|
|
533
|
+
### Changed
|
|
534
|
+
- **Precise claim, everywhere:** what the sealed PhiC31 benchmark showed is that a specific *method* (attP
|
|
535
|
+
sequence-similarity scanning) is insufficient, **NOT** that pseudosites are unpredictable. The signal is real
|
|
536
|
+
(Chalberg's palindromic consensus; IntQuery's success on 410,776 cryptic attB), just not capturable by simple
|
|
537
|
+
identity. So the narrow claim is "sequence similarity is insufficient," and this negative is the
|
|
538
|
+
empirical justification for a learned/DMS model (the indicated next step). Sharpened in `offtarget_integrase.py`,
|
|
539
|
+
`phic31_recall_metrics.json`, and the data card so nothing reads as "unpredictable."
|
|
540
|
+
- **App presentation:** `nominate_integrase` now returns a `capability` disclosure (badge + plain microcopy). The
|
|
541
|
+
Off-Target page shows a badge reading **"mechanism-based · not predictive by sequence alone"** (not a bare red
|
|
542
|
+
flag) plus one line, *"φC31 pseudosite activity is sequence-guided but not predictable from similarity alone
|
|
543
|
+
(sealed benchmark, negative); confirm empirically"*, separating the grounded facts (verified att + documented
|
|
544
|
+
pseudo-attP with GenBank accessions) from the capability limit. A trust-building disclosure, not an alarm.
|
|
545
|
+
|
|
546
|
+
## [7.2.1] - 2026-07-02 - PhiC31 integrase: close the serine-integrase data gap with verified data + a sealed recall benchmark (negative result)
|
|
547
|
+
|
|
548
|
+
Closes the one genuine open item from v7.2.0, the PhiC31 integrase data gap, with independently-verified,
|
|
549
|
+
open, citable sequences (no fabrication) and a **sealed recall benchmark whose result is reported verbatim**.
|
|
550
|
+
|
|
551
|
+
### Added
|
|
552
|
+
- **PhiC31 is now encoded** (`data/curated/integrase_att.yaml`), replacing the v7.2.0 abstain-with-disclosure. All
|
|
553
|
+
data was **independently validated against NCBI/RCSB** (which caught two errors in the completion pack's
|
|
554
|
+
citations, since corrected): att from **PDB 9U2T/9U2S** ("PhiC31 integrase-attB-attP synaptic complex"; the
|
|
555
|
+
canonical Groth-2000 34 bp attB is present in attB53); the documented human pseudo-attP **ψA/ψC/ψD** from
|
|
556
|
+
**GenBank AF333429/AF333430/AF333431** (Thyagarajan 2001, *Mol Cell Biol* 21(12), PMID 11359900,
|
|
557
|
+
DOI `10.1128/MCB.21.12.3926-3934.2001`; chr8/16/15). Corrected DOIs: Groth 2000 `10.1073/pnas.090527097`,
|
|
558
|
+
Chalberg 2006 `10.1016/j.jmb.2005.11.098` (was `...11.108`).
|
|
559
|
+
- **Sealed PhiC31 pseudo-attP recall benchmark** (`benchmarks/offtarget/integrase/`): does attP-sequence-
|
|
560
|
+
similarity recover the documented pseudo-attP above length-matched GRCh38 background? **Result: NEGATIVE,
|
|
561
|
+
reported verbatim:** all three sites score 14 mm / 30 bp (53.3% identity), exactly the background **median**
|
|
562
|
+
(60.6% / 77.0% / 82.4% of random windows are as-or-more attP-similar). Sequence identity to attP is **not** a
|
|
563
|
+
validated PhiC31 pseudo-attP predictor; φC31 recognition depends on palindromic architecture (Chalberg 2006) /
|
|
564
|
+
a learned model (IntQuery), not raw identity.
|
|
565
|
+
|
|
566
|
+
### Changed
|
|
567
|
+
- **Integrase status corrected: `semi_validated` → `mechanism_based_unvalidated` (with a sealed-NEGATIVE benchmark).**
|
|
568
|
+
The v7.2.0 "semi-validated (documented pseudosites as partial ground truth)" implied the sites validated the
|
|
569
|
+
method; the sealed benchmark shows they do not. This is a *stronger* outcome, a tested negative
|
|
570
|
+
rather than an untested claim. The verified att + documented pseudosites remain grounded facts and are surfaced
|
|
571
|
+
as verified known off-target loci. `nominate_integrase` PhiC31 returns the documented pseudo-attP + the sealed
|
|
572
|
+
benchmark; Bxb1 returns genome-wide similarity candidates carrying the same `similarity_ranking_validated: false`
|
|
573
|
+
caveat. The pre-registration was amended + re-SHA-locked; data card + deviations ledger updated; Off-Target page shows the
|
|
574
|
+
documented sites + the benchmark verdict.
|
|
575
|
+
|
|
576
|
+
## [7.2.0] - 2026-07-01 - The off-target engine becomes a genome-wide, per-mechanism off-target finder (all 5 writer classes)
|
|
577
|
+
|
|
578
|
+
The off-target engine was a candidate *scorer*; it ranked off-target sites you supplied. An off-target *finder* instead takes
|
|
579
|
+
a guide/target and enumerates the genome-wide off-target sites itself. The finder closes that enumeration gap
|
|
580
|
+
AND applies the **correct off-target mechanism for each writer class**, each carrying a truthful per-mechanism
|
|
581
|
+
validation status.
|
|
582
|
+
|
|
583
|
+
### Per-mechanism paths
|
|
584
|
+
- **Serine integrase** (`offtarget_integrase.py`): a genome-wide **pseudo-attP** scan, a fixed-sequence
|
|
585
|
+
Cas-OFFinder scan of the attP core window over GRCh38, scored by att-arm similarity. **Bxb1** is fully encoded
|
|
586
|
+
(FlyBase FBto0000359 / Ghosh 2003) and is highly specific. Status **semi-validated**. **PhiC31 is a disclosed
|
|
587
|
+
data gap** (its documented human pseudo-attP set, Chalberg 2006, could not be verified from an open source in
|
|
588
|
+
this build, so it abstains rather than fabricate). `data/curated/integrase_att.yaml`.
|
|
589
|
+
- **Bridge** (`offtarget_bridge.py`): wraps the existing DMS-scored genome scan (measured Perry-2025
|
|
590
|
+
specificity, held-out ranking AUROC 0.88). Status **hard-locked mechanism-based-unvalidated**; the ranker is
|
|
591
|
+
DMS-validated but **no genome-wide cellular off-target assay exists** for bridge recombinases, so genomic
|
|
592
|
+
recovery is unvalidated (stated in a no-ground-truth disclosure).
|
|
593
|
+
- **CAST** (`offtarget_cast.py` + `data/curated/cast_systems.yaml`), NEW: guide-directed spacer scan +
|
|
594
|
+
the distinctive **guide-independent untargeted-transposition** background per system (ShCAST/Type V-K high +
|
|
595
|
+
AT-biased; VchCAST/Type I-F >95–99% on-target), all DOI-tagged. Status **mechanism-based-unvalidated**.
|
|
596
|
+
- **PASTE / (ee)PASSIGE** (`offtarget_paste.py`), NEW: composes the validated nuclease finder (Cas9
|
|
597
|
+
nickase, pegRNA) with the semi-validated integrase pseudo-attP scan (installed att); returns both component sets
|
|
598
|
+
and recommends BOTH a nuclease assay and an integrase assay. Status **composite**.
|
|
599
|
+
|
|
600
|
+
### Status labels + assay recommender + disclosures
|
|
601
|
+
- Every nomination carries a per-mechanism status label + the mechanism-appropriate confirm assay; `recommend_assay`
|
|
602
|
+
now covers CAST (transposon insertion-site seq) and PASTE (dual). `docs/cards/offtarget_data.md` documents the
|
|
603
|
+
per-mechanism ground-truth status: **every mechanism has either a sealed benchmark (nuclease) or an
|
|
604
|
+
explicit no-ground-truth / data-gap disclosure (integrase-PhiC31, bridge, CAST), never a fabricated metric.**
|
|
605
|
+
- Disclosed deviations from the plan (no silent substitution): `att_pwm.json` → an att-similarity model in
|
|
606
|
+
`integrase_att.yaml` (a per-position PWM needs aligned pseudosites that do not exist at genome scale);
|
|
607
|
+
`bridge_dms_specificity.parquet` → the existing measured `bridge_offtarget_profile_measured.parquet` is reused;
|
|
608
|
+
`known_pseudosites.parquet` → not created (Bxb1 highly specific; PhiC31 disclosed data gap).
|
|
609
|
+
|
|
610
|
+
### Nuclease finder
|
|
611
|
+
|
|
612
|
+
### Added
|
|
613
|
+
- **Genome-wide enumeration engine** (`pen_stack/wgenome/offtarget_enumerate.py`). Given a guide + enzyme,
|
|
614
|
+
enumerates every genomic site within the mismatch tolerance across GRCh38 via **Cas-OFFinder** (Bae, Park & Kim,
|
|
615
|
+
Bioinformatics 2014, `10.1093/bioinformatics/btu048`), returning coordinates, strand, matched sequence, and
|
|
616
|
+
mismatch count. Supports SpCas9 (NGG), SaCas9 (NNGRRT), and Cas12a (TTTV, 5' PAM). A full scan is heavy, so it
|
|
617
|
+
runs **only on the VM** (`casoffinder:tools` Docker image, `docker/casoffinder.Dockerfile`); the live app
|
|
618
|
+
**replays a committed coordinate cache** for the canonical guides or **abstains** for a novel one
|
|
619
|
+
(never fabricates sites), the same replay-or-abstain pattern as the heavy structure oracles. The enumerated
|
|
620
|
+
coordinates are facts from the public GRCh38 assembly (no license restriction), so the cache is committed
|
|
621
|
+
(`data/offtarget/enumerated_cache.parquet`, 8 canonical guides, 40,268 sites).
|
|
622
|
+
- **Nuclease off-target FINDER** (`pen_stack/wgenome/offtarget_nuclease.py`): chains enumeration into the
|
|
623
|
+
existing, validated scorer, real CRISOT-Score → mismatch-calibrated risk band → chromatin annotation, so a
|
|
624
|
+
guide returns the genome-wide ranked off-target set *with coordinates*. Scoring is unchanged from v6.10 (still
|
|
625
|
+
validated: CRISOT beats homology on four unbiased assays); v2 adds the enumeration front end.
|
|
626
|
+
- **The enumeration gate passed**: enumeration recovers **100%** of EMX1's documented GUIDE-seq off-targets within the ≤5-mm
|
|
627
|
+
tolerance (all 16 validated-active sites, which are all ≤4 mm; the higher-mismatch fixture rows are inactive
|
|
628
|
+
negatives). The on-target is recovered at chr2:72,933,852. `tests/unit/test_offtarget_enumeration.py`.
|
|
629
|
+
- **Prereg** `prereg/ws_offtarget2.yaml` (SHA-locked): the mechanism taxonomy, per-enzyme enumeration parameters,
|
|
630
|
+
the truthful per-mechanism status-label rules (validated / semi-validated / mechanism-based-unvalidated), and
|
|
631
|
+
the acceptance gates.
|
|
632
|
+
- REST: `POST /offtarget` is now a **finder by default** for a nuclease guide with no supplied `candidate_sites`
|
|
633
|
+
(accepts `enzyme`, `max_mismatch`); `GET /offtarget/enumerated` lists the cached guides. The web **Off-Target**
|
|
634
|
+
page is rebuilt as a finder (guide in → genome-wide ranked off-targets with coordinates), with the scorer→finder
|
|
635
|
+
explanation and the VM/cache architecture stated.
|
|
636
|
+
|
|
637
|
+
### Unchanged / backward compatible
|
|
638
|
+
- Supplying `candidate_sites` keeps the v6.10 score-my-candidates path. The integrase (pseudo-attB sequence scan),
|
|
639
|
+
bridge (Perry-DMS), chromatin annotation, and validation-assay recommender are unchanged. Nomination remains a
|
|
640
|
+
candidate, never a clearance.
|
|
641
|
+
|
|
642
|
+
## [7.1.8] - 2026-06-30 - Writer immunogenicity moves to the Writer Atlas; SpCas9 removed from the writer options
|
|
643
|
+
|
|
644
|
+
### Changed
|
|
645
|
+
- **The writer enzyme is no longer chosen in the Design Studio; its immunogenicity moves to the Writer Atlas, where
|
|
646
|
+
writers belong.** The Design Studio's writer dropdown existed only to feed the two writer-as-antigen immune axes
|
|
647
|
+
(MHC-II + ADA); that duplicated the dedicated Writer Atlas page. Now:
|
|
648
|
+
- The **Writer enzyme dropdown is removed** from `DesignForm` (and `DEFAULT_DESIGN`). The Design Studio's "Profile
|
|
649
|
+
immune & delivery" action correctly scopes to the **delivery/vehicle** axes (genotoxicity, CD8 capsid, innate,
|
|
650
|
+
pre-existing NAb, anti-PEG). `ImmuneProfileCard` hides the writer axes by default (`hideWriterAxes`).
|
|
651
|
+
- A new **Writer immunogenicity** card on the **Writer Atlas** surfaces each genome writer's MHC-II/CD4 epitope
|
|
652
|
+
load + ADA risk + human self-match, read from the **committed NetMHCIIpan-4.0 cache, not recomputed**
|
|
653
|
+
(`GET /api/writer/immune`, `immune_profile.writer_immunogenicity_table()`).
|
|
654
|
+
- **SpCas9 is removed** from the writer set: it is a nuclease/editor, not a large-cargo genome writer. The Writer
|
|
655
|
+
Atlas immunogenicity covers the actual writers, **Bxb1** (serine integrase) and **ISCro4** (bridge recombinase);
|
|
656
|
+
the Cas9 nuclease and the human self control are excluded. (The engine retains SpCas9 in its cache for other
|
|
657
|
+
uses; only the user-facing writer list drops it.)
|
|
658
|
+
- The engine still returns the `mhc2_writer` / `ada_writer` axes from `immune_profile()` for API/MCP callers that
|
|
659
|
+
pass a `writer_family`; only the web UI moved the writer profiling to the Writer Atlas. No data was recomputed.
|
|
660
|
+
|
|
661
|
+
### Added
|
|
662
|
+
- `test_immune_profile.py`: `test_writer_immunogenicity_table_for_the_writer_atlas` (covers Bxb1 + ISCro4 from the
|
|
663
|
+
cache; SpCas9 and the self control excluded; grounded MHC-II + ADA values).
|
|
664
|
+
|
|
665
|
+
## [7.1.7] - 2026-06-30 - Administration context (in-vivo / ex-vivo) now drives the immune profile
|
|
666
|
+
|
|
667
|
+
### Fixed
|
|
668
|
+
- **The in-vivo / ex-vivo "Context" toggle had no effect on the immune profile.** It already drove the Generate
|
|
669
|
+
vehicle sweep (route-compatible vehicles) and the Verify germline-prohibition legality rule, but `immune_profile()`
|
|
670
|
+
ignored it, so the per-axis immune profile was identical for in-vivo and ex-vivo. It now applies a documented,
|
|
671
|
+
grounded administration modifier (`immune_profile._administration_modifier` / `_apply_administration`):
|
|
672
|
+
- **Pre-existing NAb is muted to "no barrier" (1.0) ex vivo.** Ex-vivo delivery (cells transduced in a dish and
|
|
673
|
+
washed before transplant) never exposes the vector to the patient's circulating antibodies, so pre-existing
|
|
674
|
+
anti-vector NAb does not gate eligibility; the eligibility fraction is 1.0 regardless of titer. The original
|
|
675
|
+
seroprevalence value is preserved (`pre_admin_value`) and the muting is explained in the axis note. This is the
|
|
676
|
+
same in-vivo/ex-vivo distinction the v5.1 `delivery_immunology` profile already encodes (`computed_ex_vivo_muted`).
|
|
677
|
+
- **CD8 capsid is flagged muted ex vivo** (systemic anti-capsid response minimal), but its intrinsic presentability
|
|
678
|
+
value is kept; transduced cells can still present capsid epitopes, a real residual concern, so no number is
|
|
679
|
+
fabricated.
|
|
680
|
+
- **Genotoxicity, innate, anti-PEG and the writer axes are unchanged** by administration context (insertional risk
|
|
681
|
+
and cargo/writer immunogenicity are intrinsic, not a function of circulating-antibody exposure).
|
|
682
|
+
- A `administration_modifier` block (parallel to the existing `route_modifier`) is added to the profile; the
|
|
683
|
+
`ImmuneProfileCard` shows an in-vivo/ex-vivo chip, a per-axis "ex-vivo muted" badge with the reason, and the
|
|
684
|
+
administration effect line. In-vivo and unspecified contexts leave every axis untouched (backward compatible).
|
|
685
|
+
|
|
686
|
+
### Added
|
|
687
|
+
- `test_immune_profile.py`: `test_administration_context_mutes_vector_facing_axes_ex_vivo` (ex-vivo mutes pre-existing
|
|
688
|
+
NAb to 1.0 and flags CD8; in-vivo/unspecified are unchanged; genotoxicity is never muted by administration).
|
|
689
|
+
|
|
690
|
+
## [7.1.6] - 2026-06-30 - Immune axes wired end-to-end + Delivery folded into Design Studio
|
|
691
|
+
|
|
692
|
+
### Fixed
|
|
693
|
+
- **Four immune-risk axes were unreachable from the web UI and showed as out-of-scope**: innate sensing, anti-PEG,
|
|
694
|
+
and the writer-as-antigen MHC-II + ADA axes abstained on every web design because the design form never collected
|
|
695
|
+
their inputs (the engine computed them correctly when called directly; this was a wiring gap, not a model gap):
|
|
696
|
+
- **`innate`** needs a cargo sequence. The design form now has an optional **Cargo sequence** field; the cargo
|
|
697
|
+
nucleic-acid form (DNA -> CpG/TLR9, mRNA -> U-content + dsRNA, RNP -> transient) is derived from the vehicle's
|
|
698
|
+
defining cargo class (`immune_profile._vehicle_cargo_form`) so the axis computes for any caller (chat / MCP /
|
|
699
|
+
REST) once a sequence is supplied. Empty sequence still abstains; an explicit `cargo_form` still wins. No
|
|
700
|
+
fabrication: an unknown vehicle returns no form and the axis abstains.
|
|
701
|
+
- **`mhc2_writer` / `ada_writer`** need a writer protein. The design form now has a **Writer enzyme** selector
|
|
702
|
+
(the three grounded families with a bundled UniProt sequence + committed NetMHCIIpan-4.0 cache: serine integrase
|
|
703
|
+
Bxb1, bridge recombinase ISCro4, Cas9 SpCas9); `DEFAULT_DESIGN` ships a serine integrase so the two axes populate
|
|
704
|
+
out of the box. No writer selected -> the two axes abstain (never fabricated).
|
|
705
|
+
- **`anti_peg`** applies only to PEGylated vehicles; selecting `lnp_mrna` now surfaces it (with an inline hint),
|
|
706
|
+
and it correctly abstains for non-PEG vehicles.
|
|
707
|
+
- `ImmuneProfileCard` now shows the **writer-as-antigen** summary (representative writer, foreign/self, dominant
|
|
708
|
+
antigen) so the writer axes are self-explanatory.
|
|
709
|
+
|
|
710
|
+
### Changed
|
|
711
|
+
- **Delivery & Immunity folded into Design Studio.** The standalone Delivery page duplicated the same design form and
|
|
712
|
+
immune profile, so it is merged into Design Studio as a third action - **Profile immune & delivery** - with the
|
|
713
|
+
per-axis immune ScoreGuide, the vehicle quick-switch, the `ImmuneProfileCard` and the scope ledger. Design Studio is
|
|
714
|
+
now one design surface with three actions (Verify / Generate / Profile immune & delivery). `/delivery` redirects to
|
|
715
|
+
`/design`; the nav drops the separate item; old links keep working.
|
|
716
|
+
|
|
717
|
+
### Added
|
|
718
|
+
- `test_immune_profile.py`: tests for the vehicle-derived cargo form (innate computes for a DNA vehicle with a cargo
|
|
719
|
+
sequence; abstains without one; explicit form overrides) and for the writer axes computing when a grounded writer
|
|
720
|
+
is supplied (and abstaining otherwise).
|
|
721
|
+
|
|
722
|
+
## [7.1.5] - 2026-06-29 - Chromosome field: validation, gene concordance, context
|
|
723
|
+
|
|
724
|
+
### Added
|
|
725
|
+
- The `chrom` design field was a free-text pass-through with no validation and no downstream effect. It is now
|
|
726
|
+
meaningful (`pen_stack/planner/chromosome.py`):
|
|
727
|
+
- **Validation**: the web form's Chromosome input is a controlled dropdown (chr1–chr22, chrX, chrY, chrM), so
|
|
728
|
+
an impossible value like `chrZZZ` can no longer be entered; `canonical_chromosome()` normalises/validates on
|
|
729
|
+
the backend (`chrX`/`X`/`x`, `chr1`/`1`, `chrM`/`chrMT`/`MT`, `23`→X, `24`→Y; rejects the rest).
|
|
730
|
+
- **Gene/chromosome concordance**: `verify()` now flags `chromosome_mismatch` when the entered chromosome does
|
|
731
|
+
not match the named gene's canonical location (e.g. *BRCA1 is on chr17, not chr1*), `chromosome_invalid` for a
|
|
732
|
+
non-standard value, and `chromosome_unverifiable` for an unknown gene. The web form shows the warning inline
|
|
733
|
+
with a one-click fix, driven by the new `GET /api/gene/location` endpoint. This closes the silent-mismatch gap.
|
|
734
|
+
- **Chromosome context**: `chromosome_context()` adds grounded, chromosome-driven advisories surfaced as scope
|
|
735
|
+
flags: **chrM** is not addressable by nuclear genome-writing tools (mtDNA needs DdCBE/TALED, out of scope),
|
|
736
|
+
**chrY** is male-specific with ampliconic repeats, **chrX** is hemizygous in 46,XY vs X-inactivated in 46,XX.
|
|
737
|
+
- The Design Studio **cell-type dropdown now shows writability-atlas coverage** (from `/api/celltypes`): K562 /
|
|
738
|
+
HepG2 / HSPC are labelled measured (full / full / partial), while h1_hesc / iPSC / CD8 T / PBMC are labelled
|
|
739
|
+
"no atlas", so a data-gated cell type is no longer silently indistinguishable from a measured one (the same
|
|
740
|
+
disclosure principle as the chromosome field). The 7 cell types are unchanged and already matched the backend.
|
|
741
|
+
|
|
742
|
+
### Note (scoping)
|
|
743
|
+
- The free-text chromosome does **not** move the scored locus: per-locus safety / durability / accessibility /
|
|
744
|
+
off-target are indexed by the gene's *resolved genomic coordinates* via the writability atlas, so a bare
|
|
745
|
+
chromosome string with no position cannot refine them. Rather than fabricate a per-chromosome score delta, the
|
|
746
|
+
field's grounded effect is validation + gene concordance (ensuring the score is read for the right locus, and
|
|
747
|
+
flagging when the entered chromosome disagrees with the gene) + the chromosome-context advisories above.
|
|
748
|
+
|
|
749
|
+
## [7.1.4] - 2026-06-29 - Germline-prohibition legality rule
|
|
750
|
+
|
|
751
|
+
### Added
|
|
752
|
+
- **Compliance rule category + `compliance.germline_prohibition` (hard_reject).** A heritable / germline edit
|
|
753
|
+
previously passed the Legality axis because no rule existed for it (the only germline handling was a
|
|
754
|
+
known-unknown scope matcher for *questions*, not *designs*). The new rule fails legality for: a reproductive
|
|
755
|
+
germline target cell (embryo / zygote / oocyte / sperm / gamete - unconditional), a declared reproductive-use
|
|
756
|
+
intent (gametes / assisted reproduction / implantation / "for reproduction"), a declared heritable intent
|
|
757
|
+
(germline / heritable / "transmitted to offspring"), or a germline-competent cell type (hESC / iPSC) edited in a
|
|
758
|
+
heritable context (in vivo, or a reproductive/heritable intent). It is cited (Lander et al. 2019 moratorium,
|
|
759
|
+
`10.1038/d41586-019-00726-5`; US National Academies 2017, `10.17226/24623`) and emits a proof-object repair hint
|
|
760
|
+
(restrict to somatic / ex-vivo editing). It is a scope-of-use legality bound, reported on the LEGALITY axis,
|
|
761
|
+
separate from the Biosecurity axis. The category is wired into every write type; `rule_spec.json` is now 11 rules.
|
|
762
|
+
- **Paraphrase + negation robustness** (red-team-hardened). The free-text intent match is NEGATION-aware
|
|
763
|
+
(negated-span detection), so a somatic design that explicitly says "somatic, not germline" / "no germline
|
|
764
|
+
transmission" / "NOT for reproduction or implantation" is not false-flagged, while paraphrased reproductive
|
|
765
|
+
intent (e.g. "generate gametes for assisted reproduction", "embryo intended for uterine transfer") with no
|
|
766
|
+
literal "germline"/"heritable" word still fails. Validated against a 30-design adversarial set: 0 evasions,
|
|
767
|
+
0 false positives.
|
|
768
|
+
|
|
769
|
+
### Fixed
|
|
770
|
+
- The Verify page's Legality description claimed it adjudicates "jurisdiction / list-agent / IP", which it does
|
|
771
|
+
not. Corrected to describe the actual legality axis (physical feasibility + germline scope-of-use compliance),
|
|
772
|
+
noting that dual-use hazard is the separate Biosecurity axis.
|
|
773
|
+
|
|
774
|
+
## [7.1.3] - 2026-06-26 - Designer correctness: Guardian biosecurity + calibrated confidence
|
|
775
|
+
|
|
776
|
+
### Fixed
|
|
777
|
+
- **CRITICAL (Designer / Guardian biosecurity):** Hazardous cargo functions (e.g. furin-cleavage viral
|
|
778
|
+
tropism-enhancement, dominant-negative tumor-suppressor ablation) passed the Designer as "Safety: Clear" with
|
|
779
|
+
full survivor tables. Several root causes, all fixed:
|
|
780
|
+
- The hazard registry (`configs/safety/hazard_registry.yaml`) had **no signatures** for engineered viral tropism
|
|
781
|
+
enhancement or oncogenic tumor-suppressor ablation. Added `FUNC-VIRAL-TROPISM-ENHANCE` (furin cleavage /
|
|
782
|
+
receptor-binding / tropism, high severity) and `FUNC-ONCOGENIC-SUPPRESSOR` (dominant-negative TP53 / RB / PTEN,
|
|
783
|
+
apoptosis-checkpoint ablation, high severity), both DURC / HHS-P3CO categories.
|
|
784
|
+
- **Oncogenic-manipulation PATTERN screen** (`oncogenic_manipulation` in the registry +
|
|
785
|
+
`HazardRegistry.oncogenic_flags`): a flat keyword list is brittle to paraphrase; a red-team pass found the
|
|
786
|
+
Guardian caught only **1/8** mechanism/synonym phrasings ("R175H p53 abolishing transactivation", "PTEN
|
|
787
|
+
knockout", "RAS G12D constitutive activation", "hTERT immortalization", "APC frameshift", "EGFR
|
|
788
|
+
ligand-independent activation", "NF1+BAX/BAK knockout"). The pattern screen flags the *combination*
|
|
789
|
+
`(tumor-suppressor + disruptive verb)` OR `(oncogene + activating signature)` OR `immortalization`, which
|
|
790
|
+
catches **8/8** while the deliberate asymmetry spares therapy with **no allow-list**: restoring a suppressor or
|
|
791
|
+
silencing an oncogene matches neither, so "p53 correction to restore apoptosis", "TRAC/CCR5 knockout",
|
|
792
|
+
"knock-down of mutant KRAS" stay clear (**11/11** benign). Disposition is escalate (dual-use → human review).
|
|
793
|
+
- **Keyword matcher hardened** (`_kw_match`): a plain substring test made the ricin abbreviation `"rip"` fire
|
|
794
|
+
inside **"transc-rip-tion"** (a word in almost every editing design → benign cassettes false-refused as ricin),
|
|
795
|
+
and let a hyphenated `"furin-cleavage"` slip past the space-form keyword. Matching is now separator-insensitive
|
|
796
|
+
(`-`/`_`/space unified) and word-boundary anchored, fixing both the false positive and the evasion.
|
|
797
|
+
- The goal-based candidate path (`pen_stack/design/space.py::candidate_space`) **dropped** the goal's
|
|
798
|
+
`cargo_function`, so the Guardian in `verify()` screened nothing. It is now propagated onto every swept
|
|
799
|
+
candidate. The `/generate` endpoint additionally screens the goal's cargo function FIRST and returns an explicit
|
|
800
|
+
biosecurity refusal (`refused: true` + the safety verdict) so an empty table is correctly attributed to a
|
|
801
|
+
refusal, not a silent "no candidates".
|
|
802
|
+
- **CRITICAL (Designer / calibration):** Confidence was a constant `1.00 · [0.56, 0.71]` for every input because the
|
|
803
|
+
page hardcoded fake planner scores (0.7 / 0.6 / 0.5) on each candidate. The page now submits the design GOAL and
|
|
804
|
+
the engine plans real writable sites with grounded per-locus safety / durability / writer-activity, so the
|
|
805
|
+
confidence band is genuinely calibrated (it differs by locus/vehicle, e.g. F9 → `[0.866, 0.972]`, and is absent
|
|
806
|
+
for a refused design). `web/src/pages/Designer.jsx` rewritten to send a goal and render the refused / empty /
|
|
807
|
+
survivor states distinctly.
|
|
808
|
+
- **Designer (cell types without a measured atlas):** a goal in a cell type with no writability atlas (cd8_t /
|
|
809
|
+
pbmc / h1_hesc / ipsc) returned an empty table, because the planner-backed `candidate_space` needs `plan_write`.
|
|
810
|
+
`generate_designs` now falls back to `space.vehicle_sweep(goal)`: it sweeps the capacity-compatible vehicles,
|
|
811
|
+
carries `cargo_function` (the Guardian still screens), runs full legality + biosecurity discrimination, and
|
|
812
|
+
ABSTAINS on the calibrated confidence (no fabricated band), surfaced as "abstained, no measured atlas for this
|
|
813
|
+
cell type". `candidate_space` still returns `[]` without the atlas; `generate_designs(candidates=[])` still
|
|
814
|
+
returns `[]`.
|
|
815
|
+
- **Designer (administration context):** the vehicle sweep now filters by the goal's `in_vivo` flag using the
|
|
816
|
+
curated `in_vivo` / `ex_vivo` route flags in `configs/delivery_vehicles.yaml` (an ex-vivo goal keeps
|
|
817
|
+
lentivirus / electroporation / eVLP; an in-vivo goal keeps AAV / LNP / HDAd / HSV / eVLP). Grounded from the
|
|
818
|
+
curated palette, not a clinical claim; `in_vivo=None` keeps all (existing callers/tests unchanged).
|
|
819
|
+
|
|
820
|
+
## [7.1.2] - 2026-06-25 - Chat response latency fix
|
|
821
|
+
|
|
822
|
+
### Fixed
|
|
823
|
+
- Chat response time was unnecessarily high because every General-lane request paid for an Ollama embedding
|
|
824
|
+
round-trip on the query side, and the LLM call ran with a generous 150 s timeout / 450-token cap suited to the
|
|
825
|
+
engine-grounded design lane, not a textbook answer. Three minimal changes, no behaviour change for the grounded
|
|
826
|
+
lanes:
|
|
827
|
+
- `pen_stack/rag/embed.py` adds an LRU-cached `embed_query()` (256 entries) so a repeated phrasing skips the
|
|
828
|
+
embedder; `pen_stack/rag/retrieve.py` uses it.
|
|
829
|
+
- `pen_stack/web/llm_provider.py` now accepts `kind="general"`, which selects `PEN_STACK_LLM_TIMEOUT_GENERAL`
|
|
830
|
+
(45 s default, was 150 s) and `OLLAMA_NUM_PREDICT_GENERAL` / `NEMOTRON_MAX_TOKENS_GENERAL` (280 / 400, was
|
|
831
|
+
450 / 700). The default-kind path used by the engine-grounded design / explain / meta lanes is unchanged
|
|
832
|
+
(`PEN_STACK_LLM_TIMEOUT` default lowered 150 → 90).
|
|
833
|
+
- The General-lane and RAG cited-answer callers (`pen_stack/rag/ground.py`, `pen_stack/web/llm.py`) now pass
|
|
834
|
+
`kind="general"`.
|
|
835
|
+
- No grounding-guard change; the LLM stays non-load-bearing and the per-lane provenance labels are unchanged.
|
|
836
|
+
|
|
837
|
+
## [7.1.1] - 2026-06-24 - Chat General-lane helpfulness fix + benchmark-validity correction
|
|
838
|
+
|
|
839
|
+
### Fixed
|
|
840
|
+
- The General lane over-abstained: it declined simple/social ("hi") and general-knowledge ("what is DNA")
|
|
841
|
+
questions because P-WS1 made corpus retrieval a GATE on the whole lane. Retrieval is now **additive**
|
|
842
|
+
(`pen_stack/rag/ground.py`): the lane ANSWERS general + social questions, clearly labelled
|
|
843
|
+
"general - not PEN-STACK-verified" (a labelled general answer is not a fabrication); a corpus hit
|
|
844
|
+
upgrades to "literature-cited"; abstention is reserved for a SPECIFIC unsourceable empirical claim. The "general"
|
|
845
|
+
provenance chip is restored in the web chat.
|
|
846
|
+
|
|
847
|
+
### Changed
|
|
848
|
+
- Benchmark-validity correction: the head-to-head headline moves from "answers-without-grounding" (which rewarded
|
|
849
|
+
over-abstention) to the **false-grounding rate** (a non-engine fact presented as a PEN-STACK result; 0.0 by
|
|
850
|
+
construction). Abstention is re-scoped to specific unsourceable empirical claims; the routing/grounding/safety
|
|
851
|
+
sets now include positive general + social cases that require a helpful, labelled answer (a regression guard).
|
|
852
|
+
`prereg/ws_penchat.yaml` amended + re-locked accordingly.
|
|
853
|
+
|
|
854
|
+
## [7.1.0] - 2026-06-24 - The grounded conversational chat system
|
|
855
|
+
|
|
856
|
+
Consolidates the four-lane chat with RAG into a fully-grounded, provenance-partitioned
|
|
857
|
+
conversational agent: every surfaced fact is engine-computed or retrieved-and-cited, no claim originates from
|
|
858
|
+
model weights, and the property is MEASURED, not asserted. The LLM is a swappable, non-load-bearing narrator.
|
|
859
|
+
|
|
860
|
+
### Added
|
|
861
|
+
- **Grounded General lane (RAG)** (`pen_stack/rag/{corpus,embed,retrieve,ground}.py`). The general lane no
|
|
862
|
+
longer answers from unsourced trained knowledge: it retrieves over a provenance-tagged corpus
|
|
863
|
+
(`data/rag_corpus.parquet`, built only from real DOI-backed repo content) with a committed embedding matrix
|
|
864
|
+
(`nomic-embed-text` via Ollama; exact cosine, no FAISS at this scale) and a deterministic lexical fallback,
|
|
865
|
+
answers under citation-or-silence, and **abstains** below a retrieval-confidence threshold. General answers are
|
|
866
|
+
labelled `literature-cited` or `abstained`, never a PEN-STACK-computed result.
|
|
867
|
+
- **Swappable LLM provider abstraction** (`pen_stack/web/llm_provider.py`): one interface over local Ollama / cloud
|
|
868
|
+
Nemotron; the grounded result (lane, provenance, sources, numbers) is invariant to the provider.
|
|
869
|
+
- **Lane + provenance memory**: a follow-up to a grounded answer stays grounded.
|
|
870
|
+
- **Evaluation suite** measuring the no-fabrication claim: `benchmarks/chat_{routing,grounding,safety,headtohead}`
|
|
871
|
+
(routing-safety 0.0, citation coverage 1.0, 0 unsupported claims, false-grounding 0.0, dual-use refusal 1.0,
|
|
872
|
+
injection-hold 1.0). Pre-registered + SHA-locked in `prereg/ws_penchat.yaml`.
|
|
873
|
+
- The chat is registered as a capability (`chat_answer`, `fabricates: False`); provenance / citation / abstention /
|
|
874
|
+
refusal chips in the web chat.
|
|
875
|
+
|
|
876
|
+
### Changed
|
|
877
|
+
- The pre-route biosecurity screen now escalates a build/express intent over any flagged dual-use hazard term even
|
|
878
|
+
when the specific agent is not catalogued; the router was made conservative so a write request never leaks to the
|
|
879
|
+
ungrounded lane.
|
|
880
|
+
|
|
881
|
+
## [7.0.0] - 2026-06-22 - Closed loop: a biosecurity-gated, Level-3 self-driving-lab engine
|
|
882
|
+
|
|
883
|
+
The capstone. Turns the in-silico closed loop into a genome-writing-specific, biosecurity-gated, autonomy-bounded
|
|
884
|
+
(Level 3) self-driving-lab engine: a cloud-lab connector, a benchmark of the experiment designer against the
|
|
885
|
+
public optimizers, and a validation-campaign engine that points active learning at the measurements which would
|
|
886
|
+
earn the program's first outcome-validated axis. It consumes the WriteSpec and pairs with the biosecurity gate.
|
|
887
|
+
Full autonomy is not claimed; the wet run is the named bottleneck.
|
|
888
|
+
|
|
889
|
+
### Added
|
|
890
|
+
- **Cloud-lab connector** (`pen_stack/build/cloudlab.py`). `submit_gated` bridges the build interface to a cloud
|
|
891
|
+
lab. The biosecurity gate runs BEFORE any submission: a flagged or illegal design raises and emits no protocol
|
|
892
|
+
(a ricin design is refused), returning a structured refusal an agent can branch on; a cleared design returns a
|
|
893
|
+
mock / dry-run job receipt. A returned readout is admitted only through an explicit human-in-control gate.
|
|
894
|
+
- **SDL-brain benchmark** (`pen_stack/active/brains.py`). Benchmarks the EIG/VOI experiment designer against the
|
|
895
|
+
public self-driving-lab optimizers BayBE (Apache-2.0) and Atlas on a shared acquisition task, reported verbatim
|
|
896
|
+
with both cited. The designer shows a positive mean information-gain advantage over random whose bootstrap CI is
|
|
897
|
+
rep-sensitive and includes 0 at higher rep counts; reported as not-CI-significant, not hidden.
|
|
898
|
+
- **Validation-campaign engine** (`pen_stack/active/campaign.py`). Orders the candidate
|
|
899
|
+
(cassette x locus x cell type) expression measurements by expected information gain, names the
|
|
900
|
+
`validate.calibrate_axis` gate they would flip, and emits an executable, cloud-lab-submittable campaign spec.
|
|
901
|
+
The campaign measures independent data, never the model's own outputs.
|
|
902
|
+
- **Loop-Bench** (`benchmarks/loop/`) reporting the three gates, and surfaces: REST `GET /api/campaign`,
|
|
903
|
+
`POST /api/cloudlab`, `GET /api/brains`; MCP `validation_campaign`, `cloudlab_submit`; `docs/closed_loop.md`.
|
|
904
|
+
|
|
905
|
+
### Notes
|
|
906
|
+
- The loop is Level 3 (human in control); Level 4-5 is not claimed. The biosecurity gate is necessary, not
|
|
907
|
+
sufficient (the full sequence screen is the downstream BioFirewall).
|
|
908
|
+
- A real wet run, and thus the first outcome-validated axis, needs a cloud-lab partner and budget; the connector
|
|
909
|
+
and the executable campaign are the mechanism, the partner is the bottleneck, surfaced not hidden.
|
|
910
|
+
|
|
911
|
+
## [6.14.0] - 2026-06-22 - WriteSpec: a typed, ontology-backed intent layer with a grounded extractor and a feasibility check
|
|
912
|
+
|
|
913
|
+
Replaces the keyword parser with a typed, machine-checkable genome-writing request (an SBOL3 profile), a grounded
|
|
914
|
+
prose-to-spec extractor that labels every inference and never fabricates intent, and a feasibility check. This is
|
|
915
|
+
the agentic front-end: one contract the whole stack consumes. A WriteSpec is a request, not a claim.
|
|
916
|
+
|
|
917
|
+
### Added
|
|
918
|
+
- **The WriteRequest type** (`pen_stack/spec/writespec.py`, `schemas/writespec.json`). A typed model carrying the
|
|
919
|
+
write semantics (write-type, cargo with Sequence-Ontology roles, target gene/locus/att-site/phenotype, cell
|
|
920
|
+
type, constraints) plus a per-field provenance map (explicit / inferred / user / unresolved). Lossless JSON
|
|
921
|
+
round-trip; SBOL3 round-trip via the real `sbol3` library (the `[spec]` extra; native Components + SO roles for
|
|
922
|
+
interoperability); GenBank export for a cargo with a sequence; and `to_legacy_design`, the adapter that lets
|
|
923
|
+
every existing stage consume a WriteRequest without a rewrite.
|
|
924
|
+
- **Vocabulary resolvers** (`pen_stack/spec/resolvers/`). Free text to canonical id: HGNC genes (atlas-grounded),
|
|
925
|
+
Cellosaurus / Cell Ontology cell types, Sequence Ontology feature roles, MONDO phenotypes, ChEBI molecules,
|
|
926
|
+
GRCh38 coordinates. Every curated id was verified against the live ontology services before commit; an
|
|
927
|
+
unresolved term stays null, never invented.
|
|
928
|
+
- **Grounded extractor + clarifying-question planner** (`pen_stack/spec/extract.py`, `clarify.py`). A
|
|
929
|
+
deterministic backbone (so the benchmark is reproducible) that labels every inferred field, asks a clarifying
|
|
930
|
+
question for anything underspecified or ambiguous, and keeps unresolved terms null.
|
|
931
|
+
- **Feasibility check** (`pen_stack/spec/satisfy.py`). Wraps reachability (the atlas), deliverability (the
|
|
932
|
+
delivery recommender), and legality (the verification proof object) into feasible / infeasible plus named
|
|
933
|
+
blocking constraints and repair hints; feasibility is necessary, not sufficient (not efficacy).
|
|
934
|
+
- **WriteSpec-Bench** (`benchmarks/writespec/`). The first prose-to-write-spec corpus, grounded in real
|
|
935
|
+
experiments, with an ambiguity subset and a sealed held-out. Reported verbatim: sealed-test structural fidelity
|
|
936
|
+
1.0 and value accuracy 0.96 versus a 0.46 keyword-dict baseline; inferred-field labelling recall 1.0.
|
|
937
|
+
- **Surfaces**: REST `POST /api/writespec`, MCP `writespec_parse`, the manifest tool, the web "Describe a Write"
|
|
938
|
+
builder page, and `docs/writespec_profile.md` + `docs/writespec_bench.md`.
|
|
939
|
+
|
|
940
|
+
### Notes
|
|
941
|
+
- Feasibility rules out unreachable / undeliverable / illegal, not whether the write will work.
|
|
942
|
+
- The extractor backbone is deterministic; an LLM pass is optional and adds no ground truth (it may only propose
|
|
943
|
+
values that still pass the resolvers).
|
|
944
|
+
|
|
945
|
+
## [6.13.0] - 2026-06-22 - Oracle mesh: binding-affinity dimension, per-oracle reliability, disagreement-to-uncertainty
|
|
946
|
+
|
|
947
|
+
Hardens the foundation-model oracle mesh under one result contract. Adds a binding-affinity dimension
|
|
948
|
+
(Boltz-2), surfaces each oracle's published reliability reported verbatim from public benchmarks, and makes
|
|
949
|
+
cross-oracle disagreement widen the reported interval. Every oracle output stays a candidate, never ground
|
|
950
|
+
truth.
|
|
951
|
+
|
|
952
|
+
### Added
|
|
953
|
+
- **Binding-affinity oracle** (`pen_stack/oracles/affinity.py`). Wraps the Boltz-2 protein-ligand affinity head
|
|
954
|
+
(MIT, `10.1101/2025.06.14.659707`): a binder probability and a predicted affinity value with native
|
|
955
|
+
uncertainty taken from the model's own outputs. The head is protein-small-molecule only, so protein-protein
|
|
956
|
+
and protein-DNA pairs are returned as out-of-scope (extrapolating). The backend runs off the request path and
|
|
957
|
+
is cached; an uncached request defers (cache-or-abstain) rather than blocking or fabricating. A grounded,
|
|
958
|
+
in-domain example is committed: 4-hydroxytamoxifen binding the ERT2 ligand-binding domain (the inducible-writer
|
|
959
|
+
switch), predicted as a high-confidence binder (binder probability 0.99, complex pLDDT 0.94).
|
|
960
|
+
- **Per-oracle reliability registry** (`pen_stack/oracles/reliability.py`, `configs/oracles/reliability.yaml`).
|
|
961
|
+
Each oracle's published benchmark accuracy, reported verbatim with citation: the Boltz-2 affinity head's
|
|
962
|
+
FEP+ Pearson r of about 0.62 (paper-reported) is the verified anchor. These are the wrapped models' published
|
|
963
|
+
numbers, not a claim about this stack's accuracy and not re-computed; where a verbatim score was not verified
|
|
964
|
+
the value is left null with the cited benchmark as the pointer.
|
|
965
|
+
- **Disagreement to uncertainty.** Cross-oracle disagreement widens the reported interval (native uncertainty
|
|
966
|
+
plus half the cross-oracle spread); a check confirms the widening is monotonic in the spread.
|
|
967
|
+
- **Held-oracle runner** (`pen_stack/oracles/structure_run.py`) for the structure oracles over writer-substrate
|
|
968
|
+
and att-site complexes: off the request path, cache-or-abstain.
|
|
969
|
+
- **Oracle-Bench** (`benchmarks/oracle/`) reporting the three gates, and surfaces: `GET /api/oracles` extended
|
|
970
|
+
with reliability and the disagreement check, `POST /api/oracle/affinity`, MCP `oracle_query`, the manifest
|
|
971
|
+
`oracle_query` tool, the web Oracle Mesh page, and `docs/oracle_mesh.md`.
|
|
972
|
+
|
|
973
|
+
### Notes
|
|
974
|
+
- Affinity predictions are candidates with native uncertainty, not measured binding constants; reliability is
|
|
975
|
+
surfaced so a confident-looking value is not over-trusted.
|
|
976
|
+
- The structure oracles over full complexes (AlphaFold3 / Boltz-2 / Chai-1 / Protenix) remain held: run
|
|
977
|
+
separately on GPU or cloud and cached, never inline on the request path.
|
|
978
|
+
|
|
979
|
+
## [6.12.0] - 2026-06-21 - Verification service: published rule spec, proof object, standards-aligned biosecurity
|
|
980
|
+
|
|
981
|
+
Hardens `verify(design)` into a formal verification service. The rule base becomes a published, citable spec;
|
|
982
|
+
`verify_proof()` returns a repair-oriented proof object an agent can fix a failed design from; and the
|
|
983
|
+
biosecurity gate is mapped to the community synthesis-screening standards.
|
|
984
|
+
|
|
985
|
+
### Added
|
|
986
|
+
- **Published rule spec** (`pen_stack/rules/spec.py`, `benchmarks/verify/rule_spec.json`, `docs/rule_spec.md`).
|
|
987
|
+
The rule base exports as a machine-readable, citable document. A parity check confirms the exported spec
|
|
988
|
+
round-trips to the exact ruleset the solver loads (0 mismatches), every rule names a registered evaluator,
|
|
989
|
+
and every rule carries a DOI or a note.
|
|
990
|
+
- **Repair-oriented proof object** (`pen_stack/verify/proof.py`). `verify_proof(design)` returns three axes,
|
|
991
|
+
legality, confidence and biosecurity, reported separately, each with a status, the rule or signature that
|
|
992
|
+
fired, evidence, and a repair hint; the collapsed verdict is `None`. `repair_from_proof` fixes a
|
|
993
|
+
failed-on-legality design using only the proof object and re-verifies it. Biosecurity hazards are
|
|
994
|
+
acknowledged and routed to human review, never auto-repaired.
|
|
995
|
+
- **Biosecurity standards alignment** (`pen_stack/safety/standards.py`). Maps the Guardian screen kinds and
|
|
996
|
+
decisions onto the IBBIS Common Mechanism categories and `ScreenStatus` (Pass / Warning / Flag) and onto
|
|
997
|
+
SecureDNA's pass/deny outcome, with a concordance report (8/8 concordant on the labelled probe set).
|
|
998
|
+
References: Common Mechanism (Wheeler et al. 2024, `10.1089/apb.2023.0034`); SecureDNA (`arXiv:2403.14023`).
|
|
999
|
+
- **Verify-Bench** (`benchmarks/verify/`) reporting the three gates, and surfaces: REST `POST /api/verify/proof`,
|
|
1000
|
+
MCP `verify_proof`, manifest tool `verify_proof`, the web Verify page (per-axis green/amber/red with the
|
|
1001
|
+
violated rule, its citation, and the suggested fix), and `docs/verify_service.md`.
|
|
1002
|
+
|
|
1003
|
+
### Notes
|
|
1004
|
+
- The verdict covers legality, feasibility and biosecurity, not efficacy (efficacy stays a downstream
|
|
1005
|
+
prediction with its own uncertainty). The biosecurity hook is the in-design gate; the full sequence-screening
|
|
1006
|
+
pipeline is BioFirewall, and the standard alignment is a concordance, not a certification.
|
|
1007
|
+
|
|
1008
|
+
## [6.11.0] - 2026-06-20 - Cross-modality deliverability and a learned capsid-fitness model
|
|
1009
|
+
|
|
1010
|
+
Delivery moves from an 8-vehicle rule palette to a cross-modality recommender. It adds a learned,
|
|
1011
|
+
benchmarked AAV capsid-fitness model, a serotype-to-tissue tropism prior grounded in approved therapies, and an
|
|
1012
|
+
immune-coupled dose tradeoff, without fabricating tropism. All datasets were independently verified.
|
|
1013
|
+
|
|
1014
|
+
### Added
|
|
1015
|
+
- **Learned AAV capsid-fitness on FLIP-AAV** (`pen_stack/planner/delivery_predict.py`, `scripts/build_capsid_fitness.py`,
|
|
1016
|
+
`benchmarks/delivery/`). Trained on the FLIP-AAV benchmark (Dallago 2021; Bryant 2021 packaging fitness,
|
|
1017
|
+
`10.1038/s41587-020-00793-4`; Ogden 2019 `10.1126/science.aaw2900`). It beats a mutation-burden baseline on
|
|
1018
|
+
both held-out splits: `sampled` Spearman 0.920 vs 0.522 (CI [0.387, 0.411]); `mut_des`
|
|
1019
|
+
(mutant to designed) 0.814 vs 0.752 (CI [0.061, 0.064]). The 217 MB/split FLIP data stays on the VM; the derived
|
|
1020
|
+
metrics and the reproducible build script are committed. The ~3 MB model itself is gitignored, regenerated via
|
|
1021
|
+
`scripts/build_capsid_fitness.py` and mounted into the deployed app (like `position_effect.pkl`); the axis abstains
|
|
1022
|
+
gracefully when absent. Predicted fitness is a candidate for the measured packaging axis, not in-vivo tropism.
|
|
1023
|
+
- **Serotype-to-tissue tropism priors** (`configs/aav_serotype_tropism.yaml`) from approved AAV therapies (AAV9 to CNS,
|
|
1024
|
+
AAVrh74 to skeletal muscle vs AAVRh74var to liver: different capsids, kept separate; AAV5 to liver; AAV2 to retina/
|
|
1025
|
+
putamen via local injection). This is a grounded prior for an approved serotype and a known-unknown (abstain) for a novel
|
|
1026
|
+
capsid. Casgevy/Lyfgenia carry no serotype prior (not-AAV controls).
|
|
1027
|
+
- **Immune-coupled dose tradeoff** (`pen_stack/planner/delivery_immune.py`) fuses deliverability with the
|
|
1028
|
+
immune profile and surfaces dose vs immunogenicity per vehicle as a vector (`collapsed_score=None`, never fused).
|
|
1029
|
+
- **Verify-gated generative capsids** (`pen_stack/design/capsid_generate.py`): fitness-filtered VP1 variants,
|
|
1030
|
+
candidates only; abstains without the model.
|
|
1031
|
+
- **Surfaces:** REST `POST /delivery`, `POST /capsid_fitness`, and `GET /delivery/tropism`; MCP `delivery_recommend`;
|
|
1032
|
+
manifest `recommend_delivery` and `capsid_fitness`; a `capsid_fitness` scope card; a `delivery` Challenge task
|
|
1033
|
+
(serotype to tissue); preregistration `ws_delivery.yaml`.
|
|
1034
|
+
|
|
1035
|
+
### Limitations
|
|
1036
|
+
- The capsid-fitness model is a one-hot gradient-boosting model, not a protein-LM (it passes the gate; a protein-LM is
|
|
1037
|
+
the upgrade path). Capsid-fitness covers AAV only (VLP/LNP data is thinner). In-vivo human tropism is
|
|
1038
|
+
a known-unknown except for the approved-therapy priors; novel capsids abstain on tropism. alpha-retro-VLP is exploratory.
|
|
1039
|
+
|
|
1040
|
+
## [6.10.4] - 2026-06-20 - Chromatin incremental-value test (annotation, not a re-ranker)
|
|
1041
|
+
|
|
1042
|
+
This patch closes out the chromatin work. v6.10.3 validated accessibility as a moderate standalone
|
|
1043
|
+
predictor; v6.10.4 tests whether it adds incremental value on top of the CRISOT sequence score, i.e. whether
|
|
1044
|
+
it should re-rank.
|
|
1045
|
+
|
|
1046
|
+
### Added
|
|
1047
|
+
- **Incremental-value analysis** (`scripts/offtarget_chromatin_incremental.py`; result in
|
|
1048
|
+
`benchmarks/offtarget/chromatin_incremental.json`). On GUIDE-seq (HEK293T-matched), per off-target CRISOT plus
|
|
1049
|
+
accessibility: (A) a conditional logistic regression `active ~ z(CRISOT) + z(accessibility)` and (B) a
|
|
1050
|
+
leave-one-guide-out held-out AUPRC of CRISOT-only vs a CRISOT+accessibility combiner, tested at two candidate
|
|
1051
|
+
imbalances (1:16 and a realistic 1:123). Result: accessibility carries a small, real conditional signal
|
|
1052
|
+
(coef ~0.35, bootstrap CI excludes 0 at both imbalances) but adds no held-out ranking improvement over CRISOT
|
|
1053
|
+
(AUPRC gap CI includes 0 at both: -0.0025 [-0.011, +0.005] and +0.0027 [-0.014, +0.021]).
|
|
1054
|
+
|
|
1055
|
+
### Decision
|
|
1056
|
+
- Chromatin is a validated annotation, not a re-ranker. The CRISOT sequence score already captures the
|
|
1057
|
+
practically-relevant nomination ranking; a CRISOT+accessibility combiner does not improve held-out AUPRC, so it is
|
|
1058
|
+
not wired into the numeric risk score (`CHROMATIN_VALIDATION.changes_numeric_risk_score = False`). The fitted
|
|
1059
|
+
combiner coefficients are recorded but intentionally not applied. Ledger and docs updated.
|
|
1060
|
+
- This completes the chromatin context work (v6.10.1 wired it, v6.10.2 cross-cell weak, v6.10.3 cell-type-matched
|
|
1061
|
+
validated moderate, v6.10.4 incremental tested, annotation-only). Nothing about chromatin remains open or
|
|
1062
|
+
undisclosed.
|
|
1063
|
+
|
|
1064
|
+
## [6.10.3] - 2026-06-20 - Chromatin context: cell-type-matched validation (validated, moderate)
|
|
1065
|
+
|
|
1066
|
+
This patch settles the chromatin test. v6.10.2's controlled experiment was ambiguous (GUIDE-seq positive, TTISS
|
|
1067
|
+
reversed) on a cross-cell-type K562 proxy; v6.10.3 re-runs it with a cell-type-matched track.
|
|
1068
|
+
|
|
1069
|
+
### Added / changed
|
|
1070
|
+
- **Cell-type-matched validation** (`scripts/offtarget_chromatin_matched.py`; result in
|
|
1071
|
+
`benchmarks/offtarget/chromatin_validation.json` phase2). Downloaded the matched ENCODE HEK293T DNase-seq track
|
|
1072
|
+
(`ENCFF529BOG`; HEK293T matches GUIDE-seq's HEK293 and TTISS's HEK293T), queried it at each off-target's 1 kb bin
|
|
1073
|
+
(pyBigWig), and recomputed the AUROC. Cell-type matching lifts the canonical WT-Cas9 cell-based assay GUIDE-seq
|
|
1074
|
+
from AUROC 0.58 (cross-cell K562) to 0.671 (matched, CI [0.642, 0.701]); the in-vitro negative control stays null
|
|
1075
|
+
(0.494). The cross-cell proxy was dampening a real effect.
|
|
1076
|
+
- Verdict: chromatin is validated (moderate, cell-type-matched) for WT-Cas9 cell-based off-target activity
|
|
1077
|
+
(`offtarget_data.CHROMATIN_VALIDATION` now `validated=True`, `effect="moderate"`). The caveats, all in-code and
|
|
1078
|
+
in the docs: the effect is moderate (the sequence/CRISOT score still dominates nomination); it does not
|
|
1079
|
+
transfer to TTISS (0.383, the expected outlier, a Cas9-variant specificity assay driven by variant fidelity, not
|
|
1080
|
+
WT chromatin); and chromatin is still surfaced as a validated annotation that does not yet change the numeric
|
|
1081
|
+
risk score (a calibrated CRISOT+accessibility combination is the remaining, deferred refinement).
|
|
1082
|
+
- Reclassified the chromatin axis from "weak/inconsistent" to "validated (moderate, cell-type-matched)" with the
|
|
1083
|
+
matched evidence and the caveats.
|
|
1084
|
+
|
|
1085
|
+
## [6.10.2] - 2026-06-20 - Chromatin context: controlled validation (weak/inconsistent result)
|
|
1086
|
+
|
|
1087
|
+
This patch validates the chromatin axis, then scopes it to what the data supports. v6.10.1 wired a real
|
|
1088
|
+
accessibility read but had not demonstrated it carries signal. v6.10.2 runs a controlled experiment and
|
|
1089
|
+
reports the result: it is not a clean win.
|
|
1090
|
+
|
|
1091
|
+
### Added
|
|
1092
|
+
- **A controlled chromatin validation** (`benchmarks/offtarget/chromatin_validation.json`,
|
|
1093
|
+
`scripts/offtarget_chromatin_validation.py`). Off-target protospacers mapped to hg38 (GRCh38.fa, exact match both
|
|
1094
|
+
strands, 98.5% mapped); AUROC of the K562 ATAC/DNase accessibility for active-vs-inactive off-targets per
|
|
1095
|
+
assay, with in-vitro assays as a negative control (cell-free, so no chromatin). Result: the in-vitro controls hug
|
|
1096
|
+
0.5 (method sound, no spurious signal); the canonical cell-based assay GUIDE-seq is a textbook modest positive
|
|
1097
|
+
(AUROC 0.58, CI [0.550, 0.613]) even with a cross-cell-type K562 proxy; but the second cell-based assay TTISS
|
|
1098
|
+
reverses (0.346). Verdict: weak and inconsistent, chromatin is not a validated quantitative axis on this data
|
|
1099
|
+
(the cross-cell-type proxy is the likely cause; a cell-type-matched accessibility track would settle it, deferred).
|
|
1100
|
+
|
|
1101
|
+
### Changed
|
|
1102
|
+
- The chromatin-accessibility modifier is now an explicit annotation only, labelled `validated=false`: it reads
|
|
1103
|
+
the real accessibility track (or a caller-supplied scalar) and notes the qualitative Lazzarotto-2020 direction, but it
|
|
1104
|
+
does not change the numeric off-target risk score. `offtarget_data.CHROMATIN_VALIDATION` carries the result.
|
|
1105
|
+
- Corrected the v6.10.1 entry that had marked chromatin "FIXED"; that was too strong. It is now recorded as
|
|
1106
|
+
tested, weak/inconsistent, documented annotation, not a validated axis.
|
|
1107
|
+
|
|
1108
|
+
This is a negative result reported in full.
|
|
1109
|
+
|
|
1110
|
+
## [6.10.1] - 2026-06-20 - Off-target rigor pass and retroactive audit (v6.7-v6.9)
|
|
1111
|
+
|
|
1112
|
+
This patch closes the v6.10.0 gaps, re-audits v6.7/v6.8/v6.9, and corrects the findings. No item is reported
|
|
1113
|
+
complete if it is a silent substitution, partial, or deferral.
|
|
1114
|
+
|
|
1115
|
+
### Added / changed
|
|
1116
|
+
- **Off-Target-Bench expanded to four unbiased assays.** Added CHANGE-seq (Lazzarotto 2020, `10.1038/s41587-020-0555-7`)
|
|
1117
|
+
and SITE-seq (Cameron 2017, `10.1038/nmeth.4284`) on independent broad guide panels (20 and 11 guides). The real
|
|
1118
|
+
CRISOT-Score (MD-physics, assay-agnostic so leakage-clean) beats the homology baseline on all four:
|
|
1119
|
+
AUPRC 0.646/0.520/0.541/0.521 vs 0.467/0.266/0.249/0.233; per-guide bootstrap CI excludes 0 on each.
|
|
1120
|
+
- **Chromatin wired to the real accessibility track and relabelled.** `locus_accessibility(chrom, bin, ct)` reads
|
|
1121
|
+
`phase_1/features/chromatin_{ct}.parquet` (ATAC/DNase) when present and abstains otherwise; the docs now say
|
|
1122
|
+
"chromatin-accessibility modifier" (not "chromatin-aware engine"), since the bare wheel and the deployed atlas do not ship the
|
|
1123
|
+
raw track, so the modifier is inactive there.
|
|
1124
|
+
- **Off-target task added to the Genome-Writing Challenge** (`benchmarks/genome_writing_challenge/harness.py`):
|
|
1125
|
+
non-circular (label = wet-lab Active call), data-gated on the fixture; the reference solver nominates correctly.
|
|
1126
|
+
- **Substitutions:** CRISOT is used instead of the plan-named CCLMoff/CRISMER (CRISMER ships no license;
|
|
1127
|
+
CCLMoff is GPU and trained on these assays, so it leaks; CRISOT is the leakage-clean, license-clean, CPU choice). A
|
|
1128
|
+
genomic-coordinate locus split is not possible (harmonized data is coordinate-free), so held-out-guide and cross-assay are used.
|
|
1129
|
+
|
|
1130
|
+
### Fixed (retroactive audit)
|
|
1131
|
+
- **v6.9:** dropped the inaccurate "OOD-gated" claim in the MHC-II axis status (it is coverage-gated, abstains
|
|
1132
|
+
when uncached, with no distributional OOD gate); corrected the stale `AXIS_STATUS["mhc2_writer"].reason` and the
|
|
1133
|
+
`immune_mhc2.py` module docstring (they still described the dropped v6.9.0 P1-anchor proxy as "the method"; the
|
|
1134
|
+
production axis is the real NetMHCIIpan-4.0). The plan-named MHC-II tool ensemble and the IEDB/ImmunoSeq/FVIII
|
|
1135
|
+
ADA datasets were not used (single-tool NetMHCIIpan-4.0; the recovery bench is a 4-protein sanity check, not an
|
|
1136
|
+
IEDB held-out leaderboard); the 6.9.1 to 6.9.2 MHC-II metric changed from peptide-fraction to residue-coverage.
|
|
1137
|
+
- **v6.8:** v6.8.0's attB was a poly-G/C schematic (replaced with the real Bxb1 attB in v6.9.2);
|
|
1138
|
+
inter-curator agreement is N/A (single contributor); "at least 1 external submission" is unmet (forward-looking).
|
|
1139
|
+
- **v6.7:** corrected the "chromosome-Mondrian" served-interval wording (per-chromosome Mondrian qhats are computed,
|
|
1140
|
+
but the global qhat is served, which is correct since a query has no chromosome at serve time); recorded the prereg
|
|
1141
|
+
consolidation and the deferred HEK293T-OOD demo / scope-manifest entry.
|
|
1142
|
+
|
|
1143
|
+
## [6.10.0] - 2026-06-20 - Cross-writer-family off-target nomination
|
|
1144
|
+
|
|
1145
|
+
Off-target moves from a single-family bridge pseudosite scan to a cross-writer-family,
|
|
1146
|
+
chromatin-aware nomination engine grounded in unbiased genome-wide assays, completing the safety triad
|
|
1147
|
+
(site B, writer C, off-target E). Nomination is framed as not a clearance: every candidate
|
|
1148
|
+
ships with the empirical assay that would confirm it.
|
|
1149
|
+
|
|
1150
|
+
### Added
|
|
1151
|
+
- **Off-Target-Bench** (`benchmarks/offtarget/`): a real, leakage-controlled nomination benchmark over canonical
|
|
1152
|
+
Cas9 guides (EMX1/VEGFA1-3/FANCF/HEK293) with experimentally validated off-targets from GUIDE-seq
|
|
1153
|
+
(Tsai 2015, `10.1038/nbt.3117`) and CIRCLE-seq (Tsai 2017, `10.1038/nmeth.4278`). Held-out-guide split, per-assay
|
|
1154
|
+
provenance, SHA256SUMS. On real data with a real tool, the licensed CRISOT-Score predictor
|
|
1155
|
+
(Chen et al., Nat Commun 2023, `10.1038/s41467-023-42695-4`; XGBoost RNA-DNA fingerprint) beats the sequence-
|
|
1156
|
+
homology baseline: GUIDE-seq AUPRC 0.646 vs 0.467 (gap +0.179, CI [0.015, 0.340]); CIRCLE-seq 0.520 vs
|
|
1157
|
+
0.266 (gap +0.253, CI [0.140, 0.361]); per-guide bootstrap CI excludes 0 on both assays.
|
|
1158
|
+
- `pen_stack/wgenome/offtarget_data.py`: validated assay/predictor provenance, a grounded mismatch-to-active-fraction
|
|
1159
|
+
risk calibration (real-data: GUIDE-seq 0-1mm to 100% active, 2mm to 76%, 3mm to 23%, 4mm to 3.3%), the bench fixture loader.
|
|
1160
|
+
- `pen_stack/wgenome/offtarget_predict.py`: `nominate_offtargets(writer_family, ...)`. Nuclease (mismatch-
|
|
1161
|
+
calibrated risk band plus the real cached CRISOT score plus a documented chromatin modifier, Lazzarotto 2020);
|
|
1162
|
+
serine integrase (cryptic pseudo-attB scan on the real documented Bxb1 attB core GCGGTCTC/GT);
|
|
1163
|
+
bridge (delegates to the existing Perry-DMS pseudosite engine). Abstains without inputs; never fabricates sites.
|
|
1164
|
+
- `pen_stack/wgenome/offtarget_assay.py`: validation-assay recommender (GUIDE/CHANGE/CIRCLE-seq for nucleases;
|
|
1165
|
+
Cryptic-seq/HIDE-seq for integrases; a documented gap for bridge recombinases, since no published genome-wide
|
|
1166
|
+
unbiased off-target assay or predictor exists, verified).
|
|
1167
|
+
- **Surfaces:** REST `POST /offtarget` and `GET /offtarget/assay`; MCP `offtarget_scan`; manifest `nominate_offtargets`
|
|
1168
|
+
(fabricates=False); an `offtarget_nomination` scope card; and a web Off-Target page.
|
|
1169
|
+
|
|
1170
|
+
### Limitations
|
|
1171
|
+
- Nomination is not a clearance; genome-wide candidate enumeration needs the on-VM Cas-OFFinder/genome scan (this
|
|
1172
|
+
engine scores, ranks, and risk-bands supplied candidates). The CRISOT predictor is CC-BY-NC: it runs only on the
|
|
1173
|
+
VM and its weights are never redistributed; only derived scores are cached (CI-safe). Bridge/integrase off-target
|
|
1174
|
+
is data-thin and unmodeled and is flagged extrapolative; IntQuery (Tome Biosciences) is a paper-only reference.
|
|
1175
|
+
|
|
1176
|
+
## [6.9.2] - 2026-06-19 - Real-tool rigor pass across the immune and writer axes (no proxies, no heuristics)
|
|
1177
|
+
|
|
1178
|
+
A top-to-bottom audit replaces every remaining proxy/heuristic in the immune and writer-design stack with
|
|
1179
|
+
the real on-VM tool (gold-standard, licensed) or an abstention. No silent fallbacks. All licensed binaries stay on
|
|
1180
|
+
the VM; only derived numbers are cached.
|
|
1181
|
+
|
|
1182
|
+
### Changed
|
|
1183
|
+
- **MHC-I capsid axis re-grounded on NetMHCpan-4.1** (`pen_stack/planner/capsid_epitope_oracle.py`). The primary
|
|
1184
|
+
capsid CD8 predictor is now the gold-standard licensed NetMHCpan-4.1 (%Rank_EL<=0.5, residue coverage, 12-allele
|
|
1185
|
+
panel; `configs/mhc_epitope_oracle.yaml` `mhc1`); the v5.3 MHCflurry value is kept as an explicit, reported
|
|
1186
|
+
cross-check (never silently substituted). Both agree AAV is the least CD8-immunogenic capsid
|
|
1187
|
+
(AAV `capsid_immune_score` 0.4585 NetMHCpan / 0.2803 MHCflurry; the predictor disagreement is surfaced, not hidden).
|
|
1188
|
+
- **ADA-risk re-grounded** (`pen_stack/planner/ada_risk.py`). `ada_risk = real NetMHCIIpan-4.0 density x foreignness`,
|
|
1189
|
+
where foreignness is the protein origin (the authoritative central-tolerance signal). Unknown origin or uncached
|
|
1190
|
+
density now abstains (no k-mer guess, no heuristic), replacing the v6.9.0 albumin-only self-tolerance
|
|
1191
|
+
heuristic. The real human-proteome 9-mer self-match (computed on the VM over the full UniProt reference
|
|
1192
|
+
proteome, 20,431 proteins / 10.4 M 9-mers) is reported as a cross-check: human albumin 1.0 (self), the
|
|
1193
|
+
foreign writers (SpCas9/ISCro4/Bxb1) and capsids 0.0 (non-self), a clean self/non-self separation.
|
|
1194
|
+
- **MHC-II axis no longer falls back to a production proxy** (`pen_stack/planner/immune_mhc2.py`). `mhc2_epitope_load`
|
|
1195
|
+
uses the real NetMHCIIpan-4.0 cache by antigen name and otherwise abstains; the documented promiscuous-binder
|
|
1196
|
+
estimate is retained as `mhc2_proxy_estimate` for offline triage only (explicitly labelled, not the production axis).
|
|
1197
|
+
- **Real Bxb1 attB written** (`pen_stack/atlas/guide_design.py`). The PASTE/PASSIGE pegRNA 3' extension now writes the
|
|
1198
|
+
real documented Bxb1 minimal attB verbatim (FlyBase FBto0000359; Ghosh, Kim & Hatfull, Mol Cell 2003;
|
|
1199
|
+
8-bp common core GCGGTCTC around the central GT crossover) instead of the schematic poly-G/poly-C arms. Integrases
|
|
1200
|
+
without a bundled documented site expose only the central core (never a fabricated full sequence).
|
|
1201
|
+
- `pen_stack/planner/immune_profile.py`: the writer-as-antigen card surfaces `foreignness`, the real
|
|
1202
|
+
`self_match_human_proteome` cross-check, and the MHC-II/ADA backends (this replaces the removed `self_tolerance` field).
|
|
1203
|
+
|
|
1204
|
+
### Deviations from the v6.9 pre-registration (`prereg/ws_immune2.yaml`)
|
|
1205
|
+
- The pre-registered "1 - self_match_fraction from a human-proteome k-mer filter" foreignness fallback is
|
|
1206
|
+
dropped: foreignness is the authoritative origin, and an unknown origin abstains rather than imputing from a
|
|
1207
|
+
k-mer match (the real self-match is reported only as a cross-check). This is a stricter rule.
|
|
1208
|
+
|
|
1209
|
+
### Data / tests
|
|
1210
|
+
- `configs/mhc_epitope_oracle.yaml`: corrected `self_match` (the v6.9.x cache had a FASTA-keying bug that collapsed
|
|
1211
|
+
the 20,431-protein proteome to 1 protein, zeroing every self-match including albumin); recomputed correctly on the VM.
|
|
1212
|
+
- `tests/unit/{test_ws_immune2,test_ws_epitope,test_ws_writer,test_ws_rel}.py` updated for the abstain semantics,
|
|
1213
|
+
the NetMHCpan-4.1 primary capsid value plus MHCflurry cross-check, the real attB, and the 6.9.2 version pins.
|
|
1214
|
+
|
|
1215
|
+
## [6.9.1] - 2026-06-20 - Real NetMHCIIpan-4.0 / NetMHCpan-4.1 MHC epitope load (replaces the v6.9.0 proxy)
|
|
1216
|
+
|
|
1217
|
+
This patch is a rigour upgrade. v6.9.0's MHC-II axis was a documented heuristic proxy (P1-anchor density). The
|
|
1218
|
+
gold-standard licensed predictors were already on the VM, so v6.9.1 computes the MHC-II epitope load with real
|
|
1219
|
+
NetMHCIIpan-4.0 (and MHC-I with NetMHCpan-4.1) over a frequent HLA panel, and re-grounds the axis on the real
|
|
1220
|
+
values. The licensed binaries are never committed or distributed; only the derived fractions are
|
|
1221
|
+
cached (`configs/mhc_epitope_oracle.yaml`), exactly like the v5.3 MHCflurry cache.
|
|
1222
|
+
|
|
1223
|
+
### Changed
|
|
1224
|
+
- `pen_stack/planner/immune_mhc2.py`: `mhc2_epitope_load(seq, name)` now uses the real NetMHCIIpan-4.0 EL
|
|
1225
|
+
%Rank<=2 cache (over 7 frequent HLA-II alleles) when the antigen is cached; the documented promiscuous-binder
|
|
1226
|
+
proxy remains only as the offline/CI fallback for uncached sequences. `real_mhc2_load(name)` exposes the cache.
|
|
1227
|
+
- `ada_risk`, `immune_profile` (writer-as-antigen), and `benchmarks/immuno` thread the antigen name to real values.
|
|
1228
|
+
- `configs/mhc_epitope_oracle.yaml` (committed): derived epitope fractions for the writer and capsid antigens.
|
|
1229
|
+
|
|
1230
|
+
### Result (the real tool is more discriminating than the proxy)
|
|
1231
|
+
- Real NetMHCIIpan-4.0 strong-binder fraction: SpCas9 0.153, Bxb1 0.152, ISCro4 0.112, AAV2 0.114 vs
|
|
1232
|
+
human albumin (self) 0.066, the lowest. The gold-standard tool shows the self protein has a genuinely lower
|
|
1233
|
+
MHC-II load and the foreign writers higher, a signal the heuristic proxy flattened (~0.08-0.10 for all). The
|
|
1234
|
+
immunogenic-vs-tolerated recovery is unchanged (foreign well above self) but now on real predictions.
|
|
1235
|
+
|
|
1236
|
+
### How it ran (no host install; per the VM Docker rule)
|
|
1237
|
+
- `penmhc:tools` (debian + tcsh + gawk + perl) with `~/netmhc` (the licensed tools) mounted, NMHOME fixed at
|
|
1238
|
+
runtime; `scratch/v691_mhc_compute.py` runs both predictors and writes the derived cache. The axis stays a
|
|
1239
|
+
population-level proxy (frequent-HLA panel, not a patient-HLA magnitude, a known-unknown).
|
|
1240
|
+
|
|
1241
|
+
## [6.9.0] - 2026-06-20 - Immune profile: MHC-II/CD4, ADA, and writer-as-antigen
|
|
1242
|
+
|
|
1243
|
+
This minor feature release extends the immune profile from CD8/MHC-I-only to a full T-cell profile: MHC-I plus
|
|
1244
|
+
MHC-II/CD4 plus ADA risk with self-tolerance filtering, scored over the writer enzyme as a distinct antigen,
|
|
1245
|
+
still population-level, OOD-gated, and never collapsed. It wraps the v5.6 unified profile. No fabrication: real
|
|
1246
|
+
UniProt sequences, a grounded documented method, proxy-labelled axes.
|
|
1247
|
+
|
|
1248
|
+
### Added: the MHC-II and ADA axes
|
|
1249
|
+
- `pen_stack/planner/immune_mhc2.py`: a grounded, dependency-free promiscuous MHC-II binder density (documented
|
|
1250
|
+
P1 hydrophobic anchor, Stern & Wiley 1994; secondary pockets, Southwood 1998) over capsid and writer sequences plus
|
|
1251
|
+
the bundled real writer/control FASTA. `configs/writer_sequences.fasta`: real UniProt for SpCas9 (Q99ZW2), ISCro4
|
|
1252
|
+
bridge recombinase (D2TGM5), Bxb1 integrase (Q9B086), human albumin self control (P02768).
|
|
1253
|
+
- `pen_stack/planner/ada_risk.py`: ADA-risk = MHC-II epitope density x foreignness with a JanusMatrix-style
|
|
1254
|
+
self-tolerance filter (origin authoritative; human-proteome k-mer filter otherwise). It recovers
|
|
1255
|
+
immunogenic-vs-tolerated: foreign writers score above the human self control (clean separation).
|
|
1256
|
+
|
|
1257
|
+
### Changed: the unified profile
|
|
1258
|
+
- `pen_stack/planner/immune_profile.py`: adds `mhc2_writer` and `ada_writer` axes and a `writer_as_antigen` card
|
|
1259
|
+
with `dominant_antigen` and `writer_dominant_risk` (which fires for a foreign writer, especially non-viral delivery
|
|
1260
|
+
where there is no capsid antigen). `collapsed_score` stays `None` (asserted). `immune_calibration.AXIS_STATUS`
|
|
1261
|
+
registers the two new axes as mechanistic/population proxies.
|
|
1262
|
+
|
|
1263
|
+
### Added: Immuno-Bench and calibration
|
|
1264
|
+
- `benchmarks/immuno/harness.py`: the immunogenic-vs-tolerated recovery track (non-circular: label = protein
|
|
1265
|
+
origin) plus a `calibrate_axis` ADA pass that remains a proxy at public-data power (no manufactured validation).
|
|
1266
|
+
- `tests/unit/test_mhc2_ada.py` (CI-safe; pure-Python method plus committed sequences). `prereg/ws_immune2.yaml`.
|
|
1267
|
+
|
|
1268
|
+
### Limitations
|
|
1269
|
+
- Every axis is a population-level proxy, never a patient-specific ADA titer or realized CD4 magnitude (known-
|
|
1270
|
+
unknowns). The MHC-II method is sequence-intrinsic presentation potential, not a trained allele-specific predictor.
|
|
1271
|
+
The self-tolerance k-mer filter is seeded by the bundled human reference (the full human proteome is substitutable on the
|
|
1272
|
+
VM); the authoritative foreignness signal is the protein origin. Axes are a vector, never fused.
|
|
1273
|
+
|
|
1274
|
+
## [6.8.0] - 2026-06-20 - Cross-family writer-efficiency engine and Writer-Efficiency Bench
|
|
1275
|
+
|
|
1276
|
+
This minor feature release upgrades the writer-selection step (pick the writer) from a curated-KB ranking to a prediction plus
|
|
1277
|
+
design layer: the first curated writer-efficiency benchmark, a learned cross-family efficiency predictor,
|
|
1278
|
+
integrated guide/att design, and serine-integrase variant critique. It wraps the Writer Atlas and v4.0 writer-verification.
|
|
1279
|
+
No fabrication: every efficiency is a real published number with a DOI and a verbatim quote.
|
|
1280
|
+
|
|
1281
|
+
### Added: the curated dataset and benchmark
|
|
1282
|
+
- `pen_stack/atlas/writer_efficiency.py` plus `data/writer_efficiency.parquet` (SHA-locked): ~45 records / 9 DOIs /
|
|
1283
|
+
4 families, each row with a DOI, a verbatim quote, and a source-access grade (39 pmc_verbatim, 1 abstract, 5 secondary).
|
|
1284
|
+
Sources: PASTE (Yarnall *Nat Biotechnol* 2023), (ee)PASSIGE (Pandey/Liu *Nat Biomed Eng* 2025), hyperactive
|
|
1285
|
+
integrases (Hew *Nucleic Acids Res* 2024 e64), evoCAST (*Science* 2025), ShCAST (*Science* 2019), enIS621
|
|
1286
|
+
(*Nat Commun* 2026), ISCro4 (*Science*).
|
|
1287
|
+
- `benchmarks/writer_efficiency/`: the Writer-Efficiency Bench, a sealed, SHA-locked held-out-family plus
|
|
1288
|
+
held-out-locus track set plus a baseline leaderboard plus a submission harness. `docs/cards/writer_efficiency_data.md`.
|
|
1289
|
+
|
|
1290
|
+
### Added: the learned predictor and the gate
|
|
1291
|
+
- `pen_stack/atlas/writer_predict.py`: interpretable-feature HistGradientBoosting plus a family-blocked split-conformal
|
|
1292
|
+
interval, candidate-flagged. The pre-registered gate: it beats the KB family-mean baseline on held-out
|
|
1293
|
+
locus (MAE 11.7 vs 15.2, paired-bootstrap CI excludes 0; rho +0.38 vs -0.26) and ranks families better on
|
|
1294
|
+
held-out family (rho +0.52 vs -0.20), but the held-out-family MAE gain is not significant at N=42/4-families, so
|
|
1295
|
+
the KB ranking is retained as primary, the predictor ships candidate-flagged, and the dataset plus bench are the
|
|
1296
|
+
contribution. The negative is reported.
|
|
1297
|
+
|
|
1298
|
+
### Added: guide design and variant critique
|
|
1299
|
+
- `pen_stack/atlas/guide_design.py`: bridge-RNA TBL/DBL loops (Durrant 2024), pegRNA+attB (Yarnall 2023; Bxb1
|
|
1300
|
+
core GT), orthogonal att-pair selection (Roelle 2023 GA/GT), with round-trip and invariant recovery tests.
|
|
1301
|
+
- `pen_stack/design/writer_variants.py`: extends v4.0 writer-verification to serine-integrase hyperactive mutants
|
|
1302
|
+
(Hew 2024 / Keravala 2009); recovers Bxb1 `c22` and PhiC31 P2/P3 retrospectively; defers the
|
|
1303
|
+
LM-vs-conservation blind claim (LM naturalness is not engineered hyperactivity).
|
|
1304
|
+
|
|
1305
|
+
### Added: the recommender surface
|
|
1306
|
+
- `pen_stack/atlas/writer_recommend.py` plus manifest tool `recommend_writers`: ranks families (KB-grounded primary)
|
|
1307
|
+
plus candidate predicted efficiency with a conformal interval plus an auto-designed guide. Efficiency is never extrapolated
|
|
1308
|
+
to a family absent from the dataset (KB-only there).
|
|
1309
|
+
|
|
1310
|
+
### Limitations
|
|
1311
|
+
- Predicted efficiencies are candidates with intervals, never asserted activity. 4 families is the binding
|
|
1312
|
+
statistical limit, reported. Range efficiencies stored as midpoints (raw string retained);
|
|
1313
|
+
secondary-source rows flagged and droppable (strict subset).
|
|
1314
|
+
|
|
1315
|
+
## [6.7.0] - 2026-06-19 - Learned, trained-conformal position-effect head and TPE-Bench
|
|
1316
|
+
|
|
1317
|
+
This minor feature release upgrades the digital twin's expression/outcome layer from a validation-failing
|
|
1318
|
+
closed-form heuristic to a learned, trained-conformal, decomposable position-effect model, and ships the
|
|
1319
|
+
held-out benchmark the expression capability never had. Wrap, don't rebuild: it extends `twin`, `wgenome.uncertainty`,
|
|
1320
|
+
`wgenome.ood`, and `benchmarks`. No fabrication: every metric is from a real CV run on real TRIP supervision, and
|
|
1321
|
+
the cross-cell-type transfer claim is data-gated, never faked.
|
|
1322
|
+
|
|
1323
|
+
### Added: the learned model and trained conformal
|
|
1324
|
+
- `pen_stack/twin/data/position_effect.py`: a unified position-effect schema plus a dataset registry with verified
|
|
1325
|
+
accessions/DOIs (TRIP live; PatchMPRA/MPIRE/lentiMPRA/Leemans registered and recorded `available=False` until
|
|
1326
|
+
fetched), z-normalization within (dataset x cassette), domain-blocked plus held-out-cell-type splits, a leakage check.
|
|
1327
|
+
- `pen_stack/twin/position_effect.py`: `PositionEffectModel` (factored `f_cassette` plus `g_context`, LightGBM),
|
|
1328
|
+
`evaluate()` (chromosome-blocked CV vs the v3.x durability head plus cassette-only, paired-bootstrap CIs,
|
|
1329
|
+
separability), split-conformal calibration (`ConformalRegressor`, chromosome-Mondrian, OOD-widened),
|
|
1330
|
+
`predict_stage_h()` serving seam. Result (real TRIP): expression rho 0.428 to 0.469 (CI excludes 0);
|
|
1331
|
+
held-out conformal coverage 0.885 vs 0.90 nominal.
|
|
1332
|
+
- `configs/twin/position_effect_conformal.json`: the shipped calibration (qhat plus N plus held-out coverage).
|
|
1333
|
+
- `scripts/p1_build_position_effect.py`: regenerates the model plus conformal artifacts (real CV report).
|
|
1334
|
+
|
|
1335
|
+
### Changed: position-effect head integration
|
|
1336
|
+
- `pen_stack/twin/outcome.py`: when a chromatin context is supplied and the artifact is present, `predict_outcome`
|
|
1337
|
+
serves the learned trained-conformal interval plus `p_silenced` plus an OOD tier (`position_effect` block,
|
|
1338
|
+
`stage_h_mode`); with no context/artifact it falls back to the heuristic band, backward compatible (the
|
|
1339
|
+
v5.9 relative-scale contract is intact).
|
|
1340
|
+
|
|
1341
|
+
### Added: TPE-Bench and controls
|
|
1342
|
+
- `benchmarks/position_effect/`: TPE-Bench, a sealed, SHA-locked held-out-chromosome track plus a baseline
|
|
1343
|
+
leaderboard (cassette-only / durability head / factored). The leave-one-cell-type-out
|
|
1344
|
+
transfer track is scaffolded and data-gated (no fabricated transfer number).
|
|
1345
|
+
- `pen_stack/validate/{expr_controls,known_biology_expr,heldout_celltype_expr}.py`: a label-shuffle-to-chance control,
|
|
1346
|
+
an H3K9me3-heterochromatin-to-silencing recovery, and the data-gated transfer harness.
|
|
1347
|
+
- `tests/unit/test_position_effect.py`: CI-safe (synthetic planted signal); the real-TRIP claim runs on a checkout, skips in CI.
|
|
1348
|
+
|
|
1349
|
+
### Limitations
|
|
1350
|
+
- Public data cannot flip expression to outcome-validated (the v6.5 wall); v6.7 ships the learned and calibrated
|
|
1351
|
+
upgrade plus the benchmark plus the data-gating, not a manufactured result. Cross-cell-type transfer needs the additional
|
|
1352
|
+
human datasets (a data-acquisition step), reported as such. Wet-lab validation omitted by scope.
|
|
1353
|
+
|
|
1354
|
+
## [6.6.0] - 2026-06-16 - License-clean provenance (COSMIC to CancerMine)
|
|
1355
|
+
|
|
1356
|
+
This minor release is a provenance refactor: no new science, no capability lost. The shipped artifact now sources the
|
|
1357
|
+
oncogene/TSG/driver list from CancerMine (CC0) instead of COSMIC Cancer Gene Census (free for academia but
|
|
1358
|
+
no-redistribution). Copyright protects the compiled database, not the fact that a gene is an oncogene, so
|
|
1359
|
+
sourcing the list from a CC0 compilation removes all licensing doubt while keeping the same capability. This is prep for
|
|
1360
|
+
the BioFirewall release, whose open repo vendors PEN-STACK's hazard data.
|
|
1361
|
+
|
|
1362
|
+
### Changed
|
|
1363
|
+
- `pen_stack/data/ingest_safety_annot.py`: `load_cancermine()` (CC0) is the default oncogene/TSG source
|
|
1364
|
+
(HUGO to coords via GENCODE, `--min-citations` precision knob); `load_cosmic()` stays available but off by
|
|
1365
|
+
default (bring-your-own-license, local enrichment only).
|
|
1366
|
+
- `configs/genotoxicity_oracle.yaml`: regenerated from CancerMine; provenance and DOIs updated (CancerMine
|
|
1367
|
+
10.1038/s41592-019-0422-y). `safety_{ct}.pkl` plus the Writable-Genome atlas regenerated on CancerMine features
|
|
1368
|
+
(re-deposited on Zenodo, superseding the COSMIC-derived deposit).
|
|
1369
|
+
|
|
1370
|
+
### Added
|
|
1371
|
+
- **`DATA_LICENSES.md`**: every source by license by redistribution-status by where-used.
|
|
1372
|
+
- `tests/unit/test_data_licenses.py`: a CI license gate that fails if a restricted source (COSMIC/OncoKB) is the
|
|
1373
|
+
shipped derived-data source or a raw restricted gene-list is committed; CancerMine is the default.
|
|
1374
|
+
- `scripts/fetch_licensed_sources.py`: a bring-your-own-license fetcher for COSMIC/OncoKB (local-only, validation).
|
|
1375
|
+
|
|
1376
|
+
### Notes
|
|
1377
|
+
- Metrics may shift (CancerMine has broader coverage than CGC), reported. The genotoxicity axis is a
|
|
1378
|
+
mechanism-grounded proxy (not outcome-validated) before and after; the swap changes only the source.
|
|
1379
|
+
|
|
1380
|
+
## [6.5.0] - 2026-06-15 - Comprehensive expression model and proxy-validation pass
|
|
1381
|
+
|
|
1382
|
+
This minor feature release has two threads, one principle (no fabrication):
|
|
1383
|
+
|
|
1384
|
+
### Added: a comprehensive, literature-cited expression model
|
|
1385
|
+
- `configs/expression/promoters.yaml`: the twin's promoter palette expands from 5 to 31 promoters (constitutive plus
|
|
1386
|
+
tissue-specific: liver TBG/LP1/hAAT, neuron hSyn/CaMKIIa, muscle MHCK7/MCK/CK8, astrocyte GfaABC1D, SFFV/MND/
|
|
1387
|
+
MSCV/RSV, and more). Each entry carries `strength` plus context plus assay plus citation plus confidence, because promoter
|
|
1388
|
+
strength has no universal scalar (it depends on cell type by vector by readout), so a single number is encoded
|
|
1389
|
+
with its context, never as a universal truth.
|
|
1390
|
+
- `configs/expression/modifiers.yaml`: a modifier layer (WPRE, intron, polyA, Kozak, codon-optimization/CAI,
|
|
1391
|
+
CpG-silencing) as literature priors/ranges, applied as a bounded uplift range (never a point multiplier, since
|
|
1392
|
+
the chimeric intron is ~20x for one transgene, ~3x for another). `twin/mechanistic.py` consumes both.
|
|
1393
|
+
|
|
1394
|
+
### Added: a proxy-to-outcome validation harness
|
|
1395
|
+
- `scripts/calibrate_immune_axes.py` plus `configs/calibration/preexisting_nab_independent.yaml`: runs the existing
|
|
1396
|
+
`calibrate_axis` gate (N>=6 AND bootstrap Spearman CI excludes 0) against independent measured data.
|
|
1397
|
+
|
|
1398
|
+
### Result (the deliverable)
|
|
1399
|
+
- No immune or expression axis flips to outcome-validated. Pre-existing NAb tested vs an independent cohort
|
|
1400
|
+
(Navarro-Oliveros 2024, Basque): rho=0.12, CI includes 0, geography-dependent. Relative-expression tested vs an
|
|
1401
|
+
independent promoter study (Damdindorj 2014): rho=0.12, CI includes 0, promoter strength is context-dependent
|
|
1402
|
+
(Damdindorj found CMV strongest; Qin found the opposite). Genotoxicity (3 vectors), CD8 (5 capsids), anti-PEG
|
|
1403
|
+
(1), and innate (0 fixed) are structurally below the N>=6 gate. The labels stay proxy with empirical backing;
|
|
1404
|
+
flipping them would require measured-outcome data at a statistical power the public literature does not provide.
|
|
1405
|
+
|
|
1406
|
+
### Tests
|
|
1407
|
+
- `tests/unit/test_expression_model.py`: the palette is comprehensive and cited; context is encoded; the modifier profile is a
|
|
1408
|
+
bounded range; the proxy does not falsely claim cross-study validation (the no-fabrication gate holds).
|
|
1409
|
+
|
|
1410
|
+
## [6.4.3] - 2026-06-12 - Chat vehicle-parse fix (AAVS1 no longer hijacks the vehicle)
|
|
1411
|
+
|
|
1412
|
+
This patch fixes a parsing bug. `web/tools.py::parse_goal` matched the delivery vehicle by substring, so the safe-harbour nickname
|
|
1413
|
+
AAVS1 (which contains "aav") wrongly selected the AAV vehicle even when the user said lentivirus or
|
|
1414
|
+
LNP, producing the wrong immune profile (e.g. genotoxicity 1.0 instead of lentivirus's 0.481). Fix: strip the
|
|
1415
|
+
safe-harbour nicknames (AAVS1/H11/HIPP11/ROSA26) from the vehicle-search text before matching, so the user's
|
|
1416
|
+
stated vehicle wins. Explicit "AAV" still selects AAV. A new test locks all three cases.
|
|
1417
|
+
|
|
1418
|
+
## [6.4.2] - 2026-06-12 - Co-Scientist chat: real writer recommendations and self-explanatory values
|
|
1419
|
+
|
|
1420
|
+
This patch fixes a stale/confusing chat experience reported from the live app. Three problems, three fixes:
|
|
1421
|
+
|
|
1422
|
+
1. **The chat dossier was generic and barely changed per query.** `web/tools.py::parse_goal` hardcoded
|
|
1423
|
+
`chrom="chr19"` (so a goal about ITGB2, chr21, was mis-located) and `run_tools` never called the planner,
|
|
1424
|
+
so a "which writer can integrate N kb in GENE" question got a vehicle-keyed immune profile but no named
|
|
1425
|
+
writer. Fix: `parse_goal` now resolves the gene's real chromosome (`planner.gene_region`, atlas-gated,
|
|
1426
|
+
falls back offline), and `run_tools` runs the planner and attaches a `plan` block: the recommended writer
|
|
1427
|
+
family, top site, safety/durability/score, cargo-capacity fit, and delivery, all engine-computed. It says so
|
|
1428
|
+
when the gene isn't in the atlas ("not found, check the HGNC symbol"); never fabricated.
|
|
1429
|
+
2. **The LLM narration produced `[unverified]` spam.** With no writer in the tool results, the model invented
|
|
1430
|
+
one (`AAV9-CRISPR` plus made-up numbers) and the grounding guard struck them all. Fix: the system prompt now
|
|
1431
|
+
forbids inventing a writer/vehicle/table/number, and if the guard still strikes 2 or more numbers the reply falls
|
|
1432
|
+
back to the fully-grounded deterministic narration, so the spam never reaches the user.
|
|
1433
|
+
3. **Values and the "extrapolating" badge weren't self-explanatory.** Each immune axis now carries a
|
|
1434
|
+
plain-language `meaning` ("0.55 on a 0-1 scale, moderate; higher = fewer patients excluded; this is a
|
|
1435
|
+
proxy, not validated against a measured outcome"), the deterministic narration uses it, and
|
|
1436
|
+
`ImmuneProfileCard` renders it plus a one-line legend explaining that "extrapolating" means a proxy estimate.
|
|
1437
|
+
|
|
1438
|
+
### Added
|
|
1439
|
+
- `tests/unit/test_grounded_chat.py`: chrom resolution, axis-meaning, real writer plan, and the no-`[unverified]`-spam
|
|
1440
|
+
fallback are locked by new tests.
|
|
1441
|
+
|
|
1442
|
+
## [6.4.1] - 2026-06-12 - Defence-in-depth: pre-route safety screen
|
|
1443
|
+
|
|
1444
|
+
This patch closes a screening gap. The grounded co-scientist chat ran the Guardian (biosecurity gate) only in the design lane (via
|
|
1445
|
+
`run_tools`); a hazardous request with no design signal (no vehicle/locus) routed to `general`/`explain`/`meta`
|
|
1446
|
+
and was never screened. Fix: `pen_stack/web/llm.py::_pre_route_safety` runs the Guardian, framing-stripped, the
|
|
1447
|
+
authority on the decision, at the top of `grounded_reply()`, before lane routing. A `refuse`/`escalate`
|
|
1448
|
+
verdict short-circuits to a clear decline (`mode="safety"`, with the decision in `tool_results`). Benign
|
|
1449
|
+
hazard-adjacent biology (vaccines, generic pathogen questions) is not blocked: the Guardian clears it and
|
|
1450
|
+
routing continues. A broad regex only decides whether to invoke the Guardian; a false trigger is harmless.
|
|
1451
|
+
|
|
1452
|
+
### Added
|
|
1453
|
+
- `tests/unit/test_grounded_chat.py`: `test_pre_route_safety_screens_a_hazardous_general_query` and
|
|
1454
|
+
`test_pre_route_safety_does_not_over_refuse_benign_questions` lock both sides of the screen.
|
|
1455
|
+
|
|
1456
|
+
## [6.4.0] - 2026-06-12 - Live Oracles (the foundation models actually execute)
|
|
1457
|
+
|
|
1458
|
+
The oracle mesh goes live. The foundation-model adapters that were deferred contracts now run real backends,
|
|
1459
|
+
without touching the no-fabrication invariant (generated outputs stay candidates, OOD inputs are flagged, a down
|
|
1460
|
+
backend defers). Live execution is opt-in via `PEN_STACK_ORACLE_NET=1`; with the flag unset (CI/offline) every
|
|
1461
|
+
oracle behaves exactly as before. This is a minor feature release on the stable 6.x API.
|
|
1462
|
+
|
|
1463
|
+
### Added: live oracles
|
|
1464
|
+
- **Evo2-40B (hosted):** `oracles/genome.py::generate_dna` calls NVIDIA's hosted Evo2-40B (real generated DNA plus
|
|
1465
|
+
per-token probability). ~1-3 s.
|
|
1466
|
+
- **AlphaGenome (hosted):** `oracles/genome.py::variant_effect` connected to the existing v3.1
|
|
1467
|
+
`wgenome.AlphaGenomeProvider` (added `score_variant`; no duplicate client), a real regulatory variant-effect
|
|
1468
|
+
magnitude. ~2-10 s. (AlphaGenome already ran live in v3.1 for expression/tracks/contact, 416 cached predictions.)
|
|
1469
|
+
- **ProteinMPNN / ESM3-open / RFdiffusion (local GPU):** `model_servers/{proteinmpnn,esm3,rfdiffusion}` small
|
|
1470
|
+
FastAPI servers on the VM GPU (reuse `penstack:phase1.5` / `rfdiffusion:base`); `oracles/protein_design.py`
|
|
1471
|
+
HTTP-calls them. ProteinMPNN ~1-9 s, ESM3 ~1-2 s warm, RFdiffusion ~1-2 min. `docker-compose.models.yml` starts
|
|
1472
|
+
them on demand.
|
|
1473
|
+
- **Execution and latency surface:** `configs/oracles/execution.yaml` plus `oracles/status.py` (`oracle_status`,
|
|
1474
|
+
`summary`) plus `GET /oracles` plus the chat meta facts: per-oracle execution, latency class
|
|
1475
|
+
(instant/seconds/slow/long_job), and live status, so the assistant states the cost before running anything.
|
|
1476
|
+
|
|
1477
|
+
### Held / deferred
|
|
1478
|
+
- **AlphaFold3, Boltz-2, Chai-1, Protenix:** held, they need a rented A100/H100 (24-80 GB; AF3 also ~1 TB
|
|
1479
|
+
databases). They run separately on cloud, never on the 16 GB VM and never in the request path.
|
|
1480
|
+
- **Arc STATE / scGPT:** the package is verified installable (`pip install arc-state`; SE-600M embeds cells), but a
|
|
1481
|
+
trustworthy perturbation outcome needs the State-Transition model plus a reference scRNA pipeline, and even
|
|
1482
|
+
SOTA doesn't beat naive baselines (Arc VCC), so the magnitude stays a known-unknown, deferred
|
|
1483
|
+
(a uniform gated hook is added via `PEN_STACK_VCELL_URL` for when an ST server is stood up).
|
|
1484
|
+
|
|
1485
|
+
### Verified on the VM (RTX A4000)
|
|
1486
|
+
Evo2-40B generation ~1.2 s; AlphaGenome variant score `chr22:36201698 A>C` max|effect| 3.15 over 14,652 tracks
|
|
1487
|
+
in 3.6 s; ProteinMPNN designed real ubiquitin-fold sequences (global_score ~0.80) in ~9 s; ESM3-open completed the
|
|
1488
|
+
ubiquitin sequence from a partial prompt in 1.4 s warm; RFdiffusion diffused a real 60-residue backbone in ~105 s.
|
|
1489
|
+
All generated outputs remain candidates (`as_claim()` raises).
|
|
1490
|
+
|
|
1491
|
+
## [6.3.1] - 2026-06-12 - Router fix: general "how does it work" no longer misrouted to the meta lane
|
|
1492
|
+
|
|
1493
|
+
This patch corrects routing. It was found by a full-stack test pass (every oracle plus every endpoint plus the 4
|
|
1494
|
+
chat lanes plus general/biological-intelligence questions).
|
|
1495
|
+
|
|
1496
|
+
### Fixed
|
|
1497
|
+
- **Router meta-lane over-capture.** A general-biology question phrased "and how does it work / cut DNA?"
|
|
1498
|
+
(e.g. *"what is CRISPR-Cas9 and how does it cut DNA?"*) matched the meta pattern `how (do|does) (you|it|this|pen)`
|
|
1499
|
+
and was answered from PEN-STACK capability facts instead of general knowledge. Narrowed the bare-pronoun meta
|
|
1500
|
+
trigger to `how (do|does) (you|pen)` so a general "how does it ..." routes to the general lane (labelled,
|
|
1501
|
+
with an engine pointer); a pen-stack-scoped "how do you compute X" stays meta (the verb-qualified pattern is
|
|
1502
|
+
unchanged). Regression cases added to `tests/unit/test_grounded_chat.py::test_router_classifies_the_four_lanes`.
|
|
1503
|
+
|
|
1504
|
+
### Verified (v6.3 test pass)
|
|
1505
|
+
- **Oracle mesh (42/42, engine-direct):** ViennaRNA computes a real MFE fold (-38.3 kcal/mol); AlphaGenome,
|
|
1506
|
+
Evo2, vcell (Arc-STATE), AF3/Boltz/Chai/Protenix, and RFdiffusion/ProteinMPNN/ESM3 either compute or defer
|
|
1507
|
+
with the OOD gate plus provenance intact, never fabricate; the generative-candidate `as_claim()` guard
|
|
1508
|
+
raises. Computed immune layers reproduce orderings from data: genotoxicity LV 0.481 < gammaretro 0.177
|
|
1509
|
+
(LMO2/SCID-X1), capsid AAV 0.28 > Ad 0.18, CpG O/E rich > poor, seroprevalence AAV 0.55 / Ad5 0.35, anti-PEG
|
|
1510
|
+
0.515; full `verify()` clears a clean design, rejects a 7 kb single-AAV (alt lentivirus legal), refuses ricin,
|
|
1511
|
+
rejects an RNP-over-AAV, and flags multiplex translocation risk 0.95.
|
|
1512
|
+
- **App surface (live, LLM on):** every endpoint 200 plus a grounded shape; the 4 chat lanes route correctly with the
|
|
1513
|
+
grounding guard clean on the grounded lanes (0 ungrounded numbers, Nemotron backend).
|
|
1514
|
+
|
|
1515
|
+
## [6.3.0] - 2026-06-12 - The Hybrid Co-Scientist (grounded engine plus general intelligence)
|
|
1516
|
+
|
|
1517
|
+
The chat gains general and biological intelligence without loosening the no-fabrication core. A 4-lane router
|
|
1518
|
+
keeps grounded engine output and general trained-knowledge in separate, explicitly-labelled lanes, so a
|
|
1519
|
+
general-knowledge fact can never be mistaken for a PEN-STACK result. Numbers now come with their meaning,
|
|
1520
|
+
reference range, and how they were computed; the conversation has memory. This is a minor feature release on the stable
|
|
1521
|
+
6.x API, SHA-locked.
|
|
1522
|
+
|
|
1523
|
+
### Added
|
|
1524
|
+
- A deterministic 4-lane chat surface: `pen_stack/web/router.py` (classifier: `design` / `explain` / `meta` /
|
|
1525
|
+
`general`, biased to the engine whenever a design signal is present) plus `pen_stack/web/guide.py`
|
|
1526
|
+
(`metric_guide()` interpretation cards plus `pen_stack_facts()` assembled from live engine data) plus a rewritten
|
|
1527
|
+
`pen_stack/web/llm.py::grounded_reply` that dispatches per lane and returns `{mode, provenance, grounded, ...}`.
|
|
1528
|
+
- **`configs/metric_guide.yaml`:** grounded interpretation for every engine number (genotoxicity, CD8 epitope,
|
|
1529
|
+
innate, pre-existing NAb, anti-PEG, confidence, relative expression, and the safety decisions): what it means, the
|
|
1530
|
+
scale plus direction, reference bands, how it is computed, and its validation status. The chat now explains a value
|
|
1531
|
+
(scale / what's good-or-bad / reference range / method), not just prints it.
|
|
1532
|
+
- **Lanes and provenance:** `design`/`explain`/`meta` are engine-grounded (the grounding guard runs over the tool
|
|
1533
|
+
results, the metric guide, or the live facts); `general` answers from the LLM's trained knowledge, is labelled
|
|
1534
|
+
"General knowledge, not PEN-STACK-verified", attributes no number to PEN-STACK, and points to the engine
|
|
1535
|
+
wherever PEN-STACK could compute a concrete answer (`pen_stack_angles`).
|
|
1536
|
+
- **Conversation memory:** the last turns are passed to every lane so follow-ups ("what does that 0.55 mean?")
|
|
1537
|
+
resolve against the prior dossier; the frontend keeps history in-session until refresh and renders a per-message
|
|
1538
|
+
provenance badge (grounded vs general) plus the "PEN-STACK can compute this" pointers.
|
|
1539
|
+
- Tests: `tests/unit/test_grounded_chat.py` covers the 4-lane router, the general lane labelled/unattributed/pointered, the
|
|
1540
|
+
meta lane grounded in live facts, the explain lane interpreting prior values without a fresh design, the metric
|
|
1541
|
+
guide complete. Preregistration `ws_hybrid` plus SHA lock; deposit `phase_6.3/`.
|
|
1542
|
+
|
|
1543
|
+
### Notes
|
|
1544
|
+
- The core is untouched. The guard still runs on every PEN-STACK-attributed number; we added a general lane,
|
|
1545
|
+
we did not loosen the grounded lane. The cost is that general-lane answers carry the LLM's fallibility,
|
|
1546
|
+
made safe by the explicit label and by redirecting to the engine for anything computable.
|
|
1547
|
+
|
|
1548
|
+
## [6.2.4] - 2026-06-12 - Faster grounded narration (LLM backends) (patch)
|
|
1549
|
+
|
|
1550
|
+
Performance plus a real fix, from benchmarking the narration backends on the deployment GPU (RTX A4000). The
|
|
1551
|
+
LLM only narrates over engine tool results (the grounding guard runs regardless), so latency is the thing to
|
|
1552
|
+
tune. Measured (real grounded prompt): Ollama qwen2.5:7b = ~50s warm / 120s cold (3.4 tok/s, a workstation
|
|
1553
|
+
GPU is slow for an LLM); qwen2.5:3b = ~27s; llama3.2:3b = ~17s; hosted Nemotron-49B = ~5s. All keep the
|
|
1554
|
+
grounding guard clean (0 ungrounded). The old Nemotron fallback model (`llama-3.1-nemotron-70b-instruct`) now
|
|
1555
|
+
404s, i.e. the fallback was silently broken.
|
|
1556
|
+
|
|
1557
|
+
### Fixed / changed (`pen_stack/web/llm.py`)
|
|
1558
|
+
- **Nemotron model corrected** to `nvidia/llama-3.3-nemotron-super-49b-v1` (the 70B name was retired, so the
|
|
1559
|
+
fallback 404'd). Restores a working, ~5s hosted backend.
|
|
1560
|
+
- **Default local model qwen2.5:7b to qwen2.5:3b-instruct** (~2x faster narration, grounding unchanged).
|
|
1561
|
+
- **`keep_alive` (default 30m)** so the model stays resident on the GPU and idle calls don't pay the cold start.
|
|
1562
|
+
- **Configurable backend order** `PEN_STACK_LLM_ORDER` (default `ollama,nemotron` = local/private-first;
|
|
1563
|
+
`nemotron,ollama` = speed-first ~5s). `web/.env.example` documents all knobs.
|
|
1564
|
+
|
|
1565
|
+
## [6.2.3] - 2026-06-12 - Scope matcher covers functional titer and durability (patch)
|
|
1566
|
+
|
|
1567
|
+
A coverage fix (from the 20-query acceptance suite, `phase_6.2/PEN-STACK_ACCEPTANCE_TESTS.md`). The
|
|
1568
|
+
known-unknowns matcher (`configs/known_unknowns.yaml`) had no entry for functional titer / absolute in-vivo
|
|
1569
|
+
expression magnitude and its durability terms were too narrow ("how long will it last in a patient"), so
|
|
1570
|
+
common measured-endpoint questions ("what functional titer (% of normal)?", "how long will episomal AAV
|
|
1571
|
+
expression last?") were not explicitly deferred. The no-fabrication spine already held (no titer/half-life was
|
|
1572
|
+
ever emitted, and the immune profile lists `patient_specific_titer`), but the matcher should flag these
|
|
1573
|
+
proactively.
|
|
1574
|
+
|
|
1575
|
+
### Added / Fixed
|
|
1576
|
+
- `configs/known_unknowns.yaml`: a new known-unknown `in_vivo_expression_magnitude` (functional titer / % of normal
|
|
1577
|
+
/ absolute expression, a measured clinical endpoint, never predicted; PEN-STACK gives the relative mechanistic
|
|
1578
|
+
proxy plus immune context); broadened `long_term_clinical_durability` match-terms/patterns to catch "how long will
|
|
1579
|
+
... last/persist", "durability", "half-life". Regression test
|
|
1580
|
+
`tests/unit/test_api_surface.py::test_scope_defers_titer_and_durability_questions`.
|
|
1581
|
+
|
|
1582
|
+
### Acceptance suite result
|
|
1583
|
+
- 20/20 behave as specified at the engine level: grounded where earned, refusing where unsafe (ricin/botulinum),
|
|
1584
|
+
abstaining/deferring where appropriate (titer, durability, phenotype), no fabricated number. T10 (RNP/AAV) and T12
|
|
1585
|
+
(multiplex translocation) are enforced via `delivery.cargo_form_compatible` and `multiplex.translocation_risk`
|
|
1586
|
+
on the structured design fields (`writer_output_form`, `edits`).
|
|
1587
|
+
|
|
1588
|
+
## [6.2.2] - 2026-06-12 - Safe-harbour locus-nickname resolution (patch)
|
|
1589
|
+
|
|
1590
|
+
A usability fix. Site Finder / `/plan` / `/writable` returned 0 plans for `AAVS1` because it is a genomic
|
|
1591
|
+
safe-harbour locus nickname, not an HGNC gene symbol, so the gene-to-coordinate lookup (`gene_coords`, 60,888
|
|
1592
|
+
symbols) could not resolve it: an empty result, but unhelpful for the most-typed safe harbour. (The cell-type
|
|
1593
|
+
atlases are complete; real symbols like `PCSK9`/`HBB`/`CCR5`/`CLYBL` resolved fine.)
|
|
1594
|
+
|
|
1595
|
+
### Fixed
|
|
1596
|
+
- `pen_stack/planner/optimize.py`: `resolve_gene()` maps well-documented safe-harbour nicknames to their host
|
|
1597
|
+
gene (`AAVS1` to `PPP1R12C` 19q13.42; `H11`/`Hipp11` to `EIF4ENIF1` 22q12) at every gene-to-coordinate lookup
|
|
1598
|
+
(`gene_region`, `plan`, `crosslink.loci_for_gene`); real symbols pass through unchanged. Regression test
|
|
1599
|
+
`tests/unit/test_api_surface.py::test_safe_harbour_nickname_resolves_to_host_gene`.
|
|
1600
|
+
|
|
1601
|
+
## [6.2.1] - 2026-06-12 - JSON-safe atlas/crosslink endpoints (patch)
|
|
1602
|
+
|
|
1603
|
+
A bug fix. The `/atlas`, `/writable`, and `/crosslink/loci` endpoints returned raw DataFrame records, which
|
|
1604
|
+
leak non-finite floats (`NaN`/`inf`) present in `atlas.parquet`; the JSON encoder rejects these
|
|
1605
|
+
(`ValueError: Out of range float values are not JSON compliant`, so HTTP 500). Surfaced on the v6.2 Web Platform's
|
|
1606
|
+
Writer Atlas and Site Finder pages.
|
|
1607
|
+
|
|
1608
|
+
### Fixed
|
|
1609
|
+
- `pen_stack/server/api.py`: a `_records()` helper serializes DataFrame rows JSON-safely (via pandas `to_json`,
|
|
1610
|
+
so `NaN`/`inf` become `null` and numpy scalars become native), applied to `/atlas`, `/writable`, `/crosslink/loci`.
|
|
1611
|
+
Regression test `tests/unit/test_api_surface.py::test_records_helper_is_json_safe_with_non_finite_floats`.
|
|
1612
|
+
|
|
1613
|
+
## [6.2.0] - 2026-06-11 - The Web Platform (the human surface)
|
|
1614
|
+
|
|
1615
|
+
A post-1.0 adoption surface for bench scientists. A complete, friendly web application: a grounded co-scientist
|
|
1616
|
+
chat plus structured feature pages, over the same typed v6.1 API the AI surface uses. The LLM narrates and
|
|
1617
|
+
routes but never sources a number; every quantitative answer renders with its confidence band, provenance, and
|
|
1618
|
+
an explicit ledger of what PEN-STACK can't tell you. This is a minor release on the stable 6.0 API, SHA-locked.
|
|
1619
|
+
|
|
1620
|
+
### Added
|
|
1621
|
+
- **Backend:** `pen_stack/web/server.py`, one FastAPI gateway that mounts the v6.1 engine surface under
|
|
1622
|
+
`/api` (so the frontend has one base URL and one OpenAPI) and adds the grounded `/chat` (plus SSE `/chat/stream`),
|
|
1623
|
+
CORS, and static serving of the built frontend (`web/dist`). A `/health` for the live grounded indicator.
|
|
1624
|
+
- **Chat (the hard gate):** `pen_stack/web/tools.py` (the deterministic engine tool-runner: parse a goal,
|
|
1625
|
+
run `verify`/`safety`/`immune_profile`/scope, return a grounded dossier; `extract_grounded_numbers` is the allow-list)
|
|
1626
|
+
and `pen_stack/web/llm.py` (the grounded co-scientist: Ollama, then Nemotron, then deterministic narrator, with
|
|
1627
|
+
`_enforce_grounding` striking any numeric token the model can't trace to a tool result). A reply's numbers are
|
|
1628
|
+
always engine-sourced; `tests/unit/test_grounded_chat.py` asserts no number in a reply is absent from the tool
|
|
1629
|
+
results, and that the deterministic narrator works with both LLMs offline.
|
|
1630
|
+
- **Frontend:** `web/` (React/Vite plus Tailwind): the UX component library (`ConfidenceBand`,
|
|
1631
|
+
`ProvenanceChip`, `ScopeLedger`, `SafetyBadge`, `ImmuneProfileCard`), so a number is never shown without its
|
|
1632
|
+
uncertainty plus provenance, and the scope ledger appears on every answer.
|
|
1633
|
+
- **Pages:** 11 feature pages over the typed API: Co-Scientist, Site Finder, Writer Atlas, Designer,
|
|
1634
|
+
Verify, Delivery & Immunity, Digital Twin, Guardian, Experiments, Challenge, Scope & About. Each renders
|
|
1635
|
+
through the UX library and degrades gracefully when the LLM is offline.
|
|
1636
|
+
- **Deploy:** `docker/web.Dockerfile` (multi-stage: a node:20 stage builds the frontend, a slim Python
|
|
1637
|
+
serves UI plus API from one origin) plus a `web` service in `docker-compose.yml`: one-command self-host
|
|
1638
|
+
(`docker compose up web ollama`, open `http://localhost:8000`). `web/.env.example`, `web/README.md` quickstart.
|
|
1639
|
+
- Read-only Challenge surface for the web page: `GET /api/challenge/{tasks,leaderboard}` (public tasks plus the
|
|
1640
|
+
PEN-STACK reference leaderboard; submissions are still scored offline, never accepted over HTTP).
|
|
1641
|
+
- Preregistration `ws_{chat,frontend}` plus SHA locks; deposit `phase_6.2/`.
|
|
1642
|
+
|
|
1643
|
+
### Notes
|
|
1644
|
+
- The LLM never sources a number. It explains, compares, and routes over the engine's tool outputs; the
|
|
1645
|
+
grounding guard strips any value it can't trace, and the app runs in a deterministic, no-LLM mode (the science
|
|
1646
|
+
lives in the engine, not the model). This cycle improves usability/adoption, not validation; a real-data
|
|
1647
|
+
result and a first lab user remain the standing bottleneck. No new science; contracts under the 1.0 commitment.
|
|
1648
|
+
|
|
1649
|
+
## [6.1.0] - 2026-06-11 - The AI Integration Surface
|
|
1650
|
+
|
|
1651
|
+
A post-1.0 adoption surface for AI builders. Not new capability: the introspectable, documented, dependable
|
|
1652
|
+
contract that lets an external agent discover what PEN-STACK offers and what it refuses to answer. This is a minor
|
|
1653
|
+
release on the stable 6.0 API, SHA-locked.
|
|
1654
|
+
|
|
1655
|
+
### Added
|
|
1656
|
+
- **Capability and scope manifests (the differentiator):** `pen_stack/api/manifest.py`: `capability_manifest()`
|
|
1657
|
+
(machine-readable: the stable tools, inputs/outputs, all `fabricates=False`, guarantees, stability) and `scope_manifest()`
|
|
1658
|
+
(machine-readable: the known-unknowns registry plus every oracle scope card, i.e. what PEN-STACK refuses to
|
|
1659
|
+
answer). Generated from the live registry/scope cards (never hand-written); internal matcher fields not leaked.
|
|
1660
|
+
- **OpenAPI:** `pen_stack/server/api.py`: `GET /capabilities` plus `GET /scope` plus `POST /verify /safety /immune
|
|
1661
|
+
/generate /predict /suggest /session`; FastAPI auto-generates the OpenAPI 3.1 spec at `/openapi.json`.
|
|
1662
|
+
- **MCP:** `pen_stack/agent/mcp_server.py`: the self-describing resources `pen-stack://capabilities` plus
|
|
1663
|
+
`pen-stack://scope`, plus the engine tools (`safety_screen`, `immune_profile`, `generate_designs`,
|
|
1664
|
+
`predict_outcome`, `suggest_experiment`, `co_scientist_session`). A hazardous design returns a structured
|
|
1665
|
+
refusal an agent branches on.
|
|
1666
|
+
- **Examples:** a runnable golden path: `examples/external_agent.py` (REST: discover scope, submit, branch on
|
|
1667
|
+
safety/legality), `examples/mcp_client.py` (MCP), `examples/agent_tools.py` (framework-agnostic tool specs built
|
|
1668
|
+
from the live manifest plus an in-process dispatcher to the validated engine).
|
|
1669
|
+
- Docs: `docs/integrations.md` rewritten as "Integrate PEN-STACK in your AI" (the four guarantees plus the scope
|
|
1670
|
+
contract plus REST/MCP/framework quickstarts); preregistration `ws_{manifest,openapi,mcp}` plus SHA locks; deposit `phase_6.1/`.
|
|
1671
|
+
|
|
1672
|
+
### Notes
|
|
1673
|
+
- Scope is data, not a disclaimer. The scope manifest makes the scope machinery itself an API, the thing
|
|
1674
|
+
that makes trustworthy autonomy something another system can build on. This cycle lowers the barrier to
|
|
1675
|
+
adoption; it does not, by itself, create it: outreach plus a real result remain the standing bottleneck. No new
|
|
1676
|
+
science or validation; contracts versioned plus deprecation-policed under the 1.0 commitment.
|
|
1677
|
+
|
|
1678
|
+
## [6.0.0] - 2026-06-11 - 1.0, First Stable (the graduation)
|
|
1679
|
+
|
|
1680
|
+
The Closed-Loop arc is complete (7/7), and PEN-STACK graduates to "1.0, First Stable." The public API,
|
|
1681
|
+
exercised across every surface (verify, safety, generative design, twin, experiment design, build interface,
|
|
1682
|
+
closed loop, co-scientist, and the Genome-Writing Challenge), is documented and frozen with a deprecation
|
|
1683
|
+
policy. "First Stable" is earned, not declared: it is cut only after the closed loop is demonstrated (v5.12),
|
|
1684
|
+
the benchmark is public (v5.13), and the integration surface ships.
|
|
1685
|
+
|
|
1686
|
+
### Changed
|
|
1687
|
+
- **`Development Status :: 5 - Production/Stable`** (was Beta). Version 6.0.0 (MAJOR).
|
|
1688
|
+
- The public API is documented and frozen with a deprecation policy: **`docs/STABILITY.md`** (semver from 6.0.0;
|
|
1689
|
+
deprecations warn at least 1 MINOR before removal in a MAJOR; the `OracleResult`/`Verdict`/`SafetyVerdict`/immune-profile
|
|
1690
|
+
contracts and invariants, including `collapsed_score is None` and the no-fabrication guard, are stable across 6.x).
|
|
1691
|
+
- The Genome-Writing Challenge is public.
|
|
1692
|
+
|
|
1693
|
+
### Notes
|
|
1694
|
+
- "1.0, First Stable" is a commitment to API stability, not a claim of solving genetic engineering. The
|
|
1695
|
+
unknown funnel remains, made legible (scope flags, known-unknowns, baselines, no fabrication), not
|
|
1696
|
+
hidden. The high version numbers of the program's fast youth finally meet a real stability commitment.
|
|
1697
|
+
|
|
1698
|
+
## [5.13.0] - 2026-06-11 - The Standard (Genome-Writing Challenge plus Co-Scientist II)
|
|
1699
|
+
|
|
1700
|
+
This cycle aims to make PEN-STACK the field's reference: an open, recurring, held-out benchmark
|
|
1701
|
+
others build to, and to give scientists a co-scientist that drives the whole loop with immune-risk first-class.
|
|
1702
|
+
SHA-locked. (The v6.0.0 "1.0, First Stable" graduation follows.)
|
|
1703
|
+
|
|
1704
|
+
### Added
|
|
1705
|
+
- **The Genome-Writing Challenge** (`benchmarks/genome_writing_challenge/`): an open,
|
|
1706
|
+
recurring, held-out leaderboard (the CASP / Virtual-Cell-Challenge model). `evaluate(Submission, round_id)`
|
|
1707
|
+
scores an external `predict_fn(public_input) -> answer` on a held-out round whose labels it never sees; labels
|
|
1708
|
+
are computed by the validated PEN-STACK layers (rules / v5.7 Guardian / v5.6 immune profile) so no task uses a
|
|
1709
|
+
circular label; a no-fabrication audit runs on every submission; task families include an immune-risk
|
|
1710
|
+
task grounded in the v5.6 oracles. A one-command runner (`run.py`); a reference submission anchors the leaderboard.
|
|
1711
|
+
- **The matured co-scientist** (`pen_stack/agent/co_scientist.py::co_scientist_session(goal, cell_state)`)
|
|
1712
|
+
drives the whole loop: safe, legal, calibrated designs, then predicted outcomes, then suggested
|
|
1713
|
+
experiments, then exportable protocols, returning the Pareto strategies, calibrated `predicted_outcomes`,
|
|
1714
|
+
per-axis immune profiles (first-class), `suggested_experiments`, citations (resolve by construction),
|
|
1715
|
+
a complete scope ledger, and the per-design safety decision. The scientist/lab decides; the co-scientist
|
|
1716
|
+
drives. No number is fabricated; hazardous candidates are discarded.
|
|
1717
|
+
- **The integration surface:** MCP server tools, the Challenge submission API, and a worked reference
|
|
1718
|
+
example (`docs/integrations.md`). The standing adoption criterion (at least 1 external integration plus at least 1 external
|
|
1719
|
+
submission) depends on outreach, the non-code bottleneck flagged since v3.1; the surface is shipped.
|
|
1720
|
+
- Docs: `docs/{challenge,co_scientist_loop,integrations}.md`; preregistration `ws_{challenge,cosci2}` plus SHA locks.
|
|
1721
|
+
|
|
1722
|
+
### Notes
|
|
1723
|
+
- A standard requires a community: PEN-STACK provides the open, reproducible, held-out benchmark and the
|
|
1724
|
+
integration surface; adoption depends on outreach. The co-scientist drives and presents (including the
|
|
1725
|
+
immune-risk profile with its known-unknowns); the scientist and lab decide.
|
|
1726
|
+
|
|
1727
|
+
## [5.12.0] - 2026-06-11 - The Closed Loop (autonomy Level 3)
|
|
1728
|
+
|
|
1729
|
+
This release integrates everything into one continual design/build/test/learn cycle,
|
|
1730
|
+
humans/lab in control, no fabrication, drift-aware. It reaches autonomy Level 3 (the program's ceiling).
|
|
1731
|
+
SHA-locked.
|
|
1732
|
+
|
|
1733
|
+
### Added
|
|
1734
|
+
- **The loop** (`pen_stack/loop/cycle.py`): `run_loop(goal, cell_state, ...)` orchestrates every prior cycle each
|
|
1735
|
+
round: generate (v5.8), decide/batch (v5.10), safety-gated export (v5.7 plus v5.11), run (sim-lab v5.11 /
|
|
1736
|
+
real lab), ingest (v4.5 gate), drift (v5.12), continual learn (v5.12). Gated: safety, build, and
|
|
1737
|
+
belief-admission each await the `approver`. Returns `autonomy_level=3`, `human_in_control=True`,
|
|
1738
|
+
`no_fabrication=True`. A hazardous candidate is discarded by the safety-gated pipeline before it is ever run.
|
|
1739
|
+
- **Drift** (`pen_stack/loop/drift.py`): `detect_drift(designs, results)` compares the v5.9 twin's predictions
|
|
1740
|
+
vs observed readouts; growing miscalibration leads to `severity:"high"` and `inflate_intervals` (widen, don't over-trust).
|
|
1741
|
+
- **Continual learning** (`pen_stack/loop/continual.py`): `continual_update(...)` recalibrates trust plus twin plus immune
|
|
1742
|
+
proxies on admitted outcomes only; each update is versioned and reversible (`rollback_to`); high drift
|
|
1743
|
+
widens intervals; an admitted immune measurement with a CI can graduate a v5.6 proxy to outcome-validated.
|
|
1744
|
+
This is recalibration, not foundation-model retraining.
|
|
1745
|
+
- **Demo and autonomy criteria:** `loop_converges_faster_than_random` reports the active-vs-random convergence with a
|
|
1746
|
+
bootstrap CI (retrospective/simulated, reported either way); `docs/autonomy.md` asserts the Level-3 criteria
|
|
1747
|
+
(closed loop, human in control at every gate, anomaly flagging, no fabrication) and that Levels 4/5 are
|
|
1748
|
+
not claimed.
|
|
1749
|
+
- **Bench v0.3.8:** a new `closed_loop` hard-gate task. The gate is the loop's integrity (gated
|
|
1750
|
+
end-to-end run plus no-fabrication plus Level-3 human-in-control plus drift detection plus versioned/reversible continual
|
|
1751
|
+
learning); an ungated autopilot fails by construction. Convergence reported informationally.
|
|
1752
|
+
- Docs: `docs/{closed_loop,autonomy}.md`; preregistration `ws_{loop,continual,drift}` plus SHA locks.
|
|
1753
|
+
|
|
1754
|
+
### Notes
|
|
1755
|
+
- The loop is Level 3: closed, but with humans/lab in control at every gate, not autonomous. It runs in
|
|
1756
|
+
silico via the sim-lab (a real lab attaches at the same interface); continual learning recalibrates rather than
|
|
1757
|
+
retrains; drift covers calibration/residual shift, not all failures; the convergence demo is retrospective/
|
|
1758
|
+
simulated, reported with CIs.
|
|
1759
|
+
|
|
1760
|
+
## [5.11.0] - 2026-06-11 - The Build Interface (digital-to-physical bridge)
|
|
1761
|
+
|
|
1762
|
+
This release makes designs executable and results ingestible: loop-ready, lab-optional,
|
|
1763
|
+
safety-gated, with the immune-risk profile attached as protocol metadata. SHA-locked.
|
|
1764
|
+
|
|
1765
|
+
### Added
|
|
1766
|
+
- **Protocol export** (`pen_stack/build/protocol.py`): `export_protocol(design, experiment, target, actor)` for
|
|
1767
|
+
Opentrons / PyLabRobot / cloud-lab. It runs `verify()` first: a safety-`refuse` or illegal design raises
|
|
1768
|
+
`ProtocolExportError` (no export path for a flagged design); a cleared design is emitted as a DRAFT
|
|
1769
|
+
("human/lab review required") carrying the v5.6 immune profile plus provenance in its metadata. Never auto-run.
|
|
1770
|
+
- **Ingest** (`pen_stack/build/ingest.py`): `ingest_result(result, ...)` validates a result (assay / readout /
|
|
1771
|
+
provenance) and turns it into a quarantined measured edge Candidate; the only path into the curated
|
|
1772
|
+
world-model is the v4.5 gate (`gate_admit`): automated checks AND explicit human approval. No auto-edit
|
|
1773
|
+
(Principle 1). Immune measurements can begin validating the v5.6 proxies on a later pass.
|
|
1774
|
+
- **Sim-lab** (`pen_stack/build/simlab.py`): `run_simulated(protocol_ir, design, cell_state)` executes a
|
|
1775
|
+
protocol in silico (samples from the v5.9 twin plus measurement noise), labelled `SIMULATED`, so the closed
|
|
1776
|
+
loop (v5.12) runs end-to-end (export, sim, ingest) without hardware; it never enters the world-model as
|
|
1777
|
+
measured truth.
|
|
1778
|
+
- **Bench v0.3.7:** a new `protocol_safety` hard-gate task (`pen_stack/validate/protocol_safety.py`):
|
|
1779
|
+
a cleared design exports with immune metadata, a safety-refused/illegal design is blocked, and the simulated
|
|
1780
|
+
loop completes with quarantined SIMULATED results; an ungated exporter (which would emit the hazardous protocol)
|
|
1781
|
+
fails by construction.
|
|
1782
|
+
- Docs: `docs/build_interface.md`; preregistration `ws_{proto,ingest,simlab}` plus SHA locks.
|
|
1783
|
+
|
|
1784
|
+
### Notes
|
|
1785
|
+
- PEN-STACK emits protocols and ingests results; it does not run experiments. Protocols are drafts requiring
|
|
1786
|
+
human/lab review, results enter only through the gate, and the simulated lab is for development / loop-validation,
|
|
1787
|
+
never a substitute for real data. Export is hard-blocked for anything the safety gate flags.
|
|
1788
|
+
|
|
1789
|
+
## [5.10.0] - 2026-06-11 - The Experiment Designer (active learning / EIG)
|
|
1790
|
+
|
|
1791
|
+
The "Learn" brain of a self-driving lab: turn "I'm uncertain" into "run
|
|
1792
|
+
this experiment next." It reads the calibrated v5.9 twin's uncertainty plus the v5.6 immune labels, scores each
|
|
1793
|
+
candidate experiment by expected information gain, assembles a diverse batch, and proves on held-out data, with
|
|
1794
|
+
CIs, that this learns faster than random/greedy (reporting plainly when it does not). SHA-locked.
|
|
1795
|
+
|
|
1796
|
+
### Added
|
|
1797
|
+
- **Acquisition** (`pen_stack/active/acquire.py`): `expected_information_gain` (reducible uncertainty from the twin's
|
|
1798
|
+
predictive distribution; `>= 0`, monotone in uncertainty), `predictive_entropy` (from the twin's interval width),
|
|
1799
|
+
and `immune_voi` (value of information for validating an immune proxy axis, v5.6): an experiment that
|
|
1800
|
+
would measure a still-proxy axis is high-VOI (it turns proxy to outcome-validated). `acquisition_score` is fully
|
|
1801
|
+
traceable to twin quantities plus v5.6 labels; deterministic; no fabricated values.
|
|
1802
|
+
- **Batch design** (`pen_stack/active/design.py`): `select_batch` greedily maximises acquisition minus a
|
|
1803
|
+
redundancy penalty (shared design facets), giving a diverse batch (not k copies of the most-uncertain point);
|
|
1804
|
+
each experiment carries its expected info gain.
|
|
1805
|
+
- **Validation** (`pen_stack/active/validate.py`): `retrospective_active_learning` simulates active vs random vs
|
|
1806
|
+
greedy campaigns on a held-out split, reports mean±CI learning curves and a bootstrap CI on the curve-area
|
|
1807
|
+
gap; `active_beats_random` only when the CI excludes zero, else the not-yet-useful negative is reported.
|
|
1808
|
+
- **Bench v0.3.6:** a new `experiment_design` hard-gate task. The gate is the Learn engine's
|
|
1809
|
+
properties (twin-sourced EIG monotone in uncertainty plus immune-VOI for proxy validation plus a diverse
|
|
1810
|
+
batch plus retrospective active-vs-random with reps and CI); a random selector fails by construction. Active-beats-
|
|
1811
|
+
random is reported informationally.
|
|
1812
|
+
- Docs: `docs/experiment_design.md`; preregistration `ws_{acq,aldesign,alvalidate}` plus SHA locks.
|
|
1813
|
+
|
|
1814
|
+
### Notes
|
|
1815
|
+
- The experiment designer is only as good as the v5.9 twin plus the v5.6 labels it queries; its advantage is validated
|
|
1816
|
+
retrospectively with CIs and reported plainly when absent. It chooses informative experiments but does
|
|
1817
|
+
not run them; prospective benefit awaits a lab partner (v5.11+). No autonomy claim.
|
|
1818
|
+
|
|
1819
|
+
## [5.9.0] - 2026-06-11 - The Digital Twin (calibrated outcome prediction)
|
|
1820
|
+
|
|
1821
|
+
The missing layer: what does the cell do after the write? Predicted with
|
|
1822
|
+
calibrated uncertainty. The twin computes what mechanism allows, adds an in-distribution virtual-cell estimate
|
|
1823
|
+
(OOD-gated), screens immune outcome from the v5.6 profile, and is explicit about its boundary at phenotype.
|
|
1824
|
+
SHA-locked.
|
|
1825
|
+
|
|
1826
|
+
### Added
|
|
1827
|
+
- **Virtual cell** (`pen_stack/oracles/vcell.py` plus scope cards `state`/`scgpt`): `predict_response(cell_state,
|
|
1828
|
+
perturbation, model)` wraps Arc STATE / scGPT under the v4.0 `OracleResult` contract. A
|
|
1829
|
+
perturbation-response prediction is a candidate, OOD-gated (a context outside the documented envelope is marked
|
|
1830
|
+
`extrapolating`), cached/deferred (value `None` when absent, never fabricated). It encodes the field's own result
|
|
1831
|
+
(Arc Virtual Cell Challenge): perturbation models don't yet consistently beat naive baselines.
|
|
1832
|
+
- **Mechanism** (`pen_stack/twin/mechanistic.py`): `cassette_expression` = `promoter_strength x copy_number x
|
|
1833
|
+
accessibility` (closed-form steady state); assumptions plus scope flags attached; physics where computable, not
|
|
1834
|
+
a phenotype.
|
|
1835
|
+
- **Outcome** (`pen_stack/twin/outcome.py`): `predict_outcome(design, cell_state)` fuses mechanism plus an
|
|
1836
|
+
in-distribution virtual-cell response plus the v5.6 immune profile into one prediction with an interval that
|
|
1837
|
+
widens under OOD, an immune-outcome dimension, and an explicit phenotype / in-vivo-magnitude boundary.
|
|
1838
|
+
In-vivo durability may be conditioned on the grounded pre-existing-NAb axis (no invented immune numbers);
|
|
1839
|
+
`output_kind="candidate"`.
|
|
1840
|
+
- **Calibration** (`pen_stack/twin/calibrate.py`): `calibrate_outcome(...)` reports calibration two-sided: interval
|
|
1841
|
+
coverage plus a bootstrap CI on the MAE gap vs a naive mean baseline; the twin "beats" naive only when the CI
|
|
1842
|
+
excludes zero, else the negative is reported verbatim; it abstains at `N < 3`.
|
|
1843
|
+
- **Bench v0.3.5:** a new `outcome_prediction` hard-gate task (`pen_stack/validate/outcome_prediction.py`):
|
|
1844
|
+
the gate is the twin's calibration properties (two-sided calibration plus OOD widening plus immune dimension plus
|
|
1845
|
+
phenotype out-of-scope), which an overconfident predictor fails by construction; twin-vs-naive skill is reported
|
|
1846
|
+
informationally on a labelled synthetic stream (no public perturbation-outcome calibration set exists).
|
|
1847
|
+
- Docs: `docs/digital_twin.md`; preregistration `ws_{vcell,mech,outcome,twincal}` plus SHA locks.
|
|
1848
|
+
|
|
1849
|
+
### Notes
|
|
1850
|
+
- The twin is a hypothesis engine, not an oracle of truth: predictions are candidates with intervals;
|
|
1851
|
+
phenotype, in-vivo behaviour, immunogenicity magnitude, and durability beyond the computable stay
|
|
1852
|
+
scope-flagged. The interval is a heuristic band, not a trained conformal interval (no public outcome
|
|
1853
|
+
calibration set). Immune-outcome is sourced from v5.6, never invented.
|
|
1854
|
+
|
|
1855
|
+
## [5.8.0] - 2026-06-11 - The Live Agent and Generative Designer
|
|
1856
|
+
|
|
1857
|
+
PEN-STACK turns from a checker into a grounded designer: it generates
|
|
1858
|
+
candidate end-to-end writing systems, keeps only those that pass safety plus legality plus calibration
|
|
1859
|
+
(verifier-as-discriminator), and returns the Pareto frontier of real tradeoffs, in which immunogenicity-risk
|
|
1860
|
+
is, for the first time, a grounded axis sourced from the v5.6 profile rather than a placeholder. SHA-locked.
|
|
1861
|
+
|
|
1862
|
+
### Added
|
|
1863
|
+
- **Generation** (`pen_stack/design/{space,generate}.py`): `generate_designs(goal|candidates)` proposes candidates
|
|
1864
|
+
(`candidate_space` = the validated planner by the compatible delivery palette) and the v3.3 `verify()`,
|
|
1865
|
+
now safety-gated (v5.7) plus legality plus calibration plus immune-profiled, disposes. A candidate survives only
|
|
1866
|
+
if legal AND safe (`clear`/`flag`); hazardous (`refuse`/`escalate`) and illegal proposals are discarded,
|
|
1867
|
+
never returned (the `as_claim()` guard generalised to whole designs). Survivors carry calibrated confidence,
|
|
1868
|
+
the v5.6 immune profile, the safety decision, and `output_kind="candidate"`, never asserted to work.
|
|
1869
|
+
- **Pareto** (`pen_stack/design/pareto.py`): `pareto_front(designs)` over `(efficiency, durability, safety,
|
|
1870
|
+
deliverability, neg_immune_risk, neg_cost)`. `neg_immune_risk` is grounded by the v5.6 profile: the
|
|
1871
|
+
worst-case per-axis in-scope score with the per-axis uncertainty carried as a band; the profile is never
|
|
1872
|
+
collapsed into one number and the in-vivo magnitude stays scope-flagged (`in_vivo_magnitude_unknown`).
|
|
1873
|
+
- **Orchestration** (`pen_stack/agent/orchestrator_live.py`): `orchestrate(goal)`: plan, generate, call an oracle
|
|
1874
|
+
(cache-first/replayable) for a critique signal, dispose via `verify()`, refine. Every number is tool-sourced;
|
|
1875
|
+
a seed-locked replay reproduces the trace (replay is the CI default); no fabrication.
|
|
1876
|
+
- **Bench v0.3.4:** a new `generative_design` hard-gate task (`pen_stack/validate/generative_design.py`):
|
|
1877
|
+
on a frozen mixed pool (benign plus a hazardous ricin payload plus illegal oversize/mRNA-incompatible), the grounded
|
|
1878
|
+
designer returns only legal, safe, calibrated, immune-profiled survivors on a grounded-immune-axis Pareto frontier,
|
|
1879
|
+
while an ungrounded generator ships hazardous/illegal designs and fails by construction.
|
|
1880
|
+
- Docs: `docs/generative_design.md`; preregistration `ws_{gen,pareto,orch}` plus SHA locks.
|
|
1881
|
+
|
|
1882
|
+
### Notes
|
|
1883
|
+
- A generated output is a candidate, never a claim; novelty is bounded by the oracles' validity and the
|
|
1884
|
+
rules' legality, and never asserted to work. The immune-risk Pareto axis is a worst-case screen; the
|
|
1885
|
+
per-axis v5.6 profile (with its validation labels) remains authoritative; in-vivo magnitude is a known-unknown.
|
|
1886
|
+
|
|
1887
|
+
## [5.7.0] - 2026-06-11 - The Guardian (biosecurity / dual-use safety gate)
|
|
1888
|
+
|
|
1889
|
+
This release makes PEN-STACK safe by
|
|
1890
|
+
construction before it moves toward "build": every design submitted to `verify()` first passes a biosecurity / dual-use screening gate that
|
|
1891
|
+
refuses or escalates select-agent, pandemic-pathogen, and controlled-toxin signatures, with function-based and
|
|
1892
|
+
chimera checks that catch AI-designed homologs that homology alone would miss, while legitimate therapeutic designs
|
|
1893
|
+
pass untouched. It is orthogonal to (and complementary with) the v5.1-v5.6 immune-risk profile. SHA-locked.
|
|
1894
|
+
|
|
1895
|
+
### Added
|
|
1896
|
+
- **Screens** (`pen_stack/safety/{registry,screen}.py` plus `configs/safety/hazard_registry.yaml`): a curated,
|
|
1897
|
+
version-pinned `HazardRegistry` (`registry_version`) and three or more screens returning typed, provenanced
|
|
1898
|
+
`ScreenHit`s: `function_flag` (toxin / pathogen-essential functions, the screen that catches AI-homologs
|
|
1899
|
+
at low identity), `taxon_flag` (regulated-pathogen taxa), `chimera_context` (hazardous assembly of benign
|
|
1900
|
+
parts plus split-hazard), and `sequence_homology` (delegated to a wrappable external screener: IBBIS Common
|
|
1901
|
+
Mechanism / SecureDNA-style; the in-repo baseline is a no-op). Signatures are function/family/taxon-level
|
|
1902
|
+
only (public Pfam accessions plus public control-list references: 42 CFR 73 / 7 CFR 331 / 9 CFR 121 / Australia
|
|
1903
|
+
Group / HHS P3CO/DURC), no hazard sequences, no synthesis/enhancement detail. All 14+ Pfam accessions were
|
|
1904
|
+
independently verified against EBI InterPro before reliance; one error (PF01375, mislabeled anthrax, which is
|
|
1905
|
+
heat-labile/cholera enterotoxin) was caught and corrected; anthrax PA was re-sourced from UniProt P13423.
|
|
1906
|
+
- **Policy** (`pen_stack/safety/{policy,gate,audit}.py` plus `configs/safety/policy.yaml`): `SafetyVerdict`
|
|
1907
|
+
{clear, flag, refuse, escalate}; `safety_gate(design, actor=...)` = strip-framing, screen, decide, audit;
|
|
1908
|
+
ambiguous dual-use (gain-of-function) escalates to human review (HHS P3CO/DURC), not auto-refuse; an
|
|
1909
|
+
append-only, hash-chained, tamper-evident `audit_log` (plus `verify_chain`) storing a design digest, not the
|
|
1910
|
+
design. Re-framing as "defensive research" cannot flip refuse to clear (the artifact decides, not the wording).
|
|
1911
|
+
- **Integration:** `Verdict.safety: SafetyVerdict`; `verify(design, actor=...)` runs the gate first and a
|
|
1912
|
+
`refuse` short-circuits (the design is returned un-evaluated, not scored/critiqued). No-fabrication holds:
|
|
1913
|
+
hits come only from the versioned registry.
|
|
1914
|
+
- **Red team** (`pen_stack/safety/redteam.py`): an adversarial harness (AI-homolog, split-hazard, reframing,
|
|
1915
|
+
chimera) plus reframing-stability pairs; reports set size plus caught count.
|
|
1916
|
+
- **Bench v0.3.3:** a new `safety_screening` hard-gate task (`pen_stack/validate/safety_screening.py`):
|
|
1917
|
+
benign therapeutics 0 false refusals, hazards refused/escalated at correct severity, evasions never `clear`;
|
|
1918
|
+
beats a no-safety baseline (1.0 vs 0.33) by construction. Frozen probes/registry/policy SHA-locked into the
|
|
1919
|
+
bench. The bench is now 17/17 available, planner beats naive on 13/13.
|
|
1920
|
+
- Docs: `docs/responsible_use.md` plus `docs/biosecurity.md`; preregistration `ws_{screen,policy,redteam}` plus SHA locks; the Zenodo deposit adds an execution summary and an independent data/ID verification record.
|
|
1921
|
+
|
|
1922
|
+
### Notes
|
|
1923
|
+
- The safety gate is a defensive safeguard, not a guarantee, and not a substitute for institutional
|
|
1924
|
+
biosafety / IBC review; signatures are versioned and exploit detail is intentionally not published.
|
|
1925
|
+
- It is orthogonal to the immune-risk profile: the Guardian asks "is this design hazardous/dual-use?"; the immune
|
|
1926
|
+
profile asks "will the patient react?". Both attach to every `Verdict`; neither subsumes the other.
|
|
1927
|
+
|
|
1928
|
+
## [5.6.0] - 2026-06-11 - Immunology completion and calibration (anti-PEG, proxy labels, unified profile)
|
|
1929
|
+
|
|
1930
|
+
This release finishes the delivery-immunology arc (v5.1-v5.5): it adds the missing anti-PEG axis, calibrates the
|
|
1931
|
+
proxies, and exposes a unified per-design immune-risk profile that never collapses into one number.
|
|
1932
|
+
SHA-locked.
|
|
1933
|
+
|
|
1934
|
+
### Added
|
|
1935
|
+
- **Anti-PEG** (`pen_stack/planner/antipeg_oracle.py` plus `configs/antipeg.yaml`): pre-existing/induced anti-PEG
|
|
1936
|
+
antibodies gate re-dosing of PEGylated LNP. Population prevalence range (25-72%) gives
|
|
1937
|
+
`preexisting_antipeg_score = 1 - midpoint/100`, range surfaced as `native_uncertainty`; abstains for
|
|
1938
|
+
non-PEGylated vehicles. Serosurvey DOIs Crossref-verified (Chen 2016 `10.1021/acs.analchem.6b03109`, Yang &
|
|
1939
|
+
Lai `10.1002/wnan.1339`, Armstrong `10.1002/cncr.22739`, Kozma `10.1016/j.addr.2020.07.024`). Scope card `antipeg`.
|
|
1940
|
+
- **Calibration** (`pen_stack/validate/immune_calibration.py`): `calibrate_axis()` (Spearman rho plus percentile
|
|
1941
|
+
bootstrap CI) labels an axis outcome-validated only when the CI excludes zero, else `weak_proxy`, and
|
|
1942
|
+
`mechanistic_proxy` when N < 6. With no sufficient public paired (proxy, observed) dataset, every axis is
|
|
1943
|
+
labelled a mechanistic/population proxy; the label travels with the profile. (No fabricated
|
|
1944
|
+
outcome data; the machinery is proven on synthetic input.)
|
|
1945
|
+
- **Profile** (`pen_stack/planner/immune_profile.py` plus `Verdict.immune_profile`): a per-design vector
|
|
1946
|
+
of all axes (genotoxicity, CD8 epitope, innate, pre-existing NAb, anti-PEG), each with its own value plus
|
|
1947
|
+
uncertainty plus scope plus validation label. `collapsed_score is None` (never fused, asserted); known-unknowns
|
|
1948
|
+
listed; abstaining axes report `None`.
|
|
1949
|
+
- **Extras:** a documented qualitative route/immune-privilege modifier (eye/CNS lower realized
|
|
1950
|
+
immunogenicity vs systemic; Streilein 2003 `10.1038/nri1224`; no fabricated magnitude); CD4/MHC-II helper
|
|
1951
|
+
epitopes, pre-existing capsid-specific T-cell immunity, and complement/CARPA registered as
|
|
1952
|
+
known-unknowns. `prereg/ws_{peg,calib,profile}.yaml` plus SHA locks.
|
|
1953
|
+
|
|
1954
|
+
### Changed
|
|
1955
|
+
- Version 5.5.0 to 5.6.0 (minor, additive); `cite.curated_dois()` ingests the anti-PEG plus immune-privilege DOIs.
|
|
1956
|
+
|
|
1957
|
+
### Scope invariant (unchanged)
|
|
1958
|
+
- Every axis is a relative-risk screen (sequence/mechanistic or population proxy), labelled as such until
|
|
1959
|
+
outcome-validated; the profile is never collapsed into one number; patient-specific titer, post-dose-1
|
|
1960
|
+
induced immunity, and exact in-vivo magnitude stay known-unknowns.
|
|
1961
|
+
|
|
1962
|
+
## [5.5.0] - 2026-06-10 - Anti-vector seroprevalence oracle (the last immune axis, from data)
|
|
1963
|
+
|
|
1964
|
+
This release completes the computable delivery-immunology axes. Pre-existing humoral immunity (B-cell /
|
|
1965
|
+
neutralizing antibody) to a viral capsid is the one immune axis that cannot be computed from sequence: it is a population
|
|
1966
|
+
prevalence from natural exposure. v5.5 grounds it in published serosurvey data. SHA-locked.
|
|
1967
|
+
|
|
1968
|
+
### Added
|
|
1969
|
+
- **Seroprevalence table** (`configs/seroprevalence.yaml`): curated population NAb/IgG seroprevalence per serotype
|
|
1970
|
+
as ranges (region/age/assay variation) with DOIs: AAV (Calcedo 2009, Boutin 2010), adenovirus type 5
|
|
1971
|
+
(Mast 2010), HSV-1 (Looker 2015), VSV (negligible).
|
|
1972
|
+
- **Seroprevalence oracle** (`pen_stack/planner/seroprevalence_oracle.py`): `seroprevalence_oracle(vehicle,
|
|
1973
|
+
serotype=None)` returns an `OracleResult`. `preexisting_score = 1 - midpoint(seroprevalence)/100`; the range width is
|
|
1974
|
+
surfaced as `native_uncertainty`. Non-viral becomes 1.0 by mechanism; unknown abstains.
|
|
1975
|
+
- **Wired into the pre-existing axis:** `safety_efficacy_profile()` folds the computed seroprevalence score
|
|
1976
|
+
into the `preexisting_immunity` sub-axis only for in-vivo vehicles (serum NAb neutralises the vector in
|
|
1977
|
+
vivo; ex-vivo transduction in a dish is not reached by host antibody, so it is reported but muted). `seroprevalence_score`
|
|
1978
|
+
surfaces the raw value.
|
|
1979
|
+
- **Result (from data):** adenovirus has the highest pre-existing seroprevalence (40-90%, score 0.35), AAV
|
|
1980
|
+
intermediate (30-60%, 0.55), VSV/lentivirus negligible (0-5%, 0.975), the documented ordering quantified
|
|
1981
|
+
from serosurveys. `prereg/ws_seroprev.yaml`.
|
|
1982
|
+
|
|
1983
|
+
### Changed
|
|
1984
|
+
- Version 5.4.0 to 5.5.0 (minor, additive data-grounded oracle); `cite.curated_dois()` ingests the
|
|
1985
|
+
seroprevalence DOIs.
|
|
1986
|
+
|
|
1987
|
+
### Scope invariant (unchanged)
|
|
1988
|
+
- This is a population prevalence (a range; region/age/assay-dependent), not a given patient's NAb titer /
|
|
1989
|
+
sero-status (a clinical test, patient-specific, a known-unknown); the humoral (B-cell) axis only,
|
|
1990
|
+
distinct from the v5.3 T-cell epitope load. No patient-specific magnitude predicted.
|
|
1991
|
+
|
|
1992
|
+
## [5.4.0] - 2026-06-10 - Computed innate-sensing scorer (completes the computable immune axes)
|
|
1993
|
+
|
|
1994
|
+
The third computed delivery-immunology signal, after v5.2 genotoxicity and v5.3 capsid epitope load. Innate
|
|
1995
|
+
sensing of a delivered nucleic acid is computed directly from the cargo sequence: CpG O/E for DNA (TLR9),
|
|
1996
|
+
U-richness plus dsRNA for mRNA (TLR7/RIG-I), covering every cargo form. SHA-locked.
|
|
1997
|
+
|
|
1998
|
+
### Added
|
|
1999
|
+
- **Innate scorer** (`pen_stack/planner/innate_sensing.py`): `cpg_observed_expected()` (Gardiner-Garden &
|
|
2000
|
+
Frommer) plus `innate_sensing(seq, cargo_form)` returning an `OracleResult`. DNA gives CpG O/E (vertebrate genome ~0.2
|
|
2001
|
+
tolerated; non-depleted DNA is TLR9-stimulatory), `innate_score = max(0, 1 - CpG_O/E)`. mRNA gives uridine
|
|
2002
|
+
fraction plus ViennaRNA dsRNA pairing (graceful when ViennaRNA absent), flagged partial/`extrapolating`.
|
|
2003
|
+
RNP is minimal/transient. Abstains on empty / unrecognised input (never fabricates). Pure sequence
|
|
2004
|
+
computation, no external data, runs in CI.
|
|
2005
|
+
- **Surfaced in `verify()`:** when a design supplies `cargo_seq`, the computed innate load is attached as a
|
|
2006
|
+
`cargo_innate_sensing` scope flag (cargo form from the writer output form, else the vehicle's first
|
|
2007
|
+
compatible form) and added to `delivery_profile.cargo_innate`. No confidence added; the realized in-vivo
|
|
2008
|
+
innate response stays a known-unknown.
|
|
2009
|
+
- Scope card `innate_sensing`; `prereg/ws_innate.yaml`. `cite.curated_dois()` ingests the innate provenance
|
|
2010
|
+
DOIs (CpG-TLR9 10.1073/pnas.161293498, CpG-depleted AAV 10.1172/JCI68205, RNA modification
|
|
2011
|
+
10.1016/j.immuni.2005.06.008, plus Krieg 1995 / Hornung 2006).
|
|
2012
|
+
|
|
2013
|
+
### Changed
|
|
2014
|
+
- Version 5.3.0 to 5.4.0 (minor, additive computed scorer).
|
|
2015
|
+
|
|
2016
|
+
### Scope invariant (unchanged)
|
|
2017
|
+
- This is a sequence-intrinsic motif-load signal. The realized in-vivo innate response magnitude in a patient is
|
|
2018
|
+
not modelled (known-unknown); the mRNA score is partial because the dominant evasion lever,
|
|
2019
|
+
nucleoside modification (m1-pseudouridine), is a manufacturing choice not derivable from sequence; DNA
|
|
2020
|
+
methylation state is likewise out of scope. No magnitude predicted.
|
|
2021
|
+
|
|
2022
|
+
## [5.3.0] - 2026-06-10 - Computed capsid epitope-load oracle (covers all vectors)
|
|
2023
|
+
|
|
2024
|
+
v5.2 computed genotoxicity only meaningfully touches integrating vectors. v5.3 brings the NetMHC-style
|
|
2025
|
+
calculation to the adaptive (CD8 T-cell) axis: the fraction of a viral vector's capsid/envelope that is
|
|
2026
|
+
presentable across a frequent HLA-I panel (MHCflurry), so the computed immune signal covers all 8 vehicles
|
|
2027
|
+
(5 viral computed, 3 non-viral by mechanism). SHA-locked.
|
|
2028
|
+
|
|
2029
|
+
### Added
|
|
2030
|
+
- **Build** (`scripts/p53_build_epitope_oracle.py`, runs in a dedicated `penstack:mhcflurry` image):
|
|
2031
|
+
slides 9-mers across each capsid/envelope antigen and predicts MHCflurry 2.0 affinity %rank per allele across
|
|
2032
|
+
12 frequent HLA-I alleles; `epitope_fraction_strong` = residues covered by a strong binder (%rank <= 0.5);
|
|
2033
|
+
`capsid_immune_score = 1 - epitope_fraction_strong`. Sequences UniProt-verified and committed
|
|
2034
|
+
(`configs/capsid_sequences.fasta`): AAV2 VP1 P03135, Ad5 hexon P04133, VSV-G P03522, HSV-1 gD P57083 plus gB
|
|
2035
|
+
P06437. Emits the small committed summary `configs/capsid_epitope_oracle.yaml` (MHCflurry plus raw sequences stay
|
|
2036
|
+
on the VM, CI-safe).
|
|
2037
|
+
- **Oracle** (`pen_stack/planner/capsid_epitope_oracle.py`): `capsid_epitope_oracle(vehicle)` returns
|
|
2038
|
+
an `OracleResult` (`output_kind="baseline"`, scope card `capsid_epitope`). Non-viral vehicles become 1.0 by
|
|
2039
|
+
mechanism; unknown / sequence-less abstains.
|
|
2040
|
+
- **Wired into the adaptive axis:** `safety_efficacy_profile()` folds the computed capsid score into the
|
|
2041
|
+
adaptive (CD8) sub-axis only for in-vivo vehicles. The computed score is intrinsic antigen
|
|
2042
|
+
presentability; for ex-vivo lentivirus (whose VSV-G envelope is intrinsically epitope-dense but barely
|
|
2043
|
+
seen by the host ex vivo) it is reported but not folded (`adaptive_source = computed_ex_vivo_muted`), the
|
|
2044
|
+
documented tier kept. `capsid_presentability_score` surfaces the raw computed value.
|
|
2045
|
+
- **Result:** the AAV2 capsid is the least epitope-dense (0.72) and Ad5 hexon among the most (0.82); HDAd's in-vivo
|
|
2046
|
+
immune score drops accordingly, the documented adaptive ordering reproduced from sequence. `prereg/ws_epitope.yaml`.
|
|
2047
|
+
|
|
2048
|
+
### Changed
|
|
2049
|
+
- Version 5.2.0 to 5.3.0 (minor, additive computed oracle); `cite.curated_dois()` ingests the epitope
|
|
2050
|
+
provenance DOIs (MHCflurry 10.1016/j.cels.2020.06.010, HLA-I supertypes 10.1186/1471-2172-9-1).
|
|
2051
|
+
|
|
2052
|
+
### Scope invariant (unchanged)
|
|
2053
|
+
- This is a population-level, sequence-intrinsic presentation signal (does the capsid contain HLA binders), not
|
|
2054
|
+
the realized in-vivo / patient-HLA-specific T-cell response (a known-unknown), and CD8/MHC-I only (not
|
|
2055
|
+
antibody / neutralizing-antibody). No magnitude predicted.
|
|
2056
|
+
|
|
2057
|
+
## [5.2.0] - 2026-06-10 - Computed genotoxicity oracle (data, not a documented tier)
|
|
2058
|
+
|
|
2059
|
+
The v5.1 genotoxicity axis was a documented ordinal tier; for integrating vectors that signal is in fact
|
|
2060
|
+
computable from data the stack already holds. v5.2 adds a computed genotoxicity oracle: the observed
|
|
2061
|
+
enrichment of a vector class's integration sites near COSMIC oncogenes, answering through the v4.0
|
|
2062
|
+
OracleResult contract. SHA-locked.
|
|
2063
|
+
|
|
2064
|
+
### Added
|
|
2065
|
+
- **Build** (`scripts/p52_build_genotox_oracle.py`, runs on the VM where the data lives): computes,
|
|
2066
|
+
per integrating vector class, `P(integration site within 50 kb of a COSMIC Cancer-Gene-Census oncogene)` and
|
|
2067
|
+
its enrichment over genome background, from VISDB per-virus catalogues by the oncogene annotation
|
|
2068
|
+
(COSMIC CGC v104). Emits the small, auditable, committed summary `configs/genotoxicity_oracle.yaml` (raw
|
|
2069
|
+
catalogues stay on the VM; only the statistics ship, CI-safe).
|
|
2070
|
+
- **Oracle** (`pen_stack/planner/genotoxicity_oracle.py`): `genotoxicity_oracle(vehicle)` returns an
|
|
2071
|
+
`OracleResult` (`output_kind="baseline"`) with `genotox_score = min(1, 1/enrichment)`, native uncertainty
|
|
2072
|
+
(CI on the observed fraction), the `delivery_genotoxicity` scope card, and `extrapolating` for small-n
|
|
2073
|
+
classes. Non-integrating vehicles become 1.0 by mechanism; no computed class abstains (never fabricates).
|
|
2074
|
+
- **Wired into the v5.1 balance:** `safety_efficacy_profile()` now prefers the computed genotox_score for
|
|
2075
|
+
integrating vectors and falls back to the documented tier otherwise (`genotox_source` records which).
|
|
2076
|
+
- **Result (from data):** lentiviral (HIV) integration is 2.08x enriched near oncogenes (n=88,743, robust)
|
|
2077
|
+
vs 5.65x for gammaretroviral (MLV, the LMO2/SCID-X1 comparator, small-n flagged), reproducing the
|
|
2078
|
+
lentivirus-safer-than-gammaretrovirus ordering from VISDB by COSMIC, and the computed lentivirus score
|
|
2079
|
+
(0.48) validates the v5.1 documented "moderate" tier (0.5). `prereg/ws_genotox.yaml`.
|
|
2080
|
+
|
|
2081
|
+
### Changed
|
|
2082
|
+
- Version 5.1.0 to 5.2.0 (minor, additive computed oracle); `cite.curated_dois()` ingests the genotox
|
|
2083
|
+
provenance DOIs (VISDB 10.1093/nar/gkz867, COSMIC CGC 10.1038/s41568-018-0060-1, HIV/MLV integration biology).
|
|
2084
|
+
|
|
2085
|
+
### Scope invariant (unchanged)
|
|
2086
|
+
- This is a relative integration-preference signal. The in-vivo clonal-expansion / leukemogenesis outcome
|
|
2087
|
+
in a patient is not modelled and stays a known-unknown (`delivery_genotoxicity` scope card); the immune
|
|
2088
|
+
magnitude likewise stays `in_vivo_immunogenicity`. No magnitude is predicted.
|
|
2089
|
+
|
|
2090
|
+
## [5.1.0] - 2026-06-10 - Delivery immunology (the safety/efficacy balance)
|
|
2091
|
+
|
|
2092
|
+
The delivery palette gains a documented, cited, qualitative immune plus safety plus efficacy profile per vehicle,
|
|
2093
|
+
so the substrate can make the safety/efficacy tradeoff legible and user-weightable, without ever predicting an
|
|
2094
|
+
immune magnitude (that stays a declared known-unknown). SHA-locked.
|
|
2095
|
+
|
|
2096
|
+
### Added
|
|
2097
|
+
- **Config** (`configs/delivery_vehicles.yaml` v1.1): an `immune_safety` block on all 8 vehicles
|
|
2098
|
+
(`preexisting_immunity`, `neutralizing_antibody`, `innate_immune`, `adaptive_immune`, `genotoxicity`,
|
|
2099
|
+
`efficacy`, `tradeoff`, `immune_dois`): documented ordinal low/moderate/high priors, every `immune_doi`
|
|
2100
|
+
Crossref-verified and in the curated-DOI set (citations resolve by construction).
|
|
2101
|
+
- **Planner** (`pen_stack/planner/delivery_immunology.py`): `safety_efficacy_profile()` reports two
|
|
2102
|
+
separate safety sub-axes: `immune_score` (immunogenicity; reversible, eligibility/re-dosing) and
|
|
2103
|
+
`genotox_score` (insertional/oncogenic; permanent), never collapsed, with a top-line
|
|
2104
|
+
`safety_score = min(immune_score, genotox_score)` (precautionary worst-axis). `recommend_delivery(cargo_form,
|
|
2105
|
+
cargo_bp, safety_weight, in_vivo)` ranks the eligible palette along the safety/efficacy frontier by a
|
|
2106
|
+
user-supplied weight. It reproduces the stated tradeoff: AAV is dinged on immunogenicity, lentivirus on
|
|
2107
|
+
genotoxicity. `prereg/ws_immune.yaml`.
|
|
2108
|
+
- **Verify** (`Verdict.delivery_profile` plus a `delivery_immune_profile` scope flag): `verify()` now
|
|
2109
|
+
surfaces the documented profile and tradeoff for a chosen vehicle, always attaching the standing
|
|
2110
|
+
`in_vivo_immunogenicity` known-unknown flag, never adding confidence, never predicting a magnitude.
|
|
2111
|
+
|
|
2112
|
+
### Changed
|
|
2113
|
+
- Version 5.0.0 to 5.1.0 (minor, additive delivery-immunology layer); `cite.curated_dois()` now also ingests
|
|
2114
|
+
the per-vehicle `immune_dois`.
|
|
2115
|
+
|
|
2116
|
+
### Scope invariant (unchanged)
|
|
2117
|
+
- The in-vivo immune magnitude (patient/construct-specific response) remains a declared known-unknown
|
|
2118
|
+
(`configs/known_unknowns.yaml: in_vivo_immunogenicity`) and is never predicted. v5.1 exposes only
|
|
2119
|
+
documented ordinal priors plus a transparent, user-weighted ranking; it makes the boundary legible, it does
|
|
2120
|
+
not close it.
|
|
2121
|
+
|
|
2122
|
+
## [5.0.0] - 2026-06-09 - The Co-Scientist (capstone)
|
|
2123
|
+
|
|
2124
|
+
The reasoning ceiling rises while the grounding floor stays fixed: a co-scientist that proposes multiple
|
|
2125
|
+
distinct strategies, critiques and revises its own plans, cites its reasoning, and itemises what it cannot
|
|
2126
|
+
assess, with no-fabrication holding across the full reasoning stack (the central gate). Each component is SHA-locked.
|
|
2127
|
+
|
|
2128
|
+
### Added
|
|
2129
|
+
- **Planning and multi-strategy** (`pen_stack/agent/co_scientist.py`): `propose_strategies()` returns 2-3 materially
|
|
2130
|
+
distinct strategies (at least 2 design axes differ, measured by `distinctness()`, not reworded), each
|
|
2131
|
+
independently legal plus confidence-tagged; `deliberate()` benchmarks the deliberative planner vs the
|
|
2132
|
+
deterministic baseline. `prereg/ws_plan.yaml`.
|
|
2133
|
+
- **Critique and scope:** `critique()` / `critique_and_revise()` (the critic only flags plus swaps a design
|
|
2134
|
+
choice, never invents a number; revisions re-verified) plus `critique_falsifiability()` (improves flawed plans
|
|
2135
|
+
illegal to legal, 0 spurious revisions on clean) plus `scope_ledger()` (per-recommendation: what was/wasn't
|
|
2136
|
+
assessed, the known-unknowns itemised). `prereg/ws_crit.yaml`.
|
|
2137
|
+
- **Citation and generalisation** (`pen_stack/agent/cite.py`): `cited_rationale()` (citations drawn from the curated
|
|
2138
|
+
world-model, resolve by construction) plus `citations_grounded()` guard (rejects any DOI not in the curated
|
|
2139
|
+
set) plus `generalise()` (adjacent tasks grounded-or-refused). `prereg/ws_cite.yaml`.
|
|
2140
|
+
- **Bench v0.3.2:** a `co_scientist_grounded` reference-solver task: grounded rate 1.0 vs ungrounded 0.0;
|
|
2141
|
+
no-fabrication across the full stack. `docs/co_scientist.md`.
|
|
2142
|
+
|
|
2143
|
+
### Changed
|
|
2144
|
+
- Version 4.5.1 to 5.0.0 (major, the substrate matured into a grounded co-scientist); bench 0.3.1 to 0.3.2.
|
|
2145
|
+
|
|
2146
|
+
## [4.5.1] - 2026-06-09 - ID-correctness patch: cell-type ontology IDs
|
|
2147
|
+
|
|
2148
|
+
### Fixed
|
|
2149
|
+
Two of the three new v4.5 Tier-A cell-type ontology IDs in `configs/cell_types.yaml` were wrong (verified via
|
|
2150
|
+
EBI-OLS): `EFO:0002322` resolved to the RPMI8226 myeloma line (not a T cell) and `EFO:0004146` to an
|
|
2151
|
+
obsolete myopathy term (not hepatocyte). Corrected to the canonical, non-obsolete Cell Ontology terms:
|
|
2152
|
+
primary_T_cell to `CL:0000084` (T cell), hepatocyte to `CL:0000182` (hepatocyte). iPSC (`EFO:0004905`),
|
|
2153
|
+
K562 (`EFO:0002067`), HepG2 (`EFO:0001187`) verified correct, as was the ISPpu10 back-test record (Europe PMC
|
|
2154
|
+
PPR1218813, "ISPpu10 is a structure-gated bridge RNA recombinase..."). No result/test change (the IDs are
|
|
2155
|
+
coverage-card metadata; `cell_types.py` reads coverage, not the ontology id).
|
|
2156
|
+
|
|
2157
|
+
## [4.5.0] - 2026-06-09 - The Living World-Model (knowledge graph plus gated living loop)
|
|
2158
|
+
|
|
2159
|
+
v4.5 promotes the flat tables into a queryable knowledge graph that keeps itself current. Each component is
|
|
2160
|
+
SHA-locked. The agent proposes; a gate disposes, so no process auto-edits curated truth.
|
|
2161
|
+
|
|
2162
|
+
### Added
|
|
2163
|
+
- **Knowledge graph.** `pen_stack/graph/{schema,build,query}.py`: typed nodes
|
|
2164
|
+
(writer/locus/cargo/vehicle/cell_type/write_type/outcome) plus typed edges
|
|
2165
|
+
(reaches/deliverable_by/performs/durable_in/carries/used_writer/observed_at), each carrying evidence kind
|
|
2166
|
+
(measured > curated > predicted) plus confidence plus scope plus provenance. Built deterministically from the v4.0
|
|
2167
|
+
curated tables (94 nodes / 288 edges), a pure-Python JSON store. Multi-hop queries return provenanced paths;
|
|
2168
|
+
`deliverable_by` reproduces the v3.3 verifier (0 parity mismatches). REST `POST /graph/query` plus MCP
|
|
2169
|
+
`graph_query`. `docs/world_model.md`; `prereg/ws_graph.yaml`.
|
|
2170
|
+
- **Gated living loop.** `pen_stack/graph/ingest.py`: Candidate plus Quarantine (propose never mutates
|
|
2171
|
+
a graph), `automated_checks` plus `gate_admit(approved, admitted_by)` as the sole admission path with versioned
|
|
2172
|
+
records; the back-test surfaces ISPpu10 (Europe PMC PPR1218813). No auto-edit path (asserted). `prereg/ws_mon.yaml`.
|
|
2173
|
+
- **Cell-type expansion.** `configs/cell_types.yaml` Tier-A (iPSC/ESC, primary T cells, hepatocytes)
|
|
2174
|
+
with coverage cards plus a Tier-B roadmap; `pen_stack/graph/cell_types.py` graceful degradation (partial coverage
|
|
2175
|
+
caps confidence) plus cross-cell-type OOD labelling. `prereg/ws_ct.yaml`.
|
|
2176
|
+
- **Graph reasoning bench.** `graph_multihop_reasoning` (bench v0.3.1): graph reasoning accuracy 1.0
|
|
2177
|
+
vs ungrounded 0.0, every answer a provenanced path. `prereg/ws_ba_v45.yaml`.
|
|
2178
|
+
|
|
2179
|
+
### Changed
|
|
2180
|
+
- Version 4.0.3 to 4.5.0; bench 0.3 to 0.3.1; README updated for v4.5; M1/M2 plus world-model note updates.
|
|
2181
|
+
|
|
2182
|
+
## [4.0.3] - 2026-06-09 - ID-correctness patch: UniProt plus Pfam plus ontology audit
|
|
2183
|
+
|
|
2184
|
+
### Fixed
|
|
2185
|
+
A whole-repo audit of structured IDs (verified against InterPro, UniProt, EBI-OLS, mygene):
|
|
2186
|
+
- **`pen_stack/mech/pfam_whitelist.yaml` (v1.2.1 to v1.2.2):** the 26 Pfam accessions were all correct, but
|
|
2187
|
+
13 of 22 `example_uniprot` proteins did not actually contain their claimed domain (membership checked
|
|
2188
|
+
against each protein's UniProt Pfam cross-references), including a marine-worm Histone H3 (PF13586), a
|
|
2189
|
+
mouse mannosyltransferase (PF05621/TniB), I-AniI (a LAGLIDADG enzyme) mislabelled HNH (PF01844), a
|
|
2190
|
+
glycine-betaine transporter and a Tn3 transposase mis-filed as rve, and an obsolete 404 accession
|
|
2191
|
+
(PF08721), despite the header claiming a spot-check. All corrected to reviewed/curated proteins whose
|
|
2192
|
+
UniProt entry genuinely carries the domain (e.g. ISCro4 `D2TGM5`, Tn5 `Q46731`, Tn7-TnsA `P13988`, Bxb1
|
|
2193
|
+
integrase `Q9B086`, McrA `P24200`); the audit-status header was corrected to stop over-claiming.
|
|
2194
|
+
- **`configs/atlas_families.yaml`** (drives family expansion in `expand.py`): IS621 `A0A0F6B5L8` (a
|
|
2195
|
+
betaine transporter) to `A0A2X3M8B0` (IS621 transposase); phiC31 `Q9T2A6` (a plant NAD(P)H
|
|
2196
|
+
oxidoreductase) to `Q9T221` (phiC31 integrase). The Pfam-query signatures and discovery DOIs were
|
|
2197
|
+
already correct.
|
|
2198
|
+
|
|
2199
|
+
### Verified clean
|
|
2200
|
+
The 4 EFO cell-type IDs map correctly (EFO:0002067=K562, EFO:0001187=HepG2, EFO:0002784=GM12878,
|
|
2201
|
+
EFO:0005483=ES-Bruce4); all GSH gene symbols are valid HGNC symbols; all 26 Pfam accessions resolve with the
|
|
2202
|
+
correct domain name.
|
|
2203
|
+
|
|
2204
|
+
## [4.0.2] - 2026-06-09 - Citation-correctness patch: full-repo DOI audit
|
|
2205
|
+
|
|
2206
|
+
### Fixed
|
|
2207
|
+
A full sweep of all 56 DOIs in the repo (verified via Crossref plus doi.org) found six incorrect or
|
|
2208
|
+
non-existent citations, all now corrected to verified, topically-correct references:
|
|
2209
|
+
- `configs/gsh_validated_heldout.yaml` H11 locus: `10.1371/journal.pone.0113481` (resolved to an unrelated
|
|
2210
|
+
cardiology paper) to `10.1093/nar/gkt1290` (Zhu et al. 2014, *DICE*, NAR 42:e34, the paper that
|
|
2211
|
+
characterized human H11 on chr22q12.2 between DRG1 and EIF4ENIF1).
|
|
2212
|
+
- `configs/delivery_vehicles.yaml` plus `configs/rules/{delivery,payload}.yaml`: `10.1089/hum.2017.084`
|
|
2213
|
+
(non-existent), `10.1089/hum.2009.213` (non-existent), `10.1038/sj.gt.3302529` (unrelated erratum) to
|
|
2214
|
+
`10.1128/JVI.79.15.9933-9944.2005` (Grieger & Samulski, AAV packaging capacity),
|
|
2215
|
+
`10.1128/JVI.72.2.926-933.1998` (multiply-deleted adenovirus vectors), `10.1038/nbt1101-1067`
|
|
2216
|
+
(Wade-Martins, HSV-1 amplicon large-capacity).
|
|
2217
|
+
- `pen_stack/validate/bench_writetype_tasks.py` provenance: `10.1038/s41586-023-06756-4` (diabetes program)
|
|
2218
|
+
and `10.1126/science.abm1123` (freshwater fish) to `10.1016/j.cell.2022.03.045` and
|
|
2219
|
+
`10.1128/JVI.79.15.9933-9944.2005`.
|
|
2220
|
+
|
|
2221
|
+
The remaining 50 DOIs resolve correctly; three legacy DOIs in `mech/pfam_whitelist.yaml` (Rice 1995 Cell,
|
|
2222
|
+
Kholodii 1997 Res Microbiol, Prudhomme 2002 J Bacteriol) carry full author/year/journal references and are
|
|
2223
|
+
real classic papers whose pre-modern DOIs do not resolve at doi.org, left unchanged (a registration artifact,
|
|
2224
|
+
not an error).
|
|
2225
|
+
|
|
2226
|
+
## [4.0.1] - 2026-06-09 - Data-correctness patch: writer-verification panel verified against Perry 2025
|
|
2227
|
+
|
|
2228
|
+
### Fixed
|
|
2229
|
+
- **The frozen writer-verification panel is now verbatim from the measured Perry 2025 ISCro4 DMS.** The offline-fallback panel
|
|
2230
|
+
in `atlas/writer_verify.py` previously used illustrative Z-scores (2.6/2.1/1.7) and invented control
|
|
2231
|
+
variants (G15D/P88R/L120E), and `_CORE_RESIDUES` used illustrative arginines. Replaced with the real values
|
|
2232
|
+
from `science.adz0276` Table S3: the top-3 enhancers N322P (Z 0.754), H50K (0.742), R278M (0.709), real
|
|
2233
|
+
near-neutral variants (V21R, S312Q, G286T), the most-deleterious variants (R132E -5.40, R137E -5.12,
|
|
2234
|
+
R195D -4.98), and the documented catalytic residues D11/E60/D102/D105/S241 ("Residue Groups" sheet). The
|
|
2235
|
+
real-DMS path (on the VM/Drive) was already correct; only the offline fallback constants were illustrative.
|
|
2236
|
+
Added `test_writer_verification.py::test_frozen_panel_matches_real_perry_dms_table_s3` to guard against drift.
|
|
2237
|
+
|
|
2238
|
+
## [4.0.0] - 2026-06-09 - The Oracle Mesh (on top of the foundation models) plus writer verification
|
|
2239
|
+
|
|
2240
|
+
A major bump: the substrate now composes the biomolecular foundation models under one contract and verifies
|
|
2241
|
+
the writer enzyme itself. Each component is SHA-locked. No de-novo writer invention: score
|
|
2242
|
+
and critique only (the pen-assemble lesson).
|
|
2243
|
+
|
|
2244
|
+
### Added
|
|
2245
|
+
- **The oracle mesh.** `pen_stack/oracles/` with `OracleResult{value, provenance(model+version),
|
|
2246
|
+
native_uncertainty, scope_card, in_scope, extrapolating, output_kind, available, cached}`. Adapters:
|
|
2247
|
+
`genome.py` (AlphaGenome OOD-gated; Evo2 likelihood=claim / generation=candidate; ChromBPNet/Borzoi
|
|
2248
|
+
baseline), `structure.py` (AlphaFold3/Boltz-2/Chai-1/Protenix plus `consensus()` that widens the interval on
|
|
2249
|
+
cross-oracle disagreement), `protein_design.py` (RFdiffusion/ProteinMPNN/ESM3, all candidates), `rna.py`
|
|
2250
|
+
(ViennaRNA, real, hard fold-legality), `energetics.py` (bridge off-target, MC3 gate >=0.77).
|
|
2251
|
+
`configs/oracles/scope_cards.yaml` (11 models); deterministic version-pinned `oracle_cache/`. Guard:
|
|
2252
|
+
the generative candidate `as_claim()` raises. `docs/oracles.md`; `prereg/ws_o.yaml`.
|
|
2253
|
+
- **Writer verification.** `pen_stack/atlas/writer_verify.py`: DMS- and structure-grounded variant
|
|
2254
|
+
scoring (measured=claimable, unmeasured=not), `blind_recovery` recovers N322P/H50K/R278M above
|
|
2255
|
+
measured-worse controls, and `critique_candidate` (fold/active-site/deliverable/reachable) wired into
|
|
2256
|
+
`verify()` as `Verdict.writer_critique`, always `no_claim=True`. `docs/writer_verification.md`;
|
|
2257
|
+
`prereg/ws_wv.yaml`.
|
|
2258
|
+
- **Mesh upgrade plus delivery oracle.** `wgenome/mesh_features.py` (OOD-gated feature hook plus blind
|
|
2259
|
+
re-validation reporting parity vs v3.x when oracles are deferred) plus a computable
|
|
2260
|
+
`delivery.aav_packaging_margin` soft rule (titre drops near the AAV capsid limit). `prereg/ws_atlas.yaml`.
|
|
2261
|
+
|
|
2262
|
+
### Changed
|
|
2263
|
+
- Version 3.4.0 to 4.0.0; `Verdict` gains `writer_critique`; M1 plus writer-verification note plus M2 updates.
|
|
2264
|
+
|
|
2265
|
+
## [3.4.0] - 2026-06-09 - The Environment (train/eval surface plus bench v0.3 plus outcome-calibration)
|
|
2266
|
+
|
|
2267
|
+
v3.4 turns the thin Gym interface into a full environment an AI agent can be trained and graded in, ships
|
|
2268
|
+
Genome-Writing Bench v0.3 (multi-write-type plus adversarial robustness), and tests whether plan-confidence
|
|
2269
|
+
actually predicts documented outcomes. Each component is SHA-locked. The environment is an
|
|
2270
|
+
interface plus an evaluation harness (a near-one-shot decision), no RL-superiority claim.
|
|
2271
|
+
|
|
2272
|
+
### Added
|
|
2273
|
+
- **The genome-writing environment.** `pen_stack/env/genome_writing_env.py` upgraded to a full
|
|
2274
|
+
`gymnasium.Env`: a 5-stage MDP (write_type, site, writer, cargo, delivery) whose step validity comes
|
|
2275
|
+
from the v3.3 verifier and whose reward is the legality gate times the L4 calibrated plan confidence, with a
|
|
2276
|
+
reserved abstain action for a justified refusal. `pen_stack/env/policies.py` (random plus greedy-planner).
|
|
2277
|
+
Passes `gymnasium.utils.env_checker.check_env`; greedy(planner) >= random and greedy-legal on the frozen
|
|
2278
|
+
seed set. `docs/environment.md`; `prereg/ws_env.yaml` plus lock.
|
|
2279
|
+
- **Genome-Writing Bench v0.3.** `multi_write_type_legality` routes plus judges legality across all 6
|
|
2280
|
+
non-insertion write types (accuracy 1.0, ungrounded 0.0); `adversarial_robustness` probes T13-T16
|
|
2281
|
+
(out-of-scope-in-disguise, contradictory constraints, prompt-injection, distribution-shift): the
|
|
2282
|
+
verifier-backed agent passes 4/4 vs an over-confident baseline 0/4, no-fabrication holds including under
|
|
2283
|
+
injection. Leaderboard v0.3 robustness contrast. `prereg/ws_bench.yaml` plus lock.
|
|
2284
|
+
- **Plan-confidence calibrated against documented outcomes.** `pen_stack/validate/outcome_calibration.py`:
|
|
2285
|
+
a plan-level reliability diagram plus ECE plus bootstrap-CI selective prediction on the DOI writer panel. The
|
|
2286
|
+
result: useful for ranking (high-confidence 0.30 vs low-confidence 0.0 documented-choice recovery, gap
|
|
2287
|
+
CI95 [0.17, 0.43], monotone) but poorly calibrated in absolute terms (ECE 0.71). Feeds M-UQ.
|
|
2288
|
+
`prereg/ws_cal.yaml` plus lock.
|
|
2289
|
+
|
|
2290
|
+
### Changed
|
|
2291
|
+
- Version 3.3.0 to 3.4.0; bench 0.2.1 to 0.3; README updated for v3.4; M2/M-UQ manuscript updates.
|
|
2292
|
+
|
|
2293
|
+
## [3.3.0] - 2026-06-09 - The Verifier (a type checker for genome writes)
|
|
2294
|
+
|
|
2295
|
+
v3.3 lifts the laws of genome writing into a versioned, machine-readable rule base and exposes a single
|
|
2296
|
+
`verify(design) -> Verdict` call (legal/illegal plus named rule plus calibrated confidence plus scope) over Python,
|
|
2297
|
+
REST, and MCP. Each component is SHA-locked.
|
|
2298
|
+
|
|
2299
|
+
### Added
|
|
2300
|
+
- **Rule base plus solver.** `pen_stack/rules/{schema,evaluators,loader,solver}.py` plus `configs/rules/*.yaml`
|
|
2301
|
+
(9 rules across reachability/fold/payload/multiplex/delivery), each id/kind/mechanism/param/provenance(DOI)/
|
|
2302
|
+
test. Evaluators delegate to the existing validated functions; a parity test proves no decision changed.
|
|
2303
|
+
Legality and confidence are kept as distinct axes.
|
|
2304
|
+
- **Delivery palette.** `configs/delivery_vehicles.yaml` plus `planner/delivery_vehicles.py`: 8 vehicles
|
|
2305
|
+
(AAV single/dual, lentivirus, HDAd, HSV amplicon, LNP-mRNA, eVLP, electroporation) with capacity/integration/
|
|
2306
|
+
cargo-form/DOIs; delivery rules (hard rejects plus soft penalties plus an immunogenicity-magnitude scope flag).
|
|
2307
|
+
- **Write-type router.** `planner/router.py` plus `configs/write_types.yaml`: dispatches insertion/
|
|
2308
|
+
excision/inversion/replacement/regulatory_rewrite/landing_pad_install/multiplex; unsupported types defer.
|
|
2309
|
+
- **Verification service.** `pen_stack/verify/{service,schema}.py`: `verify(design) -> Verdict`; `POST
|
|
2310
|
+
/verify` plus MCP `verify_write`; `docs/verify.md`. No fabrication (every number tool-sourced).
|
|
2311
|
+
- **Bench v0.2.1 plus agent.** T12 rule-grounded legality-with-explanation (verifier reason accuracy 1.0
|
|
2312
|
+
vs ungrounded 0.0); the agent submits its plan to the verifier. Bench 12/12 available, planner beats baseline
|
|
2313
|
+
8/8.
|
|
2314
|
+
- **Docs:** `docs/verify.md`, `docs/rules.md`, `docs/delivery.md`.
|
|
2315
|
+
|
|
2316
|
+
### Changed
|
|
2317
|
+
- Version 3.2.0 to 3.3.0 (pyproject, `__init__`, CITATION.cff). README updated for v3.3; bench badge v0.2.1.
|
|
2318
|
+
|
|
2319
|
+
## [3.2.0] - 2026-06-08 - A calibrated, self-aware co-scientist
|
|
2320
|
+
|
|
2321
|
+
The v3.2 cycle makes the genome-writing funnel trustworthy: every value carries a calibrated confidence,
|
|
2322
|
+
an extrapolation flag, and, where the biology is beyond any tool here, an explicit out-of-scope deferral.
|
|
2323
|
+
Each workstream is pre-registered (`prereg/ws_{uq,ep,mc,ba}.yaml`, SHA-locked) and reports its
|
|
2324
|
+
negatives. The Genome-Writing Bench bumps to v0.2.
|
|
2325
|
+
|
|
2326
|
+
### Added
|
|
2327
|
+
- **Calibrated uncertainty plus OOD.** Conformal prediction intervals (durability expression) and APS /
|
|
2328
|
+
Mondrian prediction sets (safety, silenced) wrapping the existing heads with no retraining
|
|
2329
|
+
(`pen_stack.wgenome.uncertainty`); an OOD detector that widens intervals out-of-distribution
|
|
2330
|
+
(`pen_stack.wgenome.ood`); selective prediction plus plan-level confidence
|
|
2331
|
+
(`pen_stack.validate.selective_prediction`). Held-out coverage 0.895 vs 0.90 nominal; risk-coverage accuracy
|
|
2332
|
+
0.739 to 0.930 under abstention. OOD across human cell types is weak (0.65-0.73), reported as a heuristic.
|
|
2333
|
+
- **Epistemic scoping.** A three-tier status (grounded-confident / grounded-extrapolating /
|
|
2334
|
+
not-computable) on every agent output (`pen_stack.agent.epistemic`); a known-unknowns registry plus a scope
|
|
2335
|
+
matcher (`configs/known_unknowns.yaml`, `pen_stack.agent.scope`, `docs/scope.md`) that defers out-of-scope
|
|
2336
|
+
questions (deferral 1.0, false-defer 0.0); abstention in the agent. The no-fabrication gate is intact.
|
|
2337
|
+
- **Mechanistic filters.** A hard target-site/PAM/att-site reachability reject
|
|
2338
|
+
(`pen_stack.planner.target_site`, `configs/target_sites.yaml`; controls 9/9); vehicle-specific
|
|
2339
|
+
delivery-sequence penalties (`pen_stack.planner.delivery_constraints`); and an off-target energetics
|
|
2340
|
+
model (`pen_stack.bridge.offtarget_energetics`) that beats the 0.77 baseline at held-out AUROC 0.88 on the
|
|
2341
|
+
comparable (core-disrupted) construction and ships as the default ranker. A reviewer-driven re-run
|
|
2342
|
+
(`by_negative_construction`) shows that gap is mostly the core-penalisation artifact; with the core held
|
|
2343
|
+
matched the non-core substitution-identity gain is real but modest (delta ~0.04, 0.687 vs 0.646). Both AUROCs
|
|
2344
|
+
carry a favourable-negative-set caveat (decoys derived from real off-targets; no non-recombining background).
|
|
2345
|
+
- **Bench v0.2 plus uncertainty-aware agent.** Four trust tasks (T8 calibration, T9 selective prediction,
|
|
2346
|
+
T10 OOD honesty, T11 out-of-scope refusal) contrasting the uncertainty-aware agent with an over-confident
|
|
2347
|
+
baseline (4/4); PEN-Agent emits confidence plus epistemic status plus abstains; UI surfaces them. Bench re-SHA-locked.
|
|
2348
|
+
- **Gymnasium interface (optional).** A thin `gymnasium.Env` over the planner (`pen_stack.env`,
|
|
2349
|
+
`[env]` extra) for agent-developer interoperability, interface only, no RL superiority claimed.
|
|
2350
|
+
- **Docs:** `docs/uncertainty.md`, `docs/scope.md`, `docs/mechanistic_constraints.md`; M-UQ methods note plus
|
|
2351
|
+
M1/M2 manuscript updates. The Opentrons workstream is deferred to `docs/BACKLOG.md`.
|
|
2352
|
+
|
|
2353
|
+
### Changed
|
|
2354
|
+
- Version 3.1.0 to 3.2.0 (pyproject, `__init__`, CITATION.cff). README updated for v3.2; badges plus bench
|
|
2355
|
+
v0.2. The bridge off-target default ranker is now the energetics model when its penalty table is present.
|
|
2356
|
+
|
|
2357
|
+
## [3.1.0] - 2026-06-04 - Publishable contributions plus an adopted benchmark
|
|
2358
|
+
|
|
2359
|
+
The v3.1 cycle completes (workstreams A-H). It hardens the planning benchmark, surrounds the
|
|
2360
|
+
models with strong baselines, adds a predicted-structure safety axis, and ships the first benchmark and
|
|
2361
|
+
grounded agent for the genome-writing side. Every workstream is pre-registered (`prereg/ws_*.yaml`,
|
|
2362
|
+
SHA-locked) and reports its negatives.
|
|
2363
|
+
|
|
2364
|
+
### Added
|
|
2365
|
+
- **Strong baselines plus safety primary-metric switch.** An endogenous-expression baseline (TRIP-trained
|
|
2366
|
+
Spearman 0.51 vs AlphaGenome ES-Bruce4 proxy 0.43), a multi-mark ablation (all-marks >= best single), and a
|
|
2367
|
+
published GSH rule-set: safe-harbour discrimination (learned 0.92, 95% CI [0.82, 0.98] vs distance-rule
|
|
2368
|
+
0.38, delta CI excludes zero) is now the primary safety metric; the circular `genotoxic_cis` AUROC is a
|
|
2369
|
+
labeled diagnostic. (`pen_stack.wgenome.gsh_baseline`, `pen_stack.validate.durability_baselines`.)
|
|
2370
|
+
- **AlphaGenome integration.** A hosted-API provider with an offline cache; predicted-vs-measured track
|
|
2371
|
+
validation (HepG2 ATAC Pearson 0.85) with a score-level low-confidence flag; a 3D structural-risk
|
|
2372
|
+
axis from contact-map deltas (`pen_stack.wgenome.{providers,chromatin_seq,structure3d}`,
|
|
2373
|
+
`pen_stack.validate.seq_vs_measured`).
|
|
2374
|
+
- **Cargo Polish.** A cargo-sequence silencing-risk scan (`pen_stack.planner.cargo_polish`).
|
|
2375
|
+
- **Genome-Writing Bench v0.1 plus PEN-Agent.** The first writing-side benchmark (`benchmarks/`,
|
|
2376
|
+
`bench/run.py`) with deterministic scorers, a leaderboard, and a real LLM-agent baseline; a grounded
|
|
2377
|
+
write-planning state machine with a no-fabrication hard gate (`pen_stack.agent.pen_agent`).
|
|
2378
|
+
- **Local recalibration / private-data adaptation.** Gated recalibration / fine-tuning on private
|
|
2379
|
+
data, in-container; the adapted model activates only if it beats the released model AND a no-skill
|
|
2380
|
+
baseline; the released model is provably unchanged (`pen_stack.adapt`).
|
|
2381
|
+
- **Multiplex plus guide QC.** A pairwise translocation-risk screen (`pen_stack.planner.multiplex`,
|
|
2382
|
+
surfaced in PEN-Agent) and a bridge-RNA guide ranker (`pen_stack.bridge.guide_qc`).
|
|
2383
|
+
- **Release plus dissemination.** README/badges updated for v3.1, `docs/quickstart.md`,
|
|
2384
|
+
`docs/positioning.md`, the leaderboard submission guide, the dissemination log, and version 3.1.0.
|
|
2385
|
+
|
|
2386
|
+
### Changed
|
|
2387
|
+
- The planning benchmark's `recovery_at_k` ranking is now deterministic (stable sort plus tie-breakers).
|
|
2388
|
+
- The LLM stack defaults to the local Ollama model on the compute tier with an automatic hosted-Nemotron
|
|
2389
|
+
fallback, a cooldown cache, and bounded timeouts (no more multi-minute stalls when a provider is absent).
|
|
2390
|
+
|
|
2391
|
+
## [3.1.0a0] - 2026-06-04 - De-circularize the planning benchmark (gate)
|
|
2392
|
+
|
|
2393
|
+
This release opens with de-circularizing the
|
|
2394
|
+
planning benchmark before anything builds on it.
|
|
2395
|
+
|
|
2396
|
+
### Changed
|
|
2397
|
+
- **The "discriminating-stratum recovery@10 = 1.00 vs 0.00 (McNemar p, CI)" is now labeled
|
|
2398
|
+
definitional, not predictive,** everywhere (README, manuscript abstract, `prereg/paper3.yaml`,
|
|
2399
|
+
`validate/paper3_benchmark.py` docstring). An on-target identity term dominates the score, so the planner
|
|
2400
|
+
ranks the goal's own gene first by construction. Documented in `docs/benchmark_circularity.md`.
|
|
2401
|
+
- The intent result is reframed as a specification-compliance correctness table (`validate/intent_specification.py`,
|
|
2402
|
+
7/7), with no recovery/p-value/CI language.
|
|
2403
|
+
|
|
2404
|
+
### Added (the non-circular replacements)
|
|
2405
|
+
- **Blind safe-harbour site discovery (the new lead result):** `validate/blind_gsh_discovery.py` plus
|
|
2406
|
+
`configs/gsh_validated_heldout.yaml` (5 DOI-validated held-out GSH, gene-anchored to hg38) plus a
|
|
2407
|
+
frozen/SHA-locked `data/gsh_matched_controls.parquet`. Run genome-wide (no on-target term), the planner's
|
|
2408
|
+
writability separates validated GSH from matched-context controls at AUROC 0.92 (safety-only 0.50).
|
|
2409
|
+
- **Diversified writer-family recovery:** `validate/writer_recovery.py` plus `data/writer_panel.csv` (8 writes,
|
|
2410
|
+
4 families, DOIs). recovery@1 = 1.0 vs prevalence 0.25 (smallest-capacity DSB-free writer that fits
|
|
2411
|
+
the cargo).
|
|
2412
|
+
- **Within-locus ranking** (descriptive): `validate/within_locus_ranking.py`, AAVS1 documented bin at the
|
|
2413
|
+
93rd within-locus percentile (top quartile); CLYBL at the 34th (a negative result).
|
|
2414
|
+
- **Consolidated report** `scripts/p3_benchmark_report.py` to `out/ws_a_report.md`; `prereg/ws_a.yaml` plus
|
|
2415
|
+
SHA lock. Blind AUROC reported, no circular claims remain.
|
|
2416
|
+
|
|
2417
|
+
## [Unreleased] - 2026-06-03 - Reframing, repository polish, coverage, hybrid LLM
|
|
2418
|
+
|
|
2419
|
+
### Added
|
|
2420
|
+
- **Hybrid LLM backend** (`pen_stack/rag/llm.py`, `configs/llm.yaml`): a strong hosted model for
|
|
2421
|
+
reasoning/agent/Q&A (NVIDIA Nemotron, OpenAI-compatible, free) with automatic fallback to the local
|
|
2422
|
+
Ollama model, then to the deterministic no-LLM path. One `provider` switch. The agent and RAG were
|
|
2423
|
+
refactored onto a single provider-agnostic `chat()` (NVIDIA tool-call IDs and Ollama native message
|
|
2424
|
+
threading both handled). The LLM stays non-load-bearing (every number/citation still comes from
|
|
2425
|
+
validated tools), so the model choice does not affect scientific reproducibility; it only improves
|
|
2426
|
+
orchestration (Nemotron planned a goal in 2 tool calls vs the local 7B's 8-call loop). Core scientific
|
|
2427
|
+
compute stays local/VM and uses no LLM. API keys are read from an env var or a gitignored file and
|
|
2428
|
+
are never committed.
|
|
2429
|
+
|
|
2430
|
+
### Changed
|
|
2431
|
+
- **The bridge tool reframed to its scope.** `pen-bridge` is positioned as the first measured-data-validated
|
|
2432
|
+
tool that nominates and ranks candidate off-target locations for bridge recombinases, a
|
|
2433
|
+
screening tool, not a quantitative safety calculator. The AUROC 0.77 vs 0.62 result is stated with
|
|
2434
|
+
its caveat (favourable negative set; mostly tests core integrity), and the magnitude limitation
|
|
2435
|
+
(sequence-risk does not rank recombination amount, rho ~0.30) is named as the single most important
|
|
2436
|
+
limitation. Application-Note tier, first-of-its-kind for an unoccupied gap; the Writable Genome remains
|
|
2437
|
+
the flagship. Manuscript plus `prereg/paper4.yaml` plus summaries updated.
|
|
2438
|
+
- **Variant-effect reframed:** the DMS recovers KNOWN enhancers (a catalogue feature), it is not a novel
|
|
2439
|
+
variant-design method; EVOLVEpro is the engine to wrap when generating new variants.
|
|
2440
|
+
- **Repository made clean ASCII:** removed all decorative emojis and em/en dashes and other non-ASCII
|
|
2441
|
+
punctuation across code, docs, configs, and manuscripts (box-drawing tree characters kept).
|
|
2442
|
+
|
|
2443
|
+
### Added
|
|
2444
|
+
- 72-system ortholog characterisation (`bridge/ortholog_screen.py`), explicitly descriptive (Table S1 has
|
|
2445
|
+
no activity label): sequence-similarity organisation vs the validated standout ISCro4 (IS621 ranks most
|
|
2446
|
+
similar, a sanity check). Exploratory secondary result, N ~72.
|
|
2447
|
+
- Coverage: CI runs `pytest --cov`, uploads to Codecov, and publishes a self-hosted coverage badge
|
|
2448
|
+
(`tools/make_coverage_badge.py` to `.github/badges/coverage.svg`). Unit-test coverage of the core logic
|
|
2449
|
+
is 69% (integration-only modules that need GPU/VM/network/LLM are excluded via `[tool.coverage.run]`).
|
|
2450
|
+
- Professional, emoji-free README with connected-repo badges (genome-atlas / mech-class / pen-score /
|
|
2451
|
+
pen-assemble / pen-compare), an architecture diagram, and the problem/gaps explanation.
|
|
2452
|
+
|
|
2453
|
+
## [3.0.0a5] - 2026-06-02 - Bridge-recombinase off-target engine
|
|
2454
|
+
|
|
2455
|
+
The first public instrument: a bridge-recombinase off-target screening tool.
|
|
2456
|
+
|
|
2457
|
+
### Added
|
|
2458
|
+
- **Off-target engine** (`pen_stack/bridge/offtarget.py` plus `configs/bridge_offtarget_profile.yaml`):
|
|
2459
|
+
a genome-wide hg38 pseudosite scan (CT-core seed, per-chromosome, memory-bounded) plus a position-weight
|
|
2460
|
+
risk model grounded in the published mechanism. Beats naive Hamming: AUROC 1.00 vs 0.59 at
|
|
2461
|
+
separating core-preserving (real-risk) from core-disrupting (abolished) sites. Exposes
|
|
2462
|
+
`predict_offtargets(family, site)`, completing the planner cargo hook.
|
|
2463
|
+
- **Fold / cross-loop QC** (`bridge/fold_qc.py`): a ViennaRNA fold (verified MFE on a 190-nt design) plus
|
|
2464
|
+
TBL/DBL cross-loop complementarity.
|
|
2465
|
+
- **Activity framework** (`bridge/activity.py`): an exploratory DMS plus 72-system trainer (deferred; data paywalled).
|
|
2466
|
+
- **`pen-bridge`** (`bridge/pipeline.py`, `bridge/cli.py`, `/bridge/design` API): wraps the Arc
|
|
2467
|
+
BridgeRNADesigner (verified) and adds the off-target plus QC layer.
|
|
2468
|
+
- `validate/paper4_validation.py` plus `scripts/p4_genome_scan.py`; `prereg/paper4.yaml` plus SHA lock.
|
|
2469
|
+
|
|
2470
|
+
### Notes
|
|
2471
|
+
- The pre-registered criteria were met (or gated): the off-target engine,
|
|
2472
|
+
the ViennaRNA fold, and the designer wrap are verified on the VM (real hg38 scan: chr22 in ~21 s). The blind
|
|
2473
|
+
recall of Perry 2025's measured off-targets and the DMS/activity model are gated on the paywalled
|
|
2474
|
+
Perry 2025 supplementary (drop in via `ingest.load_offtarget_profile`). 68 tests green; ruff clean.
|
|
2475
|
+
|
|
2476
|
+
## [3.0.0a4] - 2026-06-02 - The write planner and agentic platform
|
|
2477
|
+
|
|
2478
|
+
Inverse design plus the paper-defining recovery@k benchmark plus the agentic platform.
|
|
2479
|
+
|
|
2480
|
+
### Added
|
|
2481
|
+
- **Inverse-design optimiser** (`pen_stack/planner/optimize.py`, `configs/intent_weights.yaml`): an
|
|
2482
|
+
`edit_intent`-conditioned objective whose `target_gene_sign` flips whether hitting the target gene is
|
|
2483
|
+
penalised or rewarded, so the same TRAC site ranks #1 (knock-in) vs #101 (safe-harbour).
|
|
2484
|
+
- **Cargo/delivery** (`planner/cargo.py`, `planner/delivery.py`): a donor spec plus size check plus a delivery rule
|
|
2485
|
+
table; bridge/seek off-target via an optional off-target hook.
|
|
2486
|
+
- **End-to-end Planner** (`planner/pipeline.py`, `report.py`, `/plan` API, `pen-stack plan` CLI): ranked,
|
|
2487
|
+
fully traceable plans with per-field provenance.
|
|
2488
|
+
- **Two-stratum recovery@k benchmark** (`validate/paper3_benchmark.py`, `data/benchmark_panel.csv`,
|
|
2489
|
+
`prereg/paper3.yaml`): discriminating stratum planner 1.00 vs baseline 0.00, McNemar p=0.0156, gap CI
|
|
2490
|
+
[1.0,1.0] excludes zero; control tie 0.67=0.67. The panel is cited to Europe-PMC-verified sources.
|
|
2491
|
+
- **Forward hypotheses** (`validate/forward_hypotheses.py`): date-stamped novel F8/SERPINA1/CISH/HBA1
|
|
2492
|
+
proposals plus a grounded cited ranking.
|
|
2493
|
+
- **Agentic platform:** `agent/tools.py` plus `agent/orchestrator.py` (Ollama tool-calling, an auditable trace,
|
|
2494
|
+
no-fabrication, refusals), `agent/mcp_server.py` (fastmcp), `docker-compose.yml` plus `docker/ui.Dockerfile`
|
|
2495
|
+
plus a Streamlit Agent page plus `docs/DEPLOY.md`/`docs/MCP.md`, `validate/agent_eval.py`.
|
|
2496
|
+
- Shipped `data/curated/gene_coords.parquet` (GENCODE-derived) so tools work in any container.
|
|
2497
|
+
|
|
2498
|
+
### Notes
|
|
2499
|
+
- The pre-registered criteria were met (`prereg/paper3.yaml` plus `SHA256_LOCK_phase3.json`).
|
|
2500
|
+
The agent is verified on the VM in LLM mode (no-fabrication plus plan-equivalence plus refusals all pass). 63 tests
|
|
2501
|
+
green; ruff clean. Wet-lab (3.7) skipped, non-gating. The bridge off-target hook completes separately.
|
|
2502
|
+
|
|
2503
|
+
## [3.0.0a3] - 2026-06-02 - The Writer Atlas and unified stack
|
|
2504
|
+
|
|
2505
|
+
The broad, cross-family Writer Atlas, the writer-to-locus cross-link, and the installable platform.
|
|
2506
|
+
|
|
2507
|
+
### Added
|
|
2508
|
+
- **Writer Atlas** (`pen_stack/atlas/expand.py`, `atlas.parquet`): 33,370 systems across 8 families
|
|
2509
|
+
(31,885 IS110/IS1111 orthologs plus curated cores/reps), every row confidence-tagged plus at least 1 source DOI,
|
|
2510
|
+
targeting metadata inherited from the WT-KB. `configs/atlas_families.yaml` drives the UniProt queries.
|
|
2511
|
+
- **Mechanism at scale** (`pen_stack/mech/`): ported the audited 18-family Pfam whitelist v1.2.1; composite
|
|
2512
|
+
co-occurrence rules; core agreement 1.00 vs audited labels; conflicting calls go to a review queue.
|
|
2513
|
+
- **Therapeutic readiness** (`pen_stack/score/therapeutic.py`): deliverability/cargo/human-cell axes,
|
|
2514
|
+
components retained (ISCro4 326aa to AAV).
|
|
2515
|
+
- **Cross-link** (`pen_stack/atlas/crosslink.py`): bidirectional writer-to-locus queries; AAVS1 held-out
|
|
2516
|
+
check passes (0.90 writability plus bridge-reachable). Per-family caches for k562/hepg2/hspc.
|
|
2517
|
+
- **Variant proposal** (`pen_stack/atlas/variant_propose.py`): a point-mutation framework plus a retrospective
|
|
2518
|
+
harness, no chimeras; DMS model pluggable.
|
|
2519
|
+
- **Living-literature monitor** (`pen_stack/monitor/`): a Europe PMC living-database engine; the back-test surfaces ISPpu10;
|
|
2520
|
+
never auto-edits the atlas; every candidate cited.
|
|
2521
|
+
- **Grounded RAG** (`pen_stack/rag/`, `pen_stack/agent/guardrails.py`): numbers from tool calls, claims
|
|
2522
|
+
cited, clinical directives refused; an optional Ollama/Qwen phrasing layer (presentation only).
|
|
2523
|
+
- **Stack:** unified CLI subcommands, a FastAPI server (`pen_stack/server/api.py`), a Streamlit platform UI
|
|
2524
|
+
(Writer Atlas plus Ask pages), an mkdocs site plus 4 use-case tutorials. 46 tests green; ruff clean.
|
|
2525
|
+
|
|
2526
|
+
### Notes
|
|
2527
|
+
- The pre-registered criteria were met (`prereg/paper2.yaml` plus `SHA256_LOCK_phase2.json`);
|
|
2528
|
+
the atlas Zenodo DOI is pending author upload. Verified on the VM (Docker): API, UI (:8501), RAG with Qwen.
|
|
2529
|
+
|
|
2530
|
+
## [3.0.0a0] - 2026-06-01 - Initial monorepo
|
|
2531
|
+
|
|
2532
|
+
A fresh v3.0 monorepo. It supersedes the v1.0 platform repository (archived) and consolidates the five prior
|
|
2533
|
+
repositories (`genome-atlas`, `mech-class`, `pen-score`, `pen-assemble`, `pen-compare`) as provenance.
|
|
2534
|
+
|
|
2535
|
+
### Added
|
|
2536
|
+
- A monorepo scaffold: 13 modules (`atlas`, `mech`, `score`, `wgenome`, `planner`, `bridge`, `monitor`,
|
|
2537
|
+
`rag`, `agent`, `ui`, `data`, `validate`, `server`), `pyproject.toml`, a Docker image spec, the `penctl`
|
|
2538
|
+
laptop-to-VM orchestrator, CI, `configs/`, `prereg/`.
|
|
2539
|
+
- `docs/INFRA.md`: the three-tier (laptop / VM / Drive) Docker-only, SFTP-only workflow.
|
|
2540
|
+
- `configs/llm.yaml`: a single LLM switch (Ollama plus Qwen2.5-7B-Instruct, Apache-2.0).
|
|
2541
|
+
- `configs/datasets.yaml`: pinned dataset accessions plus verified IDs (see VERIFICATION_REPORT_v3.0).
|
|
2542
|
+
- **WT-KB** (`pen_stack/atlas/`): 8 fully-sourced writer families with reachability tiers; the schema enforces the at-least-1-DOI sourcing rule.
|
|
2543
|
+
- **Re-grounded axes** (`pen_stack/score/recalibrate.py`, `configs/score_axes.yaml`): `S_Cargo` from measured bp, `S_Prog` from targeting modality, `length_aa` backfilled, no per-enzyme overrides.
|
|
2544
|
+
- **Canonical universe** (`pen_stack/atlas/universe.py::assemble`): one path joining the 1,058-entity universe plus WT-KB plus crosswalk; a cross-module consistency test.
|
|
2545
|
+
- **Descriptive scorecard** (`pen_stack/atlas/scorecard.py`): reframed from the circular certification; blind concordance recovers ISCro4 as the bridge standout without naming it. 21 tests green.
|
|
2546
|
+
|
|
2547
|
+
### Notes
|
|
2548
|
+
- Independent verification of all datasets/IDs/DOIs/tools completed: no critical errors in the v3.0 plan.
|
|
2549
|
+
- All pre-registered success criteria were met (`prereg/phase0.yaml` plus SHA lock).
|