@agentic15.com/agentic15-claude-zen 3.2.0 → 3.3.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.
package/README.md CHANGED
@@ -18,22 +18,54 @@ npx @agentic15.com/agentic15-claude-zen my-project
18
18
  npx "@agentic15.com/agentic15-claude-zen" my-project
19
19
  ```
20
20
 
21
- **Step 2: Use CLI Inside Project**
21
+ **Step 2: Navigate Into Project**
22
22
  ```bash
23
23
  cd my-project
24
- npx agentic15 auth # One-time GitHub setup
25
- npx agentic15 plan # Enter interactive mode
24
+ ```
25
+
26
+ **Step 3: Launch Claude Code from Inside Project Directory**
27
+
28
+ Start Claude Code CLI from inside the `my-project` directory. Claude Code MUST be running from inside your project directory to access the framework files.
29
+
30
+ **Step 4: Configure Repository Settings (Recommended)**
31
+ ```bash
32
+ # Prevent direct pushes to main - require PRs for all changes
33
+ gh api repos/OWNER/REPO/branches/main/protection -X PUT \
34
+ -H "Accept: application/vnd.github+json" \
35
+ -f required_pull_request_reviews[required_approving_review_count]=0 \
36
+ -f enforce_admins=false \
37
+ -f allow_force_pushes=false \
38
+ -f allow_deletions=false
39
+
40
+ # Auto-delete branches after PR merge
41
+ gh api repos/OWNER/REPO -X PATCH \
42
+ -H "Accept: application/vnd.github+json" \
43
+ -f delete_branch_on_merge=true
44
+ ```
45
+ Replace `OWNER/REPO` with your GitHub username and repository name.
46
+
47
+ **Step 5: Use Framework Commands**
48
+ ```bash
49
+ npx agentic15 auth # One-time GitHub setup
50
+ npx agentic15 plan # Enter interactive mode
26
51
  # Type/paste your requirements, press Ctrl+D when done
27
- npx agentic15 task next # Start first task
28
- npx agentic15 commit # Test, commit, push, PR
52
+ # Open another terminal. Make sure that you in your project directory. Launch Claude
53
+ # Ask Claude: "Read the requirements file and generate a task breakdown plan"
54
+ npx agentic15 task next # Start first task
55
+ # Ask Claude: "Implement this task"
56
+ npx agentic15 commit # Test, commit, push, PR
29
57
  ```
30
58
 
31
- > **Note**: Project creation uses the full package name `@agentic15.com/agentic15-claude-zen`.
32
- > Once inside your project, use the short command `agentic15` for all workflows.
33
- >
34
- > **Tip**: `npx agentic15 plan` without arguments enters interactive mode where you can
35
- > paste long requirements, URLs, and detailed specs. Press Ctrl+D (Mac/Linux) or
36
- > Ctrl+Z+Enter (Windows) to save.
59
+ > **IMPORTANT**: Always launch Claude Code from inside your project directory, not from the parent directory. The framework relies on `.claude/` configuration files that must be accessible from the working directory.
60
+
61
+ **Step 6: Clean Up Local Branches**
62
+ ```bash
63
+ # If auto-delete is enabled, only clean up local branches
64
+ git branch -d feature/task-001
65
+
66
+ # For repositories without auto-delete, also delete remote
67
+ git push origin --delete feature/task-001
68
+ ```
37
69
 
38
70
  **See [WORKFLOWS.md](WORKFLOWS.md) for complete workflows.**
39
71
 
@@ -45,8 +77,8 @@ npx agentic15 commit # Test, commit, push, PR
45
77
  - `npx agentic15 plan` - Generate and lock plans
46
78
  - `npx agentic15 task next` - Start next task
47
79
  - `npx agentic15 commit` - Test + commit + push + PR
80
+ - `npx agentic15 visual-test <url>` - Capture screenshots & console errors
48
81
  - `npx agentic15 status` - Check progress
49
- - `npx agentic15 upgrade` - Upgrade framework files
50
82
  - `npm test` - Run tests
51
83
 
52
84
  **Automates:**
package/bin/agentic15.js CHANGED
@@ -1,57 +1,65 @@
1
- #!/usr/bin/env node
2
-
3
- import { Command } from 'commander';
4
- import { AuthCommand } from '../src/cli/AuthCommand.js';
5
- import { TaskCommand } from '../src/cli/TaskCommand.js';
6
- import { CommitCommand } from '../src/cli/CommitCommand.js';
7
- import { StatusCommand } from '../src/cli/StatusCommand.js';
8
- import { PlanCommand } from '../src/cli/PlanCommand.js';
9
- import { UpgradeCommand } from '../src/cli/UpgradeCommand.js';
10
-
11
- const program = new Command();
12
-
13
- program
14
- .name('agentic15')
15
- .description('Agentic15 Claude Zen - Automated AI development workflow')
16
- .version('2.0.0');
17
-
18
- // GitHub authentication setup
19
- program
20
- .command('auth')
21
- .description('GitHub authentication setup')
22
- .action(() => AuthCommand.setup());
23
-
24
- // Task management
25
- program
26
- .command('task')
27
- .description('Task management')
28
- .argument('<action>', 'Action: start, next, status')
29
- .argument('[taskId]', 'Task ID (e.g., TASK-001) - required for "start"')
30
- .action((action, taskId) => TaskCommand.handle(action, taskId));
31
-
32
- // Auto-commit workflow
33
- program
34
- .command('commit')
35
- .description('Run tests, commit, push, create PR')
36
- .action(() => CommitCommand.execute());
37
-
38
- // Show status
39
- program
40
- .command('status')
41
- .description('Show current task status and progress')
42
- .action(() => StatusCommand.show());
43
-
44
- // Plan management (single command for generate + lock)
45
- program
46
- .command('plan')
47
- .description('Generate and lock plan')
48
- .argument('[description]', 'Project description (required for first run)')
49
- .action((description) => PlanCommand.handle(description));
50
-
51
- // Upgrade framework
52
- program
53
- .command('upgrade')
54
- .description('Upgrade framework files to latest version')
55
- .action(() => UpgradeCommand.execute());
56
-
57
- program.parse();
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from 'commander';
4
+ import { AuthCommand } from '../src/cli/AuthCommand.js';
5
+ import { TaskCommand } from '../src/cli/TaskCommand.js';
6
+ import { CommitCommand } from '../src/cli/CommitCommand.js';
7
+ import { StatusCommand } from '../src/cli/StatusCommand.js';
8
+ import { PlanCommand } from '../src/cli/PlanCommand.js';
9
+ import { UpgradeCommand } from '../src/cli/UpgradeCommand.js';
10
+ import { VisualTestCommand } from '../src/cli/VisualTestCommand.js';
11
+
12
+ const program = new Command();
13
+
14
+ program
15
+ .name('agentic15')
16
+ .description('Agentic15 Claude Zen - Automated AI development workflow')
17
+ .version('2.0.0');
18
+
19
+ // GitHub authentication setup
20
+ program
21
+ .command('auth')
22
+ .description('GitHub authentication setup')
23
+ .action(() => AuthCommand.setup());
24
+
25
+ // Task management
26
+ program
27
+ .command('task')
28
+ .description('Task management')
29
+ .argument('<action>', 'Action: start, next, status')
30
+ .argument('[taskId]', 'Task ID (e.g., TASK-001) - required for "start"')
31
+ .action((action, taskId) => TaskCommand.handle(action, taskId));
32
+
33
+ // Auto-commit workflow
34
+ program
35
+ .command('commit')
36
+ .description('Run tests, commit, push, create PR')
37
+ .action(() => CommitCommand.execute());
38
+
39
+ // Show status
40
+ program
41
+ .command('status')
42
+ .description('Show current task status and progress')
43
+ .action(() => StatusCommand.show());
44
+
45
+ // Plan management (single command for generate + lock)
46
+ program
47
+ .command('plan')
48
+ .description('Generate and lock plan')
49
+ .argument('[description]', 'Project description (required for first run)')
50
+ .action((description) => PlanCommand.handle(description));
51
+
52
+ // Upgrade framework
53
+ program
54
+ .command('upgrade')
55
+ .description('Upgrade framework files to latest version')
56
+ .action(() => UpgradeCommand.execute());
57
+
58
+ // Visual testing - capture screenshots and console errors
59
+ program
60
+ .command('visual-test')
61
+ .description('Capture screenshots and console errors for UI debugging')
62
+ .argument('<url>', 'URL to test (e.g., http://localhost:3000)')
63
+ .action((url) => VisualTestCommand.execute(url));
64
+
65
+ program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentic15.com/agentic15-claude-zen",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "description": "Structured AI-assisted development framework for Claude Code with enforced quality standards",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -11,7 +11,9 @@
11
11
  "scripts": {
12
12
  "test": "node test/integration.test.js",
13
13
  "test:e2e": "node test/e2e-verification.test.js",
14
- "test:site": "node test/verify-test-site.js"
14
+ "test:site": "node test/verify-test-site.js",
15
+ "sync-readme": "node -e \"require('fs').copyFileSync('../../README.md', 'README.md')\"",
16
+ "prepublishOnly": "npm run sync-readme"
15
17
  },
16
18
  "keywords": [
17
19
  "agentic15",
@@ -0,0 +1,191 @@
1
+ import { execSync } from 'child_process';
2
+ import { existsSync, writeFileSync, mkdirSync, unlinkSync } from 'fs';
3
+ import { join } from 'path';
4
+
5
+ /**
6
+ * VisualTestCommand - Capture screenshots and console errors for UI debugging
7
+ *
8
+ * Uses Claude Code's built-in screenshot capabilities (no API key needed)
9
+ * Helps report UI issues to Claude without manual back-and-forth
10
+ */
11
+ export class VisualTestCommand {
12
+ static async execute(url) {
13
+ console.log('\n🎯 Visual Test - Capture screenshots and console errors\n');
14
+
15
+ if (!url) {
16
+ console.log('❌ URL required');
17
+ console.log(' Usage: npx agentic15 visual-test <url>\n');
18
+ console.log(' Example: npx agentic15 visual-test http://localhost:3000\n');
19
+ process.exit(1);
20
+ }
21
+
22
+ // Check if Playwright is installed
23
+ const hasPlaywright = this.checkPlaywright();
24
+
25
+ if (!hasPlaywright) {
26
+ console.log('⚠️ Playwright not installed');
27
+ console.log(' Install with: npx playwright install chromium\n');
28
+ process.exit(1);
29
+ }
30
+
31
+ console.log(`📸 Capturing screenshots and logs from: ${url}\n`);
32
+
33
+ try {
34
+ // Run Playwright visual test
35
+ this.runVisualTest(url);
36
+
37
+ console.log('\n✅ Visual test complete');
38
+ console.log(' Screenshots saved to: .claude/visual-test/\n');
39
+ console.log('💡 Next steps:');
40
+ console.log(' 1. Review screenshots in .claude/visual-test/');
41
+ console.log(' 2. Check console-errors.log for JavaScript errors');
42
+ console.log(' 3. Ask Claude to analyze the visual test results\n');
43
+
44
+ process.exit(0);
45
+ } catch (error) {
46
+ console.log(`\n❌ Visual test failed: ${error.message}\n`);
47
+ process.exit(1);
48
+ }
49
+ }
50
+
51
+ static checkPlaywright() {
52
+ const projectRoot = process.cwd();
53
+ const packageJsonPath = join(projectRoot, 'package.json');
54
+
55
+ if (!existsSync(packageJsonPath)) {
56
+ return false;
57
+ }
58
+
59
+ try {
60
+ // Check if playwright is in devDependencies
61
+ execSync('npx playwright --version', { stdio: 'pipe' });
62
+ return true;
63
+ } catch {
64
+ return false;
65
+ }
66
+ }
67
+
68
+ static runVisualTest(url) {
69
+ const testScript = `
70
+ const { chromium } = require('playwright');
71
+ const { writeFileSync, mkdirSync } = require('fs');
72
+ const { join } = require('path');
73
+
74
+ (async () => {
75
+ const outputDir = join(process.cwd(), '.claude', 'visual-test');
76
+ mkdirSync(outputDir, { recursive: true });
77
+
78
+ const consoleErrors = [];
79
+ const consoleWarnings = [];
80
+
81
+ const browser = await chromium.launch({ headless: true });
82
+ const context = await browser.newContext({
83
+ viewport: { width: 1920, height: 1080 }
84
+ });
85
+ const page = await context.newPage();
86
+
87
+ // Capture console errors
88
+ page.on('console', msg => {
89
+ if (msg.type() === 'error') {
90
+ consoleErrors.push({
91
+ timestamp: new Date().toISOString(),
92
+ message: msg.text()
93
+ });
94
+ } else if (msg.type() === 'warning') {
95
+ consoleWarnings.push({
96
+ timestamp: new Date().toISOString(),
97
+ message: msg.text()
98
+ });
99
+ }
100
+ });
101
+
102
+ // Capture page errors
103
+ page.on('pageerror', error => {
104
+ consoleErrors.push({
105
+ timestamp: new Date().toISOString(),
106
+ message: error.message,
107
+ stack: error.stack
108
+ });
109
+ });
110
+
111
+ try {
112
+ // Navigate to URL
113
+ await page.goto('${url}', { waitUntil: 'networkidle', timeout: 30000 });
114
+
115
+ // Wait for page to stabilize
116
+ await page.waitForTimeout(2000);
117
+
118
+ // Capture full page screenshot
119
+ await page.screenshot({
120
+ path: join(outputDir, 'fullpage.png'),
121
+ fullPage: true
122
+ });
123
+
124
+ // Capture viewport screenshot
125
+ await page.screenshot({
126
+ path: join(outputDir, 'viewport.png'),
127
+ fullPage: false
128
+ });
129
+
130
+ // Save console errors
131
+ if (consoleErrors.length > 0) {
132
+ const errorLog = consoleErrors.map(e =>
133
+ \`[\${e.timestamp}] \${e.message}\${e.stack ? '\\n' + e.stack : ''}\`
134
+ ).join('\\n\\n');
135
+
136
+ writeFileSync(join(outputDir, 'console-errors.log'), errorLog);
137
+ console.log(\`❌ Found \${consoleErrors.length} console errors\`);
138
+ } else {
139
+ console.log('✅ No console errors detected');
140
+ }
141
+
142
+ // Save console warnings
143
+ if (consoleWarnings.length > 0) {
144
+ const warningLog = consoleWarnings.map(w =>
145
+ \`[\${w.timestamp}] \${w.message}\`
146
+ ).join('\\n\\n');
147
+
148
+ writeFileSync(join(outputDir, 'console-warnings.log'), warningLog);
149
+ console.log(\`⚠️ Found \${consoleWarnings.length} console warnings\`);
150
+ }
151
+
152
+ // Capture page HTML for debugging
153
+ const html = await page.content();
154
+ writeFileSync(join(outputDir, 'page.html'), html);
155
+
156
+ } catch (error) {
157
+ console.error('Error during visual test:', error.message);
158
+
159
+ // Try to capture screenshot even on error
160
+ try {
161
+ await page.screenshot({
162
+ path: join(outputDir, 'error-screenshot.png')
163
+ });
164
+ } catch {}
165
+
166
+ throw error;
167
+ } finally {
168
+ await browser.close();
169
+ }
170
+ })();
171
+ `;
172
+
173
+ // Write test script to temp file and execute
174
+ const tempScriptPath = join(process.cwd(), '.claude', 'temp-visual-test.js');
175
+
176
+ mkdirSync(join(process.cwd(), '.claude'), { recursive: true });
177
+ writeFileSync(tempScriptPath, testScript);
178
+
179
+ try {
180
+ execSync(`node "${tempScriptPath}"`, {
181
+ stdio: 'inherit',
182
+ cwd: process.cwd()
183
+ });
184
+ } finally {
185
+ // Clean up temp script
186
+ try {
187
+ unlinkSync(tempScriptPath);
188
+ } catch {}
189
+ }
190
+ }
191
+ }
@@ -1,160 +1,137 @@
1
- /**
2
- * Copyright 2024-2025 agentic15.com
3
- *
4
- * Licensed under the Apache License, Version 2.0 (the "License");
5
- * you may not use this file except in compliance with the License.
6
- * You may obtain a copy of the License at
7
- *
8
- * http://www.apache.org/licenses/LICENSE-2.0
9
- *
10
- * Unless required by applicable law or agreed to in writing, software
11
- * distributed under the License is distributed on an "AS IS" BASIS,
12
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- * See the License for the specific language governing permissions and
14
- * limitations under the License.
15
- */
16
-
17
- import { mkdirSync, cpSync, readFileSync, writeFileSync, existsSync } from 'fs';
18
- import { join, dirname } from 'path';
19
- import { fileURLToPath } from 'url';
20
-
21
- const __filename = fileURLToPath(import.meta.url);
22
- const __dirname = dirname(__filename);
23
-
24
- /**
25
- * TemplateManager - Manages template copying and customization
26
- *
27
- * Single Responsibility: Copy and customize project templates
28
- */
29
- export class TemplateManager {
30
- constructor() {
31
- // From src/core/, go up two levels to package root, then into templates
32
- this.templatesDir = join(__dirname, '..', '..', 'templates');
33
- this.distDir = join(__dirname, '.');
34
- }
35
-
36
- /**
37
- * Copy all templates to target directory
38
- *
39
- * @param {string} projectName - Name of the project
40
- * @param {string} targetDir - Target directory path
41
- */
42
- async copyTemplates(projectName, targetDir) {
43
- console.log('📦 Creating project directory...');
44
- mkdirSync(targetDir, { recursive: true });
45
-
46
- console.log('📋 Copying framework templates...');
47
-
48
- // Copy .claude directory structure
49
- this.copyDirectory('.claude', targetDir);
50
-
51
- // Copy and customize package.json
52
- this.copyAndCustomize('package.json', targetDir, projectName);
53
-
54
- // Copy and customize README.md
55
- this.copyAndCustomize('README.md', targetDir, projectName);
56
-
57
- // Copy .gitignore (npm may rename it)
58
- this.copyGitignore(targetDir);
59
-
60
- // Copy test-site
61
- this.copyDirectory('test-site', targetDir);
62
-
63
- // Copy Agent directory
64
- this.copyDirectory('Agent', targetDir);
65
-
66
- // Copy scripts directory
67
- this.copyDirectory('scripts', targetDir);
68
-
69
- // Copy Jest configuration files
70
- this.copySingleFile('jest.config.js', targetDir);
71
- this.copySingleFile('jest.setup.js', targetDir);
72
- this.copySingleFile('.babelrc', targetDir);
73
-
74
- // Copy __mocks__ directory
75
- this.copyDirectory('__mocks__', targetDir);
76
-
77
- console.log('✅ Framework structure created');
78
- console.log('✅ Templates copied');
79
- console.log('✅ Configuration files generated');
80
- }
81
-
82
- /**
83
- * Extract bundled scripts and hooks to node_modules
84
- *
85
- * @param {string} targetDir - Target directory path
86
- */
87
- async extractBundledFiles(targetDir) {
88
- const bundleDir = join(targetDir, 'node_modules', '.agentic15-claude-zen');
89
- console.log('\n📦 Setting up bundled scripts and hooks...');
90
- mkdirSync(bundleDir, { recursive: true });
91
-
92
- // Copy bundled scripts
93
- console.log(' ├─ scripts/');
94
- const bundledScriptsDir = join(this.distDir, 'scripts');
95
- cpSync(bundledScriptsDir, join(bundleDir, 'scripts'), { recursive: true });
96
-
97
- // Copy bundled hooks
98
- console.log(' └─ hooks/');
99
- const bundledHooksDir = join(this.distDir, 'hooks');
100
- cpSync(bundledHooksDir, join(bundleDir, 'hooks'), { recursive: true });
101
-
102
- console.log('✅ Bundled files extracted');
103
- }
104
-
105
- /**
106
- * Copy a directory from templates to target
107
- *
108
- * @param {string} dirName - Directory name
109
- * @param {string} targetDir - Target directory path
110
- */
111
- copyDirectory(dirName, targetDir) {
112
- console.log(` ├─ ${dirName}/`);
113
- cpSync(
114
- join(this.templatesDir, dirName),
115
- join(targetDir, dirName),
116
- { recursive: true }
117
- );
118
- }
119
-
120
- /**
121
- * Copy a single file from templates to target
122
- *
123
- * @param {string} fileName - File name
124
- * @param {string} targetDir - Target directory path
125
- */
126
- copySingleFile(fileName, targetDir) {
127
- console.log(` ├─ ${fileName}`);
128
- cpSync(
129
- join(this.templatesDir, fileName),
130
- join(targetDir, fileName)
131
- );
132
- }
133
-
134
- /**
135
- * Copy and customize a file with project name replacement
136
- *
137
- * @param {string} fileName - File name
138
- * @param {string} targetDir - Target directory path
139
- * @param {string} projectName - Project name for replacement
140
- */
141
- copyAndCustomize(fileName, targetDir, projectName) {
142
- console.log(` ├─ ${fileName}`);
143
- const template = readFileSync(join(this.templatesDir, fileName), 'utf8');
144
- const customized = template.replace(/\{\{PROJECT_NAME\}\}/g, projectName);
145
- writeFileSync(join(targetDir, fileName), customized);
146
- }
147
-
148
- /**
149
- * Copy .gitignore file (handles npm renaming issue)
150
- *
151
- * @param {string} targetDir - Target directory path
152
- */
153
- copyGitignore(targetDir) {
154
- console.log(' ├─ .gitignore');
155
- const gitignoreSource = existsSync(join(this.templatesDir, '.gitignore'))
156
- ? join(this.templatesDir, '.gitignore')
157
- : join(this.templatesDir, '.npmignore');
158
- cpSync(gitignoreSource, join(targetDir, '.gitignore'));
159
- }
160
- }
1
+ /**
2
+ * Copyright 2024-2025 agentic15.com
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import { mkdirSync, cpSync, readFileSync, writeFileSync, existsSync } from 'fs';
18
+ import { join, dirname } from 'path';
19
+ import { fileURLToPath } from 'url';
20
+
21
+ const __filename = fileURLToPath(import.meta.url);
22
+ const __dirname = dirname(__filename);
23
+
24
+ /**
25
+ * TemplateManager - Manages template copying and customization
26
+ *
27
+ * Single Responsibility: Copy and customize project templates
28
+ */
29
+ export class TemplateManager {
30
+ constructor() {
31
+ // From src/core/, go up two levels to package root, then into templates
32
+ this.templatesDir = join(__dirname, '..', '..', 'templates');
33
+ this.distDir = join(__dirname, '.');
34
+ }
35
+
36
+ /**
37
+ * Copy all templates to target directory
38
+ *
39
+ * @param {string} projectName - Name of the project
40
+ * @param {string} targetDir - Target directory path
41
+ */
42
+ async copyTemplates(projectName, targetDir) {
43
+ console.log('📦 Creating project directory...');
44
+ mkdirSync(targetDir, { recursive: true });
45
+
46
+ console.log('📋 Copying framework templates...');
47
+
48
+ // Copy .claude directory structure
49
+ this.copyDirectory('.claude', targetDir);
50
+
51
+ // Copy and customize package.json
52
+ this.copyAndCustomize('package.json', targetDir, projectName);
53
+
54
+ // Copy and customize README.md
55
+ this.copyAndCustomize('README.md', targetDir, projectName);
56
+
57
+ // Copy .gitignore (npm may rename it)
58
+ this.copyGitignore(targetDir);
59
+
60
+ // Copy test-site
61
+ this.copyDirectory('test-site', targetDir);
62
+
63
+ // Copy Agent directory
64
+ this.copyDirectory('Agent', targetDir);
65
+
66
+ // Copy scripts directory
67
+ this.copyDirectory('scripts', targetDir);
68
+
69
+ // Copy Jest configuration files
70
+ this.copySingleFile('jest.config.js', targetDir);
71
+ this.copySingleFile('jest.setup.js', targetDir);
72
+ this.copySingleFile('.babelrc', targetDir);
73
+
74
+ // Copy __mocks__ directory
75
+ this.copyDirectory('__mocks__', targetDir);
76
+
77
+ console.log('✅ Framework structure created');
78
+ console.log('✅ Templates copied');
79
+ console.log('✅ Configuration files generated');
80
+ }
81
+
82
+ /**
83
+ * Copy a directory from templates to target
84
+ *
85
+ * @param {string} dirName - Directory name
86
+ * @param {string} targetDir - Target directory path
87
+ */
88
+ copyDirectory(dirName, targetDir) {
89
+ console.log(` ├─ ${dirName}/`);
90
+ cpSync(
91
+ join(this.templatesDir, dirName),
92
+ join(targetDir, dirName),
93
+ { recursive: true }
94
+ );
95
+ }
96
+
97
+ /**
98
+ * Copy a single file from templates to target
99
+ *
100
+ * @param {string} fileName - File name
101
+ * @param {string} targetDir - Target directory path
102
+ */
103
+ copySingleFile(fileName, targetDir) {
104
+ console.log(` ├─ ${fileName}`);
105
+ cpSync(
106
+ join(this.templatesDir, fileName),
107
+ join(targetDir, fileName)
108
+ );
109
+ }
110
+
111
+ /**
112
+ * Copy and customize a file with project name replacement
113
+ *
114
+ * @param {string} fileName - File name
115
+ * @param {string} targetDir - Target directory path
116
+ * @param {string} projectName - Project name for replacement
117
+ */
118
+ copyAndCustomize(fileName, targetDir, projectName) {
119
+ console.log(` ├─ ${fileName}`);
120
+ const template = readFileSync(join(this.templatesDir, fileName), 'utf8');
121
+ const customized = template.replace(/\{\{PROJECT_NAME\}\}/g, projectName);
122
+ writeFileSync(join(targetDir, fileName), customized);
123
+ }
124
+
125
+ /**
126
+ * Copy .gitignore file (handles npm renaming issue)
127
+ *
128
+ * @param {string} targetDir - Target directory path
129
+ */
130
+ copyGitignore(targetDir) {
131
+ console.log(' ├─ .gitignore');
132
+ const gitignoreSource = existsSync(join(this.templatesDir, '.gitignore'))
133
+ ? join(this.templatesDir, '.gitignore')
134
+ : join(this.templatesDir, '.npmignore');
135
+ cpSync(gitignoreSource, join(targetDir, '.gitignore'));
136
+ }
137
+ }
@@ -1,89 +1,89 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Require Active Task Hook
5
- *
6
- * BLOCKS all Edit/Write operations when no active task exists
7
- *
8
- * This is the enforcement mechanism that prevents workflow violations
9
- */
10
-
11
- const fs = require('fs');
12
- const path = require('path');
13
-
14
- // Read tool use from stdin
15
- let input = '';
16
- process.stdin.on('data', chunk => {
17
- input += chunk;
18
- });
19
-
20
- process.stdin.on('end', () => {
21
- try {
22
- const toolUse = JSON.parse(input);
23
-
24
- // Only check Edit and Write operations
25
- if (toolUse.name !== 'Edit' && toolUse.name !== 'Write') {
26
- // Allow all other tools
27
- process.exit(0);
28
- return;
29
- }
30
-
31
- // Check if active task exists
32
- const activePlanFile = '.claude/ACTIVE-PLAN';
33
-
34
- if (!fs.existsSync(activePlanFile)) {
35
- console.error('\n' + '═'.repeat(70));
36
- console.error('❌ BLOCKED: No active plan exists');
37
- console.error('═'.repeat(70));
38
- console.error('\nYou MUST have an active plan before making code changes.');
39
- console.error('\nTo create a plan:');
40
- console.error(' npx agentic15 plan "Your project requirements"');
41
- console.error('\n' + '═'.repeat(70) + '\n');
42
- process.exit(1);
43
- return;
44
- }
45
-
46
- const activePlan = fs.readFileSync(activePlanFile, 'utf8').trim();
47
- const planDir = path.join('.claude/plans', activePlan);
48
- const trackerPath = path.join(planDir, 'TASK-TRACKER.json');
49
-
50
- if (!fs.existsSync(trackerPath)) {
51
- console.error('\n' + '═'.repeat(70));
52
- console.error('❌ BLOCKED: Task tracker not found');
53
- console.error('═'.repeat(70));
54
- console.error('\nPlan exists but task tracker is missing.');
55
- console.error('This indicates a corrupted plan state.');
56
- console.error('\n' + '═'.repeat(70) + '\n');
57
- process.exit(1);
58
- return;
59
- }
60
-
61
- const tracker = JSON.parse(fs.readFileSync(trackerPath, 'utf8'));
62
-
63
- if (!tracker.activeTask) {
64
- console.error('\n' + '═'.repeat(70));
65
- console.error('❌ BLOCKED: No active task');
66
- console.error('═'.repeat(70));
67
- console.error('\nYou MUST have an active task before making code changes.');
68
- console.error('\nTo start a task:');
69
- console.error(' npx agentic15 task next');
70
- console.error('\nThis will:');
71
- console.error(' 1. Show you the next pending task');
72
- console.error(' 2. Create a feature branch');
73
- console.error(' 3. Create a GitHub issue');
74
- console.error(' 4. Mark the task as active');
75
- console.error('\nThen you can make your changes.');
76
- console.error('\n' + '═'.repeat(70) + '\n');
77
- process.exit(1);
78
- return;
79
- }
80
-
81
- // Active task exists - allow the operation
82
- process.exit(0);
83
-
84
- } catch (error) {
85
- // If we can't parse or check, fail safe and allow
86
- // (don't want to block legitimate work due to hook errors)
87
- process.exit(0);
88
- }
89
- });
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Require Active Task Hook
5
+ *
6
+ * BLOCKS all Edit/Write operations when no active task exists
7
+ *
8
+ * This is the enforcement mechanism that prevents workflow violations
9
+ */
10
+
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+
14
+ // Read tool use from stdin
15
+ let input = '';
16
+ process.stdin.on('data', chunk => {
17
+ input += chunk;
18
+ });
19
+
20
+ process.stdin.on('end', () => {
21
+ try {
22
+ const toolUse = JSON.parse(input);
23
+
24
+ // Only check Edit and Write operations
25
+ if (toolUse.name !== 'Edit' && toolUse.name !== 'Write') {
26
+ // Allow all other tools
27
+ process.exit(0);
28
+ return;
29
+ }
30
+
31
+ // Check if active task exists
32
+ const activePlanFile = '.claude/ACTIVE-PLAN';
33
+
34
+ if (!fs.existsSync(activePlanFile)) {
35
+ console.error('\n' + '═'.repeat(70));
36
+ console.error('❌ BLOCKED: No active plan exists');
37
+ console.error('═'.repeat(70));
38
+ console.error('\nYou MUST have an active plan before making code changes.');
39
+ console.error('\nTo create a plan:');
40
+ console.error(' npx agentic15 plan "Your project requirements"');
41
+ console.error('\n' + '═'.repeat(70) + '\n');
42
+ process.exit(1);
43
+ return;
44
+ }
45
+
46
+ const activePlan = fs.readFileSync(activePlanFile, 'utf8').trim();
47
+ const planDir = path.join('.claude/plans', activePlan);
48
+ const trackerPath = path.join(planDir, 'TASK-TRACKER.json');
49
+
50
+ if (!fs.existsSync(trackerPath)) {
51
+ console.error('\n' + '═'.repeat(70));
52
+ console.error('❌ BLOCKED: Task tracker not found');
53
+ console.error('═'.repeat(70));
54
+ console.error('\nPlan exists but task tracker is missing.');
55
+ console.error('This indicates a corrupted plan state.');
56
+ console.error('\n' + '═'.repeat(70) + '\n');
57
+ process.exit(1);
58
+ return;
59
+ }
60
+
61
+ const tracker = JSON.parse(fs.readFileSync(trackerPath, 'utf8'));
62
+
63
+ if (!tracker.activeTask) {
64
+ console.error('\n' + '═'.repeat(70));
65
+ console.error('❌ BLOCKED: No active task');
66
+ console.error('═'.repeat(70));
67
+ console.error('\nYou MUST have an active task before making code changes.');
68
+ console.error('\nTo start a task:');
69
+ console.error(' npx agentic15 task next');
70
+ console.error('\nThis will:');
71
+ console.error(' 1. Show you the next pending task');
72
+ console.error(' 2. Create a feature branch');
73
+ console.error(' 3. Create a GitHub issue');
74
+ console.error(' 4. Mark the task as active');
75
+ console.error('\nThen you can make your changes.');
76
+ console.error('\n' + '═'.repeat(70) + '\n');
77
+ process.exit(1);
78
+ return;
79
+ }
80
+
81
+ // Active task exists - allow the operation
82
+ process.exit(0);
83
+
84
+ } catch (error) {
85
+ // If we can't parse or check, fail safe and allow
86
+ // (don't want to block legitimate work due to hook errors)
87
+ process.exit(0);
88
+ }
89
+ });
@@ -4,11 +4,11 @@
4
4
  "Read(**)",
5
5
  "Glob",
6
6
  "Grep",
7
- "Bash(npm run *)",
8
- "Bash(git status*)",
9
- "Bash(git log*)",
10
- "Bash(git diff*)",
11
- "Bash(git branch*)",
7
+ "Bash(npm run:*)",
8
+ "Bash(git status:*)",
9
+ "Bash(git log:*)",
10
+ "Bash(git diff:*)",
11
+ "Bash(git branch:*)",
12
12
  "Edit(./Agent/**)",
13
13
  "Write(./Agent/**)",
14
14
  "Edit(./scripts/**)",
@@ -34,33 +34,32 @@
34
34
  "Edit(./.claude/settings.json)",
35
35
  "Edit(./.claude/hooks/**)",
36
36
  "Write(./.claude/hooks/**)",
37
- "Edit(./.claude/CLAUDE.md)",
38
37
  "Edit(./.claude/TASK-TRACKER.json)",
39
38
  "Read(./.claude/POST-INSTALL.md)",
40
39
  "Read(./docs/**)",
41
- "Bash(agentic15 *)",
42
- "Bash(git *)",
43
- "Bash(gh *)",
40
+ "Bash(agentic15:*)",
41
+ "Bash(git:*)",
42
+ "Bash(gh:*)",
44
43
  "Bash(npm run task:*)",
45
44
  "Bash(npm run plan:*)",
46
- "Bash(curl*)",
47
- "Bash(wget*)",
48
- "Bash(rm -rf*)",
49
- "Bash(sudo*)",
50
- "Bash(npm install*)",
51
- "Bash(npm publish*)",
52
- "Bash(git push --force*)",
53
- "Bash(git merge*)",
54
- "Bash(psql*)",
55
- "Bash(mysql*)",
56
- "Bash(sqlite3*)",
57
- "Bash(mongosh*)",
58
- "Bash(redis-cli*)",
45
+ "Bash(curl:*)",
46
+ "Bash(wget:*)",
47
+ "Bash(rm -rf:*)",
48
+ "Bash(sudo:*)",
49
+ "Bash(npm install:*)",
50
+ "Bash(npm publish:*)",
51
+ "Bash(git push --force:*)",
52
+ "Bash(git merge:*)",
53
+ "Bash(psql:*)",
54
+ "Bash(mysql:*)",
55
+ "Bash(sqlite3:*)",
56
+ "Bash(mongosh:*)",
57
+ "Bash(redis-cli:*)",
59
58
  "Bash(node ./scripts/**)",
60
59
  "Bash(node ./Agent/db/**)",
61
60
  "Bash(bash ./scripts/**)",
62
61
  "Bash(sh ./scripts/**)",
63
- "Bash(git checkout -b *)",
62
+ "Bash(git checkout -b:*)",
64
63
  "WebFetch",
65
64
  "WebSearch"
66
65
  ]
@@ -150,11 +149,7 @@
150
149
  "hooks": [
151
150
  {
152
151
  "type": "command",
153
- "command": "node node_modules/.agentic15-claude-zen/hooks/session-start-context.js"
154
- },
155
- {
156
- "type": "command",
157
- "command": "node node_modules/.agentic15-claude-zen/hooks/detect-pending-reviews.js"
152
+ "command": "node .claude/hooks/session-start-context.js"
158
153
  }
159
154
  ]
160
155
  }
@@ -174,19 +169,7 @@
174
169
  "hooks": [
175
170
  {
176
171
  "type": "command",
177
- "command": "node node_modules/.agentic15-claude-zen/hooks/enforce-hard-requirements.js"
178
- },
179
- {
180
- "type": "command",
181
- "command": "node node_modules/.agentic15-claude-zen/hooks/prevent-read-bypass.js"
182
- },
183
- {
184
- "type": "command",
185
- "command": "node node_modules/.agentic15-claude-zen/hooks/enforce-structured-development.js"
186
- },
187
- {
188
- "type": "command",
189
- "command": "node node_modules/.agentic15-claude-zen/hooks/enforce-plan-template.js"
172
+ "command": "node .claude/hooks/enforce-plan-template.js"
190
173
  }
191
174
  ]
192
175
  },
@@ -195,87 +178,18 @@
195
178
  "hooks": [
196
179
  {
197
180
  "type": "command",
198
- "command": "node node_modules/.agentic15-claude-zen/hooks/validate-git-workflow.js"
199
- },
200
- {
201
- "type": "command",
202
- "command": "node node_modules/.agentic15-claude-zen/hooks/validate-task-completion.js"
181
+ "command": "node .claude/hooks/validate-git-workflow.js"
203
182
  }
204
183
  ]
205
184
  }
206
185
  ],
207
186
  "PostToolUse": [
208
187
  {
209
- "matcher": "Edit|Write",
188
+ "matcher": "Bash(git:*)",
210
189
  "hooks": [
211
190
  {
212
191
  "type": "command",
213
- "command": "node node_modules/.agentic15-claude-zen/hooks/enforce-structured-development.js"
214
- },
215
- {
216
- "type": "command",
217
- "command": "node node_modules/.agentic15-claude-zen/hooks/auto-format.js"
218
- },
219
- {
220
- "type": "command",
221
- "command": "node node_modules/.agentic15-claude-zen/hooks/validate-ui-syntax.js"
222
- },
223
- {
224
- "type": "command",
225
- "command": "node node_modules/.agentic15-claude-zen/hooks/validate-ui-runtime.js"
226
- },
227
- {
228
- "type": "command",
229
- "command": "node node_modules/.agentic15-claude-zen/hooks/validate-ui-visual-native.js"
230
- },
231
- {
232
- "type": "command",
233
- "command": "node node_modules/.agentic15-claude-zen/hooks/validate-component-contract.js"
234
- },
235
- {
236
- "type": "command",
237
- "command": "node node_modules/.agentic15-claude-zen/hooks/validate-test-quality.js"
238
- },
239
- {
240
- "type": "command",
241
- "command": "node node_modules/.agentic15-claude-zen/hooks/validate-ui-integration.js"
242
- },
243
- {
244
- "type": "command",
245
- "command": "node node_modules/.agentic15-claude-zen/hooks/validate-integration-site.js"
246
- },
247
- {
248
- "type": "command",
249
- "command": "node node_modules/.agentic15-claude-zen/hooks/validate-database-changes.js"
250
- },
251
- {
252
- "type": "command",
253
- "command": "node node_modules/.agentic15-claude-zen/hooks/validate-migration-impact.js"
254
- },
255
- {
256
- "type": "command",
257
- "command": "node node_modules/.agentic15-claude-zen/hooks/validate-visual-regression.js"
258
- }
259
- ]
260
- },
261
- {
262
- "matcher": "Bash",
263
- "hooks": [
264
- {
265
- "type": "command",
266
- "command": "node node_modules/.agentic15-claude-zen/hooks/validate-test-results.js"
267
- },
268
- {
269
- "type": "command",
270
- "command": "node node_modules/.agentic15-claude-zen/hooks/validate-e2e-coverage.js"
271
- },
272
- {
273
- "type": "command",
274
- "command": "node node_modules/.agentic15-claude-zen/hooks/enforce-test-pyramid.js"
275
- },
276
- {
277
- "type": "command",
278
- "command": "node node_modules/.agentic15-claude-zen/hooks/enforce-migration-workflow.js"
192
+ "command": "node .claude/hooks/post-merge.js"
279
193
  }
280
194
  ]
281
195
  }
@@ -1,31 +1,31 @@
1
- {
2
- "name": "{{PROJECT_NAME}}",
3
- "version": "1.0.0",
4
- "description": "Project with Claude Code structured development framework",
5
- "type": "commonjs",
6
- "scripts": {
7
- "test": "jest --passWithNoTests"
8
- },
9
- "keywords": [
10
- "claude-code",
11
- "structured-development",
12
- "task-tracking"
13
- ],
14
- "license": "MIT",
15
- "dependencies": {
16
- "@agentic15.com/agentic15-claude-zen": "^2.0.0"
17
- },
18
- "devDependencies": {
19
- "jest": "^30.2.0",
20
- "@testing-library/react": "^16.1.0",
21
- "@testing-library/jest-dom": "^6.6.3",
22
- "@testing-library/user-event": "^14.5.2",
23
- "@babel/preset-env": "^7.26.0",
24
- "@babel/preset-react": "^7.26.3",
25
- "babel-jest": "^30.0.0",
26
- "jest-environment-jsdom": "^30.0.0",
27
- "prop-types": "^15.8.1",
28
- "identity-obj-proxy": "^3.0.0",
29
- "@playwright/test": "^1.41.0"
30
- }
31
- }
1
+ {
2
+ "name": "{{PROJECT_NAME}}",
3
+ "version": "1.0.0",
4
+ "description": "Project with Claude Code structured development framework",
5
+ "type": "commonjs",
6
+ "scripts": {
7
+ "test": "jest --passWithNoTests"
8
+ },
9
+ "keywords": [
10
+ "claude-code",
11
+ "structured-development",
12
+ "task-tracking"
13
+ ],
14
+ "license": "MIT",
15
+ "dependencies": {
16
+ "@agentic15.com/agentic15-claude-zen": "^2.0.0"
17
+ },
18
+ "devDependencies": {
19
+ "jest": "^30.2.0",
20
+ "@testing-library/react": "^16.1.0",
21
+ "@testing-library/jest-dom": "^6.6.3",
22
+ "@testing-library/user-event": "^14.5.2",
23
+ "@babel/preset-env": "^7.26.0",
24
+ "@babel/preset-react": "^7.26.3",
25
+ "babel-jest": "^30.0.0",
26
+ "jest-environment-jsdom": "^30.0.0",
27
+ "prop-types": "^15.8.1",
28
+ "identity-obj-proxy": "^3.0.0",
29
+ "@playwright/test": "^1.41.0"
30
+ }
31
+ }