Skip to content

Match file references on path-word boundaries - #89

Merged
dacharyc merged 1 commit into
mainfrom
fix/orphan-reference-word-boundaries
Aug 4, 2026
Merged

Match file references on path-word boundaries#89
dacharyc merged 1 commit into
mainfrom
fix/orphan-reference-word-boundaries

Conversation

@dacharyc

@dacharyc dacharyc commented Aug 4, 2026

Copy link
Copy Markdown
Member

What this PR does

Fixes #85, where references/lint.yml was reported as "referenced without its extension (as references/lint in references/check-skill-nonlinks.md)" even though that file never contains references/lint.

Root cause: when the referencing file and the inventory file share a directory, containsReference's sourceDir-relative fallback reduces the needle to a bare filename. The extensionless variant then reduced references/lint.yml to the single word lint and substring-matched it against ordinary prose ("Run the lint step…", "Linting catches…").

Two changes:

  • Reference matching now requires path-word boundaries on both sides of a match, so references/lint no longer matches inside references/linting, and lint.yml no longer matches inside eslint.yml.
  • The extensionless sourceDir-relative fallback is skipped when it would reduce to a bare filename. Root-relative matching is unchanged: flat layouts still resolve helper to helper.py, and nested skills still resolve scripts/check_fillable_fields to the .py file.

One test intentionally updated: Python import does not match non-Python files previously relied on the bare-word fallback to claim data_loader.sh was "referenced without its extension" by import data_loader. A Python import cannot reference a shell script, so the accurate outcome — now asserted — is an unreferenced-file warning.

How to test

Reproduced the report with a minimal fixture (a references/lint.yml beside a markdown file whose prose mentions "lint"): before this change it produces the false extension warning; after, it produces the truthful "potentially unreferenced file" warning. Also:

  • go test -race ./... -count=1
  • go vet ./..., gofmt -l .

Checklist

  • Tests pass locally (go test -race ./... -count=1)
  • Lint passes locally (golangci-lint run)
  • New functionality includes tests
  • Breaking changes are noted above (if any)

Fixes #85. When a reference source and an inventory file shared a
directory, the sourceDir-relative fallback reduced the match needle to a
bare filename, and the extensionless variant then substring-matched
ordinary prose: references/lint.yml was reported as "referenced without
its extension" because the word "lint" appeared in a sibling markdown
file that never mentions the path.

Reference matching now requires path-word boundaries on both sides of a
match (references/lint no longer matches inside references/linting, and
lint.yml no longer matches inside eslint.yml), and the extensionless
sourceDir-relative fallback is skipped when it would reduce to a bare
filename. Root-relative extensionless matching is unchanged, so flat
layouts still resolve "helper" to helper.py and nested skills still
resolve scripts/check_fillable_fields to the .py file.

The Python-import test that relied on the old fallback now expects an
orphan warning: "import data_loader" refers to a Python module and
cannot reference data_loader.sh, so reporting the script as
unreferenced is the accurate outcome.
@dacharyc
dacharyc merged commit 2de6a3d into main Aug 4, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A file is reporting a "referenced without its extension" warning, but the text of the warning is not in the reported file

1 participant