@windyroad/risk-scorer 0.18.1 → 0.18.2
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.
|
@@ -32,21 +32,37 @@ if [ -n "$SESSION_ID" ] && [ -f "$RELEASE_SCORE_FILE" ]; then
|
|
|
32
32
|
fi
|
|
33
33
|
|
|
34
34
|
# --- Read appetite from RISK-POLICY.md ---
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
35
|
+
# Mirror the canonical risk-gate parser: scope matches to the Risk Appetite
|
|
36
|
+
# section and default to the ADR-086 Low ceiling of 5.
|
|
37
|
+
APPETITE=$(python3 -c "
|
|
38
|
+
import re
|
|
39
|
+
try:
|
|
40
|
+
text = open('RISK-POLICY.md', encoding='utf-8').read()
|
|
41
|
+
except Exception:
|
|
42
|
+
text = ''
|
|
43
|
+
section = re.search(r'##\s*Risk Appetite\s*(.*?)(?=\n##\s|\Z)', text, re.DOTALL | re.IGNORECASE)
|
|
44
|
+
scope = section.group(1) if section else text
|
|
45
|
+
value = None
|
|
46
|
+
for pattern in (r'Threshold:\s*(\d+)', r'exceeds\s+(\d+)', r'(\d+)\s*/\s*Low appetite'):
|
|
47
|
+
match = re.search(pattern, scope, re.IGNORECASE)
|
|
48
|
+
if match:
|
|
49
|
+
value = match.group(1)
|
|
50
|
+
break
|
|
51
|
+
print(value or '5')
|
|
52
|
+
" 2>/dev/null || echo "5")
|
|
53
|
+
|
|
54
|
+
emit_json() {
|
|
55
|
+
HOOK_SYSTEM_MESSAGE="$1" python3 -c "
|
|
56
|
+
import json, os
|
|
57
|
+
print(json.dumps({
|
|
58
|
+
'hookSpecificOutput': {
|
|
59
|
+
'hookEventName': 'PreToolUse',
|
|
60
|
+
'permissionDecision': 'allow',
|
|
61
|
+
'systemMessage': os.environ['HOOK_SYSTEM_MESSAGE'],
|
|
62
|
+
}
|
|
63
|
+
}))
|
|
64
|
+
"
|
|
65
|
+
}
|
|
50
66
|
|
|
51
67
|
# --- P096 Phase 2 — once-per-session gating (ADR-038 progressive disclosure) ---
|
|
52
68
|
# First EnterPlanMode of a session emits the full advisory body; subsequent
|
|
@@ -54,27 +70,17 @@ fi
|
|
|
54
70
|
# ADR-038 budget). Pipeline state and appetite are unchanged across plan-mode
|
|
55
71
|
# entries within one session, so re-emitting full prose is repetition.
|
|
56
72
|
if has_announced "risk-scorer-plan-guidance" "$SESSION_ID"; then
|
|
57
|
-
|
|
58
|
-
{
|
|
59
|
-
"hookSpecificOutput": {
|
|
60
|
-
"hookEventName": "PreToolUse",
|
|
61
|
-
"permissionDecision": "allow",
|
|
62
|
-
"systemMessage": "MANDATORY release-risk gate active (RISK-POLICY.md present). Release risk: ${RELEASE_SCORE}; appetite: ${APPETITE}. ExitPlanMode will FAIL plans projected above appetite. See first-EnterPlanMode emission for full guidance."
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
EOF
|
|
73
|
+
emit_json "MANDATORY release-risk gate active (RISK-POLICY.md present). Release risk: ${RELEASE_SCORE}; appetite: ${APPETITE}. ExitPlanMode will FAIL plans projected above appetite. See first-EnterPlanMode emission for full guidance."
|
|
66
74
|
exit 0
|
|
67
75
|
fi
|
|
68
76
|
|
|
69
77
|
# --- First emission: full advisory (compressed per audit recommendation) ---
|
|
70
78
|
mark_announced "risk-scorer-plan-guidance" "$SESSION_ID"
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
EOF
|
|
79
|
+
emit_json "RELEASE RISK GUIDANCE FOR PLANNING:
|
|
80
|
+
Unreleased queue:
|
|
81
|
+
${UNRELEASED_SUMMARY}
|
|
82
|
+
|
|
83
|
+
Release risk: ${RELEASE_SCORE}. Appetite threshold: ${APPETITE}.
|
|
84
|
+
|
|
85
|
+
If projected release risk would exceed appetite, the plan MUST include a release strategy (release queue first, split into smaller batches, or risk-reducing steps). See RISK-POLICY.md for option details. ExitPlanMode runs the risk-scorer and FAILS plans above appetite without a strategy."
|
|
80
86
|
exit 0
|
package/package.json
CHANGED