factorforge-cds 3.5.11__tar.gz → 3.5.12__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.
Files changed (289) hide show
  1. {factorforge_cds-3.5.11/src/factorforge_cds.egg-info → factorforge_cds-3.5.12}/PKG-INFO +33 -7
  2. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/README.md +25 -6
  3. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/pyproject.toml +12 -2
  4. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/analysis/metrics.py +38 -11
  5. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/cli/main.py +2 -0
  6. factorforge_cds-3.5.12/src/factorforge/cli/structure_cli.py +157 -0
  7. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/registry/version_manifest.json +2 -2
  8. factorforge_cds-3.5.12/src/factorforge/structure/__init__.py +45 -0
  9. factorforge_cds-3.5.12/src/factorforge/structure/esm_annotator.py +249 -0
  10. factorforge_cds-3.5.12/src/factorforge/structure/interpro_sidecar_fetcher.py +321 -0
  11. factorforge_cds-3.5.12/src/factorforge/structure/uniprot_sidecar_fetcher.py +313 -0
  12. factorforge_cds-3.5.12/src/factorforge/structure/viewer_bridge.py +286 -0
  13. factorforge_cds-3.5.12/src/factorforge/validation/__init__.py +30 -0
  14. factorforge_cds-3.5.12/src/factorforge/validation/dp_4dp_comparison.py +1441 -0
  15. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12/src/factorforge_cds.egg-info}/PKG-INFO +33 -7
  16. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge_cds.egg-info/SOURCES.txt +16 -0
  17. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge_cds.egg-info/requires.txt +10 -0
  18. factorforge_cds-3.5.12/tests/test_benchmark_dnachisel.py +46 -0
  19. factorforge_cds-3.5.12/tests/test_conda_source_hash.py +31 -0
  20. factorforge_cds-3.5.12/tests/test_dp_4dp_comparison.py +369 -0
  21. factorforge_cds-3.5.12/tests/test_esm_annotator.py +74 -0
  22. factorforge_cds-3.5.12/tests/test_installed_distribution_smoke.py +72 -0
  23. factorforge_cds-3.5.12/tests/test_interpro_sidecar_fetcher.py +196 -0
  24. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_multi_engine_governance.py +3 -3
  25. factorforge_cds-3.5.12/tests/test_public_audit_scope.py +22 -0
  26. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_scientific_web_397.py +8 -3
  27. factorforge_cds-3.5.12/tests/test_structure_cli.py +126 -0
  28. factorforge_cds-3.5.12/tests/test_uniprot_sidecar_fetcher.py +191 -0
  29. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_version_manifest.py +2 -1
  30. factorforge_cds-3.5.12/tests/test_viewer_bridge.py +149 -0
  31. factorforge_cds-3.5.11/src/factorforge/structure/__init__.py +0 -11
  32. factorforge_cds-3.5.11/src/factorforge/validation/__init__.py +0 -3
  33. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/LICENSE +0 -0
  34. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/setup.cfg +0 -0
  35. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/__init__.py +0 -0
  36. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/__main__.py +0 -0
  37. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/analysis/__init__.py +0 -0
  38. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/analysis/feasibility.py +0 -0
  39. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/analysis/sequence_risks.py +0 -0
  40. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/benchmark/models.py +0 -0
  41. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/benchmark/runner.py +0 -0
  42. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/cli/__init__.py +0 -0
  43. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/cli/benchmark_cli.py +0 -0
  44. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/cli/legacy_cli.py +0 -0
  45. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/closed_loop/__init__.py +0 -0
  46. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/closed_loop/contracts.py +0 -0
  47. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/closed_loop/ledger.py +0 -0
  48. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/closed_loop/readiness.py +0 -0
  49. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/codon/__init__.py +0 -0
  50. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/codon/allocator.py +0 -0
  51. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/codon/policy.py +0 -0
  52. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/codon/qa.py +0 -0
  53. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/codon/twin_generator.py +0 -0
  54. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/constraints/__init__.py +0 -0
  55. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/constraints/type_iis.py +0 -0
  56. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/core/__init__.py +0 -0
  57. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/core/experiment.py +0 -0
  58. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/core/host_model.py +0 -0
  59. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/core/interfaces/__init__.py +0 -0
  60. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/core/interfaces/exporter.py +0 -0
  61. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/core/interfaces/optimizer.py +0 -0
  62. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/core/interfaces/validator.py +0 -0
  63. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/core/policy.py +0 -0
  64. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/core/reranker.py +0 -0
  65. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/core/slate_engine.py +0 -0
  66. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/core/slate_generator.py +0 -0
  67. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/data/human_stemcell_codons.json +0 -0
  68. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/data/nbenthamiana_codons.json +0 -0
  69. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/data/nbenthamiana_golden_set.json +0 -0
  70. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/data/ntabacum_codons.json +0 -0
  71. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/data/profiles/human_stemcell_derived_codons.json +0 -0
  72. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/data/profiles/human_stemcell_policy.json +0 -0
  73. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/data/profiles/nbev11_cds_all_derived_codons.json +0 -0
  74. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/data/profiles/nbev11_cds_all_derived_filtered_stats.json +0 -0
  75. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/data/profiles/nbev11_cds_all_derived_manifest.json +0 -0
  76. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/data/profiles/nbev11_cds_hc_derived_codons.json +0 -0
  77. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/data/profiles/nbev11_cds_hc_derived_filtered_stats.json +0 -0
  78. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/data/profiles/nbev11_cds_hc_derived_manifest.json +0 -0
  79. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/data/profiles/qld183_v103_derived_codons.json +0 -0
  80. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/data/profiles/qld183_v103_derived_manifest.json +0 -0
  81. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/data/profiles/qld183_v103_filtered_stats.json +0 -0
  82. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/data/reference/reference_policy_manifest.json +0 -0
  83. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/data/templates/high_expression.json +0 -0
  84. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/data/templates/standard_expression.json +0 -0
  85. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/data/wolffia_globosa_codons.json +0 -0
  86. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/database.py +0 -0
  87. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/db/__init__.py +0 -0
  88. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/db/connector.py +0 -0
  89. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/design_review.py +0 -0
  90. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/discovery/__init__.py +0 -0
  91. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/discovery/acquisition.py +0 -0
  92. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/discovery/acquisition_logger.py +0 -0
  93. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/discovery/filter.py +0 -0
  94. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/discovery/generator.py +0 -0
  95. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/discovery/panel_builder.py +0 -0
  96. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/discovery/schemas.py +0 -0
  97. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/discovery/slate.py +0 -0
  98. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/discovery/traits.py +0 -0
  99. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/__init__.py +0 -0
  100. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/balanced_optimizer.py +0 -0
  101. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/dp_adapter.py +0 -0
  102. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/dp_v2.py +0 -0
  103. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/dp_v2_1.py +0 -0
  104. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/dp_v2_1_1.py +0 -0
  105. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/dp_v2_2.py +0 -0
  106. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/dp_v2_3.py +0 -0
  107. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/dp_v2_4.py +0 -0
  108. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/lm/__init__.py +0 -0
  109. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/lm/adapter.py +0 -0
  110. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/lm/diagnostics.py +0 -0
  111. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/lm/inference.py +0 -0
  112. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/lm/models/__init__.py +0 -0
  113. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/lm/models/mbart_codon.py +0 -0
  114. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/lm/tokenizer/control_tokenizer.py +0 -0
  115. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/local_rewriter.py +0 -0
  116. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/profile/__init__.py +0 -0
  117. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/profile/codon_table_builder.py +0 -0
  118. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/profile/construct_builder.py +0 -0
  119. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/profile/exporter.py +0 -0
  120. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/profile/optimizer.py +0 -0
  121. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/profile/pipeline.py +0 -0
  122. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/profile/rules/__init__.py +0 -0
  123. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/profile/rules/domesticator.py +0 -0
  124. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/profile/rules/reverse_translator.py +0 -0
  125. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/profile/rules/rule_engine.py +0 -0
  126. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/profile/scoring.py +0 -0
  127. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/profile/scoring_ml.py +0 -0
  128. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/profile/utils.py +0 -0
  129. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/profile/validator.py +0 -0
  130. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/registry.py +0 -0
  131. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/sllm/adapters.py +0 -0
  132. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/sllm/automaton.py +0 -0
  133. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/sllm/compiler.py +0 -0
  134. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/sllm/data/__init__.py +0 -0
  135. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/sllm/data/corpus_builder.py +0 -0
  136. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/sllm/data/tokenizer.py +0 -0
  137. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/sllm/decoder.py +0 -0
  138. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/sllm/interfaces.py +0 -0
  139. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/sllm/model/__init__.py +0 -0
  140. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/sllm/model/arch.py +0 -0
  141. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/sllm/model/baselines.py +0 -0
  142. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/sllm/model/export_onnx.py +0 -0
  143. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/stemcell_3dp.py +0 -0
  144. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/structural_pause.py +0 -0
  145. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/structure_web.py +0 -0
  146. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/engines/targeted_remediator.py +0 -0
  147. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/evaluation/evaluator.py +0 -0
  148. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/evaluation/evidence_logger.py +0 -0
  149. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/evaluation/metrics.py +0 -0
  150. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/evaluation/models.py +0 -0
  151. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/guards/__init__.py +0 -0
  152. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/guards/initiation_mfe.py +0 -0
  153. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/guards/plant_rna_guards.py +0 -0
  154. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/io/__init__.py +0 -0
  155. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/io/fasta.py +0 -0
  156. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/io/package_compiler.py +0 -0
  157. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/io/validation.py +0 -0
  158. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/learning/__init__.py +0 -0
  159. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/learning/ranker.py +0 -0
  160. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/nbfold/__init__.py +0 -0
  161. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/nbfold/annotations.py +0 -0
  162. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/nbfold/bridge.py +0 -0
  163. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/nbfold/cli.py +0 -0
  164. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/nbfold/contracts.py +0 -0
  165. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/nbfold/pipeline.py +0 -0
  166. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/pipeline/__init__.py +0 -0
  167. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/pipeline/design_pipeline.py +0 -0
  168. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/profiles/profile_snapshot.py +0 -0
  169. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/protein_risk/__init__.py +0 -0
  170. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/protein_risk/annotate.py +0 -0
  171. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/protein_risk/kd_scale.py +0 -0
  172. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/protein_risk/risk_classifier.py +0 -0
  173. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/protein_risk/sp_predict.py +0 -0
  174. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/protein_risk/tm_predict.py +0 -0
  175. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/registry/__init__.py +0 -0
  176. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/registry/method_registry.py +0 -0
  177. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/registry/model_registry.py +0 -0
  178. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/registry/registry_loader.py +0 -0
  179. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/registry/versioning.py +0 -0
  180. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/review/__init__.py +0 -0
  181. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/review/evaluation_integrity.py +0 -0
  182. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/rules/models.py +0 -0
  183. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/rules/registry.py +0 -0
  184. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/schemas/__init__.py +0 -0
  185. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/schemas/design_package.py +0 -0
  186. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/schemas/design_package.schema.json +0 -0
  187. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/schemas/evidence.py +0 -0
  188. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/schemas/run_config.schema.json +0 -0
  189. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/scoring/quantization.py +0 -0
  190. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/sops/config.py +0 -0
  191. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/structure/auto_annotator.py +0 -0
  192. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/structure/auto_resolver.py +0 -0
  193. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/telemetry/__init__.py +0 -0
  194. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/telemetry/gcs_reconciliation.py +0 -0
  195. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/telemetry/training_logger.py +0 -0
  196. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/utils/__init__.py +0 -0
  197. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/utils/construct_id.py +0 -0
  198. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/utils/exceptions.py +0 -0
  199. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/utils/restriction_sites.py +0 -0
  200. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/utils/sequence_identity.py +0 -0
  201. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/utils/sequence_validator.py +0 -0
  202. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/utils/validation.py +0 -0
  203. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/validation/cli.py +0 -0
  204. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/validation/hub.py +0 -0
  205. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/validation/package_generator.py +0 -0
  206. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/validation/tradeoff_suite.py +0 -0
  207. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/validation_registry.py +0 -0
  208. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge/validation_report.py +0 -0
  209. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge_cds.egg-info/dependency_links.txt +0 -0
  210. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge_cds.egg-info/entry_points.txt +0 -0
  211. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/src/factorforge_cds.egg-info/top_level.txt +0 -0
  212. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_3dp_review_regressions.py +0 -0
  213. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_3dp_validation_suite.py +0 -0
  214. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_auto_annotator.py +0 -0
  215. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_baselines.py +0 -0
  216. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_benchmark_cli_output_guard.py +0 -0
  217. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_benchmark_codon_table_metadata.py +0 -0
  218. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_benchmark_harness.py +0 -0
  219. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_benchmark_regression.py +0 -0
  220. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_benchmark_scoring.py +0 -0
  221. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_benchmark_smoke.py +0 -0
  222. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_cai.py +0 -0
  223. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_candidate_review_safety.py +0 -0
  224. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_codon_table_manifest.py +0 -0
  225. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_cross_engine_evaluation.py +0 -0
  226. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_database.py +0 -0
  227. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_database_configuration.py +0 -0
  228. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_db_connector.py +0 -0
  229. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_design_package_schema.py +0 -0
  230. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_design_package_semantics.py +0 -0
  231. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_design_package_serialization.py +0 -0
  232. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_design_review.py +0 -0
  233. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_docs_consistency.py +0 -0
  234. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_dp_v2_1_1.py +0 -0
  235. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_dp_v2_1_initiation.py +0 -0
  236. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_dp_v2_2_0.py +0 -0
  237. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_dp_v2_3_0.py +0 -0
  238. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_dp_v2_4_0.py +0 -0
  239. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_dp_v2_4_review.py +0 -0
  240. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_durable_reconciliation.py +0 -0
  241. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_enterprise_integration_396.py +0 -0
  242. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_fasta_io.py +0 -0
  243. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_gc_content.py +0 -0
  244. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_host_profile_metadata.py +0 -0
  245. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_hpx_viewer.py +0 -0
  246. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_hpx_viewer_review.py +0 -0
  247. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_initiation_mfe.py +0 -0
  248. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_iupac_validation.py +0 -0
  249. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_job350_codon_twins.py +0 -0
  250. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_job351_closed_loop_foundation.py +0 -0
  251. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_job355_design_experiment.py +0 -0
  252. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_learning_workflow_boundary.py +0 -0
  253. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_legacy_cli.py +0 -0
  254. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_lm_alpha_contract.py +0 -0
  255. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_local_rewriter.py +0 -0
  256. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_math_v2_dp_optimality.py +0 -0
  257. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_nbfold_phase_c.py +0 -0
  258. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_nbfold_phase_c_benchmark.py +0 -0
  259. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_nbfold_pipeline.py +0 -0
  260. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_no_raw_sequence_logging.py +0 -0
  261. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_oct23_review.py +0 -0
  262. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_onnx_adapter_contract.py +0 -0
  263. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_openbio_missing_metric_contract.py +0 -0
  264. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_optional_postgres.py +0 -0
  265. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_parameter_registry.py +0 -0
  266. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_partial_dp_rescue.py +0 -0
  267. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_plant_rna_guards.py +0 -0
  268. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_policy_type_iis_targets.py +0 -0
  269. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_prepare_lm_dataset.py +0 -0
  270. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_protein_risk.py +0 -0
  271. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_public_surface_scanner.py +0 -0
  272. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_quantized_scoring.py +0 -0
  273. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_registry_production_sync.py +0 -0
  274. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_restriction_sites.py +0 -0
  275. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_rule_registry.py +0 -0
  276. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_sequence_validator.py +0 -0
  277. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_sllm_biological_pipeline.py +0 -0
  278. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_slm_decoder.py +0 -0
  279. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_slm_interface.py +0 -0
  280. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_sop_profile.py +0 -0
  281. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_stemcell_3dp.py +0 -0
  282. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_structural_pause.py +0 -0
  283. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_suite_capability_compat.py +0 -0
  284. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_training_logger.py +0 -0
  285. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_translation_integrity.py +0 -0
  286. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_validation_contract_compat.py +0 -0
  287. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_validation_registry.py +0 -0
  288. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_validation_report.py +0 -0
  289. {factorforge_cds-3.5.11 → factorforge_cds-3.5.12}/tests/test_worked_example.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: factorforge-cds
3
- Version: 3.5.11
3
+ Version: 3.5.12
4
4
  Summary: FactorForge - open-source CDS design and pre-synthesis sequence review by Eijex.
5
5
  Author-email: Eijex <eijex.lab@gmail.com>
6
6
  License-Expression: AGPL-3.0-only
@@ -34,6 +34,13 @@ Provides-Extra: ml
34
34
  Requires-Dist: transformers>=4.40; extra == "ml"
35
35
  Requires-Dist: torch>=2.0; extra == "ml"
36
36
  Requires-Dist: onnxruntime>=1.16; extra == "ml"
37
+ Provides-Extra: acceleration
38
+ Requires-Dist: pyahocorasick>=2.3.1; extra == "acceleration"
39
+ Provides-Extra: benchmark
40
+ Requires-Dist: dnachisel>=3.2.16; extra == "benchmark"
41
+ Requires-Dist: scipy>=1.17; extra == "benchmark"
42
+ Provides-Extra: ml-structure
43
+ Requires-Dist: fair-esm>=2.0.0; extra == "ml-structure"
37
44
  Dynamic: license-file
38
45
 
39
46
  # FactorForge
@@ -43,6 +50,7 @@ Dynamic: license-file
43
50
  [![License](https://img.shields.io/badge/license-AGPL--3.0-blue.svg)](LICENSE)
44
51
  [![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/)
45
52
  [![PyPI](https://img.shields.io/pypi/v/factorforge-cds.svg)](https://pypi.org/project/factorforge-cds/)
53
+ [![Bioconda](https://img.shields.io/badge/install%20with-bioconda-brightgreen.svg?style=flat)](https://anaconda.org/bioconda/factorforge-cds)
46
54
  [![CI](https://github.com/eijex/factorforge-cds/actions/workflows/ci.yml/badge.svg)](https://github.com/eijex/factorforge-cds/actions/workflows/ci.yml)
47
55
  [![codecov](https://codecov.io/gh/eijex/factorforge-cds/branch/main/graph/badge.svg)](https://codecov.io/gh/eijex/factorforge-cds)
48
56
  [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.20407330.svg)](https://doi.org/10.5281/zenodo.20407330)
@@ -52,7 +60,7 @@ Dynamic: license-file
52
60
 
53
61
  FactorForge performs deterministic CDS design with CAI/GC metrics, PolyA-signal screening, and Golden Gate/MoClo-aware checks. It is positioned as a pre-synthesis review harness: it helps teams generate reproducible CDS candidates, inspect assembly-relevant sequence constraints, and package design metadata before downstream synthesis, cloning, or experimental review. Primary support: *N. benthamiana* (agroinfiltration). Experimental host context: Tobacco BY-2 (`--host by2`).
54
62
 
55
- FactorForge v3.5.11 uses independently versioned engines:
63
+ FactorForge v3.5.12 uses independently versioned engines:
56
64
 
57
65
  | Generation | Engine | Version | Availability |
58
66
  |---|---|---:|---|
@@ -69,18 +77,31 @@ FactorForge v3.5.11 uses independently versioned engines:
69
77
  ## Quick Start
70
78
 
71
79
  ```bash
80
+ # Bioconda: Linux/macOS, or Ubuntu inside WSL on Windows
81
+ conda create -n factorforge-review --override-channels -c conda-forge -c bioconda --strict-channel-priority python=3.11 factorforge-cds
82
+ conda activate factorforge-review
83
+
84
+ # Via PyPI
72
85
  pip install factorforge-cds
86
+
87
+ # Run optimization
73
88
  factorforge optimize my_protein.fasta -o output.fasta
74
89
  ```
75
90
 
76
91
  Or use the **[web app](https://factorforge.eijex.com)** — no installation required.
77
92
 
93
+ Bioconda does not support native Windows. Use WSL for that installation route;
94
+ see [installation and reviewer checks](docs/getting-started.md) for the tested
95
+ version, platform limitations and installed-package smoke command. Local DP
96
+ optimization needs no Neon database, GCP account or GPU.
97
+
78
98
  ---
79
99
 
80
100
  ## Access Options
81
101
 
82
102
  | Method | Description | Link |
83
103
  |--------|-------------|------|
104
+ | **Bioconda** | Linux/macOS; WSL on Windows | [Isolated installation](docs/getting-started.md#via-bioconda-recommended-for-bioinformatics) |
84
105
  | **Web App** | No installation, demo & light use | [factorforge.eijex.com](https://factorforge.eijex.com) |
85
106
  | **CLI / Python** | Local use, batch processing, data privacy | `pip install factorforge-cds` |
86
107
  | **Docker** | Full web interface locally | `docker pull ghcr.io/eijex/factorforge-cds:latest` |
@@ -134,10 +155,15 @@ FactorForge outputs are **in-silico only** and have not been experimentally vali
134
155
  ## Citing
135
156
 
136
157
  ```
137
- FactorForge v3.5.11 (2026). Open-source constraint-based CDS design and sequence review.
158
+ FactorForge v3.5.12 (2026). Open-source constraint-based CDS design and sequence review.
138
159
  Eijex. https://github.com/eijex/factorforge-cds
139
160
  ```
140
161
 
162
+ The [v3.5.11 software archive](https://doi.org/10.5281/zenodo.23631740)
163
+ and the [accompanying computational preprint](https://doi.org/10.20944/preprints202610.3128.v1)
164
+ are separate citations. The preprint reports historical v3.2.0/v3.3.0 executions,
165
+ not a benchmark of every later software release.
166
+
141
167
  ---
142
168
 
143
169
  ## Maintainer
@@ -189,11 +215,11 @@ GNU Affero General Public License v3.0 — see [LICENSE](LICENSE).
189
215
 
190
216
  ## Testing status
191
217
 
192
- The web UI now labels watermark as disabled and distinguishes the sequence-only baseline from experimental structure-conditioned testing. The local approved workflow supports explicit 1DP-only or paired 3DP mode. 3DP availability is local research testing; it is not a new public optimization endpoint or a biological-performance claim. See [web UI boundaries](web/README.md).
218
+ The web UI labels watermark as disabled and distinguishes the sequence-only baseline from retained experimental structure-conditioned testing. The local reviewed workflow supports 1DP-only or paired 3DP mode. General 3DP/4DP web access is paused by default; local research availability is not a biological-performance claim. See [web UI boundaries](web/README.md).
193
219
 
194
- ## Direct 3DP browser testing (unreleased)
220
+ ## Experimental 3DP web access (paused by default)
195
221
 
196
- The FactorForge form supports explicit 1DP/3DP selection. 3DP uploads a PDB/mmCIF file, selects chain and one-based file model order, and requires reviewed one-based protein positions. The selected observed chain must exactly match the complete protein; partial or homologous structures require the retained local reviewed mapping workflow. Direct requests use `/api/optimize` with `design_mode=paired_3dp` and `structure_context={content,format,chain,model,positions,positions_reviewed,target_adaptiveness,penalty_weight}`.
222
+ The public form offers 1DP. General 3DP/4DP web access is paused pending evaluation and collaborator feedback. Research deployments require both a deliberate web build opt-in (`ENABLE_EXPERIMENTAL_STRUCTURE_WEB`) and server opt-in (`FACTORFORGE_EXPERIMENTAL_3DP_ENABLED=true`); these flags are availability controls, not authentication or research consent. Without the server flag, structure generation, recommendation and resolution requests fail with `EXPERIMENTAL_STRUCTURE_DISABLED`. Local experimental implementations are retained. See [research boundaries](docs/experimental-structure.md).
197
223
 
198
224
  Limits: 3–300 amino acids, structure content 250 KB, HTTP JSON body 1 MB. Both candidates use the configured codon reference, requested GC and canonical motif exclusions plus custom additions. Invalid inputs and infeasible candidates fail without a baseline fallback. Existing sequence-only settings and API requests remain supported. 3DP uses its explicit DP settings and does not apply Kozak, TpA, template or seed transformations. SOP checks are reported for both candidates; regeneration is manual and never silently changes mode. Watermark stays disabled.
199
225
 
@@ -201,7 +227,7 @@ This is stateless computational testing, with no external service dependencies o
201
227
 
202
228
  ## Current public policy UI (2026-10-12)
203
229
 
204
- Custom SOP management is paused. The built-in FactorForge default policy is applied; upload/export/preset/editing controls are hidden and disabled. Their code and previous browser configuration remain available for later reactivation through ENABLE_CUSTOM_SOP. Saved custom SOPs are ignored without deletion. 1DP/3DP mode selection and explicit structure inputs remain active. This supersedes the earlier public SOP upload/export instructions. Public API contracts are retained.
230
+ Custom SOP management is paused. The built-in FactorForge default policy is applied; upload/export/preset/editing controls are hidden and disabled. Their code and previous browser configuration remain available for later reactivation through ENABLE_CUSTOM_SOP. Saved custom SOPs are ignored without deletion. 1DP remains active; general 3DP selection and API structure actions are disabled by default. Their retained research contract requires explicit deployment opt-in. This supersedes the earlier public SOP upload/export instructions.
205
231
 
206
232
  ### Scientific web observations
207
233
 
@@ -5,6 +5,7 @@
5
5
  [![License](https://img.shields.io/badge/license-AGPL--3.0-blue.svg)](LICENSE)
6
6
  [![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/)
7
7
  [![PyPI](https://img.shields.io/pypi/v/factorforge-cds.svg)](https://pypi.org/project/factorforge-cds/)
8
+ [![Bioconda](https://img.shields.io/badge/install%20with-bioconda-brightgreen.svg?style=flat)](https://anaconda.org/bioconda/factorforge-cds)
8
9
  [![CI](https://github.com/eijex/factorforge-cds/actions/workflows/ci.yml/badge.svg)](https://github.com/eijex/factorforge-cds/actions/workflows/ci.yml)
9
10
  [![codecov](https://codecov.io/gh/eijex/factorforge-cds/branch/main/graph/badge.svg)](https://codecov.io/gh/eijex/factorforge-cds)
10
11
  [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.20407330.svg)](https://doi.org/10.5281/zenodo.20407330)
@@ -14,7 +15,7 @@
14
15
 
15
16
  FactorForge performs deterministic CDS design with CAI/GC metrics, PolyA-signal screening, and Golden Gate/MoClo-aware checks. It is positioned as a pre-synthesis review harness: it helps teams generate reproducible CDS candidates, inspect assembly-relevant sequence constraints, and package design metadata before downstream synthesis, cloning, or experimental review. Primary support: *N. benthamiana* (agroinfiltration). Experimental host context: Tobacco BY-2 (`--host by2`).
16
17
 
17
- FactorForge v3.5.11 uses independently versioned engines:
18
+ FactorForge v3.5.12 uses independently versioned engines:
18
19
 
19
20
  | Generation | Engine | Version | Availability |
20
21
  |---|---|---:|---|
@@ -31,18 +32,31 @@ FactorForge v3.5.11 uses independently versioned engines:
31
32
  ## Quick Start
32
33
 
33
34
  ```bash
35
+ # Bioconda: Linux/macOS, or Ubuntu inside WSL on Windows
36
+ conda create -n factorforge-review --override-channels -c conda-forge -c bioconda --strict-channel-priority python=3.11 factorforge-cds
37
+ conda activate factorforge-review
38
+
39
+ # Via PyPI
34
40
  pip install factorforge-cds
41
+
42
+ # Run optimization
35
43
  factorforge optimize my_protein.fasta -o output.fasta
36
44
  ```
37
45
 
38
46
  Or use the **[web app](https://factorforge.eijex.com)** — no installation required.
39
47
 
48
+ Bioconda does not support native Windows. Use WSL for that installation route;
49
+ see [installation and reviewer checks](docs/getting-started.md) for the tested
50
+ version, platform limitations and installed-package smoke command. Local DP
51
+ optimization needs no Neon database, GCP account or GPU.
52
+
40
53
  ---
41
54
 
42
55
  ## Access Options
43
56
 
44
57
  | Method | Description | Link |
45
58
  |--------|-------------|------|
59
+ | **Bioconda** | Linux/macOS; WSL on Windows | [Isolated installation](docs/getting-started.md#via-bioconda-recommended-for-bioinformatics) |
46
60
  | **Web App** | No installation, demo & light use | [factorforge.eijex.com](https://factorforge.eijex.com) |
47
61
  | **CLI / Python** | Local use, batch processing, data privacy | `pip install factorforge-cds` |
48
62
  | **Docker** | Full web interface locally | `docker pull ghcr.io/eijex/factorforge-cds:latest` |
@@ -96,10 +110,15 @@ FactorForge outputs are **in-silico only** and have not been experimentally vali
96
110
  ## Citing
97
111
 
98
112
  ```
99
- FactorForge v3.5.11 (2026). Open-source constraint-based CDS design and sequence review.
113
+ FactorForge v3.5.12 (2026). Open-source constraint-based CDS design and sequence review.
100
114
  Eijex. https://github.com/eijex/factorforge-cds
101
115
  ```
102
116
 
117
+ The [v3.5.11 software archive](https://doi.org/10.5281/zenodo.23631740)
118
+ and the [accompanying computational preprint](https://doi.org/10.20944/preprints202610.3128.v1)
119
+ are separate citations. The preprint reports historical v3.2.0/v3.3.0 executions,
120
+ not a benchmark of every later software release.
121
+
103
122
  ---
104
123
 
105
124
  ## Maintainer
@@ -151,11 +170,11 @@ GNU Affero General Public License v3.0 — see [LICENSE](LICENSE).
151
170
 
152
171
  ## Testing status
153
172
 
154
- The web UI now labels watermark as disabled and distinguishes the sequence-only baseline from experimental structure-conditioned testing. The local approved workflow supports explicit 1DP-only or paired 3DP mode. 3DP availability is local research testing; it is not a new public optimization endpoint or a biological-performance claim. See [web UI boundaries](web/README.md).
173
+ The web UI labels watermark as disabled and distinguishes the sequence-only baseline from retained experimental structure-conditioned testing. The local reviewed workflow supports 1DP-only or paired 3DP mode. General 3DP/4DP web access is paused by default; local research availability is not a biological-performance claim. See [web UI boundaries](web/README.md).
155
174
 
156
- ## Direct 3DP browser testing (unreleased)
175
+ ## Experimental 3DP web access (paused by default)
157
176
 
158
- The FactorForge form supports explicit 1DP/3DP selection. 3DP uploads a PDB/mmCIF file, selects chain and one-based file model order, and requires reviewed one-based protein positions. The selected observed chain must exactly match the complete protein; partial or homologous structures require the retained local reviewed mapping workflow. Direct requests use `/api/optimize` with `design_mode=paired_3dp` and `structure_context={content,format,chain,model,positions,positions_reviewed,target_adaptiveness,penalty_weight}`.
177
+ The public form offers 1DP. General 3DP/4DP web access is paused pending evaluation and collaborator feedback. Research deployments require both a deliberate web build opt-in (`ENABLE_EXPERIMENTAL_STRUCTURE_WEB`) and server opt-in (`FACTORFORGE_EXPERIMENTAL_3DP_ENABLED=true`); these flags are availability controls, not authentication or research consent. Without the server flag, structure generation, recommendation and resolution requests fail with `EXPERIMENTAL_STRUCTURE_DISABLED`. Local experimental implementations are retained. See [research boundaries](docs/experimental-structure.md).
159
178
 
160
179
  Limits: 3–300 amino acids, structure content 250 KB, HTTP JSON body 1 MB. Both candidates use the configured codon reference, requested GC and canonical motif exclusions plus custom additions. Invalid inputs and infeasible candidates fail without a baseline fallback. Existing sequence-only settings and API requests remain supported. 3DP uses its explicit DP settings and does not apply Kozak, TpA, template or seed transformations. SOP checks are reported for both candidates; regeneration is manual and never silently changes mode. Watermark stays disabled.
161
180
 
@@ -163,7 +182,7 @@ This is stateless computational testing, with no external service dependencies o
163
182
 
164
183
  ## Current public policy UI (2026-10-12)
165
184
 
166
- Custom SOP management is paused. The built-in FactorForge default policy is applied; upload/export/preset/editing controls are hidden and disabled. Their code and previous browser configuration remain available for later reactivation through ENABLE_CUSTOM_SOP. Saved custom SOPs are ignored without deletion. 1DP/3DP mode selection and explicit structure inputs remain active. This supersedes the earlier public SOP upload/export instructions. Public API contracts are retained.
185
+ Custom SOP management is paused. The built-in FactorForge default policy is applied; upload/export/preset/editing controls are hidden and disabled. Their code and previous browser configuration remain available for later reactivation through ENABLE_CUSTOM_SOP. Saved custom SOPs are ignored without deletion. 1DP remains active; general 3DP selection and API structure actions are disabled by default. Their retained research contract requires explicit deployment opt-in. This supersedes the earlier public SOP upload/export instructions.
167
186
 
168
187
  ### Scientific web observations
169
188
 
@@ -1,10 +1,10 @@
1
1
  [build-system]
2
- requires = ["setuptools>=68", "wheel"]
2
+ requires = ["setuptools>=77.0.3", "wheel"]
3
3
  build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "factorforge-cds"
7
- version = "3.5.11"
7
+ version = "3.5.12"
8
8
  description = "FactorForge - open-source CDS design and pre-synthesis sequence review by Eijex."
9
9
  readme = "README.md"
10
10
  license = "AGPL-3.0-only"
@@ -45,6 +45,16 @@ ml = [
45
45
  "torch>=2.0",
46
46
  "onnxruntime>=1.16",
47
47
  ]
48
+ acceleration = [
49
+ "pyahocorasick>=2.3.1",
50
+ ]
51
+ benchmark = [
52
+ "dnachisel>=3.2.16",
53
+ "scipy>=1.17",
54
+ ]
55
+ ml-structure = [
56
+ "fair-esm>=2.0.0",
57
+ ]
48
58
 
49
59
  [project.urls]
50
60
  Homepage = "https://factorforge.eijex.com"
@@ -408,18 +408,45 @@ def detect_repeats(sequence: str) -> list[dict[str, Any]]:
408
408
 
409
409
 
410
410
  def detect_forbidden_motifs(sequence: str, motifs: list[str]) -> list[dict[str, Any]]:
411
- """Find all exact forbidden motif occurrences."""
411
+ """Find all exact forbidden motif occurrences.
412
+
413
+ Uses pyahocorasick C-automaton when available for O(N + M) single-pass scanning;
414
+ falls back transparently to pure Python string searching if unavailable.
415
+ """
412
416
  seq = _normalize_dna(sequence)
413
- findings: list[dict[str, Any]] = []
414
- for motif in motifs:
415
- normalized = _normalize_dna(motif)
416
- if not normalized:
417
- continue
418
- start = seq.find(normalized)
419
- while start != -1:
420
- findings.append({"start": start, "end": start + len(normalized), "motif": normalized})
421
- start = seq.find(normalized, start + 1)
422
- return findings
417
+ if not seq or not motifs:
418
+ return []
419
+
420
+ try:
421
+ import ahocorasick
422
+
423
+ A = ahocorasick.Automaton()
424
+ has_motif = False
425
+ for m in motifs:
426
+ norm = _normalize_dna(m)
427
+ if norm:
428
+ A.add_word(norm, norm)
429
+ has_motif = True
430
+ if not has_motif:
431
+ return []
432
+ A.make_automaton()
433
+
434
+ findings: list[dict[str, Any]] = []
435
+ for end_idx, norm in A.iter(seq):
436
+ start = end_idx - len(norm) + 1
437
+ findings.append({"start": start, "end": end_idx + 1, "motif": norm})
438
+ return sorted(findings, key=lambda x: (x["start"], x["end"]))
439
+ except ImportError:
440
+ findings = []
441
+ for motif in motifs:
442
+ normalized = _normalize_dna(motif)
443
+ if not normalized:
444
+ continue
445
+ start = seq.find(normalized)
446
+ while start != -1:
447
+ findings.append({"start": start, "end": start + len(normalized), "motif": normalized})
448
+ start = seq.find(normalized, start + 1)
449
+ return findings
423
450
 
424
451
 
425
452
  def detect_invalid_codons(sequence: str) -> list[dict[str, Any]]:
@@ -998,8 +998,10 @@ def audit(sequence_fasta, reference_codon_profile, exclude_region, output):
998
998
 
999
999
 
1000
1000
  from factorforge.nbfold.cli import nbfold_cli
1001
+ from factorforge.cli.structure_cli import structure_cli
1001
1002
 
1002
1003
  cli.add_command(nbfold_cli)
1004
+ cli.add_command(structure_cli)
1003
1005
 
1004
1006
 
1005
1007
  if __name__ == "__main__":
@@ -0,0 +1,157 @@
1
+ """Click CLI subcommands for FactorForge structure intake, sidecars, and Mol* viewer integration."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from pathlib import Path
7
+ from typing import Optional
8
+
9
+ import click
10
+
11
+ from factorforge.structure.interpro_sidecar_fetcher import fetch_interpro_sidecar
12
+ from factorforge.structure.uniprot_sidecar_fetcher import fetch_uniprot_sidecar
13
+ from factorforge.structure.viewer_bridge import (
14
+ build_structure_position_mapping,
15
+ prepare_viewer_annotations,
16
+ )
17
+
18
+
19
+ @click.group("structure")
20
+ def structure_cli() -> None:
21
+ """Structure intake, UniProt/InterPro automated sidecars, and Mol* viewer integration."""
22
+
23
+
24
+ @structure_cli.command("fetch-uniprot")
25
+ @click.option("--accession", "-a", required=True, help="UniProt accession (e.g. P21926).")
26
+ @click.option("--sequence", "-s", default=None, help="Optional protein sequence to verify identity.")
27
+ @click.option("--output", "-o", type=click.Path(path_type=Path), help="Output path for JSON sidecar.")
28
+ @click.option("--cache-dir", type=click.Path(path_type=Path), default=None, help="Local cache directory.")
29
+ def fetch_uniprot_cmd(
30
+ accession: str,
31
+ sequence: Optional[str],
32
+ output: Optional[Path],
33
+ cache_dir: Optional[Path],
34
+ ) -> None:
35
+ """Fetch and normalize UniProt experimental/curated features into FactorForge sidecar."""
36
+ result = fetch_uniprot_sidecar(
37
+ accession=accession,
38
+ target_protein_sequence=sequence,
39
+ cache_dir=cache_dir,
40
+ )
41
+ payload_str = json.dumps(result, indent=2)
42
+ if output:
43
+ output.parent.mkdir(parents=True, exist_ok=True)
44
+ output.write_text(payload_str, encoding="utf-8")
45
+ click.echo(f"UniProt sidecar saved to {output} (status: {result.get('status')})")
46
+ else:
47
+ click.echo(payload_str)
48
+
49
+
50
+ @structure_cli.command("fetch-interpro")
51
+ @click.option("--accession", "-a", required=True, help="UniProt accession for InterPro entry search.")
52
+ @click.option("--sequence", "-s", required=True, help="Target protein sequence for coordinate bounds.")
53
+ @click.option("--output", "-o", type=click.Path(path_type=Path), help="Output path for JSON sidecar.")
54
+ @click.option("--cache-dir", type=click.Path(path_type=Path), default=None, help="Local cache directory.")
55
+ def fetch_interpro_cmd(
56
+ accession: str,
57
+ sequence: str,
58
+ output: Optional[Path],
59
+ cache_dir: Optional[Path],
60
+ ) -> None:
61
+ """Fetch and normalize InterPro domain families into FactorForge sidecar."""
62
+ result = fetch_interpro_sidecar(
63
+ accession=accession,
64
+ target_protein_sequence=sequence,
65
+ cache_dir=cache_dir,
66
+ )
67
+ payload_str = json.dumps(result, indent=2)
68
+ if output:
69
+ output.parent.mkdir(parents=True, exist_ok=True)
70
+ output.write_text(payload_str, encoding="utf-8")
71
+ click.echo(f"InterPro sidecar saved to {output} (status: {result.get('status')})")
72
+ else:
73
+ click.echo(payload_str)
74
+
75
+
76
+ @structure_cli.command("annotate")
77
+ @click.option("--accession", "-a", required=True, help="UniProt accession (e.g. P21926).")
78
+ @click.option("--structure-file", "--cif", type=click.Path(path_type=Path, exists=True), default=None, help="3D structure file (.cif, .mmcif, .pdb).")
79
+ @click.option("--chain", default="A", help="Structure chain ID (default: A).")
80
+ @click.option("--sequence", "-s", default=None, help="Optional protein sequence.")
81
+ @click.option("--interpro/--no-interpro", default=True, help="Whether to fetch InterPro domains.")
82
+ @click.option("--output", "-o", type=click.Path(path_type=Path), help="Output JSON path for consolidated annotations and viewer payload.")
83
+ @click.option("--cache-dir", type=click.Path(path_type=Path), default=None, help="Cache directory.")
84
+ def annotate_cmd(
85
+ accession: str,
86
+ structure_file: Optional[Path],
87
+ chain: str,
88
+ sequence: Optional[str],
89
+ interpro: bool,
90
+ output: Optional[Path],
91
+ cache_dir: Optional[Path],
92
+ ) -> None:
93
+ """Consolidate UniProt, InterPro, and 3D structure coordinates into verified Mol* viewer payload."""
94
+ click.echo(f"Fetching UniProt features for '{accession}'...")
95
+ uniprot_res = fetch_uniprot_sidecar(accession=accession, target_protein_sequence=sequence, cache_dir=cache_dir)
96
+
97
+ target_seq = sequence
98
+ if not target_seq and uniprot_res.get("status") == "AVAILABLE":
99
+ target_seq = uniprot_res.get("sequence", {}).get("value")
100
+
101
+ interpro_res = None
102
+ if interpro and target_seq:
103
+ click.echo(f"Fetching InterPro domains for '{accession}'...")
104
+ interpro_res = fetch_interpro_sidecar(accession=accession, target_protein_sequence=target_seq, cache_dir=cache_dir)
105
+
106
+ # Merge candidate regions
107
+ all_candidates = []
108
+ if uniprot_res.get("status") == "AVAILABLE":
109
+ all_candidates.extend(uniprot_res.get("candidate_regions", []))
110
+ if interpro_res and interpro_res.get("status") == "AVAILABLE":
111
+ all_candidates.extend(interpro_res.get("candidate_regions", []))
112
+
113
+ # Resolve 3D coordinates against structure if provided
114
+ position_mapping = None
115
+ if structure_file and target_seq:
116
+ click.echo(f"Mapping coordinates against structure '{structure_file.name}' chain '{chain}'...")
117
+ struct_text = structure_file.read_text(encoding="utf-8")
118
+ fmt = structure_file.suffix.lstrip(".").lower()
119
+ try:
120
+ position_mapping = build_structure_position_mapping(
121
+ protein_sequence=target_seq,
122
+ structure_content=struct_text,
123
+ format=fmt,
124
+ chain_id=chain,
125
+ )
126
+ click.echo(f"Successfully mapped {len(position_mapping)} residues to structure auth_seq_id.")
127
+ except Exception as exc:
128
+ click.echo(f"Warning: Structure coordinate mapping failed ({exc}). Falling back to unverified sequence indices.")
129
+
130
+ viewer_annotations = prepare_viewer_annotations(
131
+ {"candidate_regions": all_candidates},
132
+ auth_asym_id=chain,
133
+ position_mapping=position_mapping,
134
+ )
135
+
136
+ consolidated = {
137
+ "accession": accession,
138
+ "protein_length": len(target_seq) if target_seq else None,
139
+ "structure_file": str(structure_file) if structure_file else None,
140
+ "chain_id": chain,
141
+ "coordinate_mapping_verified": position_mapping is not None,
142
+ "uniprot": uniprot_res,
143
+ "interpro": interpro_res,
144
+ "candidate_regions_total": len(all_candidates),
145
+ "viewer_annotations": viewer_annotations,
146
+ "reviewed": False, # Mandatory human review invariant
147
+ "epistemic_status": "UNVERIFIED_PUBLIC_CORPUS",
148
+ "biological_validation": "NOT_AVAILABLE",
149
+ }
150
+
151
+ out_json = json.dumps(consolidated, indent=2)
152
+ if output:
153
+ output.parent.mkdir(parents=True, exist_ok=True)
154
+ output.write_text(out_json, encoding="utf-8")
155
+ click.echo(f"Consolidated annotation report & viewer payload saved to {output}")
156
+ else:
157
+ click.echo(out_json)
@@ -2,9 +2,9 @@
2
2
  "schema_version": "1.0",
3
3
  "product": {
4
4
  "name": "FactorForge",
5
- "version": "3.5.11",
5
+ "version": "3.5.12",
6
6
  "release_status": "released",
7
- "previous_stable_version": "3.5.10"
7
+ "previous_stable_version": "3.5.11"
8
8
  },
9
9
  "engines": {
10
10
  "profile": {
@@ -0,0 +1,45 @@
1
+ """Structure intake, annotation, and recommendation adapters for FactorForge."""
2
+
3
+ from factorforge.structure.auto_annotator import (
4
+ CandidateRegion,
5
+ StructureRecommendationReport,
6
+ recommend_structure_pause_regions,
7
+ )
8
+ from factorforge.structure.esm_annotator import (
9
+ ESMRecommendationReport,
10
+ ESMStructureAnnotator,
11
+ recommend_esm_pause_regions,
12
+ )
13
+ from factorforge.structure.interpro_sidecar_fetcher import (
14
+ InterProSidecarFetcher,
15
+ fetch_interpro_raw_record,
16
+ fetch_interpro_sidecar,
17
+ )
18
+ from factorforge.structure.uniprot_sidecar_fetcher import (
19
+ UniProtSidecarFetcher,
20
+ fetch_uniprot_raw_record,
21
+ fetch_uniprot_sidecar,
22
+ )
23
+ from factorforge.structure.viewer_bridge import (
24
+ COLOR_PALETTE,
25
+ build_structure_position_mapping,
26
+ prepare_viewer_annotations,
27
+ )
28
+
29
+ __all__ = [
30
+ "CandidateRegion",
31
+ "StructureRecommendationReport",
32
+ "recommend_structure_pause_regions",
33
+ "ESMRecommendationReport",
34
+ "ESMStructureAnnotator",
35
+ "recommend_esm_pause_regions",
36
+ "UniProtSidecarFetcher",
37
+ "fetch_uniprot_raw_record",
38
+ "fetch_uniprot_sidecar",
39
+ "InterProSidecarFetcher",
40
+ "fetch_interpro_raw_record",
41
+ "fetch_interpro_sidecar",
42
+ "COLOR_PALETTE",
43
+ "build_structure_position_mapping",
44
+ "prepare_viewer_annotations",
45
+ ]