@@ -224,6 +224,22 @@ def _is_committed(self, root_path: str, rel_dir: str) -> bool:
224224 except FileNotFoundError :
225225 return False
226226
227+ def _is_tracked (self , root_path : str , rel_path : str ) -> bool :
228+ """Return True if rel_path is tracked in git (in the index).
229+
230+ Untracked / gitignored files are not pushed by `git push`, so flagging
231+ them as AI-context leaks would be a false positive for the publish
232+ workflow. On any git error, return True (be conservative — flag).
233+ """
234+ try :
235+ result = subprocess .run (
236+ ["git" , "-C" , root_path , "ls-files" , "--error-unmatch" , "--" , rel_path ],
237+ capture_output = True , text = True ,
238+ )
239+ return result .returncode == 0
240+ except FileNotFoundError :
241+ return True
242+
227243 # --- Discovery ---
228244
229245 def _detect_native (self ) -> Optional [str ]:
@@ -431,15 +447,20 @@ def _unified_walk(
431447 full_path = os .path .join (dirpath , d )
432448 rel_path = os .path .relpath (full_path , root_path ).replace (os .sep , "/" )
433449 dirs .remove (d )
434- if not self ._is_excluded (rel_path ):
435- findings .append (Finding (
436- severity = Severity .CRITICAL ,
437- category = FindingCategory .AI_CONTEXT_FILE ,
438- file_path = rel_path ,
439- line_number = 0 ,
440- rule = "AI context file" ,
441- match = _ai_context_hint (rel_path ),
442- ))
450+ if self ._is_excluded (rel_path ):
451+ continue
452+ # In a git repo, only flag if something under the dir
453+ # is tracked — untracked/ignored files won't be pushed.
454+ if is_git_repo and not self ._is_committed (root_path , rel_path ):
455+ continue
456+ findings .append (Finding (
457+ severity = Severity .CRITICAL ,
458+ category = FindingCategory .AI_CONTEXT_FILE ,
459+ file_path = rel_path ,
460+ line_number = 0 ,
461+ rule = "AI context file" ,
462+ match = _ai_context_hint (rel_path ),
463+ ))
443464
444465 for filename in files :
445466 full_path = os .path .join (dirpath , filename )
@@ -453,14 +474,17 @@ def _unified_walk(
453474 if self ._warn_ai_context_files :
454475 if (filename .lower () in _AI_CONTEXT_BASENAMES
455476 or rel_path .lower () in _AI_CONTEXT_REL_PATHS ):
456- findings .append (Finding (
457- severity = Severity .CRITICAL ,
458- category = FindingCategory .AI_CONTEXT_FILE ,
459- file_path = rel_path ,
460- line_number = 0 ,
461- rule = "AI context file" ,
462- match = _ai_context_hint (rel_path ),
463- ))
477+ # In a git repo, only flag tracked files —
478+ # untracked/gitignored files won't be pushed.
479+ if not is_git_repo or self ._is_tracked (root_path , rel_path ):
480+ findings .append (Finding (
481+ severity = Severity .CRITICAL ,
482+ category = FindingCategory .AI_CONTEXT_FILE ,
483+ file_path = rel_path ,
484+ line_number = 0 ,
485+ rule = "AI context file" ,
486+ match = _ai_context_hint (rel_path ),
487+ ))
464488
465489 # Large file check
466490 try :
0 commit comments