AI Workflows: Dependencies

mapping what your code relies on and what relies on it

1. Summary

Before upgrading a library, changing a shared utility, or splitting a module, understand what depends on what. Dependency analysis answers: what does this component rely on, what relies on it, and what breaks if it changes. A depend.md file targets the analysis: it names the component under scrutiny and asks for a specific type of dependency map. Two directions matter:

2. depend.md Structure

# Dependency Context

## Target
Component, module, or function to analyze: [name and path]

## Direction
[ ] Outgoing - what does the target depend on?
[ ] Incoming - what depends on the target?
[ ] Both

## Scope
Files and directories to search: [list]
Files to exclude: [list]

## Output Format
List as: [dependent] -> [dependency], one per line.
Cite file:line for each relationship.
If a dependency is external (crate, package, stdlib), label it as such.

3. Types of Dependency Questions

QuestionWhy it matters
What does [module] import, directly and transitively? Understand the full footprint before isolating or testing it
What files import [module]? Know the blast radius before changing a public API
If [function] signature changes, what breaks? Plan the update scope before making the change
Is [package] used anywhere besides [file]? Determine if removing a dependency is safe
What would need to move if I extracted [module] into a library? Plan a library extraction before touching any files

4. Example Prompts

Map callers before a signature change:
Read depend.md.

Map all callers of [function_name] in [file.rs] across the codebase.
For each caller, state what it passes as arguments and what it does with
the return value. Cite file:line for each. Do not propose any changes.
Incoming dependencies before moving a module:
Read depend.md.

I plan to move [module] from [current_path] to [new_path].
List every file that imports it, references it by path, or links to it
(including HTML script tags and CSS links if applicable).
Cite file:line for each reference.
Library extraction planning:
Read depend.md.

I want to extract [module] into a standalone library.
List everything it depends on that would need to move with it.
Separately, list everything that depends on it that would need updating.
Do not propose how to do the extraction yet - just the dependency map.
Checking for unused external dependencies:
Read depend.md.

[package/crate] appears in [Cargo.toml / requirements.txt / package.json].
Find every file in scope that imports or uses it. If it appears nowhere,
confirm that it is safe to remove.

5. After the Dependency Map

A dependency map is a planning artifact, not a change. Use it to scope the work, then start a new session for the change itself - referencing the map as explicit context:
The dependency analysis found these callers of [function]: [paste list].

I am now changing the signature of [function] to [new signature].
Update the callers in this order: [ordered list]. Update one at a time,
stop after each so I can verify, then ask before continuing to the next.
Starting a new session with the map as explicit input prevents Claude from re-deriving the dependency structure and potentially missing a reference the analysis already found.

6. Case Study: CppNoSqlDB

This dependency map was built before any structural work on CppNoSqlDB. The goal was to understand which packages are hubs - high-impact, many dependents - and which are leaves, so that later work could be sequenced from the outside in rather than discovering ripple effects during edits. The map is the deliverable; nothing is changed here.

depend.md

# Dependency Context

## Target
CppNoSqlDB -- C++ NoSql key-value database
All packages: DateTime, DbCore, Query, Edit, Persist, PayLoad, Utilities, Executive

## Direction
Both: map outgoing dependencies (what each package includes) and
incoming dependencies (what includes each package).

## Scope
Packages in scope:
  DateTime/    DbCore/    Query/    Edit/
  Persist/     PayLoad/   Utilities/   Executive/
  TestApplication/   TestClassProj/

Label any package outside this list as external.
Do not follow includes into external packages.

## Output Format
Outgoing: [package] -> [packages it includes directly], file:line for each
Incoming: [package] <- [packages that include it], file:line for each
Hubs:   packages with 3 or more direct dependents
Leaves: packages with no intra-package dependencies
Transitive closure: tree from TestApplication showing full include chain;
  mark repeated nodes with [seen] to avoid cycles.

Prompt 1 - direct dependencies

Read depend.md.
Read Executive/NoSqlDb.h.
Read DbCore/DbCore.h.
Read Query/Query.h.
Read Edit/Edit.h.
Read Persist/Persist.h.
Read PayLoad/PayLoad.h.
Read TestApplication/TestApplication.cpp.

Map all direct package-to-package dependencies in both directions.
For each package list what it includes (outgoing) and what includes it (incoming).
Cite file:line for each relationship.
Identify hubs and leaves as defined in depend.md.

Result 1

-- Outgoing dependencies --

DateTime      -> (none -- leaf)
Utilities     -> (none -- leaf)
DbCore        -> DateTime           (DbCore.h:47)
PayLoad       -> DbCore             (PayLoad.h:41-42)
               -> XmlDocument [ext] (PayLoad.h:39-40)
Query         -> DbCore             (Query.h:33-34)
Edit          -> DbCore             (Edit.h:26)
               -> Query             (Edit.h:27)
               -> DateTime          (Edit.h:28)
Persist       -> DbCore             (Persist.h:30)
               -> Query             (Persist.h:31)
               -> DateTime          (Persist.h:32)
               -> XmlDocument [ext] (Persist.h:33-34)
Executive     -> DateTime           (NoSqlDb.h:18)
               -> DbCore            (NoSqlDb.h:19-20)
               -> Edit              (NoSqlDb.h:21)
               -> Persist           (NoSqlDb.h:22)
               -> Query             (NoSqlDb.h:23)
               -> Utilities         (NoSqlDb.h:24-25)
               -> XmlDocument [ext] (NoSqlDb.h:26-27)
TestApplication -> Executive        (TestApplication.cpp:17)
               -> PayLoad           (TestApplication.cpp:18)

-- Incoming dependencies --

DateTime      <- DbCore (DbCore.h:47), Edit (Edit.h:28),
                  Persist (Persist.h:32), Executive (NoSqlDb.h:18)
DbCore        <- Query (Query.h:33-34), Edit (Edit.h:26),
                  Persist (Persist.h:30), PayLoad (PayLoad.h:41-42),
                  Executive (NoSqlDb.h:19-20)
Query         <- Edit (Edit.h:27), Persist (Persist.h:31),
                  Executive (NoSqlDb.h:23)
Edit          <- Executive (NoSqlDb.h:21)
Persist       <- Executive (NoSqlDb.h:22)
PayLoad       <- Executive/Executive.cpp (Executive.cpp:16),
                  TestApplication (TestApplication.cpp:18)
Utilities     <- Executive (NoSqlDb.h:24-25)
XmlDocument   <- Persist (Persist.h:33-34), PayLoad (PayLoad.h:39-40),
                  Executive (NoSqlDb.h:26-27)

-- Hubs (3 or more direct dependents) --

DbCore   5 dependents: Query, Edit, Persist, PayLoad, Executive
Query    3 dependents: Edit, Persist, Executive

-- Leaves (no intra-package dependencies) --

DateTime, Utilities

Prompt 2 - transitive closure

Show the transitive closure from TestApplication.
List every package reachable from its includes as an indented tree.
Mark repeated entries with [seen].
Summarize the full package set at the end.

Result 2

TestApplication
  ├── Executive/NoSqlDb.h     (TestApplication.cpp:17)
  │   ├── DateTime            (NoSqlDb.h:18)
  │   ├── DbCore              (NoSqlDb.h:19-20)
  │   │   └── DateTime        [seen]
  │   ├── Edit                (NoSqlDb.h:21)
  │   │   ├── DbCore          [seen]
  │   │   ├── Query           [seen below]
  │   │   └── DateTime        [seen]
  │   ├── Persist             (NoSqlDb.h:22)
  │   │   ├── DbCore          [seen]
  │   │   ├── Query           [seen below]
  │   │   ├── DateTime        [seen]
  │   │   └── XmlDocument     [external]
  │   ├── Query               (NoSqlDb.h:23)
  │   │   └── DbCore          [seen]
  │   ├── Utilities           (NoSqlDb.h:24-25)
  │   └── XmlDocument         (NoSqlDb.h:26-27) [external]
  └── PayLoad                 (TestApplication.cpp:18)
      ├── DbCore              [seen]
      └── XmlDocument         [seen]

Full package set reachable from TestApplication:
  DateTime, DbCore, Query, Edit, Persist, PayLoad, Utilities
  XmlDocument [external]

Observations:
  DbCore is the most deeply embedded package: reached via 6 separate include paths
  (DbCore directly, Query, Edit, Persist, PayLoad, and the Executive aggregate).
  Any change to DbCore's public API requires verifying Query, Edit, Persist,
  PayLoad, and Executive -- the entire middle tier of the codebase.
  Utilities and DateTime are true leaves: changing either affects only the
  packages that directly include them, with no downstream ripple.