diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml index ce85c71e9..60d79786c 100644 --- a/.github/workflows/security-scan.yml +++ b/.github/workflows/security-scan.yml @@ -25,11 +25,10 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Setup Node.js - uses: actions/setup-node@v4 + - name: Run AgentShield Security Scan + uses: affaan-m/agentshield@v1 with: - node-version: '20.x' - - - name: Run AgentShield security scan - run: npx ecc-agentshield scan --path . --min-severity medium --format terminal - continue-on-error: true # Informational only — ECC contains intentional config examples + path: '.' + min-severity: 'medium' + format: 'terminal' + fail-on-findings: 'false' diff --git a/agents/build-error-resolver.md b/agents/build-error-resolver.md index 749704bd1..c9b2acab5 100644 --- a/agents/build-error-resolver.md +++ b/agents/build-error-resolver.md @@ -2,7 +2,7 @@ name: build-error-resolver description: Build and TypeScript error resolution specialist. Use PROACTIVELY when build fails or type errors occur. Fixes build/type errors only with minimal diffs, no architectural edits. Focuses on getting the build green quickly. tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] -model: opus +model: sonnet --- # Build Error Resolver diff --git a/agents/code-reviewer.md b/agents/code-reviewer.md index 0752f6b36..8ed274d91 100644 --- a/agents/code-reviewer.md +++ b/agents/code-reviewer.md @@ -2,7 +2,7 @@ name: code-reviewer description: Expert code review specialist. Proactively reviews code for quality, security, and maintainability. Use immediately after writing or modifying code. MUST BE USED for all code changes. tools: ["Read", "Grep", "Glob", "Bash"] -model: opus +model: sonnet --- You are a senior code reviewer ensuring high standards of code quality and security. diff --git a/agents/database-reviewer.md b/agents/database-reviewer.md index 7325102d3..2308f3ca3 100644 --- a/agents/database-reviewer.md +++ b/agents/database-reviewer.md @@ -2,7 +2,7 @@ name: database-reviewer description: PostgreSQL database specialist for query optimization, schema design, security, and performance. Use PROACTIVELY when writing SQL, creating migrations, designing schemas, or troubleshooting database performance. Incorporates Supabase best practices. tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] -model: opus +model: sonnet --- # Database Reviewer diff --git a/agents/doc-updater.md b/agents/doc-updater.md index 8b15fffc4..d9909506b 100644 --- a/agents/doc-updater.md +++ b/agents/doc-updater.md @@ -2,7 +2,7 @@ name: doc-updater description: Documentation and codemap specialist. Use PROACTIVELY for updating codemaps and documentation. Runs /update-codemaps and /update-docs, generates docs/CODEMAPS/*, updates READMEs and guides. tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] -model: opus +model: haiku --- # Documentation & Codemap Specialist diff --git a/agents/e2e-runner.md b/agents/e2e-runner.md index 4f8ffab57..91e1e8c06 100644 --- a/agents/e2e-runner.md +++ b/agents/e2e-runner.md @@ -2,7 +2,7 @@ name: e2e-runner description: End-to-end testing specialist using Vercel Agent Browser (preferred) with Playwright fallback. Use PROACTIVELY for generating, maintaining, and running E2E tests. Manages test journeys, quarantines flaky tests, uploads artifacts (screenshots, videos, traces), and ensures critical user flows work. tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] -model: opus +model: sonnet --- # E2E Test Runner diff --git a/agents/go-build-resolver.md b/agents/go-build-resolver.md index 78cf5316d..50825030e 100644 --- a/agents/go-build-resolver.md +++ b/agents/go-build-resolver.md @@ -2,7 +2,7 @@ name: go-build-resolver description: Go build, vet, and compilation error resolution specialist. Fixes build errors, go vet issues, and linter warnings with minimal changes. Use when Go builds fail. tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] -model: opus +model: sonnet --- # Go Build Error Resolver diff --git a/agents/go-reviewer.md b/agents/go-reviewer.md index 031a5bd01..9f040d848 100644 --- a/agents/go-reviewer.md +++ b/agents/go-reviewer.md @@ -2,7 +2,7 @@ name: go-reviewer description: Expert Go code reviewer specializing in idiomatic Go, concurrency patterns, error handling, and performance. Use for all Go code changes. MUST BE USED for Go projects. tools: ["Read", "Grep", "Glob", "Bash"] -model: opus +model: sonnet --- You are a senior Go code reviewer ensuring high standards of idiomatic Go and best practices. diff --git a/agents/python-reviewer.md b/agents/python-reviewer.md index 47e5c58cd..f4b25b66e 100644 --- a/agents/python-reviewer.md +++ b/agents/python-reviewer.md @@ -2,7 +2,7 @@ name: python-reviewer description: Expert Python code reviewer specializing in PEP 8 compliance, Pythonic idioms, type hints, security, and performance. Use for all Python code changes. MUST BE USED for Python projects. tools: ["Read", "Grep", "Glob", "Bash"] -model: opus +model: sonnet --- You are a senior Python code reviewer ensuring high standards of Pythonic code and best practices. diff --git a/agents/refactor-cleaner.md b/agents/refactor-cleaner.md index a6f7f124a..963815341 100644 --- a/agents/refactor-cleaner.md +++ b/agents/refactor-cleaner.md @@ -2,7 +2,7 @@ name: refactor-cleaner description: Dead code cleanup and consolidation specialist. Use PROACTIVELY for removing unused code, duplicates, and refactoring. Runs analysis tools (knip, depcheck, ts-prune) to identify dead code and safely removes it. tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] -model: opus +model: sonnet --- # Refactor & Dead Code Cleaner diff --git a/agents/security-reviewer.md b/agents/security-reviewer.md index df303a0c2..56c6cea21 100644 --- a/agents/security-reviewer.md +++ b/agents/security-reviewer.md @@ -2,7 +2,7 @@ name: security-reviewer description: Security vulnerability detection and remediation specialist. Use PROACTIVELY after writing code that handles user input, authentication, API endpoints, or sensitive data. Flags secrets, SSRF, injection, unsafe crypto, and OWASP Top 10 vulnerabilities. tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] -model: opus +model: sonnet --- # Security Reviewer diff --git a/agents/tdd-guide.md b/agents/tdd-guide.md index c888b7da0..b23ae79ee 100644 --- a/agents/tdd-guide.md +++ b/agents/tdd-guide.md @@ -2,7 +2,7 @@ name: tdd-guide description: Test-Driven Development specialist enforcing write-tests-first methodology. Use PROACTIVELY when writing new features, fixing bugs, or refactoring code. Ensures 80%+ test coverage. tools: ["Read", "Write", "Edit", "Bash", "Grep"] -model: opus +model: sonnet --- You are a Test-Driven Development (TDD) specialist who ensures all code is developed test-first with comprehensive coverage. diff --git a/hooks/hooks.json b/hooks/hooks.json index 4a974af32..344b1ab95 100644 --- a/hooks/hooks.json +++ b/hooks/hooks.json @@ -3,47 +3,47 @@ "hooks": { "PreToolUse": [ { - "matcher": "tool == \"Bash\" && tool_input.command matches \"(npm run dev|pnpm( run)? dev|yarn dev|bun run dev)\"", + "matcher": "Bash", "hooks": [ { "type": "command", - "command": "node -e \"console.error('[Hook] BLOCKED: Dev server must run in tmux for log access');console.error('[Hook] Use: tmux new-session -d -s dev \\\"npm run dev\\\"');console.error('[Hook] Then: tmux attach -t dev');process.exit(1)\"" + "command": "node -e \"let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const cmd=i.tool_input?.command||'';if(/(npm run dev|pnpm( run)? dev|yarn dev|bun run dev)/.test(cmd)){console.error('[Hook] BLOCKED: Dev server must run in tmux for log access');console.error('[Hook] Use: tmux new-session -d -s dev \\\"npm run dev\\\"');console.error('[Hook] Then: tmux attach -t dev');process.exit(2)}console.log(d)})\"" } ], "description": "Block dev servers outside tmux - ensures you can access logs" }, { - "matcher": "tool == \"Bash\" && tool_input.command matches \"(npm (install|test)|pnpm (install|test)|yarn (install|test)?|bun (install|test)|cargo build|make|docker|pytest|vitest|playwright)\"", + "matcher": "Bash", "hooks": [ { "type": "command", - "command": "node -e \"if(!process.env.TMUX){console.error('[Hook] Consider running in tmux for session persistence');console.error('[Hook] tmux new -s dev | tmux attach -t dev')}\"" + "command": "node -e \"let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const cmd=i.tool_input?.command||'';if(!process.env.TMUX&&/(npm (install|test)|pnpm (install|test)|yarn (install|test)?|bun (install|test)|cargo build|make\\b|docker\\b|pytest|vitest|playwright)/.test(cmd)){console.error('[Hook] Consider running in tmux for session persistence');console.error('[Hook] tmux new -s dev | tmux attach -t dev')}console.log(d)})\"" } ], "description": "Reminder to use tmux for long-running commands" }, { - "matcher": "tool == \"Bash\" && tool_input.command matches \"git push\"", + "matcher": "Bash", "hooks": [ { "type": "command", - "command": "node -e \"console.error('[Hook] Review changes before push...');console.error('[Hook] Continuing with push (remove this hook to add interactive review)')\"" + "command": "node -e \"let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const cmd=i.tool_input?.command||'';if(/git push/.test(cmd)){console.error('[Hook] Review changes before push...');console.error('[Hook] Continuing with push (remove this hook to add interactive review)')}console.log(d)})\"" } ], "description": "Reminder before git push to review changes" }, { - "matcher": "tool == \"Write\" && tool_input.file_path matches \"\\\\.(md|txt)$\" && !(tool_input.file_path matches \"README\\\\.md|CLAUDE\\\\.md|AGENTS\\\\.md|CONTRIBUTING\\\\.md\")", + "matcher": "Write", "hooks": [ { "type": "command", - "command": "node -e \"const fs=require('fs');let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const p=i.tool_input?.file_path||'';if(/\\.(md|txt)$/.test(p)&&!/(README|CLAUDE|AGENTS|CONTRIBUTING)\\.md$/.test(p)){console.error('[Hook] BLOCKED: Unnecessary documentation file creation');console.error('[Hook] File: '+p);console.error('[Hook] Use README.md for documentation instead');process.exit(1)}console.log(d)})\"" + "command": "node -e \"const fs=require('fs');let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const p=i.tool_input?.file_path||'';if(/\\.(md|txt)$/.test(p)&&!/(README|CLAUDE|AGENTS|CONTRIBUTING)\\.md$/.test(p)){console.error('[Hook] BLOCKED: Unnecessary documentation file creation');console.error('[Hook] File: '+p);console.error('[Hook] Use README.md for documentation instead');process.exit(2)}console.log(d)})\"" } ], "description": "Block creation of random .md files - keeps docs consolidated" }, { - "matcher": "tool == \"Edit\" || tool == \"Write\"", + "matcher": "Edit|Write", "hooks": [ { "type": "command", @@ -79,7 +79,7 @@ ], "PostToolUse": [ { - "matcher": "tool == \"Bash\"", + "matcher": "Bash", "hooks": [ { "type": "command", @@ -89,11 +89,11 @@ "description": "Log PR URL and provide review command after PR creation" }, { - "matcher": "tool == \"Bash\" && tool_input.command matches \"(npm run build|pnpm build|yarn build)\"", + "matcher": "Bash", "hooks": [ { "type": "command", - "command": "node -e \"let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{console.error('[Hook] Build completed - async analysis running in background');console.log(d)})\"", + "command": "node -e \"let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const cmd=i.tool_input?.command||'';if(/(npm run build|pnpm build|yarn build)/.test(cmd)){console.error('[Hook] Build completed - async analysis running in background')}console.log(d)})\"", "async": true, "timeout": 30 } @@ -101,31 +101,31 @@ "description": "Example: async hook for build analysis (runs in background without blocking)" }, { - "matcher": "tool == \"Edit\" && tool_input.file_path matches \"\\\\.(ts|tsx|js|jsx)$\"", + "matcher": "Edit", "hooks": [ { "type": "command", - "command": "node -e \"const{execFileSync}=require('child_process');const fs=require('fs');let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const p=i.tool_input?.file_path;if(p&&fs.existsSync(p)){try{execFileSync('npx',['prettier','--write',p],{stdio:['pipe','pipe','pipe']})}catch(e){}}console.log(d)})\"" + "command": "node -e \"const{execFileSync}=require('child_process');const fs=require('fs');let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const p=i.tool_input?.file_path;if(p&&/\\.(ts|tsx|js|jsx)$/.test(p)&&fs.existsSync(p)){try{execFileSync('npx',['prettier','--write',p],{stdio:['pipe','pipe','pipe']})}catch(e){}}console.log(d)})\"" } ], "description": "Auto-format JS/TS files with Prettier after edits" }, { - "matcher": "tool == \"Edit\" && tool_input.file_path matches \"\\\\.(ts|tsx)$\"", + "matcher": "Edit", "hooks": [ { "type": "command", - "command": "node -e \"const{execSync}=require('child_process');const fs=require('fs');const path=require('path');let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const p=i.tool_input?.file_path;if(p&&fs.existsSync(p)){let dir=path.dirname(p);while(dir!==path.dirname(dir)&&!fs.existsSync(path.join(dir,'tsconfig.json'))){dir=path.dirname(dir)}if(fs.existsSync(path.join(dir,'tsconfig.json'))){try{const r=execSync('npx tsc --noEmit --pretty false 2>&1',{cwd:dir,encoding:'utf8',stdio:['pipe','pipe','pipe']});const lines=r.split('\\n').filter(l=>l.includes(p)).slice(0,10);if(lines.length)console.error(lines.join('\\n'))}catch(e){const lines=(e.stdout||'').split('\\n').filter(l=>l.includes(p)).slice(0,10);if(lines.length)console.error(lines.join('\\n'))}}}console.log(d)})\"" + "command": "node -e \"const{execFileSync}=require('child_process');const fs=require('fs');const path=require('path');let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const p=i.tool_input?.file_path;if(p&&/\\.(ts|tsx)$/.test(p)&&fs.existsSync(p)){let dir=path.dirname(p);while(dir!==path.dirname(dir)&&!fs.existsSync(path.join(dir,'tsconfig.json'))){dir=path.dirname(dir)}if(fs.existsSync(path.join(dir,'tsconfig.json'))){try{const r=execFileSync('npx',['tsc','--noEmit','--pretty','false'],{cwd:dir,encoding:'utf8',stdio:['pipe','pipe','pipe']});const lines=r.split('\\n').filter(l=>l.includes(p)).slice(0,10);if(lines.length)console.error(lines.join('\\n'))}catch(e){const lines=(e.stdout||'').split('\\n').filter(l=>l.includes(p)).slice(0,10);if(lines.length)console.error(lines.join('\\n'))}}}console.log(d)})\"" } ], "description": "TypeScript check after editing .ts/.tsx files" }, { - "matcher": "tool == \"Edit\" && tool_input.file_path matches \"\\\\.(ts|tsx|js|jsx)$\"", + "matcher": "Edit", "hooks": [ { "type": "command", - "command": "node -e \"const fs=require('fs');let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const p=i.tool_input?.file_path;if(p&&fs.existsSync(p)){const c=fs.readFileSync(p,'utf8');const lines=c.split('\\n');const matches=[];lines.forEach((l,idx)=>{if(/console\\.log/.test(l))matches.push((idx+1)+': '+l.trim())});if(matches.length){console.error('[Hook] WARNING: console.log found in '+p);matches.slice(0,5).forEach(m=>console.error(m));console.error('[Hook] Remove console.log before committing')}}console.log(d)})\"" + "command": "node -e \"const fs=require('fs');let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const p=i.tool_input?.file_path;if(p&&/\\.(ts|tsx|js|jsx)$/.test(p)&&fs.existsSync(p)){const c=fs.readFileSync(p,'utf8');const lines=c.split('\\n');const matches=[];lines.forEach((l,idx)=>{if(/console\\.log/.test(l))matches.push((idx+1)+': '+l.trim())});if(matches.length){console.error('[Hook] WARNING: console.log found in '+p);matches.slice(0,5).forEach(m=>console.error(m));console.error('[Hook] Remove console.log before committing')}}console.log(d)})\"" } ], "description": "Warn about console.log statements after edits" diff --git a/rules/golang/coding-style.md b/rules/golang/coding-style.md index 21884535e..d7d6c31ac 100644 --- a/rules/golang/coding-style.md +++ b/rules/golang/coding-style.md @@ -1,3 +1,9 @@ +--- +paths: + - "**/*.go" + - "**/go.mod" + - "**/go.sum" +--- # Go Coding Style > This file extends [common/coding-style.md](../common/coding-style.md) with Go specific content. diff --git a/rules/golang/hooks.md b/rules/golang/hooks.md index 1a85291e0..f05e4ad2d 100644 --- a/rules/golang/hooks.md +++ b/rules/golang/hooks.md @@ -1,3 +1,9 @@ +--- +paths: + - "**/*.go" + - "**/go.mod" + - "**/go.sum" +--- # Go Hooks > This file extends [common/hooks.md](../common/hooks.md) with Go specific content. diff --git a/rules/golang/patterns.md b/rules/golang/patterns.md index 6d219dd1b..ba28dbabc 100644 --- a/rules/golang/patterns.md +++ b/rules/golang/patterns.md @@ -1,3 +1,9 @@ +--- +paths: + - "**/*.go" + - "**/go.mod" + - "**/go.sum" +--- # Go Patterns > This file extends [common/patterns.md](../common/patterns.md) with Go specific content. diff --git a/rules/golang/security.md b/rules/golang/security.md index 0a118c316..372b754dc 100644 --- a/rules/golang/security.md +++ b/rules/golang/security.md @@ -1,3 +1,9 @@ +--- +paths: + - "**/*.go" + - "**/go.mod" + - "**/go.sum" +--- # Go Security > This file extends [common/security.md](../common/security.md) with Go specific content. diff --git a/rules/golang/testing.md b/rules/golang/testing.md index ac87e13a5..6b8002262 100644 --- a/rules/golang/testing.md +++ b/rules/golang/testing.md @@ -1,3 +1,9 @@ +--- +paths: + - "**/*.go" + - "**/go.mod" + - "**/go.sum" +--- # Go Testing > This file extends [common/testing.md](../common/testing.md) with Go specific content. diff --git a/rules/python/coding-style.md b/rules/python/coding-style.md index c96bba429..3a01ae3f9 100644 --- a/rules/python/coding-style.md +++ b/rules/python/coding-style.md @@ -1,3 +1,8 @@ +--- +paths: + - "**/*.py" + - "**/*.pyi" +--- # Python Coding Style > This file extends [common/coding-style.md](../common/coding-style.md) with Python specific content. diff --git a/rules/python/hooks.md b/rules/python/hooks.md index 0ced0dce0..600c5ea72 100644 --- a/rules/python/hooks.md +++ b/rules/python/hooks.md @@ -1,3 +1,8 @@ +--- +paths: + - "**/*.py" + - "**/*.pyi" +--- # Python Hooks > This file extends [common/hooks.md](../common/hooks.md) with Python specific content. diff --git a/rules/python/patterns.md b/rules/python/patterns.md index 96b96c1ea..5b7f8991f 100644 --- a/rules/python/patterns.md +++ b/rules/python/patterns.md @@ -1,3 +1,8 @@ +--- +paths: + - "**/*.py" + - "**/*.pyi" +--- # Python Patterns > This file extends [common/patterns.md](../common/patterns.md) with Python specific content. diff --git a/rules/python/security.md b/rules/python/security.md index d9aec9295..e795baf73 100644 --- a/rules/python/security.md +++ b/rules/python/security.md @@ -1,3 +1,8 @@ +--- +paths: + - "**/*.py" + - "**/*.pyi" +--- # Python Security > This file extends [common/security.md](../common/security.md) with Python specific content. diff --git a/rules/python/testing.md b/rules/python/testing.md index 29a3a6692..49e3f085b 100644 --- a/rules/python/testing.md +++ b/rules/python/testing.md @@ -1,3 +1,8 @@ +--- +paths: + - "**/*.py" + - "**/*.pyi" +--- # Python Testing > This file extends [common/testing.md](../common/testing.md) with Python specific content. diff --git a/rules/typescript/coding-style.md b/rules/typescript/coding-style.md index 333f52d72..db62a9bcd 100644 --- a/rules/typescript/coding-style.md +++ b/rules/typescript/coding-style.md @@ -1,3 +1,10 @@ +--- +paths: + - "**/*.ts" + - "**/*.tsx" + - "**/*.js" + - "**/*.jsx" +--- # TypeScript/JavaScript Coding Style > This file extends [common/coding-style.md](../common/coding-style.md) with TypeScript/JavaScript specific content. diff --git a/rules/typescript/hooks.md b/rules/typescript/hooks.md index 861d9e5f1..cd4754b3f 100644 --- a/rules/typescript/hooks.md +++ b/rules/typescript/hooks.md @@ -1,3 +1,10 @@ +--- +paths: + - "**/*.ts" + - "**/*.tsx" + - "**/*.js" + - "**/*.jsx" +--- # TypeScript/JavaScript Hooks > This file extends [common/hooks.md](../common/hooks.md) with TypeScript/JavaScript specific content. diff --git a/rules/typescript/patterns.md b/rules/typescript/patterns.md index 1c5d3da45..d50729d07 100644 --- a/rules/typescript/patterns.md +++ b/rules/typescript/patterns.md @@ -1,3 +1,10 @@ +--- +paths: + - "**/*.ts" + - "**/*.tsx" + - "**/*.js" + - "**/*.jsx" +--- # TypeScript/JavaScript Patterns > This file extends [common/patterns.md](../common/patterns.md) with TypeScript/JavaScript specific content. diff --git a/rules/typescript/security.md b/rules/typescript/security.md index 5ec60e260..98ba4008e 100644 --- a/rules/typescript/security.md +++ b/rules/typescript/security.md @@ -1,3 +1,10 @@ +--- +paths: + - "**/*.ts" + - "**/*.tsx" + - "**/*.js" + - "**/*.jsx" +--- # TypeScript/JavaScript Security > This file extends [common/security.md](../common/security.md) with TypeScript/JavaScript specific content. diff --git a/rules/typescript/testing.md b/rules/typescript/testing.md index 60531afb4..6f2f4020c 100644 --- a/rules/typescript/testing.md +++ b/rules/typescript/testing.md @@ -1,3 +1,10 @@ +--- +paths: + - "**/*.ts" + - "**/*.tsx" + - "**/*.js" + - "**/*.jsx" +--- # TypeScript/JavaScript Testing > This file extends [common/testing.md](../common/testing.md) with TypeScript/JavaScript specific content. diff --git a/skills/continuous-learning-v2/hooks/observe.sh b/skills/continuous-learning-v2/hooks/observe.sh index 225c90e55..3db1a2cf2 100755 --- a/skills/continuous-learning-v2/hooks/observe.sh +++ b/skills/continuous-learning-v2/hooks/observe.sh @@ -56,20 +56,20 @@ if [ -z "$INPUT_JSON" ]; then exit 0 fi -# Parse using python (more reliable than jq for complex JSON) -PARSED=$(python3 << EOF +# Parse using python via stdin pipe (safe for all JSON payloads) +PARSED=$(echo "$INPUT_JSON" | python3 -c ' import json import sys try: - data = json.loads('''$INPUT_JSON''') + data = json.load(sys.stdin) # Extract fields - Claude Code hook format - hook_type = data.get('hook_type', 'unknown') # PreToolUse or PostToolUse - tool_name = data.get('tool_name', data.get('tool', 'unknown')) - tool_input = data.get('tool_input', data.get('input', {})) - tool_output = data.get('tool_output', data.get('output', '')) - session_id = data.get('session_id', 'unknown') + hook_type = data.get("hook_type", "unknown") # PreToolUse or PostToolUse + tool_name = data.get("tool_name", data.get("tool", "unknown")) + tool_input = data.get("tool_input", data.get("input", {})) + tool_output = data.get("tool_output", data.get("output", "")) + session_id = data.get("session_id", "unknown") # Truncate large inputs/outputs if isinstance(tool_input, dict): @@ -83,20 +83,19 @@ try: tool_output_str = str(tool_output)[:5000] # Determine event type - event = 'tool_start' if 'Pre' in hook_type else 'tool_complete' + event = "tool_start" if "Pre" in hook_type else "tool_complete" print(json.dumps({ - 'parsed': True, - 'event': event, - 'tool': tool_name, - 'input': tool_input_str if event == 'tool_start' else None, - 'output': tool_output_str if event == 'tool_complete' else None, - 'session': session_id + "parsed": True, + "event": event, + "tool": tool_name, + "input": tool_input_str if event == "tool_start" else None, + "output": tool_output_str if event == "tool_complete" else None, + "session": session_id })) except Exception as e: - print(json.dumps({'parsed': False, 'error': str(e)})) -EOF -) + print(json.dumps({"parsed": False, "error": str(e)})) +') # Check if parsing succeeded PARSED_OK=$(echo "$PARSED" | python3 -c "import json,sys; print(json.load(sys.stdin).get('parsed', False))") @@ -104,7 +103,11 @@ PARSED_OK=$(echo "$PARSED" | python3 -c "import json,sys; print(json.load(sys.st if [ "$PARSED_OK" != "True" ]; then # Fallback: log raw input for debugging timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ") - echo "{\"timestamp\":\"$timestamp\",\"event\":\"parse_error\",\"raw\":$(echo "$INPUT_JSON" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()[:1000]))')}" >> "$OBSERVATIONS_FILE" + echo "$INPUT_JSON" | python3 -c " +import json, sys +raw = sys.stdin.read()[:2000] +print(json.dumps({'timestamp': '$timestamp', 'event': 'parse_error', 'raw': raw})) +" >> "$OBSERVATIONS_FILE" exit 0 fi @@ -121,10 +124,10 @@ fi # Build and write observation timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ") -python3 << EOF -import json +echo "$PARSED" | python3 -c " +import json, sys -parsed = json.loads('''$PARSED''') +parsed = json.load(sys.stdin) observation = { 'timestamp': '$timestamp', 'event': parsed['event'], @@ -139,7 +142,7 @@ if parsed['output']: with open('$OBSERVATIONS_FILE', 'a') as f: f.write(json.dumps(observation) + '\n') -EOF +" # Signal observer if running OBSERVER_PID_FILE="${CONFIG_DIR}/.observer.pid" diff --git a/skills/django-verification/SKILL.md b/skills/django-verification/SKILL.md index 23438e8d1..886bc403e 100644 --- a/skills/django-verification/SKILL.md +++ b/skills/django-verification/SKILL.md @@ -1,6 +1,6 @@ --- name: django-verification -description: Verification loop for Django projects: migrations, linting, tests with coverage, security scans, and deployment readiness checks before release or PR. +description: "Verification loop for Django projects: migrations, linting, tests with coverage, security scans, and deployment readiness checks before release or PR." --- # Django Verification Loop diff --git a/skills/java-coding-standards/SKILL.md b/skills/java-coding-standards/SKILL.md index 9a03a41c2..1a59c4075 100644 --- a/skills/java-coding-standards/SKILL.md +++ b/skills/java-coding-standards/SKILL.md @@ -1,6 +1,6 @@ --- name: java-coding-standards -description: Java coding standards for Spring Boot services: naming, immutability, Optional usage, streams, exceptions, generics, and project layout. +description: "Java coding standards for Spring Boot services: naming, immutability, Optional usage, streams, exceptions, generics, and project layout." --- # Java Coding Standards diff --git a/skills/project-guidelines-example/SKILL.md b/skills/project-guidelines-example/SKILL.md index 01358558f..aa72a48af 100644 --- a/skills/project-guidelines-example/SKILL.md +++ b/skills/project-guidelines-example/SKILL.md @@ -1,11 +1,14 @@ +--- +name: project-guidelines-example +description: "Example project-specific skill template based on a real production application." +--- + # Project Guidelines Skill (Example) This is an example of a project-specific skill. Use this as a template for your own projects. Based on a real production application: [Zenith](https://zenith.chat) - AI-powered customer discovery platform. ---- - ## When to Use Reference this skill when working on the specific project it's designed for. Project skills contain: diff --git a/skills/springboot-verification/SKILL.md b/skills/springboot-verification/SKILL.md index 909e90ae0..abec6e8ec 100644 --- a/skills/springboot-verification/SKILL.md +++ b/skills/springboot-verification/SKILL.md @@ -1,6 +1,6 @@ --- name: springboot-verification -description: Verification loop for Spring Boot projects: build, static analysis, tests with coverage, security scans, and diff review before release or PR. +description: "Verification loop for Spring Boot projects: build, static analysis, tests with coverage, security scans, and diff review before release or PR." --- # Spring Boot Verification Loop diff --git a/skills/verification-loop/SKILL.md b/skills/verification-loop/SKILL.md index b56bb7e83..1c0904925 100644 --- a/skills/verification-loop/SKILL.md +++ b/skills/verification-loop/SKILL.md @@ -1,3 +1,8 @@ +--- +name: verification-loop +description: "A comprehensive verification system for Claude Code sessions." +--- + # Verification Loop Skill A comprehensive verification system for Claude Code sessions.