Files
ar9av__obsidian-wiki/tests/test_conftest_smoke.py
Mike Tsai fd30720223 feat: improve project ingest with optional code-graph-assisted understanding (#167) (#169)
* test: add code-understanding fixtures (fake codegraph CLI, repo builder)

* feat: add code_understanding module with builtin + codegraph providers

Provider abstraction behind code_understand(): builtin uses the regex
ast_extractor plus rg cross-file references (dependency-free fallback);
codegraph shells out to the codegraph CLI with defensive JSON parsing.
Focus-map output is ranked symbols with file:line citations, capped by
max_symbols, and never contains source bodies.

* feat(cli): wire code-understand command and doctor code-understanding checks

New 'obsidian-wiki code-understand --project' subcommand emits the focus
map JSON; doctor --project gains 5 code-understanding capability checks
(builtin, rg, codegraph, codegraph-index, codegraph-fresh). Missing
optional CodeGraph reports warn (exit 0); explicit CODE_UNDERSTANDING_
BACKEND=codegraph with a broken backend fails (exit 1).

* feat(skills): add optional code-understanding focus-map step to wiki-update

Step 3b runs 'obsidian-wiki code-understand --since <last_commit_synced>'
between deciding what to distill and distilling. GUARD-soft-fails like
wiki-ingest Step 1c; mandates file:line citations for architectural
claims and a pruning rule that removes relationships no longer
supported by the codebase. Registers CODE_UNDERSTANDING_BACKEND and
CODE_UNDERSTANDING_CODEGRAPH_BIN in the llm-wiki env reference.

* docs: document CODE_UNDERSTANDING_BACKEND and code-understand command

* docs: add CodeGraph install steps; teach wiki-update to offer install

configuration.md gains a Setup subsection under Code understanding
(npm install -g @colbymchenry/codegraph + verify + CODE_UNDERSTANDING_
CODEGRAPH_BIN fallback). wiki-update Step 3b gains an optional offer:
when codegraph is missing and the user wants the enhanced backend, the
agent may install it (with consent) and re-run the step.

* docs(readme): note code-graph-aware /wiki-update (EN + zh-TW parity)

* docs(readme): clarify zh-TW /wiki-update codegraph note

* fix(codegraph): cap impact queries at 25 seeds on full-project scans

Full scans (no --changed/--since) seed from every tracked file, so an
unbounded impact loop fired one subprocess per symbol — hundreds of
codegraph CLI calls on real repos (observed 120s+ timeout on a 4.3k-node
project). Cap impact at 25 seeds, matching the existing callers/callees
cap (seeds[:5]), keeping full scans bounded while --changed/--since
delta scans stay exhaustive for their small seed sets.

Regression test: test_codegraph_caps_impact_queries_on_full_scan pins the
25-call ceiling (RED: 30 calls -> GREEN: <= 25).

* feat(skills): add standalone code-understand skill

Exposes the code-graph-assisted focus map directly to any coding
agent session, not just as wiki-update Step 3b — so it can be invoked
on demand ("help me understand this codebase", "what breaks if I
change X") independent of a wiki sync.

---------

Co-authored-by: ar9av <ar9avg@gmail.com>
2026-08-15 12:48:11 -07:00

101 lines
3.3 KiB
Python

"""Smoke tests for the shared conftest fixtures (issue #167 wave 1)."""
from __future__ import annotations
import json
import os
import subprocess
from pathlib import Path
from conftest import (
_run_cli,
build_index_state,
make_fake_codegraph_bin,
make_project,
make_repo_two_commits,
)
def test_make_project_creates_git_repo_with_commit(tmp_path: Path) -> None:
project = make_project(tmp_path, {"README.md": "# hi\n"})
proc = subprocess.run(["git", "log", "--oneline"], capture_output=True, text=True, cwd=project)
assert proc.returncode == 0
assert "initial commit" in proc.stdout
assert (project / "README.md").read_text(encoding="utf-8") == "# hi\n"
def test_make_project_without_git(tmp_path: Path) -> None:
project = make_project(tmp_path, {"src/a.py": "x = 1\n"}, git=False)
assert (project / "src" / "a.py").read_text(encoding="utf-8") == "x = 1\n"
assert not (project / ".git").exists()
def test_fake_codegraph_bin_is_executable_and_answers_impact(tmp_path: Path) -> None:
bin_path = make_fake_codegraph_bin(tmp_path)
assert os.access(bin_path, os.X_OK)
proc = subprocess.run([str(bin_path), "impact", "Foo", "--json"], capture_output=True, text=True)
assert proc.returncode == 0
data = json.loads(proc.stdout)
assert data["symbol"] == "Foo"
names = [entry["name"] for entry in data["affected"]]
assert "Foo" in names
assert all("filePath" in entry for entry in data["affected"])
def test_fake_codegraph_bin_broke_mode_exits_1(tmp_path: Path) -> None:
bin_path = make_fake_codegraph_bin(tmp_path)
env = os.environ.copy()
env["FAKE_CODEGRAPH_MODE"] = "broke"
proc = subprocess.run(
[str(bin_path), "query", "x", "--json"], capture_output=True, text=True, env=env
)
assert proc.returncode == 1
assert proc.stderr
def test_build_index_state_fresh_is_newer_than_sources(tmp_path: Path) -> None:
project = make_project(tmp_path, {"src/a.py": "x = 1\n"}, git=False)
build_index_state(project)
db = project / ".codegraph" / "codegraph.db"
src = project / "src" / "a.py"
assert db.exists()
assert db.stat().st_mtime >= src.stat().st_mtime
assert json.loads((project / ".codegraph" / "source.json").read_text())["version"] == 1
def test_build_index_state_stale_is_older_than_sources(tmp_path: Path) -> None:
project = make_project(tmp_path, {"src/a.py": "x = 1\n"}, git=False)
build_index_state(project, fresh=False)
db = project / ".codegraph" / "codegraph.db"
src = project / "src" / "a.py"
assert db.stat().st_mtime < src.stat().st_mtime
def test_make_repo_two_commits_returns_sha_of_first(tmp_path: Path) -> None:
project, sha_first = make_repo_two_commits(tmp_path)
count = subprocess.run(
["git", "rev-list", "--count", "HEAD"], capture_output=True, text=True, cwd=project
)
assert count.stdout.strip() == "2"
assert len(sha_first) == 40
assert (project / "src" / "foo.py").exists()
assert (project / "src" / "bar.py").exists()
def test_run_cli_runs_in_cwd_with_env_overrides(tmp_path: Path) -> None:
project = make_project(tmp_path, {"src/a.py": "x = 1\n"})
proc = _run_cli(project, "--version", env_overrides={"FAKE_VAR": "1"})
assert proc.returncode == 0
assert "obsidian-wiki" in proc.stdout