create-claude-context 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.
- package/LICENSE +21 -0
- package/README.md +146 -0
- package/bin/create-claude-context.js +61 -0
- package/lib/detector.js +373 -0
- package/lib/index.js +170 -0
- package/lib/installer.js +362 -0
- package/lib/placeholder.js +208 -0
- package/lib/prompts.js +287 -0
- package/lib/spinner.js +60 -0
- package/lib/validate.js +147 -0
- package/package.json +59 -0
- package/templates/CLAUDE.md.template +235 -0
- package/templates/base/README.md +257 -0
- package/templates/base/RPI_WORKFLOW_PLAN.md +320 -0
- package/templates/base/agents/api-developer.md +76 -0
- package/templates/base/agents/context-engineer.md +525 -0
- package/templates/base/agents/core-architect.md +76 -0
- package/templates/base/agents/database-ops.md +76 -0
- package/templates/base/agents/deployment-ops.md +76 -0
- package/templates/base/agents/integration-hub.md +76 -0
- package/templates/base/analytics/README.md +114 -0
- package/templates/base/ci-templates/README.md +108 -0
- package/templates/base/ci-templates/github-actions/context-check.yml +144 -0
- package/templates/base/ci-templates/github-actions/validate-docs.yml +105 -0
- package/templates/base/commands/analytics.md +238 -0
- package/templates/base/commands/collab.md +194 -0
- package/templates/base/commands/help.md +450 -0
- package/templates/base/commands/rpi-implement.md +115 -0
- package/templates/base/commands/rpi-plan.md +93 -0
- package/templates/base/commands/rpi-research.md +88 -0
- package/templates/base/commands/validate-all.md +77 -0
- package/templates/base/commands/verify-docs-current.md +86 -0
- package/templates/base/config/base.json +57 -0
- package/templates/base/config/environments/development.json +13 -0
- package/templates/base/config/environments/production.json +17 -0
- package/templates/base/config/environments/staging.json +13 -0
- package/templates/base/config/local.json.example +21 -0
- package/templates/base/context/ARCHITECTURE_SNAPSHOT.md +156 -0
- package/templates/base/context/CODE_TO_WORKFLOW_MAP.md +94 -0
- package/templates/base/context/KNOWN_GOTCHAS.md +195 -0
- package/templates/base/context/WORKFLOW_INDEX.md +129 -0
- package/templates/base/context/workflows/WORKFLOW_TEMPLATE.md +294 -0
- package/templates/base/indexes/agents/CAPABILITY_MATRIX.md +255 -0
- package/templates/base/indexes/agents/CATEGORY_INDEX.md +44 -0
- package/templates/base/indexes/code/CATEGORY_INDEX.md +38 -0
- package/templates/base/indexes/routing/CATEGORY_INDEX.md +39 -0
- package/templates/base/indexes/search/CATEGORY_INDEX.md +39 -0
- package/templates/base/indexes/workflows/CATEGORY_INDEX.md +38 -0
- package/templates/base/knowledge/README.md +98 -0
- package/templates/base/knowledge/sessions/README.md +88 -0
- package/templates/base/knowledge/sessions/TEMPLATE.md +150 -0
- package/templates/base/knowledge/shared/decisions/0001-adopt-context-engineering.md +144 -0
- package/templates/base/knowledge/shared/decisions/README.md +49 -0
- package/templates/base/knowledge/shared/decisions/TEMPLATE.md +123 -0
- package/templates/base/knowledge/shared/patterns/README.md +62 -0
- package/templates/base/knowledge/shared/patterns/TEMPLATE.md +120 -0
- package/templates/base/plans/PLAN_TEMPLATE.md +250 -0
- package/templates/base/plans/active/.gitkeep +0 -0
- package/templates/base/plans/completed/.gitkeep +0 -0
- package/templates/base/research/RESEARCH_TEMPLATE.md +153 -0
- package/templates/base/research/active/.gitkeep +0 -0
- package/templates/base/research/completed/.gitkeep +0 -0
- package/templates/base/schemas/agent.schema.json +141 -0
- package/templates/base/schemas/command.schema.json +134 -0
- package/templates/base/schemas/manifest.schema.json +117 -0
- package/templates/base/schemas/plan.schema.json +136 -0
- package/templates/base/schemas/research.schema.json +115 -0
- package/templates/base/schemas/settings.schema.json +244 -0
- package/templates/base/schemas/workflow.schema.json +126 -0
- package/templates/base/settings.json +57 -0
- package/templates/base/standards/COMPATIBILITY.md +219 -0
- package/templates/base/standards/EXTENSION_GUIDELINES.md +280 -0
- package/templates/base/standards/QUALITY_CHECKLIST.md +211 -0
- package/templates/base/standards/README.md +66 -0
- package/templates/base/team/README.md +168 -0
- package/templates/base/team/config.json +79 -0
- package/templates/base/team/roles.json +145 -0
- package/templates/base/tools/bin/claude-context.js +151 -0
- package/templates/base/tools/lib/config-loader.js +363 -0
- package/templates/base/tools/lib/detector.js +350 -0
- package/templates/base/tools/lib/diagnose.js +206 -0
- package/templates/base/tools/lib/errors.js +199 -0
- package/templates/base/tools/lib/index.js +24 -0
- package/templates/base/tools/lib/init.js +192 -0
- package/templates/base/tools/lib/logger.js +230 -0
- package/templates/base/tools/lib/placeholder.js +201 -0
- package/templates/base/tools/lib/validate.js +521 -0
- package/templates/base/tools/package.json +49 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Context Engineering - Error Classes
|
|
3
|
+
*
|
|
4
|
+
* Structured error handling for the context engineering system.
|
|
5
|
+
* All errors are categorized and include recovery information.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Base error class for all Claude Context errors
|
|
10
|
+
*/
|
|
11
|
+
class ClaudeContextError extends Error {
|
|
12
|
+
constructor(message, code, recoverable = true, details = {}) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = 'ClaudeContextError';
|
|
15
|
+
this.code = code;
|
|
16
|
+
this.recoverable = recoverable;
|
|
17
|
+
this.details = details;
|
|
18
|
+
this.timestamp = new Date().toISOString();
|
|
19
|
+
|
|
20
|
+
// Capture stack trace
|
|
21
|
+
if (Error.captureStackTrace) {
|
|
22
|
+
Error.captureStackTrace(this, this.constructor);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
toJSON() {
|
|
27
|
+
return {
|
|
28
|
+
name: this.name,
|
|
29
|
+
message: this.message,
|
|
30
|
+
code: this.code,
|
|
31
|
+
recoverable: this.recoverable,
|
|
32
|
+
details: this.details,
|
|
33
|
+
timestamp: this.timestamp,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Configuration-related errors
|
|
40
|
+
*/
|
|
41
|
+
class ConfigurationError extends ClaudeContextError {
|
|
42
|
+
constructor(message, details = {}) {
|
|
43
|
+
super(message, ConfigurationError.codes[details.type] || 'E001', true, details);
|
|
44
|
+
this.name = 'ConfigurationError';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static codes = {
|
|
48
|
+
MISSING: 'E001',
|
|
49
|
+
INVALID: 'E002',
|
|
50
|
+
SCHEMA_VIOLATION: 'E003',
|
|
51
|
+
MERGE_CONFLICT: 'E004',
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Validation-related errors
|
|
57
|
+
*/
|
|
58
|
+
class ValidationError extends ClaudeContextError {
|
|
59
|
+
constructor(message, details = {}) {
|
|
60
|
+
super(message, ValidationError.codes[details.type] || 'E010', true, details);
|
|
61
|
+
this.name = 'ValidationError';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
static codes = {
|
|
65
|
+
SCHEMA: 'E010',
|
|
66
|
+
LINK_BROKEN: 'E011',
|
|
67
|
+
PLACEHOLDER_REMAINING: 'E012',
|
|
68
|
+
LINE_NUMBER_STALE: 'E013',
|
|
69
|
+
STRUCTURE: 'E014',
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* File system-related errors
|
|
75
|
+
*/
|
|
76
|
+
class FileSystemError extends ClaudeContextError {
|
|
77
|
+
constructor(message, details = {}) {
|
|
78
|
+
super(message, FileSystemError.codes[details.type] || 'E020', true, details);
|
|
79
|
+
this.name = 'FileSystemError';
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
static codes = {
|
|
83
|
+
NOT_FOUND: 'E020',
|
|
84
|
+
PERMISSION_DENIED: 'E021',
|
|
85
|
+
READ_ERROR: 'E022',
|
|
86
|
+
WRITE_ERROR: 'E023',
|
|
87
|
+
DIRECTORY_ERROR: 'E024',
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Initialization-related errors
|
|
93
|
+
*/
|
|
94
|
+
class InitializationError extends ClaudeContextError {
|
|
95
|
+
constructor(message, details = {}) {
|
|
96
|
+
super(message, InitializationError.codes[details.type] || 'E030', true, details);
|
|
97
|
+
this.name = 'InitializationError';
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
static codes = {
|
|
101
|
+
INCOMPLETE: 'E030',
|
|
102
|
+
TECH_STACK_UNKNOWN: 'E031',
|
|
103
|
+
WORKFLOW_DISCOVERY_FAILED: 'E032',
|
|
104
|
+
PLACEHOLDER_REPLACEMENT_FAILED: 'E033',
|
|
105
|
+
ALREADY_INITIALIZED: 'E034',
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Agent/Command execution errors
|
|
111
|
+
*/
|
|
112
|
+
class ExecutionError extends ClaudeContextError {
|
|
113
|
+
constructor(message, details = {}) {
|
|
114
|
+
super(message, ExecutionError.codes[details.type] || 'E040', details.recoverable ?? true, details);
|
|
115
|
+
this.name = 'ExecutionError';
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
static codes = {
|
|
119
|
+
AGENT_NOT_FOUND: 'E040',
|
|
120
|
+
COMMAND_NOT_FOUND: 'E041',
|
|
121
|
+
TIMEOUT: 'E042',
|
|
122
|
+
CONTEXT_EXCEEDED: 'E043',
|
|
123
|
+
DEPENDENCY_MISSING: 'E044',
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Error code reference table
|
|
129
|
+
*/
|
|
130
|
+
const ERROR_CODES = {
|
|
131
|
+
// Configuration (E001-E009)
|
|
132
|
+
E001: { name: 'CONFIG_MISSING', description: 'Configuration file not found' },
|
|
133
|
+
E002: { name: 'CONFIG_INVALID', description: 'Configuration file is invalid JSON' },
|
|
134
|
+
E003: { name: 'SCHEMA_VIOLATION', description: 'Configuration does not match schema' },
|
|
135
|
+
E004: { name: 'MERGE_CONFLICT', description: 'Configuration merge conflict' },
|
|
136
|
+
|
|
137
|
+
// Validation (E010-E019)
|
|
138
|
+
E010: { name: 'SCHEMA_ERROR', description: 'JSON schema validation failed' },
|
|
139
|
+
E011: { name: 'LINK_BROKEN', description: 'Markdown link does not resolve' },
|
|
140
|
+
E012: { name: 'PLACEHOLDER_REMAINING', description: 'Unresolved {{PLACEHOLDER}} found' },
|
|
141
|
+
E013: { name: 'LINE_NUMBER_STALE', description: 'Line number reference is outdated' },
|
|
142
|
+
E014: { name: 'STRUCTURE_ERROR', description: 'Required file or directory missing' },
|
|
143
|
+
|
|
144
|
+
// File System (E020-E029)
|
|
145
|
+
E020: { name: 'FILE_NOT_FOUND', description: 'File does not exist' },
|
|
146
|
+
E021: { name: 'PERMISSION_DENIED', description: 'Insufficient permissions' },
|
|
147
|
+
E022: { name: 'READ_ERROR', description: 'Failed to read file' },
|
|
148
|
+
E023: { name: 'WRITE_ERROR', description: 'Failed to write file' },
|
|
149
|
+
E024: { name: 'DIRECTORY_ERROR', description: 'Directory operation failed' },
|
|
150
|
+
|
|
151
|
+
// Initialization (E030-E039)
|
|
152
|
+
E030: { name: 'INIT_INCOMPLETE', description: 'Initialization did not complete' },
|
|
153
|
+
E031: { name: 'TECH_STACK_UNKNOWN', description: 'Could not detect technology stack' },
|
|
154
|
+
E032: { name: 'WORKFLOW_DISCOVERY_FAILED', description: 'Failed to discover workflows' },
|
|
155
|
+
E033: { name: 'PLACEHOLDER_REPLACEMENT_FAILED', description: 'Failed to replace placeholders' },
|
|
156
|
+
E034: { name: 'ALREADY_INITIALIZED', description: 'System already initialized' },
|
|
157
|
+
|
|
158
|
+
// Execution (E040-E049)
|
|
159
|
+
E040: { name: 'AGENT_NOT_FOUND', description: 'Agent not found' },
|
|
160
|
+
E041: { name: 'COMMAND_NOT_FOUND', description: 'Command not found' },
|
|
161
|
+
E042: { name: 'TIMEOUT', description: 'Operation timed out' },
|
|
162
|
+
E043: { name: 'CONTEXT_EXCEEDED', description: 'Context budget exceeded' },
|
|
163
|
+
E044: { name: 'DEPENDENCY_MISSING', description: 'Required dependency not available' },
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Get error details by code
|
|
168
|
+
*/
|
|
169
|
+
function getErrorInfo(code) {
|
|
170
|
+
return ERROR_CODES[code] || { name: 'UNKNOWN', description: 'Unknown error' };
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Format error for display
|
|
175
|
+
*/
|
|
176
|
+
function formatError(error) {
|
|
177
|
+
if (error instanceof ClaudeContextError) {
|
|
178
|
+
const info = getErrorInfo(error.code);
|
|
179
|
+
return `[${error.code}] ${error.name}: ${error.message}\n` +
|
|
180
|
+
` Type: ${info.name}\n` +
|
|
181
|
+
` Recoverable: ${error.recoverable ? 'Yes' : 'No'}\n` +
|
|
182
|
+
(Object.keys(error.details).length > 0
|
|
183
|
+
? ` Details: ${JSON.stringify(error.details, null, 2)}\n`
|
|
184
|
+
: '');
|
|
185
|
+
}
|
|
186
|
+
return error.toString();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
module.exports = {
|
|
190
|
+
ClaudeContextError,
|
|
191
|
+
ConfigurationError,
|
|
192
|
+
ValidationError,
|
|
193
|
+
FileSystemError,
|
|
194
|
+
InitializationError,
|
|
195
|
+
ExecutionError,
|
|
196
|
+
ERROR_CODES,
|
|
197
|
+
getErrorInfo,
|
|
198
|
+
formatError,
|
|
199
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Context Engineering Tools - Main Entry
|
|
3
|
+
*
|
|
4
|
+
* Exports all public APIs from the tools library.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { init } = require('./init');
|
|
8
|
+
const { validate } = require('./validate');
|
|
9
|
+
const { diagnose } = require('./diagnose');
|
|
10
|
+
const { configLoader } = require('./config-loader');
|
|
11
|
+
const { logger } = require('./logger');
|
|
12
|
+
const errors = require('./errors');
|
|
13
|
+
|
|
14
|
+
module.exports = {
|
|
15
|
+
// Commands
|
|
16
|
+
init,
|
|
17
|
+
validate,
|
|
18
|
+
diagnose,
|
|
19
|
+
|
|
20
|
+
// Utilities
|
|
21
|
+
configLoader,
|
|
22
|
+
logger,
|
|
23
|
+
errors,
|
|
24
|
+
};
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Context Engineering - Initialization Module
|
|
3
|
+
*
|
|
4
|
+
* Handles initialization of context engineering for a repository.
|
|
5
|
+
* Includes tech stack detection, workflow discovery, and template population.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const chalk = require('chalk');
|
|
11
|
+
const { configLoader, findClaudeDir } = require('./config-loader');
|
|
12
|
+
const { logger } = require('./logger');
|
|
13
|
+
const { InitializationError, FileSystemError } = require('./errors');
|
|
14
|
+
const { detectTechStack } = require('./detector');
|
|
15
|
+
const { replacePlaceholders } = require('./placeholder');
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Initialize context engineering for a repository
|
|
19
|
+
*/
|
|
20
|
+
async function init(options = {}) {
|
|
21
|
+
const {
|
|
22
|
+
config: configPath,
|
|
23
|
+
interactive = true,
|
|
24
|
+
resume = false,
|
|
25
|
+
validateOnly = false,
|
|
26
|
+
techStack = null,
|
|
27
|
+
projectName = null,
|
|
28
|
+
} = options;
|
|
29
|
+
|
|
30
|
+
const op = logger.startOperation('init');
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
console.log(chalk.cyan('\n📦 Initializing Claude Context Engineering...\n'));
|
|
34
|
+
|
|
35
|
+
// Find or create .claude directory
|
|
36
|
+
const claudeDir = findClaudeDir();
|
|
37
|
+
const projectRoot = path.dirname(claudeDir);
|
|
38
|
+
|
|
39
|
+
// Check for existing initialization
|
|
40
|
+
const progressFile = path.join(claudeDir, 'INIT_PROGRESS.json');
|
|
41
|
+
let progress = null;
|
|
42
|
+
|
|
43
|
+
if (fs.existsSync(progressFile)) {
|
|
44
|
+
progress = JSON.parse(fs.readFileSync(progressFile, 'utf8'));
|
|
45
|
+
|
|
46
|
+
if (!resume && progress.status !== 'COMPLETED') {
|
|
47
|
+
console.log(chalk.yellow('⚠️ Previous initialization found. Use --resume to continue.'));
|
|
48
|
+
console.log(chalk.gray(` Status: ${progress.status}`));
|
|
49
|
+
console.log(chalk.gray(` Last phase: ${progress.current_phase}`));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Validate-only mode
|
|
55
|
+
if (validateOnly) {
|
|
56
|
+
console.log(chalk.cyan('🔍 Validating existing initialization...\n'));
|
|
57
|
+
return await validateInitialization(claudeDir);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Resume mode
|
|
61
|
+
if (resume && progress) {
|
|
62
|
+
console.log(chalk.cyan(`🔄 Resuming from phase: ${progress.current_phase}\n`));
|
|
63
|
+
return await resumeInitialization(claudeDir, progress, options);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Start fresh initialization
|
|
67
|
+
console.log(chalk.white('Phase 1: Repository Analysis'));
|
|
68
|
+
console.log(chalk.gray('─'.repeat(50)));
|
|
69
|
+
|
|
70
|
+
// Detect tech stack
|
|
71
|
+
console.log(' Detecting technology stack...');
|
|
72
|
+
const detected = await detectTechStack(projectRoot, { hint: techStack });
|
|
73
|
+
|
|
74
|
+
console.log(chalk.green(` ✓ Tech stack: ${detected.stack}`));
|
|
75
|
+
console.log(chalk.gray(` Languages: ${detected.languages.join(', ')}`));
|
|
76
|
+
console.log(chalk.gray(` Frameworks: ${detected.frameworks.join(', ')}`));
|
|
77
|
+
console.log(chalk.gray(` Files: ${detected.fileCount}`));
|
|
78
|
+
|
|
79
|
+
// Create progress file
|
|
80
|
+
progress = {
|
|
81
|
+
version: '1.0.0',
|
|
82
|
+
started_at: new Date().toISOString(),
|
|
83
|
+
last_updated: new Date().toISOString(),
|
|
84
|
+
status: 'IN_PROGRESS',
|
|
85
|
+
current_phase: 'analysis',
|
|
86
|
+
phases: {
|
|
87
|
+
analysis: { status: 'COMPLETE', duration_ms: 0 },
|
|
88
|
+
discovery: { status: 'PENDING' },
|
|
89
|
+
population: { status: 'PENDING' },
|
|
90
|
+
validation: { status: 'PENDING' },
|
|
91
|
+
finalization: { status: 'PENDING' },
|
|
92
|
+
},
|
|
93
|
+
detected: {
|
|
94
|
+
tech_stack: detected.stack,
|
|
95
|
+
languages: detected.languages,
|
|
96
|
+
frameworks: detected.frameworks,
|
|
97
|
+
file_count: detected.fileCount,
|
|
98
|
+
loc: detected.loc || 0,
|
|
99
|
+
},
|
|
100
|
+
project_name: projectName || detected.projectName || path.basename(projectRoot),
|
|
101
|
+
errors: [],
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
saveProgress(progressFile, progress);
|
|
105
|
+
|
|
106
|
+
// Phase 2: Workflow Discovery
|
|
107
|
+
console.log(chalk.white('\nPhase 2: Workflow Discovery'));
|
|
108
|
+
console.log(chalk.gray('─'.repeat(50)));
|
|
109
|
+
console.log(chalk.yellow(' ⚠️ Full workflow discovery requires Claude Code agent.'));
|
|
110
|
+
console.log(chalk.gray(' Run: @context-engineer "Initialize context engineering"'));
|
|
111
|
+
console.log(chalk.gray(' The agent will discover 8-15 workflows automatically.\n'));
|
|
112
|
+
|
|
113
|
+
progress.current_phase = 'discovery';
|
|
114
|
+
progress.phases.discovery.status = 'PENDING_AGENT';
|
|
115
|
+
saveProgress(progressFile, progress);
|
|
116
|
+
|
|
117
|
+
// Phase 3: Template Population (partial - placeholders only)
|
|
118
|
+
console.log(chalk.white('Phase 3: Template Population (Partial)'));
|
|
119
|
+
console.log(chalk.gray('─'.repeat(50)));
|
|
120
|
+
|
|
121
|
+
const placeholderValues = {
|
|
122
|
+
PROJECT_NAME: progress.project_name,
|
|
123
|
+
TECH_STACK: detected.stack,
|
|
124
|
+
DATE: new Date().toISOString().split('T')[0],
|
|
125
|
+
WORKFLOWS_COUNT: '{{WORKFLOWS_COUNT}}', // To be filled by agent
|
|
126
|
+
// Add more known values
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const claudeMdPath = path.join(projectRoot, 'CLAUDE.md');
|
|
130
|
+
if (fs.existsSync(claudeMdPath)) {
|
|
131
|
+
const result = await replacePlaceholders(claudeMdPath, placeholderValues, { dryRun: false });
|
|
132
|
+
console.log(chalk.green(` ✓ Replaced ${result.replaced} placeholders in CLAUDE.md`));
|
|
133
|
+
console.log(chalk.gray(` Remaining: ${result.remaining} placeholders`));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
progress.current_phase = 'population';
|
|
137
|
+
progress.phases.population.status = 'PARTIAL';
|
|
138
|
+
saveProgress(progressFile, progress);
|
|
139
|
+
|
|
140
|
+
// Summary
|
|
141
|
+
console.log(chalk.white('\n📋 Initialization Summary'));
|
|
142
|
+
console.log(chalk.gray('─'.repeat(50)));
|
|
143
|
+
console.log(chalk.green(' ✓ Repository analyzed'));
|
|
144
|
+
console.log(chalk.green(' ✓ Tech stack detected'));
|
|
145
|
+
console.log(chalk.yellow(' ⏳ Workflow discovery pending (run agent)'));
|
|
146
|
+
console.log(chalk.yellow(' ⏳ Template population partial'));
|
|
147
|
+
|
|
148
|
+
console.log(chalk.white('\n📌 Next Steps:'));
|
|
149
|
+
console.log(chalk.cyan(' 1. Run: @context-engineer "Initialize context engineering"'));
|
|
150
|
+
console.log(chalk.gray(' This will discover workflows and complete the setup.'));
|
|
151
|
+
console.log(chalk.cyan(' 2. Review generated workflow documentation'));
|
|
152
|
+
console.log(chalk.cyan(' 3. Run: npx claude-context validate'));
|
|
153
|
+
|
|
154
|
+
op.success();
|
|
155
|
+
|
|
156
|
+
} catch (error) {
|
|
157
|
+
op.fail(error);
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Save initialization progress
|
|
164
|
+
*/
|
|
165
|
+
function saveProgress(filePath, progress) {
|
|
166
|
+
progress.last_updated = new Date().toISOString();
|
|
167
|
+
fs.writeFileSync(filePath, JSON.stringify(progress, null, 2));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Resume an interrupted initialization
|
|
172
|
+
*/
|
|
173
|
+
async function resumeInitialization(claudeDir, progress, options) {
|
|
174
|
+
console.log(chalk.cyan(`Resuming from phase: ${progress.current_phase}`));
|
|
175
|
+
// Implementation would continue from the last phase
|
|
176
|
+
console.log(chalk.yellow('⚠️ Resume functionality requires full agent support.'));
|
|
177
|
+
console.log(chalk.gray(' Run: @context-engineer "resume initialization"'));
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Validate an existing initialization
|
|
182
|
+
*/
|
|
183
|
+
async function validateInitialization(claudeDir) {
|
|
184
|
+
const { validate } = require('./validate');
|
|
185
|
+
return await validate({ all: true, claudeDir });
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
module.exports = {
|
|
189
|
+
init,
|
|
190
|
+
resumeInitialization,
|
|
191
|
+
validateInitialization,
|
|
192
|
+
};
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Context Engineering - Logger
|
|
3
|
+
*
|
|
4
|
+
* Structured logging with levels, file output, and operation tracking.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const chalk = require('chalk');
|
|
10
|
+
|
|
11
|
+
const LOG_LEVELS = {
|
|
12
|
+
debug: 0,
|
|
13
|
+
info: 1,
|
|
14
|
+
warn: 2,
|
|
15
|
+
error: 3,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const LEVEL_COLORS = {
|
|
19
|
+
debug: chalk.gray,
|
|
20
|
+
info: chalk.blue,
|
|
21
|
+
warn: chalk.yellow,
|
|
22
|
+
error: chalk.red,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const LEVEL_ICONS = {
|
|
26
|
+
debug: '🔍',
|
|
27
|
+
info: 'ℹ️ ',
|
|
28
|
+
warn: '⚠️ ',
|
|
29
|
+
error: '❌',
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Create a logger instance
|
|
34
|
+
*/
|
|
35
|
+
function createLogger(options = {}) {
|
|
36
|
+
const config = {
|
|
37
|
+
level: options.level || 'info',
|
|
38
|
+
file: options.file || null,
|
|
39
|
+
maxSizeMb: options.maxSizeMb || 10,
|
|
40
|
+
console: options.console !== false,
|
|
41
|
+
timestamps: options.timestamps !== false,
|
|
42
|
+
colors: options.colors !== false,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Ensure log directory exists if file logging enabled
|
|
46
|
+
if (config.file) {
|
|
47
|
+
const logDir = path.dirname(config.file);
|
|
48
|
+
if (!fs.existsSync(logDir)) {
|
|
49
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Check if we should log at this level
|
|
55
|
+
*/
|
|
56
|
+
function shouldLog(level) {
|
|
57
|
+
return LOG_LEVELS[level] >= LOG_LEVELS[config.level];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Format a log message
|
|
62
|
+
*/
|
|
63
|
+
function formatMessage(level, message, meta = {}) {
|
|
64
|
+
const timestamp = new Date().toISOString();
|
|
65
|
+
const parts = [];
|
|
66
|
+
|
|
67
|
+
if (config.timestamps) {
|
|
68
|
+
parts.push(`[${timestamp}]`);
|
|
69
|
+
}
|
|
70
|
+
parts.push(`[${level.toUpperCase()}]`);
|
|
71
|
+
parts.push(message);
|
|
72
|
+
|
|
73
|
+
if (Object.keys(meta).length > 0) {
|
|
74
|
+
parts.push(JSON.stringify(meta));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return parts.join(' ');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Write to console with colors
|
|
82
|
+
*/
|
|
83
|
+
function writeConsole(level, message, meta) {
|
|
84
|
+
if (!config.console) return;
|
|
85
|
+
|
|
86
|
+
const colorFn = config.colors ? LEVEL_COLORS[level] : (s) => s;
|
|
87
|
+
const icon = LEVEL_ICONS[level];
|
|
88
|
+
const timestamp = config.timestamps
|
|
89
|
+
? chalk.gray(`[${new Date().toISOString()}] `)
|
|
90
|
+
: '';
|
|
91
|
+
|
|
92
|
+
let output = `${timestamp}${icon} ${colorFn(message)}`;
|
|
93
|
+
|
|
94
|
+
if (Object.keys(meta).length > 0) {
|
|
95
|
+
output += '\n' + chalk.gray(JSON.stringify(meta, null, 2));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (level === 'error') {
|
|
99
|
+
console.error(output);
|
|
100
|
+
} else {
|
|
101
|
+
console.log(output);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Write to file
|
|
107
|
+
*/
|
|
108
|
+
function writeFile(level, message, meta) {
|
|
109
|
+
if (!config.file) return;
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
const formatted = formatMessage(level, message, meta) + '\n';
|
|
113
|
+
fs.appendFileSync(config.file, formatted);
|
|
114
|
+
|
|
115
|
+
// Check file size and rotate if needed
|
|
116
|
+
const stats = fs.statSync(config.file);
|
|
117
|
+
const sizeMb = stats.size / (1024 * 1024);
|
|
118
|
+
if (sizeMb > config.maxSizeMb) {
|
|
119
|
+
rotateLog();
|
|
120
|
+
}
|
|
121
|
+
} catch (error) {
|
|
122
|
+
// Silently fail file logging
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Rotate log file
|
|
128
|
+
*/
|
|
129
|
+
function rotateLog() {
|
|
130
|
+
if (!config.file || !fs.existsSync(config.file)) return;
|
|
131
|
+
|
|
132
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
133
|
+
const rotatedPath = config.file.replace('.log', `-${timestamp}.log`);
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
fs.renameSync(config.file, rotatedPath);
|
|
137
|
+
} catch (error) {
|
|
138
|
+
// Silently fail rotation
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Core log function
|
|
144
|
+
*/
|
|
145
|
+
function log(level, message, meta = {}) {
|
|
146
|
+
if (!shouldLog(level)) return;
|
|
147
|
+
|
|
148
|
+
writeConsole(level, message, meta);
|
|
149
|
+
writeFile(level, message, meta);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Start an operation and return tracking object
|
|
154
|
+
*/
|
|
155
|
+
function startOperation(name) {
|
|
156
|
+
const operationId = generateId();
|
|
157
|
+
const startTime = Date.now();
|
|
158
|
+
|
|
159
|
+
log('info', `Operation started: ${name}`, { operation_id: operationId });
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
id: operationId,
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Log progress
|
|
166
|
+
*/
|
|
167
|
+
progress: (message, meta = {}) => {
|
|
168
|
+
log('debug', `[${name}] ${message}`, { operation_id: operationId, ...meta });
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Mark operation as successful
|
|
173
|
+
*/
|
|
174
|
+
success: (message = 'completed', meta = {}) => {
|
|
175
|
+
const duration = Date.now() - startTime;
|
|
176
|
+
log('info', `Operation completed: ${name} - ${message}`, {
|
|
177
|
+
operation_id: operationId,
|
|
178
|
+
duration_ms: duration,
|
|
179
|
+
...meta,
|
|
180
|
+
});
|
|
181
|
+
return { success: true, duration };
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Mark operation as failed
|
|
186
|
+
*/
|
|
187
|
+
fail: (error, meta = {}) => {
|
|
188
|
+
const duration = Date.now() - startTime;
|
|
189
|
+
const errorMessage = error instanceof Error ? error.message : error;
|
|
190
|
+
log('error', `Operation failed: ${name} - ${errorMessage}`, {
|
|
191
|
+
operation_id: operationId,
|
|
192
|
+
duration_ms: duration,
|
|
193
|
+
error: error instanceof Error ? { name: error.name, stack: error.stack } : error,
|
|
194
|
+
...meta,
|
|
195
|
+
});
|
|
196
|
+
return { success: false, duration, error };
|
|
197
|
+
},
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Generate a short unique ID
|
|
203
|
+
*/
|
|
204
|
+
function generateId() {
|
|
205
|
+
return Math.random().toString(36).substring(2, 10);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Return logger interface
|
|
209
|
+
return {
|
|
210
|
+
debug: (message, meta) => log('debug', message, meta),
|
|
211
|
+
info: (message, meta) => log('info', message, meta),
|
|
212
|
+
warn: (message, meta) => log('warn', message, meta),
|
|
213
|
+
error: (message, meta) => log('error', message, meta),
|
|
214
|
+
startOperation,
|
|
215
|
+
setLevel: (level) => { config.level = level; },
|
|
216
|
+
getLevel: () => config.level,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Default logger instance
|
|
221
|
+
const logger = createLogger({
|
|
222
|
+
level: process.env.CLAUDE_LOG_LEVEL || 'info',
|
|
223
|
+
file: process.env.CLAUDE_LOG_FILE || null,
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
module.exports = {
|
|
227
|
+
createLogger,
|
|
228
|
+
logger,
|
|
229
|
+
LOG_LEVELS,
|
|
230
|
+
};
|