create-universal-ai-context 2.4.0 → 2.6.0-final
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 -21
- package/README.md +331 -294
- package/bin/create-ai-context.js +1507 -764
- package/lib/adapters/aider.js +131 -131
- package/lib/adapters/antigravity.js +205 -205
- package/lib/adapters/claude.js +397 -397
- package/lib/adapters/cline.js +125 -125
- package/lib/adapters/continue.js +138 -138
- package/lib/adapters/copilot.js +131 -131
- package/lib/adapters/index.js +78 -78
- package/lib/adapters/windsurf.js +138 -138
- package/lib/ai-context-generator.js +234 -234
- package/lib/ai-orchestrator.js +432 -432
- package/lib/call-tracer.js +444 -444
- package/lib/content-preservation.js +243 -243
- package/lib/cross-tool-sync/file-watcher.js +274 -274
- package/lib/cross-tool-sync/index.js +41 -40
- package/lib/cross-tool-sync/sync-manager.js +540 -512
- package/lib/cross-tool-sync/sync-service.js +297 -297
- package/lib/detector.js +726 -726
- package/lib/doc-discovery.js +741 -741
- package/lib/drift-checker.js +920 -920
- package/lib/environment-detector.js +239 -239
- package/lib/index.js +399 -399
- package/lib/install-hooks.js +82 -82
- package/lib/installer.js +419 -419
- package/lib/migrate.js +328 -328
- package/lib/placeholder.js +632 -632
- package/lib/prompts.js +341 -341
- package/lib/smart-merge.js +540 -540
- package/lib/spinner.js +60 -60
- package/lib/static-analyzer.js +729 -729
- package/lib/template-coordination.js +148 -148
- package/lib/template-populator.js +843 -843
- package/lib/template-renderer.js +392 -392
- package/lib/utils/fs-wrapper.js +79 -79
- package/lib/utils/path-utils.js +60 -60
- package/lib/validate.js +155 -155
- package/package.json +1 -1
- package/templates/AI_CONTEXT.md.template +245 -245
- package/templates/base/README.md +260 -257
- package/templates/base/RPI_WORKFLOW_PLAN.md +325 -320
- package/templates/base/agents/api-developer.md +76 -76
- package/templates/base/agents/context-engineer.md +525 -525
- package/templates/base/agents/core-architect.md +76 -76
- package/templates/base/agents/database-ops.md +76 -76
- package/templates/base/agents/deployment-ops.md +76 -76
- package/templates/base/agents/integration-hub.md +76 -76
- package/templates/base/analytics/README.md +114 -114
- package/templates/base/automation/config.json +58 -58
- package/templates/base/automation/generators/code-mapper.js +308 -308
- package/templates/base/automation/generators/index-builder.js +321 -321
- package/templates/base/automation/hooks/post-commit.sh +83 -83
- package/templates/base/automation/hooks/pre-commit.sh +103 -103
- package/templates/base/ci-templates/README.md +108 -108
- package/templates/base/ci-templates/github-actions/context-check.yml +144 -144
- package/templates/base/ci-templates/github-actions/validate-docs.yml +105 -105
- package/templates/base/commands/analytics.md +238 -238
- package/templates/base/commands/auto-sync.md +172 -172
- package/templates/base/commands/collab.md +194 -194
- package/templates/base/commands/context-optimize.md +226 -0
- package/templates/base/commands/help.md +485 -450
- package/templates/base/commands/rpi-implement.md +164 -115
- package/templates/base/commands/rpi-plan.md +147 -93
- package/templates/base/commands/rpi-research.md +145 -88
- package/templates/base/commands/session-resume.md +144 -144
- package/templates/base/commands/session-save.md +112 -112
- package/templates/base/commands/validate-all.md +77 -77
- package/templates/base/commands/verify-docs-current.md +86 -86
- package/templates/base/config/base.json +57 -57
- package/templates/base/config/environments/development.json +13 -13
- package/templates/base/config/environments/production.json +17 -17
- package/templates/base/config/environments/staging.json +13 -13
- package/templates/base/config/local.json.example +21 -21
- package/templates/base/context/.meta/generated-at.json +18 -18
- package/templates/base/context/ARCHITECTURE_SNAPSHOT.md +156 -156
- package/templates/base/context/CODE_TO_WORKFLOW_MAP.md +94 -94
- package/templates/base/context/FILE_OWNERSHIP.md +57 -57
- package/templates/base/context/INTEGRATION_POINTS.md +92 -92
- package/templates/base/context/KNOWN_GOTCHAS.md +195 -195
- package/templates/base/context/TESTING_MAP.md +95 -95
- package/templates/base/context/WORKFLOW_INDEX.md +129 -129
- package/templates/base/context/workflows/WORKFLOW_TEMPLATE.md +294 -294
- package/templates/base/indexes/agents/CAPABILITY_MATRIX.md +255 -255
- package/templates/base/indexes/agents/CATEGORY_INDEX.md +44 -44
- package/templates/base/indexes/code/CATEGORY_INDEX.md +38 -38
- package/templates/base/indexes/routing/CATEGORY_INDEX.md +39 -39
- package/templates/base/indexes/search/CATEGORY_INDEX.md +39 -39
- package/templates/base/indexes/workflows/CATEGORY_INDEX.md +38 -38
- package/templates/base/knowledge/README.md +98 -98
- package/templates/base/knowledge/sessions/README.md +88 -88
- package/templates/base/knowledge/sessions/TEMPLATE.md +150 -150
- package/templates/base/knowledge/shared/decisions/0001-adopt-context-engineering.md +144 -144
- package/templates/base/knowledge/shared/decisions/README.md +49 -49
- package/templates/base/knowledge/shared/decisions/TEMPLATE.md +123 -123
- package/templates/base/knowledge/shared/patterns/README.md +62 -62
- package/templates/base/knowledge/shared/patterns/TEMPLATE.md +120 -120
- package/templates/base/plans/PLAN_TEMPLATE.md +316 -250
- package/templates/base/research/RESEARCH_TEMPLATE.md +245 -153
- package/templates/base/schemas/agent.schema.json +141 -141
- package/templates/base/schemas/anchors.schema.json +54 -54
- package/templates/base/schemas/automation.schema.json +93 -93
- package/templates/base/schemas/command.schema.json +134 -134
- package/templates/base/schemas/hashes.schema.json +40 -40
- package/templates/base/schemas/manifest.schema.json +117 -117
- package/templates/base/schemas/plan.schema.json +136 -136
- package/templates/base/schemas/research.schema.json +115 -115
- package/templates/base/schemas/roles.schema.json +34 -34
- package/templates/base/schemas/session.schema.json +77 -77
- package/templates/base/schemas/settings.schema.json +244 -244
- package/templates/base/schemas/staleness.schema.json +53 -53
- package/templates/base/schemas/team-config.schema.json +42 -42
- package/templates/base/schemas/workflow.schema.json +126 -126
- package/templates/base/session/checkpoints/.gitkeep +2 -2
- package/templates/base/session/current/state.json +20 -20
- package/templates/base/session/history/.gitkeep +2 -2
- package/templates/base/settings.json +3 -3
- package/templates/base/standards/COMPATIBILITY.md +219 -219
- package/templates/base/standards/EXTENSION_GUIDELINES.md +280 -280
- package/templates/base/standards/QUALITY_CHECKLIST.md +211 -211
- package/templates/base/standards/README.md +66 -66
- package/templates/base/sync/anchors.json +6 -6
- package/templates/base/sync/hashes.json +6 -6
- package/templates/base/sync/staleness.json +10 -10
- package/templates/base/team/README.md +168 -168
- package/templates/base/team/config.json +79 -79
- package/templates/base/team/roles.json +145 -145
- package/templates/base/tools/bin/claude-context.js +151 -151
- package/templates/base/tools/lib/anchor-resolver.js +276 -276
- package/templates/base/tools/lib/config-loader.js +363 -363
- package/templates/base/tools/lib/detector.js +350 -350
- package/templates/base/tools/lib/diagnose.js +206 -206
- package/templates/base/tools/lib/drift-detector.js +373 -373
- package/templates/base/tools/lib/errors.js +199 -199
- package/templates/base/tools/lib/index.js +36 -36
- package/templates/base/tools/lib/init.js +192 -192
- package/templates/base/tools/lib/logger.js +230 -230
- package/templates/base/tools/lib/placeholder.js +201 -201
- package/templates/base/tools/lib/session-manager.js +354 -354
- package/templates/base/tools/lib/validate.js +521 -521
- package/templates/base/tools/package.json +49 -49
- package/templates/handlebars/aider-config.hbs +146 -80
- package/templates/handlebars/antigravity.hbs +377 -377
- package/templates/handlebars/claude.hbs +183 -183
- package/templates/handlebars/cline.hbs +62 -62
- package/templates/handlebars/continue-config.hbs +116 -116
- package/templates/handlebars/copilot.hbs +130 -130
- package/templates/handlebars/partials/gotcha-list.hbs +11 -11
- package/templates/handlebars/partials/header.hbs +3 -3
- package/templates/handlebars/partials/workflow-summary.hbs +16 -16
- package/templates/handlebars/windsurf-rules.hbs +69 -69
- package/templates/hooks/post-commit.hbs +28 -29
- package/templates/hooks/pre-commit.hbs +46 -46
package/lib/utils/fs-wrapper.js
CHANGED
|
@@ -1,79 +1,79 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Filesystem Operation Wrapper
|
|
3
|
-
*
|
|
4
|
-
* Adds context to filesystem errors (WARNING level, not fatal)
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const fs = require('fs');
|
|
8
|
-
const path = require('path');
|
|
9
|
-
const chalk = require('chalk');
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Wrap sync file write with better error messages
|
|
13
|
-
* Returns warning object instead of throwing (non-fatal)
|
|
14
|
-
* @param {string} filePath - File path
|
|
15
|
-
* @param {string} content - Content to write
|
|
16
|
-
* @param {object} options - Write options
|
|
17
|
-
* @returns {object} { success: boolean, warning?: string }
|
|
18
|
-
*/
|
|
19
|
-
function writeFileSyncWithContext(filePath, content, options = {}) {
|
|
20
|
-
try {
|
|
21
|
-
fs.writeFileSync(filePath, content, options);
|
|
22
|
-
return { success: true };
|
|
23
|
-
} catch (error) {
|
|
24
|
-
let message;
|
|
25
|
-
if (error.code === 'EACCES' || error.code === 'EPERM') {
|
|
26
|
-
message = `Permission denied writing to ${filePath}. Check file permissions.`;
|
|
27
|
-
} else if (error.code === 'ENOENT') {
|
|
28
|
-
message = `Directory does not exist: ${path.dirname(filePath)}. Ensure parent directory exists.`;
|
|
29
|
-
} else if (error.code === 'ENOSPC') {
|
|
30
|
-
message = `No space left on device while writing ${filePath}. Free up disk space.`;
|
|
31
|
-
} else {
|
|
32
|
-
message = `Failed to write ${filePath}: ${error.message}`;
|
|
33
|
-
}
|
|
34
|
-
return { success: false, warning: message, error };
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Wrap sync directory creation with better error messages
|
|
40
|
-
* Returns warning object instead of throwing (non-fatal)
|
|
41
|
-
* @param {string} dirPath - Directory path
|
|
42
|
-
* @param {object} options - mkdir options
|
|
43
|
-
* @returns {object} { success: boolean, warning?: string }
|
|
44
|
-
*/
|
|
45
|
-
function mkdirSyncWithContext(dirPath, options = {}) {
|
|
46
|
-
try {
|
|
47
|
-
fs.mkdirSync(dirPath, options);
|
|
48
|
-
return { success: true };
|
|
49
|
-
} catch (error) {
|
|
50
|
-
// EEXIST is not an error - directory already exists
|
|
51
|
-
if (error.code === 'EEXIST') {
|
|
52
|
-
return { success: true };
|
|
53
|
-
}
|
|
54
|
-
let message;
|
|
55
|
-
if (error.code === 'EACCES' || error.code === 'EPERM') {
|
|
56
|
-
message = `Permission denied creating directory ${dirPath}. Check directory permissions.`;
|
|
57
|
-
} else {
|
|
58
|
-
message = `Failed to create directory ${dirPath}: ${error.message}`;
|
|
59
|
-
}
|
|
60
|
-
return { success: false, warning: message, error };
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Log a warning message if verbose mode is enabled
|
|
66
|
-
* @param {object} result - Result from writeFileSyncWithContext or mkdirSyncWithContext
|
|
67
|
-
* @param {boolean} verbose - Whether to log warnings
|
|
68
|
-
*/
|
|
69
|
-
function logWarning(result, verbose = false) {
|
|
70
|
-
if (!result.success && result.warning && verbose) {
|
|
71
|
-
console.warn(chalk.yellow(`⚠ ${result.warning}`));
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
module.exports = {
|
|
76
|
-
writeFileSyncWithContext,
|
|
77
|
-
mkdirSyncWithContext,
|
|
78
|
-
logWarning
|
|
79
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* Filesystem Operation Wrapper
|
|
3
|
+
*
|
|
4
|
+
* Adds context to filesystem errors (WARNING level, not fatal)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const chalk = require('chalk');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Wrap sync file write with better error messages
|
|
13
|
+
* Returns warning object instead of throwing (non-fatal)
|
|
14
|
+
* @param {string} filePath - File path
|
|
15
|
+
* @param {string} content - Content to write
|
|
16
|
+
* @param {object} options - Write options
|
|
17
|
+
* @returns {object} { success: boolean, warning?: string }
|
|
18
|
+
*/
|
|
19
|
+
function writeFileSyncWithContext(filePath, content, options = {}) {
|
|
20
|
+
try {
|
|
21
|
+
fs.writeFileSync(filePath, content, options);
|
|
22
|
+
return { success: true };
|
|
23
|
+
} catch (error) {
|
|
24
|
+
let message;
|
|
25
|
+
if (error.code === 'EACCES' || error.code === 'EPERM') {
|
|
26
|
+
message = `Permission denied writing to ${filePath}. Check file permissions.`;
|
|
27
|
+
} else if (error.code === 'ENOENT') {
|
|
28
|
+
message = `Directory does not exist: ${path.dirname(filePath)}. Ensure parent directory exists.`;
|
|
29
|
+
} else if (error.code === 'ENOSPC') {
|
|
30
|
+
message = `No space left on device while writing ${filePath}. Free up disk space.`;
|
|
31
|
+
} else {
|
|
32
|
+
message = `Failed to write ${filePath}: ${error.message}`;
|
|
33
|
+
}
|
|
34
|
+
return { success: false, warning: message, error };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Wrap sync directory creation with better error messages
|
|
40
|
+
* Returns warning object instead of throwing (non-fatal)
|
|
41
|
+
* @param {string} dirPath - Directory path
|
|
42
|
+
* @param {object} options - mkdir options
|
|
43
|
+
* @returns {object} { success: boolean, warning?: string }
|
|
44
|
+
*/
|
|
45
|
+
function mkdirSyncWithContext(dirPath, options = {}) {
|
|
46
|
+
try {
|
|
47
|
+
fs.mkdirSync(dirPath, options);
|
|
48
|
+
return { success: true };
|
|
49
|
+
} catch (error) {
|
|
50
|
+
// EEXIST is not an error - directory already exists
|
|
51
|
+
if (error.code === 'EEXIST') {
|
|
52
|
+
return { success: true };
|
|
53
|
+
}
|
|
54
|
+
let message;
|
|
55
|
+
if (error.code === 'EACCES' || error.code === 'EPERM') {
|
|
56
|
+
message = `Permission denied creating directory ${dirPath}. Check directory permissions.`;
|
|
57
|
+
} else {
|
|
58
|
+
message = `Failed to create directory ${dirPath}: ${error.message}`;
|
|
59
|
+
}
|
|
60
|
+
return { success: false, warning: message, error };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Log a warning message if verbose mode is enabled
|
|
66
|
+
* @param {object} result - Result from writeFileSyncWithContext or mkdirSyncWithContext
|
|
67
|
+
* @param {boolean} verbose - Whether to log warnings
|
|
68
|
+
*/
|
|
69
|
+
function logWarning(result, verbose = false) {
|
|
70
|
+
if (!result.success && result.warning && verbose) {
|
|
71
|
+
console.warn(chalk.yellow(`⚠ ${result.warning}`));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = {
|
|
76
|
+
writeFileSyncWithContext,
|
|
77
|
+
mkdirSyncWithContext,
|
|
78
|
+
logWarning
|
|
79
|
+
};
|
package/lib/utils/path-utils.js
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Path Utilities
|
|
3
|
-
*
|
|
4
|
-
* Cross-platform path handling utilities
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const path = require('path');
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Normalize path separators to forward slashes for consistency
|
|
11
|
-
* @param {string} filePath - Path to normalize
|
|
12
|
-
* @returns {string} Normalized path
|
|
13
|
-
*/
|
|
14
|
-
function normalizePath(filePath) {
|
|
15
|
-
if (!filePath) return '';
|
|
16
|
-
return filePath.replace(/\\/g, '/');
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Get relative path with normalized separators
|
|
21
|
-
* @param {string} from - Source path
|
|
22
|
-
* @param {string} to - Destination path
|
|
23
|
-
* @returns {string} Normalized relative path
|
|
24
|
-
*/
|
|
25
|
-
function relativePath(from, to) {
|
|
26
|
-
const rel = path.relative(from, to);
|
|
27
|
-
return normalizePath(rel);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Join path segments and normalize
|
|
32
|
-
* @param {...string} segments - Path segments
|
|
33
|
-
* @returns {string} Normalized joined path
|
|
34
|
-
*/
|
|
35
|
-
function joinPath(...segments) {
|
|
36
|
-
return normalizePath(path.join(...segments));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Check if path is absolute (cross-platform)
|
|
41
|
-
* @param {string} filePath - Path to check
|
|
42
|
-
* @returns {boolean}
|
|
43
|
-
*/
|
|
44
|
-
function isAbsolute(filePath) {
|
|
45
|
-
if (!filePath) return false;
|
|
46
|
-
|
|
47
|
-
// Windows paths can start with drive letter (C:\) or UNC (\\)
|
|
48
|
-
if (/^[a-zA-Z]:\\/.test(filePath) || /^\\\\/.test(filePath)) {
|
|
49
|
-
return true;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return path.isAbsolute(filePath);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
module.exports = {
|
|
56
|
-
normalizePath,
|
|
57
|
-
relativePath,
|
|
58
|
-
joinPath,
|
|
59
|
-
isAbsolute
|
|
60
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* Path Utilities
|
|
3
|
+
*
|
|
4
|
+
* Cross-platform path handling utilities
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Normalize path separators to forward slashes for consistency
|
|
11
|
+
* @param {string} filePath - Path to normalize
|
|
12
|
+
* @returns {string} Normalized path
|
|
13
|
+
*/
|
|
14
|
+
function normalizePath(filePath) {
|
|
15
|
+
if (!filePath) return '';
|
|
16
|
+
return filePath.replace(/\\/g, '/');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Get relative path with normalized separators
|
|
21
|
+
* @param {string} from - Source path
|
|
22
|
+
* @param {string} to - Destination path
|
|
23
|
+
* @returns {string} Normalized relative path
|
|
24
|
+
*/
|
|
25
|
+
function relativePath(from, to) {
|
|
26
|
+
const rel = path.relative(from, to);
|
|
27
|
+
return normalizePath(rel);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Join path segments and normalize
|
|
32
|
+
* @param {...string} segments - Path segments
|
|
33
|
+
* @returns {string} Normalized joined path
|
|
34
|
+
*/
|
|
35
|
+
function joinPath(...segments) {
|
|
36
|
+
return normalizePath(path.join(...segments));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Check if path is absolute (cross-platform)
|
|
41
|
+
* @param {string} filePath - Path to check
|
|
42
|
+
* @returns {boolean}
|
|
43
|
+
*/
|
|
44
|
+
function isAbsolute(filePath) {
|
|
45
|
+
if (!filePath) return false;
|
|
46
|
+
|
|
47
|
+
// Windows paths can start with drive letter (C:\) or UNC (\\)
|
|
48
|
+
if (/^[a-zA-Z]:\\/.test(filePath) || /^\\\\/.test(filePath)) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return path.isAbsolute(filePath);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
module.exports = {
|
|
56
|
+
normalizePath,
|
|
57
|
+
relativePath,
|
|
58
|
+
joinPath,
|
|
59
|
+
isAbsolute
|
|
60
|
+
};
|
package/lib/validate.js
CHANGED
|
@@ -1,155 +1,155 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AI Context Engineering - Installation Validator
|
|
3
|
-
*
|
|
4
|
-
* Validates the installation was successful.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const fs = require('fs');
|
|
8
|
-
const path = require('path');
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Context directory and file names
|
|
12
|
-
*/
|
|
13
|
-
const AI_CONTEXT_DIR = '.ai-context';
|
|
14
|
-
const AI_CONTEXT_FILE = 'AI_CONTEXT.md';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Required files and directories for a valid installation
|
|
18
|
-
*/
|
|
19
|
-
const REQUIRED_STRUCTURE = {
|
|
20
|
-
directories: [
|
|
21
|
-
AI_CONTEXT_DIR,
|
|
22
|
-
`${AI_CONTEXT_DIR}/context`,
|
|
23
|
-
`${AI_CONTEXT_DIR}/research`,
|
|
24
|
-
`${AI_CONTEXT_DIR}/plans`,
|
|
25
|
-
],
|
|
26
|
-
files: [
|
|
27
|
-
AI_CONTEXT_FILE,
|
|
28
|
-
`${AI_CONTEXT_DIR}/README.md`,
|
|
29
|
-
`${AI_CONTEXT_DIR}/settings.json`,
|
|
30
|
-
`${AI_CONTEXT_DIR}/context/WORKFLOW_INDEX.md`,
|
|
31
|
-
],
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Validate the installation
|
|
36
|
-
*/
|
|
37
|
-
async function validateInstallation(targetDir) {
|
|
38
|
-
const result = {
|
|
39
|
-
passed: true,
|
|
40
|
-
warnings: 0,
|
|
41
|
-
errors: 0,
|
|
42
|
-
checks: [],
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
// Check required directories
|
|
46
|
-
for (const dir of REQUIRED_STRUCTURE.directories) {
|
|
47
|
-
const fullPath = path.join(targetDir, dir);
|
|
48
|
-
const exists = fs.existsSync(fullPath);
|
|
49
|
-
|
|
50
|
-
result.checks.push({
|
|
51
|
-
type: 'directory',
|
|
52
|
-
path: dir,
|
|
53
|
-
status: exists ? 'PASS' : 'FAIL',
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
if (!exists) {
|
|
57
|
-
result.errors++;
|
|
58
|
-
result.passed = false;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Check required files
|
|
63
|
-
for (const file of REQUIRED_STRUCTURE.files) {
|
|
64
|
-
const fullPath = path.join(targetDir, file);
|
|
65
|
-
const exists = fs.existsSync(fullPath);
|
|
66
|
-
|
|
67
|
-
result.checks.push({
|
|
68
|
-
type: 'file',
|
|
69
|
-
path: file,
|
|
70
|
-
status: exists ? 'PASS' : 'FAIL',
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
if (!exists) {
|
|
74
|
-
result.errors++;
|
|
75
|
-
result.passed = false;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Check for remaining placeholders in key files
|
|
80
|
-
const filesToCheck = [
|
|
81
|
-
AI_CONTEXT_FILE,
|
|
82
|
-
`${AI_CONTEXT_DIR}/README.md`,
|
|
83
|
-
`${AI_CONTEXT_DIR}/settings.json`,
|
|
84
|
-
];
|
|
85
|
-
|
|
86
|
-
for (const file of filesToCheck) {
|
|
87
|
-
const fullPath = path.join(targetDir, file);
|
|
88
|
-
if (fs.existsSync(fullPath)) {
|
|
89
|
-
const content = fs.readFileSync(fullPath, 'utf8');
|
|
90
|
-
const placeholders = content.match(/\{\{[A-Z_]+\}\}/g) || [];
|
|
91
|
-
|
|
92
|
-
if (placeholders.length > 0) {
|
|
93
|
-
result.checks.push({
|
|
94
|
-
type: 'placeholders',
|
|
95
|
-
path: file,
|
|
96
|
-
status: 'WARN',
|
|
97
|
-
details: `${placeholders.length} placeholders remaining`,
|
|
98
|
-
});
|
|
99
|
-
result.warnings++;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Validate settings.json is valid JSON
|
|
105
|
-
const settingsPath = path.join(targetDir, AI_CONTEXT_DIR, 'settings.json');
|
|
106
|
-
if (fs.existsSync(settingsPath)) {
|
|
107
|
-
try {
|
|
108
|
-
JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
109
|
-
result.checks.push({
|
|
110
|
-
type: 'json',
|
|
111
|
-
path: `${AI_CONTEXT_DIR}/settings.json`,
|
|
112
|
-
status: 'PASS',
|
|
113
|
-
});
|
|
114
|
-
} catch (e) {
|
|
115
|
-
result.checks.push({
|
|
116
|
-
type: 'json',
|
|
117
|
-
path: `${AI_CONTEXT_DIR}/settings.json`,
|
|
118
|
-
status: 'FAIL',
|
|
119
|
-
details: 'Invalid JSON',
|
|
120
|
-
});
|
|
121
|
-
result.errors++;
|
|
122
|
-
result.passed = false;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return result;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Count files in a directory
|
|
131
|
-
*/
|
|
132
|
-
function countFiles(dir, pattern = '*') {
|
|
133
|
-
if (!fs.existsSync(dir)) return 0;
|
|
134
|
-
|
|
135
|
-
let count = 0;
|
|
136
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
137
|
-
|
|
138
|
-
for (const entry of entries) {
|
|
139
|
-
if (entry.isFile()) {
|
|
140
|
-
count++;
|
|
141
|
-
} else if (entry.isDirectory()) {
|
|
142
|
-
count += countFiles(path.join(dir, entry.name), pattern);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return count;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
module.exports = {
|
|
150
|
-
validateInstallation,
|
|
151
|
-
countFiles,
|
|
152
|
-
REQUIRED_STRUCTURE,
|
|
153
|
-
AI_CONTEXT_DIR,
|
|
154
|
-
AI_CONTEXT_FILE,
|
|
155
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* AI Context Engineering - Installation Validator
|
|
3
|
+
*
|
|
4
|
+
* Validates the installation was successful.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Context directory and file names
|
|
12
|
+
*/
|
|
13
|
+
const AI_CONTEXT_DIR = '.ai-context';
|
|
14
|
+
const AI_CONTEXT_FILE = 'AI_CONTEXT.md';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Required files and directories for a valid installation
|
|
18
|
+
*/
|
|
19
|
+
const REQUIRED_STRUCTURE = {
|
|
20
|
+
directories: [
|
|
21
|
+
AI_CONTEXT_DIR,
|
|
22
|
+
`${AI_CONTEXT_DIR}/context`,
|
|
23
|
+
`${AI_CONTEXT_DIR}/research`,
|
|
24
|
+
`${AI_CONTEXT_DIR}/plans`,
|
|
25
|
+
],
|
|
26
|
+
files: [
|
|
27
|
+
AI_CONTEXT_FILE,
|
|
28
|
+
`${AI_CONTEXT_DIR}/README.md`,
|
|
29
|
+
`${AI_CONTEXT_DIR}/settings.json`,
|
|
30
|
+
`${AI_CONTEXT_DIR}/context/WORKFLOW_INDEX.md`,
|
|
31
|
+
],
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Validate the installation
|
|
36
|
+
*/
|
|
37
|
+
async function validateInstallation(targetDir) {
|
|
38
|
+
const result = {
|
|
39
|
+
passed: true,
|
|
40
|
+
warnings: 0,
|
|
41
|
+
errors: 0,
|
|
42
|
+
checks: [],
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Check required directories
|
|
46
|
+
for (const dir of REQUIRED_STRUCTURE.directories) {
|
|
47
|
+
const fullPath = path.join(targetDir, dir);
|
|
48
|
+
const exists = fs.existsSync(fullPath);
|
|
49
|
+
|
|
50
|
+
result.checks.push({
|
|
51
|
+
type: 'directory',
|
|
52
|
+
path: dir,
|
|
53
|
+
status: exists ? 'PASS' : 'FAIL',
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
if (!exists) {
|
|
57
|
+
result.errors++;
|
|
58
|
+
result.passed = false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Check required files
|
|
63
|
+
for (const file of REQUIRED_STRUCTURE.files) {
|
|
64
|
+
const fullPath = path.join(targetDir, file);
|
|
65
|
+
const exists = fs.existsSync(fullPath);
|
|
66
|
+
|
|
67
|
+
result.checks.push({
|
|
68
|
+
type: 'file',
|
|
69
|
+
path: file,
|
|
70
|
+
status: exists ? 'PASS' : 'FAIL',
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
if (!exists) {
|
|
74
|
+
result.errors++;
|
|
75
|
+
result.passed = false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Check for remaining placeholders in key files
|
|
80
|
+
const filesToCheck = [
|
|
81
|
+
AI_CONTEXT_FILE,
|
|
82
|
+
`${AI_CONTEXT_DIR}/README.md`,
|
|
83
|
+
`${AI_CONTEXT_DIR}/settings.json`,
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
for (const file of filesToCheck) {
|
|
87
|
+
const fullPath = path.join(targetDir, file);
|
|
88
|
+
if (fs.existsSync(fullPath)) {
|
|
89
|
+
const content = fs.readFileSync(fullPath, 'utf8');
|
|
90
|
+
const placeholders = content.match(/\{\{[A-Z_]+\}\}/g) || [];
|
|
91
|
+
|
|
92
|
+
if (placeholders.length > 0) {
|
|
93
|
+
result.checks.push({
|
|
94
|
+
type: 'placeholders',
|
|
95
|
+
path: file,
|
|
96
|
+
status: 'WARN',
|
|
97
|
+
details: `${placeholders.length} placeholders remaining`,
|
|
98
|
+
});
|
|
99
|
+
result.warnings++;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Validate settings.json is valid JSON
|
|
105
|
+
const settingsPath = path.join(targetDir, AI_CONTEXT_DIR, 'settings.json');
|
|
106
|
+
if (fs.existsSync(settingsPath)) {
|
|
107
|
+
try {
|
|
108
|
+
JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
109
|
+
result.checks.push({
|
|
110
|
+
type: 'json',
|
|
111
|
+
path: `${AI_CONTEXT_DIR}/settings.json`,
|
|
112
|
+
status: 'PASS',
|
|
113
|
+
});
|
|
114
|
+
} catch (e) {
|
|
115
|
+
result.checks.push({
|
|
116
|
+
type: 'json',
|
|
117
|
+
path: `${AI_CONTEXT_DIR}/settings.json`,
|
|
118
|
+
status: 'FAIL',
|
|
119
|
+
details: 'Invalid JSON',
|
|
120
|
+
});
|
|
121
|
+
result.errors++;
|
|
122
|
+
result.passed = false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Count files in a directory
|
|
131
|
+
*/
|
|
132
|
+
function countFiles(dir, pattern = '*') {
|
|
133
|
+
if (!fs.existsSync(dir)) return 0;
|
|
134
|
+
|
|
135
|
+
let count = 0;
|
|
136
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
137
|
+
|
|
138
|
+
for (const entry of entries) {
|
|
139
|
+
if (entry.isFile()) {
|
|
140
|
+
count++;
|
|
141
|
+
} else if (entry.isDirectory()) {
|
|
142
|
+
count += countFiles(path.join(dir, entry.name), pattern);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return count;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
module.exports = {
|
|
150
|
+
validateInstallation,
|
|
151
|
+
countFiles,
|
|
152
|
+
REQUIRED_STRUCTURE,
|
|
153
|
+
AI_CONTEXT_DIR,
|
|
154
|
+
AI_CONTEXT_FILE,
|
|
155
|
+
};
|
package/package.json
CHANGED