Cover command modes and transport attribution - #2144
Conversation
47e7bcd to
305c0a5
Compare
305c0a5 to
1c0b886
Compare
1c0b886 to
3eac28f
Compare
3eac28f to
115d7e2
Compare
119bcfb to
d0d0953
Compare
d0d0953 to
4d6c975
Compare
4d6c975 to
9713c76
Compare
9713c76 to
6563217
Compare
6563217 to
127b85a
Compare
a6bfe16 to
2ad4e8a
Compare
14c8d19 to
9d577da
Compare
ffca72f to
70ae342
Compare
c220de8 to
aee77dd
Compare
aee77dd to
a0af056
Compare
a0af056 to
7a397eb
Compare
7a397eb to
cd4a928
Compare
| fn capture_index_snapshot_for_workspace_command(worktree: &Path) -> Option<String> { | ||
| let git_dir = git_dir_for_worktree(worktree)?; | ||
| sweep_stale_index_snapshots(&git_dir); | ||
| let index = git_dir.join("index"); | ||
| if !index.is_file() { | ||
| return None; | ||
| } | ||
| // Git updates the index by atomically replacing its directory entry. A | ||
| // hard link retains the pre-command inode in O(1) without reading index | ||
| // contents, taking an index lock, spawning Git, or writing objects. | ||
| let created_at_ms = SystemTime::now() | ||
| .duration_since(UNIX_EPOCH) | ||
| .ok()? | ||
| .as_millis(); | ||
| for _ in 0..4 { | ||
| let snapshot_path = git_dir.join(format!( | ||
| "{INDEX_SNAPSHOT_PREFIX}{created_at_ms}-{}", | ||
| crate::uuid::generate_v4() | ||
| )); | ||
| match fs::hard_link(&index, &snapshot_path) { | ||
| Ok(()) => return Some(snapshot_path.to_string_lossy().into_owned()), | ||
| Err(error) if error.kind() == std::io::ErrorKind::AlreadyExists => continue, | ||
| Err(_) => return None, | ||
| } | ||
| } | ||
| None | ||
| } |
There was a problem hiding this comment.
🟡 Every removal command makes the daemon scan the whole repository metadata directory before git can continue
The daemon lists every entry in the repository's internal git directory and creates a link file (sweep_stale_index_snapshots at src/daemon.rs:859) while it is still receiving live data from the running command, adding unbounded directory work to a path documented as sub-millisecond sensitive.
Impact: Repositories with many files in their git directory add measurable delay to each removal command and to trace processing for all repositories.
Non-constant-time filesystem work added to trace ingestion
capture_index_snapshot_for_workspace_command (src/daemon.rs:857-883) is invoked from track_trace_payload_for_ingest while the trace_ingress_state mutex is held and on the trace socket listener thread. It performs git_dir_for_worktree, a full fs::read_dir of the git directory with a parse/stat per matching entry, an is_file check, and a hard_link. If the link fails (for example the index is missing) the guard !ingress.root_index_snapshot_at_start.contains_key(&root) means the sweep is retried on every subsequent non-terminal event of the same root.
The adjacent pathspec capture also reaches the filesystem on this path: workspace_pathspecs_from_command_dir (src/daemon.rs:1966-2015) canonicalizes two paths and, via restore_pathspecs, reads the --pathspec-from-file file from disk (src/daemon.rs:1745) — and it does so even for git rm --cached, whose result is never used because the analyzer emits OpaqueCommand for that mode.
AGENTS.md rule 2 explicitly says "even additional file reads have meaningful overhead on this path", and rule 3 forbids non-constant-time work. The sweep should run out of band (e.g. on the daemon's existing sweep/maintenance path) rather than per ingested rm event.
Prompt for agents
capture_index_snapshot_for_workspace_command in src/daemon.rs runs on the trace2 ingestion listener thread while the trace_ingress_state mutex is held. It calls sweep_stale_index_snapshots, which does a full fs::read_dir of the repository git directory (plus a filename parse per entry) before every snapshot capture, and it is retried on each subsequent root event when the capture fails. AGENTS.md forbids adding non-constant-time work and extra file reads on this path. Move the stale-snapshot sweep to an out-of-band maintenance path (the daemon already has sweep_coordinator / periodic sweeps) and keep only the O(1) hard_link on the ingest path. Also consider skipping workspace_pathspecs_from_command_dir entirely for `git rm --cached`, since the analyzer emits OpaqueCommand for that mode and the resolved pathspecs (which involve canonicalize calls and reading a --pathspec-from-file file from disk) are never used.
Was this helpful? React with 👍 or 👎 to provide feedback.
| pathspecs.iter().any(|pathspec| { | ||
| file == pathspec | ||
| pathspec == "." | ||
| || file == pathspec |
There was a problem hiding this comment.
🟡 Restoring or checking out files from a subfolder wipes AI authorship for the entire project
A selection of "." is now treated as matching every file in the repository (matches_any_pathspec at src/daemon.rs:991), so restoring or checking out the current folder discards the recorded authorship of files everywhere else in the project.
Impact: Running git restore . or git checkout -- . inside a subfolder silently loses pending AI attribution for unrelated files in other folders.
Shared pathspec matcher is used with un-rooted operands
The new pathspec == "." short-circuit makes matches_any_pathspec return true for every candidate. It is intended for the clean/rm flow, where workspace_pathspecs_from_command_dir (src/daemon.rs:1968-2029) has already re-rooted operands against the worktree, so "." only appears for a worktree-root invocation.
But the same helper is used by remove_working_log_attributions_for_pathspecs (src/daemon.rs:1603 and src/daemon.rs:1622), which is fed raw, un-rooted operands: restore_pathspecs(&parsed.command_args, ...) for restore (src/daemon.rs:1805) and parsed.pathspecs() for checkout (src/daemon.rs:1834). A literal "." typed in a subdirectory therefore prunes every file in the working log instead of only the subtree Git actually restored. Before this change "." matched nothing there.
Prompt for agents
matches_any_pathspec in src/daemon.rs gained a `pathspec == "."` case that makes it match every candidate path. That is correct for the clean/rm flow, where workspace_pathspecs_from_command_dir already re-roots operands relative to the worktree and only emits "." for a worktree-root invocation. However the same helper is shared with remove_working_log_attributions_for_pathspecs, which is called from apply_checkout_switch_working_log_side_effect with RAW operands taken straight from the command line (restore_pathspecs / parsed.pathspecs()). Those operands are relative to the invocation directory, so `git restore .` or `git checkout -- .` executed inside a subdirectory now prunes working-log attributions for the whole repository instead of just that subtree.
Consider either scoping the "." wildcard semantics to the already-rooted clean/rm call sites (e.g. a separate matcher or an explicit flag), or re-rooting the restore/checkout operands against the worktree the same way workspace_pathspecs_from_command_dir does before matching.
Was this helpful? React with 👍 or 👎 to provide feedback.
Uh oh!
There was an error while loading. Please reload this page.