@bookedsolid/reagent 0.7.1 → 0.10.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.
Files changed (127) hide show
  1. package/README.md +277 -140
  2. package/agents/engineering/motion-designer-interactive.md +5 -4
  3. package/agents/engineering/pr-voice-reviewer.md +229 -0
  4. package/agents/engineering/qa-engineer-automation.md +5 -4
  5. package/agents/engineering/qa-engineer-manual.md +5 -4
  6. package/agents/engineering/qa-lead.md +5 -4
  7. package/agents/engineering/security-engineer-appsec.md +5 -4
  8. package/agents/engineering/security-engineer-compliance.md +5 -4
  9. package/agents/engineering/security-qa-engineer.md +5 -4
  10. package/agents/engineering/technical-writer.md +5 -4
  11. package/agents/product-owner.md +152 -0
  12. package/agents/reagent-orchestrator.md +8 -0
  13. package/commands/pm-status.md +230 -0
  14. package/commands/review-pr.md +197 -0
  15. package/dist/cli/commands/catalyze/gap-detector.d.ts.map +1 -1
  16. package/dist/cli/commands/catalyze/gap-detector.js +1 -3
  17. package/dist/cli/commands/catalyze/gap-detector.js.map +1 -1
  18. package/dist/cli/commands/daemon/index.d.ts +5 -0
  19. package/dist/cli/commands/daemon/index.d.ts.map +1 -0
  20. package/dist/cli/commands/daemon/index.js +59 -0
  21. package/dist/cli/commands/daemon/index.js.map +1 -0
  22. package/dist/cli/commands/daemon/restart.d.ts +10 -0
  23. package/dist/cli/commands/daemon/restart.d.ts.map +1 -0
  24. package/dist/cli/commands/daemon/restart.js +20 -0
  25. package/dist/cli/commands/daemon/restart.js.map +1 -0
  26. package/dist/cli/commands/daemon/start.d.ts +2 -0
  27. package/dist/cli/commands/daemon/start.d.ts.map +1 -0
  28. package/dist/cli/commands/daemon/start.js +143 -0
  29. package/dist/cli/commands/daemon/start.js.map +1 -0
  30. package/dist/cli/commands/daemon/status.d.ts +2 -0
  31. package/dist/cli/commands/daemon/status.d.ts.map +1 -0
  32. package/dist/cli/commands/daemon/status.js +90 -0
  33. package/dist/cli/commands/daemon/status.js.map +1 -0
  34. package/dist/cli/commands/daemon/stop.d.ts +2 -0
  35. package/dist/cli/commands/daemon/stop.d.ts.map +1 -0
  36. package/dist/cli/commands/daemon/stop.js +73 -0
  37. package/dist/cli/commands/daemon/stop.js.map +1 -0
  38. package/dist/cli/commands/init/claude-hooks.d.ts +1 -1
  39. package/dist/cli/commands/init/claude-hooks.d.ts.map +1 -1
  40. package/dist/cli/commands/init/claude-hooks.js +10 -4
  41. package/dist/cli/commands/init/claude-hooks.js.map +1 -1
  42. package/dist/cli/commands/init/index.d.ts.map +1 -1
  43. package/dist/cli/commands/init/index.js +5 -1
  44. package/dist/cli/commands/init/index.js.map +1 -1
  45. package/dist/cli/commands/init/policy.d.ts.map +1 -1
  46. package/dist/cli/commands/init/policy.js +21 -0
  47. package/dist/cli/commands/init/policy.js.map +1 -1
  48. package/dist/cli/commands/init/types.d.ts +16 -0
  49. package/dist/cli/commands/init/types.d.ts.map +1 -1
  50. package/dist/cli/index.js +9 -0
  51. package/dist/cli/index.js.map +1 -1
  52. package/dist/config/daemon-loader.d.ts +16 -0
  53. package/dist/config/daemon-loader.d.ts.map +1 -0
  54. package/dist/config/daemon-loader.js +76 -0
  55. package/dist/config/daemon-loader.js.map +1 -0
  56. package/dist/config/gateway-config.d.ts.map +1 -1
  57. package/dist/config/gateway-config.js +6 -0
  58. package/dist/config/gateway-config.js.map +1 -1
  59. package/dist/config/policy-loader.d.ts +27 -0
  60. package/dist/config/policy-loader.d.ts.map +1 -1
  61. package/dist/config/policy-loader.js +103 -10
  62. package/dist/config/policy-loader.js.map +1 -1
  63. package/dist/gateway/circuit-breaker.d.ts +60 -0
  64. package/dist/gateway/circuit-breaker.d.ts.map +1 -0
  65. package/dist/gateway/circuit-breaker.js +104 -0
  66. package/dist/gateway/circuit-breaker.js.map +1 -0
  67. package/dist/gateway/collision-detector.d.ts +31 -0
  68. package/dist/gateway/collision-detector.d.ts.map +1 -0
  69. package/dist/gateway/collision-detector.js +53 -0
  70. package/dist/gateway/collision-detector.js.map +1 -0
  71. package/dist/gateway/middleware/blocked-paths.js +2 -2
  72. package/dist/gateway/middleware/blocked-paths.js.map +1 -1
  73. package/dist/gateway/middleware/circuit-breaker.d.ts +12 -0
  74. package/dist/gateway/middleware/circuit-breaker.d.ts.map +1 -0
  75. package/dist/gateway/middleware/circuit-breaker.js +44 -0
  76. package/dist/gateway/middleware/circuit-breaker.js.map +1 -0
  77. package/dist/gateway/middleware/injection.d.ts +23 -0
  78. package/dist/gateway/middleware/injection.d.ts.map +1 -0
  79. package/dist/gateway/middleware/injection.js +129 -0
  80. package/dist/gateway/middleware/injection.js.map +1 -0
  81. package/dist/gateway/middleware/policy.js +2 -2
  82. package/dist/gateway/middleware/policy.js.map +1 -1
  83. package/dist/gateway/middleware/rate-limit.d.ts +13 -0
  84. package/dist/gateway/middleware/rate-limit.d.ts.map +1 -0
  85. package/dist/gateway/middleware/rate-limit.js +32 -0
  86. package/dist/gateway/middleware/rate-limit.js.map +1 -0
  87. package/dist/gateway/middleware/redact.d.ts.map +1 -1
  88. package/dist/gateway/middleware/redact.js +7 -0
  89. package/dist/gateway/middleware/redact.js.map +1 -1
  90. package/dist/gateway/middleware/result-size-cap.d.ts +14 -0
  91. package/dist/gateway/middleware/result-size-cap.d.ts.map +1 -0
  92. package/dist/gateway/middleware/result-size-cap.js +49 -0
  93. package/dist/gateway/middleware/result-size-cap.js.map +1 -0
  94. package/dist/gateway/native-tools.js +1 -1
  95. package/dist/gateway/native-tools.js.map +1 -1
  96. package/dist/gateway/rate-limiter.d.ts +47 -0
  97. package/dist/gateway/rate-limiter.d.ts.map +1 -0
  98. package/dist/gateway/rate-limiter.js +89 -0
  99. package/dist/gateway/rate-limiter.js.map +1 -0
  100. package/dist/gateway/server.d.ts.map +1 -1
  101. package/dist/gateway/server.js +27 -1
  102. package/dist/gateway/server.js.map +1 -1
  103. package/dist/gateway/tool-proxy.js +1 -1
  104. package/dist/gateway/tool-proxy.js.map +1 -1
  105. package/dist/types/daemon.d.ts +45 -0
  106. package/dist/types/daemon.d.ts.map +1 -0
  107. package/dist/types/daemon.js +2 -0
  108. package/dist/types/daemon.js.map +1 -0
  109. package/dist/types/gateway.d.ts +9 -0
  110. package/dist/types/gateway.d.ts.map +1 -1
  111. package/dist/types/policy.d.ts +1 -0
  112. package/dist/types/policy.d.ts.map +1 -1
  113. package/hooks/_lib/discord.sh +75 -0
  114. package/hooks/blocked-paths-enforcer.sh +0 -1
  115. package/hooks/changeset-security-gate.sh +143 -0
  116. package/hooks/commit-review-gate.sh +12 -4
  117. package/hooks/import-guard.sh +14 -0
  118. package/hooks/network-exfil-guard.sh +20 -2
  119. package/hooks/pr-issue-link-gate.sh +65 -0
  120. package/hooks/push-review-gate.sh +17 -2
  121. package/hooks/rate-limit-guard.sh +26 -2
  122. package/hooks/reagent-notify.sh +65 -0
  123. package/hooks/security-disclosure-gate.sh +146 -0
  124. package/husky/pre-push.sh +84 -0
  125. package/package.json +10 -2
  126. package/profiles/bst-internal.json +12 -2
  127. package/profiles/client-engagement.json +12 -2
@@ -2,7 +2,7 @@
2
2
  # PreToolUse hook: rate-limit-guard.sh
3
3
  # Fires BEFORE every Bash and Write tool call.
4
4
  # Blocks if more than 20 calls to the same tool occur within 60 seconds.
5
- # Uses a log file per tool in /tmp/reagent-rate-limit-{tool}.log.
5
+ # Uses a log file per tool in $HOME/.reagent/rate-limits/{tool}.log.
6
6
  #
7
7
  # Exit codes:
8
8
  # 0 = within rate limit — allow
@@ -36,7 +36,31 @@ fi
36
36
 
37
37
  # Sanitize tool name for use in filename
38
38
  SAFE_TOOL=$(printf '%s' "$TOOL_NAME" | tr '[:upper:]' '[:lower:]' | tr -cd 'a-z0-9-')
39
- LOG_FILE="/tmp/reagent-rate-limit-${SAFE_TOOL}.log"
39
+
40
+ # ── Counter directory: prefer user-owned $HOME/.reagent/rate-limits/ ──────────
41
+ # Storing counters in /tmp is world-writable and allows symlink attacks.
42
+ # Use a user-owned directory with mode 700 instead.
43
+ RATE_LIMIT_DIR="${HOME}/.reagent/rate-limits"
44
+
45
+ if [[ -n "${HOME:-}" ]] && mkdir -p "$RATE_LIMIT_DIR" 2>/dev/null && chmod 700 "$RATE_LIMIT_DIR" 2>/dev/null; then
46
+ LOG_FILE="${RATE_LIMIT_DIR}/${SAFE_TOOL}.log"
47
+ else
48
+ # $HOME not writable — fall back to a session-scoped tmpdir (not /tmp root)
49
+ if [[ -z "${REAGENT_RATE_LIMIT_TMPDIR:-}" ]]; then
50
+ REAGENT_RATE_LIMIT_TMPDIR=$(mktemp -d 2>/dev/null || true)
51
+ export REAGENT_RATE_LIMIT_TMPDIR
52
+ if [[ -n "$REAGENT_RATE_LIMIT_TMPDIR" ]]; then
53
+ printf 'RATE-LIMIT-GUARD WARN: $HOME not writable — using session tmpdir for rate-limit counters: %s\n' \
54
+ "$REAGENT_RATE_LIMIT_TMPDIR" >&2
55
+ fi
56
+ fi
57
+ if [[ -n "${REAGENT_RATE_LIMIT_TMPDIR:-}" ]]; then
58
+ LOG_FILE="${REAGENT_RATE_LIMIT_TMPDIR}/${SAFE_TOOL}.log"
59
+ else
60
+ # Last resort: skip rate limiting rather than failing noisily
61
+ exit 0
62
+ fi
63
+ fi
40
64
 
41
65
  LIMIT=20
42
66
  WINDOW=60 # seconds
@@ -0,0 +1,65 @@
1
+ #!/bin/bash
2
+ # hooks/reagent-notify.sh — post a one-off Discord notification about a repo event
3
+ #
4
+ # Useful for CI steps, post-merge automation, or manual release announcements.
5
+ # Sources the shared discord library so webhook resolution is consistent with
6
+ # the other hooks.
7
+ #
8
+ # Usage: hooks/reagent-notify.sh <event_type> <message>
9
+ # event_type: push | merge | release | alert
10
+ #
11
+ # Event-to-channel routing:
12
+ # push → dev
13
+ # merge → dev
14
+ # release → release
15
+ # alert → alert
16
+ # (anything else) → dev
17
+
18
+ set -uo pipefail
19
+
20
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
21
+
22
+ # shellcheck source=/dev/null
23
+ source "${SCRIPT_DIR}/_lib/discord.sh"
24
+
25
+ EVENT_TYPE="${1:-}"
26
+ MESSAGE="${2:-}"
27
+
28
+ if [ -z "$EVENT_TYPE" ] || [ -z "$MESSAGE" ]; then
29
+ printf 'Usage: %s <event_type> <message>\n' "$(basename "$0")" >&2
30
+ printf ' event_type: push | merge | release | alert\n' >&2
31
+ exit 1
32
+ fi
33
+
34
+ # Route event to the appropriate channel and pick a sensible default color
35
+ channel_type="dev"
36
+ color="blue"
37
+
38
+ case "$EVENT_TYPE" in
39
+ push)
40
+ channel_type="dev"
41
+ color="green"
42
+ ;;
43
+ merge)
44
+ channel_type="dev"
45
+ color="green"
46
+ ;;
47
+ release)
48
+ channel_type="release"
49
+ color="blue"
50
+ ;;
51
+ alert)
52
+ channel_type="alert"
53
+ color="red"
54
+ ;;
55
+ *)
56
+ channel_type="dev"
57
+ color="blue"
58
+ ;;
59
+ esac
60
+
61
+ discord_notify "$channel_type" "$MESSAGE" "$color"
62
+
63
+ # Wait for the background curl before the script exits so the caller gets
64
+ # a clean exit code even in scripted pipelines.
65
+ wait
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env bash
2
+ # security-disclosure-gate.sh — PreToolUse: Bash
3
+ #
4
+ # Intercepts `gh issue create` commands that contain security-sensitive
5
+ # keywords and blocks them. Routing depends on REAGENT_DISCLOSURE_MODE:
6
+ #
7
+ # advisory (default) — redirect to GitHub Security Advisories (private)
8
+ # Use for public OSS repos
9
+ # issues — redirect to gh issue create with security + internal labels
10
+ # Use for permanently private client repos
11
+ # disabled — pass through (not recommended)
12
+ #
13
+ # Set REAGENT_DISCLOSURE_MODE in .reagent/policy.yaml (written to settings.json
14
+ # env by reagent init). Defaults to "advisory" when unset.
15
+ #
16
+ # Triggered by: PreToolUse — Bash tool
17
+
18
+ set -euo pipefail
19
+
20
+ # shellcheck source=_lib/common.sh
21
+ source "$(dirname "$0")/_lib/common.sh"
22
+
23
+ check_halt
24
+
25
+ # Read disclosure mode — default to advisory
26
+ DISCLOSURE_MODE="${REAGENT_DISCLOSURE_MODE:-advisory}"
27
+
28
+ # Disabled mode: pass through entirely
29
+ if [[ "$DISCLOSURE_MODE" == "disabled" ]]; then
30
+ exit 0
31
+ fi
32
+
33
+ INPUT="$(cat)"
34
+ TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // ""')
35
+
36
+ if [[ "$TOOL_NAME" != "Bash" ]]; then
37
+ exit 0
38
+ fi
39
+
40
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
41
+
42
+ # Only intercept gh issue create
43
+ if ! echo "$COMMAND" | grep -qE 'gh\s+issue\s+create'; then
44
+ exit 0
45
+ fi
46
+
47
+ require_jq
48
+
49
+ # Security-sensitive keywords that should not appear in public issues —
50
+ # these terms suggest a vulnerability, exploit path, or bypass technique
51
+ SECURITY_PATTERNS=(
52
+ # Vulnerability classes
53
+ 'bypass'
54
+ 'exploit'
55
+ 'injection'
56
+ 'traversal'
57
+ 'exfiltrat'
58
+ 'escalat'
59
+ 'privilege'
60
+ 'rce'
61
+ 'remote.code.exec'
62
+ 'arbitrary.code'
63
+ 'code.execution'
64
+ 'zero.day'
65
+ '0day'
66
+ 'CVE-'
67
+ 'CVSS'
68
+ 'GHSA-'
69
+ # Reagent-specific sensitive terms
70
+ 'hook.bypass'
71
+ 'HALT.bypass'
72
+ 'redaction.bypass'
73
+ 'policy.bypass'
74
+ 'middleware.bypass'
75
+ 'skip.*gate'
76
+ 'evad'
77
+ # Credential/secret exposure
78
+ 'secret.*leak'
79
+ 'credential.*leak'
80
+ 'token.*leak'
81
+ 'key.*expos'
82
+ 'expos.*secret'
83
+ # Prompt injection
84
+ 'prompt.inject'
85
+ 'jailbreak'
86
+ 'jail.break'
87
+ )
88
+
89
+ # Scan the full command text (title + body + flags) for sensitive patterns
90
+ FULL_TEXT=$(echo "$COMMAND" | tr '[:upper:]' '[:lower:]')
91
+
92
+ MATCHED_PATTERN=""
93
+ for PATTERN in "${SECURITY_PATTERNS[@]}"; do
94
+ if echo "$FULL_TEXT" | grep -qiE "$PATTERN"; then
95
+ MATCHED_PATTERN="$PATTERN"
96
+ break
97
+ fi
98
+ done
99
+
100
+ if [[ -z "$MATCHED_PATTERN" ]]; then
101
+ exit 0
102
+ fi
103
+
104
+ # ─── Route based on disclosure mode ──────────────────────────────────────────
105
+
106
+ if [[ "$DISCLOSURE_MODE" == "issues" ]]; then
107
+ # Private repo mode: redirect to labeled internal issue
108
+ json_output "block" \
109
+ "SECURITY DISCLOSURE GATE: This issue appears to describe a security finding (matched: '${MATCHED_PATTERN}').
110
+
111
+ This project is configured for PRIVATE disclosure (REAGENT_DISCLOSURE_MODE=issues).
112
+
113
+ CORRECT PATH for security findings in this private repo:
114
+ Use: gh issue create --label 'security,internal' --title '...' --body '...'
115
+
116
+ The 'security' and 'internal' labels keep this off public project boards and
117
+ mark it for maintainer-only triage. Do NOT use the public issue queue without
118
+ these labels for security findings.
119
+
120
+ If this is NOT a security finding, rephrase the title/body to avoid triggering
121
+ security patterns, then retry."
122
+
123
+ else
124
+ # Advisory mode (default): redirect to GitHub Security Advisories
125
+ json_output "block" \
126
+ "SECURITY DISCLOSURE GATE: This issue appears to describe a security vulnerability (matched: '${MATCHED_PATTERN}'). Do NOT create a public GitHub issue for security vulnerabilities.
127
+
128
+ CORRECT DISCLOSURE PATH:
129
+ 1. Use GitHub Security Advisories (private):
130
+ gh api repos/{owner}/{repo}/security-advisories --method POST --input - <<'JSON'
131
+ { \"summary\": \"...\", \"description\": \"...\", \"severity\": \"medium|high|critical\",
132
+ \"vulnerabilities\": [{\"package\": {\"name\": \"@pkg\", \"ecosystem\": \"npm\"}}] }
133
+ JSON
134
+ 2. Or navigate to: Security tab → Advisories → 'Report a vulnerability'
135
+ 3. Or email security@bookedsolid.tech (see SECURITY.md)
136
+
137
+ The finding will be publicly disclosed AFTER a patch is released (coordinated disclosure).
138
+
139
+ WHY: Public issues expose vulnerabilities before users can patch. This is enforced by the
140
+ security-disclosure-gate hook (REAGENT_DISCLOSURE_MODE=${DISCLOSURE_MODE}).
141
+
142
+ If this is NOT a security vulnerability, rephrase the issue to avoid triggering
143
+ security patterns, then retry."
144
+ fi
145
+
146
+ exit 2
package/husky/pre-push.sh CHANGED
@@ -64,12 +64,96 @@ run_gate "type-check" "TypeScript type check"
64
64
  run_gate "test" "Test suite"
65
65
  run_gate "build" "Build"
66
66
 
67
+ # Pack dry-run — validates the publish payload matches what CI would produce
68
+ # Always uses npm pack --dry-run regardless of $PKG_MANAGER: pnpm uses a
69
+ # different flag syntax and this gate mirrors the npm pack --dry-run step in CI.
70
+ if script_exists "build"; then
71
+ echo "pre-push: running Pack dry-run..."
72
+ if ! npm pack --dry-run > "$OUT" 2>&1; then
73
+ echo ""
74
+ echo "GATE FAILED: Pack dry-run"
75
+ cat "$OUT"
76
+ echo ""
77
+ FAILED="${FAILED} pack"
78
+ fi
79
+ fi
80
+
81
+ # Shellcheck — lint all hook and husky shell scripts if shellcheck is installed
82
+ if command -v shellcheck > /dev/null 2>&1; then
83
+ echo "pre-push: running Shellcheck on hook scripts..."
84
+ SHELL_SCRIPTS=$(find hooks/ husky/ -name "*.sh" 2>/dev/null | tr '\n' ' ')
85
+ if [ -n "$SHELL_SCRIPTS" ]; then
86
+ # shellcheck disable=SC2086
87
+ if ! shellcheck --shell=bash --severity=warning --exclude=SC1091,SC2034 $SHELL_SCRIPTS > "$OUT" 2>&1; then
88
+ echo ""
89
+ echo "GATE FAILED: Shellcheck"
90
+ cat "$OUT"
91
+ echo ""
92
+ FAILED="${FAILED} shellcheck"
93
+ fi
94
+ fi
95
+ else
96
+ echo "pre-push: shellcheck not installed — hook lint skipped (install: brew install shellcheck)"
97
+ fi
98
+
99
+ # ── Optional: coverage threshold gate ─────────────────────────────────────────
100
+ # Enabled via .reagent/policy.yaml:
101
+ # coverage:
102
+ # enabled: true
103
+ # threshold: 80 # line/function/statement coverage percentage (branches: threshold - 10)
104
+ #
105
+ # Only runs if coverage.enabled is true AND the project has a test script.
106
+ POLICY_FILE=".reagent/policy.yaml"
107
+ COVERAGE_ENABLED="false"
108
+ COVERAGE_THRESHOLD=80
109
+
110
+ if [ -f "$POLICY_FILE" ]; then
111
+ # Extract coverage.enabled — look for "enabled: true" within the coverage block
112
+ if awk '/^coverage:/{in_block=1} in_block && /enabled: true/{found=1; exit} in_block && /^[^ ]/{in_block=0}' "$POLICY_FILE" | grep -q "enabled: true" 2>/dev/null || \
113
+ grep -A5 "^coverage:" "$POLICY_FILE" 2>/dev/null | grep -q "enabled: true"; then
114
+ COVERAGE_ENABLED="true"
115
+ fi
116
+
117
+ # Extract coverage.threshold (default 80)
118
+ # The || true prevents set -euo pipefail from exiting when coverage: block is absent
119
+ THRESHOLD_LINE=$(grep -A5 "^coverage:" "$POLICY_FILE" 2>/dev/null | grep "threshold:" | head -1) || true
120
+ if [ -n "$THRESHOLD_LINE" ]; then
121
+ EXTRACTED=$(echo "$THRESHOLD_LINE" | awk '{print $2}' | tr -d '"' | tr -d "'")
122
+ if [ -n "$EXTRACTED" ] && [ "$EXTRACTED" -eq "$EXTRACTED" ] 2>/dev/null; then
123
+ COVERAGE_THRESHOLD="$EXTRACTED"
124
+ fi
125
+ fi
126
+ fi
127
+
128
+ if [ "$COVERAGE_ENABLED" = "true" ] && script_exists "test"; then
129
+ echo "pre-push: running Coverage threshold (≥${COVERAGE_THRESHOLD}%)..."
130
+ if ! COVERAGE_THRESHOLD="$COVERAGE_THRESHOLD" $PKG_MANAGER run test -- --coverage > "$OUT" 2>&1; then
131
+ echo ""
132
+ echo "GATE FAILED: Coverage threshold (${COVERAGE_THRESHOLD}%)"
133
+ cat "$OUT"
134
+ echo ""
135
+ FAILED="${FAILED} coverage"
136
+ fi
137
+ fi
138
+
67
139
  # ── Report ────────────────────────────────────────────────────────────────────
140
+ HOOKS_LIB="$(git rev-parse --show-toplevel 2>/dev/null)/hooks/_lib/discord.sh"
141
+
68
142
  if [ -n "$FAILED" ]; then
69
143
  echo "pre-push: FAILED gates:${FAILED}"
70
144
  echo "All quality gates must pass before push. Fix failures and retry."
145
+ if [ -f "$HOOKS_LIB" ]; then
146
+ # shellcheck source=/dev/null
147
+ source "$HOOKS_LIB"
148
+ discord_notify "alert" "Push BLOCKED -- gate failures: \`${FAILED}\` on \`$(git rev-parse --abbrev-ref HEAD 2>/dev/null)\`" "red"
149
+ fi
71
150
  exit 1
72
151
  fi
73
152
 
74
153
  echo "pre-push: all quality gates passed"
154
+ if [ -f "$HOOKS_LIB" ]; then
155
+ # shellcheck source=/dev/null
156
+ source "$HOOKS_LIB"
157
+ discord_notify "dev" "Pre-push gates passed on \`$(git rev-parse --abbrev-ref HEAD 2>/dev/null)\`" "green"
158
+ fi
75
159
  exit 0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bookedsolid/reagent",
3
- "version": "0.7.1",
3
+ "version": "0.10.0",
4
4
  "description": "Zero-trust MCP gateway — policy enforcement, secret redaction, and audit logging for AI-assisted projects",
5
5
  "license": "MIT",
6
6
  "author": "Booked Solid Technology <oss@bookedsolid.tech> (https://bookedsolid.tech)",
@@ -52,12 +52,19 @@
52
52
  "changeset": "changeset",
53
53
  "changeset:version": "changeset version",
54
54
  "changeset:publish": "changeset publish",
55
+ "daemon:start": "reagent daemon start",
56
+ "daemon:stop": "reagent daemon stop",
57
+ "daemon:status": "reagent daemon status",
58
+ "daemon:restart": "reagent daemon restart",
59
+ "daemon:build": "cargo build --release --manifest-path daemon/Cargo.toml",
55
60
  "lint": "eslint .",
56
61
  "format": "prettier --write .",
57
62
  "format:check": "prettier --check .",
58
63
  "test": "vitest run",
59
64
  "test:watch": "vitest",
60
- "type-check": "tsc --noEmit"
65
+ "type-check": "tsc --noEmit",
66
+ "docs:dev": "cd docs && npm run dev",
67
+ "docs:build": "cd docs && npm run build"
61
68
  },
62
69
  "keywords": [
63
70
  "claude",
@@ -78,6 +85,7 @@
78
85
  "@types/node": "^25.5.2",
79
86
  "@typescript-eslint/eslint-plugin": "^8.0.0",
80
87
  "@typescript-eslint/parser": "^8.0.0",
88
+ "@vitest/coverage-v8": "^3.2.4",
81
89
  "eslint": "^10.2.0",
82
90
  "husky": "^9.1.7",
83
91
  "prettier": "^3.8.1",
@@ -18,6 +18,9 @@
18
18
  "preflightCmd": "pnpm preflight",
19
19
  "attributionRule": "Do NOT include AI attribution in commits, PR bodies, code comments, or any content. When block_ai_attribution is enabled in .reagent/policy.yaml, the commit-msg hook REJECTS commits containing structural AI attribution (Co-Authored-By with AI names, 'Generated with [Tool]' footers, etc.). The attribution-advisory hook also blocks gh pr create/edit and git commit commands with attribution. You must remove all attribution markers before committing — the hooks will NOT silently fix them."
20
20
  },
21
+ "security": {
22
+ "disclosureMode": "advisory"
23
+ },
21
24
  "claudeHooks": {
22
25
  "PreToolUse": [
23
26
  {
@@ -27,12 +30,19 @@
27
30
  "env-file-protection",
28
31
  "dependency-audit-gate",
29
32
  "commit-review-gate",
30
- "push-review-gate"
33
+ "push-review-gate",
34
+ "security-disclosure-gate",
35
+ "pr-issue-link-gate"
31
36
  ]
32
37
  },
33
38
  {
34
39
  "matcher": "Write|Edit",
35
- "hooks": ["secret-scanner", "settings-protection", "blocked-paths-enforcer"]
40
+ "hooks": [
41
+ "secret-scanner",
42
+ "settings-protection",
43
+ "blocked-paths-enforcer",
44
+ "changeset-security-gate"
45
+ ]
36
46
  },
37
47
  {
38
48
  "matcher": "Bash",
@@ -18,6 +18,9 @@
18
18
  "preflightCmd": "pnpm preflight",
19
19
  "attributionRule": "Do NOT include AI attribution in commits, PR bodies, code comments, or any content. When block_ai_attribution is enabled in .reagent/policy.yaml, the commit-msg hook REJECTS commits containing structural AI attribution (Co-Authored-By with AI names, 'Generated with [Tool]' footers, etc.). The attribution-advisory hook also blocks gh pr create/edit and git commit commands with attribution. You must remove all attribution markers before committing — the hooks will NOT silently fix them."
20
20
  },
21
+ "security": {
22
+ "disclosureMode": "issues"
23
+ },
21
24
  "claudeHooks": {
22
25
  "PreToolUse": [
23
26
  {
@@ -27,12 +30,19 @@
27
30
  "env-file-protection",
28
31
  "dependency-audit-gate",
29
32
  "commit-review-gate",
30
- "push-review-gate"
33
+ "push-review-gate",
34
+ "security-disclosure-gate",
35
+ "pr-issue-link-gate"
31
36
  ]
32
37
  },
33
38
  {
34
39
  "matcher": "Write|Edit",
35
- "hooks": ["secret-scanner", "settings-protection", "blocked-paths-enforcer"]
40
+ "hooks": [
41
+ "secret-scanner",
42
+ "settings-protection",
43
+ "blocked-paths-enforcer",
44
+ "changeset-security-gate"
45
+ ]
36
46
  },
37
47
  {
38
48
  "matcher": "Bash",