feat(gain): add per-project token savings with -p flag#128
feat(gain): add per-project token savings with -p flag#128heAdz0r wants to merge 2 commits intortk-ai:masterfrom
Conversation
| /// | ||
| /// When `project_path` is `Some`, matches the exact working directory | ||
| /// or any subdirectory (prefix match with path separator). | ||
| pub fn get_summary_filtered(&self, project_path: Option<&str>) -> Result<GainSummary> { |
There was a problem hiding this comment.
LIKE ?2 without a trailing % wildcard is an exact match — subdirectory prefix matching doesn't work. project_path LIKE '/home/user/project/' will never match /home/user/project/src.
Fix: Some(format!("{}{}%", p, std::path::MAIN_SEPARATOR))
But then _ and % in path names become LIKE wildcards (e.g. my_project matches myXproject). Consider using GLOB instead of LIKE, or add an ESCAPE clause.
src/tracking.rs
Outdated
| let _ = conn.execute("ALTER TABLE commands ADD COLUMN project_path TEXT", []); | ||
| // Normalize NULL values for pre-project-aware rows // added | ||
| let _ = conn.execute( | ||
| "UPDATE commands SET project_path = '' WHERE project_path IS NULL", |
There was a problem hiding this comment.
The UPDATE commands SET project_path = '' WHERE project_path IS NULL in Tracker::new() runs on every startup, not just once. After the first migration it's a no-op query on every
command invocation. Consider wrapping it in a schema version check or checking if the column already has a default.
Address reviewer feedback on PR rtk-ai#128: 1. Replace SQL LIKE with GLOB in all project-scoped queries to prevent `_` and `%` characters in path names from being interpreted as wildcards (e.g., `my_project` matching `myXproject`). GLOB uses `*` for wildcard matching which is safer for file system paths. 2. Guard the startup `UPDATE commands SET project_path = ''` migration with an `EXISTS` check so it only runs when NULL rows actually exist, avoiding a no-op UPDATE on every startup after the first migration. 3. Add `DEFAULT ''` to the ALTER TABLE migration so new installs never create NULL project_path values. 4. Add 3 new unit tests for project_filter_params GLOB behavior. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Record project_path (cwd) in tracking database and add filtered query methods. `rtk gain -p` shows savings scoped to the current project directory instead of global aggregates. - tracking.rs: Add project_path column with auto-migration, index, and filtered variants for all query methods (summary, daily, weekly, monthly, recent) - gain.rs: Add resolve_project_scope(), shorten_path(), scope-aware header, pass project filter to all queries and exports - main.rs: Add --project/-p flag to Gain command Backward-compatible: existing rows get empty project_path, unfiltered queries delegate to filtered(None) which returns all data. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Address reviewer feedback on PR rtk-ai#128: 1. Replace SQL LIKE with GLOB in all project-scoped queries to prevent `_` and `%` characters in path names from being interpreted as wildcards (e.g., `my_project` matching `myXproject`). GLOB uses `*` for wildcard matching which is safer for file system paths. 2. Guard the startup `UPDATE commands SET project_path = ''` migration with an `EXISTS` check so it only runs when NULL rows actually exist, avoiding a no-op UPDATE on every startup after the first migration. 3. Add `DEFAULT ''` to the ALTER TABLE migration so new installs never create NULL project_path values. 4. Add 3 new unit tests for project_filter_params GLOB behavior. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
722e053 to
172099f
Compare
|
@pszymkowiak Both issues have been addressed and the branch has been rebased on latest master (conflicts resolved): 1. LIKE without trailing wildcard — Fixed in commit 722e053. Replaced
2. UPDATE on every startup — The UPDATE is now guarded by Additionally, the Branch rebased cleanly on master (merged dashboard viz from #129). Ready for re-review. |
Summary
Adds per-project scoping to
rtk gainso users can see token savings for the current project instead of global aggregates.Problem: Users working on multiple projects see combined statistics in
rtk gain. There's no way to answer "how much does rtk save in this project?"Solution:
rtk gain -pfilters all statistics to the current working directory (and subdirectories).Usage
Implementation Details
Files Changed
src/tracking.rssrc/gain.rssrc/main.rs--project/-pClap flagTotal: 215 lines added, 50 lines modified
tracking.rs
project_path TEXTcolumn viaALTER TABLE(idempotent, backward-compatible)current_project_path_string()captures canonical cwd on every command executionidx_project_path_timestampfor fast project-scoped queries_filtered(project_path: Option<&str>)variants:get_summary_filtered()get_all_days_filtered()get_by_week_filtered()get_by_month_filtered()get_recent_filtered()WHERE (?1 IS NULL OR project_path = ?1 OR project_path LIKE ?2)— exact match + subdirectory prefix match_filtered(None)(zero behavior change)gain.rs
resolve_project_scope(): Resolves--projectflag to canonical cwd pathshorten_path(): Abbreviates long paths for display (/Users/foo/bar/project→/.../bar/project)Backward Compatibility
rtk gainwithout-pbehaves identically (filtered withNonereturns all rows).Security Compliance
Critical files check
src/tracking.rsis a critical file (persecurity-check.yml)std::env::current_dir(), not CLI argumentsVerification
cargo build— compiles cleancargo clippy— no errorscargo test tracking— 7 passed, 1 pre-existing failure (unrelatedtest_default_db_path)cargo fmt— formatted🤖 Generated with Claude Code