From 08b54aa8db9d609cf1ed6b0c6593dc216b141b37 Mon Sep 17 00:00:00 2001 From: Eric Minish Date: Fri, 17 Jul 2026 23:02:57 -0400 Subject: [PATCH] Dogfood a repo architecture diagram into TECHNICAL.md; fix arch alt reproducibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Runs codeshot's own --embed on codeshot: a whole-repo file-dependency diagram (docs/architecture.svg) embedded into TECHNICAL.md via the codeshot:arch marker block, refreshable in place with codeshot --architecture --path . --embed TECHNICAL.md --format svg --out docs/architecture.svg Fix surfaced by dogfooding: the --architecture embed's alt text was derived from the checkout directory's basename, so the committed markdown varied by where the repo was cloned (a bare-worktree dir, "master", a branch name...). That both read wrong and broke --check portability — a fresh clone under a different dir name would report the committed diagram as drifted. The alt is now the fixed, path-independent "Architecture — generated by codeshot" (the repo name is redundant; the diagram already lives in that repo's own doc). Pinned by a test assertion. Tests: 75 passed; --check verified green against the committed diagram. --- TECHNICAL.md | 4 ++++ docs/architecture.svg | 32 ++++++++++++++++++++++++++++++++ render/callgraph.js | 8 +++++++- test/run.js | 5 +++++ 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 docs/architecture.svg diff --git a/TECHNICAL.md b/TECHNICAL.md index c9809de..e72d006 100644 --- a/TECHNICAL.md +++ b/TECHNICAL.md @@ -172,3 +172,7 @@ There is no service to restart, no rollback beyond `npm uninstall -g codeshot` / - A cyclic call graph (recursion, or A and B calling each other) can cause `--depth`'s transitive traversal to rediscover the root symbol or an already-drawn depth-1 node as a "from"/"to" endpoint of a deeper edge. This is harmless (graphviz just draws the extra edge; `dedupeEdges` still collapses exact repeats) but can occasionally show what looks like a redundant edge back into an already-visible node. - **`--architecture` mode's edges can be misattributed to the wrong file when symbol names collide.** `codegraph callees ` takes a bare name with no way to disambiguate which file's symbol is meant (unlike `codegraph node -f `, which does support this). In symbol mode this ambiguity affects exactly one user-chosen name — a corner case. In `--architecture` mode, Codeshot probes `codegraph callees` for every enumerated symbol in the whole repo, where generically-named methods (`render`, `init`, `get`, `run`, `String`) existing in more than one file is common, not rare, in most real codebases (confirmed: 12 duplicate names out of 500 probed symbols on a real ~1,900-node Go repo). `duplicateNameWarning` surfaces this on stderr with real examples from the current run, but Codeshot has no way to fix the underlying ambiguity — same as the other `codegraph` indexing gaps documented above, it can only draw what `codegraph` returns. - **`--architecture` mode's enumeration query (`codegraph query --json --limit -- ''`) has confirmed, inconsistent `--limit` behavior worth knowing before trusting it.** Without `--limit`, an empty-string query silently caps around 50 results regardless of actual repo size (confirmed on a real 1,870-node index). Passing a large `--limit` (confirmed with both 500 and 2000 against that same index) instead returns *every* result codegraph has — more than the requested number, not capped at it. Codeshot works around this by always passing a very large `--limit` to force the "return everything" behavior, then applying the real `--max-symbols` cap client-side — but the *order* codegraph returns results in in that case is unknown (untested whether it's insertion order, alphabetical, ID-based, or something else), so on a repo larger than `--max-symbols`, the kept subset should not be assumed to sample evenly across the whole repo — it could be clustered by file, directory, or however codegraph happens to have stored them. + + +![Architecture — generated by codeshot](docs/architecture.svg) + diff --git a/docs/architecture.svg b/docs/architecture.svg new file mode 100644 index 0000000..8fdc8f6 --- /dev/null +++ b/docs/architecture.svg @@ -0,0 +1,32 @@ + + + + + + +architecture + + + +render/callgraph.js + +render/callgraph.js + + + +test/run.js + +test/run.js + + + +render/callgraph.js->test/run.js + + +2 + + + diff --git a/render/callgraph.js b/render/callgraph.js index bfa9179..4aabd3b 100755 --- a/render/callgraph.js +++ b/render/callgraph.js @@ -768,7 +768,13 @@ async function main() { if (values.architecture) { const dot = await runArchitectureMode(repoPath, { limit, maxSymbols, maxRender }); - const alt = `${path.basename(path.resolve(repoPath))} architecture — generated by codeshot`; + // Fixed, path-independent alt: deriving it from the checkout's directory + // basename made the embedded markdown vary by where the repo was cloned + // (a bare-worktree dir, "master", a branch name...), which both read wrong + // and broke --check portability — a fresh clone under a different dir name + // would report the committed diagram as drifted. The repo name is redundant + // anyway; the diagram lives in that repo's own doc. + const alt = 'Architecture — generated by codeshot'; finishOutput(dot, { format, outFile, embedFile, check: values.check, markerId: 'arch', alt }); return; } diff --git a/test/run.js b/test/run.js index 925faed..52f0d6b 100644 --- a/test/run.js +++ b/test/run.js @@ -734,6 +734,11 @@ test('CLI --embed --architecture round-trips: writes image + block, --check then const md = fs.readFileSync(doc, 'utf8'); assert.match(md, //); assert.match(md, /!\[[^\]]*generated by codeshot\]\(codeshot-arch-[^)]+\.svg\)/); + // The arch alt must be path-independent (not the checkout dir basename), so + // the embedded markdown is reproducible across clones and --check is stable. + // Before the fix it was ` architecture — ...`. + assert.match(md, /!\[Architecture — generated by codeshot\]/); + assert.doesNotMatch(md, new RegExp(`!\\[${path.basename(path.resolve(repoRoot))} architecture`), 'alt must not leak the checkout dir name'); const imgName = md.match(/\]\((codeshot-arch-[^)]+\.svg)\)/)[1]; assert.ok(fs.existsSync(path.join(dir, imgName)), 'expected the image written next to the doc');