dev-diagnosis-cli 0.1.8 → 0.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 +89 -0
- package/README.md +120 -14
- package/bin/dev-diagnosis.js +234 -188
- package/lib/checks.mjs +280 -0
- package/lib/context.mjs +49 -9
- package/lib/mcp.mjs +271 -0
- package/lib/report.mjs +12 -0
- package/lib/setup.mjs +249 -0
- package/lib/skill.mjs +81 -0
- package/package.json +2 -2
- /package/examples/runs/{run-1 → run-01}/results.xml +0 -0
- /package/examples/runs/{run-2 → run-02}/results.xml +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,94 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.0 — 2026-11-12
|
|
4
|
+
|
|
5
|
+
- New: `dev-diagnosis --mcp` serves the four checks as an MCP server
|
|
6
|
+
on stdio (pure Node.js standard library, no new dependencies): five
|
|
7
|
+
tools (`diagnose_context`, `diagnose_path`, `diagnose_cache`,
|
|
8
|
+
`diagnose_flakes`, `diagnose_all`), each returning the same JSON the
|
|
9
|
+
CLI's `--json` produces. `initialize` (protocol 2024-11-05),
|
|
10
|
+
`tools/list`, `tools/call` and `ping` are supported. `--sandbox
|
|
11
|
+
<dir>` (alias `--root`) restricts every path the tools touch to that
|
|
12
|
+
directory and rejects anything outside it with a plain error.
|
|
13
|
+
- New: `dev-diagnosis --skill-generate` writes a Claude Agent Skills
|
|
14
|
+
SKILL.md (`.claude/skills/dev-diagnosis/SKILL.md`, or
|
|
15
|
+
`~/.claude/skills/dev-diagnosis/SKILL.md` with `--global`) telling an
|
|
16
|
+
agent to run `dev-diagnosis all` when it starts work in a repo, fix
|
|
17
|
+
what FAILs, and re-run to confirm. It refuses to overwrite an
|
|
18
|
+
existing SKILL.md.
|
|
19
|
+
- New: `context` reports what the listed noise costs in tokens —
|
|
20
|
+
`≈ 439k tokens (estimate, ~4 bytes per token)` next to the noise
|
|
21
|
+
list, and `estimatedTokens` (number, or null when there is no noise)
|
|
22
|
+
in the JSON output. The score is unchanged.
|
|
23
|
+
- New: `all` ends with a one-line summary — passed/failed/skipped
|
|
24
|
+
counts, context noise bytes, and the cache saving when the cache
|
|
25
|
+
check ran — in text output and as a `summary` object in `--json`.
|
|
26
|
+
- New: `dev-diagnosis setup` wires the MCP server into the agents on
|
|
27
|
+
your machine (Claude Code, Codex CLI, Cursor, VS Code) in one
|
|
28
|
+
command. It prints a preview of exactly what will be written before
|
|
29
|
+
writing anything: a config that already mentions dev-diagnosis is
|
|
30
|
+
left alone, one that exists without it is merged (other entries
|
|
31
|
+
kept), a missing one is created, and a config it cannot parse is
|
|
32
|
+
left alone and reported. `--dry-run` previews without writing;
|
|
33
|
+
`--check` reports which agents are wired (exit 0 when all are).
|
|
34
|
+
- New: a GitHub Action (`action.yml` at the repo root) runs
|
|
35
|
+
`dev-diagnosis all` in one CI step and fails the job when a check
|
|
36
|
+
fails. It runs the published package, so it stays current. It lives
|
|
37
|
+
at the repo root because the GitHub App cannot push
|
|
38
|
+
`.github/workflows/*`.
|
|
39
|
+
- Fix: `context --fix` (and `all --fix`, and the MCP tools with
|
|
40
|
+
`fix: true`) used to report the pre-fix verdict — exit 1 and FAIL —
|
|
41
|
+
even though the fix had landed and a re-run scores clean. A fix
|
|
42
|
+
command now re-scans after writing `.aiignore` and reports the repo
|
|
43
|
+
as it stands after the fix: the new score, the verdict and the exit
|
|
44
|
+
code all follow the post-fix scan, and `--json` carries the fix
|
|
45
|
+
outcome on the post-fix result. The fix still does not mask other
|
|
46
|
+
failures: `all --fix` exits 1 when flakes, path or cache still fail.
|
|
47
|
+
(Tests 124.)
|
|
48
|
+
- Fix: the test suite now runs serially (`node --test
|
|
49
|
+
--test-concurrency=1`): the cache check times real builds, so test
|
|
50
|
+
files running in parallel skewed its cold-vs-warm timings and
|
|
51
|
+
flipped the verdict on a loaded machine. (122 tests.)
|
|
52
|
+
- Fix: `context --fix` also wrote review suggestions into `.aiignore`
|
|
53
|
+
— a secret-like file costs no score points, so the entry fixed
|
|
54
|
+
nothing, and a basename pattern like `secret.js` hid every
|
|
55
|
+
same-named file in the repo, including harmless test fixtures.
|
|
56
|
+
Review suggestions are now advisory only (`reviewSuggestions` in
|
|
57
|
+
`--json`, printed as such) and `--fix` writes only the entries that
|
|
58
|
+
improve the score; a re-scan after `--fix` still lists the review
|
|
59
|
+
items instead of silently hiding them.
|
|
60
|
+
- Docs: the README now opens with a 22 s terminal screencast
|
|
61
|
+
(`docs/demo.gif`, 92 KB): `all` on the demo repo finds ≈439k tokens
|
|
62
|
+
of noise, `--fix` writes one `.aiignore` entry, a re-run comes back
|
|
63
|
+
94/100 PASS. Every line is verbatim CLI output captured 2026-11-12;
|
|
64
|
+
the render script is not in the repo (it lives with the run logs).
|
|
65
|
+
- Fix: the suite leaked every temp dir it created (~100 MB per run) —
|
|
66
|
+
after a few runs /tmp filled up and unrelated tests started failing
|
|
67
|
+
on file creation. Temp dirs are now removed after the test that
|
|
68
|
+
created them (`scripts/support.mjs`); the suite passes repeatedly
|
|
69
|
+
with /tmp staying clean.
|
|
70
|
+
- Fix: `context` listed noise that cost no points and told the user to
|
|
71
|
+
fix it — on a 100/100 repo it still printed "Noise to keep away"
|
|
72
|
+
and a `.aiignore` fix for the lockfile, contradicting its own PASS
|
|
73
|
+
verdict. Only noise in a category that actually lost points is now
|
|
74
|
+
listed or suggested (a 95 B lockfile in a 1.7 MB repo loses 0
|
|
75
|
+
points, so it is not something to fix); the score itself is
|
|
76
|
+
unchanged, and the README example now shows the shorter noise list.
|
|
77
|
+
- Fix: the `path` verdict said "missing in the current shell" even
|
|
78
|
+
when the command missed in all four shell contexts — which sounded
|
|
79
|
+
like it might exist somewhere else — and never said where it did
|
|
80
|
+
resolve when another context had it. It now says "not found in any
|
|
81
|
+
shell context" when nothing has it, and "missing in the current
|
|
82
|
+
shell, but resolves in login" (naming the contexts) when another one
|
|
83
|
+
does.
|
|
84
|
+
- Internals: the four checks moved into `lib/checks.mjs`, the one
|
|
85
|
+
place their logic lives — the CLI renders it, the MCP server serves
|
|
86
|
+
it, neither re-implements a verdict. (120 tests.)
|
|
87
|
+
- Docs: the README top is rewritten from the user's side — what the
|
|
88
|
+
noise costs in tokens, the three-step fix, one line per scenario, a
|
|
89
|
+
capability matrix that says what each check cannot find, and
|
|
90
|
+
copy-paste MCP configs for Claude Code and Codex.
|
|
91
|
+
|
|
3
92
|
## 0.1.8 — 2026-11-12
|
|
4
93
|
|
|
5
94
|
- Fix: `all --json` embedded the build's full stdout (`coldStdout` /
|
package/README.md
CHANGED
|
@@ -5,7 +5,47 @@
|
|
|
5
5
|
[](https://github.com/WJDdidi-1/dev-doctor/blob/main/LICENSE)
|
|
6
6
|
[](https://www.npmjs.com/package/dev-diagnosis-cli)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Every token your agent spends reading a 1.7 MB data dump is money out of your pocket. Every flaky test is CI time your agent sits waiting. Every missing command is a turn your agent burns for nothing. dev-diagnosis finds all three — plus whether your build cache actually saves anything — in one command, offline, with no dependencies.
|
|
9
|
+
|
|
10
|
+

|
|
11
|
+
|
|
12
|
+
## Try it: three steps, one fix
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
$ dev-diagnosis all
|
|
16
|
+
Files: 9 Size: 1.68 MB Score: 75/100 — Some context noise found
|
|
17
|
+
Noise to keep away from an AI agent:
|
|
18
|
+
data/export.json — large file (1.68 MB)
|
|
19
|
+
Estimated tokens wasted on this noise: ≈ 439k tokens (estimate, ~4 bytes per token)
|
|
20
|
+
FAIL some context noise found (score 75/100)
|
|
21
|
+
|
|
22
|
+
$ dev-diagnosis context --fix
|
|
23
|
+
Created .aiignore with 1 entry: data/export.json
|
|
24
|
+
Re-scanned after fix: Score: 94/100 — Looks clean for an AI coding agent
|
|
25
|
+
PASS context is clean
|
|
26
|
+
|
|
27
|
+
$ dev-diagnosis all
|
|
28
|
+
Files: 9 Size: 1.16 KB Score: 94/100 — Looks clean for an AI coding agent
|
|
29
|
+
PASS context is clean
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The noise cost 439k tokens a turn; the fix is one entry in `.aiignore`.
|
|
33
|
+
|
|
34
|
+
## When you reach for it
|
|
35
|
+
|
|
36
|
+
- Just took over a repo: `dev-diagnosis all`
|
|
37
|
+
- CI goes red, then green on retry, then red again: `dev-diagnosis flakes ci-runs/`
|
|
38
|
+
- Builds feel slow even with a cache: `dev-diagnosis cache -- npm run build`
|
|
39
|
+
- `command not found` in the IDE but works in the terminal: `dev-diagnosis path <name>`
|
|
40
|
+
|
|
41
|
+
## What each check does — and does not do
|
|
42
|
+
|
|
43
|
+
| Check | Needs | Finds | Cannot find |
|
|
44
|
+
|---|---|---|---|
|
|
45
|
+
| `context` | a directory | files your agent should not read, and what they cost in tokens | whether a large file is actually needed — it flags by size, you decide |
|
|
46
|
+
| `path` | a command name | which shell contexts resolve it, shadowed copies, toolchain installs | why a command that resolves still crashes when it runs |
|
|
47
|
+
| `cache` | a build command and a cache directory | whether the cache pays, cold vs warm | whether a different cache setup would be faster |
|
|
48
|
+
| `flakes` | JUnit XML from two or more runs | flaky, always-failing and passed-on-retry tests, ranked | why a test is flaky — only that it is |
|
|
9
49
|
|
|
10
50
|
## Install and run
|
|
11
51
|
|
|
@@ -32,7 +72,75 @@ dev-diagnosis all [path] --command <name> --flakes <dir> -- <build-command...>
|
|
|
32
72
|
|
|
33
73
|
`all` always runs `context` on `[path]` (default: the current directory) and runs `path`, `flakes` and `cache` when their input is given. Checks without their input are listed as skipped, with the command that would run them, instead of silently pretending they ran. A build command on a repo with no cache directory to measure is also listed as skipped rather than failing: nothing to measure is not a problem. `--json` gives machine-readable output for `context`, `path`, `cache`, `flakes` and `all`. In `all --json`, a check that could not run (a missing runs directory, a failing build) reports `{ "error": "<reason>" }` instead of `null`, so a script can tell why the overall result failed. Add `--fix` to `context` (or `all`) to write the suggestions into `<path>/.aiignore` instead of only printing them: entries already there are left alone, nothing else in the file is touched, and a later scan skips everything `.aiignore` lists — so `context --fix` followed by `context` comes back clean.
|
|
34
74
|
|
|
35
|
-
|
|
75
|
+
`all` ends with a one-line summary: how many checks passed, failed or were skipped, how much context noise was found, and what the cache saved when it ran. In `--json` output the same fields are in the `summary` object.
|
|
76
|
+
|
|
77
|
+
Exit codes: `0` every check that ran passed; `1` a check found something to fix or could not run; `2` usage error. With `--fix`, the exit code follows a re-scan after the fix, so a fix that leaves the repo clean exits `0` — the command reports the repo as it stands after the fix, not as it was before.
|
|
78
|
+
|
|
79
|
+
## Let your agent run it
|
|
80
|
+
|
|
81
|
+
### One-command install
|
|
82
|
+
|
|
83
|
+
`dev-diagnosis setup` detects the agents on your machine (Claude Code, Codex CLI, Cursor, VS Code) and writes the MCP config that wires dev-diagnosis into each of them. It prints a preview of exactly what will be written before writing anything: a config that already mentions dev-diagnosis is left alone, a config that exists without it is merged (other entries kept), a missing config is created. A config it cannot parse is left alone and reported.
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
dev-diagnosis setup # preview, then write
|
|
87
|
+
dev-diagnosis setup --dry-run # preview only, write nothing
|
|
88
|
+
dev-diagnosis setup --check # report which agents are wired (exit 0 when all are)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
If `dev-diagnosis` itself is not on PATH, setup says so — install it globally (`npm install -g dev-diagnosis-cli`) or the agents will not be able to run it.
|
|
92
|
+
|
|
93
|
+
### MCP server
|
|
94
|
+
|
|
95
|
+
`dev-diagnosis --mcp` serves the same four checks as MCP tools over stdio — no extra install, no network, the same code the CLI runs. Add it to your agent once:
|
|
96
|
+
|
|
97
|
+
Claude Code (`.mcp.json` in the repo, or `claude mcp add dev-diagnosis -- dev-diagnosis --mcp`):
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"mcpServers": {
|
|
102
|
+
"dev-diagnosis": {
|
|
103
|
+
"command": "dev-diagnosis",
|
|
104
|
+
"args": ["--mcp"]
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Codex (`codex mcp add dev-diagnosis -- dev-diagnosis --mcp`, or in `~/.codex/config.toml`):
|
|
111
|
+
|
|
112
|
+
```toml
|
|
113
|
+
[mcp_servers.dev-diagnosis]
|
|
114
|
+
command = "dev-diagnosis"
|
|
115
|
+
args = ["--mcp"]
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
To keep the agent inside one repo, add `--sandbox <dir>` (alias `--root`): paths outside it are rejected with a plain error. Five tools: `diagnose_context`, `diagnose_path`, `diagnose_cache`, `diagnose_flakes`, `diagnose_all` — each returns the same JSON the CLI's `--json` produces.
|
|
119
|
+
|
|
120
|
+
### Agent Skills
|
|
121
|
+
|
|
122
|
+
`dev-diagnosis --skill-generate` writes `.claude/skills/dev-diagnosis/SKILL.md` in the current repo (or `~/.claude/skills/dev-diagnosis/SKILL.md` with `--global`). The skill tells an agent to run `dev-diagnosis all` when it starts work in a repo, fix what FAILs, and re-run to confirm. It refuses to overwrite an existing SKILL.md, so your own edits are safe.
|
|
123
|
+
|
|
124
|
+
## In CI
|
|
125
|
+
|
|
126
|
+
One step runs the diagnosis and fails the job when a check fails:
|
|
127
|
+
|
|
128
|
+
```yaml
|
|
129
|
+
jobs:
|
|
130
|
+
diagnose:
|
|
131
|
+
runs-on: ubuntu-latest
|
|
132
|
+
steps:
|
|
133
|
+
- uses: actions/checkout@v4
|
|
134
|
+
- uses: actions/setup-node@v4
|
|
135
|
+
with:
|
|
136
|
+
node-version: 20
|
|
137
|
+
- uses: WJDdidi-1/dev-doctor@main
|
|
138
|
+
with:
|
|
139
|
+
path: .
|
|
140
|
+
args: --command node
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
`args` is passed straight to `dev-diagnosis all`, so `--command`, `--flakes`, `--fix` and a build command after `--` all work the same way they do on the command line. The action runs the published npm package (`@latest`), so a repo using it always gets the newest checks.
|
|
36
144
|
|
|
37
145
|
## Example
|
|
38
146
|
|
|
@@ -51,16 +159,11 @@ Files: 9 Size: 1.68 MB Score: 75/100 — Some context noise found
|
|
|
51
159
|
logs: 79 B (0%) — lost 0 of 15
|
|
52
160
|
Noise to keep away from an AI agent:
|
|
53
161
|
data/export.json — large file (1.68 MB)
|
|
54
|
-
|
|
55
|
-
logs/dev.log — local log file (79 B)
|
|
56
|
-
package-lock.json — lockfile (95 B)
|
|
162
|
+
Estimated tokens wasted on this noise: ≈ 439k tokens (estimate, ~4 bytes per token)
|
|
57
163
|
Worth a look before sharing:
|
|
58
164
|
.env.example — environment template (usually safe to share)
|
|
59
165
|
Fix: add these to .aiignore (or the agent's ignore list):
|
|
60
|
-
*.log
|
|
61
166
|
data/export.json
|
|
62
|
-
dist/
|
|
63
|
-
package-lock.json
|
|
64
167
|
FAIL some context noise found (score 75/100)
|
|
65
168
|
|
|
66
169
|
== path ==
|
|
@@ -80,11 +183,12 @@ FAIL 1 flaky, 1 always-failing across 2 runs
|
|
|
80
183
|
== cache ==
|
|
81
184
|
Cache dir: /home/hatch/workspace/dev-doctor-build/dev-doctor/examples/demo-repo/.cache
|
|
82
185
|
Command: node build.mjs
|
|
83
|
-
Cold:
|
|
84
|
-
Verdict: cache pays — warm run is
|
|
85
|
-
PASS cache pays: cold
|
|
186
|
+
Cold: 484 ms Warm: 82 ms Saved: 402 ms (83%)
|
|
187
|
+
Verdict: cache pays — warm run is 402 ms (83%) faster than cold
|
|
188
|
+
PASS cache pays: cold 484 ms, warm 82 ms (warm run is 402 ms (83%) faster than cold)
|
|
86
189
|
|
|
87
190
|
Overall: FAIL — see the checks above
|
|
191
|
+
Summary: 4 checks — 2 passed, 2 failed, 0 skipped; context noise 1.68 MB; cache saved 83%
|
|
88
192
|
```
|
|
89
193
|
|
|
90
194
|
The demo repo is intentionally noisy, so `all` exits 1: the context and flakes checks fail while path and cache pass. That is the point of the fixture.
|
|
@@ -93,9 +197,9 @@ The demo repo is intentionally noisy, so `all` exits 1: the context and flakes c
|
|
|
93
197
|
|
|
94
198
|
### `context` — what an AI agent should not read
|
|
95
199
|
|
|
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. Files and directories listed in `.gitignore` — at the repo root or in a subdirectory — are excluded the same way: they are already invisible to most agents, so flagging them would be noise about noise, and `--fix` will not duplicate them into `.aiignore`. The common pattern forms work (`*`, `?`, `[...]`, `**`, `/`-anchored paths, directory-only `dir/`, and `!` negation with last-match-wins); `.git/info/exclude` and the global gitignore are not read. `context --fix` writes the suggestions into `.aiignore` for you; `--json` includes the fix outcome in the output.
|
|
200
|
+
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. Files and directories listed in `.gitignore` — at the repo root or in a subdirectory — are excluded the same way: they are already invisible to most agents, so flagging them would be noise about noise, and `--fix` will not duplicate them into `.aiignore`. The common pattern forms work (`*`, `?`, `[...]`, `**`, `/`-anchored paths, directory-only `dir/`, and `!` negation with last-match-wins); `.git/info/exclude` and the global gitignore are not read. `context --fix` writes the suggestions into `.aiignore` for you; `--json` includes the fix outcome in the output. Review items — secret-like files and environment templates — are listed for a manual look and are never written by `--fix`: they cost no score points, so the entry would fix nothing, and a basename pattern such as `secret.js` would hide every same-named file in the repo, including test fixtures. They appear as `reviewSuggestions` in `--json`, printed as advisory.
|
|
97
201
|
|
|
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.
|
|
202
|
+
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. Only noise in a category that actually lost points is listed as noise or suggested as a fix: a 95 B lockfile in a 1.7 MB repo loses 0 points, so it is not something to fix — a 100/100 scan lists nothing to fix.
|
|
99
203
|
|
|
100
204
|
### `path` — why a command is missing
|
|
101
205
|
|
|
@@ -112,10 +216,12 @@ Reads JUnit XML across CI runs — each subdirectory of `<junit-dir>` is one run
|
|
|
112
216
|
## Development
|
|
113
217
|
|
|
114
218
|
```sh
|
|
115
|
-
npm test # node:test, no extra dependencies —
|
|
219
|
+
npm test # node:test, no extra dependencies — 124 tests, run serially
|
|
116
220
|
npm run example # run the CLI against the demo fixture
|
|
117
221
|
```
|
|
118
222
|
|
|
223
|
+
The suite runs serially on purpose (`--test-concurrency=1`): the cache check times real builds, so test files running in parallel would skew its cold-vs-warm timings.
|
|
224
|
+
|
|
119
225
|
There is nothing to install: the CLI has no runtime dependencies, so
|
|
120
226
|
`npm test` works straight after cloning. Run the checkout as
|
|
121
227
|
`node bin/dev-diagnosis.js …` — see Troubleshooting if you reach for
|