You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
.graphifyinclude is dead code. The file is read from disk on every detect() run and its patterns are parsed, but the result is assigned to a local variable that is never read again. A user who creates a .graphifyinclude file gets a silent no-op: no effect on which files are indexed, no warning, and no field in the result dict.
How it got here
.graphifyinclude was added in v0.6.6 (#583, CHANGELOG.md:1084) as a hidden-path allowlist ("opt specific hidden dirs into traversal, e.g. .hermes/plans/**/*.md"). It was wired into the detect() walk via two call sites:
if (notd.startswith(".") or_could_contain_included_path(dp/d, root, include_patterns))
...
ifp.name.startswith(".") andnot_is_included(p, root, include_patterns):
Commit df40e4d (#873, "index dot dirs") removed the blanket dot-prefix exclusion and, with it, both of those consumer lines. It left the loader, both matcher helpers, and the assignment in place. Since then the chain is: file read, patterns parsed, local variable, discarded.
Evidence (all references, repo-wide)
graphify/detect.py:1140_load_graphifyinclude(root) — working loader (walks root to VCS-root, reads .graphifyinclude, parses via _parse_gitignore_line). Dead.
graphify/detect.py:1170_is_included(path, root, patterns) — full gitignore-style matcher. Zero callers.
graphify/detect.py:1219_could_contain_included_path(...) — directory-prefix matcher. Zero callers.
graphify/detect.py:1315include_patterns = _load_graphifyinclude(root) — the only call site; value never read again (confirmed: include_patterns matches only this line plus the dead defs).
CHANGELOG.md:1084 — the v0.6.6 feature entry (the only user-facing promise).
Tests: none on mainline. The original PR's tests and a graphifyinclude_patterns result key only exist on the old origin/v5 branch; the v0.6.6 mainline squash landed the detect.py code without them, so nothing failed when the feature was later severed.
No references in README, cli.py, extract.py, watch.py, skill files, or tools. Even when live, the feature only ever affected detect(), never extract.pycollect_files.
Contrast: .graphifyignore is fully wired
Load at detect.py:1306, consumed for dir pruning (1385) and file filtering (1418), surfaced as graphifyignore_patterns in the result dict (1504), and mirrored in extract.pycollect_files (5306+). That is the pattern an include feature would need to follow.
User impact
Low severity but real: ~110 lines of maintained-but-dead code (it even received a bugfix while dead), real I/O on every scan, and a silent no-op for anyone who trusts the loader or the CHANGELOG entry. Minor wart: .graphifyinclude is not in _SKIP_FILES (detect.py:796), so the allowlist file itself shows up in the unclassified output.
Proposed fix
Two coherent directions:
Option A (preferred): remove the dead code. Delete _load_graphifyinclude, _is_included, _could_contain_included_path, and detect.py:1315. Add a CHANGELOG erratum noting .graphifyinclude has been non-functional since #873. Optionally emit a one-line stderr note when a .graphifyinclude file is present, pointing users to ! negations in .graphifyignore (which already provide re-include via last-match-wins) now that dot dirs are indexed by default. This removes the original motivation cleanly.
Option B: re-implement as an ignore-override. Make .graphifyinclude a re-include that can rescue paths excluded by .gitignore/.graphifyignore: check _is_included before recording ignored for dirs (1385) and files (1418), use _could_contain_included_path to exempt matching dirs from pruning, mirror in extract.pycollect_files, add graphifyinclude_patterns to the result dict, and restore tests. Decisions to settle first: precedence vs CLI --exclude (currently wins over all ignore files, #947); whether include can rescue _SKIP_DIRS noise and _is_sensitive files (#583 said no, keep that); the gitignore parent-exclusion rule (a negation cannot rescue files under an excluded dir); and the --code-only and watch.py re-scan paths.
Given #873 already made the original hidden-dir use case moot and ! in .graphifyignore covers the common "re-include" need, Option A is the lower-risk resolution unless there is demand for a distinct allowlist file.
Summary
.graphifyincludeis dead code. The file is read from disk on everydetect()run and its patterns are parsed, but the result is assigned to a local variable that is never read again. A user who creates a.graphifyincludefile gets a silent no-op: no effect on which files are indexed, no warning, and no field in the result dict.How it got here
.graphifyincludewas added in v0.6.6 (#583, CHANGELOG.md:1084) as a hidden-path allowlist ("opt specific hidden dirs into traversal, e.g..hermes/plans/**/*.md"). It was wired into thedetect()walk via two call sites:Commit
df40e4d(#873, "index dot dirs") removed the blanket dot-prefix exclusion and, with it, both of those consumer lines. It left the loader, both matcher helpers, and the assignment in place. Since then the chain is: file read, patterns parsed, local variable, discarded.Evidence (all references, repo-wide)
graphify/detect.py:1140_load_graphifyinclude(root)— working loader (walks root to VCS-root, reads.graphifyinclude, parses via_parse_gitignore_line). Dead.graphify/detect.py:1170_is_included(path, root, patterns)— full gitignore-style matcher. Zero callers.graphify/detect.py:1219_could_contain_included_path(...)— directory-prefix matcher. Zero callers.graphify/detect.py:1315include_patterns = _load_graphifyinclude(root)— the only call site; value never read again (confirmed:include_patternsmatches only this line plus the dead defs).CHANGELOG.md:1084— the v0.6.6 feature entry (the only user-facing promise).CHANGELOG.md:664— a v0.8.26 ([BUG] anchored gitignore pattern (/dir/) matches basename anywhere in tree, not just at root #1087) anchored-pattern bugfix that was applied to_is_includedwhile it was already dead.graphifyinclude_patternsresult key only exist on the oldorigin/v5branch; the v0.6.6 mainline squash landed the detect.py code without them, so nothing failed when the feature was later severed.No references in README, cli.py, extract.py, watch.py, skill files, or tools. Even when live, the feature only ever affected
detect(), neverextract.pycollect_files.Contrast:
.graphifyignoreis fully wiredLoad at detect.py:1306, consumed for dir pruning (1385) and file filtering (1418), surfaced as
graphifyignore_patternsin the result dict (1504), and mirrored inextract.pycollect_files(5306+). That is the pattern an include feature would need to follow.User impact
Low severity but real: ~110 lines of maintained-but-dead code (it even received a bugfix while dead), real I/O on every scan, and a silent no-op for anyone who trusts the loader or the CHANGELOG entry. Minor wart:
.graphifyincludeis not in_SKIP_FILES(detect.py:796), so the allowlist file itself shows up in theunclassifiedoutput.Proposed fix
Two coherent directions:
Option A (preferred): remove the dead code. Delete
_load_graphifyinclude,_is_included,_could_contain_included_path, and detect.py:1315. Add a CHANGELOG erratum noting.graphifyincludehas been non-functional since #873. Optionally emit a one-line stderr note when a.graphifyincludefile is present, pointing users to!negations in.graphifyignore(which already provide re-include via last-match-wins) now that dot dirs are indexed by default. This removes the original motivation cleanly.Option B: re-implement as an ignore-override. Make
.graphifyincludea re-include that can rescue paths excluded by.gitignore/.graphifyignore: check_is_includedbefore recordingignoredfor dirs (1385) and files (1418), use_could_contain_included_pathto exempt matching dirs from pruning, mirror inextract.pycollect_files, addgraphifyinclude_patternsto the result dict, and restore tests. Decisions to settle first: precedence vs CLI--exclude(currently wins over all ignore files, #947); whether include can rescue_SKIP_DIRSnoise and_is_sensitivefiles (#583 said no, keep that); the gitignore parent-exclusion rule (a negation cannot rescue files under an excluded dir); and the--code-onlyandwatch.pyre-scan paths.Given #873 already made the original hidden-dir use case moot and
!in.graphifyignorecovers the common "re-include" need, Option A is the lower-risk resolution unless there is demand for a distinct allowlist file.