@windyroad/voice-tone 0.5.12 → 0.5.14-preview.746
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.
|
@@ -23,3 +23,11 @@ EXTERNAL_COMMS_POLICY_FILE=docs/VOICE-AND-TONE.md
|
|
|
23
23
|
# concern (run by packages/risk-scorer/hooks/external-comms-gate.sh when that
|
|
24
24
|
# plugin is also installed).
|
|
25
25
|
EXTERNAL_COMMS_LEAK_PREFILTER=no
|
|
26
|
+
|
|
27
|
+
# Surfaces this evaluator's policy doc disclaims — the gate silent-passes the
|
|
28
|
+
# marker-review delegation on them (P360). docs/VOICE-AND-TONE.md § Scope
|
|
29
|
+
# excludes commit messages ("It does NOT apply to: ... Commit messages (covered
|
|
30
|
+
# by ADR-014 + ADR-018)"), so a voice-tone review of the git-commit-message
|
|
31
|
+
# surface is a guaranteed-PASS no-op (~19K tokens). Skip it. The risk evaluator
|
|
32
|
+
# does NOT skip this surface — its leak check on commit bodies is meaningful.
|
|
33
|
+
EXTERNAL_COMMS_SKIP_SURFACES=git-commit-message
|
|
@@ -78,6 +78,10 @@ source "$SCRIPT_DIR/lib/external-comms-key.sh"
|
|
|
78
78
|
# EXTERNAL_COMMS_ASSESS_SKILL — on-demand skill path for manual delegation
|
|
79
79
|
# EXTERNAL_COMMS_POLICY_FILE — policy doc whose absence triggers advisory-only
|
|
80
80
|
# EXTERNAL_COMMS_LEAK_PREFILTER — yes|no — whether to run leak-detect pre-filter
|
|
81
|
+
# EXTERNAL_COMMS_SKIP_SURFACES — space-separated surface list this evaluator's
|
|
82
|
+
# policy disclaims; the marker-review delegation
|
|
83
|
+
# silent-passes on those surfaces (P360). Default
|
|
84
|
+
# empty (gate every detected surface).
|
|
81
85
|
# Fail-closed if absent: this hook cannot operate without a configured evaluator.
|
|
82
86
|
CONF_FILE="$SCRIPT_DIR/external-comms-evaluator.conf"
|
|
83
87
|
if [ ! -f "$CONF_FILE" ]; then
|
|
@@ -91,6 +95,7 @@ source "$CONF_FILE"
|
|
|
91
95
|
: "${EXTERNAL_COMMS_ASSESS_SKILL:?assess-skill missing from $CONF_FILE}"
|
|
92
96
|
EXTERNAL_COMMS_POLICY_FILE="${EXTERNAL_COMMS_POLICY_FILE:-RISK-POLICY.md}"
|
|
93
97
|
EXTERNAL_COMMS_LEAK_PREFILTER="${EXTERNAL_COMMS_LEAK_PREFILTER:-yes}"
|
|
98
|
+
EXTERNAL_COMMS_SKIP_SURFACES="${EXTERNAL_COMMS_SKIP_SURFACES:-}"
|
|
94
99
|
|
|
95
100
|
# ---------- Bypass ----------
|
|
96
101
|
if [ "${BYPASS_RISK_GATE:-0}" = "1" ]; then
|
|
@@ -318,6 +323,48 @@ if [ "$EXTERNAL_COMMS_LEAK_PREFILTER" = "yes" ]; then
|
|
|
318
323
|
fi
|
|
319
324
|
fi
|
|
320
325
|
|
|
326
|
+
# ---------- Per-evaluator surface skip (P360) ----------
|
|
327
|
+
# Some surfaces are explicitly disclaimed by THIS evaluator's policy doc, so the
|
|
328
|
+
# marker-review delegation below would be a guaranteed-PASS no-op (the subagent
|
|
329
|
+
# reads the policy, declares the surface out of scope, emits PASS — ~19K tokens
|
|
330
|
+
# per round-trip). EXTERNAL_COMMS_SKIP_SURFACES (per-package .conf) lists those
|
|
331
|
+
# surfaces; the gate silent-passes the prose-review delegation when the detected
|
|
332
|
+
# surface is on the list. Voice-tone sets this to `git-commit-message` because
|
|
333
|
+
# docs/VOICE-AND-TONE.md § Scope excludes commit messages ("covered by ADR-014 +
|
|
334
|
+
# ADR-018"); risk-scorer leaves it empty (its leak check on commit messages is
|
|
335
|
+
# meaningful). Placed AFTER the leak pre-filter so a skipped surface still gets
|
|
336
|
+
# credential/prod-URL scanning — this silences ONLY the prose-review deny, the
|
|
337
|
+
# same conservative shape as the P365 repo-visibility precondition below.
|
|
338
|
+
if [ -n "$EXTERNAL_COMMS_SKIP_SURFACES" ]; then
|
|
339
|
+
case " $EXTERNAL_COMMS_SKIP_SURFACES " in
|
|
340
|
+
*" $SURFACE "*)
|
|
341
|
+
exit 0
|
|
342
|
+
;;
|
|
343
|
+
esac
|
|
344
|
+
fi
|
|
345
|
+
|
|
346
|
+
# ---------- Repo-visibility precondition: git-commit-message surface (P365) ----------
|
|
347
|
+
# A commit message only becomes external-facing prose when it lands in a PUBLIC
|
|
348
|
+
# GitHub repo (git log / PR commits tab / release-page auto-notes / CHANGELOG).
|
|
349
|
+
# In private or internal repos the marker-review delegation deny below is a pure
|
|
350
|
+
# false-positive (P365 — user direction 2026-06-11: "this MUST NOT fire for
|
|
351
|
+
# private repos"). Confirm visibility authoritatively via gh and silent-pass the
|
|
352
|
+
# marker gate on any non-PUBLIC result. Any INDETERMINATE result (gh absent,
|
|
353
|
+
# unauthenticated, no remote, API error → empty $REPO_VISIBILITY) is treated as
|
|
354
|
+
# non-public: a commit message is only demonstrably external when the repo is
|
|
355
|
+
# confirmably PUBLIC, so the conservative direction for THIS surface is to not
|
|
356
|
+
# fire. This is a fail-open on the voice/tone-and-prose review ONLY — the
|
|
357
|
+
# leak-pattern pre-filter above (credentials / prod-URLs) has already run for
|
|
358
|
+
# every surface in every repo, so the high-stakes secrecy net is unaffected.
|
|
359
|
+
# Scoped to git-commit-message only; the gh-issue/pr/api, npm-publish, and
|
|
360
|
+
# changeset-author surfaces are inherently external and stay gated regardless.
|
|
361
|
+
if [ "$SURFACE" = "git-commit-message" ]; then
|
|
362
|
+
REPO_VISIBILITY=$(gh repo view --json visibility -q .visibility 2>/dev/null || echo "")
|
|
363
|
+
if [ "$REPO_VISIBILITY" != "PUBLIC" ]; then
|
|
364
|
+
exit 0
|
|
365
|
+
fi
|
|
366
|
+
fi
|
|
367
|
+
|
|
321
368
|
# ---------- Marker-based gate (per-evaluator marker per ADR-028 amended 2026-05-14) ----------
|
|
322
369
|
SESSION_DIR="${TMPDIR:-/tmp}/claude-risk-${SESSION_ID}"
|
|
323
370
|
mkdir -p "$SESSION_DIR"
|
|
@@ -61,9 +61,23 @@ print(json.dumps({
|
|
|
61
61
|
" "$file_path" "$content"
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
# Mock `gh repo view --json visibility` for the git-commit-message surface
|
|
65
|
+
# repo-visibility precondition (P365). vis ∈ {PUBLIC,PRIVATE,INTERNAL}; pass the
|
|
66
|
+
# literal "FAIL" to simulate gh absent / unauthenticated (non-zero exit).
|
|
67
|
+
mock_gh_visibility() {
|
|
68
|
+
local vis="$1"
|
|
69
|
+
mkdir -p "$TEST_PROJECT_DIR/mockbin"
|
|
70
|
+
if [ "$vis" = "FAIL" ]; then
|
|
71
|
+
printf '#!/usr/bin/env bash\nexit 1\n' > "$TEST_PROJECT_DIR/mockbin/gh"
|
|
72
|
+
else
|
|
73
|
+
printf '#!/usr/bin/env bash\necho %s\n' "$vis" > "$TEST_PROJECT_DIR/mockbin/gh"
|
|
74
|
+
fi
|
|
75
|
+
chmod +x "$TEST_PROJECT_DIR/mockbin/gh"
|
|
76
|
+
}
|
|
77
|
+
|
|
64
78
|
run_hook() {
|
|
65
79
|
local input="$1"
|
|
66
|
-
run bash -c "cd '$TEST_PROJECT_DIR' && printf '%s' \"\$1\" | '$HOOK'" _ "$input"
|
|
80
|
+
run bash -c "cd '$TEST_PROJECT_DIR' && export PATH='$TEST_PROJECT_DIR/mockbin':\$PATH && printf '%s' \"\$1\" | '$HOOK'" _ "$input"
|
|
67
81
|
}
|
|
68
82
|
|
|
69
83
|
# ---------- Tests ----------
|
|
@@ -233,56 +247,75 @@ run_hook() {
|
|
|
233
247
|
}
|
|
234
248
|
|
|
235
249
|
# ---------------------------------------------------------------------------
|
|
236
|
-
#
|
|
237
|
-
#
|
|
238
|
-
#
|
|
239
|
-
#
|
|
240
|
-
# (
|
|
241
|
-
#
|
|
250
|
+
# P360 — voice-tone evaluator disclaims the git-commit-message surface.
|
|
251
|
+
# docs/VOICE-AND-TONE.md § Scope explicitly excludes commit messages ("It does
|
|
252
|
+
# NOT apply to: ... Commit messages (covered by ADR-014 + ADR-018)"), so a
|
|
253
|
+
# voice-tone review of a commit-message body is a guaranteed-PASS no-op
|
|
254
|
+
# (~19K tokens per round-trip). external-comms-evaluator.conf sets
|
|
255
|
+
# EXTERNAL_COMMS_SKIP_SURFACES=git-commit-message, so the gate silent-passes the
|
|
256
|
+
# prose-review delegation on this surface in EVERY repo — visibility-independent
|
|
257
|
+
# (the P360 skip is placed ahead of the P365 visibility precondition). The
|
|
258
|
+
# risk-scorer evaluator, whose .conf leaves the skip list empty, still gates
|
|
259
|
+
# this surface (its leak check is meaningful) — covered by
|
|
260
|
+
# packages/risk-scorer/hooks/test/external-comms-gate.bats.
|
|
261
|
+
#
|
|
262
|
+
# Supersedes the original P082 Phase 1 voice-tone commit-message tests, which
|
|
263
|
+
# asserted DENY on PUBLIC — that gate fire was the no-op P360 removes.
|
|
242
264
|
# ---------------------------------------------------------------------------
|
|
243
265
|
|
|
244
|
-
@test "
|
|
266
|
+
@test "P360: git commit -m silent-passes (voice-tone disclaims commit messages)" {
|
|
267
|
+
mock_gh_visibility PUBLIC
|
|
245
268
|
INPUT=$(build_bash_input "git commit -m \"I've implemented the feature\"")
|
|
246
269
|
run_hook "$INPUT"
|
|
247
270
|
[ "$status" -eq 0 ]
|
|
248
|
-
[
|
|
249
|
-
[[ "$output" == *"git-commit-message"* ]]
|
|
250
|
-
[[ "$output" == *"wr-voice-tone:external-comms"* ]]
|
|
271
|
+
[ -z "$output" ]
|
|
251
272
|
}
|
|
252
273
|
|
|
253
|
-
@test "
|
|
274
|
+
@test "P360: git commit --message silent-passes with no marker round-trip" {
|
|
275
|
+
mock_gh_visibility PUBLIC
|
|
254
276
|
INPUT=$(build_bash_input "git commit --message \"happy to help further with this fix\"")
|
|
255
277
|
run_hook "$INPUT"
|
|
256
278
|
[ "$status" -eq 0 ]
|
|
257
|
-
[
|
|
258
|
-
[[ "$output" == *"git-commit-message"* ]]
|
|
279
|
+
[ -z "$output" ]
|
|
259
280
|
}
|
|
260
281
|
|
|
261
|
-
@test "
|
|
282
|
+
@test "P360: git commit --amend -m silent-passes" {
|
|
283
|
+
mock_gh_visibility PUBLIC
|
|
262
284
|
INPUT=$(build_bash_input "git commit --amend -m \"rewritten subject\"")
|
|
263
285
|
run_hook "$INPUT"
|
|
264
286
|
[ "$status" -eq 0 ]
|
|
265
|
-
[
|
|
266
|
-
[[ "$output" == *"git-commit-message"* ]]
|
|
287
|
+
[ -z "$output" ]
|
|
267
288
|
}
|
|
268
289
|
|
|
269
|
-
@test "
|
|
270
|
-
|
|
271
|
-
# the <<'EOF' opener and the closing EOF marker — the extracted DRAFT is
|
|
272
|
-
# the inner text, NOT the literal `$(cat <<'EOF' ... EOF)` wrapper.
|
|
290
|
+
@test "P360: git commit HEREDOC body silent-passes without a marker" {
|
|
291
|
+
mock_gh_visibility PUBLIC
|
|
273
292
|
BODY=$'feat(foo): add bar\n\nWe observed a build failure on Node 20.'
|
|
274
293
|
CMD=$'git commit -m "$(cat <<\'EOF\'\n'"$BODY"$'\nEOF\n)"'
|
|
275
294
|
INPUT=$(build_bash_input "$CMD")
|
|
276
295
|
run_hook "$INPUT"
|
|
277
296
|
[ "$status" -eq 0 ]
|
|
278
|
-
[
|
|
279
|
-
|
|
297
|
+
[ -z "$output" ]
|
|
298
|
+
}
|
|
280
299
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
300
|
+
@test "P360: commit-message skip is visibility-independent (PRIVATE silent-passes)" {
|
|
301
|
+
mock_gh_visibility PRIVATE
|
|
302
|
+
INPUT=$(build_bash_input "git commit -m \"I've implemented the feature\"")
|
|
303
|
+
run_hook "$INPUT"
|
|
304
|
+
[ "$status" -eq 0 ]
|
|
305
|
+
[ -z "$output" ]
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
@test "P360: commit-message skip is visibility-independent (INTERNAL silent-passes)" {
|
|
309
|
+
mock_gh_visibility INTERNAL
|
|
310
|
+
INPUT=$(build_bash_input "git commit -m \"I've implemented the feature\"")
|
|
311
|
+
run_hook "$INPUT"
|
|
312
|
+
[ "$status" -eq 0 ]
|
|
313
|
+
[ -z "$output" ]
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
@test "P360: commit-message skip is visibility-independent (indeterminate gh silent-passes)" {
|
|
317
|
+
mock_gh_visibility FAIL
|
|
318
|
+
INPUT=$(build_bash_input "git commit -m \"I've implemented the feature\"")
|
|
286
319
|
run_hook "$INPUT"
|
|
287
320
|
[ "$status" -eq 0 ]
|
|
288
321
|
[ -z "$output" ]
|
|
@@ -311,16 +344,25 @@ run_hook() {
|
|
|
311
344
|
[ -z "$output" ]
|
|
312
345
|
}
|
|
313
346
|
|
|
314
|
-
@test "
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
347
|
+
@test "P360: the skip is surface-scoped — gh-issue is NOT skipped (still denies+delegates)" {
|
|
348
|
+
# EXTERNAL_COMMS_SKIP_SURFACES lists only git-commit-message; the inherently
|
|
349
|
+
# external gh-issue surface stays gated. Guards against the skip list over-
|
|
350
|
+
# matching (e.g. a substring or blanket-skip regression).
|
|
351
|
+
mock_gh_visibility PUBLIC
|
|
352
|
+
INPUT=$(build_bash_input "gh issue create --title x --body 'a clean issue body'")
|
|
353
|
+
run_hook "$INPUT"
|
|
354
|
+
[ "$status" -eq 0 ]
|
|
355
|
+
[[ "$output" == *"deny"* ]]
|
|
356
|
+
[[ "$output" == *"wr-voice-tone:external-comms"* ]]
|
|
357
|
+
}
|
|
319
358
|
|
|
320
|
-
|
|
359
|
+
@test "P365: PRIVATE visibility does NOT short-circuit the gh-issue surface (still denies+delegates)" {
|
|
360
|
+
mock_gh_visibility PRIVATE
|
|
361
|
+
INPUT=$(build_bash_input "gh issue create --title x --body 'a clean issue body'")
|
|
321
362
|
run_hook "$INPUT"
|
|
322
363
|
[ "$status" -eq 0 ]
|
|
323
|
-
[
|
|
364
|
+
[[ "$output" == *"deny"* ]]
|
|
365
|
+
[[ "$output" == *"gh-issue-create"* ]]
|
|
324
366
|
}
|
|
325
367
|
|
|
326
368
|
# ---------------------------------------------------------------------------
|