feat(app): implement AppConfig for filesystem layout resolution#19
feat(app): implement AppConfig for filesystem layout resolution#19
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (4)
✅ Files skipped from review due to trivial changes (3)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughA new ChangesConfiguration Module & Public API
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Review rate limit: 3/5 reviews remaining, refill in 18 minutes and 58 seconds. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@CHANGELOG.md`:
- Line 14: Update the changelog bullet that documents tests for AppConfig to
reflect the actual test count: change the “8 tests” mention to “6 tests” so it
matches the final test module in src-tauri/src/config.rs (the AppConfig test
module) and the note on Line [9] that already documents the 8→6 dedupe; ensure
the sentence still references AppConfig, resolve_project_root(),
AppConfig::load()/AppConfig::new(), and the use of tempfile + temp-env.
🪄 Autofix (Beta)
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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: acfd9557-a492-473c-9f01-3afaf0a0e2da
⛔ Files ignored due to path filters (1)
src-tauri/Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (6)
CHANGELOG.mdsrc-tauri/Cargo.tomlsrc-tauri/src/config.rssrc-tauri/src/domain/shared/error.rssrc-tauri/src/error.rssrc-tauri/src/lib.rs
There was a problem hiding this comment.
2 issues found across 7 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src-tauri/src/config.rs">
<violation number="1" location="src-tauri/src/config.rs:42">
P2: Do not swallow non-UTF8 `FORGENT_PROJECT_ROOT` values as if the variable were unset; handle `NotPresent` and `NotUnicode` separately so invalid config fails explicitly.</violation>
</file>
<file name="CHANGELOG.md">
<violation number="1" location="CHANGELOG.md:14">
P3: Update the `AppConfig` changelog bullet to reflect the current test count; it currently contradicts the new simplification note (6 tests vs 8 tests).</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Address PR #19 review: - cubic-dev-ai @ config.rs:42 — `std::env::var()` returns `Err(VarError::NotUnicode(_))` when the env var is set but contains non-UTF-8 bytes (legal on Unix filesystems). The old `Err(_)` arm silently fell back to CWD, swallowing user-set config. Switched to `std::env::var_os()` which returns the raw `OsString`, so explicit signal is preserved and non-UTF-8 paths work natively. Added `#[cfg(unix)]` regression test using `OsStringExt::from_vec` with `0xFF 0xFE` bytes. - coderabbitai + cubic-dev-ai @ CHANGELOG.md:14 — bullet said "8 tests" but the simplify pass deduped to 6 and this commit adds the non-UTF-8 test → 7. Updated the count.
…sk T-103)
`AppConfig` resolves Forgent's filesystem layout once at boot (PRD §0.3):
- per-project: `<root>/.claude/forgent/{tasks.db,prompts/}`
- per-user: `~/.forgent/{logs,cache}` via `dirs::home_dir()`
Three entry points:
- `AppConfig::load()` — reads env then CWD (production path)
- `AppConfig::new(project_root)` — validates + builds (testable directly)
- `resolve_project_root()` — `FORGENT_PROJECT_ROOT` env override → CWD fallback
Validates `project_root.is_dir()` else `AppError::Invalid`. Will be consumed
by `filesystem::paths::ensure_dirs` (T-104), tracing (T-105), libsql (T-106),
and `AppContainer::build` (T-116).
Tests use `tempfile` + `temp-env` (encapsulates `unsafe` env mutation that
Rust 2024 edition would otherwise force — CLAUDE.md forbids `unsafe` outside
ADRs). 8 unit tests, all green.
One deviation from the T-103 task spec, documented in CHANGELOG:
`AppConfig::load(app_handle: &tauri::AppHandle)` → `AppConfig::load()`. The
illustrative `AppHandle` param was never used in the body — per-user paths
come from `dirs::home_dir()`, not `app.path()`. Keeping it would force a
`tauri::test::MockRuntime` harness for zero functional gain.
Refs: T-103, ARCHI.md §5.5, PRD §0.3
…tests, reuse io::Error From impl - Module doc 9 → 1 line; removed T-104/T-105/T-106/T-116 task references (CLAUDE.md "no task references in comments"). - `resolve_project_root` uses existing `From<std::io::Error>` via `.map_err(Into::into)` (the impl already lives in `error.rs`; hand-rolled `AppError::Io(e.to_string())` was redundant). - Deleted `paths_use_pathbuf_join_cross_platform` — covered by `new_returns_ok_for_valid_tempdir`. - Deleted `load_with_env_override_to_tempdir_succeeds` — `load()` is just `Self::new(resolve_project_root()?)`, both legs independently tested. 8 → 6 tests, identical coverage; cargo test --workspace 23 → 21 (4 suites green).
Address PR #19 review: - cubic-dev-ai @ config.rs:42 — `std::env::var()` returns `Err(VarError::NotUnicode(_))` when the env var is set but contains non-UTF-8 bytes (legal on Unix filesystems). The old `Err(_)` arm silently fell back to CWD, swallowing user-set config. Switched to `std::env::var_os()` which returns the raw `OsString`, so explicit signal is preserved and non-UTF-8 paths work natively. Added `#[cfg(unix)]` regression test using `OsStringExt::from_vec` with `0xFF 0xFE` bytes. - coderabbitai + cubic-dev-ai @ CHANGELOG.md:14 — bullet said "8 tests" but the simplify pass deduped to 6 and this commit adds the non-UTF-8 test → 7. Updated the count.
1561f47 to
8537a1a
Compare
Summary
Implements
AppConfigstruct + boot-time path resolution (T-103). Resolves Forgent's filesystem layout once at startup — per-project paths (<root>/.claude/forgent/{tasks.db,prompts/}) + per-user paths (~/.forgent/{logs,cache}). Supports env overrideFORGENT_PROJECT_ROOTwith CWD fallback.This PR is part of Sprint 1 backend foundations and stacks on T-102 (AppError types). Both are required for
AppContainer::build(T-116).Why
Path resolution must happen once at boot before any I/O operations. Centralizing this in
AppConfigensures consistent layout across the codebase and enables testability (configs built with explicit paths rather than env vars during tests).Changes
T-102 (included as prerequisite):
AppError+DomainErrorerror types (thiserror + serde for IPC boundary)T-103 (primary):
src-tauri/src/config.rswithAppConfigstruct (5 PathBuf fields: project_root, db_path, logs_dir, cache_dir, prompts_overrides_dir)AppConfig::load()— production entry point, reads env then CWDAppConfig::new(project_root)— testable constructor with validationresolve_project_root()— envFORGENT_PROJECT_ROOToverride → CWD fallbackproject_root.is_dir()elseAppError::Invaliddirs::home_dir()for cross-platform per-user paths (Linux XDG / macOS NSHome / Windows USERPROFILE)tempfile+temp-env(safe env mutation withoutunsafe)tempfile,temp-envFollow-up cleanup (/simplify):
From<std::io::Error>impl via.map_err(Into::into)Testing
Cargo test suite — 23 tests across 4 suites pass:
Specific config tests:
new_returns_ok_for_valid_tempdir— valid temp dir acceptednew_rejects_non_existent_project_root— missing dir rejected withAppError::Invalidnew_rejects_file_instead_of_directory— file path rejectedresolve_project_root_honors_env_override—FORGENT_PROJECT_ROOTenv var usedresolve_project_root_falls_back_to_cwd_when_env_unset— CWD fallbackapp_config_is_send_sync_clone— trait bounds verifiedRelated Issues
Notes for Reviewer
This is a stacked PR containing both T-102 and T-103 commits. T-102 (
feat(domain): add AppError + DomainError) should ideally be reviewed/merged as a separate PR first, but both are included here due to the branch dependency. If preferred, they can be split — T-102 commits can land separately, then T-103 rebased.The key validation point:
AppConfig::newvalidatesproject_root.is_dir()at boot time for fast-fail diagnostics, not as a TOCTOU security boundary (the real use — libsql/ensure_dirs — happen afterward and handle errors independently).Checklist
Summary by CodeRabbit
New Features
Documentation
Chores