@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 +322 -0
- package/README.md +97 -32
- package/dist/cli.js +16978 -9960
- package/dist/tree-sitter-python-d56ewc8c.wasm +0 -0
- package/dist/tree-sitter-typescript-zxjzwt75.wasm +0 -0
- package/dist/web-tree-sitter-grrd7nak.wasm +0 -0
- package/package.json +7 -2
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
|
|
3
|
+
`repo-tools` is one command-line tool with these subcommands for repositories:
|
|
4
4
|
|
|
5
5
|
| Subcommand | Job |
|
|
6
6
|
|---|---|
|
|
7
|
-
| `
|
|
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
|
|
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
|
|
15
|
+
Status: version 2.1.0.
|
|
14
16
|
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
|
|
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/
|
|
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
|
|
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
|
|
129
|
-
|
|
130
|
-
|
|
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.
|
|
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` |
|
|
139
|
-
| `
|
|
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
|
-
| `
|
|
144
|
-
|
|
145
|
-
|
|
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
|
|
158
|
-
|
|
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
|
|
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
|
|
167
|
-
# packages/core/src/index.ts
|
|
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
|
-
|
|
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 (
|
|
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 `
|
|
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
|
|