@danielsimonjr/repo-tools 2.0.0 → 2.2.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,193 @@ All notable changes to this project are recorded in this file. The format follow
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [2.2.0] - 2026-10-02
10
+
11
+ `repo-tools docs` is the new gate of the doc comments of a repository. It ports `code_docs.py` of
12
+ the code-docs skill. `docs/parity-docs.md` lists the differences from the Python tool. The
13
+ release also adds the audit of the fix ledger and the check for dangling references to the
14
+ design document.
15
+
16
+ ### Added
17
+
18
+ - `repo-tools docs`, the gate of the doc comments. The command is a port of `code_docs.py` of the
19
+ code-docs skill, and it needs no Python. `docs scan` measures the coverage of the exported
20
+ symbols and writes `COVERAGE.md` and `coverage.json`. `docs check` is the gate: it exits 1 on a
21
+ MUST issue (M1 to M5) and on a file that does not parse. `--paths` and `--paths-from=<file>`
22
+ gate the changed files of a pull request only. `docs stub` plans a skeleton comment with the
23
+ marker `TODO:` for each exported symbol that has no comment. The default is a dry run until
24
+ `--apply`. After a change, `stub` parses the file again, and it keeps the line ends of the
25
+ file. The command reads TypeScript, JavaScript and Python with tree-sitter. A
26
+ `.code-docs.json` file at the root excludes paths, and each entry needs a reason. Section 16
27
+ of `docs/design.md` describes the command. `docs/parity-docs.md` compares the command with the
28
+ Python tool on 9 public repositories: 4665 files, 22329 symbols, 690 MUST issues and 11208
29
+ SHOULD issues. The reports are equal, except for the order of the symbols in 40 files and the
30
+ doc names of 29 symbols of one repository. The command gives 3 MUST issues more than the Python
31
+ tool, for stale names in optional `[name]` tags. The record lists the differences. Some are
32
+ defects of the Python tool. The defects are a closing `*/` in the summary, comment delimiters in
33
+ the STE check, and the parameter names in a doc. The others are the parser of Python, the exit
34
+ codes, and the files that `stub` changes.
35
+ - `repo-tools docs stub` never writes through a link. The command skips a file that is a link or
36
+ resolves outside the root, and names the file. The command does not write a TypeScript block
37
+ when another token precedes the declaration on its line, for example the end of a template. The
38
+ end of a Python signature ignores the brackets in strings and a comment after the colon. A root
39
+ with no source file gives exit code 1, as for `scan` and `check`. `--path=.` selects the whole
40
+ repository.
41
+ - `docs check --paths-from` reads the quoted names that `git diff --name-only` writes for a
42
+ non-ASCII file name. The analysers read a JSDoc parameter name with `$`, and the optional forms
43
+ `[name]` and `[name=default]`. They read a reST field with a type, for example
44
+ `:param int x:`. A destructured parameter binds the names on the left of a default value. The
45
+ analysers read each name from the source as written, so a parameter named `abstract` keeps its
46
+ name. The Python tool has each of these defects, and design section 16.6 lists them.
47
+ - The smoke test has a step for the doc gate. A run of `docs check` reads a TypeScript, a TSX and
48
+ a Python file, so one run loads the three grammars of the product. The test passes documented
49
+ source and fails a new undocumented export.
50
+ - `bun run audit:ledger`, the audit of the fix ledger. For each fix (F1 to F44, M1 and R1), the
51
+ script restores the 1.x defect in a scratch copy of the repository. Then it runs the tests.
52
+ It runs the test file of the fix first, and then the whole suite. A test of the fix file must
53
+ fail. Each test has a 30 s limit (`--test-timeout-s`). A run in which only tests hit their
54
+ time limit is an error, because load can cause it.
55
+ The script exits 0 only when this holds for every mutation. Section 12 of
56
+ `docs/design.md` describes the audit. `scripts/fix-ledger-mutations.ts` holds the 77
57
+ mutations. `docs/fix-ledger-audit.md` holds the result: 77 of 77 mutations fail a test of
58
+ their own fix. The tests of the audit make their temporary repositories with a git identity
59
+ that the privacy check accepts.
60
+ - Tests for the fixes that no test of their own locked. F12: the module map of
61
+ `dependency-layers.json`. F26: components sorted by smallest member. F30: the map resolver
62
+ picks a `.tsx` file and a directory index. F34: a workspace package folder that is a link.
63
+ F43: the `src/<sub>/index.ts` fallback of an `exports` subpath. The tests of F17, F41 and F43
64
+ assert more. They assert the `src/index.ts` fallback root, an excluded package that has an
65
+ entry, and the edges of a self-import.
66
+ - `bun run check:design`, the check for dangling references to `docs/design.md`. A comment, a
67
+ test title or a workflow can name a part of the design, for example `design 11.4`. The script
68
+ finds each such reference and looks for a heading with that number. It prints each reference
69
+ that has no heading, and it exits 1. The unit tests run it on this repository. The check
70
+ proves that the number exists. It cannot prove that the heading has the meaning that the
71
+ reference gives.
72
+
73
+ ### Changed
74
+
75
+ - The grammar loader reads a third grammar, TSX. The Node bundle and the npm package now hold four
76
+ `.wasm` files and not three, and the compiled executable holds the TSX grammar too. `docs` uses
77
+ it for `.tsx` and `.jsx` files. `map` still reads these files with the TypeScript grammar.
78
+ - The directory readers of the map engine read through `readdirHook`. The readers are discovery,
79
+ the two `.csproj` walks and the folder list of a workspace pattern. The F2 test replaces
80
+ `readdirHook`. Before, the map never called the reader that the F2 test reversed. The test
81
+ passed with or without the sort in discovery.
82
+ - `docs/fix-ledger-2.0.0.md` describes what each test locks. The rows for F9 to F12, F19 to F21,
83
+ F23, F24, F27 and F29 to F31 described other behavior. The rows for F13, F36, F41 and F44 sat
84
+ in the section "No 2.0.0 meaning", although tests lock them. The test for M1 said that
85
+ `--reachable-only` removes a file. It asserts that `map` rejects the flag.
86
+ - `docs/design.md` now holds the parts that the code names. Section 11 has the subsections 11.1
87
+ to 11.4: the Node bundle, the compiled executables, the workflows and the release. Section 12
88
+ has 12.1, the steps of the smoke test. Section 14.2 describes the API-surface flags.
89
+ - The check found 50 references in comments, test titles and workflows to a part that the
90
+ document never had. Each reference now names an existing section. Four more references named
91
+ section 4 for the chunk and compress modules. Section 4 holds the output rules, so they now
92
+ name section 8.
93
+
94
+ ### Maintenance
95
+
96
+ - The root `bun` Dependabot entry is removed from `.github/dependabot.yml`. It cannot succeed.
97
+ The bun updater of Dependabot reads `bun.lock` lockfileVersion 1, and Bun 1.4 writes 2. The
98
+ `npm` alternative aborts during file fetching on a bun-managed project. Each error recommends
99
+ the other. Measured here: the `bun in /.` updater job failed on 2026-09-24 and again on
100
+ 2026-10-01, while `github_actions in /.` succeeded on both days. `github-actions` updates are
101
+ unchanged. The file now records the two errors, the cost and a checkable revisit condition.
102
+ **Unlike the sibling repositories in this sweep, this one also has Dependabot alerts
103
+ disabled.** Thus nothing reports a vulnerable dependency either. A bump is entirely a human
104
+ action: `bun outdated`, `bun update <pkg>`, then commit the regenerated `bun.lock`.
105
+
106
+ ## [2.1.0] - 2026-10-01
107
+
108
+ `repo-tools check` is the new drift gate for the Markdown documents of a repository. It ports
109
+ `check.py` of the architecture-docs skill. The release also makes a literal `import()` a graph
110
+ edge, removes the 1.x depgraph pipeline, and adds an accept-list to the privacy check.
111
+ `docs/parity-check.md` lists the differences from the Python tool.
112
+
113
+ ### Added
114
+
115
+ - `repo-tools check --docs=<dir>`, the drift gate of the architecture documents. The command is
116
+ a port of `check.py` of the architecture-docs skill. The check reads the `## Verification`
117
+ tables of the Markdown files in the folder. The check builds a fresh graph, and the check
118
+ compares each claim with the graph. Exit 0 means that every claim matched. Exit 1 lists every
119
+ problem on standard error, one per line. A missing or empty docs folder is a problem. A
120
+ document without a Verification section is a problem. So are a section without a row, an
121
+ unknown claim, a count that the graph build declared unreliable, and a value that differs. A
122
+ document opts out when one of its lines is exactly `<!-- repo-map:no-verification -->`. A relative `--docs` path is
123
+ relative to the root, and an absolute path is used as given. The check reads
124
+ `map.duplicateAllowlist` and `map.verificationMarker` from the config file. Section 15 of
125
+ `docs/design.md` lists the differences from the Python tool. The smoke test has a `check` step.
126
+ `docs/parity-check.md` records the comparison with the Python tool on 11 repositories.
127
+ - The privacy check has an accept-list, `scripts/privacy-accepted.txt`, for a reviewed finding in
128
+ the commit history. A commit message cannot change after a merge, so a new commit cannot clear
129
+ a finding in it. An entry holds a full commit sha, one finding kind, one line of the message and
130
+ a reason. The entry accepts that finding only: no prefix, no wildcard, no whole-commit waiver,
131
+ and never a finding in a tracked file. An entry that accepts no finding is a finding
132
+ (`accepted-stale`). The check prints each accepted finding with its reason.
133
+
134
+ ### Changed
135
+
136
+ - A literal relative `import()` is an edge of the core graph. This reverses the known difference
137
+ in 2.0.0. A runtime call is a namespace use (`*`). A type-position `import('./c').Name` records
138
+ that name. `typeof import()` records no names. A template that contains `${`, and a specifier
139
+ that is not relative, are not edges. The parity record gives the merge rules. The verdict
140
+ against the Python tool is `repo_map-wrong`.
141
+ - A namespace import (`import * as ns`, `export * as ns`) counts every export of its target as
142
+ used, as a runtime `import()` does. The Python tool lists those exports as unused. A name that
143
+ a file mentions only in a comment is not an in-module reference. The Python tool counts the
144
+ comment. The parity record gives the measured effect. A test locks the namespace rule.
145
+ - The opt-out marker of `repo-tools check` must stand alone on a line. `check.py` opts a document
146
+ out when the marker is anywhere in its text. A document can quote the marker in a sentence, a
147
+ code span or a table cell. That document then skips its own table, and a stale claim passes in
148
+ silence.
149
+ `repo-tools check` opts out only when a line, trimmed, equals the marker. This changes the
150
+ result for a document that opted out from inside a sentence or a table cell: the check now
151
+ reads its claims. `repo-tools map` writes the marker alone on a line, so generated reports
152
+ still opt out. A blank `map.verificationMarker` matches no line. `docs/parity-check.md` records
153
+ the difference. The verdict is fail-closed.
154
+ - A bodiless `export function f(): T;` is not an export, as in the Python tool
155
+ (`repo_map-kept`). An overload plus an implementation records the name once.
156
+ - The 1.x depgraph pipeline is removed: the runner, the regex parser, the scanner, the inventory
157
+ reporter and the 1.x goldens. `repo-tools depgraph` stays an alias of `repo-tools map`.
158
+ `docs/fix-ledger-2.0.0.md` records which 1.x fixes the `map` tests lock, and which fixes have
159
+ no 2.0.0 meaning.
160
+
161
+ ### Fixed
162
+
163
+ - `src/check/claims.ts` and one test held the byte-order mark as an invisible U+FEFF character.
164
+ Both files now spell it as an escape sequence. A new test fails when a file under `src/`,
165
+ `tests/` or `scripts/` holds a literal U+FEFF.
166
+ - A named `export { name } from` writes one edge for that statement. The statement does not add a
167
+ second empty-imports edge to the same file.
168
+ - `write` refuses a symbolic link inside the output folder that points outside it.
169
+ - A skip-list folder under `src/` (`dist`, `build`, `coverage`, `node_modules`, `.git`) that
170
+ holds a source file produces a warning. The files stay out of the census. A root `build/` or
171
+ `dist/` folder stays silent.
172
+ - `--check-census` names the configured regenerate command. The test-coverage note names the
173
+ configured coverage-policy path.
174
+ - The config file accepts a top-level `$schema` key.
175
+ - The walk skip list is not module state. Each walk builds its own skip set.
176
+ - A type-position `import('./c').C` records the name `C`.
177
+ - In single-package mode, `main` and `exports` targets are roots after `dist/` maps to `src/`,
178
+ including when the file is not `src/index.ts`. A subpath root is the source of the export
179
+ target.
180
+ - Test coverage follows an import by package name, including the side-effect imports of the
181
+ resolved file.
182
+ - A workspace subpath uses the `exports` target, then `<sub>.ts`, then `<sub>/index.ts`.
183
+ - A package-name import is an edge in cycle detection, including the cyclic components in
184
+ `dependency-layers.json`.
185
+ - The comment mask treats `a++ / b / c` as division, and `if (x) /re/` as a regular expression.
186
+ - A bare `import './x'` together with `import('./x')` is one side-effect edge whose names are
187
+ `["*"]`.
188
+ - A dangling symbolic link is listed in `skippedLinks`.
189
+ - A `new URL` in a root config, and a `new URL('./x.js', import.meta.url)` launch, seed roots.
190
+ - A `.test.tsx` or `.spec.tsx` file is in the `tests` area.
191
+ - The repository scan of the privacy check passes again. A test fixture used an e-mail address
192
+ that the check rejects. Two trailers of the merge commit of the engine change hold a co-author
193
+ address and a name. The fixture now uses an allowed address. The accept-list records the two
194
+ trailers.
195
+
9
196
  ## [2.0.0] - 2026-09-26
10
197
 
11
198
  The unified engine. `repo-tools map` replaces the Python `repo_map.py` and depgraph 1.x with one
@@ -16,10 +203,10 @@ flags have no effect: `map` exits 1 on them, and the alias gives a warning.
16
203
 
17
204
  ### Known differences
18
205
 
19
- - `map` makes no graph edge for a dynamic `import()`, as the Python tool does. depgraph 1.x
20
- made one. So a cycle that closes only through `import()` is not a cycle in 2.0.0. On
21
- memoryjs, one type-only cyclic component has 3 files, not 7. Test coverage still counts a
22
- literal `import()` in a test file as a load.
206
+ - The 2.0.0 release made no graph edge for a dynamic `import()`. That choice is reversed in
207
+ Unreleased: a literal relative `import()` is now an edge. On memoryjs, the release counted
208
+ one type-only cyclic component as 3 files, not 7. Test coverage counted a literal `import()`
209
+ in a test file as a load, and it still does.
23
210
 
24
211
  ### Added
25
212
 
package/README.md CHANGED
@@ -6,16 +6,18 @@
6
6
  |---|---|
7
7
  | `map` | Writes the dependency graph and the architecture reports of a TypeScript/JavaScript, Python, C# or Rust repository. |
8
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. |
10
+ | `docs` | Measures the doc comments of TypeScript, JavaScript and Python files, plans the missing ones, and gates the result. |
9
11
  | `chunk` | Splits a large file into chunks, merges the chunks back, and shows which chunks changed. |
10
12
  | `compress` | Writes a compact copy of a file for a model context, and restores it. |
11
13
  | `query` | Answers structural questions from the graph of `map`, and writes two derived reports. |
12
14
  | `ste` | Checks Markdown or docstring prose against Simplified Technical English. |
13
15
 
14
- Status: version 2.0.0.
16
+ Status: version 2.2.0.
15
17
 
16
- - `map` and `query` read their settings from `repo-tools.config.json` in the root. The section
17
- of `map` is `map` (its old name, `depgraph`, is also read). `--config=<file>` makes either
18
- subcommand read another file.
18
+ - `map`, `check` and `query` read their settings from `repo-tools.config.json` in the root. The
19
+ section of `map` is `map` (its old name, `depgraph`, is also read). `--config=<file>` makes any
20
+ of the three read another file.
19
21
  - `repo-tools depgraph` prints one deprecation line and runs `map`. It accepts the 1.x
20
22
  scan-scope flags (`--src`, `--tests`, `--exclude`, `--also-exclude`, `--all`,
21
23
  `--reachable-only`, `--include-tests`) with a warning, because they have no effect in 2.0.0.
@@ -39,7 +41,7 @@ repo-tools --version
39
41
 
40
42
  The executable holds the tool and the Bun runtime. It needs no Bun, Node or `node_modules`.
41
43
  Download the file for your platform and `SHA256SUMS` from the
42
- [GitHub release](https://github.com/danielsimonjr/repo-tools/releases/tag/v2.0.0):
44
+ [GitHub release](https://github.com/danielsimonjr/repo-tools/releases/tag/v2.2.0):
43
45
 
44
46
  | Platform | File |
45
47
  |---|---|
@@ -139,7 +141,13 @@ a "GENERATED FILE -- do not edit by hand" banner.
139
141
  The census is the set of source files that git tracks (outside a git work tree, a pruned walk).
140
142
  The language with the most files decides how `map` reads the repository. Input files never come
141
143
  from the output folder. The duplicate allowlist, the duplicate baseline and the coverage policy
142
- are in `docs/architecture/`, or at the path that the config gives.
144
+ are in `docs/architecture/`, or at the path that the config gives. A repository that already has
145
+ its own allowlist must set `map.duplicateAllowlist` (the old key `depgraph.duplicateAllowlist`
146
+ is also read) to that file. Mathts has 283 allowlisted names. With the default path, the
147
+ duplicate gate fails on those names.
148
+
149
+ A literal relative `import()` is a graph edge. The Python `repo_map.py` records none. The parity
150
+ record in `docs/parity-2.0.0.md` gives the rules and the verdict.
143
151
 
144
152
  | File | What it answers |
145
153
  |---|---|
@@ -166,6 +174,94 @@ depgraph 1.x.
166
174
  | `dependency-reverse.json` | Which files import each file? The reverse edges of the graph. |
167
175
  | `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? |
168
176
 
177
+ ## Check the documents against the graph
178
+
179
+ `repo-tools check --docs=<dir>` reads every `*.md` file of the folder. The check reads the
180
+ `## Verification` table of each document. Each row `| claim | value | source |` names a metric of
181
+ the graph (`totalFiles`, `orphanedFiles`, `runtimeCircularDeps` and so on). The value is the
182
+ number that the document states. The check builds the graph again, so a stale report cannot hide
183
+ drift. A relative `--docs` path is relative to the root.
184
+
185
+ ```md
186
+ ## Verification
187
+
188
+ | Claim | Value | Source |
189
+ |---|---|---|
190
+ | totalFiles | 243 | file-inventory.json |
191
+ ```
192
+
193
+ ```sh
194
+ repo-tools check --docs=docs/architecture
195
+ # check passed: every claim matches the graph (1 claim in 1 document).
196
+ ```
197
+
198
+ When a value drifts, the exit code is 1, and standard error lists every problem, one per line:
199
+
200
+ ```text
201
+ OVERVIEW.md: totalFiles claims 243 but actual is 244
202
+ ```
203
+
204
+ A document passes without a check when one of its lines is exactly
205
+ `<!-- repo-map:no-verification -->`. The marker must stand alone on its line: a marker inside a
206
+ sentence, a code span or a table cell does not count.
207
+ `repo-tools map` writes that line at the top of each generated report. Every other gap is a
208
+ failure. A missing docs folder, a folder with no `*.md` file, a document without a Verification
209
+ section, and a section without a row are failures. An unknown claim name is a failure too. So is a
210
+ metric that the graph build declared unreliable. `docs/design.md` (section 15) gives the rules and the
211
+ differences from the Python tool. `docs/parity-check.md` records the comparison with that tool on
212
+ 11 repositories.
213
+
214
+ ## Gate the documentation comments
215
+
216
+ `repo-tools docs` reads the TypeScript, JavaScript and Python files that git tracks. It finds each
217
+ function, class, interface, type alias and method, and the doc comment of each one. It needs no
218
+ Python on the computer.
219
+
220
+ ```sh
221
+ repo-tools docs scan . # writes docs/code-docs/COVERAGE.md and coverage.json
222
+ repo-tools docs check . # the gate: exit 1 on a MUST issue
223
+ repo-tools docs stub . --path=src/api # a dry run: lists the stubs and writes nothing
224
+ repo-tools docs stub . --path=src/api --apply
225
+ ```
226
+
227
+ The rules are:
228
+
229
+ | Rule | Tier | The rule |
230
+ |---|---|---|
231
+ | M1 | MUST | An exported symbol has a doc comment. A test file is exempt. |
232
+ | M2 | MUST | The doc comment has a summary line. |
233
+ | M3 | MUST | The doc comment names no parameter that the signature lacks. |
234
+ | M4 | MUST | The doc comment holds no `TODO:` marker. |
235
+ | M5 | MUST | A file uses one doc dialect: `google`, `numpy` or `rest` for Python, `tsdoc` or `jsdoc` for TypeScript. |
236
+ | S2 | SHOULD | The summary ends with a full stop. |
237
+ | S5 | SHOULD | The doc comment does not repeat a type that the signature holds. |
238
+ | S6 | SHOULD | The prose follows Simplified Technical English (the rules of `repo-tools ste`). |
239
+
240
+ Only a MUST issue changes the exit code of `check`. A file that does not parse is also a failure,
241
+ because an unknown file is not a clean file. A repository with no source file fails too.
242
+
243
+ `stub` is a dry run until you pass `--apply`. Each stub holds the marker `TODO:`, so `check` fails
244
+ until you replace the stub with real prose. The command parses a file again after the change.
245
+ A file that would no longer parse stays unchanged. The command skips a file that is a link or
246
+ resolves outside the root, and it names the skipped file.
247
+
248
+ To gate a pull request and not the whole backlog, give `check` the changed files:
249
+
250
+ ```sh
251
+ git diff --name-only origin/main... > changed.txt
252
+ repo-tools docs check . --paths-from=changed.txt
253
+ ```
254
+
255
+ A `.code-docs.json` file at the root excludes paths. Each entry needs a reason, and the output
256
+ names each exclusion:
257
+
258
+ ```json
259
+ { "exclude": [ { "path": "assembly/", "reason": "AssemblyScript" } ] }
260
+ ```
261
+
262
+ `docs/design.md` (section 16) gives the rules, the exit codes and the differences from the Python
263
+ tool. `docs/parity-docs.md` records the comparison with that tool on 9 repositories.
264
+
169
265
  ## Query the graph
170
266
 
171
267
  `repo-tools query` answers questions from `dependency-graph.json` (and
@@ -225,6 +321,8 @@ the config key `query.out`, else from `map.out`, else from `docs/architecture`.
225
321
  | `bun run smoke -- <command...>` | Runs the smoke test against one way to run the tool. |
226
322
  | `bun run privacy` | Runs the privacy check on the tracked files and the commit messages. |
227
323
  | `bun run hooks` | Installs the `commit-msg` hook that runs the privacy check on each message. |
324
+ | `bun run audit:ledger` | Reverts each fix of `docs/fix-ledger-2.0.0.md` in a scratch copy and checks that a test of that fix fails. |
325
+ | `bun run check:design` | Finds each reference to a section of `docs/design.md` that has no heading with that number. |
228
326
 
229
327
  ## Design
230
328