oh-my-customcode 0.36.1 → 0.37.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 (63) hide show
  1. package/dist/cli/index.js +47 -2
  2. package/dist/index.js +44 -0
  3. package/package.json +1 -1
  4. package/templates/.claude/agents/arch-documenter.md +4 -1
  5. package/templates/.claude/agents/arch-speckit-agent.md +15 -0
  6. package/templates/.claude/agents/be-django-expert.md +1 -0
  7. package/templates/.claude/agents/be-express-expert.md +1 -0
  8. package/templates/.claude/agents/be-fastapi-expert.md +1 -0
  9. package/templates/.claude/agents/be-go-backend-expert.md +1 -0
  10. package/templates/.claude/agents/be-nestjs-expert.md +1 -0
  11. package/templates/.claude/agents/be-springboot-expert.md +1 -0
  12. package/templates/.claude/agents/db-postgres-expert.md +1 -0
  13. package/templates/.claude/agents/db-redis-expert.md +1 -0
  14. package/templates/.claude/agents/db-supabase-expert.md +1 -0
  15. package/templates/.claude/agents/de-airflow-expert.md +1 -0
  16. package/templates/.claude/agents/de-dbt-expert.md +1 -0
  17. package/templates/.claude/agents/de-kafka-expert.md +1 -0
  18. package/templates/.claude/agents/de-pipeline-expert.md +1 -0
  19. package/templates/.claude/agents/de-snowflake-expert.md +1 -0
  20. package/templates/.claude/agents/de-spark-expert.md +1 -0
  21. package/templates/.claude/agents/fe-flutter-agent.md +1 -0
  22. package/templates/.claude/agents/fe-svelte-agent.md +1 -0
  23. package/templates/.claude/agents/fe-vercel-agent.md +1 -0
  24. package/templates/.claude/agents/fe-vuejs-agent.md +1 -0
  25. package/templates/.claude/agents/infra-aws-expert.md +1 -0
  26. package/templates/.claude/agents/infra-docker-expert.md +1 -0
  27. package/templates/.claude/agents/lang-golang-expert.md +1 -0
  28. package/templates/.claude/agents/lang-java21-expert.md +3 -0
  29. package/templates/.claude/agents/lang-kotlin-expert.md +1 -0
  30. package/templates/.claude/agents/lang-python-expert.md +1 -0
  31. package/templates/.claude/agents/lang-rust-expert.md +1 -0
  32. package/templates/.claude/agents/lang-typescript-expert.md +1 -0
  33. package/templates/.claude/agents/mgr-claude-code-bible.md +1 -2
  34. package/templates/.claude/agents/mgr-creator.md +1 -0
  35. package/templates/.claude/agents/mgr-gitnerd.md +1 -0
  36. package/templates/.claude/agents/mgr-sauron.md +5 -2
  37. package/templates/.claude/agents/mgr-supplier.md +1 -3
  38. package/templates/.claude/agents/mgr-updater.md +1 -0
  39. package/templates/.claude/agents/qa-engineer.md +1 -0
  40. package/templates/.claude/agents/qa-planner.md +4 -1
  41. package/templates/.claude/agents/qa-writer.md +1 -1
  42. package/templates/.claude/agents/sec-codeql-expert.md +4 -2
  43. package/templates/.claude/agents/sys-memory-keeper.md +30 -0
  44. package/templates/.claude/agents/sys-naggy.md +36 -2
  45. package/templates/.claude/agents/tool-bun-expert.md +1 -1
  46. package/templates/.claude/agents/tool-npm-expert.md +1 -1
  47. package/templates/.claude/agents/tool-optimizer.md +1 -2
  48. package/templates/.claude/hooks/hooks.json +37 -7
  49. package/templates/.claude/hooks/scripts/agent-teams-advisor.sh +10 -0
  50. package/templates/.claude/hooks/scripts/audit-log.sh +55 -0
  51. package/templates/.claude/hooks/scripts/content-hash-validator.sh +2 -3
  52. package/templates/.claude/hooks/scripts/schema-validator.sh +103 -0
  53. package/templates/.claude/hooks/scripts/secret-filter.sh +97 -0
  54. package/templates/.claude/hooks/scripts/session-compliance-report.sh +65 -0
  55. package/templates/.claude/rules/MUST-agent-teams.md +0 -23
  56. package/templates/.claude/rules/MUST-orchestrator-coordination.md +1 -13
  57. package/templates/.claude/skills/django-best-practices/SKILL.md +27 -134
  58. package/templates/.claude/skills/flutter-best-practices/SKILL.md +39 -146
  59. package/templates/.claude/skills/go-backend-best-practices/SKILL.md +29 -233
  60. package/templates/.claude/skills/java21-best-practices/SKILL.md +48 -163
  61. package/templates/CLAUDE.md.en +7 -65
  62. package/templates/CLAUDE.md.ko +7 -65
  63. package/templates/manifest.json +1 -1
@@ -2,6 +2,7 @@
2
2
  name: sys-naggy
3
3
  description: Use when you need TODO list management and task tracking with proactive reminders, helping maintain project momentum by monitoring stale tasks and deadlines
4
4
  model: sonnet
5
+ domain: universal
5
6
  memory: local
6
7
  effort: low
7
8
  tools:
@@ -9,8 +10,6 @@ tools:
9
10
  - Write
10
11
  - Edit
11
12
  - Grep
12
- - Glob
13
- - Bash
14
13
  ---
15
14
 
16
15
  You are a task management specialist that proactively manages TODO items and reminds users of pending tasks.
@@ -31,6 +30,41 @@ You are a task management specialist that proactively manages TODO items and rem
31
30
  | `sys-naggy:done <id>` | Mark complete |
32
31
  | `sys-naggy:remind` | Show overdue tasks |
33
32
 
33
+ ## Rule Pattern Detection
34
+
35
+ When sys-naggy detects recurring violations (3+ occurrences of the same rule ID across sessions), it proposes a rule patch:
36
+
37
+ ### Detection Flow
38
+
39
+ 1. Read violation history from native memory (`MEMORY.md` violations section)
40
+ 2. Cross-reference with session compliance data (PPID-scoped `/tmp/.claude-session-compliance-*`)
41
+ 3. Identify rules with 3+ violations across different sessions
42
+ 4. Generate rule patch proposal as GitHub issue
43
+
44
+ ### Proposal Format
45
+
46
+ ```
47
+ Title: [R016 Auto-Patch] R0XX: {weakness description}
48
+ Body:
49
+ ## Violation Pattern
50
+ - Rule: R0XX ({rule name})
51
+ - Occurrences: {count} across {session_count} sessions
52
+ - Common trigger: {pattern description}
53
+
54
+ ## Proposed Fix
55
+ {specific change to the rule file}
56
+
57
+ ## Rationale
58
+ {why the current rule is insufficient}
59
+ ```
60
+
61
+ ### Constraints
62
+
63
+ - sys-naggy proposes patches as GitHub issues — never auto-applies
64
+ - Minimum 3 occurrences before proposing (avoids noise)
65
+ - Maximum 1 proposal per rule per week (debounce)
66
+ - Proposals require human approval before implementation
67
+
34
68
  ## Behavior
35
69
 
36
70
  Proactive but not annoying. Adapt reminder frequency to user response.
@@ -2,6 +2,7 @@
2
2
  name: tool-bun-expert
3
3
  description: Use for Bun runtime development, bunfig.toml configuration, Bun test runner, fast bundling, and Node.js to Bun migrations
4
4
  model: sonnet
5
+ domain: universal
5
6
  memory: project
6
7
  effort: medium
7
8
  tools:
@@ -9,7 +10,6 @@ tools:
9
10
  - Write
10
11
  - Edit
11
12
  - Grep
12
- - Glob
13
13
  - Bash
14
14
  ---
15
15
 
@@ -2,6 +2,7 @@
2
2
  name: tool-npm-expert
3
3
  description: Use for npm package publishing workflows, semantic versioning (major/minor/patch), package.json optimization, and dependency audits
4
4
  model: sonnet
5
+ domain: universal
5
6
  memory: project
6
7
  effort: medium
7
8
  skills:
@@ -13,7 +14,6 @@ tools:
13
14
  - Write
14
15
  - Edit
15
16
  - Grep
16
- - Glob
17
17
  - Bash
18
18
  ---
19
19
 
@@ -2,6 +2,7 @@
2
2
  name: tool-optimizer
3
3
  description: Use for bundle size analysis, tree-shaking verification, performance profiling, dead code detection, and build optimization recommendations
4
4
  model: sonnet
5
+ domain: universal
5
6
  memory: project
6
7
  effort: medium
7
8
  skills:
@@ -10,8 +11,6 @@ skills:
10
11
  - optimize-report
11
12
  tools:
12
13
  - Read
13
- - Write
14
- - Edit
15
14
  - Grep
16
15
  - Glob
17
16
  - Bash
@@ -72,6 +72,16 @@
72
72
  ],
73
73
  "description": "Validate file content hash before Edit — advisory staleness warning"
74
74
  },
75
+ {
76
+ "matcher": "tool == \"Write\" || tool == \"Edit\" || tool == \"Bash\"",
77
+ "hooks": [
78
+ {
79
+ "type": "command",
80
+ "command": "bash .claude/hooks/scripts/schema-validator.sh"
81
+ }
82
+ ],
83
+ "description": "Schema-based tool input validation — Phase 1 advisory only"
84
+ },
75
85
  {
76
86
  "matcher": "tool == \"Task\" || tool == \"Agent\"",
77
87
  "hooks": [
@@ -222,6 +232,26 @@
222
232
  ],
223
233
  "description": "Context budget advisor — track tool usage patterns and advise ecomode activation"
224
234
  },
235
+ {
236
+ "matcher": "tool == \"Edit\" || tool == \"Write\" || tool == \"Bash\" || tool == \"Task\" || tool == \"Agent\"",
237
+ "hooks": [
238
+ {
239
+ "type": "command",
240
+ "command": "bash .claude/hooks/scripts/stuck-detector.sh"
241
+ }
242
+ ],
243
+ "description": "Detect repetitive failure loops and advise recovery strategies"
244
+ },
245
+ {
246
+ "matcher": "tool == \"Edit\" || tool == \"Write\" || tool == \"Bash\" || tool == \"Task\" || tool == \"Agent\"",
247
+ "hooks": [
248
+ {
249
+ "type": "command",
250
+ "command": "bash .claude/hooks/scripts/cost-cap-advisor.sh"
251
+ }
252
+ ],
253
+ "description": "Advisory cost cap monitoring — warn when session cost approaches configurable limit"
254
+ },
225
255
  {
226
256
  "matcher": "tool == \"Read\"",
227
257
  "hooks": [
@@ -233,24 +263,24 @@
233
263
  "description": "Store content hashes for Read operations — enables Edit staleness detection"
234
264
  },
235
265
  {
236
- "matcher": "tool == \"Edit\" || tool == \"Write\" || tool == \"Bash\" || tool == \"Task\" || tool == \"Agent\"",
266
+ "matcher": "tool == \"Bash\" || tool == \"Read\" || tool == \"Grep\"",
237
267
  "hooks": [
238
268
  {
239
269
  "type": "command",
240
- "command": "bash .claude/hooks/scripts/stuck-detector.sh"
270
+ "command": "bash .claude/hooks/scripts/secret-filter.sh"
241
271
  }
242
272
  ],
243
- "description": "Detect repetitive failure loops and advise recovery strategies"
273
+ "description": "Detect potential secrets in Bash/Read/Grep output advisory warning only"
244
274
  },
245
275
  {
246
- "matcher": "tool == \"Edit\" || tool == \"Write\" || tool == \"Bash\" || tool == \"Task\" || tool == \"Agent\"",
276
+ "matcher": "tool == \"Edit\" || tool == \"Write\" || tool == \"Bash\" || tool == \"Agent\"",
247
277
  "hooks": [
248
278
  {
249
279
  "type": "command",
250
- "command": "bash .claude/hooks/scripts/cost-cap-advisor.sh"
280
+ "command": "bash .claude/hooks/scripts/audit-log.sh"
251
281
  }
252
282
  ],
253
- "description": "Advisory cost cap monitoring warn when session cost approaches configurable limit"
283
+ "description": "Append-only audit log for state-changing tool operations"
254
284
  }
255
285
  ],
256
286
  "Stop": [
@@ -269,7 +299,7 @@
269
299
  "hooks": [
270
300
  {
271
301
  "type": "prompt",
272
- "prompt": "Session-end memory checkpoint (R011 enforcement). Check conversation history for these 3 steps: 1) sys-memory-keeper was delegated to update MEMORY.md 2) claude-mem save was attempted via ToolSearch + mcp__plugin_claude-mem_mcp-search__save_memory 3) episodic-memory verification was attempted via ToolSearch + mcp__plugin_episodic-memory_episodic-memory__search. Decision rules: If ALL 3 were attempted (success or failure both count): approve. If MCP tools are unavailable after ToolSearch attempt: approve with note. If session had no explicit session-end signal from user (quick question, no memory work): approve. If any step was NOT attempted despite user signaling session end: block with systemMessage listing the missing steps."
302
+ "prompt": "Session-end memory checkpoint (R011 enforcement). Check conversation history for these 2 steps: 1) sys-memory-keeper was delegated to update MEMORY.md 2) claude-mem save was attempted via ToolSearch + mcp__plugin_claude-mem_mcp-search__save_memory. Note: episodic-memory auto-indexes after session no manual verification needed. Decision rules: If BOTH were attempted (success or failure both count): approve. If MCP tools are unavailable after ToolSearch attempt: approve with note. If session had no explicit session-end signal from user (quick question, no memory work): approve. If any step was NOT attempted despite user signaling session end: block with systemMessage listing the missing steps."
273
303
  }
274
304
  ],
275
305
  "description": "Enforce R011 session-end memory saves — block stop if claude-mem or episodic-memory saves were skipped"
@@ -8,6 +8,16 @@ set -euo pipefail
8
8
 
9
9
  input=$(cat)
10
10
 
11
+ # Skip if Agent Teams is not available
12
+ ENV_STATUS="/tmp/.claude-env-status-${PPID}"
13
+ if [ -f "$ENV_STATUS" ]; then
14
+ teams_status=$(grep "agent_teams=" "$ENV_STATUS" 2>/dev/null | cut -d= -f2 || echo "unknown")
15
+ if [ "$teams_status" != "enabled" ]; then
16
+ echo "$input"
17
+ exit 0
18
+ fi
19
+ fi
20
+
11
21
  # Extract task info from input
12
22
  agent_type=$(echo "$input" | jq -r '.tool_input.subagent_type // "unknown"')
13
23
  prompt_preview=$(echo "$input" | jq -r '.tool_input.description // ""' | head -c 60)
@@ -0,0 +1,55 @@
1
+ #!/bin/bash
2
+ # Audit Log Hook — Append-only JSONL persistence
3
+ # Trigger: PostToolUse on Edit, Write, Bash, Agent
4
+ # Purpose: Persistent audit trail for security and compliance
5
+ # Protocol: stdin JSON -> log entry -> stdout pass-through
6
+ # Always exits 0 (advisory only)
7
+
8
+ set -euo pipefail
9
+
10
+ input=$(cat)
11
+
12
+ # Extract fields from hook input
13
+ tool_name=$(echo "$input" | jq -r '.tool_name // "unknown"')
14
+ file_path=$(echo "$input" | jq -r '.tool_input.file_path // .tool_input.command // ""' | head -c 200)
15
+ agent_type=$(echo "$input" | jq -r '.agent_type // "unknown"')
16
+ model=$(echo "$input" | jq -r '.model // "unknown"')
17
+ is_error=$(echo "$input" | jq -r '.tool_output.is_error // false')
18
+ timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)
19
+
20
+ # Determine outcome
21
+ if [ "$is_error" = "true" ]; then
22
+ outcome="error"
23
+ else
24
+ outcome="success"
25
+ fi
26
+
27
+ # Audit log location
28
+ AUDIT_LOG="${HOME}/.claude/audit.jsonl"
29
+
30
+ # Ensure directory exists
31
+ mkdir -p "$(dirname "$AUDIT_LOG")"
32
+
33
+ # Write audit entry (append-only JSONL)
34
+ jq -cn \
35
+ --arg ts "$timestamp" \
36
+ --arg tool "$tool_name" \
37
+ --arg path "$file_path" \
38
+ --arg agent "$agent_type" \
39
+ --arg model "$model" \
40
+ --arg outcome "$outcome" \
41
+ --arg ppid "${PPID}" \
42
+ '{timestamp: $ts, tool: $tool, path: $path, agent_type: $agent, model: $model, outcome: $outcome, session_ppid: $ppid}' \
43
+ >> "$AUDIT_LOG" 2>/dev/null || true
44
+
45
+ # Daily rotation check (rotate if > 10MB)
46
+ if [ -f "$AUDIT_LOG" ]; then
47
+ file_size=$(stat -f%z "$AUDIT_LOG" 2>/dev/null || stat -c%s "$AUDIT_LOG" 2>/dev/null || echo "0")
48
+ if [ "$file_size" -gt 10485760 ]; then
49
+ mv "$AUDIT_LOG" "${AUDIT_LOG}.$(date -u +%Y%m%d%H%M%S)" 2>/dev/null || true
50
+ fi
51
+ fi
52
+
53
+ # Pass through
54
+ echo "$input"
55
+ exit 0
@@ -18,10 +18,9 @@ case "$tool_name" in
18
18
  "Read")
19
19
  # Store content hash for the file that was just read
20
20
  file_path=$(echo "$input" | jq -r '.tool_input.file_path // ""')
21
- output=$(echo "$input" | jq -r '.tool_output.output // ""')
22
21
 
23
- if [ -n "$file_path" ] && [ -n "$output" ] && [ "$output" != "null" ]; then
24
- content_hash=$(echo "$output" | md5 2>/dev/null || echo "$output" | md5sum 2>/dev/null | cut -d' ' -f1 || echo "unknown")
22
+ if [ -n "$file_path" ] && [ -f "$file_path" ]; then
23
+ content_hash=$(md5 -q "$file_path" 2>/dev/null || md5sum "$file_path" 2>/dev/null | cut -d' ' -f1 || echo "unknown")
25
24
  timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)
26
25
 
27
26
  # Store hash entry (overwrite previous for same file)
@@ -0,0 +1,103 @@
1
+ #!/bin/bash
2
+ # Schema Validator Hook — PreToolUse input validation
3
+ # Trigger: PreToolUse on Write, Edit, Bash
4
+ # Purpose: Validate tool inputs against JSON Schema definitions
5
+ # Phase 1: Advisory only (exit 0 with stderr warning)
6
+ # Protocol: stdin JSON -> validate -> stdout pass-through
7
+
8
+ set -euo pipefail
9
+
10
+ input=$(cat)
11
+
12
+ # Extract tool info
13
+ tool_name=$(echo "$input" | jq -r '.tool_name // "unknown"')
14
+ tool_input=$(echo "$input" | jq -r '.tool_input // {}')
15
+
16
+ SCHEMA_FILE=".claude/schemas/tool-inputs.json"
17
+
18
+ # Skip if schema file doesn't exist
19
+ if [ ! -f "$SCHEMA_FILE" ]; then
20
+ echo "$input"
21
+ exit 0
22
+ fi
23
+
24
+ warnings=()
25
+
26
+ case "$tool_name" in
27
+ "Write")
28
+ file_path=$(echo "$tool_input" | jq -r '.file_path // ""')
29
+ content=$(echo "$tool_input" | jq -r '.content // ""')
30
+
31
+ if [ -z "$file_path" ]; then
32
+ warnings+=("[Schema] Write: file_path is empty or missing")
33
+ fi
34
+ if [ -z "$content" ]; then
35
+ warnings+=("[Schema] Write: content is empty — creating empty file?")
36
+ fi
37
+ ;;
38
+
39
+ "Edit")
40
+ file_path=$(echo "$tool_input" | jq -r '.file_path // ""')
41
+ old_string=$(echo "$tool_input" | jq -r '.old_string // ""')
42
+ new_string=$(echo "$tool_input" | jq -r '.new_string // ""')
43
+
44
+ if [ -z "$file_path" ]; then
45
+ warnings+=("[Schema] Edit: file_path is empty or missing")
46
+ fi
47
+ if [ -z "$old_string" ]; then
48
+ warnings+=("[Schema] Edit: old_string is empty")
49
+ fi
50
+ if [ "$old_string" = "$new_string" ]; then
51
+ warnings+=("[Schema] Edit: old_string equals new_string — no-op edit")
52
+ fi
53
+ ;;
54
+
55
+ "Bash")
56
+ command=$(echo "$tool_input" | jq -r '.command // ""')
57
+
58
+ if [ -z "$command" ]; then
59
+ warnings+=("[Schema] Bash: command is empty")
60
+ fi
61
+
62
+ # Check dangerous patterns
63
+ if echo "$command" | grep -qE 'rm\s+-rf\s+/[^.]'; then
64
+ warnings+=("[Schema] Bash: DANGER — recursive delete from root detected")
65
+ fi
66
+ if echo "$command" | grep -qE '^\s*sudo\s+'; then
67
+ warnings+=("[Schema] Bash: elevated privilege command detected")
68
+ fi
69
+ if echo "$command" | grep -qE '> /dev/sd'; then
70
+ warnings+=("[Schema] Bash: direct disk write detected")
71
+ fi
72
+ if echo "$command" | grep -qE 'mkfs\.'; then
73
+ warnings+=("[Schema] Bash: filesystem format command detected")
74
+ fi
75
+ # Remote code execution via pipe
76
+ if echo "$command" | grep -qE 'curl\s+.*\|\s*(ba)?sh'; then
77
+ warnings+=("[Schema] Bash: remote code execution pattern (curl | bash) detected")
78
+ fi
79
+ if echo "$command" | grep -qE 'wget\s+.*\|\s*(ba)?sh'; then
80
+ warnings+=("[Schema] Bash: remote code execution pattern (wget | sh) detected")
81
+ fi
82
+ # Dynamic code execution
83
+ if echo "$command" | grep -qE 'eval\s+\$\('; then
84
+ warnings+=("[Schema] Bash: dynamic code execution (eval) detected")
85
+ fi
86
+ # Broad permission grant
87
+ if echo "$command" | grep -qE 'chmod\s+777'; then
88
+ warnings+=("[Schema] Bash: broad permission grant (chmod 777) detected")
89
+ fi
90
+ ;;
91
+ esac
92
+
93
+ # Output warnings (advisory only)
94
+ if [ ${#warnings[@]} -gt 0 ]; then
95
+ for w in "${warnings[@]}"; do
96
+ echo "$w" >&2
97
+ done
98
+ echo "[Schema] Phase 1: advisory only — not blocking" >&2
99
+ fi
100
+
101
+ # Always pass through (Phase 1)
102
+ echo "$input"
103
+ exit 0
@@ -0,0 +1,97 @@
1
+ #!/bin/bash
2
+ # Secret Output Filter Hook — Detect potential secrets in tool output
3
+ # Trigger: PostToolUse on Bash, Read, Grep
4
+ # Purpose: Advisory warning when potential secrets detected in output
5
+ # Protocol: stdin JSON -> scan -> stdout pass-through
6
+ # Always exits 0 (advisory only, never blocks)
7
+
8
+ set -euo pipefail
9
+
10
+ input=$(cat)
11
+
12
+ # Extract output to scan
13
+ tool_name=$(echo "$input" | jq -r '.tool_name // "unknown"')
14
+ output=$(echo "$input" | jq -r '.tool_output.output // ""')
15
+
16
+ # Skip if no output
17
+ if [ -z "$output" ] || [ "$output" = "null" ]; then
18
+ echo "$input"
19
+ exit 0
20
+ fi
21
+
22
+ # Secret patterns to detect
23
+ detected=false
24
+
25
+ # AWS Access Key ID
26
+ if echo "$output" | grep -qE 'AKIA[0-9A-Z]{16}'; then
27
+ echo "[Security] Potential AWS Access Key detected in ${tool_name} output" >&2
28
+ detected=true
29
+ fi
30
+
31
+ # OpenAI/Anthropic API Key
32
+ if echo "$output" | grep -qE 'sk-[a-zA-Z0-9]{32,}'; then
33
+ echo "[Security] Potential API key (sk-*) detected in ${tool_name} output" >&2
34
+ detected=true
35
+ fi
36
+
37
+ # GitHub Personal Access Token
38
+ if echo "$output" | grep -qE 'ghp_[a-zA-Z0-9]{36}'; then
39
+ echo "[Security] Potential GitHub PAT detected in ${tool_name} output" >&2
40
+ detected=true
41
+ fi
42
+
43
+ # Private Key
44
+ if echo "$output" | grep -qE '-----BEGIN.*PRIVATE KEY-----'; then
45
+ echo "[Security] Potential private key detected in ${tool_name} output" >&2
46
+ detected=true
47
+ fi
48
+
49
+ # Bearer Token (long)
50
+ if echo "$output" | grep -qE 'Bearer [a-zA-Z0-9._-]{20,}'; then
51
+ echo "[Security] Potential Bearer token detected in ${tool_name} output" >&2
52
+ detected=true
53
+ fi
54
+
55
+ # GitHub OAuth Token
56
+ if echo "$output" | grep -qE 'gho_[a-zA-Z0-9]{36}'; then
57
+ echo "[Security] Potential GitHub OAuth token detected in ${tool_name} output" >&2
58
+ detected=true
59
+ fi
60
+
61
+ # GitHub Fine-Grained PAT
62
+ if echo "$output" | grep -qE 'github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59}'; then
63
+ echo "[Security] Potential GitHub Fine-Grained PAT detected in ${tool_name} output" >&2
64
+ detected=true
65
+ fi
66
+
67
+ # GitHub Actions Token
68
+ if echo "$output" | grep -qE 'ghs_[a-zA-Z0-9]{36}'; then
69
+ echo "[Security] Potential GitHub Actions token detected in ${tool_name} output" >&2
70
+ detected=true
71
+ fi
72
+
73
+ # npm Token
74
+ if echo "$output" | grep -qE 'npm_[a-zA-Z0-9]{36}'; then
75
+ echo "[Security] Potential npm token detected in ${tool_name} output" >&2
76
+ detected=true
77
+ fi
78
+
79
+ # Slack Token
80
+ if echo "$output" | grep -qE 'xox[bsarp]-[a-zA-Z0-9-]{10,}'; then
81
+ echo "[Security] Potential Slack token detected in ${tool_name} output" >&2
82
+ detected=true
83
+ fi
84
+
85
+ # Docker Hub PAT
86
+ if echo "$output" | grep -qE 'dckr_pat_[a-zA-Z0-9_-]{20,}'; then
87
+ echo "[Security] Potential Docker Hub PAT detected in ${tool_name} output" >&2
88
+ detected=true
89
+ fi
90
+
91
+ if [ "$detected" = true ]; then
92
+ echo "[Security] Review output carefully — do NOT commit or expose secrets" >&2
93
+ fi
94
+
95
+ # Pass through (always)
96
+ echo "$input"
97
+ exit 0
@@ -0,0 +1,65 @@
1
+ #!/bin/bash
2
+ # Stop hook: Session compliance report (R265 Phase 1)
3
+ # Reads violation logs collected by PreToolUse hooks during the session
4
+ # Advisory only — never blocks session termination
5
+ # Ref: https://github.com/baekenough/oh-my-customcode/issues/265
6
+
7
+ set -euo pipefail
8
+
9
+ input=$(cat)
10
+
11
+ VIOLATIONS_FILE="/tmp/.claude-violations-${PPID}"
12
+ TASK_COUNT_FILE="/tmp/.claude-task-count-${PPID}"
13
+
14
+ echo "" >&2
15
+ echo "╔══════════════════════════════════════════════╗" >&2
16
+ echo "║ Session Compliance Report ║" >&2
17
+ echo "╚══════════════════════════════════════════════╝" >&2
18
+
19
+ # Count total Agent/Task calls
20
+ if [ -f "$TASK_COUNT_FILE" ]; then
21
+ TOTAL_TASKS=$(cat "$TASK_COUNT_FILE")
22
+ echo "[Compliance] Agent/Task calls this session: ${TOTAL_TASKS}" >&2
23
+ else
24
+ TOTAL_TASKS=0
25
+ echo "[Compliance] Agent/Task calls this session: 0" >&2
26
+ fi
27
+
28
+ # Check violations
29
+ if [ -f "$VIOLATIONS_FILE" ] && [ -s "$VIOLATIONS_FILE" ]; then
30
+ VIOLATION_COUNT=$(wc -l < "$VIOLATIONS_FILE" | tr -d ' ')
31
+ echo "[Compliance] Violations detected: ${VIOLATION_COUNT}" >&2
32
+ echo "" >&2
33
+
34
+ # Group by rule
35
+ R010_COUNT=$(grep -c '"rule":"R010"' "$VIOLATIONS_FILE" 2>/dev/null || echo "0")
36
+ R018_COUNT=$(grep -c '"rule":"R018"' "$VIOLATIONS_FILE" 2>/dev/null || echo "0")
37
+
38
+ if [ "$R010_COUNT" -gt 0 ]; then
39
+ echo " R010 (Git Delegation): ${R010_COUNT} violation(s)" >&2
40
+ grep '"rule":"R010"' "$VIOLATIONS_FILE" | jq -r '.detail' 2>/dev/null | while read -r detail; do
41
+ echo " - ${detail}" >&2
42
+ done
43
+ fi
44
+
45
+ if [ "$R018_COUNT" -gt 0 ]; then
46
+ echo " R018 (Agent Teams): ${R018_COUNT} violation(s)" >&2
47
+ grep '"rule":"R018"' "$VIOLATIONS_FILE" | jq -r '.detail' 2>/dev/null | while read -r detail; do
48
+ echo " - ${detail}" >&2
49
+ done
50
+ fi
51
+
52
+ echo "" >&2
53
+ echo "[Compliance] Review violations above and consider rule updates per R016." >&2
54
+ else
55
+ echo "[Compliance] No violations detected. All clear!" >&2
56
+ fi
57
+
58
+ echo "────────────────────────────────────────────────" >&2
59
+
60
+ # Cleanup temp files (best effort)
61
+ rm -f "$VIOLATIONS_FILE" 2>/dev/null || true
62
+
63
+ # CRITICAL: Always pass through input and exit 0
64
+ echo "$input"
65
+ exit 0
@@ -104,17 +104,6 @@ All members must be spawned in a single message. Partial spawning needs correcti
104
104
  implementer → fixes → SendMessage(reviewer, "fixed")
105
105
  reviewer → re-reviews → done
106
106
 
107
- ❌ WRONG: Multi-expert task without coordination
108
- Agent(lang-typescript-expert) → "Implement frontend"
109
- Agent(be-express-expert) → "Implement API"
110
- (no shared state, results manually combined)
111
-
112
- ✓ CORRECT: Agent Teams for cross-domain work
113
- TeamCreate("fullstack")
114
- Agent(frontend-dev) + Agent(backend-dev) → team members
115
- Shared TaskList for interface contracts
116
- SendMessage for API schema coordination
117
-
118
107
  ❌ WRONG: Spawning team members one at a time
119
108
  TeamCreate("research-team")
120
109
  Message 1: Agent(researcher-1) → Analysis 1 (only 1/3 spawned)
@@ -127,18 +116,6 @@ All members must be spawned in a single message. Partial spawning needs correcti
127
116
  Agent(researcher-1) → Analysis 1 ┐
128
117
  Agent(researcher-2) → Analysis 2 ├─ ALL spawned together
129
118
  Agent(researcher-3) → Analysis 3 ┘
130
-
131
- ❌ WRONG: Multi-issue batch as independent agents
132
- Agent(general-purpose) → "Fix issue #1"
133
- Agent(general-purpose) → "Fix issue #2"
134
- Agent(general-purpose) → "Fix issue #3"
135
- (no coordination, no shared task tracking)
136
-
137
- ✓ CORRECT: Agent Teams for multi-issue batches
138
- TeamCreate("release-fixes")
139
- TaskCreate for each issue
140
- Agent(fixer-1) + Agent(fixer-2) + Agent(fixer-3) → team members
141
- Shared task list tracks progress across all issues
142
119
  ```
143
120
 
144
121
  ## Cost Guidelines
@@ -95,12 +95,6 @@ Main Conversation (orchestrator)
95
95
  Main conversation → Agent(mgr-gitnerd) → git commit
96
96
  Main conversation → Agent(mgr-gitnerd) → git push
97
97
 
98
- ❌ WRONG: Using general-purpose when specialist exists
99
- Main conversation → Agent(general-purpose) → "Write Go code"
100
-
101
- ✓ CORRECT: Using the right specialist
102
- Main conversation → Agent(lang-golang-expert) → "Write Go code"
103
-
104
98
  ❌ WRONG: Orchestrator creates files "just this once"
105
99
  "It's just a small config file, I'll write it directly..."
106
100
 
@@ -110,15 +104,9 @@ Main Conversation (orchestrator)
110
104
  ❌ WRONG: Bundling git operations with file editing in non-gitnerd agent
111
105
  Main conversation → Agent(general-purpose) → "git revert + edit file + git commit"
112
106
  Main conversation → Agent(lang-typescript-expert) → "fix bug and commit"
113
-
114
- ✓ CORRECT: Separate file editing from git operations
115
- Main conversation → Agent(lang-typescript-expert) → "fix bug" (file edit only)
116
- Main conversation → Agent(mgr-gitnerd) → "git commit" (git operation only)
117
-
118
- ❌ WRONG: Including git commands in non-gitnerd agent prompt for "convenience"
119
107
  Agent(general-purpose, prompt="revert the last commit, edit the file, then commit the fix")
120
108
 
121
- ✓ CORRECT: Split into separate delegations
109
+ ✓ CORRECT: Separate file editing from git operations, split delegations
122
110
  Agent(mgr-gitnerd, prompt="revert the last commit")
123
111
  Agent(appropriate-expert, prompt="edit the file to fix the issue")
124
112
  Agent(mgr-gitnerd, prompt="commit the fix")