introduces a balanced set of agent + human docs: - root AGENTS.md (with CLAUDE.md symlink) — 5-rule quickstart, layout map, mental model, use-case keyed example pointers. - docs/agents/conventions.md — vault/demagify, eval-loader constraints, group inheritance, naming, do-not-touch list, suspension idioms, working-style notes. - docs/agents/commands.md — repo-specific deltas to the fork's bw runbook (apt-key offline-verify, *.py_ suspended-node visibility, vault-echo rule). - per-area AGENTS.md for bundles/, nodes/, groups/, libs/, hooks/, data/, items/, bin/ — mechanism-focused, no enumeration. - bundles/AGENTS.template.md — per-bundle doc template with optional `## Writes into` section for cross-namespace reactors. bundlewrap-language reference (item types, dep keywords, reactors, runbook, three-tier safety envelope) is not duplicated here; we link out to the fork's AGENTS.md instead. bw test still green. all internal links resolve. Phase 0 invariants preserved (libs/hooks docstrings, bin/* # purpose: headers). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2.3 KiB
hooks/
What's here
Repo-level lifecycle hooks. Each *.py exports one or more functions
named after the lifecycle event they listen to (apply_start,
node_apply_start, node_run_start, test, test_node, …). Bw
discovers them by importing each module from hooks/.
Discovery is by ls hooks/ + the one-line docstring at the top of
each file:
head -1 hooks/*.py
Conventions
- One-line module docstring. Every
hooks/*.pystarts with"""<name>: <one-line purpose>.""". Add one when introducing a new hook; baseline is enforced bygrep -L '"""' hooks/*.py. - Function name = event name. Bw calls
apply_start(repo, target, nodes, interactive=False, **kwargs),node_apply_start(repo, node, interactive, **kwargs),test(repo, **kwargs), etc. Always accept**kwargsso future bw arguments don't break the hook. - Test gates use
test/test_node. Anything that should failbw test(and therefore CI / pre-apply sanity) goes here; avoid doing test-style assertions inapply_start.
How to add a hook
- Pick the lifecycle event (see fork's
AGENTS.mdfor the full list). - Create
hooks/<name>.pywith the matching function and a docstring. - Run
bw testonce to confirm the hook loads cleanly.
Pitfalls
-
A hook that errors at import breaks every
bwinvocation that fires the hook's lifecycle — includingbw testitself, which defeats the obvious diagnostic. Test new hooks in isolation first:bw debug -c "import sys; sys.path.insert(0, 'hooks'); import <hookmodule>"Iterate there until the import is clean, then commit.
-
Hooks have access to the full repo (
repo,node,nodes). Don't make them block on network unless that's the explicit purpose (e.g.test_ptr_records.pydoesdigagainst9.9.9.9). -
Order is not guaranteed across hook files. Two hooks that both define
apply_startwill both fire; don't assume which runs first.
See also
docs/agents/conventions.md— files-not-to-touch, vault rules.docs/agents/commands.md— test workflow.- Fork's
AGENTS.md— full hook lifecycle and signatures.