Architecture
Data Flow
argv/env/config → Bootstrap → RunContext
RunContext → Preflight (bw status, version)
RunContext → Fetch (bw list items, bw list folders) → raw JSON
raw JSON → Validate (zod) → Item[], Folder[]
Item[] → Analyze (pure) → Findings
Findings → Present (Clack prompts) → PendingOp[]
PendingOp[] → Apply (serial bw edit/create/delete) → applied / failed
(on failure) → persist PendingOp[] to pending.json
(on success) → bw sync (fire-and-forget warn-only)
No stage calls backwards. The analyzer cannot invoke bw. The apply phase cannot re-analyze.
Module Layers
Commands (src/commands/)
The composition root. May import from anywhere under src/ but is never imported by library code. Reads process.argv, process.env, and process.stdout.isTTY.
Library (src/lib/)
Pure analysis and infrastructure code. Subdivided by concern:
bw.ts— the sole subprocess boundary (CLI adapter). Only file allowed to callchild_processforbwcommands.bw-serve.ts— HTTP adapter implementingBwAdapterviabw serveREST API. Usesnode:httpinstead of subprocesses. An alternative transport behind the same interface; opt-in viabw_serve.enabledconfig.bw-serve-lifecycle.ts— manages thebw servechild process lifecycle: spawn, health-check polling, graceful stop. Registered with signal handlers for cleanup on SIGINT/SIGTERM.domain/— shared types (BwItem,Finding,PendingOp). No logic, only type definitions and zod schemas.analyze/,dedup/,strength/,folders/— pure analysis modules. No I/O, nobwcalls, noprocess.*reads.pending.ts— reads/writes the pending queue to disk.
Config (src/config/)
Schema definition, file discovery, loading, and migration. May not import from bw.ts or commands.
CLI (src/cli/)
Argument parsing, help text, TTY/color detection. The bridge between raw process state and typed RunContext.
Core (src/core/)
Cross-cutting infrastructure: write-ahead journal, transactions, signal handling.
Trust Boundaries
The only external trust boundary is the bw CLI subprocess. seiton validates all bw output with zod schemas using .passthrough() to preserve unknown fields for round-tripping.
User input (config files, CLI args) is validated at entry with zod. Invalid input fails immediately with a typed error.
Error Strategy
Every module boundary uses a discriminated error union (BwError, ConfigError, PendingQueueError, UserAbortError). The command dispatcher maps error codes to BSD sysexits exit codes.
No error is swallowed. Every catch either converts to a typed error and rethrows, or logs and makes a deliberate recovery decision.