BULLPEN_HOME: run bullpen against an isolated state directory (#8) - #10
Conversation
Every bullpen process wrote to the one `~/.bullpen`, so there was no way to
run a demo, a test, or a second copy of bullpen without it sharing sessions,
credentials, and logs with the real one. The README's own recorded demo had
to work around this, and any script wanting a scratch store had nothing to
set.
`BULLPEN_HOME` moves the whole directory, not just the database. The store,
`auth.json`, and the background logs all land directly in it with no
`.bullpen` segment appended. Splitting them — a relocatable database with
logs still under `$HOME` — would leave logs keyed to session ids that live in
a database somewhere else, which is the split-brain the single-directory
concept exists to prevent.
Empty counts as unset. `env::var_os` hands back `Some("")` for
`BULLPEN_HOME=`, which taken literally would resolve the store to a bare
relative `bullpen.db` in whatever directory the process happened to start
in — a silent relocation of someone's sessions, the exact failure this change
must not introduce.
`store` and `auth` are siblings — neither depends on the other, both only on
`bullpen-llm` — so there is no existing crate to share the resolver from, and
a one-function crate is not worth its manifest. Each carries its own private
`resolve_home` and its own fallback test, so a divergence between the two
copies fails CI rather than quietly relocating one of the two files. `cli`
calls the store's public `home_dir()` for the logs directory.
Both `resolve_home`s are pure, taking the env values as arguments; only the
`home_dir()` wrapper reads the process environment. That is not a style
preference: edition 2024 makes `env::set_var` unsafe and `cargo test` runs
the suite multi-threaded in one process, so a test that mutated `HOME` would
race every other test in its binary.
Additive. No migration, no rename, no `--store` flag, and nothing on disk
moves. With the variable unset every path is byte-for-byte what it was.
Verified: fmt, clippy -D warnings, and 98 workspace tests green (4 new — the
required unset-fallback assertion and the override, in both crates). Also
checked against the built binary, since the pure tests deliberately leave the
env-reading wrapper uncovered: `BULLPEN_HOME=<tmp> bullpen sessions --json`
created `<tmp>/bullpen.db` with no `.bullpen` segment, and the same command
with the variable unset still read the pre-existing `~/.bullpen/bullpen.db`
and returned its real sessions.
Refs #8
Claude-Session: https://claude.ai/code/session_01PfAfAujueuZ3rDTiL9apx3
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughBullpen now supports ChangesBULLPEN_HOME path resolution
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant CLI
participant HomeResolution
participant Storage
CLI->>HomeResolution: Resolve BULLPEN_HOME or fallback directory
HomeResolution->>Storage: Provide resolved home directory
Storage->>Storage: Build database and log paths
Possibly related issues
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@ARCHITECTURE.md`:
- Line 33: Update both BULLPEN_HOME directory references in ARCHITECTURE.md to
state that a non-empty BULLPEN_HOME value overrides the default ~/.bullpen
location, while an empty value continues to fall back to ~/.bullpen.
In `@crates/auth/src/lib.rs`:
- Around line 5-7: Update the module documentation describing BULLPEN_HOME to
state that only a non-empty value selects $BULLPEN_HOME/auth.json; explicitly
document that an unset or empty BULLPEN_HOME falls back to ~/.bullpen/auth.json.
In `@crates/store/src/lib.rs`:
- Around line 98-99: Update the documentation comment for the Bullpen state
directory to clarify that only a non-empty BULLPEN_HOME value overrides the
~/.bullpen fallback; an unset or empty value uses the fallback.
In `@README.md`:
- Around line 129-130: Update the README SQLite command to match the resolver’s
fallback behavior: when both BULLPEN_HOME and HOME are empty, resolve the
database path under ./.bullpen rather than /.bullpen. Preserve the existing
BULLPEN_HOME and HOME precedence.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 3eddbcb6-e7df-4bbf-a058-0027fd8bd419
📒 Files selected for processing (6)
ARCHITECTURE.mdREADME.mdcrates/auth/src/lib.rscrates/cli/src/bg.rscrates/cli/src/main.rscrates/store/src/lib.rs
Every bullpen process wrote to the one
~/.bullpen. There was no way to run ademo, an end-to-end test, or a second copy of bullpen without it sharing
sessions, credentials, and background logs with the real one — the README's own
recorded demo had to work around it, and a script wanting a scratch store had
nothing to set.
BULLPEN_HOMEis that switch.Decisions a reviewer would otherwise have to reverse-engineer
Scope is the directory, not the database. The store,
auth.json, and thebackground logs all move together and land directly in
$BULLPEN_HOMEwith no.bullpensegment appended. Issue #8 names only the db and auth.json, butlogs/is the third occupant of the same directory and its filenames aresession ids from that database. Relocating the db while logs stayed under
$HOMEwould produce logs keyed to sessions living somewhere else — preciselythe split-brain a single-directory concept exists to prevent.
Empty counts as unset.
env::var_osreturnsSome("")forBULLPEN_HOME=.Taken literally that resolves the store to a bare relative
bullpen.dbinwhatever directory the process happened to start in — a silent relocation of
someone's existing sessions, which is the one failure this change must not
introduce.
The resolver is duplicated on purpose.
bullpen-storeandbullpen-authare siblings: neither depends on the other, both depend only on
bullpen-llm,so there is no existing crate to share from, and pushing a state-directory
concern down into
bullpen-llmwould be the wrong home for it. A newone-function workspace crate is not worth its manifest. Each crate carries its
own private
resolve_homeand its own fallback test, so a divergencebetween the two copies fails CI rather than quietly relocating one of the two
files.
cli::bgcalls the store's publichome_dir()rather than adding athird copy. Worth revisiting if a fourth caller appears.
Why the tests target a pure function instead of setting env vars. Edition
2024 (toolchain pinned 1.97.1) makes
std::env::set_varunsafe, andcargo testruns a binary's tests multi-threaded in one process — a test that mutatedHOMEorBULLPEN_HOMEwould race every other test alongside it. Soresolve_home(Option<OsString>, Option<PathBuf>)takes the env values asarguments and
home_dir()is a thin wrapper that reads the processenvironment. This matches the existing convention in this repo (
status::derivevs
for_session,CodexCliBorrow::newvsdefault_path).The issue asked for a test pinning the unset fallback so a future refactor
cannot silently relocate existing sessions; that is
unset_bullpen_home_still_resolves_under_dot_bullpen, present in both crates,and it also pins the pre-existing no-
$HOMErelative fallback.Not in scope
Not a rename, not a migration, no
--storeflag. Nothing on disk moves, andwith the variable unset every path is byte-for-byte what it is on
main.Verification
cargo fmt --all --check— clean.cargo clippy --workspace --all-targets -- -D warnings— clean.cargo test --workspace— 98 passed, 0 failed (was 94; the +4 are the newtests, +2 store, +2 auth). No existing test needed modification.
env-reading
home_dir()wrapper uncovered:BULLPEN_HOME=<tmp> bullpen sessions --jsoncreated<tmp>/bullpen.dbwithno
.bullpensegment; the same command with the variable unset still read thepre-existing
~/.bullpen/bullpen.dband returned its real sessions.Refs #8
Summary by CodeRabbit
New Features
BULLPEN_HOME.~/.bullpen, or./.bullpenwhen the home directory is unavailable.Documentation