@windyroad/voice-tone 0.8.7 → 0.9.0

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.
@@ -50,6 +50,17 @@
50
50
  },
51
51
  "schema_version": "2.0"
52
52
  },
53
+ "assistant-voice-tone-stop": {
54
+ "band": "Experimental",
55
+ "computed_at": "2026-09-17T00:00:00Z",
56
+ "evidence": {
57
+ "breaking_change_age_days": null,
58
+ "closed_tickets_window": 0,
59
+ "days_shipped": 0,
60
+ "invocations_30d": null
61
+ },
62
+ "schema_version": "2.0"
63
+ },
53
64
  "voice-tone-enforce-edit": {
54
65
  "band": "Experimental",
55
66
  "computed_at": "2026-05-18T11:42:50Z",
@@ -109,6 +120,17 @@
109
120
  },
110
121
  "schema_version": "2.0"
111
122
  },
123
+ "update-assistant-guide": {
124
+ "band": "Experimental",
125
+ "computed_at": "2026-09-17T00:00:00Z",
126
+ "evidence": {
127
+ "breaking_change_age_days": null,
128
+ "closed_tickets_window": 0,
129
+ "days_shipped": 0,
130
+ "invocations_30d": 0
131
+ },
132
+ "schema_version": "2.0"
133
+ },
112
134
  "update-guide": {
113
135
  "band": "Experimental",
114
136
  "computed_at": "2026-05-18T11:42:50Z",
@@ -123,5 +145,5 @@
123
145
  }
124
146
  },
125
147
  "name": "wr-voice-tone",
126
- "version": "0.8.7"
148
+ "version": "0.9.0"
127
149
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wr-voice-tone",
3
- "version": "0.8.7",
3
+ "version": "0.9.0",
4
4
  "description": "Voice, tone, and external-communications governance",
5
5
  "author": {
6
6
  "name": "Windy Road Technology",
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @windyroad/voice-tone
2
2
 
3
- **Voice and tone enforcement for Claude Code.** Reviews user-facing copy against your brand's voice and tone guide before it ships. *Maturity: Experimental (suite-bootstrap window; 169 invocations / 30d).*
3
+ **Voice and tone guidance for Claude Code and Codex.** Reviews user-facing copy before it ships and can shape ordinary assistant responses. *Maturity: Experimental (suite-bootstrap window; 169 invocations / 30d).*
4
4
 
5
5
  Part of [Windy Road Agent Plugins](../../README.md).
6
6
 
@@ -35,13 +35,20 @@ The plugin works automatically. On first use in a project without a voice guide,
35
35
 
36
36
  This examines your existing content and asks about your brand voice, target audience, and tone preferences to generate a `docs/VOICE-AND-TONE.md` tailored to your project.
37
37
 
38
+ ### Assistant responses
39
+
40
+ Run `/wr-voice-tone:update-assistant-guide` to create or update `docs/ASSISTANT-VOICE-AND-TONE.md`. The file's existence is the only enablement switch. Its prose may describe plain-language standards such as ISO 24495-1:2023 or ASD-STE100, or creative voice traits. The same assistant applies the guide and performs one semantic self-review before stopping; this adds one continuation's latency and token use, and some runtimes may briefly show the first response before its correction.
41
+
42
+ This supports the plugin's Claude Code and Codex command-hook runtimes, not ordinary web ChatGPT conversations. Standards references express alignment, not certification.
43
+
38
44
  ## How It Works
39
45
 
40
46
  | Hook | Trigger | What it does |
41
47
  |------|---------|-------------|
42
- | `voice-tone-eval.sh` | Every prompt | Evaluates whether the task involves user-facing copy |
48
+ | `voice-tone-eval.sh` | Every prompt | Evaluates copy work and injects an opted-in assistant-response guide |
43
49
  | `voice-tone-enforce-edit.sh` | Edit or Write | Blocks edits until the voice-tone agent has reviewed |
44
50
  | `voice-tone-mark-reviewed.sh` | Agent completes | Marks the review as done (TTL: 3600s) |
51
+ | `assistant-voice-tone-stop.sh` | Response stop | Requests one guarded semantic self-review when the assistant guide exists |
45
52
 
46
53
  ## Agent
47
54
 
@@ -0,0 +1,19 @@
1
+ #!/bin/bash
2
+ # Assistant response voice-and-tone Stop hook.
3
+ # If docs/ASSISTANT-VOICE-AND-TONE.md exists, ask the same assistant for one
4
+ # semantic self-review continuation. The stop_hook_active guard prevents loops.
5
+
6
+ INPUT=$(cat)
7
+
8
+ [ -f "docs/ASSISTANT-VOICE-AND-TONE.md" ] || exit 0
9
+
10
+ STOP_HOOK_ACTIVE=$(printf '%s' "$INPUT" | jq -r '.stop_hook_active // false' 2>/dev/null || echo "false")
11
+ [ "$STOP_HOOK_ACTIVE" = "true" ] && exit 0
12
+
13
+ LAST_ASSISTANT_MESSAGE=$(printf '%s' "$INPUT" | jq -r '.last_assistant_message // empty' 2>/dev/null || echo "")
14
+ [ -n "$LAST_ASSISTANT_MESSAGE" ] || exit 0
15
+
16
+ jq -n --arg reason 'Review your previous response semantically against docs/ASSISTANT-VOICE-AND-TONE.md. If the response does not align, emit one complete corrected final response in the requested voice and tone. If no correction is needed, finish without adding user-facing commentary. Do not claim standards certification; claim alignment only when relevant.' '{
17
+ decision: "block",
18
+ reason: $reason
19
+ }'
package/hooks/hooks.json CHANGED
@@ -5,7 +5,8 @@
5
5
  "hooks": [
6
6
  {
7
7
  "type": "command",
8
- "command": "${CLAUDE_PLUGIN_ROOT}/hooks/voice-tone-eval.sh"
8
+ "command": "${PLUGIN_ROOT}/hooks/voice-tone-eval.sh",
9
+ "additionalContextLimit": 0
9
10
  }
10
11
  ]
11
12
  },
@@ -13,7 +14,8 @@
13
14
  "hooks": [
14
15
  {
15
16
  "type": "command",
16
- "command": "${CLAUDE_PLUGIN_ROOT}/hooks/staleness-check.sh"
17
+ "command": "${PLUGIN_ROOT}/hooks/staleness-check.sh",
18
+ "additionalContextLimit": 0
17
19
  }
18
20
  ]
19
21
  }
@@ -33,7 +35,7 @@
33
35
  "hooks": [
34
36
  {
35
37
  "type": "command",
36
- "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/bash-write-dispatch.sh\" \"${CLAUDE_PLUGIN_ROOT}/hooks/voice-tone-enforce-edit.sh\""
38
+ "command": "\"${PLUGIN_ROOT}/hooks/bash-write-dispatch.sh\" \"${PLUGIN_ROOT}/hooks/voice-tone-enforce-edit.sh\""
37
39
  }
38
40
  ]
39
41
  },
@@ -89,6 +91,16 @@
89
91
  ]
90
92
  }
91
93
  ],
94
+ "Stop": [
95
+ {
96
+ "hooks": [
97
+ {
98
+ "type": "command",
99
+ "command": "${PLUGIN_ROOT}/hooks/assistant-voice-tone-stop.sh"
100
+ }
101
+ ]
102
+ }
103
+ ],
92
104
  "SubagentStop": [
93
105
  {
94
106
  "matcher": "^wr-voice-tone:agent$",
@@ -1,6 +1,8 @@
1
1
  #!/bin/bash
2
2
  # Voice & Tone - UserPromptSubmit hook (P095 / ADR-038)
3
3
  # Detects VOICE-AND-TONE.md in the project and injects delegation instruction.
4
+ # Also injects docs/ASSISTANT-VOICE-AND-TONE.md when a project opts into
5
+ # assistant-response voice guidance.
4
6
  # If the file doesn't exist, instructs Claude to create it via the agent.
5
7
  #
6
8
  # Progressive disclosure (ADR-038): full MANDATORY block on first
@@ -9,9 +11,45 @@
9
11
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
10
12
  # shellcheck source=lib/session-marker.sh
11
13
  source "$SCRIPT_DIR/lib/session-marker.sh"
14
+ # shellcheck source=lib/gate-helpers.sh
15
+ source "$SCRIPT_DIR/lib/gate-helpers.sh"
12
16
 
13
17
  INPUT=$(cat)
14
18
  SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // empty' 2>/dev/null || echo "")
19
+ ASSISTANT_GUIDE="docs/ASSISTANT-VOICE-AND-TONE.md"
20
+
21
+ inject_assistant_guide() {
22
+ [ -f "$ASSISTANT_GUIDE" ] || return 0
23
+
24
+ local hash marker hash_file previous_hash
25
+ hash=$(_substance_hash_path "$ASSISTANT_GUIDE")
26
+ marker="/tmp/assistant-voice-tone-announced-${SESSION_ID}"
27
+ hash_file="${marker}.hash"
28
+
29
+ if [ -n "$SESSION_ID" ] && [ -f "$marker" ] && [ -f "$hash_file" ]; then
30
+ previous_hash=$(cat "$hash_file" 2>/dev/null || echo "")
31
+ [ "$previous_hash" = "$hash" ] && return 0
32
+ fi
33
+
34
+ cat <<'HOOK_OUTPUT'
35
+ INSTRUCTION: ASSISTANT VOICE AND TONE GUIDE ACTIVE.
36
+ The project has opted into assistant-response voice guidance with docs/ASSISTANT-VOICE-AND-TONE.md.
37
+
38
+ Apply the guide to ordinary assistant responses. Treat named standards and style references as prose guidance for alignment, not as a certification claim.
39
+
40
+ <assistant-voice-and-tone-guide>
41
+ HOOK_OUTPUT
42
+ cat "$ASSISTANT_GUIDE"
43
+ cat <<'HOOK_OUTPUT'
44
+ </assistant-voice-and-tone-guide>
45
+ HOOK_OUTPUT
46
+
47
+ if [ -n "$SESSION_ID" ]; then
48
+ _atomic_mark_with_hash "$marker" "$hash" || return 1
49
+ fi
50
+ }
51
+
52
+ inject_assistant_guide
15
53
 
16
54
  if [ -f "docs/VOICE-AND-TONE.md" ]; then
17
55
  if has_announced "voice-tone" "$SESSION_ID"; then
@@ -5,7 +5,8 @@
5
5
  "hooks": [
6
6
  {
7
7
  "type": "command",
8
- "command": "${CLAUDE_PLUGIN_ROOT}/hooks/voice-tone-eval.sh"
8
+ "command": "${PLUGIN_ROOT}/hooks/voice-tone-eval.sh",
9
+ "additionalContextLimit": 0
9
10
  }
10
11
  ]
11
12
  },
@@ -13,7 +14,8 @@
13
14
  "hooks": [
14
15
  {
15
16
  "type": "command",
16
- "command": "${CLAUDE_PLUGIN_ROOT}/hooks/staleness-check.sh"
17
+ "command": "${PLUGIN_ROOT}/hooks/staleness-check.sh",
18
+ "additionalContextLimit": 0
17
19
  }
18
20
  ]
19
21
  }
@@ -33,7 +35,7 @@
33
35
  "hooks": [
34
36
  {
35
37
  "type": "command",
36
- "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/bash-write-dispatch.sh\" \"${CLAUDE_PLUGIN_ROOT}/hooks/voice-tone-enforce-edit.sh\""
38
+ "command": "\"${PLUGIN_ROOT}/hooks/bash-write-dispatch.sh\" \"${PLUGIN_ROOT}/hooks/voice-tone-enforce-edit.sh\""
37
39
  }
38
40
  ]
39
41
  },
@@ -89,6 +91,16 @@
89
91
  ]
90
92
  }
91
93
  ],
94
+ "Stop": [
95
+ {
96
+ "hooks": [
97
+ {
98
+ "type": "command",
99
+ "command": "${PLUGIN_ROOT}/hooks/assistant-voice-tone-stop.sh"
100
+ }
101
+ ]
102
+ }
103
+ ],
92
104
  "SubagentStop": [
93
105
  {
94
106
  "matcher": "^wr-voice-tone:agent$",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/voice-tone",
3
- "version": "0.8.7",
3
+ "version": "0.9.0",
4
4
  "description": "Voice and tone enforcement for user-facing copy",
5
5
  "bin": {
6
6
  "windyroad-voice-tone": "./bin/install.mjs"
@@ -0,0 +1,46 @@
1
+ ---
2
+ name: wr-voice-tone:update-assistant-guide
3
+ description: Create or update docs/ASSISTANT-VOICE-AND-TONE.md for project-specific assistant response voice, tone, and plain-language guidance.
4
+ allowed-tools: Read, Write, Edit, Bash, Glob, Grep, request_user_input
5
+ ---
6
+
7
+ <!-- Generated from the runtime-neutral skill source. Do not edit. -->
8
+
9
+ > Codex runtime note: invoke installed skills directly, use
10
+ > `request_user_input` only when the contract requires a human decision, and
11
+ > use native Codex subagents for agent delegation. Resolve bundled files from
12
+ > this installed plugin instead of the adopter repository.
13
+
14
+
15
+ # Assistant Voice and Tone Guide Generator
16
+
17
+ Create or update `docs/ASSISTANT-VOICE-AND-TONE.md`. This guide governs the assistant's ordinary responses in this project when the file exists.
18
+
19
+ This is separate from `docs/VOICE-AND-TONE.md`, which governs project-authored copy and external communications.
20
+
21
+ ## Contract
22
+
23
+ - File existence is the only opt-in switch.
24
+ - The guide body is prose. Do not add profiles, enabled flags, enforcement settings, deterministic rule tables, or a standards registry.
25
+ - Formal standards such as ISO 24495-1:2023 or ASD-STE100 may be named or described in prose, but the feature claims alignment, not certification.
26
+ - Creative voices should be described as traits and response qualities. Do not promise literal impersonation of a living person.
27
+ - When the user's direction is explicit, write the guide immediately. Do not add another confirmation or consent gate.
28
+ - Preserve unrelated existing prose. Replace or remove conflicting guidance only after confirming that exact change with the user.
29
+ - Never delete the guide unless the user explicitly asks to opt out.
30
+
31
+ ## Workflow
32
+
33
+ Inspect the current project conventions and any existing `docs/ASSISTANT-VOICE-AND-TONE.md`. Draft concise prose that tells the assistant how responses should read, including any standards or creative traits the user asked for.
34
+
35
+ Before writing a new guide or materially changing an existing one, use `request_user_input` to confirm the proposed direction when the user's intent is not already explicit.
36
+
37
+ Write or update the file with:
38
+
39
+ - a short title;
40
+ - the response voice and tone guidance;
41
+ - any named standards or creative traits expressed as prose;
42
+ - a short note that this is assistant-response guidance and does not certify conformance to external standards.
43
+
44
+ If updating, report the meaningful changes after writing.
45
+
46
+ $ARGUMENTS
@@ -0,0 +1,3 @@
1
+ interface:
2
+ display_name: "WR Voice Tone: Update Assistant Guide"
3
+ short_description: "Update assistant response voice guidance"