create-universal-ai-context 2.2.0 → 2.2.2
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 +61 -0
- package/bin/create-ai-context.js +2 -8
- package/lib/cross-tool-sync/sync-manager.js +3 -3
- package/lib/install-hooks.js +82 -0
- package/lib/migrate.js +17 -8
- package/package.json +1 -1
- package/templates/hooks/post-commit.hbs +29 -0
- package/templates/hooks/pre-commit.hbs +46 -0
package/README.md
CHANGED
|
@@ -97,6 +97,67 @@ npx create-universal-ai-context hooks:install
|
|
|
97
97
|
- `newest` - Most recently modified wins
|
|
98
98
|
- `manual` - Require manual resolution
|
|
99
99
|
|
|
100
|
+
## Automation Scripts
|
|
101
|
+
|
|
102
|
+
The generated `.ai-context/` directory includes automation that keeps documentation synchronized:
|
|
103
|
+
|
|
104
|
+
### Generators
|
|
105
|
+
|
|
106
|
+
**Code Mapper** (`.ai-context/automation/generators/code-mapper.js`)
|
|
107
|
+
- Scans workflow files for file:line references
|
|
108
|
+
- Builds CODE_TO_WORKFLOW_MAP.md (reverse index of code → docs)
|
|
109
|
+
- Shows which workflows reference each file
|
|
110
|
+
- Helps identify what needs updating after code changes
|
|
111
|
+
|
|
112
|
+
**Index Builder** (`.ai-context/automation/generators/index-builder.js`)
|
|
113
|
+
- Regenerates category indexes automatically
|
|
114
|
+
- Updates navigation indexes with accurate counts
|
|
115
|
+
- Scans workflows, agents, and commands for metadata
|
|
116
|
+
|
|
117
|
+
### Git Hooks
|
|
118
|
+
|
|
119
|
+
**Pre-Commit Hook**
|
|
120
|
+
- Validates before allowing commits
|
|
121
|
+
- Warns if code changes might affect documentation
|
|
122
|
+
- Optionally blocks commits if docs are stale
|
|
123
|
+
|
|
124
|
+
**Post-Commit Hook**
|
|
125
|
+
- Rebuilds CODE_TO_WORKFLOW_MAP.md in background
|
|
126
|
+
- Updates file hashes for change tracking
|
|
127
|
+
- Keeps indexes synchronized
|
|
128
|
+
|
|
129
|
+
### Install Hooks
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# Copy hooks to .git/hooks/
|
|
133
|
+
cp .ai-context/automation/hooks/pre-commit.sh .git/hooks/pre-commit
|
|
134
|
+
cp .ai-context/automation/hooks/post-commit.sh .git/hooks/post-commit
|
|
135
|
+
chmod +x .git/hooks/pre-commit .git/hooks/post-commit
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Run Manually
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# Regenerate code-to-workflow map
|
|
142
|
+
node .ai-context/automation/generators/code-mapper.js
|
|
143
|
+
|
|
144
|
+
# Rebuild all indexes
|
|
145
|
+
node .ai-context/automation/generators/index-builder.js
|
|
146
|
+
|
|
147
|
+
# Dry-run to preview
|
|
148
|
+
node .ai-context/automation/generators/code-mapper.js --dry-run
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Configuration
|
|
152
|
+
|
|
153
|
+
Control automation via `.ai-context/automation/config.json`:
|
|
154
|
+
- Enable/disable generators
|
|
155
|
+
- Configure hook behavior
|
|
156
|
+
- Set drift check sensitivity
|
|
157
|
+
- Toggle blocking on stale documentation
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
100
161
|
## Existing Documentation Detection
|
|
101
162
|
|
|
102
163
|
The CLI automatically detects existing AI context files:
|
package/bin/create-ai-context.js
CHANGED
|
@@ -745,15 +745,9 @@ program
|
|
|
745
745
|
.action(async () => {
|
|
746
746
|
console.log(banner);
|
|
747
747
|
|
|
748
|
-
const installScript = path.join(__dirname, '..', '.claude', 'automation', 'hooks', 'install.js');
|
|
749
|
-
|
|
750
|
-
if (!fs.existsSync(installScript)) {
|
|
751
|
-
console.error(chalk.red('\n✖ Error: Install script not found'));
|
|
752
|
-
process.exit(1);
|
|
753
|
-
}
|
|
754
|
-
|
|
755
748
|
try {
|
|
756
|
-
require(
|
|
749
|
+
const { installHooks } = require('../lib/install-hooks');
|
|
750
|
+
installHooks();
|
|
757
751
|
} catch (error) {
|
|
758
752
|
console.error(chalk.red('\n✖ Error:'), error.message);
|
|
759
753
|
process.exit(1);
|
|
@@ -9,7 +9,7 @@ const fs = require('fs');
|
|
|
9
9
|
const path = require('path');
|
|
10
10
|
const crypto = require('crypto');
|
|
11
11
|
const { getAdapter, getAllAdapters, getAdapterNames } = require('../adapters');
|
|
12
|
-
const {
|
|
12
|
+
const { analyzeCodebase } = require('../static-analyzer');
|
|
13
13
|
const { generateAll, initialize: initGenerator } = require('../ai-context-generator');
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -221,7 +221,7 @@ async function propagateContextChange(sourceTool, projectRoot, config, strategy
|
|
|
221
221
|
// 1. Re-analyze codebase to get fresh analysis
|
|
222
222
|
let analysis;
|
|
223
223
|
try {
|
|
224
|
-
analysis = await
|
|
224
|
+
analysis = await analyzeCodebase(projectRoot, config);
|
|
225
225
|
} catch (error) {
|
|
226
226
|
results.errors.push({
|
|
227
227
|
message: `Failed to analyze project: ${error.message}`
|
|
@@ -328,7 +328,7 @@ async function syncAllFromCodebase(projectRoot, config) {
|
|
|
328
328
|
|
|
329
329
|
try {
|
|
330
330
|
// Analyze project
|
|
331
|
-
const analysis = await
|
|
331
|
+
const analysis = await analyzeCodebase(projectRoot, config);
|
|
332
332
|
|
|
333
333
|
// Generate for all tools
|
|
334
334
|
const generateResults = await generateAll(analysis, config, projectRoot, {
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Install Git Hooks for AI Context Sync
|
|
4
|
+
*
|
|
5
|
+
* Usage: Called via `npx create-ai-context hooks:install`
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
|
|
11
|
+
function installHooks(projectRoot = process.cwd()) {
|
|
12
|
+
const hooksDir = path.join(__dirname, '..', 'templates', 'hooks');
|
|
13
|
+
const gitHooksDir = path.join(projectRoot, '.git', 'hooks');
|
|
14
|
+
|
|
15
|
+
// Hooks to install
|
|
16
|
+
const hooks = [
|
|
17
|
+
{ source: 'pre-commit.hbs', target: 'pre-commit' },
|
|
18
|
+
{ source: 'post-commit.hbs', target: 'post-commit' }
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
function ensureDirectory(dir) {
|
|
22
|
+
if (!fs.existsSync(dir)) {
|
|
23
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function copyHook(sourceFile, targetFile) {
|
|
28
|
+
const sourcePath = path.join(hooksDir, sourceFile);
|
|
29
|
+
const targetPath = path.join(gitHooksDir, targetFile);
|
|
30
|
+
|
|
31
|
+
if (!fs.existsSync(sourcePath)) {
|
|
32
|
+
console.warn(`Warning: ${sourceFile} not found, skipping`);
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const content = fs.readFileSync(sourcePath, 'utf-8');
|
|
37
|
+
|
|
38
|
+
fs.writeFileSync(targetPath, content, { mode: 0o755 });
|
|
39
|
+
console.log(`✓ Installed ${targetFile}`);
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
console.log('\nInstalling AI context sync git hooks...\n');
|
|
44
|
+
|
|
45
|
+
// Check if we're in a git repository
|
|
46
|
+
if (!fs.existsSync(gitHooksDir)) {
|
|
47
|
+
console.error('Error: .git/hooks directory not found');
|
|
48
|
+
console.error('Please run this command from the root of a git repository\n');
|
|
49
|
+
throw new Error('Not a git repository');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Ensure hooks directory exists
|
|
53
|
+
ensureDirectory(gitHooksDir);
|
|
54
|
+
|
|
55
|
+
// Copy hooks
|
|
56
|
+
let installed = 0;
|
|
57
|
+
for (const hook of hooks) {
|
|
58
|
+
if (copyHook(hook.source, hook.target)) {
|
|
59
|
+
installed++;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
console.log(`\nSuccessfully installed ${installed} git hooks\n`);
|
|
64
|
+
console.log('The hooks will:');
|
|
65
|
+
console.log(' • Check sync status before commits (pre-commit)');
|
|
66
|
+
console.log(' • Auto-sync after successful commits (post-commit)\n');
|
|
67
|
+
console.log('To skip sync checks, use: git commit --no-verify\n');
|
|
68
|
+
|
|
69
|
+
return { installed, total: hooks.length };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = { installHooks };
|
|
73
|
+
|
|
74
|
+
// If run directly
|
|
75
|
+
if (require.main === module) {
|
|
76
|
+
try {
|
|
77
|
+
installHooks();
|
|
78
|
+
} catch (error) {
|
|
79
|
+
console.error('\n✖ Installation failed:', error.message);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
}
|
package/lib/migrate.js
CHANGED
|
@@ -274,6 +274,11 @@ async function migrateV1ToV2(projectRoot, options = {}) {
|
|
|
274
274
|
function getMigrationStatus(projectRoot) {
|
|
275
275
|
const detection = detectV1Installation(projectRoot);
|
|
276
276
|
|
|
277
|
+
// In v2.0, both .ai-context/ AND .claude/ can exist
|
|
278
|
+
// The presence of AI_CONTEXT.md indicates v2.0 installation
|
|
279
|
+
// .claude/ in v2.0 is created by the Claude adapter for Claude-specific features
|
|
280
|
+
const hasAiContextMd = fs.existsSync(path.join(projectRoot, MIGRATIONS.entryFile.new));
|
|
281
|
+
|
|
277
282
|
if (!detection.hasV1 && !detection.hasV2) {
|
|
278
283
|
return {
|
|
279
284
|
status: 'none',
|
|
@@ -282,24 +287,28 @@ function getMigrationStatus(projectRoot) {
|
|
|
282
287
|
};
|
|
283
288
|
}
|
|
284
289
|
|
|
285
|
-
if
|
|
290
|
+
// If AI_CONTEXT.md exists, this is v2.0 (even if .claude/ also exists)
|
|
291
|
+
if (hasAiContextMd) {
|
|
286
292
|
return {
|
|
287
|
-
status: '
|
|
288
|
-
message: '
|
|
289
|
-
needsMigration:
|
|
293
|
+
status: 'v2',
|
|
294
|
+
message: 'v2.0 installation found, no migration needed',
|
|
295
|
+
needsMigration: false,
|
|
290
296
|
details: detection
|
|
291
297
|
};
|
|
292
298
|
}
|
|
293
299
|
|
|
294
|
-
|
|
300
|
+
// If .claude/ exists but no AI_CONTEXT.md, this is v1.x
|
|
301
|
+
if (detection.hasV1 && !detection.hasV2) {
|
|
295
302
|
return {
|
|
296
|
-
status: '
|
|
297
|
-
message: '
|
|
298
|
-
needsMigration:
|
|
303
|
+
status: 'v1',
|
|
304
|
+
message: 'v1.x installation found, migration available',
|
|
305
|
+
needsMigration: true,
|
|
299
306
|
details: detection
|
|
300
307
|
};
|
|
301
308
|
}
|
|
302
309
|
|
|
310
|
+
// True mixed state: both v1.x indicators and v2.0 indicators exist
|
|
311
|
+
// This shouldn't happen normally, but handle it
|
|
303
312
|
if (detection.hasV1 && detection.hasV2) {
|
|
304
313
|
return {
|
|
305
314
|
status: 'mixed',
|
package/package.json
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Post-commit hook for AI context sync
|
|
3
|
+
# This hook triggers sync after successful commits
|
|
4
|
+
|
|
5
|
+
# Don't block commit if this fails
|
|
6
|
+
set +e
|
|
7
|
+
|
|
8
|
+
# Check if ai-context binary is available
|
|
9
|
+
if ! command -v create-ai-context &> /dev/null; then
|
|
10
|
+
# Try npx
|
|
11
|
+
if command -v npx &> /dev/null; then
|
|
12
|
+
AI_CONTEXT_CMD="npx create-universal-ai-context"
|
|
13
|
+
else
|
|
14
|
+
exit 0
|
|
15
|
+
fi
|
|
16
|
+
else
|
|
17
|
+
AI_CONTEXT_CMD="create-ai-context"
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
# Run background sync (async)
|
|
21
|
+
echo "Syncing AI contexts in background..."
|
|
22
|
+
|
|
23
|
+
# Use subshell to run in background
|
|
24
|
+
(
|
|
25
|
+
sleep 2 # Wait a bit to not interfere with commit
|
|
26
|
+
$AI_CONTEXT_CMD sync:all --quiet > /dev/null 2>&1
|
|
27
|
+
) &
|
|
28
|
+
|
|
29
|
+
exit 0
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Pre-commit hook for AI context sync
|
|
3
|
+
# This hook checks if AI tool contexts are out of sync
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
# Colors for output
|
|
8
|
+
RED='\033[0;31m'
|
|
9
|
+
YELLOW='\033[1;33m'
|
|
10
|
+
GREEN='\033[0;32m'
|
|
11
|
+
NC='\033[0m' # No Color
|
|
12
|
+
|
|
13
|
+
# Check if ai-context binary is available
|
|
14
|
+
if ! command -v create-ai-context &> /dev/null; then
|
|
15
|
+
# Try npx
|
|
16
|
+
if command -v npx &> /dev/null; then
|
|
17
|
+
AI_CONTEXT_CMD="npx create-universal-ai-context"
|
|
18
|
+
else
|
|
19
|
+
echo -e "${YELLOW}Warning: create-ai-context not found. Skipping sync check.${NC}"
|
|
20
|
+
exit 0
|
|
21
|
+
fi
|
|
22
|
+
else
|
|
23
|
+
AI_CONTEXT_CMD="create-ai-context"
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
# Run sync check
|
|
27
|
+
echo -e "${GREEN}Checking AI context sync status...${NC}"
|
|
28
|
+
|
|
29
|
+
# Check for out-of-sync contexts
|
|
30
|
+
CHECK_OUTPUT=$($AI_CONTEXT_CMD sync:check 2>&1)
|
|
31
|
+
CHECK_EXIT_CODE=$?
|
|
32
|
+
|
|
33
|
+
if [ $CHECK_EXIT_CODE -ne 0 ]; then
|
|
34
|
+
echo -e "${RED}AI contexts are out of sync!${NC}"
|
|
35
|
+
echo ""
|
|
36
|
+
echo "$CHECK_OUTPUT"
|
|
37
|
+
echo ""
|
|
38
|
+
echo -e "${YELLOW}To sync all contexts, run:${NC}"
|
|
39
|
+
echo " $AI_CONTEXT_CMD sync:all"
|
|
40
|
+
echo ""
|
|
41
|
+
echo -e "${YELLOW}To skip this check, use: git commit --no-verify${NC}"
|
|
42
|
+
exit 1
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
echo -e "${GREEN}AI contexts are in sync${NC}"
|
|
46
|
+
exit 0
|