fix: resolve multiple reported issues (#205, #182, #188, #172, #173) (#207)

* fix: resolve multiple reported issues (#205, #182, #188, #172, #173)

- fix(observe.sh): replace triple-quote JSON parsing with stdin pipe to
  prevent ~49% parse failures on payloads with quotes/backslashes/unicode
- fix(hooks.json): correct matcher syntax to use simple tool name regexes
  instead of unsupported logical expressions; move command/path filtering
  into hook scripts; use exit code 2 for blocking hooks
- fix(skills): quote YAML descriptions containing colons in 3 skill files
  and add missing frontmatter to 2 skill files for Codex CLI compatibility
- feat(rules): add paths: filters to all 15 language-specific rule files
  so they only load when working on matching file types
- fix(agents): align model fields with CONTRIBUTING.md recommendations
  (opus for planner/architect, sonnet for reviewers/workers, haiku for
  doc-updater)

* ci: use AgentShield GitHub Action instead of npx

Switch from npx ecc-agentshield to uses: affaan-m/agentshield@v1
for proper GitHub Action demo and marketplace visibility.
This commit is contained in:
Affaan Mustafa
2026-02-11 23:48:45 -08:00
committed by GitHub
parent 3bc8672432
commit e41ee0c858
34 changed files with 164 additions and 64 deletions

View File

@@ -25,11 +25,10 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Setup Node.js - name: Run AgentShield Security Scan
uses: actions/setup-node@v4 uses: affaan-m/agentshield@v1
with: with:
node-version: '20.x' path: '.'
min-severity: 'medium'
- name: Run AgentShield security scan format: 'terminal'
run: npx ecc-agentshield scan --path . --min-severity medium --format terminal fail-on-findings: 'false'
continue-on-error: true # Informational only — ECC contains intentional config examples

View File

@@ -2,7 +2,7 @@
name: build-error-resolver 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. 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"] tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"]
model: opus model: sonnet
--- ---
# Build Error Resolver # Build Error Resolver

View File

@@ -2,7 +2,7 @@
name: code-reviewer 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. 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"] tools: ["Read", "Grep", "Glob", "Bash"]
model: opus model: sonnet
--- ---
You are a senior code reviewer ensuring high standards of code quality and security. You are a senior code reviewer ensuring high standards of code quality and security.

View File

@@ -2,7 +2,7 @@
name: database-reviewer 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. 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"] tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"]
model: opus model: sonnet
--- ---
# Database Reviewer # Database Reviewer

View File

@@ -2,7 +2,7 @@
name: doc-updater 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. 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"] tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"]
model: opus model: haiku
--- ---
# Documentation & Codemap Specialist # Documentation & Codemap Specialist

View File

@@ -2,7 +2,7 @@
name: e2e-runner 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. 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"] tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"]
model: opus model: sonnet
--- ---
# E2E Test Runner # E2E Test Runner

View File

@@ -2,7 +2,7 @@
name: go-build-resolver 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. 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"] tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"]
model: opus model: sonnet
--- ---
# Go Build Error Resolver # Go Build Error Resolver

View File

@@ -2,7 +2,7 @@
name: go-reviewer 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. 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"] 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. You are a senior Go code reviewer ensuring high standards of idiomatic Go and best practices.

View File

@@ -2,7 +2,7 @@
name: python-reviewer 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. 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"] 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. You are a senior Python code reviewer ensuring high standards of Pythonic code and best practices.

View File

@@ -2,7 +2,7 @@
name: refactor-cleaner 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. 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"] tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"]
model: opus model: sonnet
--- ---
# Refactor & Dead Code Cleaner # Refactor & Dead Code Cleaner

View File

@@ -2,7 +2,7 @@
name: security-reviewer 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. 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"] tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"]
model: opus model: sonnet
--- ---
# Security Reviewer # Security Reviewer

View File

@@ -2,7 +2,7 @@
name: tdd-guide 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. 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"] 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. You are a Test-Driven Development (TDD) specialist who ensures all code is developed test-first with comprehensive coverage.

View File

@@ -3,47 +3,47 @@
"hooks": { "hooks": {
"PreToolUse": [ "PreToolUse": [
{ {
"matcher": "tool == \"Bash\" && tool_input.command matches \"(npm run dev|pnpm( run)? dev|yarn dev|bun run dev)\"", "matcher": "Bash",
"hooks": [ "hooks": [
{ {
"type": "command", "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" "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": [ "hooks": [
{ {
"type": "command", "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" "description": "Reminder to use tmux for long-running commands"
}, },
{ {
"matcher": "tool == \"Bash\" && tool_input.command matches \"git push\"", "matcher": "Bash",
"hooks": [ "hooks": [
{ {
"type": "command", "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" "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": [ "hooks": [
{ {
"type": "command", "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" "description": "Block creation of random .md files - keeps docs consolidated"
}, },
{ {
"matcher": "tool == \"Edit\" || tool == \"Write\"", "matcher": "Edit|Write",
"hooks": [ "hooks": [
{ {
"type": "command", "type": "command",
@@ -79,7 +79,7 @@
], ],
"PostToolUse": [ "PostToolUse": [
{ {
"matcher": "tool == \"Bash\"", "matcher": "Bash",
"hooks": [ "hooks": [
{ {
"type": "command", "type": "command",
@@ -89,11 +89,11 @@
"description": "Log PR URL and provide review command after PR creation" "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": [ "hooks": [
{ {
"type": "command", "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, "async": true,
"timeout": 30 "timeout": 30
} }
@@ -101,31 +101,31 @@
"description": "Example: async hook for build analysis (runs in background without blocking)" "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": [ "hooks": [
{ {
"type": "command", "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" "description": "Auto-format JS/TS files with Prettier after edits"
}, },
{ {
"matcher": "tool == \"Edit\" && tool_input.file_path matches \"\\\\.(ts|tsx)$\"", "matcher": "Edit",
"hooks": [ "hooks": [
{ {
"type": "command", "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" "description": "TypeScript check after editing .ts/.tsx files"
}, },
{ {
"matcher": "tool == \"Edit\" && tool_input.file_path matches \"\\\\.(ts|tsx|js|jsx)$\"", "matcher": "Edit",
"hooks": [ "hooks": [
{ {
"type": "command", "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" "description": "Warn about console.log statements after edits"

View File

@@ -1,3 +1,9 @@
---
paths:
- "**/*.go"
- "**/go.mod"
- "**/go.sum"
---
# Go Coding Style # Go Coding Style
> This file extends [common/coding-style.md](../common/coding-style.md) with Go specific content. > This file extends [common/coding-style.md](../common/coding-style.md) with Go specific content.

View File

@@ -1,3 +1,9 @@
---
paths:
- "**/*.go"
- "**/go.mod"
- "**/go.sum"
---
# Go Hooks # Go Hooks
> This file extends [common/hooks.md](../common/hooks.md) with Go specific content. > This file extends [common/hooks.md](../common/hooks.md) with Go specific content.

View File

@@ -1,3 +1,9 @@
---
paths:
- "**/*.go"
- "**/go.mod"
- "**/go.sum"
---
# Go Patterns # Go Patterns
> This file extends [common/patterns.md](../common/patterns.md) with Go specific content. > This file extends [common/patterns.md](../common/patterns.md) with Go specific content.

View File

@@ -1,3 +1,9 @@
---
paths:
- "**/*.go"
- "**/go.mod"
- "**/go.sum"
---
# Go Security # Go Security
> This file extends [common/security.md](../common/security.md) with Go specific content. > This file extends [common/security.md](../common/security.md) with Go specific content.

View File

@@ -1,3 +1,9 @@
---
paths:
- "**/*.go"
- "**/go.mod"
- "**/go.sum"
---
# Go Testing # Go Testing
> This file extends [common/testing.md](../common/testing.md) with Go specific content. > This file extends [common/testing.md](../common/testing.md) with Go specific content.

View File

@@ -1,3 +1,8 @@
---
paths:
- "**/*.py"
- "**/*.pyi"
---
# Python Coding Style # Python Coding Style
> This file extends [common/coding-style.md](../common/coding-style.md) with Python specific content. > This file extends [common/coding-style.md](../common/coding-style.md) with Python specific content.

View File

@@ -1,3 +1,8 @@
---
paths:
- "**/*.py"
- "**/*.pyi"
---
# Python Hooks # Python Hooks
> This file extends [common/hooks.md](../common/hooks.md) with Python specific content. > This file extends [common/hooks.md](../common/hooks.md) with Python specific content.

View File

@@ -1,3 +1,8 @@
---
paths:
- "**/*.py"
- "**/*.pyi"
---
# Python Patterns # Python Patterns
> This file extends [common/patterns.md](../common/patterns.md) with Python specific content. > This file extends [common/patterns.md](../common/patterns.md) with Python specific content.

View File

@@ -1,3 +1,8 @@
---
paths:
- "**/*.py"
- "**/*.pyi"
---
# Python Security # Python Security
> This file extends [common/security.md](../common/security.md) with Python specific content. > This file extends [common/security.md](../common/security.md) with Python specific content.

View File

@@ -1,3 +1,8 @@
---
paths:
- "**/*.py"
- "**/*.pyi"
---
# Python Testing # Python Testing
> This file extends [common/testing.md](../common/testing.md) with Python specific content. > This file extends [common/testing.md](../common/testing.md) with Python specific content.

View File

@@ -1,3 +1,10 @@
---
paths:
- "**/*.ts"
- "**/*.tsx"
- "**/*.js"
- "**/*.jsx"
---
# TypeScript/JavaScript Coding Style # TypeScript/JavaScript Coding Style
> This file extends [common/coding-style.md](../common/coding-style.md) with TypeScript/JavaScript specific content. > This file extends [common/coding-style.md](../common/coding-style.md) with TypeScript/JavaScript specific content.

View File

@@ -1,3 +1,10 @@
---
paths:
- "**/*.ts"
- "**/*.tsx"
- "**/*.js"
- "**/*.jsx"
---
# TypeScript/JavaScript Hooks # TypeScript/JavaScript Hooks
> This file extends [common/hooks.md](../common/hooks.md) with TypeScript/JavaScript specific content. > This file extends [common/hooks.md](../common/hooks.md) with TypeScript/JavaScript specific content.

View File

@@ -1,3 +1,10 @@
---
paths:
- "**/*.ts"
- "**/*.tsx"
- "**/*.js"
- "**/*.jsx"
---
# TypeScript/JavaScript Patterns # TypeScript/JavaScript Patterns
> This file extends [common/patterns.md](../common/patterns.md) with TypeScript/JavaScript specific content. > This file extends [common/patterns.md](../common/patterns.md) with TypeScript/JavaScript specific content.

View File

@@ -1,3 +1,10 @@
---
paths:
- "**/*.ts"
- "**/*.tsx"
- "**/*.js"
- "**/*.jsx"
---
# TypeScript/JavaScript Security # TypeScript/JavaScript Security
> This file extends [common/security.md](../common/security.md) with TypeScript/JavaScript specific content. > This file extends [common/security.md](../common/security.md) with TypeScript/JavaScript specific content.

View File

@@ -1,3 +1,10 @@
---
paths:
- "**/*.ts"
- "**/*.tsx"
- "**/*.js"
- "**/*.jsx"
---
# TypeScript/JavaScript Testing # TypeScript/JavaScript Testing
> This file extends [common/testing.md](../common/testing.md) with TypeScript/JavaScript specific content. > This file extends [common/testing.md](../common/testing.md) with TypeScript/JavaScript specific content.

View File

@@ -56,20 +56,20 @@ if [ -z "$INPUT_JSON" ]; then
exit 0 exit 0
fi fi
# Parse using python (more reliable than jq for complex JSON) # Parse using python via stdin pipe (safe for all JSON payloads)
PARSED=$(python3 << EOF PARSED=$(echo "$INPUT_JSON" | python3 -c '
import json import json
import sys import sys
try: try:
data = json.loads('''$INPUT_JSON''') data = json.load(sys.stdin)
# Extract fields - Claude Code hook format # Extract fields - Claude Code hook format
hook_type = data.get('hook_type', 'unknown') # PreToolUse or PostToolUse hook_type = data.get("hook_type", "unknown") # PreToolUse or PostToolUse
tool_name = data.get('tool_name', data.get('tool', 'unknown')) tool_name = data.get("tool_name", data.get("tool", "unknown"))
tool_input = data.get('tool_input', data.get('input', {})) tool_input = data.get("tool_input", data.get("input", {}))
tool_output = data.get('tool_output', data.get('output', '')) tool_output = data.get("tool_output", data.get("output", ""))
session_id = data.get('session_id', 'unknown') session_id = data.get("session_id", "unknown")
# Truncate large inputs/outputs # Truncate large inputs/outputs
if isinstance(tool_input, dict): if isinstance(tool_input, dict):
@@ -83,20 +83,19 @@ try:
tool_output_str = str(tool_output)[:5000] tool_output_str = str(tool_output)[:5000]
# Determine event type # 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({ print(json.dumps({
'parsed': True, "parsed": True,
'event': event, "event": event,
'tool': tool_name, "tool": tool_name,
'input': tool_input_str if event == 'tool_start' else None, "input": tool_input_str if event == "tool_start" else None,
'output': tool_output_str if event == 'tool_complete' else None, "output": tool_output_str if event == "tool_complete" else None,
'session': session_id "session": session_id
})) }))
except Exception as e: except Exception as e:
print(json.dumps({'parsed': False, 'error': str(e)})) print(json.dumps({"parsed": False, "error": str(e)}))
EOF ')
)
# Check if parsing succeeded # Check if parsing succeeded
PARSED_OK=$(echo "$PARSED" | python3 -c "import json,sys; print(json.load(sys.stdin).get('parsed', False))") 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 if [ "$PARSED_OK" != "True" ]; then
# Fallback: log raw input for debugging # Fallback: log raw input for debugging
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ") 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 exit 0
fi fi
@@ -121,10 +124,10 @@ fi
# Build and write observation # Build and write observation
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ") timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
python3 << EOF echo "$PARSED" | python3 -c "
import json import json, sys
parsed = json.loads('''$PARSED''') parsed = json.load(sys.stdin)
observation = { observation = {
'timestamp': '$timestamp', 'timestamp': '$timestamp',
'event': parsed['event'], 'event': parsed['event'],
@@ -139,7 +142,7 @@ if parsed['output']:
with open('$OBSERVATIONS_FILE', 'a') as f: with open('$OBSERVATIONS_FILE', 'a') as f:
f.write(json.dumps(observation) + '\n') f.write(json.dumps(observation) + '\n')
EOF "
# Signal observer if running # Signal observer if running
OBSERVER_PID_FILE="${CONFIG_DIR}/.observer.pid" OBSERVER_PID_FILE="${CONFIG_DIR}/.observer.pid"

View File

@@ -1,6 +1,6 @@
--- ---
name: django-verification 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 # Django Verification Loop

View File

@@ -1,6 +1,6 @@
--- ---
name: java-coding-standards 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 # Java Coding Standards

View File

@@ -1,11 +1,14 @@
---
name: project-guidelines-example
description: "Example project-specific skill template based on a real production application."
---
# Project Guidelines Skill (Example) # Project Guidelines Skill (Example)
This is an example of a project-specific skill. Use this as a template for your own projects. 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. Based on a real production application: [Zenith](https://zenith.chat) - AI-powered customer discovery platform.
---
## When to Use ## When to Use
Reference this skill when working on the specific project it's designed for. Project skills contain: Reference this skill when working on the specific project it's designed for. Project skills contain:

View File

@@ -1,6 +1,6 @@
--- ---
name: springboot-verification 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 # Spring Boot Verification Loop

View File

@@ -1,3 +1,8 @@
---
name: verification-loop
description: "A comprehensive verification system for Claude Code sessions."
---
# Verification Loop Skill # Verification Loop Skill
A comprehensive verification system for Claude Code sessions. A comprehensive verification system for Claude Code sessions.