@garethdaine/agentops 0.9.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.
- package/.claude-plugin/plugin.json +10 -0
- package/LICENSE +21 -0
- package/README.md +410 -0
- package/agents/architecture-researcher.md +115 -0
- package/agents/code-critic.md +190 -0
- package/agents/delegation-router.md +40 -0
- package/agents/feature-researcher.md +117 -0
- package/agents/interrogator.md +11 -0
- package/agents/pitfalls-researcher.md +112 -0
- package/agents/plan-validator.md +173 -0
- package/agents/proposer.md +61 -0
- package/agents/security-reviewer.md +189 -0
- package/agents/skill-builder.md +43 -0
- package/agents/spec-compliance-reviewer.md +154 -0
- package/agents/stack-researcher.md +89 -0
- package/commands/build.md +766 -0
- package/commands/code-analysis.md +39 -0
- package/commands/code-field.md +22 -0
- package/commands/compliance-check.md +34 -0
- package/commands/configure.md +178 -0
- package/commands/cost-report.md +17 -0
- package/commands/enterprise/adr.md +78 -0
- package/commands/enterprise/brainstorm.md +461 -0
- package/commands/enterprise/design.md +203 -0
- package/commands/enterprise/dev-setup.md +136 -0
- package/commands/enterprise/docker-dev.md +229 -0
- package/commands/enterprise/e2e.md +233 -0
- package/commands/enterprise/feature.md +218 -0
- package/commands/enterprise/gap-analysis.md +204 -0
- package/commands/enterprise/handover.md +195 -0
- package/commands/enterprise/herd.md +152 -0
- package/commands/enterprise/knowledge.md +173 -0
- package/commands/enterprise/onboard.md +86 -0
- package/commands/enterprise/qa-check.md +80 -0
- package/commands/enterprise/reason.md +196 -0
- package/commands/enterprise/review.md +177 -0
- package/commands/enterprise/scaffold.md +153 -0
- package/commands/enterprise/status-report.md +101 -0
- package/commands/enterprise/tech-catalog.md +170 -0
- package/commands/enterprise/test-gen.md +138 -0
- package/commands/evolve.md +39 -0
- package/commands/flags.md +44 -0
- package/commands/interrogate.md +263 -0
- package/commands/lesson.md +15 -0
- package/commands/lessons.md +10 -0
- package/commands/plan.md +44 -0
- package/commands/prune.md +27 -0
- package/commands/star.md +17 -0
- package/commands/supply-chain-scan.md +44 -0
- package/commands/unicode-scan.md +63 -0
- package/commands/verify.md +41 -0
- package/commands/workflow.md +436 -0
- package/hooks/ai-guardrails.sh +114 -0
- package/hooks/audit-log.sh +26 -0
- package/hooks/auto-delegate.sh +45 -0
- package/hooks/auto-evolve.sh +22 -0
- package/hooks/auto-lesson.sh +26 -0
- package/hooks/auto-plan.sh +59 -0
- package/hooks/auto-test.sh +46 -0
- package/hooks/auto-verify.sh +30 -0
- package/hooks/budget-check.sh +24 -0
- package/hooks/code-field-preamble.sh +30 -0
- package/hooks/compliance-gate.sh +50 -0
- package/hooks/content-trust.sh +22 -0
- package/hooks/credential-redact.sh +23 -0
- package/hooks/delegation-trust.sh +15 -0
- package/hooks/detect-test-run.sh +19 -0
- package/hooks/enforcement-lib.sh +60 -0
- package/hooks/evolve-gate.sh +32 -0
- package/hooks/evolve-lib.sh +32 -0
- package/hooks/exfiltration-check.sh +67 -0
- package/hooks/failure-collector.sh +27 -0
- package/hooks/feature-flags.sh +67 -0
- package/hooks/file-provenance.sh +31 -0
- package/hooks/flag-utils.sh +36 -0
- package/hooks/hooks.json +145 -0
- package/hooks/injection-scan.sh +58 -0
- package/hooks/integrity-verify.sh +91 -0
- package/hooks/lessons-check.sh +17 -0
- package/hooks/lockfile-audit.sh +109 -0
- package/hooks/patterns-lib.sh +22 -0
- package/hooks/plan-gate.sh +18 -0
- package/hooks/redact-lib.sh +15 -0
- package/hooks/runtime-mode.sh +56 -0
- package/hooks/session-cleanup.sh +74 -0
- package/hooks/skill-validator.sh +28 -0
- package/hooks/standards-enforce.sh +106 -0
- package/hooks/star-gate.sh +93 -0
- package/hooks/star-preamble.sh +10 -0
- package/hooks/telemetry.sh +33 -0
- package/hooks/todo-prune.sh +84 -0
- package/hooks/unicode-firewall.sh +122 -0
- package/hooks/unicode-lib.sh +66 -0
- package/hooks/unicode-scan-session.sh +96 -0
- package/hooks/validate-command.sh +103 -0
- package/hooks/validate-env.sh +51 -0
- package/hooks/validate-path.sh +81 -0
- package/package.json +40 -0
- package/settings.json +6 -0
- package/templates/ai-config/tool-standards.md +56 -0
- package/templates/architecture/api-first.md +192 -0
- package/templates/architecture/auth-patterns.md +302 -0
- package/templates/architecture/caching-strategy.md +359 -0
- package/templates/architecture/database-patterns.md +347 -0
- package/templates/architecture/event-driven.md +252 -0
- package/templates/architecture/integration-patterns.md +185 -0
- package/templates/architecture/multi-tenancy.md +104 -0
- package/templates/architecture/service-boundaries.md +200 -0
- package/templates/build/brief-template.md +86 -0
- package/templates/build/summary-template.md +100 -0
- package/templates/build/task-plan-template.md +133 -0
- package/templates/communication/effort-estimate.md +54 -0
- package/templates/communication/incident-response.md +59 -0
- package/templates/communication/post-mortem.md +109 -0
- package/templates/communication/risk-register.md +43 -0
- package/templates/communication/sprint-demo-checklist.md +64 -0
- package/templates/communication/stakeholder-presentation-outline.md +84 -0
- package/templates/communication/technical-proposal.md +77 -0
- package/templates/delivery/deployment/deployment-checklist.md +49 -0
- package/templates/delivery/design/solution-design-checklist.md +37 -0
- package/templates/delivery/discovery/stakeholder-questions.md +33 -0
- package/templates/delivery/handover/knowledge-transfer-checklist.md +75 -0
- package/templates/delivery/handover/operational-runbook.md +117 -0
- package/templates/delivery/handover/support-escalation-matrix.md +56 -0
- package/templates/delivery/implementation/blocker-escalation-template.md +55 -0
- package/templates/delivery/implementation/sprint-planning-template.md +49 -0
- package/templates/delivery/implementation/task-decomposition-guide.md +59 -0
- package/templates/delivery/qa/test-plan-template.md +76 -0
- package/templates/delivery/qa/test-results-template.md +55 -0
- package/templates/delivery/qa/uat-signoff-template.md +44 -0
- package/templates/governance/codeowners.md +60 -0
- package/templates/integration/adapter-pattern.md +160 -0
- package/templates/scaffolds/env-validation.md +85 -0
- package/templates/scaffolds/error-handling.md +171 -0
- package/templates/scaffolds/graceful-shutdown.md +139 -0
- package/templates/scaffolds/health-check.md +109 -0
- package/templates/scaffolds/structured-logging.md +134 -0
- package/templates/standards/engineering-standards.md +413 -0
- package/templates/standards/standards-checklist.md +125 -0
- package/templates/tech-catalog.json +663 -0
- package/templates/utilities/project-detection.md +75 -0
- package/templates/utilities/requirements-collection.md +68 -0
- package/templates/utilities/template-rendering.md +81 -0
- package/templates/workflows/architecture-decision.md +90 -0
- package/templates/workflows/bug-investigation.md +83 -0
- package/templates/workflows/feature-implementation.md +80 -0
- package/templates/workflows/refactoring.md +83 -0
- package/templates/workflows/spike-exploration.md +82 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Shared Unicode detection library — single source of truth for Glassworm/Trojan Source defense.
|
|
3
|
+
# Sourced by: unicode-firewall.sh, unicode-scan-session.sh, lockfile-audit.sh
|
|
4
|
+
|
|
5
|
+
# Dangerous invisible Unicode character ranges:
|
|
6
|
+
# Cat 1: Zero-width / invisible U+200B-200F, U+2060-2064, U+FEFF
|
|
7
|
+
# Cat 2: Bidi overrides U+202A-202E, U+2066-2069
|
|
8
|
+
# Cat 3: Variation selectors U+FE00-FE0F
|
|
9
|
+
# Cat 4: Tag characters U+E0001-E007F
|
|
10
|
+
# Cat 5: Variation sel. supp. U+E0100-E01EF
|
|
11
|
+
UNICODE_PATTERN='[\x{200B}-\x{200F}\x{2060}-\x{2064}\x{FEFF}\x{202A}-\x{202E}\x{2066}-\x{2069}\x{FE00}-\x{FE0F}\x{E0001}-\x{E007F}\x{E0100}-\x{E01EF}]'
|
|
12
|
+
|
|
13
|
+
# Returns 0 (match) if dangerous invisible Unicode is found in stdin.
|
|
14
|
+
unicode_detect() {
|
|
15
|
+
perl -CSD -ne "if (/$UNICODE_PATTERN/) { exit 0 } END { exit 1 }" 2>/dev/null
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
# Returns 0 (match) if dangerous invisible Unicode is found in a file.
|
|
19
|
+
unicode_detect_file() {
|
|
20
|
+
local FILE="$1"
|
|
21
|
+
perl -CSD -ne "if (/$UNICODE_PATTERN/) { exit 0 } END { exit 1 }" "$FILE" 2>/dev/null
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
# Returns human-readable category summary from stdin.
|
|
25
|
+
unicode_classify() {
|
|
26
|
+
perl -CSD -ne '
|
|
27
|
+
BEGIN { %c = () }
|
|
28
|
+
$c{"zero-width chars"}++ if /[\x{200B}-\x{200F}\x{2060}-\x{2064}\x{FEFF}]/;
|
|
29
|
+
$c{"bidi overrides"}++ if /[\x{202A}-\x{202E}\x{2066}-\x{2069}]/;
|
|
30
|
+
$c{"variation selectors"}++ if /[\x{FE00}-\x{FE0F}]/;
|
|
31
|
+
$c{"tag characters"}++ if /[\x{E0001}-\x{E007F}]/;
|
|
32
|
+
$c{"variation sel. supplement"}++ if /[\x{E0100}-\x{E01EF}]/;
|
|
33
|
+
END { print join(", ", sort keys %c) if %c }
|
|
34
|
+
' 2>/dev/null
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
# Returns human-readable category summary from a file.
|
|
38
|
+
unicode_classify_file() {
|
|
39
|
+
local FILE="$1"
|
|
40
|
+
perl -CSD -ne '
|
|
41
|
+
BEGIN { %c = () }
|
|
42
|
+
$c{"zero-width chars"}++ if /[\x{200B}-\x{200F}\x{2060}-\x{2064}\x{FEFF}]/;
|
|
43
|
+
$c{"bidi overrides"}++ if /[\x{202A}-\x{202E}\x{2066}-\x{2069}]/;
|
|
44
|
+
$c{"variation selectors"}++ if /[\x{FE00}-\x{FE0F}]/;
|
|
45
|
+
$c{"tag characters"}++ if /[\x{E0001}-\x{E007F}]/;
|
|
46
|
+
$c{"variation sel. supplement"}++ if /[\x{E0100}-\x{E01EF}]/;
|
|
47
|
+
END { print join(", ", sort keys %c) if %c }
|
|
48
|
+
' "$FILE" 2>/dev/null
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# Count affected lines from stdin.
|
|
52
|
+
unicode_count_lines() {
|
|
53
|
+
perl -CSD -ne "print if /$UNICODE_PATTERN/" 2>/dev/null | wc -l | tr -d ' '
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
# Count affected lines in a file.
|
|
57
|
+
unicode_count_lines_file() {
|
|
58
|
+
local FILE="$1"
|
|
59
|
+
perl -CSD -ne "print if /$UNICODE_PATTERN/" "$FILE" 2>/dev/null | wc -l | tr -d ' '
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
# Strip dangerous Unicode from a file in-place.
|
|
63
|
+
unicode_strip_file() {
|
|
64
|
+
local FILE="$1"
|
|
65
|
+
perl -CSD -pi -e "s/$UNICODE_PATTERN//g" "$FILE" 2>/dev/null
|
|
66
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -uo pipefail
|
|
3
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
4
|
+
source "${SCRIPT_DIR}/feature-flags.sh"
|
|
5
|
+
|
|
6
|
+
[ "$(agentops_flag 'unicode_firewall_enabled')" = "false" ] && exit 0
|
|
7
|
+
|
|
8
|
+
source "${SCRIPT_DIR}/unicode-lib.sh"
|
|
9
|
+
|
|
10
|
+
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-.}"
|
|
11
|
+
CACHE_DIR="${PROJECT_DIR}/.agentops"
|
|
12
|
+
CACHE_FILE="${CACHE_DIR}/unicode-scan-cache"
|
|
13
|
+
|
|
14
|
+
# Skip scan if cache exists and no files have been modified since last scan
|
|
15
|
+
if [ -f "$CACHE_FILE" ]; then
|
|
16
|
+
NEWER_FILES=$(find "$PROJECT_DIR" \
|
|
17
|
+
-type f \
|
|
18
|
+
\( -name '*.js' -o -name '*.ts' -o -name '*.tsx' -o -name '*.jsx' \
|
|
19
|
+
-o -name '*.py' -o -name '*.rb' -o -name '*.go' -o -name '*.rs' \
|
|
20
|
+
-o -name '*.java' -o -name '*.php' -o -name '*.sh' -o -name '*.json' \
|
|
21
|
+
-o -name '*.yaml' -o -name '*.yml' -o -name '*.md' -o -name '*.env' \) \
|
|
22
|
+
-not -path '*/.git/*' \
|
|
23
|
+
-not -path '*/node_modules/*' \
|
|
24
|
+
-not -path '*/vendor/*' \
|
|
25
|
+
-not -path '*/.agentops/*' \
|
|
26
|
+
-newer "$CACHE_FILE" \
|
|
27
|
+
-print -quit 2>/dev/null)
|
|
28
|
+
if [ -z "$NEWER_FILES" ]; then
|
|
29
|
+
# No files modified since last scan — use cached result
|
|
30
|
+
CACHED_MSG=$(cat "$CACHE_FILE" 2>/dev/null)
|
|
31
|
+
[ -n "$CACHED_MSG" ] && echo "$CACHED_MSG"
|
|
32
|
+
exit 0
|
|
33
|
+
fi
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# Scan project directory for files containing dangerous invisible Unicode.
|
|
37
|
+
# Skips: .git, node_modules, vendor, .agentops, binary files, lock files.
|
|
38
|
+
RESULTS=$(find "$PROJECT_DIR" \
|
|
39
|
+
-type f \
|
|
40
|
+
\( -name '*.js' -o -name '*.ts' -o -name '*.tsx' -o -name '*.jsx' \
|
|
41
|
+
-o -name '*.py' -o -name '*.rb' -o -name '*.go' -o -name '*.rs' \
|
|
42
|
+
-o -name '*.java' -o -name '*.php' -o -name '*.c' -o -name '*.cpp' \
|
|
43
|
+
-o -name '*.h' -o -name '*.hpp' -o -name '*.cs' -o -name '*.swift' \
|
|
44
|
+
-o -name '*.kt' -o -name '*.scala' -o -name '*.sh' -o -name '*.bash' \
|
|
45
|
+
-o -name '*.vue' -o -name '*.svelte' -o -name '*.json' -o -name '*.yaml' \
|
|
46
|
+
-o -name '*.yml' -o -name '*.toml' -o -name '*.xml' -o -name '*.md' \
|
|
47
|
+
-o -name '*.txt' -o -name '*.html' -o -name '*.css' -o -name '*.scss' \
|
|
48
|
+
-o -name '*.env' -o -name '*.env.*' -o -name 'Makefile' -o -name 'Dockerfile' \
|
|
49
|
+
-o -name '*.cfg' -o -name '*.ini' -o -name '*.conf' \) \
|
|
50
|
+
-not -path '*/.git/*' \
|
|
51
|
+
-not -path '*/node_modules/*' \
|
|
52
|
+
-not -path '*/vendor/*' \
|
|
53
|
+
-not -path '*/.agentops/*' \
|
|
54
|
+
-not -path '*/dist/*' \
|
|
55
|
+
-not -path '*/build/*' \
|
|
56
|
+
-not -path '*/*.min.js' \
|
|
57
|
+
-not -path '*/*.min.css' \
|
|
58
|
+
-not -name 'package-lock.json' \
|
|
59
|
+
-not -name 'yarn.lock' \
|
|
60
|
+
-not -name 'pnpm-lock.yaml' \
|
|
61
|
+
-not -name 'composer.lock' \
|
|
62
|
+
-not -name 'Cargo.lock' \
|
|
63
|
+
-not -name 'Gemfile.lock' \
|
|
64
|
+
-print0 2>/dev/null | \
|
|
65
|
+
xargs -0 perl -CSD -lne "
|
|
66
|
+
if (/$UNICODE_PATTERN/) {
|
|
67
|
+
print \$ARGV;
|
|
68
|
+
close ARGV; # skip to next file after first match
|
|
69
|
+
}
|
|
70
|
+
" 2>/dev/null | sort -u)
|
|
71
|
+
|
|
72
|
+
if [ -n "$RESULTS" ]; then
|
|
73
|
+
FILE_COUNT=$(echo "$RESULTS" | wc -l | tr -d ' ')
|
|
74
|
+
|
|
75
|
+
# Build a truncated file list (max 10 files shown)
|
|
76
|
+
FILE_LIST=$(echo "$RESULTS" | head -10 | sed "s|^$PROJECT_DIR/||")
|
|
77
|
+
[ "$FILE_COUNT" -gt 10 ] && FILE_LIST="${FILE_LIST}
|
|
78
|
+
... and $((FILE_COUNT - 10)) more"
|
|
79
|
+
|
|
80
|
+
# Audit log
|
|
81
|
+
LOG_DIR="${PROJECT_DIR}/.agentops"
|
|
82
|
+
mkdir -p "$LOG_DIR" 2>/dev/null
|
|
83
|
+
jq -nc --arg ts "$(date -u +%FT%TZ)" --arg count "$FILE_COUNT" \
|
|
84
|
+
'{ts:$ts, event:"UNICODE_SESSION_SCAN", files_flagged:($count|tonumber)}' >> "$LOG_DIR/audit.jsonl" 2>/dev/null
|
|
85
|
+
|
|
86
|
+
OUTPUT=$(jq -nc --arg count "$FILE_COUNT" --arg files "$FILE_LIST" \
|
|
87
|
+
'{systemMessage:("UNICODE FIREWALL — SESSION SCAN: Found " + $count + " file(s) containing dangerous invisible Unicode characters (zero-width, bidi overrides, variation selectors, or tag characters). These may indicate a Glassworm/Trojan Source supply-chain compromise.\n\nAffected files:\n" + $files + "\n\nRun /agentops:unicode-scan to get a detailed analysis and clean these files.")}')
|
|
88
|
+
echo "$OUTPUT"
|
|
89
|
+
mkdir -p "$CACHE_DIR" 2>/dev/null
|
|
90
|
+
echo "$OUTPUT" > "$CACHE_FILE" 2>/dev/null
|
|
91
|
+
else
|
|
92
|
+
OUTPUT=$(jq -nc '{systemMessage:"Unicode firewall: session scan clean — no dangerous invisible characters detected in project files."}')
|
|
93
|
+
echo "$OUTPUT"
|
|
94
|
+
mkdir -p "$CACHE_DIR" 2>/dev/null
|
|
95
|
+
echo "$OUTPUT" > "$CACHE_FILE" 2>/dev/null
|
|
96
|
+
fi
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -uo pipefail
|
|
3
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
4
|
+
source "${SCRIPT_DIR}/feature-flags.sh"
|
|
5
|
+
|
|
6
|
+
[ "$(agentops_flag 'command_validation_enabled')" = "false" ] && exit 0
|
|
7
|
+
|
|
8
|
+
INPUT=$(cat) || exit 0
|
|
9
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null) || agentops_fail_closed
|
|
10
|
+
[ -z "$COMMAND" ] && exit 0
|
|
11
|
+
|
|
12
|
+
# Hard-deny rules execute BEFORE bypass check — they always enforce.
|
|
13
|
+
HARD_DENY=$(agentops_hard_deny)
|
|
14
|
+
|
|
15
|
+
# 1. Destructive system commands (always deny, even in bypass/unrestricted)
|
|
16
|
+
if echo "$COMMAND" | grep -qE "(rm\s+-rf\s+/[^t]|mkfs\s|dd\s+if=|shutdown|reboot|init\s+[06])"; then
|
|
17
|
+
jq -nc --arg action "$HARD_DENY" \
|
|
18
|
+
'{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:$action,permissionDecisionReason:"Destructive system command blocked by AgentOps CommandPolicy (hard deny)"}}'
|
|
19
|
+
exit 0
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
# 2. Indirect execution of destructive commands (always deny)
|
|
23
|
+
if echo "$COMMAND" | grep -qE "(eval\s|bash\s+-c|sh\s+-c|exec\s)" && echo "$COMMAND" | grep -qiE "(rm\s+-rf|chmod\s+777|curl.*\|.*sh|wget.*\|.*bash|mkfs|dd\s+if=)"; then
|
|
24
|
+
jq -nc --arg action "$HARD_DENY" \
|
|
25
|
+
'{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:$action,permissionDecisionReason:"Indirect execution of dangerous command blocked by AgentOps CommandPolicy (hard deny)"}}'
|
|
26
|
+
exit 0
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# 3. Fork bomb / resource exhaustion (always deny)
|
|
30
|
+
if echo "$COMMAND" | grep -qE ':\(\)\{|:\(\)\s*\{|\(\)\s*\{.*\|.*:\s*;'; then
|
|
31
|
+
jq -nc --arg action "$HARD_DENY" \
|
|
32
|
+
'{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:$action,permissionDecisionReason:"Fork bomb pattern detected (hard deny)"}}'
|
|
33
|
+
exit 0
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# 4. Tampering with .agentops/ state files via Bash (always deny)
|
|
37
|
+
# Covers: writes, deletions, permission changes, symlink replacement
|
|
38
|
+
# Exception: AGENTOPS_WRITABLE_STATE paths (e.g. flags.json) are whitelisted
|
|
39
|
+
if echo "$COMMAND" | grep -qE '>\s*[^ ]*\.agentops/' \
|
|
40
|
+
|| echo "$COMMAND" | grep -qE '(tee|cp|mv|install)\s+[^ ]*\s+[^ ]*\.agentops/' \
|
|
41
|
+
|| echo "$COMMAND" | grep -qE '(tee|cp|mv|install)\s+[^ ]*\.agentops/' \
|
|
42
|
+
|| echo "$COMMAND" | grep -qE 'sed\s+-i[^ ]*\s+[^ ]*\.agentops/' \
|
|
43
|
+
|| echo "$COMMAND" | grep -qE 'dd\s+of=[^ ]*\.agentops/' \
|
|
44
|
+
|| echo "$COMMAND" | grep -qE '(rm|unlink|shred|truncate)\s+[^ ]*\.agentops/' \
|
|
45
|
+
|| echo "$COMMAND" | grep -qE '(chmod|chown)\s+[^ ]*\s+[^ ]*\.agentops/' \
|
|
46
|
+
|| echo "$COMMAND" | grep -qE '(ln)\s+[^ ]*\s+[^ ]*\.agentops/'; then
|
|
47
|
+
if ! echo "$COMMAND" | grep -qE "$AGENTOPS_WRITABLE_STATE"; then
|
|
48
|
+
jq -nc --arg action "$HARD_DENY" \
|
|
49
|
+
'{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:$action,permissionDecisionReason:"Tampering with .agentops/ state files via Bash is blocked by AgentOps CommandPolicy (hard deny)"}}'
|
|
50
|
+
exit 0
|
|
51
|
+
fi
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
# 4b. Tampering with hooks/ directory via Bash (always deny — prevent hook tampering)
|
|
55
|
+
if echo "$COMMAND" | grep -qE '>\s*[^ ]*hooks/' \
|
|
56
|
+
|| echo "$COMMAND" | grep -qE '(tee|cp|mv|install)\s+[^ ]*\s+[^ ]*hooks/' \
|
|
57
|
+
|| echo "$COMMAND" | grep -qE 'sed\s+-i[^ ]*\s+[^ ]*hooks/' \
|
|
58
|
+
|| echo "$COMMAND" | grep -qE '(rm|unlink|shred|truncate)\s+[^ ]*hooks/' \
|
|
59
|
+
|| echo "$COMMAND" | grep -qE '(chmod|chown)\s+[^ ]*\s+[^ ]*hooks/' \
|
|
60
|
+
|| echo "$COMMAND" | grep -qE '(ln)\s+[^ ]*\s+[^ ]*hooks/'; then
|
|
61
|
+
jq -nc --arg action "$HARD_DENY" \
|
|
62
|
+
'{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:$action,permissionDecisionReason:"Tampering with hooks/ directory via Bash is blocked by AgentOps CommandPolicy (hard deny)"}}'
|
|
63
|
+
exit 0
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
# Soft rules below — bypass/unrestricted can downgrade these
|
|
67
|
+
agentops_is_bypass "$INPUT" && agentops_bypass_advisory "validate-command"
|
|
68
|
+
ACTION=$(agentops_enforcement_action)
|
|
69
|
+
|
|
70
|
+
# 5. Shell injection + dangerous pattern combo
|
|
71
|
+
if echo "$COMMAND" | grep -qE '\|\||&&' && echo "$COMMAND" | grep -qiE "(rm\s+-rf|chmod\s+777|curl.*\|.*sh|wget.*\|.*bash)"; then
|
|
72
|
+
jq -nc --arg action "$ACTION" \
|
|
73
|
+
'{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:$action,permissionDecisionReason:"Shell injection risk: chained operators with dangerous command"}}'
|
|
74
|
+
exit 0
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# 6. Pipe-to-shell without chaining operators
|
|
78
|
+
if echo "$COMMAND" | grep -qE "(curl|wget)\s.*\|\s*(bash|sh|zsh|dash)\b"; then
|
|
79
|
+
jq -nc --arg action "$ACTION" \
|
|
80
|
+
'{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:$action,permissionDecisionReason:"Pipe-to-shell pattern detected"}}'
|
|
81
|
+
exit 0
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
# 7. Credential file access
|
|
85
|
+
if echo "$COMMAND" | grep -qiE "(/etc/shadow|/etc/passwd|\.ssh/id_|\.env\b|\.pem\b)" && echo "$COMMAND" | grep -qE "(cat|less|head|more|tail|grep|jq|python|ruby|node|base64|xxd)\s"; then
|
|
86
|
+
jq -nc --arg action "$ACTION" \
|
|
87
|
+
'{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:$action,permissionDecisionReason:"Credential/sensitive file access detected"}}'
|
|
88
|
+
exit 0
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
# 8. Bash accessing system directories (HS-1 — path validation for Bash tool)
|
|
92
|
+
if echo "$COMMAND" | grep -qE "^/(etc|proc|sys|dev|boot|root|sbin)(/|\s)" || echo "$COMMAND" | grep -qE "\s/(etc|proc|sys|dev|boot|root|sbin)(/|\s)"; then
|
|
93
|
+
jq -nc --arg action "$ACTION" \
|
|
94
|
+
'{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:$action,permissionDecisionReason:"Bash command references system directory — review before proceeding"}}'
|
|
95
|
+
exit 0
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
# 9. Bash accessing sensitive dotfiles (HS-1)
|
|
99
|
+
if echo "$COMMAND" | grep -qE "/\.(ssh|gnupg|aws|docker/config\.json|kube/config|npmrc|pypirc|netrc|git-credentials)"; then
|
|
100
|
+
jq -nc --arg action "$ACTION" \
|
|
101
|
+
'{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:$action,permissionDecisionReason:"Bash command references sensitive dotfile/directory"}}'
|
|
102
|
+
exit 0
|
|
103
|
+
fi
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -uo pipefail
|
|
3
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
4
|
+
source "${SCRIPT_DIR}/feature-flags.sh"
|
|
5
|
+
|
|
6
|
+
[ "$(agentops_flag 'env_validation_enabled')" = "false" ] && exit 0
|
|
7
|
+
|
|
8
|
+
INPUT=$(cat) || exit 0
|
|
9
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null) || agentops_fail_closed
|
|
10
|
+
[ -z "$COMMAND" ] && exit 0
|
|
11
|
+
|
|
12
|
+
# Only check commands that set env vars (case-insensitive to catch export path=, Ld_Preload=, etc.)
|
|
13
|
+
echo "$COMMAND" | grep -qiE "(export\s+|^[A-Za-z_]+=)" || exit 0
|
|
14
|
+
|
|
15
|
+
VARS=$(echo "$COMMAND" | grep -oiE '\b[A-Za-z_][A-Za-z0-9_]*=' | sed 's/=$//' 2>/dev/null) || exit 0
|
|
16
|
+
|
|
17
|
+
# --- Hard-deny rules (always enforce, even in bypass mode) ---
|
|
18
|
+
HARD_DENY=$(agentops_hard_deny)
|
|
19
|
+
|
|
20
|
+
for VAR in $VARS; do
|
|
21
|
+
# Normalize to uppercase for comparison
|
|
22
|
+
VAR_UPPER=$(echo "$VAR" | tr '[:lower:]' '[:upper:]')
|
|
23
|
+
|
|
24
|
+
# Forbidden keys — LD_PRELOAD, PATH, HOME etc. are always dangerous
|
|
25
|
+
if echo "$VAR_UPPER" | grep -qE "^(PATH|HOME|SHELL|USER|LD_PRELOAD|LD_LIBRARY_PATH|DYLD_)"; then
|
|
26
|
+
jq -nc --arg var "$VAR" --arg action "$HARD_DENY" \
|
|
27
|
+
'{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:$action,permissionDecisionReason:("EnvPolicy: forbidden env var " + $var + " (hard deny)")}}'
|
|
28
|
+
exit 0
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# DB credentials — always deny
|
|
32
|
+
if echo "$VAR_UPPER" | grep -qE "^(DB_|TEST_DB_|REDIS_|MYSQL_|POSTGRES_)"; then
|
|
33
|
+
jq -nc --arg var "$VAR" --arg action "$HARD_DENY" \
|
|
34
|
+
'{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:$action,permissionDecisionReason:("EnvPolicy: database credential var " + $var + " (hard deny)")}}'
|
|
35
|
+
exit 0
|
|
36
|
+
fi
|
|
37
|
+
done
|
|
38
|
+
|
|
39
|
+
# --- Soft rules (bypass can skip these) ---
|
|
40
|
+
agentops_is_bypass "$INPUT" && agentops_bypass_advisory "validate-env"
|
|
41
|
+
ACTION=$(agentops_enforcement_action)
|
|
42
|
+
|
|
43
|
+
for VAR in $VARS; do
|
|
44
|
+
VAR_UPPER=$(echo "$VAR" | tr '[:lower:]' '[:upper:]')
|
|
45
|
+
# Secret patterns
|
|
46
|
+
if echo "$VAR_UPPER" | grep -qE "(SECRET|TOKEN|PASSWORD|PASS|PRIVATE|CREDENTIAL|API_KEY|AUTH)"; then
|
|
47
|
+
jq -nc --arg var "$VAR" --arg action "$ACTION" \
|
|
48
|
+
'{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:$action,permissionDecisionReason:("EnvPolicy: var matches secret pattern (" + $var + ")")}}'
|
|
49
|
+
exit 0
|
|
50
|
+
fi
|
|
51
|
+
done
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -uo pipefail
|
|
3
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
4
|
+
source "${SCRIPT_DIR}/feature-flags.sh"
|
|
5
|
+
|
|
6
|
+
[ "$(agentops_flag 'path_validation_enabled')" = "false" ] && exit 0
|
|
7
|
+
|
|
8
|
+
INPUT=$(cat) || exit 0
|
|
9
|
+
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null) || agentops_fail_closed
|
|
10
|
+
|
|
11
|
+
# Extract path based on tool
|
|
12
|
+
case "$TOOL" in
|
|
13
|
+
Read|Write|Edit) FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null) ;;
|
|
14
|
+
Glob|Grep) FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.path // empty' 2>/dev/null) ;;
|
|
15
|
+
*) exit 0 ;;
|
|
16
|
+
esac
|
|
17
|
+
|
|
18
|
+
[ -z "$FILE_PATH" ] && exit 0
|
|
19
|
+
|
|
20
|
+
# --- Hard-deny rules (always enforce, even in bypass mode) ---
|
|
21
|
+
|
|
22
|
+
# 1. Must be absolute
|
|
23
|
+
if [[ "$FILE_PATH" != /* ]]; then
|
|
24
|
+
jq -nc --arg fp "$FILE_PATH" \
|
|
25
|
+
'{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:("PathPolicy: path must be absolute (got: " + $fp + ")")}}'
|
|
26
|
+
exit 0
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# 2. Path traversal
|
|
30
|
+
if echo "$FILE_PATH" | grep -qE '\.\.(/|$)'; then
|
|
31
|
+
jq -nc '{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:"PathPolicy: path traversal (..) blocked"}}'
|
|
32
|
+
exit 0
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# 3. Length limit (1024 chars)
|
|
36
|
+
if [ ${#FILE_PATH} -gt 1024 ]; then
|
|
37
|
+
jq -nc '{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:"PathPolicy: path exceeds 1024 character limit"}}'
|
|
38
|
+
exit 0
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# Canonicalize for symlink resolution (for Write/Edit, resolve existing paths)
|
|
42
|
+
CANONICAL="$FILE_PATH"
|
|
43
|
+
if [ "$TOOL" = "Write" ] || [ "$TOOL" = "Edit" ]; then
|
|
44
|
+
PARENT_DIR=$(dirname "$FILE_PATH")
|
|
45
|
+
if [ -d "$PARENT_DIR" ]; then
|
|
46
|
+
RESOLVED=$(realpath -m "$FILE_PATH" 2>/dev/null) || RESOLVED="$FILE_PATH"
|
|
47
|
+
CANONICAL="$RESOLVED"
|
|
48
|
+
fi
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# 4. Protect plugin state files from agent writes (hard deny)
|
|
52
|
+
# Exception: AGENTOPS_WRITABLE_STATE paths (e.g. flags.json) are whitelisted
|
|
53
|
+
if [ "$TOOL" = "Write" ] || [ "$TOOL" = "Edit" ]; then
|
|
54
|
+
if echo "$CANONICAL" | grep -qE "$AGENTOPS_PROTECTED_PATHS"; then
|
|
55
|
+
if ! echo "$CANONICAL" | grep -qE "$AGENTOPS_WRITABLE_STATE"; then
|
|
56
|
+
jq -nc --arg fp "$CANONICAL" \
|
|
57
|
+
'{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:("PathPolicy: protected AgentOps state file (" + $fp + ")")}}'
|
|
58
|
+
exit 0
|
|
59
|
+
fi
|
|
60
|
+
fi
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
# --- Soft rules (bypass/unrestricted can downgrade) ---
|
|
64
|
+
agentops_is_bypass "$INPUT" && agentops_bypass_advisory "validate-path"
|
|
65
|
+
ACTION=$(agentops_enforcement_action)
|
|
66
|
+
|
|
67
|
+
# 5. System directory confinement (check both raw and canonical)
|
|
68
|
+
for CHECK_PATH in "$FILE_PATH" "$CANONICAL"; do
|
|
69
|
+
if echo "$CHECK_PATH" | grep -qE "^/(etc|proc|sys|dev|boot|root|sbin)(/|$)"; then
|
|
70
|
+
jq -nc --arg fp "$CHECK_PATH" --arg action "$ACTION" \
|
|
71
|
+
'{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:$action,permissionDecisionReason:("PathPolicy: access to system directory blocked (" + $fp + ")")}}'
|
|
72
|
+
exit 0
|
|
73
|
+
fi
|
|
74
|
+
done
|
|
75
|
+
|
|
76
|
+
# 6. Sensitive dotfiles
|
|
77
|
+
if echo "$CANONICAL" | grep -qE "/\.(ssh|gnupg|aws|docker/config\.json|kube/config)"; then
|
|
78
|
+
jq -nc --arg fp "$CANONICAL" --arg action "$ACTION" \
|
|
79
|
+
'{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:$action,permissionDecisionReason:("PathPolicy: sensitive dotfile/directory access (" + $fp + ")")}}'
|
|
80
|
+
exit 0
|
|
81
|
+
fi
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@garethdaine/agentops",
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "Enterprise guardrails, delivery lifecycle, and self-evolution for Claude Code CLI",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Gareth Daine",
|
|
7
|
+
"email": "1745959+garethdaine@users.noreply.github.com"
|
|
8
|
+
},
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/garethdaine/agentops.git"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/garethdaine/agentops",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/garethdaine/agentops/issues"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"claude-code",
|
|
20
|
+
"claude-code-plugin",
|
|
21
|
+
"guardrails",
|
|
22
|
+
"security",
|
|
23
|
+
"tdd",
|
|
24
|
+
"delivery",
|
|
25
|
+
"enterprise",
|
|
26
|
+
"ai-agent",
|
|
27
|
+
"compliance",
|
|
28
|
+
"audit"
|
|
29
|
+
],
|
|
30
|
+
"files": [
|
|
31
|
+
".claude-plugin/",
|
|
32
|
+
"agents/",
|
|
33
|
+
"commands/",
|
|
34
|
+
"hooks/",
|
|
35
|
+
"templates/",
|
|
36
|
+
"settings.json",
|
|
37
|
+
"LICENSE",
|
|
38
|
+
"README.md"
|
|
39
|
+
]
|
|
40
|
+
}
|
package/settings.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Shared AI Configuration: Tool Standards
|
|
2
|
+
|
|
3
|
+
## Approved AI Tools by Task
|
|
4
|
+
|
|
5
|
+
| Task | Primary Tool | Alternative | Notes |
|
|
6
|
+
|------|-------------|-------------|-------|
|
|
7
|
+
| Architecture decisions | Claude (Opus) | — | Needs deep reasoning |
|
|
8
|
+
| Feature implementation | Claude Code | Cursor | Structured workflow via /agentops:feature |
|
|
9
|
+
| Code review | Claude Code | — | Via /agentops:review |
|
|
10
|
+
| Bug investigation | Claude Code | — | Via bug-investigation workflow |
|
|
11
|
+
| Documentation | Claude (Sonnet) | — | Fast, high-quality prose |
|
|
12
|
+
| Test generation | Claude Code | — | Via /agentops:test-gen |
|
|
13
|
+
| Refactoring | Claude Code | Cursor | Via refactoring workflow |
|
|
14
|
+
|
|
15
|
+
## AI Output Quality Standards
|
|
16
|
+
|
|
17
|
+
### Code Quality
|
|
18
|
+
- Generated code must pass TypeScript strict mode
|
|
19
|
+
- No `any` types unless explicitly justified
|
|
20
|
+
- All functions must handle error cases
|
|
21
|
+
- No placeholder values (TODO, FIXME, example.com)
|
|
22
|
+
- Follows existing project patterns and conventions
|
|
23
|
+
|
|
24
|
+
### Documentation Quality
|
|
25
|
+
- Clear, concise, professional tone
|
|
26
|
+
- No hallucinated links or references
|
|
27
|
+
- All code examples must be syntactically correct
|
|
28
|
+
- Technical accuracy verified against codebase
|
|
29
|
+
|
|
30
|
+
### Review Quality
|
|
31
|
+
- All findings must reference specific file:line locations
|
|
32
|
+
- Fix suggestions must be concrete and implementable
|
|
33
|
+
- Severity ratings must be justified
|
|
34
|
+
- No false positives from pattern matching
|
|
35
|
+
|
|
36
|
+
## Model Selection Guide
|
|
37
|
+
|
|
38
|
+
| Consideration | Use Opus/Large | Use Sonnet/Medium | Use Haiku/Small |
|
|
39
|
+
|---------------|---------------|-------------------|-----------------|
|
|
40
|
+
| Architecture | Yes | — | — |
|
|
41
|
+
| Complex features | Yes | — | — |
|
|
42
|
+
| Simple features | — | Yes | — |
|
|
43
|
+
| Code review | Yes | Yes | — |
|
|
44
|
+
| Documentation | — | Yes | — |
|
|
45
|
+
| Quick questions | — | — | Yes |
|
|
46
|
+
| Content filtering | — | — | Yes |
|
|
47
|
+
|
|
48
|
+
## Prompt Library Index
|
|
49
|
+
|
|
50
|
+
| Category | Template | Location |
|
|
51
|
+
|----------|----------|----------|
|
|
52
|
+
| Feature build | feature-implementation.md | templates/workflows/ |
|
|
53
|
+
| Bug fix | bug-investigation.md | templates/workflows/ |
|
|
54
|
+
| Refactoring | refactoring.md | templates/workflows/ |
|
|
55
|
+
| Architecture | architecture-decision.md | templates/workflows/ |
|
|
56
|
+
| Spike | spike-exploration.md | templates/workflows/ |
|