Skip to main content
Glama
heavnzor
by heavnzor

ProofMill turns CSV/JSONL transformations into reproducible, row-traceable experiments. An agent proposes a bounded recipe. DuckDB executes it. A four-way comparison separates the data effect, recipe effect and their interaction, with source hashes and business-key-level evidence.

See the proof

Requires Python 3.11+ and uv.

git clone https://github.com/heavnzor/heavnz0r-proofmill.git
cd heavnz0r-proofmill
uv sync
uv run proofmill demo

Open .proofmill-demo/report.html. The synthetic invoice demo produces:

Old recipe

New recipe: exclude void invoices

Old data

525

450

New data

745

600

Baseline          525
Data effect      +220
Recipe effect     -75
Interaction       -70
─────────────────────
Current           600      Net change: +75

The interaction matters: some new or changed invoices are precisely the ones removed by the new recipe. Counting data and recipe effects alone would overstate the result.

Trace a specific invoice:

uv run proofmill explain .proofmill-demo/comparison.json --key C

Each source reference includes the input SHA-256, one-based data record, inclusion/filter/quarantine status and numeric contribution. A repeated demo requires a fresh --out directory.

Related MCP server: RefineDataMCP

Four runs, one explanation

                         OLD RECIPE             NEW RECIPE
                       ┌────────────┐         ┌────────────┐
OLD DATA               │ baseline   │────────→│ recipe only│
                       └─────┬──────┘         └──────┬─────┘
                             │                      │
                       ┌─────▼──────┐         ┌──────▼─────┐
NEW DATA               │ data only  │────────→│ current    │
                       └────────────┘         └────────────┘

For the same declared metric and unit:

  • data = F(new data, old recipe) − baseline

  • recipe = F(old data, new recipe) − baseline

  • interaction = current − data-only − recipe-only + baseline

  • data + recipe + interaction = current − baseline

The same conservation identity is checked across row-level contributions. This is an execution decomposition, not proof of real-world business causality.

If one combination cannot execute, the report says not comparable and preserves the failure. It does not invent an attribution.

AI proposes. The engine verifies.

The recipe is a small typed language: rename, cast, filter, then grouped sum. Unknown operations and arbitrary SQL are rejected.

{
  "schema": "proofmill.recipe/v1",
  "name": "Paid revenue by region",
  "key": "invoice_id",
  "steps": [
    { "op": "cast", "column": "amount", "to": "decimal" },
    { "op": "filter", "column": "status", "operator": "eq", "value": "paid" }
  ],
  "metric": {
    "id": "invoice-total", "column": "amount",
    "group_by": ["region"], "unit": "EUR"
  }
}

An OpenCode/Claude Code agent can inspect the source schema, obtain the recipe JSON Schema, propose and validate a recipe, present its assumptions, then run the accepted comparison. Its model and authentication stay in the client.

Example MCP configuration for OpenCode:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "proofmill": {
      "type": "local",
      "command": [
        "uv", "run", "--project", "/path/to/heavnz0r-proofmill",
        "proofmill", "mcp", "--root", "/path/to/data-workspace"
      ]
    }
  }
}

Merge and restart OpenCode. Claude Code can register the same stdio command. All tool paths must resolve inside --root. The profiling tool returns column names and counts, not raw row samples; an explicit explanation can return a selected record's provenance. The workflow skill describes the full loop.

Use your own snapshots

uv run proofmill profile exports/old.csv
uv run proofmill schema
uv run proofmill validate recipes/new.json

uv run proofmill compare \
  --old-data exports/old.csv --new-data exports/new.csv \
  --old-recipe recipes/old.json --new-recipe recipes/new.json \
  --out comparison

For a single transformation:

uv run proofmill run --input exports/new.csv --recipe recipes/new.json --out cleaned

Each successful cell exports:

data.parquet       transformed records + source record/hash columns
metrics.parquet    grouped totals + contributing record numbers
quarantine.json    rejected values and reasons
receipt.json       recipe, hashes, counts, groups and row provenance

A comparison adds comparison.json and a self-contained HTML report. Output directories must be new, so a previous result is not silently overwritten.

Contracts that matter

  • A unique, nonempty source business key aligns records across snapshots. Duplicate identities block the run.

  • Metric identity, unit, grouping columns and source key must agree between recipes.

  • Decimal casts use DECIMAL(38,6). Values that would round, overflow, or become non-finite are quarantined; integer casts reject fractional input.

  • A source record is a logical CSV/JSONL record, not necessarily a physical file line. Hashes identify the exact input bytes.

  • Filtering uses SQL null semantics. Invalid cast rows are quarantined; filtered rows remain traceable with a reason.

  • Grouped sums are the v0.1 metric. Flat UTF-8 CSV/JSONL inputs are bounded to 25 MiB and 100,000 records. No joins, OCR, arbitrary SQL, or warehouse connector is implied.

  • Receipts and quarantine outputs contain local data. Inspect them before sharing. The demo uses synthetic invoices.

See the method for comparison semantics and precision boundaries.

Development

uv sync
uv run ruff check .
uv run pytest

Tests exercise the known decomposition, conservation, missing schema, duplicate identities, decimal precision, quarantine, SQL-parameter escaping, Parquet provenance, and MCP transport.

Inspired by the reproducibility and lineage concerns explored by Hamilton and OpenLineage. ProofMill's focus is the small, inspectable data × recipe experiment.

Available Tools

5 tools
proofmill_compareB

Run an accepted four-way comparison and write receipts/Parquet to a new local folder.

ParametersJSON Schema
NameRequiredDescriptionDefault
outputYes
new_dataYes
old_dataYes
new_recipeYes
old_recipeYes

TDQS

B3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the behavioral disclosure burden. It does disclose a key side effect: writing receipts/Parquet to a new local folder. But it does not explain whether the tool overwrites anything, what 'accepted' means, what permissions or environment it requires, or what happens on failure. This is partial transparency with clear gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single front-loaded sentence with no filler. It opens with the action verb and packs the key artifact and destination into a compact form. Every word earns its place, and it is appropriately sized for the amount of information it conveys.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given five required parameters, nested recipe objects, no output schema, no annotations, and 0% schema description coverage, the description is far too thin. It leaves the agent to infer the meaning of all parameters, the prerequisite implied by 'accepted', and the tool's return or failure behavior. This is not enough for confident invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate for the undocumented parameters. It only implies four inputs via 'four-way comparison' and maps 'output' to a local folder, but it does not clarify whether inputs are file paths or inline data, what formats are expected, or how the recipe objects should be structured. This does not meaningfully fill the schema gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Run an accepted four-way comparison') and a concrete output ('write receipts/Parquet to a new local folder'). It moves beyond the tool name and gives a clear sense of what the tool does. However, it never explicitly distinguishes itself from siblings like proofmill_validate or proofmill_explain, and the word 'accepted' is vague.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool compared to proofmill_validate, proofmill_explain, or proofmill_profile. The term 'accepted' hints at a prerequisite, but it does not say what must happen before this tool is called or what makes it the right choice over a sibling. There are no exclusions or alternatives named.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

proofmill_explainA

Trace one business key across the four executions in a saved comparison receipt.

ParametersJSON Schema
NameRequiredDescriptionDefault
keyYes
receiptYes

TDQS

A3.5/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden of behavioral disclosure. It reveals that the operation is per-key and depends on a saved comparison receipt, but it does not state whether the operation is read-only, what output or failure mode to expect, what happens when the key is missing, or any preconditions beyond having a receipt.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single active-voice sentence that front-loads the action and scope. Every word earns its place, and there is no filler or redundant restatement of the tool name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter tool, the description gives enough to understand the operation and identify both inputs. However, there is no output schema and no annotation coverage, and the description does not explain what the returned 'trace' looks like or how the saved receipt should be obtained, leaving notable gaps for autonomous invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description partially compensates by mapping 'receipt' to a saved comparison receipt and 'key' to a business key. However, it adds no format details, sources, or constraints for either string parameter, so the agent still has to infer what values to supply.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('trace') and a specific resource ('one business key across the four executions in a saved comparison receipt'), which makes the tool's purpose clear and distinguishes it from validate/profile-style tools. It does not explicitly name a sibling alternative, but the reference to a saved comparison receipt ties it clearly to the compare workflow.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'saved comparison receipt' clearly implies this tool is meant to be used after a comparison has been produced, so the intended context is reasonably explicit. It does not name alternative tools or state when not to use it, so it stops short of full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

proofmill_profileB

Inspect column names, null counts and cardinality without sending raw row samples.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It states the tool inspects rather than modifies (read-only implied) and explicitly promises not to send raw row samples, which is a valuable privacy guarantee. However, it does not disclose other potential behaviors such as output format, performance characteristics, or failure modes. The description is minimal but not misleading; it covers the most critical behavioral aspect.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, concise sentence that front-loads the action ('Inspect') and the key details. It has no filler and efficiently conveys the core purpose and a key constraint. Every word earns its place, making it appropriately sized and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple (one parameter, no output schema), but the description is incomplete for an agent to use it correctly. It omits any explanation of the 'path' parameter, which is essential for invocation. It also does not describe the output format or any prerequisites (e.g., file type, permissions). While the tool's scope is clear, the missing parameter information makes it incomplete for reliable use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate for the single 'path' parameter. The description does not mention 'path' at all, leaving the agent to infer what the path points to, how it should be formatted, or whether it refers to a file path, directory, or something else. This is a critical gap because the description adds zero meaning to the parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Inspect') and resource ('column names, null counts and cardinality'), which clearly defines the tool's function. The phrase 'without sending raw row samples' distinguishes it from siblings like proofmill_validate or proofmill_compare, which might involve data transmission. This is a precise and unambiguous purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context: it is for inspecting metadata rather than raw data, and explicitly mentions not sending raw row samples, which hints at a privacy/performance trade-off. However, it does not explicitly name alternatives or state conditions like 'use this when you need schema information' or 'when you need validation use proofmill_validate'. The guidance is implicit, not explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

proofmill_recipe_schemaA

Return the bounded recipe schema for rename, cast, filter and grouped sum operations.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The word 'Return' implies a non-mutating metadata retrieval, which is the core behavior. With no annotations, the description carries the full burden, but it does not explain 'bounded' or disclose edge cases, auth requirements, or failure behavior. For a low-risk schema-retrieval tool this is adequate but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence with a clear verb-first structure and no filler. Every word earns its place, and the operation list is compactly presented.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter, no-output-schema tool, the description tells the agent what to call and what broad content to expect. It could clarify whether the return is a JSON Schema object and what 'bounded' means, but nothing essential is missing given the tool's simplicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has zero parameters, so there is nothing to document; baseline of 4 applies. The operation names in the description describe the content of the returned schema rather than parameters, so no additional parameter semantics are needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a direct action ('Return') and a specific resource ('the bounded recipe schema'), and narrows scope to four operation types. It is also distinguishable from siblings by focusing on a schema rather than profile/validate/compare/explain, though 'bounded' is left undefined.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit when-to-use or exclusion is provided, but the operation list implies it is the tool for retrieving schema details. Siblings are clearly different actions, so a misfire is less likely; however, there is no guidance about when this schema lookup is appropriate relative to the other tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

proofmill_validateA

Validate an AI-proposed recipe before execution; no data is read or written.

ParametersJSON Schema
NameRequiredDescriptionDefault
recipeYes

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations present, the description carries the disclosure burden and explicitly states that the tool has no read/write side effects, which is useful behavioral context. It does not describe what happens when validation fails or what the return value represents, so some behavioral detail is missing.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One compact sentence, front-loaded with the action and object, followed by a critical side-effect guarantee. There is no filler or redundancy; every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no annotations, no output schema, and an untyped nested object, the description is too thin: it leaves validation criteria, result semantics, and the relationship to sibling tools (e.g., proofmill_recipe_schema) unspecified. The side-effect statement helps, but an agent cannot confidently construct a valid recipe object or interpret the response.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema provides only a free-form 'recipe' object with additionalProperties true and no property descriptions; schema description coverage is 0%. The description labels the object as 'AI-proposed' but does not compensate by specifying expected structure, required fields, or how to distinguish valid from invalid recipes.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('validate') and resource ('AI-proposed recipe') and adds a clear temporal context ('before execution'). It does not explicitly differentiate from sibling tools like proofmill_profile or proofmill_compare, but the action itself is distinctive enough.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'before execution' gives a clear when-to-use signal, and 'no data is read or written' reinforces that this is a safe pre-flight check. It does not mention when to prefer siblings such as proofmill_recipe_schema or proofmill_compare, so it stops short of explicit exclusions or alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv0.1.0
    • First observedproofmill_compare
    • First observedproofmill_explain
    • First observedproofmill_profile
    • First observedproofmill_recipe_schema
    • First observedproofmill_validate

TDQS

A3.6/5.0

Scored across 5 tools

Disambiguation5/5

Each tool targets a distinct stage in the proofmill workflow: profiling, recipe schema creation, validation, comparison execution, and receipt explanation. There is no meaningful overlap between their responsibilities.

Naming Consistency4/5

All tools share the proofmill_ prefix and use lowercase snake_case, which is predictable. Four names are verb-led, while recipe_schema is noun-led, a minor deviation from the otherwise consistent pattern.

Tool Count5/5

Five tools is well-scoped for a focused data profiling and comparison pipeline. Each tool earns its place and corresponds to a clear phase in the workflow.

Completeness4/5

The core lifecycle is covered: profile, schema, validate, execute, and explain. A minor gap is the lack of a tool for listing saved receipts or inspecting broader comparison outputs beyond tracing a single business key.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    Agentic data quality MCP server — runs structured validation rules against warehouses (DuckDB, BigQuery, Athena, Databricks, Postgres), diagnoses failures with LLM root cause analysis, and proposes SQL remediations. Full audit trail of every AI decision.
    6
    4
    Apache 2.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to compare database tables using read-only tools, with credentials managed locally and never exposed to the model.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables autonomous data quality inspection and repair workflows. It scans DuckDB warehouses for anomalies, generates and verifies fixes in a dry-run copy, then applies them after validation, with full audit logging.
    MIT