[mine-blindspots hyperthrive corpus] DeadReferencePointer skips leading-slash repo-relative paths (false negative) #162
Labels
No labels
P0
P1
P2
P3
bug
create
delete
enhancement
filed-by/agent
filed-by/user
frozen
lint-rule
needs-info
needs-triage
next
plugin/cc-architect
plugin/os
plugin/os-adr
plugin/os-aidd-lint
plugin/os-backlog
plugin/os-context
plugin/os-doc-hygiene
plugin/os-sdlc
plugin/os-vault
project/cc-os
ready-for-agent
ready-for-human
recurring
review
update
waiting
wayfinder:grilling
wayfinder:map
wayfinder:map
wayfinder:research
wayfinder:task
wayfinder:task
wontfix
worklist/deviations
worklist/lint-rule
worklist/new-implement-build
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
jared/cc-os#162
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Cross-project filing from a
mine-blindspotsrun against thehyperthrive-websitesrepo as external corpus. Bucket (a): "rule exists, logic gap" —DeadReferencePointer/PathReferenceScannerfalse-negative (misses a dead reference), the mirror-image of the existing false-positive tickets #129/#150 on the same code.Problem
hyperthrive-websites/docs/onboarding-tasks.md:5:hyperthrive-websites/context/workflow/delivery.md:12:Neither
/inventory/repos.mdnor/delivery/swap-checklist.mdexists anywhere in thehyperthrive-websitesrepo (confirmed: noinventory/ordelivery/directory exists at repo root;onboarding-tasks.md:6even documents that/inventory/"this repo never grew"). Both are genuinely dead, repo-relative references written with a leading slash — butDeadReferencePointernever flags either.Detection
plugins/os-aidd-lint/lib/aidd_lint/path_reference_scanner.rb:99-101:Any matched path starting with
/is unconditionally treated asoutside_repo?(an absolute filesystem path) and excluded frompaths_in/paths_in_documentbeforeDeadReferencePointerever gets a chance to check it against disk (comment at lines 91-93 states "this codebase's own convention never writes a repo-relative reference with a leading slash" — a convention this external corpus violates). The result: both dead references are silently invisible to the cop, identical in effect to a false negative on a path that should be checked and would fail.Correction
Before classifying a leading-slash path as
outside_repo?, attempt repo-root-relative resolution first (File.expand_path(path, root)treating the leading/as repo-root-relative, not filesystem-root-relative) and only fall back to the current unconditional exclusion if no enclosing repo root is found (e.g., scanning a file with noConfig.repo_root_forresult).Pass/fail examples
/inventory/repos.mdreferenced from a file inside a repo whose root contains noinventory/directory.Config.repo_root_forreturns nil) — falls back to current behavior.Provenance
/os-aidd-lint:mine-blindspotsrun, external corpushyperthrive-websites, bucket (a), cop citationpath_reference_scanner.rb:99-101(outside_repo?), evidencehyperthrive-websites/docs/onboarding-tasks.md:5andhyperthrive-websites/context/workflow/delivery.md:12. Verified independently by a second agent pass against the live cop source and the live corpus files (confirmed neither/inventory/nor/delivery/exists in the repo). 2026-07-27. Related to but distinct from #129/#150 (false-positive classes on the sameoutside_repo?/resolution logic) — this is the false-negative mirror case and should be triaged alongside them since a single resolution-logic fix may address both directions.Fix direction
Attempt repo-root-relative resolution for leading-slash paths before excluding them as
outside_repo?, so a leading-slash reference that doesn't resolve from repo root is still flagged as dead rather than silently skipped.Discoverer: hyperthrive-websites, session id unavailable, 2026-07-27. Filed from a mine-blindspots run against this repo as external corpus.
Work started — branch
fix/162-leading-slash-repo-relative-paths. Classified OBVIOUS. Fix shape: thread an optionalfrom_file:throughPathReferenceScanner.paths_in/paths_in_documentso a leading-slash path is only surfaced when the referencing file has an enclosing repo root;candidate_pathsthen tries the path as written (absolute) and repo-root-relative (leading slash stripped). Default no-arg behavior is unchanged, so Tier-2 AuthoritySourceResolver is untouched by construction.Green on branch
fix/162-leading-slash-repo-relative-paths(commitbf02a35). Not closing — needs sign-off.Fix.
PathReferenceScanner.paths_in/paths_in_documentnow take an optionalfrom_file:. Given one with an enclosing repo root, a leading-slash path is surfaced as checkable, andcandidate_pathstries it two ways: as written (absolute) and repo-root-relative. The slash has to be stripped for the second candidate —File.expand_pathignores its base for an absolute path, so both candidates would otherwise collapse to the same string and root-relative resolution would silently never happen.DeadReferencePointerpassesdocument.path; Tier 2'sAuthoritySourceResolvercalls the no-arg form and is unchanged by construction (verified: 0 authority sources resolved from leading-slash paths across the in-scope corpus). That answers the #129 blast-radius warning for this change.One thing the ticket did not anticipate. A naive version of this fix flags 24 new offenses in cc-os, 21 of them false.
PATH_PATTERNhas no character class for~,${},<>or*, so these surface only their/...tail:${CLAUDE_PLUGIN_ROOT}/workflows/build-plan.md->/workflows/build-plan.mdskills/<role>/SKILL.md->/SKILL.md**/PRD.md->/PRD.mdSame truncation class the existing
~guard was written for.outside_repo?now only treats a leading-slash match as repo-root-relative when nothing of a path precedes it (start of span, whitespace, or an opening bracket).Measured over the 99 in-scope files: 49 -> 50 offenses. The single addition is
plugins/cc-architect/references/plugin-architecture-philosophy-review.md:9, pointing at/home/jared/dev/cc-plugins/cc-architect/references/plugin-architecture-philosophy.md— a real stale cross-repo absolute path, i.e. a #150-class residual (advisory severity, one instance). Flagged here so it is not later mistaken for a regression.Ticket evidence re-verified against the live corpus. hyperthrive
docs/onboarding-tasks.mdhas been edited since filing: line 5's/inventory/repos.mdis gone, andcontext/workflow/delivery.md:12now writes the path relative (already caught). The remaining must-fail case reproduces:onboarding-tasks.md:6-> "points at /inventory/smartlead-api.md, which does not exist."Tests: 6 new in
tests/path_reference_scanner_test.rb, 3 intests/cops/dead_reference_pointer_test.rb, covering all three ticket pass/fail cases plus the truncation regressions. Full plugin suite:301 runs, 725 assertions, 0 failures, 0 errors, 0 skips.