@windyroad/voice-tone 0.3.1-preview.300 → 0.4.0-preview.303

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.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "wr-voice-tone",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Voice and tone enforcement for Claude Code"
5
5
  }
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env bats
2
+
3
+ # Tests for voice-tone-enforce-edit.sh — verifies the path-based exemption
4
+ # for governance-managed surfaces (docs/story-maps/, docs/stories/) per
5
+ # ADR-060 § Phase 2 amendment 2026-05-12 lines 481-496 (P170 Phase 2 Slice 2.5).
6
+ #
7
+ # The voice-tone hook is opt-in (gates *.html|*.jsx|*.tsx|*.vue|*.svelte|
8
+ # *.ejs|*.hbs) and blocks outright when docs/VOICE-AND-TONE.md is absent.
9
+ # Story-map HTML files would otherwise be blocked even when no policy
10
+ # exists — this is the empirical block P170 line 297 documented when the
11
+ # STORY-MAP-001 bootstrap was attempted. The exemption short-circuits before
12
+ # the extension check.
13
+
14
+ setup() {
15
+ SCRIPT_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
16
+ HOOK="$SCRIPT_DIR/voice-tone-enforce-edit.sh"
17
+ ORIG_DIR="$PWD"
18
+ TEST_DIR=$(mktemp -d)
19
+ cd "$TEST_DIR"
20
+ }
21
+
22
+ teardown() {
23
+ cd "$ORIG_DIR"
24
+ rm -rf "$TEST_DIR"
25
+ }
26
+
27
+ run_hook_with_file() {
28
+ local file_path="$1"
29
+ local json="{\"tool_input\":{\"file_path\":\"${file_path}\"},\"session_id\":\"test-session-$$\"}"
30
+ echo "$json" | bash "$HOOK"
31
+ }
32
+
33
+ assert_path_allowed() {
34
+ local file_path="$1"
35
+ run run_hook_with_file "$file_path"
36
+ [ "$status" -eq 0 ]
37
+ [[ "$output" != *"BLOCKED"* ]]
38
+ }
39
+
40
+ assert_path_blocked() {
41
+ local file_path="$1"
42
+ run run_hook_with_file "$file_path"
43
+ [ "$status" -eq 0 ]
44
+ [[ "$output" == *"BLOCKED"* ]]
45
+ }
46
+
47
+ # --- Story maps + stories exemptions (P170 Phase 2 Slice 2.5 / ADR-060) ---
48
+
49
+ @test "voice-tone: exempts docs/story-maps/ HTML in per-state subdir" {
50
+ assert_path_allowed "$PWD/docs/story-maps/draft/STORY-MAP-001-foo.html"
51
+ }
52
+
53
+ @test "voice-tone: exempts docs/story-maps/ HTML in completed subdir" {
54
+ assert_path_allowed "$PWD/docs/story-maps/completed/STORY-MAP-002-bar.html"
55
+ }
56
+
57
+ @test "voice-tone: exempts docs/story-maps/ even when no VOICE-AND-TONE.md exists" {
58
+ # P170 line 297: STORY-MAP-001 bootstrap was blocked here exactly because
59
+ # this exemption did not exist. Behavioural regression-guard.
60
+ [ ! -f docs/VOICE-AND-TONE.md ]
61
+ assert_path_allowed "$PWD/docs/story-maps/in-progress/STORY-MAP-001-rfc-framework.html"
62
+ }
63
+
64
+ @test "voice-tone: exempts docs/stories/ files even though .md isn't normally gated" {
65
+ assert_path_allowed "$PWD/docs/stories/draft/STORY-001-foo.md"
66
+ }
67
+
68
+ # --- Regression: non-exempt HTML still gate ---
69
+
70
+ @test "voice-tone: still blocks an unrelated .html file when no policy exists" {
71
+ assert_path_blocked "$PWD/public/index.html"
72
+ }
73
+
74
+ @test "voice-tone: still blocks a .tsx component file when no policy exists" {
75
+ assert_path_blocked "$PWD/src/Component.tsx"
76
+ }
@@ -45,6 +45,20 @@ case "$FILE_PATH" in
45
45
  ;;
46
46
  esac
47
47
 
48
+ # Governance-managed surface exemptions — ADR-060 § Phase 2 amendment
49
+ # 2026-05-12 lines 481-496 (P170 Phase 2 Slice 2.5). Story-map HTML and
50
+ # story Markdown are governed by capture-story-map / manage-story-map and
51
+ # capture-story / manage-story skills (peer-plugin pattern, mirrors the
52
+ # docs/problems and docs/jtbd exemptions on architect + jtbd gates).
53
+ # Short-circuits before the *.html opt-in match below would otherwise fire
54
+ # on story-map HTML — the empirical block documented at P170 line 297.
55
+ case "$FILE_PATH" in
56
+ */docs/story-maps/*|docs/story-maps/*)
57
+ exit 0 ;;
58
+ */docs/stories/*|docs/stories/*)
59
+ exit 0 ;;
60
+ esac
61
+
48
62
  # Gate copy-bearing files
49
63
  case "$FILE_PATH" in
50
64
  *.html|*.jsx|*.tsx|*.vue|*.svelte|*.ejs|*.hbs) ;;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/voice-tone",
3
- "version": "0.3.1-preview.300",
3
+ "version": "0.4.0-preview.303",
4
4
  "description": "Voice and tone enforcement for user-facing copy",
5
5
  "bin": {
6
6
  "windyroad-voice-tone": "./bin/install.mjs"