diff --git a/graphify/extract.py b/graphify/extract.py index 65e62c646..feaa399ff 100644 --- a/graphify/extract.py +++ b/graphify/extract.py @@ -2668,7 +2668,7 @@ def extract(paths: list[Path]) -> dict: } -def collect_files(target: Path, *, follow_symlinks: bool = False) -> list[Path]: +def collect_files(target: Path, *, follow_symlinks: bool = False, root: Path | None = None) -> list[Path]: if target.is_file(): return [target] _EXTENSIONS = { @@ -2678,12 +2678,20 @@ def collect_files(target: Path, *, follow_symlinks: bool = False) -> list[Path]: ".lua", ".toc", ".zig", ".ps1", ".m", ".mm", } + from graphify.detect import _load_graphifyignore, _is_ignored + ignore_root = root if root is not None else target + patterns = _load_graphifyignore(ignore_root) + + def _ignored(p: Path) -> bool: + return bool(patterns and _is_ignored(p, ignore_root, patterns)) + if not follow_symlinks: results: list[Path] = [] for ext in sorted(_EXTENSIONS): results.extend( p for p in target.rglob(f"*{ext}") if not any(part.startswith(".") for part in p.parts) + and not _ignored(p) ) return sorted(results) # Walk with symlink following + cycle detection @@ -2701,7 +2709,7 @@ def collect_files(target: Path, *, follow_symlinks: bool = False) -> list[Path]: continue for fname in filenames: p = dp / fname - if p.suffix in _EXTENSIONS and not fname.startswith("."): + if p.suffix in _EXTENSIONS and not fname.startswith(".") and not _ignored(p): results.append(p) return sorted(results) diff --git a/graphify/skill-codex.md b/graphify/skill-codex.md index 94d41584d..c75a407ec 100644 --- a/graphify/skill-codex.md +++ b/graphify/skill-codex.md @@ -305,10 +305,12 @@ Output exactly this JSON (no other text): **Step B3 - Collect, cache, and merge** Wait for all subagents. For each result: -- If a subagent returned valid JSON with `nodes` and `edges`, include it and save each file's nodes/edges to the cache +- Check that `graphify-out/.graphify_chunk_NN.json` exists on disk — this is the success signal +- If the file exists and contains valid JSON with `nodes` and `edges`, include it and save to cache +- If the file is missing, the subagent was likely dispatched as read-only (Explore type) — print a warning: "chunk N missing from disk — subagent may have been read-only. Re-run with general-purpose agent." Do not silently skip. - If a subagent failed or returned invalid JSON, print a warning and skip that chunk - do not abort -If more than half the chunks failed, stop and tell the user. +If more than half the chunks failed or are missing, stop and tell the user to re-run and ensure `subagent_type="general-purpose"` is used. Save new results to cache: ```bash diff --git a/graphify/skill-copilot.md b/graphify/skill-copilot.md index 981224738..1bd26f0aa 100644 --- a/graphify/skill-copilot.md +++ b/graphify/skill-copilot.md @@ -301,10 +301,12 @@ Output exactly this JSON (no other text): **Step B3 - Collect, cache, and merge** Wait for all subagents. For each result: -- If a subagent returned valid JSON with `nodes` and `edges`, include it and save each file's nodes/edges to the cache +- Check that `graphify-out/.graphify_chunk_NN.json` exists on disk — this is the success signal +- If the file exists and contains valid JSON with `nodes` and `edges`, include it and save to cache +- If the file is missing, the subagent was likely dispatched as read-only (Explore type) — print a warning: "chunk N missing from disk — subagent may have been read-only. Re-run with general-purpose agent." Do not silently skip. - If a subagent failed or returned invalid JSON, print a warning and skip that chunk - do not abort -If more than half the chunks failed, stop and tell the user. +If more than half the chunks failed or are missing, stop and tell the user to re-run and ensure `subagent_type="general-purpose"` is used. Save new results to cache: ```bash diff --git a/graphify/skill-droid.md b/graphify/skill-droid.md index 49197ffec..979972017 100644 --- a/graphify/skill-droid.md +++ b/graphify/skill-droid.md @@ -302,10 +302,12 @@ Output exactly this JSON (no other text): **Step B3 - Collect, cache, and merge** Wait for all subagents. For each result: -- If a subagent returned valid JSON with `nodes` and `edges`, include it and save each file's nodes/edges to the cache +- Check that `graphify-out/.graphify_chunk_NN.json` exists on disk — this is the success signal +- If the file exists and contains valid JSON with `nodes` and `edges`, include it and save to cache +- If the file is missing, the subagent was likely dispatched as read-only (Explore type) — print a warning: "chunk N missing from disk — subagent may have been read-only. Re-run with general-purpose agent." Do not silently skip. - If a subagent failed or returned invalid JSON, print a warning and skip that chunk - do not abort -If more than half the chunks failed, stop and tell the user. +If more than half the chunks failed or are missing, stop and tell the user to re-run and ensure `subagent_type="general-purpose"` is used. Save new results to cache: ```bash diff --git a/graphify/skill-opencode.md b/graphify/skill-opencode.md index 7e86c6f31..d2200f640 100644 --- a/graphify/skill-opencode.md +++ b/graphify/skill-opencode.md @@ -301,10 +301,12 @@ Output exactly this JSON (no other text): **Step B3 - Collect, cache, and merge** Wait for all subagents. For each result: -- If a subagent returned valid JSON with `nodes` and `edges`, include it and save each file's nodes/edges to the cache +- Check that `graphify-out/.graphify_chunk_NN.json` exists on disk — this is the success signal +- If the file exists and contains valid JSON with `nodes` and `edges`, include it and save to cache +- If the file is missing, the subagent was likely dispatched as read-only (Explore type) — print a warning: "chunk N missing from disk — subagent may have been read-only. Re-run with general-purpose agent." Do not silently skip. - If a subagent failed or returned invalid JSON, print a warning and skip that chunk - do not abort -If more than half the chunks failed, stop and tell the user. +If more than half the chunks failed or are missing, stop and tell the user to re-run and ensure `subagent_type="general-purpose"` is used. Save new results to cache: ```bash diff --git a/graphify/skill-trae.md b/graphify/skill-trae.md index fdbb3ebd2..89b34c619 100644 --- a/graphify/skill-trae.md +++ b/graphify/skill-trae.md @@ -298,10 +298,12 @@ Accumulate nodes/edges/hyperedges across all results and write to `.graphify_sem **Step B3 - Collect, cache, and merge** Wait for all subagents. For each result: -- If a subagent returned valid JSON with `nodes` and `edges`, include it and save each file's nodes/edges to the cache +- Check that `graphify-out/.graphify_chunk_NN.json` exists on disk — this is the success signal +- If the file exists and contains valid JSON with `nodes` and `edges`, include it and save to cache +- If the file is missing, the subagent was likely dispatched as read-only (Explore type) — print a warning: "chunk N missing from disk — subagent may have been read-only. Re-run with general-purpose agent." Do not silently skip. - If a subagent failed or returned invalid JSON, print a warning and skip that chunk - do not abort -If more than half the chunks failed, stop and tell the user. +If more than half the chunks failed or are missing, stop and tell the user to re-run and ensure `subagent_type="general-purpose"` is used. Save new results to cache: ```bash diff --git a/graphify/skill-windows.md b/graphify/skill-windows.md index 9d7bc6bba..2016f8d2b 100644 --- a/graphify/skill-windows.md +++ b/graphify/skill-windows.md @@ -291,10 +291,12 @@ Output exactly this JSON (no other text): **Step B3 - Collect, cache, and merge** Wait for all subagents. For each result: -- If a subagent returned valid JSON with `nodes` and `edges`, include it and save each file's nodes/edges to the cache +- Check that `graphify-out/.graphify_chunk_NN.json` exists on disk — this is the success signal +- If the file exists and contains valid JSON with `nodes` and `edges`, include it and save to cache +- If the file is missing, the subagent was likely dispatched as read-only (Explore type) — print a warning: "chunk N missing from disk — subagent may have been read-only. Re-run with general-purpose agent." Do not silently skip. - If a subagent failed or returned invalid JSON, print a warning and skip that chunk - do not abort -If more than half the chunks failed, stop and tell the user. +If more than half the chunks failed or are missing, stop and tell the user to re-run and ensure `subagent_type="general-purpose"` is used. Save new results to cache: ```powershell diff --git a/graphify/skill.md b/graphify/skill.md index 5a6d137f3..c9fdb8540 100644 --- a/graphify/skill.md +++ b/graphify/skill.md @@ -238,11 +238,13 @@ Load files from `graphify-out/.graphify_uncached.txt`. Split into chunks of 20-2 Call the Agent tool multiple times IN THE SAME RESPONSE - one call per chunk. This is the only way they run in parallel. If you make one Agent call, wait, then make another, you are doing it sequentially and defeating the purpose. +**IMPORTANT - subagent type:** Always use `subagent_type="general-purpose"`. Do NOT use `Explore` - it is read-only and cannot write chunk files to disk, which silently drops extraction results. General-purpose has Write and Bash access which the subagent needs. + Concrete example for 3 chunks: ``` -[Agent tool call 1: files 1-15] -[Agent tool call 2: files 16-30] -[Agent tool call 3: files 31-45] +[Agent tool call 1: files 1-15, subagent_type="general-purpose"] +[Agent tool call 2: files 16-30, subagent_type="general-purpose"] +[Agent tool call 3: files 31-45, subagent_type="general-purpose"] ``` All three in one message. Not three separate messages. @@ -304,10 +306,12 @@ Output exactly this JSON (no other text): **Step B3 - Collect, cache, and merge** Wait for all subagents. For each result: -- If a subagent returned valid JSON with `nodes` and `edges`, include it and save each file's nodes/edges to the cache +- Check that `graphify-out/.graphify_chunk_NN.json` exists on disk — this is the success signal +- If the file exists and contains valid JSON with `nodes` and `edges`, include it and save to cache +- If the file is missing, the subagent was likely dispatched as read-only (Explore type) — print a warning: "chunk N missing from disk — subagent may have been read-only. Re-run with general-purpose agent." Do not silently skip. - If a subagent failed or returned invalid JSON, print a warning and skip that chunk - do not abort -If more than half the chunks failed, stop and tell the user. +If more than half the chunks failed or are missing, stop and tell the user to re-run and ensure `subagent_type="general-purpose"` is used. Save new results to cache: ```bash