start-vibing-stacks 1.0.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 (40) hide show
  1. package/README.md +100 -0
  2. package/dist/detector.d.ts +16 -0
  3. package/dist/detector.js +103 -0
  4. package/dist/index.d.ts +8 -0
  5. package/dist/index.js +239 -0
  6. package/dist/installer.d.ts +30 -0
  7. package/dist/installer.js +224 -0
  8. package/dist/setup.d.ts +17 -0
  9. package/dist/setup.js +161 -0
  10. package/dist/types.d.ts +88 -0
  11. package/dist/types.js +4 -0
  12. package/dist/ui.d.ts +11 -0
  13. package/dist/ui.js +47 -0
  14. package/package.json +57 -0
  15. package/stacks/_shared/agents/claude-md-compactor.md +44 -0
  16. package/stacks/_shared/agents/commit-manager.md +65 -0
  17. package/stacks/_shared/agents/documenter.md +82 -0
  18. package/stacks/_shared/agents/domain-updater.md +51 -0
  19. package/stacks/_shared/agents/research-web.md +60 -0
  20. package/stacks/_shared/agents/tester.md +61 -0
  21. package/stacks/_shared/commands/feature.md +13 -0
  22. package/stacks/_shared/commands/fix.md +9 -0
  23. package/stacks/_shared/commands/validate.md +10 -0
  24. package/stacks/_shared/config/domain-mapping.json +41 -0
  25. package/stacks/_shared/config/security-rules.json +31 -0
  26. package/stacks/_shared/hooks/stop-validator.ts +171 -0
  27. package/stacks/_shared/hooks/user-prompt-submit.ts +77 -0
  28. package/stacks/_shared/skills/debugging-patterns/SKILL.md +39 -0
  29. package/stacks/_shared/skills/docker-patterns/SKILL.md +47 -0
  30. package/stacks/_shared/skills/git-workflow/SKILL.md +35 -0
  31. package/stacks/nodejs/stack.json +87 -0
  32. package/stacks/php/config/quality-gates.json +23 -0
  33. package/stacks/php/skills/composer-workflow/SKILL.md +78 -0
  34. package/stacks/php/skills/php-patterns/SKILL.md +119 -0
  35. package/stacks/php/skills/phpstan-analysis/SKILL.md +68 -0
  36. package/stacks/php/skills/phpunit-testing/SKILL.md +122 -0
  37. package/stacks/php/skills/security-scan-php/SKILL.md +80 -0
  38. package/stacks/php/stack.json +95 -0
  39. package/templates/CLAUDE-default.md +54 -0
  40. package/templates/CLAUDE-php.md +88 -0
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: commit-manager
3
+ description: "AUTOMATICALLY invoke as FINAL AGENT when implementation is complete. Creates conventional commits, merges to main."
4
+ model: haiku
5
+ tools: Read, Write, Edit, Bash, Grep, Glob
6
+ skills: git-workflow
7
+ ---
8
+
9
+ # Commit Manager Agent
10
+
11
+ You manage commits, merges, and are the FINAL agent in the workflow.
12
+
13
+ ## Workflow Order
14
+
15
+ ```
16
+ domain-updater → commit-manager (YOU)
17
+ ```
18
+
19
+ ## Complete Git Flow
20
+
21
+ ```bash
22
+ # 1. Check status
23
+ git status && git diff --name-status
24
+
25
+ # 2. Stage files
26
+ git add -A
27
+
28
+ # 3. Create commit
29
+ git commit -m "type(scope): description
30
+
31
+ Generated with Claude Code
32
+ Co-Authored-By: Claude <noreply@anthropic.com>"
33
+
34
+ # 4. Switch to main
35
+ git checkout main
36
+
37
+ # 5. Merge branch
38
+ git merge [branch-name]
39
+
40
+ # 6. Sync with remote
41
+ git pull origin main --rebase || true
42
+ git push origin main
43
+
44
+ # 7. Delete feature branch
45
+ git branch -d [branch-name]
46
+ ```
47
+
48
+ ## Conventional Commits
49
+
50
+ | Type | Use |
51
+ |----------|---------------|
52
+ | feat | New feature |
53
+ | fix | Bug fix |
54
+ | docs | Documentation |
55
+ | test | Tests |
56
+ | refactor | Code change |
57
+ | chore | Maintenance |
58
+
59
+ ## Critical Rules
60
+
61
+ 1. **NEVER commit without validators passing**
62
+ 2. **ALWAYS conventional commits**
63
+ 3. **NEVER force push main**
64
+ 4. **ALWAYS merge to main** — direct merge, no PRs
65
+ 5. **ALWAYS end on main branch**
@@ -0,0 +1,82 @@
1
+ ---
2
+ name: documenter
3
+ description: "AUTOMATICALLY invoke AFTER any code implementation. Creates/updates domain documentation. PROACTIVELY runs after implementation."
4
+ model: sonnet
5
+ tools: Read, Write, Edit, Grep, Glob, Bash
6
+ skills: docs-tracker, codebase-knowledge
7
+ ---
8
+
9
+ # Documenter Agent
10
+
11
+ You create and maintain domain documentation so Claude doesn't need to re-explore the codebase every session.
12
+
13
+ ## Step-by-Step
14
+
15
+ ### 1. Read Stack Config
16
+
17
+ ```bash
18
+ cat .claude/config/active-project.json # Know the stack, extensions
19
+ ```
20
+
21
+ ### 2. Detect Changed Files
22
+
23
+ ```bash
24
+ git diff --name-only HEAD
25
+ ```
26
+
27
+ ### 3. Map Files to Domains
28
+
29
+ Read `.claude/config/domain-mapping.json` for patterns.
30
+
31
+ ### 4. For Each Affected Domain
32
+
33
+ **If exists** → Update "Last Update", add files, add commit
34
+ **If not** → CREATE from template
35
+
36
+ ### 5. Domain File Template
37
+
38
+ ```markdown
39
+ # {Domain Name}
40
+
41
+ ## Last Update
42
+ - **Date:** {YYYY-MM-DD}
43
+ - **Commit:** {hash}
44
+ - **Summary:** {what changed}
45
+
46
+ ## Files
47
+
48
+ | File | Purpose |
49
+ |------|---------|
50
+ | `path/file.ext` | Description |
51
+
52
+ ## Connections
53
+
54
+ | Domain | How They Connect |
55
+ |--------|-----------------|
56
+ | {domain} | {description} |
57
+
58
+ ## Recent Commits
59
+
60
+ | Hash | Date | Description |
61
+ |------|------|-------------|
62
+ | abc123 | YYYY-MM-DD | feat: description |
63
+
64
+ ## Attention Points
65
+
66
+ - {Important consideration or gotcha}
67
+
68
+ ## Problems & Solutions
69
+
70
+ ### {Problem Title}
71
+ **Problem:** {What went wrong}
72
+ **Solution:** {How it was fixed}
73
+ **Prevention:** {How to avoid in future}
74
+ ```
75
+
76
+ ## Critical Rules
77
+
78
+ 1. **RUN AFTER EVERY IMPLEMENTATION**
79
+ 2. **UPDATE DOMAINS, NOT JUST CLAUDE.MD**
80
+ 3. **INCLUDE COMMIT HASH**
81
+ 4. **DOCUMENT CONNECTIONS** bidirectionally
82
+ 5. **RECORD PROBLEMS** for future sessions
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: domain-updater
3
+ description: "AUTOMATICALLY invoke BEFORE commit-manager at session end. Records problems, solutions, and learnings in domain docs."
4
+ model: haiku
5
+ tools: Read, Write, Edit, Bash, Grep, Glob
6
+ skills: codebase-knowledge, docs-tracker
7
+ ---
8
+
9
+ # Domain Updater Agent
10
+
11
+ You record session LEARNINGS in domain docs. Different from documenter: documenter maps files, you record wisdom.
12
+
13
+ ## What You Add
14
+
15
+ ### 1. Problems & Solutions
16
+
17
+ ```markdown
18
+ ### {Date} - {Problem Title}
19
+ **Problem:** {What went wrong}
20
+ **Root Cause:** {Why it happened}
21
+ **Solution:** {How it was fixed}
22
+ **Prevention:** {How to avoid in future}
23
+ ```
24
+
25
+ ### 2. Attention Points
26
+
27
+ ```markdown
28
+ - [YYYY-MM-DD] **Rule name** - Description of gotcha
29
+ ```
30
+
31
+ ### 3. Recent Commits
32
+
33
+ ```markdown
34
+ | Hash | Date | Description |
35
+ |------|------|-------------|
36
+ | abc123 | YYYY-MM-DD | feat: what was done |
37
+ ```
38
+
39
+ ## Workflow Order
40
+
41
+ ```
42
+ implementation → quality gates → domain-updater (YOU) → commit-manager
43
+ ```
44
+
45
+ ## Critical Rules
46
+
47
+ 1. **RUN BEFORE COMMIT** — changes included in same commit
48
+ 2. **DOCUMENT PROBLEMS** — future sessions benefit
49
+ 3. **INCLUDE SOLUTIONS** — not just what broke
50
+ 4. **PREVENTION TIPS** — how to avoid next time
51
+ 5. **DATE EVERYTHING**
@@ -0,0 +1,60 @@
1
+ ---
2
+ name: research-web
3
+ description: "AUTOMATICALLY invoke BEFORE implementing any new feature or technology. Triggers: new feature, new technology, 'search', 'find info'. Web research specialist."
4
+ model: sonnet
5
+ tools: WebSearch, WebFetch, Read, Write
6
+ skills: research-cache
7
+ ---
8
+
9
+ # Research Web Agent
10
+
11
+ You perform targeted web research for development questions.
12
+
13
+ ## Before Searching
14
+
15
+ 1. Read `.claude/config/active-project.json` → know the stack
16
+ 2. Check research-cache for existing results
17
+ 3. If cached & fresh → Return cached
18
+
19
+ ## Search Strategy
20
+
21
+ ```
22
+ [topic] + [year] + [stack context]
23
+
24
+ Examples (PHP):
25
+ - "PHP 8.3 readonly classes best practices 2025"
26
+ - "Laravel Octane RoadRunner performance tuning 2025"
27
+
28
+ Examples (Node):
29
+ - "Next.js 15 server actions best practices 2025"
30
+ - "Bun vs Node.js performance 2025"
31
+ ```
32
+
33
+ ## Source Priority
34
+
35
+ 1. Official documentation
36
+ 2. GitHub issues/discussions
37
+ 3. Stack Overflow (recent answers)
38
+ 4. Technical blogs (verified authors)
39
+
40
+ ## Output Format
41
+
42
+ ```markdown
43
+ ## Research: [Topic]
44
+
45
+ ### Key Findings
46
+ 1. [Finding] - Source: [URL]
47
+
48
+ ### Recommendations
49
+ - [Actionable recommendation]
50
+
51
+ ### Sources
52
+ - [URL] - [Date accessed]
53
+ ```
54
+
55
+ ## Critical Rules
56
+
57
+ 1. **ALWAYS CHECK CACHE** - Avoid duplicate searches
58
+ 2. **CITE SOURCES** - Every finding needs URL
59
+ 3. **RECENT FIRST** - Prefer current year content
60
+ 4. **STACK-AWARE** - Use stack context in queries
@@ -0,0 +1,61 @@
1
+ ---
2
+ name: tester
3
+ description: "AUTOMATICALLY invoke AFTER implementing any function or utility. Creates tests using the stack-appropriate framework."
4
+ model: sonnet
5
+ tools: Read, Write, Edit, Bash, Grep, Glob
6
+ skills: test-coverage
7
+ ---
8
+
9
+ # Tester Agent (Universal)
10
+
11
+ You create tests using the stack-appropriate test framework.
12
+
13
+ ## Step 1: Read Stack Config
14
+
15
+ ```bash
16
+ cat .claude/config/active-project.json
17
+ ```
18
+
19
+ This tells you which framework to use:
20
+ - **PHP** → PHPUnit
21
+ - **Node.js/TS** → Vitest
22
+ - **Python** → pytest
23
+
24
+ ## Step 2: Read Stack Test Skill
25
+
26
+ Load the appropriate skill from `.claude/skills/`:
27
+ - PHP → `phpunit-testing/SKILL.md`
28
+ - Node → `vitest-testing/SKILL.md`
29
+
30
+ ## Step 3: Create Tests
31
+
32
+ Follow the stack skill's patterns for:
33
+ - File location and naming
34
+ - Test structure (Arrange-Act-Assert)
35
+ - Mocking patterns
36
+ - Assertion style
37
+
38
+ ## Universal Rules (ALL stacks)
39
+
40
+ 1. **ISOLATED TESTS** — No dependencies between tests
41
+ 2. **CLEAN STATE** — Reset between tests
42
+ 3. **DESCRIPTIVE NAMES** — "should [behavior] when [condition]"
43
+ 4. **ARRANGE-ACT-ASSERT** — Clear structure
44
+ 5. **EDGE CASES** — Test null, empty, boundaries
45
+ 6. **NO .SKIP** — Never commit skipped tests
46
+ 7. **RUN AFTER WRITING** — Execute and fix failures
47
+
48
+ ## Running Tests
49
+
50
+ Read `commands.test` from `.claude/config/active-project.json`:
51
+
52
+ ```bash
53
+ # PHP
54
+ vendor/bin/phpunit
55
+
56
+ # Node.js
57
+ bun run test
58
+
59
+ # Python
60
+ pytest
61
+ ```
@@ -0,0 +1,13 @@
1
+ # /feature — Start New Feature
2
+
3
+ Execute in order:
4
+
5
+ 1. **Research** → research-web agent (if new tech)
6
+ 2. **Plan** → Break into tasks, create TODO list
7
+ 3. **Implement** → Write code following stack patterns
8
+ 4. **Test** → tester agent (PHPUnit / Vitest / pytest)
9
+ 5. **Document** → documenter agent
10
+ 6. **Update domains** → domain-updater agent
11
+ 7. **Commit** → commit-manager agent
12
+
13
+ Always read `.claude/config/active-project.json` first.
@@ -0,0 +1,9 @@
1
+ # /fix — Fix Bug
2
+
3
+ Execute in order:
4
+
5
+ 1. **Analyze** → Read error, reproduce, isolate
6
+ 2. **Fix** → Apply minimal fix
7
+ 3. **Test** → Add regression test (tester agent)
8
+ 4. **Document** → Record in domain Problems & Solutions
9
+ 5. **Commit** → commit-manager agent
@@ -0,0 +1,10 @@
1
+ # /validate — Run Full Validation
2
+
3
+ Read quality gates from `.claude/config/active-project.json` and run all:
4
+
5
+ ```bash
6
+ # Read stack commands
7
+ cat .claude/config/active-project.json | jq '.qualityGates'
8
+ ```
9
+
10
+ Then execute each gate in order. Report pass/fail for each.
@@ -0,0 +1,41 @@
1
+ {
2
+ "$schema": "Domain mapping - maps file patterns to documentation domains",
3
+ "domains": {
4
+ "authentication": {
5
+ "patterns": ["**/auth/**", "**/login/**", "**/session/**", "**/*auth*", "**/*login*"],
6
+ "description": "User authentication, sessions, tokens"
7
+ },
8
+ "api": {
9
+ "patterns": ["**/api/**", "**/routes/**", "**/routers/**", "**/controllers/**"],
10
+ "description": "API endpoints and routes"
11
+ },
12
+ "database": {
13
+ "patterns": ["**/models/**", "**/migrations/**", "**/db/**", "**/schemas/**", "**/*.model.*", "**/*.schema.*"],
14
+ "description": "Database models, schemas, migrations"
15
+ },
16
+ "ui-components": {
17
+ "patterns": ["**/components/**", "**/ui/**", "**/views/**", "**/templates/**"],
18
+ "description": "Reusable UI components"
19
+ },
20
+ "pages": {
21
+ "patterns": ["**/pages/**", "**/app/**/page.*", "**/app/**/layout.*"],
22
+ "description": "Page routes and layouts"
23
+ },
24
+ "utilities": {
25
+ "patterns": ["**/lib/**", "**/utils/**", "**/helpers/**", "**/common/**"],
26
+ "description": "Utility functions and helpers"
27
+ },
28
+ "testing": {
29
+ "patterns": ["**/tests/**", "**/*.test.*", "**/*.spec.*", "**/*Test.php"],
30
+ "description": "All test files"
31
+ },
32
+ "infrastructure": {
33
+ "patterns": ["**/docker*", "**/Dockerfile*", "**/.github/**", "**/scripts/**", "**/deploy/**"],
34
+ "description": "Docker, CI/CD, deployment"
35
+ }
36
+ },
37
+ "rules": {
38
+ "domainFileLocation": ".claude/skills/codebase-knowledge/domains/",
39
+ "requiredSections": ["Last Update", "Files", "Connections", "Recent Commits", "Attention Points"]
40
+ }
41
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "$comment": "Universal security rules. Agents read active-project.json for stack-specific additions.",
3
+ "validation": {
4
+ "requireOnAllRoutes": true
5
+ },
6
+ "sensitivePatterns": {
7
+ "forbidden": [
8
+ "eval(",
9
+ "exec(",
10
+ "system(",
11
+ "passthru(",
12
+ "shell_exec(",
13
+ "password:",
14
+ "passwordHash",
15
+ "apiKey:",
16
+ "secret:"
17
+ ]
18
+ },
19
+ "cookies": {
20
+ "httpOnly": true,
21
+ "secure": true,
22
+ "sameSite": "strict"
23
+ },
24
+ "owaspChecks": {
25
+ "a01_brokenAccessControl": true,
26
+ "a02_cryptographicFailures": true,
27
+ "a03_injection": true,
28
+ "a07_authenticationFailures": true,
29
+ "a09_securityLogging": true
30
+ }
31
+ }
@@ -0,0 +1,171 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Stop Validator Hook — Start Vibing Stacks (Universal)
4
+ *
5
+ * Reads active-project.json to determine stack-specific validations.
6
+ * Blocks task completion if:
7
+ * 1. Branch != main (work must be merged)
8
+ * 2. Git tree not clean
9
+ * 3. CLAUDE.md not updated
10
+ * 4. CLAUDE.md missing required sections
11
+ * 5. CLAUDE.md exceeds 40k chars
12
+ */
13
+
14
+ import { execSync } from 'child_process';
15
+ import { existsSync, readFileSync } from 'fs';
16
+ import { join } from 'path';
17
+
18
+ const PROJECT_DIR = process.env['CLAUDE_PROJECT_DIR'] || process.cwd();
19
+ const CLAUDE_MD = join(PROJECT_DIR, 'CLAUDE.md');
20
+ const ACTIVE_PROJECT = join(PROJECT_DIR, '.claude', 'config', 'active-project.json');
21
+ const MAX_CHARS = 40000;
22
+
23
+ // Load stack info
24
+ let stackId = 'unknown';
25
+ try {
26
+ if (existsSync(ACTIVE_PROJECT)) {
27
+ const config = JSON.parse(readFileSync(ACTIVE_PROJECT, 'utf8'));
28
+ stackId = config.stack || 'unknown';
29
+ }
30
+ } catch {}
31
+
32
+ // Source extensions per stack
33
+ const STACK_EXTENSIONS: Record<string, Set<string>> = {
34
+ php: new Set(['.php', '.blade.php', '.twig']),
35
+ nodejs: new Set(['.ts', '.tsx', '.js', '.jsx', '.mjs']),
36
+ python: new Set(['.py']),
37
+ go: new Set(['.go']),
38
+ rust: new Set(['.rs']),
39
+ };
40
+
41
+ const sourceExtensions = STACK_EXTENSIONS[stackId] || new Set(['.ts', '.js', '.php', '.py']);
42
+
43
+ interface HookResult {
44
+ continue: boolean;
45
+ decision: 'approve' | 'block';
46
+ reason: string;
47
+ }
48
+
49
+ function cmd(command: string): string {
50
+ try {
51
+ return execSync(command, { cwd: PROJECT_DIR, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
52
+ } catch {
53
+ return '';
54
+ }
55
+ }
56
+
57
+ function getBranch(): string {
58
+ return cmd('git rev-parse --abbrev-ref HEAD') || 'unknown';
59
+ }
60
+
61
+ function getModifiedFiles(): string[] {
62
+ const staged = cmd('git diff --name-only --cached').split('\n').filter(Boolean);
63
+ const unstaged = cmd('git diff --name-only').split('\n').filter(Boolean);
64
+ const untracked = cmd('git ls-files --others --exclude-standard').split('\n').filter(Boolean);
65
+ return [...new Set([...staged, ...unstaged, ...untracked])];
66
+ }
67
+
68
+ function validate(): HookResult {
69
+ const branch = getBranch();
70
+ const isMain = branch === 'main' || branch === 'master';
71
+ const modified = getModifiedFiles();
72
+ const isClean = modified.length === 0;
73
+
74
+ // 1. Must be on main with clean tree
75
+ if (!isMain && modified.length > 0) {
76
+ return {
77
+ continue: true,
78
+ decision: 'block',
79
+ reason: `BLOCKED: On branch '${branch}' with ${modified.length} modified files.\n\nComplete git workflow:\n1. git add -A\n2. git commit -m "type: description"\n3. git checkout main\n4. git merge ${branch}\n5. git push origin main\n6. git branch -d ${branch}`,
80
+ };
81
+ }
82
+
83
+ if (!isMain) {
84
+ return {
85
+ continue: true,
86
+ decision: 'block',
87
+ reason: `BLOCKED: On branch '${branch}'. Switch to main:\n1. git checkout main\n2. git merge ${branch}\n3. git push origin main`,
88
+ };
89
+ }
90
+
91
+ if (!isClean) {
92
+ return {
93
+ continue: true,
94
+ decision: 'block',
95
+ reason: `BLOCKED: ${modified.length} uncommitted files:\n${modified.slice(0, 10).map(f => ` - ${f}`).join('\n')}\n\nCommit or stash before completing.`,
96
+ };
97
+ }
98
+
99
+ // 2. CLAUDE.md must exist
100
+ if (!existsSync(CLAUDE_MD)) {
101
+ return {
102
+ continue: true,
103
+ decision: 'block',
104
+ reason: 'BLOCKED: CLAUDE.md not found. Create it with required sections.',
105
+ };
106
+ }
107
+
108
+ const content = readFileSync(CLAUDE_MD, 'utf8');
109
+
110
+ // 3. Size check
111
+ if (content.length > MAX_CHARS) {
112
+ return {
113
+ continue: true,
114
+ decision: 'block',
115
+ reason: `BLOCKED: CLAUDE.md is ${content.length} chars (max ${MAX_CHARS}). Run claude-md-compactor agent.`,
116
+ };
117
+ }
118
+
119
+ // 4. Required sections
120
+ const required = [
121
+ { pattern: /^# .+/m, name: 'Project Title (H1)' },
122
+ { pattern: /^## Last Change/m, name: 'Last Change' },
123
+ { pattern: /^## Stack/m, name: 'Stack' },
124
+ ];
125
+
126
+ const missing = required.filter(r => !r.pattern.test(content)).map(r => r.name);
127
+ if (missing.length > 0) {
128
+ return {
129
+ continue: true,
130
+ decision: 'block',
131
+ reason: `BLOCKED: CLAUDE.md missing sections: ${missing.join(', ')}`,
132
+ };
133
+ }
134
+
135
+ // All good
136
+ return {
137
+ continue: false,
138
+ decision: 'approve',
139
+ reason: `ALL CHECKS PASSED ✅\nStack: ${stackId}\nBranch: ${branch}\nTree: Clean`,
140
+ };
141
+ }
142
+
143
+ async function main(): Promise<void> {
144
+ // Read stdin (hook input)
145
+ let hookInput: any = {};
146
+ try {
147
+ const chunks: string[] = [];
148
+ process.stdin.setEncoding('utf8');
149
+ const timeout = setTimeout(() => process.stdin.destroy(), 1000);
150
+ for await (const chunk of process.stdin) {
151
+ chunks.push(chunk);
152
+ }
153
+ clearTimeout(timeout);
154
+ hookInput = JSON.parse(chunks.join('') || '{}');
155
+ } catch {}
156
+
157
+ // Prevent loop
158
+ if (hookInput.stop_hook_active) {
159
+ console.log(JSON.stringify({ continue: false, decision: 'approve', reason: 'Cycle detected' }));
160
+ process.exit(0);
161
+ }
162
+
163
+ const result = validate();
164
+ console.log(JSON.stringify(result));
165
+ process.exit(0);
166
+ }
167
+
168
+ main().catch(() => {
169
+ console.log(JSON.stringify({ continue: false, decision: 'approve', reason: 'Hook error' }));
170
+ process.exit(0);
171
+ });
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * UserPromptSubmit Hook — Start Vibing Stacks
4
+ *
5
+ * Injects workflow instructions before each user prompt.
6
+ * Reads active-project.json for stack-specific context.
7
+ */
8
+
9
+ import { existsSync, readFileSync } from 'fs';
10
+ import { join } from 'path';
11
+
12
+ const PROJECT_DIR = process.env['CLAUDE_PROJECT_DIR'] || process.cwd();
13
+ const ACTIVE_PROJECT = join(PROJECT_DIR, '.claude', 'config', 'active-project.json');
14
+
15
+ let stackName = 'Unknown';
16
+ let qualityCmd = 'Run quality gates';
17
+ try {
18
+ if (existsSync(ACTIVE_PROJECT)) {
19
+ const config = JSON.parse(readFileSync(ACTIVE_PROJECT, 'utf8'));
20
+ stackName = config.stack || 'Unknown';
21
+ // Read quality gates command from stack config
22
+ const stackConfig = join(PROJECT_DIR, '.claude', 'config', 'quality-gates.json');
23
+ if (existsSync(stackConfig)) {
24
+ const gates = JSON.parse(readFileSync(stackConfig, 'utf8'));
25
+ qualityCmd = gates.runAll || qualityCmd;
26
+ }
27
+ }
28
+ } catch {}
29
+
30
+ async function main(): Promise<void> {
31
+ let hookInput: any = {};
32
+ try {
33
+ const chunks: string[] = [];
34
+ process.stdin.setEncoding('utf8');
35
+ const timeout = setTimeout(() => process.stdin.destroy(), 1000);
36
+ for await (const chunk of process.stdin) {
37
+ chunks.push(chunk);
38
+ }
39
+ clearTimeout(timeout);
40
+ hookInput = JSON.parse(chunks.join('') || '{}');
41
+ } catch {}
42
+
43
+ const prompt = hookInput.user_prompt || hookInput.prompt || '';
44
+ if (!prompt.trim()) {
45
+ console.log(JSON.stringify({ continue: true }));
46
+ process.exit(0);
47
+ }
48
+
49
+ const today = new Date().toISOString().split('T')[0];
50
+
51
+ const systemMessage = `TASK WORKFLOW (Stack: ${stackName}):
52
+
53
+ 0. READ both CLAUDE.md and .claude/config/active-project.json before changes.
54
+
55
+ 1. CREATE a detailed todo-list breaking down the request.
56
+ Include "Update CLAUDE.md" as final task.
57
+
58
+ 2. WORK through each item sequentially.
59
+
60
+ 3. Run quality gates: ${qualityCmd}
61
+
62
+ 4. COMMIT using conventional commits via commit-manager agent.
63
+
64
+ 5. UPDATE CLAUDE.md:
65
+ a. "## Last Change" (date: ${today}, branch, summary)
66
+ b. Update ALL affected rule/flow sections
67
+
68
+ 6. Run stop-validator before finishing.`;
69
+
70
+ console.log(JSON.stringify({ continue: true, systemMessage }));
71
+ process.exit(0);
72
+ }
73
+
74
+ main().catch(() => {
75
+ console.log(JSON.stringify({ continue: true }));
76
+ process.exit(0);
77
+ });