feat: add SCI report output method - #1361
Open
davidberenstein1957 wants to merge 3 commits into
Open
Conversation
Emit an ISO/IEC 21031 Software Carbon Intensity report alongside the existing output methods. E and I come from the measured run; R and M are user declarations and are reported as undeclared rather than guessed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1361 +/- ##
==========================================
+ Coverage 91.39% 91.60% +0.20%
==========================================
Files 49 50 +1
Lines 5056 5156 +100
==========================================
+ Hits 4621 4723 +102
+ Misses 435 433 -2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
task_out() handed the same declared M to every task, so a run with 5 tasks reported the device's full embodied carbon 5 times and each per-task sci included 100% of it. Split M by each task's share of the run duration. Chosen over dropping M from task reports because the split is exhaustive: the per-task figures now sum back to the run-level report, and M_source records the share applied. Also document that `output_methods = csv,sci` alone can never produce a non-null sci unless the context file hardcodes functionalUnit.count. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
davidberenstein1957
marked this pull request as ready for review
August 12, 2026 19:14
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.
Adds an SCI (Software Carbon Intensity, ISO/IEC 21031:2024) output method, following the same pattern as the existing BoAmps exporter.
What it adds
codecarbon/output_methods/sci.py, a single module holding the two declaration dataclasses, the pure mapping function, and the handler:FunctionalUnit/EmbodiedDeclaration— theRandMterms, which only the user can supply.map_emissions_to_sci(data, ...)— pure, no I/O.Iis derived asemissions * 1000 / energy_consumedrather than recomputed, so the report agrees with the CSV by construction and inherits the cloud-region, PUE and country/region handling already applied upstream.SCIOutput(BaseOutput)—out()writessci_report_<run_id>.json,task_out()writessci_report_tasks_<run_id>.jsonwith one entry per task,live_out()is a documented no-op because the report is final rather than incremental.OutputMethod.SCIregistered in_init_output_methods, reading an optionalsci_context_filefrom the usual config hierarchy.Two honesty rules, both tested:
Rdeclared → the report is still written, withsci: nulland astatusfield explaining why, instead of dividing by zero or assumingR = 1.Mdeclared →M_gCO2e: 0withM_source: "not declared", so a reader can see the report covers only the operational half.User-facing surface
sci.set_functional_unit_count(n)for the common case where the count is only known at the end;SCIOutput.from_file("sci_context.json")for the declarative path;output_methods = csv,sciplussci_context_filein.codecarbon.config.Docs: a new SCI section in
docs/reference/output.md(including a sample report), a row indocs/how-to/examples.md, and a runnableexamples/sci_output.py. No new dependencies.Verification
uv run pytest tests/test_sci_output.py -q— 14 tests covering the formula, provenance assembly, the undeclared-Rand undeclared-Mbranches, zero-energy, the handler and its task path, and context-file loading (valid, missing, malformed).black --checkandruff checkwere run scoped to the touched files; the remaining ruff hits are the sameOptional/List/dict()style the surrounding modules already use, so the new code matches its neighbours.Deliberately left out
EmbodiedProfiletracker parameter, no bundled hardware table, no cloud per-instance figures. CodeCarbon has no defensible manufacturing data, and an uncitedMin a compliance report is worse than a blank one.Mis user-declared or explicitly undeclared.emissionsmeans. Existing consumers are untouched.Closes #1353
🤖 Generated with Claude Code
Review follow-up: embodied carbon in task reports
task_out()passed the same declaredMto every task, so a run with 5 tasks reported the device's full embodied carbon 5 times, and each per-tasksciincluded 100% of it — a wrong number in a document framed as ISO/IEC 21031 output.Mis now apportioned by each task's share of the run duration. Chosen over omittingMfrom task reports because the split is exhaustive:Ris already the run-level count, so with an apportionedMthe per-task figures sum back to the run-level report instead of quietly dropping half the accounting.M_sourcerecords the share applied, e.g."vendor LCA; apportioned by duration (25.0% of the run)".Tested by
test_task_out_apportions_embodied_by_duration(unequal durations: asserts the 10/30 split of a declared 40 gCO2e and that the shares sum back to 40), plus the undeclared-Mand zero-duration branches.Also documented in
docs/reference/output.mdthat the configuration-only path (output_methods = csv,sci) can never produce a non-nullsciunlessfunctionalUnit.countis hardcoded in the context file, sinceset_functional_unit_count()needs a reference to a handler the tracker owns.