Commit Graph
15 Commits
Author SHA1 Message Date
JunoLee 97f0dc197e fix(cluster,analyze,report): isolate AMBIGUOUS edges from top-N and modularity
AMBIGUOUS-tagged edges (confidence ≈ 0.35, often `conceptually_related_to`
from LLM semantic extraction) could glue otherwise-independent clusters
together through Leiden/Louvain modularity, and the resulting bridge
questions crowded `Suggested Questions` with low-signal entries. The
`AMBIGUOUS` flag was already correct — only downstream consumers
treated it identically to EXTRACTED/INFERRED.

Changes:
- `cluster()` gains `ambiguous_scale: float = 0.5` (overridable via
  `GRAPHIFY_AMBIGUOUS_SCALE`). Multiplier is applied to AMBIGUOUS edge
  `weight` in a graph copy before partitioning so the raw graph (and
  `/graphify path`/`explain` output) stays untouched. 1.0 restores
  legacy behavior.
- `suggest_questions()` tags each ambiguous_edge entry with
  `low_confidence=True`. Interleave + top_n contract from #3849 is
  preserved; the tag is purely metadata.
- `report.py` splits tagged entries into a new "Low-confidence Hints"
  section below the main Suggested Questions.

Tests:
- `test_cluster_ambiguous_scale.py` (new, 7 tests): default scale
  demotes AMBIGUOUS weight, scale=0.0 drops it entirely, scale=1.0
  is no-op, env override + malformed env fail-soft, raw graph not
  mutated, no copy when no AMBIGUOUS edges present.
- `test_suggest_questions_ambiguous.py` (new, 4 tests): tag present
  on every ambiguous_edge entry, never on other types.
- `test_analyze.py::test_suggest_questions_diversity_preserves_limit_and_candidates`
  relaxed to allow the optional `low_confidence` key.

Fixes #4199

---
한국어 요약: AMBIGUOUS edge (LLM 추론, 신뢰도 ~0.35) 가 Leiden 모듈러리티로 독립
클러스터를 묶거나 Suggested Questions top-N 을 잠식하던 문제 수정. cluster() 에
ambiguous_scale 파라미터 (default 0.5, env override) 추가, 원본 그래프는 복사 후
수정하여 /graphify path/explain 영향 없음. suggest_questions 는 low_confidence
플래그만 추가하고 interleave contract (#3849) 유지. report.py 가 분리 렌더링.
regression test 11 개 신규 + 기존 1 개 relax.

(cherry picked from commit ff52a29266)
2026-10-08 14:27:06 +01:00
Mahaboob pasha 9d3ccfc99c fix(analyze): keep edge direction in graph_diff
graph_diff keyed undirected edges by their sorted endpoints, so a call
that reversed (a->b became b->a) dropped out of the --update summary.
When both snapshots carry _src/_tgt and they differ, the edge is now
reported as one removed and one new edge, with source/target taken from
the markers. Graphs without the markers diff as before.

The skill's diff step loaded the old graph.json with a plain
node_link_graph call, which drops the stored direction, so it now uses
paths.load_node_link_graph (#4066/#4088). Skills regenerated with
skillgen, and the aider/devin monolith round-trip allows the changed
lines.

Closes #4067

Co-Authored-By: Grok Bot <noreply@x.ai>
(cherry picked from commit 917fab9fbb)
2026-10-06 20:55:02 +01:00
azizur100389 bb20ef7234 fix(analyze): diversify suggested questions across signal types
Round-robin the existing question categories before truncating the result. Preserve within-category order, existing small-limit priority, candidate schema, and no-signal behavior. Fixes #3849.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
(cherry picked from commit 560b88d86f)
2026-10-04 20:40:34 +01:00
neo1777 a20c272d46 fix(analyze): make the cross-repo/directory surprise bonus match its reason
_top_level_dir() returned the whole path when it had no "/", so two
files at the scan root (a flat folder of notes, or README.md and
setup.py) got different "top-level dirs". Every such cross-file edge
(other than suppressed INFERRED calls/uses) received +2 and the reason
"connects across different repos/directories" in surprising_connections,
which is false.

- A path without "/" now maps to the scan root ("."). "." rather than ""
  keeps root files distinct from an absolute path outside the scan root,
  whose first component is "".
- Backslashes and a leading "./" are normalized first: build_from_json
  converts backslashes but keeps "./", and serve.py's _load_graph() and
  API callers can skip build_from_json altogether.
- The comparison key is (node "repo", top-level dir). merge-graphs and
  global add keep source_file repo-relative and tag nodes with "repo",
  so two repos can share directory names; single-repo graphs have no
  "repo" and are unaffected. On merged graphs a cross-repo edge now gets
  the bonus whenever the repos differ; before, it depended on whether
  the top-level directory names happened to differ.

Tests: the flat case (fails on d6eaa8a), merged graphs, backslash and
"./" paths, plus pins for what must not change (root vs subdirectory,
root vs out-of-root absolute path).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 05d6410535)
2026-09-30 20:41:10 +01:00
balloon72andClaude Opus 4.8 15a86536c4 fix(analyze): exclude rationale nodes from suggested-question gap count (#1768)
suggest_questions()'s "isolated/weakly-connected nodes" filter was missing the
`file_type != "rationale"` exclusion that report.py's Knowledge Gaps section
already applies, so the same GRAPH_REPORT.md reported two different counts for
the same concept (757 vs 245 on a real graph) — an internal inconsistency that
made a healthy graph look like a documentation problem. Add the same filter so
both computations agree.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-11 11:52:12 +01:00
Manoj Mishra c066511bf2 feat: detect circular import dependencies at file level (#961)
* feat: detect circular import dependencies at file level

- Add find_import_cycles() to analyze.py
- Collapses symbol nodes to parent files, builds directed file graph
- Uses nx.simple_cycles() bounded by max_cycle_length (default 5)
- Deduplicates rotations, returns shortest cycles first
- Considers both imports_from and re_exports edges

Tested on a 976-file Next.js codebase: found 4 cycles including
a known utils↔barrel circular dependency and a 4-file API cycle.

* fix: resolve import-cycle merge blockers

- use source_file-only endpoint resolution (no label fallback)
- support Graph/DiGraph orientation via edge source_file
- return structured cycle records and include self-loops
- integrate Import Cycles section into GRAPH_REPORT.md
- expand cycle tests for real-schema IDs, undirected input,
  missing source_file nodes, and non-import relations
2026-05-30 21:37:47 +01:00
balloon72andhanmo1 a4a475c8b6 perf(analyze): reuse degrees for surprise scoring (#914)
Co-authored-by: hanmo1 <hanmo1@lenovo.com>
2026-05-18 12:05:21 +01:00
Christopher BeaulieuandClaude Sonnet 4.6 2aaa216825 fix(analyze): exclude npm dep-block keys from god-node selection (#905)
* fix(analyze): exclude npm dep-block keys from god-node selection

Extends _JSON_NOISE_LABELS in graphify/analyze.py with the six npm
package.json dependency-block keys (dependencies, devDependencies,
peerDependencies, optionalDependencies, bundledDependencies,
bundleDependencies — lowercased to match the existing .strip().lower()
comparison in _is_json_key_node).

On JS/TS corpora with non-trivial dependency counts, the dep-block key
node accumulates contains+imports edges to every package entry and was
surfacing as the top god-node in the report. The fix is a one-line
extension of the existing frozenset; no new helpers or code paths.

Includes a parametrized regression test in tests/test_analyze.py
covering all five npm keys: dependencies, devDependencies,
peerDependencies, optionalDependencies, bundledDependencies.

Validated live against rsl-siege-manager @ 6085fd66 — zero npm dep-block
keys in the top-10 god-nodes after the fix. Pre-existing failures
(Windows symlink + SQL tree-sitter): 17, unchanged.

Closes #2

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* style: drop fork-local issue refs from analyze comments

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 11:32:53 +01:00
SafiandClaude Sonnet 4.6 766566f6a8 Fill test gaps from PR #890 and fix case-insensitive path in _is_json_key_node
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 14:27:01 +01:00
SafiandClaude Sonnet 4.6 aa541a680a Suppress code-doc INFERRED edges and filter JSON key nodes from god_nodes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 14:23:38 +01:00
Safi d14e8a72d1 Suppress cross-language INFERRED calls/uses edges in surprising connections
In Python+TypeScript monorepos, the call and import resolvers match by
label across language boundaries (AuthError -> Member), producing false
positives that dominate 'Surprising Connections' due to cross-dir (+2)
and cross-community (+1) bonuses.

Expand the existing calls guard to also cover uses edges, and zero the
cross-dir and cross-community bonuses for these pairs — not just conf_bonus.
Leaves semantically_similar_to, EXTRACTED, and AMBIGUOUS edges unaffected.

5 new tests: calls suppressed, uses suppressed, semantically_similar_to
preserved, same-language INFERRED preserved, cross-language EXTRACTED preserved.
2026-05-16 00:07:18 +01:00
SafiandClaude Sonnet 4.6 429e46a665 v0.4.15: VS Code Copilot Chat, OpenCode/Gemini Windows fixes, .mjs/.ejs, macOS watch, god_nodes degree rename
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 23:08:43 +01:00
SafiandClaude Sonnet 4.6 c3817d6144 Apply PRs #82 #93 #102 #109: extension drift, click detection, skill coverage, .graphify_python persistence
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 08:22:01 +01:00
Safi 693d2ba991 feat: composite surprise score — cross-type, cross-repo, community distance, peripheral→hub 2026-04-06 16:06:31 +01:00
Safi ce47198be1 feat: Claude Code skill, Obsidian vault, install, tests
skill.md with full pipeline steps, Obsidian as default output (canvas, tags,
dataview, graph colors), two-command install, 71 tests, .gitignore, deps
2026-04-04 18:53:43 +01:00