@itz4blitz/agentful 1.2.0 → 1.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 +28 -1
- package/bin/cli.js +11 -1055
- package/bin/hooks/block-file-creation.js +271 -0
- package/bin/hooks/product-spec-watcher.js +151 -0
- package/lib/index.js +0 -11
- package/lib/init.js +2 -21
- package/lib/parallel-execution.js +235 -0
- package/lib/presets.js +26 -4
- package/package.json +4 -7
- package/template/.claude/agents/architect.md +2 -2
- package/template/.claude/agents/backend.md +17 -30
- package/template/.claude/agents/frontend.md +17 -39
- package/template/.claude/agents/orchestrator.md +63 -4
- package/template/.claude/agents/product-analyzer.md +1 -1
- package/template/.claude/agents/tester.md +16 -29
- package/template/.claude/commands/agentful-generate.md +221 -14
- package/template/.claude/commands/agentful-init.md +621 -0
- package/template/.claude/commands/agentful-product.md +1 -1
- package/template/.claude/commands/agentful-start.md +99 -1
- package/template/.claude/product/EXAMPLES.md +2 -2
- package/template/.claude/product/index.md +1 -1
- package/template/.claude/settings.json +22 -0
- package/template/.claude/skills/research/SKILL.md +432 -0
- package/template/CLAUDE.md +5 -6
- package/template/bin/hooks/architect-drift-detector.js +242 -0
- package/template/bin/hooks/product-spec-watcher.js +151 -0
- package/version.json +1 -1
- package/bin/hooks/post-agent.js +0 -101
- package/bin/hooks/post-feature.js +0 -227
- package/bin/hooks/pre-agent.js +0 -118
- package/bin/hooks/pre-feature.js +0 -138
- package/lib/VALIDATION_README.md +0 -455
- package/lib/ci/claude-action-integration.js +0 -641
- package/lib/ci/index.js +0 -10
- package/lib/core/analyzer.js +0 -497
- package/lib/core/cli.js +0 -141
- package/lib/core/detectors/conventions.js +0 -342
- package/lib/core/detectors/framework.js +0 -276
- package/lib/core/detectors/index.js +0 -15
- package/lib/core/detectors/language.js +0 -199
- package/lib/core/detectors/patterns.js +0 -356
- package/lib/core/generator.js +0 -626
- package/lib/core/index.js +0 -9
- package/lib/core/output-parser.js +0 -458
- package/lib/core/storage.js +0 -515
- package/lib/core/templates.js +0 -556
- package/lib/pipeline/cli.js +0 -423
- package/lib/pipeline/engine.js +0 -928
- package/lib/pipeline/executor.js +0 -440
- package/lib/pipeline/index.js +0 -33
- package/lib/pipeline/integrations.js +0 -559
- package/lib/pipeline/schemas.js +0 -288
- package/lib/remote/client.js +0 -361
- package/lib/server/auth.js +0 -270
- package/lib/server/client-example.js +0 -190
- package/lib/server/executor.js +0 -477
- package/lib/server/index.js +0 -494
- package/lib/update-helpers.js +0 -505
- package/lib/validation.js +0 -460
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Block File Creation Hook
|
|
5
|
+
*
|
|
6
|
+
* Prevents creation of arbitrary files outside of permitted directories and types.
|
|
7
|
+
* Stops agents from littering the codebase with random JSON, TXT, LOG files.
|
|
8
|
+
*
|
|
9
|
+
* Allowed file creation:
|
|
10
|
+
* - Source code files (.js, .ts, .jsx, .tsx, .py, .go, .rs, .java, .c, .cpp, .h, .cs, .rb, .php, etc.)
|
|
11
|
+
* - Config files in project root (package.json, tsconfig.json, vite.config.js, etc.)
|
|
12
|
+
* - Test files in test directories
|
|
13
|
+
* - Documentation in approved locations (see block-random-docs hook)
|
|
14
|
+
*
|
|
15
|
+
* Blocked:
|
|
16
|
+
* - Random .json files outside of root config
|
|
17
|
+
* - Random .txt, .log, .tmp files anywhere
|
|
18
|
+
* - State snapshots outside .agentful/
|
|
19
|
+
* - Arbitrary data files in src/, lib/, test/ directories
|
|
20
|
+
*
|
|
21
|
+
* Permitted directories for non-code artifacts:
|
|
22
|
+
* - .agentful/ - Runtime state (with validation)
|
|
23
|
+
* - fixtures/ - Test fixtures
|
|
24
|
+
* - mocks/ - Test mocks
|
|
25
|
+
* - public/assets/ - Static assets
|
|
26
|
+
* - docs/ - Documentation (if directory exists)
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import path from 'path';
|
|
30
|
+
import fs from 'fs';
|
|
31
|
+
|
|
32
|
+
// Get file path from environment (set by Claude Code hooks)
|
|
33
|
+
const filePath = process.env.FILE || '';
|
|
34
|
+
const toolName = process.env.TOOL_NAME || '';
|
|
35
|
+
|
|
36
|
+
// Only intercept Write tool calls
|
|
37
|
+
if (toolName !== 'Write') {
|
|
38
|
+
process.exit(0);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Normalize path
|
|
42
|
+
const normalizedPath = path.normalize(filePath);
|
|
43
|
+
|
|
44
|
+
// Source code extensions (always allowed)
|
|
45
|
+
const SOURCE_CODE_EXTENSIONS = [
|
|
46
|
+
'.js', '.mjs', '.cjs',
|
|
47
|
+
'.ts', '.mts', '.cts',
|
|
48
|
+
'.jsx', '.tsx',
|
|
49
|
+
'.py', '.pyi',
|
|
50
|
+
'.go',
|
|
51
|
+
'.rs',
|
|
52
|
+
'.java',
|
|
53
|
+
'.c', '.cpp', '.cc', '.cxx', '.h', '.hpp',
|
|
54
|
+
'.cs',
|
|
55
|
+
'.rb',
|
|
56
|
+
'.php',
|
|
57
|
+
'.swift',
|
|
58
|
+
'.kt', '.kts',
|
|
59
|
+
'.scala',
|
|
60
|
+
'.ex', '.exs',
|
|
61
|
+
'.clj', '.cljs',
|
|
62
|
+
'.sh', '.bash',
|
|
63
|
+
'.sql',
|
|
64
|
+
'.graphql', '.gql',
|
|
65
|
+
'.proto',
|
|
66
|
+
'.vue', '.svelte',
|
|
67
|
+
'.css', '.scss', '.sass', '.less',
|
|
68
|
+
'.html', '.htm',
|
|
69
|
+
'.xml', '.yaml', '.yml',
|
|
70
|
+
'.toml', '.ini', '.env.example',
|
|
71
|
+
'.gitignore', '.dockerignore', '.eslintignore'
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
// Check if file is source code
|
|
75
|
+
const ext = path.extname(normalizedPath);
|
|
76
|
+
if (SOURCE_CODE_EXTENSIONS.includes(ext)) {
|
|
77
|
+
process.exit(0);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Markdown files are handled by block-random-docs hook
|
|
81
|
+
if (ext === '.md' || ext === '.mdx') {
|
|
82
|
+
process.exit(0);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Root-level config files (explicitly allowed)
|
|
86
|
+
const ROOT_CONFIG_FILES = [
|
|
87
|
+
'package.json',
|
|
88
|
+
'package-lock.json',
|
|
89
|
+
'yarn.lock',
|
|
90
|
+
'pnpm-lock.yaml',
|
|
91
|
+
'bun.lockb',
|
|
92
|
+
'tsconfig.json',
|
|
93
|
+
'jsconfig.json',
|
|
94
|
+
'vite.config.js',
|
|
95
|
+
'vite.config.ts',
|
|
96
|
+
'vitest.config.js',
|
|
97
|
+
'vitest.config.ts',
|
|
98
|
+
'vitest.setup.js',
|
|
99
|
+
'vitest.setup.ts',
|
|
100
|
+
'vitest.global-teardown.js',
|
|
101
|
+
'jest.config.js',
|
|
102
|
+
'jest.config.ts',
|
|
103
|
+
'next.config.js',
|
|
104
|
+
'next.config.mjs',
|
|
105
|
+
'nuxt.config.js',
|
|
106
|
+
'nuxt.config.ts',
|
|
107
|
+
'svelte.config.js',
|
|
108
|
+
'astro.config.mjs',
|
|
109
|
+
'tailwind.config.js',
|
|
110
|
+
'tailwind.config.ts',
|
|
111
|
+
'postcss.config.js',
|
|
112
|
+
'eslint.config.js',
|
|
113
|
+
'.eslintrc.json',
|
|
114
|
+
'.eslintrc.js',
|
|
115
|
+
'.prettierrc',
|
|
116
|
+
'.prettierrc.json',
|
|
117
|
+
'prettier.config.js',
|
|
118
|
+
'turbo.json',
|
|
119
|
+
'nx.json',
|
|
120
|
+
'lerna.json',
|
|
121
|
+
'Dockerfile',
|
|
122
|
+
'docker-compose.yml',
|
|
123
|
+
'docker-compose.yaml',
|
|
124
|
+
'.dockerignore',
|
|
125
|
+
'.gitignore',
|
|
126
|
+
'.env.example',
|
|
127
|
+
'vercel.json',
|
|
128
|
+
'railway.json',
|
|
129
|
+
'render.yaml',
|
|
130
|
+
'fly.toml'
|
|
131
|
+
];
|
|
132
|
+
|
|
133
|
+
// Check if file is a root config file
|
|
134
|
+
const fileName = path.basename(normalizedPath);
|
|
135
|
+
if (ROOT_CONFIG_FILES.includes(fileName) && !normalizedPath.includes('/')) {
|
|
136
|
+
process.exit(0);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Allowed directory patterns for non-code files
|
|
140
|
+
const ALLOWED_DIRECTORY_PATTERNS = [
|
|
141
|
+
/^\.agentful\//, // Runtime state
|
|
142
|
+
/^\.claude\//, // Claude configuration
|
|
143
|
+
/^fixtures\//, // Test fixtures
|
|
144
|
+
/^test\/fixtures\//,
|
|
145
|
+
/^tests\/fixtures\//,
|
|
146
|
+
/^__fixtures__\//,
|
|
147
|
+
/^mocks\//, // Test mocks
|
|
148
|
+
/^test\/mocks\//,
|
|
149
|
+
/^tests\/mocks\//,
|
|
150
|
+
/^__mocks__\//,
|
|
151
|
+
/^public\/assets\//, // Static assets
|
|
152
|
+
/^public\/data\//,
|
|
153
|
+
/^static\/assets\//,
|
|
154
|
+
/^static\/data\//,
|
|
155
|
+
/^docs\/assets\//, // Documentation assets
|
|
156
|
+
/^\.github\//, // GitHub config
|
|
157
|
+
/^\.vscode\//, // VSCode config
|
|
158
|
+
/^config\//, // Config directory
|
|
159
|
+
/^\.config\//,
|
|
160
|
+
/^dist\//, // Build output (warn but allow)
|
|
161
|
+
/^build\//,
|
|
162
|
+
/^out\//
|
|
163
|
+
];
|
|
164
|
+
|
|
165
|
+
// Check if file is in allowed directory
|
|
166
|
+
const isInAllowedDir = ALLOWED_DIRECTORY_PATTERNS.some(pattern => pattern.test(normalizedPath));
|
|
167
|
+
|
|
168
|
+
if (isInAllowedDir) {
|
|
169
|
+
// Additional validation for .agentful/ files
|
|
170
|
+
if (normalizedPath.startsWith('.agentful/')) {
|
|
171
|
+
const agentfulFiles = [
|
|
172
|
+
'.agentful/state.json',
|
|
173
|
+
'.agentful/completion.json',
|
|
174
|
+
'.agentful/decisions.json',
|
|
175
|
+
'.agentful/architecture.json',
|
|
176
|
+
'.agentful/conversation-state.json',
|
|
177
|
+
'.agentful/conversation-history.json',
|
|
178
|
+
'.agentful/agent-metrics.json',
|
|
179
|
+
'.agentful/metadata.json'
|
|
180
|
+
];
|
|
181
|
+
|
|
182
|
+
if (agentfulFiles.includes(normalizedPath)) {
|
|
183
|
+
process.exit(0);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Block random files in .agentful/
|
|
187
|
+
console.error(`
|
|
188
|
+
❌ BLOCKED: Arbitrary file creation in .agentful/
|
|
189
|
+
|
|
190
|
+
File: ${filePath}
|
|
191
|
+
|
|
192
|
+
Allowed .agentful/ files:
|
|
193
|
+
- state.json (current work phase)
|
|
194
|
+
- completion.json (feature progress)
|
|
195
|
+
- decisions.json (pending decisions)
|
|
196
|
+
- architecture.json (tech stack)
|
|
197
|
+
- conversation-state.json (conversation context)
|
|
198
|
+
- conversation-history.json (message history)
|
|
199
|
+
- agent-metrics.json (agent lifecycle hooks)
|
|
200
|
+
- metadata.json (version tracking)
|
|
201
|
+
|
|
202
|
+
Do NOT create random state snapshots or debug files in .agentful/.
|
|
203
|
+
`);
|
|
204
|
+
process.exit(1);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Allow other permitted directories
|
|
208
|
+
process.exit(0);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Risky file extensions (almost never allowed outside approved directories)
|
|
212
|
+
const RISKY_EXTENSIONS = [
|
|
213
|
+
'.json',
|
|
214
|
+
'.txt',
|
|
215
|
+
'.log',
|
|
216
|
+
'.tmp',
|
|
217
|
+
'.temp',
|
|
218
|
+
'.bak',
|
|
219
|
+
'.backup',
|
|
220
|
+
'.old',
|
|
221
|
+
'.data',
|
|
222
|
+
'.dat',
|
|
223
|
+
'.bin',
|
|
224
|
+
'.dump',
|
|
225
|
+
'.out'
|
|
226
|
+
];
|
|
227
|
+
|
|
228
|
+
if (RISKY_EXTENSIONS.includes(ext)) {
|
|
229
|
+
console.error(`
|
|
230
|
+
❌ BLOCKED: Random file creation
|
|
231
|
+
|
|
232
|
+
File: ${filePath}
|
|
233
|
+
Type: ${ext} file
|
|
234
|
+
|
|
235
|
+
This file type is not allowed outside of approved directories.
|
|
236
|
+
|
|
237
|
+
Allowed locations for ${ext} files:
|
|
238
|
+
${ext === '.json' ? '- Project root (config files like package.json, tsconfig.json)' : ''}
|
|
239
|
+
- .agentful/ (runtime state, validation required)
|
|
240
|
+
- fixtures/ (test fixtures)
|
|
241
|
+
- mocks/ (test mocks)
|
|
242
|
+
- public/assets/ (static assets)
|
|
243
|
+
${ext === '.json' ? '- test/**/fixtures/ (test data)' : ''}
|
|
244
|
+
|
|
245
|
+
Source code files (.js, .ts, .py, etc.) can be created anywhere.
|
|
246
|
+
|
|
247
|
+
Instead of creating random ${ext} files:
|
|
248
|
+
1. Use proper source code files
|
|
249
|
+
2. Store test data in fixtures/
|
|
250
|
+
3. Store config in root (package.json, tsconfig.json)
|
|
251
|
+
4. Store runtime state in .agentful/ (validated files only)
|
|
252
|
+
|
|
253
|
+
Do NOT litter the codebase with arbitrary data files.
|
|
254
|
+
`);
|
|
255
|
+
process.exit(1);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Unknown file type - warn but allow (might be a legitimate file)
|
|
259
|
+
console.warn(`
|
|
260
|
+
⚠️ WARNING: Creating file with uncommon extension
|
|
261
|
+
|
|
262
|
+
File: ${filePath}
|
|
263
|
+
Extension: ${ext || '(no extension)'}
|
|
264
|
+
|
|
265
|
+
This file type is not explicitly allowed or blocked.
|
|
266
|
+
If this is a legitimate file, you can proceed.
|
|
267
|
+
If this is a random artifact, please reconsider.
|
|
268
|
+
`);
|
|
269
|
+
|
|
270
|
+
// Allow with warning
|
|
271
|
+
process.exit(0);
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Product Spec Watcher Hook
|
|
5
|
+
*
|
|
6
|
+
* Triggered on Write/Edit of .claude/product/ markdown files
|
|
7
|
+
* Auto-triggers /agentful-generate when product spec is updated
|
|
8
|
+
*
|
|
9
|
+
* Use case:
|
|
10
|
+
* 1. User runs /agentful-init → creates .claude/product/index.md
|
|
11
|
+
* 2. This hook detects the file creation
|
|
12
|
+
* 3. Checks if from /agentful-init flow
|
|
13
|
+
* 4. Auto-triggers agent generation with BOTH tech stack + requirements
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import fs from 'fs';
|
|
17
|
+
import path from 'path';
|
|
18
|
+
import { execSync } from 'child_process';
|
|
19
|
+
|
|
20
|
+
// Get tool use metadata from environment
|
|
21
|
+
const toolUseEnv = process.env.CLAUDE_TOOL_USE || '{}';
|
|
22
|
+
let toolUse;
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
toolUse = JSON.parse(toolUseEnv);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
// Invalid JSON - exit silently
|
|
28
|
+
process.exit(0);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Get the file path that was written/edited
|
|
32
|
+
const filePath = toolUse.parameters?.file_path || '';
|
|
33
|
+
|
|
34
|
+
// Only trigger on product spec files
|
|
35
|
+
if (!filePath.includes('.claude/product/')) {
|
|
36
|
+
process.exit(0);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Get the root directory
|
|
40
|
+
const getRepoRoot = () => {
|
|
41
|
+
try {
|
|
42
|
+
return execSync('git rev-parse --show-toplevel', {
|
|
43
|
+
encoding: 'utf8'
|
|
44
|
+
}).trim();
|
|
45
|
+
} catch {
|
|
46
|
+
// Not a git repo - use cwd
|
|
47
|
+
return process.cwd();
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const repoRoot = getRepoRoot();
|
|
52
|
+
const setupProgressPath = path.join(repoRoot, '.agentful', 'setup-progress.json');
|
|
53
|
+
const architecturePath = path.join(repoRoot, '.agentful', 'architecture.json');
|
|
54
|
+
|
|
55
|
+
// Check if this is from /agentful-init flow
|
|
56
|
+
let isFromInit = false;
|
|
57
|
+
let setupProgress = null;
|
|
58
|
+
|
|
59
|
+
if (fs.existsSync(setupProgressPath)) {
|
|
60
|
+
try {
|
|
61
|
+
setupProgress = JSON.parse(fs.readFileSync(setupProgressPath, 'utf8'));
|
|
62
|
+
|
|
63
|
+
// Check if setup just completed but agents not yet generated
|
|
64
|
+
isFromInit = setupProgress.completed &&
|
|
65
|
+
!setupProgress.agents_generated &&
|
|
66
|
+
// Must be recent (within last 5 minutes)
|
|
67
|
+
(Date.now() - new Date(setupProgress.timestamp).getTime()) < 5 * 60 * 1000;
|
|
68
|
+
} catch (error) {
|
|
69
|
+
// Ignore JSON parse errors
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Check if agents already exist
|
|
74
|
+
const hasExistingAgents = fs.existsSync(architecturePath);
|
|
75
|
+
|
|
76
|
+
if (isFromInit && !hasExistingAgents) {
|
|
77
|
+
console.log(`
|
|
78
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
79
|
+
Product Specification Updated
|
|
80
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
81
|
+
|
|
82
|
+
File: ${path.relative(repoRoot, filePath)}
|
|
83
|
+
|
|
84
|
+
Auto-triggering agent generation with:
|
|
85
|
+
✓ Tech stack (detected)
|
|
86
|
+
✓ Product requirements (from /agentful-init)
|
|
87
|
+
|
|
88
|
+
This ensures specialized agents are tailored to your product.
|
|
89
|
+
|
|
90
|
+
Starting analysis...
|
|
91
|
+
`);
|
|
92
|
+
|
|
93
|
+
// Mark that we're about to generate agents
|
|
94
|
+
if (setupProgress) {
|
|
95
|
+
setupProgress.agents_generation_triggered = true;
|
|
96
|
+
setupProgress.agents_generation_timestamp = new Date().toISOString();
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
fs.writeFileSync(setupProgressPath, JSON.stringify(setupProgress, null, 2));
|
|
100
|
+
} catch (error) {
|
|
101
|
+
// Non-fatal - continue anyway
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// NOTE: The actual triggering of /agentful-generate would happen here
|
|
106
|
+
// This depends on Claude Code's slash command triggering system
|
|
107
|
+
// For now, we just notify the user
|
|
108
|
+
|
|
109
|
+
console.log(`
|
|
110
|
+
⏭️ Next: Agent generation will continue automatically.
|
|
111
|
+
|
|
112
|
+
If it doesn't start automatically, run:
|
|
113
|
+
/agentful-generate
|
|
114
|
+
`);
|
|
115
|
+
|
|
116
|
+
} else if (!isFromInit && !hasExistingAgents) {
|
|
117
|
+
// Manual edit of product spec, but no agents yet
|
|
118
|
+
console.log(`
|
|
119
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
120
|
+
Product Specification Updated
|
|
121
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
122
|
+
|
|
123
|
+
File: ${path.relative(repoRoot, filePath)}
|
|
124
|
+
|
|
125
|
+
To generate specialized agents based on your product spec:
|
|
126
|
+
/agentful-generate
|
|
127
|
+
|
|
128
|
+
Or to use the guided setup:
|
|
129
|
+
/agentful-init
|
|
130
|
+
`);
|
|
131
|
+
|
|
132
|
+
} else if (hasExistingAgents) {
|
|
133
|
+
// Agents already exist - notify about regeneration
|
|
134
|
+
console.log(`
|
|
135
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
136
|
+
Product Specification Updated
|
|
137
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
138
|
+
|
|
139
|
+
File: ${path.relative(repoRoot, filePath)}
|
|
140
|
+
|
|
141
|
+
Your product spec changed, but agents already exist.
|
|
142
|
+
|
|
143
|
+
To regenerate agents with updated requirements:
|
|
144
|
+
/agentful-generate
|
|
145
|
+
|
|
146
|
+
Or continue with existing agents:
|
|
147
|
+
/agentful-start
|
|
148
|
+
`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
process.exit(0);
|
package/lib/index.js
CHANGED
|
@@ -12,10 +12,6 @@ export { initProject, copyDirectory, isInitialized, getState } from './init.js';
|
|
|
12
12
|
// Export pipeline orchestration system
|
|
13
13
|
export * from './pipeline/index.js';
|
|
14
14
|
|
|
15
|
-
// Export codebase analyzer
|
|
16
|
-
export * from './core/analyzer.js';
|
|
17
|
-
export * from './core/detectors/index.js';
|
|
18
|
-
|
|
19
15
|
// Export Claude Code executor abstraction
|
|
20
16
|
export {
|
|
21
17
|
ClaudeExecutor,
|
|
@@ -26,13 +22,6 @@ export {
|
|
|
26
22
|
executeAgent
|
|
27
23
|
} from './core/claude-executor.js';
|
|
28
24
|
|
|
29
|
-
// Export output parser for agent responses
|
|
30
|
-
export * from './core/output-parser.js';
|
|
31
|
-
|
|
32
|
-
// Export safe agent execution (prevents runaway agents)
|
|
33
|
-
export { SafeAgentExecutor, executeAgentSafely } from './safe-agent-executor.js';
|
|
34
|
-
export { ParallelAgentOrchestrator, spawnAgentsSafely } from './orchestrator-safe-spawn.js';
|
|
35
|
-
|
|
36
25
|
// Export CI integration for claude-code-action
|
|
37
26
|
export * from './ci/index.js';
|
|
38
27
|
|
package/lib/init.js
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import fs from 'fs/promises';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
|
-
import {
|
|
5
|
-
initializeMetadata,
|
|
6
|
-
recordFileMetadata,
|
|
7
|
-
computeFileHash
|
|
8
|
-
} from './update-helpers.js';
|
|
9
4
|
import { generateHooksConfig } from './presets.js';
|
|
10
5
|
|
|
11
6
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -32,14 +27,11 @@ export async function initProject(targetDir, config = null) {
|
|
|
32
27
|
// Ensure target directory exists
|
|
33
28
|
await fs.access(targetDir);
|
|
34
29
|
|
|
35
|
-
// Read package version
|
|
30
|
+
// Read package version
|
|
36
31
|
const packageJsonPath = path.join(PACKAGE_ROOT, 'package.json');
|
|
37
32
|
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8'));
|
|
38
33
|
const version = packageJson.version;
|
|
39
34
|
|
|
40
|
-
// Initialize metadata tracking
|
|
41
|
-
await initializeMetadata(targetDir, version);
|
|
42
|
-
|
|
43
35
|
// 1. Copy .claude/ directory (agents, skills, commands) from template
|
|
44
36
|
const claudeTargetDir = path.join(targetDir, '.claude');
|
|
45
37
|
|
|
@@ -77,9 +69,7 @@ export async function initProject(targetDir, config = null) {
|
|
|
77
69
|
await fs.access(claudeMdSource);
|
|
78
70
|
await fs.copyFile(claudeMdSource, claudeMdTarget);
|
|
79
71
|
|
|
80
|
-
//
|
|
81
|
-
const hash = await computeFileHash(claudeMdTarget);
|
|
82
|
-
await recordFileMetadata(targetDir, 'CLAUDE.md', hash, version);
|
|
72
|
+
// CLAUDE.md copied
|
|
83
73
|
|
|
84
74
|
createdFiles.push('CLAUDE.md');
|
|
85
75
|
} catch {
|
|
@@ -473,8 +463,6 @@ async function copySelectiveComponents(src, dest, targetDir, config, version) {
|
|
|
473
463
|
|
|
474
464
|
try {
|
|
475
465
|
await fs.copyFile(sourcePath, targetPath);
|
|
476
|
-
const hash = await computeFileHash(targetPath);
|
|
477
|
-
await recordFileMetadata(targetDir, `.claude/agents/${agentFile}`, hash, version);
|
|
478
466
|
} catch (error) {
|
|
479
467
|
console.warn(`Warning: Agent ${agentName} not found, skipping`);
|
|
480
468
|
}
|
|
@@ -539,8 +527,6 @@ async function copySelectiveComponents(src, dest, targetDir, config, version) {
|
|
|
539
527
|
};
|
|
540
528
|
|
|
541
529
|
await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2));
|
|
542
|
-
const hash = await computeFileHash(settingsPath);
|
|
543
|
-
await recordFileMetadata(targetDir, '.claude/settings.json', hash, version);
|
|
544
530
|
|
|
545
531
|
// 5. Create product directory (always included)
|
|
546
532
|
const productDir = path.join(dest, 'product');
|
|
@@ -599,11 +585,6 @@ export async function copyDirectoryWithTracking(src, dest, targetDir, baseRelati
|
|
|
599
585
|
} else {
|
|
600
586
|
// Copy file
|
|
601
587
|
await fs.copyFile(srcPath, destPath);
|
|
602
|
-
|
|
603
|
-
// Compute hash and track file
|
|
604
|
-
const relativePath = path.join(baseRelativePath, entry.name);
|
|
605
|
-
const hash = await computeFileHash(destPath);
|
|
606
|
-
await recordFileMetadata(targetDir, relativePath, hash, version);
|
|
607
588
|
}
|
|
608
589
|
}
|
|
609
590
|
}
|