Local-first provenance, uncertainty, and audit trails for electrical-engineering experiments.
Project description
BenchLineage turns an ordinary project directory into a verifiable chain from research intent to instrument identity, calibration coverage, raw measurement, derived analysis, uncertainty budget, and published report.
It does not replace a full electronic laboratory notebook, instrument-control framework, or institutional data repository. It focuses on a smaller failure mode that is especially common in electrical-engineering research: six months after a measurement, the plot survives but the exact instrument, calibration window, run conditions, raw file, and analysis lineage do not.
The default workflow is offline. There is no account, server, database, API key, telemetry, or runtime dependency.
Live demonstration · Synthetic report · PyPI package · Methodology · CI · Python 3.11+ · MIT · zero runtime dependencies
[!IMPORTANT] BenchLineage is a research recordkeeping tool, not a calibration authority, regulatory compliance system, or safety certification. A cryptographic digest shows whether recorded bytes changed; it cannot prove that a physical measurement was performed correctly or honestly.
See it before installing
Every instrument name, serial number, certificate, and measurement in the public demonstration is synthetic. The demo illustrates the evidence model; it makes no claim about physical hardware.
The evidence chain
Every stage writes an inspectable file; the final bundle keeps those files together.
| Layer | Durable artifact | Question it answers |
|---|---|---|
| Workspace | benchlineage.json |
Who owns this record and which format does it use? |
| Study | studies/*.json |
Why was the experiment run and what was planned? |
| Instrument | instruments/*.json |
Which physical device produced the observation? |
| Calibration | calibrations/*.json |
Was traceability recorded for the run date? |
| Run | runs/*.json |
Who did what, when, under which conditions? |
| Raw data | data/raw/* |
What was actually observed? |
| Analysis | analysis/*.json |
Which deterministic derivation produced the result? |
| Seal | seals/*.json |
Do the current bytes match the published evidence root? |
| Report | reports/*.html |
Can another person inspect the chain without this package? |
A result is more than a number
The figure below uses one fictional RC-filter result to show the five kinds of context that travel with it. This is the smallest useful mental model for BenchLineage: the reported value sits in the middle, and every surrounding statement has a recorded source.
Integrity checks answer whether recorded files changed; they do not certify whether the experiment was scientifically correct.
Install
Install from PyPI:
python -m pip install benchlineage
benchlineage --version
For an isolated one-off demonstration with pipx:
pipx run benchlineage demo my-bench --seed 20260804
PyPI distributions are published from the tagged GitHub workflow with a short-lived OIDC credential and a public provenance attestation. Each GitHub Release also carries the same wheel, source archive, and a SHA-256 checksum file.
For development:
git clone https://github.com/CAOShurong/benchlineage.git
cd benchlineage
python -m pip install -e .
Try the complete demonstration
benchlineage demo my-bench --seed 20260804
benchlineage audit my-bench
benchlineage verify my-bench
Open my-bench/reports/demo-report.html. It is a single HTML file with embedded CSS, JavaScript,
charts, audit evidence, and source records. It uses no CDN and sends no network requests.
The generated demonstration includes:
- a 41-point RC low-pass sweep with a baseline component value;
- a second sweep after a deliberate resistor substitution;
- a ten-point buck-converter load and efficiency sweep;
- three synthetic instruments and three synthetic calibration records;
- three derived analyses and three uncertainty budgets;
- a SHA-256 evidence inventory and root digest.
Start a real workspace
benchlineage init thesis-bench \
--title "Wide-bandgap converter characterization" \
--owner "Your Name"
benchlineage add-instrument thesis-bench \
--id scope-01 \
--kind oscilloscope \
--manufacturer Tektronix \
--model MSO58 \
--serial C012345
benchlineage add-calibration thesis-bench \
--id scope-01-2026 \
--instrument scope-01 \
--performed-at 2026-01-18T09:00:00+08:00 \
--due-at 2027-01-18T09:00:00+08:00 \
--certificate CAL-2026-001 \
--standard-uncertainty 0.0025 \
--unit V
benchlineage create-study thesis-bench \
--id gate-loop \
--title "Gate-loop ringing characterization" \
--objective "Measure overshoot across three gate resistances." \
--hypothesis "Higher gate resistance reduces overshoot at the cost of switching loss." \
--protocol "Record 200 switching events per resistor at fixed bus voltage and load." \
--tag power-electronics \
--tag switching
Raw evidence is intentionally added as an ordinary file. This keeps acquisition independent from BenchLineage and avoids locking a lab into one driver ecosystem:
thesis-bench/data/raw/gate-loop-rg2p2.csv
Record the run:
benchlineage add-run thesis-bench \
--id gate-loop-rg2p2-001 \
--study gate-loop \
--operator "Your Name" \
--started-at 2026-08-04T14:00:00+08:00 \
--instrument scope-01 \
--raw-file data/raw/gate-loop-rg2p2.csv \
--conditions '{"bus_voltage_v":400,"load_current_a":20,"gate_resistance_ohm":2.2}'
Then analyze, audit, seal, and report:
benchlineage analyze thesis-bench \
--run gate-loop-rg2p2-001 \
--kind column_summary
benchlineage audit thesis-bench --output audit.json
benchlineage seal thesis-bench --label "Preprint figure 4 evidence"
benchlineage verify thesis-bench
benchlineage report thesis-bench \
--title "Gate-loop characterization evidence" \
--note "Dataset frozen before manuscript submission." \
--output gate-loop-report.html
Publish a reviewable evidence bundle
After audit and sealing, create one deterministic ZIP for a collaborator, reviewer, or data repository:
benchlineage bundle thesis-bench --output thesis-bench-evidence.zip
benchlineage verify-bundle thesis-bench-evidence.zip
The bundle includes the workspace records, raw files, reports, latest seal, a
human-readable README, and BUNDLE-MANIFEST.json. The manifest lists every
included path, byte length, and SHA-256 digest. Rebuilding from unchanged bytes
produces the same ZIP bytes.
The verifier refuses unsafe archive paths and reports duplicate, missing, added, or changed members without extracting the bundle. This is an integrity check, not a digital signature or a claim that the experiment was valid.
Built-in analyses
BenchLineage deliberately implements a small, inspectable analysis core:
| Analysis | Detected columns | Main outputs |
|---|---|---|
| Frequency response | frequency_hz, vin_v, vout_v, optional phase_deg |
gain, dB curve, passband estimate, interpolated −3 dB cutoff |
| Power efficiency | vin_v, iin_a, vout_v, iout_a, optional load_ohm |
input/output power, loss, efficiency, peak operating point |
| Linear calibration | reference, observed |
slope, intercept, R², RMSE, error summary |
| Column summary | any all-numeric CSV | count, mean, median, extrema, standard deviation, standard error |
These are reference implementations, not an attempt to replace NumPy, SciPy, SPICE, MATLAB, or domain-specific analysis. The JSON analysis artifacts are designed so more specialized tools can write compatible results.
Uncertainty budgets
An analysis can include Type A or Type B components:
[
{
"name": "vertical accuracy",
"limit": 0.005,
"distribution": "rectangular",
"source": "certificate CAL-2026-001"
},
{
"name": "repeatability",
"standard_uncertainty": 0.0016,
"distribution": "normal",
"source": "twenty repeated acquisitions"
}
]
benchlineage analyze thesis-bench \
--run gate-loop-rg2p2-001 \
--uncertainty uncertainty.json \
--coverage-factor 2
The engine converts stated limits for normal, rectangular, and triangular distributions into standard uncertainties, applies sensitivity coefficients, combines independent contributions by root-sum-square, and reports component variance shares. See Uncertainty model for assumptions and limitations.
Auditing and sealing are different
benchlineage audit checks semantic relationships:
- referenced study, instrument, raw-data, and analysis records exist;
- calibration dates cover each run date when possible;
- raw paths remain inside the workspace;
- unreferenced raw files are reported;
- the latest seal still matches the evidence.
benchlineage seal checks byte identity. It records the SHA-256 digest and byte length of each
evidence file, then hashes the ordered inventory into one root digest. Reports and previous seals
are excluded so presentation can be regenerated without changing the recorded evidence.
A passing seal does not prove scientific truth. It proves only that the inventoried bytes match the declared root.
Why plain files?
Large ELN and LIMS platforms solve collaboration, permissions, inventory, scheduling, and institutional deployment. BenchLineage instead optimizes for:
- one researcher or a small team;
- offline operation on Windows, macOS, or Linux;
- Git-friendly review and long-term readability;
- instrument-agnostic ingestion;
- explicit, deterministic audit rules;
- a migration path rather than another data silo.
All core records are readable JSON and CSV. If BenchLineage disappears, the evidence remains usable.
Repository map
src/benchlineage/ CLI, analysis, audit, report, sealing, and bundle engine
schemas/ JSON Schema contracts for durable artifacts
demo/workspace/ committed synthetic example
site/ public project site and generated report
docs/ methodology, workflows, comparison, and design notes
tests/ unit, integration, CLI, tamper, and report tests
scripts/ reproducible demo and repository checks
Project boundaries
BenchLineage does not currently:
- control instruments or promise SCPI-driver compatibility;
- sign records with a trusted timestamping authority;
- provide multi-user permissions or electronic signatures;
- store secrets safely;
- validate laboratory safety or regulatory compliance;
- infer uncertainty models automatically;
- replace raw binary formats with CSV;
- guarantee FAIR compliance merely because metadata fields exist.
Those boundaries are intentional and documented in the roadmap.
Development
python -m pip install -e .
python -m unittest discover -s tests -v
ruff check src tests scripts
ruff format --check src tests scripts
python -m compileall -q src tests scripts
python scripts/build_demo.py --check
python scripts/check_repository.py
The package targets Python 3.11 and newer and has zero runtime dependencies.
Responsible citation
If BenchLineage contributes to a published evidence workflow, cite the software version and the
root digest of the sealed workspace. A software citation file is provided in
CITATION.cff.
License
MIT. Contributions are welcome under the same license. Questions and concrete laboratory workflows belong in Discussions; reproducible defects and inspectable analysis proposals belong in Issues.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file benchlineage-0.2.1.tar.gz.
File metadata
- Download URL: benchlineage-0.2.1.tar.gz
- Upload date:
- Size: 41.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dee10575a802117687aeba0108aea904cd35e38bed5f3ece8bbf13110341be84
|
|
| MD5 |
6cb845f4ef72032cbcd199db6c471548
|
|
| BLAKE2b-256 |
b5a39e77eb0993b6051e8e863d1b74e31d1320fe03437fdea713877cd367b4ac
|
Provenance
The following attestation bundles were made for benchlineage-0.2.1.tar.gz:
Publisher:
release.yml on CAOShurong/benchlineage
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
benchlineage-0.2.1.tar.gz -
Subject digest:
dee10575a802117687aeba0108aea904cd35e38bed5f3ece8bbf13110341be84 - Sigstore transparency entry: 2346227868
- Sigstore integration time:
-
Permalink:
CAOShurong/benchlineage@7becbbe117889286036d8b780c8b0e25f028a3d0 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/CAOShurong
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7becbbe117889286036d8b780c8b0e25f028a3d0 -
Trigger Event:
push
-
Statement type:
File details
Details for the file benchlineage-0.2.1-py3-none-any.whl.
File metadata
- Download URL: benchlineage-0.2.1-py3-none-any.whl
- Upload date:
- Size: 36.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2504947c06b27834fed7de2b31a7f0137146f36098563ad4f4f3422e3024154a
|
|
| MD5 |
c210e7e864ee6c8835f6e7e7e1b1e323
|
|
| BLAKE2b-256 |
ebb2beacc0ea495917c1b19d57181ca3b5c397c2cb15e9213869983412b51fdd
|
Provenance
The following attestation bundles were made for benchlineage-0.2.1-py3-none-any.whl:
Publisher:
release.yml on CAOShurong/benchlineage
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
benchlineage-0.2.1-py3-none-any.whl -
Subject digest:
2504947c06b27834fed7de2b31a7f0137146f36098563ad4f4f3422e3024154a - Sigstore transparency entry: 2346228219
- Sigstore integration time:
-
Permalink:
CAOShurong/benchlineage@7becbbe117889286036d8b780c8b0e25f028a3d0 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/CAOShurong
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7becbbe117889286036d8b780c8b0e25f028a3d0 -
Trigger Event:
push
-
Statement type: