Repository navigation
Conversation
…ted in element uptake
…ance of claude web
…fixes to community and flexible biomass and thermo and adding features to msexpression
MSTemplateBuilder.from_dict() was silently dropping the drain_list from template JSON files, so template.drains stayed empty. This meant MSBuilder.build_drains() fell back to DEFAULT_SINKS and only created SK_ (sink) reactions, never DM_ (demand) reactions. Without DM_cpd11416_c0, cobrapy FBA returns 0 growth because the biomass compound (cpd11416) produced by bio1 has no outlet. Two fixes: 1. mstemplate.py: from_dict() now reads drain_list into builder.drains 2. msbuilder.py: build_demands() creates DM_ reactions for all drain compounds (previously required lower_bound < 0, but template drain_list entries use [0, 1000]) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix drain_list loading: create DM_ demand reactions during model build
…dd frontmatter - Replace 306-line obsolete CLAUDE.md with focused tier-split version - Remove non-home expert/dev skills (only universal + home-repo skills remain) - Retire: run_headless, free-agent, analyze-email, generate-tasks, create-prd, create-skill - Add YAML frontmatter (name, description, scope) to all surviving skills Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Convention pivot: .claude/commands/ is now runtime-only (gitignored, populated by `claude-skills sync`). Source-of-truth lives in agent-io/skills/.
The docstrings for MSGapfill.run_multi_gapfill and MSGapfill.integrate_gapfill_solution listed "Cumulative" and "Simultaneous" as valid gapfilling_mode values, but the code only branches on "Sequential", "Independent", and "Global". Passing one of the historical names silently fell through all branches and produced a no-op. Rewrote both docstrings to describe the three real modes accurately and explicitly call out that "Cumulative" and "Simultaneous" are not honored. Also updated two inline comments that referred to "cumulative" / "simultaneous" gapfilling when describing the Sequential / Global branches. Doc-only change: no logic, signatures, branches, or defaults modified. The cumulative_solution local variable and cumulative_gapfilling attribute are preserved as-is (they refer to the solution list, not the mode name).
…feature lookup
Two related changes that unblock the modelseed-api bulk-reconstruction
endpoint (Phase 3 per Chris Henry's PRD).
1. New factory: AnnotationOntology.from_prd_input(genome_id, annotations,
data_dir, translator, ...). Mirrors from_kbase_data but for inputs
whose ontology terms have NOT been pre-translated to ModelSEED
reaction IDs. The translator callable is injected so the factory
stays decoupled from any specific translation backend
(KBUtilLib.KBAnnotationUtils.translate_term_to_modelseed is the
canonical impl; tests use a small in-memory fake).
Input shape: {gene_id: {ontology_type: [{term, score}, ...]}}.
Synthesizes one AnnotationOntologyEvent per ontology type, keeps
priority-list logic untouched. Unmapped terms (translator returns
[]) are retained with an empty msrxns set - per PRD, unmapped genes
must never silently disappear.
2. Fix latent bug at msbuilder.py:789 in build_from_annotaton_ontology.
The line called anno_ont.get_feature(gene.id) but AnnotationOntology
has no such method (features are keyed in genes or cdss dicts). Any
call path that reached this line would AttributeError as soon as it
tried to attach evidence to a built reaction. Replaced with the
correct accessor: anno_ont.genes.get(gene.id) or anno_ont.cdss.get(gene.id).
9 unit tests cover both changes:
- 7 cases for from_prd_input (happy path, multi-gene/multi-ontology,
score recording, default score, unmapped retention, namespaced-term
passing, empty input)
- 2 regression tests for the msbuilder fix (one positive, one negative
lock to flag if get_feature is ever added back without reconciling
the msbuilder line)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…e in run_multi_gapfill Two-stage gapfilling: Stage 1 maximizes simultaneously-active native reactions (ReactionActivationPkg + RevBinPkg MILP), Stage 2 minimizes database additions that sustain those locked active directions while producing biomass. The method is exposed both as MSGapfill.run_comprehensive_gapfilling() and as gapfilling_mode='Comprehensive' in run_multi_gapfill (integrating cumulatively like Sequential across multiple media). Six integration tests cover: correct return shape, positive biomass after integration, comprehensive > sequential active-reaction count, no native reaction removal, gfmodel reusability after lock release, and correct shape from run_multi_gapfill. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ease Activation variable lower-bounds are now unconditionally released via a finally block, even if an unexpected exception fires during Stage 2 or test-condition evaluation. Functional behaviour is unchanged; all six integration tests pass. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… run set_base_objective built the biomass>=minobjective constraint directly but never updated self.parameters["minimum_obj"]. Because test_gapfill_database later restores the biomass floor via reset_objective_minimum(parameters[ "minimum_obj"]), a run_gapfilling(minimum_obj=X) with X above the construction -time default was silently relaxed back to the default before the final optimization -- so the gapfiller returned the cheapest reaction set reaching the default threshold rather than the requested growth. Keep parameters[ "minimum_obj"] in sync inside set_base_objective. Fixes test_ms_gap_fill2 (growth 0.8 now re-adds the full oxidative-phosphorylation set: GLCpts, O2t, NADH16, CYTBD). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…mode Comprehensive gapfilling activates the model's native reactions as a collectively-necessary set; per-reaction knockout pruning classifies each as individually redundant and strips them, leaving the model unable to grow. run_multi_gapfill now overrides remove_unneeded_reactions to False (with a warning) for gapfilling_mode='Comprehensive' so callers cannot defeat the activation by leaving the default True in place. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…V->V in Gibbs constraint The membrane term in build_gibbs_constraint was computing charge * Faraday(kC/mol) * compartment_potential without the /1000 factor needed to convert the mV input to V. With the default c0 = -160 mV this inflated the term by ~1000x (charge * 96.485 * -160 kJ/mol instead of charge * 96.485 * -0.16 kJ/mol), driving TMFA infeasible for any charged cytoplasmic metabolite. Changes: - build_gibbs_constraint: divide compartment_potential by 1000 (mV->V) so that Faraday(kC/mol) * V = kJ/mol, matching deltaG units - Keep the -160 mV default for c0 unchanged; update comments to state mV explicitly on both defaults (e0=0 mV, c0=-160 mV) - Add warns-only guard (no raise/clamp): WARNING >300 mV (suspicious), stronger WARNING >1000 mV (egregiously non-physical) - Add regression test suite in tests/fbapkg/test_fullthermo_membrane_potential_unit.py verifying: default values, mV-scaled constant arithmetic, neutralcharge/e0 edge cases, and the two-band warning guard Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…d-input feat(annoont): AnnotationOntology.from_prd_input + fix msbuilder get_feature lookup
Author agent-io/roadmaps/energy-loop-analysis.md as the first production roadmap arc for the modelseedpy project. 6 milestones (m1a/m1b parallel in group g1, m2-m5 sequential); sourced from the ai-roadmap humanprompt Example 2 and conforms to the AIAssistant roadmap schema. Parses cleanly via assistant.state.roadmap.load_roadmap. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… record Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Parse check: 6 milestones, grouped 2 [g1], status enum ok. File matches AIAssistant fixture byte-for-byte.
`rpcclient.py:75` does `raise ServerError(**err["error"])` which
requires `err["error"]` to be a mapping. Well-behaved JSON-RPC servers
return a dict there, but tutorial.theseed.org (and other backends
under load) occasionally return a plain string or a list. The
`**` unpack then raises
TypeError: argument after ** must be a mapping, not str
which masks the real upstream failure and surfaces to callers as a
completely unrelated exception. modelseed-api's failure_watcher has
been auto-filing GitHub issues for this shape.
Fix: check `isinstance(error_body, dict)` before the `**` unpack. When
it's not a mapping, coerce the body into `ServerError("Unknown", 0,
str(body))` - the same shape we already produce for a non-JSON 500 or
a JSON 500 without an `error` key. Callers see a `ServerError` with
the upstream body attached to `.message` instead of a `TypeError` with
no context.
5 unit tests in tests/core/test_rpcclient.py:
- dict error body -> populated ServerError (happy path)
- string error body -> Unknown ServerError with body in message (regression)
- list error body -> same shape as string
- 500 with no `error` key -> pre-existing Unknown branch, locked in
- 500 with non-JSON content-type -> pre-existing branch, locked in
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fix(rpcclient): handle non-dict error bodies from JSON-RPC 500 responses
…rmoPkg
Extends FullThermoPkg.build_concfit_objective with an optional per-metabolite
weights dict (weights=None reproduces the pre-change unweighted objective
exactly) and adds a new build_concfit_objective_l2 builder for a quadratic
weighted-least-squares fit, guarded to require a QP-capable optlang backend
(gurobi/cplex) since GLPK cannot hold a quadratic objective. build_package
gains concfit_objective_type ("l1"|"l2", default "l1") and concfit_weights
(default None) to dispatch between them, and now raises a clear ValueError
(not KeyError) when set_concfit_objective=True but target_concentrations is
absent. Implements Modules 1-3 of
agent-io/prds/tmfa-weighted-concfit/fullprompt.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`run_atp_correction` ends `return self.build_tests()` -- that is, AFTER `expand_model_to_genome_scale` has applied the ATP expansion filter by zeroing one direction of each cycle-forming reaction. `build_tests` opened with a truthiness test on `selected_media`, so a model where NO medium qualified re-entered the "not yet computed" branch, and that branch ends in `restore_noncore_reactions()` -- which writes `original_bounds` back over every non-core reaction and so silently undoes the filter. `selected_media` is initialised to None and `determine_growth_media` sets it to a list before appending, so an EMPTY list means "evaluated, and nothing qualified" -- a real answer, not a missing one. `is None` is the check the guard was always meant to make; truthiness conflated the two states. Measured on KBDL builds: `rxn08941_c0` went from blocked back to [-1000, 1000] and free ATP from 0 to 1000, returning energy-generating cycles to a delivered model with no error and no warning. This fires for any genome that ends up with zero selected media, so it is latent in every caller of `run_atp_correction`, modelseed-api included -- not only in the KBDL path that exposed it. Also drop a stray line in `MSModelUtil.get_atputl` that built a correctly configured `MSATPCorrection` and then immediately overwrote it with `MSATPCorrection(self.model)`, discarding `core_template`, the ATP media path and the gap-filling settings. Anything reaching ATP tests through `get_atp_tests` was getting that unconfigured object. The new regression test applies the filter the way `expand_model_to_genome_scale` does and asserts it survives `build_tests`, using the existing infinite-ATP-loop fixture -- the victim it selects is `Kt2r_c0`, the reaction that forms that fixture's cycle. It needs no solver result and no local biochemistry database. A second test pins the `None` side, so narrowing the guard cannot silently disable it. The first fails against the previous code. Refs kbaseincubator/KBDLJobRunningPrototype#28 (cause 2). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Brings in AnnotationOntology.from_prd_input plus the msbuilder get_feature lookup fix (#26), and non-dict JSON-RPC 500 error-body handling in rpcclient (#27). Neither touches msatpcorrection.py or msmodelutl.py, so the ATP-safety fix in c49e958 is unaffected; git merge-tree previewed this as conflict-free before it was run. Merging so that main carries both halves before it is pushed: GitHub main was at b758b44, which still carried the build_tests bug that c49e958 fixes, and that commit is what the modelseed-api Docker image pins.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.