One-page reference. For deep dives see explanation/architecture.md, reference/contracts.md, reference/testing.md.
# from source
git clone https://github.com/DeeRocking/bfev.git
cd bfev
uv venv && source .venv/bin/activate
uv pip install -e ".[dev]" # core + tests
uv pip install -e ".[dev,live]" # + claude-agent-sdk for `bfev test --live`
# from ghcr (private — needs Collaborator on github.com/DeeRocking/bfev)
gh auth token | docker login ghcr.io -u <username> --password-stdin
docker pull ghcr.io/deerocking/bfev:0.1.0
export BFEV_HOME=$HOME/bfev # default ~/bfev; never in the bfev repo
mkdir -p "$BFEV_HOME/.bfev"
echo "PORTEO" >> "$BFEV_HOME/.bfev/isolation-blacklist.txt" # one client token per line
bfev init <slug> # bootstrap $BFEV_HOME/clients/<slug>/
$EDITOR $BFEV_HOME/clients/<slug>/client.yaml # fill name, country, sector, period, actors[]
# (4 stages run via Claude Code plugin: /plugin install bfev@bfev)
# Then verify:
bfev status <slug> # dashboard: artefact presence + runs + audit
bfev audit <slug> # cross-stage check (anti-leak + reconciliation + entities)
bfev log <slug> -n 20 # tail runs.jsonl
/plugin marketplace add /path/to/bfev # the repo root (NOT plugin/)
/plugin install bfev@bfev
/reload-plugins
Verify with /agents — you should see bfev-orchestrator, bfev-collection, bfev-simulate, bfev-calculate, bfev-report.
pytest -q # unit tests, <5s
bfev test calculate # replay (no Claude), 3 cases
bfev test calculate --case diesel-only # single case
bfev test calculate --case diesel-only --accept # regenerate golden after intentional change
bfev ping --verbose # ~$0.05, 5s — SDK + plugin sanity
bfev test --live calculate --case diesel-only --verbose # ~$0.25, 30s — true E2E
bfev test --live calculate --case <c> --verbose --keep-tmp # keep the tmpdir for inspection
bfev audit enforces)| Check | What it does | Fails when |
|---|---|---|
anti_leak |
greps deliverable PDFs for v1/v2/recalibrage/audit interne/en attente de/à confirmer par/mis à jour quand |
any forbidden phrase appears in a rendered PDF |
crosscheck_reconciliation |
recomputes Σ AD·EF·GWP from crosscheck.xlsx, compares to aggregates.json |
drift > tolerance_pct (default 0.5%) on any scope |
entity_allowlist |
report self-audit's entities_referenced ⊆ client.yaml.actors |
the report cites an actor not in client.yaml |
Exit code: 0 if all pass, 1 otherwise. Output written to $BFEV_HOME/clients/<slug>/deliverables-<scenario>/consistency-audit.json.
from bfev.crosscheck import build
from pathlib import Path
build(Path("calculations-v0/results.json"), Path("calculations-v0/crosscheck.xlsx"))
co2e_kg, uncertainty_low_kg, uncertainty_high_kg are formulas (=B2*C2*D2 etc.), not literals.CalculateContract.check_postconditions rejects literal values in those columns — break this and the contract fails loudly.bfev.crosscheck.build.~/.claude/skills/ changes)./scripts/apply-vendor-patches.sh # default: $HOME/.claude/skills
SKILLS=ghg-reporting ./scripts/apply-vendor-patches.sh # narrow to one
./scripts/apply-vendor-patches.sh /alt/skills/source # custom upstream
Fails loud on patch conflict — that's the signal that upstream has drifted into a patched zone. To regenerate a patch:
diff -u $HOME/.claude/skills/<skill>/<path> plugin/skills/<skill>/<path> \
| sed -E "1s|^--- .*|--- a/<path>|; 2s|^\+\+\+ .*|+++ b/<path>|" \
> plugin/skills/.patches/<skill>/<NN>-<name>.patch
# build (~10 min cold, ~1.5 GB)
docker build -t bfev:latest .
docker build --build-arg LIVE=1 -t bfev:live .
# run
docker run --rm -v "$HOME/bfev:/work/bfev-home" \
-e BFEV_HOME=/work/bfev-home \
ghcr.io/deerocking/bfev:0.1.0 bfev init demo
# publish
docker tag bfev:latest ghcr.io/deerocking/bfev:0.1.0
docker push ghcr.io/deerocking/bfev:0.1.0
Never re-push under the same tag if content changed — bump version (0.1.1, etc.). lockfile.yaml relies on stable digests.
plugin.json install fails → don't put agents: "./agents/" as a string. Either an array of paths or omit (auto-discovery).bfev test --live hits max_turns → check --verbose for AskUserQuestion (interactive) or Task (delegation loop). The harness restricts allowed_tools=[Read,Write,Edit,Bash] to avoid this; if you add a new agent's test prompt, keep it directive.AssistantMessage Bash × N then nothing → the agent is exploring. Tighten the system prompt in _TEST_PROMPTS (in src/bfev/testing/live.py).pytest reports executable file not found inside Docker → image was built without [dev] extra. Rebuild with pip install ".[dev]".ANTHROPIC_API_KEY, the SDK uses Claude Code session auth → consumes your Pro/Max quota, not API credit.$BFEV_HOME/
├── .bfev/
│ ├── isolation-blacklist.txt # client tokens to refuse in deliverables
│ └── isolation-allowlist/<slug>.txt # per-client exemptions (optional)
├── resources/
│ ├── categories.json # master taxonomy
│ └── ipcc-volume-{1..5}/... # IPCC AR2006 PDFs
└── clients/<slug>/
├── client.yaml # name, country, sector, period, actors[]
├── lockfile.yaml # bfev version + EF/IPCC/skill hashes
├── runs.jsonl # append-only audit trail
├── collection/{schema.xlsx,request.pdf}
├── activity-data-<sc>/{filled.xlsx,provenance.yaml}
├── calculations-<sc>/{aggregates.json,results.json,crosscheck.xlsx,meta.yaml,audit.log,figures/}
└── deliverables-<sc>/{executive.pdf,scientific.pdf,official.pdf,consistency-audit.json,self-audit.json}
$BFEV_HOME/clients/ — never inside the bfev repo (.gitignore enforces).~/.claude/skills/ — vendored skills are config-driven via .bfev/isolation-blacklist.txt.