@windyroad/risk-scorer 0.14.1-preview.792 → 0.14.2-preview.795

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.
@@ -310,5 +310,5 @@
310
310
  }
311
311
  },
312
312
  "name": "wr-risk-scorer",
313
- "version": "0.14.1"
313
+ "version": "0.14.2"
314
314
  }
@@ -7,6 +7,16 @@
7
7
  # scaffolds the register on-demand via /wr-risk-scorer:bootstrap-catalog
8
8
  # (ADR-059); this hook is the discovery surface — it does NOT write.
9
9
  #
10
+ # P375 (2026-06-27): once docs/risks/ exists, the hook no longer goes
11
+ # silent — it counts entries still carrying the `**Curation**: pending
12
+ # review` marker and re-surfaces the count every session. This closes the
13
+ # audit's "one step short of the jtbd pattern" gap: the scaffold check
14
+ # alone went quiet once stubs existed, so the pending-review backlog
15
+ # (auto-scaffolded entries whose controls + Impact×Likelihood scoring are
16
+ # not yet human-curated) rotted invisibly. Counting content state and
17
+ # re-surfacing until drained is the class-B self-surfacing pattern that
18
+ # jtbd-oversight-nudge.sh / architect-oversight-nudge.sh already use.
19
+ #
10
20
  # Read-only, side-effect-free. Modelled on
11
21
  # packages/architect/hooks/architect-oversight-nudge.sh (ADR-066) and
12
22
  # packages/jtbd/hooks/jtbd-oversight-nudge.sh (ADR-068). Per ADR-040 the
@@ -36,8 +46,24 @@ REGISTER_DIR="$PROJECT_DIR/docs/risks"
36
46
  # it, the absence of docs/risks/ is not a governance gap.
37
47
  [ -f "$POLICY_FILE" ] || exit 0
38
48
 
39
- # Silent when the register directory already exists the scaffold has
40
- # either already happened or the user has populated it manually.
41
- [ -d "$REGISTER_DIR" ] && exit 0
49
+ # Register directory missingnudge to scaffold it.
50
+ if [ ! -d "$REGISTER_DIR" ]; then
51
+ echo "[wr-risk-scorer] RISK-POLICY.md present but docs/risks/ is missing — run /wr-risk-scorer:bootstrap-catalog to scaffold the standing-risk register."
52
+ exit 0
53
+ fi
54
+
55
+ # Register exists: count entries still carrying the curation marker so the
56
+ # pending-review backlog self-surfaces every session (class-B, P375)
57
+ # instead of going silent once stubs exist. Token-cheap grep over the
58
+ # register dir — no body reads, no per-file LLM call (matches the
59
+ # jtbd-oversight-nudge.sh cost profile).
60
+ PENDING="$(grep -rlE '^\*\*Curation\*\*: pending review' "$REGISTER_DIR" 2>/dev/null | grep -c . || true)"
61
+ PENDING="${PENDING:-0}"
62
+
63
+ [ "$PENDING" -gt 0 ] 2>/dev/null || exit 0
42
64
 
43
- echo "[wr-risk-scorer] RISK-POLICY.md present but docs/risks/ is missing — run /wr-risk-scorer:bootstrap-catalog to scaffold the standing-risk register."
65
+ if [ "$PENDING" -eq 1 ]; then
66
+ echo "[wr-risk-scorer] 1 standing-risk entry is pending review — curate it in docs/risks/ (enumerate controls + Impact×Likelihood scoring)."
67
+ else
68
+ echo "[wr-risk-scorer] $PENDING standing-risk entries are pending review — curate them in docs/risks/ (enumerate controls + Impact×Likelihood scoring)."
69
+ fi
@@ -6,6 +6,13 @@
6
6
  # otherwise, and self-suppresses under the AFK guard
7
7
  # (WR_SUPPRESS_OVERSIGHT_NUDGE=1 per ADR-068) so the interactive
8
8
  # scaffold-confirm never fires into an absent-user iteration (JTBD-006).
9
+ #
10
+ # P375 (2026-06-27): once docs/risks/ exists, the hook no longer goes
11
+ # silent — it counts entries still carrying the `**Curation**: pending
12
+ # review` marker and re-surfaces the count every session so the
13
+ # pending-review backlog self-surfaces (class-B) instead of rotting
14
+ # silently once stubs exist (the audit's "one step short of the jtbd
15
+ # pattern" gap).
9
16
  # Behavioural — exercises the hook against fixture trees and asserts on stdout.
10
17
 
11
18
  setup() {
@@ -27,7 +34,7 @@ teardown() {
27
34
  [[ "$output" == *"/wr-risk-scorer:bootstrap-catalog"* ]]
28
35
  }
29
36
 
30
- @test "silent when RISK-POLICY.md exists and docs/risks/ also exists" {
37
+ @test "silent when RISK-POLICY.md exists and docs/risks/ exists but is empty" {
31
38
  printf 'placeholder policy\n' > "$DIR/RISK-POLICY.md"
32
39
  mkdir -p "$DIR/docs/risks"
33
40
  run env CLAUDE_PROJECT_DIR="$DIR" CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" bash "$HOOK"
@@ -35,6 +42,45 @@ teardown() {
35
42
  [ -z "$output" ]
36
43
  }
37
44
 
45
+ @test "silent when docs/risks/ exists with entries but none are pending review" {
46
+ printf 'placeholder policy\n' > "$DIR/RISK-POLICY.md"
47
+ mkdir -p "$DIR/docs/risks"
48
+ printf '# R001\n**Curation**: curated\n' > "$DIR/docs/risks/R001-foo.active.md"
49
+ run env CLAUDE_PROJECT_DIR="$DIR" CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" bash "$HOOK"
50
+ [ "$status" -eq 0 ]
51
+ [ -z "$output" ]
52
+ }
53
+
54
+ @test "surfaces a pending-review count when entries carry the curation marker (P375 self-surfacing)" {
55
+ printf 'placeholder policy\n' > "$DIR/RISK-POLICY.md"
56
+ mkdir -p "$DIR/docs/risks"
57
+ printf '# R001\n**Curation**: pending review (auto-scaffolded 2026-06-17)\n' > "$DIR/docs/risks/R001-foo.active.md"
58
+ printf '# R002\n**Curation**: pending review\n' > "$DIR/docs/risks/R002-bar.active.md"
59
+ printf '# R003\n**Curation**: curated\n' > "$DIR/docs/risks/R003-baz.active.md"
60
+ run env CLAUDE_PROJECT_DIR="$DIR" CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" bash "$HOOK"
61
+ [ "$status" -eq 0 ]
62
+ [[ "$output" == *"2 standing-risk entries are pending review"* ]]
63
+ [[ "$output" == *"docs/risks/"* ]]
64
+ }
65
+
66
+ @test "singular phrasing when exactly one entry is pending review" {
67
+ printf 'placeholder policy\n' > "$DIR/RISK-POLICY.md"
68
+ mkdir -p "$DIR/docs/risks"
69
+ printf '# R001\n**Curation**: pending review\n' > "$DIR/docs/risks/R001-foo.active.md"
70
+ run env CLAUDE_PROJECT_DIR="$DIR" CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" bash "$HOOK"
71
+ [ "$status" -eq 0 ]
72
+ [[ "$output" == *"1 standing-risk entry is pending review"* ]]
73
+ }
74
+
75
+ @test "AFK guard suppresses the pending-review nudge too" {
76
+ printf 'placeholder policy\n' > "$DIR/RISK-POLICY.md"
77
+ mkdir -p "$DIR/docs/risks"
78
+ printf '# R001\n**Curation**: pending review\n' > "$DIR/docs/risks/R001-foo.active.md"
79
+ run env WR_SUPPRESS_OVERSIGHT_NUDGE=1 CLAUDE_PROJECT_DIR="$DIR" CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" bash "$HOOK"
80
+ [ "$status" -eq 0 ]
81
+ [ -z "$output" ]
82
+ }
83
+
38
84
  @test "silent when RISK-POLICY.md is absent (no policy file = no register expectation)" {
39
85
  run env CLAUDE_PROJECT_DIR="$DIR" CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT" bash "$HOOK"
40
86
  [ "$status" -eq 0 ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/risk-scorer",
3
- "version": "0.14.1-preview.792",
3
+ "version": "0.14.2-preview.795",
4
4
  "description": "Pipeline risk scoring, commit/push gates, and secret leak detection",
5
5
  "bin": {
6
6
  "windyroad-risk-scorer": "./bin/install.mjs"