OverviewGetting startedInstallationComponentsFoundationsCore and stateTheming and layoutAgent toolingAI toolingChange impactRecipesArchitectureRoadmapHelp and releasesAnalyzer and agentsAI toolingChange impact

How it works

oddkin-impact (in @oddkin/analyzer) takes a snapshot of each revision’s built packages: the Custom Elements Manifest, oddkin.metadata.json, the package exports, and a hash of each module they name. It reads these files and runs none of the code. Each change between two snapshots is classified:

  • Incompatible: a removed component, property, attribute, event, method, slot, part, CSS property, custom state, registration, export, or token; a token whose type or unit changed; a property whose values narrowed.
  • Review: any other change to a contract, such as a token value, a template, a style, or a widened type. A person decides.
  • Informational: an addition, or a change to descriptions only.

From each change it follows the dependencies (a style that reads a token, a definition that uses a style, a component built with another) to the components it affects. Their examples are the checks it selects, each with the path that selected it. A check passes only when every run of it passed; a check that did not run is never shown as passing.

Terminal
# A snapshot of each revision's built package directories
npx oddkin-impact snapshot <package-dir>... --out base.json
npx oddkin-impact snapshot <package-dir>... --out head.json
# The changes, the affected components, and the selected checks
npx oddkin-impact compare base.json head.json --markdown report.md --json report.json

--theme and --inspection add a theme’s tokens to a snapshot. --results merges the results of the checks you ran, and compare then exits with 1 when one failed. Everything runs locally: there is no hosted service, and nothing is published.

A recorded change

In this repository, scripts/impact-demo.mjs makes a real change and reports on it. In a temporary worktree it commits two edits on a base commit (the menu’s item part becomes menuitem, and the default theme’s specimen surface gets lighter), builds both revisions with their own build steps, compares them, and runs the selected checks on the head’s build in three browsers. This page is generated from the run recorded in docs/impact-demo.

Base: 35b6dcd2e327. Head: the base and 2 commits:

The commits of the recorded change
CommitSubjectFiles
d74d1f391f9cMenu: name the item part after its role, menuitempackages/components/src/menu/menu.template.ts, packages/components/src/menu/menu.ts
749a34f00b91Theme: a lighter specimen surfacepackages/tokens/themes/default.theme.json

6 changes: 1 incompatible, 4 review, 1 informational. 4 components affected, with no coverage gaps. 29 checks selected: 29 passed, in Chromium, Firefox, and WebKit.

What changed

Renaming the part breaks a consumer’s odd-menu::part(item) rule, and no test notices. Items are matched by id, so without a migration record a rename is a removal and an addition: the report notes the likely rename, as the two parts have the same contract, and still counts the removal.

Changes, incompatible first
ItemClassificationChangeReason
part:odd-menu#itemincompatibleremovedremoved; possible rename to part:odd-menu#menuitem (unconfirmed)
class:odd-menureviewchangedclass changed
template:@oddkin/components/dist/menu/menu.template.js#menuTemplatereviewchangedtemplate changed
theme:basereviewchangedtheme changed
token:color.surface.specimenreviewchangedvalue or definition changed
part:odd-menu#menuiteminformationaladdedadded

What it affects

Each path runs from a changed item to the component it reaches.

Affected components, each with the path that reaches it
ComponentPath
odd-comboboxtoken:color.surface.specimen → style:@oddkin/components/dist/combobox/combobox.styles.js#comboboxStyles → definition:odd-combobox → component:odd-combobox
odd-menuclass:odd-menu → component:odd-menu
odd-pickertoken:color.surface.specimen → style:@oddkin/components/dist/combobox/combobox.styles.js#comboboxStyles → definition:odd-picker → component:odd-picker
odd-split-buttonclass:odd-menu → component:odd-menu → definition:odd-split-button → component:odd-split-button

What checks it

The examples of the affected components, run on the head’s build. The report lists each check with its path.

Selected checks, by component
ComponentExamplesResult
odd-comboboxchildren, default, disabled, grouped, inForm, loading, multiple, readonly, selectAll, serverFiltered, views11 passed in Chromium, Firefox, and WebKit
odd-menucontextMenu, default, disabled, fromData, glyphOnly5 passed in Chromium, Firefox, and WebKit
odd-pickerdefault, disabled, empty, inForm, list, listMultiple, loading, multiple8 passed in Chromium, Firefox, and WebKit
odd-split-buttondefault, disabled, fromData, loading, secondary5 passed in Chromium, Firefox, and WebKit

Every selected check passed, and the report still marks part:odd-menu#item incompatible: passing checks do not make a contract change compatible.

What agents read

The agent kits of both revisions, packaged with the same oddkin-kit, differ where the change does, so an agent that reads the head’s kit finds the new part and the new value. Each kit.json holds a fingerprint of the kit’s inputs (inputs) and the hash of the metadata it was written from (sha256), so a kit that no longer matches its package is detectable.

Agent-kit files that differ between the revisions
FileChange
ai/kit.jsoninputs changed
ai/references/tokens/semantic.mdcolor.surface.specimen: light: #efedfc; dark: #29263d → light: #f3f1fd; dark: #29263d
components/kit.jsoninputs and sha256 changed
components/references/components/odd-menu.mditem → menuitem
components/references/tokens/semantic.mdcolor.surface.specimen: light: #efedfc; dark: #29263d → light: #f3f1fd; dark: #29263d

Reproduce it

In a checkout of the repository:

Terminal
npm install
npm run build
node scripts/impact-demo.mjs --base 35b6dcd2e327 --run

The files go to .oddkin/impact/demo; --record <dir> copies the ones recorded here. The script exits with 1 when a selected check fails.

The evidence

What the site’s claims rest on, where each is kept:

  • CI in three browsers

    Each push to main and each pull request: lint, type checks, the build, the unit tests, the browser and end-to-end tests in Chromium, Firefox, and WebKit, the packed packages, and a change-impact report against its base in the job summary.

  • Fresh installs

    New Vite, React, Vue, Svelte, and Angular projects install the packed packages and their own build tools, type-check when they use TypeScript, and are tested from their production builds. Each week, the same tests install the published packages from npm.

  • Change-impact analysis

    How snapshots, classifications, dependency paths, and check states work, and what is not built yet.

  • Architecture decisions

    Every decision record, with its area and status, as the records give them.

  • The recorded run

    The patch, the report in Markdown and JSON, and the kit diff this page is generated from.

Limits

  • The snapshot and report formats are not frozen: they can change in a minor release (ADR 0047).
  • A path is only as complete as its inputs. A module whose source was not supplied, a package that was not read, or a dynamic definition is listed as a coverage gap, and widens the selection to every example of its package.
  • Visual differences and component-family mappings are not compared yet.
  • A library described only by a standard Custom Elements Manifest gets its changes and affected components; it gets checks where it publishes examples (libraries not built with Oddkin).