Skip to main content

An evidence-axes project map where DONE is computed, never filed: every status claim needs an evidence record, and 'connected' must be grep-proven.

Project description

provenmap

A project map where DONE is computed, never filed.

Every tracker you have ever used lets anyone — you on an optimistic day, a teammate in a hurry, an AI coding agent that just announced "implemented and fully wired up!" — set a status field to done. The status is an assertion. Nothing checks it. Over time the board drifts from the code, and the drift is always in the same flattering direction.

Provenmap refuses assertions. Every item carries four independent evidence axes, each FALSE unless it holds an evidence record:

Axis Claim Evidence demanded
designed the design exists a doc path — checked to exist on disk
built the code exists a commit hash or file path
connected something on the production path calls it a call-site file:line that is grep-real at filing time, plus the census digest
verified a live run proved it an artifact path — checked to exist; whether it matches the item's acceptance signal is your judgment, on record

Enforcement is strictest on the two axes that lie most: hard connected evidence can only be filed through provenmap census --record (the generic file command refuses callsite-kind connected evidence outright), and verified hard-requires an on-disk artifact — while designed/built accept any recorded evidence kind.

DONE = all four axes evidenced. It is computed at read time. Storing done, progress, or status on an item, an arc, or the map itself is a validation error.

Built for my own workflow directing AI coding agents on the Ticos project, where "the model said it built it" and "production can actually reach it" turned out to be very different claims. Separated out in case it's useful elsewhere.

Install

pip install provenmap

Quickstart

provenmap init                 # scaffold a stamped map (provenmap.json) in the current directory
provenmap status               # progress bars + the honesty counters
provenmap file A1.example designed --kind doc --ref docs/DESIGN.md --by you   # any doc path that exists
provenmap census A1.example   # grep the item's census_targets; add --record --callsite <root>/<file>:<line> --by you to file evidence
provenmap serve                # read-only dashboard in the browser

(init scaffolds a starter item A1.example; rename and add items with provenmap edit.)

Or explore the fictional example in the repository (examples/demo) first:

provenmap status --map examples/demo/provenmap.json
ACTIVE-SCOPE completion :  75.0%
TOTAL-SCOPE completion  :  62.5%
VERIFICATION DEBT       : 2 built-but-not-verified item(s)
CENSUS-PENDING          : 1 attestation-backed claim(s)
REACHABILITY-PENDING    : 0 connected claim(s) with no proven path from a production entry point
pointer                 : CORE / CORE.search

[#####################-------]  75.0%  CORE    snippet core (active)
    DBCV  DONE  CORE.store                   (M, active)
    DB..   50%  CORE.search                  (M, active)
    DBC.   75%  CORE.export                  (S, active)
[----------------------------]   0.0%  UX      polish (queued)
    ....    0%  UX.themes                    (S, deferred)

What a grep proves — and what it does not

The connected axis is where trackers lie hardest, so it gets the most machinery.

provenmap census ITEM greps the item's declared census_targets across the production roots configured in the map, prints the hits (up to --limit) plus a digest over all of them, and — with --record — files connected evidence only when the claim survives three custody rules:

  1. A declaration is not a call. --callsite pointing at a def / class line is refused. That the code exists is the built axis; connected demands that something calls it.
  2. A module calling its own symbol is not a connection. If every production hit lies inside the module that declares the symbol, nothing else in production reaches it — refused. (The specimen that forced this rule: a module whose only callers were itself and the test harness filed connected clean for weeks.) Escapable only by naming a production entry point explicitly — which is then recorded, auditable, and your judgment on record instead of silent.
  3. A connected filing with no entry-point evidence is DEBT, not proof. It records, but it counts as REACHABILITY-PENDING with a warning. Admissible — grep beats nothing — but never silently equal to a reachability-proven connection.

And the honest limit, stated so nobody over-reads the fence: a grep proves a symbol is mentioned; it cannot prove production reaches it. The census is a one-hop text search, not a call-graph walk. The digest is proof at filing time: validate re-checks that referenced files still exist, but it does not re-grep — re-run census after refactors to refresh a stale connection claim. connected is a cheap necessary condition — verified, a live run matching the item's acceptance signal, is the only axis that proves a thing is real. That is why VERIFICATION DEBT (built-but-not-verified) is the headline counter, not the completion percentage.

Tamper-evidence

All writes go through the CLI: schema-validated, atomic (tmp+rename), sha256-integrity-stamped, and appended to a changelog (provenmap.changelog.jsonl). Hand-editing the map breaks the integrity hash and turns provenmap validate RED — by construction, not by policy. Deliberate manual edits are allowed, but they cost an explicit provenmap restamp --by you --author-ack, which puts the acknowledgment on the record (the changelog records that an edit happened, not its diff).

The scope of that guarantee, honestly: the unkeyed hash defends against accidental and unrecorded edits — the silent drift class. It cannot stop a deliberate forger who recomputes the stamp, and doesn't try; nothing local can.

The other honesty mechanics

  • Progress is weighted realistically: designed 0.15 / built 0.35 / connected 0.25 / verified 0.25 by default — an item that is designed and built still reads 50%, never 100%.
  • Two completion numbers, always together: ACTIVE-SCOPE (deferred/parked/graveyard excluded) and TOTAL-SCOPE (deferred and parked included) — deferring work must never inflate progress.
  • Dispositions are intent, never progress: deferred/parked require a written trigger; abandoned requires a date and reason; superseded requires a successor — and the graveyard renders visibly in the dashboard instead of vanishing.
  • Attestations are honest IOUs: a human/agent claim may temporarily stand in on the mechanical axes, but only marked CENSUS-PENDING, and it is counted and displayed as such until converted into grep or artifact evidence.
  • Approvals sit above DONE: optional operator_approved / bench_approved records (an explicit human sign-off; a real benchmark artifact) render last and can never add progress or satisfy an axis.

Working with AI coding agents

This tool exists because agent-reported status inflates. The division of labor that works:

  • Judgment (yours): item meaning, acceptance signals, sizes, dispositions, triggers, the designed axis, and declaring each item's census_targets.
  • Mechanical (the agent's, or anyone's): built records a commit; connected must be filed through provenmap census --record, which refuses everything it cannot prove — and the file command refuses to accept hand-filed callsite evidence on that axis at all; verified needs an artifact that exists on disk.

An agent that files its own roadmap state through provenmap at the end of every run either produces evidence or produces a visible refusal. Both are useful. (The edit command remains the full-document judgment escape hatch — validated, stamped, and changelogged, but judgment nonetheless; don't hand it to the agent.)

Configuration

The census configuration lives inside the map, so it is integrity-stamped with everything else:

"census": {
  "production_roots": ["src"],
  "aux_roots": ["tools"],
  "include_globs": ["*.py"],
  "skip_dir_prefixes": [".", "__pycache__", "tests", "test"],
  "skip_file_prefixes": ["test_"],
  "definition_pattern": "^(async\\s+def|def|class)\\s"
}

aux_roots are searched and reported but never count as production. definition_pattern is what makes custody rule 1 work; the default recognizes Python definitions — override it for other languages. All commands take --map (default ./provenmap.json); evidence paths resolve against the map's directory (--root to override).

Honest limits

  • Single JSON file, single writer at a time — built for solo devs and small teams, not org-scale program management.
  • The census is a line-regex search. Python-first defaults; other languages work via include_globs + definition_pattern, with less sharp definition detection — and when the pattern matches no census line at all, recording demands the explicit --entry-point escape rather than pretending the declaration rules were checked.
  • File-glob matching follows the platform: on Windows, *.py also matches X.PY, so census hit counts can differ across platforms for mixed-case trees.
  • --root is not persisted in the map: if you validate with a custom root, pass it consistently.
  • The dashboard is read-only by construction (POST is refused). All writes go through the CLI.
  • The integrity stamp detects unrecorded edits; it does not authenticate authors.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

provenmap-0.1.0.tar.gz (40.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

provenmap-0.1.0-py3-none-any.whl (30.0 kB view details)

Uploaded Python 3

File details

Details for the file provenmap-0.1.0.tar.gz.

File metadata

  • Download URL: provenmap-0.1.0.tar.gz
  • Upload date:
  • Size: 40.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for provenmap-0.1.0.tar.gz
Algorithm Hash digest
SHA256 09a08c1a00826a4bd9b949192bd21dbb58868c182e82d58abf9aff9981541bc2
MD5 b38a469c85edba9776e1e9396dad7b0e
BLAKE2b-256 14b3fa4010d89d694cc47dfe9ad52fa773d7d92dad2e00c6ec98bad78d28411d

See more details on using hashes here.

Provenance

The following attestation bundles were made for provenmap-0.1.0.tar.gz:

Publisher: release.yml on Sicatho/provenmap

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file provenmap-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: provenmap-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 30.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for provenmap-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1a365f8ccf64db13ebffb1e938fa0813bddeec87a9c305c283337183f5ef7550
MD5 762c8aa42149e9fe4260689259a4ed73
BLAKE2b-256 dd2b5984acb68f0d19bd578a06d03aadbb6f35b3677e96e945a7558150e98efb

See more details on using hashes here.

Provenance

The following attestation bundles were made for provenmap-0.1.0-py3-none-any.whl:

Publisher: release.yml on Sicatho/provenmap

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page