Impact Check — Code Change Impact Analysis
Repo profile — read
.claude/repo-profile.mdfirst. This skill is repo-agnostic; arc is the reference implementation. The monorepo layout, package naming, and paths below (packages/,providers/,runtimes/,blocklets/) are arc's — map them to the consuming repo's structure via the profile.
Analyze code changes and find related areas in the codebase that may also need modification.
Input Modes
Parse $ARGUMENTS to determine the diff mode:
| Input | Mode | Diff Command |
|---|---|---|
| (empty) | working-tree | git diff HEAD |
--branch |
current branch vs main | git diff $(git merge-base <main> HEAD)..HEAD |
--branch <name> |
named branch vs main | git diff $(git merge-base <main> <name>)..<name> |
--branch <name> --base <base> |
branch vs custom base | git diff $(git merge-base <base> <name>)..<name> |
contains .. |
commit range | git diff <from>..<to> |
| other | single commit | git diff <ref>^..<ref> |
When detecting the main branch, check which of main or master exists.
Analysis Process
Step 1: Collect Changes
- Determine diff mode from arguments
- Run the appropriate
git diffcommand (with--statfor summary, and full diff for content) - List all changed files and summarize: N files changed, +X -Y lines
- If no changes found, report "Nothing to analyze" and stop
Step 2: Understand What Changed
For each changed file, read the diff and identify:
- Interface/type changes: function signatures, type definitions, exported types
- Export changes: added, removed, or renamed exports
- Behavioral changes: logic changes that could affect callers
- Configuration changes: package.json, tsconfig, linter/formatter config, etc.
- Schema/model changes: data structure modifications
Step 3: Find Related Code
For each significant change identified in Step 2:
- Import/reference search: Use Grep to find every file that references the changed module.
- For a deleted or renamed file/export, grep the bare basename or symbol (e.g.
agent-core,deriveAgentTools) to get the full candidate set — then filter comments in Step 4 by reading. Do not rely on a single-lineimport … from/require(…)regex: it misses multi-line imports (where thefrom "…"line has noimportkeyword) and re-exports, silently dropping real breaks. - Also search string / dynamic references that no import regex catches:
readSource("…/foo.ts"),readFileSync/join/resolvewith the file path, dynamicimport(…), and worker/route path literals. Cross-package breakage most often hides here (e.g. aruntimes/node/test/**thatreadSource()s a deletedproviders/**file).
- For a deleted or renamed file/export, grep the bare basename or symbol (e.g.
- Symbol usage search: For changed/removed exports, Grep for their usage across the codebase
- Test file check: For each changed file
src/foo.ts, check iftest/foo.test.tsexists and whether it was also modified - Documentation check: If interfaces or public APIs changed, check if README or docs reference them
- Conformance test check: If the repo's Custom Impact Checks (
.claude/repo-profile.md) declare a provider conformance suite, and a provider changed, verify its conformance fixture was updated - Caller check (new exports): For each added export/function/param, grep its call sites repo-wide. Zero callers inside the repo — and not a public API/SDK re-export — is a speculative abstraction with no consumer; flag it. A lower layer nothing calls should not land on its own; the author should point to the consumer, or the follow-up change that adds it.
- Parity check — mirror & registration: Two flavors, both cross-file invariants a self-contained diff won't reveal:
- Cross-runtime mirror: multi-target builds must stay in sync — a change that touches one deployment target or a shared cross-target provider means the sibling target(s) need the same semantic. A one-sided change is behavior drift between targets unless intentional. See the repo's Deployment Environments section (
.claude/repo-profile.md) for which targets exist. - Declaration ↔ dispatch/renderer: the diff adds a variant to an enum / union type / registry / factory (a new widget, message type, provider kind, event, …) in one package → grep the consumer that switches on it (dispatch table,
switch, renderer map, handler registry — often in a different package) and confirm it gained the matchingcase/handler. This is the inverse hazard of reverse-reference: deleting breaks compilation loudly, but adding-without-wiring compiles clean. Adefault/fallback branch (renders "Unknown", silent no-op, drops the message) swallows the missing case, socheck-typesand build stay green and the gap only shows at runtime as a degraded/absent result. Also check the reverse — a new dispatchcasefor a variant the declaration side never added.
- Cross-runtime mirror: multi-target builds must stay in sync — a change that touches one deployment target or a shared cross-target provider means the sibling target(s) need the same semantic. A one-sided change is behavior drift between targets unless intentional. See the repo's Deployment Environments section (
Use the Agent tool with subagent_type=Explore to parallelize searches when there are many changed files (>5).
Step 4: Evaluate Impact
For each related file found in Step 3, Read the relevant sections and assess:
- Will it break? Type errors, missing imports, incompatible API calls
- Will it behave incorrectly? Logic assumptions that no longer hold
- Is it incomplete? Tests that don't cover the new behavior, docs that are now stale
- Redefinition ≠ break: a symbol matched by name because a new or ported module now defines it (common after a rename/rewrite — e.g.
runAgentmoved to a new provider) is not a break. Only a dangling reference — one that still resolves to the deleted/changed definition — breaks. Confirm by reading which module the reference actually resolves to before flagging 🔴; a name match alone is noise.
Step 5: Output Report
## Impact Analysis — <scope description>
<N> files changed | +X -Y lines | <mode: working-tree / branch X vs Y / commit abc1234 / ...>
### Changes Summary
- brief bullet points of what changed and why it matters
### 🔴 MUST — Requires Modification
> Files that will break or produce incorrect behavior if not updated.
- **`path/to/file.ts:42`** — <specific reason>
Changed: `oldThing` → `newThing`, but this file still references `oldThing`
### 🟡 SHOULD — Recommended to Check
> Files that likely need updates but won't immediately break.
- **`path/to/file.test.ts`** — test does not cover the new <behavior>
- **`README.md`** — example code references old API signature
- **`path/to/new-export.ts:12`** — new export `fooBar` has zero call sites repo-wide and isn't a public re-export (speculative — confirm a consumer exists or lands in a follow-up)
- **`runtimes/cloudflare/…`** — node side changed `<behavior>` but the CF mirror was not updated (cross-runtime parity)
- **`providers/…/dispatch.ts`** — new variant `fooKind` added to the enum/registry in `types.ts` but the consumer switch has no matching `case`; falls through to the `default` (renders "Unknown"/no-op) — compiles clean, degrades at runtime (declaration ↔ dispatch parity)
### 🟢 OK — No Action Needed
> Confirmed these related files are unaffected.
- `path/to/other.ts` — imports the module but doesn't use the changed API
Important Rules
- Be specific: Every finding must include a file path, line number (when possible), and concrete reason
- No false alarms: Only flag something as 🔴 MUST if you've confirmed the incompatibility by reading the code. When uncertain, use 🟡 SHOULD
- Scope to 1 hop: Only analyze direct dependents of changed files, not transitive dependencies
- Skip noise: Ignore changes that are purely formatting, comments, or whitespace
- Respect project conventions: This is a
<package_manager>monorepo. Cross-package impacts within the repo's monorepo layout are the highest-value findings — see the repo's Custom Impact Checks section (.claude/repo-profile.md) for which package boundaries matter - Fast exit: If all changes are documentation-only, test-only, or config-only with no code impact, report 🟢 OK immediately
Project-Specific Checks
On top of the universal steps above, run the repo's Custom Impact Checks — the domain-specific
reverse-reference checks documented in .claude/repo-profile.md. Arc's are the AFS/AUP-specific ones
(e.g. @aigne/afs importers, runProviderTests / test/conformance.test.ts, AUP widget dispatch
parity, the cross-runtime mirror, joinURL from ufo) — read that section rather than assuming
this list, since a different repo's profile will name entirely different checks.