@@ -174,6 +174,24 @@ def _repo_root(start):
174174 return out or start
175175
176176
177+ def _repo_slug (root ):
178+ """The origin remote parsed to (owner/name, name), both lowercased; ('', '') if there is no origin.
179+
180+ Two callers need to identify the current repo from its origin URL: the per-repo denylist
181+ exemption (keyed on owner/name) and the P1.5 self-exclusion (keyed on name). Kept in one place so
182+ the parse cannot drift between them. NOTE: `git filter-repo` strips the origin remote, so inside a
183+ freshly-filtered bare clone this returns ('', '') -- self-exclusion then cannot fire and a repo's
184+ OWN `<name>-config` companion false-positives; re-add origin before scanning such a clone.
185+ """
186+ url = _run (["git" , "remote" , "get-url" , "origin" ], root ).strip ().lower ().rstrip ("/" )
187+ if url .endswith (".git" ):
188+ url = url [:- 4 ]
189+ parts = [p for p in url .replace (":" , "/" ).split ("/" ) if p ]
190+ key = "/" .join (parts [- 2 :]) if len (parts ) >= 2 else ""
191+ name = parts [- 1 ] if parts else ""
192+ return key , name
193+
194+
177195def load_repo_allow (root ):
178196 """Repo-local `.pii-allow`: real literals this repo is ALLOWED to contain, each with a reason."""
179197 path = os .path .join (root , ".pii-allow" )
@@ -219,11 +237,7 @@ def load_private_denylist(root=None):
219237 exempt = json .load (f )
220238 except (OSError , ValueError ):
221239 return toks
222- url = _run (["git" , "remote" , "get-url" , "origin" ], root ).strip ().lower ().rstrip ("/" )
223- if url .endswith (".git" ):
224- url = url [:- 4 ]
225- parts = [p for p in url .replace (":" , "/" ).split ("/" ) if p ]
226- key = "/" .join (parts [- 2 :]) if len (parts ) >= 2 else ""
240+ key , _ = _repo_slug (root )
227241 drop = {str (t ).lower () for t in (exempt .get (key ) or [])}
228242 return [t for t in toks if t not in drop ]
229243
@@ -249,11 +263,7 @@ def load_cross_repo_tokens(root, vis_path=None):
249263 return []
250264 if not isinstance (vis , dict ):
251265 return []
252- url = _run (["git" , "remote" , "get-url" , "origin" ], root ).strip ().lower ().rstrip ("/" )
253- if url .endswith (".git" ):
254- url = url [:- 4 ]
255- parts = [p for p in url .replace (":" , "/" ).split ("/" ) if p ]
256- self_name = parts [- 1 ] if parts else ""
266+ _ , self_name = _repo_slug (root )
257267 toks = set ()
258268 for key , v in vis .items ():
259269 if str (v ).upper () != "PRIVATE" :
@@ -341,15 +351,15 @@ def scan_text(text, where, allow, deny, out, strict=True, deny_only=False):
341351 for m in USER_PATH_RE .finditer (text ):
342352 if m .group (1 ).lower () in GENERIC_USERS :
343353 continue # a standard / CI / placeholder account, not a person
344- hit = m .group (0 ); low = hit .lower ()
345- if low in allow or any (a in low for a in allow ):
354+ hit = m .group (0 ); hl = hit .lower ()
355+ if hl in allow or any (a in hl for a in allow ):
346356 continue
347357 out .append ((where , "USER-PATH" , hit )) # a real account name: never, anywhere
348358 for m in PRIVATE_PATH_RE .finditer (text ):
349- dotpath = m .group (1 ); low = dotpath .lower ()
350- if PUBLIC_DOTPATH_RE .match (low ):
359+ dotpath = m .group (1 ); dl = dotpath .lower ()
360+ if PUBLIC_DOTPATH_RE .match (dl ):
351361 continue # ~/.claude.json, .claude-plugin, shallow skills/<name>
352- if low in allow or any (a in low for a in allow ):
362+ if dl in allow or any (a in dl for a in allow ):
353363 continue
354364 out .append ((where , "PRIVATE-PATH" , m .group (0 ))) # the full home-anchored path
355365
0 commit comments