ChangeGraphChangeGraph

Product

Architecture

How ChangeGraph turns production signals into ranked change candidates, with hard boundaries between deterministic code, the in-repo Mastra-compatible runtime, and the ChangeGraph provider router.

Incident pipeline

  1. 1

    Incident

    Sentry issue opens a window around the spike.

  2. 2

    Ingest

    Normalize GitHub / Sentry / Vercel into the graph.

  3. 3

    Correlate

    LKG + window ladder; map release → commit when known.

  4. 4

    Score

    Deterministic ranks with fixed weights. No LLM.

  5. 5

    Evidence

    Package facts and why-not-others.

  6. 6

    Explain

    In-repo explain_incident / investigate_incident over the packed digest.

Scores are correlation aids. Causation stays with the engineer.

01 · Ingest

Adapters normalize signals. The scorer never sees a vendor SDK.

GitHub App webhooks and API, Sentry issues/events, and Vercel deployments upsert into tenant-scoped entities. HMAC on every webhook. Delivery IDs are claimed so retries never double-apply. Natural keys (tenant + PR number / commit SHA) keep the graph consistent.

Where the running app reads data

02 · Graph

A timeline of what changed: PRs, commits, files, releases, deploys.

The change graph is the product. Incidents hang off a window of that graph, not a chat transcript. Last-known-good deploy, when present, bounds “what changed since things were good.”

Tier-1 production path

  1. 1

    GitHub

    PR / commit / files via App webhooks + API.

  2. 2

    Vercel

    Deploy linked to project + SHA.

  3. 3

    Sentry

    Issue + stack frames open the window.

  4. 4

    Graph

    Tenant-scoped entities, natural keys.

  5. 5

    ChangeGraph

    Ranked candidates and evidence.

Adapters only. Scoring stays provider-agnostic.

03 · Score

Fixed weights. No model in the ranking loop.

Scorer v2 ranks PRs/commits with temporal 25, deployment 25, file/stack overlap 25, service 15, historical 10. Penalties for no overlap or docs/test-only diffs. Identical inputs → identical ranks. Window ladder 24h → 72h → 7d when the set is thin.

Write-up: Scoring & LKG

04 · Evidence

Package the facts. Label what you do not know.

The evidence package carries overlapping paths, timing, release membership, and counter-evidence (“why not others”). Secrets never enter it. FACT vs CORRELATION vs HYPOTHESIS vs UNKNOWN keep humans honest.

05 · LLM

In-repo runtime. Packed. Validated.

OpenAI, Anthropic, xAI, Groq, and Fireworks are called by the ChangeGraph provider router (src/lib/llm/providers.ts). Workflows explain_incident and investigate_incident run on the in-repo Mastra-compatible runtime (src/lib/agents/mastra-runtime, package name @mastra/core). Agent.generate throws. AgentConfig.model is a string or function, not an object with url, id, and apiKey. Workflows summarize only the packed digest. Invented PRs and files are dropped; absolute causation is softened. Investigation needs a configured provider and fails closed as not_configured. Headroom can compress after pack; the packer works without it, and falls back if the proxy is down. Deterministic scoring always runs.

Providers: LLM providers · Open source tools

06 · MCP

Agents inspect ChangeGraph. They do not rewrite it.

Read-only stdio tools: list_incidents, get_incident, get_evidence_package. Token required beyond localhost. The MCP client is a gated read adapter (FEATURE_MCP_CLIENT, default off) and fails closed as not_configured without a registry. The full multi-server registry is deferred. Adapters only; never core domain types.

Deterministic vs agent vs LLM

Core ranking never depends on a model. explain_incident and investigate_incident run on the in-repo Mastra-compatible runtime and explain a packed digest. Model HTTP is the ChangeGraph provider router. Optional Headroom compresses after pack; the packer works without it.

  1. MCP + UI

    06

    Read-only tools and the investigation surface. Agent never mutates ranks.

  2. In-repo runtime

    05

    explain_incident and investigate_incident on the in-repo Mastra-compatible runtime. Model HTTP is the ChangeGraph provider router. Optional Headroom after pack (packer works without it). Validated output; ranks frozen. Missing provider fails closed as not_configured.

  3. Evidence package

    04

    FACTS, score CORRELATION, why-not-others. Secrets never enter the package.

  4. Scorer v2 + LKG

    03

    Fixed weights, window ladder, last-known-good bounds. Identical inputs → identical ranks.

  5. Change graph

    02

    Tenant-scoped PRs, commits, files, releases, deploys. Natural keys. Idempotent upserts.

  6. Ingestion adapters

    01

    GitHub, Sentry, Vercel webhooks/API with HMAC. Scoring stays provider-agnostic.

The same packed evidence package feeds the UI, MCP tools, and Mastra explain_incident / investigate_incident. Scoring still renders when the provider is unset (`not_configured`). See Architecture overview.

Shipped

MCP server

External agents call ChangeGraph tools over stdio: list_incidents, get_incident, get_evidence_package. Read-only; auth via CHANGEGRAPH_MCP_TOKEN when exposed beyond localhost.

Agents → ChangeGraph (inspect incidents & evidence)

Gated

MCP client

Gated read adapter (FEATURE_MCP_CLIENT, default off). Fails closed as not_configured without a registry. The full multi-server registry is deferred. Evidence adapters only; scoring stays MCP-agnostic.

ChangeGraph → external tools (pull more evidence)

How-to: Architecture overview · per-tool setup: Tools reference · Open source tools · How it works

Explore fixtures and the graph locally

Docker Compose, seed fixtures A–D, and investigate with ranked change candidates, evidence, and Mastra workflows.