# ADR 052: Knip (Dead Code & Dependency Hygiene)

- HTML version: https://robbiepalmer.me/projects/recipe-site/adrs/056-knip
- Project: Recipe Site (https://robbiepalmer.me/projects/recipe-site.md)
- Status: Accepted
- Date: 2026-07-20
- Inherited from project: personal-site (https://robbiepalmer.me/projects/personal-site/adrs/052-knip.md)

# Additional Context for Recipe Site

The recipe pipeline is where Knip needed the most teaching, and where it then
found the most: its entry points are invisible to static import analysis — DVC
stages in `ml-pipelines/*`, Cloudflare Pages Functions, worker scripts, and the
viz tool's Vite app — so `knip.json` declares them explicitly (see
[personal-site ADR 052](/projects/personal-site/adrs/052-knip)). That
configuration is what let Knip confidently identify a superseded 12-component
cluster in the viz tool as dead, deleted on adoption.

The Workers also supplied the config's canonical false positive: workerd's
`cloudflare:workers`/`cloudflare:workflows` virtual modules are provided by the
runtime, not by any npm package, and Knip initially reported them as an
unlisted `cloudflare` dependency. They are now declared in `knip.json`, so the
unlisted-dependency check stays trustworthy for the case it exists to catch —
a Worker importing a package that only another workspace declares, which would
break on a lockfile reshuffle.

# Consequences

## Positive

* Genuinely undeclared dependencies in deployed Workers now fail CI instead of
  waiting for a lockfile change to expose them.
* The recipe pipeline's non-obvious entry points (DVC stages, Pages Functions,
  worker scripts) are documented in one config.

## Negative

* New pipeline stages, workers, or runtime-provided modules must be added to
  `knip.json` when their usage isn't a plain import; the failure mode is a
  loud false positive.

## Notes for Recipe Site

# Additional Context for Recipe Site

The recipe pipeline is where Knip needed the most teaching, and where it then
found the most: its entry points are invisible to static import analysis — DVC
stages in `ml-pipelines/*`, Cloudflare Pages Functions, worker scripts, and the
viz tool's Vite app — so `knip.json` declares them explicitly (see
[personal-site ADR 052](/projects/personal-site/adrs/052-knip)). That
configuration is what let Knip confidently identify a superseded 12-component
cluster in the viz tool as dead, deleted on adoption.

The Workers also supplied the config's canonical false positive: workerd's
`cloudflare:workers`/`cloudflare:workflows` virtual modules are provided by the
runtime, not by any npm package, and Knip initially reported them as an
unlisted `cloudflare` dependency. They are now declared in `knip.json`, so the
unlisted-dependency check stays trustworthy for the case it exists to catch —
a Worker importing a package that only another workspace declares, which would
break on a lockfile reshuffle.

# Consequences

## Positive

* Genuinely undeclared dependencies in deployed Workers now fail CI instead of
  waiting for a lockfile change to expose them.
* The recipe pipeline's non-obvious entry points (DVC stages, Pages Functions,
  worker scripts) are documented in one config.

## Negative

* New pipeline stages, workers, or runtime-provided modules must be added to
  `knip.json` when their usage isn't a plain import; the failure mode is a
  loud false positive.

---

Markdown index of this site: https://robbiepalmer.me/llms.txt
