Skip to content

Declarative method patches + exclude-long-term on bulk impacts#192

Merged
ccomb merged 4 commits into
mainfrom
compare2
Jul 11, 2026
Merged

Declarative method patches + exclude-long-term on bulk impacts#192
ccomb merged 4 commits into
mainfrom
compare2

Conversation

@ccomb

@ccomb ccomb commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds [[methods.patches]]: a declarative, idempotent way to rescale or override matched characterization factors at method-load time — the data-driven equivalent of a Brightway import strategy, without its statefulness (re-loading never compounds a patch, since it's re-derived from the untouched source file every time).
  • Extends exclude-long-term to the bulk POST /impacts endpoint and the score_activities MCP tool, which previously only supported it per-activity.

Test plan

  • cabal build lib:volca — clean, no warnings
  • cabal test lca-tests — 1543 examples, 0 failures
  • Live server smoke test: a real TOML config with a [[methods.patches]] block loads without a "touched 0 CFs" warning; a deliberately wrong selector does trigger the warning

ccomb added 4 commits July 11, 2026 08:12
Method import strategies (Brightway's term for imperative CF-mutation
functions applied at import time) are stateful and non-idempotent: they
mutate a persisted store, so re-running an import re-applies the
mutation. VoLCA parses methods fresh from source on every load, so the
same adjustment can be expressed as data instead: a `[[methods.patches]]`
TOML block that rescales or overrides matched characterization factors,
applied as a pure transform right after parsing.

A patch selector (category, flow name/prefix, CAS, subcompartment
substring) is a product type with conjunctive matching; the decoder
rejects an empty selector and requires exactly one of `scale` or
`set-value`, so invalid patches are unrepresentable rather than silently
ambiguous. A patch that matches zero characterization factors logs a
warning at load time instead of failing silently.

Config.mcPatches defaults to `[]`, so existing configs are unaffected.
The per-activity /impacts endpoint already let a caller drop delayed
long-term emissions before scoring; the bulk multi-activity endpoint
(POST /db/{db}/impacts/{collection}) didn't, forcing scripts that need
both a full panel and long-term exclusion onto the much slower
per-activity path. Threads the same LongTermMode through
batchImpactsH/runBatchImpacts, applied to each solved inventory before
characterization. Also exposed on the score_activities MCP tool, which
had the same gap relative to score_activity.
mapAccumL instead of a foldl with quadratic list append, maybeToList
instead of a local reimplementation, and a total factorValues helper in
the spec instead of irrefutable let patterns that would crash rather
than fail cleanly.
Also record the bulk exclude-long-term extension in the changelog.
@ccomb ccomb merged commit b9fbfaf into main Jul 11, 2026
9 checks passed
@ccomb ccomb deleted the compare2 branch July 11, 2026 07:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant