@vantageos/mcp-doctor 0.3.1 → 0.3.2

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
@@ -3,6 +3,37 @@
3
3
  All notable changes to `@vantageos/mcp-doctor` are documented here.
4
4
  This project adheres to [Semantic Versioning](https://semver.org/).
5
5
 
6
+ ## 0.3.2 — 2026-10-04
7
+
8
+ ### Changed — read this if your CI distinguishes exit codes
9
+ - **Unreadable input is now `could-not-judge` (exit 2), no longer a crash (exit 1).**
10
+ A tree holding input a detector could not read — malformed JSON in an extension
11
+ manifest or `evals.json`, a computed or non-literal value where a literal is
12
+ required — used to abort the run with a stack trace and exit 1, the code this
13
+ tool uses for *a violation*. It now completes the run, names the unreadable
14
+ file in the row, and exits 2 (no violation, but part of the tree was not judged).
15
+ Pipelines that treat any non-zero exit as failure are unaffected. Pipelines that
16
+ distinguish 1 from 2 must read the new state: a run that used to exit 1 on
17
+ unreadable input now exits 2. (#46)
18
+
19
+ ### Fixed
20
+ - **A manifest that parses but is wrong is `non-conforming`.** It is a finding
21
+ (exit 1) rather than an abstention or a crash. (#46)
22
+ - **An unparseable `package.json` is `could-not-judge` for C17, D10 and D7** (and C14, D12), where each had judged an empty manifest and reported the emptiness as a finding (C17, D10 non-conforming) or an absence (D7), so the run exited 1 instead of 2. The parse failure is now recorded once at load time and every detector reading that file honours it.
23
+ - **Tools declared as descriptor objects are now found.** Five detectors (D3, D4, D8, D11, DServer2) and C19 reported "no registered tools" on servers that declare their tools as descriptor objects (`{ name, inputSchema }`). They now find those tools. A tree that serves tools but where none can be located reads `could-not-judge`, not `absent`. On a real vCRM tree, the "no registered tools found" rows went from 1 to 0, and D11 is now a real finding. (#48)
24
+ - **`package.json` is now what npm publishes.** `npm publish` of 0.3.1 printed
25
+ "npm auto-corrected some errors in your package.json": `bin` was `"./dist/doctor.js"`
26
+ and is now `"dist/doctor.js"`, and `files` is reformatted, both exactly as
27
+ `npm pkg fix` writes them. A new test, `tests/publish-manifest-clean.test.ts`,
28
+ runs `npm publish --dry-run` and fails if that warning returns, and asserts the
29
+ tarball lists `dist/doctor.js`, `README.md` and `LICENSE`.
30
+
31
+ ### Docs
32
+ - README: the states table and the known limits no longer say unreadable input is
33
+ handled in band by D9 only.
34
+
35
+ ---
36
+
6
37
  ## 0.3.1 — 2026-10-04
7
38
 
8
39
  ### Fixed
package/README.md CHANGED
@@ -63,8 +63,8 @@ exit: 0 clean, 1 a violation, 2 an abstention with no violation
63
63
  |---|---|---|
64
64
  | `present` | the standard item is satisfied | none |
65
65
  | `absent` | the detector found nothing to judge — see the caveat below | none |
66
- | `non-conforming` | the item is present and wrong | **exit 1** |
67
- | `could-not-judge` | the detector could not read its input and says so in the row — in 0.3.1, only D9 does this (no `package.json` above the root); see the limits below | **exit 2**, unless something else is non-conforming |
66
+ | `non-conforming` | the item is present and wrong (this includes a manifest that parses but holds a wrong value) | **exit 1** |
67
+ | `could-not-judge` | the detector could not read its input and says so in the row — malformed JSON, a computed or non-literal value, no `package.json` above the root; the run completes and the row names the file | **exit 2**, unless something else is non-conforming |
68
68
 
69
69
  The exit code keeps three outcomes distinct, which is what makes the tool safe in CI:
70
70
 
@@ -73,16 +73,12 @@ The exit code keeps three outcomes distinct, which is what makes the tool safe i
73
73
  - **2** — no violation, but at least one detector abstained. **An abstention is never a pass**: it
74
74
  means part of the tree was not judged, and the row names which part and why.
75
75
 
76
- **Two known limits in 0.3.1, stated rather than hidden:**
76
+ **One known limit in 0.3.2, stated rather than hidden:**
77
77
 
78
78
  - **`absent` currently means two things.** It is used both for "this rule does not apply here" and,
79
79
  for some detectors, "this is required and missing". The second should move the exit code and
80
80
  today does not. Until that is split, read an `absent` row against the rule it names rather than
81
81
  treating it as harmless.
82
- - **Unreadable input is handled in band by D9 only.** In 0.3.1, D9 reports `could-not-judge` when no
83
- `package.json` sits above the scanned root, and the run completes. Several other detectors still
84
- **throw** on unreadable input — a malformed manifest, a computed value — which aborts the run with
85
- exit 1 and a stack trace, indistinguishable from a violation. Converting them is in progress.
86
82
 
87
83
  By design, a detector whose own internal self-check fails stops the run — that is the instrument
88
84
  reporting that it is broken, and silencing it would hide the fault behind a normal-looking table.
package/dist/doctor.d.ts CHANGED
@@ -13,9 +13,15 @@ interface SourceFile {
13
13
  interface Tree {
14
14
  root: string;
15
15
  files: SourceFile[];
16
+ /**
17
+ * `unreadable` is set (with the parse error) when the file exists but is not a
18
+ * JSON object; `json` is then `{}` and MUST NOT be read as the file's content.
19
+ * Detectors that read this file go through `guardUnreadablePackageJson`.
20
+ */
16
21
  packageJson: {
17
22
  path: string;
18
23
  json: Record<string, unknown>;
24
+ unreadable?: string;
19
25
  } | null;
20
26
  }
21
27