abc report
Researcher-productivity summary read entirely from ~/.abc/db/local.db. No
network calls — abc report is a seed-tier-native command.
Usage
abc report # personal YTD summary, default text mode
abc report --since=2026-01-01 --until=2026-04-30
abc report --show-rate-card # append the full per-rate provenance block
abc report --json # machine-readable; metric IDs as keys
abc report --json --by=investigation
abc report --technical # metric IDs replace human Titles
abc report runs # per-run cost + emissions table (subverb)
abc report runs --full # forensic per-row block (run_id, nomad job, …)
Flags
| Flag | Default | Description |
|---|---|---|
--since=YYYY-MM-DD | Jan 1 of current year | Window start (UTC) |
--until=YYYY-MM-DD | now | Window end (inclusive end-of-day) |
--by=<axis> | unset | Aggregation axis: investigation / project / pipeline / user. JSON-only in v1; text mode rejects with a "deferred to v2" message. |
--show-rate-card | false | Append the detailed per-rate provenance block (currency, CPU/GPU/memory/storage cost rates, all emissions coefficients) + override hints. Hidden by default — the headline already carries a "rates are suggestive default values" disclaimer. |
--json | false | Emit the structured JSON contract documented below |
--technical | false | Replace human Titles with metric IDs in the text headline (useful for reproducible doc snippets) |
--all-contexts | false | Cross-context aggregation. Phase 2: rejects with --all-contexts requires abc-controller-svc; not available in this context. (gated until the controller service is deployed) |
Default output is cost + emissions only (2026-05-27). The "Research time saved" heuristic block was removed from the default render pending real measurement (see the "Research time saved" section below). The detailed rate card moved behind
--show-rate-card.
Two-layer metric naming
Every metric has a stable technical ID (frozen at first ship; used in JSON
keys, --by flag values, SQL view names, and manuscript scripts) plus a
revisable user-facing Title and Gloss (revisable without an ADR).
ID | Title | Gloss |
|---|---|---|
mttfs | First-success time | How long from first attempt to first working run |
failure_to_result_ratio | Failed runs per result | How many tries it took to get a usable answer |
retry_depth | Tries before success | Attempts before the run worked |
mttr_failure | Recovery time | How fast you got back on track after a failure |
stabilisation_runs | Runs to settle | Submissions before the pipeline ran reliably |
queue_wait_fraction | Waiting in queue | Share of total time spent waiting, not running |
active_engagement_hours | Hands-on time | Hours actually at the terminal |
spectator_hours | Watching time | Hours spent monitoring runs |
async_job_fraction | Walked-away runs | Runs you submitted and didn't babysit |
cognitive_overhead_score | Tools per workflow | Distinct commands touched to get one result |
workflows_unattended | Hands-off completions | Pipelines that finished without you stepping in |
submission_source | Submission source | How the run was authored: template / handwritten / rerun |
resource_fit | Right-sized requests | How close requested CPU/RAM matched what was used |
cost_per_investigation | Spend per question | ZAR per investigation, resolved via internal/accounting rate card |
emissions_per_investigation | Carbon per question | kg CO₂e attributed to each investigation, resolved via internal/emissions |
spend_zar | Total spend | Window-wide ZAR aggregate, computed via the shared internal/accounting rate-card resolver |
emissions_kgco2e | Total emissions | Window-wide kg CO₂e, computed via the shared emissions resolver |
hours_saved | Research time saved | Headline composite: estimated busywork avoided |
Adding a metric requires populating all four fields (ID, Title, Gloss, Unit) in the same patch. The ID contract is enforced by tests; titles are capped at 32 characters.
Research time saved (heuristic; JSON / --show-rate-card only)
Removed from default text output (2026-05-27). The
hours_savedfamily is a set of compile-time heuristics (counts of auto-retries, accepted defaults, etc. × hardcoded minute-multipliers) not yet backed by real measurement, so presenting it as a headline number was misleading at the seedling tier. The defaultabc reportnow shows only cost + emissions. The metric is still computed and exposed in the JSON contract (metrics.hours_saved) for downstream consumers; a future instrumented version may return to the text view behind its own flag.
The hours_saved heuristic is the sum of five compile-time constants:
| Constant | Minutes saved per applicable run | Source |
|---|---|---|
AutoRetrySavedMinutes | 15 | brainstorm §5.10; manual re-submit round-trip |
SmartDefaultSavedMinutes | 10 | resource_fit metric rationale |
FailureSummarySavedMinutes | 30 | structured failure summary vs. log diving |
TemplateReuseSavedMinutes | 60 | template / rerun vs. setup from scratch |
AsyncRunSpectatorAvoidedMin | 30 | spectator_hours; median observed monitoring session |
One ledger, one read-side command
abc report is the canonical read-side surface over the local SQLite
runs ledger. The Layer-0/1/2 rate-card resolver (internal/accounting)
and the grid-intensity resolver are consumed directly here; the prior
abc accounting report and abc emissions [report] commands were folded
into this single closed-loop output (spec
cli-verb-tree-restructure).
abc report --since=… --until=…
produces spend, emissions, and postdoc-hours-returned together, with per-investigation rollups.
Subcommands
abc report also hosts the dedicated environmental-footprint reports,
folded in from former top-level verbs on 2026-06-05:
| Command | Was | Purpose |
|---|---|---|
abc report emissions | abc emissions | CO₂e report (Cloud Carbon Footprint v3 coefficients) |
abc report water | abc water | freshwater report (Green Grid Program-WUE formula) |
abc report runs | — | per-run cost + emissions ledger |
abc report compliance | — | compliance status from the ABC API |
All share the same Layer-0/1/2 rate-card resolver, so energy/cost/CO₂e/water
figures stay consistent. Rate-card inputs are configured under
abc config emissions (coefficients) and
abc config accounting (cost rates) — distinct from the read-side reports here.
Sample output
Default — cost + emissions headline only:
$ abc report
Your 2026 so far:
────────────────────────────────────────────────────
Questions explored (investigations): 3
Pipeline runs: 12 (10 worked, 2 retried)
Total compute: 47 CPU-hrs, 0 GPU-hrs
Spend this period: R 1,420
Emissions this period: 47.3 kg CO₂e
These rates are suggestive based on the reasonable default values,
the real-time rates are coming soon.
With --show-rate-card — appends the full per-rate provenance block:
$ abc report --show-rate-card
[ … headline blocks as above … ]
Rate card (effective):
currency ZAR built-in (SA market default)
cost.cpu_hour 0.5 built-in (abc-cluster-cli vX — SA on-prem indicative)
cost.gpu_hour 9 built-in (abc-cluster-cli vX — SA on-prem indicative)
cost.memory_gb_hour 0.05 built-in (abc-cluster-cli vX — SA on-prem indicative)
cost.storage_scratch_gb_hour 0.0001 built-in (amortised enterprise NVMe + power)
cost.postdoc_per_hour 350 built-in (HSRC 2025 SA postdoctoral compensation guidance)
emissions.grid_factor_gco2_per_kwh 900 built-in (Eskom Integrated Annual Report 2023)
emissions.cpu_w 12 built-in (Cloud Carbon Footprint v3 coefficient set)
emissions.gpu_w 250 built-in (Cloud Carbon Footprint v3 coefficient set)
emissions.memory_gb_w 0.3725 built-in (Cloud Carbon Footprint v3 coefficient set)
emissions.pue 1.5 built-in (Uptime Institute 2023 — generic on-prem average)
emissions.storage_scratch_w_per_tb 8 built-in (Samsung PM9A3 envelope amortised)
These rates are suggestive based on the reasonable default values,
the real-time rates are coming soon. To override locally:
abc config accounting set cost.postdoc_per_hour=400
abc config emissions set pue=1.27 grid_factor_gco2_per_kwh=950
The provenance footer is generated from the resolved rate card — every
value carries its layer (built-in / local / flag) and citation. A
Layer-1 override in ~/.abc/config.yaml (e.g. cost.postdoc_per_hour: 525) flows through the same resolver abc accounting uses. One ledger,
two lenses (abc report for showback, abc accounting for budget caps).
abc report runs — per-run cost + emissions
Lists one row per submitted job/pipeline with cost + emissions derived
from the stored resources × the rate card. Jobs sort first (most-recent
within), then pipelines. Reads ~/.abc/db/local.db; re-probes Nomad for
runs whose completion watcher died (the CLI exits seconds after
submission, but jobs take minutes) unless --no-reconcile is passed.
abc report runs # last 30d, 20 rows, jobs first
abc report runs --since=7d --limit=50
abc report runs --verb=job # jobs only (no pipeline footnote)
abc report runs --verb=pipeline # pipelines only
abc report runs --full # per-row forensic block
abc report runs --json # machine-readable
abc report runs --no-reconcile # skip the Nomad re-probe (faster offline)
$ abc report runs --since=30m
Runs · 2026-05-27 → 2026-05-27
────────────────────────────────────────────────────────────────────────────
TIME (UTC) VERB WORKLOAD CPU·hr COST(R) CO₂e (kg) STATUS
2026-05-27 13:30 job cpu-burn.sh 0.33 0.17 0.01 completed
2026-05-27 13:25 job timed-30.sh 0.01 0.00 0.00 completed
2026-05-27 13:30 pipeline nextflow-io/hello 0.02 — — completed
(—) Pipeline cost/emissions are pending: the head-orchestrator's
resources alone undercount the real pipeline by 10-100×, so the
numbers are intentionally blank until the per-task cache aggregator
ships. Job rows are computed directly from Nomad alloc resources
and are honest.
Jobs are honest; pipelines are head-only today. A job is a single
Nomad alloc — the watcher reads its resources and the cost is accurate.
A pipeline is a head orchestrator that dispatches many worker jobs the
watcher doesn't yet sum, so pipeline cost/emissions cells render —
until the Nextflow-cache aggregator lands. --full adds a per-row
vertical block surfacing run_id, nomad_job_id, namespace,
exit_code, exit_reason, project / investigation attachments, and
(for pipelines) workdir_root — useful for tracing a row to its Nomad
job (abc job show <nomad_job_id>).
JSON schema
{
"window": {"since": "<RFC3339>", "until": "<RFC3339>"},
"context_name": "abc-dev",
"metrics": {
"<metric-id>": {
"id": "<metric-id>",
"label": "<human Title>",
"gloss": "<one-line gloss>",
"unit": "hours|count|percent|currency",
"value": <number | object>,
"computable": true,
"reason": "(present only when computable=false)"
}
},
"rate_card": {
"currency": {"value": "ZAR", "source": "built-in", "citation": "SA market default"},
"cost.cpu_hour": {"value": 0.5, "source": "built-in", "citation": "abc-cluster-cli vX — SA on-prem indicative"},
"cost.gpu_hour": {"value": 9, "source": "built-in", "citation": "..."},
"cost.memory_gb_hour": {"value": 0.05, "source": "built-in", "citation": "..."},
"cost.storage_scratch_gb_hour": {"value": 0.0001, "source": "built-in", "citation": "..."},
"cost.postdoc_per_hour": {"value": 350, "source": "built-in", "citation": "HSRC 2025 SA postdoctoral compensation guidance"},
"emissions.grid_factor_gco2_per_kwh": {"value": 900, "source": "built-in", "citation": "Eskom IAR 2023"},
"emissions.cpu_w": {"value": 12, "source": "built-in", "citation": "CCF v3"},
"emissions.gpu_w": {"value": 250, "source": "built-in", "citation": "CCF v3"},
"emissions.memory_gb_w": {"value": 0.3725, "source": "built-in", "citation": "CCF v3"},
"emissions.pue": {"value": 1.5, "source": "built-in", "citation": "Uptime Institute 2023"},
"emissions.storage_scratch_w_per_tb": {"value": 8, "source": "built-in", "citation": "Samsung PM9A3 envelope"}
},
"groups": [ // present only when --by=<axis> set
{
"by": "investigation",
"key": "inv-abc",
"metrics": { "<metric-id>": { ... } }
}
]
}
Required substrate (migrations)
abc report reads existing columns where available and gracefully degrades to
"n/a (reason)" otherwise.
| Migration | Adds | Unlocks metric |
|---|---|---|
0008_runs_queue_wait | pending_seconds | queue_wait_fraction |
0009_runs_resource_request | cpu_request, mem_request_gb | resource_fit |
0010_runs_submission_source | submission_source | submission_source, contributes to hours_saved |
Run abc localdb migrate to apply pending migrations. abc localdb status
lists feature flags advertised through the capability layer.
No network guarantee
abc report declares Required{ AllOf: [{Service: "local-state"}] } — the
local-state pseudo-service derived from the migration framework. The command
makes zero outbound HTTP calls in any code path. A test in
cmd/report/report_test.go swaps http.DefaultTransport for a tripwire and
asserts zero RoundTrip calls during render.
Capability layer
| Need | Backend | Available |
|---|---|---|
AllOf local-state | local SQLite | seed (always) |
--all-contexts → abc-controller-svc (federation-aggregate) | controller service | gated; rejects until controller service is reachable |
--all-contexts rejects with the standard capability.Require failure message
when the controller service isn't deployed in the active context's capabilities
map.
See also
abc localdb status— schema version, applied migrations, feature flags.