queue-aiops 0.2.1__tar.gz → 0.2.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 (88) hide show
  1. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/PKG-INFO +5 -4
  2. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/README.md +4 -3
  3. queue_aiops-0.2.2/RELEASE_NOTES.md +29 -0
  4. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/pyproject.toml +1 -1
  5. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/ops/rabbit_reads.py +15 -15
  6. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/ops/redis_reads.py +4 -4
  7. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/server.json +2 -2
  8. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/uv.lock +1 -1
  9. queue_aiops-0.2.1/RELEASE_NOTES.md +0 -26
  10. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/.github/workflows/mcp-publish.yml +0 -0
  11. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/.github/workflows/publish.yml +0 -0
  12. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/.gitignore +0 -0
  13. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/CHANGELOG.md +0 -0
  14. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/LICENSE +0 -0
  15. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/SECURITY.md +0 -0
  16. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/docs/VERIFICATION.md +0 -0
  17. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/mcp_server/__init__.py +0 -0
  18. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/mcp_server/_shared.py +0 -0
  19. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/mcp_server/server.py +0 -0
  20. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/mcp_server/tools/__init__.py +0 -0
  21. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/mcp_server/tools/analysis.py +0 -0
  22. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/mcp_server/tools/overview.py +0 -0
  23. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/mcp_server/tools/rabbit_reads.py +0 -0
  24. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/mcp_server/tools/redis_reads.py +0 -0
  25. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/mcp_server/tools/undo.py +0 -0
  26. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/mcp_server/tools/writes.py +0 -0
  27. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/__init__.py +0 -0
  28. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/cli/__init__.py +0 -0
  29. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/cli/_common.py +0 -0
  30. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/cli/_root.py +0 -0
  31. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/cli/analyze.py +0 -0
  32. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/cli/doctor.py +0 -0
  33. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/cli/init.py +0 -0
  34. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/cli/overview.py +0 -0
  35. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/cli/rabbit_cmds.py +0 -0
  36. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/cli/redis_cmds.py +0 -0
  37. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/cli/secret.py +0 -0
  38. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/cli/undo.py +0 -0
  39. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/config.py +0 -0
  40. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/connection.py +0 -0
  41. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/doctor.py +0 -0
  42. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/governance/__init__.py +0 -0
  43. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/governance/audit.py +0 -0
  44. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/governance/budget.py +0 -0
  45. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/governance/decorators.py +0 -0
  46. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/governance/paths.py +0 -0
  47. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/governance/patterns.py +0 -0
  48. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/governance/policy.py +0 -0
  49. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/governance/readonly.py +0 -0
  50. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/governance/sanitize.py +0 -0
  51. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/governance/undo.py +0 -0
  52. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/ops/__init__.py +0 -0
  53. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/ops/_util.py +0 -0
  54. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/ops/analysis.py +0 -0
  55. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/ops/overview.py +0 -0
  56. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/ops/writes.py +0 -0
  57. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/platform.py +0 -0
  58. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/queue_aiops/secretstore.py +0 -0
  59. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/skills/queue-aiops/SKILL.md +0 -0
  60. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/skills/queue-aiops/references/agent-guardrails.md +0 -0
  61. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/skills/queue-aiops/references/capabilities.md +0 -0
  62. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/skills/queue-aiops/references/cli-reference.md +0 -0
  63. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/skills/queue-aiops/references/setup-guide.md +0 -0
  64. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/smithery.yaml +0 -0
  65. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/conftest.py +0 -0
  66. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/fakes.py +0 -0
  67. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_analysis.py +0 -0
  68. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_cli_rabbit_writes.py +0 -0
  69. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_cli_reads.py +0 -0
  70. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_cli_secret.py +0 -0
  71. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_cli_writes.py +0 -0
  72. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_connection.py +0 -0
  73. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_doctor.py +0 -0
  74. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_gov_audit.py +0 -0
  75. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_gov_decorators.py +0 -0
  76. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_gov_patterns.py +0 -0
  77. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_gov_policy.py +0 -0
  78. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_governance_persistence.py +0 -0
  79. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_init.py +0 -0
  80. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_mcp_reads.py +0 -0
  81. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_optional_fields.py +0 -0
  82. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_platform.py +0 -0
  83. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_readonly.py +0 -0
  84. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_reads.py +0 -0
  85. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_secretstore.py +0 -0
  86. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_smoke.py +0 -0
  87. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_undo_executor.py +0 -0
  88. {queue_aiops-0.2.1 → queue_aiops-0.2.2}/tests/test_writes.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: queue-aiops
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary: Governed AI-ops for redis + rabbitmq: memory-pressure/latency/queue-backlog/connection-churn RCAs, slowlog and SCAN-budgeted big-key sampling, queues/policies/nodes, and governed writes (config set, client kill, purge/delete queue, policies) with a built-in governance harness (audit, budget, undo, risk tiers)
5
5
  Author-email: wei <zhouwei008@gmail.com>
6
6
  License-Expression: MIT
@@ -192,15 +192,16 @@ queue-aiops analyze memory|latency|backlog|churn
192
192
 
193
193
  ## Verification status
194
194
 
195
- **Live-verified against Redis 7.4.9 (2026-07-19); RabbitMQ still mock-only.**
195
+ **Live-verified against Redis 7.4.9 and RabbitMQ 3.13.7 (2026-07-19/20).**
196
196
  Connectivity, every Redis read (cross-checked against `redis-cli` ground truth), all
197
197
  four analyses, and the full governance loop (real `redis_config_set` → audit row →
198
198
  undo restoring the prior value) were exercised against a real server. That run found
199
199
  and fixed a real defect: integer quantities — key counts, client counts, byte totals —
200
200
  were rendered as floats (`202.0` keys), which equality assertions cannot catch.
201
201
 
202
- The **entire RabbitMQ command group** remains unverified against a live broker, as do
203
- Redis cluster/sentinel topologies and AUTH/TLS connections.
202
+ The RabbitMQ group is now verified end-to-end too — reads cross-checked against
203
+ `rabbitmqadmin`, and `set_policy` → `undo_apply` closing on the live broker. **Redis
204
+ cluster/sentinel topologies and AUTH/TLS connections** remain unverified.
204
205
 
205
206
  [docs/VERIFICATION.md](docs/VERIFICATION.md) records exactly what was checked and what
206
207
  is still open. `queue-aiops doctor` is the fastest live check.
@@ -175,15 +175,16 @@ queue-aiops analyze memory|latency|backlog|churn
175
175
 
176
176
  ## Verification status
177
177
 
178
- **Live-verified against Redis 7.4.9 (2026-07-19); RabbitMQ still mock-only.**
178
+ **Live-verified against Redis 7.4.9 and RabbitMQ 3.13.7 (2026-07-19/20).**
179
179
  Connectivity, every Redis read (cross-checked against `redis-cli` ground truth), all
180
180
  four analyses, and the full governance loop (real `redis_config_set` → audit row →
181
181
  undo restoring the prior value) were exercised against a real server. That run found
182
182
  and fixed a real defect: integer quantities — key counts, client counts, byte totals —
183
183
  were rendered as floats (`202.0` keys), which equality assertions cannot catch.
184
184
 
185
- The **entire RabbitMQ command group** remains unverified against a live broker, as do
186
- Redis cluster/sentinel topologies and AUTH/TLS connections.
185
+ The RabbitMQ group is now verified end-to-end too — reads cross-checked against
186
+ `rabbitmqadmin`, and `set_policy` → `undo_apply` closing on the live broker. **Redis
187
+ cluster/sentinel topologies and AUTH/TLS connections** remain unverified.
187
188
 
188
189
  [docs/VERIFICATION.md](docs/VERIFICATION.md) records exactly what was checked and what
189
190
  is still open. `queue-aiops doctor` is the fastest live check.
@@ -0,0 +1,29 @@
1
+ # Release notes — queue-aiops 0.2.2
2
+
3
+ Previous release: 0.2.1.
4
+
5
+ ## Fixed: the remaining float-typed integer quantities
6
+
7
+ 0.2.1 converted the obvious counts, but a regex-driven sweep missed 19 more —
8
+ `consumers`, per-node `fdUsed`/`socketsUsed`, `queues`/`connections`/`channels`
9
+ object totals, connection `connectedAt`, slowlog `id`/`startTime`/`durationUs`, and
10
+ Redis `totalCommands`. A live RabbitMQ broker reported `"consumers": 0.0`.
11
+
12
+ These are integers now. Genuinely fractional values — `consumerUtilisation`,
13
+ `opsPerSec`, `fragmentationRatio`, and the `*Rate` fields — are unchanged.
14
+
15
+ ## Live-verified: RabbitMQ
16
+
17
+ The entire RabbitMQ command group had never been run against a live broker. It has
18
+ now been exercised against **RabbitMQ 3.13.7**: `doctor`, every read
19
+ (`overview`, `queues`, `queue`, `connections`, `channels`, `policies`, `nodes`) with
20
+ queue depth cross-checked against `rabbitmqadmin` ground truth, the backlog and
21
+ churn analyses, and the full governance loop — `set_policy` really created a policy
22
+ on the broker, `priorState` recorded that it had not existed, and `undo_apply`
23
+ deleted it, with all three calls audited.
24
+
25
+ The platform guard was confirmed too: a Redis-only analysis against a RabbitMQ
26
+ target fails with a teaching error naming the mismatch.
27
+
28
+ See [docs/VERIFICATION.md](docs/VERIFICATION.md). Redis cluster/sentinel topologies
29
+ and AUTH/TLS connections remain unverified.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "queue-aiops"
7
- version = "0.2.1"
7
+ version = "0.2.2"
8
8
  description = "Governed AI-ops for redis + rabbitmq: memory-pressure/latency/queue-backlog/connection-churn RCAs, slowlog and SCAN-budgeted big-key sampling, queues/policies/nodes, and governed writes (config set, client kill, purge/delete queue, policies) with a built-in governance harness (audit, budget, undo, risk tiers)"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -31,10 +31,10 @@ def broker_overview(conn: Any) -> dict:
31
31
  "messagesReady": as_int(totals.get("messages_ready")),
32
32
  "messagesUnacked": as_int(totals.get("messages_unacknowledged")),
33
33
  "messagesTotal": as_int(totals.get("messages")),
34
- "queues": num(objects.get("queues")),
35
- "connections": num(objects.get("connections")),
36
- "channels": num(objects.get("channels")),
37
- "consumers": num(objects.get("consumers")),
34
+ "queues": as_int(objects.get("queues")),
35
+ "connections": as_int(objects.get("connections")),
36
+ "channels": as_int(objects.get("channels")),
37
+ "consumers": as_int(objects.get("consumers")),
38
38
  "publishRate": rate(stats.get("publish_details")),
39
39
  "deliverRate": rate(stats.get("deliver_get_details")),
40
40
  "ackRate": rate(stats.get("ack_details")),
@@ -59,7 +59,7 @@ def _queue_row(q: dict) -> dict:
59
59
  "messages": as_int(q.get("messages")),
60
60
  "messagesReady": as_int(q.get("messages_ready")),
61
61
  "messagesUnacked": as_int(q.get("messages_unacknowledged")),
62
- "consumers": num(q.get("consumers")),
62
+ "consumers": as_int(q.get("consumers")),
63
63
  "memoryBytes": as_int(q.get("memory")),
64
64
  "publishRate": rate(stats.get("publish_details")),
65
65
  "deliverRate": rate(stats.get("deliver_get_details")),
@@ -123,8 +123,8 @@ def list_connections(conn: Any) -> dict:
123
123
  "peerHost": opt(pick(c, "peer_host", default="(unknown)"), 64),
124
124
  "user": opt(c.get("user"), 64),
125
125
  "state": opt(c.get("state"), 32),
126
- "channels": num(c.get("channels")),
127
- "connectedAt": num(c.get("connected_at")),
126
+ "channels": as_int(c.get("channels")),
127
+ "connectedAt": as_int(c.get("connected_at")),
128
128
  "clientProduct": s(as_obj(c.get("client_properties")).get("product"), 64),
129
129
  }
130
130
  for c in conn.platform.rows(conn.get(conn.platform.path("connections")))
@@ -158,9 +158,9 @@ def list_channels(conn: Any) -> dict:
158
158
  "connection": s(as_obj(c.get("connection_details")).get("name"), 128),
159
159
  "user": opt(c.get("user"), 64),
160
160
  "state": opt(c.get("state"), 32),
161
- "unacked": num(c.get("messages_unacknowledged")),
162
- "prefetch": num(c.get("prefetch_count")),
163
- "consumers": num(c.get("consumer_count")),
161
+ "unacked": as_int(c.get("messages_unacknowledged")),
162
+ "prefetch": as_int(c.get("prefetch_count")),
163
+ "consumers": as_int(c.get("consumer_count")),
164
164
  }
165
165
  for c in conn.platform.rows(conn.get(conn.platform.path("channels")))
166
166
  ]
@@ -190,7 +190,7 @@ def list_policies(conn: Any, vhost: str | None = None) -> dict:
190
190
  "vhost": opt(p.get("vhost"), 64),
191
191
  "pattern": opt(p.get("pattern"), 128),
192
192
  "applyTo": opt(pick(p, "apply-to", "apply_to", default="all"), 32),
193
- "priority": num(p.get("priority")),
193
+ "priority": as_int(p.get("priority")),
194
194
  "definition": as_obj(p.get("definition")),
195
195
  }
196
196
  for p in conn.platform.rows(conn.get(path))
@@ -223,10 +223,10 @@ def node_health(conn: Any) -> dict:
223
223
  "diskFreeBytes": as_int(n.get("disk_free")),
224
224
  "diskFreeLimitBytes": as_int(n.get("disk_free_limit")),
225
225
  "diskAlarm": bool(n.get("disk_free_alarm")),
226
- "fdUsed": num(n.get("fd_used")),
227
- "fdTotal": num(n.get("fd_total")),
228
- "socketsUsed": num(n.get("sockets_used")),
229
- "socketsTotal": num(n.get("sockets_total")),
226
+ "fdUsed": as_int(n.get("fd_used")),
227
+ "fdTotal": as_int(n.get("fd_total")),
228
+ "socketsUsed": as_int(n.get("sockets_used")),
229
+ "socketsTotal": as_int(n.get("sockets_total")),
230
230
  }
231
231
  )
232
232
  rows.sort(key=lambda r: r["memUsedBytes"], reverse=True)
@@ -40,7 +40,7 @@ def server_info(conn: Any) -> dict:
40
40
  "connectedClients": as_int(info.get("connected_clients")),
41
41
  "blockedClients": as_int(info.get("blocked_clients")),
42
42
  "opsPerSec": num(info.get("instantaneous_ops_per_sec")),
43
- "totalCommands": num(info.get("total_commands_processed")),
43
+ "totalCommands": as_int(info.get("total_commands_processed")),
44
44
  "keyspaceHits": as_int(info.get("keyspace_hits")),
45
45
  "keyspaceMisses": as_int(info.get("keyspace_misses")),
46
46
  "hitRatePct": pct(
@@ -143,9 +143,9 @@ def slowlog(conn: Any, count: int = MAX_SLOWLOG_ROWS) -> dict:
143
143
  entries = conn.redis_slowlog(want + 1)
144
144
  rows = [
145
145
  {
146
- "id": num(e.get("id")),
147
- "startTime": num(e.get("start_time")),
148
- "durationUs": num(e.get("duration")),
146
+ "id": as_int(e.get("id")),
147
+ "startTime": as_int(e.get("start_time")),
148
+ "durationUs": as_int(e.get("duration")),
149
149
  "command": _command_text(e.get("command")),
150
150
  "clientAddr": opt(e.get("client_address"), 64),
151
151
  "clientName": opt(e.get("client_name"), 64),
@@ -7,12 +7,12 @@
7
7
  "url": "https://github.com/AIops-tools/Queue-AIops",
8
8
  "source": "github"
9
9
  },
10
- "version": "0.2.1",
10
+ "version": "0.2.2",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "pypi",
14
14
  "identifier": "queue-aiops",
15
- "version": "0.2.1",
15
+ "version": "0.2.2",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  }
@@ -781,7 +781,7 @@ wheels = [
781
781
 
782
782
  [[package]]
783
783
  name = "queue-aiops"
784
- version = "0.2.1"
784
+ version = "0.2.2"
785
785
  source = { editable = "." }
786
786
  dependencies = [
787
787
  { name = "cryptography" },
@@ -1,26 +0,0 @@
1
- # Release notes — queue-aiops 0.2.1
2
-
3
- Previous release: 0.2.0.
4
-
5
- ## Fixed: integer quantities were rendered as floats
6
-
7
- Key counts, client counts and byte totals were routed through the float coercion
8
- helper, so a live server reported `202.0` keys and `1.0` connected clients. The
9
- values were arithmetically right but semantically wrong — a count cannot be
10
- fractional, and a reader should not have to wonder whether `.0` means the number was
11
- rounded.
12
-
13
- These now use a new `as_int()` helper and come back as integers. Genuinely fractional
14
- values (`hitRatePct`, `usedPctOfMax`, `opsPerSec`, `expiresPct`) are unchanged. Note
15
- that equality assertions cannot catch this class of bug (`202 == 202.0`), so the
16
- regression test asserts the *type*.
17
-
18
- If you parse these fields, the JSON shape changes from `202.0` to `202`.
19
-
20
- ## Live-verified
21
-
22
- This release was exercised end-to-end against a real **Redis 7.4.9** server: every
23
- Redis read cross-checked against `redis-cli` ground truth, all four analyses, and the
24
- full governance loop (real `redis_config_set` → audit row → `undo_apply` restoring the
25
- prior value). See [docs/VERIFICATION.md](docs/VERIFICATION.md) — **RabbitMQ remains
26
- mock-only** and is now the largest gap in this repo.
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes