Skip to main content

plumb-line-provenance (Python)

A conservative provenance / confidence / lineage envelope with a taint-propagation combination law: once any input is mock or low-confidence, every value derived from it inherits that taint automatically — there is no escape hatch that silently clears the flag.

from plumb_line_provenance import mark, derive, meta_of, audit_meta

base = mark(1000, source='real', confidence='high')
rate = mark(1.25, source='mock', confidence='low')
total = derive([base, rate], lambda a, r: a * r)

total['meta']['derived_from_mock']  # True  — inherited from rate, cannot be cleared
total['meta']['confidence']         # 'low' — only as certain as the weakest input
audit_meta(meta_of(total))          # []    — internally consistent

You can also copy the module files directly into a project and import them flat (from marked import mark); both styles work.

This package is the run-time half of plumb-line, which also ships review-time audit skills and a GitHub Action that enforce the same discipline on a codebase.

HTTP ingestion adapters (optional)

Auto-tag HTTP responses at ingestion. Install the extra for your client:

pip install "plumb-line-provenance[requests]"
pip install "plumb-line-provenance[httpx]"
from plumb_line_provenance.http_adapter import tag_requests, tagged_get
from plumb_line_provenance import derive
import requests

resp = requests.get(url)
data = tag_requests(resp)                     # marked by status/cache
body = derive([data], lambda r: r.json())     # extract; taint propagates

data = tagged_get(url, timeout=5)             # fetch + tag in one call

Mapping (source = origin, confidence = freshness):

HTTP condition source confidence
2xx, fresh real high
2xx cached / 304 real medium
4xx / 5xx (no data) unavailable none

Cache is detected best-effort from response headers (Age > 0, X-Cache: HIT, 304) and only lowers confidence, never source. (A from_cache attribute is also honored if present — set by caching wrappers such as requests-cache — but stock requests/httpx responses don't carry one, so header detection is the path that fires for them.) The tagger never emits fallback — that's for a value you substitute on error. The core (classify_response) is dependency-free; the taggers guard-import their library and raise a clear ImportError if the extra isn't installed.

The HTTP adapter is http_adapter.py. Until 0.11.2 it was http.py, which shadowed the standard library's http package (and broke requests/httpx) whenever the directory was on sys.path. Flat copies import it as http_adapter; the installed package keeps plumb_line_provenance.http as an alias of plumb_line_provenance.http_adapter through 0.x (1.0 decision: #429), so existing imports still work at run time. The alias is a runtime entry static type checkers cannot see; new code should import http_adapter.

Dataframe adapters (optional)

Provenance-carrying wrappers for pandas / numpy, with explicit combinators that propagate taint. Install the extra:

pip install "plumb-line-provenance[pandas]"
pip install "plumb-line-provenance[numpy]"
from plumb_line_provenance.frames import PlumbDataFrame, plumb_concat, plumb_merge

base = PlumbDataFrame(df_a, source="real", confidence="high")
rate = PlumbDataFrame(df_b, source="mock", confidence="low")

total = plumb_concat([base, rate])          # runs pd.concat, propagates taint
joined = plumb_merge(base, rate, on="id")   # runs .merge, propagates taint

total.meta["derived_from_mock"]  # True — mock taint propagated, cannot be cleared
total.meta["confidence"]         # 'low' — only as certain as the weakest input
total.value                      # the underlying DataFrame

plumb_derive([a, b], fn) is the general combinator (any transform). numpy is the same pattern: from plumb_line_provenance.arrays import PlumbArray, plumb_concatenate, plumb_stack.

You declare the source when you wrap (a raw frame carries no intrinsic provenance — there is no auto-classification). Pass a real source= for a leaf: the default ("derived") is meant for combinator outputs, and a "derived" leaf with no lineage will show up as unreproducible under .audit(). Operations outside the combinators work on .value and drop provenance until you re-wrap via plumb_derive — the combination point stays visible in your code (see ADR-0013). The core is dependency-free; the wrappers guard-import their library and raise a clear ImportError if the extra isn't installed.

Golden baseline

Pin a derived value with its envelope as a golden record, then refuse silent drift: because lineage travelled with the value, a drift finding names which field moved, not just that the number did. No extra needed.

from plumb_line_provenance import assert_baseline, update

update('fx-rate', priced, because='initial pricing baseline')  # first run, or an accepted change
assert_baseline('fx-rate', priced)  # raises AssertionError, attributed, on drift

Records live in .plumb-line/baselines/ unless you pass dir=. Accepting a new state needs a non-empty because, stored in the record's append-only history. check returns the report instead of raising; list_baselines, show and validate_baseline inspect records. Inspect them from a shell with python -m plumb_line_provenance.baseline <list|show <name>|validate> [--dir D] (read-only: only running code carries the envelope, so it cannot check or update).

Compared: each lineage step's trust fields and of, the lineage length, the top-level trust fields and basis, then the value. basis counts as drift on its own. Three drift classes are not-implemented: cross-step causality, structural diffing inside a nested value, and float tolerance (comparison is exact).

  • Specification: SPEC.md (envelope schema version 2)
  • Model, law, examples: README.md
  • License: Apache-2.0

JavaScript parity package: plumb-line-provenance on npm.

Release files for plumb-line-provenance 0.11.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for plumb-line-provenance 0.11.3
File Size Uploaded
plumb_line_provenance-0.11.3.tar.gz 42.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for plumb-line-provenance 0.11.3
File Interpreter ABI Platform
plumb_line_provenance-0.11.3-py3-none-any.whl Python 3 none any Details

Total release size: 70.1 kB

Release files / plumb_line_provenance-0.11.3.tar.gz

Download URL plumb_line_provenance-0.11.3.tar.gz
Size 42.7 kB
Tags Source
SHA-256 checksum
How to use checksums
f09a9a98a2abd7f36a5f116a649feb7e065575488b7461b2c21e12e6c8b87002
BLAKE2b-256 checksum
How to use checksums
29156c0f55625b0daf429202bc867ae0a8dd4921f5a8de631c34d45940a51462
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / plumb_line_provenance-0.11.3-py3-none-any.whl

Download URL plumb_line_provenance-0.11.3-py3-none-any.whl
Size 27.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a6e8c7b82d4096c945fafab871a75ad4eaa38ee4af6ef6ae44b01b2d0f7adc94
BLAKE2b-256 checksum
How to use checksums
b4d5edb92a587b2e9db7b975a923efa520c2c728c6f5f0b923d5235080b63fac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.11.3 This release

2 release files

0.11.2

2 release files

0.11.1

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page