How-to: find where to change code in an unfamiliar codebase, and wrap external tools so
their failures are safe. Adapted from docs/code-map.md, tools/dep_graph.py,
tools/decompctx.py, and tools/download_tool.py in the Melee for Mac snapshot
(t3dotgg/melee4mac, head a276aeb70f9879204d891d967f1c9442523568e1). Companion guide:
09-verification-contracts.md.
Part A — finding the right code
- Start from behavior, not from files. Melee's code map is a table of tasks → entry file → named functions → deeper guide (docs/code-map.md). Before grepping, write one sentence describing the behavior you need to touch; if you cannot, you are not ready to edit.
- Read the types before guessing names. Melee keeps structure definitions in
types.hper module and treats offset-named or address-named identifiers as clues, not placeholders to rename on a hunch: a matching executable does not establish that a newly chosen source name describes the behavior correctly (docs/code-map.md). In any codebase: confirm a field's meaning from its reads and writes, not its name. - Build a dependency view from real artifacts when source navigation is incomplete. For callback-
or table-driven code, a source grep misses connections. Melee compiles all units
(
ninja all_source), then derives file-level dependencies from object symbols withtools/dep_graph.py --deps/--rdeps/--cycles/--chain, cross-checking unit lists betweenconfigure.pyand the generated build config and erroring on any mismatch (tools/dep_graph.py; usage in docs/code-map.md). The equivalent in most projects:nm,objdump, an LSP's references, orcompile_commands.jsonfor include paths. - Generate a self-contained context for one unit of work.
tools/decompctx.pyexpands one source file plus its headers into a single context file with a dependency sidecar, so an agent or reviewer sees everything relevant without the whole tree (tools/decompctx.py; Ninja wires it per file in docs/code/context-generation.md). For your task: assemble the one file plus its headers/config, and record what you excluded. - Know what your navigation output does not tell you. Melee documents that its
object graph is not a call graph and says nothing about callback timing
(docs/code-map.md), and that its context expander does not evaluate
#if(docs/code/context-generation.md). State the equivalent limits of whatever view you produced. - Write the map down for the next reader. After resolving an unfamiliar area, add
the entry: task → file → function → guide, as
docs/code-map.mddoes. Ownership is documentation plus explicit scopes — Melee gives each parallel agent a worktree and an owned-file list (AGENTS.md).
Part B — safe external-tool adapters
- One module per tool, with a URL/source table.
tools/download_tool.pymaps six tool names to small per-tool URL functions handling OS/arch naming (tools/download_tool.py). Keep per-tool quirks in one place. - Download to a temp file in the destination directory, then atomic-replace. The
staged file is chmod'ed, size-checked against
Content-Length, and swapped in withPath.replace; afinallyunlink removes residue (tools/download_tool.py). An interrupted download leaves the previous working tool intact — tested for both a short response and a mid-copy exception (tools/tests/test_download_tool.py). - Detect truncation explicitly. Sized HTTP reads can reach EOF without an
IncompleteReaderror, so compare received bytes toContent-Lengthand raise with both numbers (tools/download_tool.py, note at tools/tests/test_download_tool.py). The same applies to any partial file your tools produce: check the expected size or a footer before accepting it. - Handle the environment failure you actually have, narrowly. The certificate
retry fires only on
CERTIFICATE_VERIFY_FAILEDand exits 1 with an install hint when the fallback package is missing (tools/download_tool.py). - Discover tool binaries through a fallback chain.
find_nm_toolprefers the project's bundled binary, then cross-toolchain, devkit, LLVM, and systemnm, and raises a message naming the options (tools/dep_graph.py). Pin what you pin; fall back where fallback is safe. - Test the failure cases, not just the happy path. The download suite asserts the old tool survives each failure and that no temp files remain (tools/tests/test_download_tool.py). Your adapter is done when its worst day is a clean nonzero exit and unchanged state.
Acceptance evidence
- For navigation: you can name the file and function you will change, the callers and relationships inspected, and what your view cannot show.
- For adapters: a test run showing a failed download leaves the previous tool byte- identical and the directory free of temp files. Note that Melee's guarantee covers single-file downloads only; its zip path extracts in place (tools/download_tool.py) — a boundary worth checking in any adapter you copy.
Troubleshooting
If a navigation tool reports nothing, build its inputs first — dep_graph.py stops
with "Run ninja all_source" when objects are missing (tools/dep_graph.py).
If a context or generated file is stale after a failure, Melee clears per-run state at
the start of each invocation and writes output atomically
(tools/decompctx.py); copy that order. If a check keeps passing when
it should fail, see guide 09 step 7: report what the environment could actually verify.