bfev cheatsheet¶
One-page reference. For deep dives see explanation/architecture.md, reference/contracts.md, reference/testing.md.
Install¶
# 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
Configure¶
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
Pipeline lifecycle¶
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 install (one-time per machine)¶
/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.
Test harness¶
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
Audit checks (what 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.
Crosscheck XLSX — the human-audit story¶
from bfev.crosscheck import build
from pathlib import Path
build(Path("calculations-v0/results.json"), Path("calculations-v0/crosscheck.xlsx"))
- Cells in
co2e_kg,uncertainty_low_kg,uncertainty_high_kgare formulas (=B2*C2*D2etc.), not literals. - The
CalculateContract.check_postconditionsrejects literal values in those columns — break this and the contract fails loudly. - Never hand-author the workbook — always call
bfev.crosscheck.build.
Vendor skill re-sync (when upstream ~/.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
Docker¶
# 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.
Common gotchas¶
plugin.jsoninstall fails → don't putagents: "./agents/"as a string. Either an array of paths or omit (auto-discovery).bfev test --livehits max_turns → check--verboseforAskUserQuestion(interactive) orTask(delegation loop). The harness restrictsallowed_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(insrc/bfev/testing/live.py).pytestreportsexecutable file not foundinside Docker → image was built without[dev]extra. Rebuild withpip install ".[dev]".- Live mode billed to wrong account → without
ANTHROPIC_API_KEY, the SDK uses Claude Code session auth → consumes your Pro/Max quota, not API credit.
File layout reference¶
$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}
Memory hygiene¶
- Client data lives only under
$BFEV_HOME/clients/— never inside the bfev repo (.gitignoreenforces). - No client name in
~/.claude/skills/— vendored skills are config-driven via.bfev/isolation-blacklist.txt. - No tCO2e/% scope per named client in CVs, job summaries, or internal memos — only contractual deliverables.