@windyroad/risk-scorer 0.3.6 → 0.4.0-preview.196

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.3.6",
3
+ "version": "0.4.0",
4
4
  "description": "Pipeline risk scoring, commit/push/release gates for Claude Code"
5
5
  }
@@ -169,6 +169,47 @@ Include downstream back-pressure in the remediation list:
169
169
 
170
170
  Do NOT emit free-text "Your call:" or "consider splitting" prose. The structured `RISK_REMEDIATIONS:` block is the only output for above-appetite guidance.
171
171
 
172
+ ## Risk Register Hand-Off (Passive Trigger)
173
+
174
+ When a pipeline run identifies a **register-worthy risk shape**, emit a structured `RISK_REGISTER_HINT:` block so the calling orchestrator can hand the finding off to `/wr-risk-scorer:create-risk` with pre-filled context. This is the passive trigger for the standing-risk register (`docs/risks/`) — it routes findings the pipeline already computes into the register without relying on the assistant remembering to invoke the create-risk skill (P110 / JTBD-001).
175
+
176
+ ### Trigger conditions (emit a hint when ANY fire)
177
+
178
+ 1. **Above-appetite residual** — any cumulative residual score exceeds appetite (> 4 per `RISK-POLICY.md`). A risk that breaches appetite on this change is a standing-risk candidate, not just a one-off remediation target.
179
+ 2. **Confidentiality disclosure** — the Confidential Information Disclosure check (below) flagged business metrics (revenue, user counts, pricing, client names, traffic volumes) in the diff. Confidentiality leaks are standing-risk-shaped even after the immediate remediation.
180
+ 3. **User-stated precondition** — the User-Stated Preconditions Check (below) flagged an unmet paired capability as a standalone Risk item. Unmet preconditions are standing-risk-shaped because the dependency gap persists until the paired capability ships.
181
+
182
+ ### Format (bulleted-list shape, multi-hint capable)
183
+
184
+ A single pipeline run MAY surface more than one register-worthy shape (e.g. both an above-appetite residual AND a confidentiality leak). Emit one bullet per triggered condition:
185
+
186
+ ```
187
+ RISK_REGISTER_HINT:
188
+ - above-appetite-residual | <one-line prefill describing the risk>
189
+ - confidentiality-disclosure | <one-line prefill citing what was flagged>
190
+ - user-stated-precondition | <one-line prefill citing the unmet precondition>
191
+ ```
192
+
193
+ ### Reason-tag vocabulary (enumerated — reserved)
194
+
195
+ The first column is one of exactly three reserved tags. Do NOT invent new tags; open new tickets to extend the vocabulary.
196
+
197
+ | Tag | Meaning | Source section in this prompt |
198
+ |---|---|---|
199
+ | `above-appetite-residual` | Cumulative residual score > appetite | Above-Appetite Remediations |
200
+ | `confidentiality-disclosure` | Business metric or client detail flagged in diff | Confidential Information Disclosure |
201
+ | `user-stated-precondition` | Paired capability unmet; standalone Risk item | User-Stated Preconditions Check |
202
+
203
+ The second column is free-form prose — a one-line prefill the orchestrator can pass to `/wr-risk-scorer:create-risk` as the initial risk title and description.
204
+
205
+ ### Consumption semantics (post-loop)
206
+
207
+ The hint is consumed by the calling orchestrator **after** the ADR-042 auto-apply remediation loop converges (risk returns within appetite) or halts (Rule 5 exhaustion / user-aborted). Do NOT expect the hint to be consumed interleaved with remediation execution — if a remediation reduces the residual back within appetite, the above-appetite hint should still be recorded because the risk is standing even if this change is no longer in breach. The orchestrator decides whether to invoke `/wr-risk-scorer:create-risk` with the prefill or to defer to the user.
208
+
209
+ ### Silence guarantee (when no trigger fires)
210
+
211
+ Do NOT emit `RISK_REGISTER_HINT:` when all cumulative scores are within appetite AND no confidentiality disclosure AND no user-stated-precondition fired. The hint is additive to the existing Below-Appetite Output Rule — a silent pass MUST remain silent. Do not emit an empty `RISK_REGISTER_HINT:` header with no bullets either — omit the block entirely.
212
+
172
213
  ## Confidential Information Disclosure
173
214
 
174
215
  Check diffs for business metrics (revenue, user counts, pricing, traffic volumes). Flag as a standalone risk if found.
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env bats
2
+ # Doc-lint guard: pipeline scorer MUST emit a structured RISK_REGISTER_HINT
3
+ # block when a register-worthy risk shape is identified.
4
+ #
5
+ # Structural assertions — Permitted Exception to the source-grep ban (ADR-005 / P011).
6
+ # These tests assert that the pipeline scorer's prompt defines the passive-trigger
7
+ # contract required by P110. Agent prompts are specification documents; a
8
+ # behavioural check of an LLM's output is out of scope for bats — the contract
9
+ # document is what the PostToolUse hook and consuming orchestrator rely on.
10
+ #
11
+ # Background: P102 landed `/wr-risk-scorer:create-risk` as an on-demand
12
+ # invocation surface for the risk register (docs/risks/). JTBD-001
13
+ # (Enforce Governance Without Slowing Down) requires passive triggers that
14
+ # fire "without a manual step" — assistant-remembering-to-invoke is the same
15
+ # failure mode the job identifies as a pain point. P110 closes the gap by
16
+ # having the pipeline scorer — which fires on every commit/push/release gate
17
+ # — emit a structured hint line when it sees a register-worthy risk shape.
18
+ # The calling orchestrator consumes the hint post-remediation-loop and
19
+ # invokes /wr-risk-scorer:create-risk with pre-filled context.
20
+ #
21
+ # Cross-reference:
22
+ # P110: docs/problems/110-risk-register-has-no-passive-trigger-slash-command-alone-partial-jtbd-001.open.md
23
+ # P102: the parent ticket (slash-command MVP invocation surface)
24
+ # ADR-015: docs/decisions/015-on-demand-assessment-skills.proposed.md (Scorer Output Contract)
25
+ # ADR-013: docs/decisions/013-structured-user-interaction-for-governance-decisions.proposed.md
26
+ # ADR-042: docs/decisions/042-auto-apply-scorer-remediations-open-vocabulary.proposed.md (consumption timing)
27
+ # @jtbd JTBD-001 (enforce governance without slowing down — passive trigger)
28
+ # @jtbd JTBD-005 (invoke governance assessments on demand — composed via pre-filled create-risk)
29
+
30
+ setup() {
31
+ AGENTS_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
32
+ PIPELINE="${AGENTS_DIR}/pipeline.md"
33
+ }
34
+
35
+ # ──────────────────────────────────────────────────────────────────────────────
36
+ # Contract surface: RISK_REGISTER_HINT block exists and is documented
37
+ # ──────────────────────────────────────────────────────────────────────────────
38
+
39
+ @test "pipeline.md defines RISK_REGISTER_HINT block" {
40
+ # The structured hint line is the machine-readable passive-trigger contract.
41
+ run grep -q "RISK_REGISTER_HINT:" "$PIPELINE"
42
+ [ "$status" -eq 0 ]
43
+ }
44
+
45
+ @test "pipeline.md RISK_REGISTER_HINT uses bulleted-list shape" {
46
+ # Multi-hint capable: a single pipeline run can surface both an
47
+ # above-appetite residual AND a confidentiality-disclosure risk.
48
+ # Shape parallels RISK_REMEDIATIONS: (list-valued), not RISK_BYPASS_REASON: (single).
49
+ run grep -qE "^RISK_REGISTER_HINT:[[:space:]]*$" "$PIPELINE"
50
+ [ "$status" -eq 0 ]
51
+ }
52
+
53
+ # ──────────────────────────────────────────────────────────────────────────────
54
+ # Trigger conditions: architect-approved three-trigger set
55
+ # ──────────────────────────────────────────────────────────────────────────────
56
+
57
+ @test "pipeline.md names above-appetite-residual trigger" {
58
+ # Trigger (a): any cumulative residual score > appetite.
59
+ run grep -q "above-appetite-residual" "$PIPELINE"
60
+ [ "$status" -eq 0 ]
61
+ }
62
+
63
+ @test "pipeline.md names confidentiality-disclosure trigger" {
64
+ # Trigger (b): confidential information (client names, revenue, pricing) flagged.
65
+ # Composes with the existing "Confidential Information Disclosure" section.
66
+ run grep -q "confidentiality-disclosure" "$PIPELINE"
67
+ [ "$status" -eq 0 ]
68
+ }
69
+
70
+ @test "pipeline.md names user-stated-precondition trigger" {
71
+ # Trigger (c): unmet user-stated precondition flagged as a Risk item.
72
+ # Composes with the existing "User-Stated Preconditions Check" section.
73
+ run grep -q "user-stated-precondition" "$PIPELINE"
74
+ [ "$status" -eq 0 ]
75
+ }
76
+
77
+ # ──────────────────────────────────────────────────────────────────────────────
78
+ # Consumption semantics: hint is consumed post-loop, not interleaved
79
+ # ──────────────────────────────────────────────────────────────────────────────
80
+
81
+ @test "pipeline.md documents post-loop consumption semantics" {
82
+ # Architect advisory: the hint is consumed by the orchestrator AFTER the
83
+ # ADR-042 auto-apply remediation loop converges (or Rule 5 halts), not
84
+ # interleaved — otherwise register entries would be created for risks the
85
+ # loop might have remediated away.
86
+ run grep -qiE "post.?loop|after.*remediation.*(converge|loop)|after.*auto.?apply" "$PIPELINE"
87
+ [ "$status" -eq 0 ]
88
+ }
89
+
90
+ # ──────────────────────────────────────────────────────────────────────────────
91
+ # Cross-reference: hint hands off to /wr-risk-scorer:create-risk
92
+ # ──────────────────────────────────────────────────────────────────────────────
93
+
94
+ @test "pipeline.md names the create-risk hand-off target" {
95
+ # The hint routes the consuming orchestrator to the MVP invocation surface
96
+ # from P102. Without the hand-off target, a hint line is undirected.
97
+ run grep -q "create-risk" "$PIPELINE"
98
+ [ "$status" -eq 0 ]
99
+ }
100
+
101
+ # ──────────────────────────────────────────────────────────────────────────────
102
+ # Silence guarantee: below appetite + no special triggers = no hint
103
+ # ──────────────────────────────────────────────────────────────────────────────
104
+
105
+ @test "pipeline.md documents no-hint silence when within appetite and no triggers fire" {
106
+ # JTBD-001 "without slowing down": no hint noise when nothing is
107
+ # register-worthy. This parallels the Below-Appetite Output Rule for
108
+ # RISK_REMEDIATIONS: and protects the solo-developer 60-second review budget.
109
+ run grep -qE "[Dd]o NOT emit.*RISK_REGISTER_HINT|[Oo]mit.*RISK_REGISTER_HINT|no hint|no.*RISK_REGISTER_HINT" "$PIPELINE"
110
+ [ "$status" -eq 0 ]
111
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/risk-scorer",
3
- "version": "0.3.6",
3
+ "version": "0.4.0-preview.196",
4
4
  "description": "Pipeline risk scoring, commit/push gates, and secret leak detection",
5
5
  "bin": {
6
6
  "windyroad-risk-scorer": "./bin/install.mjs"