create-claude-context 1.2.0 → 1.2.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.
- package/README.md +29 -6
- package/bin/create-claude-context.js +15 -1
- package/lib/ai-orchestrator.js +423 -0
- package/lib/call-tracer.js +444 -0
- package/lib/detector.js +83 -0
- package/lib/environment-detector.js +239 -0
- package/lib/index.js +128 -27
- package/lib/placeholder.js +80 -19
- package/lib/static-analyzer.js +729 -0
- package/lib/template-populator.js +835 -0
- package/package.json +1 -1
- package/templates/base/settings.json +1 -77
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# create-claude-context
|
|
2
2
|
|
|
3
|
-
Set up Claude Context Engineering for any project with a single command.
|
|
3
|
+
Set up Claude Context Engineering for any project with a single command. **Automatically analyzes your codebase** and generates real documentation.
|
|
4
4
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
@@ -16,12 +16,22 @@ npm init claude-context
|
|
|
16
16
|
|
|
17
17
|
## What It Does
|
|
18
18
|
|
|
19
|
-
This CLI tool
|
|
19
|
+
This CLI tool performs **real codebase analysis** and creates a complete context engineering system:
|
|
20
20
|
|
|
21
|
-
1. **
|
|
22
|
-
2. **Creates
|
|
23
|
-
3. **
|
|
24
|
-
4. **
|
|
21
|
+
1. **Analyzes codebase** - Discovers entry points, workflows, architecture
|
|
22
|
+
2. **Creates `.claude/` directory** - Populated with real project data
|
|
23
|
+
3. **Creates `CLAUDE.md`** - Entry point with actual file references
|
|
24
|
+
4. **Detects tech stack** - Auto-configures for your project
|
|
25
|
+
5. **AI handoff** - Creates instructions for `@context-engineer` (when in Claude Code)
|
|
26
|
+
|
|
27
|
+
### Automatic Analysis
|
|
28
|
+
|
|
29
|
+
| What's Detected | Description |
|
|
30
|
+
|-----------------|-------------|
|
|
31
|
+
| Entry Points | API routes, CLI handlers, event listeners |
|
|
32
|
+
| Workflows | Authentication, payments, data processing patterns |
|
|
33
|
+
| Architecture | Directory structure, layers, dependencies |
|
|
34
|
+
| Tech Stack | Languages, frameworks, package managers |
|
|
25
35
|
|
|
26
36
|
## Options
|
|
27
37
|
|
|
@@ -34,11 +44,24 @@ Options:
|
|
|
34
44
|
-t, --template Use a tech stack preset
|
|
35
45
|
--no-git Skip git initialization
|
|
36
46
|
--dry-run Show what would be done
|
|
47
|
+
--ai Force AI mode (requires Claude Code)
|
|
48
|
+
--static Force static-only analysis
|
|
49
|
+
--analyze-only Run analysis without installation
|
|
37
50
|
-v, --verbose Show detailed output
|
|
38
51
|
-V, --version Output version number
|
|
39
52
|
-h, --help Display help
|
|
40
53
|
```
|
|
41
54
|
|
|
55
|
+
## Execution Modes
|
|
56
|
+
|
|
57
|
+
| Mode | Condition | Capabilities |
|
|
58
|
+
|------|-----------|--------------|
|
|
59
|
+
| **full-ai** | Claude Code + API key | Complete AI-enhanced analysis |
|
|
60
|
+
| **hybrid** | Claude Code (no API) | Static analysis + AI handoff |
|
|
61
|
+
| **standalone** | No Claude Code | Static analysis only |
|
|
62
|
+
|
|
63
|
+
In hybrid mode, `INIT_REQUEST.md` is created for `@context-engineer` to complete setup.
|
|
64
|
+
|
|
42
65
|
## Tech Stack Presets
|
|
43
66
|
|
|
44
67
|
```bash
|
|
@@ -36,9 +36,19 @@ program
|
|
|
36
36
|
.option('--no-git', 'Skip git initialization')
|
|
37
37
|
.option('--dry-run', 'Show what would be done without making changes')
|
|
38
38
|
.option('-v, --verbose', 'Show detailed output')
|
|
39
|
+
// New options for context engineering initialization
|
|
40
|
+
.option('--ai', 'Force AI mode (creates INIT_REQUEST.md for @context-engineer)')
|
|
41
|
+
.option('--static', 'Force standalone mode (static analysis only, no AI setup)')
|
|
42
|
+
.option('--analyze-only', 'Run codebase analysis without installation')
|
|
39
43
|
.action(async (projectName, options) => {
|
|
40
44
|
console.log(banner);
|
|
41
45
|
|
|
46
|
+
// Validate mutually exclusive options
|
|
47
|
+
if (options.ai && options.static) {
|
|
48
|
+
console.error(chalk.red('\n✖ Error: --ai and --static are mutually exclusive'));
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
|
|
42
52
|
try {
|
|
43
53
|
await run({
|
|
44
54
|
projectName,
|
|
@@ -47,7 +57,11 @@ program
|
|
|
47
57
|
template: options.template,
|
|
48
58
|
initGit: options.git !== false,
|
|
49
59
|
dryRun: options.dryRun,
|
|
50
|
-
verbose: options.verbose
|
|
60
|
+
verbose: options.verbose,
|
|
61
|
+
// New options
|
|
62
|
+
forceAi: options.ai,
|
|
63
|
+
forceStatic: options.static,
|
|
64
|
+
analyzeOnly: options.analyzeOnly
|
|
51
65
|
});
|
|
52
66
|
} catch (error) {
|
|
53
67
|
console.error(chalk.red('\n✖ Error:'), error.message);
|
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Orchestrator
|
|
3
|
+
*
|
|
4
|
+
* Coordinates with @context-engineer agent for full AI-powered analysis.
|
|
5
|
+
* Creates initialization requests and generates agent instructions.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Marker file for pending initialization
|
|
13
|
+
*/
|
|
14
|
+
const INIT_MARKER = '.init-pending';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Instruction file for agent
|
|
18
|
+
*/
|
|
19
|
+
const INIT_REQUEST_FILE = 'INIT_REQUEST.md';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Progress tracking file
|
|
23
|
+
*/
|
|
24
|
+
const PROGRESS_FILE = 'INIT_PROGRESS.json';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Create an initialization request marker
|
|
28
|
+
* @param {string} claudeDir - .claude directory path
|
|
29
|
+
* @param {object} config - Configuration from CLI
|
|
30
|
+
* @returns {object} Request object
|
|
31
|
+
*/
|
|
32
|
+
function createInitializationRequest(claudeDir, config) {
|
|
33
|
+
const request = {
|
|
34
|
+
version: '1.0.0',
|
|
35
|
+
createdAt: new Date().toISOString(),
|
|
36
|
+
projectName: config.projectName || path.basename(path.dirname(claudeDir)),
|
|
37
|
+
config: {
|
|
38
|
+
techStack: config.techStack,
|
|
39
|
+
features: config.features,
|
|
40
|
+
installPlugin: config.installPlugin
|
|
41
|
+
},
|
|
42
|
+
phases: [
|
|
43
|
+
{ id: 'repository-analysis', name: 'Repository Analysis', status: 'pending', progress: 0 },
|
|
44
|
+
{ id: 'workflow-discovery', name: 'Workflow Discovery', status: 'pending', progress: 0 },
|
|
45
|
+
{ id: 'template-population', name: 'Template Population', status: 'pending', progress: 0 },
|
|
46
|
+
{ id: 'index-generation', name: 'Index Generation', status: 'pending', progress: 0 },
|
|
47
|
+
{ id: 'validation', name: 'Validation', status: 'pending', progress: 0 },
|
|
48
|
+
{ id: 'finalization', name: 'Finalization', status: 'pending', progress: 0 }
|
|
49
|
+
],
|
|
50
|
+
status: 'pending',
|
|
51
|
+
completedAt: null
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const markerPath = path.join(claudeDir, INIT_MARKER);
|
|
55
|
+
fs.writeFileSync(markerPath, JSON.stringify(request, null, 2));
|
|
56
|
+
|
|
57
|
+
return request;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Generate agent instruction file with pre-analysis results
|
|
62
|
+
* @param {string} claudeDir - .claude directory path
|
|
63
|
+
* @param {object} analysis - Pre-analysis results from static analyzer
|
|
64
|
+
* @param {object} config - Configuration from CLI
|
|
65
|
+
*/
|
|
66
|
+
function generateAgentInstructions(claudeDir, analysis, config) {
|
|
67
|
+
const projectName = config.projectName || path.basename(path.dirname(claudeDir));
|
|
68
|
+
const pkgVersion = getPackageVersion();
|
|
69
|
+
|
|
70
|
+
const instructions = `# Context Engineering Initialization Request
|
|
71
|
+
|
|
72
|
+
> **Auto-generated by \`create-claude-context\` v${pkgVersion}**
|
|
73
|
+
> Generated: ${new Date().toISOString()}
|
|
74
|
+
|
|
75
|
+
## Status: Awaiting AI Completion
|
|
76
|
+
|
|
77
|
+
The CLI has performed static pre-analysis and prepared the template structure.
|
|
78
|
+
Full AI-powered context engineering is requested to complete initialization.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Project Overview
|
|
83
|
+
|
|
84
|
+
| Property | Value |
|
|
85
|
+
|----------|-------|
|
|
86
|
+
| **Project Name** | ${projectName} |
|
|
87
|
+
| **Tech Stack** | ${analysis.techStack?.summary || 'Detected during analysis'} |
|
|
88
|
+
| **Source Files** | ${analysis.sourceFiles || 'TBD'} |
|
|
89
|
+
| **Lines of Code** | ${analysis.linesOfCode?.total || 'TBD'} |
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Pre-Analysis Results
|
|
94
|
+
|
|
95
|
+
### Entry Points Discovered (${analysis.entryPoints?.length || 0})
|
|
96
|
+
|
|
97
|
+
${formatEntryPoints(analysis.entryPoints)}
|
|
98
|
+
|
|
99
|
+
### Workflow Candidates (${analysis.workflows?.length || 0})
|
|
100
|
+
|
|
101
|
+
${formatWorkflows(analysis.workflows)}
|
|
102
|
+
|
|
103
|
+
### Architecture Layers
|
|
104
|
+
|
|
105
|
+
${formatLayers(analysis.architecture?.layers)}
|
|
106
|
+
|
|
107
|
+
### Dependencies (${analysis.dependencies?.length || 0})
|
|
108
|
+
|
|
109
|
+
${formatDependencies(analysis.dependencies)}
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Requested Actions
|
|
114
|
+
|
|
115
|
+
Please complete the context engineering initialization by:
|
|
116
|
+
|
|
117
|
+
### Phase 1: Verify Pre-Analysis
|
|
118
|
+
- [ ] Review discovered entry points for accuracy
|
|
119
|
+
- [ ] Confirm workflow candidates are valid
|
|
120
|
+
- [ ] Identify any missed entry points or workflows
|
|
121
|
+
|
|
122
|
+
### Phase 2: Deep Workflow Discovery
|
|
123
|
+
- [ ] Trace call chains for each workflow (3 levels deep)
|
|
124
|
+
- [ ] Identify database operations per workflow
|
|
125
|
+
- [ ] Map external API calls per workflow
|
|
126
|
+
- [ ] Document error handling patterns
|
|
127
|
+
|
|
128
|
+
### Phase 3: Template Population
|
|
129
|
+
- [ ] Fill ARCHITECTURE_SNAPSHOT.md with real architecture
|
|
130
|
+
- [ ] Create individual workflow files (8-15 total)
|
|
131
|
+
- [ ] Populate CODE_TO_WORKFLOW_MAP.md with file references
|
|
132
|
+
- [ ] Update WORKFLOW_INDEX.md with all workflows
|
|
133
|
+
|
|
134
|
+
### Phase 4: Index Generation
|
|
135
|
+
- [ ] Generate proper category indexes
|
|
136
|
+
- [ ] Create semantic anchors for key functions
|
|
137
|
+
- [ ] Build reverse lookup indexes
|
|
138
|
+
|
|
139
|
+
### Phase 5: Validation
|
|
140
|
+
- [ ] Verify line number accuracy (target: 60%+)
|
|
141
|
+
- [ ] Check all internal links
|
|
142
|
+
- [ ] Confirm no placeholder values remain
|
|
143
|
+
|
|
144
|
+
### Phase 6: Finalization
|
|
145
|
+
- [ ] Generate summary report
|
|
146
|
+
- [ ] Update CLAUDE.md with project-specific info
|
|
147
|
+
- [ ] Create maintenance schedule
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Quick Start Command
|
|
152
|
+
|
|
153
|
+
\`\`\`bash
|
|
154
|
+
@context-engineer "Complete initialization for ${projectName} using the pre-analysis in INIT_REQUEST.md"
|
|
155
|
+
\`\`\`
|
|
156
|
+
|
|
157
|
+
Or use the dedicated command:
|
|
158
|
+
|
|
159
|
+
\`\`\`bash
|
|
160
|
+
/rpi-research "Complete context engineering initialization"
|
|
161
|
+
\`\`\`
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Files to Update
|
|
166
|
+
|
|
167
|
+
| File | Action |
|
|
168
|
+
|------|--------|
|
|
169
|
+
| \`context/ARCHITECTURE_SNAPSHOT.md\` | Populate with real architecture |
|
|
170
|
+
| \`context/WORKFLOW_INDEX.md\` | Add all discovered workflows |
|
|
171
|
+
| \`context/CODE_TO_WORKFLOW_MAP.md\` | Map files to workflows |
|
|
172
|
+
| \`context/workflows/*.md\` | Create individual workflow docs |
|
|
173
|
+
| \`indexes/workflows/CATEGORY_INDEX.md\` | Generate category index |
|
|
174
|
+
| \`../CLAUDE.md\` | Finalize with project info |
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Pre-Analysis Data
|
|
179
|
+
|
|
180
|
+
The following JSON contains the full pre-analysis for programmatic use:
|
|
181
|
+
|
|
182
|
+
\`\`\`json
|
|
183
|
+
${JSON.stringify(analysis.summary || {}, null, 2)}
|
|
184
|
+
\`\`\`
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
*This file will be deleted automatically after successful initialization.*
|
|
189
|
+
*Generated by create-claude-context v${pkgVersion}*
|
|
190
|
+
`;
|
|
191
|
+
|
|
192
|
+
const instructionPath = path.join(claudeDir, INIT_REQUEST_FILE);
|
|
193
|
+
fs.writeFileSync(instructionPath, instructions);
|
|
194
|
+
|
|
195
|
+
return instructionPath;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Format entry points for markdown
|
|
200
|
+
* @param {object[]} entryPoints - Entry points array
|
|
201
|
+
* @returns {string}
|
|
202
|
+
*/
|
|
203
|
+
function formatEntryPoints(entryPoints) {
|
|
204
|
+
if (!entryPoints || entryPoints.length === 0) {
|
|
205
|
+
return '*No entry points discovered during pre-analysis. AI analysis will discover them.*\n';
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const limited = entryPoints.slice(0, 15);
|
|
209
|
+
let output = '| File | Line | Route | Method |\n|------|------|-------|--------|\n';
|
|
210
|
+
|
|
211
|
+
for (const ep of limited) {
|
|
212
|
+
output += `| \`${ep.file}\` | ${ep.line} | ${ep.route || '-'} | ${ep.method || '-'} |\n`;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (entryPoints.length > 15) {
|
|
216
|
+
output += `\n*...and ${entryPoints.length - 15} more entry points*\n`;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return output;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Format workflows for markdown
|
|
224
|
+
* @param {object[]} workflows - Workflows array
|
|
225
|
+
* @returns {string}
|
|
226
|
+
*/
|
|
227
|
+
function formatWorkflows(workflows) {
|
|
228
|
+
if (!workflows || workflows.length === 0) {
|
|
229
|
+
return '*No workflows discovered during pre-analysis. AI analysis will discover them.*\n';
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
let output = '| Workflow | Category | Complexity | Files | Confidence |\n|----------|----------|------------|-------|------------|\n';
|
|
233
|
+
|
|
234
|
+
for (const wf of workflows) {
|
|
235
|
+
output += `| **${wf.name}** | ${wf.category} | ${wf.complexity} | ${wf.fileCount || wf.files?.length || 0} | ${wf.confidence || '-'}% |\n`;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return output;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Format architecture layers for markdown
|
|
243
|
+
* @param {object[]} layers - Layers array
|
|
244
|
+
* @returns {string}
|
|
245
|
+
*/
|
|
246
|
+
function formatLayers(layers) {
|
|
247
|
+
if (!layers || layers.length === 0) {
|
|
248
|
+
return '*Architecture layers will be determined during AI analysis.*\n';
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
let output = '| Layer | Directories | Purpose |\n|-------|-------------|----------|\n';
|
|
252
|
+
|
|
253
|
+
for (const layer of layers) {
|
|
254
|
+
output += `| **${layer.name}** | ${layer.directories?.join(', ') || '-'} | ${layer.purpose || '-'} |\n`;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return output;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Format dependencies for markdown
|
|
262
|
+
* @param {object[]} dependencies - Dependencies array
|
|
263
|
+
* @returns {string}
|
|
264
|
+
*/
|
|
265
|
+
function formatDependencies(dependencies) {
|
|
266
|
+
if (!dependencies || dependencies.length === 0) {
|
|
267
|
+
return '*No dependencies detected.*\n';
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Group by ecosystem
|
|
271
|
+
const byEcosystem = {};
|
|
272
|
+
for (const dep of dependencies) {
|
|
273
|
+
const eco = dep.ecosystem || 'unknown';
|
|
274
|
+
if (!byEcosystem[eco]) byEcosystem[eco] = [];
|
|
275
|
+
byEcosystem[eco].push(dep);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
let output = '';
|
|
279
|
+
for (const [ecosystem, deps] of Object.entries(byEcosystem)) {
|
|
280
|
+
output += `\n**${ecosystem.toUpperCase()}** (${deps.length}):\n`;
|
|
281
|
+
const topDeps = deps.slice(0, 10);
|
|
282
|
+
output += topDeps.map(d => `- ${d.name}@${d.version}`).join('\n') + '\n';
|
|
283
|
+
if (deps.length > 10) {
|
|
284
|
+
output += `- *...and ${deps.length - 10} more*\n`;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return output;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Get package version
|
|
293
|
+
* @returns {string}
|
|
294
|
+
*/
|
|
295
|
+
function getPackageVersion() {
|
|
296
|
+
try {
|
|
297
|
+
const pkgPath = path.join(__dirname, '..', 'package.json');
|
|
298
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
299
|
+
return pkg.version || '1.0.0';
|
|
300
|
+
} catch {
|
|
301
|
+
return '1.0.0';
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Check initialization status
|
|
307
|
+
* @param {string} claudeDir - .claude directory path
|
|
308
|
+
* @returns {object}
|
|
309
|
+
*/
|
|
310
|
+
function checkInitializationStatus(claudeDir) {
|
|
311
|
+
const markerPath = path.join(claudeDir, INIT_MARKER);
|
|
312
|
+
|
|
313
|
+
if (!fs.existsSync(markerPath)) {
|
|
314
|
+
return { status: 'not-started', request: null };
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
try {
|
|
318
|
+
const request = JSON.parse(fs.readFileSync(markerPath, 'utf-8'));
|
|
319
|
+
const completedPhases = request.phases.filter(p => p.status === 'completed').length;
|
|
320
|
+
const totalPhases = request.phases.length;
|
|
321
|
+
|
|
322
|
+
return {
|
|
323
|
+
status: completedPhases === totalPhases ? 'completed' : 'in-progress',
|
|
324
|
+
progress: Math.round((completedPhases / totalPhases) * 100),
|
|
325
|
+
completedPhases,
|
|
326
|
+
totalPhases,
|
|
327
|
+
request
|
|
328
|
+
};
|
|
329
|
+
} catch {
|
|
330
|
+
return { status: 'error', request: null };
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Update initialization progress
|
|
336
|
+
* @param {string} claudeDir - .claude directory path
|
|
337
|
+
* @param {string} phaseId - Phase ID to update
|
|
338
|
+
* @param {string} status - New status ('in-progress', 'completed', 'failed')
|
|
339
|
+
* @param {number} progress - Progress percentage (0-100)
|
|
340
|
+
*/
|
|
341
|
+
function updateInitializationProgress(claudeDir, phaseId, status, progress = 0) {
|
|
342
|
+
const markerPath = path.join(claudeDir, INIT_MARKER);
|
|
343
|
+
|
|
344
|
+
if (!fs.existsSync(markerPath)) {
|
|
345
|
+
return false;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
try {
|
|
349
|
+
const request = JSON.parse(fs.readFileSync(markerPath, 'utf-8'));
|
|
350
|
+
const phase = request.phases.find(p => p.id === phaseId);
|
|
351
|
+
|
|
352
|
+
if (phase) {
|
|
353
|
+
phase.status = status;
|
|
354
|
+
phase.progress = progress;
|
|
355
|
+
phase.updatedAt = new Date().toISOString();
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Check if all phases are completed
|
|
359
|
+
const allCompleted = request.phases.every(p => p.status === 'completed');
|
|
360
|
+
if (allCompleted) {
|
|
361
|
+
request.status = 'completed';
|
|
362
|
+
request.completedAt = new Date().toISOString();
|
|
363
|
+
} else {
|
|
364
|
+
request.status = 'in-progress';
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
fs.writeFileSync(markerPath, JSON.stringify(request, null, 2));
|
|
368
|
+
return true;
|
|
369
|
+
} catch {
|
|
370
|
+
return false;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Mark initialization as complete and clean up
|
|
376
|
+
* @param {string} claudeDir - .claude directory path
|
|
377
|
+
* @param {boolean} removeMarker - Whether to remove the marker file
|
|
378
|
+
*/
|
|
379
|
+
function completeInitialization(claudeDir, removeMarker = true) {
|
|
380
|
+
const markerPath = path.join(claudeDir, INIT_MARKER);
|
|
381
|
+
const instructionPath = path.join(claudeDir, INIT_REQUEST_FILE);
|
|
382
|
+
|
|
383
|
+
if (fs.existsSync(markerPath)) {
|
|
384
|
+
const request = JSON.parse(fs.readFileSync(markerPath, 'utf-8'));
|
|
385
|
+
request.status = 'completed';
|
|
386
|
+
request.completedAt = new Date().toISOString();
|
|
387
|
+
|
|
388
|
+
// Archive to progress file
|
|
389
|
+
const progressPath = path.join(claudeDir, PROGRESS_FILE);
|
|
390
|
+
fs.writeFileSync(progressPath, JSON.stringify(request, null, 2));
|
|
391
|
+
|
|
392
|
+
if (removeMarker) {
|
|
393
|
+
fs.unlinkSync(markerPath);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Remove instruction file
|
|
398
|
+
if (removeMarker && fs.existsSync(instructionPath)) {
|
|
399
|
+
fs.unlinkSync(instructionPath);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Check if initialization is pending
|
|
405
|
+
* @param {string} claudeDir - .claude directory path
|
|
406
|
+
* @returns {boolean}
|
|
407
|
+
*/
|
|
408
|
+
function isInitializationPending(claudeDir) {
|
|
409
|
+
const markerPath = path.join(claudeDir, INIT_MARKER);
|
|
410
|
+
return fs.existsSync(markerPath);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
module.exports = {
|
|
414
|
+
createInitializationRequest,
|
|
415
|
+
generateAgentInstructions,
|
|
416
|
+
checkInitializationStatus,
|
|
417
|
+
updateInitializationProgress,
|
|
418
|
+
completeInitialization,
|
|
419
|
+
isInitializationPending,
|
|
420
|
+
INIT_MARKER,
|
|
421
|
+
INIT_REQUEST_FILE,
|
|
422
|
+
PROGRESS_FILE
|
|
423
|
+
};
|