I split Relay into small stages so I can reason about what each stage knows—and, just as importantly, what it does not know.
discoveryrefuses symlink roots, applies Git-compatible root ignore patterns, and enforces file-count, per-file, and aggregate-byte limits.languagesmaps extensions to explicit analysis models.parserusesast.parsefor Python without importing the target. C/C++, JavaScript, TypeScript, Java, C#, Go, Rust, Kotlin, Swift, Ruby, and PHP use visibly labelled structural models.callgraphkeeps file, class, and nested-function qualification. It links only exact or unique references; ambiguous method basenames stay unresolved.rulesdistinguishes cooperative async operations from blocking waits, emits immutable findings, and lowers confidence for structural models.timing_summarycompares reachable waits with explicit task contracts. It does not simulate a scheduler.reportswrites deterministic text, Markdown, JSON schema 2.0, and SARIF with stable fingerprints and explicit model metadata.schemaspackages the configuration and report contracts so an installedrelaycommand can furnish the exact files used by editors, CI jobs, and other integrations.
analyser.analyse_path is the public orchestration boundary. Oh—one design choice I do not want
to blur: no stage invokes a compiler, interpreter, hardware tool, network service, or target
source. Compiler- or Tree-sitter-backed front ends can be added later through the same model
boundary without pretending the present structural models are semantic.