@windyroad/risk-scorer 0.11.3-preview.472 → 0.11.3-preview.484
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.
|
@@ -14,6 +14,14 @@
|
|
|
14
14
|
# - gh api .../comments (any REST surface accepting prose)
|
|
15
15
|
# - npm publish (README / package metadata to npm)
|
|
16
16
|
# - PreToolUse:Write|Edit on .changeset/*.md (P073 — gates author-time)
|
|
17
|
+
# - git commit -m / --message (incl. HEREDOC) (P082 Phase 1 — commit message
|
|
18
|
+
# body reaches every reader of git
|
|
19
|
+
# log, PR commits tab, release-page
|
|
20
|
+
# auto-notes, CHANGELOG. Editor
|
|
21
|
+
# flow is out of scope per P082 SC1
|
|
22
|
+
# — message is written to
|
|
23
|
+
# .git/COMMIT_EDITMSG AFTER
|
|
24
|
+
# PreToolUse, nothing to read.)
|
|
17
25
|
#
|
|
18
26
|
# Gate behaviour:
|
|
19
27
|
# 1. BYPASS_RISK_GATE=1 short-circuits the gate (consistent with git-push-gate.sh).
|
|
@@ -144,20 +152,59 @@ except Exception:
|
|
|
144
152
|
SURFACE="gh-api-comments"
|
|
145
153
|
elif echo "$COMMAND" | grep -qE '(^|;|&&|\|\|)\s*npm publish(\s|$)'; then
|
|
146
154
|
SURFACE="npm-publish"
|
|
155
|
+
elif echo "$COMMAND" | grep -qE '(^|;|&&|\|\|)\s*git commit(\s|$)'; then
|
|
156
|
+
# P082 Phase 1: gate `git commit -m / --message / HEREDOC` so commit
|
|
157
|
+
# message bodies are reviewed by the voice-tone + risk evaluators
|
|
158
|
+
# before they land in git log / PR commits tab / release notes /
|
|
159
|
+
# CHANGELOG. Editor flow (bare `git commit`) is out of scope per
|
|
160
|
+
# P082 SC1 — git writes .git/COMMIT_EDITMSG AFTER PreToolUse fires,
|
|
161
|
+
# so there's no body to extract at gate time. Skip silently when
|
|
162
|
+
# neither -m nor --message is present.
|
|
163
|
+
if echo "$COMMAND" | grep -qE '(\s|^)(-m|--message)(\s|=)'; then
|
|
164
|
+
SURFACE="git-commit-message"
|
|
165
|
+
else
|
|
166
|
+
exit 0
|
|
167
|
+
fi
|
|
147
168
|
else
|
|
148
169
|
exit 0
|
|
149
170
|
fi
|
|
150
171
|
|
|
151
|
-
# Best-effort body extraction
|
|
152
|
-
#
|
|
153
|
-
#
|
|
172
|
+
# Best-effort body extraction. Order matters — most-specific first.
|
|
173
|
+
#
|
|
174
|
+
# HEREDOC first: `git commit -m "$(cat <<'EOF'\n...\nEOF\n)"` is the
|
|
175
|
+
# AI-dominant form. Must precede --body "..." / -m "..." because
|
|
176
|
+
# those would otherwise match the literal `$(cat <<'EOF'...EOF)`
|
|
177
|
+
# text as the body, defeating the marker key match against the
|
|
178
|
+
# subagent's <draft> body.
|
|
179
|
+
# Then --body / --field for the gh + npm + security-advisories surfaces.
|
|
180
|
+
# Then -m / --message for git commit (single-line literal forms).
|
|
181
|
+
#
|
|
182
|
+
# When absent (npm publish, --body-file, editor flow already filtered),
|
|
183
|
+
# DRAFT="" is acceptable: the agent will be invoked with command
|
|
184
|
+
# context and read whatever body source the call uses.
|
|
154
185
|
DRAFT=$(printf '%s' "$COMMAND" | python3 -c "
|
|
155
186
|
import sys, re
|
|
156
187
|
cmd = sys.stdin.read()
|
|
157
|
-
#
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
188
|
+
# (pattern, flags) — first match wins.
|
|
189
|
+
patterns = [
|
|
190
|
+
# HEREDOC body — matches a here-doc with EOF delimiter (quoted or
|
|
191
|
+
# unquoted). The literal '<<' is written as the char-class pair
|
|
192
|
+
# [<][<] so bash's command-substitution parser does NOT mis-parse
|
|
193
|
+
# this regex as a real here-doc operator (P082 implementation note).
|
|
194
|
+
# DOTALL so the body can span newlines.
|
|
195
|
+
(r\"[<][<]\s*['\\\"]?EOF['\\\"]?\s*\n(.*?)\nEOF\", re.DOTALL),
|
|
196
|
+
# gh issue/pr + npm publish --body 'TEXT' / --body \"TEXT\" (existing).
|
|
197
|
+
(r\"--body[= ]'([^']*)'\", 0),
|
|
198
|
+
(r'--body[= ]\"([^\"]*)\"', 0),
|
|
199
|
+
# gh api --field summary='TEXT' / --field summary=\"TEXT\" (existing).
|
|
200
|
+
(r\"--field [a-zA-Z_]+='([^']*)'\", 0),
|
|
201
|
+
(r'--field [a-zA-Z_]+=\"([^\"]*)\"', 0),
|
|
202
|
+
# git commit -m / --message single-line literal forms (P082 Phase 1).
|
|
203
|
+
(r\"(?:-m|--message)[= ]'([^']*)'\", 0),
|
|
204
|
+
(r'(?:-m|--message)[= ]\"([^\"]*)\"', 0),
|
|
205
|
+
]
|
|
206
|
+
for pat, flags in patterns:
|
|
207
|
+
m = re.search(pat, cmd, flags)
|
|
161
208
|
if m:
|
|
162
209
|
print(m.group(1))
|
|
163
210
|
break
|
|
@@ -224,3 +224,95 @@ run_hook() {
|
|
|
224
224
|
[ "$status" -eq 0 ]
|
|
225
225
|
[ -z "$output" ]
|
|
226
226
|
}
|
|
227
|
+
|
|
228
|
+
# ---------------------------------------------------------------------------
|
|
229
|
+
# P082 Phase 1 — git commit message surface (risk evaluator).
|
|
230
|
+
# Commit messages reach git log / PR commits tab / release notes /
|
|
231
|
+
# CHANGELOG. The risk evaluator gates the body for leak patterns
|
|
232
|
+
# (credentials, prod URLs, business-context-paired financials/user counts)
|
|
233
|
+
# AND defers structured leak-free drafts to the wr-risk-scorer:external-comms
|
|
234
|
+
# subagent. Editor flow (bare `git commit`) is out of scope per P082 SC1.
|
|
235
|
+
# ---------------------------------------------------------------------------
|
|
236
|
+
|
|
237
|
+
@test "P082: git commit -m with leak-shaped credential body denies via leak pre-filter" {
|
|
238
|
+
INPUT=$(build_bash_input "git commit -m \"docs: token=${GH_TOKEN_LIKE}\"")
|
|
239
|
+
run_hook "$INPUT"
|
|
240
|
+
[ "$status" -eq 0 ]
|
|
241
|
+
[[ "$output" == *"deny"* ]]
|
|
242
|
+
[[ "$output" == *"git-commit-message"* ]]
|
|
243
|
+
[[ "$output" == *"GitHub token"* ]] || [[ "$output" == *"credential"* ]]
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
@test "P082: git commit -m with leak-free body denies and delegates to risk evaluator" {
|
|
247
|
+
INPUT=$(build_bash_input "git commit -m \"fix(foo): handle null input\"")
|
|
248
|
+
run_hook "$INPUT"
|
|
249
|
+
[ "$status" -eq 0 ]
|
|
250
|
+
[[ "$output" == *"deny"* ]]
|
|
251
|
+
[[ "$output" == *"git-commit-message"* ]]
|
|
252
|
+
[[ "$output" == *"wr-risk-scorer:external-comms"* ]]
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
@test "P082: git commit --amend -m is intercepted (P082 SC2)" {
|
|
256
|
+
INPUT=$(build_bash_input "git commit --amend -m \"rewritten subject\"")
|
|
257
|
+
run_hook "$INPUT"
|
|
258
|
+
[ "$status" -eq 0 ]
|
|
259
|
+
[[ "$output" == *"deny"* ]]
|
|
260
|
+
[[ "$output" == *"git-commit-message"* ]]
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
@test "P082: git commit HEREDOC body is intercepted and the body becomes the marker key" {
|
|
264
|
+
# Build a HEREDOC-shaped command. The hook regex pulls the body BETWEEN
|
|
265
|
+
# the <<'EOF' opener and the closing EOF marker — the extracted DRAFT is
|
|
266
|
+
# the inner text, NOT the literal `$(cat <<'EOF' ... EOF)` wrapper.
|
|
267
|
+
BODY=$'feat(foo): add bar\n\nWe observed a build failure on Node 20.'
|
|
268
|
+
CMD=$'git commit -m "$(cat <<\'EOF\'\n'"$BODY"$'\nEOF\n)"'
|
|
269
|
+
INPUT=$(build_bash_input "$CMD")
|
|
270
|
+
run_hook "$INPUT"
|
|
271
|
+
[ "$status" -eq 0 ]
|
|
272
|
+
[[ "$output" == *"deny"* ]]
|
|
273
|
+
[[ "$output" == *"git-commit-message"* ]]
|
|
274
|
+
|
|
275
|
+
# Pre-place the per-evaluator marker keyed on the extracted HEREDOC body
|
|
276
|
+
# + the git-commit-message surface; the second run must permit silently.
|
|
277
|
+
SURFACE="git-commit-message"
|
|
278
|
+
KEY=$(printf '%s\n%s' "$BODY" "$SURFACE" | shasum -a 256 | cut -d' ' -f1)
|
|
279
|
+
touch "${RDIR}/external-comms-risk-reviewed-${KEY}"
|
|
280
|
+
run_hook "$INPUT"
|
|
281
|
+
[ "$status" -eq 0 ]
|
|
282
|
+
[ -z "$output" ]
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
@test "P082: bare git commit (editor flow) is silently allowed per SC1" {
|
|
286
|
+
# No -m / --message → .git/COMMIT_EDITMSG doesn't exist at PreToolUse
|
|
287
|
+
# time. Phase 1 skip is pragmatic; the editor flow has user-eyeballs.
|
|
288
|
+
INPUT=$(build_bash_input "git commit")
|
|
289
|
+
run_hook "$INPUT"
|
|
290
|
+
[ "$status" -eq 0 ]
|
|
291
|
+
[ -z "$output" ]
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
@test "P082: git merge is silently allowed (not a git commit verb, SC3)" {
|
|
295
|
+
INPUT=$(build_bash_input "git merge --no-ff feature-branch")
|
|
296
|
+
run_hook "$INPUT"
|
|
297
|
+
[ "$status" -eq 0 ]
|
|
298
|
+
[ -z "$output" ]
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
@test "P082: BYPASS_RISK_GATE=1 short-circuits the git commit gate" {
|
|
302
|
+
INPUT=$(build_bash_input "git commit -m \"fix(foo): handle null input\"")
|
|
303
|
+
run bash -c "cd '$TEST_PROJECT_DIR' && BYPASS_RISK_GATE=1 printf '%s' \"\$1\" | BYPASS_RISK_GATE=1 '$HOOK'" _ "$INPUT"
|
|
304
|
+
[ "$status" -eq 0 ]
|
|
305
|
+
[ -z "$output" ]
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
@test "P082: per-evaluator marker keyed on (body, git-commit-message) permits the call" {
|
|
309
|
+
BODY="docs(retro): close iter 3 ask-hygiene trail"
|
|
310
|
+
SURFACE="git-commit-message"
|
|
311
|
+
KEY=$(printf '%s\n%s' "$BODY" "$SURFACE" | shasum -a 256 | cut -d' ' -f1)
|
|
312
|
+
touch "${RDIR}/external-comms-risk-reviewed-${KEY}"
|
|
313
|
+
|
|
314
|
+
INPUT=$(build_bash_input "git commit -m \"$BODY\"")
|
|
315
|
+
run_hook "$INPUT"
|
|
316
|
+
[ "$status" -eq 0 ]
|
|
317
|
+
[ -z "$output" ]
|
|
318
|
+
}
|
package/package.json
CHANGED