@danielsimonjr/repo-tools 1.1.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,328 @@ All notable changes to this project are recorded in this file. The format follow
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [2.1.0] - 2026-10-01
10
+
11
+ `repo-tools check` is the new drift gate for the Markdown documents of a repository. It ports
12
+ `check.py` of the architecture-docs skill. The release also makes a literal `import()` a graph
13
+ edge, removes the 1.x depgraph pipeline, and adds an accept-list to the privacy check.
14
+ `docs/parity-check.md` lists the differences from the Python tool.
15
+
16
+ ### Added
17
+
18
+ - `repo-tools check --docs=<dir>`, the drift gate of the architecture documents. The command is
19
+ a port of `check.py` of the architecture-docs skill. The check reads the `## Verification`
20
+ tables of the Markdown files in the folder. The check builds a fresh graph, and the check
21
+ compares each claim with the graph. Exit 0 means that every claim matched. Exit 1 lists every
22
+ problem on standard error, one per line. A missing or empty docs folder is a problem. A
23
+ document without a Verification section is a problem. So are a section without a row, an
24
+ unknown claim, a count that the graph build declared unreliable, and a value that differs. A
25
+ document opts out when one of its lines is exactly `<!-- repo-map:no-verification -->`. A relative `--docs` path is
26
+ relative to the root, and an absolute path is used as given. The check reads
27
+ `map.duplicateAllowlist` and `map.verificationMarker` from the config file. Section 15 of
28
+ `docs/design.md` lists the differences from the Python tool. The smoke test has a `check` step.
29
+ `docs/parity-check.md` records the comparison with the Python tool on 11 repositories.
30
+ - The privacy check has an accept-list, `scripts/privacy-accepted.txt`, for a reviewed finding in
31
+ the commit history. A commit message cannot change after a merge, so a new commit cannot clear
32
+ a finding in it. An entry holds a full commit sha, one finding kind, one line of the message and
33
+ a reason. The entry accepts that finding only: no prefix, no wildcard, no whole-commit waiver,
34
+ and never a finding in a tracked file. An entry that accepts no finding is a finding
35
+ (`accepted-stale`). The check prints each accepted finding with its reason.
36
+
37
+ ### Changed
38
+
39
+ - A literal relative `import()` is an edge of the core graph. This reverses the known difference
40
+ in 2.0.0. A runtime call is a namespace use (`*`). A type-position `import('./c').Name` records
41
+ that name. `typeof import()` records no names. A template that contains `${`, and a specifier
42
+ that is not relative, are not edges. The parity record gives the merge rules. The verdict
43
+ against the Python tool is `repo_map-wrong`.
44
+ - A namespace import (`import * as ns`, `export * as ns`) counts every export of its target as
45
+ used, as a runtime `import()` does. The Python tool lists those exports as unused. A name that
46
+ a file mentions only in a comment is not an in-module reference. The Python tool counts the
47
+ comment. The parity record gives the measured effect. A test locks the namespace rule.
48
+ - The opt-out marker of `repo-tools check` must stand alone on a line. `check.py` opts a document
49
+ out when the marker is anywhere in its text. A document can quote the marker in a sentence, a
50
+ code span or a table cell. That document then skips its own table, and a stale claim passes in
51
+ silence.
52
+ `repo-tools check` opts out only when a line, trimmed, equals the marker. This changes the
53
+ result for a document that opted out from inside a sentence or a table cell: the check now
54
+ reads its claims. `repo-tools map` writes the marker alone on a line, so generated reports
55
+ still opt out. A blank `map.verificationMarker` matches no line. `docs/parity-check.md` records
56
+ the difference. The verdict is fail-closed.
57
+ - A bodiless `export function f(): T;` is not an export, as in the Python tool
58
+ (`repo_map-kept`). An overload plus an implementation records the name once.
59
+ - The 1.x depgraph pipeline is removed: the runner, the regex parser, the scanner, the inventory
60
+ reporter and the 1.x goldens. `repo-tools depgraph` stays an alias of `repo-tools map`.
61
+ `docs/fix-ledger-2.0.0.md` records which 1.x fixes the `map` tests lock, and which fixes have
62
+ no 2.0.0 meaning.
63
+
64
+ ### Fixed
65
+
66
+ - `src/check/claims.ts` and one test held the byte-order mark as an invisible U+FEFF character.
67
+ Both files now spell it as an escape sequence. A new test fails when a file under `src/`,
68
+ `tests/` or `scripts/` holds a literal U+FEFF.
69
+ - A named `export { name } from` writes one edge for that statement. The statement does not add a
70
+ second empty-imports edge to the same file.
71
+ - `write` refuses a symbolic link inside the output folder that points outside it.
72
+ - A skip-list folder under `src/` (`dist`, `build`, `coverage`, `node_modules`, `.git`) that
73
+ holds a source file produces a warning. The files stay out of the census. A root `build/` or
74
+ `dist/` folder stays silent.
75
+ - `--check-census` names the configured regenerate command. The test-coverage note names the
76
+ configured coverage-policy path.
77
+ - The config file accepts a top-level `$schema` key.
78
+ - The walk skip list is not module state. Each walk builds its own skip set.
79
+ - A type-position `import('./c').C` records the name `C`.
80
+ - In single-package mode, `main` and `exports` targets are roots after `dist/` maps to `src/`,
81
+ including when the file is not `src/index.ts`. A subpath root is the source of the export
82
+ target.
83
+ - Test coverage follows an import by package name, including the side-effect imports of the
84
+ resolved file.
85
+ - A workspace subpath uses the `exports` target, then `<sub>.ts`, then `<sub>/index.ts`.
86
+ - A package-name import is an edge in cycle detection, including the cyclic components in
87
+ `dependency-layers.json`.
88
+ - The comment mask treats `a++ / b / c` as division, and `if (x) /re/` as a regular expression.
89
+ - A bare `import './x'` together with `import('./x')` is one side-effect edge whose names are
90
+ `["*"]`.
91
+ - A dangling symbolic link is listed in `skippedLinks`.
92
+ - A `new URL` in a root config, and a `new URL('./x.js', import.meta.url)` launch, seed roots.
93
+ - A `.test.tsx` or `.spec.tsx` file is in the `tests` area.
94
+ - The repository scan of the privacy check passes again. A test fixture used an e-mail address
95
+ that the check rejects. Two trailers of the merge commit of the engine change hold a co-author
96
+ address and a name. The fixture now uses an allowed address. The accept-list records the two
97
+ trailers.
98
+
99
+ ## [2.0.0] - 2026-09-26
100
+
101
+ The unified engine. `repo-tools map` replaces the Python `repo_map.py` and depgraph 1.x with one
102
+ engine for TypeScript/JavaScript, Python, C# and Rust. On 11 public repositories, its four core
103
+ files are identical to the Python tool, apart from the deliberate differences that the parity
104
+ record lists. `repo-tools depgraph` stays as a deprecated alias through 2.x. The 1.x scan-scope
105
+ flags have no effect: `map` exits 1 on them, and the alias gives a warning.
106
+
107
+ ### Known differences
108
+
109
+ - The 2.0.0 release made no graph edge for a dynamic `import()`. That choice is reversed in
110
+ Unreleased: a literal relative `import()` is now an edge. On memoryjs, the release counted
111
+ one type-only cyclic component as 3 files, not 7. Test coverage counted a literal `import()`
112
+ in a test file as a load, and it still does.
113
+
114
+ ### Added
115
+
116
+ - `repo-tools map` (design decision D8): the command of the 2.0.0 engine. It writes each report
117
+ of the engine into the output folder, for TypeScript/JavaScript, Python, C# and Rust.
118
+ `repo-tools depgraph` is now its deprecated alias through 2.x, and prints one deprecation line.
119
+ The 1.x scan-scope flags (`--src`, `--tests`, `--exclude`, `--also-exclude`, `--all`/`-a`,
120
+ `--reachable-only`, `--include-tests`/`-t`) have no effect in 2.0.0. `map` exits 1 on them,
121
+ and the alias gives a warning and continues. The config section `map` is the new name of
122
+ `depgraph`, and a file with both sections exits 1.
123
+ - `map` (design decision D9): the duplicate allowlist and baseline and the coverage policy
124
+ default to `docs/architecture/`, never to the output folder. A root-relative `--out=../x`
125
+ writes outside the root.
126
+ - `map` gates: `--strict-orphans`, `--strict-census`, `--check-census`, `--check-duplicates`,
127
+ `--no-regen` and `--write-duplicate-baseline`, and the `preflight` and `report` hooks of the
128
+ extensions. `--strict-census` compares the census with a walk of the root. It finds a source
129
+ file on disk that git does not track. The duplicate gate works for TypeScript only, and says
130
+ so for another language. The `report` hook receives the core `dependency-graph.json`.
131
+ - `map --api-surface` (design decision D5): TypeScript keeps the 1.x report, and the
132
+ mini-repo report is byte-identical to the 1.x golden. Python and Rust list the surface names
133
+ of the entry file. C# exits 1 with the reason.
134
+ - Goldens for `map` (`tests/golden/map`, written by `scripts/update-map-goldens.ts`). The smoke
135
+ test (design 13.3) runs `map`.
136
+ - README and `docs/design.md` describe the 2.0.0 engine. The README gives `map`, the
137
+ `depgraph` alias, the report list of `map` and new query examples from the mono-repo fixture.
138
+ `docs/design.md` has a new section 14, "The 2.0.0 engine". Both documents in `docs/` start
139
+ with the `repo-map:no-verification` marker and give the reason: neither one makes a claim
140
+ about the graph of this repository.
141
+ - `docs/parity-2.0.0.md`: the parity record of the 2.0.0 engine on public repositories. On side
142
+ 1, the four core files are identical to the Python tool on 11 repositories, apart from the
143
+ two deliberate workspace differences on Mathts. A control shows that these two differences
144
+ cause all of the Mathts differences. Side 2 compares each extra with depgraph 1.x on
145
+ memoryjs, Mathts and universal-physics-tensor, and gives a verdict for each difference.
146
+ - `repo-tools query` reads the core graph of `map` (design decision D8), and refuses a 1.x graph.
147
+ `dependents`, `symbol-users` and `cycles` have the meaning of the Python tool. They read each
148
+ area of the graph, and a path that is not a file of the graph exits 1. `symbol-users` lists
149
+ files. `cycles` lists the simple cycles, and `cycles --components` lists the runtime and
150
+ type-only components. `is-public` reads `package-export-surfaces.json` only when it runs. The
151
+ browser-safety commands serve TypeScript/JavaScript only, and exit 1 with the reason for
152
+ another language. They now follow the workspace imports too, so they find a `node:` file
153
+ that another package reaches through an import of its package name.
154
+
155
+ - 2.0.0 engine, step 1: `src/map/discovery.ts` ports `repo_map/discovery.py` from the
156
+ architecture-docs skill. It holds the language detection, the file census and the area and
157
+ disposition rules. It refuses a repository in an unsupported language. The census comes from
158
+ `git ls-files`, or from a pruned walk. The 30 tests of its four test files are ported. Four
159
+ repositories give the same result in the port and in the Python tool: memoryjs, Mathts,
160
+ universal-physics-tensor and repo-tools. For all 3,717 files, the language, path, area,
161
+ disposition and line count agree. The file order is code-unit order on every operating system.
162
+ - 2.0.0 engine, step 2: the TypeScript reader (`src/map/parsing.ts`) and the lazy grammar loader
163
+ (`src/map/grammars.ts`), on tree-sitter-typescript 0.23.2. The 18 tests of `test_parsing.py` are
164
+ ported; a synthetic barrel file replaces the source test's absolute path. On 3,719 files of four
165
+ repositories, the port gives the same imports, exports, kinds and default export as the Python
166
+ reader, file by file.
167
+ - 2.0.0 engine, step 3: the C# and Rust readers (`parseCs`, `parseRs`), regex readers ported
168
+ with their exact behavior. Python's line-start anchor and `.` get exact translations. The 22
169
+ reader tests of `test_parsing_csharp.py` and `test_rust.py` are ported.
170
+ - 2.0.0 engine, step 4: the Python reader (`parsePy`) on tree-sitter-python 0.25.0, in place of
171
+ CPython's `ast`. The import order is the order of `ast.walk` (ast depth, then source position).
172
+ A module that does not parse raises `SyntaxError`. The 9 tests of `test_parsing_python.py` are
173
+ ported; 8 new tests pin the import order and the export forms against CPython's output. The
174
+ Python, C# and Rust readers match the Python tool file by file on 726 files. The files come
175
+ from 7 public repositories: PITS-MRAS, auto-memory, fermat-mcp and memvid (Python), IronClaw
176
+ (Rust), ui-mcp and Windows-mcp (C#).
177
+ - 2.0.0 engine, step 5: the resolvers (`src/map/resolvers.ts`) for TypeScript, Python, C# and
178
+ Rust, with Python's `posixpath` rules in `src/py.ts`. The Python standard-library list is the
179
+ `sys.stdlib_module_names` of CPython 3.13.15, as generated data. The 35 resolver tests of four
180
+ test files are ported.
181
+ - Tests: `tests/unit/node-compat.test.ts` also fails when `src/` uses the `Bun` global or a
182
+ `bun:` module, because `npx` runs the Node bundle. It found `Bun.spawnSync` in the map
183
+ discovery; the git file list now comes from `node:child_process`.
184
+ - 2.0.0 engine, step 6: the graph (`src/map/graph.ts`) and its schema (`src/map/schema.ts`).
185
+ It holds the classify-before-resolve buckets, barrel expansion, entry-point roots for four
186
+ languages, thin launchers, reachability and simple-cycle enumeration. The 29 tests of
187
+ `test_schema.py` and `test_graph.py` are ported. On 11 repositories and 4,456 files, the port
188
+ and the Python tool give the same dispositions, ordered edges, buckets, roots and warnings.
189
+ The empty-repo warning names the root, not its absolute path (output rule R4).
190
+ `pyproject.toml` is read with `smol-toml` 1.9.0, bundled and pinned.
191
+ - 2.0.0 engine: the end-to-end graph tests of C#, Python and Rust are ported (18 tests, from
192
+ `test_graph_csharp.py`, `test_python_repo_end_to_end.py` and `test_rust.py`).
193
+ - 2.0.0 engine, step 7: the four core artifacts (`src/map/artifacts.ts`). They are
194
+ `dependency-graph.json`, `file-inventory.json`, `duplicate-symbols.json` and
195
+ `unused-analysis.json`, with 27 ported tests. On 11 repositories, all 44 files are
196
+ byte-identical to the Python tool after the approved changes. The port writes LF line ends and
197
+ schema version 2.0.0, with no `generated` field. Warnings name no absolute root path. Paths
198
+ sort by code unit, and the Python tool sorts them in the Windows case-insensitive order.
199
+ - 2.0.0 engine: the artifact tests of C# and Rust are ported (16 tests, from
200
+ `test_csharp_repo_end_to_end.py`, `test_unused_csharp.py` and `test_rust_unused_caveat.py`).
201
+ The source tests that read a local repository are not ported. The side-1 parity run covers
202
+ that repository.
203
+ - 2.0.0 engine: the read-only queries (`src/map/query.ts`, from `repo_map/query.py`):
204
+ `loadGraph`, `dependents`, `symbolUsers` and `cycles`, with 23 ported tests. The query module
205
+ reads only the graph JSON. A test scans its imports and fails if a reader, resolver, grammar or
206
+ graph module is reachable. A 1.x graph is refused, because its major version is not 2.
207
+ - 2.0.0 engine: the simple-cycle enumeration moves to `src/map/cycles.ts`. The graph and the
208
+ queries share it. The Python tool keeps two copies of this algorithm. On 10 repositories, the
209
+ artifacts are byte-identical before and after the move.
210
+ - 2.0.0 engine (design decision D2): `dependency-graph.json` statistics also count the cyclic
211
+ components. The new keys are `runtimeCyclicComponents`, `typeOnlyCyclicComponents`,
212
+ `runtimeFilesInCycles` and `typeOnlyFilesInCycles`, after `circularDepsTruncated`. A cap never
213
+ truncates these counts. The Tarjan search moves from `src/depgraph/cycles.ts` to
214
+ `src/map/cycles.ts`, so depgraph and the core graph count components in the same way.
215
+ - 2.0.0 engine (design decision D2): for a TypeScript repo, the statistics also give the
216
+ per-kind export counts of depgraph. The keys are `totalClasses`, `totalInterfaces`,
217
+ `totalFunctions`, `totalTypeGuards`, `totalEnums`, `totalConstants` and `totalReExports`. The
218
+ core reader gives the kinds, so the counts come from one parser. On memoryjs, each file has
219
+ the same names of each kind as in depgraph 1.x. The totals differ for two reasons. The core
220
+ counts every area, and depgraph counts the `src` files only. Also, depgraph counts an
221
+ overloaded or merged name one time for each declaration.
222
+ - 2.0.0 engine (design decisions D3 and D5): `src/map/adapter.ts` changes the `src` files of the
223
+ graph into depgraph's parsed-file records. Then depgraph's analyzers run on the one graph for
224
+ each language. Each edge carries its resolved target. The new helper `targetOf` uses that
225
+ target, and a 1.x parse still resolves the specifier. The graph now also keeps each file's
226
+ export kinds, re-exports and re-export edges. The graph JSON does not write them. The records
227
+ have no workspace edges and no package name. The graph does not keep these facts.
228
+ - 2.0.0 engine (design decision D3): `src/map/layers.ts` writes `dependency-layers.json`, which
229
+ is depgraph's subsystem view built on the graph. The file holds `metadata`, `entryPoints`,
230
+ `modules`, `cyclicComponents` and `layers`. `modules`, `entryPoints` and `layers` hold the
231
+ `src` files, as in depgraph 1.x. `cyclicComponents` holds every area, so its counts agree with
232
+ the core statistics. The adapter now also gives each edge its written specifier, and the
233
+ names of each package or built-in import. On memoryjs, the modules, files, entry points and
234
+ layers are identical to depgraph 1.x, and each field difference has a recorded cause.
235
+ `generateJSON` gets three helpers (`modulesJsonOf`, `layersOf`, `entryPointsOf`), and its
236
+ output does not change.
237
+ - 2.0.0 engine (design decisions D3 and D5): `src/map/reports.ts` writes `DEPENDENCY_GRAPH.md`,
238
+ `dependency-graph.yaml` and `dependency-summary.compact.json` for each language. The
239
+ Markdown and the compact summary show the subsystem view with the core statistics. The YAML
240
+ is a copy of the core `dependency-graph.json` in YAML. The Markdown banner names
241
+ `repo-tools map`, and its table uses language-neutral labels. A language with no kind counts
242
+ gets no kind rows. In depgraph, `generateMarkdown` gets an optional `summaryRows` parameter.
243
+ Its cycle section counts the files of the listed components. The per-kind export counts of
244
+ `Statistics` are optional. After these changes, depgraph 1.x writes all 12 reports on
245
+ memoryjs byte-identical to a run before them.
246
+ - 2.0.0 engine (design decision D4): `file-inventory.json` also gives depgraph's `byPackage`
247
+ and `skippedLinks`, the links that discovery does not follow. A walk does not follow a folder
248
+ link. In a git work tree, discovery does not follow a tracked link (mode 120000) to a folder
249
+ or to a missing file. The new `gitTrackedLinks` reads the modes with `git ls-files --stage`. The
250
+ git branch has a test that makes a folder link when the host permits it. The other core
251
+ files of 10 repositories stay byte-identical.
252
+ - 2.0.0 engine (design decision D4): for a TypeScript repo, `duplicate-symbols.json` also
253
+ holds depgraph's classified lists: `runtime`, `types`, `classificationNote` and the four
254
+ summary counts. The allowlist is `<root>/docs/architecture/duplicate-allowlist.json`,
255
+ never a file in the output folder (D9). A declaration file (`.d.ts`) is no definer in the
256
+ classified lists, because it has no body. Another language gets an explicit
257
+ `classificationNote` and no classified lists. The adapter now gives each file its workspace
258
+ package, as depgraph 1.x does. On memoryjs, MathTS and universal-physics-tensor, each
259
+ classified entry is identical to depgraph 1.x. The one exception is a 1.x definer that is a
260
+ declaration file.
261
+ - 2.0.0 engine (design decisions D4 and D5): `src/map/markdown.ts` writes `FILE_INVENTORY.md`,
262
+ `duplicate-symbols.md` and `unused-analysis.md` for each language. Each report reads the
263
+ JSON files in the output folder. A TypeScript duplicate report keeps the depgraph renderer.
264
+ Another language gets the name-only list and the explicit note. The inventory and unused
265
+ reports have new text, because the 1.x text described a census of TypeScript files only. The
266
+ unused report also lists the dormant files of the core reachability.
267
+ - 2.0.0 engine (design decision D5): `src/map/coverage.ts` writes `TEST_COVERAGE.md` and
268
+ `test-coverage.json` for each language, with depgraph's analyzer. The name of a file decides
269
+ if it is a test. For TypeScript and JavaScript, the name is `*.test.*` or `*.spec.*`, as in
270
+ 1.x. For Python, the name is `test_*.py` or `*_test.py`. For C# and Rust, each file in the
271
+ tests area is a test. A test also covers a file that it loads with a literal `import()`, or
272
+ through a relative `dist/` path. The core graph has no edge for these loads. The coverage
273
+ policy is `<root>/docs/architecture/coverage-policy.json` (D9). The reader records the bare
274
+ side-effect imports and the literal `import()` specifiers of TypeScript. The graph JSON does
275
+ not write them. On memoryjs, MathTS and universal-physics-tensor, the tested files are the
276
+ same as in depgraph 1.x.
277
+ - 2.0.0 engine (design decision D5): `src/map/surfaces.ts` writes
278
+ `package-export-surfaces.json` for TypeScript with depgraph's public-surface rules. Fix: a
279
+ bare `export *` edge now keeps a `star` flag, and the adapter shows it as `*`, as 1.x does.
280
+ Before the fix, barrel expansion replaced the `*` with names. Then a name deep in an
281
+ `export *` chain was not public, which a test found. The layers module entries show star
282
+ edges as 1.x does. On memoryjs the surfaces are identical to 1.x. On MathTS and
283
+ universal-physics-tensor, each difference has a recorded cause.
284
+ - 2.0.0 engine (design decision D5): `package-export-surfaces.json` for Python and Rust, with a
285
+ `note` that gives the rule. A Python package lists its `__all__`, else the public names that
286
+ its `__init__.py` defines. A Rust library crate root (`lib.rs`) lists its `pub` items and the
287
+ names of its plain `pub use` statements. The new `pubUseNames` reads an alias only as the
288
+ whole word `as`, so a name such as `HashMap` keeps its letters. For C#, no file is written,
289
+ because C# has no rule for a public surface of a package.
290
+ - Dependencies (bundled, not installed by users): `web-tree-sitter` 0.27.0,
291
+ `tree-sitter-typescript` 0.23.2 and `tree-sitter-python` 0.25.0, pinned. The engine parses with
292
+ them in a later step. `src/ste/py.ts` moves to `src/py.ts`, because the engine also uses it.
293
+
294
+ ### Fixed
295
+
296
+ - `map`: the Rust `use` reader kept the error of the Python tool. The Python tool removes the white
297
+ space of a `use` path, then cuts the path at the letters `as`. So `HashMap` gave `H`, `wasm`
298
+ gave `w` and `task` gave `t`, and a cut path could resolve to the wrong module. The reader now
299
+ removes only an alias that is the whole word `as` and a name. On IronClaw, 139 names are
300
+ complete again. The internal edges of 14 files go to the correct modules, and the simple
301
+ runtime cycle count goes from 1667 to 1009. The fix is a deliberate difference from the
302
+ Python tool.
303
+ - Tests: the build test that runs `map` from the Node bundle writes `{"type": "module"}` next to
304
+ the bundle, as in the installed package. Without it, Node reads the nearest `package.json`
305
+ above the temporary folder. A stray one with no `type` makes Node write a warning to standard
306
+ error, and the test failed on such a machine.
307
+ - The code-docs gate passes (399 of 399 exported symbols have a doc comment). Seven exported
308
+ types had no doc comment. The doc comment of `resolvePath` was apart from its function,
309
+ because `targetOf` was in the space between them. `src/map/graph.ts` and `src/ste/index.ts`
310
+ wrote the type `import("node:fs").Dirent` in the code, which the tree-sitter TypeScript
311
+ grammar cannot parse. They now import the type `Dirent`.
312
+ - `map`: a workspace monorepo now has entry roots. The Python tool reads the root `package.json`
313
+ only, so each workspace source file showed as an orphan. The engine now also reads the
314
+ `package.json` of each workspace package, then the extra entries of depgraph, then a
315
+ `src/index.*` file. The workspace roots are a deliberate difference from the Python tool. On
316
+ MathTS, the roots go from 0 to 1167, and each disposition equals depgraph 1.x.
317
+ - Build (design decision D7): `scripts/build.ts` now writes the three tree-sitter `.wasm` assets
318
+ next to `dist/cli.js`, under the names that the bundle refers to. Before this fix, the build
319
+ kept the JavaScript output only, so the Node bundle had no grammar files. `package.json`
320
+ `files` adds `dist/*.wasm`, and `npm pack --dry-run` lists the three files. The smoke test
321
+ passes 8 of 8 steps on the Windows executable, and on `dist/cli.js` with Bun, Node 20, Node
322
+ 22 and Node 24. A bundle with no `.wasm` file fails the smoke test. The engine has three
323
+ `.wasm` files, not four, because it reads `.tsx` with the TypeScript grammar.
324
+ - `map`: an import of a workspace package by name is now an edge to its entry file. In a single
325
+ package, an import of its own name is an edge too (1.x fix F43). The Python tool keeps each
326
+ such import as an external package, so a monorepo had no edges between its packages. The
327
+ import stays external when the census does not hold the entry file. The adapter lists these
328
+ edges as workspace edges, as depgraph 1.x does. On MathTS, 485 exports that other packages
329
+ use are no longer counted as unused.
330
+
9
331
  ## [1.1.0] - 2026-09-25
10
332
 
11
333
  The STE release. `repo-tools ste` checks Markdown, and docstring prose with `--prose`, against the
package/README.md CHANGED
@@ -1,20 +1,26 @@
1
1
  # repo-tools
2
2
 
3
- `repo-tools` is one command-line tool with five subcommands for repositories:
3
+ `repo-tools` is one command-line tool with these subcommands for repositories:
4
4
 
5
5
  | Subcommand | Job |
6
6
  |---|---|
7
- | `depgraph` | Writes the dependency graph and the architecture reports of a TypeScript tree. |
7
+ | `map` | Writes the dependency graph and the architecture reports of a TypeScript/JavaScript, Python, C# or Rust repository. |
8
+ | `depgraph` | The deprecated alias of `map` (through 2.x). |
9
+ | `check` | Checks the `## Verification` tables of Markdown documents against a fresh graph, and fails on drift. |
8
10
  | `chunk` | Splits a large file into chunks, merges the chunks back, and shows which chunks changed. |
9
11
  | `compress` | Writes a compact copy of a file for a model context, and restores it. |
10
- | `query` | Answers structural questions from the depgraph reports, and writes two derived reports. |
12
+ | `query` | Answers structural questions from the graph of `map`, and writes two derived reports. |
11
13
  | `ste` | Checks Markdown or docstring prose against Simplified Technical English. |
12
14
 
13
- Status: version 1.1.0.
15
+ Status: version 2.1.0.
14
16
 
15
- - All five subcommands work.
16
- - `depgraph` and `query` read their settings from `repo-tools.config.json` in the root.
17
- `--config=<file>` makes either subcommand read another file.
17
+ - `map`, `check` and `query` read their settings from `repo-tools.config.json` in the root. The
18
+ section of `map` is `map` (its old name, `depgraph`, is also read). `--config=<file>` makes any
19
+ of the three read another file.
20
+ - `repo-tools depgraph` prints one deprecation line and runs `map`. It accepts the 1.x
21
+ scan-scope flags (`--src`, `--tests`, `--exclude`, `--also-exclude`, `--all`,
22
+ `--reachable-only`, `--include-tests`) with a warning, because they have no effect in 2.0.0.
23
+ `map` exits 1 on them.
18
24
  - `compress -d` restores JSON files only.
19
25
 
20
26
  ## Install
@@ -34,7 +40,7 @@ repo-tools --version
34
40
 
35
41
  The executable holds the tool and the Bun runtime. It needs no Bun, Node or `node_modules`.
36
42
  Download the file for your platform and `SHA256SUMS` from the
37
- [GitHub release](https://github.com/danielsimonjr/repo-tools/releases/tag/v1.1.0):
43
+ [GitHub release](https://github.com/danielsimonjr/repo-tools/releases/tag/v2.1.0):
38
44
 
39
45
  | Platform | File |
40
46
  |---|---|
@@ -112,7 +118,7 @@ Prerequisites: Bun 1.4.2 or later, and a clone of this repository.
112
118
 
113
119
  ```sh
114
120
  bin/repo-tools-windows-x64.exe --version
115
- bin/repo-tools-windows-x64.exe depgraph --root=path/to/repo
121
+ bin/repo-tools-windows-x64.exe map --root=path/to/repo
116
122
  ```
117
123
 
118
124
  4. Test the executable, not only the source. The executable is the artifact that ships:
@@ -121,28 +127,44 @@ Prerequisites: Bun 1.4.2 or later, and a clone of this repository.
121
127
  bun run smoke -- bin/repo-tools-windows-x64.exe
122
128
  ```
123
129
 
124
- `bun run build` writes a second channel, the Node bundle `dist/cli.js` (`node dist/cli.js --help`).
130
+ `bun run build` writes a second channel, the Node bundle `dist/cli.js` (`node dist/cli.js --help`),
131
+ with the tree-sitter grammar files (`dist/*.wasm`) next to it.
125
132
 
126
133
  ## Reports
127
134
 
128
- `repo-tools depgraph` writes its reports into `docs/architecture/` under the root. Every file is
129
- generated: do not edit it by hand. Run `repo-tools depgraph` again to update it. Each Markdown
130
- report starts with a "GENERATED FILE -- do not edit by hand" banner.
135
+ `repo-tools map` writes its reports into `docs/architecture/` under the root (`--out=<dir>`
136
+ names another folder; `--out=../reports` writes outside the root). Every file is generated: do
137
+ not edit it by hand. Run `repo-tools map` again to update it. Each Markdown report starts with
138
+ a "GENERATED FILE -- do not edit by hand" banner.
139
+
140
+ The census is the set of source files that git tracks (outside a git work tree, a pruned walk).
141
+ The language with the most files decides how `map` reads the repository. Input files never come
142
+ from the output folder. The duplicate allowlist, the duplicate baseline and the coverage policy
143
+ are in `docs/architecture/`, or at the path that the config gives. A repository that already has
144
+ its own allowlist must set `map.duplicateAllowlist` (the old key `depgraph.duplicateAllowlist`
145
+ is also read) to that file. Mathts has 283 allowlisted names. With the default path, the
146
+ duplicate gate fails on those names.
147
+
148
+ A literal relative `import()` is a graph edge. The Python `repo_map.py` records none. The parity
149
+ record in `docs/parity-2.0.0.md` gives the rules and the verdict.
131
150
 
132
151
  | File | What it answers |
133
152
  |---|---|
153
+ | `dependency-graph.json` | The core graph: each file by area, with its imports, exports and edges; the reachability; the cycle counts; and the statistics. |
154
+ | `file-inventory.json` | Where is each source file, and what is it? Package, area and disposition (reachable, build entry, test-only, orphan, test, tool, config, example, bench), and the links that the census did not follow. |
155
+ | `duplicate-symbols.json` | Which names do two or more files define? For TypeScript, also the classified lists. |
156
+ | `unused-analysis.json` | Which exports and files does nothing import? |
157
+ | `dependency-layers.json` | The subsystem view: the `src` files by module, the entry points, the layers and the cyclic components. |
134
158
  | `DEPENDENCY_GRAPH.md` | How do the files and modules depend on each other? Per-file imports and exports, the dependency matrix, cyclic components (runtime and type-only), a Mermaid diagram, and statistics. |
135
- | `dependency-graph.json` | The same graph as data, for tools: modules, files, imports, exports, entry points, cyclic components and statistics. |
136
- | `dependency-graph.yaml` | The same data as YAML. |
159
+ | `dependency-graph.yaml` | `dependency-graph.json` as YAML. |
137
160
  | `dependency-summary.compact.json` | A small summary of the graph, with short keys, to give to a model. |
138
- | `unused-analysis.md` | Which files and exports does nothing import? Dormant files, split into orphans (reachable from nothing) and test-only files. |
139
- | `FILE_INVENTORY.md` | Where is every `.ts` file, and what is it? Area and disposition (reachable, build entry, test-only, orphan, test, tool, config, example, bench), and the result of the census self-check. |
140
- | `file-inventory.json` | The same inventory as data. |
141
- | `TEST_COVERAGE.md` | Which source files does a test import (directly, through a barrel, or through a side-effect import), and which files does no test reach? |
161
+ | `FILE_INVENTORY.md`, `duplicate-symbols.md`, `unused-analysis.md` | The three JSON reports above, for a person to read. |
162
+ | `TEST_COVERAGE.md` | Which source files does a test load (directly, through a barrel, through a side-effect import, or by `import()`), and which files does no test reach? |
142
163
  | `test-coverage.json` | The same coverage data, with the test-to-source map. |
143
- | `duplicate-symbols.md` | Which names do two or more files define? Each name is classified. |
144
- | `duplicate-symbols.json` | The same duplicate data as data. |
145
- | `package-export-surfaces.json` | Which names does each package export publicly? |
164
+ | `package-export-surfaces.json` | Which names does each package export publicly? Not written for C#. |
165
+
166
+ `docs/parity-2.0.0.md` records how these reports compare with the Python tool and with
167
+ depgraph 1.x.
146
168
 
147
169
  `repo-tools query --emit` writes two more files into the same folder. They are also generated.
148
170
 
@@ -151,30 +173,73 @@ report starts with a "GENERATED FILE -- do not edit by hand" banner.
151
173
  | `dependency-reverse.json` | Which files import each file? The reverse edges of the graph. |
152
174
  | `node-safety.json` | Which packages are browser-safe, which files import a `node:` builtin, and which of those files does the `.` entry of each browser-safe package reach? |
153
175
 
176
+ ## Check the documents against the graph
177
+
178
+ `repo-tools check --docs=<dir>` reads every `*.md` file of the folder. The check reads the
179
+ `## Verification` table of each document. Each row `| claim | value | source |` names a metric of
180
+ the graph (`totalFiles`, `orphanedFiles`, `runtimeCircularDeps` and so on). The value is the
181
+ number that the document states. The check builds the graph again, so a stale report cannot hide
182
+ drift. A relative `--docs` path is relative to the root.
183
+
184
+ ```md
185
+ ## Verification
186
+
187
+ | Claim | Value | Source |
188
+ |---|---|---|
189
+ | totalFiles | 243 | file-inventory.json |
190
+ ```
191
+
192
+ ```sh
193
+ repo-tools check --docs=docs/architecture
194
+ # check passed: every claim matches the graph (1 claim in 1 document).
195
+ ```
196
+
197
+ When a value drifts, the exit code is 1, and standard error lists every problem, one per line:
198
+
199
+ ```text
200
+ OVERVIEW.md: totalFiles claims 243 but actual is 244
201
+ ```
202
+
203
+ A document passes without a check when one of its lines is exactly
204
+ `<!-- repo-map:no-verification -->`. The marker must stand alone on its line: a marker inside a
205
+ sentence, a code span or a table cell does not count.
206
+ `repo-tools map` writes that line at the top of each generated report. Every other gap is a
207
+ failure. A missing docs folder, a folder with no `*.md` file, a document without a Verification
208
+ section, and a section without a row are failures. An unknown claim name is a failure too. So is a
209
+ metric that the graph build declared unreliable. `docs/design.md` (section 15) gives the rules and the
210
+ differences from the Python tool. `docs/parity-check.md` records the comparison with that tool on
211
+ 11 repositories.
212
+
154
213
  ## Query the graph
155
214
 
156
- `repo-tools query` answers questions from `dependency-graph.json` and
157
- `package-export-surfaces.json`. It parses no source file, so run `repo-tools depgraph` first.
158
- The examples use a copy of `tests/fixtures/depgraph/mono-repo`:
215
+ `repo-tools query` answers questions from `dependency-graph.json` (and
216
+ `package-export-surfaces.json` for `is-public`). It parses no source file, so run
217
+ `repo-tools map` first. It reads each area of the graph, and a path that is not a file of the
218
+ graph exits 1. The examples use a copy of `tests/fixtures/depgraph/mono-repo`:
159
219
 
160
220
  ```sh
161
- repo-tools depgraph
221
+ repo-tools map
162
222
  repo-tools query dependents packages/core/src/math.ts
163
223
  # packages/core/src/index.ts
164
224
  # packages/core/src/worker.ts
225
+ # packages/core/tests/math.test.ts
165
226
  repo-tools query symbol-users add
166
- # packages/cli/src/main.ts [@scope/core]
167
- # packages/core/src/index.ts [internal]
227
+ # packages/cli/src/main.ts
228
+ # packages/core/src/index.ts
229
+ # packages/core/tests/math.test.ts
168
230
  repo-tools query is-public packages/core add
169
231
  # PUBLIC: add is exported from packages/core
170
232
  repo-tools query is-public packages/core double
171
233
  # INTERNAL: double is not in the public export surface of packages/core
172
234
  repo-tools query cycles
235
+ # 0 simple cycles
236
+ repo-tools query cycles --components
173
237
  # runtime: 0 cyclic components
174
238
  # type-only: 0 cyclic components
175
239
  ```
176
240
 
177
- A package is the folder above a `src/index.ts` entry (`.` for the root entry). Each package is
241
+ The browser-safety commands serve TypeScript/JavaScript only. A package is the folder above a
242
+ `src/index.ts` file (`.` for the root file). Each package is
178
243
  browser-safe, unless `--node-runtime=<pkg,...>` or the config key `query.nodeRuntimes` lists it.
179
244
  The `.` entry of a browser-safe package must not reach a file that imports a `node:` builtin:
180
245
 
@@ -184,12 +249,12 @@ repo-tools query node-safety
184
249
  repo-tools query --check-browser-safety
185
250
  # browser-safety check passed: the . entries of 1 browser-safe package reach no node: code.
186
251
  repo-tools query --emit
187
- # Written: docs/architecture/dependency-reverse.json (3 files)
252
+ # Written: docs/architecture/dependency-reverse.json (4 files)
188
253
  # Written: docs/architecture/node-safety.json (0 node files, 0 leaks)
189
254
  ```
190
255
 
191
256
  `--check-browser-safety` exits 1 on a leak. The query reads its reports from `--out`, else from
192
- the config key `query.out`, else from `depgraph.out`, else from `docs/architecture`. Run
257
+ the config key `query.out`, else from `map.out`, else from `docs/architecture`. Run
193
258
  `repo-tools query --help` for every option.
194
259
 
195
260
  ## Develop
@@ -208,7 +273,7 @@ the config key `query.out`, else from `depgraph.out`, else from `docs/architectu
208
273
  ## Design
209
274
 
210
275
  `docs/design.md` describes the modules, the output rules, the config, the extension contract,
211
- the privacy check and the verification.
276
+ the privacy check and the verification. Its section "The 2.0.0 engine" describes `map`.
212
277
 
213
278
  ## License
214
279