@windyroad/jtbd 0.14.12 → 0.15.0
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.
|
@@ -154,6 +154,9 @@ _HOOK_INPUT=""
|
|
|
154
154
|
|
|
155
155
|
_parse_input() {
|
|
156
156
|
_HOOK_INPUT=$(cat)
|
|
157
|
+
if ! printf '%s' "$_HOOK_INPUT" | python3 -c 'import json,sys; assert isinstance(json.load(sys.stdin),dict)' 2>/dev/null; then
|
|
158
|
+
_governance_advisory "Hook input could not be parsed."
|
|
159
|
+
fi
|
|
157
160
|
}
|
|
158
161
|
|
|
159
162
|
_get_tool_name() {
|
|
@@ -327,3 +330,8 @@ _is_doc_file() {
|
|
|
327
330
|
esac
|
|
328
331
|
return 1
|
|
329
332
|
}
|
|
333
|
+
|
|
334
|
+
# Mechanical evaluation failures are advisory; never mint approval receipts.
|
|
335
|
+
_governance_advisory() {
|
|
336
|
+
python3 -c 'import json,sys; print(json.dumps({"systemMessage": "Governance evidence unavailable; action permitted. " + sys.argv[1]}))' "$1" || echo 'Governance evidence unavailable; action permitted.' >&2
|
|
337
|
+
}
|
package/hooks/lib/review-gate.sh
CHANGED
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
_REVIEW_GATE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
8
8
|
source "$_REVIEW_GATE_DIR/gate-helpers.sh"
|
|
9
9
|
|
|
10
|
-
#
|
|
10
|
+
# Validate review receipt; the public gate below converts unavailable evidence to an advisory.
|
|
11
11
|
# Sets REVIEW_GATE_REASON on failure.
|
|
12
12
|
# Usage: check_review_gate "$SESSION_ID" "style-guide" "docs/STYLE-GUIDE.md"
|
|
13
|
-
|
|
13
|
+
_check_review_receipt() {
|
|
14
14
|
local SESSION_ID="$1"
|
|
15
15
|
local SYSTEM="$2" # e.g., "a11y", "voice-tone", "style-guide"
|
|
16
16
|
local POLICY_FILE="$3" # e.g., "docs/STYLE-GUIDE.md"
|
|
@@ -82,24 +82,21 @@ store_review_hash() {
|
|
|
82
82
|
return 0
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
# Emit
|
|
85
|
+
# Emit an advisory for unverifiable review requirements.
|
|
86
86
|
review_gate_deny() {
|
|
87
|
-
|
|
88
|
-
cat <<EOF
|
|
89
|
-
{
|
|
90
|
-
"hookSpecificOutput": {
|
|
91
|
-
"hookEventName": "PreToolUse",
|
|
92
|
-
"permissionDecision": "deny",
|
|
93
|
-
"permissionDecisionReason": "$REASON"
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
EOF
|
|
87
|
+
_governance_advisory "$1"
|
|
97
88
|
}
|
|
98
89
|
|
|
99
|
-
#
|
|
90
|
+
# Permit parsing failures with an unavailable-evidence advisory.
|
|
100
91
|
review_gate_parse_error() {
|
|
101
92
|
cat <<'EOF'
|
|
102
|
-
{ "hookSpecificOutput": { "hookEventName": "PreToolUse", "permissionDecision": "
|
|
103
|
-
"permissionDecisionReason": "
|
|
93
|
+
{ "hookSpecificOutput": { "hookEventName": "PreToolUse", "permissionDecision": "allow",
|
|
94
|
+
"permissionDecisionReason": "Governance evidence unavailable: could not parse hook input; action permitted." } }
|
|
104
95
|
EOF
|
|
105
96
|
}
|
|
97
|
+
|
|
98
|
+
check_review_gate() {
|
|
99
|
+
if _check_review_receipt "$@"; then return 0; fi
|
|
100
|
+
_governance_advisory "$REVIEW_GATE_REASON"
|
|
101
|
+
return 0
|
|
102
|
+
}
|
|
@@ -5,8 +5,34 @@ target="$1"
|
|
|
5
5
|
input="$(cat)"
|
|
6
6
|
tool="$(printf '%s' "$input" | jq -r '.tool_name // empty')"
|
|
7
7
|
|
|
8
|
+
ADVISORIES=""
|
|
9
|
+
collect_gate_output() {
|
|
10
|
+
local output="$1" parsed
|
|
11
|
+
[ -n "$output" ] || return 0
|
|
12
|
+
if ! parsed="$(printf '%s' "$output" | jq -cs '
|
|
13
|
+
if any(.[]; .hookSpecificOutput.permissionDecision == "deny")
|
|
14
|
+
then map(select(.hookSpecificOutput.permissionDecision == "deny"))[0]
|
|
15
|
+
else {systemMessage: map(.systemMessage // .hookSpecificOutput.permissionDecisionReason // "Governance evidence unavailable; action permitted.") | join("\n")} end' 2>/dev/null)"; then
|
|
16
|
+
parsed='{"systemMessage":"Governance evidence unavailable: malformed evaluator output; action permitted."}'
|
|
17
|
+
fi
|
|
18
|
+
if printf '%s' "$parsed" | jq -e '.hookSpecificOutput.permissionDecision == "deny"' >/dev/null 2>&1; then
|
|
19
|
+
printf '%s\n' "$parsed"
|
|
20
|
+
exit 0
|
|
21
|
+
fi
|
|
22
|
+
ADVISORIES="$ADVISORIES
|
|
23
|
+
$parsed"
|
|
24
|
+
}
|
|
25
|
+
flush_advisories() {
|
|
26
|
+
[ -n "$ADVISORIES" ] || return 0
|
|
27
|
+
printf '%s' "$ADVISORIES" | jq -s '{systemMessage: map(.systemMessage // .hookSpecificOutput.permissionDecisionReason // "Governance evidence unavailable; action permitted.") | join("\n")}'
|
|
28
|
+
}
|
|
8
29
|
run_hook() {
|
|
9
|
-
|
|
30
|
+
local output
|
|
31
|
+
if ! output="$(printf '%s' "$1" | "$target" 2>/dev/null)"; then
|
|
32
|
+
collect_gate_output '{"systemMessage":"Governance evaluator unavailable; action permitted. A crashed hook output was discarded."}'
|
|
33
|
+
return 0
|
|
34
|
+
fi
|
|
35
|
+
collect_gate_output "$output"
|
|
10
36
|
}
|
|
11
37
|
|
|
12
38
|
if [ "$tool" = "apply_patch" ]; then
|
|
@@ -16,6 +42,7 @@ if [ "$tool" = "apply_patch" ]; then
|
|
|
16
42
|
payload="$(printf '%s' "$input" | jq --arg path "$path" '.tool_name = "Edit" | .tool_input.file_path = $path')"
|
|
17
43
|
run_hook "$payload" || exit $?
|
|
18
44
|
done <<< "$paths"
|
|
45
|
+
flush_advisories
|
|
19
46
|
exit 0
|
|
20
47
|
fi
|
|
21
48
|
fi
|
|
@@ -25,3 +52,4 @@ if [ "$tool" = "spawn_agent" ] || [ "$tool" = "Agent" ]; then
|
|
|
25
52
|
fi
|
|
26
53
|
|
|
27
54
|
run_hook "$input"
|
|
55
|
+
flush_advisories
|