Skip to content

refactor(gemini): PathResolver::new takes a required home argument - #206

Open
ecalifornica wants to merge 11 commits into
robert/config-cleanupfrom
robert/config-gemini
Open

refactor(gemini): PathResolver::new takes a required home argument#206
ecalifornica wants to merge 11 commits into
robert/config-cleanupfrom
robert/config-gemini

Conversation

@ecalifornica

@ecalifornica ecalifornica commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

Part of #185: the crate reads no environment variable, Config owns every read, and the caller supplies what the crate used to resolve itself.

PathResolver::new(home) takes the home directory as a required argument. The crate keeps the layout knowledge (<home>/.gemini); the caller owns "what is home". With the home always present, the pure path accessors drop their Result and the Default impls go with them.

Judgment calls:

  • A required argument, not Option<home> and not a kept default. A resolver with no home has no meaningful paths, so representing that state inside the crate re-creates the Result accessors. The absent-home state lives in the CLI instead, where "harness out of reach" is a real condition with a real error message.
  • A missing home degrades differently by surface: providers::gemini_resolver returns Option<PathResolver>, the harness bundle silently omits Gemini, and the 5 commands that target Gemini error through require_gemini_resolver. This is a behavior decision, not part of the mechanical refactor.

The change is breaking for toolpath-gemini and bumps it to 0.7.0. The CHANGELOG lists the affected API.

@ecalifornica ecalifornica changed the title robert/config gemini refactor(gemini): PathResolver::new(home), a required home argument Aug 13, 2026
@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown

🔍 Preview deployed: https://c13b461d.toolpath.pages.dev

@ecalifornica
ecalifornica force-pushed the robert/config-gemini branch 2 times, most recently from 2eba22f to 8929e4f Compare August 14, 2026 13:13
@ecalifornica ecalifornica changed the title refactor(gemini): PathResolver::new(home), a required home argument refactor(gemini): PathResolver::new takes a required home argument Aug 14, 2026
@ecalifornica
ecalifornica marked this pull request as ready for review August 17, 2026 17:05
@ecalifornica
ecalifornica requested a review from akesling August 17, 2026 17:05
@ecalifornica ecalifornica assigned akesling and unassigned akesling Aug 17, 2026
cmd_cache and cmd_query resolve the config directory once and build
the HarnessBundle through providers::harness_bundle. The manifest
layer takes config_dir; manifest_path is infallible. The transitional
record surfaces load Config and resolve the directory per call.
The share command receives `&Config` from run() and passes it down:
the harness bundle, the derive helpers, the manifest record surfaces,
and the configured-remote lookup.

- `cmd_share::run` takes `&Config`. `share_explicit`,
  `derive_session`, and `resolve_destination` take it as a parameter.
- The picker bundle and the freshness-stat bundle come from
  `providers::harness_bundle(config)`.
- `sync::fresh_cache_id` takes `&Config`. It is the last record
  surface that loaded one per call.
- `share_config::resolve_remote` takes `&Config` and resolves the
  config file through `Config::config_dir`.
- `HarnessBundle::from_environment` is deleted. Share was its last
  caller.
`resolve_url` takes `&Config` and reads `$PATHBASE_URL` from it.
`credentials_path` and `preflight_auth` take `&Config` and resolve the
config directory through `Config::config_dir`. `cmd_pathbase` reads no
environment variable.

`run()` passes `&Config` to `cmd_auth`. The Pathbase call sites in
`cmd_import`, `cmd_export`, and `cmd_share` pass the `&Config` they
already hold.

Precedence is unchanged: `--url`, then `$PATHBASE_URL`, then
https://pathbase.dev.
`resume` receives `&Config` from run() and passes it to the input
resolver and the projectors. The transitional `Config::load()` calls
in `run_with_strategy` and `resolve_input` are gone.

- `cmd_resume::run`, `run_with_strategy`, and `resolve_input` take
  `&Config`. The Pathbase fetch calls
  `derive::pathbase_fetch_to_doc(config, …)`.
- `Config` is public and `config` is a public module.
  `run_with_strategy` is the public entry point for
  `tests/resume.rs`, so its parameter type must be nameable there.
  The public items are `#[doc(hidden)]` and the fields stay
  crate-private; `Config::load` is the only constructor outside the
  crate.
- The `$PATH` read for the harness binary lookup stays. A binary
  lookup is execution environment, not configuration.
- The `project_into_harness` unit test injects a `Config` rooted at
  a tempdir. The `run_with_strategy` unit test does the same and
  keeps the `$PATH` guard.
- The `resolve_input` unit tests inject a `Config`. The Pathbase
  fetch test needs no environment guard. The cache-hit test and the
  unresolvable-input test still set `$TOOLPATH_CONFIG_DIR`, because
  `cache.rs` reads it.
- `ScopedHomeForResume` is deleted. The unit tests set no `$HOME`.
- `ScopedHome::config` gives the integration tests the `Config` the
  CLI extracts at its composition root.
Every `cache.rs` function takes `&Config` and resolves the documents
directory through `Config::config_dir`. The cache reads no environment
variable.

- `cache_dir`, `cache_path`, `write_cached`, `cache_ref`, `list_cached`,
  and `remove_cached` take `&Config` as their first parameter.
  `make_id` and `pathbase_cache_id` are pure and unchanged.
- Every call site passes the `&Config` it already holds. `cmd_export`'s
  `load_path_doc` and its three session builders take `&Config`;
  `query::run`, `stream_files`, and `select_files` take one;
  `sync::engine::is_unchanged` takes one.
- `p derive` still loads a transitional `Config` and hands it to
  `cmd_import`. The cleanup PR owns that load.
- The free `config_dir()` in `config.rs` had no caller left, so it is
  deleted along with the test that drove it.
- The `cache.rs` unit tests inject a `Config` rooted at a tempdir. They
  set no environment variable and take no `TEST_ENV_LOCK`.
…n root (#184)

Delete the free `home_dir()` from config.rs. Its two callers take a
`&Config` already: `cmd_share::bail_no_sessions` and
`share_config::resolve_remote` now use `Config::home_dir()`.

Thread `&Config` into `p derive` and delete its transitional
`Config::load()`. `Config::load()` runs once, in `run()`.

Test cleanup:
- `sync::engine::tests::with_cfg` builds a `Config` only. It drops the
  `$TOOLPATH_CONFIG_DIR` write and the `TEST_ENV_LOCK` hold.
- Two `cmd_resume` tests drop their `$TOOLPATH_CONFIG_DIR` write and
  their `TEST_ENV_LOCK` hold.

`$PATH` is the only variable read below the root. It is the execution
environment, not configuration.
)

toolpath-gemini reads no environment variable. The caller supplies the
home directory; the crate keeps the layout below it (`<home>/.gemini`).

Library (breaking, 0.7.0):

- `PathResolver::new(home)` takes the home directory as a required
  argument. `GeminiConvo::new(home)` and `ConvoIO::new(home)` take the
  same argument.
- Delete the `Default` impls on the three types, `with_home`, the
  private `dirs::home_dir` helper, and the `NoHomeDirectory` error
  variant.
- Keep `with_gemini_dir` as the full override.
- The home directory is always present, so `home_dir()`,
  `gemini_dir()`, `projects_file()`, `tmp_dir()`, and
  `ConvoIO::gemini_dir_path()` return a path, not a `Result`. Callers
  inside the crate drop the dead error arms.

path-cli:

- `providers::gemini_resolver` returns `Option<PathResolver>`. `None`
  means `Config` carries no home directory, so Gemini is out of reach.
- `harness_bundle` omits the Gemini manager in that case.
- `providers::require_gemini_resolver` reports "cannot determine the
  home directory" for the 5 commands that target Gemini.

Version bump per the release checklist: crate manifest, workspace
dependency, site/_data/crates.json, CHANGELOG.md.
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.

2 participants