Skip to main content

Production diff-detective: when something breaks, what actually changed?

Project description

WhyChanged (whychanged)

Production diff-detective. When monitoring tells you something broke, what actually changed?

Why

Production incidents almost always trace back to something that happened in the recent past — a deploy, a feature-flag toggle, a config push, a dependency bump. But your dashboards tell you what's broken, not why. WhyChanged correlates change sources in a time window around an incident and ranks them by likelihood of having caused it.

Status

v0.1.0 beta. Ships the engine + a local Git change provider + the GitHub Deployments cloud provider. Other cloud plugins (LaunchDarkly, Render, Vercel, ArgoCD, Kubernetes events) land in v0.2+.

What v0.0.1 does

  1. Asks every configured ChangeProvider for changes in the requested window.
  2. Scores each change with a deterministic heuristic:
    • Recency — exponential decay relative to the incident time (30-min half-life)
    • File scope — bonus when a change touches files that belong to the affected service
    • Kind weight — schema migrations and config changes outscore feature-flag toggles when all else is equal
  3. Sorts by score and emits a JSON + Markdown report.

CLI

whychanged version

# Rolling 30-minute window from now
whychanged explain --repo .

# Explicit incident time + service scope
whychanged explain --repo . \
  --since 1h \
  --incident-at 2026-05-08T14:30:00+00:00 \
  --service api \
  --service-file src/api/models.py \
  --service-file src/api/views.py

# v0.1: combine local commits with GitHub Deployments events
export WHYCHANGED_GITHUB_TOKEN=ghp_...
whychanged explain --repo . \
  --since 2h \
  --github-repo myorg/api \
  --github-environment production

Output: .whychanged/report.json (versioned, machine-consumable) + .whychanged/report.md (human companion).

Change kinds

Kind Source examples
deploy Git commit on main, container release, cloud build
feature-flag LaunchDarkly / Statsig / homegrown flag toggle
config Kubernetes ConfigMap, env-var change, infra apply
dependency package.json / requirements update, image bump
schema Database migration / schema change
unknown Catch-all for unclassified providers

Roadmap

  • v0.2 — GitHub App installation-token auth + incident-aware webhook receiver: post the top culprit to Slack / Datadog
  • v0.2 — outcome-trained ranker (replaces the deterministic heuristic with a learned model once we have "was the top rank actually the culprit?" data)
  • v0.3 — service-graph integration (rank higher when a change is upstream of the affected service)

Apache-2.0 license. See CHANGELOG.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

devtrust_whychanged-0.1.0.tar.gz (19.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

devtrust_whychanged-0.1.0-py3-none-any.whl (16.7 kB view details)

Uploaded Python 3

File details

Details for the file devtrust_whychanged-0.1.0.tar.gz.

File metadata

  • Download URL: devtrust_whychanged-0.1.0.tar.gz
  • Upload date:
  • Size: 19.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for devtrust_whychanged-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3156c8ad60a18cf981e2c2aa0e14f1dc802670e18600325c22c1e2f36c5f275e
MD5 3150cfc803b8002d96369d076d8bbbe1
BLAKE2b-256 730a1ad550723d798f1083d23091a409192165a2e51a8d0578496464af6dcca3

See more details on using hashes here.

Provenance

The following attestation bundles were made for devtrust_whychanged-0.1.0.tar.gz:

Publisher: release.yml on AbdullahBakir97/DevTrust

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file devtrust_whychanged-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for devtrust_whychanged-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 423dde37755d18a4b5f595d527bc64a3d70972d65f0d08ffb7d84de890e36905
MD5 2935b8b3d46917551764dc7a20d91420
BLAKE2b-256 67181040da8b4ad1a2105fb421e9c7cb9f698a4aff4196b8fe07b08abe88413b

See more details on using hashes here.

Provenance

The following attestation bundles were made for devtrust_whychanged-0.1.0-py3-none-any.whl:

Publisher: release.yml on AbdullahBakir97/DevTrust

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page