# Extract builds one knowledge graph from free AST edges and paid semantic edges
*Graphify-Labs/graphify@v8 · informative · 8 markers*

> **Default.** Code files map through a local tree-sitter AST pass — no model call, no egress.
>
> **Trigger.** `graphify extract` only spends LLM budget on docs, papers, and images; `--code-only` drops that pass so a mixed repo still indexes without a backend key.
>
> **Merge.** Both extractions land in one NetworkX graph, get Leiden communities and god-node analysis, then write `graph.json` with every edge tagged `EXTRACTED`, `INFERRED`, or `AMBIGUOUS`.

**Author:** SquallLeonhart13 · **Updated:** 2026-07-12T15:10:10.496Z

## Markers
1. **Extract runs the full pipeline** — `graphify/cli.py:1901–1907`
   `graphify extract` is the headless CI/script entry. The comment at the top of the branch lists the stage order explicitly: detect → AST extraction on code → semantic LLM extraction on docs/papers/images → merge → build → cluster → write outputs. Skill-mode does the same work through assistant subagents; this path calls `extract_corpus_parallel` with whichever backend has a key.
2. **Detect buckets code vs media** — `graphify/detect.py:1068–1079`
   `detect(root)` walks the corpus and fills a `files` dict keyed by `FileType`: `CODE`, `DOCUMENT`, `PAPER`, `IMAGE`, `VIDEO`. That split is the fork the rest of the pipeline depends on — code goes to free AST, everything else to the semantic path. Ignore rules (`.graphifyignore`, CLI `--exclude`) and word-count caching sit on this scan so later stages never re-enumerate the tree.
3. **Code extract is pure AST** — `graphify/extract.py:4232–4255`
   `extract(paths)` runs a two-pass tree-sitter process: per-file structural nodes (classes, functions, imports), then cross-file import resolution that turns file-level imports into class-level `INFERRED` edges. No LLM is involved — the docstring and the CLI both treat this as the free, fully local map. Optional `ProcessPoolExecutor` parallelism only kicks in above a size threshold.
4. **Docs need a semantic pass** — `graphify/cli.py:2121–2135`
   After detect, `semantic_files = doc_files + paper_files + image_files`. With `--code-only`, that list is cleared and the CLI prints how many non-code files were skipped rather than silently dropping them. Without the flag, uncached semantic paths call `extract_corpus_parallel` through a configured backend — this is the only stage that spends model tokens on a normal extract.
5. **Every edge carries confidence** — `graphify/validate.py:4–14`
   `VALID_CONFIDENCES = {EXTRACTED, INFERRED, AMBIGUOUS}` and `REQUIRED_EDGE_FIELDS` include `confidence`. `validate_extraction` rejects edges that omit it or use any other label before `build` can assemble the graph. `EXTRACTED` means the relationship is explicit in source; `INFERRED` is resolution (e.g. cross-file call graph); `AMBIGUOUS` is uncertain and surfaces for human review.
6. **Build merges both extractions** — `graphify/build.py:765–800`
   `build(extractions)` concatenates nodes/edges/hyperedges from every extraction dict, optionally runs `deduplicate_entities` (with an optional LLM only for the ambiguous Jaro-Winkler band), then `build_from_json`. AST and semantic results share one NetworkX graph — order of the list decides which attributes win on duplicate IDs.
7. **Cluster then surface god nodes** — `graphify/cli.py:2558–2574`
   After build, the extract path calls `_cluster` (Leiden, with optional hub exclusion), `_score_all` for cohesion, `_god_nodes` for highest-degree real entities, and `_surprising` for non-obvious cross-file or cross-community edges. Those analysis dicts are written beside `graph.json` as `.graphify_analysis.json` for report and export consumers.
8. **Extract stops at graph.json** — `graphify/cli.py:2630–2637`
   `_to_json` writes the durable graph, then extract prints the handoff: run `graphify cluster-only` to generate `GRAPH_REPORT.md` and name communities. Headless extract intentionally stops at `graph.json` + analysis so CI can index without forcing LLM labeling; agents or a later step own the readable report.

---
Interactive view: https://app.principal-ade.com/trail/d9509577-6d49-498a-aaec-6995ccf60c20
JSON: https://app.principal-ade.com/api/trails/by-id/d9509577-6d49-498a-aaec-6995ccf60c20
Authored at `eec7a01` (v8).
To open a trail or tour locally in the interactive viewer, see https://app.principal-ade.com for the Principal CLI quickstart.
