fix(detect): honor .graphifyignore for the memory tree (fixes #2267) - #2272
fix(detect): honor .graphifyignore for the memory tree (fixes #2267)#2272Munawarx wants to merge 3 commits into
Conversation
…y-Labs#2267) The memory tree (graphify-out/memory/, where saved Q&A results are filed back into the graph) was exempt from the ignore check, so a user could never exclude their own Q&A output from the corpus. detect.py guarded the _is_ignored call with 'not in_memory', silently bypassing user patterns. Remove the guard so ignore patterns apply to the memory tree like every other path. Default behavior (memory included unless explicitly ignored) is preserved. Adds a regression test (test_graphifyignore_excludes_memory_tree) matching the existing tests/test_detect.py style. Fixes Graphify-Labs#2267
safishamsi
left a comment
There was a problem hiding this comment.
Thanks @Munawarx — the gap is real (user ignore patterns never reach graphify-out/memory/). But the one-line change over-reaches: ignore_patterns includes .gitignore and $GIT_DIR/info/exclude, not just .graphifyignore. Since graphify-out/ is generated output and is commonly gitignored, dropping the guard silently disables the memory round-trip by default for those repos — I verified _is_ignored(<root>/graphify-out/memory/query_1.md, ...) returns True with graphify-out/ in .gitignore, which contradicts the 'default unchanged' claim. Please scope this to .graphifyignore-sourced patterns only (track pattern provenance and apply just those to the memory tree), and add a regression test that a gitignored graphify-out/ still keeps memory included. Happy to re-review.
…raphify-Labs#2267) Maintainer feedback on PR Graphify-Labs#2272: the one-line guard removal was too broad — ignore_patterns includes .gitignore and $GIT_DIR/info/exclude, not just .graphifyignore. Since graphify-out/ is generated output commonly placed in .gitignore, dropping the guard silently disables the memory round-trip by default. Track pattern provenance so memory files respect ONLY .graphifyignore-sourced patterns: - Add source tag (3rd tuple element) to every ignore pattern: 'gitignore', 'graphifyignore', 'info_exclude', 'cli_exclude' - _load_dir_own_ignore: tags .gitignore vs .graphifyignore per entry - _load_graphifyignore: tags info/exclude + propagates dir tags - _is_ignored: new optional 'sources' param filters by provenance - detect(): memory tree calls _is_ignored with sources={'graphifyignore'} Regression tests: - test_gitignored_graphify_out_keeps_memory_included: graphify-out/ in .gitignore → memory files stay included (default unchanged) - test_info_exclude_does_not_drop_memory: graphify-out/ in info/exclude → memory files stay included - test_graphifyignore_excludes_memory_tree: user .graphifyignore still excludes memory tree as before
|
Thanks @safishamsi for the detailed review. I've reworked the fix to track pattern provenance exactly as you described. What changed: Each ignore pattern now carries a source tag (3rd tuple element):
This means a gitignored Regression tests added:
All 3 new tests pass; no regressions in the existing suite (225 passed). Happy to address anything else. |
There was a problem hiding this comment.
Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).
Graphify reviewed this change.
Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).
Graphify review — findings
This PR adds provenance tracking to the ignore-pattern loading in graphify/detect.py, so each pattern is tagged with its source (.gitignore, .graphifyignore, $GIT_DIR/info/exclude, or CLI exclude) by changing the pattern tuples from (anchor, pattern) to (anchor, pattern, source). The _is_ignored function gains an optional sources filter, and detect() uses it so that files under the graphify-out/memory/ tree are only filtered by .graphifyignore-sourced patterns rather than all ignore sources. It also adds tests covering the memory-tree exclusion behavior for .graphifyignore, gitignored graphify-out/, and $GIT_DIR/info/exclude. Surface area is _load_dir_own_ignore, _load_graphifyignore, _is_ignored, the memory-handling branch in detect, plus new/updated tests in tests/test_detect.py.
Worth a look
- _is_ignored cache reuses results across different source filters —
graphify/detect.py:1109· Escalate · medium- agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 1151 functions depend on the 425 functions this change touches.
Health — this change adds coupling hotspots:
- worse:
detect()— 83 callers, 11 callees
Verification — 1151 functions in the blast radius were not formally verified this run (proofs are advisory here).
Gate & verification
graphify gate
PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.
Advisory (not blocking):
- verification_scope: 618 function(s) in the blast radius were not formally verified this run
· 1 more finding(s) on lines outside this diff (see the check run).
Graphify bot review flagged: _is_ignored caches results keyed by path alone, but the same path can be evaluated under different 'sources' filters (e.g. all-sources for code files vs graphifyignore-only for memory files). A non-memory file under graphify-out/ cached as ignored via .gitignore would poison the cache — when a memory file's ancestor walk hits that same cached entry, it wrongly returns True and drops the memory file. Fix: cache key is now (path, frozenset(sources)) when a source filter is active, so evaluations under different filters never collide. Test: test_memory_cache_not_poisoned_by_non_memory_eval — places a non-memory file + memory file under the same gitignored graphify-out/ and verifies the memory file survives.
|
Also addressed the cache collision flagged by the Graphify review bot. Issue: Fix: Cache key is now Test added: All tests pass: 226 passed, 0 new failures. |
There was a problem hiding this comment.
Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).
Graphify reviewed this change.
Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).
Graphify review — findings
This PR adds provenance tracking to graphify's ignore-pattern system, changing the internal (anchor, pattern) tuples into (anchor, pattern, source) triples tagged with constants like _IGNORE_SOURCE_GITIGNORE and _IGNORE_SOURCE_GRAPHIFYIGNORE. The _is_ignored function gains an optional sources filter (and correspondingly keyed cache) so callers can evaluate only patterns from selected origins. In detect(), files under graphify-out/memory/ are now filtered using only .graphifyignore-sourced patterns rather than being fully exempt from ignore checks. The surface area spans _load_dir_own_ignore, _load_graphifyignore, _is_ignored, and the walk loop in detect(), plus two new tests covering memory-tree exclusion via .graphifyignore and non-exclusion via .gitignore. Most of the listed changed test symbols appear to be rationale/fixture entries rather than substantive logic changes.
Worth a look
- sources={} filter uses truthy check causing empty set to behave as no filter for cache key but as filter for evaluation —
graphify/detect.py:1122· Escalate · medium- agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
- Shared ignore_cache collides between filtered and unfiltered lookups when sources is empty —
graphify/detect.py:1123· Escalate · medium- agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 1153 functions depend on the 427 functions this change touches.
Health — this change adds coupling hotspots:
- worse:
detect()— 84 callers, 11 callees
Verification — 1153 functions in the blast radius were not formally verified this run (proofs are advisory here).
Gate & verification
graphify gate
PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.
Advisory (not blocking):
- verification_scope: 620 function(s) in the blast radius were not formally verified this run
· 1 more finding(s) on lines outside this diff (see the check run).
Problem
.graphifyignorepatterns are silently bypassed forgraphify-out/memory/, so users cannot exclude their own saved Q&A output from the corpus. The tree gets re-ingested on every run and node counts grow for reasons unrelated to the source tree.Root cause
In
graphify/detect.pythe ignore check is guarded:The
not in_memorycondition means user ignore patterns never apply to the memory tree. This is issue #2267, Option 1 (the maintainer-friendly fix the reporter requested).Solution
Remove the
not in_memoryguard so_is_ignoredapplies to the memory tree like every other path. Default behavior is unchanged: memory is still ingested unless explicitly ignored.As a side benefit, the hidden/noise filter (which also keyed off
in_memory) now correctly applies to the memory tree, so stray dotfiles dropped there are no longer unconditionally picked up.Testing
test_graphifyignore_excludes_memory_treeintests/test_detect.py(matches existing style, usestmp_path)..graphifyignore, memory is still ingested (default loop intact).graphify-out/, nestedproj/graphify-out/memory/, and negation patterns behave correctly.Expected impact
Users can finally scope the graph to the source tree only. Removes silent config-ignored behavior.
Fixes #2267