start-vibing 1.1.1

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 (47) hide show
  1. package/README.md +149 -0
  2. package/dist/cli.js +199 -0
  3. package/package.json +42 -0
  4. package/template/.claude/CLAUDE.md +168 -0
  5. package/template/.claude/README.md +208 -0
  6. package/template/.claude/agents/analyzer.md +139 -0
  7. package/template/.claude/agents/commit-manager.md +231 -0
  8. package/template/.claude/agents/documenter.md +160 -0
  9. package/template/.claude/agents/domain-updater.md +200 -0
  10. package/template/.claude/agents/final-validator.md +182 -0
  11. package/template/.claude/agents/orchestrator.md +136 -0
  12. package/template/.claude/agents/quality-checker.md +264 -0
  13. package/template/.claude/agents/research.md +262 -0
  14. package/template/.claude/agents/security-auditor.md +199 -0
  15. package/template/.claude/agents/tester.md +572 -0
  16. package/template/.claude/agents/ui-ux-reviewer.md +180 -0
  17. package/template/.claude/commands/feature.md +102 -0
  18. package/template/.claude/commands/fix.md +80 -0
  19. package/template/.claude/commands/research.md +107 -0
  20. package/template/.claude/commands/validate.md +72 -0
  21. package/template/.claude/config/README.md +30 -0
  22. package/template/.claude/config/domain-mapping.json +26 -0
  23. package/template/.claude/config/project-config.json +53 -0
  24. package/template/.claude/config/quality-gates.json +46 -0
  25. package/template/.claude/config/security-rules.json +45 -0
  26. package/template/.claude/config/testing-config.json +168 -0
  27. package/template/.claude/hooks/SETUP.md +181 -0
  28. package/template/.claude/hooks/post-tool-use.py +155 -0
  29. package/template/.claude/hooks/pre-tool-use.py +159 -0
  30. package/template/.claude/hooks/security-check.js +202 -0
  31. package/template/.claude/hooks/stop-validation.py +155 -0
  32. package/template/.claude/hooks/user-prompt-submit.py +277 -0
  33. package/template/.claude/hooks/validate-commit.py +200 -0
  34. package/template/.claude/hooks/workflow-manager.py +350 -0
  35. package/template/.claude/settings.json +269 -0
  36. package/template/.claude/skills/codebase-knowledge/SKILL.md +145 -0
  37. package/template/.claude/skills/codebase-knowledge/TEMPLATE.md +35 -0
  38. package/template/.claude/skills/codebase-knowledge/domains/claude-system.md +321 -0
  39. package/template/.claude/skills/docs-tracker/SKILL.md +239 -0
  40. package/template/.claude/skills/final-check/SKILL.md +284 -0
  41. package/template/.claude/skills/quality-gate/SKILL.md +278 -0
  42. package/template/.claude/skills/research-cache/SKILL.md +207 -0
  43. package/template/.claude/skills/security-scan/SKILL.md +206 -0
  44. package/template/.claude/skills/test-coverage/SKILL.md +441 -0
  45. package/template/.claude/skills/ui-ux-audit/SKILL.md +254 -0
  46. package/template/.claude/workflow-state.schema.json +200 -0
  47. package/template/CLAUDE.md +96 -0
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Hook de Seguranca Pre-Tool
3
+ *
4
+ * Este hook e executado ANTES de qualquer ferramenta ser chamada.
5
+ * Sua funcao e bloquear acoes potencialmente perigosas.
6
+ *
7
+ * Baseado em: OpenSSF Security Guide for AI Code Assistants
8
+ * https://best.openssf.org/Security-Focused-Guide-for-AI-Code-Assistant-Instructions
9
+ */
10
+
11
+ // Padroes perigosos que devem ser bloqueados
12
+ const DANGEROUS_PATTERNS = {
13
+ // Comandos destrutivos
14
+ commands: [
15
+ /rm\s+-rf\s+[\/~]/i, // rm -rf com path perigoso
16
+ /rm\s+-rf\s+\*/i, // rm -rf *
17
+ /sudo\s+rm/i, // sudo rm
18
+ /mkfs/i, // formatar disco
19
+ /dd\s+if=/i, // dd (pode destruir dados)
20
+ />\s*\/dev\//i, // escrever em devices
21
+ /chmod\s+777/i, // permissoes muito abertas
22
+ /curl.*\|\s*(ba)?sh/i, // curl pipe to shell
23
+ /wget.*\|\s*(ba)?sh/i, // wget pipe to shell
24
+ ],
25
+
26
+ // Padroes de codigo inseguro
27
+ code: [
28
+ /eval\s*\(/i, // eval()
29
+ /new\s+Function\s*\(/i, // new Function()
30
+ /innerHTML\s*=/i, // innerHTML assignment (XSS)
31
+ /document\.write\s*\(/i, // document.write (XSS)
32
+ /dangerouslySetInnerHTML/i, // React dangerous prop
33
+ /\$\{.*\}\s*\)/i, // Template injection em queries
34
+ ],
35
+
36
+ // Exposicao de dados sensiveis
37
+ sensitive: [
38
+ /password\s*[:=]/i, // Senha hardcoded
39
+ /api[_-]?key\s*[:=]/i, // API key hardcoded
40
+ /secret\s*[:=]/i, // Secret hardcoded
41
+ /private[_-]?key/i, // Private key
42
+ /BEGIN\s+(RSA|DSA|EC)\s+PRIVATE/i, // Chave privada PEM
43
+ ],
44
+
45
+ // Patterns especificos do projeto
46
+ project: [
47
+ /userId.*req\.body/i, // userId do request body
48
+ /userId.*input\./i, // userId do input tRPC
49
+ /findById\(.*input/i, // Query sem validacao de owner
50
+ /z\.any\(\)/i, // Zod any (sem validacao)
51
+ ],
52
+ };
53
+
54
+ // Arquivos que nao devem ser modificados
55
+ const PROTECTED_FILES = ['.env', '.env.local', '.env.production', '.env.development', 'bun.lockb'];
56
+
57
+ // Diretorios que nao devem ser acessados
58
+ const PROTECTED_DIRS = ['/etc', '/var', '/usr', '/root', '/home', 'node_modules', '.git/objects'];
59
+
60
+ /**
61
+ * Verifica se um comando/codigo contem padroes perigosos
62
+ * @param {string} content - Conteudo a verificar
63
+ * @param {string} category - Categoria de padroes
64
+ * @returns {Object} - { blocked: boolean, reason: string }
65
+ */
66
+ function checkDangerousPatterns(content, category) {
67
+ const patterns = DANGEROUS_PATTERNS[category] || [];
68
+
69
+ for (const pattern of patterns) {
70
+ if (pattern.test(content)) {
71
+ return {
72
+ blocked: true,
73
+ reason: `Padrao perigoso detectado: ${pattern.toString()}`,
74
+ category,
75
+ };
76
+ }
77
+ }
78
+
79
+ return { blocked: false };
80
+ }
81
+
82
+ /**
83
+ * Verifica se um arquivo e protegido
84
+ * @param {string} filePath - Caminho do arquivo
85
+ * @returns {boolean}
86
+ */
87
+ function isProtectedFile(filePath) {
88
+ return PROTECTED_FILES.some(
89
+ (protected) => filePath.endsWith(protected) || filePath.includes(protected)
90
+ );
91
+ }
92
+
93
+ /**
94
+ * Verifica se um diretorio e protegido
95
+ * @param {string} dirPath - Caminho do diretorio
96
+ * @returns {boolean}
97
+ */
98
+ function isProtectedDir(dirPath) {
99
+ return PROTECTED_DIRS.some(
100
+ (protected) => dirPath.startsWith(protected) || dirPath.includes(protected)
101
+ );
102
+ }
103
+
104
+ /**
105
+ * Hook principal - executado antes de cada tool call
106
+ * @param {Object} toolCall - Dados da chamada de ferramenta
107
+ * @returns {Object} - { allowed: boolean, reason?: string }
108
+ */
109
+ function preToolHook(toolCall) {
110
+ const { name, args } = toolCall;
111
+
112
+ // Verificar comandos bash
113
+ if (name === 'bash' && args.command) {
114
+ const result = checkDangerousPatterns(args.command, 'commands');
115
+ if (result.blocked) {
116
+ return {
117
+ allowed: false,
118
+ reason: `Comando bloqueado: ${result.reason}`,
119
+ };
120
+ }
121
+ }
122
+
123
+ // Verificar escrita de arquivos
124
+ if (['file_write', 'file_edit'].includes(name)) {
125
+ // Verificar arquivo protegido
126
+ if (args.path && isProtectedFile(args.path)) {
127
+ return {
128
+ allowed: false,
129
+ reason: `Arquivo protegido: ${args.path}`,
130
+ };
131
+ }
132
+
133
+ // Verificar conteudo perigoso
134
+ if (args.content) {
135
+ const codeResult = checkDangerousPatterns(args.content, 'code');
136
+ if (codeResult.blocked) {
137
+ return {
138
+ allowed: false,
139
+ reason: `Codigo inseguro: ${codeResult.reason}`,
140
+ };
141
+ }
142
+
143
+ const sensitiveResult = checkDangerousPatterns(args.content, 'sensitive');
144
+ if (sensitiveResult.blocked) {
145
+ return {
146
+ allowed: false,
147
+ reason: `Dados sensiveis detectados: ${sensitiveResult.reason}`,
148
+ };
149
+ }
150
+
151
+ const projectResult = checkDangerousPatterns(args.content, 'project');
152
+ if (projectResult.blocked) {
153
+ return {
154
+ allowed: false,
155
+ reason: `Violacao de regra do projeto: ${projectResult.reason}`,
156
+ };
157
+ }
158
+ }
159
+ }
160
+
161
+ // Verificar leitura de diretorios protegidos
162
+ if (name === 'file_read' && args.path) {
163
+ if (isProtectedDir(args.path)) {
164
+ return {
165
+ allowed: false,
166
+ reason: `Diretorio protegido: ${args.path}`,
167
+ };
168
+ }
169
+ }
170
+
171
+ // Permitir por padrao
172
+ return { allowed: true };
173
+ }
174
+
175
+ /**
176
+ * Log de seguranca para auditoria
177
+ * @param {string} action - Acao tomada
178
+ * @param {Object} details - Detalhes
179
+ */
180
+ function logSecurityEvent(action, details) {
181
+ const timestamp = new Date().toISOString();
182
+ const logEntry = {
183
+ timestamp,
184
+ action,
185
+ ...details,
186
+ };
187
+
188
+ // Em producao, enviar para sistema de logging
189
+ console.log('[SECURITY]', JSON.stringify(logEntry));
190
+ }
191
+
192
+ // Exportar para uso pelo SDK
193
+ module.exports = {
194
+ preToolHook,
195
+ checkDangerousPatterns,
196
+ isProtectedFile,
197
+ isProtectedDir,
198
+ logSecurityEvent,
199
+ DANGEROUS_PATTERNS,
200
+ PROTECTED_FILES,
201
+ PROTECTED_DIRS,
202
+ };
@@ -0,0 +1,155 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Stop Hook - Workflow Validation Before Stopping
4
+
5
+ This hook validates that the workflow was properly executed before
6
+ allowing Claude to stop. If validation fails, Claude is forced to continue.
7
+
8
+ Exit codes:
9
+ - 0: Allow stop (or output JSON to block)
10
+ """
11
+
12
+ import json
13
+ import sys
14
+ import os
15
+ from pathlib import Path
16
+
17
+ PROJECT_DIR = os.environ.get('CLAUDE_PROJECT_DIR', os.getcwd())
18
+ WORKFLOW_STATE_PATH = Path(PROJECT_DIR) / '.claude' / 'workflow-state.json'
19
+
20
+
21
+ def load_workflow_state():
22
+ """Load current workflow state"""
23
+ if not WORKFLOW_STATE_PATH.exists():
24
+ return None
25
+ try:
26
+ with open(WORKFLOW_STATE_PATH) as f:
27
+ return json.load(f)
28
+ except (json.JSONDecodeError, IOError):
29
+ return None
30
+
31
+
32
+ def validate_workflow(state: dict) -> tuple[bool, list[str]]:
33
+ """Validate workflow completion"""
34
+ issues = []
35
+
36
+ if not state or not state.get('currentTask'):
37
+ # No task, allow stop
38
+ return True, []
39
+
40
+ task = state['currentTask']
41
+ task_type = task.get('type', 'feature')
42
+ agents = task.get('agents', {})
43
+ modified_files = task.get('modifiedFiles', [])
44
+
45
+ # Skip validation for research/config tasks
46
+ if task_type in ['research', 'config']:
47
+ return True, []
48
+
49
+ # Check required agents executed
50
+ required_agents = {
51
+ 'feature': ['orchestrator', 'analyzer', 'research', 'tester', 'securityAuditor', 'qualityChecker', 'finalValidator', 'domainUpdater'],
52
+ 'fix': ['analyzer', 'research', 'tester', 'securityAuditor', 'qualityChecker', 'finalValidator', 'domainUpdater'],
53
+ 'refactor': ['analyzer', 'tester', 'qualityChecker', 'finalValidator', 'domainUpdater'],
54
+ }
55
+
56
+ for agent in required_agents.get(task_type, []):
57
+ agent_status = agents.get(agent, {})
58
+ if not agent_status.get('executed'):
59
+ issues.append(f"Agent '{agent}' has not executed")
60
+ elif agent_status.get('result') == 'vetoed':
61
+ issues.append(f"Agent '{agent}' VETOED - must resolve before stopping")
62
+
63
+ # Check if files were modified without tests
64
+ if modified_files and task_type in ['feature', 'fix']:
65
+ tests_created = task.get('testsCreated', [])
66
+ # Exclude: tests, specs, docs, markdown, and .claude config files
67
+ source_files = [m for m in modified_files if not any(
68
+ p in m['path'].lower() for p in ['test', 'spec', '.md', 'docs/', '.claude/']
69
+ )]
70
+
71
+ if source_files and not tests_created:
72
+ issues.append(f"Modified {len(source_files)} source file(s) but no tests created")
73
+
74
+ # Check documentation (skip for .claude config files)
75
+ if modified_files and task_type == 'feature':
76
+ non_config_files = [m for m in modified_files if '.claude/' not in m['path']]
77
+ if non_config_files:
78
+ docs_updated = task.get('docsUpdated', [])
79
+ if not docs_updated:
80
+ issues.append("No documentation updated for feature")
81
+
82
+ # Check quality gates
83
+ quality = task.get('qualityGates', {})
84
+ for gate in ['typecheck', 'lint', 'build']:
85
+ gate_result = quality.get(gate, {})
86
+ if gate_result and not gate_result.get('passed'):
87
+ issues.append(f"Quality gate '{gate}' failed")
88
+
89
+ # Check security audit
90
+ security = task.get('securityAudit', {})
91
+ if security.get('result') == 'vetoed':
92
+ issues.append("Security audit VETOED - must resolve vulnerabilities")
93
+
94
+ # Check final validation
95
+ final = task.get('finalValidation', {})
96
+ if final.get('executed') and not final.get('readyToCommit'):
97
+ issues.append("Final validation not approved for commit")
98
+
99
+ # Check domain-updater (critical for knowledge retention)
100
+ domain_updater = agents.get('domainUpdater', {})
101
+ if modified_files and not domain_updater.get('executed'):
102
+ issues.append("Domain updater has not run - domains must be updated with session learnings")
103
+
104
+ # Check commit-manager (critical for persisting changes - FINAL step)
105
+ commit_manager = agents.get('commitManager', {})
106
+ if domain_updater.get('executed') and not commit_manager.get('executed'):
107
+ issues.append("Commit-manager has not run - changes must be committed before session ends")
108
+
109
+ return len(issues) == 0, issues
110
+
111
+
112
+ def main():
113
+ # Read hook input
114
+ try:
115
+ hook_input = json.load(sys.stdin)
116
+ except json.JSONDecodeError:
117
+ sys.exit(0)
118
+
119
+ # Load state
120
+ state = load_workflow_state()
121
+
122
+ # Validate
123
+ is_valid, issues = validate_workflow(state)
124
+
125
+ if is_valid:
126
+ # Allow stop
127
+ sys.exit(0)
128
+ else:
129
+ # Block stop and force continuation
130
+ output = {
131
+ "decision": "block",
132
+ "reason": f"""WORKFLOW INCOMPLETE - Cannot stop yet.
133
+
134
+ Issues found:
135
+ {chr(10).join(f' ❌ {issue}' for issue in issues)}
136
+
137
+ You must complete these steps before stopping:
138
+ 1. Execute all required agents
139
+ 2. Resolve any VETOs
140
+ 3. Create tests for modified files
141
+ 4. Update documentation
142
+ 5. Pass all quality gates
143
+ 6. Get final validation approval
144
+ 7. Run domain-updater to update domains with session learnings
145
+ 8. Run commit-manager to commit changes (FINAL step)
146
+
147
+ Resume the workflow to address these issues."""
148
+ }
149
+
150
+ print(json.dumps(output))
151
+ sys.exit(0)
152
+
153
+
154
+ if __name__ == '__main__':
155
+ main()
@@ -0,0 +1,277 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ UserPromptSubmit Hook - Agent Selection Enforcement
4
+
5
+ This hook runs BEFORE Claude processes any user prompt and:
6
+ 1. Lists all available agents
7
+ 2. Analyzes the prompt to suggest the best agent
8
+ 3. Reminds Claude to follow the workflow strictly
9
+ 4. Prevents over-engineering and redundant file creation
10
+
11
+ Output is sent to Claude as context before processing the user's request.
12
+
13
+ Based on official Claude Code documentation:
14
+ https://code.claude.com/docs/en/hooks.md
15
+ """
16
+
17
+ import json
18
+ import sys
19
+ import os
20
+ import re
21
+ from pathlib import Path
22
+
23
+ PROJECT_DIR = os.environ.get('CLAUDE_PROJECT_DIR', os.getcwd())
24
+ WORKFLOW_STATE_PATH = Path(PROJECT_DIR) / '.claude' / 'workflow-state.json'
25
+ SETTINGS_PATH = Path(PROJECT_DIR) / '.claude' / 'settings.json'
26
+
27
+ # Agent definitions with triggers
28
+ AGENTS = {
29
+ 'orchestrator': {
30
+ 'description': 'Coordinates entire development flow',
31
+ 'triggers': ['implement feature', 'build', 'create', 'fix and test', 'full workflow', 'multi-step'],
32
+ 'priority': 1,
33
+ 'when': 'Task requires >2 agents or touches >3 files'
34
+ },
35
+ 'analyzer': {
36
+ 'description': 'Analyzes impact before code modification',
37
+ 'triggers': ['implement', 'add feature', 'fix bug', 'refactor', 'change', 'modify', 'update code'],
38
+ 'priority': 2,
39
+ 'when': 'BEFORE any Edit/Write to source files'
40
+ },
41
+ 'research': {
42
+ 'description': 'Researches best practices and recent solutions (2024-2025)',
43
+ 'triggers': ['research', 'investigate', 'study', 'best practice', 'how to', 'pattern'],
44
+ 'priority': 3,
45
+ 'when': 'AFTER analyzer - finds best practices before implementation'
46
+ },
47
+ 'ui-ux-reviewer': {
48
+ 'description': 'Reviews UI/UX and researches competitors',
49
+ 'triggers': ['ui', 'component', 'page', 'design', 'layout', 'style', 'responsive', 'frontend'],
50
+ 'priority': 3,
51
+ 'when': 'Files in components/, app/, or .tsx with JSX'
52
+ },
53
+ 'documenter': {
54
+ 'description': 'Creates and maintains documentation',
55
+ 'triggers': ['document', 'readme', 'docs', 'explain'],
56
+ 'priority': 4,
57
+ 'when': 'After code implementation completes'
58
+ },
59
+ 'tester': {
60
+ 'description': 'Creates unit tests (Vitest) and E2E tests (Playwright)',
61
+ 'triggers': ['test', 'coverage', 'spec', 'e2e'],
62
+ 'priority': 5,
63
+ 'when': 'After any code implementation'
64
+ },
65
+ 'security-auditor': {
66
+ 'description': 'Audits security (CAN VETO)',
67
+ 'triggers': ['auth', 'session', 'password', 'token', 'api', 'database', 'user data', 'security'],
68
+ 'priority': 6,
69
+ 'when': 'Code touches auth/, api/, server/, or sensitive data',
70
+ 'can_veto': True
71
+ },
72
+ 'quality-checker': {
73
+ 'description': 'Runs typecheck, lint, test, build',
74
+ 'triggers': ['check', 'verify', 'validate', 'run tests', 'quality'],
75
+ 'priority': 7,
76
+ 'when': 'After implementation and tests complete'
77
+ },
78
+ 'final-validator': {
79
+ 'description': 'Final validation before commit (CAN VETO)',
80
+ 'triggers': ['final', 'commit ready', 'approve'],
81
+ 'priority': 8,
82
+ 'when': 'Before any commit operation',
83
+ 'can_veto': True
84
+ },
85
+ 'commit-manager': {
86
+ 'description': 'Creates conventional commits and completes workflow',
87
+ 'triggers': ['commit', 'save changes', 'push', 'finalize', 'git'],
88
+ 'priority': 10,
89
+ 'when': 'FINAL step - after domain-updater, runs complete-task'
90
+ },
91
+ 'domain-updater': {
92
+ 'description': 'Updates domain knowledge with session learnings',
93
+ 'triggers': ['update domain', 'document learnings', 'session end'],
94
+ 'priority': 9,
95
+ 'when': 'BEFORE commit-manager - updates domains so git stays clean'
96
+ }
97
+ }
98
+
99
+ # Workflow sequences (research after analyzer, domain-updater BEFORE commit-manager for clean git)
100
+ WORKFLOWS = {
101
+ 'feature': ['analyzer', 'research', 'ui-ux-reviewer', 'documenter', 'tester', 'security-auditor', 'quality-checker', 'final-validator', 'domain-updater', 'commit-manager'],
102
+ 'fix': ['analyzer', 'research', 'tester', 'security-auditor', 'quality-checker', 'final-validator', 'domain-updater', 'commit-manager'],
103
+ 'refactor': ['analyzer', 'tester', 'quality-checker', 'final-validator', 'domain-updater', 'commit-manager'],
104
+ 'config': ['quality-checker', 'domain-updater', 'commit-manager']
105
+ }
106
+
107
+
108
+ def load_workflow_state():
109
+ """Load current workflow state"""
110
+ if not WORKFLOW_STATE_PATH.exists():
111
+ return None
112
+ try:
113
+ with open(WORKFLOW_STATE_PATH) as f:
114
+ return json.load(f)
115
+ except (json.JSONDecodeError, IOError):
116
+ return None
117
+
118
+
119
+ def detect_task_type(prompt: str) -> str:
120
+ """Detect task type from prompt"""
121
+ prompt_lower = prompt.lower()
122
+
123
+ if any(word in prompt_lower for word in ['bug', 'fix', 'error', 'broken', 'not working', 'issue']):
124
+ return 'fix'
125
+ elif any(word in prompt_lower for word in ['refactor', 'restructure', 'reorganize', 'clean up']):
126
+ return 'refactor'
127
+ elif any(word in prompt_lower for word in ['config', 'setting', 'env', 'package.json', 'tsconfig']):
128
+ return 'config'
129
+ else:
130
+ return 'feature'
131
+
132
+
133
+ def detect_best_agent(prompt: str) -> tuple[str, str]:
134
+ """Detect best agent for the task"""
135
+ prompt_lower = prompt.lower()
136
+
137
+ # Check for multi-step tasks first
138
+ multi_step_indicators = ['and then', 'after that', 'also', 'implement', 'build', 'create feature']
139
+ if any(indicator in prompt_lower for indicator in multi_step_indicators):
140
+ return 'orchestrator', 'Multi-step task detected - orchestrator will coordinate all agents'
141
+
142
+ # Check each agent's triggers
143
+ matches = []
144
+ for agent_name, agent_info in AGENTS.items():
145
+ for trigger in agent_info['triggers']:
146
+ if trigger in prompt_lower:
147
+ matches.append((agent_name, agent_info['priority'], trigger))
148
+
149
+ if matches:
150
+ # Sort by priority (lower is better)
151
+ matches.sort(key=lambda x: x[1])
152
+ best = matches[0]
153
+ return best[0], f"Matched trigger '{best[2]}'"
154
+
155
+ # Default to orchestrator for unknown tasks
156
+ return 'orchestrator', 'No specific trigger matched - orchestrator will analyze'
157
+
158
+
159
+ def format_agent_list() -> str:
160
+ """Format agent list for display"""
161
+ lines = []
162
+ for name, info in sorted(AGENTS.items(), key=lambda x: x[1]['priority']):
163
+ veto = ' [CAN VETO]' if info.get('can_veto') else ''
164
+ lines.append(f" - {name}: {info['description']}{veto}")
165
+ return '\n'.join(lines)
166
+
167
+
168
+ def format_workflow_status(state: dict) -> str:
169
+ """Format current workflow status"""
170
+ if not state or not state.get('currentTask'):
171
+ return "STATUS: No active task. Start with orchestrator or workflow-manager.py start-task"
172
+
173
+ task = state['currentTask']
174
+ agents = task.get('agents', {})
175
+
176
+ executed = [name for name, status in agents.items() if status.get('executed')]
177
+ pending = [name for name, status in agents.items() if not status.get('executed')]
178
+
179
+ return f"""STATUS: Task active
180
+ ID: {task.get('id', 'unknown')}
181
+ Type: {task.get('type', 'unknown')}
182
+ Description: {task.get('description', 'unknown')}
183
+ Executed: {', '.join(executed) if executed else 'none'}
184
+ Pending: {', '.join(pending) if pending else 'none'}
185
+ Approved files: {len(task.get('approvedFiles', []))}"""
186
+
187
+
188
+ def main():
189
+ # Read hook input from stdin
190
+ try:
191
+ hook_input = json.load(sys.stdin)
192
+ except json.JSONDecodeError:
193
+ hook_input = {}
194
+
195
+ # Get user prompt (may not be available in all hook contexts)
196
+ prompt = hook_input.get('user_prompt', hook_input.get('prompt', ''))
197
+
198
+ # Load current state
199
+ state = load_workflow_state()
200
+
201
+ # Detect task type and best agent
202
+ task_type = detect_task_type(prompt) if prompt else 'unknown'
203
+ best_agent, reason = detect_best_agent(prompt) if prompt else ('orchestrator', 'Default')
204
+
205
+ # Build output message
206
+ output = f"""
207
+ ================================================================================
208
+ WORKFLOW ENFORCEMENT - UserPromptSubmit Hook
209
+ ================================================================================
210
+
211
+ AVAILABLE AGENTS:
212
+ {format_agent_list()}
213
+
214
+ TASK ANALYSIS:
215
+ Detected type: {task_type}
216
+ Recommended agent: {best_agent}
217
+ Reason: {reason}
218
+ Workflow sequence: {' -> '.join(WORKFLOWS.get(task_type, WORKFLOWS['feature']))}
219
+
220
+ {format_workflow_status(state)}
221
+
222
+ ================================================================================
223
+ CRITICAL: INVOKE AGENTS VIA TASK TOOL - NOT MANUALLY
224
+ ================================================================================
225
+
226
+ You MUST use the Task tool with subagent_type to invoke agents.
227
+ DO NOT execute agent logic manually - INVOKE the agent properly.
228
+
229
+ AGENTS THAT CAN BE INVOKED VIA TASK TOOL:
230
+ - commit-manager: Use Task(subagent_type="commit-manager", prompt="...")
231
+ - analyzer: Use Task(subagent_type="analyzer", prompt="...")
232
+ - tester: Use Task(subagent_type="tester", prompt="...")
233
+ - security-auditor: Use Task(subagent_type="security-auditor", prompt="...")
234
+ - quality-checker: Use Task(subagent_type="quality-checker", prompt="...")
235
+ - final-validator: Use Task(subagent_type="final-validator", prompt="...")
236
+ - documenter: Use Task(subagent_type="documenter", prompt="...")
237
+ - ui-ux-reviewer: Use Task(subagent_type="ui-ux-reviewer", prompt="...")
238
+ - orchestrator: Use Task(subagent_type="orchestrator", prompt="...")
239
+
240
+ WRONG (manual execution):
241
+ "Let me create the commit..." then git commands directly
242
+
243
+ CORRECT (agent invocation):
244
+ Use Task tool with subagent_type="commit-manager"
245
+
246
+ ================================================================================
247
+ MANDATORY RULES:
248
+ ================================================================================
249
+
250
+ 1. I WILL use Task tool to invoke agent: {best_agent}
251
+ 2. I WILL NOT execute agent logic manually - ALWAYS invoke via Task tool
252
+ 3. I WILL NOT create redundant files
253
+ 4. I WILL NOT over-engineer - keep solutions simple and focused
254
+ 5. I WILL follow the workflow sequence strictly
255
+ 6. I MUST run analyzer BEFORE any Edit/Write to source files
256
+ 7. I MUST run commit-manager via Task tool for ALL commits
257
+ 8. After commit, I MUST update domains and run complete-task
258
+
259
+ WORKFLOW COMMANDS (for tracking, not replacement for agents):
260
+ Start task: python .claude/hooks/workflow-manager.py start-task --type {task_type} --description "..."
261
+ Approve files: python .claude/hooks/workflow-manager.py approve-files --files "path/to/file"
262
+
263
+ ================================================================================
264
+ """
265
+
266
+ # Return as JSON with decision to continue
267
+ result = {
268
+ "continue": True,
269
+ "systemMessage": output
270
+ }
271
+
272
+ print(json.dumps(result))
273
+ sys.exit(0)
274
+
275
+
276
+ if __name__ == '__main__':
277
+ main()