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
Incident
Sentry issue opens a window around the spike.
- 2
Ingest
Normalize GitHub / Sentry / Vercel into the graph.
- 3
Correlate
LKG + window ladder; map release → commit when known.
- 4
Score
Deterministic ranks with fixed weights. No LLM.
- 5
Evidence
Package facts and why-not-others.
- 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.
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
GitHub
PR / commit / files via App webhooks + API.
- 2
Vercel
Deploy linked to project + SHA.
- 3
Sentry
Issue + stack frames open the window.
- 4
Graph
Tenant-scoped entities, natural keys.
- 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.
MCP + UI
06Read-only tools and the investigation surface. Agent never mutates ranks.
In-repo runtime
05explain_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.
Evidence package
04FACTS, score CORRELATION, why-not-others. Secrets never enter the package.
Scorer v2 + LKG
03Fixed weights, window ladder, last-known-good bounds. Identical inputs → identical ranks.
Change graph
02Tenant-scoped PRs, commits, files, releases, deploys. Natural keys. Idempotent upserts.
Ingestion adapters
01GitHub, 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.
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)
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.