Surface co-product allocation in pyvolca#150
Merged
Merged
Conversation
A multi-output process splits its parent activity's burden across its co-products, and the engine carries each share as `allocationPercent` on every `allProducts` entry. The typed client dropped it: `Activity` declared only its six identity/quantity fields and `FromJson` keeps only declared keys, so the share never reached `ActivityDetail.all_products`. Declare `allocation_percent` / `allocation_formula` on `Activity` (both optional — search results carry no share) and add `ActivityDetail.allocation_percent` for the fetched process's own share. `is_allocated` now counts the structured shares rather than importing the description-text parser.
…ield `is_allocated` and `decompose`'s co-product enumeration scraped the allocation factors out of the description text. That text is rounded and can drift from the factor the engine actually applied — e.g. a cheese whose allocation comment reads 52.62% but whose applied share is 51.4%. Read the per-product shares from `all_products` instead, falling back to the text parse only when structured shares are absent (older databases). `parse_allocation` stays for the one thing the wire doesn't carry: the human-readable allocation method label.
Adds co-product allocation shares to the typed client. Client-only and additive — it reads wire fields the engine already emits, so the wire contract is unchanged.
Generated by scripts/gen_api_md.py — picks up the new Activity allocation_percent / allocation_formula fields. Keeps the test_readme_api_reference_in_sync drift gate green.
is_allocated had become a thin alias to ActivityDetail.is_allocated, which reads structured allocation_percent only. On older Agribalyse databases that carry no structured shares — just an allocation block in the description — a genuinely allocated process then reported False, disagreeing with decompose, which still parses that text to enumerate co-products. Restore the prefer-structured-then-text precedence decompose uses, so the Agribalyse-specific helper keeps the text fallback while the generic property stays structured-only.
Merged
ccomb
added a commit
that referenced
this pull request
Jun 24, 2026
Patch release. The only engine change since v0.8.0 is the #151 scoring fix: aggregate single scores (e.g. PEF) failed with `Unknown variable` on JRC ILCD method collections such as EF 3.1, because methods sharing a coarse damage category collapsed in the scoring input map. #151 keys that map by method name, so the per-method scoring variables resolve. - Bump `volca.cabal` 0.8.0 → 0.8.1 - Add `## [0.8.1]` CHANGELOG section #150 is also on main since v0.8.0 but is pyvolca-only (already shipped on its own `pyvolca-v0.7.0` tag) and adds no engine surface, so this stays a patch, not a minor.
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.
A multi-output process splits its parent activity's burden across its
co-products — a cheese activity, for instance, also yields whey, cream,
permeate and whey concentrate, each carrying a share that sums to ~100%. The
engine already emits these shares as
allocationPercenton everyallProductsentry, but the Python client silently dropped them:Activitydeclared only its identity/quantity fields, and
FromJsonkeeps only declaredkeys — so the share never reached
ActivityDetail.all_products.What changes
Activity.allocation_percent/Activity.allocation_formulaare now decoded(optional — search results carry no share). They populate every
ActivityDetail.all_productsentry, so you can read how a process's impactis split across its products:
ActivityDetail.allocation_percentreturns the fetched process's own share.is_allocatedand the Agribalysedecomposehelper now read thesestructured shares instead of scraping the description text. That text is
rounded and can drift from the factor the engine actually applied (e.g. an
allocation comment reading 52.62% where the applied share is 51.4%);
parse_allocationis kept only for the human-readable allocation methodlabel, which the wire doesn't carry.
Notes
Client-only and additive: it reads wire fields the engine already produces, so
the wire contract is unchanged. Released as pyvolca 0.7.0.