@windyroad/risk-scorer 0.7.2-preview.300 → 0.7.3-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-risk-scorer",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "description": "Pipeline risk scoring, commit/push/release gates for Claude Code"
5
5
  }
package/agents/wip.md CHANGED
@@ -84,8 +84,7 @@ The verdict is `RISK_VERDICT: PAUSE`. This blocks the next edit until the risk i
84
84
  After assessing the risk profile, check whether uncommitted changes represent **completed governance work** that should be committed immediately to reduce WIP pipeline risk (ADR-016).
85
85
 
86
86
  **Governance-artefact detection heuristic**: Check `git status --short` and `git diff HEAD --name-only`. If ALL uncommitted files fall within these paths:
87
- - `docs/problems/*.md` (flat layout — pre-RFC-002)
88
- - `docs/problems/*/*.md` (per-state subdir layout — post-RFC-002 per ADR-031; one of `open/`, `known-error/`, `verifying/`, `parked/`, `closed/`)
87
+ - `docs/problems/**/*.md` (recursive glob — per ADR-031 accepted 2026-05-12 per-state-subdirectory encoding; matches both flat-layout (`docs/problems/<NNN>-<slug>.<state>.md` — pre-RFC-002 / pre-T5a) and per-state subdir layout (`docs/problems/<state>/<NNN>-<slug>.md` — post-T5a, the canonical end-state). Subdirs are one of `open/`, `known-error/`, `verifying/`, `parked/`, `closed/`.)
89
88
  - `packages/*/skills/**/*.md`
90
89
  - `packages/*/skills/**/*.bats`
91
90
  - `docs/decisions/*.md`
@@ -16,6 +16,21 @@ TOOL_NAME=$(_get_tool_name)
16
16
  COMMAND=$(_get_command)
17
17
  echo "$COMMAND" | grep -qE '(^|;|&&|\|\|)\s*git commit' || exit 0
18
18
 
19
+ # P170 / RFC-002 / ADR-031 T11: commit-message-embedded RISK_BYPASS
20
+ # marker recognition. The adopter auto-migrate routine (T7,
21
+ # packages/shared/lib/migrate-problems-layout.sh) emits a standalone
22
+ # commit with `RISK_BYPASS: adr-031-migration` in its body so the
23
+ # pure-rename + pure-mkdir migration commit (policy-authorised under
24
+ # ADR-013 Rule 6 + ADR-019 precedent) skips the full risk-score
25
+ # overhead while preserving the audit trail (per ADR-031 Open
26
+ # Execution-time Questions resolution Q3 lean (b)). Case-sensitive
27
+ # token match; only `adr-031-migration` is accepted at this surface.
28
+ # Future commit-message-embedded markers MUST be added explicitly
29
+ # here and to ADR-014's commit-message convention table.
30
+ if echo "$COMMAND" | grep -qE 'RISK_BYPASS:[[:space:]]*adr-031-migration([^A-Za-z0-9_-]|$)'; then
31
+ exit 0
32
+ fi
33
+
19
34
  SESSION_ID=$(_get_session_id)
20
35
  [ -n "$SESSION_ID" ] || exit 0
21
36
 
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env bats
2
+
3
+ # P170 / RFC-002 / ADR-031 T11: risk-score-commit-gate.sh recognises
4
+ # the `RISK_BYPASS: adr-031-migration` self-attestation marker in the
5
+ # git commit command's message arguments. Migration commits emitted by
6
+ # `migrate_problems_to_per_state_layout` carry this marker in their
7
+ # body so adopter auto-migration commits skip the full risk-score
8
+ # overhead while preserving the audit trail (per ADR-031 § Open
9
+ # Execution-time Questions resolution Q3 lean (b)).
10
+
11
+ setup() {
12
+ HOOKS_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
13
+ GATE_SCRIPT="$HOOKS_DIR/risk-score-commit-gate.sh"
14
+ TEST_SESSION="bats-test-$$-${BATS_TEST_NUMBER}"
15
+
16
+ # Run inside a temp work tree so the gate's RISK-POLICY.md presence
17
+ # check has something to bind to. The migration test fixture (T10)
18
+ # creates a real adopter repo; here we just need a minimal stub.
19
+ TMP_REPO="$(mktemp -d)"
20
+ cd "$TMP_REPO"
21
+ cat > RISK-POLICY.md <<EOF
22
+ # Risk Policy
23
+
24
+ Last reviewed: $(date -u +%Y-%m-%d)
25
+ EOF
26
+ }
27
+
28
+ teardown() {
29
+ rm -rf "$TMP_REPO"
30
+ rm -rf "${TMPDIR:-/tmp}/claude-risk-${TEST_SESSION}"
31
+ }
32
+
33
+ # Helper: invoke the gate with a Bash tool_input json + given command.
34
+ # Returns 0 if gate allows (exits 0 with no JSON deny), non-zero on deny.
35
+ invoke_gate() {
36
+ local command="$1"
37
+ local input
38
+ input=$(python3 -c "
39
+ import json, sys
40
+ print(json.dumps({
41
+ 'tool_name': 'Bash',
42
+ 'tool_input': {'command': sys.argv[1]},
43
+ 'session_id': sys.argv[2]
44
+ }))
45
+ " "$command" "$TEST_SESSION")
46
+ echo "$input" | bash "$GATE_SCRIPT"
47
+ }
48
+
49
+ @test "T11: commit with RISK_BYPASS: adr-031-migration marker bypasses the gate" {
50
+ local cmd='git commit -m "docs(problems): auto-migrate" -m "RISK_BYPASS: adr-031-migration"'
51
+ run invoke_gate "$cmd"
52
+ [ "$status" -eq 0 ]
53
+ # Gate should emit NO deny JSON when bypassed (silent allow).
54
+ [[ "$output" != *"permissionDecision"* ]] || [[ "$output" != *"deny"* ]]
55
+ }
56
+
57
+ @test "T11: commit message body containing RISK_BYPASS marker (multi-paragraph -m sequence) bypasses" {
58
+ local cmd='git commit -m "docs(problems): auto-migrate to per-state subdirectory layout (ADR-031)" -m "See: docs/decisions/031-problem-ticket-directory-layout.accepted.md" -m "RISK_BYPASS: adr-031-migration"'
59
+ run invoke_gate "$cmd"
60
+ [ "$status" -eq 0 ]
61
+ [[ "$output" != *"permissionDecision"* ]] || [[ "$output" != *"deny"* ]]
62
+ }
63
+
64
+ @test "T11: normal commit without RISK_BYPASS marker still gated (no score = deny)" {
65
+ local cmd='git commit -m "feat: normal commit"'
66
+ run invoke_gate "$cmd"
67
+ # Either exits with deny JSON output OR exits non-zero — both indicate the
68
+ # gate didn't silently allow. We assert deny JSON appears in the output.
69
+ [[ "$output" == *"deny"* ]]
70
+ }
71
+
72
+ @test "T11: heredoc-style git commit -m with embedded RISK_BYPASS marker bypasses" {
73
+ # Heredoc shape used by the migration routine + manual workflows;
74
+ # marker must be detected regardless of how the message reaches the
75
+ # command string.
76
+ local cmd=$'git commit -m "$(cat <<\'EOF\'\ndocs(problems): auto-migrate\n\nRISK_BYPASS: adr-031-migration\nEOF\n)"'
77
+ run invoke_gate "$cmd"
78
+ [ "$status" -eq 0 ]
79
+ [[ "$output" != *"permissionDecision"* ]] || [[ "$output" != *"deny"* ]]
80
+ }
81
+
82
+ @test "T11: marker is case-sensitive (adr-031-MIGRATION not recognised — security guard)" {
83
+ local cmd='git commit -m "RISK_BYPASS: adr-031-MIGRATION"'
84
+ run invoke_gate "$cmd"
85
+ [[ "$output" == *"deny"* ]]
86
+ }
87
+
88
+ @test "T11: unrelated RISK_BYPASS token (e.g. reducing) does NOT match adr-031-migration path" {
89
+ # `reducing` is the existing risk-score-mark.sh marker for risk-reducing
90
+ # scoring runs — different mechanism (filesystem marker via PostToolUse
91
+ # agent return), not commit-message detection. The commit-gate should
92
+ # NOT treat a `RISK_BYPASS: reducing` line in the COMMIT MESSAGE as a
93
+ # bypass — only `adr-031-migration` (and any future commit-message
94
+ # markers added explicitly).
95
+ local cmd='git commit -m "RISK_BYPASS: reducing"'
96
+ run invoke_gate "$cmd"
97
+ [[ "$output" == *"deny"* ]]
98
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/risk-scorer",
3
- "version": "0.7.2-preview.300",
3
+ "version": "0.7.3-preview.303",
4
4
  "description": "Pipeline risk scoring, commit/push gates, and secret leak detection",
5
5
  "bin": {
6
6
  "windyroad-risk-scorer": "./bin/install.mjs"