vmware-debug 2.3.0__tar.gz → 2.3.1__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.
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/.claude-plugin/plugin.json +1 -1
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/.mcp.json +1 -1
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/PKG-INFO +8 -3
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/README-CN.md +4 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/README.md +4 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/RELEASE_NOTES.md +10 -1
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/openclaw.plugin.json +1 -1
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/package.json +1 -1
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/pyproject.toml +4 -3
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/server.json +2 -2
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/skills/vmware-debug/SKILL.md +3 -1
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/skills/vmware-debug/references/setup-guide.md +2 -2
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/test_audit_isolation.py +7 -2
- vmware_debug-2.3.1/tests/eval/regression/test_cli_policy_denial.py +23 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/uv.lock +16 -14
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/__init__.py +1 -1
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/cli.py +17 -1
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/.clawhubignore +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/.gitignore +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/SECURITY.md +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/docs/plans/2026-08-28-investigation-layer-design.md +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/skills/vmware-debug/references/agent-guardrails.md +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/skills/vmware-debug/references/capabilities.md +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/skills/vmware-debug/references/cli-reference.md +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/skills/vmware-debug/references/event-envelope.md +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/skills/vmware-debug/references/routing.md +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/__init__.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/conftest.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/__init__.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/capability/__init__.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/capability/_family.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/capability/_scores.json +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/capability/_scoring.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/capability/_skill.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/capability/conftest.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/capability/test_entity_reachability.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/capability/test_error_actionability.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/capability/test_tool_description_quality.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/capability/test_tool_manifest_budget.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/__init__.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/_vsphere_event_vocabulary.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/test_capability_grader.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/test_case_id_non_ascii.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/test_case_plan_max_steps.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/test_classification_against_vsphere_vocabulary.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/test_debug_regressions.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/test_environment_resolver_isolation.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/test_every_tool_parameter_is_documented.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/test_evidence_payload_contract.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/test_host_lifecycle_classification.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/test_investigation_metrics.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/test_real_alert_titles_classify.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/test_result_envelope.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/test_skill_name_aliases.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/test_spike_resolution.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/test_tool_annotations.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/test_case_conclusion.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/test_case_evidence.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/test_case_grading.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/test_case_grading_per_hypothesis.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/test_case_hypotheses.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/test_case_ids.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/test_case_ledger_concurrency.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/test_case_plan.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/test_case_readiness.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/test_case_store.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/test_case_timeline_close.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/test_case_tools.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/test_knowledge.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/test_mcp_audit.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/test_policy_roles.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/test_safe_error_passthrough.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/test_timeline.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/envelope.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/mcp/__init__.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/mcp/tools.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/mcp_server/__init__.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/mcp_server/server.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/ops/__init__.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/ops/cases/__init__.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/ops/cases/api.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/ops/cases/conclusion.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/ops/cases/evidence.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/ops/cases/grading.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/ops/cases/hypotheses.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/ops/cases/ids.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/ops/cases/knowledge.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/ops/cases/model.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/ops/cases/payloads.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/ops/cases/plan.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/ops/cases/readiness.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/ops/cases/sources.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/ops/cases/store.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/ops/cases/timeline.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/ops/skill_names.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/ops/timeline.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/policy_roles.py +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/rules/evidence_sources.yaml +0 -0
- {vmware_debug-2.3.0 → vmware_debug-2.3.1}/vmware_debug/rules/grading_rules.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": "2.3.
|
|
5
|
+
"version": "2.3.1",
|
|
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",
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: vmware-debug
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.1
|
|
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
|
|
7
7
|
Project-URL: Issues, https://github.com/vmware-skills/VMware-Debug/issues
|
|
8
8
|
Project-URL: Changelog, https://github.com/vmware-skills/VMware-Debug/blob/main/RELEASE_NOTES.md
|
|
9
|
-
Author-email: Wei Zhou <
|
|
9
|
+
Author-email: Wei Zhou <zhouwei008@gmail.com>
|
|
10
10
|
License-Expression: MIT
|
|
11
11
|
Keywords: ai-ops,debug,diagnostics,mcp,rca,troubleshooting,vmware,vsphere
|
|
12
12
|
Classifier: Development Status :: 4 - Beta
|
|
@@ -14,7 +14,8 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
14
14
|
Classifier: Programming Language :: Python :: 3
|
|
15
15
|
Classifier: Topic :: System :: Monitoring
|
|
16
16
|
Requires-Python: >=3.10
|
|
17
|
-
Requires-Dist:
|
|
17
|
+
Requires-Dist: certifi>=2026.10.19
|
|
18
|
+
Requires-Dist: mcp[cli]<2.0,>=1.30
|
|
18
19
|
Requires-Dist: pyyaml<7.0,>=6.0
|
|
19
20
|
Requires-Dist: rich<15.0,>=13.0
|
|
20
21
|
Requires-Dist: typer<1.0,>=0.12
|
|
@@ -25,6 +26,8 @@ Description-Content-Type: text/markdown
|
|
|
25
26
|
|
|
26
27
|
# VMware Debug
|
|
27
28
|
|
|
29
|
+
For a read-only check of this skill with your model and agent host, use the shared [model-fit self-test](https://github.com/vmware-skills/marketplace/blob/main/MODEL_FIT_SELF_TEST.md) in the marketplace root.
|
|
30
|
+
|
|
28
31
|
> **Disclaimer**: Community-maintained open-source project, **not affiliated with,
|
|
29
32
|
> endorsed by, or sponsored by VMware, Inc. or Broadcom Inc.** "VMware" and
|
|
30
33
|
> "vSphere" are trademarks of Broadcom. Source is publicly auditable under the MIT
|
|
@@ -105,6 +108,8 @@ event actually is.
|
|
|
105
108
|
|
|
106
109
|
## Security
|
|
107
110
|
|
|
111
|
+
CLI policy refusals print the reason and rule, exit with code 1, and retain one `denied` audit row.
|
|
112
|
+
|
|
108
113
|
Offline and credential-free by construction: it connects to no vCenter/NSX/Aria, has no destructive surface on
|
|
109
114
|
VMware, and holds no secret to leak. The only writes are the local case ledger: evidence, gaps, hypotheses and
|
|
110
115
|
grade history are append-only; `timeline.md` is regenerated from the evidence, and `case.json` holds the current
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
# VMware Debug(中文)
|
|
4
4
|
|
|
5
|
+
要用自己的模型和 Agent 平台进行只读自测,请看 marketplace 根目录的[共享模型适配自测任务](https://github.com/vmware-skills/marketplace/blob/main/MODEL_FIT_SELF_TEST.md)。
|
|
6
|
+
|
|
5
7
|
> **声明**:本项目为社区维护的开源项目,**与 VMware, Inc. 或 Broadcom Inc. 无任何隶属、
|
|
6
8
|
> 背书或赞助关系。** "VMware"、"vSphere" 为 Broadcom 商标。源码以 MIT 许可证公开可审计。
|
|
7
9
|
|
|
@@ -68,6 +70,8 @@ debug;debug 因此与其它包零运行时依赖。**请把每条事件的 `ev
|
|
|
68
70
|
|
|
69
71
|
## 安全
|
|
70
72
|
|
|
73
|
+
CLI 被策略拒绝时会显示原因和规则,以退出码 1 结束,并保留一条 `denied` 审计记录。
|
|
74
|
+
|
|
71
75
|
结构上离线、无凭据:不连任何 vCenter/NSX/Aria,对 VMware 没有可破坏面,也没有秘密可泄露。
|
|
72
76
|
唯一的写入是本地案卷:证据、缺口、假设和等级历史只增不改;`timeline.md` 由证据重新生成,
|
|
73
77
|
`case.json` 保存当前等级和状态。多个写入者同样成立:每次写案卷都要先拿该案卷的锁文件(`.ledger.lock`,
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
# VMware Debug
|
|
4
4
|
|
|
5
|
+
For a read-only check of this skill with your model and agent host, use the shared [model-fit self-test](https://github.com/vmware-skills/marketplace/blob/main/MODEL_FIT_SELF_TEST.md) in the marketplace root.
|
|
6
|
+
|
|
5
7
|
> **Disclaimer**: Community-maintained open-source project, **not affiliated with,
|
|
6
8
|
> endorsed by, or sponsored by VMware, Inc. or Broadcom Inc.** "VMware" and
|
|
7
9
|
> "vSphere" are trademarks of Broadcom. Source is publicly auditable under the MIT
|
|
@@ -82,6 +84,8 @@ event actually is.
|
|
|
82
84
|
|
|
83
85
|
## Security
|
|
84
86
|
|
|
87
|
+
CLI policy refusals print the reason and rule, exit with code 1, and retain one `denied` audit row.
|
|
88
|
+
|
|
85
89
|
Offline and credential-free by construction: it connects to no vCenter/NSX/Aria, has no destructive surface on
|
|
86
90
|
VMware, and holds no secret to leak. The only writes are the local case ledger: evidence, gaps, hypotheses and
|
|
87
91
|
grade history are append-only; `timeline.md` is regenerated from the evidence, and `case.json` holds the current
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## v2.3.1 — readable Policy refusals and dependency security (2026-11-08)
|
|
2
|
+
|
|
3
|
+
* Update public author/project contact metadata to `zhouwei008@gmail.com`.
|
|
4
|
+
|
|
5
|
+
### dependency security and sandbox test stability
|
|
6
|
+
* Require certifi 2026.10.19 or later for MCP's HTTP/TLS dependencies (GHSA-6q48-6c7w-9gw2); the lock resolves 2026.10.23.
|
|
7
|
+
* The audit-isolation regression still proves its write reached only the sandbox DB; it skips the production-DB comparison when the host sandbox denies even read-only access to that DB.
|
|
8
|
+
* CLI policy refusals now print their reason and rule without a traceback. The audited wrapper still records exactly one `denied` row before the CLI exits with code 1.
|
|
9
|
+
|
|
1
10
|
## v2.3.0 — roles for network callers (HLD §18)
|
|
2
11
|
|
|
3
12
|
* Declares the role metadata vmware-policy ≥ 1.24.0 needs to apply **roles** to this server over HTTPS
|
|
@@ -898,4 +907,4 @@ executes fixes (advisor/executor split, mirroring vmware-harden → vmware-pilot
|
|
|
898
907
|
### Notes
|
|
899
908
|
- Read-only by construction; remediation is routed, never executed.
|
|
900
909
|
- `parse_timestamp` rejects implausible/garbage timestamps loudly rather than
|
|
901
|
-
silently landing at the epoch.
|
|
910
|
+
silently landing at the epoch.
|
|
@@ -4,12 +4,12 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "vmware-debug"
|
|
7
|
-
version = "2.3.
|
|
7
|
+
version = "2.3.1"
|
|
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"
|
|
11
11
|
requires-python = ">=3.10"
|
|
12
|
-
authors = [{ name = "Wei Zhou", email = "
|
|
12
|
+
authors = [{ name = "Wei Zhou", email = "zhouwei008@gmail.com" }]
|
|
13
13
|
keywords = ["vmware", "vsphere", "debug", "troubleshooting", "diagnostics", "rca", "mcp", "ai-ops"]
|
|
14
14
|
classifiers = [
|
|
15
15
|
"Development Status :: 4 - Beta",
|
|
@@ -20,7 +20,8 @@ classifiers = [
|
|
|
20
20
|
dependencies = [
|
|
21
21
|
"typer>=0.12,<1.0",
|
|
22
22
|
"rich>=13.0,<15.0",
|
|
23
|
-
"mcp[cli]>=1.
|
|
23
|
+
"mcp[cli]>=1.30,<2.0",
|
|
24
|
+
"certifi>=2026.10.19", # GHSA-6q48-6c7w-9gw2 via MCP/httpx
|
|
24
25
|
"vmware-policy>=1.21.0,<2.0",
|
|
25
26
|
# Imported directly by ops/cases/grading.py for the rules file. It has
|
|
26
27
|
# always arrived transitively via vmware-policy; a package should
|
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
"url": "https://github.com/vmware-skills/VMware-Debug",
|
|
8
8
|
"source": "github"
|
|
9
9
|
},
|
|
10
|
-
"version": "2.3.
|
|
10
|
+
"version": "2.3.1",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "pypi",
|
|
14
14
|
"identifier": "vmware-debug",
|
|
15
|
-
"version": "2.3.
|
|
15
|
+
"version": "2.3.1",
|
|
16
16
|
"runtimeHint": "uvx",
|
|
17
17
|
"packageArguments": [
|
|
18
18
|
{
|
|
@@ -25,6 +25,8 @@ metadata: {"openclaw":{"requires":{"anyBins":["vmware-debug","uvx"]},"optional":
|
|
|
25
25
|
|
|
26
26
|
# VMware Debug
|
|
27
27
|
|
|
28
|
+
> Self-test: [guide](https://github.com/vmware-skills/marketplace/blob/main/MODEL_FIT_SELF_TEST.md).
|
|
29
|
+
|
|
28
30
|
> **Disclaimer**: Community-maintained open-source project, **not affiliated with,
|
|
29
31
|
> endorsed by, or sponsored by VMware, Inc. or Broadcom Inc.** "VMware" and "vSphere"
|
|
30
32
|
> are trademarks of Broadcom. Source is publicly auditable under the MIT license.
|
|
@@ -51,7 +53,7 @@ write tools touch only the local case ledger.
|
|
|
51
53
|
## Quick Install
|
|
52
54
|
|
|
53
55
|
```bash
|
|
54
|
-
uv tool install vmware-debug==2.3.
|
|
56
|
+
uv tool install vmware-debug==2.3.1
|
|
55
57
|
vmware-debug categories # see what it can diagnose
|
|
56
58
|
```
|
|
57
59
|
|
|
@@ -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==2.3.
|
|
9
|
+
uv tool install vmware-debug==2.3.1
|
|
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==2.3.
|
|
18
|
+
"args": ["--from", "vmware-debug==2.3.1", "vmware-debug-mcp"]
|
|
19
19
|
}
|
|
20
20
|
```
|
|
21
21
|
|
|
@@ -62,6 +62,11 @@ def test_an_audited_write_lands_in_the_sandbox_and_not_in_the_real_db() -> None:
|
|
|
62
62
|
real_db = REAL_HOME / ".vmware" / "audit.db"
|
|
63
63
|
if not real_db.exists():
|
|
64
64
|
pytest.skip("no production audit database on this machine to check against")
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
try:
|
|
66
|
+
with sqlite3.connect(f"file:{real_db}?mode=ro", uri=True) as con:
|
|
67
|
+
leaked = con.execute("SELECT count(*) FROM audit_log WHERE tool = ?", (marker,)).fetchone()[0]
|
|
68
|
+
except sqlite3.OperationalError as exc:
|
|
69
|
+
if "unable to open database file" not in str(exc):
|
|
70
|
+
raise
|
|
71
|
+
pytest.skip("production audit DB is inaccessible from this sandbox")
|
|
67
72
|
assert leaked == 0, f"{leaked} row(s) from this test reached {real_db}"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""CLI policy denial must remain a denial in audit and be readable by an operator."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from typer.testing import CliRunner
|
|
5
|
+
|
|
6
|
+
from vmware_debug.cli import app
|
|
7
|
+
from vmware_policy import cli_guard
|
|
8
|
+
from vmware_policy.policy import PolicyDenied, PolicyResult
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@pytest.mark.parametrize("args", [["categories"], ["triage"]])
|
|
12
|
+
def test_denied_cli_command_prints_reason_and_records_one_denial(monkeypatch, args):
|
|
13
|
+
rows = []
|
|
14
|
+
def deny(*args, **kwargs):
|
|
15
|
+
raise PolicyDenied(PolicyResult(allowed=False, rule="ops-review", reason="offline checks denied"))
|
|
16
|
+
monkeypatch.setattr(cli_guard, "guard", deny)
|
|
17
|
+
monkeypatch.setattr(cli_guard, "audit_call", lambda *a, **kw: rows.append(kw))
|
|
18
|
+
result = CliRunner().invoke(app, args, input="[]")
|
|
19
|
+
assert result.exit_code == 1
|
|
20
|
+
assert "Denied by policy" in result.output
|
|
21
|
+
assert "offline checks denied" in result.output and "ops-review" in result.output
|
|
22
|
+
assert "Traceback" not in result.output
|
|
23
|
+
assert len(rows) == 1 and rows[0]["status"] == "denied"
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
version = 1
|
|
2
|
-
revision =
|
|
2
|
+
revision = 5
|
|
3
3
|
requires-python = ">=3.10"
|
|
4
4
|
resolution-markers = [
|
|
5
5
|
"python_full_version >= '3.14' and sys_platform == 'win32'",
|
|
6
6
|
"python_full_version >= '3.14' and sys_platform != 'win32'",
|
|
7
7
|
"python_full_version >= '3.11' and python_full_version < '3.14' and sys_platform == 'win32'",
|
|
8
|
-
"python_full_version < '3.11' and sys_platform == 'win32'",
|
|
9
8
|
"python_full_version >= '3.11' and python_full_version < '3.14' and sys_platform != 'win32'",
|
|
9
|
+
"python_full_version < '3.11' and sys_platform == 'win32'",
|
|
10
10
|
"python_full_version < '3.11' and sys_platform != 'win32'",
|
|
11
11
|
]
|
|
12
12
|
|
|
@@ -53,11 +53,11 @@ wheels = [
|
|
|
53
53
|
|
|
54
54
|
[[package]]
|
|
55
55
|
name = "certifi"
|
|
56
|
-
version = "2026.
|
|
56
|
+
version = "2026.10.23"
|
|
57
57
|
source = { registry = "https://pypi.org/simple" }
|
|
58
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
58
|
+
sdist = { url = "https://files.pythonhosted.org/packages/fd/11/b524cbd9bbdaca58608e4cf4053fd463417549e1959fa8d3aa18319f9555/certifi-2026.10.23.tar.gz", hash = "sha256:a9895e6e2758b371e0545e321a3a8fd1fcfd9829ada8824a936dfb16aaaf36cd", size = 136225, upload-time = "2026-10-23T11:36:16.478Z" }
|
|
59
59
|
wheels = [
|
|
60
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
60
|
+
{ url = "https://files.pythonhosted.org/packages/32/d1/a3652fe2c19134d0d15922177821d863cbd7e842d53a21bbe7e8e3a1b5ac/certifi-2026.10.23-py3-none-any.whl", hash = "sha256:e9b54de76e530bb6cf0ccd036787103acb58fd42ba930ea8bf948ddbaa2f61d1", size = 135082, upload-time = "2026-10-23T11:36:14.763Z" },
|
|
61
61
|
]
|
|
62
62
|
|
|
63
63
|
[[package]]
|
|
@@ -356,7 +356,7 @@ name = "exceptiongroup"
|
|
|
356
356
|
version = "1.3.1"
|
|
357
357
|
source = { registry = "https://pypi.org/simple" }
|
|
358
358
|
dependencies = [
|
|
359
|
-
{ name = "typing-extensions"
|
|
359
|
+
{ name = "typing-extensions" },
|
|
360
360
|
]
|
|
361
361
|
sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
|
|
362
362
|
wheels = [
|
|
@@ -469,7 +469,7 @@ wheels = [
|
|
|
469
469
|
|
|
470
470
|
[[package]]
|
|
471
471
|
name = "mcp"
|
|
472
|
-
version = "1.
|
|
472
|
+
version = "1.30.0"
|
|
473
473
|
source = { registry = "https://pypi.org/simple" }
|
|
474
474
|
dependencies = [
|
|
475
475
|
{ name = "anyio" },
|
|
@@ -487,9 +487,9 @@ dependencies = [
|
|
|
487
487
|
{ name = "typing-inspection" },
|
|
488
488
|
{ name = "uvicorn", marker = "sys_platform != 'emscripten'" },
|
|
489
489
|
]
|
|
490
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
490
|
+
sdist = { url = "https://files.pythonhosted.org/packages/ba/93/0142dc84a666daf8ad51a34268f34c12fd6fda4f3810c4be2504eecc8212/mcp-1.30.0.tar.gz", hash = "sha256:445414625fce5c295faa505bb11bacece661ab6f4028d57c935db57820b7a3e4", size = 680511, upload-time = "2026-09-07T14:34:15.845Z" }
|
|
491
491
|
wheels = [
|
|
492
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
492
|
+
{ url = "https://files.pythonhosted.org/packages/f5/f4/e58bc33317c92a0203664daaf00bf6f41166cc0149e5d6870a03f7cd004a/mcp-1.30.0-py3-none-any.whl", hash = "sha256:666edb5009503e1047c9d60346a756f94b261f05cc2625f23d41c728ffc484d0", size = 234581, upload-time = "2026-09-07T14:34:14.266Z" },
|
|
493
493
|
]
|
|
494
494
|
|
|
495
495
|
[package.optional-dependencies]
|
|
@@ -1293,9 +1293,10 @@ wheels = [
|
|
|
1293
1293
|
|
|
1294
1294
|
[[package]]
|
|
1295
1295
|
name = "vmware-debug"
|
|
1296
|
-
version = "2.3.
|
|
1296
|
+
version = "2.3.1"
|
|
1297
1297
|
source = { editable = "." }
|
|
1298
1298
|
dependencies = [
|
|
1299
|
+
{ name = "certifi" },
|
|
1299
1300
|
{ name = "mcp", extra = ["cli"] },
|
|
1300
1301
|
{ name = "pyyaml" },
|
|
1301
1302
|
{ name = "rich" },
|
|
@@ -1312,7 +1313,8 @@ dev = [
|
|
|
1312
1313
|
|
|
1313
1314
|
[package.metadata]
|
|
1314
1315
|
requires-dist = [
|
|
1315
|
-
{ name = "
|
|
1316
|
+
{ name = "certifi", specifier = ">=2026.10.19" },
|
|
1317
|
+
{ name = "mcp", extras = ["cli"], specifier = ">=1.30,<2.0" },
|
|
1316
1318
|
{ name = "pyyaml", specifier = ">=6.0,<7.0" },
|
|
1317
1319
|
{ name = "rich", specifier = ">=13.0,<15.0" },
|
|
1318
1320
|
{ name = "typer", specifier = ">=0.12,<1.0" },
|
|
@@ -1328,14 +1330,14 @@ dev = [
|
|
|
1328
1330
|
|
|
1329
1331
|
[[package]]
|
|
1330
1332
|
name = "vmware-policy"
|
|
1331
|
-
version = "1.24.
|
|
1333
|
+
version = "1.24.2"
|
|
1332
1334
|
source = { registry = "https://pypi.org/simple" }
|
|
1333
1335
|
dependencies = [
|
|
1334
1336
|
{ name = "pyyaml" },
|
|
1335
1337
|
{ name = "rich" },
|
|
1336
1338
|
{ name = "typer" },
|
|
1337
1339
|
]
|
|
1338
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
1340
|
+
sdist = { url = "https://files.pythonhosted.org/packages/15/8d/b9867ea1c0112caa481841c290c3fe718c0dbd738757db7877836f46267a/vmware_policy-1.24.2.tar.gz", hash = "sha256:6c816174fcd0b490bcd1f9ebaaa18b80fcb26b0eccb614e938938bb2e8452a40", size = 369315, upload-time = "2026-10-18T03:43:52.753Z" }
|
|
1339
1341
|
wheels = [
|
|
1340
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1342
|
+
{ url = "https://files.pythonhosted.org/packages/20/01/bc5f984a420d22514d8c3a627f332891f2008213d455c2f682f311e355f1/vmware_policy-1.24.2-py3-none-any.whl", hash = "sha256:2734ab49a76474fd74beb221a2d6535caab1f91a477668484c145dc2802ae072", size = 134565, upload-time = "2026-10-18T03:43:50.856Z" },
|
|
1341
1343
|
]
|
|
@@ -11,6 +11,7 @@ from __future__ import annotations
|
|
|
11
11
|
|
|
12
12
|
import json
|
|
13
13
|
import sys
|
|
14
|
+
from functools import wraps
|
|
14
15
|
from pathlib import Path
|
|
15
16
|
from typing import Optional
|
|
16
17
|
|
|
@@ -20,7 +21,7 @@ from rich.table import Table
|
|
|
20
21
|
|
|
21
22
|
from vmware_debug import __version__
|
|
22
23
|
from vmware_debug.mcp.tools import build_incident_timeline, list_symptom_categories
|
|
23
|
-
from vmware_policy import audited, cli_local
|
|
24
|
+
from vmware_policy import PolicyDenied, audited, cli_local, sanitize
|
|
24
25
|
|
|
25
26
|
|
|
26
27
|
def _harden_console_encoding() -> None:
|
|
@@ -53,6 +54,19 @@ app = typer.Typer(
|
|
|
53
54
|
console = Console()
|
|
54
55
|
|
|
55
56
|
|
|
57
|
+
def handle_cli_errors(func):
|
|
58
|
+
"""Render policy refusals after the audited wrapper has recorded the denial."""
|
|
59
|
+
@wraps(func)
|
|
60
|
+
def wrapper(*args, **kwargs):
|
|
61
|
+
try:
|
|
62
|
+
return func(*args, **kwargs)
|
|
63
|
+
except PolicyDenied as exc:
|
|
64
|
+
rule = f" (rule: {sanitize(exc.result.rule, 100)})" if exc.result.rule else ""
|
|
65
|
+
typer.echo(f"Denied by policy: {sanitize(exc.result.reason, 500)}{rule}", err=True)
|
|
66
|
+
raise typer.Exit(1) from None
|
|
67
|
+
return wrapper
|
|
68
|
+
|
|
69
|
+
|
|
56
70
|
@app.command()
|
|
57
71
|
@cli_local("prints the installed version")
|
|
58
72
|
def version() -> None:
|
|
@@ -61,6 +75,7 @@ def version() -> None:
|
|
|
61
75
|
|
|
62
76
|
|
|
63
77
|
@app.command()
|
|
78
|
+
@handle_cli_errors
|
|
64
79
|
@audited(tool="list_symptom_categories")
|
|
65
80
|
def categories() -> None:
|
|
66
81
|
"""List the symptom categories debug recognises and what to check for each."""
|
|
@@ -74,6 +89,7 @@ def categories() -> None:
|
|
|
74
89
|
|
|
75
90
|
|
|
76
91
|
@app.command()
|
|
92
|
+
@handle_cli_errors
|
|
77
93
|
@audited(tool="build_incident_timeline")
|
|
78
94
|
def triage(
|
|
79
95
|
events_file: Optional[Path] = typer.Option(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vmware_debug-2.3.0 → vmware_debug-2.3.1}/docs/plans/2026-08-28-investigation-layer-design.md
RENAMED
|
File without changes
|
{vmware_debug-2.3.0 → vmware_debug-2.3.1}/skills/vmware-debug/references/agent-guardrails.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/capability/test_tool_description_quality.py
RENAMED
|
File without changes
|
{vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/capability/test_tool_manifest_budget.py
RENAMED
|
File without changes
|
|
File without changes
|
{vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/_vsphere_event_vocabulary.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/test_evidence_payload_contract.py
RENAMED
|
File without changes
|
|
File without changes
|
{vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/test_investigation_metrics.py
RENAMED
|
File without changes
|
{vmware_debug-2.3.0 → vmware_debug-2.3.1}/tests/eval/regression/test_real_alert_titles_classify.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|