track everything in jb ides#672
Merged
svarlamov merged 7 commits intogit-ai-project:mainfrom Mar 16, 2026
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix false-positive AI attribution in IntelliJ plugin sweep checkpoints
Problem
The sweep checkpoint mechanism incorrectly attributes human edits to AI agents. When Copilot or Junie edits a file, the plugin "tags" that file in an
agentTouchedFilesmap. The original implementation then watched for any subsequentdocumentChangedevent on that file where the stack trace didn't contain the AI agent's packages -- and treated the content delta as an AI-attributable change.The flaw:
documentChangedfires for every content modification to the in-memory document, regardless of source. Human typing, IDE refactoring, VCS operations, and format-on-save all trigger it. None of these carry AI agent packages in their stack traces. So after an AI agent touches a file, every human keystroke in that file gets checkpointed astype: "ai_agent"until the tracking entry expires.Root cause
A single
BulkAwareDocumentListenerwas serving two fundamentally different detection roles:documentChangedcallbackThe
documentChangedcallback has no built-in mechanism to tell you why the content changed. It only tells you what changed.Solution
Separate the two detection roles into distinct IntelliJ event listeners, each using the correct event source:
DocumentChangeListenerhandles role 1: stack-trace-based AI detection for in-memory edits. When no AI agent is detected, it does nothing (guard clause returns early). It never triggers sweep checkpoints.VfsRefreshListener(new) handles role 2: implementsBulkFileListener, which fires on VFS-level events. It filters forVFileContentChangeEventwhereisFromRefresh == true-- meaning the change originated from a disk scan, not from an in-process write. It cross-references againstagentTouchedFilesand triggers sweep checkpoints only for tracked files whose disk content differs from the last checkpoint.The
isFromRefreshproperty is the key discriminator. IntelliJ's VFS distinguishes between:isFromRefresh == false): document saves, VFS API writes, IDE refactoringisFromRefresh == true): another process wrote to the file and IntelliJ detected it during a VFS refreshHuman typing never produces a
BulkFileListenerevent at all -- it only modifies the in-memory Document model. Auto-save producesisFromRefresh == false. Only actual external disk writes produceisFromRefresh == true.Architecture
DocumentChangeTrackerServiceis the coordinator. It owns the shared state and injects it into both listeners via constructor:Neither listener knows about the other. Adding a third detection mechanism would be another constructor injection.
What this eliminates
*External non-AI disk writes to a tracked file remain a false positive because the file system doesn't record which process performed a write. This is unsolvable at the application level without OS-level auditing. In practice it requires a human to externally edit the exact same file an AI recently touched, within the 5-minute staleness window.
Additional changes
StackTraceAnalyzer: Fixed frame collection to only include frames for the first detected agent. Previously, if two agents' packages both appeared in a stack trace (theoretically possible with future agent additions), frames from both would be collected inrelevantFrameseven though only one agent is reported.Dead code removal: Removed a no-op
contentBeforeconditional block inexecuteAfterEditCheckpointthat checked for content changes but had an empty body.toRelativePathextracted: Moved to a package-level function inTrackedAgent.ktsince both listeners need it (was previously a private method onDocumentChangeListener).Resource lifecycle:
DocumentChangeTrackerService.dispose()now callsscheduler.shutdownNow()for clean shutdown. The message bus connection and editor factory listener both use the service'sDisposablefor automatic cleanup.Files
listener/TrackedAgent.ktTrackedAgentdata class +toRelativePath()listener/VfsRefreshListener.ktBulkFileListenerwithisFromRefreshfilteringlistener/DocumentChangeListener.ktlistener/StackTraceAnalyzer.ktservices/DocumentChangeTrackerService.kt