vouch-paper 0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vouch_paper-0.1/.gitattributes +3 -0
- vouch_paper-0.1/.github/workflows/docs.yml +43 -0
- vouch_paper-0.1/.github/workflows/publish.yml +38 -0
- vouch_paper-0.1/.gitignore +24 -0
- vouch_paper-0.1/.pre-commit-hooks.yaml +7 -0
- vouch_paper-0.1/LICENSE +21 -0
- vouch_paper-0.1/PKG-INFO +278 -0
- vouch_paper-0.1/README.md +233 -0
- vouch_paper-0.1/SPEC.md +1875 -0
- vouch_paper-0.1/docs/assets/images/README.md +33 -0
- vouch_paper-0.1/docs/assets/images/explore-ui-function-detail.png +0 -0
- vouch_paper-0.1/docs/assets/images/explore-ui-overview.png +0 -0
- vouch_paper-0.1/docs/assets/images/pdf-provenance-appendix.png +0 -0
- vouch_paper-0.1/docs/assets/images/pdf-provenance-link.png +0 -0
- vouch_paper-0.1/docs/assets/images/terminal-vouch-check-fail.png +0 -0
- vouch_paper-0.1/docs/assets/images/terminal-vouch-check-pass.png +0 -0
- vouch_paper-0.1/docs/cli/author.md +95 -0
- vouch_paper-0.1/docs/cli/check.md +81 -0
- vouch_paper-0.1/docs/cli/index.md +55 -0
- vouch_paper-0.1/docs/cli/inspect.md +135 -0
- vouch_paper-0.1/docs/cli/integrations.md +68 -0
- vouch_paper-0.1/docs/cli/setup.md +76 -0
- vouch_paper-0.1/docs/examples.md +61 -0
- vouch_paper-0.1/docs/guide/change-notification.md +78 -0
- vouch_paper-0.1/docs/guide/checks-and-lints.md +51 -0
- vouch_paper-0.1/docs/guide/concepts.md +82 -0
- vouch_paper-0.1/docs/guide/derived-values.md +162 -0
- vouch_paper-0.1/docs/guide/formatting.md +58 -0
- vouch_paper-0.1/docs/guide/freshness.md +93 -0
- vouch_paper-0.1/docs/guide/latex.md +138 -0
- vouch_paper-0.1/docs/guide/non-python-experiments.md +49 -0
- vouch_paper-0.1/docs/guide/project-layout.md +106 -0
- vouch_paper-0.1/docs/guide/provenance-csv.md +40 -0
- vouch_paper-0.1/docs/guide/recording.md +279 -0
- vouch_paper-0.1/docs/guide/workflow-integration.md +52 -0
- vouch_paper-0.1/docs/index.md +52 -0
- vouch_paper-0.1/docs/llm/claude-code.md +84 -0
- vouch_paper-0.1/docs/llm/index.md +90 -0
- vouch_paper-0.1/docs/llm/mcp-server.md +80 -0
- vouch_paper-0.1/docs/quickstart.md +81 -0
- vouch_paper-0.1/docs/requirements.txt +1 -0
- vouch_paper-0.1/docs/tutorial/01-record.md +70 -0
- vouch_paper-0.1/docs/tutorial/02-describe-and-find.md +52 -0
- vouch_paper-0.1/docs/tutorial/03-cite-and-build.md +69 -0
- vouch_paper-0.1/docs/tutorial/04-derived-and-tables.md +84 -0
- vouch_paper-0.1/docs/tutorial/05-check.md +61 -0
- vouch_paper-0.1/docs/tutorial/06-when-code-changes.md +89 -0
- vouch_paper-0.1/docs/tutorial/07-submitting-and-next.md +33 -0
- vouch_paper-0.1/docs/tutorial/index.md +75 -0
- vouch_paper-0.1/examples/minimal/models.py +36 -0
- vouch_paper-0.1/examples/minimal/paper/main.tex +56 -0
- vouch_paper-0.1/examples/minimal/train.py +32 -0
- vouch_paper-0.1/examples/minimal/vouch.toml +6 -0
- vouch_paper-0.1/examples/minimal/vouch_values.py +30 -0
- vouch_paper-0.1/examples/tutorial/README.md +451 -0
- vouch_paper-0.1/examples/tutorial/finished/experiment.py +102 -0
- vouch_paper-0.1/examples/tutorial/finished/paper/main.tex +69 -0
- vouch_paper-0.1/examples/tutorial/finished/vouch.toml +19 -0
- vouch_paper-0.1/examples/tutorial/finished/vouch_values.py +59 -0
- vouch_paper-0.1/examples/tutorial/start/experiment.py +97 -0
- vouch_paper-0.1/examples/tutorial/start/paper/main.tex +23 -0
- vouch_paper-0.1/examples/viewer-check/viewer-check.tex +28 -0
- vouch_paper-0.1/mkdocs.yml +89 -0
- vouch_paper-0.1/pyproject.toml +45 -0
- vouch_paper-0.1/src/vouch/__init__.py +82 -0
- vouch_paper-0.1/src/vouch/__main__.py +4 -0
- vouch_paper-0.1/src/vouch/_entry.py +48 -0
- vouch_paper-0.1/src/vouch/_version.py +24 -0
- vouch_paper-0.1/src/vouch/agents.py +214 -0
- vouch_paper-0.1/src/vouch/api.py +1096 -0
- vouch_paper-0.1/src/vouch/assist.py +561 -0
- vouch_paper-0.1/src/vouch/build.py +634 -0
- vouch_paper-0.1/src/vouch/catalog.py +187 -0
- vouch_paper-0.1/src/vouch/changes.py +381 -0
- vouch_paper-0.1/src/vouch/check.py +289 -0
- vouch_paper-0.1/src/vouch/cli.py +1315 -0
- vouch_paper-0.1/src/vouch/config.py +231 -0
- vouch_paper-0.1/src/vouch/console.py +41 -0
- vouch_paper-0.1/src/vouch/data/explore.html +409 -0
- vouch_paper-0.1/src/vouch/data/vouch.sty +352 -0
- vouch_paper-0.1/src/vouch/derived.py +856 -0
- vouch_paper-0.1/src/vouch/edithook.py +235 -0
- vouch_paper-0.1/src/vouch/exec.py +45 -0
- vouch_paper-0.1/src/vouch/explore.py +501 -0
- vouch_paper-0.1/src/vouch/figures.py +175 -0
- vouch_paper-0.1/src/vouch/fmt.py +87 -0
- vouch_paper-0.1/src/vouch/freshness.py +335 -0
- vouch_paper-0.1/src/vouch/hashing.py +120 -0
- vouch_paper-0.1/src/vouch/hooks.py +61 -0
- vouch_paper-0.1/src/vouch/index.py +400 -0
- vouch_paper-0.1/src/vouch/init.py +124 -0
- vouch_paper-0.1/src/vouch/issues.py +66 -0
- vouch_paper-0.1/src/vouch/mcp_server.py +315 -0
- vouch_paper-0.1/src/vouch/provenance.py +189 -0
- vouch_paper-0.1/src/vouch/render.py +318 -0
- vouch_paper-0.1/src/vouch/runner.py +296 -0
- vouch_paper-0.1/src/vouch/schema/v1.json +45 -0
- vouch_paper-0.1/src/vouch/store.py +201 -0
- vouch_paper-0.1/src/vouch/tex/__init__.py +1 -0
- vouch_paper-0.1/src/vouch/tex/annotate.py +76 -0
- vouch_paper-0.1/src/vouch/tex/emit.py +89 -0
- vouch_paper-0.1/src/vouch/tex/lint.py +391 -0
- vouch_paper-0.1/src/vouch/tex/scan.py +482 -0
- vouch_paper-0.1/src/vouch/tex/suggest.py +93 -0
- vouch_paper-0.1/src/vouch/tracing.py +481 -0
- vouch_paper-0.1/src/vouch/tracked.py +623 -0
- vouch_paper-0.1/src/vouch/units.py +223 -0
- vouch_paper-0.1/src/vouch/values.py +315 -0
- vouch_paper-0.1/src/vouch/valuesmod.py +42 -0
- vouch_paper-0.1/src/vouch/verdict.py +150 -0
- vouch_paper-0.1/tests/conftest.py +81 -0
- vouch_paper-0.1/tests/test_annotate.py +40 -0
- vouch_paper-0.1/tests/test_api.py +359 -0
- vouch_paper-0.1/tests/test_assist.py +391 -0
- vouch_paper-0.1/tests/test_auto_track.py +297 -0
- vouch_paper-0.1/tests/test_build.py +365 -0
- vouch_paper-0.1/tests/test_changes.py +127 -0
- vouch_paper-0.1/tests/test_check.py +221 -0
- vouch_paper-0.1/tests/test_derive.py +632 -0
- vouch_paper-0.1/tests/test_explore.py +166 -0
- vouch_paper-0.1/tests/test_fmt_config.py +92 -0
- vouch_paper-0.1/tests/test_freshness.py +142 -0
- vouch_paper-0.1/tests/test_lint.py +131 -0
- vouch_paper-0.1/tests/test_mcp.py +193 -0
- vouch_paper-0.1/tests/test_render.py +98 -0
- vouch_paper-0.1/tests/test_runner.py +154 -0
- vouch_paper-0.1/tests/test_scan.py +125 -0
- vouch_paper-0.1/tests/test_store.py +89 -0
- vouch_paper-0.1/tests/test_tracing.py +300 -0
- vouch_paper-0.1/tests/test_track.py +486 -0
- vouch_paper-0.1/tests/test_tutorial.py +182 -0
- vouch_paper-0.1/tests/test_units.py +151 -0
- vouch_paper-0.1/tests/test_values.py +120 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- "docs/**"
|
|
8
|
+
- "mkdocs.yml"
|
|
9
|
+
- ".github/workflows/docs.yml"
|
|
10
|
+
workflow_dispatch: {}
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
pages: write
|
|
15
|
+
id-token: write
|
|
16
|
+
|
|
17
|
+
concurrency:
|
|
18
|
+
group: pages
|
|
19
|
+
cancel-in-progress: false
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
build:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
- uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: "3.12"
|
|
29
|
+
- run: pip install -r docs/requirements.txt
|
|
30
|
+
- run: mkdocs build --strict
|
|
31
|
+
- uses: actions/upload-pages-artifact@v3
|
|
32
|
+
with:
|
|
33
|
+
path: site
|
|
34
|
+
|
|
35
|
+
deploy:
|
|
36
|
+
needs: build
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
environment:
|
|
39
|
+
name: github-pages
|
|
40
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
41
|
+
steps:
|
|
42
|
+
- id: deployment
|
|
43
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
with:
|
|
16
|
+
fetch-depth: 0
|
|
17
|
+
- uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.12"
|
|
20
|
+
- run: pip install build
|
|
21
|
+
- run: python -m build
|
|
22
|
+
- uses: actions/upload-artifact@v4
|
|
23
|
+
with:
|
|
24
|
+
name: dist
|
|
25
|
+
path: dist/
|
|
26
|
+
|
|
27
|
+
publish:
|
|
28
|
+
needs: build
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
environment: pypi
|
|
31
|
+
permissions:
|
|
32
|
+
id-token: write
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/download-artifact@v4
|
|
35
|
+
with:
|
|
36
|
+
name: dist
|
|
37
|
+
path: dist/
|
|
38
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
.venv/
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.egg-info/
|
|
4
|
+
.pytest_cache/
|
|
5
|
+
build/
|
|
6
|
+
dist/
|
|
7
|
+
site/
|
|
8
|
+
src/vouch/_version.py
|
|
9
|
+
|
|
10
|
+
# example outputs (regenerated by running the example)
|
|
11
|
+
examples/**/.vouch/
|
|
12
|
+
examples/**/vouch.sty
|
|
13
|
+
examples/**/vouch-values.tex
|
|
14
|
+
examples/**/vouch-provenance.csv
|
|
15
|
+
examples/**/vouch-tables/
|
|
16
|
+
examples/**/.gitattributes
|
|
17
|
+
examples/**/*.pdf
|
|
18
|
+
examples/**/*.aux
|
|
19
|
+
examples/**/*.log
|
|
20
|
+
examples/**/*.fls
|
|
21
|
+
examples/**/*.fdb_latexmk
|
|
22
|
+
examples/**/*.out
|
|
23
|
+
examples/**/*.upa
|
|
24
|
+
examples/**/*.upb
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
- id: vouch-check
|
|
2
|
+
name: vouch check (paper numbers vouched for by their runs)
|
|
3
|
+
description: Fails when a number the paper cites is unknown, stale, out of sync, or a claim no longer holds.
|
|
4
|
+
entry: vouch check --quiet
|
|
5
|
+
language: python
|
|
6
|
+
pass_filenames: false
|
|
7
|
+
always_run: true
|
vouch_paper-0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Daniel Felps
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
vouch_paper-0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: vouch-paper
|
|
3
|
+
Version: 0.1
|
|
4
|
+
Summary: Every number in your paper, vouched for by the code that produced it.
|
|
5
|
+
Author: Daniel Felps
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Daniel Felps
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
29
|
+
Requires-Python: >=3.10
|
|
30
|
+
Requires-Dist: tomli>=1.1; python_version < '3.11'
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: matplotlib; extra == 'dev'
|
|
33
|
+
Requires-Dist: mcp>=2; extra == 'dev'
|
|
34
|
+
Requires-Dist: pandas; extra == 'dev'
|
|
35
|
+
Requires-Dist: pytest>=7; extra == 'dev'
|
|
36
|
+
Provides-Extra: mcp
|
|
37
|
+
Provides-Extra: pandas
|
|
38
|
+
Requires-Dist: pandas; extra == 'pandas'
|
|
39
|
+
Provides-Extra: test
|
|
40
|
+
Requires-Dist: matplotlib; extra == 'test'
|
|
41
|
+
Requires-Dist: mcp>=2; extra == 'test'
|
|
42
|
+
Requires-Dist: pandas; extra == 'test'
|
|
43
|
+
Requires-Dist: pytest>=7; extra == 'test'
|
|
44
|
+
Description-Content-Type: text/markdown
|
|
45
|
+
|
|
46
|
+
# vouch
|
|
47
|
+
|
|
48
|
+
Every number in your paper, vouched for by the code that produced it.
|
|
49
|
+
|
|
50
|
+
**Full documentation: https://dlfelps.github.io/vouch/**
|
|
51
|
+
|
|
52
|
+
Experiments **record** their results as they run. The paper **cites** them by key,
|
|
53
|
+
`\vouch{key}`, and never contains a typed number. `vouch check` proves that every
|
|
54
|
+
cited value exists, comes from a run whose code hasn't changed since, and that
|
|
55
|
+
every claim still holds. When a cited value changes, vouch shows you the sentences
|
|
56
|
+
to re-read. Any number traces back to the function, arguments, seeds, command and
|
|
57
|
+
commit that produced it, from the terminal, a local web page, or by clicking it in
|
|
58
|
+
the PDF.
|
|
59
|
+
|
|
60
|
+
It is built for people and for LLM agents writing papers: the correct number is
|
|
61
|
+
always cheaper to use than a guessed one.
|
|
62
|
+
|
|
63
|
+
**New here? Start with the [tutorial](examples/tutorial/README.md)** (also
|
|
64
|
+
browsable at https://dlfelps.github.io/vouch/tutorial/): a two-second experiment
|
|
65
|
+
and a paper draft, taken step by step to a PDF whose values, table and figure
|
|
66
|
+
all come from the code.
|
|
67
|
+
|
|
68
|
+
```console
|
|
69
|
+
$ pip install -e . # from a clone; Python ≥ 3.10, no dependencies
|
|
70
|
+
$ vouch init # finds your paper, writes vouch.toml, copies vouch.sty
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The base install is everything, the MCP server included, with no dependencies
|
|
74
|
+
(only `tomli` on Python 3.10). Extras: `.[pandas]` to record pandas DataFrames;
|
|
75
|
+
`.[mcp]` installs nothing more (`vouch mcp` needs nothing); `.[test]` for the test
|
|
76
|
+
suite, which includes the official MCP SDK to test `vouch mcp` against, and
|
|
77
|
+
matplotlib for the tutorial.
|
|
78
|
+
|
|
79
|
+
## 1. Record
|
|
80
|
+
|
|
81
|
+
Decorate the function that computes your results. Every call is recorded, keyed by
|
|
82
|
+
the function and its arguments, together with the call itself: arguments, seeds,
|
|
83
|
+
each seed's result, how long it took, and the exact code that ran.
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
import vouch
|
|
87
|
+
|
|
88
|
+
@vouch.track(over="seed") # calls that differ only in seed -> mean ± std
|
|
89
|
+
def evaluate(dataset: str, model: str, seed: int = 0) -> dict:
|
|
90
|
+
...
|
|
91
|
+
return {"acc": acc, "loss": loss}
|
|
92
|
+
|
|
93
|
+
for model in ("resnet", "vit"):
|
|
94
|
+
for seed in range(5):
|
|
95
|
+
evaluate("cifar", model, seed=seed)
|
|
96
|
+
# -> evaluate.cifar.resnet.acc, evaluate.cifar.resnet.loss, evaluate.cifar.resnet.time, ...
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Run the script as usual: `python train.py`. Formats and descriptions for whole
|
|
100
|
+
families of keys go in `vouch.toml`:
|
|
101
|
+
|
|
102
|
+
```toml
|
|
103
|
+
[metrics]
|
|
104
|
+
"*.acc" = { fmt = ".1pct", better = "higher", desc = "top-1 test accuracy" }
|
|
105
|
+
"*.loss" = { fmt = ".3f", better = "lower", desc = "test loss" }
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Other ways to record, when a decorator doesn't fit:
|
|
109
|
+
|
|
110
|
+
| | |
|
|
111
|
+
|---|---|
|
|
112
|
+
| No code changes at all | list the function in `vouch.toml` (`[[track]] function = "train.py::evaluate"`) and run `python -m vouch.exec train.py` |
|
|
113
|
+
| A single number | `vouch.record("cifar.n_test", 10000, desc="test images")` |
|
|
114
|
+
| A dict or table of results | `vouch.record_all(metrics, prefix="cifar.resnet")`, `vouch.table("main", rows, row_key="model")` |
|
|
115
|
+
| A claim | `vouch.claim("resnet_wins", vouch.gt(acc_r, acc_v), desc="ResNet beats ViT")` |
|
|
116
|
+
| Another language | `vouch run vit_jl --dep src/ -- julia train.jl` (the program writes its values to `$VOUCH_VALUES`) |
|
|
117
|
+
| Results that already exist | `vouch import results.json --run eval --producer eval.py` (marked *imported*) |
|
|
118
|
+
|
|
119
|
+
## 2. Find the key
|
|
120
|
+
|
|
121
|
+
```console
|
|
122
|
+
$ vouch explore --open # a local page: script -> function -> keys; one click copies \vouch{...}
|
|
123
|
+
$ vouch search vit accuracy cifar # ranked lookup from the terminal
|
|
124
|
+
$ vouch cite evaluate.cifar.vit.acc # the exact snippet, what it renders as, its subfields
|
|
125
|
+
\vouch{evaluate.cifar.vit.acc} → 90.6 ± 0.4% (fmt .1pct)
|
|
126
|
+
\vouch[.2pct]{evaluate.cifar.vit.acc} → 90.59 ± 0.44% (fmt .2pct)
|
|
127
|
+
top-1 test accuracy · higher is better · fresh · run experiments.train
|
|
128
|
+
subfields: .mean 90.6% · .std 0.4% · .n 5 · .ci95 90.0-91.1% · .min 90.2% · .max 91.1%
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`.vouch/CATALOG.md`, rewritten by every build, lists every citable key on one line
|
|
132
|
+
each: the file an agent reads first.
|
|
133
|
+
|
|
134
|
+
Long generated keys can get short names in `vouch_values.py`:
|
|
135
|
+
`vouch.alias("resnet", "evaluate.cifar.resnet")` makes `\vouch{resnet.acc}` work.
|
|
136
|
+
|
|
137
|
+
## 3. Cite
|
|
138
|
+
|
|
139
|
+
```latex
|
|
140
|
+
\usepackage{vouch}
|
|
141
|
+
...
|
|
142
|
+
ResNet reaches \vouch{evaluate.cifar.resnet.acc} top-1 accuracy
|
|
143
|
+
(\vouch[.3f]{evaluate.cifar.resnet.acc.mean} as a fraction).
|
|
144
|
+
\vouchclaim{resnet_wins}{ResNet outperforms ViT.}
|
|
145
|
+
\begin{tabular}{lr} \toprule Model & Acc \\ \midrule \vouchtable{main} \bottomrule \end{tabular}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Then build the generated values and compile as usual:
|
|
149
|
+
|
|
150
|
+
```console
|
|
151
|
+
$ vouch build
|
|
152
|
+
$ latexmk -pdf paper/main.tex
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
In the draft, every number is a link to a "Value provenance" appendix: what the
|
|
156
|
+
value is, the call that produced it (`evaluate(dataset=cifar, model=resnet) over
|
|
157
|
+
seed=0..4 (5 calls)`), each seed's result, the run, the command and the commit.
|
|
158
|
+
`\usepackage[final]{vouch}` removes all of it for submission.
|
|
159
|
+
|
|
160
|
+
## 4. Numbers computed from numbers
|
|
161
|
+
|
|
162
|
+
Differences, ratios, best-of and derived tables live in `vouch_values.py`, never
|
|
163
|
+
in anyone's head. `vouch build` evaluates them and records exactly which values
|
|
164
|
+
each one read.
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
import vouch
|
|
168
|
+
|
|
169
|
+
@vouch.derive("cifar.gap", fmt=".1f", unit="points", desc="ResNet minus ViT, points")
|
|
170
|
+
def gap(v):
|
|
171
|
+
return 100 * (v["evaluate.cifar.resnet.acc.mean"] - v["evaluate.cifar.vit.acc.mean"])
|
|
172
|
+
|
|
173
|
+
@vouch.claim("cifar.big_gap", desc="ResNet leads by more than a point")
|
|
174
|
+
def big_gap(v):
|
|
175
|
+
return vouch.gt(v["cifar.gap"], 1) # "2.3 > 1 (margin 130%)"; thin margins warn
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
`vouch compare A B` does the arithmetic for you (difference, ratio, a Welch t-test
|
|
179
|
+
for two means ± std) and prints the `derive` and `claim` that make it citable;
|
|
180
|
+
`--write` adds them to `vouch_values.py`.
|
|
181
|
+
|
|
182
|
+
A number the paper needs before any run has produced it is a placeholder, never a
|
|
183
|
+
guess:
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
vouch.expect("imagenet.vit.acc", desc="ViT top-1 on ImageNet", producer="python train.py --dataset imagenet")
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
The PDF shows `[pending: imagenet.vit.acc]`, `vouch todo` lists what is owed, and
|
|
190
|
+
the placeholder resolves once a run records the key.
|
|
191
|
+
|
|
192
|
+
## 5. Check
|
|
193
|
+
|
|
194
|
+
```console
|
|
195
|
+
$ vouch check
|
|
196
|
+
vouch check: paper/main.tex · 16 citations · 1/1 cited runs fresh
|
|
197
|
+
✓ OK
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
`vouch check` never runs your code. It fails when:
|
|
201
|
+
- a cited key doesn't exist
|
|
202
|
+
- the code behind a cited run changed since the run (comments and formatting don't count)
|
|
203
|
+
- a claim no longer holds
|
|
204
|
+
- a figure is stale
|
|
205
|
+
- the generated files are out of date
|
|
206
|
+
|
|
207
|
+
It warns when a cited value changed since someone last read the sentences around
|
|
208
|
+
it (`vouch changes`, then `vouch ack KEY`), and when the paper contains a typed
|
|
209
|
+
number:
|
|
210
|
+
|
|
211
|
+
```
|
|
212
|
+
! bare-number 93.2% is typed by hand; it is evaluate.cifar.resnet.acc.mean: cite it as \vouch[.1pct]{...}
|
|
213
|
+
! no-source 97.1% matches no recorded value: record it where it is computed, or remove it
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Converting a paper that already has typed numbers: `vouch suggest` shows, for each
|
|
217
|
+
one, the key that prints it (or that nothing does); `vouch suggest --apply` rewrites
|
|
218
|
+
the unambiguous ones.
|
|
219
|
+
|
|
220
|
+
Use it in a pre-commit hook (`vouch hook install`) and in CI:
|
|
221
|
+
|
|
222
|
+
```yaml
|
|
223
|
+
# .github/workflows/paper.yml
|
|
224
|
+
name: paper
|
|
225
|
+
on: [push, pull_request]
|
|
226
|
+
jobs:
|
|
227
|
+
vouch:
|
|
228
|
+
runs-on: ubuntu-latest
|
|
229
|
+
steps:
|
|
230
|
+
- uses: actions/checkout@v4
|
|
231
|
+
- uses: actions/setup-python@v5
|
|
232
|
+
with: { python-version: "3.12" }
|
|
233
|
+
- run: pip install -e path/to/vouch # wherever vouch comes from
|
|
234
|
+
- run: vouch check --strict
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## With Claude Code (or another agent)
|
|
238
|
+
|
|
239
|
+
```console
|
|
240
|
+
$ vouch init --agents --yes
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
This installs a skill (`.claude/skills/vouch/SKILL.md`), which teaches the agent to
|
|
244
|
+
record, find, cite, compare and wait for results; a short rules block in `CLAUDE.md`;
|
|
245
|
+
and a hook that checks each `.tex` file the agent edits. A typed number, a mistyped
|
|
246
|
+
key or a broken macro goes straight back to the agent in the same turn, with the
|
|
247
|
+
fix. `--stop-gate` also stops the agent from finishing while `vouch check --strict`
|
|
248
|
+
fails.
|
|
249
|
+
|
|
250
|
+
Any MCP client can use the same lookups as tools (search, get a value, cite,
|
|
251
|
+
compare, pending, changes, check, trace) with `vouch mcp`; `vouch init --agents mcp`
|
|
252
|
+
registers it in `.mcp.json`. Acknowledging changes stays a human action: there is
|
|
253
|
+
no tool for it.
|
|
254
|
+
|
|
255
|
+
## Commands
|
|
256
|
+
|
|
257
|
+
| | |
|
|
258
|
+
|---|---|
|
|
259
|
+
| `vouch init` | set up `vouch.toml`, `.vouch/` and `paper/vouch.sty` |
|
|
260
|
+
| `vouch build` | evaluate `vouch_values.py`, write the generated LaTeX, report changes |
|
|
261
|
+
| `vouch check [--strict]` | the gate (exit 0 pass, 1 fail, 2 could not check) |
|
|
262
|
+
| `vouch explore` | browse every recorded value; copy the LaTeX that cites it |
|
|
263
|
+
| `vouch search` / `vouch cite` | find a key by words / the exact snippet to paste |
|
|
264
|
+
| `vouch compare A B [--write]` | arithmetic and significance between two values, as citable code |
|
|
265
|
+
| `vouch suggest [--apply]` | turn numbers typed into the paper into citations |
|
|
266
|
+
| `vouch todo` | values the paper cites that no run has recorded yet |
|
|
267
|
+
| `vouch ls` / `vouch trace` / `vouch status` | list keys, see where a value came from, see which runs are stale |
|
|
268
|
+
| `vouch changes` / `vouch ack` / `vouch review` | cited values that moved since they were last read |
|
|
269
|
+
| `vouch accept RUN --why ...` | a reviewed staleness that doesn't affect the result |
|
|
270
|
+
| `vouch run` / `vouch import` | record runs of other languages; register existing results files |
|
|
271
|
+
| `vouch sync [--strip]` | write each cited value into a `% vouch:` comment on its line |
|
|
272
|
+
| `vouch export --csv FILE` | the provenance table |
|
|
273
|
+
| `vouch catalog` | rewrite `.vouch/CATALOG.md` |
|
|
274
|
+
| `vouch init --agents` | set up Claude Code: skill, rules, edit hook |
|
|
275
|
+
| `vouch mcp` | the lookups as MCP tools, over stdio |
|
|
276
|
+
|
|
277
|
+
The full design is in [SPEC.md](SPEC.md). Browsable documentation:
|
|
278
|
+
https://dlfelps.github.io/vouch/.
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# vouch
|
|
2
|
+
|
|
3
|
+
Every number in your paper, vouched for by the code that produced it.
|
|
4
|
+
|
|
5
|
+
**Full documentation: https://dlfelps.github.io/vouch/**
|
|
6
|
+
|
|
7
|
+
Experiments **record** their results as they run. The paper **cites** them by key,
|
|
8
|
+
`\vouch{key}`, and never contains a typed number. `vouch check` proves that every
|
|
9
|
+
cited value exists, comes from a run whose code hasn't changed since, and that
|
|
10
|
+
every claim still holds. When a cited value changes, vouch shows you the sentences
|
|
11
|
+
to re-read. Any number traces back to the function, arguments, seeds, command and
|
|
12
|
+
commit that produced it, from the terminal, a local web page, or by clicking it in
|
|
13
|
+
the PDF.
|
|
14
|
+
|
|
15
|
+
It is built for people and for LLM agents writing papers: the correct number is
|
|
16
|
+
always cheaper to use than a guessed one.
|
|
17
|
+
|
|
18
|
+
**New here? Start with the [tutorial](examples/tutorial/README.md)** (also
|
|
19
|
+
browsable at https://dlfelps.github.io/vouch/tutorial/): a two-second experiment
|
|
20
|
+
and a paper draft, taken step by step to a PDF whose values, table and figure
|
|
21
|
+
all come from the code.
|
|
22
|
+
|
|
23
|
+
```console
|
|
24
|
+
$ pip install -e . # from a clone; Python ≥ 3.10, no dependencies
|
|
25
|
+
$ vouch init # finds your paper, writes vouch.toml, copies vouch.sty
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The base install is everything, the MCP server included, with no dependencies
|
|
29
|
+
(only `tomli` on Python 3.10). Extras: `.[pandas]` to record pandas DataFrames;
|
|
30
|
+
`.[mcp]` installs nothing more (`vouch mcp` needs nothing); `.[test]` for the test
|
|
31
|
+
suite, which includes the official MCP SDK to test `vouch mcp` against, and
|
|
32
|
+
matplotlib for the tutorial.
|
|
33
|
+
|
|
34
|
+
## 1. Record
|
|
35
|
+
|
|
36
|
+
Decorate the function that computes your results. Every call is recorded, keyed by
|
|
37
|
+
the function and its arguments, together with the call itself: arguments, seeds,
|
|
38
|
+
each seed's result, how long it took, and the exact code that ran.
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
import vouch
|
|
42
|
+
|
|
43
|
+
@vouch.track(over="seed") # calls that differ only in seed -> mean ± std
|
|
44
|
+
def evaluate(dataset: str, model: str, seed: int = 0) -> dict:
|
|
45
|
+
...
|
|
46
|
+
return {"acc": acc, "loss": loss}
|
|
47
|
+
|
|
48
|
+
for model in ("resnet", "vit"):
|
|
49
|
+
for seed in range(5):
|
|
50
|
+
evaluate("cifar", model, seed=seed)
|
|
51
|
+
# -> evaluate.cifar.resnet.acc, evaluate.cifar.resnet.loss, evaluate.cifar.resnet.time, ...
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Run the script as usual: `python train.py`. Formats and descriptions for whole
|
|
55
|
+
families of keys go in `vouch.toml`:
|
|
56
|
+
|
|
57
|
+
```toml
|
|
58
|
+
[metrics]
|
|
59
|
+
"*.acc" = { fmt = ".1pct", better = "higher", desc = "top-1 test accuracy" }
|
|
60
|
+
"*.loss" = { fmt = ".3f", better = "lower", desc = "test loss" }
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Other ways to record, when a decorator doesn't fit:
|
|
64
|
+
|
|
65
|
+
| | |
|
|
66
|
+
|---|---|
|
|
67
|
+
| No code changes at all | list the function in `vouch.toml` (`[[track]] function = "train.py::evaluate"`) and run `python -m vouch.exec train.py` |
|
|
68
|
+
| A single number | `vouch.record("cifar.n_test", 10000, desc="test images")` |
|
|
69
|
+
| A dict or table of results | `vouch.record_all(metrics, prefix="cifar.resnet")`, `vouch.table("main", rows, row_key="model")` |
|
|
70
|
+
| A claim | `vouch.claim("resnet_wins", vouch.gt(acc_r, acc_v), desc="ResNet beats ViT")` |
|
|
71
|
+
| Another language | `vouch run vit_jl --dep src/ -- julia train.jl` (the program writes its values to `$VOUCH_VALUES`) |
|
|
72
|
+
| Results that already exist | `vouch import results.json --run eval --producer eval.py` (marked *imported*) |
|
|
73
|
+
|
|
74
|
+
## 2. Find the key
|
|
75
|
+
|
|
76
|
+
```console
|
|
77
|
+
$ vouch explore --open # a local page: script -> function -> keys; one click copies \vouch{...}
|
|
78
|
+
$ vouch search vit accuracy cifar # ranked lookup from the terminal
|
|
79
|
+
$ vouch cite evaluate.cifar.vit.acc # the exact snippet, what it renders as, its subfields
|
|
80
|
+
\vouch{evaluate.cifar.vit.acc} → 90.6 ± 0.4% (fmt .1pct)
|
|
81
|
+
\vouch[.2pct]{evaluate.cifar.vit.acc} → 90.59 ± 0.44% (fmt .2pct)
|
|
82
|
+
top-1 test accuracy · higher is better · fresh · run experiments.train
|
|
83
|
+
subfields: .mean 90.6% · .std 0.4% · .n 5 · .ci95 90.0-91.1% · .min 90.2% · .max 91.1%
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
`.vouch/CATALOG.md`, rewritten by every build, lists every citable key on one line
|
|
87
|
+
each: the file an agent reads first.
|
|
88
|
+
|
|
89
|
+
Long generated keys can get short names in `vouch_values.py`:
|
|
90
|
+
`vouch.alias("resnet", "evaluate.cifar.resnet")` makes `\vouch{resnet.acc}` work.
|
|
91
|
+
|
|
92
|
+
## 3. Cite
|
|
93
|
+
|
|
94
|
+
```latex
|
|
95
|
+
\usepackage{vouch}
|
|
96
|
+
...
|
|
97
|
+
ResNet reaches \vouch{evaluate.cifar.resnet.acc} top-1 accuracy
|
|
98
|
+
(\vouch[.3f]{evaluate.cifar.resnet.acc.mean} as a fraction).
|
|
99
|
+
\vouchclaim{resnet_wins}{ResNet outperforms ViT.}
|
|
100
|
+
\begin{tabular}{lr} \toprule Model & Acc \\ \midrule \vouchtable{main} \bottomrule \end{tabular}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Then build the generated values and compile as usual:
|
|
104
|
+
|
|
105
|
+
```console
|
|
106
|
+
$ vouch build
|
|
107
|
+
$ latexmk -pdf paper/main.tex
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
In the draft, every number is a link to a "Value provenance" appendix: what the
|
|
111
|
+
value is, the call that produced it (`evaluate(dataset=cifar, model=resnet) over
|
|
112
|
+
seed=0..4 (5 calls)`), each seed's result, the run, the command and the commit.
|
|
113
|
+
`\usepackage[final]{vouch}` removes all of it for submission.
|
|
114
|
+
|
|
115
|
+
## 4. Numbers computed from numbers
|
|
116
|
+
|
|
117
|
+
Differences, ratios, best-of and derived tables live in `vouch_values.py`, never
|
|
118
|
+
in anyone's head. `vouch build` evaluates them and records exactly which values
|
|
119
|
+
each one read.
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
import vouch
|
|
123
|
+
|
|
124
|
+
@vouch.derive("cifar.gap", fmt=".1f", unit="points", desc="ResNet minus ViT, points")
|
|
125
|
+
def gap(v):
|
|
126
|
+
return 100 * (v["evaluate.cifar.resnet.acc.mean"] - v["evaluate.cifar.vit.acc.mean"])
|
|
127
|
+
|
|
128
|
+
@vouch.claim("cifar.big_gap", desc="ResNet leads by more than a point")
|
|
129
|
+
def big_gap(v):
|
|
130
|
+
return vouch.gt(v["cifar.gap"], 1) # "2.3 > 1 (margin 130%)"; thin margins warn
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
`vouch compare A B` does the arithmetic for you (difference, ratio, a Welch t-test
|
|
134
|
+
for two means ± std) and prints the `derive` and `claim` that make it citable;
|
|
135
|
+
`--write` adds them to `vouch_values.py`.
|
|
136
|
+
|
|
137
|
+
A number the paper needs before any run has produced it is a placeholder, never a
|
|
138
|
+
guess:
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
vouch.expect("imagenet.vit.acc", desc="ViT top-1 on ImageNet", producer="python train.py --dataset imagenet")
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
The PDF shows `[pending: imagenet.vit.acc]`, `vouch todo` lists what is owed, and
|
|
145
|
+
the placeholder resolves once a run records the key.
|
|
146
|
+
|
|
147
|
+
## 5. Check
|
|
148
|
+
|
|
149
|
+
```console
|
|
150
|
+
$ vouch check
|
|
151
|
+
vouch check: paper/main.tex · 16 citations · 1/1 cited runs fresh
|
|
152
|
+
✓ OK
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
`vouch check` never runs your code. It fails when:
|
|
156
|
+
- a cited key doesn't exist
|
|
157
|
+
- the code behind a cited run changed since the run (comments and formatting don't count)
|
|
158
|
+
- a claim no longer holds
|
|
159
|
+
- a figure is stale
|
|
160
|
+
- the generated files are out of date
|
|
161
|
+
|
|
162
|
+
It warns when a cited value changed since someone last read the sentences around
|
|
163
|
+
it (`vouch changes`, then `vouch ack KEY`), and when the paper contains a typed
|
|
164
|
+
number:
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
! bare-number 93.2% is typed by hand; it is evaluate.cifar.resnet.acc.mean: cite it as \vouch[.1pct]{...}
|
|
168
|
+
! no-source 97.1% matches no recorded value: record it where it is computed, or remove it
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Converting a paper that already has typed numbers: `vouch suggest` shows, for each
|
|
172
|
+
one, the key that prints it (or that nothing does); `vouch suggest --apply` rewrites
|
|
173
|
+
the unambiguous ones.
|
|
174
|
+
|
|
175
|
+
Use it in a pre-commit hook (`vouch hook install`) and in CI:
|
|
176
|
+
|
|
177
|
+
```yaml
|
|
178
|
+
# .github/workflows/paper.yml
|
|
179
|
+
name: paper
|
|
180
|
+
on: [push, pull_request]
|
|
181
|
+
jobs:
|
|
182
|
+
vouch:
|
|
183
|
+
runs-on: ubuntu-latest
|
|
184
|
+
steps:
|
|
185
|
+
- uses: actions/checkout@v4
|
|
186
|
+
- uses: actions/setup-python@v5
|
|
187
|
+
with: { python-version: "3.12" }
|
|
188
|
+
- run: pip install -e path/to/vouch # wherever vouch comes from
|
|
189
|
+
- run: vouch check --strict
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## With Claude Code (or another agent)
|
|
193
|
+
|
|
194
|
+
```console
|
|
195
|
+
$ vouch init --agents --yes
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
This installs a skill (`.claude/skills/vouch/SKILL.md`), which teaches the agent to
|
|
199
|
+
record, find, cite, compare and wait for results; a short rules block in `CLAUDE.md`;
|
|
200
|
+
and a hook that checks each `.tex` file the agent edits. A typed number, a mistyped
|
|
201
|
+
key or a broken macro goes straight back to the agent in the same turn, with the
|
|
202
|
+
fix. `--stop-gate` also stops the agent from finishing while `vouch check --strict`
|
|
203
|
+
fails.
|
|
204
|
+
|
|
205
|
+
Any MCP client can use the same lookups as tools (search, get a value, cite,
|
|
206
|
+
compare, pending, changes, check, trace) with `vouch mcp`; `vouch init --agents mcp`
|
|
207
|
+
registers it in `.mcp.json`. Acknowledging changes stays a human action: there is
|
|
208
|
+
no tool for it.
|
|
209
|
+
|
|
210
|
+
## Commands
|
|
211
|
+
|
|
212
|
+
| | |
|
|
213
|
+
|---|---|
|
|
214
|
+
| `vouch init` | set up `vouch.toml`, `.vouch/` and `paper/vouch.sty` |
|
|
215
|
+
| `vouch build` | evaluate `vouch_values.py`, write the generated LaTeX, report changes |
|
|
216
|
+
| `vouch check [--strict]` | the gate (exit 0 pass, 1 fail, 2 could not check) |
|
|
217
|
+
| `vouch explore` | browse every recorded value; copy the LaTeX that cites it |
|
|
218
|
+
| `vouch search` / `vouch cite` | find a key by words / the exact snippet to paste |
|
|
219
|
+
| `vouch compare A B [--write]` | arithmetic and significance between two values, as citable code |
|
|
220
|
+
| `vouch suggest [--apply]` | turn numbers typed into the paper into citations |
|
|
221
|
+
| `vouch todo` | values the paper cites that no run has recorded yet |
|
|
222
|
+
| `vouch ls` / `vouch trace` / `vouch status` | list keys, see where a value came from, see which runs are stale |
|
|
223
|
+
| `vouch changes` / `vouch ack` / `vouch review` | cited values that moved since they were last read |
|
|
224
|
+
| `vouch accept RUN --why ...` | a reviewed staleness that doesn't affect the result |
|
|
225
|
+
| `vouch run` / `vouch import` | record runs of other languages; register existing results files |
|
|
226
|
+
| `vouch sync [--strip]` | write each cited value into a `% vouch:` comment on its line |
|
|
227
|
+
| `vouch export --csv FILE` | the provenance table |
|
|
228
|
+
| `vouch catalog` | rewrite `.vouch/CATALOG.md` |
|
|
229
|
+
| `vouch init --agents` | set up Claude Code: skill, rules, edit hook |
|
|
230
|
+
| `vouch mcp` | the lookups as MCP tools, over stdio |
|
|
231
|
+
|
|
232
|
+
The full design is in [SPEC.md](SPEC.md). Browsable documentation:
|
|
233
|
+
https://dlfelps.github.io/vouch/.
|