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
- Asks every configured
ChangeProviderfor changes in the requested window. - 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
- 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.
Metadata
Release files for devtrust-whychanged 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| devtrust_whychanged-0.1.0.tar.gz | 19.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| devtrust_whychanged-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 35.7 kB
Release files / devtrust_whychanged-0.1.0.tar.gz
| Download URL | devtrust_whychanged-0.1.0.tar.gz |
|---|---|
| Size | 19.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3156c8ad60a18cf981e2c2aa0e14f1dc802670e18600325c22c1e2f36c5f275e
|
|
BLAKE2b-256 checksum How to use checksums |
730a1ad550723d798f1083d23091a409192165a2e51a8d0578496464af6dcca3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 9, 2026.
Transparency logRelease files / devtrust_whychanged-0.1.0-py3-none-any.whl
| Download URL | devtrust_whychanged-0.1.0-py3-none-any.whl |
|---|---|
| Size | 16.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
423dde37755d18a4b5f595d527bc64a3d70972d65f0d08ffb7d84de890e36905
|
|
BLAKE2b-256 checksum How to use checksums |
67181040da8b4ad1a2105fb421e9c7cb9f698a4aff4196b8fe07b08abe88413b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 9, 2026.
Transparency log