vmware-debug 1.13.0__tar.gz → 1.13.2__tar.gz

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.
Files changed (97) hide show
  1. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/.claude-plugin/plugin.json +1 -1
  2. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/.mcp.json +1 -1
  3. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/PKG-INFO +1 -1
  4. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/RELEASE_NOTES.md +44 -0
  5. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/openclaw.plugin.json +1 -1
  6. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/package.json +1 -1
  7. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/pyproject.toml +1 -1
  8. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/server.json +2 -2
  9. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/skills/vmware-debug/SKILL.md +13 -6
  10. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/skills/vmware-debug/references/agent-guardrails.md +4 -0
  11. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/skills/vmware-debug/references/routing.md +1 -1
  12. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/skills/vmware-debug/references/setup-guide.md +2 -2
  13. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/capability/_scores.json +37 -37
  14. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/capability/_scoring.py +1 -1
  15. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/regression/test_capability_grader.py +2 -2
  16. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/test_case_grading.py +9 -2
  17. vmware_debug-1.13.2/tests/test_case_grading_per_hypothesis.py +304 -0
  18. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/test_case_hypotheses.py +16 -2
  19. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/uv.lock +7 -7
  20. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/__init__.py +1 -1
  21. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/mcp_server/server.py +9 -9
  22. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/ops/cases/api.py +5 -1
  23. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/ops/cases/grading.py +120 -40
  24. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/ops/cases/hypotheses.py +25 -5
  25. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/rules/grading_rules.yaml +2 -0
  26. vmware_debug-1.13.0/tests/test_case_grading_per_hypothesis.py +0 -131
  27. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/.clawhubignore +0 -0
  28. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/.gitignore +0 -0
  29. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/README-CN.md +0 -0
  30. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/README.md +0 -0
  31. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/SECURITY.md +0 -0
  32. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/docs/plans/2026-08-28-investigation-layer-design.md +0 -0
  33. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/skills/vmware-debug/references/capabilities.md +0 -0
  34. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/skills/vmware-debug/references/cli-reference.md +0 -0
  35. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/skills/vmware-debug/references/event-envelope.md +0 -0
  36. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/__init__.py +0 -0
  37. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/conftest.py +0 -0
  38. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/__init__.py +0 -0
  39. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/capability/__init__.py +0 -0
  40. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/capability/_family.py +0 -0
  41. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/capability/_skill.py +0 -0
  42. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/capability/conftest.py +0 -0
  43. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/capability/test_entity_reachability.py +0 -0
  44. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/capability/test_error_actionability.py +0 -0
  45. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/capability/test_tool_description_quality.py +0 -0
  46. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/capability/test_tool_manifest_budget.py +0 -0
  47. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/regression/__init__.py +0 -0
  48. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/regression/_vsphere_event_vocabulary.py +0 -0
  49. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/regression/test_audit_isolation.py +0 -0
  50. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/regression/test_case_id_non_ascii.py +0 -0
  51. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/regression/test_case_plan_max_steps.py +0 -0
  52. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/regression/test_classification_against_vsphere_vocabulary.py +0 -0
  53. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/regression/test_debug_regressions.py +0 -0
  54. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/regression/test_environment_resolver_isolation.py +0 -0
  55. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/regression/test_every_tool_parameter_is_documented.py +0 -0
  56. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/regression/test_evidence_payload_contract.py +0 -0
  57. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/regression/test_host_lifecycle_classification.py +0 -0
  58. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/regression/test_investigation_metrics.py +0 -0
  59. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/regression/test_real_alert_titles_classify.py +0 -0
  60. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/regression/test_result_envelope.py +0 -0
  61. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/regression/test_skill_name_aliases.py +0 -0
  62. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/regression/test_spike_resolution.py +0 -0
  63. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/eval/regression/test_tool_annotations.py +0 -0
  64. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/test_case_conclusion.py +0 -0
  65. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/test_case_evidence.py +0 -0
  66. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/test_case_ids.py +0 -0
  67. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/test_case_ledger_concurrency.py +0 -0
  68. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/test_case_plan.py +0 -0
  69. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/test_case_readiness.py +0 -0
  70. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/test_case_store.py +0 -0
  71. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/test_case_timeline_close.py +0 -0
  72. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/test_case_tools.py +0 -0
  73. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/test_knowledge.py +0 -0
  74. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/test_mcp_audit.py +0 -0
  75. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/test_safe_error_passthrough.py +0 -0
  76. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/tests/test_timeline.py +0 -0
  77. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/cli.py +0 -0
  78. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/envelope.py +0 -0
  79. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/mcp/__init__.py +0 -0
  80. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/mcp/tools.py +0 -0
  81. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/mcp_server/__init__.py +0 -0
  82. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/ops/__init__.py +0 -0
  83. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/ops/cases/__init__.py +0 -0
  84. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/ops/cases/conclusion.py +0 -0
  85. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/ops/cases/evidence.py +0 -0
  86. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/ops/cases/ids.py +0 -0
  87. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/ops/cases/knowledge.py +0 -0
  88. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/ops/cases/model.py +0 -0
  89. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/ops/cases/payloads.py +0 -0
  90. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/ops/cases/plan.py +0 -0
  91. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/ops/cases/readiness.py +0 -0
  92. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/ops/cases/sources.py +0 -0
  93. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/ops/cases/store.py +0 -0
  94. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/ops/cases/timeline.py +0 -0
  95. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/ops/skill_names.py +0 -0
  96. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/ops/timeline.py +0 -0
  97. {vmware_debug-1.13.0 → vmware_debug-1.13.2}/vmware_debug/rules/evidence_sources.yaml +0 -0
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://anthropic.com/claude-code/plugin.schema.json",
3
3
  "name": "vmware-debug",
4
4
  "displayName": "VMware Debug",
5
- "version": "1.13.0",
5
+ "version": "1.13.2",
6
6
  "description": "VMware incident timeline, root-cause routing, local case ledger; no vSphere access. 14 MCP tools.",
7
7
  "author": {
8
8
  "name": "Wei Zhou",
@@ -5,7 +5,7 @@
5
5
  "command": "uvx",
6
6
  "args": [
7
7
  "--from",
8
- "vmware-debug==1.13.0",
8
+ "vmware-debug==1.13.2",
9
9
  "vmware-debug-mcp"
10
10
  ]
11
11
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: vmware-debug
3
- Version: 1.13.0
3
+ Version: 1.13.2
4
4
  Summary: VMware diagnostic brain — offline incident triage, log/event correlation, and root-cause routing across the VMware skill family
5
5
  Project-URL: Homepage, https://github.com/vmware-skills/VMware-Debug
6
6
  Project-URL: Repository, https://github.com/vmware-skills/VMware-Debug
@@ -1,3 +1,47 @@
1
+ ## v1.13.2 — auth diagnosis never reads or records a secret
2
+
3
+ Docs only; no code change.
4
+
5
+ * **The auth routing said to check "config/.env"** without limiting that to whether a credential is set, and nothing
6
+ told the agent to keep secret values out of case evidence, which is stored as submitted and kept until deleted.
7
+ The auth route now uses the owning skill's `doctor` (it reports whether a credential is set and whether login
8
+ works, never the value). SKILL.md and the small-model guardrails now forbid putting a password, token or `.env`
9
+ contents into any evidence field, and forbid opening `.env` files to diagnose. Raised by ClawHub's review of
10
+ 1.13.1.
11
+
12
+ ## v1.13.1 — a hypothesis is ruled out only by sources against it
13
+
14
+ Corrections to 1.13.0, from a second independent review on 2026-09-15. Each case below was reproduced on 1.13.0
15
+ and is now a test.
16
+
17
+ * **Exclusion counts sources per hypothesis.** 1.13.0 counted the two independent sources an exclusion needs
18
+ across the whole case. One observation against H2 plus any unrelated evidence ruled H2 out, retired the gap that
19
+ blocked H2, and promoted the case from Candidate to Probable; H1 falsified by Aria and H2 by Monitor excluded
20
+ both. A hypothesis is now ruled out only when two independent skills falsify *that* hypothesis.
21
+ * **No registered hypotheses never grades Excluded.** With a missing ledger, or a case older than the ledger,
22
+ "every hypothesis is ruled out" was true of an empty list, and the case was graded Excluded.
23
+ * **A contradicted hypothesis holds the case at Candidate.** Evidence against an open hypothesis that is not yet
24
+ enough to rule it out now holds the case where a gap that could overturn it would. Without this, the stricter
25
+ count above made a lone falsifier count for nothing, and a case kept Probable, or Confirmed, with an observation
26
+ against a hypothesis still unanswered (third review, same day).
27
+ * **A corrupt `hypotheses.md` is a reason, not a crash.** 1.13.0 handled a missing file but let a hand-edited
28
+ broken entry raise out of `case_grade`, including entries that are valid JSON but not a hypothesis (`[]`,
29
+ `null`, `{}`).
30
+ * **Falsifying evidence never counts as support.** 1.13.0 took it out of the count only when an exclusion
31
+ succeeded, so under a site rule needing three sources two falsifiers of H2 graded the case Probable.
32
+ * `case_hypotheses` loads the grading rules before registering a hypothesis, so a broken site
33
+ `grading_rules.yaml` fails the call without writing; a retry no longer registers it twice.
34
+ * **Behaviour change:** `case_hypotheses` marks a hypothesis `refuted` by the same rule as `case_grade`. With one
35
+ falsifying source it stays `open` or `blocked`; `refuted_by` still lists the item, and the first next step says
36
+ how many more sources are needed. `case_grade` reasons name each contradicted hypothesis with its evidence and
37
+ source count. A site that sets `excluded.requires_falsifying_evidence: false` never excludes, so under that
38
+ setting a contradicted hypothesis holds its case at Candidate for as long as the contradiction stands — the
39
+ grade reason says so instead of promising a rule-out that cannot happen.
40
+
41
+ Re-running the lab investigation of the same Aria alert on this code: the first observation against H2 held the
42
+ case at Candidate ("H2 is contradicted by E007 from 1 independent source(s)"), a second skill ruled H2 out, H3
43
+ went the same way, and the case ended **Probable** on H1, held below Confirmed by three open gaps.
44
+
1
45
  ## v1.13.0 — exclusion is per hypothesis
2
46
 
3
47
  Found in a real investigation of an Aria "vCenter app health is affected" alert on 2026-09-15, then corrected
@@ -11,7 +11,7 @@
11
11
  "command": "uvx",
12
12
  "args": [
13
13
  "--from",
14
- "vmware-debug==1.13.0",
14
+ "vmware-debug==1.13.2",
15
15
  "vmware-debug-mcp"
16
16
  ]
17
17
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zw008/vmware-debug",
3
- "version": "1.13.0",
3
+ "version": "1.13.2",
4
4
  "description": "VMware incident timeline, root-cause routing, local case ledger; no vSphere access. 14 MCP tools.",
5
5
  "private": true,
6
6
  "license": "MIT",
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "vmware-debug"
7
- version = "1.13.0"
7
+ version = "1.13.2"
8
8
  description = "VMware diagnostic brain — offline incident triage, log/event correlation, and root-cause routing across the VMware skill family"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -7,12 +7,12 @@
7
7
  "url": "https://github.com/vmware-skills/VMware-Debug",
8
8
  "source": "github"
9
9
  },
10
- "version": "1.13.0",
10
+ "version": "1.13.2",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "pypi",
14
14
  "identifier": "vmware-debug",
15
- "version": "1.13.0",
15
+ "version": "1.13.2",
16
16
  "runtimeHint": "uvx",
17
17
  "packageArguments": [
18
18
  {
@@ -51,7 +51,7 @@ write tools touch only the local case ledger.
51
51
  ## Quick Install
52
52
 
53
53
  ```bash
54
- uv tool install vmware-debug==1.13.0
54
+ uv tool install vmware-debug==1.13.2
55
55
  vmware-debug categories # see what it can diagnose
56
56
  ```
57
57
 
@@ -77,7 +77,7 @@ a recommended plan.
77
77
  | CPU / memory contention | vmware-aria (metrics/anomalies) | rightsizing via pilot |
78
78
  | HA / DRS / cluster | vmware-monitor, vmware-aiops | cluster remediation via pilot |
79
79
  | Power / clone / snapshot | vmware-aiops, vmware-monitor | task status, then fix via aiops |
80
- | Auth / cert / login | check creds & cert; (security) | fix config/.env |
80
+ | Auth / cert / login | owning skill's `doctor`, cert, time sync | user fixes config |
81
81
 
82
82
  ## Common Workflows
83
83
 
@@ -175,10 +175,12 @@ ledger — submit the missing evidence, or record the gap that is blocking it.
175
175
  - **Confirmed** — that, plus a decisive item: a direct hardware diagnostic, a
176
176
  version-checked knowledge-base entry, or a vendor SR; and no gap left open
177
177
  - **Excluded** — an observation that actually rules it out. "We looked and found
178
- nothing" is a gap, not an exclusion. Exclusion is per hypothesis: the case is
179
- Excluded only when every registered hypothesis is ruled out. Otherwise
180
- `case_grade` grades what remains, counting only evidence that rules nothing
181
- out, and lists each hypothesis as `open` or `excluded` in `hypotheses`
178
+ nothing" is a gap, not an exclusion. Exclusion is per hypothesis: two
179
+ independent sources must falsify *that* hypothesis, and the case is Excluded
180
+ only when every registered hypothesis is ruled out. A hypothesis contradicted
181
+ by too few sources holds the case at Candidate. Otherwise `case_grade`
182
+ grades what remains, counting only evidence that falsifies nothing, and lists
183
+ each hypothesis as `open` or `excluded` in `hypotheses`
182
184
 
183
185
  `case_plan` is not a checklist: submit evidence and the next plan is shorter,
184
186
  lose a source and it routes around it. Its `unavailable` half is the important
@@ -254,6 +256,11 @@ fetches with the other skills' read tools and submits the results here. Its only
254
256
  writes are to the local case ledger. Running with local or small models? See
255
257
  [`references/agent-guardrails.md`](references/agent-guardrails.md).
256
258
 
259
+ **Never put a secret into a case.** For an auth symptom, record *that* a credential is
260
+ missing, expired or rejected (the owning skill's `doctor` says which) — never a password,
261
+ token, or the contents of a `.env` file, in any evidence `summary`, `query` or `payload`.
262
+ Do not open `.env` files to diagnose; case folders are kept until you delete them.
263
+
257
264
  ## CLI Quick Reference
258
265
 
259
266
  ```bash
@@ -99,6 +99,10 @@ your agent's instruction block.
99
99
  - Report the timeline in the order the tool returned it.
100
100
  - If a requested field was not returned, show it as "not available".
101
101
  - When a response is long, report every item it contains.
102
+ - Never record a secret. For an auth problem, record that a credential is
103
+ missing, expired or rejected (the owning skill's `doctor` reports which) —
104
+ never a password, token, or `.env` contents, in any evidence field. Do not
105
+ open `.env` files to diagnose.
102
106
 
103
107
  ## Analysis discipline
104
108
 
@@ -12,7 +12,7 @@ Keep this in sync with `_CATEGORY_SIGNATURES` in `vmware_debug/ops/timeline.py`
12
12
  | **ha_drs** | ha, high availability, drs, failover, admission control, isolation | vmware-monitor, vmware-aiops (cluster) | pilot |
13
13
  | **host_lifecycle** | maintenance mode, shut down of, host reboot, standby mode, lost connection to, cannot synchronize, not responding | vmware-monitor (host/cluster state), vmware-harden (drift — a host that left service on cue was told to), vmware-log-insight (vpxd/hostd) | pilot |
14
14
  | **power_lifecycle** | power on/off, failed to start, boot, vmx, ovf, clone, snapshot | vmware-aiops (snapshot tree), vmware-monitor | aiops |
15
- | **auth** | login, authentication, denied, 401, 403, token, certificate, tls, password | config/.env, target cert + time sync | config fix |
15
+ | **auth** | login, authentication, denied, 401, 403, token, certificate, tls, password | the owning skill's `doctor` (reports whether a credential is set and whether login works — never its value), target cert + time sync | config fix (by the user) |
16
16
  | **platform** | vpxd, hostd, service restart, crash, 503, not responding, disconnected | vmware-monitor (connection/service), vmware-log-insight (vpxd/hostd) | pilot |
17
17
  | **hardware** | tpm, attestation, ipmi, sensor, bmc | vmware-monitor (host sensors and the CIM Server that supplies them, host logs for ipmi/cim), the server's BMC | site / vendor |
18
18
  | **licensing** | license | vmware-monitor (license_status — which asset holds which key); an Aria alert on "Unlicensed Group" is Aria's own license | license portal |
@@ -6,7 +6,7 @@ is a pure, offline correlation engine. There is no `config.yaml` and no `.env`.
6
6
  ## Install
7
7
 
8
8
  ```bash
9
- uv tool install vmware-debug==1.13.0
9
+ uv tool install vmware-debug==1.13.2
10
10
  vmware-debug categories # verify it runs
11
11
  ```
12
12
 
@@ -15,7 +15,7 @@ vmware-debug categories # verify it runs
15
15
  ```json
16
16
  {
17
17
  "command": "uvx",
18
- "args": ["--from", "vmware-debug==1.13.0", "vmware-debug-mcp"]
18
+ "args": ["--from", "vmware-debug==1.13.2", "vmware-debug-mcp"]
19
19
  }
20
20
  ```
21
21
 
@@ -62,7 +62,7 @@
62
62
  "names_artifact",
63
63
  "states_remedy"
64
64
  ],
65
- "where": "conclusion.py:81"
65
+ "where": "conclusion.py:91"
66
66
  },
67
67
  {
68
68
  "message": "Evidence field {} is required and cannot be blank. {}",
@@ -70,7 +70,7 @@
70
70
  "names_artifact",
71
71
  "states_remedy"
72
72
  ],
73
- "where": "evidence.py:41"
73
+ "where": "evidence.py:48"
74
74
  },
75
75
  {
76
76
  "message": "Cannot read gaps.json for case {}: {}.",
@@ -78,7 +78,7 @@
78
78
  "names_artifact",
79
79
  "states_remedy"
80
80
  ],
81
- "where": "evidence.py:289"
81
+ "where": "evidence.py:308"
82
82
  },
83
83
  {
84
84
  "message": "gaps.json in case {} is not valid JSON: {}. It was hand-edited. Restore it rather than deleting it \u2014",
@@ -86,7 +86,7 @@
86
86
  "names_artifact",
87
87
  "states_remedy"
88
88
  ],
89
- "where": "evidence.py:291"
89
+ "where": "evidence.py:310"
90
90
  },
91
91
  {
92
92
  "message": "Cannot read grading_rules.yaml at {}: {}",
@@ -94,7 +94,7 @@
94
94
  "names_artifact",
95
95
  "states_remedy"
96
96
  ],
97
- "where": "grading.py:57"
97
+ "where": "grading.py:133"
98
98
  },
99
99
  {
100
100
  "message": "grading_rules.yaml at {} is not valid YAML: {}. Fix it rather than deleting it \u2014 falling back to the",
@@ -102,7 +102,7 @@
102
102
  "names_artifact",
103
103
  "states_remedy"
104
104
  ],
105
- "where": "grading.py:59"
105
+ "where": "grading.py:135"
106
106
  },
107
107
  {
108
108
  "message": "A hypothesis needs a statement \u2014 what you think happened, in one line. An unnamed hypothesis cannot ",
@@ -111,7 +111,7 @@
111
111
  "names_input",
112
112
  "states_remedy"
113
113
  ],
114
- "where": "hypotheses.py:88"
114
+ "where": "hypotheses.py:101"
115
115
  },
116
116
  {
117
117
  "message": "Cannot read hypotheses.md for case {}: {}",
@@ -119,7 +119,7 @@
119
119
  "names_artifact",
120
120
  "states_remedy"
121
121
  ],
122
- "where": "hypotheses.py:60"
122
+ "where": "hypotheses.py:66"
123
123
  },
124
124
  {
125
125
  "message": "Scope field {} is required and cannot be blank. It is what step 01 of the evidence loop produces; a ",
@@ -159,7 +159,7 @@
159
159
  "names_artifact",
160
160
  "states_remedy"
161
161
  ],
162
- "where": "store.py:81"
162
+ "where": "store.py:293"
163
163
  },
164
164
  {
165
165
  "message": "Case {} is already closed. Its record is not rewritten \u2014 reopen the question by opening a new case t",
@@ -167,7 +167,7 @@
167
167
  "names_artifact",
168
168
  "states_remedy"
169
169
  ],
170
- "where": "timeline.py:137"
170
+ "where": "timeline.py:154"
171
171
  },
172
172
  {
173
173
  "message": "Cannot read case.json for {}: {}",
@@ -175,39 +175,39 @@
175
175
  "names_artifact",
176
176
  "states_remedy"
177
177
  ],
178
- "where": "timeline.py:151"
178
+ "where": "timeline.py:168"
179
179
  }
180
180
  ],
181
181
  "per_dimension_pct": {
182
- "names_artifact": 37.2,
183
- "names_input": 95.3,
184
- "states_remedy": 62.8
182
+ "names_artifact": 40.0,
183
+ "names_input": 95.6,
184
+ "states_remedy": 64.4
185
185
  },
186
- "raise_sites": 43
186
+ "raise_sites": 45
187
187
  },
188
- "maximum": 129,
189
- "pct": 65.1,
188
+ "maximum": 135,
189
+ "pct": 66.7,
190
190
  "unit": "points",
191
- "value": 84
191
+ "value": 90
192
192
  },
193
193
  "manifest_context_headroom": {
194
194
  "detail": {
195
195
  "heaviest_tools": {
196
196
  "case_open": 521,
197
- "case_plan": 499,
197
+ "case_plan": 502,
198
198
  "case_record_gap": 410,
199
199
  "case_submit_evidence": 971,
200
200
  "incident_timeline": 521
201
201
  },
202
- "manifest_tokens": 5160,
203
- "mean_tokens_per_tool": 368.6,
202
+ "manifest_tokens": 5215,
203
+ "mean_tokens_per_tool": 372.5,
204
204
  "reference_context": 16384,
205
205
  "tool_count": 14
206
206
  },
207
207
  "maximum": 16384,
208
- "pct": 68.5,
208
+ "pct": 68.2,
209
209
  "unit": "tokens",
210
- "value": 11224
210
+ "value": 11169
211
211
  },
212
212
  "parameter_documentation_coverage": {
213
213
  "detail": {
@@ -248,7 +248,7 @@
248
248
  "ceiling": 350,
249
249
  "over_ceiling": {
250
250
  "case_open": 521,
251
- "case_plan": 499,
251
+ "case_plan": 502,
252
252
  "case_record_gap": 410,
253
253
  "case_submit_evidence": 971,
254
254
  "case_timeline": 393,
@@ -290,27 +290,27 @@
290
290
  "remedy_after_interpolation": [
291
291
  "envelope.py:126",
292
292
  "envelope.py:138",
293
- "conclusion.py:135",
294
- "conclusion.py:144",
295
- "evidence.py:179",
296
- "evidence.py:211",
297
- "evidence.py:248",
298
- "grading.py:67",
299
- "hypotheses.py:47",
300
- "hypotheses.py:70"
293
+ "conclusion.py:145",
294
+ "conclusion.py:154",
295
+ "evidence.py:186",
296
+ "evidence.py:229",
297
+ "evidence.py:264",
298
+ "grading.py:143",
299
+ "hypotheses.py:53",
300
+ "hypotheses.py:76"
301
301
  ]
302
302
  },
303
- "maximum": 28,
303
+ "maximum": 30,
304
304
  "pct": 100.0,
305
305
  "unit": "messages",
306
- "value": 28
306
+ "value": 30
307
307
  },
308
308
  "teaching_error_rate": {
309
309
  "detail": {},
310
- "maximum": 43,
311
- "pct": 34.9,
310
+ "maximum": 45,
311
+ "pct": 37.8,
312
312
  "unit": "messages",
313
- "value": 15
313
+ "value": 17
314
314
  },
315
315
  "tool_description_quality": {
316
316
  "detail": {
@@ -31,7 +31,7 @@ from __future__ import annotations
31
31
 
32
32
  import json
33
33
  import re
34
- from dataclasses import dataclass, field, replace
34
+ from dataclasses import dataclass, field
35
35
  from pathlib import Path
36
36
  from typing import Any
37
37
 
@@ -306,7 +306,7 @@ def test_credits_a_named_env_var():
306
306
 
307
307
  import ast # noqa: E402 — grouped with the tests that use it
308
308
 
309
- from ..capability.test_error_actionability import _messages_in_tree
309
+ from ..capability.test_error_actionability import _messages_in_tree # noqa: E402
310
310
 
311
311
 
312
312
  def _messages(src: str):
@@ -344,7 +344,7 @@ def test_folds_in_the_strings_a_hint_helper_can_return():
344
344
  # on fabricated messages because a repo with nothing over budget would pass this
345
345
  # check without exercising a line of it.
346
346
 
347
- from ..capability.test_error_actionability import _truncation_findings
347
+ from ..capability.test_error_actionability import _truncation_findings # noqa: E402
348
348
 
349
349
  _TAUGHT = {"names_input": True, "states_remedy": True, "names_artifact": True}
350
350
  _BARE = {"names_input": True, "states_remedy": False, "names_artifact": False}
@@ -194,13 +194,20 @@ class TestExclusionNeedsAFalsifyingObservation:
194
194
  record_gap(case, blocking_gap())
195
195
  assert grade_case(case).grade != "excluded"
196
196
 
197
- def test_a_falsifying_observation_excludes(self, case):
197
+ def test_falsifying_observations_from_two_skills_exclude(self, case):
198
198
  record_evidence(case, evidence(skill="vmware-monitor", falsifies=("H1",)))
199
- record_evidence(case, evidence(skill="vmware-log-insight"))
199
+ record_evidence(case, evidence(skill="vmware-log-insight", falsifies=("H1",)))
200
200
  r = grade_case(case)
201
201
  assert r.grade == "excluded"
202
202
  assert any("E001" in reason for reason in r.reasons)
203
203
 
204
+ def test_one_falsifier_and_an_unrelated_source_do_not_exclude(self, case):
205
+ """The two sources have to be against the hypothesis, not anywhere in the
206
+ case (independent review, 2026-09-15)."""
207
+ record_evidence(case, evidence(skill="vmware-monitor", falsifies=("H1",)))
208
+ record_evidence(case, evidence(skill="vmware-log-insight"))
209
+ assert grade_case(case).grade != "excluded"
210
+
204
211
 
205
212
  class TestDemotion:
206
213
  def test_a_new_gap_takes_confirmed_back_down_to_probable(self, case, mounted_kb):