Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The Three Graphs

OxyMake uses three distinct graph representations, each at a different level of abstraction. Understanding them is key to understanding how OxyMake works — and how to debug when things go wrong.

Overview

graph TD
    A[Oxymakefile.toml] --> B["RuleGraph<br/><i>What you declared (abstract, compact)</i>"]
    B -->|"Wildcard resolution<br/>+ guard evaluation"| C["JobGraph<br/><i>What will execute (concrete, optimized)</i>"]
    C -->|"Runtime state annotation"| D["ExecGraph<br/><i>What is happening (live status)</i>"]

RuleGraph — The Logical View

The RuleGraph is what you wrote in the Oxymakefile. Each rule is a node, and edges connect rules whose output patterns match other rules' input patterns. Wildcards are NOT resolved — this is the abstract view.

A single call node represents ALL variant-call instances, not a specific one.

$ ox plan --level=rules

  data ──→ features ──→ call ──→ annotate

What you can learn from the RuleGraph:

  • Is my pipeline structure correct?
  • Are there circular dependencies?
  • Which rules depend on which?

Inspect it: ox plan --level=rules

JobGraph — The Physical Plan

The JobGraph is the RuleGraph after wildcard resolution. Every concrete job instance is a separate node. With 3 cohorts and 4 windows, a single features rule becomes 12 concrete jobs.

The JobGraph goes through optimization passes before execution:

PassWhat it does
Cache pruningMarks up-to-date jobs as "skip"
Task fusionMerges sequential call-mode jobs
Materialization eliminationRemoves unnecessary file I/O
Critical path analysisPrioritizes bottleneck jobs

These passes run internally; ox plan reports the resolved jobs after optimization. For the 3-rule workflow from Your First Workflow:

$ ox plan
Plan: 3 rules, 3 jobs, 2 source files
Targets: results/summary.json
  1. [stats-bob] rule=stats -> [results/bob_stats.json]
  2. [stats-alice] rule=stats -> [results/alice_stats.json]
  3. [summary] rule=summary -> [results/summary.json]

The header line summarizes the graph (N rules, N jobs, N source files), followed by the requested targets and the concrete jobs that would run.

What you can learn from the JobGraph:

  • How many concrete jobs will execute?
  • Which rule produced each job, and what outputs it writes?
  • Which jobs are already cached? (re-run after a build to see fewer jobs)

Inspect it: ox plan (optimized, the default), ox plan --no-optimize (skip the optimization passes), or ox plan --level rules to view the RuleGraph instead of the JobGraph.

ExecGraph — The Live Execution

The ExecGraph is the JobGraph annotated with runtime state. Each node carries its status (Pending → Running → Completed/Failed), timing, and resource usage.

$ ox status --group-by stage

  data          3/3 completed
  features      145/3412 running (12%)
  call          waiting (blocked)
  annotate      waiting

What you can learn from the ExecGraph:

  • What's running right now?
  • What failed and why?
  • How long has each job been running?
  • Which sessions are active?

Inspect it: ox status

The Relationship

Each graph is a refinement of the previous one:

PropertyRuleGraphJobGraphExecGraph
NodesRules (abstract)Concrete jobsJobs + status
WildcardsUnresolvedResolvedResolved
SizeSmall (tens)Large (thousands)Same as JobGraph
LifetimeStatic (parse time)Static (plan time)Dynamic (runtime)
Changes during runNeverGrows (checkpoints)Continuously

Vocabulary

To avoid confusion, OxyMake uses these terms consistently:

  • Rule = a declaration in the Oxymakefile (unresolved wildcards)
  • Job = a concrete, executable instance of a rule (wildcards resolved)
  • Pass = an optimization transformation on the JobGraph
  • Phase = a stage of the pipeline (parse → resolve → optimize → execute)