Packaging & sharing

bfev is intended to be shareable with colleagues who may not have your exact setup. Two distribution layers:

1. Python package

Standard wheel via Hatchling:

uv build                       # produces dist/bfev-0.1.0-*.whl + sdist
uv pip install dist/bfev-0.1.0-*.whl

A colleague then needs only Python 3.11+ and the wheel:

pip install bfev-0.1.0-*.whl
bfev --version
bfev init my-first-client

This installs the CLI, contracts, logging, lockfile, audit, and the crosscheck-XLSX builder. It does not install Claude Code or any agent definitions — those come from the plugin.

2. Claude Code plugin

The plugin (plugin/) ships:

A colleague installs the plugin via:

/plugin add <repo-url-or-path>/plugin

Then their Claude Code sees agent:orchestrator etc.

3. Optional: Docker

For colleagues who can't install Quarto / openpyxl / fonts cleanly:

docker build -t bfev:0.1.0 .
docker run -v ~/bfev:/data -e BFEV_HOME=/data bfev:0.1.0 init my-client

The Dockerfile bundles Python, uv, Quarto, fonts, and the bfev package. It mounts $BFEV_HOME so client data stays on the host filesystem.

Confidentiality boundary

Client data must never end up in the package. Two safeguards:

  1. $BFEV_HOME defaults to ~/bfev, outside any git repo.
  2. Any project that does check bfev.toml into git must .gitignore the clients/ directory. The repo's own .gitignore does this.

The package ships only resources/ (the master taxonomy, regulatory anchors, EF tables). IPCC volumes are fetched separately via bfev fetch-ipcc — they're public but heavy.

Versioning

bfev follows semver. Breaking changes to:

…bump the major version. Adding optional fields or new audit checks bumps the minor. Bug fixes bump the patch.

Every project's lockfile.yaml records the bfev version it was created with. A project initialised under bfev 0.x won't run under bfev 1.x without an explicit bfev upgrade.

Build the documentation

Markdown is canonical. A single declarative manifest, docs/build.yaml, drives one pilot that regenerates the whole site (HTML + PDF) in one command:

python docs/build_docs.py                 # → docs/_site/ (HTML + assets + PDF)
python docs/build_docs.py --format html   # HTML only (no LaTeX needed)
python docs/build_docs.py --dry-run       # enumerate the build plan, render nothing

HTML is rendered by a pure-Python markdown→HTML converter (no pandoc, no LaTeX), output mirroring the Diátaxis tree under _site/. PDFs go through Quarto and need a LaTeX toolchain (Windows MiKTeX with the Times/Arial fonts); without it the pilot renders HTML, reports the PDF step as skipped, and never crashes.