Skip to content

feat(discovery): honor CCB_PROJECT_DIR env var for project anchor lookup#190

Open
SevenX77 wants to merge 2 commits intobfly123:mainfrom
SevenX77:feature/ccb-project-dir-env-var
Open

feat(discovery): honor CCB_PROJECT_DIR env var for project anchor lookup#190
SevenX77 wants to merge 2 commits intobfly123:mainfrom
SevenX77:feature/ccb-project-dir-env-var

Conversation

@SevenX77
Copy link
Copy Markdown

Motivation

find_nearest_project_anchor in lib/project/discovery.py discovers the CCB project by walking the current working directory upward looking for the first .ccb/ dir. This makes CLI usage cwd-sensitive: callers that change directory between commands (shell scripts, Bash-tool-based agent harnesses, CI runners, editor integrations) can accidentally resolve to the wrong project when cwd drifts.

A concrete example: an assistant harness running ccb ask a2 ... after a cd /some/git/repo call hits unknown agent: a2 because /some/git/repo/.ccb/ccb.config uses a different agent naming scheme than the user's daily project. Today's only workaround is passing --project /path/to/project on every single invocation, which is error-prone.

Change

Add support for CCB_PROJECT_DIR environment variable:

  • Set it to a path containing .ccb/ and that path wins over the cwd-upward search.
  • If unset, empty, points to a missing path, or points to a path without .ccb/, behavior falls through to the existing cwd-upward search — no regression.

Matches the pattern of GIT_DIR, KUBECONFIG, XDG_*, etc.: let the caller pin the working target via env rather than implicit cwd.

Scope limited on purpose

  • Only find_nearest_project_anchor is changed.
  • find_parent_project_anchor_dir is not changed. That function has different semantics: it is used e.g. by test/conftest.py::_ignore_host_level_tmp_anchor to cut off the host-level .ccb/ when running pytest, and should continue walking upward unconditionally.

Tests

test/test_project_discovery_env.py — 6 new unit tests:

  1. test_env_unset_walks_cwd — absent env → preserves original behavior
  2. test_env_set_with_valid_ccb_dir_wins_over_cwd — env beats cwd
  3. test_env_set_with_path_that_has_no_ccb_dir_falls_through — graceful fallback
  4. test_env_set_with_nonexistent_path_falls_through — graceful fallback
  5. test_env_set_to_empty_string_treated_as_unset
  6. test_env_bypasses_dangerous_root_check — user explicit intent via env overrides the $HOME-as-project-root heuristic

All pass (0.25s).

Risk

Minimal. New code path is guarded by an env var that is currently unused, so existing installations and scripts are unaffected until a user opts in by exporting CCB_PROJECT_DIR.

Rollback

Single commit, revertible via git revert.

`find_nearest_project_anchor` currently discovers the project root by
walking the current working directory upward looking for the first
`.ccb/` dir. This makes CLI usage cwd-sensitive: callers that `cd`
between commands (shell scripts, Bash-tool-based agent harnesses,
CI runners) can accidentally resolve to the wrong project.

Add support for `CCB_PROJECT_DIR` environment variable. If set to a
path containing `.ccb/`, that path wins over the cwd-upward search.
If the env var is unset, empty, points to a missing path, or points
to a path without `.ccb/`, behavior falls through to the existing
cwd-upward search — no regression.

This matches the pattern of `GIT_DIR`, `KUBECONFIG`, etc., giving
callers a reliable override without relying on cwd discipline.

Does not touch `find_parent_project_anchor_dir`: that function has a
different semantics (used e.g. by `test/conftest.py` to isolate
pytest tmp from host-level `.ccb/`) and should continue walking
upward unconditionally.

Tests: 6 new unit tests in `test/test_project_discovery_env.py`
covering unset / valid / invalid / nonexistent / empty-string cases,
and the $HOME-as-project-root bypass (env is explicit intent, so
dangerous-root heuristic should not block it).
… too

Follow-up to the previous commit. `find_current_project_anchor` is the
code path used when `bootstrap_if_missing=True` (see `cli/context.py`
and `phase2_runtime/context.py`), i.e. for subcommands like `ps`,
`ask`, etc. Without env support here, a caller running from a non-
project cwd (e.g. /tmp) would still fail to resolve the project even
with `CCB_PROJECT_DIR` set, because the resolver picks
`find_current_project_anchor` over `find_nearest_project_anchor` in
bootstrap mode — and only the latter had env support.

Symmetric change, same fall-through semantics (unset / empty / invalid
env → original cwd-only behavior). Adds three unit tests for this
second entry point.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant