-
Notifications
You must be signed in to change notification settings - Fork 5
fix(daemon): reject projectless watch roots #559
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -184,23 +184,31 @@ fn proxy_serve_handshake( | |
| let path = sanitize_serve_path_arg(path_arg); | ||
| let explicit_path = path.is_some(); | ||
| let mut project_path = if explicit_path { | ||
| crate::config::resolve_path(path) | ||
| Some(crate::config::resolve_path(path)) | ||
| } else { | ||
| crate::config::resolve_path_with_discovery(None) | ||
| original_cwd.and_then(crate::config::discover_project_root) | ||
| }; | ||
|
Comment on lines
188
to
190
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Using only synchronous filesystem discovery makes an initialized profile-sharded project invisible when its local enrollment marker is missing but its store remains resolvable through the global registry—a supported state handled by Useful? React with 👍 / 👎. |
||
|
|
||
| let initialized = TraceDecay::is_initialized(&project_path); | ||
| let auto_init_root = (!initialized && crate::config::load_sync_config(&project_path).auto_init) | ||
| .then(|| crate::worktree::git_worktree_root(&project_path)) | ||
| .flatten(); | ||
| let initialized = project_path | ||
| .as_deref() | ||
| .is_some_and(TraceDecay::is_initialized); | ||
| let auto_init_candidate = project_path.as_deref().or(original_cwd); | ||
| let auto_init_root = auto_init_candidate | ||
| .filter(|candidate| !initialized && crate::config::load_sync_config(candidate).auto_init) | ||
| .and_then(crate::worktree::git_worktree_root); | ||
|
Comment on lines
+195
to
+198
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When discovery-mode Useful? React with 👍 / 👎. |
||
| if let Some(root) = auto_init_root.as_ref() { | ||
| project_path.clone_from(root); | ||
| project_path = Some(root.clone()); | ||
| } | ||
|
|
||
| let scope_prefix = serve_scope_prefix(original_cwd, &project_path); | ||
| let telemetry_timings = timings || crate::config::load_telemetry_config(&project_path).timings; | ||
| let scope_prefix = project_path | ||
| .as_deref() | ||
| .and_then(|project_path| serve_scope_prefix(original_cwd, project_path)); | ||
| let telemetry_timings = timings | ||
| || project_path | ||
| .as_deref() | ||
| .is_some_and(|path| crate::config::load_telemetry_config(path).timings); | ||
|
Comment on lines
+206
to
+209
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For a projectless CWD that is later routed to a real project through MCP Useful? React with 👍 / 👎. |
||
| let mut handshake = crate::daemon::DaemonHandshake::for_current_client( | ||
| Some(project_path), | ||
| project_path, | ||
| scope_prefix, | ||
| telemetry_timings, | ||
| auto_init_root.is_some(), | ||
|
|
@@ -234,6 +242,19 @@ pub const DEGRADED_SERVE_STDERR_MARKER: &str = | |
| mod tests { | ||
| use super::*; | ||
|
|
||
| #[test] | ||
| fn projectless_cwd_does_not_become_a_daemon_project() { | ||
| let _profile = crate::config::PinnedUserDataDir::new(); | ||
| let cwd = tempfile::tempdir().unwrap(); | ||
|
|
||
| let handshake = proxy_serve_handshake(None, Some(cwd.path()), false) | ||
| .expect("build projectless proxy handshake"); | ||
|
|
||
| assert_eq!(handshake.project_path, None); | ||
| assert!(!handshake.allow_init); | ||
| assert!(handshake.allow_initialize_root_routing); | ||
| } | ||
|
|
||
| #[tokio::test] | ||
| async fn direct_project_open_fails_closed() { | ||
| let path = Path::new("/tmp/tracedecay-direct-open-must-not-run"); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code_projects_seen_within(window, cap)applies its SQLLIMITbefore these new validity checks, so recent stale or projectless rows still consume the entire watcher budget. If the newestwatch_max_projectsrows are invalid, initialized Git projects that are only slightly older are never examined or watched after daemon startup, even though no watcher slots were actually used. Fetch enough candidates to fill the cap after filtering, or move equivalent validity filtering ahead of the limit.Useful? React with 👍 / 👎.