dev-diagnosis-cli 0.1.3 → 0.1.5
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 +29 -1
- package/README.md +18 -2
- package/bin/dev-diagnosis.js +12 -4
- package/lib/context.mjs +7 -1
- package/lib/flakes.mjs +17 -7
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.
|
|
3
|
+
## 0.1.5 — unreleased
|
|
4
|
+
|
|
5
|
+
- Fix: a JUnit file that cannot be parsed no longer passes silently —
|
|
6
|
+
`flakes` used to collect the parse error into a warnings list nothing
|
|
7
|
+
ever printed, so a run set of only corrupt XML reported "no flaky
|
|
8
|
+
tests" and exited 0. The warning is now printed with the file and the
|
|
9
|
+
parse position, and the check fails with how many files could not be
|
|
10
|
+
parsed, so the verdict is never based on half-read data. (58 tests.)
|
|
11
|
+
- Docs: a Troubleshooting note for running `npx` inside a checkout of
|
|
12
|
+
this repo — npx prefers the checkout's own package.json and fails
|
|
13
|
+
with `dev-diagnosis: not found`; `npm install` does not fix it (no
|
|
14
|
+
dependencies, so no `node_modules` is created). Run
|
|
15
|
+
`node bin/dev-diagnosis.js` directly, `npm link`, or run `npx` from
|
|
16
|
+
another directory.
|
|
17
|
+
|
|
18
|
+
## 0.1.4 — 2026-11-11
|
|
19
|
+
|
|
20
|
+
- Fix: a large file now carries a suggestion — its exact path from the
|
|
21
|
+
repo root — so `context --fix` writes it into `.aiignore` and a
|
|
22
|
+
re-scan comes back clean. Large files used to carry no suggestion, so
|
|
23
|
+
on any repo with one oversized file the fix wrote everything else and
|
|
24
|
+
the next scan still failed on the same file, including this project's
|
|
25
|
+
own demo fixture (its 1.7 MB `data/export.json`). The documented
|
|
26
|
+
"`--fix` followed by a re-scan comes back clean" promise now holds
|
|
27
|
+
for every kind of noise. (54 tests.)
|
|
28
|
+
- Docs: the 0.1.3 entry below is now dated — it went live on npm on
|
|
29
|
+
2026-11-11 but the entry still said "unreleased".
|
|
30
|
+
|
|
31
|
+
## 0.1.3 — 2026-11-11
|
|
4
32
|
|
|
5
33
|
- Fix: nested build-output directories are reported by their full path
|
|
6
34
|
from the repo root (`packages/foo/dist/`) instead of a bare `dist/` —
|
package/README.md
CHANGED
|
@@ -58,6 +58,7 @@ Worth a look before sharing:
|
|
|
58
58
|
.env.example — environment template (usually safe to share)
|
|
59
59
|
Fix: add these to .aiignore (or the agent's ignore list):
|
|
60
60
|
*.log
|
|
61
|
+
data/export.json
|
|
61
62
|
dist/
|
|
62
63
|
package-lock.json
|
|
63
64
|
FAIL some context noise found (score 75/100)
|
|
@@ -92,7 +93,7 @@ The demo repo is intentionally noisy, so `all` exits 1: the context and flakes c
|
|
|
92
93
|
|
|
93
94
|
### `context` — what an AI agent should not read
|
|
94
95
|
|
|
95
|
-
Walks the repo (skipping `.git`, `node_modules` and other hidden directories) and classifies every file: build output, large files over 1 MB, lockfiles, logs, binary payloads, secret-like files and environment templates. It prints a 0–100 score, the bytes lost per category, the noisy files, the files worth a look before sharing, and the `.aiignore` entries that would fix it. Build-output directories are reported by their full path from the repo root (`packages/foo/dist/`, not a bare `dist/`) and rolled up into one row per directory, so the entry `--fix` writes matches nested build output too. Files the repo's `.aiignore` already lists are excluded from the scan entirely — they are what the agent will not be handed, so they are not noise any more. `context --fix` writes the suggestions into `.aiignore` for you; `--json` includes the fix outcome in the output.
|
|
96
|
+
Walks the repo (skipping `.git`, `node_modules` and other hidden directories) and classifies every file: build output, large files over 1 MB, lockfiles, logs, binary payloads, secret-like files and environment templates. It prints a 0–100 score, the bytes lost per category, the noisy files, the files worth a look before sharing, and the `.aiignore` entries that would fix it. Build-output directories are reported by their full path from the repo root (`packages/foo/dist/`, not a bare `dist/`) and rolled up into one row per directory, so the entry `--fix` writes matches nested build output too. A large file is fixed by its exact path from the repo root — no glob can single one file out — so `--fix` followed by a re-scan comes back clean even when the noise is a single oversized file. Files the repo's `.aiignore` already lists are excluded from the scan entirely — they are what the agent will not be handed, so they are not noise any more. `context --fix` writes the suggestions into `.aiignore` for you; `--json` includes the fix outcome in the output.
|
|
96
97
|
|
|
97
98
|
The score is the *noise-only* part of ai-context-doctor's score: 100 minus the category-weighted share of noise bytes (build 40, large 25, lockfile 20, log 15). The full ai-context-doctor score also weighs context volume, one file dominating, file sprawl and binary payloads, so its composite number reads lower on the same repo. The file classification itself is the same.
|
|
98
99
|
|
|
@@ -111,12 +112,27 @@ Reads JUnit XML across CI runs — each subdirectory of `<junit-dir>` is one run
|
|
|
111
112
|
## Development
|
|
112
113
|
|
|
113
114
|
```sh
|
|
114
|
-
npm test # node:test, no extra dependencies —
|
|
115
|
+
npm test # node:test, no extra dependencies — 58 tests
|
|
115
116
|
npm run example # run the CLI against the demo fixture
|
|
116
117
|
```
|
|
117
118
|
|
|
119
|
+
There is nothing to install: the CLI has no runtime dependencies, so
|
|
120
|
+
`npm test` works straight after cloning. Run the checkout as
|
|
121
|
+
`node bin/dev-diagnosis.js …` — see Troubleshooting if you reach for
|
|
122
|
+
`npx` inside the checkout.
|
|
123
|
+
|
|
118
124
|
Requires Node.js 18 or later. CI runs the tests and the demo on Node 18, 20, 22 and 24 across Ubuntu, macOS and Windows, and smoke-tests the packed tarball by installing it in a clean directory. Windows is covered by CI only — the Windows-only code paths (the `cmd.exe` retry for `.cmd`/`.bat` shims, `PATHEXT` lookup) have not been run on a real Windows machine.
|
|
119
125
|
|
|
126
|
+
## Troubleshooting
|
|
127
|
+
|
|
128
|
+
**`npx dev-diagnosis-cli` inside a checkout of this repo fails with
|
|
129
|
+
`dev-diagnosis: not found`.** npx sees the checkout's own `package.json`
|
|
130
|
+
— same name, same version — and tries to run the local bin, which only
|
|
131
|
+
exists once the bin is linked. `npm install` does not link it: with no
|
|
132
|
+
dependencies to install, npm creates no `node_modules` at all. Run the
|
|
133
|
+
checkout directly instead — `node bin/dev-diagnosis.js …` — or `npm link`
|
|
134
|
+
to get a `dev-diagnosis` command, or run `npx` from any other directory.
|
|
135
|
+
|
|
120
136
|
## Credits
|
|
121
137
|
|
|
122
138
|
dev-diagnosis merges four tools by the same author, each of which keeps working on its own:
|
package/bin/dev-diagnosis.js
CHANGED
|
@@ -247,13 +247,21 @@ function printFlakes(result, top, json) {
|
|
|
247
247
|
function runFlakes(dir) {
|
|
248
248
|
if (!dir) throw new UsageError('flakes needs a runs directory, for example: dev-diagnosis flakes examples/runs');
|
|
249
249
|
const result = scanRuns(dir);
|
|
250
|
-
const
|
|
250
|
+
const unparsable = result.warnings.length;
|
|
251
|
+
// A file that could not be parsed means the verdict is based on
|
|
252
|
+
// incomplete data: "no flaky tests" on a half-read run set is not a
|
|
253
|
+
// pass, so the check fails and the verdict says how many files were
|
|
254
|
+
// unreadable. The warnings themselves are printed with the table.
|
|
255
|
+
const passed = result.totals.flaky === 0 && result.totals.alwaysFailing === 0 && unparsable === 0;
|
|
256
|
+
const base = result.totals.flaky === 0 && result.totals.alwaysFailing === 0
|
|
257
|
+
? `no flaky tests across ${result.totals.runs} runs`
|
|
258
|
+
: `${result.totals.flaky} flaky, ${result.totals.alwaysFailing} always-failing across ${result.totals.runs} runs`;
|
|
251
259
|
return {
|
|
252
260
|
result,
|
|
253
261
|
passed,
|
|
254
|
-
verdict:
|
|
255
|
-
?
|
|
256
|
-
:
|
|
262
|
+
verdict: unparsable > 0
|
|
263
|
+
? `${base}; ${unparsable} file${unparsable === 1 ? '' : 's'} could not be parsed`
|
|
264
|
+
: base,
|
|
257
265
|
};
|
|
258
266
|
}
|
|
259
267
|
|
package/lib/context.mjs
CHANGED
|
@@ -114,7 +114,13 @@ export function classifyPath(relativePath, size = 0) {
|
|
|
114
114
|
return { noise: { label: normalized, reason: 'local log file' }, suggestion: '*.log' };
|
|
115
115
|
}
|
|
116
116
|
if (size > LARGE_FILE_THRESHOLD_BYTES) {
|
|
117
|
-
|
|
117
|
+
// A large file has no pattern that fixes it — a glob would be wrong —
|
|
118
|
+
// so the fix is its exact path from the repo root. Without that, a
|
|
119
|
+
// repo with one oversized file could never come back clean: --fix
|
|
120
|
+
// would write everything else and the next scan would still fail on
|
|
121
|
+
// the same file, which is exactly what the --fix round-trip promises
|
|
122
|
+
// not to do.
|
|
123
|
+
return { noise: { label: normalized, reason: 'large file' }, suggestion: normalized };
|
|
118
124
|
}
|
|
119
125
|
if (isTemplateFile(basename)) {
|
|
120
126
|
return { review: { label: normalized, reason: 'environment template (usually safe to share)' }, suggestion: null };
|
package/lib/flakes.mjs
CHANGED
|
@@ -166,7 +166,10 @@ export function scanRuns(root, options = {}) {
|
|
|
166
166
|
try {
|
|
167
167
|
parsed = parseJunitFile(file);
|
|
168
168
|
} catch (error) {
|
|
169
|
-
|
|
169
|
+
// parseJunitFile already puts the file path in an XML error's
|
|
170
|
+
// message; only prepend it for errors that do not carry it, so
|
|
171
|
+
// the warning never reads "file: file:line:col: ...".
|
|
172
|
+
warnings.push(error.message.startsWith(file) ? error.message : `${file}: ${error.message}`);
|
|
170
173
|
continue;
|
|
171
174
|
}
|
|
172
175
|
for (const test of parsed) {
|
|
@@ -253,13 +256,20 @@ export function formatFlakesTable(result, top = null) {
|
|
|
253
256
|
lines.push(`runs: ${result.totals.runs} tests: ${result.totals.tests} flaky: ${result.totals.flaky} always-failing: ${result.totals.alwaysFailing}`);
|
|
254
257
|
if (unstable.length === 0) {
|
|
255
258
|
lines.push('No flaky tests: every test passed in every run it appeared in.');
|
|
256
|
-
|
|
259
|
+
} else {
|
|
260
|
+
const header = `${'test'.padEnd(46)} ${'unstable'.padStart(8)} ${'runs'.padStart(5)} ${'trend'.padStart(8)} classification`;
|
|
261
|
+
lines.push(header);
|
|
262
|
+
for (const test of unstable) {
|
|
263
|
+
const label = test.id.length > 46 ? `${test.id.slice(0, 43)}...` : test.id;
|
|
264
|
+
lines.push(`${label.padEnd(46)} ${`${test.unstableRuns}/${test.eligibleRuns}`.padStart(8)} ${String(test.eligibleRuns).padStart(5)} ${test.trend.padStart(8)} ${test.classification}`);
|
|
265
|
+
}
|
|
257
266
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
const
|
|
262
|
-
lines.push(
|
|
267
|
+
// A file that could not be parsed is not "no flaky tests": say so on
|
|
268
|
+
// screen, with the file and the reason, instead of passing silently.
|
|
269
|
+
if (result.warnings && result.warnings.length > 0) {
|
|
270
|
+
const noun = result.warnings.length === 1 ? 'file' : 'files';
|
|
271
|
+
lines.push(`Warning: ${result.warnings.length} ${noun} could not be parsed — results are incomplete:`);
|
|
272
|
+
for (const warning of result.warnings) lines.push(` ${warning}`);
|
|
263
273
|
}
|
|
264
274
|
return lines.join('\n');
|
|
265
275
|
}
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"author":"WJDdidi-1","bin":{"dev-diagnosis":"bin/dev-diagnosis.js"},"bugs":{"url":"https://github.com/WJDdidi-1/dev-doctor/issues"},"description":"One offline CLI that diagnoses a repo the way four small tools do: context noise for AI agents, missing CLI commands, build-cache value, and flaky tests.","engines":{"node":">=18"},"files":["bin/","lib/","examples/","README.md","LICENSE","CHANGELOG.md"],"homepage":"https://github.com/WJDdidi-1/dev-doctor#readme","keywords":["cli","diagnostics","ai-coding","context","build-cache","flaky-tests","path","developer-tools","offline"],"license":"Apache-2.0","name":"dev-diagnosis-cli","repository":{"type":"git","url":"git+https://github.com/WJDdidi-1/dev-doctor.git"},"scripts":{"example":"node examples/demo.mjs","test":"node --test"},"type":"module","version":"0.1.
|
|
1
|
+
{"author":"WJDdidi-1","bin":{"dev-diagnosis":"bin/dev-diagnosis.js"},"bugs":{"url":"https://github.com/WJDdidi-1/dev-doctor/issues"},"description":"One offline CLI that diagnoses a repo the way four small tools do: context noise for AI agents, missing CLI commands, build-cache value, and flaky tests.","engines":{"node":">=18"},"files":["bin/","lib/","examples/","README.md","LICENSE","CHANGELOG.md"],"homepage":"https://github.com/WJDdidi-1/dev-doctor#readme","keywords":["cli","diagnostics","ai-coding","context","build-cache","flaky-tests","path","developer-tools","offline"],"license":"Apache-2.0","name":"dev-diagnosis-cli","repository":{"type":"git","url":"git+https://github.com/WJDdidi-1/dev-doctor.git"},"scripts":{"example":"node examples/demo.mjs","test":"node --test"},"type":"module","version":"0.1.5"}
|