@sigrun/warden 0.1.0 → 0.1.1

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
@@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.1.1] - 2026-11-06
9
+
10
+ ### Fixed
11
+
12
+ - Annotation mapping read the warden spec's flat `readOnly` /
13
+ `destructive` keys — a shape no provider ever served. The published
14
+ `mcp.tool-annotations` hook (ext-mcp 0.2.3) returns the hints NESTED
15
+ under `annotations`, spelled `readOnlyHint` / `destructiveHint`, so
16
+ every annotated MCP tool — including `readOnlyHint: true` ones —
17
+ classified as destructive (fail-closed, but wrong: read-only calls
18
+ were held/steered). The mapping now reads the nested wire shape
19
+ (nested wins; the flat keys stay accepted defensively). Found live
20
+ during the 2026-11-05 rollout: `transmission_list_torrents` was
21
+ steered on a clear list request.
22
+
8
23
  ## [0.1.0] - 2026-11-05
9
24
 
10
25
  ### Added
package/dist/classify.js CHANGED
@@ -31,14 +31,31 @@ export function annotationFromHookResult(tool, result) {
31
31
  if (record.unknown === true)
32
32
  return { status: "unknown" };
33
33
  const { server, mcpName } = splitMcpName(tool);
34
+ // The hook's published output schema (ext-mcp 0.2.3's
35
+ // `mcp.tool-annotations`) nests the hints under `annotations`, spelled
36
+ // `readOnlyHint` / `destructiveHint`. The flat `readOnly` / `destructive`
37
+ // keys were the warden spec's shorthand and no provider ever served
38
+ // them; they stay accepted defensively, but the nested shape is the
39
+ // wire truth and wins when both appear.
40
+ const hints = typeof record.annotations === "object" && record.annotations !== null
41
+ ? record.annotations
42
+ : {};
43
+ const readOnlyHint = hints.readOnlyHint;
44
+ const destructiveHint = hints.destructiveHint;
34
45
  return {
35
46
  status: "found",
36
47
  server,
37
48
  mcpName,
38
- ...(typeof record.readOnly === "boolean" ? { readOnly: record.readOnly } : {}),
39
- ...(typeof record.destructive === "boolean"
40
- ? { destructive: record.destructive }
41
- : {}),
49
+ ...(typeof readOnlyHint === "boolean"
50
+ ? { readOnly: readOnlyHint }
51
+ : typeof record.readOnly === "boolean"
52
+ ? { readOnly: record.readOnly }
53
+ : {}),
54
+ ...(typeof destructiveHint === "boolean"
55
+ ? { destructive: destructiveHint }
56
+ : typeof record.destructive === "boolean"
57
+ ? { destructive: record.destructive }
58
+ : {}),
42
59
  };
43
60
  }
44
61
  /** Every string argument of a tool call (the `path`-rule match surface). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sigrun/warden",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Guardrail extension for sigrun: action classification, holds, and judge-backed confirmations (pi-warden port)",
5
5
  "type": "module",
6
6
  "engines": {